From 92196d9a0c20cb37dd5c73c5e08eb2df89fd52ed Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Mon, 26 Apr 2021 10:29:32 +0300 Subject: [PATCH 001/112] Merge of AttracsBold --- Bold.dpk | 5 +- Bold.dproj | 32 +- BoldComGUI.dpk | 1 - BoldUDPProp.dpk | 3 +- BoldUtility.dpk | 13 +- BoldVCLGUI.dpk | 4 +- .../BoldControls/BoldCaptionController.pas | 29 +- .../BoldControls/BoldCheckBox.pas | 26 +- .../BoldControls/BoldComboBox.pas | 251 +- .../BoldControls/BoldDataSet.UnitDoc | 556 -- .../BoldAwareGUI/BoldControls/BoldDataSet.pas | 1785 ----- .../BoldControls/BoldDragDropTarget.pas | 33 +- Source/BoldAwareGUI/BoldControls/BoldEdit.pas | 85 +- Source/BoldAwareGUI/BoldControls/BoldGrid.pas | 406 +- .../BoldControls/BoldGridRTColEditor.pas | 20 +- .../BoldAwareGUI/BoldControls/BoldImage.pas | 38 +- .../BoldControls/BoldImageBitmap.pas | 36 +- .../BoldControls/BoldImageJPEG.pas | 31 +- .../BoldAwareGUI/BoldControls/BoldLabel.pas | 37 +- .../BoldAwareGUI/BoldControls/BoldListBox.pas | 66 +- Source/BoldAwareGUI/BoldControls/BoldMemo.pas | 43 +- .../BoldControls/BoldNavigator.pas | 34 +- .../BoldControls/BoldPageControl.pas | 13 +- .../BoldControls/BoldProgressBar.pas | 20 +- .../BoldControls/BoldPropertiesController.pas | 116 +- .../BoldControls/BoldRichEdit.pas | 13 +- .../BoldStringsPropertyController.pas | 93 +- .../BoldControls/BoldTrackBar.pas | 16 +- .../BoldControls/BoldTreeView.pas | 307 +- .../BoldControls/BoldTreeViewConfig.pas | 38 +- .../BoldControls/BoldXCVTreeView.pas | 3 + .../BoldCheckboxStateControlPack.pas | 141 +- .../ControlPacks/BoldControlPack.pas | 1190 ++-- .../BoldControllerListControlPack.pas | 66 +- .../ControlPacks/BoldDateTimeControlPack.pas | 178 +- .../BoldElementHandleFollower.pas | 43 +- .../ControlPacks/BoldFloatControlPack.pas | 148 +- .../BoldGenericListControlPack.pas | 85 +- .../ControlPacks/BoldListControlPack.pas | 393 +- .../ControlPacks/BoldListHandleFollower.pas | 55 +- .../ControlPacks/BoldListListControlPack.pas | 164 +- .../ControlPacks/BoldMLRenderers.pas | 210 +- .../ControlPacks/BoldNodeControlPack.pas | 69 +- .../ControlPacks/BoldNumericControlPack.pas | 135 +- .../ControlPacks/BoldStringControlPack.pas | 381 +- .../ControlPacks/BoldVariantControlPack.pas | 674 ++ .../ControlPacks/BoldViewerControlPack.pas | 175 +- .../Core/BoldExceptionHandlers.pas | 78 +- Source/BoldAwareGUI/Core/BoldGUI.pas | 56 +- .../Core/BoldGuiResourceStrings.pas | 10 + .../BoldAwareGUI/FormGen/BoldAFPDefault.pas | 95 +- .../FormGen/BoldAFPPluggableReg.pas | 2 - Source/BoldAwareGUI/IDE/BoldAwareGuiReg.pas | 89 +- .../IDE/BoldComboBoxPropertyEditors.pas | 7 +- .../IDE/BoldControlPackPropertyEditors.pas | 121 +- .../IDE/BoldDataSetPropertyEditors.pas | 96 - .../IDE/BoldGridPropertyEditors.pas | 15 +- .../IDE/BoldNodeDescriptionEditor.pas | 19 +- ...oldPropertiesControllerPropertyEditors.pas | 34 +- .../BoldQAwareGUI/BoldControls/BoldQEdit.pas | 1 - .../BoldQAwareGUI/BoldControls/BoldQLabel.pas | 1 - .../ControlPacks/BoldQControlPack.pas | 1 - .../BoldQElementHandleFollower.pas | 1 - .../ControlPacks/BoldQStringControlPack.pas | 1 - Source/BoldQAwareGUI/Core/BoldQGUI.pas | 1 - .../BoldControls/BoldCaptionControllerCom.pas | 10 +- .../BoldControls/BoldCheckBoxCom.pas | 19 +- .../BoldControls/BoldComboBoxCom.pas | 78 +- .../BoldControls/BoldDragDropTargetCom.pas | 15 +- .../ClientGuiCom/BoldControls/BoldEditCom.pas | 75 +- .../ClientGuiCom/BoldControls/BoldGridCom.pas | 199 +- .../BoldControls/BoldGridRTColEditorCom.pas | 10 +- .../BoldControls/BoldImageBitmapCom.pas | 11 +- .../BoldControls/BoldImageCom.pas | 19 +- .../BoldControls/BoldImageJPEGCom.pas | 9 +- .../BoldControls/BoldLabelCom.pas | 28 +- .../BoldControls/BoldListBoxCom.pas | 65 +- .../ClientGuiCom/BoldControls/BoldMemoCom.pas | 34 +- .../BoldControls/BoldNavigatorCom.pas | 46 +- .../BoldControls/BoldPageControlCom.pas | 12 +- .../BoldControls/BoldProgressBarCom.pas | 22 +- .../BoldPropertiesControllerCom.pas | 50 +- .../BoldControls/BoldRichEditCom.pas | 3 + .../BoldStringsPropertyControllerCom.pas | 12 +- .../BoldControls/BoldTrackBarCom.pas | 6 +- .../BoldControls/BoldTreeViewCom.pas | 72 +- .../BoldControls/BoldTreeViewConfigCom.pas | 10 +- .../BoldControls/BoldXCVTreeViewCom.pas | 3 + .../BoldCheckboxStateControlPackCom.pas | 30 +- .../ControlPacks/BoldControlPackCom.pas | 89 +- .../BoldControllerListControlPackCom.pas | 10 +- .../BoldDateTimeControlPackCom.pas | 37 +- .../BoldElementHandleFollowerCom.pas | 13 +- .../ControlPacks/BoldFloatControlPackCom.pas | 20 +- .../BoldGenericListControlPackCom.pas | 52 +- .../ControlPacks/BoldListControlPackCom.pas | 15 +- .../BoldListHandleFollowerCom.pas | 19 +- .../BoldListListControlPackCom.pas | 41 +- .../ControlPacks/BoldNodeControlPackCom.pas | 20 +- .../BoldNumericControlPackCom.pas | 35 +- .../ControlPacks/BoldStringControlPackCom.pas | 40 +- .../ControlPacks/BoldViewerControlPackCom.pas | 32 +- .../Core/BoldExceptionHandlersCom.pas | 40 +- .../Core/BoldGuiResourceStringsCom.pas | 5 +- .../ClientGuiCom/IDE/BoldAwareGuiComReg.pas | 61 +- .../IDE/BoldCOMPropertyEditors.pas | 3 + .../IDE/BoldGridPropertyEditorsCom.pas | 43 +- ...PropertiesControllerPropertyEditorsCom.pas | 20 +- .../Core/BoldAbstractListHandleCom.pas | 12 +- .../Core/BoldClientElementSupport.pas | 13 +- .../Core/BoldCursorHandleCom.pas | 44 +- .../Core/BoldDerivedHandleCom.pas | 31 +- .../Core/BoldExpressionHandleCom.pas | 70 +- .../ClientHandlesCom/Core/BoldHandlesCom.pas | 12 +- .../Core/BoldListHandleCom.pas | 77 +- .../Core/BoldPlaceableSubscriberCom.pas | 50 +- .../Core/BoldReferenceHandleCom.pas | 37 +- .../Core/BoldRootedHandlesCom.pas | 28 +- .../Core/BoldSQLHandleCom.pas | 61 +- .../Core/BoldSystemHandleCom.pas | 31 +- .../Core/BoldVariableDefinitionCom.pas | 46 +- .../Core/BoldVariableHandleCom.pas | 36 +- .../ClientHandlesCom/Core/ComHandlesConst.pas | 2 +- .../ClientHandlesCom/IDE/BoldHandleComReg.pas | 49 +- Source/Common/COM/BoldApartmentThread.pas | 21 +- Source/Common/COM/BoldComAdapter.pas | 165 +- Source/Common/COM/BoldComEventQueue.pas | 79 +- Source/Common/COM/BoldComObj.pas | 12 + Source/Common/COM/BoldComThreads.pas | 18 +- Source/Common/COM/BoldComUtils.pas | 10 +- .../COM/BoldThreadedComObjectFactory.pas | 14 +- Source/Common/Connection/BoldClient.pas | 6 +- Source/Common/Connection/BoldServer.pas | 6 +- Source/Common/ConnectionCOM/BoldComClient.pas | 26 +- .../ConnectionCOM/BoldComConnection.pas | 84 +- Source/Common/ConnectionCOM/BoldComServ.pas | 8 + Source/Common/ConnectionCOM/BoldComServer.pas | 255 +- .../ConnectionHandles/BoldClientHandles.pas | 8 + .../ConnectionHandles/BoldServerHandles.pas | 8 +- .../BoldComClientHandles.pas | 47 +- .../BoldComServerHandles.pas | 22 +- .../BoldXMLDispatcher.pas | 31 +- .../BoldXMLDispatcherVB.pas | 23 +- Source/Common/Core/BoldBase.pas | 292 +- Source/Common/Core/BoldContainers.pas | 478 +- Source/Common/Core/BoldDefs.pas | 166 +- Source/Common/Core/BoldStreams.pas | 8 + Source/Common/Core/BoldThreadSafeQueue.pas | 68 +- Source/Common/Environment/BoldEnvironment.pas | 57 +- .../BoldEnvironmentAllowBothUseCLX.pas | 7 +- .../BoldEnvironmentAllowBothUseVCL.pas | 7 +- .../Common/Environment/BoldEnvironmentCLX.pas | 32 +- .../Common/Environment/BoldEnvironmentIDE.pas | 12 +- .../Common/Environment/BoldEnvironmentVCL.pas | 32 +- Source/Common/HTTP/BoldDataBlock.pas | 8 +- Source/Common/HTTP/BoldWebConnection.pas | 23 +- Source/Common/Handles/BoldHandle.pas | 6 +- Source/Common/IDE/BoldAbout.dfm | 12 +- Source/Common/IDE/BoldAbout.pas | 2 +- .../IDE/BoldAbstractPropertyEditors.pas | 17 +- Source/Common/IDE/BoldDefsDT.pas | 26 +- Source/Common/IDE/BoldExpert.pas | 26 +- Source/Common/IDE/BoldExpertMenus.pas | 8 + .../Common/IDE/BoldGettingStartedExpert.pas | 30 +- Source/Common/IDE/BoldGettingStartedForm.pas | 8 + Source/Common/IDE/BoldIDEConsts.pas | 11 +- Source/Common/IDE/BoldIDEMenus.pas | 46 +- Source/Common/IDE/BoldIDESupport.pas | 46 +- Source/Common/IDE/BoldLicenseTextForm.pas | 9 +- .../IDE/BoldModelAwareComponentEditor.pas | 13 +- Source/Common/IDE/BoldOTAFileHandler.pas | 79 +- Source/Common/IDE/BoldOTASupport.pas | 119 +- Source/Common/IDE/BoldPropertyEditors.pas | 5 + Source/Common/IDE/BoldReg.pas | 4 + Source/Common/IDE/BoldTextStream.pas | 10 +- Source/Common/IDE/BoldWebConnectionReg.pas | 4 + Source/Common/IDECOM/BoldComEditors.pas | 44 +- Source/Common/IDECOM/BoldComReg.pas | 12 +- .../IDECOM/BoldObjectNamePropertyEditor.pas | 26 +- .../Common/IDECOM/BoldXMLDispatcherEditor.pas | 16 +- Source/Common/IDECOM/BoldXMLDispatcherReg.pas | 6 +- .../Common/IDECOM/BoldXMLDispatcherVBReg.pas | 8 +- Source/Common/Include/Bold.inc | 492 ++ Source/Common/Logging/BoldLogForm.pas | 61 +- Source/Common/Logging/BoldLogHandler.pas | 70 +- Source/Common/Logging/BoldLogHandlerForm.pas | 45 +- .../Common/Logging/BoldLogHandlerSimple.pas | 29 +- .../Logging/BoldLogReceiverInterface.pas | 10 + Source/Common/Logging/BoldSmallLogFrame.pas | 30 +- Source/Common/Logging/BoldThreadSafeLog.pas | 14 +- Source/Common/MsXml/MSXML_TLB.pas | 746 +- Source/Common/Queue/BoldAbstractDequeuer.pas | 62 +- Source/Common/Queue/BoldEventQueue.pas | 31 +- Source/Common/Queue/BoldQueue.pas | 309 +- .../Common/Rose2000/BoldRose2000Support.pas | 58 +- .../Common/Rose2000/RationalRose2000_TLB.pas | 3117 ++++----- Source/Common/Rose98/BoldRose98Support.pas | 78 +- Source/Common/Rose98/RationalRose98_TLB.pas | 7 +- Source/Common/SOAP/BoldSOAP2_TLB.pas | 100 +- Source/Common/SOAP/BoldSOAP_TLB.pas | 100 +- Source/Common/SOAP/BoldXMLRequests.pas | 69 +- Source/Common/Subscription/BoldDeriver.pas | 158 +- .../BoldSubscribableCollection.pas | 18 +- .../Common/Subscription/BoldSubscription.pas | 1187 ++-- Source/Common/Support/BoldBase64.pas | 51 +- Source/Common/Support/BoldCollections.pas | 17 +- Source/Common/Support/BoldCommonBitmaps.pas | 4 + Source/Common/Support/BoldControlPackDefs.pas | 10 + Source/Common/Support/BoldControlsDefs.pas | 9 +- .../Support/BoldExternalizedReferences.pas | 59 +- Source/Common/Support/BoldFileHandler.pas | 27 +- Source/Common/Support/BoldGuard.pas | 10 +- Source/Common/Support/BoldHashIndexes.pas | 212 +- Source/Common/Support/BoldIndex.pas | 794 ++- Source/Common/Support/BoldIndexCollection.pas | 179 + Source/Common/Support/BoldIndexableList.pas | 375 +- Source/Common/Support/BoldIsoDateTime.pas | 110 +- .../Support/BoldLoggableCriticalSection.pas | 17 +- Source/Common/Support/BoldMath.pas | 8 +- Source/Common/Support/BoldMemoryManager.pas | 169 +- Source/Common/Support/BoldNamedValueList.pas | 32 +- Source/Common/Support/BoldNavigatorDefs.pas | 15 +- .../Common/Support/BoldPerformanceCounter.pas | 417 +- Source/Common/Support/BoldPriorityQueue.pas | 19 +- Source/Common/Support/BoldRegistry.pas | 6 +- Source/Common/Support/BoldRev.pas | 21 +- Source/Common/Support/BoldSharedStrings.pas | 383 +- Source/Common/Support/BoldSorter.pas | 9 + Source/Common/Support/BoldStringList.pas | 9 +- .../Common/Support/BoldTemplateExpander.pas | 81 +- Source/Common/Support/BoldUtils.pas | 284 +- Source/Common/Support/BoldXMLStreaming.pas | 257 +- Source/Common/SupportWin/BoldThread.pas | 35 +- Source/Common/SupportWin/BoldWinINet.pas | 50 +- Source/Common/SupportWin/BoldWinUtils.pas | 7 +- .../TaggedValues/BoldDefaultTaggedValues.pas | 245 +- .../TaggedValues/BoldTaggedValueList.pas | 6 +- .../TaggedValues/BoldTaggedValueSupport.pas | 43 +- .../TaggedValues/BoldUMLTaggedValues.pas | 32 +- Source/Common/Template/BoldTemplate.pas | 9 + Source/Common/UML/BoldUMLDelphiSupport.pas | 29 +- Source/Common/UML/BoldUMLTypes.pas | 14 +- Source/Common/UtilsGUI/BoldCursorGuard.pas | 8 +- .../COM/BoldLockManagerAdminHandleCom.pas | 5 + .../COM/BoldLockManagerHandleCom.pas | 8 +- .../BoldAbstractLockManagerAdminHandle.pas | 10 +- .../Common/BoldAbstractLockManagerHandle.pas | 8 + .../Common/BoldLockingDefs.pas | 8 +- .../IDECOM/BoldConcurrencyControlReg.pas | 8 +- .../OLLE/Core/BoldOLLEController.pas | 26 +- .../BoldOLLEDistributableObjectHandlers.pas | 67 +- .../Extensions/OLLE/Core/BoldOLLEHandles.pas | 7 + .../Extensions/OLLE/Core/BoldOLLEdmmain.pas | 4 +- .../OLLE/Core/DistributableInfo.pas | 69 +- Source/Extensions/OLLE/Core/OlleConsts.pas | 2 +- .../IDE/BoldOLLEHandlesComponentEditor.pas | 12 +- .../OLLE/IDE/BoldOLLEHandlesReg.pas | 6 +- .../Core/BoldFreeStandingValueFactories.pas | 13 +- .../Core/BoldFreeStandingValues.pas | 954 ++- .../Core/FreeStandingValuesConst.pas | 2 +- Source/Handles/Actions/BoldActionDefs.pas | 4 +- Source/Handles/Actions/BoldActions.pas | 18 +- Source/Handles/Actions/BoldHandleAction.pas | 9 +- Source/Handles/Actions/BoldListActions.pas | 33 +- Source/Handles/Actions/BoldUndoActions.pas | 14 +- .../COM/BoldComClientElementHandles.pas | 8 + .../COM/BoldComServerElementHandleFactory.pas | 7 +- .../COM/BoldComServerElementHandles.pas | 8 +- .../Handles/Core/BoldAbstractListHandle.pas | 101 +- Source/Handles/Core/BoldCursorHandle.pas | 23 +- Source/Handles/Core/BoldDerivedHandle.pas | 25 +- Source/Handles/Core/BoldExpressionHandle.pas | 101 +- Source/Handles/Core/BoldFilteredHandle.pas | 20 +- Source/Handles/Core/BoldHandles.pas | 195 +- Source/Handles/Core/BoldListHandle.pas | 100 +- Source/Handles/Core/BoldOclRepository.pas | 104 +- Source/Handles/Core/BoldOclVariables.pas | 471 +- .../Handles/Core/BoldPlaceableSubscriber.pas | 24 +- Source/Handles/Core/BoldRawSQLHandle.pas | 176 + Source/Handles/Core/BoldReferenceHandle.pas | 55 +- Source/Handles/Core/BoldRootedHandles.pas | 128 +- Source/Handles/Core/BoldSQLHandle.pas | 31 +- Source/Handles/Core/BoldSortedHandle.pas | 50 +- Source/Handles/Core/BoldSystemHandle.pas | 91 +- .../Handles/Core/BoldVariableDefinition.pas | 8 + Source/Handles/Core/BoldVariableHandle.pas | 38 +- Source/Handles/Core/HandlesConst.pas | 2 +- Source/Handles/IDE/BoldHandlePropEditor.pas | 34 +- Source/Handles/IDE/BoldHandleReg.pas | 9 + Source/Handles/IDE/BoldLockingReg.pas | 5 +- Source/Handles/IDE/BoldManipulatorReg.pas | 4 + Source/Handles/IDE/BoldXMLReg.pas | 7 +- .../IDECOM/BoldComElementHandleReg.pas | 7 +- .../Handles/Manipulators/BoldManipulators.pas | 64 +- .../PessimisticLocking/BoldLockingHandles.pas | 22 +- .../Handles/UnLoader/BoldUnloaderHandle.pas | 92 +- Source/Handles/XML/BoldXMLProducers.pas | 15 +- Source/MoldModel/Bld/BoldBld.pas | 163 +- Source/MoldModel/CodeGenerator/BoldGen.pas | 575 +- .../CodeGenerator/BoldGeneratorTemplates.pas | 24 +- .../BoldGeneratorTemplatesCPP.pas | 73 +- .../BoldGeneratorTemplatesDelphi.pas | 82 +- Source/MoldModel/Core/BoldMeta.pas | 601 +- Source/MoldModel/Core/BoldMetaSupport.pas | 61 +- Source/MoldModel/Core/BoldMoldConsts.pas | 53 +- Source/MoldModel/Core/BoldNameExpander.pas | 52 +- .../MoldModel/Handles/BoldAbstractModel.pas | 13 +- .../MoldModel/Handles/BoldTypeNameHandle.pas | 8 +- Source/MoldModel/IDE/BoldModelReg.pas | 14 +- .../MoldModel/IDE/BoldTypeNameHandleReg.pas | 33 +- .../BoldTypeNameDictionary.pas | 76 +- .../MoldModel/UtilsGUI/BoldTypeNameEditor.pas | 52 +- .../BORepresentation/BoldAttributes.pas | 2489 +++++-- .../BORepresentation/BoldDerivedValueSet.pas | 18 +- .../BORepresentation/BoldDomainElement.pas | 133 +- .../BORepresentation/BoldElementList.pas | 56 +- .../BoldExternalObjectSpaceEventHandler.pas | 530 +- .../BORepresentation/BoldLinks.pas | 1327 ++-- .../BORepresentation/BoldMLAttributes.pas | 163 +- .../BORepresentation/BoldOSSMessage.pas | 166 + .../BoldObjectListControllers.pas | 597 +- .../BORepresentation/BoldObjectSpaceLists.pas | 350 +- .../BoldOptimisticLockingSupport.pas | 99 +- .../BORepresentation/BoldSystem.pas | 5978 ++++++++++++----- .../BoldSystemOldValuehandler.pas | 123 +- .../BoldSystemPersistenceHandler.pas | 399 +- .../BORepresentation/BoldTypeList.pas | 53 +- Source/ObjectSpace/COM/BoldComObjectSpace.pas | 10 +- .../COM/BoldComObjectSpaceAdapters.pas | 235 +- .../COM/BoldComObjectSpace_TLB.pas | 403 +- .../COM/BoldComponentValidatorCom.pas | 9 +- Source/ObjectSpace/Core/BoldCoreConsts.pas | 3 + Source/ObjectSpace/Core/BoldElements.pas | 605 +- .../ObjectSpace/Core/BoldMetaElementList.pas | 81 +- .../AttributeWizard/BoldAttributeWizard.pas | 44 +- .../IDE/AttributeWizard/BoldOTACodeGen.pas | 8 +- .../IDE/AttributeWizard/BoldVclUtils.pas | 9 +- .../IDE/AttributeWizard/BoldWAClassInfo.pas | 9 +- .../IDE/AttributeWizard/BoldWACustomAttr.pas | 36 +- .../AttributeWizard/BoldWACustomAttrForm1.pas | 224 +- .../AttributeWizard/BoldWAInputFormUnit.pas | 7 +- .../IDE/AttributeWizard/BoldWAInterfaces.pas | 10 +- .../IDE/AttributeWizard/BoldWAMainForm.pas | 10 +- .../IDE/AttributeWizard/BoldWAMethodInfo.pas | 49 +- .../BoldWAStringGridManager.pas | 17 +- .../AttributeWizard/BoldWASubClassForm1.pas | 31 +- .../IDE/AttributeWizard/BoldWAValueSetDlg.pas | 7 +- .../AttributeWizard/BoldWAValueSetForm1.pas | 43 +- .../IDE/AttributeWizard/BoldWAdatamodule.pas | 9 + .../IDE/AttributeWizard/BoldWAdmTemplates.pas | 3 + .../IDE/AttributeWizard/BoldWCodeInformer.pas | 35 +- .../AttributeWizard/BoldWProjectWizard.pas | 39 +- .../IDE/AttributeWizard/BoldWScanner.pas | 21 +- .../IDE/BoldComponentValidatorIDE.pas | 41 +- ...BoldExternalObjectSpaceEventHandlerReg.pas | 4 + .../ObjectSpace/IDE/BoldWSimpleMenuWizard.pas | 45 +- .../Interfaces/BoldUndoInterfaces.pas | 42 +- Source/ObjectSpace/Ocl/BoldORed.pas | 30 +- Source/ObjectSpace/Ocl/BoldOcl.pas | 706 +- Source/ObjectSpace/Ocl/BoldOclClasses.pas | 502 +- .../ObjectSpace/Ocl/BoldOclConstructors.inc | 170 +- Source/ObjectSpace/Ocl/BoldOclError.pas | 15 +- Source/ObjectSpace/Ocl/BoldOclEvaluator.pas | 290 +- .../Ocl/BoldOclLightWeightNodeMaker.pas | 73 +- .../Ocl/BoldOclLightWeightNodes.pas | 224 +- Source/ObjectSpace/Ocl/BoldOclRTDebug.pas | 7 + Source/ObjectSpace/Ocl/BoldOclSemantics.pas | 202 +- .../Ocl/BoldOclSymbolImplementations.pas | 1724 ++++- Source/ObjectSpace/Ocl/BoldSSExcept.pas | 21 +- Source/ObjectSpace/Ocl/BoldSSLexU.pas | 1919 +++--- Source/ObjectSpace/Ocl/BoldSSYaccU.pas | 4049 +++++++++-- .../PessimisticLocking/BoldLockHandler.pas | 87 +- .../PessimisticLocking/BoldLockHolder.pas | 71 +- .../PessimisticLocking/BoldLockRegions.pas | 246 +- .../BoldRegionDefinitionParser.pas | 57 +- .../BoldRegionDefinitions.pas | 62 +- .../RTModel/BoldGeneratedCodeDictionary.pas | 34 +- .../RTModel/BoldMemberTypeDictionary.pas | 25 +- Source/ObjectSpace/RTModel/BoldSystemRT.pas | 1030 ++- Source/ObjectSpace/Undo/BoldUndoHandler.pas | 1053 ++- Source/ObjectSpace/Unloader/BoldUnloader.pas | 146 +- .../UtilsGUI/BoldComponentValidator.pas | 58 +- .../UtilsGUI/BoldOCLGraphicRTDebug.pas | 22 +- .../UtilsGUI/BoldOclPropEditor.pas | 566 +- .../UtilsGUI/BoldTypeNameSelector.dfm | 6 +- .../UtilsGUI/BoldTypeNameSelector.pas | 163 +- .../Core/BoldAbstractObjectUpgrader.pas | 13 +- Source/PMapper/Core/BoldPMConsts.pas | 1 + Source/PMapper/Core/BoldPMapper.pas | 9 +- Source/PMapper/Core/BoldPMapperLists.pas | 51 +- Source/PMapper/Core/BoldPMappers.pas | 534 +- Source/PMapper/Core/BoldPSDescriptions.pas | 15 +- Source/PMapper/Core/BoldPSParams.pas | 8 + Source/PMapper/DbEvolutor/BoldDbEvolutor.pas | 451 +- .../PMapper/DbEvolutor/BoldDbEvolutorForm.pas | 78 +- .../DbEvolutor/BoldDbEvolutorScript.pas | 362 +- .../PMapper/Default/BoldCustomBlobMapper.pas | 95 +- Source/PMapper/Default/BoldMappingInfo.pas | 321 +- .../Default/BoldPMappersAttributeDefault.pas | 720 +- .../PMapper/Default/BoldPMappersDefault.pas | 2409 +++++-- .../Default/BoldPMappersLinkDefault.pas | 546 +- .../Default/BoldPSDescriptionsDefault.pas | 234 +- .../PMapper/Default/BoldPSParamsDefault.pas | 9 + Source/PMapper/SQL/BoldPMappersSQL.pas | 685 +- Source/PMapper/SQL/BoldPSDescriptionsSQL.pas | 362 +- Source/PMapper/SQL/BoldPSParamsSQL.pas | 11 + Source/PMapper/SQL/BoldSQLDatabaseConfig.pas | 898 ++- Source/PMapper/SQL/BoldSQLMappingInfo.pas | 189 +- Source/PMapper/SQL/BoldSQLQuery.pas | 324 +- Source/PMapper/SQL/BoldSqlNodeMaker.pas | 19 +- Source/PMapper/SQL/BoldSqlNodes.pas | 75 +- Source/PMapper/SQL/BoldSqlNodesResolver.pas | 32 +- Source/PMapper/SQL/BoldSqlQueryGenerator.pas | 16 +- Source/PMapper/SQL/BoldSqlSymbols.pas | 451 +- .../PMapper/Validator/BoldDbDataValidator.pas | 485 +- .../Validator/BoldDbStructureValidator.pas | 264 +- Source/PMapper/Validator/BoldDbValidator.pas | 68 +- Source/Persistence/ADO/ADOConsts.pas | 2 +- Source/Persistence/ADO/BoldADOInterfaces.pas | 193 +- .../ADO/BoldDatabaseAdapterADO.pas | 13 +- .../ADO/BoldPersistenceHandleADO.pas | 61 +- .../ADO/BoldPersistenceHandleADOReg.pas | 7 +- .../Advantage/BoldAdvantageInterfaces.pas | 42 +- .../BoldDatabaseAdapterAdvantage.pas | 18 +- .../BoldPersistenceHandleAdvantage.pas | 12 +- .../BoldPersistenceHandleAdvantageReg.pas | 11 +- Source/Persistence/BDE/BDEConsts.pas | 2 +- .../BDE/BoldBDEBatchInterfaces.pas | 25 +- Source/Persistence/BDE/BoldBDEInterfaces.pas | 137 +- .../BDE/BoldDatabaseAdapterBDE.pas | 17 +- .../BDE/BoldPersistenceHandleBDE.pas | 68 +- ...oldPersistenceHandleBDEPropertyEditors.pas | 12 +- .../BDE/BoldPersistenceHandleBdeReg.pas | 9 +- ...oldAbstractComClientPersistenceHandles.pas | 7 +- ...dAbstractComPersistenceControllerProxy.pas | 11 +- .../Persistence/Core/BoldAbstractSnooper.pas | 291 +- .../Core/BoldPersistenceController.pas | 49 +- .../Core/BoldPersistenceHandle.pas | 83 +- .../Core/BoldPersistenceHandlePTWithModel.pas | 9 +- .../Core/BoldPersistenceHandlePassthrough.pas | 27 +- .../Core/BoldPersistenceNotifier.pas | 78 +- .../Core/BoldUpdatePrecondition.pas | 61 +- Source/Persistence/Core/PersistenceConsts.pas | 2 +- .../DB/BoldAbstractDatabaseAdapter.pas | 27 +- .../DB/BoldAbstractPersistenceHandleDB.pas | 61 +- Source/Persistence/DB/BoldDBActions.pas | 10 +- Source/Persistence/DB/BoldDBInterfaces.pas | 1308 +++- .../DB/BoldPersistenceControllerDefault.pas | 190 +- .../DB/BoldPersistenceHandleDB.pas | 30 +- .../DB/BoldPersistenceHandleDB_deprecated.pas | 32 +- .../DB/BoldPersistenceHandleDBreg.pas | 24 +- .../DBExpress/BoldDBXInterfaces.pas | 348 +- .../DBExpress/BoldDatabaseAdapterDBX.pas | 9 +- .../DBExpress/BoldPersistenceHandleDBX.pas | 12 +- .../DBExpress/BoldPersistenceHandleDBXReg.pas | 14 +- .../DBISAM/BoldDBISAMInterfaces.pas | 45 +- .../DBISAM/BoldDatabaseAdapterDBIsam.pas | 17 +- .../DBISAM/BoldPersistenceHandleDBISAM.pas | 31 +- .../DBISAM/BoldPersistenceHandleDBISAMReg.pas | 15 +- Source/Persistence/DBISAM/DBISAMConsts.pas | 2 +- Source/Persistence/DOA/BoldDOAInterfaces.pas | 203 +- .../DOA/BoldDatabaseAdapterDOA.pas | 15 +- .../DOA/BoldPersistenceHandleDOA.pas | 19 +- .../DOA/BoldPersistenceHandleDOAReg.pas | 13 +- Source/Persistence/DOA/DOAConsts.pas | 2 +- ...dAbstractExternalPersistenceController.pas | 71 +- .../BoldAbstractExternalPersistenceHandle.pas | 27 +- .../BoldAbstractPartiallyExternalPC.pas | 141 +- .../BoldAbstractPartiallyExternalPH.pas | 9 +- ...ldExternalPersistenceConfigItemDataSet.pas | 9 + ...oldExternalPersistenceControllerConfig.pas | 9 + ...ldExternalPersistenceControllerDataSet.pas | 58 +- ...ternalPersistenceControllerEventDriven.pas | 74 +- .../BoldExternalPersistenceControllerSQL.pas | 109 +- .../BoldExternalPersistenceHandleDataSet.pas | 8 +- ...ldExternalPersistenceHandleEventDriven.pas | 10 +- .../BoldExternalPersistenceHandleSQL.pas | 11 +- ...ExternalPersistenceHandleSQLPropEditor.pas | 3 + .../BoldExternalPersistenceHandlesReg.pas | 32 +- .../BoldExternalPersistenceSupport.pas | 7 +- .../ExternalPersistence/ExPeConsts.pas | 2 +- .../File/BoldPersistenceHandleFile.pas | 72 +- .../File/BoldPersistenceHandleFileXML.pas | 63 +- .../HTTP/BoldHTTPClientPersistenceHandle.pas | 14 +- .../BoldHTTPPersistenceControllerClient.pas | 16 +- ...HTTPServerPersistenceHandlePassthrough.pas | 13 +- .../Persistence/IBX/BoldDatabaseAdapterIB.pas | 48 +- .../Persistence/IBX/BoldIBDatabaseAction.pas | 25 +- Source/Persistence/IBX/BoldIBInterfaces.pas | 206 +- .../IBX/BoldPersistenceHandleIB.pas | 44 +- .../IBX/BoldPersistenceHandleIBReg.pas | 11 +- .../IDE/BoldHandlesPropagationReg.pas | 9 +- .../IDE/BoldObjectUpgraderHandleReg.pas | 6 +- .../IDE/BoldPersistenceHandleFileReg.pas | 9 +- .../IDE/BoldPersistenceHandleReg.pas | 8 +- .../IDE/BoldPersistenceHandleSystemReg.pas | 6 +- .../IDE/BoldPersistenceNotifierReg.pas | 6 +- .../IDECOM/BoldComPersistenceHandleReg.pas | 7 +- .../BoldHTTPClientPersistenceHandleReg.pas | 6 +- ...PServerPersistenceHandlePassthroughReg.pas | 6 +- .../IDEUDP/BoldUDPBroadcasterReg.pas | 6 +- .../BoldAbstractObjectUpgraderHandle.pas | 10 +- .../ObjectUpgrading/BoldBatchUpgrader.pas | 31 +- .../ObjectUpgrading/BoldObjectUpgrader.pas | 29 +- .../BoldObjectUpgraderHandle.pas | 14 +- .../Persistence/Propagation/BoldIDAdder.pas | 18 +- .../Propagation/BoldIDAdderHandle.pas | 48 +- .../Propagation/BoldListenerCOM.pas | 22 +- .../Propagation/BoldListenerHandle.pas | 33 +- .../Propagation/BoldListenerThread.pas | 53 +- .../BoldPersistenceControllerPassthrough.pas | 62 +- .../Propagation/BoldPropagatorUtils.pas | 13 +- .../Persistence/Propagation/BoldSnooper.pas | 36 +- .../Propagation/BoldSnooperHandle.pas | 32 +- ...ldPersistenceControllerSOAPAdapterCore.pas | 51 +- .../BoldPersistenceOperationXMLStreaming.pas | 80 +- .../SOAP/BoldSOAPClientPersistenceHandles.pas | 5 + .../BoldSOAPPersistenceControllerProxy.pas | 67 +- .../BoldSOAPPersistenceControllerStub.pas | 9 +- .../SOAP/BoldSOAPServerPersistenceHandles.pas | 8 + .../BoldDatabaseAdapterSQLDirect.pas | 37 +- .../BoldPersistenceHandleSQLDirect.pas | 18 +- .../BoldPersistenceHandleSQLDirectReg.pas | 15 +- .../SQLDirect/BoldSQLDirectInterfaces.pas | 317 +- .../BoldPersistenceControllerSystem.pas | 628 +- .../System/BoldPersistenceHandleSystem.pas | 69 +- .../BoldAbstractModificationPropagator.pas | 47 +- .../BoldUDPModificationBroadcaster.pas | 10 +- .../UniDAC/BoldDatabaseAdapterUniDAC.pas | 89 + .../UniDAC/BoldPersistenceHandleUniDAC.pas | 333 + .../UniDAC/BoldPersistenceHandleUniDACReg.pas | 28 + .../UniDAC/BoldUniDACInterfaces.pas | 1638 +++++ Source/Persistence/UniDAC/UniDACConsts.pas | 18 + .../COM/BoldPropagatorHandleCOM.pas | 13 +- .../Common/BoldAbstractPropagatorHandle.pas | 9 + .../BoldLockingSupportInterfaces_TLB.pas | 98 +- .../Propagator/Common/BoldObjectMarshaler.pas | 16 +- .../Common/BoldPropagatorConstants.pas | 3 + .../Propagator/Common/BoldPropagatorGUIDs.pas | 3 + .../Common/BoldPropagatorInterfaces_TLB.pas | 139 +- Source/Propagator/Common/PropagatorConsts.pas | 2 +- .../BoldAbstractOutputQueueHandler.pas | 10 +- .../Enterprise/BoldAdvancedPropagator.pas | 19 +- .../Enterprise/BoldAdvancedPropagatorCOM.pas | 6 +- .../Enterprise/BoldClientHandler.pas | 113 +- .../Enterprise/BoldClientHandlerCOM.pas | 15 +- .../BoldClientHandlerExportHandle.pas | 5 +- .../Enterprise/BoldClientNotifierHandler.pas | 66 +- .../Propagator/Enterprise/BoldClientQueue.pas | 10 +- .../Enterprise/BoldComServiceRegister.pas | 23 +- Source/Propagator/Enterprise/BoldEnqueuer.pas | 20 +- .../Propagator/Enterprise/BoldEnqueuerCOM.pas | 11 +- .../Enterprise/BoldEnqueuerExportHandle.pas | 5 +- .../Propagator/Enterprise/BoldIndexList.pas | 8 +- .../Propagator/Enterprise/BoldIndexedList.pas | 53 +- .../Propagator/Enterprise/BoldListNodes.pas | 6 +- Source/Propagator/Enterprise/BoldLockList.pas | 25 +- .../Propagator/Enterprise/BoldLockManager.pas | 14 +- .../Enterprise/BoldLockManagerAdmin.pas | 27 +- .../Enterprise/BoldLockManagerAdminCOM.pas | 9 +- .../BoldLockManagerAdminExportHandle.pas | 9 +- .../Enterprise/BoldLockManagerCOM.pas | 9 +- .../BoldLockManagerExportHandle.pas | 9 +- .../Enterprise/BoldOutputQueueHandler.pas | 12 +- .../Enterprise/BoldPriorityListEnlister.pas | 4 + .../Enterprise/BoldPropagatorApplication.pas | 8 +- .../Enterprise/BoldPropagatorCleanup.pas | 25 +- .../Enterprise/BoldPropagatorMainForm.pas | 115 +- .../Enterprise/BoldPropagatorServer.pas | 95 +- .../BoldPropagatorSubscriptions.pas | 13 +- .../Enterprise/BoldPropagatorUIManager.pas | 47 +- .../Enterprise/BoldServerHandlesDataMod.pas | 7 +- .../Enterprise/BoldServicePropagatorUnit.pas | 3 + .../Enterprise/BoldSubscriptionHandler.pas | 30 +- .../IDECOM/BoldPropagatorHandleCOMReg.pas | 6 +- .../LowEnd/BoldLowEndPropagatorClasses.pas | 6 +- .../LowEnd/BoldLowEndPropagatorMainForm.pas | 10 +- Source/Samples/Actions/BoldDebugActions.pas | 22 +- Source/Samples/Actions/BoldEditOCLAction.pas | 5 + .../BoldCheckListBox/BoldCheckListBox.pas | 9 + .../BoldCheckListBox/BoldCheckListBoxReg.pas | 8 +- .../BoldCustomCheckListBox.pas | 28 +- .../BoldCheckListBox/BoldSelectionListBox.pas | 33 +- .../BoldSelectionListBoxReg.pas | 6 +- Source/Samples/FormSaver/BoldFormSaver.pas | 221 +- .../IDE/BoldEditOCLActionPropEditor.pas | 8 +- Source/Samples/IDE/BoldSamplesReg.pas | 27 +- Source/Samples/Misc/BoldLockUtils.pas | 11 +- Source/Samples/Misc/BoldObjectRetriever.pas | 15 +- .../Samples/ModelLoader/BoldModelLoader.pas | 8 +- .../BoldNewObjectInterceptor.pas | 8 +- .../Samples/SortingGrid/BoldSortingGrid.pas | 20 +- .../SystemComparer/BoldSystemComparer.pas | 155 +- .../SystemDebugger/BoldSystemDebuggerForm.pas | 8 +- .../Samples/UMLPlugins/BoldUMLNameTrimmer.pas | 21 +- .../Unicode/BoldAttributeWideString.pas | 82 +- Source/Samples/Unicode/BoldPMWideString.pas | 21 +- .../Unicode/BoldWideStringControlPack.pas | 59 +- .../Unicode/BoldWideStringInterface.pas | 14 +- .../Core/BoldUMLAbstractModelValidator.pas | 35 +- Source/UMLModel/Core/BoldUMLAttributes.pas | 138 +- Source/UMLModel/Core/BoldUMLModel.inc | 20 +- Source/UMLModel/Core/BoldUMLModel.pas | 1296 ++-- .../UMLModel/Core/BoldUMLModelConverter.pas | 18 +- .../UMLModel/Core/BoldUMLModelDataModule.pas | 7 +- Source/UMLModel/Core/BoldUMLModelSupport.pas | 208 +- Source/UMLModel/Core/BoldUMLModelUpdater.pas | 9 +- .../UMLModel/Core/BoldUMLModelValidator.pas | 291 +- .../UMLModel/Core/BoldUMLModel_Interface.inc | 418 +- Source/UMLModel/Core/BoldUMLOCLValidator.pas | 94 +- Source/UMLModel/Core/BoldUMLUtils.pas | 4 +- .../BoldDerivationExpressionsEditor.pas | 3 + Source/UMLModel/Editor/BoldDragObject.pas | 50 +- Source/UMLModel/Editor/BoldUMLAddTV.pas | 3 + .../Editor/BoldUMLConstraintEditor.pas | 4 +- Source/UMLModel/Editor/BoldUMLModelEdit.pas | 57 +- .../UMLModel/Editor/BoldUMLModelEditForm.pas | 264 +- .../Editor/BoldUMLModelValidationForm.pas | 64 +- Source/UMLModel/Editor/BoldUMLOCLEditor.pas | 8 +- .../Editor/BoldUMLTaggedValuesEditor.pas | 28 +- .../UMLModel/Editor/BoldUMLUsesEditorForm.pas | 4 +- Source/UMLModel/Handles/BoldModel.pas | 45 +- .../UMLModel/Handles/BoldUMLModelStreamer.pas | 61 +- Source/UMLModel/Ide/BoldUMLModelEditReg.pas | 11 +- Source/UMLModel/Ide/BoldUMLModelHandleReg.pas | 4 +- .../ModelLinks/Bld/BoldUMLBldLink.pas | 67 +- .../ModelLinks/Core/BoldUMLModelLink.pas | 7 +- .../Core/BoldUMLModelLinkSupport.pas | 5 + .../ModelMaker/Link/BoldMMLinkReg.pas | 17 +- .../ModelMaker/Link/BoldModelMaker_TLB.pas | 139 +- .../ModelMaker/Link/BoldUMLMMLink.pas | 20 +- .../ModelMaker/MMPlugin/BoldMMExpert.pas | 7 +- .../ModelMaker/MMPlugin/BoldMMPlugin_TLB.pas | 100 +- .../ModelMaker/MMPlugin/BoldMMTVDefGen.pas | 64 +- .../ModelMaker/MMPlugin/BoldMMTVDefGenGUI.pas | 3 + .../ModelMaker/MMPlugin/BoldMMTVDefs.pas | 3 + .../ModelMaker/MMPlugin/BoldMMTVEditor.pas | 3 + .../ModelMaker/MMPlugin/BoldMMTVMemo.pas | 3 + .../ModelMaker/Support/BoldMMImporter.pas | 43 +- .../Rose98/BoldRose98TaggedValues.pas | 53 +- .../Rose98/BoldRose98ptyCreator.pas | 297 +- .../ModelLinks/Rose98/BoldUMLRose98Link.pas | 114 +- .../Rose98/BoldUMLRose98Linkreg.pas | 14 +- .../Rose98/BoldUMLRose98MappingUtils.pas | 42 +- .../Rose98/BoldUMLRose98Support.pas | 17 +- .../UMLModel/ModelLinks/XMI/BoldDTDParser.pas | 79 +- .../ModelLinks/XMI/BoldMOFInterfaces.pas | 3 + .../ModelLinks/XMI/BoldUMLDTDData.pas | 6 +- .../XMI/BoldUMLModelMOFAdapters.pas | 78 +- .../ModelLinks/XMI/BoldUMLXMICommon.pas | 25 +- .../ModelLinks/XMI/BoldUMLXMIImporter.pas | 124 +- .../ModelLinks/XMI/BoldUMLXMILink.pas | 5 +- .../ModelLinks/XMI/BoldUMLXMILinkSupport.pas | 32 +- .../ModelLinks/XMI/BoldUMXMILinkreg.pas | 13 +- .../ModelLinks/XMI/BoldXMI10Exporter.pas | 27 +- Source/UMLModel/Plugins/BoldCodePlugins.pas | 21 +- Source/UMLModel/Plugins/BoldDbPlugins.pas | 45 +- .../Plugins/BoldModelOCLValidatorPlugIn.pas | 5 +- .../Plugins/BoldUMLModelEditPlugIn.pas | 7 +- .../Plugins/BoldUMLPluginCallBacks.pas | 11 +- Source/UMLModel/Plugins/BoldUMLPlugins.pas | 16 +- Source/ValueSpace/Condition/BoldCondition.pas | 72 +- .../BoldObjectSpaceExternalEvents.pas | 125 +- Source/ValueSpace/Id/BoldDefaultId.pas | 53 +- Source/ValueSpace/Id/BoldGlobalId.pas | 6 +- Source/ValueSpace/Id/BoldId.pas | 635 +- Source/ValueSpace/Id/BoldStringId.pas | 10 +- Source/ValueSpace/Id/ValueSpaceConst.pas | 2 +- .../Interfaces/BoldValueInterfaces.pas | 103 +- .../Interfaces/BoldValueSpaceInterfaces.pas | 30 +- .../XMLStreaming/BoldDefaultStreamNames.pas | 54 +- .../XMLStreaming/BoldDefaultXMLStreaming.pas | 333 +- 672 files changed, 55583 insertions(+), 28581 deletions(-) delete mode 100644 Source/BoldAwareGUI/BoldControls/BoldDataSet.UnitDoc delete mode 100644 Source/BoldAwareGUI/BoldControls/BoldDataSet.pas create mode 100644 Source/BoldAwareGUI/ControlPacks/BoldVariantControlPack.pas delete mode 100644 Source/BoldAwareGUI/IDE/BoldDataSetPropertyEditors.pas create mode 100644 Source/Common/Support/BoldIndexCollection.pas create mode 100644 Source/Handles/Core/BoldRawSQLHandle.pas create mode 100644 Source/ObjectSpace/BORepresentation/BoldOSSMessage.pas create mode 100644 Source/Persistence/UniDAC/BoldDatabaseAdapterUniDAC.pas create mode 100644 Source/Persistence/UniDAC/BoldPersistenceHandleUniDAC.pas create mode 100644 Source/Persistence/UniDAC/BoldPersistenceHandleUniDACReg.pas create mode 100644 Source/Persistence/UniDAC/BoldUniDACInterfaces.pas create mode 100644 Source/Persistence/UniDAC/UniDACConsts.pas diff --git a/Bold.dpk b/Bold.dpk index fe59210..155ec5e 100644 --- a/Bold.dpk +++ b/Bold.dpk @@ -88,7 +88,6 @@ contains BoldOclSemantics in 'Source\ObjectSpace\Ocl\BoldOclSemantics.pas', BoldOclSymbolImplementations in 'Source\ObjectSpace\Ocl\BoldOclSymbolImplementations.pas', BoldORed in 'Source\ObjectSpace\Ocl\BoldORed.pas', - BoldRegularExpression in 'Source\ObjectSpace\Ocl\BoldRegularExpression.pas', BoldSSExcept in 'Source\ObjectSpace\Ocl\BoldSSExcept.pas', BoldSSLexU in 'Source\ObjectSpace\Ocl\BoldSSLexU.pas', BoldSSYaccU in 'Source\ObjectSpace\Ocl\BoldSSYaccU.pas', @@ -123,7 +122,6 @@ contains BoldHandle in 'Source\Common\Handles\BoldHandle.pas', BoldDataBlock in 'Source\Common\HTTP\BoldDataBlock.pas', BoldWebConnection in 'Source\Common\HTTP\BoldWebConnection.pas', - BoldAbout in 'Source\Common\IDE\BoldAbout.pas', BoldAbstractPropertyEditors in 'Source\Common\IDE\BoldAbstractPropertyEditors.pas', BoldDefsDT in 'Source\Common\IDE\BoldDefsDT.pas', BoldExpert in 'Source\Common\IDE\BoldExpert.pas', @@ -163,6 +161,7 @@ contains BoldSubscription in 'Source\Common\Subscription\BoldSubscription.pas', BoldBase64 in 'Source\Common\Support\BoldBase64.pas', BoldCollections in 'Source\Common\Support\BoldCollections.pas', + BoldIndexCollection in 'Source\Common\Support\BoldIndexCollection.pas', BoldCommonBitmaps in 'Source\Common\Support\BoldCommonBitmaps.pas', BoldControlPackDefs in 'Source\Common\Support\BoldControlPackDefs.pas', BoldControlsDefs in 'Source\Common\Support\BoldControlsDefs.pas', @@ -223,11 +222,13 @@ contains BoldListHandle in 'Source\Handles\Core\BoldListHandle.pas', BoldOclRepository in 'Source\Handles\Core\BoldOclRepository.pas', BoldOclVariables in 'Source\Handles\Core\BoldOclVariables.pas', + BoldOSSMessage in 'Source\ObjectSpace\BORepresentation\BoldOSSMessage.pas', BoldPlaceableSubscriber in 'Source\Handles\Core\BoldPlaceableSubscriber.pas', BoldReferenceHandle in 'Source\Handles\Core\BoldReferenceHandle.pas', BoldRootedHandles in 'Source\Handles\Core\BoldRootedHandles.pas', BoldSortedHandle in 'Source\Handles\Core\BoldSortedHandle.pas', BoldSQLHandle in 'Source\Handles\Core\BoldSQLHandle.pas', + BoldRawSQLHandle in 'Source\Handles\Core\BoldRawSQLHandle.pas', BoldSystemHandle in 'Source\Handles\Core\BoldSystemHandle.pas', BoldVariableDefinition in 'Source\Handles\Core\BoldVariableDefinition.pas', BoldVariableHandle in 'Source\Handles\Core\BoldVariableHandle.pas', diff --git a/Bold.dproj b/Bold.dproj index 218c111..a800311 100644 --- a/Bold.dproj +++ b/Bold.dproj @@ -7,19 +7,19 @@ 1 Package VCL - 16.1 + 19.2 Win32 true - - true + + true Base true - - true + + true Base true @@ -62,16 +62,18 @@ true false - - package=com.embarcadero.$(MSBuildProjectName);label=$(MSBuildProjectName);versionCode=1;versionName=1.0.0;persistent=False;restoreAnyVersion=False;installLocation=preferExternal;largeHeap=False;theme=TitleBar;hardwareAccelerated=true - Debug - - CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments= + CompanyName=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName);FileDescription=$(MSBuildProjectName);ProductName=$(MSBuildProjectName) System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) 1033 true + + System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;$(DCC_Namespace) + Debug + true + CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments= + false RELEASE;$(DCC_Define) @@ -85,7 +87,7 @@ BOLD_DELPHI;$(DCC_Define) - CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments= + CompanyName=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName);FileDescription=$(MSBuildProjectName);ProductName=$(MSBuildProjectName) true @@ -146,7 +148,6 @@ - @@ -181,7 +182,6 @@ - @@ -221,6 +221,7 @@ + @@ -281,11 +282,13 @@ + + @@ -446,9 +449,6 @@ - False - False - False True False diff --git a/BoldComGUI.dpk b/BoldComGUI.dpk index 32bfb08..6a0aac1 100644 --- a/BoldComGUI.dpk +++ b/BoldComGUI.dpk @@ -31,7 +31,6 @@ package BoldComGUI; requires vcl, - VclJpg, Bold, BoldCom, DesignIDE; diff --git a/BoldUDPProp.dpk b/BoldUDPProp.dpk index c156cc2..fdf8478 100644 --- a/BoldUDPProp.dpk +++ b/BoldUDPProp.dpk @@ -31,7 +31,8 @@ package BoldUDPProp; requires vcl, - Indy9v, + IndySystem, + IndyCore, Bold; contains diff --git a/BoldUtility.dpk b/BoldUtility.dpk index 5eeb76f..65ae893 100644 --- a/BoldUtility.dpk +++ b/BoldUtility.dpk @@ -46,19 +46,20 @@ contains BoldSelectionListBox in 'Source\Samples\BoldCheckListBox\BoldSelectionListBox.pas', BoldSelectionListBoxReg in 'Source\Samples\BoldCheckListBox\BoldSelectionListBoxReg.pas', BoldFormSaver in 'Source\Samples\FormSaver\BoldFormSaver.pas', +{ + BoldAttributeWideString in 'Source\Samples\Unicode\BoldAttributeWideString.pas', + BoldPMWideString in 'Source\Samples\Unicode\BoldPMWideString.pas', + BoldWideStringControlPack in 'Source\Samples\Unicode\BoldWideStringControlPack.pas', + BoldWideStringInterface in 'Source\Samples\Unicode\BoldWideStringInterface.pas', +} BoldEditOCLActionPropEditor in 'Source\Samples\IDE\BoldEditOCLActionPropEditor.pas', BoldSamplesReg in 'Source\Samples\IDE\BoldSamplesReg.pas', BoldLockUtils in 'Source\Samples\Misc\BoldLockUtils.pas', BoldObjectRetriever in 'Source\Samples\Misc\BoldObjectRetriever.pas', BoldModelLoader in 'Source\Samples\ModelLoader\BoldModelLoader.pas', BoldNewObjectInterceptor in 'Source\Samples\NewObjectInterceptor\BoldNewObjectInterceptor.pas', - BoldSortingGrid in 'Source\Samples\SortingGrid\BoldSortingGrid.pas', BoldSystemComparer in 'Source\Samples\SystemComparer\BoldSystemComparer.pas', BoldSystemDebuggerForm in 'Source\Samples\SystemDebugger\BoldSystemDebuggerForm.pas', - BoldUMLNameTrimmer in 'Source\Samples\UMLPlugins\BoldUMLNameTrimmer.pas', - BoldAttributeWideString in 'Source\Samples\Unicode\BoldAttributeWideString.pas', - BoldPMWideString in 'Source\Samples\Unicode\BoldPMWideString.pas', - BoldWideStringControlPack in 'Source\Samples\Unicode\BoldWideStringControlPack.pas', - BoldWideStringInterface in 'Source\Samples\Unicode\BoldWideStringInterface.pas'; + BoldUMLNameTrimmer in 'Source\Samples\UMLPlugins\BoldUMLNameTrimmer.pas'; end. diff --git a/BoldVCLGUI.dpk b/BoldVCLGUI.dpk index 3d93cff..f9d804f 100644 --- a/BoldVCLGUI.dpk +++ b/BoldVCLGUI.dpk @@ -32,14 +32,12 @@ package BoldVCLGUI; requires vcl, DesignIDE, - VclJpg, Bold; contains BoldCaptionController in 'Source\BoldAwareGUI\BoldControls\BoldCaptionController.pas', BoldCheckBox in 'Source\BoldAwareGUI\BoldControls\BoldCheckBox.pas', BoldComboBox in 'Source\BoldAwareGUI\BoldControls\BoldComboBox.pas', - BoldDataSet in 'Source\BoldAwareGUI\BoldControls\BoldDataSet.pas', BoldDragDropTarget in 'Source\BoldAwareGUI\BoldControls\BoldDragDropTarget.pas', BoldEdit in 'Source\BoldAwareGUI\BoldControls\BoldEdit.pas', BoldGrid in 'Source\BoldAwareGUI\BoldControls\BoldGrid.pas', @@ -63,6 +61,7 @@ contains BoldCheckboxStateControlPack in 'Source\BoldAwareGUI\ControlPacks\BoldCheckboxStateControlPack.pas', BoldControllerListControlPack in 'Source\BoldAwareGUI\ControlPacks\BoldControllerListControlPack.pas', BoldControlPack in 'Source\BoldAwareGUI\ControlPacks\BoldControlPack.pas', + BoldVariantControlPack in 'Source\BoldAwareGUI\ControlPacks\BoldVariantControlPack.pas', BoldDateTimeControlPack in 'Source\BoldAwareGUI\ControlPacks\BoldDateTimeControlPack.pas', BoldElementHandleFollower in 'Source\BoldAwareGUI\ControlPacks\BoldElementHandleFollower.pas', BoldFloatControlPack in 'Source\BoldAwareGUI\ControlPacks\BoldFloatControlPack.pas', @@ -86,7 +85,6 @@ contains BoldAwareGuiReg in 'Source\BoldAwareGUI\IDE\BoldAwareGuiReg.pas', BoldComboBoxPropertyEditors in 'Source\BoldAwareGUI\IDE\BoldComboBoxPropertyEditors.pas', BoldControlPackPropertyEditors in 'Source\BoldAwareGUI\IDE\BoldControlPackPropertyEditors.pas', - BoldDataSetPropertyEditors in 'Source\BoldAwareGUI\IDE\BoldDataSetPropertyEditors.pas', BoldGridPropertyEditors in 'Source\BoldAwareGUI\IDE\BoldGridPropertyEditors.pas', BoldNodeDescriptionEditor in 'Source\BoldAwareGUI\IDE\BoldNodeDescriptionEditor.pas', BoldPropertiesControllerPropertyEditors in 'Source\BoldAwareGUI\IDE\BoldPropertiesControllerPropertyEditors.pas'; diff --git a/Source/BoldAwareGUI/BoldControls/BoldCaptionController.pas b/Source/BoldAwareGUI/BoldControls/BoldCaptionController.pas index e8293cf..767e8cd 100644 --- a/Source/BoldAwareGUI/BoldControls/BoldCaptionController.pas +++ b/Source/BoldAwareGUI/BoldControls/BoldCaptionController.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldCaptionController; {$UNDEF BOLDCOMCLIENT} @@ -7,12 +10,13 @@ interface uses Classes, Controls, - BoldEnvironmentVCL, // Make sure VCL environement loaded, and finalized after + BoldEnvironmentVCL, BoldHandles, BoldElementHandleFollower, BoldElements, BoldControlPack, - BoldStringControlPack; + BoldStringControlPack, + BoldDefs; type TBoldCustomCaptionController = class; @@ -27,8 +31,8 @@ TBoldCustomCaptionController = class(TComponent, IBoldOCLComponent) fHandleFollower: TBoldElementHandleFollower; fTrackControl: TWinControl; function GetContextType: TBoldElementTypeInfo; - procedure SetExpression(Expression: String); - function GetExpression: String; + procedure SetExpression(const Value: TBoldExpression); + function GetExpression: TBoldExpression; function GetVariableList: TBoldExternalVariableList; function GetBoldHandle: TBoldElementHandle; @@ -65,7 +69,8 @@ TBoldCaptionController = class(TBoldCustomCaptionController) implementation uses - SysUtils; + SysUtils, + BoldRev; type {---TWinControlWithCaption---} @@ -110,7 +115,7 @@ procedure TBoldCustomCaptionController.SetCaption(s: TCaption); (s <> TrackedCaption) then begin fCaption := s; - TrackedCaption := Caption; //TrackedCaption ensures valid fTrackControl + TrackedCaption := Caption; end; end; @@ -119,7 +124,7 @@ procedure TBoldCustomCaptionController.SetTrackControl(Control: TWinControl); if Control <> fTrackControl then begin fTrackControl := Control; - Caption := Caption; //Update caption if new Control; + Caption := Caption; end; end; @@ -167,15 +172,14 @@ function TBoldCustomCaptionController.GetContextType: TBoldElementTypeInfo; result := nil; end; -function TBoldCustomCaptionController.GetExpression: String; +function TBoldCustomCaptionController.GetExpression: TBoldExpression; begin result := BoldProperties.Expression; - end; -procedure TBoldCustomCaptionController.SetExpression(Expression: String); +procedure TBoldCustomCaptionController.SetExpression(const Value: TBoldExpression); begin - BoldProperties.Expression := Expression; + BoldProperties.Expression := Value; end; function TBoldCustomCaptionController.GetVariableList: TBoldExternalVariableList; @@ -183,5 +187,6 @@ function TBoldCustomCaptionController.GetVariableList: TBoldExternalVariableList result := BoldProperties.VariableList; end; -end. +initialization +end. diff --git a/Source/BoldAwareGUI/BoldControls/BoldCheckBox.pas b/Source/BoldAwareGUI/BoldControls/BoldCheckBox.pas index fdcbfea..cd2ffe9 100644 --- a/Source/BoldAwareGUI/BoldControls/BoldCheckBox.pas +++ b/Source/BoldAwareGUI/BoldControls/BoldCheckBox.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldCheckBox; {$UNDEF BOLDCOMCLIENT} @@ -9,12 +12,13 @@ interface Classes, Controls, StdCtrls, - BoldEnvironmentVCL, // Make sure VCL environement loaded, and finalized after + BoldEnvironmentVCL, BoldHandles, BoldElementHandleFollower, BoldElements, BoldControlPack, - BoldCheckboxStateControlPack; + BoldCheckboxStateControlPack, + BoldDefs; type TBoldCustomCheckBox = class; @@ -29,8 +33,8 @@ TBoldCustomCheckBox = class(TCustomCheckBox, IBoldOCLComponent) fHandleFollower: TBoldElementHandleFollower; fMyReadOnly: Boolean; function GetContextType: TBoldElementTypeInfo; - procedure SetExpression(Expression: String); - function GetExpression: String; + procedure SetExpression(const Value: TBoldExpression); + function GetExpression: TBoldExpression; function GetVariableList: TBoldExternalVariableList; function GetBoldHandle: TBoldElementHandle; @@ -116,9 +120,7 @@ implementation uses SysUtils, - BoldDefs, - BoldControlPackDefs, - BoldGuiResourceStrings; + BoldControlPackDefs; {---TBoldCustomCheckBox---} constructor TBoldCustomCheckBox.Create(AOwner: TComponent); @@ -177,7 +179,7 @@ procedure TBoldCustomCheckBox.SetState(v: TCheckBoxState); Perform(CM_CHANGED, 0, 0); end else - raise EBold.CreateFmt(sStateNotModifiable, [ClassName]); + raise EBold.CreateFmt('%s.State: Not modifiable', [ClassName]); end; end; @@ -241,14 +243,14 @@ function TBoldCustomCheckBox.GetContextType: TBoldElementTypeInfo; result := nil; end; -function TBoldCustomCheckBox.GetExpression: String; +function TBoldCustomCheckBox.GetExpression: TBoldExpression; begin result := BoldProperties.Expression; end; -procedure TBoldCustomCheckBox.SetExpression(Expression: String); +procedure TBoldCustomCheckBox.SetExpression(const Value: TBoldExpression); begin - BoldProperties.Expression := Expression; + BoldProperties.Expression := Value; end; function TBoldCustomCheckBox.GetVariableList: TBoldExternalVariableList; @@ -256,4 +258,6 @@ function TBoldCustomCheckBox.GetVariableList: TBoldExternalVariableList; result := BoldProperties.VariableList; end; +initialization + end. diff --git a/Source/BoldAwareGUI/BoldControls/BoldComboBox.pas b/Source/BoldAwareGUI/BoldControls/BoldComboBox.pas index a60d805..63ce9ae 100644 --- a/Source/BoldAwareGUI/BoldControls/BoldComboBox.pas +++ b/Source/BoldAwareGUI/BoldControls/BoldComboBox.pas @@ -1,6 +1,10 @@ +///////////////////////////////////////////////////////// + + unit BoldComboBox; {$UNDEF BOLDCOMCLIENT} +{$INCLUDE bold.inc} interface @@ -16,6 +20,7 @@ interface BoldEnvironmentVCL, // Make sure VCL environement loaded, and finalized after BoldDefs, BoldControlsDefs, + BoldControlPackDefs, BoldHandles, BoldElements, BoldAbstractListHandle, @@ -38,10 +43,12 @@ TBoldComboBox = class; TBoldComboListController = class(TBoldAbstractListAsFollowerListController) published + property DragMode; + property DropMode; property NilElementMode; end; - TBoldCustomComboBox = class(TCustomComboBox, IBoldValidateableComponent) + TBoldCustomComboBox = class(TCustomComboBox, IBoldValidateableComponent, IBoldOCLComponent) private fAlignment: TAlignment; fHandleFollower: TBoldElementHandleFollower; @@ -51,6 +58,7 @@ TBoldCustomComboBox = class(TCustomComboBox, IBoldValidateableComponent) fBoldRowProperties: TBoldStringFollowerController; fBoldSelectChangeAction: TBoldComboSelectChangeAction; fBoldSetValueExpression: TBoldExpression; + fInternalChange: boolean; fColor: TColor; fEffectiveReadOnly: Boolean; fFocused: Boolean; @@ -60,15 +68,18 @@ TBoldCustomComboBox = class(TCustomComboBox, IBoldValidateableComponent) fReadOnly: Boolean; fOnSelectChanged: TNotifyEvent; fIsEditEvent: boolean; + fProcessingClick: Integer; fOnSelectChangedIsCalled:Boolean; + fAutoSearch: boolean; function GetBoldHandle: TBoldElementHandle; procedure SetBoldHandle(value: TBoldElementHandle); function GetFollower: TBoldFOllower; function GetBoldListHandle: TBoldAbstractListHandle; procedure SetBoldListHandle(value: TBoldAbstractListHandle); function GetListFollower: TBoldFOllower; - procedure _InsertItem(Follower: TBoldFollower); + procedure _InsertItem(Index: Integer; Follower: TBoldFollower); procedure _DeleteItem(Index: Integer; OwningFollower: TBoldFollower); + procedure _ReplaceItem(index: Integer; AFollower: TBoldFollower); procedure _RowAfterMakeUptoDate(Follower: TBoldFollower); procedure _AfterMakeUptoDate(Follower: TBoldFollower); procedure FontChanged(Sender: TObject); @@ -102,6 +113,12 @@ TBoldCustomComboBox = class(TCustomComboBox, IBoldValidateableComponent) {$IFNDEF BOLDCOMCLIENT} function ValidateComponent(ComponentValidator: TBoldComponentValidator; NamePrefix: String): Boolean; {$ENDIF} + procedure WMChar(var Message: TWMChar); message WM_CHAR; + {IBoldOCLComponent} + function GetContextType: TBoldElementTypeInfo; + procedure SetExpression(const Value: TBoldExpression); + function GetVariableList: TBoldExternalVariableList; + function GetExpression: TBoldExpression; protected function HandleApplyException(E: Exception; Elem: TBoldElement; var discard: Boolean): boolean; procedure Change; override; @@ -139,6 +156,8 @@ TBoldCustomComboBox = class(TCustomComboBox, IBoldValidateableComponent) // property Items write SetItems; property ReadOnly: Boolean read FReadOnly write SetReadOnly default False; property Text: string read GetText write SetText; + procedure Click; override; + public constructor Create(AOwner: TComponent); override; destructor Destroy; override; @@ -224,9 +243,9 @@ implementation {$IFNDEF BOLDCOMCLIENT} BoldSystem, {$ENDIF} - BoldControlPackDefs, BoldListControlPack, BoldQueue, + BoldUtils, BoldGuiResourceStrings; { TBoldCustomComboBox } @@ -234,10 +253,17 @@ implementation type TWinControlHack = class(TWinControl) {We need access to Parents Font and Color property} end; + TBoldQueueableAccess = class(TBoldQueueable); + TBoldElementHandleAccess = class(TBoldElementHandle); -procedure TBoldCustomComboBox._InsertItem(Follower: TBoldFollower); +procedure TBoldCustomComboBox._InsertItem(Index: Integer; Follower: TBoldFollower); begin - Items.Insert(Follower.Index, ''); + Items.Insert(Index, ''); + if Assigned(Follower) then + begin + Follower.EnsureDisplayable; + Items[index] := TBoldStringFollowerController(Follower.Controller).GetCurrentAsString(Follower); + end; end; procedure TBoldCustomComboBox._DeleteItem(index: Integer; OwningFollower: TBoldFollower); @@ -245,13 +271,26 @@ procedure TBoldCustomComboBox._DeleteItem(index: Integer; OwningFollower: TBoldF Items.Delete(index); end; +procedure TBoldCustomComboBox._ReplaceItem(index: Integer; + AFollower: TBoldFollower); +var + s: string; +begin + AFollower.EnsureDisplayable; + s := TBoldStringFollowerController(AFollower.Controller).GetCurrentAsString(AFollower); + if s <> Items[index] then + Items[index] := s; +end; + procedure TBoldCustomComboBox._RowAfterMakeUptoDate(Follower: TBoldFollower); var index: Integer; begin index := Follower.index; if (index > -1) and (index < Items.Count) then + begin Items[index] := TBoldStringFollowerController(Follower.Controller).GetCurrentAsString(Follower); + end; Invalidate; // forces a redisplay of the edit-area, the windows component might go blank if the active row is removed and then reinserted fHandleFollower.Follower.MarkValueOutOfDate; @@ -266,12 +305,19 @@ procedure TBoldCustomComboBox._AfterMakeUptoDate(Follower: TBoldFollower); // if not (Style = csSimple) and DroppedDown then // PostMessage(Handle, CB_SHOWDROPDOWN, 0, 0); //FIXME Bad solution! CloseUp if changed while dropped down! - UpdateEffectiveColor; - UpdateEffectiveReadOnly; - UpdateEffectiveFont; - NewText := BoldProperties.GetCurrentAsString(Follower); - if inherited Text <> NewText then - SetEffectiveText(NewText); + if not fInternalChange then + begin + UpdateEffectiveColor; + UpdateEffectiveReadOnly; + UpdateEffectiveFont; + NewText := BoldProperties.GetCurrentAsString(Follower); + if inherited Text <> NewText then + begin + fInternalChange := true; + SetEffectiveText(NewText); + fInternalChange := false; + end; + end; end; procedure TBoldCustomComboBox.Change; @@ -306,7 +352,9 @@ procedure TBoldCustomComboBox.CMEnter(var Message: TCMEnter); procedure TBoldCustomComboBox.CMExit(var Message: TCMExit); begin if not (csDestroying in ComponentState) and (Follower.Controller.ApplyPolicy = bapExit) then + begin Follower.Apply; + end; SetFocused(False); inherited; end; @@ -328,7 +376,9 @@ procedure TBoldCustomComboBox.CMParentFontChanged(var Message: TMessage); if ParentFont then begin if Message.wParam <> 0 then +{$WARN UNSAFE_CAST OFF} SetFont(TFont(Message.lParam)) +{$WARN UNSAFE_CAST ON} else SetFont(TWinControlHack(Parent).Font); ParentFont := True; @@ -359,11 +409,9 @@ constructor TBoldCustomComboBox.Create(AOwner: TComponent); fBoldRowProperties.AfterMakeUptoDate := _RowAfterMakeUptoDate; fBoldRowProperties.OnGetContextType := GetContextForBoldRowProperties; fBoldListProperties := TBoldComboListController.Create(Self, fBoldRowProperties); - with fBoldListProperties do - begin - OnAfterInsertItem := _InsertItem; - OnAfterDeleteItem := _DeleteItem; - end; + fBoldListProperties.OnAfterInsertItem := _InsertItem; + fBoldListProperties.OnAfterDeleteItem := _DeleteItem; + fBoldListProperties.OnReplaceitem := _ReplaceItem; fHandleFollower := TBoldElementHandleFollower.Create(Owner, fBoldProperties); fListHandleFollower := TBoldListHandleFollower.Create(Owner, fBoldListProperties); fHandleFollower.PrioritizedQueuable := fListHandleFollower; @@ -481,6 +529,26 @@ function TBoldCustomComboBox.GetText: string; end; end; +function TBoldCustomComboBox.GetContextType: TBoldElementTypeInfo; +begin + result := GetContextForBoldProperties; +end; + +function TBoldCustomComboBox.GetExpression: TBoldExpression; +begin + result := self.BoldProperties.Expression; +end; + +procedure TBoldCustomComboBox.SetExpression(const Value: TBoldExpression); +begin + BoldProperties.Expression := Value; +end; + +function TBoldCustomComboBox.GetVariableList: TBoldExternalVariableList; +begin + result := BoldProperties.VariableList; +end; + function TBoldCustomComboBox.IsColorStored: Boolean; begin Result := not ParentColor; @@ -499,17 +567,26 @@ procedure TBoldCustomComboBox.KeyDown(var Key: Word; Shift: TShiftState); end; procedure TBoldCustomComboBox.KeyPress(var Key: Char); +var + Message: TMessage; +// lWideChar: WideChar; +// s: string; +// lKey: Char; begin inherited KeyPress(Key); - if (Key in [#32..#255]) then + if CharInSet(Key, [#32..#255]) then begin +{ lWideChar := GetWideCharFromWMCharMsg(LastWMCHarMessage); + s := lWideChar; + lKey := s[1]; if (Style <> csDropDownList) and (BoldSelectChangeAction <> bdcsSetReference) and - not BoldProperties.ValidateCharacter(Key, Follower) then + not BoldProperties.ValidateCharacter(lKey, Follower) then begin MessageBeep(0); Key := BOLDNULL; end; +} end; if Key = BOLDESC then begin @@ -517,13 +594,33 @@ procedure TBoldCustomComboBox.KeyPress(var Key: Char); SelectAll; Key := BOLDNULL; end; + if (Ord(Key) = 9) and DroppedDown then + begin + Message.Msg := CB_SETCURSEL; +{$WARN UNSAFE_CAST OFF} + TWMCommand(Message).NotifyCode := CBN_SELCHANGE; +{$WARN UNSAFE_CAST ON} + WndProc(Message); +// fAutoSearch := true; + + +// if ((Message.Msg = CB_SETCURSEL) and (BoldSelectChangeAction = bdcsSetReference)) or (TWMCommand(Message).NotifyCode = CBN_SELCHANGE) or (fAutoSearch) and not DroppedDown then +// if not (DroppedDown and (Message.Msg = 273) and (TWMCommand(Message).NotifyCode = CBN_SELCHANGE)) then + +// PostMessage(Handle, CBN_CLOSEUP, 0, 0); //FIXME Bad solution! CloseUp if changed while dropped down! +// CloseUp; +// Invalidate; +// Follower.Apply; +// SelectAll; + end; + if Follower.IsInDisplayList then + Follower.DisplayAll; end; procedure TBoldCustomComboBox.SetBoldHandle(Value: TBoldElementHandle); begin - if assigned(Value) and (BoldSelectChangeAction = bdcsSetReference) and - not (Value is TBoldReferenceHandle) then - raise EBold.Create(sHandleMustBeReferenceHandle); + if assigned(Value) and (BoldSelectChangeAction = bdcsSetReference) and not Value.CanSetValue then + raise EBold.CreateFMt('The BoldHandle property must be a TBoldReferenceHandle when BoldSelectChangeAction is bdscSetReference. It is %s', [Value.ClassName]); fHandleFollower.BoldHandle := value; end; @@ -679,18 +776,38 @@ procedure TBoldCustomComboBox.WndProc(var Message: TMessage); Discard: Boolean; LocalSelectedElement: TBoldElement; begin +{$WARN UNSAFE_CAST OFF} CallInherited := True; if not (csDesigning in ComponentState) then begin case Message.Msg of CB_SETCURSEL, - WM_COMMAND: - if ((Message.Msg = CB_SETCURSEL) and (BoldSelectChangeAction = bdcsSetReference)) or - (TWMCommand(Message).NotifyCode = CBN_SELCHANGE) then + WM_COMMAND, + 305: + begin +// CodeSite.Category := 'combo'; +// CodeSite.Send(IntToStr(Message.Msg) + ':' + IntToStr(TWMCommand(Message).NotifyCode)); +// CodeSite.Category := ''; + +// ( fAutoSearch and DroppedDown and (Message.Msg = CB_SETCURSEL) and (BoldSelectChangeAction = bdcsSetValue) and (TWMCommand(Message).NotifyCode = 0) ) + if not ((Message.Msg = 334) and (TWMCommand(Message).NotifyCode = 0) and not fAutoSearch) then + if ( + ( ( (Message.Msg = CB_SETCURSEL) and (BoldSelectChangeAction = bdcsSetReference) ) or (TWMCommand(Message).NotifyCode = CBN_SELCHANGE) or (fAutoSearch) and not DroppedDown) + or ((Message.Msg = 305) and DroppedDown) +// or (not (DroppedDown and (Message.Msg = WM_COMMAND) and (TWMCommand(Message).NotifyCode = CBN_SELCHANGE))) + or ( (Message.Msg = WM_COMMAND) and (TWMCommand(Message).NotifyCode = CBN_SELCHANGE) ) + ) + and not ( (Message.Msg = WM_COMMAND) and ( TWMCommand(Message).NotifyCode = 256 ) ) + and not ( (Message.Msg = WM_COMMAND) and ( TWMCommand(Message).NotifyCode = 1024 ) ) + and not ( (Message.Msg = WM_COMMAND) and ( TWMCommand(Message).NotifyCode = 3 ) ) +// and not ( (Message.Msg = WM_COMMAND) and ( TWMCommand(Message).NotifyCode = 1 ) ) + and not fInternalChange + then begin - if (Message.Msg = CB_SETCURSEL) and assigned(BoldListHandle) and (BoldListHandle.Count > Message.WParam) then +// CodeSite.Send(IntToStr(Message.Msg) + ':' + IntToStr(TWMCommand(Message).NotifyCode)); + if (Message.Msg = CB_SETCURSEL) and assigned(BoldListHandle) and (Cardinal(BoldListHandle.Count) > Message.WParam) then begin - if Message.WParam = -1 then + if NativeInt(Message.WParam) = -1 then LocalSelectedElement := nil else LocalSelectedElement := BoldListHandle.List[Message.WParam] @@ -703,7 +820,6 @@ procedure TBoldCustomComboBox.WndProc(var Message: TMessage); CallInherited := not EffectiveReadOnly; bdcsSetValue: begin - Follower.DiscardChange; if Assigned(BoldHandle) and Assigned(BoldHandle.value) then begin {$IFDEF BOLDCOMCLIENT} // BoldSetValueExpression @@ -724,7 +840,23 @@ procedure TBoldCustomComboBox.WndProc(var Message: TMessage); (not (elementToAssignTo is TBoldMember) or TBoldMember(ElementTOAssignTo).CanModify) then try - ElementToAssignTo.Assign(LocalSelectedElement); // checkme take from follwer instead? + if elementToAssignTo is TBoldObjectReference then + begin + ElementToAssignTo.Assign(LocalSelectedElement); + end + else + begin + if Assigned(LocalSelectedElement) then + BoldProperties.MayHaveChanged(LocalSelectedElement.AsString, Follower) + else + BoldProperties.MayHaveChanged('', Follower); + fInternalChange := true; + try + TBoldQueueableAccess(Follower).Display; + finally + fInternalChange := false; + end; + end; except on E: Exception do begin @@ -736,13 +868,13 @@ procedure TBoldCustomComboBox.WndProc(var Message: TMessage); end; {$ENDIF} end; - CallInherited := false; + CallInherited := true; end; bdcsSetReference: begin Follower.DiscardChange; - if assigned(BoldHandle) and (BoldHandle is TBoldReferenceHandle) then - (BoldHandle as TBoldReferenceHandle).Value := LocalSelectedElement; + if assigned(BoldHandle) and BoldHandle.CanSetValue then + TBoldElementHandleAccess(BoldHandle).SetValue(LocalSelectedElement); CallInherited := Message.Msg = CB_SETCURSEL; end; bdcsSetListIndex: @@ -779,7 +911,7 @@ procedure TBoldCustomComboBox.WndProc(var Message: TMessage); end; end; end; - + end; CB_SHOWDROPDOWN: if (Message.WParam=0) and EffectiveReadOnly then _AfterMakeUptoDate(Follower); {Restore text} //FIXME Maybe an UpdateEffectiveText? @@ -787,6 +919,7 @@ procedure TBoldCustomComboBox.WndProc(var Message: TMessage); end; if CallInherited then inherited WndProc(Message); +{$WARN UNSAFE_CAST ON} end; procedure TBoldCustomComboBox.SetBoldListProperties(Value: TBoldComboListController); @@ -795,14 +928,24 @@ procedure TBoldCustomComboBox.SetBoldListProperties(Value: TBoldComboListControl end; function TBoldCustomComboBox.GetSelectedElement: TBoldElement; +var + lFollower: TBoldFollower; begin +{$WARN UNSAFE_CAST OFF} with ListFollower.RendererData as TBoldFollowerList do begin if (ItemIndex >= 0)and (ItemIndex < Count) then - Result := Followers[ItemIndex].Element + begin + lFollower := Followers[ItemIndex]; + if Assigned(lFollower) then + Result := lFollower.Element + else + result := nil; + end else Result := nil; end; +{$WARN UNSAFE_CAST ON} end; function TBoldCustomComboBox.GetBoldHandle: TBoldElementHandle; @@ -812,7 +955,7 @@ function TBoldCustomComboBox.GetBoldHandle: TBoldElementHandle; function TBoldCustomComboBox.GetFollower: TBoldFOllower; begin - Result := fHandleFollower.Follower; + Result := fHandleFollower.Follower; end; function TBoldCustomComboBox.GetBoldListHandle: TBoldAbstractListHandle; @@ -822,7 +965,7 @@ function TBoldCustomComboBox.GetBoldListHandle: TBoldAbstractListHandle; function TBoldCustomComboBox.GetListFollower: TBoldFOllower; begin - Result := fListHandleFollower.Follower; + Result := fListHandleFollower.Follower; end; function TBoldCustomComboBox.GetContextForBoldProperties: TBoldElementTypeInfo; @@ -862,9 +1005,8 @@ function TBoldCustomComboBox.ValidateComponent(ComponentValidator: TBoldComponen procedure TBoldCustomComboBox.SetBoldSelectChangeAction(Value: TBoldComboSelectChangeAction); begin - if (Value = bdcsSetReference) and assigned(BoldHandle) and - not (BoldHandle is TBoldReferenceHandle) then - raise EBold.Create(sChangeActionCannotBeSetReference); + if (Value = bdcsSetReference) and assigned(BoldHandle) and not BoldHandle.CanSetValue then + raise EBold.Create('The BoldSelectChangeAction property can not be bdscSetReference when BoldHandle is not a TBoldReferenceHandle'); fBoldSelectChangeAction := Value; end; @@ -888,4 +1030,37 @@ function TBoldCustomComboBox.HandleApplyException(E: Exception; Elem: TBoldEleme ExceptionHandler.HandleApplyException(E, self, Elem, Discard, Result); end; +procedure TBoldCustomComboBox.Click; +var + aMsg: TWMCommand; +begin + Inc(fProcessingClick); + try + inherited; + if fProcessingClick=1 then + begin + with aMsg do begin + Msg := WM_COMMAND; + NotifyCode := CBN_SELCHANGE; + ItemID := ItemIndex; + Ctl := Handle; + Result := 0; + end; +{$WARN UNSAFE_CAST OFF} + WndProc(TMessage(aMsg)); +{$WARN UNSAFE_CAST ON} + end; + finally + Dec(fProcessingClick); + end; +end; + +procedure TBoldCustomComboBox.WMChar(var Message: TWMChar); +begin + fAutoSearch := true; + inherited; + fAutoSearch := false; +end; + end. + diff --git a/Source/BoldAwareGUI/BoldControls/BoldDataSet.UnitDoc b/Source/BoldAwareGUI/BoldControls/BoldDataSet.UnitDoc deleted file mode 100644 index 1bb7a51..0000000 --- a/Source/BoldAwareGUI/BoldControls/BoldDataSet.UnitDoc +++ /dev/null @@ -1,556 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - A handle containing the list of objects that should be exposed as a Dataset - The objects in the ListHandle will make up the rows in the dataset - - - Returns the model information for a field in the dataset - If the field refered to by the parameter exists, and contains an attribute or a role, the model information about this value is returned. If the field contains a calculated value (such as aPerson.firstName + ' ' + aPerson.lastName), the result is nil - - - - - - - - - - - - A collection of field descriptions that make up the dataset - - - - - - - - - - - This version of the Bold Dataset is intended for subclassing - - - - Exposes a list of objects as a TDataset to be used with reporting tools or other Dataset aware components - This components allows a list of bold objects to be exposed as a TDataset so that they can be displayed/edited by the rich set of db aware components available in Delphi and as third party components. - - - There is an example in the example folder that shows how to use the TBoldDataSet component with a reporting tool (QuickReport) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - The BoldProperties contains the OCL expression that is used to calculate the value of the field - - - - - - - - - - - - - - - Identical to BoldProperties.Expression - Identical to BoldProperties.Expression - - - - - - - The name of the field - The name of the field - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Source/BoldAwareGUI/BoldControls/BoldDataSet.pas b/Source/BoldAwareGUI/BoldControls/BoldDataSet.pas deleted file mode 100644 index e81898c..0000000 --- a/Source/BoldAwareGUI/BoldControls/BoldDataSet.pas +++ /dev/null @@ -1,1785 +0,0 @@ -unit BoldDataSet; - -interface - -uses - Classes, - DB, - BoldEnvironmentVCL, // Make sure VCL environement loaded, and finalized after - BoldSystem, - BoldSystemRT, - BoldElements, - BoldSubscription, - BoldAbstractListHandle, - BoldListListControlPack, - BoldControlPack, - BoldControllerListControlPack, - BoldStringControlPack, - BoldListHandleFollower; - -type - TBDSBookmarkInfo = record - Flag: TBookmarkFlag; - Element: TBoldElement; - end; - - PBDSBookmarkInfo = ^TBDSBookmarkInfo; - - TBoldAbstractDataSet = class; - TBoldDataSet = class; - TBoldDataSetFieldDescription = class; - TBoldDataSetFieldDescriptions = class; - - { TBoldDataSetFieldDescription } - TBoldDataSetFieldDescription = class(TCollectionItem) - private - fRTInfo: TBoldMemberRTInfo; - fBoldProperties: TBoldStringFollowerController; - fBufferSize: integer; - fFieldName: string; - fFieldOfs: integer; - fFieldSize: integer; - fFieldType: TFieldType; - fRequired: boolean; - fUseFieldSize: boolean; - fInvalid: Boolean; - function GetDataSet: TBoldAbstractDataSet; - function GetExpression: string; - function GetFieldDescriptions: TBoldDataSetFieldDescriptions; - function GetListElementType: TBoldElementTypeInfo; - procedure SetBoldProperties(AValue: TBoldStringFollowerController); - procedure SetExpression(AValue: string); - function GetFieldOfs: integer; - function GetFieldSize: integer; - function GetFieldType: TFieldType; - function GetRequired: boolean; - function GetRTInfo: TBoldMemberRTInfo; - function GetUseFieldSize: boolean; - procedure SetFieldName(const Value: String); - function GetEffectiveFieldName: String; - procedure Invalidate; - procedure EnsureValid; - procedure AfterMakeUptoDate(Follower: TBoldFollower); - procedure DefineFieldType(aClass: TClass); - protected - function GetDisplayName: string; override; - public - constructor Create(AOwner: TCollection); override; - destructor Destroy; override; - procedure Assign(Source: TPersistent); override; - property BufferSize: integer read FBuffersize; - property EffectiveFieldName: String read GetEffectiveFieldName; - property FieldSize: integer read GetFieldSize; - property FieldType: TFieldType read GetFieldType; - property FieldOfs: integer read GetFieldOfs; - property ListelementType: TBoldElementTypeInfo read GetListelementType; - property Required: boolean read GetRequired; - property RTInfo: TBoldMemberRTInfo read GetRTInfo; - property UseFieldSize: boolean read GetUseFieldSize; - property Dataset: TBoldAbstractDataSet read GetDataset; - property FieldDescriptions: TBoldDataSetFieldDescriptions read GetFieldDescriptions; - property Expression: string read GetExpression write SetExpression; - published - property BoldProperties: TBoldStringFollowerController read FBoldProperties write SetBoldProperties; - property FieldName: String read fFieldName write SetFieldName; - end; - - { TBoldDataSetFieldDescriptions } - TBoldDataSetFieldDescriptions = class(TCollection) - private - FDataset: TBoldAbstractDataSet; - FFieldFollowers: TBoldControllerList; - function GetItem(AIndex: Integer): TBoldDataSetFieldDescription; - protected - function GetOwner: TPersistent; override; - property FieldFollowers: TBoldControllerList read FFieldFollowers; - public - constructor Create(AOwner: TBoldAbstractDataSet); - destructor Destroy; override; - function Add: TBoldDataSetFieldDescription; - procedure InvalidateFields; - property Items[index: Integer]: TBoldDataSetFieldDescription read GetItem; default; - property Dataset: TBoldAbstractDataSet read FDataset; - end; - - { TBoldAbstractDataSet } - TBoldAbstractDataSet = class(TDataSet) - private - FAutoOpen: boolean; - FBookmarkOfs: integer; - FContextSubscriber: TBoldPassthroughSubscriber; - FFieldDescriptions: TBoldDataSetFieldDescriptions; - FLayoutChanged: boolean; - FListFollowerController: TBoldListAsFollowerListController; - FListFollower: TBoldListHandleFollower; - FRecordPos: integer; - FBufferSize: integer; - FRecordSize: integer; - fLastKnownType: TBoldElementTypeInfo; - fInternalCursorReady: Boolean; - function GetIndexForBookmark(Bookmark: Pointer): integer; - procedure InsertElement(ABuffer: PChar); virtual; - procedure _ReceiveContext(Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent); - procedure BoldToBuffer(ABuffer: PChar); - procedure _InsertRow(Follower: TBoldFollower); - procedure _DeleteRow(index: Integer; owningFollower: TBoldFollower); - procedure BufferToBoldElement(AIndex: integer; ABuffer: PChar); - procedure BoldElementToBuffer(AIndex: integer; ABuffer: PChar); - function GetBookmarkInfo(Buffer: PChar): PBDSBookmarkInfo; - function GetActiveBoldElement: TBoldElement; - function GetActiveBoldObject: TBoldObject; - procedure SetAutoOpen(AValue: boolean); - function GetBoldRTInfo(AFieldName: string): TBoldMemberRTInfo; - function GetBoldHandle: TBoldAbstractListHandle; - procedure SetBoldHandle(NewValue: TBoldAbstractListHandle); - procedure SetFieldDescriptions(const Value: TBoldDataSetFieldDescriptions); - procedure EnsureRecordPosInValidRange; - protected - procedure Loaded; override; - function CreateNewElement: TBoldElement; virtual; - procedure TypeMayHaveChanged; - procedure TypeHasChanged; virtual; - procedure LayoutChanged; - procedure ClearCalcFields(Buffer: PChar); override; - procedure DoOnNewRecord; override; - function GetActiveRecBuf(var RecBuf: PChar): Boolean; - function GetListElementType: TBoldElementTypeInfo; virtual; - procedure DeleteAllFields; - { Mandatory overrides } - // Record buffer methods: - function AllocRecordBuffer: PChar; override; - procedure FreeRecordBuffer(var Buffer: PChar); override; - procedure InternalInitRecord(Buffer: PChar); override; - function GetRecord(Buffer: PChar; GetMode: TGetMode; DoCheck: Boolean): TGetResult; override; - procedure SetRecNo(Value: Integer); override; - function GetRecordSize: Word; override; - procedure SetFieldData(Field: TField; Buffer: Pointer); override; - // Bookmark methods: - procedure GetBookmarkData(Buffer: PChar; Data: Pointer); override; - function GetBookmarkFlag(Buffer: PChar): TBookmarkFlag; override; - procedure InternalGotoBookmark(Bookmark: Pointer); override; - procedure InternalSetToRecord(Buffer: PChar); override; - procedure SetBookmarkFlag(Buffer: PChar; Value: TBookmarkFlag); override; - procedure SetBookmarkData(Buffer: PChar; Data: Pointer); override; - // Navigational methods: - procedure InternalFirst; override; - procedure InternalLast; override; - // Editing methods: - procedure InternalAddRecord(Buffer: Pointer; Append: Boolean); override; - procedure InternalDelete; override; - procedure InternalPost; override; - // Misc methods: - procedure InternalClose; override; - procedure InternalHandleException; override; - procedure InternalInitFieldDefs; override; - procedure InternalOpen; override; - function IsCursorOpen: Boolean; override; - function LocateRecord(const KeyFields: string; - const KeyValues: Variant; Options: TLocateOptions; - SyncCursor: Boolean): Boolean; - function ValuesInFields(AFields: TList; const KeyValues: Variant; Options: TLocateOptions): Boolean; - { Optional overrides } - function GetRecordCount: Integer; override; - function GetRecNo: Integer; override; - procedure DoAfterScroll; override; - function GetCanModify: boolean; override; - procedure InternalEdit; override; - procedure InternalCancel; override; - //Bold related methods - function GetList: TBoldList; - //Bold related properties - property List: TBoldList read GetList; - property ListElementType: TBoldElementTypeInfo read GetListElementType; - property BoldHandle: TBoldAbstractListHandle read GetBoldHandle write SetBoldHandle; - property AutoOpen: boolean read FAutoOpen write SetAutoOpen; - public - constructor Create(AOwner: TComponent); override; - destructor Destroy; override; - function BookmarkValid(Bookmark: TBookmark): Boolean; override; - function CreateBlobStream(Field: TField; Mode: TBlobStreamMode): TStream; override; - procedure CreateDefaultFields; - function GetFieldData(Field: TField; Buffer: Pointer): Boolean; override; - function Locate(const KeyFields: string; const KeyValues: Variant; Options: TLocateOptions): Boolean; override; - function Lookup(const KeyFields: string; const KeyValues: Variant; const ResultFields: string): Variant; override; - procedure TryToOpen; - property ActiveBoldElement: TBoldElement read GetActiveBoldElement ; - property ActiveBoldObject: TBoldObject read GetActiveBoldObject; - property BoldRTInfo[AFieldName: string]: TBoldMemberRTInfo read GetBoldRTInfo; - published - property FieldDescriptions: TBoldDataSetFieldDescriptions read fFieldDescriptions write SetFieldDescriptions; - end; - - { TBoldDataSet } - TBoldDataSet = class(TBoldAbstractDataSet) - published - {$IFNDEF T2H} - property Active; - property AutoOpen; - property BoldHandle; - //published from Dataset - property BeforePost; - property BeforeClose; - property BeforeInsert; - property AfterInsert; - property AfterOpen; - property BeforeScroll; - property AfterScroll; - property AfterCancel; - {$ENDIF} - end; - -implementation - -uses - SysUtils, - DBConsts, - Variants, - BoldDefs, - BoldAttributes, - BoldGuiResourceStrings, - BoldEnvironment; - -type - TBoldConvInfo = record - FBoldType: TClass; - FFieldType: TFieldType; - FBufferSize: integer; - FUseSize: boolean; - FUseDecimals: boolean; - end; - -const - // It is important that subclasses come after their superclass! - arConvInfo: array [0..14] of TBoldConvInfo = - ( - (FBoldType: TBAString; FFieldType: ftString; FBufferSize: 255; FUseSize: True; FUseDecimals: False), - (FBoldType: TBANumeric; FFieldType: ftInteger; FBufferSize: sizeof(integer); FUseSize: False; FUseDecimals: True), - (FBoldType: TBAInteger; FFieldType: ftInteger; FBufferSize: sizeof(integer); FUseSize: False; FUseDecimals: True), - (FBoldType: TBASmallInt; FFieldType: ftSmallint; FBufferSize: sizeof(smallint); FUseSize: False; FUseDecimals: True), - (FBoldType: TBAShortInt; FFieldType: ftSmallint; FBufferSize: sizeof(smallint); FUseSize: False; FUseDecimals: True), - (FBoldType: TBAWord; FFieldType: ftWord; FBufferSize: sizeof(word); FUseSize: False; FUseDecimals: True), - (FBoldType: TBAByte; FFieldType: ftSmallint; FBufferSize: sizeof(smallint); FUseSize: False; FUseDecimals: True), - (FBoldType: TBAFloat; FFieldType: ftFloat; FBufferSize: sizeof(double); FUseSize: False; FUseDecimals: True), - (FBoldType: TBACurrency; FFieldType: ftCurrency; FBufferSize: sizeof(double); FUseSize: False; FUseDecimals: True), - (FBoldType: TBABlob; FFieldType: ftBlob; FBufferSize: 40; FUseSize: true; FUseDecimals: False), - (FBoldType: TBADateTime; FFieldType: ftDateTime; FBufferSize: sizeof(TDateTime); FUseSize: False; FUseDecimals: False), - (FBoldType: TBADate; FFieldType: ftDate; FBufferSize: SizeOf(Longint); FUseSize: False; FUseDecimals: False), - (FBoldType: TBATime; FFieldType: ftTime; FBufferSize: SizeOf(Longint); FUseSize: False; FUseDecimals: False), - (FBoldType: TBAValueSet; FFieldType: ftInteger; FBufferSize: sizeof(integer); FUseSize: false; FUseDecimals: False), - (FBoldType: TBABoolean; FFieldType: ftBoolean; FBufferSize: sizeof(wordbool); FUseSize: false; FUseDecimals: False) - ); -// (FBoldType: 'TBAVALUESET'; FFieldType: ftDateTime; FBufferSize: sizeof(TDateTime); FUseSize: False; FUseDecimals: False), -// (FBoldType: 'TBABLOBCONTENT'; FFieldType: ftDateTime; FBufferSize: sizeof(TDateTime); FUseSize: False; FUseDecimals: False), - -{**************************************************************************** - TBoldDataSetFieldDescription - ****************************************************************************} - -constructor TBoldDataSetFieldDescription.Create(AOwner: TCollection); -begin - Assert(AOwner is TBoldDataSetFieldDescriptions); - inherited Create(AOwner); - FBoldProperties := TBoldStringFollowerController.Create(nil); - FBoldProperties.AfterMakeUptoDate := self.AfterMakeUptoDate; - fBoldProperties.OnGetContextType := GetListElementType; - FieldDescriptions.FieldFollowers.Add(FBoldProperties); - Invalidate; -end; - -destructor TBoldDataSetFieldDescription.Destroy; -begin - FieldDescriptions.FieldFollowers.Remove(FBoldProperties); - FreeAndNil(FBoldProperties); - inherited Destroy; -end; - -procedure TBoldDataSetFieldDescription.DefineFieldType(aClass: TClass); -var - i: integer; -begin - //if we didn't find the bold type, we will set the field type to string(255) - FFieldType := ftString; - FFieldSize := 255; - FBufferSize := 255; - FRequired := False; - - for i := high(arConvInfo) downto Low(arConvInfo) do - begin - with arConvInfo[i] do - begin - if AClass.inheritsfrom(arConvInfo[i].FBoldType) then - begin - self.FFieldType := arConvInfo[i].FFieldType; - self.FBufferSize := arConvInfo[i].FBufferSize; - self.FUseFieldSize := arConvInfo[i].FUseSize; - if FUseSize then - self.FFieldSize := arConvInfo[i].FBufferSize - else - self.FFieldSize := 0; - self.FRequired := False; - break; - end; - end; // with - end; // for -end; - -procedure TBoldDataSetFieldDescription.AfterMakeUptoDate(Follower: TBoldFollower); -var - LField: TField; - ActiveBuf: PChar; - - function FindFieldNo(ANo: integer): TField; - var - FieldIx: integer; - begin - result := nil; - for FieldIx := 0 to Dataset.FieldCount - 1 do - begin - if Dataset.Fields[FieldIx].FieldNo = ANo then - begin - result := Dataset.Fields[FieldIx]; - Exit; - end; - end; // for - end; - -begin - with Dataset do - begin - if not Active then - Exit; - - if not (Dataset.State in dsWriteModes) then - begin - UpdateCursorPos; - Resync([]); - end - else - begin - if GetActiveRecBuf(ActiveBuf) and (GetBookmarkInfo(ActiveBuf)^.Element = Follower.OwningFollower.Element) then - begin - BoldElementToBuffer(Follower.Index, ActiveBuf); - if not (State in [dsCalcFields, dsFilter, dsNewValue]) then - begin - LField := FindFieldNo(Follower.Index + 1); - if Assigned(LField) then - DataEvent(deFieldChange, LongInt(LField)); - end; - SetModified(True); - end - end - end; // with -end; - -function TBoldDataSetFieldDescription.GetEffectiveFieldName: String; -var - i: integer; -begin - if FieldName <> '' then - result := FieldName - else - begin - result := BoldProperties.Expression; - for i := 1 to length(Result) do - if Result[i] in ['.', '(', '-', '>', ')'] then - result[i] := '_' - end; -end; - -procedure TBoldDataSetFieldDescription.EnsureValid; -var - LFieldType: TBoldElementTypeInfo; -begin - if fInvalid then - begin - if not Assigned(ListElementType) then - raise EBold.CreateFmt(sCannotInitializeFieldsWithoutContext, [Dataset.Name]); - - LFieldType := ListElementType.Evaluator.ExpressionType(Expression, ListElementType, false); - if not Assigned(LFieldType) then - raise Exception.CreateFmt(sInvalidFieldExpression, [Expression]); - - if ListElementType.Evaluator is TBoldRTEvaluator then - fRTInfo := (ListElementType.Evaluator as TBoldRTEvaluator).RTInfo(Expression, ListElementType, false) - else - fRTInfo := nil; - - if LFieldType is TBoldAttributeTypeInfo then - begin - DefineFieldType(TBoldAttributeTypeInfo(LFieldType).AttributeClass); - if (fRTInfo is TBoldAttributeRTInfo) and - (TBoldAttributeRTInfo(FRTInfo).Length > 0) and - FUseFieldSize then - begin - FBufferSize := TBoldAttributeRTInfo(FRTInfo).Length + 1; - FFieldSize := FBufferSize - 1; - end; - end - else if LFieldType is TBoldClassTypeInfo then - begin - FFieldType := ftInteger; - FFieldSize := 0; - FBufferSize := sizeof(integer); - FRequired := False; - end - else - begin - FFieldType := ftString; - FFieldSize := 40; - FBufferSize := 40; - FRequired := False; - end; - fInvalid := false; - end; -end; - -function TBoldDataSetFieldDescription.GetFieldDescriptions: TBoldDataSetFieldDescriptions; -begin - result := TBoldDataSetFieldDescriptions(Collection); -end; - -function TBoldDataSetFieldDescription.GetDataset: TBoldAbstractDataSet; -begin - result := FieldDescriptions.Dataset; -end; - -function TBoldDataSetFieldDescription.GetListElementType: TBoldElementTypeInfo; -begin - result := Dataset.ListelementType; -end; - -function TBoldDataSetFieldDescription.GetExpression: string; -begin - result := FBoldProperties.Expression; -end; - -procedure TBoldDataSetFieldDescription.SetExpression(AValue: string); -begin - fBoldProperties.Expression := aValue; - Invalidate; -end; - -procedure TBoldDataSetFieldDescription.SetBoldProperties(AValue: TBoldStringFollowerController); -begin - if (AValue <> FBoldProperties) and Assigned(AValue) then - FBoldProperties.Assign(AValue); - invalidate; -end; - -procedure TBoldDataSetFieldDescription.Assign(Source: TPersistent); -begin - if source is TBoldDataSetFieldDescription then - begin - self.BoldProperties.Assign(TBoldDataSetFieldDescription(Source).BoldProperties); - self.FieldName := TBoldDataSetFieldDescription(Source).FieldName; - Invalidate; - end; -end; - -procedure TBoldDataSetFieldDescription.Invalidate; -begin - fInvalid := true; -end; - -function TBoldDataSetFieldDescription.GetFieldOfs: integer; -begin - EnsureValid; - Result := FFieldOfs; -end; - -function TBoldDataSetFieldDescription.GetFieldSize: integer; -begin - EnsureValid; - REsult := fFieldSize; -end; - -function TBoldDataSetFieldDescription.GetFieldType: TFieldType; -begin - EnsureValid; - result := fFieldType; -end; - -function TBoldDataSetFieldDescription.GetRequired: boolean; -begin - Ensurevalid; - result := fRequired; -end; - -function TBoldDataSetFieldDescription.GetRTInfo: TBoldMemberRTInfo; -begin - EnsureValid; - result := fRTInfo; -end; - -function TBoldDataSetFieldDescription.GetUseFieldSize: boolean; -begin - EnsureValid; - result := fUseFieldSize; -end; - -procedure TBoldDataSetFieldDescription.SetFieldName(const Value: String); -begin - fFieldName := Value; - Invalidate; -end; - -function TBoldDataSetFieldDescriptions.GetOwner: TPersistent; -begin - result := DataSet; -end; - -function TBoldDataSetFieldDescription.GetDisplayName: string; -begin - result := EffectiveFieldName + ' = ' + Expression; -end; - -{**************************************************************************** - TBoldDataSetFieldDescriptions -****************************************************************************} - -constructor TBoldDataSetFieldDescriptions.Create(AOwner: TBoldAbstractDataSet); -begin - inherited Create(TBoldDataSetFieldDescription); - FFieldFollowers := TBoldControllerList.Create(nil); - FDataset := AOwner; -end; - -destructor TBoldDataSetFieldDescriptions.Destroy; -begin - Clear; - FreeAndNil(FFieldFollowers); - inherited Destroy; -end; - -function TBoldDataSetFieldDescriptions.Add: TBoldDataSetFieldDescription; -begin - result := TBoldDataSetFieldDescription(inherited Add); - // B Crotaz 17/4/2002 - removed next line - // this will fail on an active dataset - // because this new field description has no fieldname - // and the dataset does a TryToOpen as part of LayoutChanged - // removed - FDataset.LayoutChanged; -end; - -function TBoldDataSetFieldDescriptions.GetItem(AIndex: Integer): TBoldDataSetFieldDescription; -begin - result := TBoldDataSetFieldDescription(inherited Items[AIndex]); -end; - -procedure TBoldDataSetFieldDescriptions.InvalidateFields; -var - i: integer; -begin - for i := 0 to count - 1 do - items[i].Invalidate; -end; - -{**************************************************************************** - TBoldAbstractDataSet - ****************************************************************************} - -constructor TBoldAbstractDataSet.Create(AOwner: TComponent); -begin - inherited Create(AOwner); - fLastKnownType := nil; - fInternalCursorReady := false; - FContextSubscriber := TBoldPassthroughSubscriber.Create(_ReceiveContext); - - FFieldDescriptions := TBoldDataSetFieldDescriptions.Create(self); - FLayoutChanged := True; - - FListFollowerController := TBoldListAsFollowerListController.Create(self, FFieldDescriptions.FieldFollowers); - FListFollowerController.OnAfterInsertItem := _InsertRow; - FListFollowerController.OnAfterDeleteItem := _DeleteRow; - FListFollowerController.OnGetContextType := GetListElementType; - - FListFollower := TBoldListHandleFollower.Create(Owner, FListFollowerController); - FRecordSize := 0; - FRecordPos := -1; -end; - -destructor TBoldAbstractDataSet.Destroy; -begin - Close; - FRecordPos := -1; - FreeAndNil(FContextSubscriber); - FreeAndNil(FListFollower); - FreeAndNil(FListFollowerController); - FreeAndNil(FFieldDescriptions); - inherited Destroy; -end; - -function TBoldAbstractDataSet.GetListElementType: TBoldElementTypeInfo; -begin - if assigned(BoldHandle) then - result := BoldHandle.StaticBoldType - else - result := nil; -end; - -procedure TBoldAbstractDataSet.SetAutoOpen(AValue: boolean); -begin - if (FAutoOpen <> AValue) then - begin - FAutoOpen := AValue; - if FAutoOpen then - TryToOpen; - end; -end; - -procedure TBoldAbstractDataSet.TryToOpen; -begin - if not (csLoading in ComponentState) and - not (csDestroying in ComponentState) and - not Active then - try - Open; - except - // Eat exceptions quietly - end; -end; - -procedure TBoldAbstractDataSet.DoOnNewRecord; -begin - InsertElement(ActiveBuffer); - inherited DoOnNewRecord; -end; - -function TBoldAbstractDataSet.CreateNewElement: TBoldElement; -begin - result := nil; - if assigned(BoldHandle) and - assigned(BoldHandle.List) and - BoldHandle.List.CanCreateNew then - result := BoldHandle.List.AddNew; -end; - -procedure TBoldAbstractDataSet.InsertElement(ABuffer: PChar); -var - LElement: TBoldElement; -begin - lElement := CreateNewElement; - if not Assigned(LElement) then - Abort; - - fRecordPos := List.IndexOf(LElement); - - with GetBookmarkInfo(ABuffer)^ do - begin - Flag := bfInserted; - Element := LElement; - end; // with - BoldToBuffer(ABuffer); -end; - -function TBoldAbstractDataSet.GetBoldRTInfo(AFieldName: string): TBoldMemberRTInfo; -var - FieldDesc: TBoldDataSetFieldDescription; - i: integer; -begin - InternalInitFieldDefs; - FieldDesc := nil; - for i := 0 to FieldDescriptions.Count - 1 do - begin - if FieldDescriptions[i].EffectiveFieldName = AFieldName then - begin - FieldDesc := FieldDescriptions.Items[i]; - break; - end; - end; - - if Assigned(FieldDesc) then - result := FieldDesc.RTInfo - else - raise Exception.CreateFmt(sInvalidFieldName, [AFieldName]); -end; - -procedure TBoldAbstractDataSet.EnsureRecordPosInValidRange; -begin - if assigned(list) then - begin - if fRecordPos > List.Count-1 then - fRecordPos := List.Count-1 - end - else - fRecordPos := -1; -end; - -procedure TBoldAbstractDataSet._ReceiveContext(Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent); -begin - case RequestedEvent of - beDestroying: Close; - beValueIdentityChanged: - begin - TypeMayHaveChanged; - EnsureRecordPosInValidRange; - end; - beItemDeleted: EnsureRecordPosInValidRange; - end; -end; - -function TBoldAbstractDataSet.CreateBlobStream(Field: TField; Mode: TBlobStreamMode): TStream; -var - BoldDataSetFieldDescription: TBoldDataSetFieldDescription; - BlobValue: TBABlob; - IndirectElement: TBoldIndirectElement; -begin - if IsEmpty then - Result := TMemoryStream.Create - else - begin - IndirectElement := TBoldIndirectElement.Create; - try - BoldDataSetFieldDescription := FieldDescriptions[Field.FieldNo - 1]; - List[RecNo - 1].EvaluateExpression(BoldDataSetFieldDescription.Expression, IndirectElement); - BlobValue := (IndirectElement.Value as TBABlob); - if not assigned(BlobValue) or BlobValue.IsNull then - result := TMemoryStream.Create - else - result := BlobValue.CreateBlobStream(TBoldBlobStreamMode(Mode)); - finally - IndirectElement.Free; - end; - end; -end; - -procedure TBoldAbstractDataSet.InternalEdit; -begin - inherited InternalEdit; -end; - -function TBoldAbstractDataSet.GetCanModify: boolean; -begin - result := True; -end; - -procedure TBoldAbstractDataSet.InternalCancel; -begin - if Assigned(ActiveBoldObject) then - ActiveBoldObject.Discard; -{CHECKME Is this needed??? - - if State = dsInsert then - begin - if SQL then - self.FListHandle.RemoveCurrentElement - end; -} - inherited; -end; - -function TBoldAbstractDataSet.Lookup(const KeyFields: string; const KeyValues: Variant; - const ResultFields: string): Variant; -begin - Result := null; - if LocateRecord(KeyFields, KeyValues, [loCaseInsensitive], false) then - begin - SetTempState(dsCalcFields); - try - CalculateFields(TempBuffer); - Result := FieldValues[ResultFields]; - finally - RestoreState(dsBrowse); - end; - end; -end; - -procedure TBoldAbstractDataSet.DoAfterScroll; -begin - if (FListFollower.Follower.CurrentIndex <> RecNo - 1) then - fListFollower.SetFollowerIndex(RecNo - 1); - inherited ; -end; - -function TBoldAbstractDataSet.ValuesInFields(AFields: TList; const KeyValues: Variant; Options: TLocateOptions): Boolean; -var - i: Integer; - - function CompareField(AField: TField; AValue: variant): boolean; - begin - if (loPartialKey in Options) then - begin - if (loCaseInsensitive in Options) then - Result := AnsiStrLIComp(PChar(AField.AsString), - PChar(VarToStr(AValue)), - Length(AValue)) = 0 - else - Result := AnsiStrLComp(PChar(AField.AsString), - PChar(VarToStr(AValue)), - Length(AValue)) = 0 - end - else - begin - if loCaseInsensitive in Options then - Result := AnsiStrIComp(PChar(AField.AsString), - PChar(VarToStr(AValue))) = 0 - else // aucune options - Result := AnsiStrComp(PChar(AField.AsString), - PChar(VarToStr(AValue))) = 0 - end; - end; - -begin - if AFields.count = 1 then - result := CompareField(TField(AFields[0]), KeyValues) - else - begin - Result := True; - for i := 0 to AFields.count - 1 do - begin - Result := Result and CompareField(TField(AFields[i]), KeyValues[i]); - if not Result then - Exit; - end; - end; -end; - -//called internally by Locate and Lookup -function TBoldAbstractDataSet.LocateRecord(const KeyFields: string; - const KeyValues: Variant; Options: TLocateOptions; - SyncCursor: Boolean): Boolean; -var - LFields: TList; - Locator: TBoldObjectLocator; - LocatorPtr: pointer; - LElement: TBoldElement; - i: Integer; -begin - result := false; - if BoldHandle.Count = 0 then - Exit; - - CheckBrowseMode; - CursorPosChanged; - SetTempState(dsFilter); - try - if UpperCase(KeyFields) = 'SELF' then // Do not localize - begin - LocatorPtr := Pointer(Integer(KeyValues)); - if Assigned(LocatorPtr) then - begin - try - Locator := TObject(LocatorPtr) as TBoldObjectLocator; - LElement := Locator.BoldObject; - with GetBookmarkInfo(TempBuffer)^ do - begin - Element := LElement; - Flag := bfCurrent; - end; - BoldToBuffer(TempBuffer); - FRecordPos := List.IndexOf(LElement); - Result := FRecordPos <> -1; - except - // Eat exceptions quietly - end - end - end - else - begin - LFields := TList.Create; - try - GetFieldList(LFields, KeyFields); - for i := 0 to List.Count - 1 do - begin - with GetBookmarkInfo(TempBuffer)^ do - begin - Element := List[i]; - Flag := bfCurrent; - end; - - BoldToBuffer(TempBuffer); - if ValuesInFields(LFields, KeyValues, Options) then - begin - FRecordPos := i; - Result := True; - break; - end; - end; //for - finally - LFields.Free; - end; - end; - finally - RestoreState(dsBrowse); - end; -end; - -function TBoldAbstractDataSet.Locate(const KeyFields: string; const KeyValues: Variant; - Options: TLocateOptions): Boolean; -begin - DoBeforeScroll; - Result := LocateRecord(KeyFields, KeyValues, Options, True); - if Result then - begin - Resync([rmExact, rmCenter]); - DoAfterScroll; - end; -end; - -function TBoldAbstractDataSet.BookmarkValid(Bookmark: TBookmark): Boolean; -begin - Result := GetIndexForBookmark(Bookmark) <> -1; -end; - -procedure TBoldAbstractDataSet.BoldToBuffer(ABuffer: PChar); -var - i: integer; -begin - for i := 0 to FieldDescriptions.Count - 1 do - BoldElementToBuffer(i, ABuffer); - - GetCalcFields(ABuffer); -end; - -procedure TBoldAbstractDataSet._DeleteRow(index: Integer; owningFollower: TBoldFollower); -begin - //_DeleteRow will also be called when closing the dataset, so do nothing - if not Active then - Exit; - - if State = dsInsert then - Exit; - UpdateCursorPos; - if BoldHandle.CurrentElement <> ActiveBoldElement then - if (State in dsWriteModes) then - Cancel - else - Resync([]) - else - if not (State in dsWriteModes) then - Resync([]); - -end; - -procedure TBoldAbstractDataSet._InsertRow(Follower: TBoldFollower); -begin - if State in [dsInsert, dsInactive] then - Exit; - if (State in dsWriteModes) then - UpdateRecord; - UpdateCursorPos; - Resync([]); -end; - -function TBoldAbstractDataSet.GetList: TBoldList; -begin - if Assigned(BoldHandle) then - result := BoldHandle.List - else - Result := nil; -end; - -procedure TBoldAbstractDataSet.BufferToBoldElement(AIndex: integer; ABuffer: PChar); -var - Locator: TBoldObjectLocator; - LocatorPointer: pointer; - LFieldAdr: pointer; - LFieldDescr: TBoldDataSetFieldDescription; - IndirectElement: TBoldIndirectElement; - LValue: TBoldElement; - LActiveElement: TBoldElement; -begin - LFieldDescr := FieldDescriptions[AIndex]; - - with LFieldDescr do - begin - LFieldAdr := ABuffer + FieldOfs; - - IndirectElement := TBoldIndirectElement.Create; - try - LValue := nil; - try - LActiveElement := GetBookmarkInfo(ABuffer)^.Element; - - LActiveElement.EvaluateExpression(Expression, IndirectElement); - LValue := IndirectElement.Value; - except - // Eat exceptions quietly - end; - - if Assigned(LValue) and LValue.Mutable then - case FieldType of // - ftBoolean: begin - if Boolean(LFieldAdr^) then - LValue.AsString := 'Y' - else - LValue.AsString := 'N' - end; - - ftString: begin - LValue.AsString := Copy(PChar(LFieldAdr), 1, BufferSize - 1); - end; - - ftInteger: begin - if LValue is TBoldObjectReference then - begin - if Integer(LFieldAdr^) <> 0 then - begin - LocatorPointer := Pointer(LFieldAdr^); - if Assigned(LocatorPointer) then - begin - Locator := TObject(LocatorPointer) as TBoldObjectLocator; - Locator.EnsureBoldObject; - TBoldObjectReference(LValue).BoldObject := Locator.BoldObject; - end - else - TBoldObjectReference(LValue).BoldObject := nil; - end - else - TBoldObjectReference(LValue).BoldObject := nil; - end - else if lValue is TBAValueSet then - (lValue as TBAValueSet).AsInteger := Integer(LFieldAdr^) - else - LValue.AsString := IntToStr(Integer(LFieldAdr^)); - end; - - ftCurrency, - ftFloat: begin - LValue.AsString := FloatToStr(Double(LFieldAdr^)); - end; - - ftTime: - if Double(LFieldAdr^) <> 0 then - LValue.AsString := TimeToStr(TimeStampToDateTime(MSecsToTimeStamp(Double(LFieldAdr^)))) - else - LValue.AsString := ''; - - ftDate: - if Double(LFieldAdr^) <> 0 then - LValue.AsString := DateToStr(TimeStampToDateTime(MSecsToTimeStamp(Double(LFieldAdr^)))) - else - LValue.AsString := ''; - - ftDateTime: - if Double(LFieldAdr^) <> 0 then - LValue.AsString := DateTimeToStr(TimeStampToDateTime(MSecsToTimeStamp(Double(LFieldAdr^)))) - else - LValue.AsString := ''; - end; // case - finally - IndirectElement.Free; - end; - end; // with -end; - -procedure TBoldAbstractDataSet.BoldElementToBuffer(AIndex: integer; ABuffer: PChar); -var - LDateTime: TDateTime; - LTimeStamp: TTimeStamp; - LInteger: integer; - LBoolean: boolean; - LFloat: double; - LFieldAdr: pointer; - IndirectElement: TBoldIndirectElement; - LActiveElement: TBoldElement; - LFieldDescr: TBoldDataSetFieldDescription; - Locator: TBoldObjectLocator; - LString: string; -begin - LFieldDescr := FieldDescriptions[AIndex]; - - with LFieldDescr do - begin - LFieldAdr := ABuffer + FieldOfs; - - IndirectElement := TBoldIndirectElement.Create; - try - FillChar(LFieldAdr^, BufferSize, 0); - try - LActiveElement := GetBookmarkInfo(ABuffer)^.Element; - LActiveElement.EvaluateExpression(Expression, IndirectElement); - if Assigned(IndirectElement.Value) then - case FieldType of // - ftBoolean: begin - if IndirectElement.Value.AsString = 'Y' then - LBoolean := True - else - LBoolean := False; - Move(LBoolean, LFieldAdr^, SizeOf(LBoolean)); - end; - - ftString: begin - StrLCopy(LFieldAdr, PChar(IndirectElement.Value.AsString), BufferSize - 1); - end; - - ftInteger: begin - if IndirectElement.Value is TBoldObjectReference then - begin - Locator := TBoldObjectReference(IndirectElement.Value).Locator; - Move(Integer(Pointer(Locator)), LFieldAdr^, BufferSize); - end - else if IndirectElement.Value is TBoldObject then - begin - Locator := TBoldObject(IndirectElement.Value).BoldObjectLocator; - Move(Integer(Pointer(Locator)), LFieldAdr^, BufferSize); - end - else if IndirectElement.Value is TBAValueSet then - begin - if (IndirectElement.Value as TBAValueSet).IsNull then - LInteger := 0 - else - lInteger := (IndirectElement.Value as TBAValueSet).AsInteger; - Move(LInteger, LFieldAdr^, BufferSize); - end - else - begin - if IndirectElement.Value.AsString = '' then - LInteger := 0 - else - LInteger := StrToInt(IndirectElement.Value.AsString); - Move(LInteger, LFieldAdr^, BufferSize); - end; - end; - - ftCurrency, - ftFloat: begin - LFloat := StrToFloat(IndirectElement.Value.AsString); - Move(LFloat, LFieldAdr^, BufferSize); - end; - - ftDate: begin - LTimeStamp.Date := 0; - if IndirectElement.Value is TBADate then - LTimeStamp := DateTimeToTimeStamp((IndirectElement.value as TBADate).asDate) - else - begin - LString := Trim(IndirectElement.Value.AsString); - if LString <> '' then - LTimeStamp := DateTimeToTimeStamp(StrToDate(IndirectElement.Value.AsString)); - end; - Move(LTimeStamp.Date, LFieldAdr^, BufferSize); - end; - - ftTime: begin - LTimeStamp.Time := 0; - if IndirectElement.value is TBATime then - lTimeStamp := DateTimeToTimeStamp((IndirectElement.value as TBATime).asTime) - else - begin - LString := Trim(IndirectElement.Value.AsString); - if LString <> '' then - LTimestamp := DateTimeToTimeStamp(StrToTime(IndirectElement.Value.AsString)); - end; - Move(LTimeStamp.Time, LFieldAdr^, BufferSize); - end; - - ftDateTime: begin - lFloat := 0; - if IndirectElement.Value is TBADateTime then - begin - lDateTime := (IndirectElement.value as TBADateTime).asDateTime; - LFloat := TimeStampToMSecs(DateTimeToTimeStamp(LDateTime)); - end - else - begin - LString := Trim(IndirectElement.Value.AsString); - if LString <> '' then - begin - LDateTime := StrToDateTime(IndirectElement.Value.AsString); - LFloat := TimeStampToMSecs(DateTimeToTimeStamp(LDateTime)); - end - end; - Move(LFloat, LFieldAdr^, BufferSize); - end; - - ftBlob, - ftMemo: begin - StrLCopy(LFieldAdr, PChar(IndirectElement.Value.AsString), BufferSize - 1); - end; - end; // case - except - // Eat exceptions quietly - end; - finally - IndirectElement.Free; - end; - end; // with -end; - -function TBoldAbstractDataSet.GetActiveBoldElement: TBoldElement; -var - ActiveBuf: PChar; -begin - if Active and GetActiveRecBuf(ActiveBuf) then - result := GetBookmarkInfo(ActiveBuf)^.Element - else - result := nil; -end; - -function TBoldAbstractDataSet.GetActiveBoldObject: TBoldObject; -begin - result := (ActiveBoldElement as TBoldObject); -end; - -function TBoldAbstractDataSet.GetBookmarkInfo(Buffer: PChar): PBDSBookmarkInfo; -begin - result := PBDSBookmarkInfo(Buffer + FBookmarkOfs); -end; - -//The AllocRecordBuffer method is called to allocate memory for a single record buffer. -//This method will be called internally by Delphi several times. -function TBoldAbstractDataSet.AllocRecordBuffer: PChar; -begin - GetMem(Result, FBufferSize); -end; - -//As you might expect, FreeRecordBuffer must free the memory allocated -//by the AllocRecordBuffer() method. -procedure TBoldAbstractDataSet.FreeRecordBuffer(var Buffer: PChar); -begin - FreeMem(Buffer); -end; - -//The InternalInitRecord method is called to initialize a record buffer. -//In this method, you could do things like set default field values or perform -//some type of initialization of custom record buffer data. -procedure TBoldAbstractDataSet.InternalInitRecord(Buffer: PChar); -begin - FillChar(Buffer^, FBufferSize, 0); -// InsertElement(Buffer); -end; - -//The primary function of the GetRecord method is to retrieve the record data -//for either the current, next or prior record in the dataset, depending on the value of the GetMode parameter, -//a TGetMode enumerated type which is defined as: TGetMode = (gmCurrent, gmNext, gmPrior) -// -//The return value may be any of the TGetResult enumerated values which is defined as: TGetResult = (grOK, grBOF, grEOF, grError) -// -// GrOk means success, grBOF means the dataset is at the beginning, -// grEOF means the dataset is at the end, and grError means an error has occurred. -// -// When the DoCheck parameter is True, and grError is the potential return value, -// an exception should be raised. - -// After having retrieved the current, next or prior record, the pysical file pointer(i.e. FRecordPos) -// should reflect the position of the record that was retrieved, for this reason the value of FReocordPos is -// incremented when the next record is requested, decremented when the prior record is requested, and unchanged -// when the current record is requested. - -function TBoldAbstractDataSet.GetRecord(Buffer: PChar; GetMode: TGetMode; - DoCheck: Boolean): TGetResult; -begin - Result := grError; - if not Assigned(List) then - begin - Result := grEOF; - exit; - end; - - if RecordCount = 0 then - Exit; - - result := grOk; - case GetMode of - gmCurrent: begin - if (FRecordPos < 0) or (FRecordPos >= RecordCount) then - result := grError; - end; - - gmNext: begin - if FRecordPos >= RecordCount - 1 then - begin - result := grEof; - end - else - Inc(FRecordPos, 1); - end; - - gmPrior: if FRecordPos <= 0 then - begin - result := grBof; - FRecordPos := -1; - end - else - Dec(FRecordPos, 1); - end; - - if result = grOk then - begin - GetCalcFields(Buffer); //maan: write the field data in the record buffer. - with GetBookmarkInfo(Buffer)^ do - begin - Element := List[FRecordPos]; - Flag := bfCurrent; - end; // with - BoldToBuffer(Buffer); - end - else - if (result = grError) and (DoCheck) then - DatabaseError(sNoRecordsFound); -end; - -//The GetRecordSize function should return the size of the data record. -//This does not include additional information contained in the record buffer -//such as the bookmark information. - -function TBoldAbstractDataSet.GetRecordSize: Word; -begin - Result := FRecordSize; -end; - -function TBoldAbstractDataSet.GetActiveRecBuf(var RecBuf: PChar): Boolean; -begin - case State of - dsBrowse: if IsEmpty then - RecBuf := nil - else - RecBuf := ActiveBuffer; - - dsEdit, - dsInsert: RecBuf := ActiveBuffer; - - dsSetKey: RecBuf := nil; - - dsCalcFields: RecBuf := CalcBuffer; - - dsFilter: RecBuf := TempBuffer; - - dsNewValue: RecBuf := nil; - - dsOldValue: RecBuf := nil; - else - RecBuf := nil; - end; - Result := RecBuf <> nil; -end; - -procedure TBoldAbstractDataSet.ClearCalcFields(Buffer: PChar); -begin - FillChar(Buffer[RecordSize], CalcFieldsSize, 0); -end; - -//GetFieldData may be called with a nil-pointer in the Buffer argument -//which means corresponds to an "IsNull" request for the related field -function TBoldAbstractDataSet.GetFieldData(Field: TField; Buffer: Pointer): Boolean; -var - LActiveElement: TBoldElement; - IndirectElement: TBoldIndirectElement; - LRecBuf: PChar; - Attr: TBoldAttribute; -begin - Result := False; - if not GetActiveRecBuf(LRecBuf) then - Exit; - - with Field do - begin - if FieldNo > 0 then - begin - with FieldDescriptions[Field.FieldNo - 1] do - begin - IndirectElement := TBoldIndirectElement.Create; - try - LActiveElement := GetBookmarkInfo(LRecBuf)^.Element; - LActiveElement.EvaluateExpression(Expression, IndirectElement); - if Assigned(IndirectElement.Value) and (IndirectElement.Value is TBoldAttribute) then - begin - Attr := TBoldAttribute(IndirectElement.Value); - result := not Attr.IsNull; - if Assigned(Buffer) and (Field.DataType=ftVariant) then - Variant(Buffer^) := IndirectElement.Value.GetAsVariant; - Field.readOnly := not Attr.CanModify; - end - else - result := True; - finally - IndirectElement.Free; - end; - if Assigned(Buffer) then - begin - Move((LRecBuf + FieldOfs)^, Buffer^ , Field.Datasize); - end; - end; // with - end - else - begin - if State in [dsBrowse, dsEdit, dsInsert, dsCalcFields] then - begin - Inc(LRecBuf, FRecordSize + Offset); - Result := Boolean(LRecBuf[0]); - if Result and (Buffer <> nil) then - Move(LRecBuf[1], Buffer^, DataSize); - end; - end; - if (DataType = ftString) and (fRecordSize > 30) then - DisplayWidth := 30; - end; -end; - -procedure TBoldAbstractDataSet.SetFieldData(Field: TField; Buffer: Pointer); -var - LRecBuf: PChar; -begin - with Field do - begin - if not (State in dsWriteModes) then - DatabaseError(SNotEditing); - - if not GetActiveRecBuf(LRecBuf) then - Exit; - - if FieldNo > 0 then - begin - if State = dsCalcFields then - DatabaseError(SNotEditing); - if ReadOnly and not (State in [dsSetKey, dsFilter]) then - DatabaseErrorFmt(SFieldReadOnly, [DisplayName]); - Validate(Buffer); - if FieldKind <> fkInternalCalc then - begin - with FieldDescriptions[Field.FieldNo - 1] do - begin - if not Assigned(Buffer) then - FillChar((LRecBuf + FieldOfs)^, BufferSize, #0) - else - Move(Buffer^, (LRecBuf + FieldOfs)^, BufferSize); - end; // with - BufferToBoldElement(Field.FieldNo - 1, LRecBuf); - end; - end - else {fkCalculated, fkLookup} - begin - Inc(LRecBuf, FRecordSize + Offset); - Boolean(LRecBuf[0]) := LongBool(Buffer); - if Boolean(LRecBuf[0]) then - Move(Buffer^, LRecBuf[1], DataSize); - end; - if not (State in [dsCalcFields, dsFilter, dsNewValue]) then - DataEvent(deFieldChange, Longint(Field)); - end; -end; - -//TDataSet.GetBookmarkData / TDataSet.SetBookmarkData -//The GetBookmarkData and SetBookmarkData methods provide a means for TDataSet to manipulate a record's bookmark data without repositioning the current record. - -procedure TBoldAbstractDataSet.GetBookmarkData(Buffer: PChar; Data: Pointer); -begin - TBoldElement(Data^) := GetBookmarkInfo(Buffer)^.Element; -end; - -//TDataSet.GetBookmarkFlag / TDataSet.SetBookmarkFlag -// -//Bookmark flags are used internally by TDataSet to determine whether -//a particular record is the current, first or last in the dataset. -//The first and last records are also referred to as the BOF and EOF cracks. -//You don't have to worry about setting the BOF and EOF flags as this is done internally -//by TDataSet. However, you must override the GetBookmarkFlag and SetBookmarkFlag methods -//to get and set the offset off the record buffer points to the bookmark flag. - -function TBoldAbstractDataSet.GetBookmarkFlag(Buffer: PChar): TBookmarkFlag; -begin - Result := GetBookmarkInfo(Buffer)^.Flag; -end; - -//see GetBookmarkFlag -procedure TBoldAbstractDataSet.SetBookmarkFlag(Buffer: PChar; Value: TBookmarkFlag); -begin - GetBookmarkInfo(Buffer)^.Flag := Value; -end; - -function TBoldAbstractDataSet.GetIndexForBookmark(Bookmark: Pointer): integer; -begin - if Assigned(Bookmark) then - try - result := List.IndexOf(TBoldElement(Bookmark^)) - except - result := -1; - end - else - result := -1; -end; - -//maan: this method should position the physical file pointer (i.e. FRecordPos) on the record of interest -procedure TBoldAbstractDataSet.InternalGotoBookmark(Bookmark: Pointer); -var - LIndex: integer; -begin - LIndex := GetIndexForBookmark(Bookmark); - if LIndex >= 0 then - FRecordPos := LIndex; -end; - -procedure TBoldAbstractDataSet.InternalSetToRecord(Buffer: PChar); -begin - InternalGotoBookmark(@GetBookmarkInfo(Buffer)^.Element); -end; - -procedure TBoldAbstractDataSet.SetBookmarkData(Buffer: PChar; Data: Pointer); -begin - GetBookmarkInfo(Buffer)^.Element := Data; -end; - -//InternalFirst should position the current record to the beginning of the physical file. -procedure TBoldAbstractDataSet.InternalFirst; -begin - FRecordPos := -1; //BOF -end; - -//InternalLast should set the record to the end of the physical file. -procedure TBoldAbstractDataSet.InternalLast; -begin - FRecordPos := List.Count; //EOF -end; - -//InternalClose is called by TDataSet.Close. -//In this method, you should de-allocate all resources associated -//with the dataset that were allocated by InternalOpen or that were allocated -//throughout the course of using the dataset. -procedure TBoldAbstractDataSet.InternalClose; -begin - BindFields(False); - if DefaultFields then DestroyFields; // destroy the TField components - fInternalCursorReady := false; -end; - -procedure TBoldAbstractDataSet.InternalHandleException; -begin - BoldEffectiveEnvironment.HandleDesigntimeException(Self); -end; - -//The InternalDelete method deletes the current record from the dataset. -procedure TBoldAbstractDataSet.InternalDelete; -begin - ActiveBoldObject.Delete; - if List.Count = 0 then - FRecordPos := -1; -end; - -//InternalAddRecord is called when a record is inserted or appended to the dataset. -//The Buffer parameter points to the record buffer to be added to the dataset, -//and the Append parameter is True when a record is being appended and False -//when a record is being inserted. -procedure TBoldAbstractDataSet.InternalAddRecord(Buffer: Pointer; Append: Boolean); -var - RecPos: Integer; -begin - if Append then - begin - List.AddNew; - InternalLast; - end - else - begin - if FRecordPos = -1 then - RecPos := 0 - else - RecPos := FRecordPos; - List.InsertNew(RecPos); - end; -end; - -//The InternalOpen method is called by TDataSet.Open. -//In this method, you should open the underlying data source, -//initialize any internal fields or properties, create the field definitions (field defs) -//if necessary, and bind the field defs to the data. -//Additionally, this method should initialize the record position, -//determine record size and determine the record count. -procedure TBoldAbstractDataSet.InternalOpen; -begin - fInternalCursorReady := Assigned(BoldHandle) and BoldHandle.Enabled; - if not fInternalCursorReady then Exit; - FRecordPos := -1; //should be -1, we are not positioned at the first record yet - - if Assigned(BoldHandle.ListElementType) then - InternalInitFieldDefs; //populate FieldDefs - if DefaultFields then CreateFields; //populate Fields from FieldDefs: create TField components if no persistent fields - - BindFields(True); // bind FieldDefs to actual data - - BookmarkSize := SizeOf(TBDSBookmarkInfo); - //compute offsets to various record buffer segments - FBookmarkOfs := FRecordSize + CalcFieldsSize; - FBufferSize := FBookmarkOfs + BookmarkSize; -end; - -//The InternalPost method is called by TDataSet.Post. -//In this method, you should write the data from the active record buffer to the data file. -procedure TBoldAbstractDataSet.InternalPost; -begin - FRecordPos := List.IndexOf(ActiveBoldElement); - if (FRecordPos <> FListFollower.Follower.CurrentIndex) then - begin - FListFollower.SetFollowerIndex(FRecordPos); - CursorPosChanged; - end; -end; - -//The IsCursorOpen method is called internal to TDataSet to determine -//whether or not the data file has been opened or closed. -//Normally, the TDataSet descendant should maintain some boolean field -//which is used to determine the status of the data file. -function TBoldAbstractDataSet.IsCursorOpen: Boolean; -begin - //maan: should return true if we are ready to read from the physical file - Result := fInternalCursorReady ; -end; - -//The GetRecordCount method is one of the optional methods -//that you can override if you want to give Delphi 4's TDBGrid -//the ability to scroll relative to the cursor position in the dataset. -//While this feature makes sense for this implementation, -//there are many cases where this capability isn't practical or even possible. -//For example, if you are working with a huge amount of data, -//it might not be practical to obtain a record count, such as when communicating -//with a SQL server. - -function TBoldAbstractDataSet.GetRecordCount: Integer; -begin - if not Assigned(List) then - result := 0 - else - Result := List.Count; -end; - -function TBoldAbstractDataSet.GetRecNo: Integer; -var - ActiveBuf: PChar; - LIndex: integer; -begin - //maan: this function should return the ACTIVE record NOT the physical file position!!! - Result := 0; - if GetActiveRecBuf(ActiveBuf) then - begin - LIndex := List.IndexOf(GetBookmarkInfo(ActiveBuf)^.Element); - if (LIndex >= 0) and (LIndex < RecordCount) then - Result := LIndex + 1; - end; -end; - -procedure TBoldAbstractDataSet.InternalInitFieldDefs; -var - i: integer; -begin - FRecordSize := 0; - FieldDefs.Clear; - - for i := 0 to FieldDescriptions.Count - 1 do - begin - with FieldDescriptions[i] do - begin - TFieldDef.Create(FieldDefs, EffectiveFieldName, FieldType, FieldSize, Required, i + 1); - fFieldOfs := fRecordSize; - fRecordSize := fRecordSize + BufferSize; - end; - end; -end; - -procedure TBoldAbstractDataSet.LayoutChanged; -var - WasActive: boolean; -begin - WasActive := Active; - FLayoutChanged := True; - if WasActive then - Close; - - FieldDescriptions.InvalidateFields; - - if (WasActive or AutoOpen) and not (csDestroying in componentState) then - TryToOpen; -end; - -function TBoldAbstractDataSet.GetBoldHandle: TBoldAbstractListHandle; -begin - result := FListFollower.BoldHandle; -end; - -procedure TBoldAbstractDataSet.SetBoldHandle(NewValue: TBoldAbstractListHandle); -begin - if fListFollower.BoldHandle <> NewValue then - begin - fListFollower.BoldHandle := NewValue; - fContextSubscriber.CancelAllSubscriptions; - if assigned(NewValue) then - begin - NewValue.addsubscription(fContextSubscriber, beDestroying, beDestroying); - NewValue.addsubscription(fContextSubscriber, beValueIdentityChanged, beValueIdentityChanged); - if assigned(NewValue.List) then - NewValue.List.addsubscription(fContextSubscriber, beItemDeleted, beItemDeleted); - end; - end; -end; - -procedure TBoldAbstractDataSet.SetFieldDescriptions(const Value: TBoldDataSetFieldDescriptions); -begin - FieldDescriptions.Assign(Value); -end; - -procedure TBoldAbstractDataSet.TypeMayHaveChanged; -var - NewType: TBoldElementTypeInfo; -begin - NewType := ListElementType; - if (NewType <> fLastKnownType) then - begin - fLastKnownType := NewType; - TypeHasChanged; - end; -end; - -procedure TBoldAbstractDataSet.TypeHasChanged; -begin - //what to do? - LayOutChanged; -end; - -procedure TBoldAbstractDataSet.Loaded; -begin - if not (csdesigning in ComponentState) and (FieldDescriptions.Count = 0) then - CreateDefaultFields; - inherited; - if AutoOpen and not Active then - TryToOpen; -end; - -procedure TBoldAbstractDataSet.CreateDefaultFields; -var - i: integer; - NewField: TBoldDataSetFieldDescription; -begin - try - DeleteAllFields; - if Assigned(ListElementType) then - begin - if (ListElementType is TBoldClassTypeInfo) then - begin - with ListElementType as TBoldClassTypeInfo do - begin - for i := 0 to AllMembers.Count - 1 do - if AllMembers[i].IsAttribute then - begin - NewField := FieldDescriptions.Add; - NewField.Boldproperties.Expression := AllMembers[i].ExpressionName; - end; - end; - end - else if (ListElementType is TBoldAttributeTypeInfo) then - begin - FieldDescriptions.Add; - //Columns[ColCount - 1].Title.Caption := TBoldAttributeTypeInfo(ListElementType).ModelName; - end - else if (ListElementType is TBoldListTypeInfo) then - begin - FieldDescriptions.Add; - //Columns[ColCount - 1].Title.Caption := 'ClassName'; - end; - end; - finally - LayoutChanged; - end; -end; - -procedure TBoldAbstractDataSet.DeleteAllFields; -begin - while FieldDescriptions.Count > 0 do - FieldDescriptions.Delete(0); -end; - -procedure TBoldAbstractDataSet.SetRecNo(Value: Integer); -begin - // maan: when implemented this method should set the ACTIVE record; implementing this is not crucial. -end; - -end. - diff --git a/Source/BoldAwareGUI/BoldControls/BoldDragDropTarget.pas b/Source/BoldAwareGUI/BoldControls/BoldDragDropTarget.pas index 6ba6938..cbf1ec4 100644 --- a/Source/BoldAwareGUI/BoldControls/BoldDragDropTarget.pas +++ b/Source/BoldAwareGUI/BoldControls/BoldDragDropTarget.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldDragDropTarget; {$UNDEF BOLDCOMCLIENT} @@ -7,7 +10,7 @@ interface Classes, Controls, ExtCtrls, - BoldEnvironmentVCL, // Make sure VCL environement loaded, and finalized after + BoldEnvironmentVCL, BoldElements, {$IFNDEF BOLDCOMCLIENT} BoldSystem, @@ -15,7 +18,8 @@ interface BoldControlpack, BoldElementHandleFollower, BoldReferenceHandle, - BoldNodeControlPack; + BoldNodeControlPack, + BoldDefs; type TBoldDropTarget = class(TImage, IBoldOclComponent) @@ -42,16 +46,16 @@ TBoldDropTarget = class(TImage, IBoldOclComponent) function GetContextType: TBoldElementTypeInfo; procedure SetEmptyImageIndex(const Value: integer); function GetElement: TBoldElement; - procedure SetExpression(Expression: String); - function GetExpression: String; + procedure SetExpression(const Value: TBoldExpression); + function GetExpression: TBoldExpression; function GetVariableList: TBoldExternalVariableList; protected property DraggedObject: TBoldObject read GetDraggedObject; property Element: TBoldElement read GetElement; procedure Notification(AComponent: TComponent; Operation: TOperation); override; public - constructor Create(owner: TComponent); override; - destructor Destroy; override; + constructor create(owner: TComponent); override; + destructor destroy; override; procedure DoStartDrag(var DragObject: TDragObject); override; procedure DoEndDrag(Target:TObject; X, Y: Integer); override; procedure MouseDown(BUTTON: TMouseButton; Shift: TShiftState; X, Y: Integer); override; @@ -68,14 +72,14 @@ TBoldDropTarget = class(TImage, IBoldOclComponent) end; implementation - uses Graphics, SysUtils, + BoldAttributes, {$IFNDEF BOLDCOMCLIENT} BoldGui, {$ENDIF} - BoldAttributes; + BoldRev; { TBoldDropTarget } @@ -111,11 +115,11 @@ constructor TBoldDropTarget.create(owner: TComponent); FRepresentations.OnGetContextType := GetContextType; fHandleFollower := TBoldElementHandleFollower.create(Owner, Representations); FRepresentations.AfterMakeUptoDate := AfterMakeUptoDate; - FNodeSelectionExpression := 'oclType.asstring->union(oclType.allsupertypes.asString)->union('''')'; // do not localize + FNodeSelectionExpression := 'oclType.asstring->union(oclType.allsupertypes.asString)->union('''')'; AfterMakeUptoDate(fHandleFollower.Follower); end; -destructor TBoldDropTarget.Destroy; +destructor TBoldDropTarget.destroy; begin FreeAndNil(FHandleFollower); FreeAndNil(FRepresentations); @@ -151,12 +155,9 @@ procedure TBoldDropTarget.DragDrop(Source: TObject; X, Y: Integer); procedure TBoldDropTarget.DragOver(Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean); begin - // First set the hard accept value Accept := IsDropTarget and CanAcceptDraggedObject; - // Then, if we accept, invoke user code if Accept and Assigned(OnDragOver) then OnDragOver(Self, Source, X, Y, State, Accept); - // Make sure we only accept if hard conditions are true. Accept := Accept and IsDropTarget and CanAcceptDraggedObject; end; @@ -185,7 +186,6 @@ function TBoldDropTarget.GetCurrentNodeDescription: TBoldNodeDescription; begin ie := TBoldIndirectElement.create; try - // this code should move to the treeview support classes (or is it already there???) Element.EvaluateAndSubscribeToExpression(NodeSelectionExpression, fHandleFollower.Follower.Subscriber, ie); if ie.value is TBoldList then begin list := ie.value as TBoldList; @@ -285,9 +285,9 @@ procedure TBoldDropTarget.SetEmptyImageIndex(const Value: integer); FEmptyImageIndex := Value; end; -procedure TBoldDropTarget.SetExpression(Expression: String); +procedure TBoldDropTarget.SetExpression(const Value: TBoldExpression); begin - NodeSelectionExpression := Expression; + NodeSelectionExpression := Value; end; procedure TBoldDropTarget.SetImageList(const Value: TImageList); @@ -317,4 +317,5 @@ procedure TBoldDropTarget.SetRepresentations(Value: TBoldTreeFollowerController) FRepresentations.Assign(Value); end; +initialization end. diff --git a/Source/BoldAwareGUI/BoldControls/BoldEdit.pas b/Source/BoldAwareGUI/BoldControls/BoldEdit.pas index 9eef2cf..33aa3be 100644 --- a/Source/BoldAwareGUI/BoldControls/BoldEdit.pas +++ b/Source/BoldAwareGUI/BoldControls/BoldEdit.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldEdit; {$UNDEF BOLDCOMCLIENT} @@ -13,13 +16,14 @@ interface Menus, Graphics, Buttons, - BoldEnvironmentVCL, // Make sure VCL environement loaded, and finalized after + BoldEnvironmentVCL, BoldControlsDefs, BoldHandles, BoldElements, BoldControlPack, BoldElementHandleFollower, - BoldStringControlPack; + BoldStringControlPack, + BoldDefs; type {Forward declarations of all classes} @@ -45,10 +49,10 @@ TBoldCustomEdit = class(TCustomEdit, IBoldOCLComponent) fMaxLength: integer; {Bold stuff} function GetContextType: TBoldElementTypeInfo; - procedure SetExpression(Expression: String); - function GetExpression: String; + procedure SetExpression(const Value: TBoldExpression); + function GetExpression: TBoldExpression; function GetVariableList: TBoldExternalVariableList; - + function GetBoldHandle: TBoldElementHandle; procedure SetBoldHandle(value: TBoldElementHandle); function GetFollower: TBoldFOllower; @@ -99,7 +103,7 @@ TBoldCustomEdit = class(TCustomEdit, IBoldOCLComponent) property BeepOnInvalidKey: boolean read fBeepOnInvalidKey write fBeepOnInvalidKey default True; property Button: TSpeedButton read GetButton; - property ButtonControl: TWinControl read fBtnControl; //NOTE Do not publish. + property ButtonControl: TWinControl read fBtnControl; property EffectiveReadOnly: Boolean read GetEffectiveReadOnly; property EffectiveFont: TFont read GetEffectiveFont; property EffectiveColor: TColor read GetEffectiveColor write SetEffectiveColor; @@ -143,20 +147,16 @@ TBoldEdit = class(TBoldCustomEdit) property Anchors; property AutoSelect; property AutoSize; -// property BiDiMode; property BorderStyle; property CharCase; -// property Color; property Constraints; property Ctl3D; property DragCursor; property DragKind; property DragMode; property Enabled; -// property Font; property HideSelection; -// property ImeMode; -// property ImeName; + property MaxLength; property ParentColor; property ParentCtl3D; @@ -164,11 +164,9 @@ TBoldEdit = class(TBoldCustomEdit) property ParentShowHint; property PasswordChar; property PopupMenu; -// property ReadOnly; property ShowHint; property TabOrder; property TabStop; -// property Text; property Visible; property OnChange; property OnClick; @@ -196,15 +194,14 @@ implementation uses BoldControlPackDefs, SysUtils, - Forms, // bssingle - {$IFNDEF BOLDCOMCLIENT} // uses - BoldSystem, // For Specialized Drag/Drop in EditBox - BoldGUI, // For Specialized Drag/Drop in EditBox + BoldUtils, + Forms, + {$IFNDEF BOLDCOMCLIENT} + BoldSystem, + BoldGUI, BoldReferenceHandle, BoldRootedHandles, {$ENDIF} - BoldDefs, - BoldGuiResourceStrings, BoldCommonBitmaps; { TBoldComboButton } @@ -217,6 +214,7 @@ TBoldComboButton = class(TSpeedButton) X, Y: Integer); override; end; + {---TBoldCustomEdit---} constructor TBoldCustomEdit.Create(AOwner: TComponent); begin @@ -271,7 +269,7 @@ procedure TBoldCustomEdit.DoEndDrag(Target: TObject; X, Y: Integer); procedure TBoldCustomEdit.DragOver(Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean); begin - {$IFNDEF BOLDCOMCLIENT} //dragdrop + {$IFNDEF BOLDCOMCLIENT} if (BoldProperties.DropMode = bdpReplace) and (assigned(BoldHandle)) and (not assigned(BoldHandle.Value) or (BoldHandle.Value is TBoldObject)) and @@ -290,7 +288,7 @@ procedure TBoldCustomEdit.DragOver(Source: TObject; X, Y: Integer; State: TDragS procedure TBoldCustomEdit.DragDrop(Source: TObject; X, Y: Integer); begin - {$IFNDEF BOLDCOMCLIENT} //dragdrop + {$IFNDEF BOLDCOMCLIENT} if (BoldProperties.DropMode = bdpReplace) and (assigned(BoldHandle)) and (not assigned(BoldHandle.Value) or (BoldHandle.Value is TBoldObject)) and @@ -373,17 +371,17 @@ function TBoldCustomEdit.GetEffectiveColor: TColor; procedure TBoldCustomEdit.SetEffectiveColor(v: TColor); begin - if (EffectiveColor <> v) and not ParentColor then + if EffectiveColor <> v then inherited Color := v; end; -procedure TBoldCustomEdit.SetText(value: string); //CHECKME Remove? Text is not published any longer! +procedure TBoldCustomEdit.SetText(value: string); begin if not (csLoading in ComponentState) then if not EffectiveReadOnly then inherited Text := value else - raise EBold.CreateFmt(sTextNotModifiable, [ClassName]); + raise EBold.CreateFmt('%s.Text: Not modifiable', [ClassName]); end; function TBoldCustomEdit.GetText: string; @@ -411,13 +409,13 @@ procedure TBoldCustomEdit.InvalidKey(Key: Char); procedure TBoldCustomEdit.KeyPress(var Key: Char); begin inherited KeyPress(Key); - if (Key in [#32..#255]) and + if CharInSet(Key, [#32..#255]) and not BoldProperties.ValidateCharacter(Key, Follower) then begin InvalidKey(Key); Key := BOLDNULL; end - else if Key = #1 then // CTRL-A + else if Key = #1 then begin SelectAll; end @@ -471,12 +469,9 @@ procedure TBoldCustomEdit.AfterMakeUptoDate(Follower: TBoldFollower); inherited MaxLength := EffectiveMaxLength; - if not ParentColor then - begin - ec := EffectiveColor; - BoldProperties.SetColor(ec, Color, Follower); - EffectiveColor := ec; - end; + ec := EffectiveColor; + BoldProperties.SetColor(ec, Color, Follower); + EffectiveColor := ec; end; @@ -667,7 +662,6 @@ procedure TBoldCustomEdit.SetEditRect; var Loc: TRect; begin -// SendMessage(Handle, EM_GETRECT, 0, LongInt(@Loc)); Loc.Bottom := ClientHeight+1; Loc.Right := ClientWidth-1; Loc.Top := 0; @@ -686,15 +680,13 @@ procedure TBoldCustomEdit.SetEditRect; end; procedure TBoldCustomEdit.WMSize(var message: TWMSize); -//var -// MinHeight: Integer; + begin inherited; -// if (csDesigning in ComponentState) then -// FGrid.SetBounds(0, Height + 1, 10, 10); -// MinHeight := GetMinHeight; -// if Height < MinHeight then Height := MinHeight -// else begin + + + + if Assigned(fBtnControl) and Assigned(fButton) then SetEditRect; end; @@ -710,7 +702,6 @@ procedure TBoldCustomEdit.SetButtonStyle(const Value: TBoldEditButtonStyle); begin if Assigned(fBtnControl) then fBtnControl.Visible := False; - //NOTE Skip destruction of button and recreation of control in runtime to eliminate flicker. if (csDesigning in ComponentState) then RecreateWnd; end @@ -749,7 +740,6 @@ procedure TBoldComboButton.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin with TBoldCustomEdit(Parent.Parent) do - //CHECKME We may need to skip the change of focus if the popupcontrol is visible! if (Handle <> GetFocus) and CanFocus then begin SetFocus; @@ -763,8 +753,7 @@ procedure TBoldComboButton.MouseDown(Button: TMouseButton; Shift: TShiftState; procedure TBoldComboButton.MouseMove(Shift: TShiftState; X, Y: Integer); begin inherited MouseMove (Shift, X, Y); -// if (ssLeft in Shift) and (GetCapture = Parent.Handle) then -// MouseDragToGrid(Self, TDBLookupCombo(Parent.Parent).FGrid, X, Y); + end; function TBoldCustomEdit.GetBoldHandle: TBoldElementHandle; @@ -785,15 +774,15 @@ function TBoldCustomEdit.GetContextType: TBoldElementTypeInfo; result := nil; end; -function TBoldCustomEdit.GetExpression: String; +function TBoldCustomEdit.GetExpression: TBoldExpression; begin result := BoldProperties.Expression; end; -procedure TBoldCustomEdit.SetExpression(Expression: String); +procedure TBoldCustomEdit.SetExpression(const Value: TBoldExpression); begin Assert(Assigned(BoldProperties)); - BoldProperties.Expression := Expression; + BoldProperties.Expression := Value; end; function TBoldCustomEdit.GetVariableList: TBoldExternalVariableList; @@ -801,4 +790,6 @@ function TBoldCustomEdit.GetVariableList: TBoldExternalVariableList; result := BoldProperties.VariableList; end; +initialization + end. diff --git a/Source/BoldAwareGUI/BoldControls/BoldGrid.pas b/Source/BoldAwareGUI/BoldControls/BoldGrid.pas index 474ca76..cf75b70 100644 --- a/Source/BoldAwareGUI/BoldControls/BoldGrid.pas +++ b/Source/BoldAwareGUI/BoldControls/BoldGrid.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldGrid; {$UNDEF BOLDCOMCLIENT} @@ -6,9 +9,9 @@ interface uses {$IFDEF DELPHI6_OR_LATER} - Types, // IFDEF DELPHI6_OR_LATER + Types, {$ELSE} - Windows, // else-part of IFDEF DELPHI6_OR_LATER + Windows, {$ENDIF} Messages, Graphics, @@ -17,8 +20,8 @@ interface Menus, StdCtrls, Classes, - BoldEnvironmentVCL, // Make sure VCL environement loaded, and finalized after - {$IFNDEF BOLDCOMCLIENT} // uses + BoldEnvironmentVCL, + {$IFNDEF BOLDCOMCLIENT} BoldSystem, {$ENDIF} BoldCommonBitmaps, @@ -72,7 +75,6 @@ TBoldGridCheckBoxPainterRenderer = class(TBoldAsStringRenderer) TBoldConstraintRenderer = class(TBoldAsStringRenderer) {Override draw in Controllers since we need access to follower} - procedure DefaultMakeUptodateAndSetMayModifyAndSubscribe(Element: TBoldElement; RendererData: TBoldRendererData; FollowerController: TBoldStringFollowerController; Subscriber: TBoldSubscriber); override; procedure DrawOnCanvas(Follower: TBoldFollower; Canvas: TCanvas; Rect: TRect; Alignment: TAlignment; Margins: TPoint); override; end; @@ -81,9 +83,9 @@ TBoldConstraintRenderer = class(TBoldAsStringRenderer) TBoldGridColumns = class(TCollection) private fGrid: TBoldCustomGrid; - function GetColumn(index: Integer): TBoldGridColumn; - procedure MoveColumn(FromIndex, ToIndex: Longint); - procedure SetColumn(index: Integer; Value: TBoldGridColumn); + function GetColumn(index: Integer): TBoldGridColumn; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure MoveColumn(FromIndex, ToIndex: Longint); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure SetColumn(index: Integer; Value: TBoldGridColumn); {$IFDEF BOLD_INLINE} inline; {$ENDIF} protected function GetOwner: TPersistent; override; public @@ -95,7 +97,6 @@ TBoldGridColumns = class(TCollection) end; { TBoldColumnTitle } - // Borrowed from TDBGrid TBoldColumnTitle = class(TPersistent) private fAlignment: TAlignment; @@ -254,34 +255,34 @@ TBoldCustomGrid = class(TCustomGrid, IBoldValidateableComponent) fIsDragging: Boolean; fIsMultiSelecting: Boolean; fLastMouseDownShiftState: TShiftState; + fPostDisplayEventSet: boolean; procedure EnsureOneFixedCol; function GetBoldHandle: TBoldAbstractListHandle; - function GetBoldList: TBoldList; - function GetCurrentBoldElement: TBoldElement; - function GetFollower: TBoldFOllower; - function GetOptions: TGridOptions; + function GetBoldList: TBoldList; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetCurrentBoldElement: TBoldElement; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetFollower: TBoldFOllower; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetOptions: TGridOptions; {$IFDEF BOLD_INLINE} inline; {$ENDIF} function GetSelected(DataRow: integer): Boolean; procedure SetBoldHandle(value: TBoldAbstractListHandle); - procedure SetColumns(Value: TBoldGridColumns); - procedure SetController(Value: TBoldListAsFollowerListController); - procedure SetOptions(val: TGridOptions); + procedure SetColumns(Value: TBoldGridColumns); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure SetController(Value: TBoldListAsFollowerListController); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure SetOptions(val: TGridOptions); {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure SetSelection(aRow: Integer; Shift: TShiftState; ForceClearOfOtherRows: Boolean; IgnoreToggles: Boolean); procedure TypeMayHaveChanged; - // DRAW FUNCTIONS function CellFont(Column: TBoldGridColumn): TFont; function GetString(GridCol, DataRow: Integer): string; function HighlightCell(AState: TGridDrawState; aRow: integer): Boolean; - // EDIT FUNCTIONS procedure _AfterMakeCellUptoDate(Follower: TBoldFollower); procedure _DeleteRow(index: Integer; owningFollower: TBoldFollower); - procedure _InsertRow(Follower: TBoldFollower); + procedure _InsertRow(index: Integer; OwningFollower: TBoldFollower); + procedure _ReplaceRow(index: Integer; AFollower: TBoldFollower); procedure AdjustCol(Col: Integer); function DefaultTitlePopup(Col: Integer): TPopupMenu; procedure DefaultTitlePopupOnClick(Sender: TObject); function GetCellFollower(ListCol, DataRow: Integer): TBoldFollower; function GetCurrentCellFollower: TBoldFollower; function GetMultiSelect: Boolean; - function GetRowFollower(DataRow: Integer): TBoldFollower; + function GetRowFollower(DataRow: Integer): TBoldFollower; {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure InvalidateFromRow(DisplayDataRow: Longint); procedure SetCurrentRow(DataRow: Integer); procedure SetMultiSelect(V: Boolean); @@ -294,16 +295,18 @@ TBoldCustomGrid = class(TCustomGrid, IBoldValidateableComponent) function ColumnIsCheckBox(col: integer): Boolean; procedure WMChar(var Msg: TWMChar); message WM_CHAR; {$ENDIF} - function GetMutableList: TBoldList; + function GetMutableList: TBoldList; {$IFDEF BOLD_INLINE} inline; {$ENDIF} function GetShowTitleRow: Boolean; procedure SetShowTitleRow(const Value: Boolean); function GetTitleRow: integer; procedure GetActiveRange(var FirstActive, LastActive: integer); property MultiSelect: Boolean read GetMultiSelect write SetMultiSelect; procedure EnsureRowActive(DataRow: integer); - procedure DisplayAvailableFollowers; + procedure DisplayAvailableFollowers; {$IFDEF BOLD_INLINE} inline; {$ENDIF} function GetCellText(col, row: integer): string; procedure _FontChanged(Sender: TObject); + procedure PostDisplayEvent(Sender: TObject); + procedure SetPostDisplayEvent; protected { Protected declarations } procedure _AfterMakeListUptoDate(Follower: TBoldFollower); virtual; @@ -318,8 +321,8 @@ TBoldCustomGrid = class(TCustomGrid, IBoldValidateableComponent) procedure ColWidthsChanged; override; function CreateColumns: TBoldGridColumns; dynamic; procedure CreateDefaultColumns; virtual; - function DataRow(GridRow: Integer): Integer; - function GridRow(Datarow: Integer): Integer; + function DataRow(GridRow: Integer): Integer; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GridRow(Datarow: Integer): Integer; {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure DblClick; override; procedure DefaultColumns; procedure DeleteAllColumns; @@ -393,7 +396,7 @@ TBoldCustomGrid = class(TCustomGrid, IBoldValidateableComponent) procedure DisplayAllCells; function AsClipBoardText: String; procedure ActivateAllCells; - property ColCount;// read GetColCount; + property ColCount; property CellText[col, row: integer]: string read GetCellText; property MutableList: TBoldList read GetMutableList; end; @@ -431,7 +434,7 @@ TBoldGrid = class(TBoldCustomGrid) property Color; property Constraints; property Columns; - {$IFNDEF BCB} // for some reason, the below line gives an error in the generated .hpp-file + {$IFNDEF BCB} property Ctl3d; {$ENDIF} property DefaultColWidth; @@ -484,7 +487,6 @@ TBoldGrid = class(TBoldCustomGrid) end; { TBoldInplaceEdit } - // Used to access Font property of InplaceEditor TBoldInplaceEdit = class(TInplaceEdit) private {$IFNDEF BOLDCOMCLIENT} @@ -532,19 +534,18 @@ implementation uses SysUtils, Forms, - {$IFNDEF BOLDCOMCLIENT} // uses + {$IFNDEF BOLDCOMCLIENT} BoldAttributes, BoldSystemRT, BoldAFP, BoldGUI, {$ENDIF} -// BoldGridRTColEditor BoldEnvironment, - BoldGuiResourceStrings, BoldDefs, BoldListControlPack, + BoldUtils, TypInfo, - BoldMath; + BoldMath, BoldQueue; const ColumnTitleValues = [cvTitleColor..cvTitleFont]; @@ -565,12 +566,12 @@ TBoldInplaceCombo = class(TCombobox) protected procedure WndProc(var Message: TMessage); override; public - constructor createWithInplaceEditor(InplaceEdit: TBoldInplaceEdit); + constructor CreateWithInplaceEditor(InplaceEdit: TBoldInplaceEdit); end; { TBoldInplaceCombo } -constructor TBoldInplaceCombo.createWithInplaceEditor(InplaceEdit: TBoldInplaceEdit); +constructor TBoldInplaceCombo.CreateWithInplaceEditor(InplaceEdit: TBoldInplaceEdit); begin inherited Create(InplaceEdit); fInplaceEdit := InplaceEdit; @@ -619,7 +620,6 @@ procedure TBoldInplaceEdit.BoundsChanged; var R: TRect; begin - // This method replaces ancestor method, as it doesn't seem to do the right thING Assert(Assigned(Grid)); R := Rect(2, 2, TBoldCustomGrid(Grid).Columns[TBoldCustomGrid(Grid).Col].Width - 2, Height); SendMessage(Handle, EM_SETRECTNP, 0, LongInt(@R)); @@ -632,9 +632,8 @@ procedure TBoldInplaceEdit.KeyPress(var Key: Char); begin inherited KeyPress(Key); Grid := TBoldCustomGrid(Owner); - // when editing, clear all other selected rows Grid.SetSelection(grid.DataRow(grid.Row), [], true, false); - if (Key in [#32..#255]) and + if CharInSet(Key, [#32..#255]) and not Grid.Columns[Grid.Col].BoldProperties.ValidateCharacter(Key, Grid.CurrentCellFollower) then begin MessageBeep(0); @@ -774,7 +773,7 @@ procedure TBoldColumnTitle._FontChanged(Sender: TObject); Exclude(fColumn.fAssignedValues, cvTitleFont) else Include(fColumn.fAssignedValues, cvTitleFont); - Changed; // ??? + Changed; end; function TBoldColumnTitle.GetAlignment: TAlignment; @@ -916,7 +915,7 @@ constructor TBoldGridColumn.Create(theCollection: TCollection); begin inherited Create(theCollection); if not (theCollection is TBoldGridColumns) then - raise EBold.CreateFmt(sCannotCreateColumnOutsideCollection, [ClassName]); + raise EBold.CreateFmt('%s.Create: Cannot create TBoldGridColumn outside a TBoldGridColumns', [ClassName]); fGrid := (theCollection as TBoldGridColumns).Grid; FBoldProperties := TBoldStringFollowerController.Create(fGrid); fColor := fGrid.Color; @@ -937,7 +936,6 @@ constructor TBoldGridColumn.Create(theCollection: TCollection); end; destructor TBoldGridColumn.Destroy; - // CollectionItem removes itself from collection when destroyed begin if fGrid.fFixedColumn = self then fGrid.fFixedColumn := nil; @@ -955,7 +953,6 @@ destructor TBoldGridColumn.Destroy; procedure TBoldGridColumn.Assign(Source: TPersistent); -// Code mainly from DBGrids var SourceCol: TBoldGridColumn; begin @@ -976,12 +973,11 @@ procedure TBoldGridColumn.Assign(Source: TPersistent); if cvAlignment in SourceCol.AssignedValues then Alignment := SourceCol.Alignment; Title := SourceCol.Title; -// if cvReadOnly in SourceCol.AssignedValues then -// ReadOnly := SourceCol.ReadOnly; -// DropDownRows := SourceCol.DropDownRows; -// ButtonStyle := SourceCol.ButtonStyle; -// PickList := SourceCol.PickList; -// PopupMenu := SourceCol.PopupMenu; + + + + + finally if Assigned(Collection) then Collection.EndUpdate; @@ -1012,8 +1008,7 @@ procedure TBoldGridColumn.RestoreDefaults; FTitle.RestoreDefaults; FAssignedValues := []; RefreshDefaultFont; -// FreeAndNil(FPickList); -// ButtonStyle := cbsAuto; + Changed(FontAssigned); end; @@ -1155,11 +1150,11 @@ constructor TBoldCustomGrid.Create(AOwner: TComponent); fBoldProperties := TBoldListAsFollowerListController.Create(self, fBoldColumnsProperties); fBoldProperties.OnAfterInsertItem := _InsertRow; fBoldProperties.OnAfterDeleteItem := _DeleteRow; + fBoldProperties.OnReplaceitem := _ReplaceRow; fBoldProperties.AfterMakeUptoDate := _AfterMakeListUptoDate; fBoldProperties.BeforeMakeUptoDate := _BeforeMakeListUptoDate; fBoldProperties.OnGetContextType := GetHandleStaticType; fHandleFollower := TBoldListHandleFollower.Create(Owner, fBoldProperties); - // fHandleFollower.OnHandleIndexChanged := HandleIndexChanged; FColumns := CreateColumns; fAnchor := 0; Options := [goFixedVertLine, goFixedHorzLine, goVertLine, @@ -1209,7 +1204,7 @@ procedure TBoldCustomGrid.TypeMayHaveChanged; {$ENDIF} begin if BoldEffectiveEnvironment.RunningInIDE and (not Assigned(BoldHandle) or not Assigned(BoldHandle.List) or (BoldHandle.List.Count = 0)) then - Exit; // only update at runtime if there are values, avoids update on every UML model change. + Exit; NewListElementType := GetHandleListElementType; if (NewListElementType <> fCurrentListElementType) then @@ -1242,12 +1237,11 @@ procedure TBoldCustomGrid.DeleteAllColumns; Columns[ColCount - 1].Free; if columns.count = 0 then AddColumn; - // ensure column 0 EnsureOneFixedCol; end; procedure TBoldCustomGrid.CreateDefaultColumns; -{$IFNDEF BOLDCOMCLIENT} // defaultcolumns +{$IFNDEF BOLDCOMCLIENT} var i: integer; ListElementType: TBoldElementTypeInfo; @@ -1266,7 +1260,7 @@ procedure TBoldCustomGrid.CreateDefaultColumns; {$ENDIF} begin - {$IFNDEF BOLDCOMCLIENT} // defaultcolumns + {$IFNDEF BOLDCOMCLIENT} ListElementType := GetHandleListElementType; DeleteAllColumns; UsedFirstCol := false; @@ -1298,7 +1292,7 @@ procedure TBoldCustomGrid.CreateDefaultColumns; end else if (ListElementType is TBoldListTypeInfo) then begin - GetEmptyCol.Title.Caption := sCaptionClassName; + GetEmptyCol.Title.Caption := 'ClassName'; end; end; if Columns.Count = 2 then @@ -1313,14 +1307,14 @@ procedure TBoldCustomGrid.CreateDefaultColumns; AddColumn; with Columns[ColCount - 1] do begin - Boldproperties.Expression := 'self.oclType'; //do not localize - Title.Caption := sCaptionType; + Boldproperties.Expression := 'self.oclType'; + Title.Caption := 'Type'; end; AddColumn; with Columns[ColCount - 1] do begin Boldproperties.Expression := ''; - Title.Caption := sCaptionAsString; + Title.Caption := 'AsString'; end; end; if BoldShowConstraints then @@ -1370,7 +1364,6 @@ procedure TBoldCustomGrid.ColumnMoved(FromIndex, ToIndex: Longint); begin Columns.MoveColumn(FromIndex, ToIndex); inherited ColumnMoved(FromIndex, ToIndex); - // Redraw affected columns for Col := MinIntValue([FromIndex, ToIndex]) to MaxIntValue([FromIndex, ToIndex]) do Columns.Update(Columns[Col]); end; @@ -1406,21 +1399,17 @@ procedure TBoldCustomGrid.EnsureOneFixedCol; not fIsEnsuringFixedCol then begin fIsEnsuringFixedCol := true; - // there must be atleast one column more than the fixed column while Columns.Count < 2 do if not FirstIsOK then Columns.Insert(0) else Columns.Add; - - // see if the existing first column can be used as our fixed column... if not FirstIsOk then Columns.Insert(0); fFixedColumn := Columns[0]; - // make this column the fixed column. fFixedColumn.BoldProperties.Expression := ''; - fFixedColumn.Title.Caption := ''; // Clear the title + fFixedColumn.Title.Caption := ''; fFixedColumn.Color := Self.FixedColor; if not (csDesigning in componentstate) then fFixedColumn.BoldProperties.Renderer := fFirstColumnRenderer; @@ -1452,6 +1441,12 @@ procedure TBoldCustomGrid.MoveColumn(FromIndex, ToIndex: Longint); inherited MoveColumn(FromIndex, ToIndex); end; +procedure TBoldCustomGrid.PostDisplayEvent(Sender: TObject); +begin + Invalidate; + fPostDisplayEventSet := false; +end; + function TBoldCustomGrid.CreateEditor: TInplaceEdit; begin Result := TBoldInplaceEdit.Create(self); @@ -1460,13 +1455,11 @@ function TBoldCustomGrid.CreateEditor: TInplaceEdit; end; procedure TBoldCustomGrid.EditStop; - // Same as OnExit for each cell var CellFollower: TBoldFollower; begin CellFollower := CurrentCellFollower; - // if the grid is changed under our feet (for example because it is sorted, and we just changed the sort order) - // then ignore the edit stop + if assigned(CellFollower) and (CellFollower.Controller.ApplyPolicy = bapExit) then CellFollower.Apply; @@ -1486,9 +1479,8 @@ function TBoldCustomGrid.GetEditText(GridCol, GridRow: Longint): string; end; procedure TBoldCustomGrid.SetEditText(GridCol, GridRow: Longint; const Value: string); - // called for each change == OnChange begin - if not (csDesigning in ComponentState) and Editormode and assigned(CurrentCellFollower) then // CHECKME heeded? + if not (csDesigning in ComponentState) and Editormode and assigned(CurrentCellFollower) then TBoldStringFollowerController(CurrentCellFollower.Controller).MayHaveChanged(Value, CurrentCellFollower) end; @@ -1510,7 +1502,7 @@ procedure TBoldCustomGrid.DblClick; else if BoldProperties.DefaultDblClick and Assigned(CurrentBoldElement) then begin - {$IFDEF BOLDCOMCLIENT} // autoform + {$IFDEF BOLDCOMCLIENT} AutoForm := nil; {$ELSE} AutoForm := AutoFormProviderRegistry.FormForElement(CurrentBoldElement); @@ -1538,14 +1530,6 @@ procedure TBoldCustomGrid.SetBoldHandle(Value: TBoldAbstractListHandle); fHandleFollower.BoldHandle := value; end; -function TBoldCustomGrid.DataRow(GridRow: Integer): Integer; -begin - if HasGhostRow then - Result := -1 - else - Result := GridRow - FixedRows; -end; - function TBoldCustomGrid.GetCurrentBoldElement: TBoldElement; begin if Assigned(CurrentCellFollower) then @@ -1580,14 +1564,20 @@ procedure TBoldCustomGrid.SetOptions(val: TGridOptions); inherited Options := val - [goRangeSelect]; end; +procedure TBoldCustomGrid.SetPostDisplayEvent; +begin + if fPostDisplayEventSet then + exit; + fPostDisplayEventSet := true; + BoldInstalledQueue.AddEventToPostDisplayQueue(PostDisplayEvent, nil, self) +end; + procedure TBoldCustomGrid.SetSelection(aRow: Integer; Shift: TShiftState; ForceClearOfOtherRows: Boolean; IgnoreToggles: Boolean); begin if aRow = -1 then Exit; fIsMultiSelecting := MultiSelect and ((ssShift in Shift) or (ssCtrl in Shift)); - - // Clear previous selection, Select one item if not ((ssShift in Shift) or (ssCtrl in Shift)) or not MultiSelect then begin if (not Follower.SubFollowers[aRow].Selected) or ForceClearOfOtherRows then @@ -1596,22 +1586,15 @@ procedure TBoldCustomGrid.SetSelection(aRow: Integer; Shift: TShiftState; ForceC fBoldProperties.SetSelected(Follower, aRow, True); end; end; - - // Select range from first selected item if (ssShift in Shift) and MultiSelect then begin fBoldProperties.SelectRange(Follower, aRow); end; - - - // Toggle selection on current item if (ssCtrl in Shift) and MultiSelect and (not IgnoreToggles) then begin fBoldProperties.ToggleSelected(Follower, aRow); end; - // At this point we would rather have invalidated col 0, - // but that does not yield desired redraw WHEN THE GRID SCROLLS. Invalidate; AdjustActiveRange; @@ -1659,7 +1642,7 @@ procedure TBoldCustomGrid.DefaultTitlePopupOnClick(Sender: TObject); begin TMenuItem(Sender).checked := not TMenuItem(Sender).checked; - if Pos('__mnuBoldGridCWA', TMenuItem(Sender).name) = 1 then // do not translate + if Pos('__mnuBoldGridCWA', TMenuItem(Sender).name) = 1 then with Columns[TMenuItem(Sender).Owner.Tag] do if TMenuItem(Sender).checked then CWAdjust := CWAdjust + [TBoldCWAdjust(TMenuItem(Sender).Tag)] @@ -1687,22 +1670,21 @@ function TBoldCustomGrid.DefaultTitlePopup(Col: Integer): TPopupMenu; M := TMenuItem.Create(TheDefaultTitlePopup); M.Caption := GetEnumName(TypeInfo(TBoldCWAdjust), I); M.OnClick := DefaultTitlePopupOnClick; - M.name := '__mnuBoldGridCWA' + GetEnumName(TypeInfo(TBoldCWAdjust), I); // do not translate + M.name := '__mnuBoldGridCWA' + GetEnumName(TypeInfo(TBoldCWAdjust), I); M.Tag := I; M.RadioItem := False; Items.Add(M); end; M := TMenuItem.Create(TheDefaultTitlePopup); - M.Caption := '-'; // do not translate - M.name := '__mnuBoldGridSeparator'; // do not translate + M.Caption := '-'; + M.name := '__mnuBoldGridSeparator'; Items.Add(M); M := TMenuItem.Create(TheDefaultTitlePopup); - M.Caption := sClosePopup; - M.name := '__mnuBoldGridCancel'; // do not translate + M.Caption := '&Close Popup'; + M.name := '__mnuBoldGridCancel'; Items.Add(M); - // Additional possibilities: - // M := nil; - // * Alignment + + end; end; Result := TheDefaultTitlePopup; @@ -1753,11 +1735,10 @@ procedure TBoldCustomGrid.MouseUp(BUTTON: TMouseButton; Shift: TShiftState; X, Y if (Button = mbLeft) then begin if not fIsDragging then - SetSelection(DataRow(Row), Shift, true, false) // Call setselection with currentrow and shiftstate + SetSelection(DataRow(Row), Shift, true, false) else begin - // starting a drag on a nonselected row with ctrl pressed should select the row - // odd behaviour cuases VCL to clear the shiftstate when we expect a ssCTRL, so we check the MouseDownstate instead + if not selected[DataRow(Row)] and (ssCtrl in fLastMouseDownShiftState) then SetSelection(DataRow(Row), fLastMouseDownShiftState, true, false) end; @@ -1793,14 +1774,13 @@ procedure TBoldCustomGrid.MouseDown(BUTTON: TMouseButton; Shift: TShiftState; X, {$ENDIF} inherited; - // Top Left cell marks all rows - // FIXME FIXEDROW handling + if (fLastMouseDownGridCoord.y <> -1) and (fLastMouseDownGridCoord.Y = TitleRow) then begin if fLastMouseDownGridCoord.X = Pred(FixedCols) then begin fBoldProperties.SelectAll(Follower, True); - ReallyInvalidateCol(Pred(FixedCols)); // FIXME InvalidateCol doesn't invalidate last when scrolling + ReallyInvalidateCol(Pred(FixedCols)); AdjustActiveRange; end else @@ -1810,17 +1790,15 @@ procedure TBoldCustomGrid.MouseDown(BUTTON: TMouseButton; Shift: TShiftState; X, fLastMouseDownScreenCoord := Point(-1, -1); end; end - else //mark clicked row + else begin - if (Button = mbLeft) and (fLastMouseDownGridCoord.Y >= FixedRows) then // if clicking outside datacells, y is -1 + if (Button = mbLeft) and (fLastMouseDownGridCoord.Y >= FixedRows) then begin Row := fLastMouseDownGridCoord.Y; - // if the click is in column 0 and it is already selected, don't reselect anything if not ((fLastMouseDownGridCoord.x = pred(FixedCols)) and Selected[fLastMouseDownGridCoord.y]) then - SetSelection(DataRow(Row), Shift, false, true) // SetSelection Invalidates entire grid + SetSelection(DataRow(Row), Shift, false, true) end; end; - // drag if on col 0 if (Button = mbLeft) and (fLastMouseDownGridCoord.X = Pred(FixedCols)) then begin try @@ -1835,31 +1813,33 @@ procedure TBoldCustomGrid.MouseDown(BUTTON: TMouseButton; Shift: TShiftState; X, procedure TBoldCustomGrid.KeyDown(var KEY: Word; Shift: TShiftState); const - RowMovementKeys = [VK_LEFT, VK_RIGHT, VK_UP, VK_PRIOR, VK_DOWN, VK_NEXT, VK_HOME, VK_END, VK_TAB]; + RowMovementKeys = [VK_UP, VK_PRIOR, VK_DOWN, VK_NEXT, VK_HOME, VK_END, VK_TAB]; begin if Key in Rowmovementkeys then begin HideEditor; - if (ssShift in Shift) and MultiSelect and (key <> VK_TAB) then + if (ssShift in Shift) and MultiSelect then fIsMultiSelecting := true; end; - if CanEditShow and (Key = VK_DELETE) and (Shift = []) then + if (Key = VK_DELETE) and (Shift = []) then begin - ShowEditor; - InplaceEditor.Text := ''; - SetEditText(Col, Row, ''); + if (goEditing in Options) and not (BoldHandle.List.Count = 0) then begin + ShowEditor; + InplaceEditor.Text := ''; + SetEditText(Col, Row, ''); + end; end; - + if (Row = RowCount - 1) and (KEY = 40) then {40 = KeyDown} begin if AddNewAtEnd and (fBoldProperties.NilElementMode<>neAddLast) then begin BoldHandle.List.AddNew; - Follower.EnsureDisplayable; // Force control to get in sync with Object Layer + Follower.EnsureDisplayable; end else - KEY := 0; // Avoid walking below last row + KEY := 0; end; {$IFNDEF BOLDCOMCLIENT} if not (Key in RowMovementKeys) and not (Key in [VK_LEFT, VK_RIGHT]) and ColumnIsCheckBox(Col) then @@ -1871,13 +1851,12 @@ procedure TBoldCustomGrid.KeyDown(var KEY: Word; Shift: TShiftState); procedure TBoldCustomGrid.KeyUp(var KEY: Word; Shift: TShiftState); begin - if (KEY in [33..40]) and not Editormode then //PGUP..DOWN + if KEY in [33..40] then begin - //FIXME: It *is* possible to make non-consecutive selections with keyboard. - // I think the algorithm has to be rewritten to accommodate this. - // Also: Check how Delphi/Windows implements keyboard selections (keys/combinations) - Exclude(Shift, ssCtrl); // Cannot make non-consecutive selections with keyboard - SetSelection(DataRow(Row), Shift, true, true); // Call setselection with currentrow and shiftstate + + + Exclude(Shift, ssCtrl); + SetSelection(DataRow(Row), Shift, true, true); end; inherited; end; @@ -1889,9 +1868,11 @@ function TBoldCustomGrid.GetString(GridCol, DataRow: Integer): string; else begin EnsureRowActive(DataRow); - // if a cell's controller has not be created yet then you'll get an AV (ex: setting the CWAdjust flag) if Assigned(CellFollowers[GridCol, DataRow]) and Assigned(CellFollowers[GridCol, DataRow].Controller) then + begin + Follower.EnsureDisplayable; Result := TBoldStringFollowerController(CellFollowers[GridCol, DataRow].Controller).GetCurrentAsString(CellFollowers[GridCol, DataRow]); + end; end; end; @@ -1942,9 +1923,8 @@ procedure TBoldCustomGrid.AdjustCol(Col: Integer); procedure TBoldCustomGrid.ColWidthsChanged; begin inherited; - // By including TopLeftChanged, [caAllowGrow, caAllowShrink] - // effectively freezes the column width - // TopLeftChanged; + + end; function TBoldCustomGrid.CanEditAcceptKey(KEY: Char): Boolean; @@ -1958,7 +1938,7 @@ function TBoldCustomGrid.CanEditModify: Boolean; if not Assigned(CurrentCellFollower) then Result := False else - Result := CurrentCellFollower.Controller.MayModify(CurrentCellFollower) and + Result := CurrentCellFollower.MayModify and not Columns[Col].ColReadOnly; end; @@ -1966,9 +1946,8 @@ function TBoldCustomGrid.CanEditShow: Boolean; begin Result := (inherited CanEditShow) and Assigned(CurrentCellFollower) and not Columns[Col].ColReadOnly; - // editable if we have a write-allowing renderer or a lookup-handle result := result and - (CurrentCellFollower.RendererData.MayModify + (CurrentCellFollower.MayModify {$IFNDEF BOLDCOMCLIENT} or assigned(Columns[Col].LookupHandle) {$ENDIF}); @@ -1994,6 +1973,31 @@ procedure TBoldCustomGrid.TopLeftChanged; FOnTopLeftChanged(Self); end; +function TBoldCustomGrid.GetRowFollower(DataRow: Integer): TBoldFollower; +begin + if datarow < Follower.SubFollowerCount then + begin + Result := Follower.SubFollowers[DataRow]; + end + else + result := nil; +end; + +function TBoldCustomGrid.GetCellFollower(ListCol, DataRow: Integer): TBoldFollower; +var + RowFollower: TBoldFollower; +begin + RowFollower := GetRowFollower(DataRow); + if assigned(RowFollower) and + (ListCol >= 0) and + (listCol < RowFollower.SubFollowerCount) then + begin + Result := RowFollower.SubFollowers[ListCol]; + end + else + result := nil; +end; + procedure TBoldCustomGrid.DrawCell(ACol, aRow: Longint; ARect: TRect; AState: TGridDrawState); var aListRow: Integer; @@ -2002,10 +2006,9 @@ procedure TBoldCustomGrid.DrawCell(ACol, aRow: Longint; ARect: TRect; AState: TG cl: TColor; TempRect: TRect; FrameFlags1, FrameFlags2: DWORD; - + CellFollower: TBoldFollower; begin -// if (csDesigning in ComponentState) and (aRow > 0) then -// Exit; //FIXME Removed to test Grids in designtime + if Follower.IsInDisplayList then exit; aListRow := DataRow(aRow); if (ACol > Columns.Count - 1) then @@ -2037,7 +2040,7 @@ procedure TBoldCustomGrid.DrawCell(ACol, aRow: Longint; ARect: TRect; AState: TG begin if (aRow = TitleRow) then {Title row} begin - if Assigned(DrawColumn.Title) then // Attempts to redraw before column is done creating + if Assigned(DrawColumn.Title) then begin Font.Assign(DrawColumn.Title.Font); Align := DrawColumn.Title.Alignment; @@ -2045,13 +2048,23 @@ procedure TBoldCustomGrid.DrawCell(ACol, aRow: Longint; ARect: TRect; AState: TG TBoldAsStringRenderer.DrawStringOnCanvas(Canvas, ARect, Align, Point(1, 1), DrawColumn.Title.Caption); end end - else if RowFollowers[aListRow].Displayable then + else begin + if not Assigned(RowFollowers[aListRow]) or RowFollowers[aListRow].IsInDisplayList then + begin + SetPostDisplayEvent; + exit; + end; + CellFollower := CellFollowers[ACol, aListRow]; + if not Assigned(CellFollower) or CellFollower.IsInDisplayList then + begin + SetPostDisplayEvent; + exit; + end; with Columns[ACol].BoldProperties do begin - // Render font and color - SetFont(Canvas.Font, CellFont(DrawColumn), CellFollowers[ACol, aListRow]); - SetColor(cl, DrawColumn.Color, CellFollowers[ACol, aListRow]) + SetFont(Canvas.Font, CellFont(DrawColumn), CellFollower); + SetColor(cl, DrawColumn.Color, CellFollower) end; if HighlightCell(AState, aRow) then @@ -2068,7 +2081,9 @@ procedure TBoldCustomGrid.DrawCell(ACol, aRow: Longint; ARect: TRect; AState: TG OnDrawCell(DrawColumn, Canvas, ACol, aRow, ARect, AState); end else - Columns[ACol].BoldProperties.DrawOnCanvas(CellFollowers[ACol, aListRow], Canvas, ARect, DrawColumn.Alignment, Point(2, 2)); + begin + Columns[ACol].BoldProperties.DrawOnCanvas(CellFollower, Canvas, ARect, DrawColumn.Alignment, Point(2, 2)); + end; end; if (gdFixed in AState) and Ctl3D and ((FrameFlags1 or FrameFlags2) <> 0) then @@ -2091,6 +2106,19 @@ procedure TBoldCustomGrid.DrawCell(ACol, aRow: Longint; ARect: TRect; AState: TG end; end; +function TBoldCustomGrid.GridRow(Datarow: Integer): Integer; +begin + Result := Datarow + FixedRows; +end; + +function TBoldCustomGrid.DataRow(GridRow: Integer): Integer; +begin + if HasGhostRow then + Result := -1 + else + Result := GridRow - FixedRows; +end; + procedure TBoldCustomGrid._AfterMakeCellUptoDate(Follower: TBoldFollower); var DisplayGridRow: Integer; @@ -2112,44 +2140,30 @@ procedure TBoldCustomGrid.InvalidateFromRow(DisplayDataRow: Longint); InvalidateRow(I); end; -procedure TBoldCustomGrid._InsertRow(Follower: TBoldFollower); -begin - if Follower.Index < fInvalidateFrom then - fInvalidateFrom := Follower.Index; - fLastInsertedRowIndex := Follower.Index; -end; - -procedure TBoldCustomGrid._DeleteRow(index: Integer; owningFollower: TBoldFollower); +procedure TBoldCustomGrid._InsertRow(index: Integer; OwningFollower: TBoldFollower); begin if Index < fInvalidateFrom then fInvalidateFrom := Index; + fLastInsertedRowIndex := Index; end; -procedure TBoldCustomGrid.SetCurrentRow(DataRow: Integer); +procedure TBoldCustomGrid._ReplaceRow(index: Integer; + AFollower: TBoldFollower); begin - Row := GridRow(MaxIntValue([0, DataRow])); // Need to make sure we never focus on row 0 - ReallyInvalidateCol(0); // Need to redraw first column FIXME let renderer to this too + if Index < fInvalidateFrom then + fInvalidateFrom := Index; end; -function TBoldCustomGrid.GetRowFollower(DataRow: Integer): TBoldFollower; +procedure TBoldCustomGrid._DeleteRow(index: Integer; owningFollower: TBoldFollower); begin - if datarow < Follower.SubFollowerCount then - Result := Follower.SubFollowers[DataRow] - else - result := nil; + if Index < fInvalidateFrom then + fInvalidateFrom := Index; end; -function TBoldCustomGrid.GetCellFollower(ListCol, DataRow: Integer): TBoldFollower; -var - RowFollower: TBoldFollower; +procedure TBoldCustomGrid.SetCurrentRow(DataRow: Integer); begin - RowFollower := GetRowFollower(DataRow); - if assigned(RowFollower) and - (ListCol >= 0) and - (listCol < RowFollower.SubFollowerCount) then - Result := RowFollower.SubFollowers[ListCol] - else - result := nil; + Row := GridRow(MaxIntValue([0, DataRow])); + ReallyInvalidateCol(0); end; function TBoldCustomGrid.GetCurrentCellFollower; @@ -2161,11 +2175,16 @@ function TBoldCustomGrid.GetCurrentCellFollower; end; function TBoldCustomGrid.GetSelected(DataRow: integer): Boolean; +var + lBoldFollower: TBoldFollower; begin + Result := false; if (DataRow >= 0) and (DataRow < Follower.SubFollowerCount) then - Result := RowFollowers[DataRow].Selected - else - Result := false; + begin + lBoldFollower := RowFollowers[DataRow]; + if Assigned(lBoldFollower) then + Result := RowFollowers[DataRow].Selected; + end; end; procedure TBoldCustomGrid._AfterMakeListUptoDate(Follower: TBoldFollower); @@ -2180,12 +2199,9 @@ procedure TBoldCustomGrid._AfterMakeListUptoDate(Follower: TBoldFollower); RowCount := FixedRows + 1 else RowCount := Follower.SubFollowerCount + FixedRows; - - // if exactly one row has been inserted, then select it. if AutoSelectNewRows and (fSubFollowerCountBeforeMakeUpToDate = Follower.SubFollowerCount - 1) then begin - // perhaps this is a bit overkill, but it works. anyone with a better suggestion? BoldHandle.CurrentIndex := fLastInsertedRowIndex; Follower.CurrentIndex := fLastInsertedRowIndex; SetCurrentRow(Follower.CurrentIndex); @@ -2196,19 +2212,17 @@ procedure TBoldCustomGrid._AfterMakeListUptoDate(Follower: TBoldFollower); not assigned(RowFollowers[Follower.CurrentIndex]) or (fEditedElementBeforeMakeUpToDate <> RowFollowers[Follower.CurrentIndex].Element)) then EditorMode := false; - +{ if (fSubFollowerCountBeforeMakeUpToDate = 0) and (Follower.SubFollowerCount > 0) and (Follower.CurrentIndex <> -1) then begin Follower.SubFollowers[Follower.CurrentIndex].Selected := true; end; - +} AdjustActiveRange; if fInvalidateFrom <> MAXINT then InvalidateFromRow(fInvalidateFrom); - - // setting the currentRow will reset the LeftCol if GridRow(Follower.CurrentIndex) < RowCount then begin OldLeftCol := LeftCol; @@ -2216,7 +2230,7 @@ procedure TBoldCustomGrid._AfterMakeListUptoDate(Follower: TBoldFollower); LeftCol := OldLeftCol; end; - if not fIsMultiSelecting and + if not fIsMultiSelecting and (Follower.CurrentIndex <> -1) and (Follower.SubFollowerCount > 0) and assigned(Follower.SubFollowers[Follower.CurrentIndex]) and not Follower.SubFollowers[Follower.CurrentIndex].Selected then begin @@ -2242,7 +2256,7 @@ function TBoldCustomGrid.GetFollower: TBoldFOllower; procedure TBoldCustomGrid._BeforeMakeListUpToDate(Follower: TBoldFollower); begin - TypeMayHaveChanged; // IMPROVEME, subscribe to listidentitychanged instead. + TypeMayHaveChanged; fMakingListUpToDate := True; AdjustActiveRange; fInvalidateFrom := MAXINT; @@ -2311,8 +2325,7 @@ function TBoldInplaceEdit.GetDestElement(CellFollower: TBoldFollower; Column: TB result := nil; if assigned(cellFollower) and assigned(CellFollower.Element) then begin - // if the event is active, then return the element in the grid, otherwise - // see if we get any useful element from the cell. + if assigned(Column.OnLookupChange) then result := CellFollower.Element else @@ -2406,7 +2419,7 @@ procedure TBoldInplaceEdit.InitCombo(var Message: TWMWindowPosChanged); ListElement := fEditColumn.LookupHandle.List[i]; Combo.Items.AddObject( - Renderer.GetAsStringAndSubscribe(ListElement, fEditColumn.LookUpProperties, nil), + ListElement.EvaluateExpressionAsString(fEditColumn.LookUpProperties.Expression, fEditColumn.LookUpProperties.Representation), ListElement); if (CellValue = ListElement) or @@ -2471,7 +2484,6 @@ function TBoldCustomGrid.GetEditLimit: Integer; begin result := 0; {$IFNDEF BOLDCOMCLIENT} - // set the maxlength of the editor; El := TBoldInplaceEdit(InplaceEditor).GetDestElement(CurrentCellFollower, Columns[Col]); if (el is TBAString) and assigned((el as TBAString).BoldAttributeRTInfo) then Result := (el as TBAString).BoldAttributeRTInfo.Length; @@ -2562,7 +2574,6 @@ procedure TBoldGridCheckBoxPainterRenderer.CheckBoxClick(BUTTON: TMouseButton; S begin GridCoord := GRid.MouseCoord(X, Y); CellRect.Left := 0; - // sum the column widths of the fixed cols and then the visible cols. for i := 0 to Grid.FixedCols - 1 do CellRect.Left := CellRect.Left + Grid.Columns[i].Width + Grid.GridLineWidth; for i := GRid.LeftCol to GridCoord.x - 1 do @@ -2604,7 +2615,7 @@ procedure TBoldGridCheckBoxPainterRenderer.ToggleValue(GridCoord: TGridCoord; Gr ie: TBoldIndirectElement; begin CurrentFollower := Grid.CellFollowers[GridCoord.x, GridCoord.y-Grid.FixedRows]; - if CurrentFollower.rendererData.MayModify then + if CurrentFollower.MayModify then begin if fColumn.ColumnHasCheckBoxOverrides then begin @@ -2715,12 +2726,6 @@ procedure TBoldGridCheckBoxPainterRenderer.DrawOnCanvas(Follower: TBoldFollower; { TBoldConstraintRenderer } -procedure TBoldConstraintRenderer.DefaultMakeUptodateAndSetMayModifyAndSubscribe(Element: TBoldElement; RendererData: TBoldRendererData; FollowerController: TBoldStringFollowerController; Subscriber: TBoldSubscriber); -begin - inherited DefaultMakeUptoDateAndSetMayModifyAndSubscribe(Element, RendererData, FollowerController, Subscriber); - RendererData.MayModify := false; -end; - procedure TBoldConstraintRenderer.DrawOnCanvas(Follower: TBoldFollower; Canvas: TCanvas; Rect: TRect; Alignment: TAlignment; Margins: TPoint); var @@ -2768,7 +2773,7 @@ procedure TBoldCustomGrid.EnsureConstraintColumn; with AddColumn do begin SetIndex(1); - BoldProperties.Expression := 'constraints->exists(c|not c)'; // do not localize + BoldProperties.Expression := 'constraints->exists(c|not c)'; Width := bmpBoldGridSelected.Width + 3; Title.Caption := '§'; BoldProperties.Renderer := TBoldConstraintRenderer.Create(Self); @@ -2781,7 +2786,7 @@ procedure TBoldGridColumn.SetIndex(Value: Integer); begin fGrid.fBoldColumnsProperties.Move(index, value); inherited; - fGrid.Invalidate; // Fixes a bug in Borland grid to invalidate col that does not handle scrolled grids + fGrid.Invalidate; end; procedure TBoldCustomGrid.ReallyInvalidateCol(Column: integer); @@ -2816,7 +2821,7 @@ procedure TBoldCustomGrid.AdjustActiveRange; begin GetActiveRange(FirstActive, LastActive); BoldProperties.SetActiveRange(Follower, firstActive, lastActive, 10); - EnsureActiveCellFollowerExpressions; +// EnsureActiveCellFollowerExpressions; end; end; @@ -2827,11 +2832,6 @@ procedure TBoldCustomGrid.Resize; AdjustActiveRange; end; -function TBoldCustomGrid.GridRow(Datarow: Integer): Integer; -begin - Result := Datarow + FixedRows; -end; - function TBoldCustomGrid.GetShowTitleRow: Boolean; begin result := fixedRows = 1; @@ -2872,13 +2872,13 @@ function TBoldCustomGrid.ValidateComponent(ComponentValidator: TBoldComponentVal begin Context := GetHandleStaticType; result := ComponentValidator.ValidateExpressionInContext( - '', Context, format('%s%s', [NamePrefix, Name])); // do not localize + '', Context, format('%s%s', [NamePrefix, Name])); if assigned(context) then for i := 0 to Columns.Count - 1 do result := ComponentValidator.ValidateExpressionInContext( Columns[i].BoldProperties.Expression, Context, - format('%s%s.Column[%d]', [NamePrefix, Name, i])) and result; // do not localize + format('%s%s.Column[%d]', [NamePrefix, Name, i])) and result; end; procedure TBoldCustomGrid.LookUpChange(sender: Tobject; DestElement: TBoldElement; EditColumn: TBoldGridColumn); @@ -2921,7 +2921,6 @@ function TBoldCustomGrid.AsClipBoardText: String; var Col, Row: integer; begin - // as the grid is optimizing the active followers, we need to activate them manually ActivateAllCells; Result := ''; for row := 0 to RowCount - 1 do @@ -2954,7 +2953,7 @@ procedure TBoldGridColumn.SetCheckBoxRendererIfAppropriate; begin ListElementTypeInfo := Grid.BoldHandle.ListElementType; SystemTypeInfo := ListElementTypeInfo.SystemTypeInfo as TBoldSystemTypeInfo; - BooleanTypeInfo := SystemTypeinfo.AttributeTypeInfoByExpressionName['Boolean']; // do not localize + BooleanTypeInfo := SystemTypeinfo.AttributeTypeInfoByExpressionName['Boolean']; ResultTypeInfo := SystemTypeinfo.Evaluator.ExpressionType(BoldProperties.Expression, ListElementTypeInfo, false, BoldProperties.VariableList); if (assigned(ResultTypeInfo) and ResultTypeInfo.ConformsTo(BooleanTypeInfo)) or ColumnHasCheckBoxOverrides then begin @@ -2973,13 +2972,11 @@ function TBoldGridColumn.ColumnHasCheckBoxOverrides: Boolean; function TBoldGridColumn.GetCurrentCheckBoxState( Follower: TBoldFollower): TCheckBoxState; begin - // will only be called if ColumnHasCheckBoxOverrides returns true result := cbGrayed; end; procedure TBoldGridColumn.SetCurrentCheckBoxState(Follower: TBoldFollower; NewValue: TCheckBoxState); begin - // will only be called if ColumnHasCheckBoxOverrides returns true end; function TBoldGridColumn.GetLookupContext: TBoldElementTypeInfo; @@ -3041,7 +3038,6 @@ procedure TBoldCustomGrid.GetActiveRange(var FirstActive, LastActive: integer); begin firstActive := DataRow(TopRow) - 1; LastActive := DataRow(TopRow + VisibleRowCount) + 1; - // extend range to include all selected elements for i := 0 to FirstActive - 1 do if Selected[i] then begin @@ -3071,7 +3067,6 @@ procedure TBoldCustomGrid.EnsureRowActive(DataRow: integer); else if DataRow > LastActive then LastActive := DataRow; BoldProperties.SetActiveRange(Follower, firstActive, lastActive, 10); - // this can fail if the FollowerHandle is invalid... Follower.EnsureDisplayable; end; end; @@ -3095,7 +3090,7 @@ procedure TBoldCustomGrid.DisplayAllCells; BoldProperties.SelectAll(Follower, true); Invalidate; AdjustActiveRange; - EnsureActiveCellFollowerExpressions; {TODO: Remove? AdjustActiveRange already calls this method, why call it again??} + EnsureActiveCellFollowerExpressions; Follower.EnsureDisplayable; BoldProperties.SelectAll(Follower, false); BoldProperties.SetSelected(Follower, DataRow(Row), true); @@ -3114,4 +3109,7 @@ procedure TBoldCustomGrid.EnsureActiveCellFollowerExpressions; end; end; + +initialization + end. diff --git a/Source/BoldAwareGUI/BoldControls/BoldGridRTColEditor.pas b/Source/BoldAwareGUI/BoldControls/BoldGridRTColEditor.pas index c4d6b31..5e36624 100644 --- a/Source/BoldAwareGUI/BoldControls/BoldGridRTColEditor.pas +++ b/Source/BoldAwareGUI/BoldControls/BoldGridRTColEditor.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldGridRTColEditor; {$UNDEF BOLDCOMCLIENT} @@ -12,7 +15,7 @@ interface Classes, BoldDefs, BoldGrid, - {$IFNDEF BOLDCOMCLIENT} // uses + {$IFNDEF BOLDCOMCLIENT} BoldOclPropEditor, {$ENDIF} BoldSystemRT, @@ -69,7 +72,6 @@ implementation uses SysUtils, - BoldGuiResourceStrings, BoldUtils; {$R *.dfm} @@ -135,14 +137,14 @@ procedure TfrmRTColEditor.GetColumns; var i: integer; begin - for i := 1 to Grid.ColCount - 1 do + for i := 1 to Grid.ColCount-1 do lbxColumns.Items.AddObject(EGrid.Columns[i].Title.Caption, EGrid.Columns[i]); end; procedure TfrmRTColEditor.Execute(BoldCustomGrid: TBoldCustomGrid); begin if not Assigned(BoldCustomGrid) then - raise EBold.CreateFmt(sExecuteGridNotAssigned, [ClassName]); + raise EBold.CreateFmt('%s.Execute: BoldCustomGrid not assigned', [ClassName]); Grid := BoldCustomGrid; CurrentGridColumn := nil; @@ -177,8 +179,8 @@ procedure TfrmRTColEditor.cmdAddColumnClick(Sender: TObject); Grid.AddColumn; with EGrid do begin - Columns[ColCount - 1].Title.Caption := sNewColumn; - lbxColumns.Items.AddObject(Columns[ColCount - 1].Title.Caption, Columns[ColCount - 1]); + Columns[ColCount-1].Title.Caption := ''; + lbxColumns.Items.AddObject(Columns[ColCount-1].Title.Caption, Columns[ColCount-1]); end; end; @@ -192,12 +194,12 @@ procedure TfrmRTColEditor.cmdDeleteColumnClick(Sender: TObject); procedure TfrmRTColEditor.PropertyKeyPress(Sender: TObject; var Key: Char); begin if not Assigned(CurrentGridColumn) then - Key := BOLDNULL; + Key := BOLDNULL; end; procedure TfrmRTColEditor.cmdOCLEditorClick(Sender: TObject); begin - {$IFNDEF BOLDCOMCLIENT} // ocleditor + {$IFNDEF BOLDCOMCLIENT} with TBoldOCLPropEditForm.Create(nil) do try Context := EGrid.GetHandleListElementType; @@ -210,4 +212,6 @@ procedure TfrmRTColEditor.cmdOCLEditorClick(Sender: TObject); {$ENDIF} end; +initialization + end. diff --git a/Source/BoldAwareGUI/BoldControls/BoldImage.pas b/Source/BoldAwareGUI/BoldControls/BoldImage.pas index d91171e..6abb964 100644 --- a/Source/BoldAwareGUI/BoldControls/BoldImage.pas +++ b/Source/BoldAwareGUI/BoldControls/BoldImage.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldImage; {$UNDEF BOLDCOMCLIENT} @@ -10,14 +13,15 @@ interface Classes, Graphics, Controls, - Forms, // TBorderStyle - BoldEnvironmentVCL, // Make sure VCL environement loaded, and finalized after + Forms, + BoldEnvironmentVCL, BoldControlsDefs, BoldHandles, BoldElementHandleFollower, BoldControlPack, BoldViewerControlPack, - BoldElements; + BoldElements, + BoldDefs; type {forward declarations} @@ -38,16 +42,16 @@ TBoldImage = class(TCustomControl, IBoldOCLComponent) fQuickDraw: Boolean; fScale: Double; fDisplayRect: TRect; - FOnResize: TNotifyEvent; + FOnResize: TNotifyEvent; function GetContextType: TBoldElementTypeInfo; - procedure SetExpression(Expression: String); - function GetExpression: String; + procedure SetExpression(const Value: TBoldExpression); + function GetExpression: TBoldExpression; function GetVariableList: TBoldExternalVariableList; function GetBoldHandle: TBoldElementHandle; function GetFollower: TBoldFOllower; procedure SetBorderStyle(Value: TBorderStyle); - procedure SetAutoSize(Value: Boolean); + procedure SetAutoSize(Value: Boolean); reintroduce; procedure SetDrawFocus(Value: Boolean); procedure SetBoldProperties(Value: TBoldViewerFollowerController); procedure SetBoldHandle(value: TBoldElementHandle); @@ -95,7 +99,6 @@ TBoldImage = class(TCustomControl, IBoldOCLComponent) property Scale: Integer read GetScale write SetScale default 100; property Center: Boolean read fCenter write fCenter; property QuickDraw: Boolean read fQuickDraw write fQuickDraw; -// property ContentType: string //Use this property to specify property BorderStyle: TBorderStyle read FBorderStyle write SetBorderStyle default bsSingle; property OnResize: TNotifyEvent read FOnResize write FOnResize; {Standard properties} @@ -138,8 +141,6 @@ implementation uses SysUtils, - BoldGuiResourceStrings, - BoldDefs, BoldControlPackDefs; {-- TBoldImage --} @@ -205,7 +206,6 @@ function TBoldImage.GetViewer: TBoldAbstractViewAdapter; procedure TBoldImage.SetViewer(Value: TBoldAbstractViewAdapter); begin fBoldProperties.MayHaveChanged(Value, Follower); -// Invalidate; end; procedure TBoldImage.SetBorderStyle(Value: TBorderStyle); @@ -314,12 +314,10 @@ procedure TBoldImage.WMSize(var Message: TMessage); procedure TBoldImage.CMTextChanged(var Message: TMessage); begin inherited; -// FIXME Invalidate to redraw Caption when there is no picture end; procedure TBoldImage.WMEraseBkgnd(var Message: TWMEraseBkgnd); begin -//Ignore erase background to prevent flicker end; {} @@ -447,7 +445,7 @@ procedure TBoldImage.Paint; if (csDesigning in ComponentState) then S := '(' + Name + ')' else - S := ''; //FIXME Some text in runtime? + S := ''; Size := TextExtent(S); R := ClientRect; TextRect(R, (R.Right - Size.cx) div 2, (R.Bottom - Size.cy) div 2, S); @@ -536,8 +534,7 @@ procedure TBoldImage.PasteFromClipboard; aViewer: TBoldAbstractViewAdapter; function GetViewer: TBoldAbstractViewAdapter; - // FixMe: Could be a classmethod on TBoldAbstractViewAdapter - // reuse in method above aswell /JoHo + var I: Integer; begin @@ -564,7 +561,7 @@ procedure TBoldImage.PasteFromClipboard; Follower.Apply; end else - raise EBold.CreateFmt(sUnknownFileFormat, [ClassName, FileName]); + raise EBold.CreateFmt('%s.LoadFromFile: File format unknown: File: ''%s''', [ClassName, FileName]); end; end; @@ -586,14 +583,14 @@ function TBoldImage.GetContextType: TBoldElementTypeInfo; Result := nil; end; -function TBoldImage.GetExpression: String; +function TBoldImage.GetExpression: TBoldExpression; begin Result := BoldProperties.Expression; end; -procedure TBoldImage.SetExpression(Expression: String); +procedure TBoldImage.SetExpression(const Value: TBoldExpression); begin - BoldProperties.Expression := Expression; + BoldProperties.Expression := Value; end; function TBoldImage.GetVariableList: TBoldExternalVariableList; @@ -601,4 +598,5 @@ function TBoldImage.GetVariableList: TBoldExternalVariableList; result := BoldProperties.VariableList; end; +initialization end. diff --git a/Source/BoldAwareGUI/BoldControls/BoldImageBitmap.pas b/Source/BoldAwareGUI/BoldControls/BoldImageBitmap.pas index 5030286..0272ce8 100644 --- a/Source/BoldAwareGUI/BoldControls/BoldImageBitmap.pas +++ b/Source/BoldAwareGUI/BoldControls/BoldImageBitmap.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldImageBitmap; {$UNDEF BOLDCOMCLIENT} @@ -5,7 +8,7 @@ interface uses - Windows, // Delphi Units + Windows, Classes, Graphics, Clipbrd, @@ -29,7 +32,7 @@ TBoldViewBitmapAdapter = class(TBoldAbstractViewAdapter) function HasChanged: Boolean; override; class function CanReadContent(const ContentType: string): Boolean; override; function ContentType: string; override; - class function Description: string; override; // How to handle Localizastion? + class function Description: string; override; {Clipboard} procedure CopyToClipboard; override; class function CanPasteFromClipboard(const AcceptedContentType: string): Boolean; override; @@ -39,7 +42,7 @@ TBoldViewBitmapAdapter = class(TBoldAbstractViewAdapter) procedure SaveToStream(Stream: TStream); override; {Files} class function DefaultExtension: string; override; - class function FileFilter: string; override; // How to handle Localizastion? + class function FileFilter: string; override; class function CanLoadFromFile(const Filename: string): Boolean; override; procedure LoadFromFile(const Filename: string); override; procedure SaveToFile(const Filename: string); override; @@ -54,12 +57,7 @@ implementation uses SysUtils, - BoldGuiResourceStrings; - -const - MIME_image_bmp = 'image/bmp'; - MIME_image_bitmap = 'image/bitmap'; - + BoldRev; {-- TBoldViewBitmapAdapter --} @@ -105,8 +103,8 @@ class function TBoldViewBitmapAdapter.CanReadContent(const ContentType: string): begin S := AnsiLowerCase(ContentType); Result := (S = '') or - (S = MIME_image_bitmap) or - (S = MIME_image_bmp); + (S = 'image/bitmap') or + (S = 'image/bmp'); end; function TBoldViewBitmapAdapter.ContentType: string; @@ -114,12 +112,12 @@ function TBoldViewBitmapAdapter.ContentType: string; if Empty then Result := '' else - Result := MIME_image_bitmap + Result := 'image/bitmap' end; class function TBoldViewBitmapAdapter.Description: string; begin - Result := sBitMapImage; + Result := 'Bitmap image' end; {Clipboard} @@ -136,8 +134,8 @@ class function TBoldViewBitmapAdapter.CanPasteFromClipboard(const AcceptedConten S := AnsiLowerCase(AcceptedContentType); Result := Clipboard.HasFormat(CF_BITMAP) and ((S = '') or - (S = 'image/*') or // do not localize - (S = MIME_image_bitmap)); + (S = 'image/*') or + (S = 'image/bitmap')); end; procedure TBoldViewBitmapAdapter.PasteFromClipboard; @@ -162,12 +160,12 @@ procedure TBoldViewBitmapAdapter.SaveToStream(Stream: TStream); {Files} class function TBoldViewBitmapAdapter.DefaultExtension: string; begin - Result := 'bmp'; // do not localize + Result := 'bmp'; end; class function TBoldViewBitmapAdapter.FileFilter: string; begin - Result := Format('%s (*.bmp)|*.bmp', [Description]); // do not localize + Result := Format('%s (*.bmp)|*.bmp', [Description]); end; class function TBoldViewBitmapAdapter.CanLoadFromFile(const Filename: string): Boolean; @@ -176,7 +174,7 @@ class function TBoldViewBitmapAdapter.CanLoadFromFile(const Filename: string): B begin Extension := ExtractFileExt(FileName); Extension := Copy(Extension, 2, Length(Extension)); - Result := CompareText(Extension, 'bmp') = 0; // do not localize + Result := CompareText(Extension, 'bmp') = 0; end; procedure TBoldViewBitmapAdapter.LoadFromFile(const Filename: string); @@ -235,5 +233,5 @@ function TBoldViewBitmapAdapter.Height: Integer; initialization TBoldViewBitmapAdapter.RegisterViewAdapter(TBoldViewBitmapAdapter); - + end. diff --git a/Source/BoldAwareGUI/BoldControls/BoldImageJPEG.pas b/Source/BoldAwareGUI/BoldControls/BoldImageJPEG.pas index eff55bb..1ce3dfc 100644 --- a/Source/BoldAwareGUI/BoldControls/BoldImageJPEG.pas +++ b/Source/BoldAwareGUI/BoldControls/BoldImageJPEG.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldImageJPEG; {$UNDEF BOLDCOMCLIENT} @@ -30,7 +33,7 @@ TBoldViewJPEGAdapter = class(TBoldAbstractViewAdapter) function HasChanged: Boolean; override; class function CanReadContent(const ContentType: string): Boolean; override; function ContentType: string; override; - class function Description: string; override; // How to handle Localizastion? + class function Description: string; override; {Clipboard} procedure CopyToClipboard; override; class function CanPasteFromClipboard(const AcceptedContentType: string): Boolean; override; @@ -40,7 +43,7 @@ TBoldViewJPEGAdapter = class(TBoldAbstractViewAdapter) procedure SaveToStream(Stream: TStream); override; {Files} class function DefaultExtension: string; override; - class function FileFilter: string; override; // How to handle Localizastion? + class function FileFilter: string; override; class function CanLoadFromFile(const Filename: string): Boolean; override; procedure LoadFromFile(const Filename: string); override; procedure SaveToFile(const Filename: string); override; @@ -55,10 +58,8 @@ implementation uses SysUtils, - BoldGuiResourceStrings; + BoldRev; -const - MIME_image_jpeg = 'image/jpeg'; {-- TBoldViewJPEGAdapter --} @@ -103,7 +104,7 @@ class function TBoldViewJPEGAdapter.CanReadContent(const ContentType: string): B S: string; begin S := AnsiLowerCase(ContentType); - Result := (S = MIME_image_jpeg); + Result := (S = 'image/jpeg'); end; function TBoldViewJPEGAdapter.ContentType: string; @@ -111,12 +112,12 @@ function TBoldViewJPEGAdapter.ContentType: string; if Empty then Result := '' else - Result := MIME_image_jpeg + Result := 'image/jpeg' end; class function TBoldViewJPEGAdapter.Description: string; begin - Result := sJpegImage; + Result := 'JPEG image' end; {Clipboard} @@ -132,12 +133,12 @@ class function TBoldViewJPEGAdapter.CanPasteFromClipboard(const AcceptedContentT begin S := AnsiLowerCase(AcceptedContentType); Result := Clipboard.HasFormat(CF_BITMAP) and - ((S = '') or (S = 'image/*') or (S = MIME_image_jpeg)); // do not localize + ((S = '') or (S = 'image/*') or (S = 'image/jpeg')); end; type THack = class(TJPEGImage) - end; //FIX to access NewBitmap so LoadFromClipboardFormat does not return an exception. + end; procedure TBoldViewJPEGAdapter.PasteFromClipboard; var @@ -173,12 +174,12 @@ procedure TBoldViewJPEGAdapter.SaveToStream(Stream: TStream); {Files} class function TBoldViewJPEGAdapter.DefaultExtension: string; begin - Result := 'jpg'; // do not localize + Result := 'jpg'; end; class function TBoldViewJPEGAdapter.FileFilter: string; begin - Result := Format('%s (*.jpg, *.jpeg)|*.jpg;*.jpeg', [Description]); // do not localize + Result := Format('%s (*.jpg, *.jpeg)|*.jpg;*.jpeg', [Description]); end; class function TBoldViewJPEGAdapter.CanLoadFromFile(const Filename: string): Boolean; @@ -187,8 +188,8 @@ class function TBoldViewJPEGAdapter.CanLoadFromFile(const Filename: string): Boo begin Extension := ExtractFileExt(FileName); Extension := Copy(Extension, 2, Length(Extension)); - Result := (CompareText(Extension, 'jpg') = 0) or // do not localize - (CompareText(Extension, 'jpeg') = 0); // do not localize + Result := (CompareText(Extension, 'jpg') = 0) or + (CompareText(Extension, 'jpeg') = 0); end; procedure TBoldViewJPEGAdapter.LoadFromFile(const Filename: string); @@ -215,6 +216,7 @@ procedure TBoldViewJPEGAdapter.SaveToFile(const Filename: string); end; end; + {Canvas} procedure TBoldViewJPEGAdapter.Paint(Canvas: TCanvas; Rect: TRect); begin @@ -247,5 +249,4 @@ function TBoldViewJPEGAdapter.Height: Integer; initialization TBoldViewJPEGAdapter.RegisterViewAdapter(TBoldViewJPEGAdapter); - end. diff --git a/Source/BoldAwareGUI/BoldControls/BoldLabel.pas b/Source/BoldAwareGUI/BoldControls/BoldLabel.pas index 7b834f6..602e206 100644 --- a/Source/BoldAwareGUI/BoldControls/BoldLabel.pas +++ b/Source/BoldAwareGUI/BoldControls/BoldLabel.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldLabel; {$UNDEF BOLDCOMCLIENT} @@ -10,12 +13,13 @@ interface Graphics, Controls, StdCtrls, - BoldEnvironmentVCL, // Make sure VCL environement loaded, and finalized after + BoldEnvironmentVCL, BoldHandles, BoldControlPack, BoldElements, BoldStringControlPack, - BoldElementHandleFollower; + BoldElementHandleFollower, + BoldDefs; type {Forward declaration of classes} @@ -31,8 +35,8 @@ TBoldCustomLabel = class(TCustomLabel, IBoldOCLComponent) fMyColor: TColor; fMyFont: TFont; function GetContextType: TBoldElementTypeInfo; - procedure SetExpression(Expression: String); - function GetExpression: String; + procedure SetExpression(const Value: TBoldExpression); + function GetExpression: TBoldExpression; function GetVariableList: TBoldExternalVariableList; procedure _FontChanged(sender: TObject); procedure AfterMakeUptoDate(Follower: TBoldFollower); @@ -138,7 +142,7 @@ constructor TBoldCustomLabel.Create(AOwner: TComponent); fMyFont.OnChange := _FontChanged; fMyColor := EffectiveColor; if (csDesigning in ComponentState) then - ParentColor := True; //CHECKME This should not be necesary... + ParentColor := True; end; destructor TBoldCustomLabel.Destroy; @@ -211,7 +215,7 @@ function TBoldCustomLabel.GetEffectiveColor: TColor; procedure TBoldCustomLabel.SetEffectiveColor(v: TColor); begin - if (EffectiveColor <> v) and not ParentColor then + if EffectiveColor <> v then begin inherited Color := v; if (csDesigning in ComponentState) then @@ -236,7 +240,6 @@ procedure TBoldCustomLabel.AfterMakeUptoDate(Follower: TBoldFollower); begin if (csDesigning in ComponentState) then begin - // caption during design-time with BoldProperties do if Assigned(Renderer) then NewText := Format('%s.%s', [Renderer.name, Expression]) @@ -246,20 +249,16 @@ procedure TBoldCustomLabel.AfterMakeUptoDate(Follower: TBoldFollower); NewText := name; end else - // Caption at run-time newText := BoldProperties.GetCurrentAsString(Follower); if Text <> newText then Text := newText; BoldProperties.SetFont(EffectiveFont, Font, Follower); - if not parentColor then - begin - ec := EffectiveColor; - BoldProperties.SetColor(ec, Color, Follower); - EffectiveColor := ec; - end; -end; + ec := EffectiveColor; + BoldProperties.SetColor(ec, Color, Follower); + EffectiveColor := ec; +end; function TBoldCustomLabel.GetText: TCaption; begin @@ -284,14 +283,14 @@ function TBoldCustomLabel.GetContextType: TBoldElementTypeInfo; result := nil; end; -function TBoldCustomLabel.GetExpression: String; +function TBoldCustomLabel.GetExpression: TBoldExpression; begin result := BoldProperties.Expression; end; -procedure TBoldCustomLabel.SetExpression(Expression: String); +procedure TBoldCustomLabel.SetExpression(const Value: TBoldExpression); begin - BoldProperties.Expression := Expression; + BoldProperties.Expression := Value; end; function TBoldCustomLabel.GetVariableList: TBoldExternalVariableList; @@ -327,5 +326,5 @@ procedure TBoldCustomLabel.DragDrop(Source: TObject; X, Y: Integer); BoldProperties.DragDrop(Follower, follower.Element, 0); end; +initialization end. - diff --git a/Source/BoldAwareGUI/BoldControls/BoldListBox.pas b/Source/BoldAwareGUI/BoldControls/BoldListBox.pas index 06d4584..ea9fcf4 100644 --- a/Source/BoldAwareGUI/BoldControls/BoldListBox.pas +++ b/Source/BoldAwareGUI/BoldControls/BoldListBox.pas @@ -1,6 +1,10 @@ +///////////////////////////////////////////////////////// + + unit BoldListBox; {$UNDEF BOLDCOMCLIENT} +{$INCLUDE bold.inc} interface @@ -22,7 +26,8 @@ interface BoldControlPack, BoldListHandleFollower, BoldListListControlPack, - BoldStringControlPack; + BoldStringControlPack, + BoldDefs; // CHECKME is a destroywind needed that saves the extra list. // when is DestroyWnd actually called. @@ -42,8 +47,8 @@ TBoldCustomListBox = class(TCustomListBox, IBoldOCLComponent) fBoldRowProperties: TBoldStringFollowerController; function GetContextType: TBoldElementTypeInfo; - procedure SetExpression(Expression: String); - function GetExpression: String; + procedure SetExpression(const Value: TBoldExpression); + function GetExpression: TBoldExpression; function GetVariableList: TBoldExternalVariableList; function GetBoldHandle: TBoldAbstractListHandle; @@ -54,10 +59,10 @@ TBoldCustomListBox = class(TCustomListBox, IBoldOCLComponent) function GetCurrentBoldElement: TBoldElement; function GetCurrentBoldObject: TBoldObject; function GetBoldList: TBoldList; - function GetItemIndex: Integer; + function GetItemIndex: Integer; reintroduce; function GetBoldHandleIndexLock: Boolean; procedure SetBoldHandleIndexLock(Value: Boolean); - procedure SetItemIndex(Value: Integer); + procedure SetItemIndex(Value: Integer); reintroduce; procedure SetSelected(index: Integer; V: Boolean); procedure InternalSetSelected(index: integer; v: Boolean); procedure SetSelection(aRow: Integer; Shift: TShiftState); @@ -65,7 +70,7 @@ TBoldCustomListBox = class(TCustomListBox, IBoldOCLComponent) procedure SetAlignment(Value: TAlignment); procedure _BeforeMakeUptoDate(Follower: TBoldFollower); procedure _AfterMakeUptoDate(Follower: TBoldFollower); - procedure _InsertItem(Follower: TBoldFollower); + procedure _InsertItem(index: Integer; Follower: TBoldFollower); procedure _DeleteItem(index: Integer; OwningFollower: TBoldFollower); procedure _RowAfterMakeUptoDate(Follower: TBoldFollower); procedure CNDrawItem(var Message: TWMDrawItem); message CN_DRAWITEM; @@ -177,6 +182,7 @@ implementation BoldGui, // IFNDEF BOLDCOMCLIENT {$ENDIF} BoldControlPackDefs, + BoldGuiResourceStrings, BoldListControlPack; {---TBoldCustomListBox---} @@ -187,13 +193,10 @@ constructor TBoldCustomListBox.Create(AOwner: TComponent); fBoldRowProperties.AfterMakeUptoDate := _RowAfterMakeUptoDate; fBoldRowProperties.OnGetContextType := GetContextType; fBoldProperties := TBoldListAsFollowerListController.Create(Self, fBoldRowProperties); - with fBoldProperties do - begin - OnAfterInsertItem := _InsertItem; - OnAfterDeleteItem := _DeleteItem; - BeforeMakeUptoDate := _BeforeMakeUptoDate; - AfterMakeUptoDate := _AfterMakeUptoDate; - end; + fBoldProperties.OnAfterInsertItem := _InsertItem; + fBoldProperties.OnAfterDeleteItem := _DeleteItem; + fBoldProperties.BeforeMakeUptoDate := _BeforeMakeUptoDate; + fBoldProperties.AfterMakeUptoDate := _AfterMakeUptoDate; fHandleFollower := TBoldListHandleFollower.Create(Owner, fBoldProperties); DragMode := dmAutomatic; Style := lbOwnerDrawVariable; @@ -361,11 +364,13 @@ function TBoldCustomListBox.GetCurrentBoldElement: TBoldElement; var Subfollower: TBoldFollower; begin - SubFollower := Follower.SubFollowers[ItemIndex]; - if assigned(SubFollower) then - Result := Subfollower.Element - else - Result := nil; + Result := nil; + if ItemIndex <> -1 then + begin + SubFollower := Follower.SubFollowers[ItemIndex]; + if assigned(SubFollower) then + Result := Subfollower.Element + end; end; function TBoldCustomListBox.GetBoldList: TBoldList; @@ -401,9 +406,11 @@ procedure TBoldCustomListBox._RowAfterMakeUptoDate(Follower: TBoldFollower); Items[index] := TBoldStringFollowerController(Follower.Controller).GetCurrentAsString(Follower); end; -procedure TBoldCustomListBox._InsertItem(Follower: TBoldFollower); +procedure TBoldCustomListBox._InsertItem(index: Integer; Follower: TBoldFollower); begin - Items.Insert(Follower.Index, ''); + Assert(Assigned(Follower)); + Follower.EnsureDisplayable; + Items.Insert(Follower.Index, TBoldStringFollowerController(Follower.Controller).GetCurrentAsString(Follower)); end; procedure TBoldCustomListBox._DeleteItem(index: Integer; OwningFollower: TBoldFollower); @@ -453,6 +460,8 @@ procedure TBoldCustomListBox.CNDrawItem(var Message: TWMDrawItem); State: TOwnerDrawState; SignedItemId: integer; // this variable is used to suppress warning from D4 when comparing signed and unsigned values begin + {$WARN UNSAFE_CAST OFF} + {$WARN UNSAFE_CODE OFF} with Message.DrawItemStruct^ do begin State := TOwnerDrawState(LongRec(itemState).Lo); @@ -467,6 +476,8 @@ procedure TBoldCustomListBox.CNDrawItem(var Message: TWMDrawItem); //FIXME Apperens of selected and current... Canvas.DrawFocusRect(rcItem); end; + {$WARN UNSAFE_CAST ON} + {$WARN UNSAFE_CODE ON} end; procedure TBoldCustomListBox.DefaultSetFontAndColor(index: Integer); @@ -479,12 +490,10 @@ procedure TBoldCustomListBox.DefaultSetFontAndColor(index: Integer); Canvas.Brush.Color := ec; // Selected state yields default highlight colors SubFollower := Follower.SubFollowers[index]; - if assigned(Subfollower) and Subfollower.Selected then - with Canvas do - begin - Brush.Color := clHighlight; - Font.Color := clHighlightText; - end; + if assigned(Subfollower) and Subfollower.Selected then begin + Canvas.Brush.Color := clHighlight; + Canvas.Font.Color := clHighlightText; + end; end; procedure TBoldCustomListBox.DefaultDrawItem(Index: integer; Rect: TRect); @@ -553,9 +562,9 @@ function TBoldCustomListBox.GetExpression: String; result := BoldRowProperties.Expression; end; -procedure TBoldCustomListBox.SetExpression(Expression: String); +procedure TBoldCustomListBox.SetExpression(const Value: TBoldExpression); begin - BoldRowProperties.Expression := Expression; + BoldRowProperties.Expression := Value; end; function TBoldCustomListBox.GetBoldHandleIndexLock: Boolean; @@ -594,3 +603,4 @@ procedure TBoldCustomListBox.InternalSetSelected(index: integer; v: Boolean); end. + diff --git a/Source/BoldAwareGUI/BoldControls/BoldMemo.pas b/Source/BoldAwareGUI/BoldControls/BoldMemo.pas index 663e486..c943234 100644 --- a/Source/BoldAwareGUI/BoldControls/BoldMemo.pas +++ b/Source/BoldAwareGUI/BoldControls/BoldMemo.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldMemo; {$UNDEF BOLDCOMCLIENT} @@ -11,12 +14,13 @@ interface Controls, StdCtrls, Menus, - BoldEnvironmentVCL, // Make sure VCL environement loaded, and finalized after + BoldEnvironmentVCL, BoldHandles, BoldElements, BoldControlPack, BoldStringControlPack, - BoldElementHandleFollower; + BoldElementHandleFollower, + BoldDefs; type TBoldCustomMemo = class; @@ -36,8 +40,8 @@ TBoldCustomMemo = class(TCustomMemo, IBoldOCLComponent) fMyReadOnly: Boolean; fMaxLength: integer; function GetContextType: TBoldElementTypeInfo; - procedure SetExpression(Expression: String); - function GetExpression: String; + procedure SetExpression(const Value: TBoldExpression); + function GetExpression: TBoldExpression; function GetVariableList: TBoldExternalVariableList; procedure _FontChanged(sender: TObject); @@ -151,8 +155,7 @@ implementation uses SysUtils, - BoldGuiResourceStrings, - BoldDefs, + BoldUtils, BoldControlPackDefs; {---TBoldCustomMemo---} @@ -290,7 +293,7 @@ function TBoldCustomMemo.GetEffectiveColor: TColor; procedure TBoldCustomMemo.SetEffectiveColor(v: TColor); begin - if (EffectiveColor <> v) and not ParentColor then + if EffectiveColor <> v then inherited Color := v; end; @@ -300,7 +303,7 @@ procedure TBoldCustomMemo.SetText(value: string); if not EffectiveReadOnly then inherited Text := value else - raise Exception.CreateFmt(sTextNotModifiable, [ClassName]); + raise Exception.CreateFmt('%s.Text: Not modifiable', [ClassName]); end; function TBoldCustomMemo.GetText: string; @@ -318,13 +321,13 @@ function TBoldCustomMemo.GetPopupmenu: TPopupMenu; procedure TBoldCustomMemo.KeyPress(var Key: Char); begin inherited KeyPress(Key); - if (Key in [#32..#255]) and + if CharInSet(Key, [#32..#255]) and not BoldProperties.ValidateCharacter(Key, Follower) then begin MessageBeep(0); Key := BOLDNULL; end; - + if Key = BOLDESC then begin Follower.DiscardChange; @@ -363,12 +366,9 @@ procedure TBoldCustomMemo.AfterMakeUptoDate(Follower: TBoldFollower); inherited ReadOnly := FMyReadOnly or not BoldProperties.MayModify(Follower); BoldProperties.SetFont(EffectiveFont, Font, Follower); - if not ParentColor then - begin - ec := EffectiveColor; - BoldProperties.SetColor(ec, Color, Follower); - EffectiveColor := ec; - end; + ec := EffectiveColor; + BoldProperties.SetColor(ec, Color, Follower); + EffectiveColor := ec; EffectiveMaxLength := 0; RendererDataMaxLength := (Follower.RendererData as TBoldStringRendererData).MaxStringLength; @@ -390,7 +390,7 @@ procedure TBoldCustomMemo.CMEnter(var Message: TCMEnter); procedure TBoldCustomMemo.CMExit(var Message: TCMExit); begin if (Follower.Controller.ApplyPolicy = bapExit) then - Follower.Apply; + Follower.Apply; SetFocused(False); DoExit; end; @@ -413,14 +413,14 @@ function TBoldCustomMemo.GetContextType: TBoldElementTypeInfo; Result := nil; end; -function TBoldCustomMemo.GetExpression: String; +function TBoldCustomMemo.GetExpression: TBoldExpression; begin result := BoldProperties.Expression; end; -procedure TBoldCustomMemo.SetExpression(Expression: String); +procedure TBoldCustomMemo.SetExpression(const Value: TBoldExpression); begin - BoldProperties.Expression := Expression; + BoldProperties.Expression := Value; end; function TBoldCustomMemo.GetVariableList: TBoldExternalVariableList; @@ -428,5 +428,6 @@ function TBoldCustomMemo.GetVariableList: TBoldExternalVariableList; result := BoldProperties.VariableList; end; -end. +initialization +end. diff --git a/Source/BoldAwareGUI/BoldControls/BoldNavigator.pas b/Source/BoldAwareGUI/BoldControls/BoldNavigator.pas index 2150fb0..a8054ad 100644 --- a/Source/BoldAwareGUI/BoldControls/BoldNavigator.pas +++ b/Source/BoldAwareGUI/BoldControls/BoldNavigator.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldNavigator; {$UNDEF BOLDCOMCLIENT} @@ -11,9 +14,9 @@ interface Controls, ExtCtrls, Buttons, - BoldEnvironmentVCL, // Make sure VCL environement loaded, and finalized after + BoldEnvironmentVCL, BoldElements, - {$IFNDEF BOLDCOMCLIENT} // uses + {$IFNDEF BOLDCOMCLIENT} BoldSystem, {$ENDIF} BoldDefs, @@ -24,7 +27,7 @@ interface BoldControlPack, BoldCommonBitmaps, BoldListControlPack, - BoldListListControlPack; + BoldListListControlPack; type { forward declarations } @@ -97,7 +100,7 @@ TBoldCustomNavigator = class(TBoldNavigateBtnImageIndexOwner) public constructor Create(AOwner: TComponent); override; destructor Destroy; override; - procedure Assign(Source: TPersistent); override; + procedure assign(Source: TPersistent); override; procedure BtnClick(index: TBoldNavigateBtn); procedure SetBounds(ALeft, ATop, AWidth, AHeight: Integer); override; end; @@ -161,7 +164,6 @@ implementation BoldControlsDefs; var -// BtnTypeName: array[TBoldNavigateBtn] of PChar = ('FIRST', 'PRIOR', 'NEXT', 'LAST', 'INSERT', 'DELETE', 'MOVEUP', 'MOVEDOWN'); //Do not localize BtnHintId: array[TBoldNavigateBtn] of Pointer = (@SNavHintFirst, @SNavHintPrior, @SNavHintNext, @SNavHintLast, @SNavHintNew, @SNavHintDelete, @SNavHintMoveUp, @SNavHintMoveDown); procedure TBoldCustomNavigator.InitHints; @@ -202,8 +204,7 @@ procedure TBoldCustomNavigator.SetHints(Value: TStrings); procedure TBoldCustomNavigator.GetChildren(Proc: TGetChildProc; ROOT: TComponent); begin - // Implementation is empty to prevent control - // from behaving like a TPanel + end; procedure TBoldCustomNavigator.SetVisible(Value: TBoldButtonSet); @@ -444,10 +445,10 @@ constructor TBoldCustomNavigator.Create(AOwner: TComponent); fBoldProperties.AfterMakeUptoDate := _AfterMakeUptoDate; fBoldProperties.BeforeMakeUptoDate := _BeforeMakeUptoDate; - fDeleteQuestion := sDeleteQuestion; + fDeleteQuestion := 'Delete "%1:s"?'; {$IFNDEF BOLDCOMCLIENT} - fUnlinkQuestion := sUnlinkQuestion; - fRemoveQuestion := sRemoveQuestion; + fUnlinkQuestion := 'Unlink "%1:s" from "%2:s"?'; + fRemoveQuestion := 'Remove "%1:s" from the list?'; {$ENDIF} end; @@ -513,7 +514,6 @@ procedure TBoldCustomNavigator.BtnClick(index: TBoldNavigateBtn); if BoldDeleteMode = dmDefault then begin - // Delete from classlists, remove from other lists if assigned(BoldHandle.ObjectList) and (BoldHandle.ObjectList.OwningElement is TBoldSystem) then EffectiveDeleteMode := dmDelete else @@ -526,7 +526,6 @@ procedure TBoldCustomNavigator.BtnClick(index: TBoldNavigateBtn); begin if assigned(RoleRTInfo) then begin - // linkobjects will be deleted... other objects will be unlinked if RoleRTInfo.RoleType = rtLinkRole then EffectiveDeleteMode := dmDelete else @@ -592,7 +591,7 @@ procedure TBoldCustomNavigator.BtnClick(index: TBoldNavigateBtn); nbInsert: CurrentIndex := List.IndexOf(MutableList.AddNew); nbDelete: - Delete(fConfirmDelete); //FIXME Localize + Delete(fConfirmDelete); nbMoveUp: List.Move(CurrentIndex, CurrentIndex - 1); nbMoveDown: @@ -685,7 +684,7 @@ function TBoldCustomNavigator.MapMinus(CanDeleteObject: Boolean): Boolean; dmUnlinkAllAndDelete: Result := True; else - raise EBold.CreateFmt(sUnknownDeleteMode, [ClassName]); + raise EBold.CreateFmt('%s.MapMinus: Unknown delete mode', [ClassName]); end; end; @@ -750,9 +749,10 @@ procedure TBoldCustomNavigator.SetImages(const Value: TImageList); procedure TBoldCustomNavigator._BeforeMakeUptoDate(Follower: TBoldFollower); begin - fBoldProperties.SetActiveRange(Follower, BoldHandle.CurrentIndex, BoldHandle.CurrentIndex); + if Assigned(BoldHandle) then + fBoldProperties.SetActiveRange(Follower, BoldHandle.CurrentIndex, BoldHandle.CurrentIndex) end; -end. - +initialization +end. diff --git a/Source/BoldAwareGUI/BoldControls/BoldPageControl.pas b/Source/BoldAwareGUI/BoldControls/BoldPageControl.pas index a8f77e2..7628d6d 100644 --- a/Source/BoldAwareGUI/BoldControls/BoldPageControl.pas +++ b/Source/BoldAwareGUI/BoldControls/BoldPageControl.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldPageControl; {$UNDEF BOLDCOMCLIENT} @@ -7,7 +10,7 @@ interface uses Classes, Controls, - BoldEnvironmentVCL, // Make sure VCL environement loaded, and finalized after + BoldEnvironmentVCL, Boldhandles, BoldControlPack, BoldElementHandleFollower, @@ -32,8 +35,8 @@ TBoldPageControl = class(TPageControl) property Follower: TBoldFollower read GetFollower; public { Public declarations } - constructor Create(owner: TComponent); override; - destructor Destroy; override; + constructor create(owner: TComponent); override; + destructor destroy; override; published { Published declarations } property BoldHandle: TBoldElementHandle read GetBoldHandle write SetBoldHandle; @@ -57,7 +60,7 @@ constructor TBoldPageControl.create(owner: TComponent); fBoldProperties.OnGetContextType := _GetContextType; end; -destructor TBoldPageControl.Destroy; +destructor TBoldPageControl.destroy; begin FreeAndNil(fHandleFollower); FreeAndNil(fBoldProperties); @@ -107,4 +110,6 @@ function TBoldPageControl._GetContextType: TBoldElementTypeInfo; result := nil; end; +initialization + end. diff --git a/Source/BoldAwareGUI/BoldControls/BoldProgressBar.pas b/Source/BoldAwareGUI/BoldControls/BoldProgressBar.pas index 49f56dd..edf3207 100644 --- a/Source/BoldAwareGUI/BoldControls/BoldProgressBar.pas +++ b/Source/BoldAwareGUI/BoldControls/BoldProgressBar.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldProgressBar; {$UNDEF BOLDCOMCLIENT} @@ -9,12 +12,13 @@ interface Controls, ComCtrls, Menus, - BoldEnvironmentVCL, // Make sure VCL environement loaded, and finalized after + BoldEnvironmentVCL, BoldElements, BoldHandles, BoldControlPack, BoldNumericControlPack, - BoldElementHandleFollower; + BoldElementHandleFollower, + BoldDefs; type { forward declarations } @@ -28,8 +32,8 @@ TBoldProgressBar = class(TProgressBar, IBoldOCLComponent) FBoldProperties: TBoldIntegerFollowerController; fHandleFollower: TBoldElementHandleFollower; function GetContextType: TBoldElementTypeInfo; - procedure SetExpression(Expression: String); - function GetExpression: String; + procedure SetExpression(const Value: TBoldExpression); + function GetExpression: TBoldExpression; function GetVariableList: TBoldExternalVariableList; procedure AfterMakeUptoDate(Follower: TBoldFollower); function GetBoldHandle: TBoldElementHandle; @@ -61,7 +65,6 @@ implementation uses BoldControlPackDefs, - BoldDefs, SysUtils, BoldGuiResourceStrings, BoldControlsDefs; @@ -163,14 +166,14 @@ function TBoldProgressBar.GetContextType: TBoldElementTypeInfo; result := nil; end; -function TBoldProgressBar.GetExpression: String; +function TBoldProgressBar.GetExpression: TBoldExpression; begin result := BoldProperties.Expression; end; -procedure TBoldProgressBar.SetExpression(Expression: String); +procedure TBoldProgressBar.SetExpression(const Value: TBoldExpression); begin - BoldProperties.Expression := Expression; + BoldProperties.Expression := Value; end; function TBoldProgressBar.GetPosition: integer; @@ -203,4 +206,5 @@ function TBoldProgressBar.GetVariableList: TBoldExternalVariableList; result := BoldProperties.VariableList; end; +initialization end. diff --git a/Source/BoldAwareGUI/BoldControls/BoldPropertiesController.pas b/Source/BoldAwareGUI/BoldControls/BoldPropertiesController.pas index dad7c26..59f5a9f 100644 --- a/Source/BoldAwareGUI/BoldControls/BoldPropertiesController.pas +++ b/Source/BoldAwareGUI/BoldControls/BoldPropertiesController.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldPropertiesController; {$UNDEF BOLDCOMCLIENT} @@ -6,12 +9,13 @@ interface uses Classes, - BoldEnvironmentVCL, // Make sure VCL environement loaded, and finalized after + BoldEnvironmentVCL, BoldElements, BoldHandles, BoldControlPack, BoldStringControlPack, - BoldElementHandleFollower; + BoldElementHandleFollower, + BoldOclVariables; type { forward declarations } @@ -91,6 +95,9 @@ TBoldPropertiesController = class(TComponent) property DrivenProperties: TBoldDrivenPropertyCollection read FDrivenProperties write SetDrivenProperties; end; + procedure CreatePropertyControllerMapping(aBoldHandle: TBoldElementHandle; aExpression: string; + aVCLComponent: TComponent; aPropertyName: string; aReadOnly: boolean = true; aBoldVariables: TBoldOclVariables = nil); + implementation uses @@ -98,15 +105,27 @@ implementation TypInfo, BoldControlPackDefs, BoldControlsDefs, - BoldGuiResourceStrings, {$IFNDEF BOLDCOMCLIENT} - BoldSystem, // IFNDEF BOLDCOMCLIENT + BoldSystem, {$ENDIF} Variants, BoldGuard; -const - EventNameOnExit = 'OnExit'; +procedure CreatePropertyControllerMapping(aBoldHandle: TBoldElementHandle; aExpression: string; + aVCLComponent: TComponent; aPropertyName: string; aReadOnly: boolean; aBoldVariables: TBoldOclVariables); +var + lBoldPropertiesController: TBoldPropertiesController; + lBoldDrivenProperty: TBoldDrivenProperty; +begin + lBoldPropertiesController:= TBoldPropertiesController.Create(aVCLComponent); + lBoldPropertiesController.BoldHandle:= aBoldHandle; + lBoldPropertiesController.BoldProperties.Expression:= aExpression; + lBoldPropertiesController.BoldProperties.Variables := aBoldVariables; + lBoldDrivenProperty:= lBoldPropertiesController.DrivenProperties.Add; + lBoldDrivenProperty.VCLComponent:= aVCLComponent; + lBoldDrivenProperty.PropertyName:= aPropertyName; + lBoldDrivenProperty.ReadOnly:= aReadOnly; +end; { TBoldPropertiesController } @@ -180,20 +199,16 @@ constructor TBoldDrivenProperty.Create(Collection: TCollection); end; procedure TBoldDrivenProperty.EnsureValidPropertyName; -// Searches through the list of properties of the assigned component to check that PropertyName -// is valid for this particular component type. If not, it empties Property Name. -// This is called by the Component property setter SetVCLComponent. -// This is not used anymore at the moment. It was easy when we did not cater for property paths ! + + + var PropList: TPropList; Count, I: Integer; Found: Boolean; begin - // At least clear the property when we clear the component if not Assigned(VCLComponent) then PropertyName := ''; - - // Original code below exit; Found := False; I := 0; @@ -202,7 +217,7 @@ procedure TBoldDrivenProperty.EnsureValidPropertyName; Count := GetPropList(VCLComponent.ClassInfo, BoldPropertiesController_SupportedPropertyTypes, @PropList); while (I < Count) and (not Found) do begin - Found := PropList[I]^.Name = PropertyName; + Found := String(PropList[I]^.Name) = PropertyName; Inc(I); end; end; @@ -214,7 +229,6 @@ procedure TBoldDrivenProperty.SetVCLComponent(const Value: TComponent); var AllowHookUnHook: Boolean; begin - //We don't support the two way update for collections of more than one driven property AllowHookUnHook := assigned(value) and not ((csDesigning in Value.ComponentState) or (Collection.Count > 1)); @@ -240,7 +254,6 @@ procedure TBoldDrivenProperty.SetReadOnly(const Value: Boolean); end; procedure TBoldDrivenProperty.DoOnExit(Sender: TObject); -// Event that we have assigned as the OnExit of VCLComponent (Hooked) begin if (not ReadOnly) and PropertiesController.BoldProperties.MayModify(PropertiesController.HandleFollower.Follower) then begin @@ -248,31 +261,27 @@ procedure TBoldDrivenProperty.DoOnExit(Sender: TObject); if PropertiesController.BoldProperties.ApplyPolicy = bapExit then PropertiesController.HandleFollower.Follower.Apply; end; - //Call the original event if Assigned(FOnExit) then FOnExit(Sender); end; procedure TBoldDrivenProperty.HookOnExit; -// This method, replaces any existing OnExit event of VCLComponent with ours var DoOnExitMethod: TNotifyEvent; begin - // We could have simply used TWinControl(VCLComponent).OnExit := ... if only it was not protected ! - // Has the VCLComponent got an OnExit event ? - if Assigned(VCLComponent) and Assigned(GetPropInfo(VCLComponent.ClassInfo, EventNameOnExit)) then + + if Assigned(VCLComponent) and Assigned(GetPropInfo(VCLComponent.ClassInfo, 'OnExit')) then begin - FOnExit := TNotifyEvent(Typinfo.GetMethodProp(VCLComponent, EventNameOnExit)); + FOnExit := TNotifyEvent(Typinfo.GetMethodProp(VCLComponent, 'OnExit')); DoOnExitMethod := DoOnExit; - Typinfo.SetMethodProp(VCLComponent, EventNameOnExit, TMethod(DoOnExitMethod)); + Typinfo.SetMethodProp(VCLComponent, 'OnExit', TMethod(DoOnExitMethod)); end; end; procedure TBoldDrivenProperty.UnhookOnExit; begin - // Reassign the original event - if Assigned(VCLComponent) and Assigned(GetPropInfo(VCLComponent.ClassInfo, EventNameOnExit)) then - Typinfo.SetMethodProp(VCLComponent, EventNameOnExit, TMethod(FOnExit)); + if Assigned(VCLComponent) and Assigned(GetPropInfo(VCLComponent.ClassInfo, 'OnExit')) then + Typinfo.SetMethodProp(VCLComponent, 'OnExit', TMethod(FOnExit)); end; procedure TBoldDrivenProperty.SetPropertyValue(Follower: TBoldFollower); @@ -298,7 +307,7 @@ procedure TBoldDrivenProperty.SetPropertyValue(Follower: TBoldFollower); if assigned(PropertiesController.BoldHandle) and assigned(Follower.element) then begin - Follower.Element.EvaluateExpression(PropertiesController.BoldProperties.Expression, ie); + Follower.Element.EvaluateExpression(PropertiesController.BoldProperties.Expression, ie, false, PropertiesController.BoldProperties.VariableList); SendElement := ie.Value; end else @@ -314,11 +323,10 @@ function TBoldDrivenProperty.GetPropertiesController: TBoldPropertiesController; procedure TBoldDrivenProperty.ConvertRelativeProp(StartInstance: TObject; PropNamePath: String; var LastObject: TObject; var PropName: String); -// This method will follow the objects specified in the PropNamePath starting from StartInstance -// and set the LastObject and PropName -// E.g: ConvertRelativeProp(Label1,'FocusControl.Font.Size') will return -// LastObject points to instance of Font -// LastProp : Size + + + + var I, ColIndex, OpenBracketPos: Integer; @@ -328,22 +336,19 @@ procedure TBoldDrivenProperty.ConvertRelativeProp(StartInstance: TObject; begin BoldGuard := TBoldGuard.Create(Path); Path := TStringList.Create; - - //convert . notation to commas so we can use CommaText function Path.CommaText := StringReplace(PropNamePath, '.', ',', [rfReplaceAll]); LastObject := StartInstance; for I := 0 to Path.Count - 1 do begin - // The path may very well follow unassigned links. This check prevents an AV if not Assigned(LastObject) then Exit; PathItem := Path[I]; OpenBracketPos := Pos('[', PathItem); if OpenBracketPos = 0 then begin - if (I < Path.Count - 1) //Special case for when the last property is of tkClass we don't want - //to loose LastObject to be in fact the Previous before Last ! + if (I < Path.Count - 1) + and (GetPropInfo(LastObject.ClassInfo, PathItem)^.PropType^.Kind = tkClass) then begin LastObject := TObject(Typinfo.GetOrdProp(LastObject, PathItem)) @@ -373,16 +378,13 @@ procedure TBoldDrivenProperty.SetRelativePropValue(StartInstance: TObject; TypeKind: TTypeKind; PropInfo: PPropInfo; begin - // No property specified if PropNamePath = '' then Exit; ConvertRelativeProp(StartInstance, PropNamePath, LastObject, PropName); - // Property path followed unassigned links if not Assigned(LastObject) then Exit; PropInfo := GetPropInfo(LastObject.ClassInfo, PropName); - // Property name misspelled if not Assigned(PropInfo) then Exit; TypeKind := PropInfo^.PropType^.Kind; @@ -392,29 +394,25 @@ procedure TBoldDrivenProperty.SetRelativePropValue(StartInstance: TObject; {$IFDEF BOLDCOMCLIENT} VarValue := Value.AsVariant; {$ELSE} - VarValue := Value.GetAsVariant; + VarValue := Value.AsVariant; {$ENDIF} end else - // Handle nil equivalents for various property types case TypeKind of tkEnumeration: VarValue := 0; tkInteger: VarValue := 0; else VarValue := PropertiesController.BoldProperties.NilStringRepresentation; end; - - // Special case for booleans that don't seem to be handled properly by SetPropValue if VarType(VarValue) = varBoolean then begin if VarValue then - VarValue := 'True' // do not localize + VarValue := 'True' else - VarValue := 'False'; // do not localize + VarValue := 'False'; end; if TypeKind = tkClass then begin - // Special case for objects PropertyObj := TObject(Typinfo.GetOrdProp(LastObject, PropName)); if PropertyObj is TStrings then begin @@ -436,19 +434,27 @@ procedure TBoldDrivenProperty.SetRelativePropValue(StartInstance: TObject; end; end else if TypeKind = tkInteger then - // This is needed to handle an error in TypInfo when setting CARDINAL properties try + if not VarIsNull(VarValue) then SetOrdProp(LastObject, PropName, VarValue) except on E: Exception do - raise Exception.CreateFmt(sCannotSetIntegerProperty, [PropNamePath, VarValue, e.Message]); + raise Exception.CreateFmt('Could not set the integer %s property to value %s. (%s)', [PropNamePath, VarValue, e.Message]); + end + else if TypeKind = tkFloat then + try + if VarIsFloat(VarValue) then + SetPropValue(LastObject, PropName, VarValue); + except + on E: Exception do + raise Exception.CreateFmt('Could not set the float %s property to value %s. (%s)', [PropNamePath, VarValue, e.Message]); end else try SetPropValue(LastObject, PropName, VarValue); except on E: Exception do - raise Exception.CreateFmt(sCannotSetProperty, [PropNamePath, VarValue, e.Message]); + raise Exception.CreateFmt('Could not set the %s property to value %s. (%s)', [PropNamePath, VarValue, e.Message]); end; end; @@ -469,17 +475,17 @@ function TBoldDrivenProperty.GetDisplayName: string; if assigned(VCLComponent) then result := VCLComponent.Name else - result := ''; // do not localize + result := ''; if trim(propertyName) <> '' then result := result + '.' + trim(PropertyName) else - result := result + '.'; // do not localize + result := result + '.'; if ReadOnly then - result := result + ' (RO)' // do not localize + result := result + ' (RO)' else - result := result + ' (RW)'; // do not localize + result := result + ' (RW)'; end; { TBoldDrivenPropertyCollection } @@ -518,4 +524,6 @@ function TBoldPropertiesController.GetContextType: TBoldElementTypeInfo; result := nil; end; +initialization + end. diff --git a/Source/BoldAwareGUI/BoldControls/BoldRichEdit.pas b/Source/BoldAwareGUI/BoldControls/BoldRichEdit.pas index e9def6a..cd3a55f 100644 --- a/Source/BoldAwareGUI/BoldControls/BoldRichEdit.pas +++ b/Source/BoldAwareGUI/BoldControls/BoldRichEdit.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldRichEdit; {$UNDEF BOLDCOMCLIENT} @@ -138,8 +141,9 @@ implementation StdCtrls, BoldDefs, BoldControlPackDefs, + BoldUtils, SysUtils, - BoldGuiResourceStrings; + BoldRev; {---TBoldCustomRichEdit---} constructor TBoldCustomRichEdit.Create(AOwner: TComponent); @@ -290,7 +294,7 @@ procedure TBoldCustomRichEdit.SetText(value: string); if not EffectiveReadOnly then inherited Text := value else - raise EBold.CreateFmt(sTextNotModifiable, [ClassName]); + raise EBold.Create('TBoldEdit.Text: Not modifiable'); end; function TBoldCustomRichEdit.GetText: string; @@ -308,7 +312,7 @@ function TBoldCustomRichEdit.GetPopupmenu: TPopupMenu; procedure TBoldCustomRichEdit.KeyPress(var Key: Char); begin inherited KeyPress(Key); - if (Key in [#32..#255]) and + if CharInSet(Key, [#32..#255]) and not BoldProperties.ValidateCharacter(Key, Follower) then begin MessageBeep(0); @@ -380,4 +384,7 @@ function TBoldCustomRichEdit.GetFollower: TBoldFollower; Result := fHandleFollower.Follower; end; +initialization + + end. diff --git a/Source/BoldAwareGUI/BoldControls/BoldStringsPropertyController.pas b/Source/BoldAwareGUI/BoldControls/BoldStringsPropertyController.pas index 2a6b02f..a8ff671 100644 --- a/Source/BoldAwareGUI/BoldControls/BoldStringsPropertyController.pas +++ b/Source/BoldAwareGUI/BoldControls/BoldStringsPropertyController.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldStringsPropertyController; {$UNDEF BOLDCOMCLIENT} @@ -38,6 +41,8 @@ TBoldStringsPropertyController = class(TComponent) fOnListBeforeInsertItem: TBoldControlSubFollowerEvent; fOnListAfterDeleteItem: TBoldControlSubFollowerEvent; fOnItemAfterMakeUpToDate: TBoldControlFollowerEvent; + fOnReplaceItem: TBoldControlSubFollowerEvent; + fStringsChanged: boolean; function GetBoldHandle: TBoldAbstractListHandle; procedure SetBoldHandle(value: TBoldAbstractListHandle); procedure SetBoldProperties(Value: TBoldListAsFollowerListController); @@ -46,13 +51,16 @@ TBoldStringsPropertyController = class(TComponent) procedure _ListBeforeMakeUptoDate(Follower: TBoldFollower); procedure _ListAfterMakeUptoDate(Follower: TBoldFollower); procedure _ListBeforeInsertItem(index: Integer; OwningFollower: TBoldFollower); - procedure _ListAfterInsertItem(Follower: TBoldFollower); + procedure _ListAfterInsertItem(index: Integer; Follower: TBoldFollower); procedure _ListAfterDeleteItem(index: Integer; OwningFollower: TBoldFollower); - procedure _ListBeforeDeleteItem(Follower: TBoldFollower); + procedure _ListBeforeDeleteItem(index: Integer; Follower: TBoldFollower); procedure _ItemAfterMakeUptoDate(Follower: TBoldFollower); procedure _ItemBeforeMakeUptoDate(Follower: TBoldFollower); + procedure _ListReplaceItem(index: Integer; AFollower: TBoldFollower); function GetStringsProperty: TStrings; procedure SetVCLComponent(const Value: TComponent); + procedure MarkStringsChanged; + procedure EndUpdate; protected procedure Notification(AComponent: TComponent; Operation: TOperation); override; property StringsProperty: TStrings read GetStringsProperty; @@ -87,6 +95,19 @@ implementation {-- TBoldStringsPropertyController ----------------------------------------------------------} +procedure TBoldStringsPropertyController.MarkStringsChanged; +var + Strings: TStrings; +begin + if not fStringsChanged then + begin + fStringsChanged := true; + Strings := StringsProperty; + if Assigned(Strings) then + Strings.BeginUpdate; + end; +end; + constructor TBoldStringsPropertyController.Create(AOwner: TComponent); begin inherited; @@ -99,6 +120,7 @@ constructor TBoldStringsPropertyController.Create(AOwner: TComponent); begin OnAfterInsertItem := _ListAfterInsertItem; OnAfterDeleteItem := _ListAfterDeleteItem; + OnReplaceitem := _ListReplaceItem; OnBeforeInsertItem := _ListBeforeInsertItem; OnBeforeDeleteItem := _ListBeforeDeleteItem; BeforeMakeUptoDate := _ListBeforeMakeUptoDate; @@ -144,7 +166,7 @@ procedure TBoldStringsPropertyController._ListAfterMakeUptoDate(Follower: TBoldF begin Strings := StringsProperty; if Assigned(Strings) then - Strings.EndUpdate; + EndUpdate; if Assigned(fOnListAfterMakeUptoDate) then fOnListAfterMakeUptoDate(self, Follower); end; @@ -156,17 +178,36 @@ procedure TBoldStringsPropertyController._ListBeforeMakeUptoDate(Follower: TBold Strings := StringsProperty; if Assigned(Strings) then begin - Strings.BeginUpdate; if Follower.SubFollowerCount <> Strings.Count then if Follower.SubFollowerCount = 0 then + begin + MarkStringsChanged; Strings.Clear + end else - raise EBold.CreateFmt(sStringsControlledByOtherMeans, [Name]); + raise EBold.CreateFmt('Strings property controlled by "%s" changed by other means', [Name]); end; if Assigned(fOnListBeforeMakeUptoDate) then fOnListBeforeMakeUptoDate(self, Follower); end; +procedure TBoldStringsPropertyController._ListReplaceItem(index: Integer; + AFollower: TBoldFollower); +var + Strings: TStrings; +begin + Strings := StringsProperty; + if Assigned(Strings) then + begin + AFollower.EnsureDisplayable; + MarkStringsChanged; + Strings.Objects[Index] := AFollower; + Strings[Index] := TBoldStringFollowerController(AFollower.Controller).GetCurrentAsString(AFollower); + end; + if Assigned(fOnReplaceItem) then + fOnReplaceItem(self, index, AFollower); +end; + procedure TBoldStringsPropertyController._ListAfterDeleteItem(index: Integer; OwningFollower: TBoldFollower); var @@ -174,18 +215,25 @@ procedure TBoldStringsPropertyController._ListAfterDeleteItem(index: Integer; begin Strings := StringsProperty; if Assigned(Strings) then + begin + MarkStringsChanged; Strings.Delete(Index); + end; if Assigned(fOnListAfterDeleteItem) then fOnListAfterDeleteItem(self, index, OwningFollower); end; -procedure TBoldStringsPropertyController._ListAfterInsertItem(Follower: TBoldFollower); +procedure TBoldStringsPropertyController._ListAfterInsertItem(index: Integer; Follower: TBoldFollower); var Strings: TStrings; begin Strings := StringsProperty; if Assigned(Strings) then - Strings.InsertObject(Follower.Index, '', Follower); + begin + Follower.EnsureDisplayable; + MarkStringsChanged; + Strings.InsertObject(Index, TBoldStringFollowerController(Follower.Controller).GetCurrentAsString(Follower), Follower); + end; if Assigned(fOnListAfterInsertItem) then fOnListAfterInsertItem(self, Follower); end; @@ -194,14 +242,26 @@ procedure TBoldStringsPropertyController._ItemAfterMakeUptoDate(Follower: TBoldF var index: Integer; Strings: TStrings; + s: string; begin Strings := StringsProperty; if Assigned(Strings) then begin index := Follower.index; if (index > -1) and (index < Strings.Count) then - Strings[index] := TBoldStringFollowerController(Follower.Controller).GetCurrentAsString(Follower); - Strings.Objects[index] := Follower; + begin + s := TBoldStringFollowerController(Follower.Controller).GetCurrentAsString(Follower); + if s <> Strings[index] then + begin + MarkStringsChanged; + Strings[index] := TBoldStringFollowerController(Follower.Controller).GetCurrentAsString(Follower); + end; + if Strings.Objects[index] <> Follower then + begin + MarkStringsChanged; + Strings.Objects[index] := Follower; + end; + end; end; if Assigned(fOnItemAfterMakeUptoDate) then fOnItemAfterMakeUptoDate(self, Follower); @@ -230,7 +290,7 @@ function TBoldStringsPropertyController.GetStringsProperty: TStrings; end; end; -procedure TBoldStringsPropertyController._ListBeforeDeleteItem(Follower: TBoldFollower); +procedure TBoldStringsPropertyController._ListBeforeDeleteItem(index: Integer; Follower: TBoldFollower); begin if Assigned(fOnListBeforeDeleteItem) then fOnListBeforeDeleteItem(self, Follower); @@ -260,4 +320,17 @@ procedure TBoldStringsPropertyController.SetVCLComponent(const Value: TComponent PropertyName := ''; end; +procedure TBoldStringsPropertyController.EndUpdate; +var + Strings: TStrings; +begin + if fStringsChanged then + begin + Strings := StringsProperty; + if Assigned(Strings) then + Strings.EndUpdate; + fStringsChanged := false; + end; +end; + end. diff --git a/Source/BoldAwareGUI/BoldControls/BoldTrackBar.pas b/Source/BoldAwareGUI/BoldControls/BoldTrackBar.pas index cfc6e4d..8d5cce4 100644 --- a/Source/BoldAwareGUI/BoldControls/BoldTrackBar.pas +++ b/Source/BoldAwareGUI/BoldControls/BoldTrackBar.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldTrackBar; {$UNDEF BOLDCOMCLIENT} @@ -13,7 +16,7 @@ interface CommCtrl, Menus, BoldDefs, - BoldEnvironmentVCL, // Make sure VCL environement loaded, and finalized after + BoldEnvironmentVCL, BoldControlPackDefs, BoldHandles, BoldElements, @@ -33,8 +36,8 @@ TBoldTrackBar = class(TTrackBar, IBoldOCLComponent) fHandleFollower: TBoldElementHandleFollower; FReadOnly: Boolean; function GetContextType: TBoldElementTypeInfo; - procedure SetExpression(Expression: String); - function GetExpression: String; + procedure SetExpression(const Value: TBoldExpression); + function GetExpression: TBoldExpression; function GetVariableList: TBoldExternalVariableList; procedure AfterMakeUptoDate(Follower: TBoldFollower); procedure CMExit(var Message: TCMExit); message CM_EXIT; @@ -239,14 +242,14 @@ function TBoldTrackBar.GetContextType: TBoldElementTypeInfo; result := nil; end; -function TBoldTrackBar.GetExpression: String; +function TBoldTrackBar.GetExpression: TBoldExpression; begin result := BoldProperties.Expression; end; -procedure TBoldTrackBar.SetExpression(Expression: String); +procedure TBoldTrackBar.SetExpression(const Value: TBoldExpression); begin - BoldProperties.Expression := Expression; + BoldProperties.Expression := Value; end; function TBoldTrackBar.GetVariableList: TBoldExternalVariableList; @@ -254,4 +257,5 @@ function TBoldTrackBar.GetVariableList: TBoldExternalVariableList; result := BoldProperties.VariableList; end; +initialization end. diff --git a/Source/BoldAwareGUI/BoldControls/BoldTreeView.pas b/Source/BoldAwareGUI/BoldControls/BoldTreeView.pas index 5f21469..aca634e 100644 --- a/Source/BoldAwareGUI/BoldControls/BoldTreeView.pas +++ b/Source/BoldAwareGUI/BoldControls/BoldTreeView.pas @@ -1,6 +1,10 @@ +///////////////////////////////////////////////////////// + + unit BoldTreeView; {$UNDEF BOLDCOMCLIENT} +{$INCLUDE bold.inc} interface @@ -16,7 +20,7 @@ interface BoldEnvironmentVCL, // Make sure VCL environement loaded, and finalized after {$IFNDEF BOLDCOMCLIENT} // uses BoldSystem, // IFNDEF BOLDCOMCLIENT - BoldGui, // IFNDEF BOLDCOMCLIENT + BoldGui, // IFNDEF BOLDCOMCLIENT {$ENDIF} BoldElements, BoldHandles, @@ -36,6 +40,9 @@ TBoldCustomTreeView = class; TBoldTreeView = class; TBoldTreeNode = class; + TDestroyWndNotifyEvent = procedure (Sender: TObject) of object; + TCreateWndNotifyEvent = procedure (Sender: TObject) of object; + {---TBoldTreeNode---} TBoldTreeNode = class(TTreeNode) private @@ -56,21 +63,21 @@ TBoldTreeNode = class(TTreeNode) end; {---TBoldCustomTreeView---} - TBoldCustomTreeView = class(TCustomTreeView, IBoldValidateableComponent) + TBoldCustomTreeView = class(TTreeView, IBoldValidateableComponent) private fHandleFollower: TBoldElementHandleFollower; - FTreeController: TBoldTreeFollowerController; - FMaxLevels: Integer; - FAutoExpandLevels: Integer; - FSelectInserted: Boolean; - FSelectedIndexDelta: Integer; + fTreeController: TBoldTreeFollowerController; + fMaxLevels: Integer; + fAutoExpandLevels: Integer; + fSelectInserted: Boolean; + fSelectedIndexDelta: Integer; fSelectedImageIndex: integer; fStateImageSelected: integer; fStateImageUnselected: integer; - FNodeExpansion: TBoldNodeExpansionMethod; - FDragFollower: TBoldFollower; - FEditFollower: TBoldFollower; - FUpdateCount: Integer; + fNodeExpansion: TBoldNodeExpansionMethod; + fDragFollower: TBoldFollower; + fEditFollower: TBoldFollower; + fUpdateCount: Integer; fMultiSelect: Boolean; fSelectAnchor: TBoldTreeNode; fLastSelectedNode: TBoldTreeNode; @@ -82,6 +89,9 @@ TBoldCustomTreeView = class(TCustomTreeView, IBoldValidateableComponent) fSelectedElementPreUpdate: TBoldElement; fSelectedNodeDescriptionPreUpdate: TBoldNodeDescription; fNodesHaveBeenDeleted: Boolean; + FItemsRecreated: Boolean; + FOnDestroyWnd: TDestroyWndNotifyEvent; + FOnCreateWnd: TCreateWndNotifyEvent; procedure _CustomDrawItem(Sender: TCustomTreeView; Node: TTreeNode; State: TCustomDrawState; var DefaultDraw: Boolean); procedure ClearAllSelections; procedure SetBoldHandle(Value: TBoldElementHandle); @@ -99,7 +109,7 @@ TBoldCustomTreeView = class(TCustomTreeView, IBoldValidateableComponent) procedure SetMultiSelect(NewValue: Boolean); procedure UpdateMultiSelect(Node: TBoldTreeNode; Shift: TShiftState; MouseDirection: TBoldMouseDirection); {$IFNDEF BOLDCOMCLIENT} - function ValidateComponent(ComponentValidator: TBoldComponentValidator; NamePrefix: String): Boolean; + function ValidateComponent(ComponentValidator: TBoldComponentValidator; NamePrefix: string): Boolean; {$ENDIF} property MultiSelect: Boolean read fMultiSelect write SetMultiSelect default false; function GetPopupElement: TBoldElement; @@ -117,7 +127,7 @@ TBoldCustomTreeView = class(TCustomTreeView, IBoldValidateableComponent) function CreateNode: TTreeNode; override; procedure CreateWnd; override; procedure DestroyWnd; override; - procedure DeleteNode(Follower: TBoldFollower); virtual; + procedure DeleteNode(Index: integer; Follower: TBoldFollower); virtual; procedure DisplayText(Follower: TBoldFollower); virtual; procedure DisplayIcon(Follower: TBoldFollower); virtual; procedure DoEndDrag(Target: TObject; X, Y: Integer); override; @@ -128,7 +138,7 @@ TBoldCustomTreeView = class(TCustomTreeView, IBoldValidateableComponent) procedure Edit(const Item: TTVItem); override; procedure Expand(Node: TTreeNode); override; function GetPopupMenu: TPopupMenu; override; - procedure InsertNode(Follower: TBoldFollower); virtual; + procedure InsertNode(Index: integer; Follower: TBoldFollower); virtual; procedure KeyUp(var Key: Word; Shift: TShiftState); override; procedure KeyPress(var Key: Char); override; @@ -140,7 +150,7 @@ TBoldCustomTreeView = class(TCustomTreeView, IBoldValidateableComponent) function TreeFollowerControllerClass: TBoldTreeFollowerControllerClass; virtual; {To be published} property AutoExpandLevels: Integer read FAutoExpandLevels write SetAutoExpandLevels default -1; - property BoldHandle: TBoldElementHandle read GetBoldHandle write SetBoldHandle; + property BoldHandle: TBoldElementHandle read GetBoldHandle write SetBoldHandle; property BoldProperties: TBoldTreeFollowerController read FTreeController write SetTreeController; property MaxLevels: Integer read FMaxLevels write SetMaxLevels default -1; property NodeExpansion: TBoldNodeExpansionMethod read FNodeExpansion write FNodeExpansion default neDemand; @@ -152,16 +162,19 @@ TBoldCustomTreeView = class(TCustomTreeView, IBoldValidateableComponent) public constructor Create(aOwner: TComponent); override; destructor Destroy; override; +// procedure LogNodes; procedure DragDrop(Source: TObject; X, Y: Integer); override; function GetElementAt(X, Y: Integer): TBoldElement; function GetFollowerAt(X, Y: Integer): TBoldFollower; procedure FillListWithSelectedObjects(List: TBoldObjectList); - function FindListPartByNames(const NodeDescName, ListPartName: String): TBoldGenericListPart; + function FindListPartByNames(const NodeDescName, ListPartName: string): TBoldGenericListPart; property CurrentFollower: TBoldFollower read GetCurrentFollower; property CurrentElement: TBoldElement read GetCurrentElement; property PopupElement: TBoldElement read GetPopupElement; property Selected: TBoldTreeNode read GetSelected write SetSelected; property RootFollower: TBoldFollower read GetRootFollower; + property OnDestroyWnd: TDestroyWndNotifyEvent read FOnDestroyWnd write FOnDestroyWnd; + property OnCreateWnd: TCreateWndNotifyEvent read FOnCreateWnd write FOnCreateWnd; end; {---TBoldTreeView---} @@ -243,12 +256,14 @@ implementation uses SysUtils, - BoldUtils; + BoldUtils, BoldQueue; {---TBoldTreeNode---} + function TBoldTreeNode.GetNodeDescription: TBoldNodeDescription; var I: Integer; + bnd: TBoldNodeDescriptions; begin // Check if cache is accurate. if Assigned(FNodeDescription) and (FNodeDescription.NodeFollowerController = Follower.Controller) then @@ -258,16 +273,14 @@ function TBoldTreeNode.GetNodeDescription: TBoldNodeDescription; else begin I := 0; - with TBoldTreeView(TreeView).BoldProperties.NodeDescriptions do - begin - while (I Follower.Controller) do - Inc(I); - if (Items[I].NodeFollowerController = Follower.Controller) then - FNodeDescription := Items[I] - else - FNodeDescription := nil; - Result := FNodeDescription; - end; + bnd:=TBoldTreeView(TreeView).BoldProperties.NodeDescriptions; + while (I < bnd.Count) and (bnd.Items[I].NodeFollowerController <> Follower.Controller) do + Inc(I); + if (bnd.Items[I].NodeFollowerController = Follower.Controller) then + FNodeDescription := bnd.Items[I] + else + FNodeDescription := nil; + Result := FNodeDescription; end; end; @@ -283,23 +296,23 @@ function TBoldTreeNode.ExistsInParent: Boolean; {---TBoldCustomTreeView---} (*Constructor and destructor*) + constructor TBoldCustomTreeView.Create(aOwner: TComponent); begin inherited Create(aOwner); - FTreeController := TreeFollowerControllerClass.Create(Self); - FTreeController.OnAfterInsertItem := InsertNode; - FTreeController.OnBeforeDeleteItem := DeleteNode; - FTreeController.OnIconChanged := DisplayIcon; - FTreeController.OnTextChanged := DisplayText; - FTreeController.OnGetContextType := GetContextType; - FTreeController.AfterMakeUptoDate := AfterMakeUptoDate; - FTreeController.BeforeMakeUptoDate := BeforeMakeUptoDate; - + fTreeController := TreeFollowerControllerClass.Create(Self); + fTreeController.OnAfterInsertItem := InsertNode; + fTreeController.OnBeforeDeleteItem := DeleteNode; + fTreeController.OnIconChanged := DisplayIcon; + fTreeController.OnTextChanged := DisplayText; + fTreeController.OnGetContextType := GetContextType; + fTreeController.AfterMakeUptoDate := AfterMakeUptoDate; + fTreeController.BeforeMakeUptoDate := BeforeMakeUptoDate; fHandleFollower := TBoldElementHandleFollower.Create(Owner, FTreeController); - FMaxLevels := -1; - FAutoExpandLevels := -1; - FNodeExpansion := neDemand; + fMaxLevels := -1; + fAutoExpandLevels := -1; + fNodeExpansion := neDemand; fSelectedImageIndex := -1; fStateImageSelected := -1; fStateImageUnselected := -1; @@ -309,7 +322,7 @@ constructor TBoldCustomTreeView.Create(aOwner: TComponent); destructor TBoldCustomTreeView.Destroy; begin FreeAndNil(fHandleFollower); - FreeAndNil(FTreeController); + FreeAndNil(fTreeController); inherited Destroy; end; @@ -341,24 +354,24 @@ procedure TBoldCustomTreeView.SetMaxLevels(Value: Integer); var I: Integer; begin - for I := 0 to Follower.SubFollowerCount-1 do + for I := 0 to Follower.SubFollowerCount - 1 do begin //Update this node - if (Follower.SubFollowers[I].Controller as TBoldNodeFollowerController).HideNodeWithNoChildren then + if (Follower.SubFollowers[I].Controller as TBoldNodeFollowerController).HideNodeWithNoChildren then DoInsertHiddenNode(Follower.SubFollowers[I]) else SetNodeState(TBoldTreeNode(Follower.SubFollowers[I].ControlData)); //Recurse through subfollowers - if Follower.SubFollowers[I].Active and (Follower.SubFollowers[I].SubFollowerCount>=BoldNodeListIndex) and Follower.SubFollowers[I].SubFollowers[BoldNodeListIndex].Active then - DoList(Level+1, Follower.SubFollowers[I].SubFollowers[BoldNodeListIndex]) + if Follower.SubFollowers[I].Active and (Follower.SubFollowers[I].SubFollowerCount >= BoldNodeListIndex) and Follower.SubFollowers[I].SubFollowers[BoldNodeListIndex].Active then + DoList(Level + 1, Follower.SubFollowers[I].SubFollowers[BoldNodeListIndex]) end; end; begin RootFollower.EnsureDisplayable; - if Value<-1 then + if Value < -1 then Value := -1; - if (Value<>FMaxLevels) then + if (Value <> FMaxLevels) then begin FMaxLevels := Value; BeginUpdate; @@ -376,7 +389,7 @@ procedure TBoldCustomTreeView.SetAutoExpandLevels(Value: Integer); Node: TBoldTreeNode; begin RootFollower.EnsureDisplayable; - if Value<-1 then + if Value < -1 then Value := -1; FAutoExpandLevels := Value; if (FAutoExpandLevels <> -1) then @@ -384,7 +397,7 @@ procedure TBoldCustomTreeView.SetAutoExpandLevels(Value: Integer); I := 0; BeginUpdate; try - while (I 0) and (csRecreating in ControlState) then begin + FItemsRecreated := True; + if Assigned(FOnDestroyWnd) then FOnDestroyWnd(Self); + end; RootFollower.Active := false; Items.Clear; - Inherited DestroyWnd; + inherited DestroyWnd; end; function TBoldCustomTreeView.GetSelected: TBoldTreeNode; @@ -469,6 +491,7 @@ procedure TBoldCustomTreeView.EndUpdate; end; (*Display values add and remove of nodes*) + procedure TBoldCustomTreeView.DisplayText(Follower: TBoldFollower); var Node: TTreeNode; @@ -546,12 +569,16 @@ function TBoldCustomTreeView.DoInsertVisibleNode(Follower: TBoldFollower): TBold ParentNode: TTreeNode; PrevSiblingNode: TTreeNode; I: Integer; + lBoldTreeNode: TBoldTreeNode; + s: string; +// TextController: TBoldStringFollowerController; +// lTextFollower: TBoldFollower; begin - + s := ''; ParentNode := nil; PrevSiblingNode := nil; I := Follower.Index; - while not Assigned(PrevSiblingNode) and (I #32) and - not (FEditFollower.Controller as TBoldStringFollowerController).ValidateCharacter(Key, FEditFollower) then + not (FEditFollower.Controller as TBoldStringFollowerController).ValidateCharacter(Key, FEditFollower) then begin MessageBeep(0); Key := #0; @@ -762,11 +801,13 @@ procedure TBoldCustomTreeView.Edit(const Item: TTVItem); S: string; Node: TTreeNode; - function GetNodeFromItem(Item: TTVItem):TTreeNode; + function GetNodeFromItem(Item: TTVItem): TTreeNode; begin with Item do - if (state and TVIF_PARAM) <> 0 then Result := Pointer(lParam) - else Result := Items.GetNode(hItem); + if (state and TVIF_PARAM) <> 0 then Result := Pointer(lParam) + {$WARN UNSAFE_CAST OFF} + else Result := Items.GetNode(hItem); + {$WARN UNSAFE_CAST ON} end; begin @@ -907,6 +948,7 @@ procedure TBoldCustomTreeView.DragDrop(Source: TObject; X, Y: Integer); end; (*Popup menu*) + function TBoldCustomTreeView.GetPopupmenu: TPopupMenu; begin Result := inherited GetPopupMenu; @@ -915,33 +957,36 @@ function TBoldCustomTreeView.GetPopupmenu: TPopupMenu; end; (*Expand and collapse*) + function TBoldCustomTreeView.CanExpand(Node: TTreeNode): Boolean; var I: Integer; ChildNode: TBoldTreeNode; + lFollower: TBoldFollower; begin - Result := inherited CanExpand(Node) and Assigned(TBoldTreeNode(Node).Follower) and ((MaxLevels=-1) or (Node.Level BoldNodeListIndex) then + (lFollower.SubFollowerCount > BoldNodeListIndex) then begin - for I := 0 to TBoldTreeNode(Node).Follower.SubFollowers[BoldNodeListIndex].SubFollowerCount-1 do + for I := 0 to lFollower.SubFollowers[BoldNodeListIndex].SubFollowerCount - 1 do begin - ChildNode := (TBoldTreeNode(Node).Follower.SubFollowers[BoldNodeListIndex].SubFollowers[I].ControlData as TBoldTreeNode); + ChildNode := (lFollower.SubFollowers[BoldNodeListIndex].SubFollowers[I].ControlData as TBoldTreeNode); if Assigned(ChildNode) and - ((MaxLevels = -1) or (ChildNode.Level < MaxLevels)) and - not TBoldTreeNode(ChildNode).ExistsInParent and - ((ChildNode.Follower.SubFollowerCount = 0) or (not ChildNode.Follower.SubFollowers[BoldNodeListIndex].Active)) then + ((MaxLevels = -1) or (ChildNode.Level < MaxLevels)) and + not TBoldTreeNode(ChildNode).ExistsInParent and + ((ChildNode.Follower.SubFollowerCount = 0) or (not ChildNode.Follower.SubFollowers[BoldNodeListIndex].Active)) then begin ChildNode.HasChildren := False; (ChildNode.Follower.Controller as TBoldNodeFollowerController).SetActiveRange(ChildNode.Follower, BoldNodeListIndex, BoldNodeTextIndex); @@ -976,6 +1021,7 @@ procedure TBoldCustomTreeView.Collapse(Node: TTreeNode); end; (*Other*) + function TBoldCustomTreeView.CanChange(Node: TTreeNode): Boolean; begin Result := inherited CanChange(Node); @@ -1027,10 +1073,11 @@ function TBoldCustomTreeView.GetContextType: TBoldElementTypeInfo; end; {$IFNDEF BOLDCOMCLIENT} -function TBoldCustomTreeView.ValidateComponent(ComponentValidator: TBoldComponentValidator; NamePrefix: String): Boolean; + +function TBoldCustomTreeView.ValidateComponent(ComponentValidator: TBoldComponentValidator; NamePrefix: string): Boolean; var j, i: integer; - BaseName: String; + BaseName: string; Context: TBoldElementTypeInfo; begin // We want to evaluate everything. Thus suboptimized expressions. @@ -1043,28 +1090,28 @@ function TBoldCustomTreeView.ValidateComponent(ComponentValidator: TBoldComponen with BoldProperties.NodeDescriptions[i] do begin Context := NodeFollowerController.ContextType; - BaseName:= format('%s%s.Node[%d:%s]', [NamePrefix, self.Name, i, Name]); // do not localize + BaseName := format('%s%s.Node[%d:%s]', [NamePrefix, self.Name, i, Name]); // do not localize Result := ComponentValidator.ValidateExpressionInContext('', Context, BaseName); if Assigned(Context) then begin Result := ComponentValidator.ValidateExpressionInContext( - IconController.Expression, - Context, - BaseName + '.IconController') and Result; // do not localize + IconController.Expression, + Context, + BaseName + '.IconController') and Result; // do not localize Result := ComponentValidator.ValidateExpressionInContext( - TextController.Expression, - Context, - BaseName + '.TextController') and Result; // do not localize + TextController.Expression, + Context, + BaseName + '.TextController') and Result; // do not localize for j := 0 to ListController.Parts.Count - 1 do begin Result := ComponentValidator.ValidateExpressionInContext( - ListController.Parts[j].ControllerExpression, - Context, - BaseName + format('.ListPart[%d]', [j])) and Result; // do not localize + ListController.Parts[j].ControllerExpression, + Context, + BaseName + format('.ListPart[%d]', [j])) and Result; // do not localize end; end; end; @@ -1074,7 +1121,7 @@ function TBoldCustomTreeView.ValidateComponent(ComponentValidator: TBoldComponen function TBoldCustomTreeView.TreeFollowerControllerClass: TBoldTreeFollowerControllerClass; begin - result := TBoldTreeFollowerController; + Result := TBoldTreeFollowerController; end; procedure TBoldCustomTreeView.SetMultiSelect(NewValue: Boolean); @@ -1186,12 +1233,15 @@ procedure TBoldCustomTreeView.FillListWithSelectedObjects(List: TBoldObjectList) destructor TBoldTreeNode.destroy; begin inherited; + if Assigned(FFollower) and (FFollower.ControlData = self) then + FFollower.ControlData := nil; if TreeView.fLastSelectedNode = self then TreeView.fLastSelectedNode := nil; if TreeView.fSelectAnchor = self then TreeView.fSelectAnchor := nil; if TreeView.fPopupNode = self then TreeView.fPopupNode := nil; + FFollower := nil; end; function TBoldTreeNode.GetTreeView: TBoldTreeView; @@ -1214,7 +1264,7 @@ procedure TBoldCustomTreeView.SetSelectionInSubtree(Node: TTreeNode; Selected: B procedure TBoldTreeNode.UpdateIcon; begin - if assigned(Follower) and assigned(Follower.SubFollowers[1]) then + if assigned(Follower) and assigned(Follower.Controller) and assigned(Follower.SubFollowers[1]) then Follower.SubFollowers[1].MarkValueOutOfDate; end; @@ -1240,7 +1290,36 @@ procedure TBoldCustomTreeView.KeyUp(var Key: Word; Shift: TShiftState); UpdateMultiSelect(Selected as TBoldTreeNode, Shift, dirMouseDown); end; -function TBoldCustomTreeView.FindListPartByNames(const NodeDescName, ListPartName: String): TBoldGenericListPart; +//procedure TBoldCustomTreeView.LogNodes; +//var +// lIndex: Integer; +// lBoldTreeNode: TBoldTreeNode; +// lBoldFollowerController: TBoldFollowerController; +//begin +// CodeSite.Category := 'LogNodes'; +// CodeSite.Send('**** Start LogNodes ***'); +// +// for lIndex := 0 to Items.Count - 1 do +// begin +// lBoldTreeNode := Items[lIndex] as TBoldTreeNode; +// if Assigned(lBoldTreeNode.Follower) then +// begin +// CodeSite.Send('lBoldTreeNode.Follower ', Integer(lBoldTreeNode.Follower)); +// Assert(lBoldTreeNode.Follower is TBoldFollower); +// lBoldFollowerController := lBoldTreeNode.Follower.AssertedController; +// CodeSite.Send('Integer(lBoldFollowerController)', Integer(lBoldFollowerController)); +// CodeSite.Send(lBoldFollowerController.ClassName); +// if not (lBoldFollowerController is TBoldNodeFollowerController) then +// begin +// raise exception.Create('Improper Controller has been assigned'); +// end; +// end; +// end; +// CodeSite.Send('**** End LogNodes ***'); +// CodeSite.Category := ''; +//end; + +function TBoldCustomTreeView.FindListPartByNames(const NodeDescName, ListPartName: string): TBoldGenericListPart; var NodeDesc: TBoldNodeDescription; begin @@ -1256,9 +1335,11 @@ procedure TBoldCustomTreeView._CustomDrawItem(Sender: TCustomTreeView; Node: TTr Follower: TBoldfollower; aColor: TColor; TextController: TBoldStringFollowerController; + lBoldTreeNode: TBoldTreeNode; begin - Follower := (Node as TBoldTreeNode).Follower; - if assigned(Follower) then + lBoldTreeNode := Node as TBoldTreeNode; + Follower := lBoldTreeNode.Follower; + if assigned(Follower) and not Follower.IsInDisplayList and Assigned(Follower.Controller) then begin TextController := (Follower.Controller as TBoldNodeFollowerController).TextFollowerController; if not (cdsSelected in State) then @@ -1271,3 +1352,5 @@ procedure TBoldCustomTreeView._CustomDrawItem(Sender: TCustomTreeView; Node: TTr end; end. + + diff --git a/Source/BoldAwareGUI/BoldControls/BoldTreeViewConfig.pas b/Source/BoldAwareGUI/BoldControls/BoldTreeViewConfig.pas index dc8a1a9..6752f15 100644 --- a/Source/BoldAwareGUI/BoldControls/BoldTreeViewConfig.pas +++ b/Source/BoldAwareGUI/BoldControls/BoldTreeViewConfig.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldTreeViewConfig; {$UNDEF BOLDCOMCLIENT} @@ -9,8 +12,8 @@ interface BoldGenericListControlPack, BoldNodeControlPack, BoldSystemRT, - {$IFDEF BOLDCOMCLIENT} // uses - BoldSystem, // to get the ObjectSpace interfaces + {$IFDEF BOLDCOMCLIENT} + BoldSystem, {$ENDIF} BoldTreeView; @@ -22,7 +25,7 @@ implementation SysUtils, BoldUtils; -{$IFDEF BOLDCOMCLIENT} // BoldGenericTreeView +{$IFDEF BOLDCOMCLIENT} procedure BoldGenericTreeView(SystemTypeInfo: IBoldSystemTypeInfo; TreeView: TBoldTreeViewCom); begin end; @@ -33,11 +36,11 @@ procedure FillListpartForAttr(RTAttr: TBoldAttributeRTInfo; var s: string; begin - s := format('''%s: '' + %s.asString', [RTAttr.ExpressionName, RTAttr.ExpressionName]); // do not localize + s := format('''%s: '' + %s.asString', [RTAttr.ExpressionName, RTAttr.ExpressionName]); s[2] := UpCase(s[2]); ListPart.ElementExpression := s; ListPart.InterpretAsList := False; - ListPart.ControllerExpression := '''AttributeNode'''; // do not localize + ListPart.ControllerExpression := '''AttributeNode'''; end; @@ -54,15 +57,13 @@ procedure FillListpartForRole(RTRole: TBoldRoleRTInfo; ListPart.ControllerExpression := format('''%s''', [RoleName]); ListPart.InterpretAsList := False; if DefiningClass = RTRole.ClassTypeInfo then - with TreeView.BoldProperties.NodeDescriptions.Add do - begin + with TreeView.BoldProperties.NodeDescriptions.Add do begin Name := RoleName; s := format('''%s:''', [RTRole.ExpressionName]); s[2] := UpCase(s[2]); TextController.Expression := s; - with ListController.Parts.Add do - begin - ControllerExpression := 'oclType'; // do not localize + with ListController.Parts.Add do begin + ControllerExpression := 'oclType'; InterpretAsList := RTRole.IsMultiRole; end; end; @@ -76,9 +77,8 @@ procedure FillNodeDescriptorForClass(ClassTypeInfo: TBoldClassTypeInfo; Role: TBoldRoleRTInfo; begin NodeDescriptor.Name := ClassTypeInfo.ExpressionName; - NodeDescriptor.TextController.Expression := 'self.asString + '': '' + oclType.asString'; // do not localize - for i := 0 to ClassTypeInfo.AllMembers.Count - 1 do - begin + NodeDescriptor.TextController.Expression := 'self.asString + '': '' + oclType.asString'; + for i := 0 to ClassTypeInfo.AllMembers.Count-1 do begin DefiningClass := ClassTypeInfo; while i < DefiningClass.FirstOwnMemberIndex do DefiningClass := DefiningClass.SuperClassTypeInfo; @@ -104,18 +104,15 @@ procedure BoldGenericTreeView(SystemTypeInfo: TBoldSystemTypeInfo; TreeView: TBo var i: integer; begin - with TreeView.BoldProperties.NodeDescriptions.Add do - begin - Name := 'AttributeNode'; // do not localize + With TreeView.BoldProperties.NodeDescriptions.Add do begin + Name := 'AttributeNode'; end; - with TreeView.BoldProperties.parts.add do - begin + With TreeView.BoldProperties.parts.add do begin InterpretAsList := true; end; - for i := 0 to SystemTypeInfo.TopSortedClasses.count - 1 do - begin + for i := 0 to SystemTypeInfo.TopSortedClasses.count-1 do begin FillNodeDescriptorForClass( SystemTypeInfo.TopSortedClasses[i], TreeView.BoldProperties.NodeDescriptions.Add, @@ -125,4 +122,5 @@ procedure BoldGenericTreeView(SystemTypeInfo: TBoldSystemTypeInfo; TreeView: TBo {$ENDIF} +initialization end. diff --git a/Source/BoldAwareGUI/BoldControls/BoldXCVTreeView.pas b/Source/BoldAwareGUI/BoldControls/BoldXCVTreeView.pas index 5fc8272..d0fb907 100644 --- a/Source/BoldAwareGUI/BoldControls/BoldXCVTreeView.pas +++ b/Source/BoldAwareGUI/BoldControls/BoldXCVTreeView.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldXCVTreeView; interface diff --git a/Source/BoldAwareGUI/ControlPacks/BoldCheckboxStateControlPack.pas b/Source/BoldAwareGUI/ControlPacks/BoldCheckboxStateControlPack.pas index 1ec7c5a..e341ad3 100644 --- a/Source/BoldAwareGUI/ControlPacks/BoldCheckboxStateControlPack.pas +++ b/Source/BoldAwareGUI/ControlPacks/BoldCheckboxStateControlPack.pas @@ -1,3 +1,7 @@ + +{ Global compiler directives } +{$include bold.inc} + unit BoldCheckboxStateControlPack; {$UNDEF BOLDCOMCLIENT} @@ -18,10 +22,10 @@ TBoldAsCheckBoxStateRenderer = class; TBoldCheckBoxRendererData = class; { TBoldAsCheckBoxStateRenderer } - TBoldGetAsCheckBoxState = function (Element: TBoldElement; Representation: TBoldRepresentation; Expression: TBoldExpression): TCheckBoxState of object; - TBoldSetAsCheckBoxState = procedure (Element: TBoldElement; newValue: TCheckBoxState; Representation: TBoldRepresentation; Expression: TBoldExpression) of object; - TBoldValidateCheckBoxState = function (Element: TBoldElement; Value: TCheckBoxState; Representation: TBoldRepresentation; Expression: TBoldExpression): Boolean of object; - TBoldCheckBoxIsChanged = function (RendererData: TBoldCheckBoxRendererData; NewValue: TCheckBoxState; Representation: TBoldRepresentation; Expression: TBoldExpression): Boolean of object; + TBoldGetAsCheckBoxState = function (aFollower: TBoldFollower): TCheckBoxState of object; + TBoldSetAsCheckBoxState = procedure (aFollower: TBoldFollower; newValue: TCheckBoxState) of object; + TBoldValidateCheckBoxState = function (aFollower: TBoldFollower; Value: TCheckBoxState): Boolean of object; + TBoldCheckBoxIsChanged = function (Follower: TBoldFollower; NewValue: TCheckBoxState): Boolean of object; { TBoldCheckBoxRendererData } TBoldCheckBoxRendererData = class(TBoldRendererData) @@ -44,15 +48,15 @@ TBoldAsCheckBoxStateRenderer = class(TBoldSingleRenderer) function GetRendererDataClass: TBoldRendererDataClass; override; public class function DefaultRenderer: TBoldAsCheckBoxStateRenderer; - class function DefaultGetAsCheckBoxStateAndSubscribe(Element: TBoldElement; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList; Subscriber: TBoldSubscriber): TCheckBoxState; virtual; - class procedure DefaultSetAsCheckBoxState(Element: TBoldElement; newValue: TCheckBoxState; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList); virtual; - class function DefaultValidateCheckBoxState(Element: TBoldElement; Value: TCheckBoxState; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList): Boolean; virtual; - procedure MakeUptodateAndSubscribe(Element: TBoldElement; RendererData: TBoldRendererData; FollowerController: TBoldFollowerController; Subscriber: TBoldSubscriber); override; - function DefaultIsChanged(RendererData: TBoldCheckBoxRendererData; NewValue: TCheckBoxState; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList): Boolean; - function GetAsCheckBoxStateAndSubscribe(Element: TBoldElement; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList; Subscriber: TBoldSubscriber): TCheckBoxState; virtual; - procedure SetAsCheckBoxState(Element: TBoldElement; Value: TCheckBoxState; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList); virtual; - function ValidateCheckBoxState(Element: TBoldElement; Value: TCheckBoxState; Representation: TBoldRepresentation; Expression: TBoldExpression;VariableList: TBoldExternalVariableList): Boolean; virtual; - function IsChanged(RendererData: TBoldCheckBoxRendererData; NewValue: TCheckBoxState; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList): Boolean; + class function DefaultGetAsCheckBoxStateAndSubscribe(aFollower: TBoldFollower; Subscriber: TBoldSubscriber): TCheckBoxState; virtual; + class procedure DefaultSetAsCheckBoxState(aFollower: TBoldFollower; newValue: TCheckBoxState); virtual; + class function DefaultValidateCheckBoxState(aFollower: TBoldFollower; Value: TCheckBoxState): Boolean; virtual; + procedure MakeUptodateAndSubscribe(aFollower: TBoldFollower; Subscriber: TBoldSubscriber); override; + function DefaultIsChanged(Follower: TBoldFollower; NewValue: TCheckBoxState): Boolean; + function GetAsCheckBoxStateAndSubscribe(aFollower: TBoldFollower; Subscriber: TBoldSubscriber): TCheckBoxState; virtual; + procedure SetAsCheckBoxState(aFollower: TBoldFollower; Value: TCheckBoxState); virtual; + function ValidateCheckBoxState(aFollower: TBoldFollower; Value: TCheckBoxState): Boolean; virtual; + function IsChanged(Follower: TBoldFollower; NewValue: TCheckBoxState): Boolean; published property OnGetAsCheckBoxState: TBoldGetAsCheckBoxState read FOnGetAsCheckBoxState write FOnGetAsCheckBoxState; property OnSetAsCheckBoxState: TBoldSetAsCheckBoxState read FOnSetAsCheckBoxState write FOnSetAsCheckBoxState; @@ -85,7 +89,8 @@ implementation SysUtils, BoldGuiResourceStrings, BoldControlPackDefs, - BoldAttributes; + BoldAttributes, + BoldGuard; var DefaultAsCheckBoxStateRenderer: TBoldAsCheckBoxStateRenderer; @@ -122,52 +127,65 @@ function TBoldCheckBoxStateFollowerController.GetCurrentAsCheckBoxState(Follower procedure TBoldCheckBoxStateFollowerController.SetAsCheckBoxState(Value: TCheckBoxState; Follower: TBoldFollower); begin - EffectiveAsCheckBoxStateRenderer.SetAsCheckBoxState(Follower.Element, Value, Representation, Expression, VariableList); + EffectiveAsCheckBoxStateRenderer.SetAsCheckBoxState(Follower, Value); end; function TBoldCheckBoxStateFollowerController.ValidateCheckBoxState(Value: TCheckBoxState; Follower: TBoldFollower): Boolean; begin - Result := EffectiveAsCheckBoxStateRenderer.ValidateCheckBoxState(Follower.Element, Value, Representation, Expression, VariableList); + Result := EffectiveAsCheckBoxStateRenderer.ValidateCheckBoxState(Follower, Value); end; procedure TBoldCheckBoxStateFollowerController.MayHaveChanged(NewValue: TCheckBoxState; Follower: TBoldFollower); +var + lIsChanged: boolean; + lRendererData: TBoldCheckBoxRendererData; begin if Follower.State in bfsDisplayable then begin - (Follower.RendererData as TBoldCheckBoxRendererData).CurrentValue := NewValue; - Follower.ControlledValueChanged(EffectiveAsCheckBoxStateRenderer.IsChanged(Follower.RendererData as TBoldCheckBoxRendererData, NewValue, Representation, Expression, VariableList)); + lRendererData := Follower.RendererData as TBoldCheckBoxRendererData; + lRendererData.CurrentValue := NewValue; + lIsChanged := EffectiveAsCheckBoxStateRenderer.IsChanged(Follower, NewValue); + if lIsChanged then + begin + Follower.ControlledValueChanged; + end; end; end; procedure TBoldCheckBoxStateFollowerController.MakeClean(Follower: TBoldFollower); begin - ReleaseChangedValue(Follower); // note, must do first, since set can change element +// if (ApplyPolicy <> bapChange) or EffectiveRenderer.ChangedValueEventsAssigned then + begin + ReleaseChangedValue(Follower); // note, must do first, since set can change element + end; SetAsCheckBoxState(GetCurrentAsCheckBoxState(Follower), Follower); end; { TBoldAsCheckBoxStateRenderer } -procedure TBoldAsCheckBoxStateRenderer.MakeUpToDateANdSubscribe(Element: TBoldElement; RendererData: TBoldRendererData; FollowerController: TBoldFollowerController; Subscriber: TBoldSubscriber); +procedure TBoldAsCheckBoxStateRenderer.MakeUpToDateANdSubscribe(aFollower: TBoldFollower; Subscriber: TBoldSubscriber); var s: TCheckBoxState; - Controller: TBoldCheckBoxStateFollowerController; + lRendererData: TBoldCheckBoxRendererData; begin - Controller := FollowerController as TBoldCheckBoxStateFollowerController; - s := GetAsCheckBoxStateAndSubscribe(Element, Controller.Representation, Controller.Expression, Controller.GetVariableListAndSubscribe(Subscriber), Subscriber); - (RendererData as TBoldCheckBoxRendererData).OldValue := s; - (RendererData as TBoldCheckBoxRendererData).CurrentValue := s; + s := GetAsCheckBoxStateAndSubscribe(aFollower, Subscriber); + lRendererData := (aFollower.RendererData as TBoldCheckBoxRendererData); + lRendererData.OldValue := s; + lRendererData.CurrentValue := s; end; -class function TBoldAsCheckBoxStateRenderer.DefaultGetAsCheckBoxStateAndSubscribe(Element: TBoldElement; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList; Subscriber: TBoldSubscriber): TCheckBoxState; +class function TBoldAsCheckBoxStateRenderer.DefaultGetAsCheckBoxStateAndSubscribe(aFollower: TBoldFollower; Subscriber: TBoldSubscriber): TCheckBoxState; var {$IFDEF BOLDCOMCLIENT} // DefaultGet e: IBoldElement; Attribute: IBoldAttribute; {$ELSE} E: TBoldIndirectElement; + lResultElement: TBoldElement; + lGuard: IBoldGuard; {$ENDIF} begin Result := cbGrayed; - if Assigned(Element) then + if Assigned(aFollower.Element) then begin {$IFDEF BOLDCOMCLIENT} // defaultGet if assigned(Subscriber) then @@ -184,32 +202,34 @@ class function TBoldAsCheckBoxStateRenderer.DefaultGetAsCheckBoxStateAndSubscrib Result := cbUnchecked; end; {$ELSE} - E := TBoldIndirectElement.Create; - try - Element.EvaluateAndSubscribeToExpression(Expression, Subscriber, E, False, False, VariableList); - if E.Value is TBABoolean then - with E.Value as TBABoolean do - if IsNull then - Result := cbGrayed - else if AsBoolean then - Result := cbChecked - else - Result := cbUnchecked; - finally - E.Free; + lResultElement := aFollower.Value; + if not Assigned(lResultElement) then + begin + lGuard:= TBoldGuard.Create(E); + e := TBoldIndirectElement.Create; + aFollower.Element.EvaluateAndSubscribeToExpression(aFollower.AssertedController.Expression, Subscriber, E, False, False, aFollower.Controller.GetVariableListAndSubscribe(Subscriber)); + lResultElement := e.Value; end; + if lResultElement is TBABoolean then + with lResultElement as TBABoolean do + if IsNull then + Result := cbGrayed + else if AsBoolean then + Result := cbChecked + else + Result := cbUnchecked; {$ENDIF} end; end; -class procedure TBoldAsCheckBoxStateRenderer.DefaultSetAsCheckBoxState(Element: TBoldElement; newValue: TCheckBoxState; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList); +class procedure TBoldAsCheckBoxStateRenderer.DefaultSetAsCheckBoxState(aFollower: TBoldFollower; newValue: TCheckBoxState); var ValueElement: TBoldElement; {$IFDEF BOLDCOMCLIENT} // defaulSet Attribute: IBoldAttribute; {$ENDIF} begin - ValueElement := GetExpressionAsDirectElement(Element, Expression, VariableList); + ValueElement := aFollower.Value; {$IFDEF BOLDCOMCLIENT} // defaultSet if valueElement.QueryInterface(IBoldAttribute, Attribute) = S_OK then begin @@ -234,7 +254,7 @@ class procedure TBoldAsCheckBoxStateRenderer.DefaultSetAsCheckBoxState(Element: {$ENDIF} end else - raise EBold.CreateFmt(sCannotSetValue, [ClassName]); + raise EBold.CreateFmt('%s: Can''t set value', [ClassName]); end; function TBoldAsCheckBoxStateRenderer.GetRendererDataClass: TBoldRendererDataClass; @@ -242,40 +262,40 @@ function TBoldAsCheckBoxStateRenderer.GetRendererDataClass: TBoldRendererDataCla Result := TBoldCheckBoxRendererData; end; - class function TBoldAsCheckBoxStateRenderer.DefaultValidateCheckBoxState(Element: TBoldElement; Value: TCheckBoxState; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList): Boolean; +class function TBoldAsCheckBoxStateRenderer.DefaultValidateCheckBoxState(aFollower: TBoldFollower; Value: TCheckBoxState): Boolean; begin Result := True; end; -function TBoldAsCheckBoxStateRenderer.GetAsCheckBoxStateAndSubscribe(Element: TBoldElement; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList; Subscriber: TBoldSubscriber): TCheckBoxState; +function TBoldAsCheckBoxStateRenderer.GetAsCheckBoxStateAndSubscribe(aFollower: TBoldFollower; Subscriber: TBoldSubscriber): TCheckBoxState; begin if Assigned(OnSubscribe) and Assigned(Subscriber) then begin - if Assigned(Element) then - OnSubscribe(Element, Representation, Expression, Subscriber); + if Assigned(aFollower.Element) then + OnSubscribe(aFollower, Subscriber); Subscriber := nil; end; if Assigned(OnGetAsCheckBoxState) then - Result := OnGetAsCheckBoxState(Element, Representation, Expression) + Result := OnGetAsCheckBoxState(aFollower) else - Result := DefaultGetAsCheckBoxStateAndSubscribe(Element, Representation, Expression, VariableList, Subscriber); + Result := DefaultGetAsCheckBoxStateAndSubscribe(aFollower, Subscriber); end; -procedure TBoldAsCheckBoxStateRenderer.SetAsCheckBoxState(Element: TBoldElement; Value: TCheckBoxState; Representation: TBoldRepresentation; Expression: TBoldExpression;VariableList: TBoldExternalVariableList); +procedure TBoldAsCheckBoxStateRenderer.SetAsCheckBoxState(aFollower: TBoldFollower; Value: TCheckBoxState); begin if Assigned(OnSetAsCheckBoxState) then - OnSetAsCheckBoxState(Element, Value, Representation, Expression) + OnSetAsCheckBoxState(aFollower, Value) else - DefaultSetAsCheckBoxState(Element, Value, Representation, Expression, VariableList); + DefaultSetAsCheckBoxState(aFollower, Value); end; -function TBoldAsCheckBoxStateRenderer.ValidateCheckBoxState(Element: TBoldElement; Value: TCheckBoxState; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList): Boolean; +function TBoldAsCheckBoxStateRenderer.ValidateCheckBoxState(aFollower: TBoldFollower; Value: TCheckBoxState): Boolean; begin if Assigned(OnValidateCheckBoxState) then - Result := OnValidateCheckBoxState(Element, Value, Representation, Expression) + Result := OnValidateCheckBoxState(aFollower, Value) else - Result := DefaultValidateCheckBoxState(Element, Value, Representation, Expression, VariableList); + Result := DefaultValidateCheckBoxState(aFollower, Value); end; class function TBoldAsCheckBoxStateRenderer.DefaultRenderer: TBoldAsCheckBoxStateRenderer; @@ -283,17 +303,17 @@ function TBoldAsCheckBoxStateRenderer.ValidateCheckBoxState(Element: TBoldElemen Result := DefaultAsCheckBoxStateRenderer; end; -function TBoldAsCheckBoxStateRenderer.DefaultIsChanged(RendererData: TBoldCheckBoxRendererData; NewValue: TCheckBoxState; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList): Boolean; +function TBoldAsCheckBoxStateRenderer.DefaultIsChanged(Follower: TBoldFollower; NewValue: TCheckBoxState): Boolean; begin - Result := NewValue <> TBoldCheckBoxRendererData(RendererData).OldValue; + Result := NewValue <> TBoldCheckBoxRendererData(Follower.RendererData).OldValue; end; -function TBoldAsCheckBoxStateRenderer.IsChanged(RendererData: TBoldCheckBoxRendererData; NewValue: TCheckBoxState; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList): Boolean; +function TBoldAsCheckBoxStateRenderer.IsChanged(Follower: TBoldFollower; NewValue: TCheckBoxState): Boolean; begin if Assigned(fOnIsChanged) then - Result := fOnIsChanged(RendererData, NewValue, Representation, Expression) + Result := fOnIsChanged(Follower, NewValue) else - Result := DefaultIsChanged(RendererData, NewValue, Representation, Expression, VariableList); + Result := DefaultIsChanged(Follower, NewValue); end; initialization @@ -303,3 +323,4 @@ finalization FreeAndNil(DefaultAsCheckBoxStateRenderer); end. + diff --git a/Source/BoldAwareGUI/ControlPacks/BoldControlPack.pas b/Source/BoldAwareGUI/ControlPacks/BoldControlPack.pas index 6afe786..c44fbec 100644 --- a/Source/BoldAwareGUI/ControlPacks/BoldControlPack.pas +++ b/Source/BoldAwareGUI/ControlPacks/BoldControlPack.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldControlPack; {$UNDEF BOLDCOMCLIENT} @@ -9,8 +12,12 @@ interface SysUtils, Controls, {$IFDEF BOLD_DELPH6_OR_LATER} - Types, // IFDEF BOLD_DELPH6_OR_LATER + Types, {$ENDIF} +{$IFNDEF BOLDCOMCLIENT} + BoldSystemRT, + BoldSystem, +{$ENDIF} Menus, Graphics, Windows, @@ -21,8 +28,13 @@ interface BoldSubscription, BoldElements, BoldQueue, + BoldHandles, BoldOclVariables; +const + befFollowerResultElementOutOfDate = BoldElementFlag4; + befFollowerEnsured = BoldElementFlag5; + type {Forward declarations of all classes} TBoldRendererData = class; @@ -33,12 +45,35 @@ TBoldFollowerController = class; TBoldSingleFollowerController = class; TBoldSingleRenderer = class; TBoldPopup = class; + TBoldAbstractHandleFollower = class; TBoldRendererDataClass = class of TBoldRendererData; + TBoldFollowerControllerClass = class of TBoldFollowerController; TBoldFollowerEvent = procedure (Follower: TBoldFollower) of object; TBoldGetContextTypeEvent = function: TBoldElementTypeInfo of object; TBoldSubFollowerEvent = procedure (index: Integer; OwningFollower: TBoldFollower) of object; + TBoldValidateString = function (aFollower: TBoldFollower; const Value: string): Boolean of object; + TBoldApplyExceptionEvent = function (E: Exception; Elem: TBoldElement; var Discard: Boolean): Boolean of object; + TBoldDisplayExceptionEvent = function(E: Exception; Elem: TBoldElement): Boolean of object; + + TBoldFollowerArray = array of TBoldFollower; + + { TBoldAbstractHandleFollower } + TBoldAbstractHandleFollower = class(TBoldQueueable) + private + fFollower: TBoldFollower; + fSubscriber: TBoldSubscriber; + protected + function GetBoldHandle: TBoldElementHandle; virtual; abstract; + procedure Receive(Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent); virtual; abstract; + property Subscriber: TBoldSubscriber read fSubscriber; + public + constructor Create(AMatchObject: TObject; Controller: TBoldFollowerController); + destructor Destroy; override; + property BoldHandle: TBoldElementHandle read GetBoldHandle; + property Follower: TBoldFollower read fFollower; + end; { TBoldFollowerSubscriber } TBoldFollowerSubscriber = class(TBoldSubscriber) @@ -47,39 +82,41 @@ TBoldFollowerSubscriber = class(TBoldSubscriber) protected procedure Receive(Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent); override; function GetContextString: string; override; + function ContextObject: TObject; override; public - constructor Create(follower: TBoldFollower); + constructor Create(Follower: TBoldFollower); + destructor Destroy; override; property Follower: TBoldFollower read fFollower; end; { TBoldRendererData } - // Abstract class, concrete versions defined with typed renderer TBoldRendererData = class(TBoldMemoryManagedObject) private fOwningFollower: TBoldFollower; - fMayModify: Boolean; protected procedure EnsureSubfollowersDisplayable; virtual; function GetSubFollowerCount: Integer; virtual; function GetSubFollower(index: Integer): TBoldFollower; virtual; + function GetEnsuredSubFollower(Index: Integer): TBoldFollower; virtual; function GetCurrentSubFollowerIndex: Integer; virtual; procedure SetCurrentSubFollowerIndex(index:integer); virtual; + function GetSubFollowerAssigned(Index: Integer): boolean; virtual; public constructor Create(OwningFollower: TBoldFollower); virtual; property OwningFollower: TBoldFollower read fOwningFollower; - property MayModify: Boolean read fMayModify write fMayModify; end; { TBoldRenderer } - TBoldMayModify = function (Element: TBoldElement; Representation: TBoldRepresentation; Expression: TBoldExpression; Subscriber: TBoldSubscriber): Boolean of object; - TBoldHoldsChangedValue = procedure (Element: TBoldElement; Representation: TBoldRepresentation; Expression: TBoldExpression; Subscriber: TBoldSubscriber) of object; - TBoldReleaseChangedValue = procedure (Element: TBoldElement; Representation: TBoldRepresentation; Expression: TBoldExpression; Subscriber: TBoldSubscriber) of object; - TBoldSubscribe = procedure (Element: TBoldElement; Representation: TBoldRepresentation; Expression: TBoldExpression; Subscriber: TBoldSubscriber) of object; - + TBoldMayModify = function(aFollower: TBoldFollower): Boolean of object; + TBoldHoldsChangedValue = procedure(aFollower: TBoldFollower) of object; + TBoldReleaseChangedValue = procedure(aFollower: TBoldFollower) of object; + TBoldSubscribe = procedure(aFollower: TBoldFollower; Subscriber: TBoldSubscriber) of object; + TBoldEnsureFetched = procedure (List: TBoldObjectList; Expression: TBoldExpression) of object; TBoldStartDrag = procedure (Element: TBoldElement; DragMode: TBoldDragMode; RendererData: TBoldRendererData) of object; TBoldEndDrag = procedure (DragMode: TBoldDragMode; InternalDrag: Boolean) of object; TBoldDragOver = function (Element: TBoldElement; DropMode: TBoldDropMode; InternalDrag: Boolean; RendererData: TBoldRendererData; dropindex: Integer): Boolean of object; TBoldDragDrop = procedure (Element: TBoldElement; DropMode: TBoldDropMode; dropindex: Integer) of object; + TBoldValidateCharacter = function (AFollower: TBoldFollower; C: Char): Boolean of object; TBoldRenderer = class(TBoldSubscribableComponentViaBoldElem) private @@ -91,7 +128,9 @@ TBoldRenderer = class(TBoldSubscribableComponentViaBoldElem) FOnHoldsChangedValue: TBoldHoldsChangedValue; FOnReleaseChangedValue: TBoldReleaseChangedValue; FOnSubscribe: TBoldSubscribe; + FOnEnsureFetched: TBoldEnsureFetched; FRepresentations: TStringList; + FOnValidateCharacter: TBoldValidateCharacter; function GetRepresentations: TStrings; procedure SetRepresentations(Value: TStrings); function StoreRepresentations: Boolean; @@ -100,12 +139,17 @@ TBoldRenderer = class(TBoldSubscribableComponentViaBoldElem) class function GetExpressionAsDirectElement(Element: TBoldElement; Expression: TBoldExpression; VariableList: TBoldExternalVariableList): TBoldElement; function GetRendererDataClass: TBoldRendererDataClass; virtual; function GetSupportsMulti: Boolean; virtual; + procedure DefaultHoldsChangedValue(aFollower: TBoldFollower); virtual; + procedure DefaultReleaseChangedValue(aFollower: TBoldFollower); virtual; + function DefaultMayModify(aFollower: TBoldFollower): Boolean; virtual; + function DefaultValidateCharacter(aFollower: TBoldFollower; C: Char): Boolean; virtual; procedure DefaultStartDrag(Element: TBoldElement; DragMode: TBoldDragMode; RendererData: TBoldRendererData); virtual; procedure DefaultEndDrag(DragMode: TBoldDragMode; InternalDrag: Boolean); virtual; function DefaultDragOver(Element: TBoldElement; DropMode: TBoldDropMode; InternalDrag: Boolean; RendererData: TBoldRendererData; dropindex: Integer): Boolean; virtual; procedure DefaultDragDrop(Element: TBoldElement; DropMode: TBoldDropMode; dropindex: Integer); virtual; procedure DrawOnCanvas(Follower: TBoldFollower; Canvas: TCanvas; Rect: TRect; Aligment: TAlignment; Margins: TPoint); virtual; - function HasEventOverrides: boolean; virtual; + function HasSetValueEventOverrides: boolean; virtual; + function ValidateCharacter(aFollower: TBoldFollower; C: Char): Boolean; virtual; function GetDefaultRepresentationStringList: TStringList; virtual; property OnStartDrag: TBoldStartDrag read FOnStartDrag write FOnStartDrag; property OnEndDrag: TBoldEndDrag read FOnEndDrag write FOnEndDrag; @@ -113,18 +157,17 @@ TBoldRenderer = class(TBoldSubscribableComponentViaBoldElem) property OnDragDrop: TBoldDragDrop read FOnDragDrop write FOnDragDrop; public destructor Destroy; override; - procedure Changed; - function DefaultMayModify(Element: TBoldElement; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList; Subscriber: TBoldSubscriber): Boolean; virtual; - procedure DefaultHoldsChangedValue(Element: TBoldElement; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList; Subscriber: TBoldSubscriber); virtual; - procedure DefaultReleaseChangedValue(Element: TBoldElement; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList;Subscriber: TBoldSubscriber); virtual; - function MayModify(Element: TBoldElement; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList; Subscriber: TBoldSubscriber): Boolean; virtual; - procedure HoldsChangedValue(Element: TBoldElement; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList; Subscriber: TBoldSubscriber); virtual; - procedure ReleaseChangedValue(Element: TBoldElement; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList; Subscriber: TBoldSubscriber); virtual; + procedure Assign(Source: TPersistent); override; + procedure Changed; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function MayModify(aFollower: TBoldFollower): Boolean; virtual; + procedure HoldsChangedValue(Follower: TBoldFollower); virtual; + procedure ReleaseChangedValue(Follower: TBoldFollower); virtual; procedure StartDrag(Element: TBoldElement; DragMode: TBoldDragMode; RendererData: TBoldRendererData); virtual; procedure EndDrag(DragMode: TBoldDragMode; InternalDrag: Boolean); virtual; function DragOver(Element: TBoldElement; DropMode: TBoldDropMode; InternalDrag: Boolean; RendererData: TBoldRendererData; dropindex: Integer): Boolean; virtual; procedure DragDrop(Element: TBoldElement; DropMode: TBoldDropMode; dropindex: Integer); virtual; - procedure SubscribeToElement(Element: TBoldElement; Representation: TBoldRepresentation; Expression: TBoldExpression; Subscriber: TBoldSubscriber; VariableList: TBoldExternalVariableList = nil); + procedure SubscribeToElement(aFollower: TBoldFollower); + procedure EnsureFetched(List: TBoldObjectList; BoldType: TBoldClassTypeInfo; Expression: TBoldExpression); property RendererDataClass: TBoldRendererDataClass read GetRendererDataClass; property SupportsMulti: Boolean read GetSupportsMulti; published @@ -133,6 +176,8 @@ TBoldRenderer = class(TBoldSubscribableComponentViaBoldElem) property OnHoldsChangedValue: TBoldHoldsChangedValue read FOnHoldsChangedValue write FOnHoldsChangedValue; property OnReleaseChangedValue: TBoldReleaseChangedValue read FOnReleaseChangedValue write FOnReleaseChangedValue; property OnSubscribe: TBoldSubscribe read FOnSubscribe write SetOnSubscribe; + property OnEnsureFetched: TBoldEnsureFetched read FOnEnsureFetched write FOnEnsureFetched; + property OnValidateCharacter: TBoldValidateCharacter read FOnValidateCharacter write FOnValidateCharacter; end; { TBoldFollower } @@ -140,56 +185,69 @@ TBoldFollower = class(TBoldQueueable) private fIndex: Integer; fOwningFollower: TBoldFollower; -// fSelected: Boolean; fState: TBoldFollowerState; fElement: TBoldElement; fRendererData: TBoldRendererData; fController: TBoldFollowerController; fControlData: TObject; FSubscriber: TBoldSubscriber; - function GetActive: Boolean; + FIndirectElement: TBoldIndirectElement; + function GetActive: Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure SetActive(Value: Boolean); - function GetElementValid: Boolean; + function GetElementValid: Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure SetElementValid(Value: Boolean); - function GetSubFollower(index: Integer): TBoldFollower; - function GetSubFollowerCount: Integer; - function GetCurrentIndex: Integer; + function GetSubFollower(index: Integer): TBoldFollower; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetEnsuredSubFollower(Index: Integer): TBoldFollower; + function GetSubFollowerCount: Integer; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetCurrentIndex: Integer; {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure SetCurrentIndex(index: integer); - procedure SetElement(theElement: TBoldElement); - procedure SetState(Value: TBoldFollowerState); - function GetRendererData: TBoldRendererData; - procedure CollectMatchingDownwards(Followers: TBoldObjectArray; MatchController: TBoldFollowerController); - function GetAssertedController: TBoldFollowerController; + procedure SetElement(AElement: TBoldElement); + procedure SetState(AValue: TBoldFollowerState); + function GetRendererData: TBoldRendererData; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function CollectMatchingDownwards(Followers: TBoldFollowerArray; MatchController: TBoldFollowerController): TBoldFollowerArray; + function GetAssertedController: TBoldFollowerController; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetCurrentSubFollower: TBoldFollower; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetIsDirty: Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetValue: TBoldElement; + function GetSubFollowerAssigned(index: Integer): boolean; protected + function GetDebugInfo: string; override; procedure AddToDisplayList; override; procedure Receive(Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent); - {The following two are virtual to allow overriden in the old hierarchy} - procedure MakeUptoDateAndSubscribe; // Displays, i.e. moves from B.O. to RendereData, also resubscribes if needed - class procedure MultiMakeUptodateAndSubscribe(Followers: TBoldObjectArray); - procedure MakeClean; // Applies, i.e. moves from rendererdata to B.O. + procedure MakeUptodateAndSubscribe; + class procedure MultiMakeUptodateAndSubscribe(Followers: TBoldFollowerArray); + procedure MakeClean; {State handling} procedure MarkDirty; - procedure MarkClean; - procedure CollectMatching(Followers: TBoldObjectArray; MatchController: TBoldFollowerController); + procedure MarkClean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure MarkEnsured; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function CollectMatching(MatchController: TBoldFollowerController): TBoldFollowerArray; + function CollectMatchingSiblings(WindowSize: Integer): TBoldFollowerArray; + property Ensured: Boolean index befFollowerEnsured read GetElementFlag write SetElementFlag; public constructor Create(MatchObject: TObject; Controller: TBoldFollowerController); constructor CreateSubFollower( OwningFollower: TBoldFollower; - Controller: TBoldFollowerController; - Element: TBoldElement); + aController: TBoldFollowerController; + aElement: TBoldElement; + aActive: boolean; + aIndex: integer); destructor Destroy; override; + procedure SetElementAndMakeCurrent(AElement: TBoldElement; AActive: boolean); procedure Display; override; procedure Apply; override; procedure MarkValueOutOfDate; procedure MarkSubscriptionOutOfDate; function CheckIfInHierarchy(aElement: TBoldElement; aController: TBoldFollowerController): Boolean; - procedure ControlledValueChanged(IsChanged: Boolean); + procedure ControlledValueChanged; procedure DiscardChange; override; - function Displayable: Boolean; + function Displayable: Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure EnsureDisplayable; function ExistInOwner: Boolean; - function MayChange: Boolean; + function MayChange: Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function MayModify: Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure EnsureMulti; + procedure EnsureSiblings; property Active: Boolean read GetActive write SetActive; property ElementValid: Boolean read GetElementValid write SetElementValid; property Controller: TBoldFollowerController read fController; @@ -201,10 +259,16 @@ TBoldFollower = class(TBoldQueueable) property OwningFollower: TBoldFollower read FOwningFollower; property RendererData: TBoldRendererData read GetRendererData; property State: TBoldFollowerState read fState; + property IsDirty: boolean read GetIsDirty; property Selected: Boolean index befFollowerSelected read GetElementFlag write SetElementFlag; + property ResultElementOutOfDate: Boolean index befFollowerResultElementOutOfDate read GetElementFlag write SetElementFlag; property SubFollowerCount: Integer read GetSubFollowerCount; property SubFollowers[index: Integer]: TBoldFollower read GetSubFollower; + property SubFollowerAssigned[index: Integer]: boolean read GetSubFollowerAssigned; + property CurrentSubFollower : TBoldFollower read GetCurrentSubFollower; + property EnsuredSubFollowers[Index: Integer]: TBoldFollower read GetEnsuredSubFollower; property Subscriber: TBoldSubscriber read fSubscriber; + property Value: TBoldElement read GetValue; end; { TBoldFollowerController } @@ -225,14 +289,15 @@ TBoldFollowerController = class(TBoldSubscribablePersistent) fComponentSubscriber: TBoldPassthroughSubscriber; FOnGetContextType: TBoldGetContextTypeEvent; fVariables: TBoldOclVariables; + fApplyException: TBoldApplyExceptionEvent; + fDisplayException: TBoldDisplayExceptionEvent; procedure _Receive(Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent); - function GetRendererDataClass: TBoldRendererDataClass; + function GetRendererDataClass: TBoldRendererDataClass; {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure SetRepresentation(Value: TBoldRepresentation); - procedure SetExpression(Value: string); + procedure SetExpression(const Value: string); procedure SetUntypedRenderer(NewRender: TBoldRenderer); procedure SetVariables(const Value: TBoldOclVariables); procedure Resubscribe; - function GetVariableList: TBoldExternalVariableList; function GetSupportsMulti: Boolean; function HandleApplyException(E: Exception; Elem: TBoldElement; var Discard: Boolean): Boolean; function HandleDisplayException(E: Exception; Elem: TBoldElement): Boolean; @@ -240,19 +305,19 @@ TBoldFollowerController = class(TBoldSubscribablePersistent) function GetOwner: TPersistent; override; function GetEffectiveRenderer: TBoldRenderer; virtual; function GetContextType: TBoldElementTypeInfo; virtual; + function GetVariableList: TBoldExternalVariableList; virtual; procedure DoMakeUptodateAndSubscribe(Follower: TBoldFollower; Subscribe: Boolean); virtual; - procedure DoMultiMakeUptodateAndSubscribe(Followers: TBoldObjectArray); virtual; - procedure Changed; + procedure DoMultiMakeUptodateAndSubscribe(Followers: TBoldFollowerArray); virtual; + procedure Changed; {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure DoAssign(Source: TPersistent); virtual; + function DoApplyException(E: Exception; Elem: TBoldElement; var Discard: Boolean): Boolean; + function DoDisplayException(E: Exception; Elem: TBoldElement): Boolean; procedure CleanRendererData(RendererData: TBoldRendererData); virtual; - procedure MultiMakeEnsure(Followers: TBoldObjectArray); + procedure MultiMakeEnsure(Followers: TBoldFollowerArray); function GetSupportsMultiEnsure: Boolean; virtual; property EffectiveRenderer: TBoldRenderer read GetEffectiveRenderer; property RendererDataClass: TBoldRendererDataClass read GetRendererDataClass; - property OwningComponent: TComponent read FOwningComponent; property InternalDrag: Boolean read FInternalDrag write FInternalDrag; - property Representation: TBoldRepresentation read FRepresentation write SetRepresentation default brDefault; - property Expression: TBoldExpression read FExpression write SetExpression nodefault; property UntypedRenderer: TBoldRenderer read fUntypedRenderer write SetUntypedRenderer; property Variables: TBoldOclVariables read fVariables write SetVariables; public @@ -260,20 +325,22 @@ TBoldFollowerController = class(TBoldSubscribablePersistent) destructor Destroy; override; procedure Assign(Source: TPersistent); override; procedure MakeClean(Follower: TBoldFollower); virtual; - function MayModify(Follower: TBoldFollower): Boolean; - procedure HoldsChangedValue(Follower: TBoldFollower); - procedure ReleaseChangedValue(Follower: TBoldFollower); + function MayModify(Follower: TBoldFollower): Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure HoldsChangedValue(Follower: TBoldFollower); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure ReleaseChangedValue(Follower: TBoldFollower); {$IFDEF BOLD_INLINE} inline; {$ENDIF} function GetVariableListAndSubscribe(Subscriber: TBoldSubscriber): TBoldExternalVariableList; procedure StartDrag(Follower: TBoldFollower); procedure EndDrag; - procedure MakeUptodateAndSubscribe(Follower: TBoldFollower; Subscribe: Boolean); - procedure SubscribeToElement(Element: TBoldElement; Subscriber: TBoldSubscriber); - procedure MultiMakeUptodateAndSubscribe(Followers: TBoldObjectArray); + procedure MakeUptodateAndSubscribe(aFollower: TBoldFollower; Subscribe: Boolean); + procedure SubscribeToElement(aFollower: TBoldFollower); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure MultiMakeUptodateAndSubscribe(Followers: TBoldFollowerArray); function DragOver(Follower: TBoldFollower; ReceivingElement: TBoldElement; dropindex: Integer): Boolean; virtual; procedure DragDrop(Follower: TBoldFollower; ReceivingElement: TBoldElement; dropindex: Integer); virtual; procedure DrawOnCanvas(Follower: TBoldFollower; Canvas: TCanvas; Rect: TRect; Alignment: TAlignment; Margins: TPoint); virtual; + function SubFollowersActive: boolean; virtual; + property OwningComponent: TComponent read FOwningComponent; property ApplyPolicy: TBoldApplyPolicy read FApplyPolicy write FApplyPolicy default bapExit; - property CleanOnEqual: Boolean read FCleanOnEqual write FCleanOnEqual default false; + property CleanOnEqual: Boolean read FCleanOnEqual write FCleanOnEqual default true; property Popup: TBoldPopup read FPopup write FPopup; {temporarily} property AfterMakeUptoDate: TBoldFollowerEvent read fAfterMakeUptoDate write fAfterMakeUptoDate; property BeforeMakeUptoDate: TBoldFollowerEvent read fBeforeMakeUptoDate write fBeforeMakeUptoDate; @@ -282,16 +349,19 @@ TBoldFollowerController = class(TBoldSubscribablePersistent) property VariableList: TBoldExternalVariableList read GetVariableList; property SupportsMulti: Boolean read GetSupportsMulti; property SupportsMultiEnsure : Boolean read GetSupportsMultiEnsure; + property Expression: TBoldExpression read FExpression write SetExpression nodefault; + property Representation: TBoldRepresentation read FRepresentation write SetRepresentation default brDefault; published - property DragMode: TBoldDragMode read FDragMode write FDragMode default bdgNone; - property DropMode: TBoldDropMode read FDropMode write FDropMode default bdpNone; - // property Popup: TBoldPopup read fPopup write fPopup; + property DragMode: TBoldDragMode read FDragMode write FDragMode default DefaultBoldDragMode; + property DropMode: TBoldDropMode read FDropMode write FDropMode default DefaultBoldDropMode; + property OnApplyException: TBoldApplyExceptionEvent read fApplyException write fApplyException; + property OnDisplayException: TBoldDisplayExceptionEvent read fDisplayException write fDisplayException; end; { TBoldSingleRenderer } TBoldSingleRenderer = class(TBoldRenderer) public - procedure MakeUptodateAndSubscribe(Element: TBoldElement; RendererData: TBoldRendererData; FollowerController: TBoldFollowerController; Subscriber: TBoldSubscriber); virtual; abstract; + procedure MakeUptodateAndSubscribe(aFollower: TBoldFollower; Subscriber: TBoldSubscriber); virtual; abstract; end; { TBoldSingleFollowerController } @@ -312,7 +382,7 @@ TBoldSingleFollowerController = class(TBoldFollowerController) { TBoldPopup } TBoldPopup = class(TPersistent) private - FEnable: Boolean; // FIXME notify owner of change here + FEnable: Boolean; FInsertNew: Boolean; FDelete: TBoldPopupDeleteType; FMove: Boolean; @@ -326,7 +396,7 @@ TBoldPopup = class(TPersistent) property Move: Boolean read FMove write FMove default False; end; -{$IFDEF BOLDCOMCLIENT} // List/InterfaceArray +{$IFDEF BOLDCOMCLIENT} type TBoldClientableList = TBoldInterfaceArray; @@ -343,12 +413,15 @@ implementation uses BoldExceptionHandlers, BoldGuiResourceStrings, -{$IFNDEF BOLDCOMCLIENT} // uses - BoldSystem, - BoldSystemRT, +{$IFNDEF BOLDCOMCLIENT} BoldGUI, {$ENDIF} - BoldGuard; +{$IFDEF SpanFetch} + AttracsSpanFetchManager, +{$ENDIF} + BoldGuard, + BoldListControlPack, + BoldDomainElement; const breVariablesRemoved = 42; @@ -360,7 +433,7 @@ implementation var DefaultRenderer: TBoldRenderer; -{$IFDEF BOLDCOMCLIENT} // BoldTestType +{$IFDEF BOLDCOMCLIENT} function BoldTestType(element: IUnknown; const TypeOrInterface: TGUID): Boolean; var Res: IUnknown; @@ -388,7 +461,7 @@ function TBoldRendererData.GetSubFollowerCount: Integer; function TBoldRendererData.GetSubFollower(index: Integer): TBoldFollower; begin - raise EBold.CreateFmt(sClassHasNoSubfollowers, [ClassName]); + raise EBold.CreateFmt('%s: This class has no subfollowers', [ClassName]); end; function TBoldRendererData.GetCurrentSubFollowerIndex: Integer; @@ -396,6 +469,12 @@ function TBoldRendererData.GetCurrentSubFollowerIndex: Integer; Result := -1; end; +function TBoldRendererData.GetEnsuredSubFollower( + Index: Integer): TBoldFollower; +begin + result := GetSubFollower(Index); +end; + { TBoldFollowerController } constructor TBoldFollowerController.Create(aOwningComponent: TComponent); @@ -404,16 +483,20 @@ constructor TBoldFollowerController.Create(aOwningComponent: TComponent); fComponentSubscriber := TBoldPassthroughSubscriber.Create(_Receive); FOwningComponent := aOwningComponent; FApplyPolicy := bapExit; - FDragMode := bdgNone; - FDropMode := bdpNone; + FDragMode := DefaultBoldDragMode; + FDropMode := DefaultBoldDropMode; FPopup := TBoldPopup.Create; FRepresentation := brDefault; + fCleanOnEqual := true; end; destructor TBoldFollowerController.Destroy; begin FreeAndNil(fComponentSubscriber); FreeAndNil(FPopup); + fBeforeMakeUptodate := nil; + fAfterMakeUptodate := nil; + fVariables := nil; inherited; end; @@ -425,6 +508,14 @@ procedure TBoldFollowerController.Assign(Source: TPersistent); inherited Assign(Source); end; +function TBoldFollowerController.DoApplyException(E: Exception; + Elem: TBoldElement; var Discard: Boolean): Boolean; +begin + result := false; + if Assigned(fApplyException) then + result := fApplyException(E, Elem, Discard); +end; + procedure TBoldFollowerController.DoAssign(Source: TPersistent); begin Assert(Source is TBoldFollowerController); @@ -440,21 +531,35 @@ procedure TBoldFollowerController.DoAssign(Source: TPersistent); UntypedRenderer := (TBoldFollowerController(Source).UntypedRenderer); end; -procedure TBoldFollowerController.MakeUptodateAndSubscribe(Follower: TBoldFollower; Subscribe: Boolean); +function TBoldFollowerController.DoDisplayException(E: Exception; + Elem: TBoldElement): Boolean; +begin + result := false; + if Assigned(fApplyException) then + result := fDisplayException(E, Elem); +end; + +procedure TBoldFollower.MarkClean; +begin + SetState(bfsCurrent); +end; + +procedure TBoldFollowerController.MakeUptodateAndSubscribe(aFollower: TBoldFollower; Subscribe: Boolean); begin if Assigned(BeforeMakeUptoDate) then - BeforeMakeUptoDate(Follower); + BeforeMakeUptoDate(aFollower); try - DoMakeUptodateAndSubscribe(Follower, Subscribe); + DoMakeUptodateAndSubscribe(aFollower, Subscribe); finally + aFollower.MarkClean; if Assigned(AfterMakeUptoDate) then - AfterMakeUptoDate(Follower); + AfterMakeUptoDate(aFollower); end; end; procedure TBoldFollowerController.MakeClean(Follower: TBoldFollower); begin - raise EBoldInternal.CreateFmt(sNotImplemented, [ClassName, 'MakeClean']); // do not localize + raise EBoldInternal.CreateFmt('%s.MakeClean not implemented', [ClassName]); end; procedure TBoldFollowerController.Changed; @@ -479,7 +584,64 @@ function TBoldFollowerController.GetEffectiveRenderer: TBoldRenderer; procedure TBoldFollowerController.DoMakeUptodateAndSubscribe(Follower: TBoldFollower; Subscribe: Boolean); begin - Follower.RendererData.MayModify := EffectiveRenderer.MayModify(Follower.Element, Representation, Expression, GetVariableListAndSubscribe(Follower.Subscriber), Follower.Subscriber); +end; + +function TBoldFollower.GetAssertedController: TBoldFollowerController; +begin + if not assigned(fController) then + raise EBold.CreateFmt('%s.GetAssertedController: Controller not assigned', [classname]); + result := fController; +end; + +function TBoldFollower.GetActive: Boolean; +begin + Result := not (State in [bfsInactiveValidElement, bfsInactiveInvalidElement]); +end; + +function TBoldFollower.GetElementValid: Boolean; +begin + Result := State <> bfsInactiveInValidElement; +end; + +function TBoldFollower.GetRendererData: TBoldRendererData; +begin + if not Active then + raise EBold.Create(SBoldInactiveFollowerNoRenderData); + if not Assigned(FRendererData) then + FRendererData := AssertedController.RendererDataClass.Create(Self); + Result := FRendererData; +end; + +function TBoldFollower.GetSubFollower(index: Integer): TBoldFollower; +begin + Result := RendererData.GetSubFollower(index); +end; + +function TBoldFollower.GetEnsuredSubFollower( + Index: Integer): TBoldFollower; +begin + Result := RendererData.GetEnsuredSubFollower(index); +end; + +function TBoldFollower.GetSubFollowerCount: Integer; +begin + if Active then + Result := RendererData.GetSubFollowerCount + else + result := 0 +end; + +function TBoldFollower.GetCurrentIndex: Integer; +begin + Result := RendererData.GetCurrentSubFollowerIndex; +end; + +function TBoldFollower.GetCurrentSubFollower: TBoldFollower; +begin + if CurrentIndex = -1 then + result := nil + else + Result := SubFollowers[CurrentIndex]; end; procedure TBoldFollowerController.StartDrag(Follower: TBoldFollower); @@ -520,13 +682,11 @@ procedure TBoldFollowerController.DragDrop(Follower: TBoldFollower; ReceivingEle except on E: Exception do begin - Discard := true; Handled := HandleApplyException(E, ReceivingElement, Discard); if Discard then Follower.DiscardChange; if not Handled then raise; - end; end; end; @@ -538,7 +698,7 @@ procedure TBoldFollowerController.DrawOnCanvas(Follower: TBoldFollower; Canvas: function TBoldFollowerController.MayModify(Follower: TBoldFollower): Boolean; begin - Result := Follower.RendererData.MayModify; + result := EffectiveRenderer.MayModify(Follower) end; procedure TBoldFollowerController.SetRepresentation(Value: TBoldRepresentation); @@ -550,7 +710,7 @@ procedure TBoldFollowerController.SetRepresentation(Value: TBoldRepresentation); end; end; -procedure TBoldFollowerController.SetExpression(Value: string); +procedure TBoldFollowerController.SetExpression(const Value: string); begin if Value <> Expression then begin @@ -571,12 +731,12 @@ procedure TBoldFollowerController.SetUntypedRenderer(NewRender: TBoldRenderer); procedure TBoldFollowerController.HoldsChangedValue(Follower: TBoldFollower); begin - EffectiveRenderer.HoldsChangedValue(Follower.Element, Representation, Expression, VariableList, Follower.Subscriber); + EffectiveRenderer.HoldsChangedValue(Follower); end; procedure TBoldFollowerController.ReleaseChangedValue(Follower: TBoldFollower); begin - EffectiveRenderer.ReleaseChangedValue(Follower.Element, Representation, Expression, VariableList, Follower.Subscriber); + EffectiveRenderer.ReleaseChangedValue(Follower); end; { TBoldSingleFollowerController } @@ -586,9 +746,9 @@ procedure TBoldSingleFollowerController.DoMakeUptodateAndSubscribe(Follower: TBo with EffectiveRenderer as TBoldSingleRenderer do begin if Subscribe then - MakeUptodateAndSubscribe(Follower.Element, Follower.RendererData, Self, Follower.Subscriber) + MakeUptodateAndSubscribe(Follower, Follower.Subscriber) else - MakeUptodateAndSubscribe(Follower.Element, Follower.RendererData, Self, nil); + MakeUptodateAndSubscribe(Follower, nil); end; end; @@ -614,7 +774,6 @@ procedure TBoldRenderer.SetRepresentations(Value: TStrings); end; function TBoldRenderer.StoreRepresentations: Boolean; - // Don't store the stringlist if it's empty or if it's equal to the default representation stringlist. begin Result := False; if Assigned(FRepresentations) and (FRepresentations.Count > 0) then @@ -630,11 +789,18 @@ class function TBoldRenderer.GetExpressionAsDirectElement(Element: TBoldElement; begin Result := nil; if Assigned(Element) then - {$IFDEF BOLDCOMCLIENT} // GetAsDirectElement // FIXME: VariableList is lost - Result := Element.EvaluateExpression(Expression); - {$ELSE} - Result := Element.EvaluateExpressionAsDirectElement(Expression, VariableList); - {$ENDIF} + begin + if Expression = '' then + begin + Result := Element; + end + else + {$IFDEF BOLDCOMCLIENT} + Result := Element.EvaluateExpression(Expression); + {$ELSE} + Result := Element.EvaluateExpressionAsDirectElement(Expression, VariableList); + {$ENDIF} + end; end; function TBoldRenderer.GetRendererDataClass: TBoldRendererDataClass; @@ -658,62 +824,111 @@ function TBoldRenderer.GetDefaultRepresentationStringList: TStringList; end; end; -function TBoldRenderer.DefaultMayModify(Element: TBoldElement; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList; Subscriber: TBoldSubscriber): Boolean; +function TBoldRenderer.DefaultMayModify(aFollower: TBoldFollower): Boolean; + + function CheckPessimisticLocking(AElement: TBoldDomainElement): boolean; + var + BoldSystem: TBoldSystem; + begin + result := true; + BoldSystem := TBoldDomainElement(AElement).BoldSystem as TBoldSystem; + if Assigned(BoldSystem) and Assigned(BoldSystem.PessimisticLockHandler) then + result := BoldSystem.PessimisticLockHandler.LockElement(AElement); + end; + var ValueElement: TBoldElement; begin - ValueElement := GetExpressionAsDirectElement(Element, Expression, VariableList); + ValueElement := aFollower.Value; if Assigned(ValueElement) then - {$IFDEF BOLDCOMCLIENT} // DefaultMayModify // fixme - result := ValueElement.mutable + begin + {$IFDEF BOLDCOMCLIENT} + result := ValueElement.mutable; {$ELSE} - Result := ValueElement.ObserverMayModify(Subscriber) + Result := ValueElement.ObserverMayModify(aFollower.Subscriber); {$ENDIF} + if (ValueElement is TBoldDomainElement) then + result := result and CheckPessimisticLocking(ValueElement as TBoldDomainElement); + end else Result := False; end; -procedure TBoldRenderer.DefaultHoldsChangedValue(Element: TBoldElement; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList; Subscriber: TBoldSubscriber); -{$IFNDEF BOLDCOMCLIENT} // DefaultHoldsChangedValue +procedure TBoldRenderer.DefaultHoldsChangedValue(aFollower: TBoldFollower); +{$IFNDEF BOLDCOMCLIENT} var ValueElement: TBoldElement; begin - ValueElement := GetExpressionAsDirectElement(Element, Expression, VariableList); + ValueElement := aFollower.Value; if Assigned(ValueElement) then - ValueElement.RegisterModifiedValueHolder(Subscriber) - else - raise EBold.CreateFmt(sCannotModifyValue, [ClassName]); + ValueElement.RegisterModifiedValueHolder(aFollower.Subscriber) end; {$ELSE} begin end; {$ENDIF} -procedure TBoldRenderer.DefaultReleaseChangedValue(Element: TBoldElement; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList; Subscriber: TBoldSubscriber); -{$IFNDEF BOLDCOMCLIENT} // defaultReleaseChangedValue +procedure TBoldRenderer.DefaultReleaseChangedValue(aFollower: TBoldFollower); +{$IFNDEF BOLDCOMCLIENT} var ValueElement: TBoldElement; begin - ValueElement := GetExpressionAsDirectElement(Element, Expression, VariableList); + ValueElement := aFollower.Value; if Assigned(ValueElement) then - ValueElement.UnRegisterModifiedValueHolder(Subscriber) + ValueElement.UnRegisterModifiedValueHolder(aFollower.Subscriber) end; {$ELSE} begin end; {$ENDIF} -function TBoldRenderer.MayModify(Element: TBoldElement; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList; Subscriber: TBoldSubscriber): Boolean; +function TBoldRenderer.MayModify(aFollower: TBoldFollower): Boolean; begin - if Assigned(FOnMayModify) and - Assigned(Element) then - Result := OnMayModify(Element, Representation, Expression, Subscriber) - else if HasEventOverrides then - // this forces readonly of renderers that has an OnSubscribeEvent but no OnMayModify - // OnMayModify is mandatory for a writeable renderer. - result := false + if Assigned(aFollower.Value) then + begin + Result := aFollower.Value.ObserverMayModify(aFollower.Subscriber); + if not result then + Result := HasSetValueEventOverrides and + ((aFollower.Value.ModifiedValueHolder = nil) or (aFollower.Value.ModifiedValueHolder = aFollower.Subscriber)); + end + else + Result := HasSetValueEventOverrides; + if Assigned(FOnMayModify) then + Result := Result and OnMayModify(aFollower) else - Result := DefaultMayModify(Element, Representation, Expression, VariableList, Subscriber) + Result := Result and HasSetValueEventOverrides or DefaultMayModify(aFollower); +end; + +procedure TBoldRenderer.EnsureFetched(List: TBoldObjectList; BoldType: TBoldClassTypeInfo; Expression: TBoldExpression); +{$IFNDEF SpanFetch} +var + ListType: TBoldListTypeInfo; + RealObjectList: TBoldObjectList; + ie: TBoldIndirectElement; + i: Integer; +{$ENDIF} +begin + if assigned(FOnEnsureFetched) then + FOnEnsureFetched(List, expression) + else if Expression <> '' then + {$IFDEF SpanFetch} + FetchOclSpan(List, Expression); + {$ELSE} + if (List.Count > 1) then + begin + try + List.EnsureObjects; + ListType := BoldType.ListTypeInfo; + RealObjectlist := TBoldMemberFactory.CreateMemberFromBoldType(ListType) as TBoldObjectList; + RealObjectList.AddList(List); + ie := TBoldIndirectElement.Create; + RealObjectList.EvaluateExpression('self->collect(' + Expression + ')', ie); + finally + FreeAndNil(RealObjectList); + FreeAndNil(ie); + end; + end; +{$ENDIF} end; function TBoldRenderer.GetSupportsMulti: Boolean; @@ -721,29 +936,29 @@ function TBoldRenderer.GetSupportsMulti: Boolean; Result := false; end; -procedure TBoldRenderer.HoldsChangedValue(Element: TBoldElement; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList; Subscriber: TBoldSubscriber); +procedure TBoldRenderer.HoldsChangedValue(Follower: TBoldFollower); begin if Assigned(FOnHoldsChangedValue) then - OnHoldsChangedValue(Element, Representation, Expression, Subscriber) + OnHoldsChangedValue(Follower) else - DefaultHoldsChangedValue(Element, Representation, Expression, VariableList, Subscriber) + DefaultHoldsChangedValue(Follower) end; -procedure TBoldRenderer.ReleaseChangedValue(Element: TBoldElement; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList; Subscriber: TBoldSubscriber); +procedure TBoldRenderer.ReleaseChangedValue(Follower: TBoldFollower); begin if Assigned(FOnReleaseChangedValue) then - OnReleaseChangedValue(Element, Representation, Expression, Subscriber) + OnReleaseChangedValue(Follower) else - DefaultReleaseChangedValue(Element, Representation, Expression, VariableList, Subscriber) + DefaultReleaseChangedValue(Follower) end; procedure TBoldRenderer.DefaultStartDrag(Element: TBoldElement; DragMode: TBoldDragMode; RendererData: TBoldRendererData); -{$IFNDEF BOLDCOMCLIENT} // DragDrop +{$IFNDEF BOLDCOMCLIENT} var Obj: TBoldObject; -{$ENDIF} +{$ENDIF} begin - {$IFNDEF BOLDCOMCLIENT} // DragDrop + {$IFNDEF BOLDCOMCLIENT} if BoldGUIHandler.DraggedObjects.Count <> 0 then raise EBold.Create(SDraggedObjectsNotCleared); @@ -762,16 +977,27 @@ procedure TBoldRenderer.DefaultStartDrag(Element: TBoldElement; DragMode: TBoldD {$ENDIF} end; +function TBoldRenderer.DefaultValidateCharacter(aFollower: TBoldFollower; C: Char): Boolean; +var + ValueElement: TBoldElement; +begin + ValueElement := aFollower.Value; + if Assigned(ValueElement) then + Result := ValueElement.ValidateCharacter(C, aFollower.AssertedController.Representation) + else + Result := True; +end; + procedure TBoldRenderer.DefaultEndDrag(DragMode: TBoldDragMode; InternalDrag: Boolean); begin - {$IFNDEF BOLDCOMCLIENT} // dragdrop + {$IFNDEF BOLDCOMCLIENT} BoldGUIHandler.DraggedObjects.Clear; {$ENDIF} end; function TBoldRenderer.DefaultDragOver(Element: TBoldElement; DropMode: TBoldDropMode; InternalDrag: Boolean; RendererData: TBoldRendererData; dropindex: Integer): Boolean; begin - {$IFDEF BOLDCOMCLIENT} // dragdrop + {$IFDEF BOLDCOMCLIENT} result := false; {$ELSE} Result := Assigned(Element) and Element.ObserverMayModify(Self) and @@ -781,7 +1007,7 @@ function TBoldRenderer.DefaultDragOver(Element: TBoldElement; DropMode: TBoldDro end; procedure TBoldRenderer.DefaultDragDrop(Element: TBoldElement; DropMode: TBoldDropMode; dropindex: Integer); -{$IFNDEF BOLDCOMCLIENT} // dragdrop +{$IFNDEF BOLDCOMCLIENT} var i: integer; offset, @@ -789,17 +1015,18 @@ procedure TBoldRenderer.DefaultDragDrop(Element: TBoldElement; DropMode: TBoldDr BoldObject: TBoldObject; TheLink: TBoldObjectReference; TheList: TBoldObjectList; + DraggedObjects: TBoldObjectList; begin + DraggedObjects := BoldGUIHandler.DraggedObjects; if element is TBoldObjectReference then begin TheLink := Element as TBoldObjectReference; - with BoldGUIHandler.DraggedObjects do - if Count = 0 then - BoldObject := nil - else if Count = 1 then - BoldObject := BoldObjects[0] - else - raise EBold.Create(SCannotDragOverMultipleObjects); + if DraggedObjects.Count = 0 then + BoldObject := nil + else if DraggedObjects.Count = 1 then + BoldObject := DraggedObjects[0] + else + raise EBold.Create(SCannotDragOverMultipleObjects); case DropMode of bdpInsert, bdpAppend: if Assigned(TheLink.BoldObject) and Assigned(BoldObject) then @@ -815,25 +1042,25 @@ procedure TBoldRenderer.DefaultDragDrop(Element: TBoldElement; DropMode: TBoldDr TheList := Element as TBoldObjectlist; case DropMode of bdpAppend: - for i := 0 to BoldGUIHandler.DraggedObjects.Count - 1 do - if TheList.IndexOf(BoldGUIHandler.DraggedObjects[I]) = -1 then - TheList.Add(BoldGUIHandler.DraggedObjects[i]); + for i := 0 to DraggedObjects.Count - 1 do + if TheList.IndexOf(DraggedObjects[I]) = -1 then + TheList.Add(DraggedObjects[i]); bdpReplace: - raise EBoldFeatureNotImplementedYet.CreateFmt(sReplaceNotImplemented, [ClassName]); + raise EBoldFeatureNotImplementedYet.CreateFmt('%s.DefaultDragDrop: Replace not implemented yet', [ClassName]); bdpInsert: begin if dropindex < 0 then dropindex := 0; - for I := 0 to BoldGUIHandler.DraggedObjects.Count - 1 do + for I := 0 to DraggedObjects.Count - 1 do begin - prevIndex := TheList.IndexOf(BoldGUIHandler.DraggedObjects[I]); + prevIndex := TheList.IndexOf(DraggedObjects[I]); Offset := 0; if prevIndex = -1 then begin if dropindex < TheList.Count then - TheList.Insert(dropindex + Offset, BoldGUIHandler.DraggedObjects[I]) + TheList.Insert(dropindex + Offset, DraggedObjects[I]) else - TheList.Add(BoldGUIHandler.DraggedObjects[I]); + TheList.Add(DraggedObjects[I]); INC(dropindex); end else @@ -876,16 +1103,27 @@ function TBoldRenderer.DragOver(Element: TBoldElement; DropMode: TBoldDropMode; Result := DefaultDragOver(Element, DropMode, InternalDrag, RendererData, dropindex) end; -procedure TBoldRenderer.SubscribeToElement(Element: TBoldElement; Representation: TBoldRepresentation; Expression: TBoldExpression; Subscriber: TBoldSubscriber; VariableList: TBoldExternalVariableList = nil); +procedure TBoldRenderer.SubscribeToElement(aFollower: TBoldFollower); begin - if assigned(fOnSubscribe) then - fOnSubscribe(element, representation, expression, subscriber) - else if assigned(Element) then - {$IFDEF BOLDCOMCLIENT} - Element.SubscribeToExpression(Expression, Subscriber.ClientId, Subscriber.SubscriberId, False, false); - {$ELSE} - Element.SubscribeToExpression(expression, subscriber, false, false, variableList); - {$ENDIF} + if Assigned(aFollower.Element) then + begin + if assigned(fOnSubscribe) then + fOnSubscribe(aFollower, aFollower.Subscriber) + else + {$IFDEF BOLDCOMCLIENT} + Element.SubscribeToExpression(Expression, Subscriber.ClientId, Subscriber.SubscriberId, False, false); + {$ELSE} + aFollower.Element.SubscribeToExpression(aFollower.AssertedController.Expression, aFollower.subscriber, false, false, aFollower.Controller.GetVariableListAndSubscribe(aFollower.subscriber)); + {$ENDIF} + end; +end; + +function TBoldRenderer.ValidateCharacter(aFollower: TBoldFollower; C: Char): Boolean; +begin + if Assigned(FOnValidateCharacter) then + Result := OnValidateCharacter(aFollower, C) + else + Result := DefaultValidateCharacter(aFollower, C); end; procedure TBoldRenderer.DragDrop(Element: TBoldElement; DropMode: TBoldDropMode; dropindex: Integer); @@ -900,41 +1138,98 @@ procedure TBoldRenderer.DrawOnCanvas(Follower: TBoldFollower; Canvas: TCanvas; R begin end; -function TBoldRenderer.HasEventOverrides: boolean; +function TBoldRenderer.HasSetValueEventOverrides: boolean; begin - result := assigned(fOnSubscribe); + result := false; end; { TBoldFollower } +procedure TBoldFollower.SetElementAndMakeCurrent(AElement: TBoldElement; AActive: boolean); +begin + if {not assigned(AElement) or} (AElement <> fElement) then + begin + fElement := AElement; + if IsInDisplayList then + RemoveFromDisplayList(false); + if AActive then + begin + SetState(bfsActivating); + MakeUptodateAndSubscribe; + end + else + begin + if Assigned(fElement) then + fState := bfsInactiveValidElement + else + fState := bfsInactiveInvalidElement; + end; + end; +end; + constructor TBoldFollower.Create(MatchObject: TObject; Controller: TBoldFollowerController); begin - inherited Create(MatchObject); + inherited Create(BoldGuiHandler.FindHostingForm(MatchObject as TComponent)); Assert(assigned(Controller)); fController := Controller; fSubscriber := TBoldFollowerSubscriber.Create(Self); + fIndirectElement := TBoldIndirectElement.Create; + ResultElementOutOfDate := true; fIndex := -1; end; constructor TBoldFollower.CreateSubFollower(OwningFollower: TBoldFollower; - Controller: TBoldFollowerController; - Element: TBoldElement); + aController: TBoldFollowerController; + aElement: TBoldElement; + aActive: boolean; + aIndex: integer); + begin + Assert(assigned(aController)); inherited Create(OwningFollower.MatchObject); FOwningFollower := OwningFollower; PrioritizedQueuable := OwningFollower; - Assert(assigned(Controller)); - fController := Controller; + fController := aController; fSubscriber := TBoldFollowerSubscriber.Create(Self); - fElement := Element; - fIndex := -1; - MarkSubscriptionOutOfDate; + fIndirectElement := TBoldIndirectElement.Create; + fElement := aElement; + fIndex := aIndex; + ResultElementOutOfDate := true; + if aActive {and not PrioritizedQueuable.IsInDisplayList} and // check MostPrioritizedQueuable instead of PrioritizedQueuable ? + not ((aController is TBoldAsFollowerListController) and TBoldAsFollowerListController(aController).PrecreateFollowers) then + begin + fState := bfsActivating; + MakeUptodateAndSubscribe; + end + else + if aActive then + begin +// MarkSubscriptionOutOfDate + fState := bfsSubscriptionOutOfDate; + AddToDisplayList; + if Assigned(fElement) then + fElement.AddSubscription(Subscriber, beDestroying, beDestroying); + end + else + begin + if Assigned(fElement) then + fState := bfsInactiveValidElement + else + fState := bfsInactiveInvalidElement; + if Assigned(fElement) then + fElement.AddSubscription(Subscriber, beDestroying, beDestroying); + end; end; destructor TBoldFollower.Destroy; begin + FreeAndNil(FIndirectElement); FreeAndNil(FRendererData); FreeAndNil(fSubscriber); + fCOntroller := nil; + fControlData := nil; + fElement := nil; + fOwningFollower := nil; inherited; end; @@ -981,27 +1276,75 @@ function TBoldFollower.CheckIfInHierarchy(aElement: TBoldElement; aController: T end; end; -function TBoldFollower.GetSubFollower(index: Integer): TBoldFollower; +function TBoldFollower.GetIsDirty: Boolean; begin - Result := RendererData.GetSubFollower(index); + result := fState = bfsDirty; end; -function TBoldFollower.GetSubFollowerCount: Integer; -begin - if Active then - Result := RendererData.GetSubFollowerCount - else - result := 0 -end; +type + TBoldFlaggedObjectAccess = class(TBoldFlaggedObject); -function TBoldFollower.GetCurrentIndex: Integer; +procedure TBoldFollower.SetState(AValue: TBoldFollowerState); begin - Result := RendererData.GetCurrentSubFollowerIndex; + if not (fState in [bfsEmpty, bfsCurrent, bfsDirty, + bfsValueOutOfDate, bfsSubscriptionOutOfDate, + bfsInactiveValidElement, bfsInactiveInvalidElement, bfsActivating]) then + raise Exception.Create('TBoldFollower.SetState old state is ' + IntToStr(Integer(fState))); + {action when leaving state} + case State of + bfsValueOutOfDate, bfsSubscriptionOutOfDate: {bfsOutOfDate} + RemoveFromDisplayList(false); + bfsDirty: + begin + if not ResultElementOutOfDate and Assigned(fIndirectElement.Value) + and TBoldFlaggedObjectAccess(fIndirectElement.Value).GetElementFlag(befHasModifiedValueHolder) + and (fIndirectElement.Value.ModifiedValueHolder = Subscriber) then + AssertedController.ReleaseChangedValue(self); + RemoveFromApplyList; + end; + end; + + if AValue = bfsDirty then // process Dirty before changeing fState, since HoldsChangedValue can fail. + begin + AssertedController.HoldsChangedValue(Self); + AddToApplyList; + end; + + fState := AValue; + + {action when entering state} + case State of + bfsValueOutOfDate: + begin + AddToDisplayList; + Ensured := false; + ResultElementOutOfDate := true; + end; + bfsSubscriptionOutOfDate: + begin + AddToDisplayList; + Ensured := false; + Subscriber.CancelAllSubscriptions; + ResultElementOutOfDate := true; + end; + bfsInactiveValidElement, bfsInactiveInvalidElement: + begin + Subscriber.CancelAllSubscriptions; + FreeAndNil(fRendererData); + ResultElementOutOfDate := true; + if Assigned(fElement) then + Element.AddSubscription(Subscriber, beDestroying, beDestroying); + end; + bfsEmpty, bfsCurrent, bfsActivating, bfsDirty: + {no action} + else + raise EBoldInternal.CreateFmt('%s: Unknown FollowerState', [ClassName]); + end; end; -function TBoldFollower.GetActive: Boolean; +function TBoldFollower.GetSubFollowerAssigned(index: Integer): boolean; begin - Result := not (State in [bfsInactiveValidElement, bfsInactiveInvalidElement]); + result := Active and RendererData.GetSubFollowerAssigned(Index); end; procedure TBoldFollower.SetActive(Value: Boolean); @@ -1012,8 +1355,7 @@ procedure TBoldFollower.SetActive(Value: Boolean); begin Assert(State <> bfsInactiveInvalidElement); SetState(bfsActivating); - MakeUptodateAndSubscribe; //CHECKME This could cause errors if an owning follower is in bfsOutOfDate - MarkClean; + MakeUptodateAndSubscribe; end else if (State <> bfsDirty) then @@ -1021,30 +1363,33 @@ procedure TBoldFollower.SetActive(Value: Boolean); end; end; -function TBoldFollower.GetElementValid: Boolean; +function TBoldFollower.GetValue: TBoldElement; begin - Result := State <> bfsInactiveInValidElement; + if ResultElementOutOfDate then + begin + fIndirectElement.SetReferenceValue(nil); + if {ElementValid and} Assigned(Element) then + try + ResultElementOutOfDate := false; + Element.EvaluateAndSubscribeToExpression(Controller.Expression, Subscriber, FIndirectElement, false, false, Controller.GetVariableListAndSubscribe(Subscriber)); + except + // perhaps raise exception + end; + if (state = bfsInactiveValidElement) then + Active := true; + end; + result := fIndirectElement.Value; end; procedure TBoldFollower.SetElementValid(Value: Boolean); begin - Assert(not Active or value); - if value <> elementValid then - begin - if value then - SetState(bfsInactivevalidElement) - else - SetState(bfsInactiveInvalidElement); - end; -end; - -function TBoldFollower.GetRendererData: TBoldRendererData; -begin - if not Active then - raise EBold.Create(SBoldInactiveFollowerNoRenderData); - if not Assigned(FRendererData) then - FRendererData := AssertedController.RendererDataClass.Create(Self); - Result := FRendererData; + if value <> elementValid then + begin + if value then + SetState(bfsInactivevalidElement) + else + SetState(bfsInactiveInvalidElement); + end; end; function TBoldFollower.MayChange: Boolean; @@ -1055,6 +1400,11 @@ function TBoldFollower.MayChange: Boolean; Result := True; end; +function TBoldFollower.MayModify: Boolean; +begin + result := AssertedController.MayModify(self); +end; + procedure TBoldFollower.DiscardChange; begin if State = bfsDirty then @@ -1067,9 +1417,9 @@ procedure TBoldFollower.DiscardChange; procedure TBoldFollower.Receive(Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent); begin -{$IFNDEF BOLDCOMCLIENT} // CHECKME +{$IFNDEF BOLDCOMCLIENT} if (OriginalEvent = beDestroying) and (Originator = Element) then - FElement := nil; //CHECKME Is this necesary? /frha + FElement := nil; {$ENDIF} case RequestedEvent of breReEvaluate: @@ -1080,6 +1430,7 @@ procedure TBoldFollower.Receive(Originator: TObject; OriginalEvent: TBoldEvent; begin if OriginalEvent = beDestroying then begin + RemoveFromDisplayList(false); if assigned(fRendererData) then AssertedController.CleanRendererData(fRendererData); FreeAndNil(fRendererData); @@ -1088,9 +1439,9 @@ procedure TBoldFollower.Receive(Originator: TObject; OriginalEvent: TBoldEvent; if Assigned(FRendererData) and not (FRendererData is AssertedController.RendererDataClass) then FreeAndNil(fRendererData); MarkSubscriptionOutOfDate; + if OriginalEvent <> beDestroying then + AssertedController.AddSmallSubscription(Subscriber, [beValueChanged, beDestroying], breControllerChanged); end; - else - raise EBoldInternal.CreateFmt(sUnknownRequestedEvent, [Classname, RequestedEvent]); end; end; @@ -1100,8 +1451,14 @@ procedure TBoldFollower.MakeUptodateAndSubscribe; begin Subscriber.CancelAllSubscriptions; AssertedController.AddSmallSubscription(Subscriber, [beValueChanged, beDestroying], breControllerChanged); - end; - AssertedController.MakeUptodateAndSubscribe(Self, State in bfdNeedResubscribe); + Controller.MakeUptodateAndSubscribe(Self, true); + if Assigned(Element) then + Element.AddSubscription(Subscriber, beDestroying, beDestroying); + if Assigned(Element) and (State in bfdNeedResubscribe) then + Controller.SubscribeToElement(self); + end + else + AssertedController.MakeUptodateAndSubscribe(Self, State in bfdNeedResubscribe); end; procedure TBoldFollower.MakeClean; @@ -1111,35 +1468,18 @@ procedure TBoldFollower.MakeClean; SetState(bfsSubscriptionOutOfDate); end; -procedure TBoldFollower.ControlledValueChanged(IsChanged: Boolean); +procedure TBoldFollower.ControlledValueChanged; begin - if IsChanged then + if (State <> bfsDirty) then begin - if (State <> bfsDirty) then - begin - AssertedController.HoldsChangedValue(Self); - MarkDirty; - end; - if AssertedController.ApplyPolicy = bapChange then - Apply; - end - else - begin - if (State = bfsDirty) and AssertedController.CleanOnEqual then - DiscardChange; + // if ApplyPolicy is bapChange and there are no events assigned for HoldsChangedValue and ReleaseChangedValue + // then there's no need to call HoldsChangedValue and ReleaseChangedValue + // no need to call Controller.HoldsChangedValue(Self); here as it will be called in SetState as a result of MarkDirty bellow + MarkDirty; end; -end; - -procedure TBoldFollower.SetElement(theElement: TBoldElement); -begin - // if the fElement is nil and the new element is nil aswell we still need - // to mark the follower out of date since other properties of the controller - // might have changed (especially the nilstringrepresentation) - if not assigned(theElement) or (theElement <> fElement) then + if AssertedController.ApplyPolicy = bapChange then begin - fElement := theElement; - ElementValid := true; - MarkSubscriptionOutOfDate; + Apply; end; end; @@ -1149,10 +1489,10 @@ procedure TBoldFollower.MarkValueOutOfDate; bfsEmpty, bfsCurrent, bfsDirty: SetState(bfsValueOutOfDate); bfsInactiveValidElement, bfsValueOutOfDate, - bfsSubscriptionOutOfDate, bfsActivating: // FIXME bfsActivating is a temporary fix for the delayd fetch problem + bfsSubscriptionOutOfDate, bfsActivating: {no action} else - raise EBoldInternal.CreateFmt(sFollowerStateError, [ClassName, 'MarkOutOfDate']); // do not localize + raise EBoldInternal.CreateFmt('%s.MarkOutOfDate: Follower state error', [ClassName]); end; end; @@ -1165,16 +1505,27 @@ procedure TBoldFollower.MarkSubscriptionOutOfDate; bfsSubscriptionOutOfDate, bfsActivating : {no action}; - // these two should not happen, but it is safe to ignore them - // a bug in the grid seems to cause these when the grid is not displayed - // right after creation (if it is on an invisible pagecontrol) + bfsInactiveValidElement, bfsInactiveInvalidElement: begin - // DebugCode below - can safely be removed SetState(State);{no action} end else - raise EBoldInternal.CreateFmt(sFollowerStateError, [ClassName, 'MarkSubscriptionOutOfDate']); + raise EBoldInternal.CreateFmt('%s.MarkSubscriptionOutOfDate: Follower state error', [ClassName]); + end; +end; + +procedure TBoldFollower.SetElement(AElement: TBoldElement); +begin + if not assigned(AElement) or (AElement <> fElement) then + begin + Assert(not (not ResultElementOutOfDate and Assigned(fIndirectElement.Value) + and TBoldFlaggedObjectAccess(fIndirectElement.Value).GetElementFlag(befHasModifiedValueHolder) + and (fIndirectElement.Value.ModifiedValueHolder = Subscriber))); + fElement := AElement; + ElementValid := true; + MarkSubscriptionOutOfDate; + ResultElementOutOfDate := true; end; end; @@ -1186,13 +1537,14 @@ procedure TBoldFollower.MarkDirty; bfsDirty: {no action} else - raise EBoldInternal.CreateFmt(sFollowerStateError, [Classname, 'MarkDirty']); + raise EBoldInternal.CreateFmt('%s.MarkDirty: Follower state error', [Classname]); end; end; -procedure TBoldFollower.MarkClean; + +procedure TBoldFollower.MarkEnsured; begin - SetState(bfsCurrent); + Ensured := true; end; function TBoldFollower.Displayable: Boolean; @@ -1200,72 +1552,25 @@ function TBoldFollower.Displayable: Boolean; Result := State in bfsDisplayable; end; -procedure TBoldFollower.SetState(Value: TBoldFollowerState); -begin - {action when leaving state} - case State of - bfsValueOutOfDate, bfsSubscriptionOutOfDate: {bfsOutOfDate} - RemoveFromDisplayList; - bfsDirty: - RemoveFromApplyList; - end; - - fState := Value; - - {action when entering state} - case State of - bfsValueOutOfDate: - AddToDisplayList; - bfsSubscriptionOutOfDate: - begin - AddToDisplayList; - Subscriber.CancelAllSubscriptions; - end; - bfsDirty: - begin - AssertedController.HoldsChangedValue(Self); - AddToApplyList; - end; - bfsInactiveValidElement, bfsInactiveInvalidElement: - begin - Subscriber.CancelAllSubscriptions; - FreeAndNil(fRendererData); - end; - bfsEmpty, bfsCurrent, bfsActivating: - {no action} - else - raise EBoldInternal.CreateFmt('%s: Unknown FollowerState', [ClassName]); - end; -end; - procedure TBoldFollower.Display; procedure DisplaySelf; begin - try +{.$IFNDEF BoldQueue_Optimization} +// This check is already done in Queue.DisplayOne, so it only serves to protect direct calls to Display. That shouldn't be done anyway. if (MostPrioritizedQueuable <> nil) then - raise EBold.CreateFmt(sCannotDisplayInThisOrder, [ClassName]); + raise EBold.CreateFmt('%s.Display: Can not display because there is an owning follower that must be displayed before', [ClassName]); +{.$ENDIF} MakeUptodateAndSubscribe; - finally - MarkClean; - end; end; procedure DisplayMulti; var - i: integer; - Followers: TBoldObjectArray; - BoldGuard: IBoldGuard; + Followers: TBoldFollowerArray; + F: TBoldFollower; begin - BoldGuard := TBoldGuard.Create(Followers); - Followers := TBoldObjectArray.Create(10, []); - CollectMatching(Followers, Controller); - if Followers.Count > 1 then - try - MultiMakeUptodateAndSubscribe(Followers); - finally - for i := 0 to Followers.Count - 1 do - TBoldFollower(Followers[i]).MarkClean; - end + Followers := CollectMatching( Controller); + if Length(Followers) > 1 then + MultiMakeUptodateAndSubscribe(Followers) else DisplaySelf; end; @@ -1278,12 +1583,11 @@ procedure TBoldFollower.Display; except on E: Exception do begin - if assigned(Controller) and Controller.HandleDisplayException(E, Element) then - // don't re-raise + if assigned(Controller) and not Controller.HandleDisplayException(E, Element) then else begin if assigned(Controller) then - E.message := Format(sDisplayError, [E.message, BOLDCRLF, Controller.GetNamePath]); + E.message := Format('%s' + BOLDCRLF + 'occured when displaying component %s', [E.message, Controller.GetNamePath]); raise; end; end; @@ -1292,29 +1596,46 @@ procedure TBoldFollower.Display; procedure TBoldFollower.EnsureMulti; var - Followers: TBoldObjectArray; + Followers: TBoldFollowerArray; BoldGuard: IBoldGuard; begin - BoldGuard := TBoldGuard.Create(Followers); - Followers := TBoldObjectArray.Create(10, []); - CollectMatching(Followers, Controller); + Followers := CollectMatching(Controller); - if Followers.Count > 1 then + if Length(Followers) > 1 then try Controller.MultiMakeEnsure(Followers); except - ; // silence any exceptions + ; + end +end; + +procedure TBoldFollower.EnsureSiblings; +var + Followers: TBoldFollowerArray; +begin + if (not Assigned(fOwningFollower)) and (not Ensured) then + begin + SetLength(Followers, 1); + Followers[0] := self; end + else + Followers := CollectMatchingSiblings(20); + if Length(Followers) > 0 then + try + Controller.MultiMakeEnsure(Followers); + except + ; + end + end; procedure TBoldFollower.EnsureDisplayable; -//EnsureDisplayable may only be called when within Display or when ALL owning followers not is in bfsOutOfDate! begin if not Displayable then begin Active := True; - MakeUptodateAndSubscribe; - MarkClean; + if not Displayable then + MakeUptodateAndSubscribe; end; RendererData.EnsureSubfollowersDisplayable; end; @@ -1322,7 +1643,7 @@ procedure TBoldFollower.EnsureDisplayable; procedure TBoldFollower.Apply; var Discard: Boolean; - Handled: Boolean; + Handled: Boolean; begin if State = bfsDirty then begin @@ -1332,11 +1653,13 @@ procedure TBoldFollower.Apply; except on E: Exception do begin - Discard := true; Handled := assigned(Controller) and Controller.HandleApplyException(E, Element, Discard); if Discard then - DiscardChange; - if not handled then + DiscardChange + else + if State = bfsDirty then + AssertedController.HoldsChangedValue(self); + if not Handled then raise; end; end; @@ -1347,10 +1670,9 @@ procedure TBoldFollower.Apply; function TBoldPopup.GetMenu(CONTROL: TControl; Element: TBoldElement): TPopupMenu; begin Result := nil; - {$IFNDEF BOLDCOMCLIENT} // popup + {$IFNDEF BOLDCOMCLIENT} BoldGUIHandler.PopupElement := Element; BoldGUIHandler.PopupControl := CONTROL; - // fixme build actual menu if not Enable then Result := BoldPopupMenu; {$ENDIF} @@ -1375,9 +1697,20 @@ constructor TBoldFollowerSubscriber.Create(follower: TBoldFollower); fFollower := Follower; end; +destructor TBoldFollowerSubscriber.Destroy; +begin + fFollower := nil; + inherited; +end; + function TBoldFollowerSubscriber.GetContextString: string; begin - Result := Follower.AssertedController.Getnamepath + Result := Follower.AssertedController.GetNamepath +end; + +function TBoldFollowerSubscriber.ContextObject: TObject; +begin + result := Follower; end; procedure TBoldFollowerController._Receive(Originator: TObject; @@ -1401,7 +1734,11 @@ procedure TBoldFollower.SetCurrentIndex(index: integer); procedure TBoldRendererData.SetCurrentSubFollowerIndex(index: integer); begin - // just ignore; +end; + +function TBoldRendererData.GetSubFollowerAssigned(Index: Integer): boolean; +begin + raise EBold.CreateFmt('%s: This class has no subfollowers', [ClassName]); end; function TBoldFollowerController.GetContextType: TBoldElementTypeInfo; @@ -1412,6 +1749,21 @@ function TBoldFollowerController.GetContextType: TBoldElementTypeInfo; result := nil; end; +procedure TBoldRenderer.Assign(Source: TPersistent); +begin + inherited; + With Source as TBoldRenderer do + begin + self.OnMayModify := OnMayModify; + self.OnHoldsChangedValue := OnHoldsChangedValue; + self.OnReleaseChangedValue := OnReleaseChangedValue; + self.OnSubscribe := OnSubscribe; + self.OnEnsureFetched := OnEnsureFetched; + self.OnValidateCharacter := OnValidateCharacter; + self.Representations.Assign(Representations); + end; +end; + procedure TBoldRenderer.Changed; begin SendEvent(Self, beValueChanged); @@ -1473,31 +1825,84 @@ function TBoldFollowerController.GetVariableListAndSubscribe(Subscriber: TBoldSu result := GetVariableList; {$IFNDEF BOLDCOMCLIENT} if assigned(Subscriber) and assigned(Variables) then - Variables.SubscribeToHandles(Subscriber); + Variables.SubscribeToHandles(Subscriber, Expression); {$ENDIF} end; -procedure TBoldFollower.CollectMatching(Followers: TBoldObjectArray; - MatchController: TBoldFollowerController); +function TBoldFollower.CollectMatching( + MatchController: TBoldFollowerController): TBoldFollowerArray; begin if Assigned(fOwningFollower) then - fOwningFollower.CollectMatching(Followers, MatchController) + Result := fOwningFollower.CollectMatching(MatchController) else - CollectMatchingDownwards(Followers, MatchController); + Result := CollectMatchingDownwards(Result, MatchController); end; -procedure TBoldFollower.CollectMatchingDownwards(Followers: TBoldObjectArray; - MatchController: TBoldFollowerController); +function TBoldFollower.CollectMatchingSiblings(WindowSize: Integer): TBoldFollowerArray; +var + I, FirstToEnsure, LastToEnsure, found, RowIndex: integer; + CellFollower: TBoldFollower; + RowFollower, ListFollower: TBoldFollower; +begin + FirstToEnsure := 0; + LastToEnsure := -1; + // This actully only works for an array, and maybe a treewiew, but that is what we are trying to optimize anyway + RowFollower := OwningFollower; + if not Assigned(RowFollower) or (RowFollower.state in bfsOutOfDate) then + Exit; + ListFollower := RowFollower.OwningFollower; + if not Assigned(ListFollower) or (ListFollower.state in bfsOutOfDate) then + Exit; + RowIndex := RowFollower.index; + if WindowSize > 1 then + begin + FirstToEnsure := (RowIndex DIV WindowSize -1) * WindowSize; + LastToEnsure := ((RowIndex DIV WindowSize) + 1) * WindowSize; + end; + if FirstToEnsure < 0 then + FirstToEnsure := 0; + if FirstToEnsure >= ListFollower.SubfollowerCount then + FirstToEnsure := ListFollower.SubfollowerCount - 1; + if LastToEnsure >= ListFollower.SubfollowerCount then + LastToEnsure := ListFollower.SubfollowerCount - 1; + + SetLength(Result,LastToEnsure- FirstToEnsure+1); + Found := 0; + for I := FirstToEnsure to LastToEnsure do + begin + RowFollower := ListFollower.SubFollowers[I]; + if (RowFollower = nil) or (not RowFollower.Active) or (RowFollower.SubfollowerCount <= Index) then + Continue; + CellFollower := RowFollower.SubFollowers[Index]; + if Assigned(CellFollower) and (CellFollower.Controller = self.Controller) and Assigned(CellFollower.Element) and + (not CellFollower.Ensured) then + begin + Result[Found] := CellFollower; + Inc(Found); + end; + end; + SetLength(Result, Found); +end; + +function TBoldFollower.CollectMatchingDownwards(Followers: TBoldFollowerArray; + MatchController: TBoldFollowerController): TBoldFollowerArray; var I: integer; begin if (Controller = MatchController) and Assigned(Element) and (State in bfsOutOfDate) and (MostPrioritizedQueuable = nil) then - Followers.Add(Self); + begin + SetLength(Result, Length(Followers) + 1); + for i := 0 to Length(Followers) - 1 do + Result[i] := Followers[i]; + Result[Length(Followers)] := Self; + end + else + Result := Followers; if not (state in bfsOutOfDate) then begin for I := 0 to SubfollowerCount - 1 do - SubFollowers[I].CollectMatchingDownwards(Followers, MatchController); + if Assigned(SubFollowers[I]) then SubFollowers[I].CollectMatchingDownwards(Followers, MatchController); end; end; @@ -1507,41 +1912,43 @@ function TBoldFollowerController.GetSupportsMulti: Boolean; end; class procedure TBoldFollower.MultiMakeUptodateAndSubscribe( - Followers: TBoldObjectArray); + Followers: TBoldFollowerArray); var - I: integer; + F: TBoldFollower; Controller: TBoldFollowerController; begin - Assert(Followers.Count > 0); + Assert(Length(Followers) > 0); Controller := TBoldFollower(Followers[0]).AssertedController; - for I := 0 to Followers.Count - 1 do - if TBoldFollower(Followers[i]).State in bfdNeedResubscribe then + for F in Followers do + if F.State in bfdNeedResubscribe then begin - TBoldFollower(Followers[i]).Subscriber.CancelAllSubscriptions; // CHECKME ever needed? - Controller.AddSmallSubscription(TBoldFollower(Followers[i]).Subscriber, [beValueChanged, beDestroying], breControllerChanged); + F.Subscriber.CancelAllSubscriptions; + Controller.AddSmallSubscription(F.Subscriber, [beValueChanged, beDestroying], breControllerChanged); end; Controller.MultiMakeUptodateAndSubscribe(Followers); end; procedure TBoldFollowerController.MultiMakeUptodateAndSubscribe( - Followers: TBoldObjectArray); + Followers: TBoldFollowerArray); var - I: integer; + F: TBoldFollower; begin if Assigned(BeforeMakeUptoDate) then - for i := 0 to Followers.Count - 1 do - BeforeMakeUptoDate(TBoldFollower(Followers[I])); + for F in Followers do + BeforeMakeUptoDate(F); try DoMultiMakeUptodateAndSubscribe(Followers); finally + for F in Followers do + F.MarkClean; if Assigned(AfterMakeUptoDate) then - for i := 0 to Followers.Count - 1 do - AfterMakeUptoDate(TBoldFollower(Followers[I])); + for F in Followers do + AfterMakeUptoDate(F); end; end; procedure TBoldFollowerController.DoMultiMakeUptodateAndSubscribe( - Followers: TBoldObjectArray); + Followers: TBoldFollowerArray); begin raise EBoldInternal.Create('DoMultiMakeUptodateAndSubscribe: called when Multi not supported'); end; @@ -1549,34 +1956,30 @@ procedure TBoldFollowerController.DoMultiMakeUptodateAndSubscribe( procedure TBoldFollowerSubscriber.Receive(Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent); begin + if not Assigned(Follower) then + raise EBold.Create('TBoldFollowerSubscriber.Receive called after Destroy'); Follower.Receive(Originator, OriginalEvent, RequestedEvent); end; -function TBoldFollower.GetAssertedController: TBoldFollowerController; +procedure TBoldFollowerController.SubscribeToElement(aFollower: TBoldFollower); begin - if not assigned(fController) then - raise EBold.CreateFmt(sControllerNotAssigned, [classname]); - result := fController; -end; - -procedure TBoldFollowerController.SubscribeToElement(Element: TBoldElement; Subscriber: TBoldSubscriber); -begin - EffectiveRenderer.SubscribeToElement(Element, representation, Expression, Subscriber, VariableList); + EffectiveRenderer.SubscribeToElement(aFollower); end; function TBoldFollowerController.HandleApplyException(E: Exception; Elem: TBoldElement; var Discard: Boolean): Boolean; var ExceptionHandler: TBoldExceptionHandler; begin - ExceptionHandler := TBoldExceptionHandler.FindExceptionHandler(fOwningComponent); - Result := assigned(ExceptionHandler); - if Result then - ExceptionHandler.HandleApplyException(E, fOwningComponent, Elem, Discard, Result); -end; - -procedure TBoldFollowerController.CleanRendererData(RendererData: TBoldRendererData); -begin - // do nothing + Result := false; + Discard := False; + if Assigned(fApplyException) then + Result := DoApplyException(E, Elem, Discard); + if not result and not Discard then + begin + ExceptionHandler := TBoldExceptionHandler.FindExceptionHandler(fOwningComponent); + if assigned(ExceptionHandler) then + ExceptionHandler.HandleApplyException(E, fOwningComponent, Elem, Discard, Result); + end; end; function TBoldFollowerController.HandleDisplayException(E: Exception; @@ -1584,21 +1987,23 @@ function TBoldFollowerController.HandleDisplayException(E: Exception; var ExceptionHandler: TBoldExceptionHandler; begin + Result := false; ExceptionHandler := TBoldExceptionHandler.FindExceptionHandler(fOwningComponent); - Result := Assigned(ExceptionHandler); - if Result then + if Assigned(ExceptionHandler) then ExceptionHandler.HandleDisplayException(E, fOwningComponent, Elem, Result); end; -procedure TBoldFollowerController.MultiMakeEnsure(Followers: TBoldObjectArray); +procedure TBoldFollowerController.CleanRendererData(RendererData: TBoldRendererData); +begin +end; + +procedure TBoldFollowerController.MultiMakeEnsure(Followers: TBoldFollowerArray); {$IFNDEF BOLDCOMCLIENT} var BoldType: TBoldClassTypeInfo; ListType: TBoldListTypeInfo; ObjectList: TBoldObjectList; - RealObjectList: TBoldObjectLIst; ie: TBoldIndirectElement; - i: integer; follower: TBoldFollower; procedure AddObject(Obj: TBoldObject); begin @@ -1613,12 +2018,12 @@ procedure TBoldFollowerController.MultiMakeEnsure(Followers: TBoldObjectArray); BoldGuard: IBoldGuard; begin - BoldGuard := TBoldGuard.Create(ie, RealObjectList, ObjectList); + BoldGuard := TBoldGuard.Create(ObjectList); ObjectList := TBoldObjectList.Create; BoldType := nil; - for i := 0 to Followers.Count - 1 do + for Follower in Followers do begin - Follower := TBoldFollower(Followers[i]); + Follower.MarkEnsured; if Follower.element is TBoldObject then begin AddObject(Follower.element as TBoldObject); @@ -1626,18 +2031,7 @@ procedure TBoldFollowerController.MultiMakeEnsure(Followers: TBoldObjectArray); end; if assigned(BoldType) then - begin - ObjectList.EnsureObjects; - if (ObjectList.Count > 1) and (Expression <> '') then - begin - ListType := BoldType.SystemTypeInfo.ListTypeInfoByElement[BoldType]; - RealObjectlist := TBoldMemberFactory.CreateMemberFromBoldType(ListType) as TBoldObjectList; - RealObjectList.AddList(ObjectList); - - ie := TBoldIndirectElement.Create; - RealObjectList.EvaluateExpression(Expression, ie); - end; - end; + TBoldFollower(Followers[0]).Controller.EffectiveRenderer.EnsureFetched(ObjectList,BoldType, Expression); end; {$ELSE} @@ -1650,12 +2044,61 @@ function TBoldFollowerController.GetSupportsMultiEnsure: Boolean; result := false; end; +function TBoldFollowerController.SubFollowersActive: boolean; +begin + result := true; +end; + procedure TBoldFollower.AddToDisplayList; begin if Assigned(Controller) then inherited AddToDisplayList; end; +function TBoldFollower.GetDebugInfo: string; +var + vFollower: TBoldFollower; +begin + result := ''; +{ vFollower := self; + repeat + + until ; + if Assigned(OwningFollower) then + result := OwningFollower.GetDebugInfo + else +} + if Assigned(MatchObject) then + begin + if MatchObject is TComponent then + result := TComponent(MatchObject).Name + ':' + TComponent(MatchObject).ClassName + else + if MatchObject is TBoldElement then + result := TBoldElement(MatchObject).DebugInfo + else + Assert(false, MatchObject.ClassName); + end; +end; + +{ TBoldAbstractHandleFollower } + +constructor TBoldAbstractHandleFollower.Create(AMatchObject: TObject; + Controller: TBoldFollowerController); +begin + inherited Create(BoldGuiHandler.FindHostingForm(AMatchObject as TComponent)); + fSubscriber := TBoldPassthroughSubscriber.Create(Receive); + fFollower := TBoldFollower.Create(MatchObject, Controller); + fFollower.PrioritizedQueuable := Self; +end; + +destructor TBoldAbstractHandleFollower.Destroy; +begin + RemoveFromDisplayList(true); + FreeAndNil(fFollower); + FreeAndNil(fSubscriber); + inherited; +end; + initialization DefaultRenderer := TBoldRenderer.Create(nil); @@ -1663,4 +2106,3 @@ finalization FreeAndNil(DefaultRenderer); end. - diff --git a/Source/BoldAwareGUI/ControlPacks/BoldControllerListControlPack.pas b/Source/BoldAwareGUI/ControlPacks/BoldControllerListControlPack.pas index e301aa5..82df9f8 100644 --- a/Source/BoldAwareGUI/ControlPacks/BoldControllerListControlPack.pas +++ b/Source/BoldAwareGUI/ControlPacks/BoldControllerListControlPack.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldControllerListControlPack; {$UNDEF BOLDCOMCLIENT} @@ -6,7 +9,7 @@ interface uses Classes, - BoldControlPackDefs, + BoldControlPackDefs, BoldElements, BoldControlPack, BoldListControlPack; @@ -19,19 +22,21 @@ TBoldControllerList = class; TBoldControllerList = class(TBoldAsFollowerListController) private FList: TList; - function GetCount: Integer; - function GetSubController(index: Integer): TBoldFollowerController; + function GetCount: Integer; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetSubController(index: Integer): TBoldFollowerController; {$IFDEF BOLD_INLINE} inline; {$ENDIF} protected procedure DoMakeUptodateAndSubscribe(Follower: TBoldFollower; Subscribe: Boolean); override; function GetEffectiveRenderer: TBoldRenderer; override; - function GetEffectiveDisplayPropertyListRenderer: TBoldControllerListAsFollowerListRenderer; + function GetEffectiveDisplayPropertyListRenderer: TBoldControllerListAsFollowerListRenderer; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + class function PrecreateFollowers: boolean; override; public constructor Create(aOwningComponent: TComponent); destructor Destroy; override; - procedure Add(BoldFollowerController: TBoldFollowerController); - procedure Delete(index: Integer); - procedure Remove(BoldFollowerController: TBoldFollowerController); - procedure Move(CurIndex, ToIndex: Integer); + procedure Add(BoldFollowerController: TBoldFollowerController); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure Delete(index: Integer); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure Remove(BoldFollowerController: TBoldFollowerController); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure Move(CurIndex, ToIndex: Integer); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function IndexOf(BoldFollowerController: TBoldFollowerController): integer; {$IFDEF BOLD_INLINE} inline; {$ENDIF} property Count: Integer read GetCount; property Items[index: Integer]: TBoldFollowerController read GetSubController; default; published @@ -49,7 +54,8 @@ TBoldControllerListAsFollowerListRenderer = class(TBoldAsFollowerListRenderer) implementation uses - SysUtils; + SysUtils, + BoldRev; var DefaultDisplayPropertyListRenderer: TBoldControllerListAsFollowerListRenderer; @@ -63,6 +69,16 @@ constructor TBoldControllerList.Create(aOwningComponent: TComponent); DropMode := bdpInsert; end; +function TBoldControllerList.GetCount: Integer; +begin + Result := FList.Count; +end; + +function TBoldControllerList.GetSubController(index: Integer): TBoldFollowerController; +begin + Result := TBoldSingleFollowerController(FList[index]); +end; + destructor TBoldControllerList.Destroy; var I: Integer; @@ -78,18 +94,13 @@ procedure TBoldControllerList.DoMakeUptodateAndSubscribe(Follower: TBoldFollower inherited DoMakeUptodateAndSubscribe(Follower, Subscribe); (EffectiveRenderer as TBoldControllerListAsFollowerListRenderer).MakeUptodate(Follower, Follower.Element); if Subscribe and Assigned(Follower.Element) then - {$IFDEF BOLDCOMCLIENT} // MakeUpToDate + {$IFDEF BOLDCOMCLIENT} Follower.Element.SubscribeToExpression('', Follower.Subscriber.ClientId, Follower.Subscriber.SubscriberId, False, true); {$ELSE} - Follower.Element.SubscribeToExpression('', Follower.Subscriber, False); + Follower.Element.SubscribeToExpression('', Follower.Subscriber, False); // Follower.Element.DefaultSubscribe(Follower.Subscriber); {$ENDIF} end; -function TBoldControllerList.GetSubController(index: Integer): TBoldFollowerController; -begin - Result := TBoldSingleFollowerController(FList[index]); -end; - procedure TBoldControllerList.Add(BoldFollowerController: TBoldFollowerController); begin FList.Add(BoldFollowerController); @@ -115,9 +126,9 @@ procedure TBoldControllerList.Move(CurIndex, ToIndex: Integer); Changed; end; -function TBoldControllerList.GetCount: Integer; +function TBoldControllerList.GetEffectiveDisplayPropertyListRenderer: TBoldControllerListAsFollowerListRenderer; begin - Result := FList.Count; + Result := TBoldControllerListAsFollowerListRenderer.DefaultRenderer; end; function TBoldControllerList.GetEffectiveRenderer: TBoldRenderer; @@ -125,9 +136,15 @@ function TBoldControllerList.GetEffectiveRenderer: TBoldRenderer; Result := GetEffectiveDisplayPropertyListRenderer; end; -function TBoldControllerList.GetEffectiveDisplayPropertyListRenderer: TBoldControllerListAsFollowerListRenderer; +function TBoldControllerList.IndexOf( + BoldFollowerController: TBoldFollowerController): integer; +begin + result := fList.IndexOf(BoldFollowerController); +end; + +class function TBoldControllerList.PrecreateFollowers: boolean; begin - Result := TBoldControllerListAsFollowerListRenderer.DefaultRenderer; // currently always uses default. + result := false; end; {---TBoldControllerListAsFollowerListRenderer---} @@ -142,11 +159,17 @@ procedure TBoldControllerListAsFollowerListRenderer.MakeUptodate(Follower: TBold SourceList: TBoldControllerList; SourceIndex: Integer; DestList: TBoldFollowerList; + lPrecreateFollowers: boolean; begin DestList := Follower.RendererData as TBoldFollowerList; SourceList := Follower.Controller as TBoldControllerList; + lPrecreateFollowers := SourceList.PrecreateFollowers; + DestList.SetCapacity(SourceList.Count); for sourceIndex := 0 to SourceList.Count-1 do - DestList.EnsureFollower(SourceList, SourceIndex, Element, SourceList[SourceIndex]); + if lPrecreateFollowers then + DestList.EnsuredFollower(SourceList, SourceIndex, Element, SourceList[SourceIndex]) + else + DestList.EnsuredFollower(SourceList, SourceIndex, nil, SourceList[SourceIndex]); DestList.PurgeEnd(SourceList, SourceList.Count); end; @@ -157,4 +180,3 @@ finalization FreeAndNil(DefaultDisplayPropertyListRenderer); end. - diff --git a/Source/BoldAwareGUI/ControlPacks/BoldDateTimeControlPack.pas b/Source/BoldAwareGUI/ControlPacks/BoldDateTimeControlPack.pas index 3549bf7..0f3d6d1 100644 --- a/Source/BoldAwareGUI/ControlPacks/BoldDateTimeControlPack.pas +++ b/Source/BoldAwareGUI/ControlPacks/BoldDateTimeControlPack.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldDateTimeControlPack; {$UNDEF BOLDCOMCLIENT} @@ -17,9 +20,9 @@ TBoldAsDateTimeRenderer = class; TBoldDateTimeFollowerController = class; {TBoldAsDateTimeRenderer} - TBoldGetAsDateTimeEvent = function (Element: TBoldElement; Representation: TBoldRepresentation; Expression: TBoldExpression): TDateTime of object; - TBoldSetAsDateTimeEvent = procedure (Element: TBoldElement; const Value: TDateTime; Representation: TBoldRepresentation; Expression: TBoldExpression) of object; - TBoldDateTimeIsChangedEvent = function (RenderData: TBoldDateTimeRendererData; const NewValue: TDateTime; Representation: TBoldRepresentation; Expression: TBoldExpression): Boolean of object; + TBoldGetAsDateTimeEvent = function (aFollower: TBoldFollower): TDateTime of object; + TBoldSetAsDateTimeEvent = procedure (aFollower: TBoldFollower; const Value: TDateTime) of object; + TBoldDateTimeIsChangedEvent = function (aFollower: TBoldFollower; const NewValue: TDateTime): Boolean of object; { TBoldDateTimeRendererData } TBoldDateTimeRendererData = class(TBoldRendererData) @@ -40,15 +43,16 @@ TBoldAsDateTimeRenderer = class(TBoldsingleRenderer) protected class function DefaultRenderer: TBoldAsDateTimeRenderer; function GetRendererDataClass: TBoldRendererDataClass; override; - function DefaultGetAsDateTimeAndSubscribe(Element: TBoldElement; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList; Subscriber: TBoldSubscriber): TDateTime; virtual; - procedure DefaultSetAsDateTime(Element: TBoldElement; const Value: TDateTime; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList); virtual; - function GetAsDateTimeAndSubscribe(Element: TBoldElement; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList; Subscriber: TBoldSubscriber): TDateTime; virtual; - procedure SetAsDateTime(Element: TBoldElement; const Value: TDateTime; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList); virtual; + function DefaultGetAsDateTimeAndSubscribe(aFollower: TBoldFollower; Subscriber: TBoldSubscriber): TDateTime; virtual; + procedure DefaultSetAsDateTime(aFollower: TBoldFollower; const Value: TDateTime); virtual; + function GetAsDateTimeAndSubscribe(aFollower: TBoldFollower; Subscriber: TBoldSubscriber): TDateTime; virtual; + procedure SetAsDateTime(aFollower: TBoldFollower; const Value: TDateTime); virtual; + function HasSetValueEventOverrides: boolean; override; public - procedure MakeUptodateAndSubscribe(Element: TBoldElement; RendererData: TBoldRendererData; FollowerController: TBoldFollowerController; Subscriber: TBoldSubscriber); override; - function DefaultMayModify(Element: TBoldElement; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList; Subscriber: TBoldSubscriber): Boolean; override; - function DefaultIsChanged(RendererData: TBoldDateTimeRendererData; const NewValue: TDateTime; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList): Boolean; - function IsChanged(RendererData: TBoldDateTimeRendererData; const NewValue: TDateTime; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList): Boolean; + procedure MakeUptodateAndSubscribe(aFollower: TBoldFollower; Subscriber: TBoldSubscriber); override; + function DefaultMayModify(aFollower: TBoldFollower): Boolean; override; + function DefaultIsChanged(aFollower: TBoldFollower; const NewValue: TDateTime): Boolean; + function IsChanged(aFollower: TBoldFollower; const NewValue: TDateTime): Boolean; published property OnGetAsDateTime: TBoldGetAsDateTimeEvent read FOnGetAsDateTime write FOnGetAsDateTime; property OnSetAsDateTime: TBoldSetAsDateTimeEvent read FOnSetAsDateTime write FOnSetAsDateTime; @@ -65,7 +69,6 @@ TBoldDateTimeFollowerController = class(TBoldSingleFollowerController) function GetEffectiveRenderer: TBoldRenderer; override; property EffectiveAsDateTimeRenderer: TBoldAsDateTimeRenderer read GetEffectiveAsDateTimeRenderer; public -// procedure Assign(Source: TPersistent); override; function GetCurrentAsDateTime(Follower: TBoldFollower): TDateTime; procedure MakeClean(Follower: TBoldFollower); override; procedure MayHaveChanged(NewValue: TDateTime; Follower: TBoldFollower); @@ -78,9 +81,8 @@ implementation uses SysUtils, - BoldGuiResourceStrings, BoldControlPackDefs, - BoldAttributes, + BoldAttributes, BoldGuard; var @@ -97,35 +99,41 @@ function TBoldAsDateTimeRenderer.GetRendererDataClass: TBoldRendererDataClass; Result := TBoldDateTimeRendererData; end; -function TBoldAsDateTimeRenderer.DefaultMayModify(Element: TBoldElement; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList; Subscriber: TBoldSubscriber): Boolean; -{$IFNDEF BOLDCOMCLIENT} // defaultMayModify +function TBoldAsDateTimeRenderer.HasSetValueEventOverrides: boolean; +begin + result := Assigned(FOnSetAsDateTime); +end; + +function TBoldAsDateTimeRenderer.DefaultMayModify(aFollower: TBoldFollower): Boolean; +{$IFNDEF BOLDCOMCLIENT} var ValueElement: TBoldElement; -{$ENDIF} +{$ENDIF} begin - {$IFDEF BOLDCOMCLIENT} // defaultMayModify + {$IFDEF BOLDCOMCLIENT} result := inherited DefaultMayModify(Element, Representation, Expression, VariableList, Subscriber); {$ELSE} - // Note! We don't call inherited DefaultMayModify to prevent evaluation of expression two times! - ValueElement := GetExpressionAsDirectElement(Element, Expression, VariableList); - result := (ValueElement is TBAMoment) and ValueElement.ObserverMayModify(Subscriber); + ValueElement := aFollower.Value; + result := (ValueElement is TBAMoment) and ValueElement.ObserverMayModify(aFollower.Subscriber); {$ENDIF} end; -function TBoldAsDateTimeRenderer.DefaultGetAsDateTimeAndSubscribe(Element: TBoldElement; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList; Subscriber: TBoldSubscriber): TDateTime; +function TBoldAsDateTimeRenderer.DefaultGetAsDateTimeAndSubscribe(aFollower: TBoldFollower; Subscriber: TBoldSubscriber): TDateTime; var - {$IFDEF BOLDCOMCLIENT} // DefaultGet + {$IFDEF BOLDCOMCLIENT} el: IBoldElement; attr: IBoldAttribute; {$ELSE} - IndirectElement: TBoldIndirectElement; - g: IBoldGuard; + lBoldIndirectElement: TBoldIndirectElement; + lBoldGuard: IBoldGuard; + lResultElement: TBoldElement; + lBAMoment: TBAMoment; {$ENDIF} begin Result := 0; - if Assigned(Element) then + if Assigned(aFollower.Element) then begin - {$IFDEF BOLDCOMCLIENT} //defaultGet + {$IFDEF BOLDCOMCLIENT} if assigned(Subscriber) then el := Element.EvaluateAndSubscribeToExpression(Expression, Subscriber.ClientId, Subscriber.SubscriberId, false, false) else @@ -135,40 +143,59 @@ function TBoldAsDateTimeRenderer.DefaultGetAsDateTimeAndSubscribe(Element: TBold if el.QueryInterface(IBoldAttribute, attr) = S_OK then Result := attr.AsVariant else - raise EBold.CreateFmt(sCannotGetDateTimeValueFromElement, [Attr.Asstring]) + raise EBold.CreateFmt('Can''t get datetime value from element (%s)', [Attr.Asstring]) end; {$ELSE} - g := TBoldGuard.Create(IndirectElement); - IndirectElement := TBoldIndirectElement.Create; - Element.EvaluateAndSubscribeToExpression(Expression, Subscriber, IndirectElement, False, false, VariableList); - if Assigned(IndirectElement.Value) then + lResultElement := aFollower.Value; + if not Assigned(lResultElement) then + begin + lBoldGuard:= TBoldGuard.Create(lBoldIndirectElement); + lBoldIndirectElement := TBoldIndirectElement.Create; + aFollower.Element.EvaluateAndSubscribeToExpression(aFollower.AssertedController.Expression, Subscriber, lBoldIndirectElement, False, False, aFollower.Controller.GetVariableListAndSubscribe(Subscriber)); + lResultElement := lBoldIndirectElement.Value; + end; + if Assigned(lResultElement) then begin - if (IndirectElement.Value is TBADateTime) then - Result := TBADateTime(IndirectElement.Value).AsDateTime - else if (IndirectElement.Value is TBADate) then - Result := TBADate(IndirectElement.Value).AsDate - else if (IndirectElement.Value is TBATime) then - Result := TBATime(IndirectElement.Value).AsTime + if (lResultElement is TBAMoment) then + begin + lBAMoment := lResultElement as TBAMoment; + if lBAMoment.IsNull then + begin + Result := 0; //TODO Null will display as 0 which isn't best + end + else if (lBAMoment is TBADateTime) then + begin + Result := TBADateTime(lBAMoment).AsDateTime + end + else if (lBAMoment is TBADate) then + begin + Result := TBADate(lBAMoment).AsDate + end + else if (lBAMoment is TBATime) then + begin + Result := TBATime(lBAMoment).AsTime + end + end else - raise EBold.CreateFmt(sCannotGetDateTimeValueFromElement, [IndirectElement.Value.ClassName]) + raise EBold.CreateFmt('Can''t get datetime value from element (%s)', [lResultElement.ClassName]) end; {$ENDIF} end; end; -procedure TBoldAsDateTimeRenderer.DefaultSetAsDateTime(Element: TBoldElement; const Value: TDateTime; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList); +procedure TBoldAsDateTimeRenderer.DefaultSetAsDateTime(aFollower: TBoldFollower; const Value: TDateTime); var - {$IFDEF BOLDCOMCLIENT} // defaultSet + {$IFDEF BOLDCOMCLIENT} Attr: IBoldAttribute; {$ENDIF} ValueElement: TBoldElement; begin - ValueElement := GetExpressionAsDirectElement(Element, Expression, VariableList); - {$IFDEF BOLDCOMCLIENT} // defaultSet + ValueElement := aFollower.Value; + {$IFDEF BOLDCOMCLIENT} if assigned(ValueElement) and (ValueElement.QueryInterface(IBoldAttribute, Attr) = S_OK) then Attr.AsVariant := Value else - raise EBold.CreateFmt(sCannotSetDateTimeValueOnElement, [ValueElement.AsString]); + raise EBold.CreateFmt('Can''t set datetime value on element (%s)', [ValueElement.AsString]); {$ELSE} if Assigned(ValueElement) and (ValueElement is TBADateTime) then TBADateTime(ValueElement).AsDateTime := Value @@ -177,59 +204,54 @@ procedure TBoldAsDateTimeRenderer.DefaultSetAsDateTime(Element: TBoldElement; co else if Assigned(ValueElement) and (ValueElement is TBATime) then TBATime(ValueElement).AsTime := Value else - raise EBold.CreateFmt(sCannotSetDateTimeValueOnElement, [ValueElement.ClassName]); + raise EBold.CreateFmt('Can''t set datetime value on element (%s)', [ValueElement.ClassName]); {$ENDIF} end; -function TBoldAsDateTimeRenderer.GetAsDateTimeAndSubscribe(Element: TBoldElement; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList; Subscriber: TBoldSubscriber): TDateTime; +function TBoldAsDateTimeRenderer.GetAsDateTimeAndSubscribe(aFollower: TBoldFollower; Subscriber: TBoldSubscriber): TDateTime; begin if Assigned(OnSubscribe) and Assigned(Subscriber) then begin - if Assigned(Element) then - OnSubscribe(Element, Representation, Expression, Subscriber); + if Assigned(aFollower.Element) then + OnSubscribe(aFollower, Subscriber); Subscriber := nil; end; if Assigned(OnGetAsDateTime) then - Result := OnGetAsDateTime(Element, Representation, Expression) + Result := OnGetAsDateTime(aFollower) else - Result := DefaultGetAsDateTimeAndSubscribe(Element, Representation, Expression, VariableList, Subscriber); + Result := DefaultGetAsDateTimeAndSubscribe(aFollower, Subscriber); end; -procedure TBoldAsDateTimeRenderer.SetAsDateTime(Element: TBoldElement; const Value: TDateTime; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList); +procedure TBoldAsDateTimeRenderer.SetAsDateTime(aFollower: TBoldFollower; const Value: TDateTime); begin if Assigned(FOnSetAsDateTime) then - OnSetAsDateTime(Element, Value, Representation, Expression) + OnSetAsDateTime(aFollower, Value) else - DefaultSetAsDateTime(Element, Value, Representation, Expression, VariableList) + DefaultSetAsDateTime(aFollower, Value) end; -procedure TBoldAsDateTimeRenderer.MakeUptodateAndSubscribe(Element: TBoldElement; RendererData: TBoldRendererData; FollowerController: TBoldFollowerController; Subscriber: TBoldSubscriber); +procedure TBoldAsDateTimeRenderer.MakeUptodateAndSubscribe(aFollower: TBoldFollower; Subscriber: TBoldSubscriber); var - Value: TDateTime; + lDateTime: TDateTime; + lRendererData: TBoldDateTimeRendererData; begin - Assert(FollowerController is TBoldDateTimeFollowerController); - Value := GetAsDateTimeAndSubscribe(Element, - TBoldDateTimeFollowerController(FollowerController).Representation, - TBoldDateTimeFollowerController(FollowerController).Expression, FollowerController.GetVariableListAndSubscribe(Subscriber), - subscriber); - with (RendererData as TBoldDateTimeRendererData) do - begin - OldDateTimeValue := Value; - CurrentDateTimeValue := Value; - end; + lDateTime := GetAsDateTimeAndSubscribe(aFollower, subscriber); + lRendererData := aFollower.RendererData as TBoldDateTimeRendererData; + lRendererData.OldDateTimeValue := lDateTime; + lRendererData.CurrentDateTimeValue := lDateTime; end; -function TBoldAsDateTimeRenderer.DefaultIsChanged(RendererData: TBoldDateTimeRendererData; const NewValue: TDateTime; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList): Boolean; +function TBoldAsDateTimeRenderer.DefaultIsChanged(aFollower: TBoldFollower; const NewValue: TDateTime): Boolean; begin - Result := NewValue <> RendererData.OldDateTimeValue; + Result := NewValue <> TBoldDateTimeRendererData(aFollower.RendererData).OldDateTimeValue; end; -function TBoldAsDateTimeRenderer.IsChanged(RendererData: TBoldDateTimeRendererData; const NewValue: TDateTime; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList): Boolean; +function TBoldAsDateTimeRenderer.IsChanged(aFollower: TBoldFollower; const NewValue: TDateTime): Boolean; begin if Assigned(FOnIsChanged) then - Result := FOnIsChanged(RendererData, NewValue, Representation, Expression) + Result := FOnIsChanged(aFollower, NewValue) else - Result := DefaultIsChanged(RendererData, NewValue, Representation, Expression, VariableList); + Result := DefaultIsChanged(aFollower, NewValue); end; { TBoldDateTimeFollowerController } @@ -260,7 +282,7 @@ function TBoldDateTimeFollowerController.GetEffectiveAsDateTimeRenderer: TBoldAs if Assigned(Renderer) then Result := Renderer else - Result := DefaultAsDateTimeRenderer; //FIXME + Result := DefaultAsDateTimeRenderer; end; procedure TBoldDateTimeFollowerController.MakeClean(Follower: TBoldFollower); @@ -276,15 +298,23 @@ function TBoldDateTimeFollowerController.GetCurrentAsDateTime(Follower: TBoldFol procedure TBoldDateTimeFollowerController.SetAsDateTime(Value: TDateTime; Follower: TBoldFollower); begin - EffectiveAsDateTimeRenderer.SetAsDateTime(Follower.Element, Value, Representation, Expression, VariableList); + EffectiveAsDateTimeRenderer.SetAsDateTime(Follower, Value); end; procedure TBoldDateTimeFollowerController.MayHaveChanged(NewValue: TDateTime; Follower: TBoldFollower); +var + lIsChanged: boolean; + lRendererData: TBoldDateTimeRendererData; begin if Follower.State in bfsDisplayable then begin - (Follower.RendererData as TBoldDateTimeRendererData).CurrentDateTimeValue := NewValue; - Follower.ControlledValueChanged(EffectiveAsDateTimeRenderer.IsChanged(Follower.RendererData as TBoldDateTimeRendererData, NewValue, Representation, Expression, VariableList)); + lRendererData := (Follower.RendererData as TBoldDateTimeRendererData); + lRendererData.CurrentDateTimeValue := NewValue; + lIsChanged := EffectiveAsDateTimeRenderer.IsChanged(Follower, NewValue); + if lIsChanged then + begin + Follower.ControlledValueChanged; + end; end; end; diff --git a/Source/BoldAwareGUI/ControlPacks/BoldElementHandleFollower.pas b/Source/BoldAwareGUI/ControlPacks/BoldElementHandleFollower.pas index 1700c4d..1e3b7d7 100644 --- a/Source/BoldAwareGUI/ControlPacks/BoldElementHandleFollower.pas +++ b/Source/BoldAwareGUI/ControlPacks/BoldElementHandleFollower.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldElementHandleFollower; {$UNDEF BOLDCOMCLIENT} @@ -18,27 +21,23 @@ interface TBoldElementHandleFollower = class; { TBoldElementHandleFollower } - TBoldElementHandleFollower = class(TBoldQueueable) + TBoldElementHandleFollower = class(TBoldAbstractHandleFollower) private fBoldHandle: TBoldElementHandle; - fFollower: TBoldFollower; fFollowerValueCurrent: Boolean; - fSubscriber: TBoldSubscriber; procedure SetFollowerValueCurrent(value: Boolean); procedure SetBoldHandle(value: TBoldElementHandle); property FollowerValueCurrent: Boolean read fFollowerValueCurrent write SetFollowerValueCurrent; protected - procedure Receive(Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent); + function GetBoldHandle: TBoldElementHandle; override; + procedure Receive(Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent); override; procedure Display; override; - property Subscriber: TBoldSubscriber read fSubscriber; public - constructor Create(MatchObject: TObject; Controller: TBoldFollowerController); - destructor Destroy; override; + constructor Create(AMatchObject: TObject; Controller: TBoldFollowerController); procedure Apply; override; procedure DiscardChange; override; - published +// published property BoldHandle: TBoldElementHandle read FBoldHandle write SetBoldHandle; - property Follower: TBoldFollower read fFollower; end; implementation @@ -60,29 +59,18 @@ procedure TBoldElementHandleFollower.Receive(Originator: TObject; FollowerValueCurrent := false; end; -constructor TBoldElementHandleFollower.Create(MatchObject: TObject; +constructor TBoldElementHandleFollower.Create(AMatchObject: TObject; Controller: TBoldFollowerController); begin - inherited Create(nil); - fSubscriber := TBoldPassthroughSubscriber.Create(Receive); - fFollower := TBoldFollower.Create(MatchObject, Controller); - fFollower.PrioritizedQueuable := Self; + inherited Create(AMatchObject, Controller); fFollowerValueCurrent := true; end; -destructor TBoldElementHandleFollower.Destroy; -begin - FreeAndNil(fFollower); - FreeAndNil(fSubscriber); - inherited; -end; - procedure TBoldElementHandleFollower.SetBoldHandle(value: TBoldElementHandle); begin if (value <> BoldHandle) then begin fBoldHandle := Value; - // will force subscription on Handle FollowerValueCurrent := false; end; end; @@ -129,12 +117,14 @@ procedure TBoldElementHandleFollower.SetFollowerValueCurrent(value: Boolean); begin if Value then begin - RemoveFromDisplayList; + RemoveFromDisplayList(false); PropagateValue; Subscribe; end else begin + if Follower.IsDirty then + Follower.DiscardChange; Follower.element := nil; Subscriber.CancelAllSubscriptions; AddToDisplayList; @@ -144,5 +134,10 @@ procedure TBoldElementHandleFollower.SetFollowerValueCurrent(value: Boolean); SubscribeToHandleReference; end; -end. +function TBoldElementHandleFollower.GetBoldHandle: TBoldElementHandle; +begin + result := fBoldHandle; +end; +initialization +end. diff --git a/Source/BoldAwareGUI/ControlPacks/BoldFloatControlPack.pas b/Source/BoldAwareGUI/ControlPacks/BoldFloatControlPack.pas index 953a64f..5f445c2 100644 --- a/Source/BoldAwareGUI/ControlPacks/BoldFloatControlPack.pas +++ b/Source/BoldAwareGUI/ControlPacks/BoldFloatControlPack.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldFloatControlPack; {$UNDEF BOLDCOMCLIENT} @@ -17,9 +20,9 @@ TBoldAsFloatRenderer = class; TBoldFloatFollowerController = class; { TBoldAsFloatRenderer } - TBoldGetAsFloatEvent = function (Element: TBoldElement; Representation: TBoldRepresentation; Expression: TBoldExpression): double of object; - TBoldSetAsFloatEvent = procedure (Element: TBoldElement; const Value: double; Representation: TBoldRepresentation; Expression: TBoldExpression) of object; - TBoldFloatIsChangedEvent = function (RenderData: TBoldFloatRendererData; const NewValue: double; Representation: TBoldRepresentation; Expression: TBoldExpression): Boolean of object; + TBoldGetAsFloatEvent = function (aFollower: TBoldFollower): double of object; + TBoldSetAsFloatEvent = procedure (aFollower: TBoldFollower; const Value: double) of object; + TBoldFloatIsChangedEvent = function (aFollower: TBoldFollower; const NewValue: double): Boolean of object; { TBoldFloatRendererData } TBoldFloatRendererData = class(TBoldRendererData) @@ -40,15 +43,16 @@ TBoldAsFloatRenderer = class(TBoldSingleRenderer) protected class function DefaultRenderer: TBoldAsFloatRenderer; function GetRendererDataClass: TBoldRendererDataClass; override; - function DefaultGetAsFloatAndSubscribe(Element: TBoldElement; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList; Subscriber: TBoldSubscriber): double; virtual; - procedure DefaultSetAsFloat(Element: TBoldElement; const Value: double; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList); virtual; - function GetAsFloatAndSubscribe(Element: TBoldElement; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList; Subscriber: TBoldSubscriber): double; virtual; - procedure SetAsFloat(Element: TBoldElement; const Value: double; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList); virtual; + function DefaultGetAsFloatAndSubscribe(aFollower: TBoldFollower; Subscriber: TBoldSubscriber): double; virtual; + procedure DefaultSetAsFloat(aFollower: TBoldFollower; const Value: double); virtual; + function GetAsFloatAndSubscribe(aFollower: TBoldFollower; Subscriber: TBoldSubscriber): double; virtual; + procedure SetAsFloat(aFollower: TBoldFollower; const Value: double); virtual; + function HasSetValueEventOverrides: boolean; override; public - procedure MakeUptodateAndSubscribe(Element: TBoldElement; RendererData: TBoldRendererData; FollowerController: TBoldFollowerController; Subscriber: TBoldSubscriber); override; - function DefaultMayModify(Element: TBoldElement; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList; Subscriber: TBoldSubscriber): Boolean; override; - function DefaultIsChanged(RendererData: TBoldFloatRendererData; const NewValue: double; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList): Boolean; - function IsChanged(RendererData: TBoldFloatRendererData; const NewValue: double; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList): Boolean; + procedure MakeUptodateAndSubscribe(aFollower: TBoldFollower; Subscriber: TBoldSubscriber); override; + function DefaultMayModify(aFollower: TBoldFollower): Boolean; override; + function DefaultIsChanged(aFollower: TBoldFollower; const NewValue: double): Boolean; + function IsChanged(aFollower: TBoldFollower; const NewValue: double): Boolean; published property OnGetAsFloat: TBoldGetAsFloatEvent read FOnGetAsFloat write FOnGetAsFloat; property OnSetAsFloat: TBoldSetAsFloatEvent read FOnSetAsFloat write FOnSetAsFloat; @@ -65,7 +69,6 @@ TBoldFloatFollowerController = class(TBoldSingleFollowerController) property EffectiveAsFloatRenderer: TBoldAsFloatRenderer read GetEffectiveAsFloatRenderer; function GetEffectiveRenderer: TBoldRenderer; override; public -// procedure Assign(Source: TPersistent); override; function GetCurrentAsFloat(Follower: TBoldFollower): double; procedure MakeClean(Follower: TBoldFollower); override; procedure MayHaveChanged(NewValue: double; Follower: TBoldFollower); @@ -78,10 +81,9 @@ implementation uses SysUtils, - BoldGuiResourceStrings, BoldUtils, BoldAttributes, - BoldControlPackDefs, + BoldControlPackDefs, BoldGuard; var @@ -98,33 +100,38 @@ function TBoldAsFloatRenderer.GetRendererDataClass: TBoldRendererDataClass; Result := TBoldFloatRendererData; end; -function TBoldAsFloatRenderer.DefaultMayModify(Element: TBoldElement; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList; Subscriber: TBoldSubscriber): Boolean; -{$IFNDEF BOLDCOMCLIENT} // defaultMayModify +function TBoldAsFloatRenderer.HasSetValueEventOverrides: boolean; +begin + result := Assigned(FOnSetAsFloat); +end; + +function TBoldAsFloatRenderer.DefaultMayModify(aFollower: TBoldFollower): Boolean; +{$IFNDEF BOLDCOMCLIENT} var ValueElement: TBoldElement; {$ENDIF} begin - {$IFDEF BOLDCOMCLIENT} // defaultMayModify + {$IFDEF BOLDCOMCLIENT} result := inherited DefaultMayModify(Element, Representation, Expression, VariableList, Subscriber); {$ELSE} - // Note! We don't call inherited DefaultMayModify to prevent evaluation of expression two times! - ValueElement := GetExpressionAsDirectElement(Element, Expression, VariableList); - result := ((ValueElement is TBAFloat) or (ValueElement is TBADateTime)) and ValueElement.ObserverMayModify(Subscriber) + ValueElement := aFollower.Value; + result := ((ValueElement is TBAFloat) or (ValueElement is TBACurrency) {or (ValueElement is TBADateTime)}) and ValueElement.ObserverMayModify(aFollower.Subscriber) {$ENDIF} end; -function TBoldAsFloatRenderer.DefaultGetAsFloatAndSubscribe(Element: TBoldElement; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList; Subscriber: TBoldSubscriber): double; +function TBoldAsFloatRenderer.DefaultGetAsFloatAndSubscribe(aFollower: TBoldFollower; Subscriber: TBoldSubscriber): double; var {$IFDEF BOLDCOMCLIENT} // defaultGet el: IBoldElement; attr: IBoldAttribute; {$ELSE} IndirectElement: TBoldIndirectElement; - g: IBoldGuard; + lGuard: IBoldGuard; + lResultElement: TBoldElement; {$ENDIF} begin Result := 0; - if Assigned(Element) then + if Assigned(aFollower.Element) then begin {$IFDEF BOLDCOMCLIENT} // defaultGet if assigned(Subscriber) then @@ -136,34 +143,39 @@ function TBoldAsFloatRenderer.DefaultGetAsFloatAndSubscribe(Element: TBoldElemen else raise EBold.CreateFmt(sCannotGetFloatValueFromElement, [Attr.AsString]) {$ELSE} - g := TBoldGuard.Create(IndirectElement); - IndirectElement := TBoldIndirectElement.Create; - Element.EvaluateAndSubscribeToExpression(Expression, Subscriber, IndirectElement, False, False, VariableList); - if Assigned(IndirectElement.Value) then + lResultElement := aFollower.Value; + if not Assigned(lResultElement) then begin - if (IndirectElement.Value is TBANumeric) then - Result := TBANumeric(IndirectElement.Value).AsFloat - else if (IndirectElement.Value is TBADate) then - Result := TBADate(IndirectElement.Value).AsDate - else if (IndirectElement.Value is TBATime) then - Result := TBATime(IndirectElement.Value).AsTime - else if (IndirectElement.Value is TBADateTime) then - Result := TBADateTime(IndirectElement.Value).AsDateTime - else - raise EBold.CreateFmt(sCannotGetFloatValueFromElement, [IndirectElement.Value.ClassName]) + lGuard:= TBoldGuard.Create(IndirectElement); + IndirectElement := TBoldIndirectElement.Create; + aFollower.Element.EvaluateAndSubscribeToExpression(aFollower.AssertedController.Expression, Subscriber, IndirectElement, False, False, aFollower.Controller.GetVariableListAndSubscribe(Subscriber)); + lResultElement := IndirectElement.Value; + end; + if Assigned(lResultElement) then + begin + if (lResultElement is TBANumeric) then + Result := TBANumeric(lResultElement).AsFloat +{ else if (lResultElement is TBADate) then + Result := TBADate(lResultElement).AsDate + else if (lResultElement is TBATime) then + Result := TBATime(lResultElement).AsTime + else if (lResultElement is TBADateTime) then + Result := TBADateTime(lResultElement).AsDateTime +} else + raise EBold.CreateFmt('Can''t get float value from element (%s)', [lResultElement.ClassName]) end; {$ENDIF} end; end; -procedure TBoldAsFloatRenderer.DefaultSetAsFloat(Element: TBoldElement; const Value: double; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList); +procedure TBoldAsFloatRenderer.DefaultSetAsFloat(aFollower: TBoldFollower; const Value: double); var ValueElement: TBoldElement; {$IFDEF BOLDCOMCLIENT} // defaultSet attr: IBoldAttribute; {$ENDIF} begin - ValueElement := GetExpressionAsDirectElement(Element, Expression , VariableList); + ValueElement := aFollower.Value; {$IFDEF BOLDCOMCLIENT} // defaultSet if assigned(ValueElement) and (ValueElement.QueryInterface(IBoldAttribute, attr) = S_OK) then Attr.AsVariant := Value @@ -172,62 +184,61 @@ procedure TBoldAsFloatRenderer.DefaultSetAsFloat(Element: TBoldElement; const Va {$ELSE} if ValueElement is TBAFloat then TBAFloat(ValueElement).AsFloat := Value - else if ValueElement is TBADateTime then - TBADateTime(ValueElement).AsDateTime := Value else - raise EBold.CreateFmt(sCannotSetFloatValueOnElement, [ValueElement.ClassName]); + if ValueElement is TBACurrency then + TBACurrency(ValueElement).AsCurrency := Value +{ else + if ValueElement is TBADateTime then + TBADateTime(ValueElement).AsDateTime := Value} + else + raise EBold.CreateFmt('Can''t set float value on element (%s)', [ValueElement.ClassName]); {$ENDIF} end; -function TBoldAsFloatRenderer.GetAsFloatAndSubscribe(Element: TBoldElement; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList; Subscriber: TBoldSubscriber): double; +function TBoldAsFloatRenderer.GetAsFloatAndSubscribe(aFollower: TBoldFollower; Subscriber: TBoldSubscriber): double; begin if Assigned(OnSubscribe) and Assigned(Subscriber) then begin - if Assigned(Element) then - OnSubscribe(Element, Representation, Expression, Subscriber); + if Assigned(aFollower.Element) then + OnSubscribe(aFollower, Subscriber); Subscriber := nil; end; if Assigned(OnGetAsFloat) then - Result := OnGetAsFloat(Element, Representation, Expression) + Result := OnGetAsFloat(aFollower) else - Result := DefaultGetAsFloatAndSubscribe(Element, Representation, Expression, VariableList, Subscriber); + Result := DefaultGetAsFloatAndSubscribe(aFollower, Subscriber); end; -procedure TBoldAsFloatRenderer.SetAsFloat(Element: TBoldElement; const Value: double; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList); +procedure TBoldAsFloatRenderer.SetAsFloat(aFollower: TBoldFollower; const Value: double); begin if Assigned(FOnSetAsFloat) then - OnSetAsFloat(Element, Value, Representation, Expression) + OnSetAsFloat(aFollower, Value) else - DefaultSetAsFloat(Element, Value, Representation, Expression, VariableList) + DefaultSetAsFloat(aFollower, Value) end; -procedure TBoldAsFloatRenderer.MakeUptodateAndSubscribe(Element: TBoldElement; RendererData: TBoldRendererData; FollowerController: TBoldFollowerController; Subscriber: TBoldSubscriber); +procedure TBoldAsFloatRenderer.MakeUptodateAndSubscribe(aFollower: TBoldFollower; Subscriber: TBoldSubscriber); var Value: double; + lRendererData: TBoldFloatRendererData; begin - Value := GetAsFloatAndSubscribe(Element, - (FollowerController as TBoldFloatFollowerController).Representation, - (FollowerController as TBoldFloatFollowerController).Expression, - FollowerController.GetVariableListAndSubscribe(Subscriber), - Subscriber); - with (RendererData as TBoldFloatRendererData) do - begin - OldFloatValue := Value; - CurrentFloatValue := Value; - end; + Value := GetAsFloatAndSubscribe(aFollower, Subscriber); + lRendererData := (aFollower.RendererData as TBoldFloatRendererData); + lRendererData.OldFloatValue := Value; + lRendererData.CurrentFloatValue := Value; end; -function TBoldAsFloatRenderer.DefaultIsChanged(RendererData: TBoldFloatRendererData; const NewValue: double; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList): Boolean; +function TBoldAsFloatRenderer.DefaultIsChanged(aFollower: TBoldFollower; const NewValue: double): Boolean; begin - Result := NewValue <> RendererData.OldFloatValue; + Result := NewValue <> TBoldFloatRendererData(aFollower.RendererData).OldFloatValue; end; -function TBoldAsFloatRenderer.IsChanged(RendererData: TBoldFloatRendererData; const NewValue: double; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList): Boolean; +function TBoldAsFloatRenderer.IsChanged(aFollower: TBoldFollower; const NewValue: double): Boolean; begin if Assigned(FOnIsChanged) then - Result := FOnIsChanged(RendererData, NewValue, Representation, Expression) + Result := FOnIsChanged(aFollower, NewValue) else - Result := DefaultIsChanged(RendererData, NewValue, Representation, Expression, VariableList); + Result := DefaultIsChanged(aFollower, NewValue); end; { TBoldFloatFollowerController } @@ -279,7 +290,7 @@ function TBoldFloatFollowerController.GetCurrentAsFloat(Follower: TBoldFollower) procedure TBoldFloatFollowerController.SetAsFloat(Value: double; Follower: TBoldFollower); begin - EffectiveAsFloatRenderer.SetAsFloat(Follower.Element, Value, Representation, Expression, VariableList); + EffectiveAsFloatRenderer.SetAsFloat(Follower, Value); end; procedure TBoldFloatFollowerController.MayHaveChanged(NewValue: double; Follower: TBoldFollower); @@ -287,7 +298,8 @@ procedure TBoldFloatFollowerController.MayHaveChanged(NewValue: double; Follower if Follower.State in bfsDisplayable then begin (Follower.RendererData as TBoldFloatRendererData).CurrentFloatValue := NewValue; - Follower.ControlledValueChanged(EffectiveAsFloatRenderer.IsChanged(Follower.RendererData as TBoldFloatRendererData, NewValue, Representation, Expression, VariableList)); + if EffectiveAsFloatRenderer.IsChanged(Follower, NewValue) then + Follower.ControlledValueChanged; end; end; diff --git a/Source/BoldAwareGUI/ControlPacks/BoldGenericListControlPack.pas b/Source/BoldAwareGUI/ControlPacks/BoldGenericListControlPack.pas index cf41b92..2036cf0 100644 --- a/Source/BoldAwareGUI/ControlPacks/BoldGenericListControlPack.pas +++ b/Source/BoldAwareGUI/ControlPacks/BoldGenericListControlPack.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldGenericListControlPack; {$UNDEF BOLDCOMCLIENT} @@ -21,18 +24,18 @@ TBoldGenericListParts = class; TBoldFollowerListWithOwnedList = class; {$IFDEF BOLD_BCB} - TGetFollowerControllerByNameEvent = procedure (Name: string; var FollowerController: TBoldFollowerController) of object; + TGetFollowerControllerByNameEvent = procedure (const Name: string; var FollowerController: TBoldFollowerController) of object; TGetFollowerControllerEvent = procedure (Element: TBoldElement; Subscriber: TBoldSubscriber; GetFollowerControllerByName: TGetFollowerControllerByNameEvent; var FollowerController: TBoldFollowerController) of object; {$ENDIF} {$IFDEF BOLD_DELPHI} - TGetFollowerControllerByNameEvent = function (Name: string): TBoldFollowerController of object; + TGetFollowerControllerByNameEvent = function (const Name: string): TBoldFollowerController of object; TGetFollowerControllerEvent = function (Element: TBoldElement; Subscriber: TBoldSubscriber; GetFollowerControllerByName: TGetFollowerControllerByNameEvent): TBoldFollowerController of object; {$ENDIF} - {$IFNDEF BOLDCOMCLIENT} // GetElementEvent + {$IFNDEF BOLDCOMCLIENT} TGetElementEvent = procedure (Sender: TBoldGenericListPart; Element: TBoldElement; Subscriber: TBoldSubscriber; ResultElement: TBoldIndirectElement; Resubscribe: Boolean) of object; - {$ENDIF} + {$ENDIF} { TBoldFollowerListWithOwnedList } TBoldFollowerListWithOwnedList = class (TBoldFollowerList) @@ -41,8 +44,8 @@ TBoldFollowerListWithOwnedList = class (TBoldFollowerList) public constructor Create(OwningFollower: TBoldFollower); override; destructor Destroy; override; - procedure AddOwnedElement(Element: TBoldElement); - procedure FreeAllOwnedElements; + procedure AddOwnedElement(Element: TBoldElement); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure FreeAllOwnedElements; {$IFDEF BOLD_INLINE} inline; {$ENDIF} end; { TBoldGenericListPart } @@ -51,18 +54,18 @@ TBoldGenericListPart = class(TCollectionItem) FElementExpression: TBoldExpression; FControllerExpression: TBoldExpression; FInterpretAsList: Boolean; - {$IFNDEF BOLDCOMCLIENT} // GetElementEvent + {$IFNDEF BOLDCOMCLIENT} FOnGetElement: TGetElementEvent; {$ENDIF} FOnGetFollowerController: TGetFollowerControllerEvent; fEnabled: Boolean; fName: String; fPublisher: TBoldPublisher; - function GetPublisher: TBoldPublisher; - function GetContextType: TBoldElementTypeInfo; + function GetPublisher: TBoldPublisher; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetContextType: TBoldElementTypeInfo; {$IFDEF BOLD_INLINE} inline; {$ENDIF} - procedure SetElementExpression(Value: TBoldExpression); - procedure SetControllerExpression(Value: TBoldExpression); + procedure SetElementExpression(const Value: TBoldExpression); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure SetControllerExpression(const Value: TBoldExpression); {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure SetInterpretAsList(Value: Boolean); procedure SetEnabled(const Value: Boolean); property Publisher: TBoldPublisher read GetPublisher; @@ -70,7 +73,7 @@ TBoldGenericListPart = class(TCollectionItem) constructor Create(Collection: TCollection); override; destructor Destroy; override; procedure Assign(Source: TPersistent); override; - {$IFDEF BOLDCOMCLIENT} // GetElementEvent + {$IFDEF BOLDCOMCLIENT} function GetElement(Element: TBoldElement; Subscriber: TBoldSubscriber; Resubscribe: Boolean): IBoldElement; {$ELSE} procedure DefaultGetElement(Element: TBoldElement; Subscriber: TBoldSubscriber; ResultElement: TBoldIndirectElement; Resubscribe: Boolean); @@ -85,7 +88,7 @@ TBoldGenericListPart = class(TCollectionItem) property InterpretAsList: Boolean read FInterpretAsList write SetInterpretAsList; property Name: String read fName write fName; property Enabled: Boolean read fEnabled write SetEnabled default true; - {$IFNDEF BOLDCOMCLIENT} // GetElementEvent + {$IFNDEF BOLDCOMCLIENT} property OnGetElement: TGetElementEvent read FOnGetElement write FOnGetElement; {$ENDIF} property OnGetFollowerController: TGetFollowerControllerEvent read FOnGetFollowerController write FOnGetFollowerController; @@ -95,14 +98,14 @@ TBoldGenericListPart = class(TCollectionItem) TBoldGenericListParts = class(TCollection) private FOwner: TBoldGenericListController; - function GetPart(Index: Integer): TBoldGenericListPart; - procedure SetPart(Index: Integer; Value: TBoldGenericListPart); + function GetPart(Index: Integer): TBoldGenericListPart; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure SetPart(Index: Integer; Value: TBoldGenericListPart); {$IFDEF BOLD_INLINE} inline; {$ENDIF} protected function GetOwner: TPersistent; override; procedure Update(Item: TCollectionItem); override; public constructor Create(aOwner: TBoldGenericListController); - function Add: TBoldGenericListPart; + function Add: TBoldGenericListPart; {$IFDEF BOLD_INLINE} inline; {$ENDIF} property Items[Index: Integer]: TBoldGenericListPart read GetPart write SetPart; default; end; @@ -122,12 +125,13 @@ TBoldGenericListController = class(TBoldAsFollowerListController) private FParts: TBoldGenericListParts; FGetFollowerControllerByName: TGetFollowerControllerByNameEvent; - procedure SetParts(Value: TBoldGenericListParts); - function GetRenderer: TBoldGenericAsListRenderer; - procedure SetRenderer(Value: TBoldGenericAsListRenderer); + procedure SetParts(Value: TBoldGenericListParts); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetRenderer: TBoldGenericAsListRenderer; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure SetRenderer(Value: TBoldGenericAsListRenderer); {$IFDEF BOLD_INLINE} inline; {$ENDIF} protected + class function PrecreateFollowers: boolean; override; function GetEffectiveRenderer: TBoldRenderer; override; - function GetEffectiveGenericAsListRenderer: TBoldGenericAsListRenderer; + function GetEffectiveGenericAsListRenderer: TBoldGenericAsListRenderer; {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure DoMakeUptodateAndSubscribe(Follower: TBoldFollower; Subscribe: Boolean); override; procedure DoAssign(Source: TPersistent); override; property EffectiveGenericAsListRenderer: TBoldGenericAsListRenderer read GetEffectiveGenericAsListRenderer; @@ -135,8 +139,8 @@ TBoldGenericListController = class(TBoldAsFollowerListController) constructor Create(aOwningComponent: TComponent; GetFollowerControllerByNameFunc: TGetFollowerControllerByNameEvent); destructor Destroy; override; - function FindPartByName(Name: string): TBoldGenericListPart; - function CanHaveSubFollowers: Boolean; + function FindPartByName(const Name: string): TBoldGenericListPart; + function CanHaveSubFollowers: Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} published property Parts: TBoldGenericListParts read FParts write SetParts; property Renderer: TBoldGenericAsListRenderer read GetRenderer write SetRenderer; @@ -149,8 +153,7 @@ implementation BoldUtils, BoldContainers, BoldControlPackDefs, - BoldGuiResourceStrings, - {$IFNDEF BOLDCOMCLIENT} // uses + {$IFNDEF BOLDCOMCLIENT} BoldSystem, {$ENDIF} BoldNodeControlPack; @@ -186,7 +189,7 @@ procedure TBoldFollowerListWithOwnedList.FreeAllOwnedElements; constructor TBoldGenericListPart.Create(Collection: TCollection); begin inherited Create(Collection); - FControllerExpression := 'oclType.asstring->union(oclType.allsupertypes.asString)->union('''')'; // do not localize + FControllerExpression := 'oclType.asstring->union(oclType.allsupertypes.asString)->union('''')'; fEnabled := true; end; @@ -197,7 +200,7 @@ procedure TBoldGenericListPart.Assign(Source: TPersistent); ElementExpression := TBoldGenericListPart(Source).ElementExpression; ControllerExpression := TBoldGenericListPart(Source).ControllerExpression; InterpretAsList := TBoldGenericListPart(Source).InterpretAsList; - {$IFNDEF BOLDCOMCLIENT} // GetElementEvent + {$IFNDEF BOLDCOMCLIENT} OnGetElement := TBoldGenericListPart(Source).OnGetElement; {$ENDIF} OnGetFollowerController := TBoldGenericListPart(Source).OnGetFollowerController; @@ -206,7 +209,7 @@ procedure TBoldGenericListPart.Assign(Source: TPersistent); inherited Assign(Source); end; -procedure TBoldGenericListPart.SetElementExpression(Value: TBoldExpression); +procedure TBoldGenericListPart.SetElementExpression(const Value: TBoldExpression); begin if Value <> ElementExpression then begin @@ -215,7 +218,7 @@ procedure TBoldGenericListPart.SetElementExpression(Value: TBoldExpression); end; end; -procedure TBoldGenericListPart.SetControllerExpression(Value: TBoldExpression); +procedure TBoldGenericListPart.SetControllerExpression(const Value: TBoldExpression); begin if Value <> ControllerExpression then begin @@ -233,7 +236,7 @@ procedure TBoldGenericListPart.SetInterpretAsList(Value: Boolean); end; end; -{$IFDEF BOLDCOMCLIENT} // GetElementEvent +{$IFDEF BOLDCOMCLIENT} function TBoldGenericListPart.GetElement(Element: TBoldElement; Subscriber: TBoldSubscriber; Resubscribe: Boolean): IBoldElement; begin if Assigned(Element) then @@ -268,7 +271,7 @@ procedure TBoldGenericListPart.GetElement(Element: TBoldElement; Subscriber: TBo function TBoldGenericListPart.DefaultGetFollowerController(Element: TBoldElement; Subscriber: TBoldSubscriber; GetFollowerControllerByName: TGetFollowerControllerByNameEvent): TBoldFollowerController; var -{$IFDEF BOLDCOMCLIENT} // DefaultGet +{$IFDEF BOLDCOMCLIENT} e: IBoldElement; {$ELSE} E: TBoldIndirectElement; @@ -296,7 +299,7 @@ function LoopList(List: TBoldList): TBoldFollowerController; begin Result := nil; - {$IFDEF BOLDCOMCLIENT} // DefaultGet + {$IFDEF BOLDCOMCLIENT} e := Element.EvaluateAndSubscribeToExpression(ControllerExpression, Subscriber.ClientId, Subscriber.SubscriberId, False, false); if Assigned(E) then begin @@ -344,7 +347,7 @@ function TBoldGenericListPart.GetFollowerController(Element: TBoldElement; Subsc except on E: Exception do begin - E.message := Format(sCouldNotGetController, [E.message, BOLDCRLF, GetNamePath]); + E.message := Format('%s' + BOLDCRLF + 'occured when getting controller for component %s', [E.message, GetNamePath]); raise; end; end; @@ -388,6 +391,11 @@ function TBoldGenericListController.GetRenderer: TBoldGenericAsListRenderer; Result := (UntypedRenderer as TBoldGenericAsListRenderer); end; +class function TBoldGenericListController.PrecreateFollowers: boolean; +begin + result := true; +end; + procedure TBoldGenericListController.SetRenderer(Value: TBoldGenericAsListRenderer); begin UntypedRenderer := Value; @@ -457,7 +465,7 @@ procedure TBoldGenericAsListRenderer.MakeUptodate(Follower: TBoldFollower; FollowerController := Part.GetFollowerController(Element, Follower.Subscriber, GetFollowerControllerByName); if Assigned(FollowerController) then begin - DestList.EnsureFollower(Controller, DestListIndex, Element, FollowerController); + DestList.EnsuredFollower(Controller, DestListIndex, Element, FollowerController); Inc(DestListIndex); end; end; @@ -466,7 +474,7 @@ procedure TBoldGenericAsListRenderer.MakeUptodate(Follower: TBoldFollower; {$IFDEF BOLDCOMCLIENT} begin element := part.GetElement(Follower.Element, Follower.Subscriber, False); - result := assigned(element); // fixme: true or false? + result := assigned(element); end; {$ELSE} var @@ -475,12 +483,11 @@ procedure TBoldGenericAsListRenderer.MakeUptodate(Follower: TBoldFollower; ie := TBoldIndirectElement.Create; try Part.GetElement(Follower.Element, Follower.Subscriber, ie, False); - if ie.OwnsValue then + result := ie.OwnsValue; + if result then Element := ie.RelinquishValue else Element := ie.Value; - - result := ie.OwnsValue; finally ie.Free; end; @@ -499,7 +506,7 @@ procedure TBoldGenericAsListRenderer.MakeUptodate(Follower: TBoldFollower; DestList.AddOwnedElement(Element); if Assigned(Element) then begin - {$IFDEF BOLDCOMCLIENT} // listconverting + {$IFDEF BOLDCOMCLIENT} Element.QueryInterface(IBoldList, SourceList); {$ELSE} if element is TBoldList then @@ -561,7 +568,7 @@ destructor TBoldGenericListPart.Destroy; inherited; end; -function TBoldGenericListController.FindPartByName(Name: string): TBoldGenericListPart; +function TBoldGenericListController.FindPartByName(const Name: string): TBoldGenericListPart; var i: integer; begin diff --git a/Source/BoldAwareGUI/ControlPacks/BoldListControlPack.pas b/Source/BoldAwareGUI/ControlPacks/BoldListControlPack.pas index 87b8d56..98c793c 100644 --- a/Source/BoldAwareGUI/ControlPacks/BoldListControlPack.pas +++ b/Source/BoldAwareGUI/ControlPacks/BoldListControlPack.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldListControlPack; {$UNDEF BOLDCOMCLIENT} @@ -8,7 +11,7 @@ interface BoldDefs, Classes, BoldElements, - {$IFNDEF BOLDCOMCLIENT} // uses + {$IFNDEF BOLDCOMCLIENT} BoldSystem, {$ENDIF} BoldSubscription, @@ -24,27 +27,32 @@ TBoldFollowerList = class; TBoldAsFollowerListController = class(TBoldFollowerController) private fOnBeforeInsertItem: TBoldSubFollowerEvent; - fOnAfterInsertItem: TBoldFollowerEvent; - fOnBeforeDeleteItem: TBoldFollowerEvent; + fOnAfterInsertItem: TBoldSubFollowerEvent; + fOnBeforeDeleteItem: TBoldSubFollowerEvent; fOnAfterDeleteItem: TBoldSubFollowerEvent; + fOnReplaceItem: TBoldSubFollowerEvent; protected - procedure DoBeforeInsertItem(index: Integer; OwningFollower: TBoldFollower); - procedure DoAfterInsertItem(Follower: TBoldFollower); - procedure DoBeforeDeleteItem(Follower: TBoldFollower); - procedure DoAfterDeleteItem(index: Integer; OwningFollower: TBoldFollower); + procedure DoBeforeInsertItem(index: Integer; OwningFollower: TBoldFollower); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure DoAfterInsertItem(index: Integer; Follower: TBoldFollower); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure DoBeforeDeleteItem(index: Integer; Follower: TBoldFollower); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure DoAfterDeleteItem(index: Integer; OwningFollower: TBoldFollower); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure DoReplaceItem(index: Integer; Follower: TBoldFollower); {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure CleanRendererData(RendererData: TBoldRendererData); override; public + class function PrecreateFollowers: boolean; virtual; constructor Create(aOwningComponent: TComponent); procedure SetActiveRange(Follower: TBoldFollower; FirstActive: Integer; LastActive: Integer; RangeBuffer: Integer = 1); procedure SelectAll(Follower: TBoldFollower; SetSelect: Boolean); {Maybe make available in renderer?} - procedure SelectRange(Follower: TBoldFollower; index: Integer); - procedure SetSelected(Follower: TBoldFollower; index: Integer; Value: Boolean); - procedure ToggleSelected(Follower: TBoldFollower; index: Integer); - function GetSelected(Follower: TBoldFollower; index: Integer): Boolean; + procedure SelectRange(Follower: TBoldFollower; index: Integer); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure SetSelected(Follower: TBoldFollower; index: Integer; Value: Boolean); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure ToggleSelected(Follower: TBoldFollower; index: Integer); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure AddSelectedToList(Follower: TBoldFollower; BoldList: TBoldList); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetSelected(Follower: TBoldFollower; index: Integer): Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} property OnBeforeInsertItem: TBoldSubFollowerEvent read fOnBeforeInsertItem write fOnBeforeInsertItem; - property OnAfterInsertItem: TBoldFollowerEvent read fOnAfterInsertItem write fOnAfterInsertItem; - property OnBeforeDeleteItem: TBoldFollowerEvent read fOnBeforeDeleteItem write fOnBeforeDeleteItem; + property OnAfterInsertItem: TBoldSubFollowerEvent read fOnAfterInsertItem write fOnAfterInsertItem; + property OnBeforeDeleteItem: TBoldSubFollowerEvent read fOnBeforeDeleteItem write fOnBeforeDeleteItem; property OnAfterDeleteItem: TBoldSubFollowerEvent read fOnAfterDeleteItem write fOnAfterDeleteItem; + property OnReplaceitem: TBoldSubFollowerEvent read fOnReplaceItem write fOnReplaceItem; end; {--- TBoldAsFollowerListRenderer ---} @@ -64,28 +72,34 @@ TBoldFollowerList = class(TBoldRendererData) FPrevSelected: Integer; function GetSelectedCount: Integer; procedure SetSelected(index: Integer; V: Boolean); - function GetSelected(index: Integer): Boolean; -// procedure UnselectPrev; + function GetSelected(index: Integer): Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function UnsafeGetSelected(index: Integer): Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure Insert(ListFollowerController: TBoldAsFollowerListController; Index: Integer; Follower: TBoldFollower); procedure Delete(ListFollowerController: TBoldAsFollowerListController; index: Integer); + procedure Replace(ListFollowerController: TBoldAsFollowerListController; index: Integer; Follower: TBoldFollower); + function GetBoldList: TBoldList; protected + function UnsafeGetSubFollower(Index: Integer): TBoldFollower; {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure EnsureSubfollowersDisplayable; override; function GetSubFollowerCount: Integer; override; function GetSubFollower(Index: Integer): TBoldFollower; override; + function GetEnsuredSubFollower(Index: Integer): TBoldFollower; override; function GetCurrentSubFollowerIndex: Integer; override; procedure SetCurrentSubFollowerIndex(index: integer); override; + function GetSubFollowerAssigned(Index: Integer): boolean; override; public constructor Create(OwningFollower: TBoldFollower); override; destructor Destroy; override; + procedure SetCapacity(aNewCapacity: integer); procedure SetActiveRange(FirstActive, LastActive: Integer); procedure SelectAll(SetSelect: Boolean); procedure SelectRange(index: Integer); procedure AddSelectedToList(BoldList: TBoldList); procedure PurgeEnd(ListFollowerController: TBoldAsFollowerListController; PurgeCount: Integer); - procedure EnsureFollower(ListFollowerController: TBoldAsFollowerListController; - Index: Integer; - Element: TBoldElement; - Controller: TBoldFollowerController); { may disturb list after index} + function EnsuredFollower(aListFollowerController: TBoldAsFollowerListController; + aIndex: Integer; + aElement: TBoldElement; + aController: TBoldFollowerController): TBoldFollower; { may disturb list after index} property Followers[index: Integer]: TBoldFollower read GetSubFollower; default; property Count: Integer read GetSubFollowerCount; property FirstActive: Integer read FFirstActive; @@ -93,13 +107,16 @@ TBoldFollowerList = class(TBoldRendererData) property SelectedCount: Integer read GetSelectedCount; property Selected[index: Integer]: Boolean read GetSelected write SetSelected; property CurrentItem: Integer read FCurrentItem write FCurrentItem; + property BoldList: TBoldList read GetBoldList; end; implementation uses SysUtils, - BoldUtils; + BoldUtils, + BoldControllerListControlPack, + BoldListListControlPack; {---TBoldAsFollowerListController---} @@ -114,16 +131,23 @@ procedure TBoldAsFollowerListController.DoBeforeInsertItem(index: Integer; Ownin FOnBeforeInsertItem(index, OwningFollower); end; -procedure TBoldAsFollowerListController.DoAfterInsertItem(Follower: TBoldFollower); +procedure TBoldAsFollowerListController.DoReplaceItem(index: Integer; + Follower: TBoldFollower); +begin + if Assigned(fOnReplaceItem) then + fOnReplaceItem(index, Follower); +end; + +procedure TBoldAsFollowerListController.DoAfterInsertItem(index: Integer; Follower: TBoldFollower); begin if Assigned(FOnAfterInsertItem) then - FOnAfterInsertItem(Follower); + FOnAfterInsertItem(index, Follower); end; -procedure TBoldAsFollowerListController.DoBeforeDeleteItem(Follower: TBoldFollower); +procedure TBoldAsFollowerListController.DoBeforeDeleteItem(index: Integer; Follower: TBoldFollower); begin if Assigned(FOnBeforeDeleteItem) then - FOnBeforeDeleteItem(Follower); + FOnBeforeDeleteItem(index, Follower); end; procedure TBoldAsFollowerListController.DoAfterDeleteItem(index: Integer; OwningFollower: TBoldFollower); @@ -134,12 +158,14 @@ procedure TBoldAsFollowerListController.DoAfterDeleteItem(index: Integer; Owning procedure TBoldAsFollowerListController.SetActiveRange(Follower: TBoldFollower; FirstActive, LastActive: Integer; RangeBuffer: Integer = 1); begin - if Assigned(EffectiveRenderer) then // may be nil after finalization + if Assigned(EffectiveRenderer) then (EffectiveRenderer as TBoldAsFollowerListRenderer).SetActiveRange(Follower, FirstActive, LastActive, RangeBuffer); end; procedure TBoldAsFollowerListController.SelectAll(Follower: TBoldFollower; SetSelect: Boolean); begin + if SetSelect {and Follower.ElementValid and (Follower.Element is TBoldList)} then + TBoldAbstractListAsFollowerListController(Follower.Controller).SetActiveRange(Follower, 0, MaxInt); (Follower.RendererData as TBoldFollowerList).SelectAll(SetSelect) end; @@ -155,7 +181,8 @@ procedure TBoldAsFollowerListController.SetSelected(Follower: TBoldFollower; ind procedure TBoldAsFollowerListController.ToggleSelected(Follower: TBoldFollower; index: Integer); begin - (Follower.RendererData as TBoldFollowerList).Selected[index] := not (Follower.RendererData as TBoldFollowerList).Selected[index]; + with (Follower.RendererData as TBoldFollowerList) do + Selected[index] := not Selected[index]; end; function TBoldAsFollowerListController.GetSelected(Follower: TBoldFollower; index: Integer): Boolean; @@ -179,40 +206,64 @@ constructor TBoldFollowerList.Create(OwningFollower: TBoldFollower); begin inherited Create(OwningFollower); FArray := TList.Create; - FLastActive := High(FLastActive); FCurrentItem := -1; + FLastActive := MaxInt; +end; + +function TBoldFollowerList.UnsafeGetSubFollower( + Index: Integer): TBoldFollower; +begin + Result := TBoldFollower(FArray[index]) end; destructor TBoldFollowerList.Destroy; var I: Integer; + Follower: TBoldFollower; +// lBoldTreeNode: TBoldTreeNode; begin - for I := 0 to Count - 1 do - Followers[I].Free; + for I := Count - 1 downto 0 do + begin +{ Follower := UnsafeGetSubFollower(I); + if Assigned(Follower) and Assigned(Follower.ControlData) then + begin + lBoldTreeNode := Follower.ControlData as TBoldTreeNode; + lBoldTreeNode.Follower := nil; + end; +} + UnsafeGetSubFollower(I).free; + end; FreeAndNil(FArray); inherited; end; procedure TBoldFollowerList.SetActiveRange(FirstActive, LastActive: Integer); var - I: Integer; + lIndex: Integer; + lFollower: TBoldFollower; + lActive: boolean; begin FFirstActive := FirstActive; FLastActive := LastActive; - for I := 0 to Count - 1 do + for lIndex := 0 to Count - 1 do begin - Followers[I].Active := (I >= FirstActive) and (I <= LastActive); + lActive := (lIndex >= FirstActive) and (lIndex <= LastActive); + if lActive then + lFollower := GetSubFollower(lIndex) + else + lFollower := UnsafeGetSubFollower(lIndex); + if Assigned(lFollower) then + lFollower.Active := lActive; end; end; - function TBoldFollowerList.GetSelectedCount: Integer; var Row: Integer; begin Result := 0; for Row := 0 to Count - 1 do - if Selected[Row] then + if UnsafeGetSelected(Row) then Inc(Result); end; @@ -222,11 +273,65 @@ function TBoldFollowerList.GetSubFollowerCount: Integer; end; function TBoldFollowerList.GetSubFollower(Index: Integer): TBoldFollower; + procedure InternalRaise; + begin + Assert( Cardinal(Index) < Cardinal(fArray.Count), 'TBoldFollowerList.GetSubFollower index out of range.' + IntToStr(Index) + '/' + IntToStr(fArray.count)); + end; + +begin + if Cardinal(Index) >= Cardinal(fArray.Count) then + InternalRaise; + Result := TBoldFollower(FArray[index]); + if not Assigned(Result) then + begin + if (OwningFollower.Controller is TBoldControllerList) then + begin + result := EnsuredFollower( + OwningFollower.Controller as TBoldAsFollowerListController, + Index, + OwningFollower.element, + TBoldControllerList(OwningFollower.Controller)[Index]); + FArray[index] := result; + Assert(Assigned(result)); + end; + end; +end; + +function TBoldFollowerList.GetEnsuredSubFollower( + Index: Integer): TBoldFollower; +var + BoldAsFollowerListController: TBoldAsFollowerListController; +begin + result := GetSubFollower(Index); + if not Assigned(result) then + begin + BoldAsFollowerListController := nil; + if (OwningFollower.Controller is TBoldControllerList) then + BoldAsFollowerListController := OwningFollower.Controller as TBoldControllerList + else + if (OwningFollower.Controller is TBoldListAsFollowerListController) then + BoldAsFollowerListController := TBoldListAsFollowerListController(OwningFollower.Controller); + + if Assigned(BoldAsFollowerListController) then + begin +// Delete(OwningFollower.Controller as TBoldAsFollowerListController, Index); + result := TBoldFollower.CreateSubFollower(OwningFollower, BoldAsFollowerListController, OwningFollower.element, true, Index); + Replace(BoldAsFollowerListController, Index, result); +// Insert(OwningFollower.Controller as TBoldAsFollowerListController, Index, result); + end; + end; +end; + +function TBoldFollowerList.GetBoldList: TBoldList; begin - if (index >= 0) and (index < fArray.Count) then - Result := TBoldFollower(FArray[index]) + Assert(Assigned(OwningFollower)); + if OwningFollower.Element = nil then + result := nil else - result := nil; + begin + Assert(OwningFollower.Element is TBoldList); + result := OwningFollower.Element as TBoldList; + end; end; function TBoldFollowerList.GetCurrentSubFollowerIndex: Integer; @@ -238,7 +343,7 @@ procedure TBoldFollowerList.SetSelected(index: Integer; V: Boolean); begin if (index > -1) and (index < Count) and - (Followers[index].Selected <> V) then + Assigned(Followers[index]) and (Followers[index].Selected <> V) then begin if V then FPrevSelected := index; @@ -246,17 +351,34 @@ procedure TBoldFollowerList.SetSelected(index: Integer; V: Boolean); end; end; +function TBoldFollowerList.GetSubFollowerAssigned(Index: Integer): boolean; +begin + if Index < Count then + Result := Assigned(UnsafeGetSubFollower(index)) + else + result := false; +end; + function TBoldFollowerList.GetSelected(index: Integer): Boolean; begin - Result := Followers[index].Selected; + Result := Assigned(Followers[index]) and Followers[index].Selected; end; procedure TBoldFollowerList.SelectAll(SetSelect: Boolean); var Row: Integer; + lFollower: TBoldFollower; begin for Row := 0 to Count - 1 do - Followers[Row].Selected := SetSelect; + begin + if SetSelect then + lFollower := GetEnsuredSubFollower(Row) + else + lFollower := UnsafeGetSubFollower(Row); + Assert(not SetSelect or Assigned(lFollower)); + if Assigned(lFollower) then + lFollower.Selected := SetSelect; + end; end; procedure TBoldFollowerList.SelectRange(index: Integer); @@ -285,64 +407,166 @@ procedure TBoldFollowerList.UnselectPrev; procedure TBoldFollowerList.AddSelectedToList(BoldList: TBoldList); var Row: Integer; + lBoldFollower: TBoldFollower; begin for Row := 0 to Count - 1 do - if (Followers[Row].Selected) and - Assigned(Followers[Row].Element) and - BoldTestType(Followers[Row].Element, TBoldObject) then - BoldList.Add(Followers[Row].Element); + begin + lBoldFollower := UnsafeGetSubFollower(Row); + if Assigned(lBoldFollower) and (lBoldFollower.Selected) and + Assigned(lBoldFollower.Element) and + BoldTestType(lBoldFollower.Element, TBoldObject) then + BoldList.Add(lBoldFollower.Element); + end; end; procedure TBoldFollowerList.Delete(ListFollowerController: TBoldAsFollowerListController; Index: Integer); var I: Integer; + lFollower: TBoldFollower; begin - ListFollowerController.DoBeforeDeleteItem(Followers[index]); - Followers[index].Free; + lFollower := UnsafeGetSubFollower(index); + begin + ListFollowerController.DoBeforeDeleteItem(index, lFollower); + lFollower.Free; + end; FArray.Delete(index); for I := index to Count - 1 do - Followers[I].Index := I; + begin + lFollower := UnsafeGetSubFollower(I); + if Assigned(lFollower) then + lFollower.Index := I; + end; ListFollowerController.DoAfterDeleteItem(Index, OwningFollower); end; procedure TBoldFollowerList.Insert(ListFollowerController: TBoldAsFollowerListController; Index: Integer; Follower: TBoldFollower); var I: Integer; + lFollower: TBoldFollower; begin ListFollowerController.DoBeforeInsertItem(Index, OwningFollower); FArray.Insert(index, Follower); - for I := index to Count - 1 do - Followers[I].Index := I; - ListFollowerController.DoAfterInsertItem(Followers[Index]); + Assert(not Assigned(Follower) or (Follower.index = index)); + for I := index+1 to Count - 1 do + begin + lFollower := UnsafeGetSubFollower(I); + if Assigned(lFollower) then + lFollower.Index := I; + end; + ListFollowerController.DoAfterInsertItem(Index, Follower); +end; + +procedure TBoldFollowerList.Replace(ListFollowerController: TBoldAsFollowerListController; Index: Integer; Follower: TBoldFollower); +begin + ListFollowerController.DoReplaceItem(Index, Follower); + FArray[Index] := Follower; end; procedure TBoldFollowerList.PurgeEnd(ListFollowerController: TBoldAsFollowerListController; PurgeCount: Integer); var I: Integer; begin - TBoldPublisher.StartNotify; - try - for I := Count - 1 downto PurgeCount do - Delete(ListFollowerController, I); - finally - TBoldPublisher.EndNotify; + if Count > PurgeCount then + begin + TBoldPublisher.StartNotify; + try + for I := Count - 1 downto PurgeCount do + Delete(ListFollowerController, I); + finally + TBoldPublisher.EndNotify; + end; end; end; -procedure TBoldFollowerList.EnsureFollower(ListFollowerController: TBoldAsFollowerListController; - Index: Integer; - Element: TBoldElement; - Controller: TBoldFollowerController); +function TBoldFollowerList.EnsuredFollower(aListFollowerController: TBoldAsFollowerListController; + aIndex: Integer; + aElement: TBoldElement; + aController: TBoldFollowerController): TBoldFollower; +var + lBoldFollower: TBoldFollower; + lActive: boolean; begin - if (element = nil) and (index < Count) and (Followers[index].Controller = Controller) then - Followers[index].Element := Element; - if (index < Count) and (Followers[index].Element = Element) and (Followers[index].Controller = Controller) then - {all ok} - else if (index + 1 < Count) and (Followers[index + 1].Element = Element) and (Followers[index + 1].Controller = Controller) then - Delete(ListFollowerController, Index) + result := nil; + lActive := (aIndex <= LastActive) and (aIndex >= FirstActive); // and not aController.DelayedActivate; + if (not Assigned(aElement) or not lActive) and not (aListFollowerController.PrecreateFollowers) then + begin + if (aIndex >= Count) then + begin + Assert(aIndex = Count); + Insert(aListFollowerController, aIndex, nil); + end + else + begin + result := TBoldFollower(FArray[aIndex]); + if (not Assigned(result) and Assigned(aElement)) then + begin +// Delete(aListFollowerController, aIndex); + lBoldFollower := TBoldFollower.CreateSubFollower(OwningFollower, aController, aElement, lActive, aIndex); + Replace(aListFollowerController, aIndex, lBoldFollower); +// Insert(aListFollowerController, aIndex, lBoldFollower); + result := lBoldFollower; + end + else + begin + if (Assigned(result) and not Assigned(aElement) and ((result.Controller <> aController))) then + begin + Insert(aListFollowerController, aIndex, nil); + result := nil; + end; + end; + end; + exit; + end; + if (aIndex < Count) then + begin + lBoldFollower := UnsafeGetSubFollower(aIndex); + if Assigned(lBoldFollower) then + begin + if (lBoldFollower.Element = aElement) and (lBoldFollower.Controller = aController) then + begin + result := lBoldFollower; + result.Active := lActive; + exit; + end + else + begin + Assert(Assigned(aListFollowerController), lBoldFollower.className ); +// if (lBoldFollower.Controller = aController) +// begin +// lBoldFollower.SetElementAndMakeCurrent(AElement, lActive); +// Replace(aListFollowerController, aIndex, lBoldFollower); +// result := lBoldFollower; +// end +// else + begin + Delete(aListFollowerController, aIndex); + lBoldFollower := TBoldFollower.CreateSubFollower(OwningFollower, aController, aElement, lActive, aIndex); + Insert(aListFollowerController, aIndex, lBoldFollower); + result := lBoldFollower; + end; + end; + end + else + begin +// Delete(aListFollowerController, aIndex); + lBoldFollower := TBoldFollower.CreateSubFollower(OwningFollower, aController, aElement, lActive, aIndex); + Replace(aListFollowerController, aIndex, lBoldFollower); +// Insert(aListFollowerController, aIndex, lBoldFollower); + result := lBoldFollower; + end; + end else - Insert(ListFollowerController, index, TBoldFollower.CreateSubFollower(OwningFollower, Controller, Element)); - Followers[index].Active := (index >= FirstActive) and (index <= LastActive); + begin + lBoldFollower := TBoldFollower.CreateSubFollower(OwningFollower, aController, aElement, lActive, aIndex); + Insert(aListFollowerController, aIndex, lBoldFollower); + result := lBoldFollower; + end; +end; + +procedure TBoldFollowerList.SetCapacity(aNewCapacity: integer); +begin + if aNewCapacity > FArray.Capacity then + FArray.Capacity := aNewCapacity; end; procedure TBoldFollowerList.SetCurrentSubFollowerIndex(index: integer); @@ -353,12 +577,17 @@ procedure TBoldFollowerList.SetCurrentSubFollowerIndex(index: integer); procedure TBoldFollowerList.EnsureSubfollowersDisplayable; var - i: integer; + lIndex: integer; + lBoldFollower: TBoldFollower; begin - for I := 0 to Count - 1 do - with Followers[I] do - if Active then - EnsureDisplayable; + for lIndex := 0 to Count - 1 do + begin + lBoldFollower := UnsafeGetSubFollower(lIndex); + if Assigned(lBoldFollower) and not lBoldFollower.Displayable and lBoldFollower.Active then + begin + lBoldFollower.EnsureDisplayable; + end; + end; end; procedure TBoldAsFollowerListController.CleanRendererData(RendererData: TBoldRendererData); @@ -367,5 +596,21 @@ procedure TBoldAsFollowerListController.CleanRendererData(RendererData: TBoldRen (RendererData as TBoldFollowerList).PurgeEnd(self, 0); end; -end. +procedure TBoldAsFollowerListController.AddSelectedToList(Follower: TBoldFollower; + BoldList: TBoldList); +begin + (Follower.RendererData as TBoldFollowerList).AddSelectedToList(BoldList); +end; + +function TBoldFollowerList.UnsafeGetSelected(index: Integer): Boolean; +begin + Result := UnsafeGetSubFollower(index).Selected; +end; +class function TBoldAsFollowerListController.PrecreateFollowers: boolean; +begin + result := false; +end; + +initialization +end. diff --git a/Source/BoldAwareGUI/ControlPacks/BoldListHandleFollower.pas b/Source/BoldAwareGUI/ControlPacks/BoldListHandleFollower.pas index bf7f54f..caea797 100644 --- a/Source/BoldAwareGUI/ControlPacks/BoldListHandleFollower.pas +++ b/Source/BoldAwareGUI/ControlPacks/BoldListHandleFollower.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldListHandleFollower; {$UNDEF BOLDCOMCLIENT} @@ -12,39 +15,34 @@ interface BoldSubscription, BoldControlPack, BoldListListControlPack, - BoldAbstractListHandle; + BoldAbstractListHandle, + BoldHandles; -// Note, Currently subscibes to value-identity-change via element of handle, until -// subscribability has been added to the handle. type { forward declarations } TBoldListHandleFollower = class; { TBoldListHandleFollower } - TBoldListHandleFollower = class(TBoldQueueable) + TBoldListHandleFollower = class(TBoldAbstractHandleFollower) private fBoldHandle: TBoldAbstractListHandle; - fFollower: TBoldFollower; fFollowerValueCurrent: Boolean; fHandleIndexLock: Boolean; - fSubscriber: TBoldSubscriber; procedure SetFollowerValueCurrent(value: Boolean); procedure SetBoldHandle(value: TBoldAbstractListHandle); property FollowerValueCurrent: Boolean read fFollowerValueCurrent write SetFollowerValueCurrent; protected - procedure Receive(Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent); + function GetBoldHandle: TBoldElementHandle; override; + procedure Receive(Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent); override; procedure Display; override; - property Subscriber: TBoldSubscriber read fSubscriber; public procedure Apply; override; procedure DiscardChange; override; procedure SetFollowerIndex(index: integer); property BoldHandle: TBoldAbstractListHandle read FBoldHandle write SetBoldHandle; property HandleIndexLock: boolean read fHandleIndexLock write fHandleIndexLock default True; - property Follower: TBoldFollower read fFollower; - constructor Create(MatchObject: TObject; Controller: TBoldAbstractListAsFollowerListController); - destructor Destroy; override; + constructor Create(AMatchObject: TObject; Controller: TBoldAbstractListAsFollowerListController); end; implementation @@ -69,31 +67,20 @@ procedure TBoldListHandleFollower.Receive(Originator: TObject; end; end; -constructor TBoldListHandleFollower.Create(MatchObject: TObject; +constructor TBoldListHandleFollower.Create(AMatchObject: TObject; Controller: TBoldAbstractListAsFollowerListController); begin - inherited Create(nil); - fSubscriber := TBoldPassthroughSubscriber.Create(Receive); - fFollower := TBoldFollower.Create(MatchObject, Controller); - fFollower.PrioritizedQueuable := Self; + inherited Create(AMatchObject, Controller); fFollowerValueCurrent := true; fHandleIndexLock := true; end; -destructor TBoldListHandleFollower.Destroy; -begin - FreeAndNil(fFollower); - FreeAndNil(fSubscriber); - inherited; -end; - procedure TBoldListHandleFollower.SetBoldHandle( value: TBoldAbstractListHandle); begin if (value <> BoldHandle) then begin fBoldHandle := Value; - // will force subscription on Handle FollowerValueCurrent := false; end; end; @@ -119,13 +106,13 @@ procedure TBoldListHandleFollower.SetFollowerValueCurrent(value: Boolean); Assert(Assigned(Follower)); if Assigned(BoldHandle) then begin - fFollower.Element := BoldHandle.List; + Follower.Element := BoldHandle.List; if (HandleIndexLock) then - SetfollowerIndex((Follower.Controller as TBoldAbstractListAsFollowerListController).ListIndex(BoldHandle.CurrentIndex)); + SetFollowerIndex((Follower.Controller as TBoldAbstractListAsFollowerListController).ListIndex(BoldHandle.CurrentIndex)); end else begin - fFollower.Element := nil; + Follower.Element := nil; end; end; @@ -133,8 +120,8 @@ procedure TBoldListHandleFollower.SetFollowerValueCurrent(value: Boolean); begin if Assigned(BoldHandle) then begin - BoldHandle.AddSmallSubscription(Subscriber, [beValueIdentityChanged], breListIdentityChanged); // FIXME - BoldHandle.AddSmallSubscription(Subscriber, [beValueIdentityChanged], breHandleIndexChanged); // FIXME + BoldHandle.AddSmallSubscription(Subscriber, [beValueIdentityChanged], breListIdentityChanged); + BoldHandle.AddSmallSubscription(Subscriber, [beValueIdentityChanged], breHandleIndexChanged); end; end; @@ -150,7 +137,7 @@ procedure TBoldListHandleFollower.SetFollowerValueCurrent(value: Boolean); if Value then begin PropagateValue; - RemoveFromDisplayList; + RemoveFromDisplayList(false); Subscribe; end else @@ -177,5 +164,11 @@ procedure TBoldListHandleFollower.SetFollowerIndex(index: integer); BoldHandle.CurrentIndex := NewHandleIndex; end; -end. +function TBoldListHandleFollower.GetBoldHandle: TBoldElementHandle; +begin + result := fBoldHandle; +end; + +initialization +end. diff --git a/Source/BoldAwareGUI/ControlPacks/BoldListListControlPack.pas b/Source/BoldAwareGUI/ControlPacks/BoldListListControlPack.pas index a48b8ad..735c82c 100644 --- a/Source/BoldAwareGUI/ControlPacks/BoldListListControlPack.pas +++ b/Source/BoldAwareGUI/ControlPacks/BoldListListControlPack.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldListListControlPack; {$UNDEF BOLDCOMCLIENT} @@ -5,7 +8,7 @@ interface uses - Classes, + Classes, BoldDefs, BoldElements, BoldControlPackDefs, @@ -25,28 +28,28 @@ TBoldAbstractListAsFollowerListController = class(TBoldAsFollowerListControlle fDefaultDblClick: Boolean; fFollowerController: TBoldFollowerController; fNilElementMode: TBoldNilElementMode; - function GetRenderer: TBoldListAsFollowerListRenderer; - procedure SetRenderer(Value: TBoldListAsFollowerListRenderer); + function GetRenderer: TBoldListAsFollowerListRenderer; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure SetRenderer(Value: TBoldListAsFollowerListRenderer); {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure SetNilElementMode(const Value: TBoldNilElementMode); protected + class function PrecreateFollowers: boolean; override; function GetEffectiveRenderer: TBoldRenderer; override; - function GetEffectiveListAsFollowerListRenderer: TBoldListAsFollowerListRenderer; + function GetEffectiveListAsFollowerListRenderer: TBoldListAsFollowerListRenderer; {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure DoMakeUptodateAndSubscribe(Follower: TBoldFollower; Subscribe: Boolean); override; procedure DoAssign(Source: TPersistent); override; property EffectiveListAsFollowerListRenderer: TBoldListAsFollowerListRenderer read GetEffectiveListAsFollowerListRenderer; property DefaultDblClick: Boolean read fDefaultDblClick write fDefaultDblClick default True; - property DragMode default bdgSelection; - property DropMode default bdpAppend; + property DragMode; + property DropMode; property InternalDrag: Boolean read fInternalDrag write fInternalDrag default True; property Renderer: TBoldListAsFollowerListRenderer read GetRenderer write SetRenderer; - property NilElementMode: TBoldNilElementMode read fNilElementMode write SetNilElementMode; + property NilElementMode: TBoldNilElementMode read fNilElementMode write SetNilElementMode default neNone; public constructor Create(aOwningComponent: TComponent; FollowerController: TBoldFollowerController); -// procedure DragDrop(Follower: TBoldFollower; ReceivingElement: TBoldElement; dropindex: Integer); override; -// function DragOver(Follower: TBoldFollower; ReceivingElement: TBoldElement; dropindex: Integer): Boolean; override; - function GetListIndex(Follower: TBoldFollower): Integer; - function ListIndexToIndex(Follower: TBoldFollower; ListIndex: Integer): integer; - function ListIndex(index: integer): integer; + + function GetListIndex(Follower: TBoldFollower): Integer; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function ListIndexToIndex(Follower: TBoldFollower; ListIndex: Integer): integer; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function ListIndex(index: integer): integer; {$IFDEF BOLD_INLINE} inline; {$ENDIF} end; { TBoldListAsFollowerListController } @@ -75,9 +78,8 @@ implementation uses SysUtils, - BoldGuiResourceStrings, BoldUtils, - {$IFNDEF BOLDCOMCLIENT} // uses + {$IFNDEF BOLDCOMCLIENT} BoldSystem, BoldGUI, {$ENDIF} @@ -91,8 +93,8 @@ constructor TBoldAbstractListAsFollowerListController.Create(aOwningComponent: T begin inherited Create(aOwningComponent); fFollowerController := FollowerController; - DragMode := bdgSelection; - DropMode := bdpAppend; + DragMode := DefaultBoldDragMode; + DropMode := DefaultBoldDropMode; fDefaultDblClick := True; fNilElementMode := neNone; fInternalDrag := True; @@ -135,7 +137,7 @@ procedure TBoldAbstractListAsFollowerListController.DoMakeUptodateAndSubscribe(F begin inherited DoMakeUptodateAndSubscribe(Follower, Subscribe); (EffectiveRenderer as TBoldListAsFollowerListRenderer).MakeUptodate(Follower, fFollowerController); - {$IFDEF BOLDCOMCLIENT} // MakeUptodateAndSubscribe + {$IFDEF BOLDCOMCLIENT} if Subscribe and Assigned(Follower.Element) then Follower.Element.SubscribeToExpression('', Follower.Subscriber.ClientId, Follower.Subscriber.SubscriberId, false, false); {$ELSE} @@ -163,11 +165,6 @@ procedure TBoldAbstractListAsFollowerListController.SetNilElementMode(const Valu end; end; -function TBoldAbstractListAsFollowerListController.GetEffectiveRenderer: TBoldRenderer; -begin - Result := EffectiveListAsFollowerListRenderer; -end; - function TBoldAbstractListAsFollowerListController.GetEffectiveListAsFollowerListRenderer: TBoldListAsFollowerListRenderer; begin if Assigned(Renderer) then @@ -176,11 +173,29 @@ function TBoldAbstractListAsFollowerListController.GetEffectiveListAsFollowerLis Result := TBoldListAsFollowerListRenderer.DefaultRenderer; end; +function TBoldAbstractListAsFollowerListController.GetEffectiveRenderer: TBoldRenderer; +begin + Result := EffectiveListAsFollowerListRenderer; +end; + function TBoldAbstractListAsFollowerListController.GetListIndex(Follower: TBoldFollower): Integer; begin Result := Follower.CurrentIndex; if (NilElementMode = neInsertFirst) and (Result >= 0) then - Dec(Result); + Dec(Result) + else + if (NilElementMode = neAddLast) and (Result = Follower.SubFollowerCount-1) then + result := -1; +end; + +function TBoldAbstractListAsFollowerListController.ListIndex(index: integer): integer; +begin + if index = MaxInt then + result := index + else if NilElementMode = neInsertFirst then + Result := index + 1 + else + Result := index; end; {---TBoldListAsFollowerListRenderer---} @@ -192,6 +207,7 @@ procedure TBoldListAsFollowerListRenderer.SetActiveRange(Follower: TBoldFollower FirstToEnsure, LastToEnsure: integer; FirstFollowerActive, LastFollowerActive: integer; FollowerController: TBoldAbstractListAsFollowerListController; + Element: TBoldElement; begin if not assigned(follower.element) then exit; @@ -211,13 +227,18 @@ procedure TBoldListAsFollowerListRenderer.SetActiveRange(Follower: TBoldFollower if FirstToEnsure < 0 then FirstToEnsure := 0; - if FirstToEnsure >= List.Count then - FirstToEnsure := List.Count - 1; + i := List.Count; + if FirstToEnsure >= i then + FirstToEnsure := i - 1; - if LastToEnsure >= list.Count then - LastToEnsure := List.Count - 1; + if LastToEnsure >= i then + LastToEnsure := i - 1; - list.EnsureRange(FirstToEnsure, LastToEnsure); + if (LastToEnsure > FirstToEnsure) and (LastToEnsure <> -1) then + list.EnsureRange(FirstToEnsure, LastToEnsure); + + if Follower.Element <> List then + Follower.Element := List; FirstFollowerActive := FirstActive; LastFollowerActive := LastActive; @@ -225,22 +246,30 @@ procedure TBoldListAsFollowerListRenderer.SetActiveRange(Follower: TBoldFollower if FirstFollowerActive >= Follower.SubFollowerCount then FirstFollowerActive := Follower.SubFollowerCount-1; - if FirstFollowerActive >= List.Count then - FirstFollowerActive := List.Count - 1; + if FirstFollowerActive >= i then + FirstFollowerActive := i - 1; if FirstFollowerActive < 0 then FirstFollowerActive := 0; if LastFollowerActive >= Follower.SubFollowerCount then LastFollowerActive := Follower.SubFollowerCount - 1; - if LastFollowerActive >= list.Count then - LastFollowerActive := List.Count - 1; + if LastFollowerActive >= i then + LastFollowerActive := i - 1; - for i := FirstFollowerActive to LastFollowerActive do +{ for i := FirstFollowerActive to LastFollowerActive do with Follower.SubFollowers[i] do if not ElementValid then Element := List.Elements[FollowerController.ListIndex(i)]; +} + inherited SetActiveRange(Follower, FirstFollowerActive, LastFollowerActive); + + for i := FirstFollowerActive to LastFollowerActive do + begin + Element := List.Elements[FollowerController.ListIndex(i)]; + (Follower.RendererData as TBoldFollowerList).EnsuredFollower(FollowerController, i, Element, FollowerController.fFollowerController); + end; end; class function TBoldListAsFollowerListRenderer.DefaultRenderer: TBoldListAsFollowerListRenderer; @@ -263,12 +292,13 @@ procedure TBoldListAsFollowerListRenderer.MakeUptodate(Follower: TBoldFollower; procedure AddElement(aElement: TBoldElement); begin - DestList.EnsureFollower(Controller, DestIndex, aElement, FollowerController); + DestList.EnsuredFollower(Controller, DestIndex, aElement, FollowerController); Inc(DestIndex); end; begin DestList := Follower.RendererData as TBoldFollowerList; + Assert(DestList.BoldList = Follower.Element); Controller := Follower.Controller as TBoldAbstractListAsFollowerListController; DestIndex := 0; @@ -277,27 +307,37 @@ procedure TBoldListAsFollowerListRenderer.MakeUptodate(Follower: TBoldFollower; if Assigned(Follower.Element) then begin SourceList := Follower.Element as TBoldList; + Assert(Assigned(SourceList), 'TBoldListAsFollowerListRenderer.MakeUptodate: Assigned(SourceList)'); {$IFNDEF BOLDCOMCLIENT} SourceList.EnsureRange(Controller.ListIndex(DestList.FirstActive), Controller.ListIndex(DestList.LastActive)); {$ELSE} SourceVariant := SourceList.GetRange(Controller.ListIndex(DestList.FirstActive), Controller.ListIndex(DestList.LastActive)); {$ENDIF} - for SourceIndex := 0 to SourceList.Count - 1 do - if (DestIndex >= DestList.FirstActive) and (Destindex <= DestList.LastActive) then - {$IFNDEF BOLDCOMCLIENT} - AddElement(SourceList[SourceIndex]) - {$ELSE} - begin - unk := SourceVariant[SourceIndex]; - ElementInterface := unk as IBoldElement; - AddElement(ElementInterface); - end - {$ENDIF} - else + SourceIndex := 0; + SourceList := Follower.Element as TBoldList; + if Assigned(SourceList) then + begin + if SourceList.Count > 4 then + DestList.SetCapacity(SourceList.Count); + while SourceIndex < SourceList.Count do begin - AddElement(nil); - DestList[DestIndex-1].ElementValid := false; + if (DestIndex >= DestList.FirstActive) and (Destindex <= DestList.LastActive) then + begin + DestList.EnsuredFollower(Controller, DestIndex, SourceList[SourceIndex], FollowerController); + if not (Follower.Element = SourceList) then + Assert(Follower.Element = SourceList, 'If this fails, make a clone of SourceList before the loop.'); + // SourceList := Follower.Element as TBoldList; + Inc(DestIndex); + end + else + begin + DestList.EnsuredFollower(Controller, DestIndex, nil, FollowerController); + // DestList[DestIndex].ElementValid := false; + Inc(DestIndex); + end; + inc(SourceIndex); end; + end; end; if (Controller.NilElementMode=neAddLast) then AddElement(nil); @@ -305,16 +345,16 @@ procedure TBoldListAsFollowerListRenderer.MakeUptodate(Follower: TBoldFollower; end; procedure TBoldListAsFollowerListRenderer.DefaultStartDrag(Element: TBoldElement; DragMode: TBoldDragMode; RendererData: TBoldRendererData); -{$IFNDEF BOLDCOMCLIENT} // dragdrop - DefaultStartDrag +{$IFNDEF BOLDCOMCLIENT} var FollowerList: TBoldFollowerList; {$ENDIF} begin - {$IFNDEF BOLDCOMCLIENT} // dragdrop - DefaultStartDrag + {$IFNDEF BOLDCOMCLIENT} if (DragMode = bdgSelection) then begin if BoldGUIHandler.DraggedObjects.Count <> 0 then - raise EBold.CreateFmt(sDraggedObjectsNotCleared, [ClassName]); + raise EBold.Create('TBoldListAsFollowerListRenderer.DefaultStartDrag: TBoldGUIHandler.DraggedObjects not cleared'); Followerlist := RendererData as TBoldFollowerList; Followerlist.AddSelectedToList(BoldGUIHandler.DraggedObjects); @@ -324,16 +364,16 @@ procedure TBoldListAsFollowerListRenderer.DefaultStartDrag(Element: TBoldElement function TBoldListAsFollowerListRenderer.DefaultDragOver(Element: TBoldElement; DropMode: TBoldDropMode; InternalDrag: Boolean; RendererData: TBoldRendererData; dropindex: Integer): Boolean; begin - {$IFNDEF BOLDCOMCLIENT} // dragdrop - DefaultDragOver + {$IFNDEF BOLDCOMCLIENT} Result := (BoldGUIHandler.DraggedObjects.Count > 0) and - BoldGUIHandler.DraggedObjectsAssignable(Element, DropMode); // FIXME move here + BoldGUIHandler.DraggedObjectsAssignable(Element, DropMode); {$ELSE} result := false; {$ENDIF} end; procedure TBoldListAsFollowerListRenderer.DefaultDragDrop(Element: TBoldElement; DropMode: TBoldDropMode; dropindex: Integer); -{$IFNDEF BOLDCOMCLIENT} // dragdrop - DefaultDragDrop +{$IFNDEF BOLDCOMCLIENT} var prevIndex, Offset, @@ -344,7 +384,7 @@ procedure TBoldListAsFollowerListRenderer.DefaultDragDrop(Element: TBoldElement; (* if (NilElementMode=neInsertFirst) then Offset := 1 - else*) //FIXME + else*) Offset := 0; case DropMode of bdpInsert: @@ -376,11 +416,10 @@ procedure TBoldListAsFollowerListRenderer.DefaultDragDrop(Element: TBoldElement; bdpAppend: for I := 0 to BoldGUIHandler.DraggedObjects.Count - 1 do - // Dupe checking by the ObjectList ObjectList.Add(BoldGUIHandler.DraggedObjects[I]); bdpReplace: - raise EBoldFeatureNotImplementedYet.CreateFmt(sReplaceNotImplemented, [ClassName]); + raise EBoldFeatureNotImplementedYet.CreateFmt('%s.DefaultDragDrop: Replace not implemented yet', [ClassName]); end; end; {$ELSE} @@ -396,14 +435,10 @@ function TBoldAbstractListAsFollowerListController.ListIndexToIndex(Follower: TB Result := Listindex; end; -function TBoldAbstractListAsFollowerListController.ListIndex(index: integer): integer; + +class function TBoldAbstractListAsFollowerListController.PrecreateFollowers: boolean; begin - if index = MaxInt then - result := index // otherwise the result will overflow to -maxint - else if NilElementMode = neInsertFirst then - Result := index + 1 - else - Result := index; + result := false; end; initialization @@ -413,4 +448,3 @@ finalization FreeAndNil(DefaultListAsFollowerListRenderer); end. - diff --git a/Source/BoldAwareGUI/ControlPacks/BoldMLRenderers.pas b/Source/BoldAwareGUI/ControlPacks/BoldMLRenderers.pas index 9d1fef5..d2f622c 100644 --- a/Source/BoldAwareGUI/ControlPacks/BoldMLRenderers.pas +++ b/Source/BoldAwareGUI/ControlPacks/BoldMLRenderers.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldMLRenderers; interface @@ -13,9 +16,9 @@ interface { forward declarations } TBoldAsMLStringRenderer = class; - TBoldLanguageGetAsString = function (Element: TBoldElement; Representation: TBoldRepresentation; Expression: TBoldExpression; Language: String): string of object; - TBoldLanguageSetAsString = procedure (Element: TBoldElement; Value: string; Representation: TBoldRepresentation; Expression: TBoldExpression; Language: String) of object; - TBoldLanguageSubscribe = procedure (Element: TBoldElement; Representation: TBoldRepresentation; Expression: TBoldExpression; Subscriber: TBoldSubscriber; Language: String) of object; + TBoldLanguageGetAsString = function (aFollower: TBoldFollower; const Language: String): string of object; + TBoldLanguageSetAsString = procedure (aFollower: TBoldFollower; const Value: string; const Language: String) of object; + TBoldLanguageSubscribe = procedure (aFollower: TBoldFollower; const Language: String; Subscriber: TBoldSubscriber) of object; { TBoldAsMLStringRenderer } TBoldAsMLStringRenderer = class (TBoldAsStringRenderer) @@ -23,15 +26,15 @@ TBoldAsMLStringRenderer = class (TBoldAsStringRenderer) fLanguage: String; fOnLanguageGetAsString: TBoldLanguageGetAsString; fOnLanguageSetAsString: TBoldLanguageSetAsString; - fOnLanguageSubscribe: TBoldLAnguageSubscribe; - procedure SetLanguage(newValue: String); + fOnLanguageSubscribe: TBoldLanguageSubscribe; + procedure SetLanguage(const newValue: String); protected - procedure SetAsString(Element: TBoldElement; Value: string; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList); override; - function GetAsStringAndSubscribe(Element: TBoldElement; FollowerController: TBoldStringFollowerController; Subscriber: TBoldSubscriber): string; override; + procedure SetAsString(aFollower: TBoldFollower; const Value: string); override; + function GetAsStringAndSubscribe(aFollower: TBoldFollower; Subscriber: TBoldSubscriber): string; override; public - function DefaultGetAsStringAndSubscribe(Element: TBoldElement; FollowerController: TBoldStringFollowerController; Subscriber: TBoldSubscriber): string; override; - procedure DefaultSetAsString(Element: TBoldElement; Value: string; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList); override; - procedure DefaultMakeUptodateAndSetMayModifyAndSubscribe(Element: TBoldElement; RendererData: TBoldRendererData; FollowerController: TBoldStringFollowerController; Subscriber: TBoldSubscriber); override; + function DefaultGetAsStringAndSubscribe(aFollower: TBoldFollower; Subscriber: TBoldSubscriber): string; override; + procedure DefaultSetAsString(aFollower: TBoldFollower; const Value: string); override; + procedure DefaultMakeUptodateAndSetMayModifyAndSubscribe(aFollower: TBoldFollower; Subscriber: TBoldSubscriber); override; published property Language: String read fLanguage write SetLanguage; property OnLanguageGetAsString: TBoldLanguageGetAsString read FOnLanguageGetAsString write FOnLanguageGetAsString; @@ -43,153 +46,173 @@ implementation uses SysUtils, - BoldGuiResourceStrings, BoldMLAttributes, - BoldUtils; + BoldUtils, + BoldGuard; -function TBoldAsMLStringRenderer.GetAsStringAndSubscribe(Element: TBoldElement; FollowerController: TBoldStringFollowerController; Subscriber: TBoldSubscriber): string; +function TBoldAsMLStringRenderer.GetAsStringAndSubscribe(aFollower: TBoldFollower; Subscriber: TBoldSubscriber): string; begin if Assigned(OnLanguageSubscribe) and Assigned(Subscriber) then begin - if Assigned(Element) then - OnLanguageSubscribe(Element, FollowerController.Representation, FollowerController.Expression, Subscriber, Language); + if Assigned(aFollower.Element) then + OnLanguageSubscribe(aFollower, Language, Subscriber); Subscriber := nil; end; if Assigned(OnLanguageGetAsString) then begin - Result := OnLanguageGetAsString(Element, FollowerController.Representation, FollowerController.Expression, Language); + Result := OnLanguageGetAsString(aFollower, Language); if not assigned(OnLanguageSubscribe) and assigned(Subscriber) then - DefaultGetAsStringAndSubscribe(Element, FollowerController, Subscriber); + DefaultGetAsStringAndSubscribe(aFollower, Subscriber); end else - Result := DefaultGetAsStringAndSubscribe(Element, FollowerController, Subscriber); + Result := DefaultGetAsStringAndSubscribe(aFollower, Subscriber); end; -function TBoldAsMLStringRenderer.DefaultGetAsStringAndSubscribe(Element: TBoldElement; FollowerController: TBoldStringFollowerController; Subscriber: TBoldSubscriber): string; +function TBoldAsMLStringRenderer.DefaultGetAsStringAndSubscribe(aFollower: TBoldFollower; Subscriber: TBoldSubscriber): string; var E: TBoldIndirectElement; + lResultElement: TBoldElement; + lGuard: IBoldGuard; + lFollowerController: TBoldFollowerController; begin Result := ''; - if Assigned(Element) then + if Assigned(aFollower.Element) then begin - E := TBoldIndirectElement.Create; - try - Element.EvaluateAndSubscribeToExpression(FollowerController.Expression, Subscriber, E, False, false, FollowerController.GetVariableListAndSubscribe(subscriber)); - if Assigned(E.Value) then + lFollowerController := aFollower.AssertedController; + if Assigned(aFollower.Value) then + begin + lResultElement := aFollower.Value + end + else + begin + lGuard:= TBoldGuard.Create(E); + E := TBoldIndirectElement.Create; + aFollower.Element.EvaluateAndSubscribeToExpression(lFollowerController.Expression, Subscriber, E, False, False, lFollowerController.GetVariableListAndSubscribe(Subscriber)); + lResultElement := e.Value; + end; + if Assigned(lResultElement) then + begin + if lResultElement is TBAMLString then begin - if e.Value is TBAMLString then + result := (lResultElement as TBAMLString).AsStringByLanguage[Language].StringRepresentation[lFollowerController.Representation]; + if Assigned(Subscriber) then begin - result := (e.Value as TBAMLString).AsStringByLanguage[Language].StringRepresentation[FollowerController.Representation]; - if Assigned(Subscriber) then - begin - (e.Value as TBAMLString).SubscribeToLanguage(Language, Subscriber, breReEvaluate); - Publisher.AddSubscription(subscriber, beValueChanged, breReevaluate); - end; - end - else if e.Value is TBAMLValueSet then - begin - result := (e.Value as TBAMLValueSet).StringRepresentationByLanguage[FollowerController.Representation, Language]; - if Assigned(Subscriber) then - begin - (e.Value as TBAMLvalueSet).SubscribeToLanguage(FollowerController.Representation, Language, Subscriber, breReEvaluate); - Publisher.AddSubscription(subscriber, beValueChanged, breReevaluate); - end; - end - else + (lResultElement as TBAMLString).SubscribeToLanguage(Language, Subscriber, breReEvaluate); + Publisher.AddSubscription(subscriber, beValueChanged, breReevaluate); + end; + end + else if lResultElement is TBAMLValueSet then + begin + result := (lResultElement as TBAMLValueSet).StringRepresentationByLanguage[lFollowerController.Representation, Language]; + if Assigned(Subscriber) then begin - Result := E.Value.StringRepresentation[FollowerController.Representation]; - if Assigned(Subscriber) then - E.Value.SubscribeToStringRepresentation(FollowerController.Representation, Subscriber, breReEvaluate); + (lResultElement as TBAMLvalueSet).SubscribeToLanguage(lFollowerController.Representation, Language, Subscriber, breReEvaluate); + Publisher.AddSubscription(subscriber, beValueChanged, breReevaluate); end; end else - Result := ''; - finally - E.Free; - end; + begin + Result := lResultElement.StringRepresentation[lFollowerController.Representation]; + if Assigned(Subscriber) then + lResultElement.SubscribeToStringRepresentation(lFollowerController.Representation, Subscriber, breReEvaluate); + end; + end + else + Result := ''; end; end; -procedure TBoldAsMLStringRenderer.SetAsString(Element: TBoldElement; Value: string; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList); +procedure TBoldAsMLStringRenderer.SetAsString(aFollower: TBoldFollower; const Value: string); begin if assigned(OnLanguageSetAsString) then - OnLanguageSetAsString(Element, Value, Representation, Expression, Language) + OnLanguageSetAsString(aFollower, Value, Language) else - DefaultSetAsString(Element, Value, Representation, Expression, VariableList); + DefaultSetAsString(aFollower, Value); end; -procedure TBoldAsMLStringRenderer.DefaultSetAsString(Element: TBoldElement; Value: string; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList); +procedure TBoldAsMLStringRenderer.DefaultSetAsString(aFollower: TBoldFollower; const Value: string); var ValueElement: TBoldElement; MLValueSet: TBAMLValueSet; + lRepresentation: integer; begin - ValueElement := GetExpressionAsDirectElement(Element, Expression, VariableList); + ValueElement := aFollower.Value; + lRepresentation := aFollower.AssertedController.Representation; if Assigned(ValueElement) then begin if (ValueElement is TBAMLValueSet) then begin MLValueSet := (ValueElement as TBAMLValueSet); - MLValueSet.StringRepresentationByLanguage[Representation, Language] := Value + MLValueSet.StringRepresentationByLanguage[lRepresentation, Language] := Value end else if ValueElement is TBAMLString then - (ValueElement as TBAMLString).AsStringByLanguage[Language].StringRepresentation[Representation] := Value + (ValueElement as TBAMLString).AsStringByLanguage[Language].StringRepresentation[lRepresentation] := Value else - ValueElement.StringRepresentation[Representation] := Value + ValueElement.StringRepresentation[lRepresentation] := Value end else - raise EBold.CreateFmt(sCannotSetStringValue, [ClassName]); + raise EBold.CreateFmt('%s.DefaultSetAsString: Can''t set string value', [ClassName]); end; -procedure TBoldAsMLStringRenderer.DefaultMakeUptodateAndSetMayModifyAndSubscribe(Element: TBoldElement; RendererData: TBoldRendererData; FollowerController: TBoldStringFollowerController; Subscriber: TBoldSubscriber); +procedure TBoldAsMLStringRenderer.DefaultMakeUptodateAndSetMayModifyAndSubscribe(aFollower: TBoldFollower; Subscriber: TBoldSubscriber); var E: TBoldIndirectElement; S: String; + lRepresentation: integer; + lRendererData: TBoldStringRendererData; + lResultElement: TBoldElement; + lFollowerController: TBoldFollowerController; + lGuard: IBoldGuard; begin S := ''; - - if Assigned(Element) then + lRendererData := aFollower.RendererData as TBoldStringRendererData; + lFollowerController := aFollower.AssertedController; + if Assigned(aFollower.Element) then begin - E := TBoldIndirectElement.Create; - try - Element.EvaluateAndSubscribeToExpression(FollowerController.Expression, Subscriber, E, False); - if Assigned(E.Value) then + lRepresentation := lFollowerController.Representation; + lResultElement := aFollower.Value; + if not Assigned(lResultElement) then + begin + lGuard:= TBoldGuard.Create(E); + E := TBoldIndirectElement.Create; + aFollower.Element.EvaluateAndSubscribeToExpression(lFollowerController.Expression, Subscriber, E, False, False, lFollowerController.GetVariableListAndSubscribe(Subscriber)); + lResultElement := e.Value; + end; + if Assigned(lResultElement) then + begin + if lResultElement is TBAMLString then begin - if e.Value is TBAMLString then - begin - S := (e.Value as TBAMLString).AsStringByLanguage[Language].StringRepresentation[FollowerController.Representation]; - if Assigned(Subscriber) then - begin - (e.Value as TBAMLString).SubscribeToLanguage(Language, Subscriber, breReEvaluate); - Publisher.AddSubscription(subscriber, beValueChanged, breReevaluate); - end - end - else if e.Value is TBAMLValueSet then + S := (lResultElement as TBAMLString).AsStringByLanguage[Language].StringRepresentation[lRepresentation]; + if Assigned(Subscriber) then begin - S := (e.Value as TBAMLValueSet).StringRepresentationByLanguage[FollowerController.Representation, Language]; - if Assigned(Subscriber) then - begin - (e.Value as TBAMLvalueSet).SubscribeToLanguage(FollowerController.Representation, Language, Subscriber, breReEvaluate); - Publisher.AddSubscription(subscriber, beValueChanged, breReevaluate); - end; + (lResultElement as TBAMLString).SubscribeToLanguage(Language, Subscriber, breReEvaluate); + Publisher.AddSubscription(subscriber, beValueChanged, breReevaluate); end - else + end + else if lResultElement is TBAMLValueSet then + begin + S := TBAMLValueSet(lResultElement).StringRepresentationByLanguage[lRepresentation, Language]; + if Assigned(Subscriber) then begin - S := E.Value.StringRepresentation[FollowerController.Representation]; - if Assigned(Subscriber) then - E.Value.SubscribeToStringRepresentation(FollowerController.Representation, Subscriber, breReEvaluate); + TBAMLValueSet(lResultElement).SubscribeToLanguage(lRepresentation, Language, Subscriber, breReEvaluate); + Publisher.AddSubscription(subscriber, beValueChanged, breReevaluate); end; - RendererData.MayModify := E.Value.ObserverMayModify(Subscriber); end else - S := ''; - finally - E.Free; - end; + begin + S := lResultElement.StringRepresentation[lRepresentation]; + if Assigned(Subscriber) then + lResultElement.SubscribeToStringRepresentation(lRepresentation, Subscriber, breReEvaluate); + end; +// lRendererData.MayModify := lResultElement.ObserverMayModify(Subscriber); + end + else + S := ''; end; - (RendererData as TBoldStringRendererData).OldStringValue := S; - (RendererData as TBoldStringRendererData).CurrentStringValue := S; + lRendererData.OldStringValue := S; + lRendererData.CurrentStringValue := S; end; -procedure TBoldAsMLStringRenderer.SetLanguage(newValue: String); +procedure TBoldAsMLStringRenderer.SetLanguage(const newValue: String); begin if NewValue <> fLanguage then begin @@ -198,4 +221,5 @@ procedure TBoldAsMLStringRenderer.SetLanguage(newValue: String); end; end; +initialization end. diff --git a/Source/BoldAwareGUI/ControlPacks/BoldNodeControlPack.pas b/Source/BoldAwareGUI/ControlPacks/BoldNodeControlPack.pas index 40f6393..0456e93 100644 --- a/Source/BoldAwareGUI/ControlPacks/BoldNodeControlPack.pas +++ b/Source/BoldAwareGUI/ControlPacks/BoldNodeControlPack.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldNodeControlPack; {$UNDEF BOLDCOMCLIENT} @@ -39,17 +42,18 @@ TBoldTreeFollowerController = class(TBoldGenericListController) FOnIconChanged: TBoldFollowerEvent; FOnTextChanged: TBoldFollowerEvent; FOnGetFollowerController: TGetFollowerControllerByNameEvent; - procedure SetNodeDescriptions(Value: TBoldNodeDescriptions); - function GetDefaultNodeDescriptionName: string; + procedure SetNodeDescriptions(Value: TBoldNodeDescriptions); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetDefaultNodeDescriptionName: string; {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure SetDefaultNodeDescriptionName(const Value: string); protected - procedure DoIconChanged(Follower: TBoldFollower); - procedure DoTextChanged(Follower: TBoldFollower); + class function PrecreateFollowers: boolean; override; + procedure DoIconChanged(Follower: TBoldFollower); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure DoTextChanged(Follower: TBoldFollower); {$IFDEF BOLD_INLINE} inline; {$ENDIF} {$IFDEF BOLD_BCB} - procedure DoGetFollowerController(Name: string; var FollowerController: TBoldFollowerController); + procedure DoGetFollowerController(const Name: string; var FollowerController: TBoldFollowerController); {$ENDIF} {$IFDEF BOLD_DELPHI} - function DoGetFollowerController(Name: string): TBoldFollowerController; + function DoGetFollowerController(const Name: string): TBoldFollowerController; {$IFDEF BOLD_INLINE} inline; {$ENDIF} {$ENDIF} procedure DoAssign(Source: TPersistent); override; function GetBoldNodeDescriptionsClass: TBoldNodeDescriptionsClass; virtual; @@ -69,8 +73,8 @@ TBoldTreeFollowerController = class(TBoldGenericListController) TBoldNodeDescriptions = class(TCollection) private FTreeFollowerController: TBoldTreeFollowerController; - function GetNodeControllerItem(Index: Integer): TBoldNodeDescription; - procedure SetNodeControllerItem(Index: Integer; Value: TBoldNodeDescription); + function GetNodeControllerItem(Index: Integer): TBoldNodeDescription; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure SetNodeControllerItem(Index: Integer; Value: TBoldNodeDescription); {$IFDEF BOLD_INLINE} inline; {$ENDIF} protected function GetNodeDescriptionClass: TBoldNodeDescriptionClass; virtual; function GetOwner: TPersistent; override; @@ -87,17 +91,17 @@ TBoldNodeDescription = class(TCollectionItem) private FName: string; FNodeFollowerController: TBoldNodeFollowerController; - procedure SetName(Value: string); - function GetHideNodeWithNoChildren: Boolean; - procedure SetHideNodeWithNoChildren(Value: Boolean); - function GetListController: TBoldGenericListController; - function GetIconController: TBoldIntegerFollowerController; - function GetTextController: TBoldStringFollowerController; - procedure SetListController(Value: TBoldGenericListController); - procedure SetIconController(Value: TBoldIntegerFollowerController); - procedure SetTextController(Value: TBoldStringFollowerController); - function GetContextTypeName: String; - procedure SetContextTypeName(const Value: String); + procedure SetName(const Value: string); + function GetHideNodeWithNoChildren: Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure SetHideNodeWithNoChildren(Value: Boolean); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetListController: TBoldGenericListController; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetIconController: TBoldIntegerFollowerController; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetTextController: TBoldStringFollowerController; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure SetListController(Value: TBoldGenericListController); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure SetIconController(Value: TBoldIntegerFollowerController); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure SetTextController(Value: TBoldStringFollowerController); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetContextTypeName: String; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure SetContextTypeName(const Value: String); {$IFDEF BOLD_INLINE} inline; {$ENDIF} function GetContextType: TBoldElementTypeInfo; protected function GetDisplayName: string; override; @@ -128,6 +132,8 @@ TBoldNodeFollowerController = class(TBoldControllerList) procedure SetHideNodeWithNoChildren(Value: Boolean); procedure SetContextTypeName(const Value: String); function GetSystemTypeInfo: TBoldSystemTypeInfo; + protected + class function PrecreateFollowers: boolean; override; public constructor Create(aTreeFollowerController: TBoldTreeFollowerController);virtual; destructor Destroy; override; @@ -179,6 +185,11 @@ function TBoldTreeFollowerController.GetDefaultNodeDescriptionName: string; Result := ''; end; +class function TBoldTreeFollowerController.PrecreateFollowers: boolean; +begin + result := true; +end; + procedure TBoldTreeFollowerController.SetDefaultNodeDescriptionName(const Value: string); var NodeDescription: TBoldNodeDescription; @@ -192,7 +203,7 @@ procedure TBoldTreeFollowerController.SetDefaultNodeDescriptionName(const Value: Changed; end else - raise EBold.CreateFmt(sInvalidNodeName, [ClassName, Value]); + raise EBold.CreateFmt('%s.SetDefaultNodeDescriptionName: ''%s'' is not a valid name', [ClassName, Value]); end; end; @@ -223,10 +234,10 @@ procedure TBoldTreeFollowerController.DoTextChanged(Follower: TBoldFollower); end; {$IFDEF BOLD_BCB} -procedure TBoldTreeFollowerController.DoGetFollowerController(Name: string; var FollowerController: TBoldFollowerController); +procedure TBoldTreeFollowerController.DoGetFollowerController(const Name: string; var FollowerController: TBoldFollowerController); {$ENDIF} {$IFDEF BOLD_DELPHI} -function TBoldTreeFollowerController.DoGetFollowerController(Name: string): TBoldFollowerController; +function TBoldTreeFollowerController.DoGetFollowerController(const Name: string): TBoldFollowerController; {$ENDIF} begin {$IFDEF BOLD_BCB} @@ -319,7 +330,6 @@ function TBoldNodeDescription.GetBoldNodeFollowerControllerClass:TBoldNodeFollow destructor TBoldNodeDescription.Destroy; begin - // FIXME ??? FreePublisher; //CHECKME Is this really needed? FreeAndNil(FNodeFollowerController); inherited Destroy; end; @@ -346,7 +356,7 @@ function TBoldNodeDescription.GetDisplayName: string; Result := inherited GetDisplayName; end; -procedure TBoldNodeDescription.SetName(Value: string); +procedure TBoldNodeDescription.SetName(const Value: string); begin if FName <> Value then begin @@ -415,6 +425,7 @@ constructor TBoldNodeFollowerController.Create(aTreeFollowerController: TBoldTre fGenericListFollowerController.OnBeforeDeleteItem := FTreeFollowerController.DoBeforeDeleteItem; fGenericListFollowerController.OnAfterDeleteItem := FTreeFollowerController.DoAfterDeleteItem; fGenericListFollowerController.BeforeMakeUptoDate := FTreeFollowerController.BeforeMakeUptoDate; +// fGenericListFollowerController.OnReplaceitem := FTreeFollowerController.OnReplaceitem; fGenericListFollowerController.OnGetContextType := GetContextType; Add(fGenericListFollowerController); @@ -441,7 +452,7 @@ procedure TBoldNodeFollowerController.SetHideNodeWithNoChildren(Value: Boolean); destructor TBoldNodeFollowerController.Destroy; begin - FreePublisher; //CHECKME Is this really needed? + FreePublisher; inherited Destroy; end; @@ -482,6 +493,11 @@ function TBoldNodeFollowerController.GetSystemTypeInfo: TBoldSystemTypeInfo; result := nil; end; +class function TBoldNodeFollowerController.PrecreateFollowers: boolean; +begin + result := true; +end; + function TBoldNodeDescription.GetContextType: TBoldElementTypeInfo; var ContextType: TBoldElementTypeInfo; @@ -498,6 +514,5 @@ function TBoldNodeDescription.GetContextType: TBoldElementTypeInfo; result := nil; end; +initialization end. - - diff --git a/Source/BoldAwareGUI/ControlPacks/BoldNumericControlPack.pas b/Source/BoldAwareGUI/ControlPacks/BoldNumericControlPack.pas index 98245e9..4d31f7b 100644 --- a/Source/BoldAwareGUI/ControlPacks/BoldNumericControlPack.pas +++ b/Source/BoldAwareGUI/ControlPacks/BoldNumericControlPack.pas @@ -1,3 +1,6 @@ +///////////////////////////////////////////////////////// + + unit BoldNumericControlPack; {$UNDEF BOLDCOMCLIENT} @@ -20,9 +23,9 @@ TBoldAsIntegerRenderer = class; TBoldIntegerFollowerController = class; {TBoldAsIntegerRenderer} - TBoldGetAsIntegerEvent = function (Element: TBoldElement; Representation: TBoldRepresentation; Expression: TBoldExpression): Integer of object; - TBoldSetAsIntegerEvent = procedure (Element: TBoldElement; const Value: Integer; Representation: TBoldRepresentation; Expression: TBoldExpression) of object; - TBoldIntegerIsChangedEvent = function (RenderData: TBoldIntegerRendererData; const NewValue: Integer; Representation: TBoldRepresentation; Expression: TBoldExpression): Boolean of object; + TBoldGetAsIntegerEvent = function (aFollower: TBoldFollower): Integer of object; + TBoldSetAsIntegerEvent = procedure (aFollower: TBoldFollower; const Value: Integer) of object; + TBoldIntegerIsChangedEvent = function (aFollower: TBoldFollower; const NewValue: Integer): Boolean of object; { TBoldIntegerRendererData } TBoldIntegerRendererData = class(TBoldRendererData) @@ -42,16 +45,16 @@ TBoldAsIntegerRenderer = class(TBoldsingleRenderer) FOnIsChanged: TBoldIntegerIsChangedEvent; protected function GetRendererDataClass: TBoldRendererDataClass; override; - function DefaultGetAsIntegerAndSubscribe(Element: TBoldElement; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList; Subscriber: TBoldSubscriber): Integer; virtual; - procedure DefaultSetAsInteger(Element: TBoldElement; const Value: Integer; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList); virtual; - function GetAsIntegerAndSubscribe(Element: TBoldElement; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList; Subscriber: TBoldSubscriber): Integer; virtual; - procedure SetAsInteger(Element: TBoldElement; const Value: Integer; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList); virtual; + function DefaultGetAsIntegerAndSubscribe(aFollower: TBoldFollower; Subscriber: TBoldSubscriber): Integer; virtual; + procedure DefaultSetAsInteger(aFollower: TBoldFollower; const Value: Integer); virtual; + function GetAsIntegerAndSubscribe(aFollower: TBoldFollower; Subscriber: TBoldSubscriber): Integer; virtual; + procedure SetAsInteger(aFollower: TBoldFollower; const Value: Integer); virtual; public class function DefaultRenderer: TBoldAsIntegerRenderer; - function DefaultIsChanged(RendererData: TBoldIntegerRendererData; const NewValue: Integer; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList): Boolean; - function DefaultMayModify(Element: TBoldElement; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList; Subscriber: TBoldSubscriber): Boolean; override; - procedure MakeUptodateAndSubscribe(Element: TBoldElement; RendererData: TBoldRendererData; FollowerController: TBoldFollowerController; Subscriber: TBoldSubscriber); override; - function IsChanged(RendererData: TBoldIntegerRendererData; const NewValue: Integer; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList): Boolean; + function DefaultIsChanged(aFollower: TBoldFollower; const NewValue: Integer): Boolean; + function DefaultMayModify(aFollower: TBoldFollower): Boolean; override; + procedure MakeUptodateAndSubscribe(aFollower: TBoldFollower; Subscriber: TBoldSubscriber); override; + function IsChanged(aFollower: TBoldFollower; const NewValue: Integer): Boolean; published property OnGetAsInteger: TBoldGetAsIntegerEvent read FOnGetAsInteger write FOnGetAsInteger; property OnSetAsInteger: TBoldSetAsIntegerEvent read FOnSetAsInteger write FOnSetAsInteger; @@ -83,7 +86,8 @@ implementation BoldUtils, BoldGuiResourceStrings, BoldAttributes, - BoldControlPackDefs; + BoldControlPackDefs, + BoldGuard; var DefaultAsIntegerRenderer: TBoldAsIntegerRenderer = nil; @@ -99,14 +103,14 @@ function TBoldAsIntegerRenderer.GetRendererDataClass: TBoldRendererDataClass; Result := TBoldIntegerRendererData; end; -function TBoldAsIntegerRenderer.DefaultMayModify(Element: TBoldElement; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList; Subscriber: TBoldSubscriber): Boolean; +function TBoldAsIntegerRenderer.DefaultMayModify(aFollower: TBoldFollower): Boolean; {$IFNDEF BOLDCOMCLIENT} // defaultMayModify var ValueElement: TBoldElement; begin // Note! We don't call inherited DefaultMayModify to prevent evaluation of expression two times! - ValueElement := GetExpressionAsDirectElement(Element, Expression, VariableList); - result := (ValueElement is TBANumeric) and ValueElement.ObserverMayModify(Subscriber) + ValueElement := aFollower.Value; + result := (ValueElement is TBANumeric) and ValueElement.ObserverMayModify(aFollower.Subscriber) end; {$ELSE} begin @@ -114,17 +118,19 @@ function TBoldAsIntegerRenderer.DefaultMayModify(Element: TBoldElement; Represen end; {$ENDIF} -function TBoldAsIntegerRenderer.DefaultGetAsIntegerAndSubscribe(Element: TBoldElement; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList; Subscriber: TBoldSubscriber): Integer; +function TBoldAsIntegerRenderer.DefaultGetAsIntegerAndSubscribe(aFollower: TBoldFollower; Subscriber: TBoldSubscriber): Integer; var {$IFDEF BOLDCOMCLIENT} // defaultGet el: IBoldElement; attr: IBoldAttribute; {$ELSE} IndirectElement: TBoldIndirectElement; + lResultElement: TBoldElement; + lGuard: IBoldGuard; {$ENDIF} begin Result := 0; - if Assigned(Element) then + if Assigned(aFollower.Element) then begin {$IFDEF BOLDCOMCLIENT} // defaultGet if assigned(Subscriber) then @@ -136,33 +142,35 @@ function TBoldAsIntegerRenderer.DefaultGetAsIntegerAndSubscribe(Element: TBoldEl else raise EBold.CreateFmt(sCantGetIntegerValue, [el.AsString]) {$ELSE} - IndirectElement := TBoldIndirectElement.Create; - try - Element.EvaluateAndSubscribeToExpression(Expression, Subscriber, IndirectElement, False, False, VariableList); - if Assigned(IndirectElement.Value) then - begin - if (IndirectElement.Value is TBAInteger) then - Result := (IndirectElement.Value as TBAInteger).AsInteger - else if (IndirectElement.Value is TBANumeric) then - Result := Round((IndirectElement.Value as TBANumeric).AsFloat) - else - raise EBold.CreateFmt(sCantGetIntegerValue, [IndirectElement.Value.ClassName]) - end; - finally - IndirectElement.Free; + lResultElement := aFollower.Value; + if not Assigned(lResultElement) then + begin + lGuard:= TBoldGuard.Create(IndirectElement); + IndirectElement := TBoldIndirectElement.Create; + aFollower.Element.EvaluateAndSubscribeToExpression(aFollower.AssertedController.Expression, Subscriber, IndirectElement, False, False, aFollower.Controller.GetVariableListAndSubscribe(Subscriber)); + lResultElement := IndirectElement.Value; + end; + if Assigned(lResultElement) then + begin + if (lResultElement is TBAInteger) then + Result := TBAInteger(lResultElement).AsInteger + else if (lResultElement is TBANumeric) then + Result := Round(TBANumeric(lResultElement).AsFloat) + else + raise EBold.CreateFmt(sCantGetIntegerValue, [lResultElement.ClassName]) end; {$ENDIF} end; end; -procedure TBoldAsIntegerRenderer.DefaultSetAsInteger(Element: TBoldElement; const Value: Integer; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList); +procedure TBoldAsIntegerRenderer.DefaultSetAsInteger(aFollower: TBoldFollower; const Value: Integer); var ValueElement: TBoldElement; {$IFDEF BOLDCOMCLIENT} // defaultSet Attr: IBoldAttribute; {$ENDIF} begin - ValueElement := GetExpressionAsDirectElement(Element, Expression, VariableList); + ValueElement := aFollower.Value; {$IFDEF BOLDCOMCLIENT} // defaultSet if assigned(ValueElement) and (ValueElement.QueryInterface(IBoldAttribute, attr) = S_OK) then attr.AsVariant := Value @@ -170,59 +178,54 @@ procedure TBoldAsIntegerRenderer.DefaultSetAsInteger(Element: TBoldElement; cons raise EBold.CreateFmt(sCantSetIntegerValue, [ValueElement.AsString]); {$ELSE} if ValueElement is TBANumeric then - (ValueElement as TBANumeric).AsInteger := Value + TBANumeric(ValueElement).AsInteger := Value else raise EBold.CreateFmt(sCantSetIntegerValue, [ValueElement.ClassName]); {$ENDIF} end; -function TBoldAsIntegerRenderer.GetAsIntegerAndSubscribe(Element: TBoldElement; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList; Subscriber: TBoldSubscriber): Integer; +function TBoldAsIntegerRenderer.GetAsIntegerAndSubscribe(aFollower: TBoldFollower; Subscriber: TBoldSubscriber): Integer; begin if Assigned(OnSubscribe) and Assigned(Subscriber) then begin - if Assigned(Element) then - OnSubscribe(Element, Representation, Expression, Subscriber); + if Assigned(aFollower.Element) then + OnSubscribe(aFollower, Subscriber); Subscriber := nil; end; if Assigned(OnGetAsInteger) then - Result := OnGetAsInteger(Element, Representation, Expression) + Result := OnGetAsInteger(aFollower) else - Result := DefaultGetAsIntegerAndSubscribe(Element, Representation, Expression, VariableList, Subscriber); + Result := DefaultGetAsIntegerAndSubscribe(aFollower, Subscriber); end; -procedure TBoldAsIntegerRenderer.SetAsInteger(Element: TBoldElement; const Value: Integer; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList); +procedure TBoldAsIntegerRenderer.SetAsInteger(aFollower: TBoldFollower; const Value: Integer); begin if Assigned(FOnSetAsInteger) then - OnSetAsInteger(Element, Value, Representation, Expression) + OnSetAsInteger(aFollower, Value) else - DefaultSetAsInteger(Element, Value, Representation, Expression, VariableList) + DefaultSetAsInteger(aFollower, Value) end; -procedure TBoldAsIntegerRenderer.MakeUpToDateAndSubscribe(Element: TBoldElement; RendererData: TBoldRendererData; FollowerController: TBoldFollowerController; Subscriber: TBoldSubscriber); +procedure TBoldAsIntegerRenderer.MakeUpToDateAndSubscribe(aFollower: TBoldFollower; Subscriber: TBoldSubscriber); var Value: Integer; - Controller: TBoldIntegerFollowerController; begin - Controller := FollowerController as TBoldIntegerFollowerController; - Value := GetAsIntegerAndSubscribe(Element, Controller.Representation, Controller.Expression, Controller.GetVariableListAndSubscribe(Subscriber) ,Subscriber); - with (RendererData as TBoldIntegerRendererData) do - begin - OldIntegerValue := Value; - CurrentIntegerValue := Value; - end; + Value := GetAsIntegerAndSubscribe(aFollower ,Subscriber); + (aFollower.RendererData as TBoldIntegerRendererData).OldIntegerValue := Value; + (aFollower.RendererData as TBoldIntegerRendererData).CurrentIntegerValue := Value; end; -function TBoldAsIntegerRenderer.DefaultIsChanged(RendererData: TBoldIntegerRendererData; const NewValue: Integer; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList): Boolean; +function TBoldAsIntegerRenderer.DefaultIsChanged(aFollower: TBoldFollower; const NewValue: Integer): Boolean; begin - Result := NewValue <> RendererData.OldIntegerValue; + Result := NewValue <> TBoldIntegerRendererData(aFollower.RendererData).OldIntegerValue; end; -function TBoldAsIntegerRenderer.IsChanged(RendererData: TBoldIntegerRendererData; const NewValue: Integer; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList): Boolean; +function TBoldAsIntegerRenderer.IsChanged(aFollower: TBoldFollower; const NewValue: Integer): Boolean; begin if Assigned(FOnIsChanged) then - Result := FOnIsChanged(RendererData, NewValue, Representation, Expression) + Result := FOnIsChanged(aFollower, NewValue) else - Result := DefaultIsChanged(RendererData, NewValue, Representation, Expression, VariableList); + Result := DefaultIsChanged(aFollower, NewValue); end; { TBoldIntegerFollowerController } @@ -252,7 +255,10 @@ function TBoldIntegerFollowerController.GetEffectiveAsIntegerRenderer: TBoldAsIn procedure TBoldIntegerFollowerController.MakeClean(Follower: TBoldFollower); begin - ReleaseChangedValue(Follower); +// if (ApplyPolicy <> bapChange) or EffectiveRenderer.ChangedValueEventsAssigned then + begin + ReleaseChangedValue(Follower); // note, must do first, since set can change element + end; SetAsInteger(GetCurrentAsInteger(Follower), Follower); end; @@ -263,15 +269,23 @@ function TBoldIntegerFollowerController.GetCurrentAsInteger(Follower: TBoldFollo procedure TBoldIntegerFollowerController.SetAsInteger(Value: Integer; Follower: TBoldFollower); begin - EffectiveAsIntegerRenderer.SetAsInteger(Follower.Element, Value, Representation, Expression, GetVariableListAndSubscribe(follower.Subscriber)); + EffectiveAsIntegerRenderer.SetAsInteger(Follower, Value); end; procedure TBoldIntegerFollowerController.MayHaveChanged(NewValue: Integer; Follower: TBoldFollower); +var + lIsChanged: boolean; + lRendererData: TBoldIntegerRendererData; begin if Follower.State in bfsDisplayable then begin - (Follower.RendererData as TBoldIntegerRendererData).CurrentIntegerValue := NewValue; - Follower.ControlledValueChanged(EffectiveAsIntegerRenderer.IsChanged(Follower.RendererData as TBoldIntegerRendererData, NewValue, Representation, Expression, GetVariableListAndSubscribe(follower.Subscriber))); + lRendererData := (Follower.RendererData as TBoldIntegerRendererData); + lRendererData.CurrentIntegerValue := NewValue; + lIsChanged := EffectiveAsIntegerRenderer.IsChanged(Follower, NewValue); + if lIsChanged then + begin + Follower.ControlledValueChanged; + end; end; end; @@ -283,3 +297,4 @@ finalization end. + diff --git a/Source/BoldAwareGUI/ControlPacks/BoldStringControlPack.pas b/Source/BoldAwareGUI/ControlPacks/BoldStringControlPack.pas index 26f989b..28303e9 100644 --- a/Source/BoldAwareGUI/ControlPacks/BoldStringControlPack.pas +++ b/Source/BoldAwareGUI/ControlPacks/BoldStringControlPack.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldStringControlPack; {$UNDEF BOLDCOMCLIENT} @@ -21,12 +24,12 @@ TBoldAsStringRenderer = class; TBoldStringRendererData = class; { TBoldAsStringRenderer prototypes } - TBoldGetAsString = function (Element: TBoldElement; Representation: TBoldRepresentation; Expression: TBoldExpression): string of object; - TBoldSetAsString = procedure (Element: TBoldElement; NewValue: string; Representation: TBoldRepresentation; Expression: TBoldExpression) of object; - TBoldValidateString = function (Element: TBoldElement; Value: string; Representation: TBoldRepresentation; Expression: TBoldExpression): Boolean of object; - TBoldSetFont = procedure (Element: TBoldElement; AFont: TFont; Representation: TBoldRepresentation; Expression: TBoldExpression) of object; - TBoldSetColor = procedure (Element: TBoldElement; var AColor: TColor; Representation: TBoldRepresentation; Expression: TBoldExpression) of object; - TBoldStringIsChanged = function (RendererData: TBoldStringRendererData; NewValue: string; Representation: TBoldRepresentation; Expression: TBoldExpression): Boolean of object; + TBoldGetAsString = function (aFollower: TBoldFollower): string of object; + TBoldSetAsString = procedure (aFollower: TBoldFollower; const NewValue: string) of object; + TBoldValidateString = function (aFollower: TBoldFollower; const Value: string): Boolean of object; + TBoldSetFont = procedure (aFollower: TBoldFollower; AFont: TFont) of object; + TBoldSetColor = procedure (aFollower: TBoldFollower; var AColor: TColor) of object; + TBoldStringIsChanged = function (aFollower: TBoldFollower; const NewValue: string): Boolean of object; { TBoldStringRendererData } TBoldStringRendererData = class(TBoldRendererData) @@ -51,29 +54,29 @@ TBoldAsStringRenderer = class(TBoldSingleRenderer) fOnSetFont: TBoldSetFont; fOnSetColor: TBoldSetColor; fOnIsChanged: TBoldStringIsChanged; - function DefaultDisplayString: string; + function DefaultDisplayString: string; protected function GetSupportsMulti: Boolean; override; function GetRendererDataClass: TBoldRendererDataClass; override; - function GetAsStringAndSubscribe(Element: TBoldElement; FollowerController: TBoldStringFollowerController; Subscriber: TBoldSubscriber): string; virtual; - procedure SetAsString(Element: TBoldElement; Value: string; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList); virtual; + function GetAsStringAndSubscribe(aFollower: TBoldFollower; Subscriber: TBoldSubscriber): string; virtual; + procedure SetAsString(aFollower: TBoldFollower; const Value: string); virtual; procedure DrawOnCanvas(Follower: TBoldFollower; Canvas: TCanvas; Rect: TRect; Alignment: TAlignment; Margins: TPoint); override; public class function DefaultRenderer: TBoldAsStringRenderer; class procedure DrawStringOnCanvas(Canvas: TCanvas; Rect: TRect; Alignment: TAlignment; Margins: TPoint; S: string); - function DefaultGetAsStringAndSubscribe(Element: TBoldElement; FollowerController: TBoldStringFollowerController; Subscriber: TBoldSubscriber): string; virtual; - procedure DefaultSetAsString(Element: TBoldElement; Value: string; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList); virtual; - function DefaultValidateCharacter(Element: TBoldElement; C: AnsiChar; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList): Boolean; virtual; - function DefaultValidateString(Element: TBoldElement; Value: string; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList): Boolean; virtual; - function DefaultIsChanged(RendererData: TBoldStringRendererData; NewValue: string; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList): Boolean; - function ValidateCharacter(Element: TBoldElement; C: AnsiChar; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList): Boolean; virtual; - function ValidateString(Element: TBoldElement; Value: string; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList): Boolean; virtual; - function IsChanged(RendererData: TBoldStringRendererData; NewValue: string; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList): Boolean; - procedure SetFont(Element: TBoldElement; EffectiveFont, Font: TFont; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList); - procedure SetColor(Element: TBoldElement; var EffectiveColor: TColor; Color: TColor; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList); - procedure MakeUptodateAndSubscribe(Element: TBoldElement; RendererData: TBoldRendererData; FollowerController: TBoldFollowerController; Subscriber: TBoldSubscriber); override; + function DefaultGetAsStringAndSubscribe(aFollower: TBoldFollower; Subscriber: TBoldSubscriber): string; virtual; + procedure DefaultSetAsString(aFollower: TBoldFollower; const Value: string); virtual; + function DefaultValidateCharacter(aFollower: TBoldFollower; C: Char): Boolean; override; + function DefaultValidateString(aFollower: TBoldFollower; const Value: string): Boolean; virtual; + function DefaultIsChanged(aFollower: TBoldFollower; const NewValue: string): Boolean; + function ValidateCharacter(aFollower: TBoldFollower; C: Char): Boolean; override; + function ValidateString(aFollower: TBoldFollower; const Value: string): Boolean; virtual; + function IsChanged(aFollower: TBoldFollower; const NewValue: string): Boolean; + procedure SetFont(aFollower: TBoldFollower; EffectiveFont, Font: TFont); + procedure SetColor(aFollower: TBoldFollower; var EffectiveColor: TColor; Color: TColor); + procedure MakeUptodateAndSubscribe(aFollower: TBoldFollower; Subscriber: TBoldSubscriber); override; procedure MultiMakeUpToDateAndSubscribe(Elements: TBoldClientableList; Subscribers: TBoldObjectArray; RendererData: TBoldObjectArray; FollowerController: TBoldFollowerController); - procedure DefaultMakeUptodateAndSetMayModifyAndSubscribe(Element: TBoldElement; RendererData: TBoldRendererData; FollowerController: TBoldStringFollowerController; Subscriber: TBoldSubscriber); virtual; + procedure DefaultMakeUptodateAndSetMayModifyAndSubscribe(aFollower: TBoldFollower; Subscriber: TBoldSubscriber); virtual; published property OnGetAsString: TBoldGetAsString read FOnGetAsString write FOnGetAsString; property OnSetAsString: TBoldSetAsString read FOnSetAsString write FOnSetAsString; @@ -88,26 +91,26 @@ TBoldAsStringRenderer = class(TBoldSingleRenderer) TBoldStringFollowerController = class(TBoldSingleFollowerController) private FNilStringRepresentation: string; - function GetRenderer: TBoldAsStringRenderer; - procedure SetRenderer(Value: TBoldAsStringRenderer); - function GetEffectiveAsStringRenderer: TBoldAsStringRenderer; + function GetRenderer: TBoldAsStringRenderer; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure SetRenderer(Value: TBoldAsStringRenderer); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetEffectiveAsStringRenderer: TBoldAsStringRenderer; {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure SetNilStringRepresentation(const Value: string); protected function GetSupportsMultiEnsure: Boolean; override; function GetEffectiveRenderer: TBoldRenderer; override; property EffectiveAsStringRenderer: TBoldAsStringRenderer read GetEffectiveAsStringRenderer; - procedure DoMultiMakeUptodateAndSubscribe(Followers: TBoldObjectArray); override; + procedure DoMultiMakeUptodateAndSubscribe(Followers: TBoldFollowerArray); override; public procedure MakeClean(Follower: TBoldFollower); override; - function GetCurrentAsString(Follower: TBoldFollower): string; - procedure SetAsString(Value: string; Follower: TBoldFollower); - function ValidateCharacter(C: AnsiChar; Follower: TBoldFollower): Boolean; - function ValidateString(Value: string; Follower: TBoldFollower): Boolean; - procedure SetFont(EffectiveFont, Font: tFont; Follower: TBoldFollower); - procedure SetColor(var EffectiveColor: tColor; COLOR: tColor; Follower: TBoldFollower); - procedure MayHaveChanged(NewValue: string; Follower: TBoldFollower); + function GetCurrentAsString(Follower: TBoldFollower): string; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure SetAsString(Value: string; Follower: TBoldFollower); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function ValidateCharacter(C: Char; Follower: TBoldFollower): Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function ValidateString(Value: string; Follower: TBoldFollower): Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure SetFont(EffectiveFont, Font: tFont; Follower: TBoldFollower); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure SetColor(var EffectiveColor: tColor; COLOR: tColor; Follower: TBoldFollower); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function MayHaveChanged(const NewValue: string; Follower: TBoldFollower): boolean; procedure DoMakeUptodateAndSubscribe(Follower: TBoldFollower; Subscribe: Boolean); override; - function GetAsString(Element: TBoldElement): string; + function GetAsString(aFollower: TBoldFollower): string; {$IFDEF BOLD_INLINE} inline; {$ENDIF} published property Renderer: TBoldAsStringRenderer read GetRenderer write SetRenderer; property NilStringRepresentation: string read FNilStringRepresentation write SetNilStringRepresentation; @@ -119,12 +122,13 @@ implementation SysUtils, BoldControlPackDefs, {$IFNDEF BOLDCOMCLIENT} - BoldSystem, // IFNDEF BOLDCOMCLIENT + BoldSystem, BoldDomainElement, {$ELSE} - Variants, // IFDEF BOLDCOMCLIENT + Variants, {$ENDIF} - BoldGuiResourceStrings; + BoldGuard, + BoldRev; var DefaultAsStringRenderer: TBoldAsStringRenderer; @@ -161,36 +165,45 @@ function TBoldStringFollowerController.GetCurrentAsString(Follower: TBoldFollowe procedure TBoldStringFollowerController.SetAsString(Value: string; Follower: TBoldFollower); begin - EffectiveAsStringRenderer.SetAsString(Follower.Element, Value, Representation, Expression, VariableList); + EffectiveAsStringRenderer.SetAsString(Follower, Value); end; -function TBoldStringFollowerController.ValidateCharacter(C: AnsiChar; Follower: TBoldFollower): Boolean; +function TBoldStringFollowerController.ValidateCharacter(C: Char; Follower: TBoldFollower): Boolean; begin - Result := EffectiveAsStringRenderer.ValidateCharacter(Follower.Element, C, Representation, Expression, VariableList); + Result := EffectiveAsStringRenderer.ValidateCharacter(Follower, C); end; function TBoldStringFollowerController.ValidateString(Value: string; Follower: TBoldFollower): Boolean; begin - Result := EffectiveAsStringRenderer.ValidateString(Follower.Element, Value, Representation, Expression, VariableList); + Result := EffectiveAsStringRenderer.ValidateString(Follower, Value); end; procedure TBoldStringFollowerController.SetFont(EffectiveFont, Font: tFont; Follower: TBoldFollower); begin - EffectiveAsStringRenderer.SetFont(Follower.Element, EffectiveFont, Font, Representation, Expression, VariableList); + EffectiveAsStringRenderer.SetFont(Follower, EffectiveFont, Font); end; procedure TBoldStringFollowerController.SetColor(var EffectiveColor: tColor; COLOR: tColor; Follower: TBoldFollower); begin - EffectiveAsStringRenderer.SetColor(Follower.Element, EffectiveColor, COLOR, Representation, Expression, VariableList); + EffectiveAsStringRenderer.SetColor(Follower, EffectiveColor, Color); end; -procedure TBoldStringFollowerController.MayHaveChanged(NewValue: string; Follower: TBoldFollower); +function TBoldStringFollowerController.MayHaveChanged(const NewValue: string; Follower: TBoldFollower): boolean; +var + lBoldStringRendererData: TBoldStringRendererData; begin if Follower.State in bfsDisplayable then begin - (Follower.RendererData as TBoldStringRendererData).CurrentStringValue := NewValue; - Follower.ControlledValueChanged(EffectiveAsStringRenderer.IsChanged(Follower.RendererData as TBoldStringRendererData, NewValue, Representation, Expression, VariableList)); - end; + lBoldStringRendererData := Follower.RendererData as TBoldStringRendererData; + lBoldStringRendererData.CurrentStringValue := NewValue; + result := EffectiveAsStringRenderer.IsChanged(Follower, NewValue); + if result then + begin + Follower.ControlledValueChanged; + end; + end + else + result := false; end; procedure TBoldStringFollowerController.MakeClean(Follower: TBoldFollower); @@ -202,7 +215,7 @@ procedure TBoldStringFollowerController.MakeClean(Follower: TBoldFollower); begin if ValidateString(GetCurrentAsString(Follower), Follower) then begin - ReleaseChangedValue(Follower); // note, must do first, since set can change element + ReleaseChangedValue(Follower); SetAsString(GetCurrentAsString(Follower), Follower); end else @@ -214,10 +227,10 @@ procedure TBoldStringFollowerController.MakeClean(Follower: TBoldFollower); el := nil; FailureReason := GetBoldLastFailureReason; if assigned(FailureReason) then - GetBoldLastFailureReason.MessageFormatStr := sStringValidationFailedExtended; - BoldRaiseLastFailure(el, '', sUnknownReason); + GetBoldLastFailureReason.MessageFormatStr := 'String validation failed for %s: %2:s'; + BoldRaiseLastFailure(el, '', 'Unknown reason'); {$ELSE} - raise EBold.Create(sStringValidationFailed); + raise EBold.Create('String validation failed'); {$ENDIF} end; end; @@ -232,11 +245,12 @@ procedure TBoldStringFollowerController.DoMakeUptodateAndSubscribe(Follower: TBo else Subscriber := nil; Renderer := EffectiveRenderer as TBoldAsStringRenderer; - if Assigned(Renderer.OnGetAsString) or Assigned(Renderer.OnSubscribe) or Assigned(Renderer.OnMayModify) then begin - Renderer.MakeUptodateAndSubscribe(Follower.Element, Follower.RendererData, Self, Subscriber); - Follower.RendererData.MayModify := Renderer.MayModify(Follower.Element, Representation, Expression, GetVariableListAndSubscribe(follower.Subscriber), Follower.Subscriber); - end else - renderer.DefaultMakeUptodateAndSetMayModifyAndSubscribe(Follower.Element, Follower.RendererData, Self, Subscriber); + if Assigned(Renderer.OnGetAsString) or Assigned(Renderer.OnSubscribe) or Assigned(Renderer.OnMayModify) then + begin + Renderer.MakeUptodateAndSubscribe(Follower, Subscriber); + end + else + renderer.DefaultMakeUptodateAndSetMayModifyAndSubscribe(Follower, Subscriber); end; procedure TBoldStringFollowerController.SetNilStringRepresentation(const Value: string); @@ -253,7 +267,6 @@ procedure TBoldStringFollowerController.SetNilStringRepresentation(const Value: var Left: Integer; begin - // Adjust for alignment case Alignment of taLeftJustify: Left := Margins.X + Rect.Left; taRightJustify: Left := (Rect.Right - Rect.Left) - Canvas.TextWidth(S) + Rect.Left - 1 - Margins.X; @@ -268,24 +281,18 @@ procedure TBoldAsStringRenderer.DrawOnCanvas(Follower: TBoldFollower; Canvas: TC DrawStringOnCanvas(Canvas, Rect, Alignment, Margins, TBoldStringRendererData(Follower.RendererData).CurrentStringValue); end; -procedure TBoldAsStringRenderer.MakeUpToDateAndSubscribe(Element: TBoldElement; RendererData: TBoldRendererData; FollowerController: TBoldFollowerController; Subscriber: TBoldSubscriber); +procedure TBoldAsStringRenderer.MakeUpToDateAndSubscribe(aFollower: TBoldFollower; Subscriber: TBoldSubscriber); var S: string; + lRendererData: TBoldStringRendererData; begin - S := GetAsStringAndSubscribe(Element, FollowerController as TBoldStringFollowerController, Subscriber); - (RendererData as TBoldStringRendererData).OldStringValue := S; - (RendererData as TBoldStringRendererData).CurrentStringValue := S; + S := GetAsStringAndSubscribe(aFollower, Subscriber); + lRendererData := (aFollower.RendererData as TBoldStringRendererData); + lRendererData.OldStringValue := S; + lRendererData.CurrentStringValue := S; end; -function TBoldAsStringRenderer.DefaultDisplayString: string; -begin - if Name <> '' then - Result := '(' + Name + ')' - else - Result := '(' + ClassName + ')'; -end; - -procedure TBoldAsStringRenderer.DefaultMakeUptodateAndSetMayModifyAndSubscribe(Element: TBoldElement; RendererData: TBoldRendererData; FollowerController: TBoldStringFollowerController; Subscriber: TBoldSubscriber); +procedure TBoldAsStringRenderer.DefaultMakeUptodateAndSetMayModifyAndSubscribe(aFollower: TBoldFollower; Subscriber: TBoldSubscriber); var {$IFDEF BOLDCOMCLIENT} // defaultMakeUpToDate e: IBoldElement; @@ -293,16 +300,24 @@ procedure TBoldAsStringRenderer.DefaultMakeUptodateAndSetMayModifyAndSubscribe(E E: TBoldIndirectElement; {$ENDIF} S: String; + lFollowerController: TBoldStringFollowerController; + lRendererData: TBoldStringRendererData; + lRepresentation: integer; + lResultElement: TBoldElement; + lGuard: IBoldGuard; begin S := ''; + lRendererData:= aFollower.RendererData as TBoldStringRendererData; if (csDesigning in ComponentState) and (Self <> DefaultRenderer) then begin s := DefaultDisplayString; - RendererData.MayModify := False; +// lRendererData.MayModify := False; end else begin - if Assigned(Element) then + lFollowerController := aFollower.AssertedController as TBoldStringFollowerController; + lRepresentation := lFollowerController.Representation; + if Assigned(aFollower.Element) then begin {$IFDEF BOLDCOMCLIENT} // defaultMakeUpToDate if assigned(Subscriber) then @@ -315,45 +330,50 @@ procedure TBoldAsStringRenderer.DefaultMakeUptodateAndSetMayModifyAndSubscribe(E S := E.StringRepresentation[FollowerController.Representation]; if Assigned(Subscriber) then E.SubscribeToStringRepresentation(FollowerController.Representation, Subscriber.ClientId, Subscriber.SubscriberId, breReEvaluate, false); - RendererData.MayModify := true; + lRendererData.MayModify := true; end else S := FollowerController.NilStringRepresentation {$ELSE} - E := TBoldIndirectElement.Create; - try - Element.EvaluateAndSubscribeToExpression(FollowerController.Expression, Subscriber, E, False, False, FollowerController.GetVariableListAndSubscribe(Subscriber)); - if (e.Value is TBoldObjectReference) and not assigned((e.Value as TBoldObjectReference).BoldObject) then - begin - s := FollowerController.NilStringRepresentation; - if Assigned(Subscriber) then - E.Value.SubscribeToStringRepresentation(FollowerController.Representation, Subscriber, breReEvaluate); - RendererData.MayModify := E.Value.ObserverMayModifyAsString(FollowerController.Representation, Subscriber); - (RendererData as TBoldStringRendererData).MaxStringLength := -1; - end - else if Assigned(E.Value) then - begin - S := E.Value.StringRepresentation[FollowerController.Representation]; - if Assigned(Subscriber) then - E.Value.SubscribeToStringRepresentation(FollowerController.Representation, Subscriber, breReEvaluate); - RendererData.MayModify := E.Value.ObserverMayModifyAsString(FollowerController.Representation, Subscriber); - if (E.Value is TBoldAttribute) and assigned((E.Value as TBoldAttribute).BoldAttributeRTInfo) then - (RendererData as TBoldStringRendererData).MaxStringLength := (E.Value as TBoldAttribute).BoldAttributeRTInfo.Length - else - (RendererData as TBoldStringRendererData).MaxStringLength := -1; - end + lResultElement := aFollower.Value; + if (lResultElement is TBoldObjectReference) and not assigned(TBoldObjectReference(lResultElement).BoldObject) then + begin + s := lFollowerController.NilStringRepresentation; + if Assigned(Subscriber) then + lResultElement.SubscribeToStringRepresentation(lRepresentation, Subscriber, breReEvaluate); +// lRendererData.MayModify := lResultElement.ObserverMayModify(Subscriber); +// lRendererData.MayModify := lResultElement.ObserverMayModifyAsString(lRepresentation, Subscriber); + lRendererData.MaxStringLength := -1; + end + else if Assigned(lResultElement) then + begin + S := lResultElement.StringRepresentation[lRepresentation]; + if Assigned(Subscriber) then + lResultElement.SubscribeToStringRepresentation(lRepresentation, Subscriber, breReEvaluate); +// lRendererData.MayModify := lResultElement.ObserverMayModify(Subscriber); +// lRendererData.MayModify := lResultElement.ObserverMayModifyAsString(lRepresentation, Subscriber); + if (lResultElement is TBoldAttribute) and assigned(TBoldAttribute(lResultElement).BoldAttributeRTInfo) then + lRendererData.MaxStringLength := TBoldAttribute(lResultElement).BoldAttributeRTInfo.Length else - S := FollowerController.NilStringRepresentation - finally - E.Free; - end; + lRendererData.MaxStringLength := -1; +{ if (lResultElement is TBoldDomainElement) and not TBoldDomainElement(lResultElement).BoldDirty then + begin + lRendererData.OldStringValue := S; + end; +} + end + else + S := lFollowerController.NilStringRepresentation; {$ENDIF} end else - S := FollowerController.NilStringRepresentation + begin + S := lFollowerController.NilStringRepresentation; +// lRendererData.MayModify := false; + end; end; - (RendererData as TBoldStringRendererData).OldStringValue := S; - (RendererData as TBoldStringRendererData).CurrentStringValue := S; + lRendererData.OldStringValue := S; + lRendererData.CurrentStringValue := S; end; function TBoldAsStringRenderer.GetRendererDataClass: TBoldRendererDataClass; @@ -361,13 +381,24 @@ function TBoldAsStringRenderer.GetRendererDataClass: TBoldRendererDataClass; Result := TBoldStringRendererData; end; -function TBoldAsStringRenderer.DefaultGetAsStringAndSubscribe(Element: TBoldElement; FollowerController: TBoldStringFollowerController; Subscriber: TBoldSubscriber): string; +function TBoldAsStringRenderer.DefaultDisplayString: string; +begin + if Name <> '' then + Result := '(' + Name + ')' + else + Result := '(' + ClassName + ')'; +end; + +function TBoldAsStringRenderer.DefaultGetAsStringAndSubscribe(aFollower: TBoldFollower; Subscriber: TBoldSubscriber): string; var {$IFDEF BOLDCOMCLIENT} // DefaultGet e: IBoldElement; {$ELSE} E: TBoldIndirectElement; {$ENDIF} + lFollowerController: TBoldStringFollowerController; + lResultElement: TBoldElement; + lGuard: IBoldGuard; begin Result := ''; if (csDesigning in ComponentState) and (Self <> DefaultRenderer) then @@ -376,7 +407,8 @@ function TBoldAsStringRenderer.DefaultGetAsStringAndSubscribe(Element: TBoldElem end else begin - if Assigned(Element) then + lFollowerController := aFollower.AssertedController as TBoldStringFollowerController; + if Assigned(aFollower.Element) then begin {$IFDEF BOLDCOMCLIENT} // defaultGet if assigned(Subscriber) then @@ -392,134 +424,136 @@ function TBoldAsStringRenderer.DefaultGetAsStringAndSubscribe(Element: TBoldElem else Result := FollowerController.NILStringRepresentation; {$ELSE} - E := TBoldIndirectElement.Create; - try - Element.EvaluateAndSubscribeToExpression(FollowerController.Expression, Subscriber, E, False, False, FollowerController.GetVariableListAndSubscribe(Subscriber)); - if (e.Value is TBoldObjectReference) and not assigned((e.Value as TBoldObjectReference).BoldObject) then - begin - result := FollowerController.NilStringRepresentation; - if Assigned(Subscriber) then - E.Value.SubscribeToStringRepresentation(FollowerController.Representation, Subscriber, breReEvaluate); - end - else if Assigned(E.Value) then - begin - Result := E.Value.StringRepresentation[FollowerController.Representation]; - if Assigned(Subscriber) then - E.Value.SubscribeToStringRepresentation(FollowerController.Representation, Subscriber, breReEvaluate); - end - else - Result := FollowerController.NILStringRepresentation; - finally - E.Free; + lResultElement := aFollower.Value; + if not Assigned(lResultElement) then + begin + lGuard:= TBoldGuard.Create(E); + E := TBoldIndirectElement.Create; + aFollower.Element.EvaluateAndSubscribeToExpression(lFollowerController.Expression, Subscriber, E, False, False, lFollowerController.GetVariableListAndSubscribe(Subscriber)); + lResultElement := e.Value; end; + if (lResultElement is TBoldObjectReference) and not assigned(TBoldObjectReference(lResultElement).BoldObject) then + begin + result := lFollowerController.NilStringRepresentation; + if Assigned(Subscriber) then + lResultElement.SubscribeToStringRepresentation(lFollowerController.Representation, Subscriber, breReEvaluate); + end + else if Assigned(lResultElement) then + begin + Result := lResultElement.StringRepresentation[lFollowerController.Representation]; + if Assigned(Subscriber) then + lResultElement.SubscribeToStringRepresentation(lFollowerController.Representation, Subscriber, breReEvaluate); + end + else + Result := lFollowerController.NILStringRepresentation; {$ENDIF} end else - Result := FollowerController.NILStringRepresentation; + Result := lFollowerController.NILStringRepresentation; end; end; -procedure TBoldAsStringRenderer.DefaultSetAsString(Element: TBoldElement; Value: string; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList); +procedure TBoldAsStringRenderer.DefaultSetAsString(aFollower: TBoldFollower; const Value: string); var ValueElement: TBoldElement; begin - ValueElement := GetExpressionAsDirectElement(Element, Expression, VariableList); + ValueElement := aFollower.Value; if Assigned(ValueElement) then - ValueElement.StringRepresentation[Representation] := Value + ValueElement.StringRepresentation[aFollower.AssertedController.Representation] := Value else - raise EBold.CreateFmt(sCannotSetStringValue, [ClassName]); + raise EBold.Create('TBoldAsStringRenderer.DefaultSetAsString: Can''t set string value'); end; -function TBoldAsStringRenderer.DefaultValidateCharacter(Element: TBoldElement; C: AnsiChar; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList): Boolean; +function TBoldAsStringRenderer.DefaultValidateCharacter(aFollower: TBoldFollower; C: Char): Boolean; var ValueElement: TBoldElement; begin - ValueElement := GetExpressionAsDirectElement(Element, Expression, VariableList); + ValueElement := aFollower.Value; if Assigned(ValueElement) then - Result := ValueElement.ValidateCharacter(C, Representation) + Result := ValueElement.ValidateCharacter(C, aFollower.AssertedController.Representation ) else - Result := False; + Result := HasSetValueEventOverrides; end; -function TBoldAsStringRenderer.DefaultValidateString(Element: TBoldElement; Value: string; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList): Boolean; +function TBoldAsStringRenderer.DefaultValidateString(aFollower: TBoldFollower; const Value: string): Boolean; var ValueElement: TBoldElement; begin - ValueElement := GetExpressionAsDirectElement(Element, Expression, VariableList); + ValueElement := aFollower.Value; if Assigned(ValueElement) then - Result := ValueElement.ValidateString(Value, Representation) + Result := ValueElement.ValidateString(Value, aFollower.AssertedController.Representation) else Result := False; end; -function TBoldAsStringRenderer.GetAsStringAndSubscribe(Element: TBoldElement; FollowerController: TBoldStringFollowerController; Subscriber: TBoldSubscriber): string; +function TBoldAsStringRenderer.GetAsStringAndSubscribe(aFollower: TBoldFollower; Subscriber: TBoldSubscriber): string; begin if Assigned(OnSubscribe) and Assigned(Subscriber) then begin - if Assigned(Element) then - OnSubscribe(Element, FollowerController.Representation, FollowerController.Expression, Subscriber); + if Assigned(aFollower.Element) then + OnSubscribe(aFollower, Subscriber); Subscriber := nil; end; if Assigned(OnGetAsString) then - Result := OnGetAsString(Element, FollowerController.Representation, FollowerController.Expression) + Result := OnGetAsString(aFollower) else - Result := DefaultGetAsStringAndSubscribe(Element, FollowerController, Subscriber); + Result := DefaultGetAsStringAndSubscribe(aFollower, Subscriber); end; -procedure TBoldAsStringRenderer.SetAsString(Element: TBoldElement; Value: string; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList); +procedure TBoldAsStringRenderer.SetAsString(aFollower: TBoldFollower; const Value: string); begin if Assigned(FOnSetAsString) then - OnSetAsString(Element, Value, Representation, Expression) + OnSetAsString(aFollower, Value) else - DefaultSetAsString(Element, Value, Representation, Expression, VariableList) + DefaultSetAsString(aFollower, Value) end; -function TBoldAsStringRenderer.ValidateCharacter(Element: TBoldElement; C: AnsiChar; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList): Boolean; +function TBoldAsStringRenderer.ValidateCharacter(aFollower: TBoldFollower; C: Char): Boolean; begin if Assigned(FOnValidateCharacter) then - Result := OnValidateCharacter(Element, C, Representation, Expression) + Result := OnValidateCharacter(aFollower, c) else - Result := DefaultValidateCharacter(Element, C, Representation, Expression, VariableList); + Result := DefaultValidateCharacter(aFollower, c); end; -function TBoldAsStringRenderer.ValidateString(Element: TBoldElement; Value: string; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList): Boolean; +function TBoldAsStringRenderer.ValidateString(aFollower: TBoldFollower; const Value: string): Boolean; begin if Assigned(FOnValidateString) then - Result := OnValidateString(Element, Value, Representation, Expression) + Result := OnValidateString(aFollower, Value) else - Result := DefaultValidateString(Element, Value, Representation, Expression, VariableList); + Result := DefaultValidateString(aFollower, Value); end; -procedure TBoldAsStringRenderer.SetFont(Element: TBoldElement; EffectiveFont, Font: tFont; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList); +procedure TBoldAsStringRenderer.SetFont(aFollower: TBoldFollower; EffectiveFont, Font: TFont); begin EffectiveFont.Assign(Font); if Assigned(fOnSetFont) then - fOnSetFont(Element, EffectiveFont, Representation, Expression); + fOnSetFont(aFollower, EffectiveFont); end; -procedure TBoldAsStringRenderer.SetColor(Element: TBoldElement; var EffectiveColor: tColor; COLOR: tColor; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList); +procedure TBoldAsStringRenderer.SetColor(aFollower: TBoldFollower; var EffectiveColor: TColor; Color: TColor); begin - EffectiveColor := COLOR; + EffectiveColor := Color; if Assigned(fOnSetColor) then - fOnSetColor(Element, EffectiveColor, Representation, Expression); + fOnSetColor(aFollower, EffectiveColor); end; - class function TBoldAsStringRenderer.DefaultRenderer: TBoldAsStringRenderer; +class function TBoldAsStringRenderer.DefaultRenderer: TBoldAsStringRenderer; begin Result := DefaultAsStringRenderer; end; -function TBoldAsStringRenderer.DefaultIsChanged(RendererData: TBoldStringRendererData; NewValue: string; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList): Boolean; +function TBoldAsStringRenderer.DefaultIsChanged(aFollower: TBoldFollower; const NewValue: string): Boolean; begin - Result := NewValue <> RendererData.OldStringValue; + Result := NewValue <> TBoldStringRendererData(aFollower.RendererData).OldStringValue; end; -function TBoldAsStringRenderer.IsChanged(RendererData: TBoldStringRendererData; NewValue: string; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList): Boolean; +function TBoldAsStringRenderer.IsChanged(aFollower: TBoldFollower; const NewValue: string): Boolean; begin if Assigned(fOnIsChanged) then - Result := fOnIsChanged(RendererData, NewValue, Representation, Expression) + Result := fOnIsChanged(aFollower, NewValue) else - Result := DefaultIsChanged(RendererData, NewValue, Representation, Expression, Variablelist); + Result := DefaultIsChanged(aFollower, NewValue); end; { TBoldStringRendererData } @@ -550,32 +584,28 @@ function TBoldStringFollowerController.GetSupportsMultiEnsure: Boolean; end; procedure TBoldStringFollowerController.DoMultiMakeUptodateAndSubscribe( - Followers: TBoldObjectArray); + Followers: TBoldFollowerArray); var Renderer: TBoldAsStringRenderer; Elements: TBoldClientableList; - TempFollower: TBoldFollower; + F: TBoldFollower; Subscribers: TBoldObjectArray; RendererData: TBoldObjectArray; - I: integer; - MaxIndex: integer; begin Assert(SupportsMulti); - MaxIndex := Followers.Count - 1; Renderer := EffectiveRenderer as TBoldAsStringRenderer; - Elements := TBoldClientableList.Create(MaxIndex,[]); - Subscribers := TBoldObjectArray.Create(MaxIndex,[]); - RendererData := TBoldObjectArray.Create(MaxIndex,[]); + Elements := TBoldClientableList.Create(Length(Followers),[]); + Subscribers := TBoldObjectArray.Create(Length(Followers),[]); + RendererData := TBoldObjectArray.Create(Length(Followers),[]); try - for I := 0 to MaxIndex do + for F in Followers do begin - TempFollower := TBoldFollower(Followers[I]); - Elements.Add(Tempfollower.Element); - if TempFollower.State in bfdNeedResubscribe then - Subscribers.Add(TempFollower.Subscriber) + Elements.Add(F.Element); + if F.State in bfdNeedResubscribe then + Subscribers.Add(F.Subscriber) else Subscribers.Add(nil); - RendererData.Add(TempFollower.RendererData); + RendererData.Add(F.RendererData); end; Renderer.MultiMakeUpToDateAndSubscribe(Elements, Subscribers, RendererData, Self); finally @@ -629,9 +659,9 @@ procedure TBoldAsStringRenderer.MultiMakeUpToDateAndSubscribe( {$ENDIF} end; -function TBoldStringFollowerController.GetAsString(Element: TBoldElement): string; +function TBoldStringFollowerController.GetAsString(aFollower: TBoldFollower): string; begin - result := EffectiveAsStringRenderer.GetAsStringAndSubscribe(element, self, nil); + result := EffectiveAsStringRenderer.GetAsStringAndSubscribe(aFollower, nil); end; initialization @@ -641,4 +671,3 @@ finalization FreeAndNil(DefaultAsStringRenderer); end. - diff --git a/Source/BoldAwareGUI/ControlPacks/BoldVariantControlPack.pas b/Source/BoldAwareGUI/ControlPacks/BoldVariantControlPack.pas new file mode 100644 index 0000000..1b75b0f --- /dev/null +++ b/Source/BoldAwareGUI/ControlPacks/BoldVariantControlPack.pas @@ -0,0 +1,674 @@ +unit BoldVariantControlPack; + +{ Global compiler directives } +{$include bold.inc} + +{$UNDEF BOLDCOMCLIENT} + +interface + +uses + Graphics, + Classes, + Windows, + BoldDefs, + BoldContainers, + BoldElements, + BoldControlPack, + BoldSubscription, + Variants; + +type + {Forward declaration of classes} + TBoldVariantFollowerController = class; + TBoldCustomAsVariantRenderer = class; + TBoldAsVariantRenderer = class; + TBoldVariantRendererData = class; + + { TBoldAsVariantRenderer prototypes } + TBoldGetAsVariant = function (AFollower: TBoldFollower): Variant of object; + TBoldSetAsVariant = procedure (aFollower: TBoldFollower; const NewValue: Variant) of object; + TBoldValidateVariant = function (aFollower: TBoldFollower; const Value: Variant): Boolean of object; + TBoldSetFont = procedure (aFollower: TBoldFollower; AFont: TFont) of object; + TBoldSetColor = procedure (aFollower: TBoldFollower; var AColor: TColor) of object; + TBoldVariantIsChanged = function (aFollower: TBoldFollower; const NewValue: Variant): Boolean of object; + TBoldValidateString = function (aFollower: TBoldFollower; const Value: string): Boolean of object; + TBoldGetAsString = function (AFollower: TBoldFollower{; Subscriber: TBoldSubscriber}): string of object; + + { TBoldVariantRendererData } + TBoldVariantRendererData = class(TBoldRendererData) + private + fOldVariantValue: Variant; + fCurrentVariantValue: Variant; + fMaxStringLength: integer; + public + constructor Create(OwningFollower: TBoldFollower); override; + property OldVariantValue: Variant read fOldVariantValue write fOldVariantValue; + property CurrentVariantValue: Variant read fCurrentVariantValue write fCurrentVariantValue; + property MaxStringLength: integer read fMaxStringLength write fMaxStringLength; + end; + + { TBoldCustomAsVariantRenderer } + TBoldCustomAsVariantRenderer = class(TBoldSingleRenderer) + private + FOnGetAsVariant: TBoldGetAsVariant; + FOnSetAsVariant: TBoldSetAsVariant; + FOnValidateVariant: TBoldValidateVariant; + fOnSetFont: TBoldSetFont; + fOnSetColor: TBoldSetColor; + fOnIsChanged: TBoldVariantIsChanged; + FOnGetAsString: TBoldGetAsString; + protected + function DefaultDisplayString: string; + function GetSupportsMulti: Boolean; override; + function GetRendererDataClass: TBoldRendererDataClass; override; + function GetAsVariantAndSubscribe(aFollower: TBoldFollower; Subscriber: TBoldSubscriber): Variant; virtual; + procedure SetAsVariant(aFollower: TBoldFollower; const Value: Variant); virtual; + procedure DrawOnCanvas(Follower: TBoldFollower; Canvas: TCanvas; Rect: TRect; Alignment: TAlignment; Margins: TPoint); override; + function HasSetValueEventOverrides: boolean; override; + public + class function DefaultRenderer: TBoldCustomAsVariantRenderer; virtual; + class procedure DrawValueOnCanvas(Canvas: TCanvas; Rect: TRect; Alignment: TAlignment; Margins: TPoint; const aValue: Variant); + procedure Assign(Source: TPersistent); override; + procedure AssignTo(Dest: TPersistent); override; + function EffectiveRenderer: TBoldCustomAsVariantRenderer; virtual; + function DefaultGetAsVariantAndSubscribe(aFollower: TBoldFollower; Subscriber: TBoldSubscriber): Variant; virtual; + procedure DefaultSetAsVariant(aFollower: TBoldFollower; const Value: Variant); virtual; + function DefaultValidateVariant(aFollower: TBoldFollower; const Value: Variant): Boolean; virtual; + function DefaultIsChanged(aFollower: TBoldFollower; const NewValue: Variant): Boolean; virtual; + function DefaultGetAsString(AFollower: TBoldFollower): string; + function ValidateVariant(aFollower: TBoldFollower; const Value: Variant): Boolean; virtual; + function IsChanged(aFollower: TBoldFollower; const NewValue: Variant): Boolean; + function GetAsString(aFollower: TBoldFollower): string; + procedure SetFont(aFollower: TBoldFollower; EffectiveFont, Font: TFont); + procedure SetColor(aFollower: TBoldFollower; var EffectiveColor: TColor; Color: TColor); + procedure MakeUptodateAndSubscribe(aFollower: TBoldFollower; Subscriber: TBoldSubscriber); override; +// procedure MultiMakeUpToDateAndSubscribe(Elements: TBoldClientableList; Subscribers: TBoldObjectArray; RendererData: TBoldObjectArray; FollowerController: TBoldFollowerController); + procedure DefaultMakeUptodateAndSetMayModifyAndSubscribe(aFollower: TBoldFollower; Subscriber: TBoldSubscriber); virtual; + + property OnGetAsVariant: TBoldGetAsVariant read FOnGetAsVariant write FOnGetAsVariant; + property OnSetAsVariant: TBoldSetAsVariant read FOnSetAsVariant write FOnSetAsVariant; + property OnValidateVariant: TBoldValidateVariant read FOnValidateVariant write FOnValidateVariant; + property OnSetFont: TBoldSetFont read fOnSetFont write fOnSetFont; + property OnSetColor: TBoldSetColor read fOnSetColor write fOnSetColor; + property OnIsChanged: TBoldVariantIsChanged read fOnIsChanged write fOnIsChanged; + property OnGetAsString: TBoldGetAsString read fOnGetAsString write fOnGetAsString; + end; + + TBoldAsVariantRenderer = class(TBoldCustomAsVariantRenderer) + published + property OnGetAsVariant; + property OnSetAsVariant; + property OnValidateVariant; + property OnSetFont; + property OnSetColor; + property OnIsChanged; + property OnGetAsString; + end; + + { TBoldVariantFollowerController } + TBoldVariantFollowerController = class(TBoldSingleFollowerController) + private + FNilRepresentation: Variant; + function GetRenderer: TBoldCustomAsVariantRenderer; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure SetRenderer(Value: TBoldCustomAsVariantRenderer); + function GetEffectiveAsVariantRenderer: TBoldCustomAsVariantRenderer; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure SetNilRepresentation(const Value: Variant); + function IsNilRepresentationStored: boolean; + protected + function GetSupportsMultiEnsure: Boolean; override; + function GetEffectiveRenderer: TBoldRenderer; override; + property EffectiveAsVariantRenderer: TBoldCustomAsVariantRenderer read GetEffectiveAsVariantRenderer; + procedure DoMultiMakeUptodateAndSubscribe(Followers: TBoldFollowerArray); override; + procedure DoAssign(Source: TPersistent); override; + public + constructor Create(aOwningComponent: TComponent); reintroduce; + procedure MakeClean(Follower: TBoldFollower); override; + function GetCurrentAsVariant(Follower: TBoldFollower): Variant; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure SetAsVariant(const Value: Variant; Follower: TBoldFollower); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function ValidateVariant(const Value: Variant; Follower: TBoldFollower): Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function ValidateCharacter(C: Char; aFollower: TBoldFollower): Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure SetFont(EffectiveFont, Font: TFont; Follower: TBoldFollower); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure SetColor(var EffectiveColor: TColor; Color: TColor; Follower: TBoldFollower); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function MayHaveChanged(const NewValue: Variant; Follower: TBoldFollower): boolean; + procedure DoMakeUptodateAndSubscribe(Follower: TBoldFollower; Subscribe: Boolean); override; + function GetAsVariant(aFollower: TBoldFollower): Variant; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetAsString(aFollower: TBoldFollower): String; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + published + property Renderer: TBoldCustomAsVariantRenderer read GetRenderer write SetRenderer; + property NilRepresentation: Variant read FNilRepresentation write SetNilRepresentation stored IsNilRepresentationStored; + end; + +implementation + +uses + SysUtils, + BoldControlPackDefs, + BoldSystem, + BoldDomainElement, + BoldGuiResourceStrings, + BoldGuard, + BoldValueInterfaces; + +var + DefaultAsVariantRenderer: TBoldCustomAsVariantRenderer; + +const +// These should be moved to BoldGuiResourceStrings.pas and perhaps rephrased + sVariantValidationFailedExtended = 'Validation failed for %s: %2:s'; + sVariantValidationFailed = 'Validation failed'; + sCannotSetVariantValue = '%s.DefaultSetAsVariant: Can''t set variant value'; + sUnknownReason = 'Unknown reason'; + +type + TBoldFollowerControllerAccess = class(TBoldFollowerController); + +{ TBoldVariantFollowerController } + +constructor TBoldVariantFollowerController.Create(aOwningComponent: TComponent); +begin + FNilRepresentation := Null; + inherited; +end; + +procedure TBoldVariantFollowerController.DoAssign(Source: TPersistent); +begin + inherited; + FNilRepresentation := TBoldVariantFollowerController(Source).NilRepresentation; +end; + +procedure TBoldVariantFollowerController.DoMakeUptodateAndSubscribe( + Follower: TBoldFollower; Subscribe: Boolean); +var + renderer: TBoldCustomAsVariantRenderer; + Subscriber: TBoldSubscriber; +begin + If Subscribe then + Subscriber := Follower.Subscriber + else + Subscriber := nil; + Renderer := EffectiveRenderer as TBoldCustomAsVariantRenderer; + if Assigned(Renderer.OnGetAsVariant) or Assigned(Renderer.OnSubscribe) or Assigned(Renderer.OnMayModify) then + Renderer.MakeUptodateAndSubscribe(Follower, Subscriber) + else + renderer.DefaultMakeUptodateAndSetMayModifyAndSubscribe(Follower, Subscriber); +end; + +procedure TBoldVariantFollowerController.DoMultiMakeUptodateAndSubscribe( + Followers: TBoldFollowerArray); +begin + Assert(SupportsMulti); +end; + +function TBoldVariantFollowerController.GetAsString( + aFollower: TBoldFollower): String; +begin + result := EffectiveAsVariantRenderer.GetAsString(aFollower); +end; + +function TBoldVariantFollowerController.GetAsVariant( + aFollower: TBoldFollower): Variant; +begin + result := EffectiveAsVariantRenderer.GetAsVariantAndSubscribe(aFollower, aFollower.Subscriber); +end; + +function TBoldVariantFollowerController.GetCurrentAsVariant( + Follower: TBoldFollower): Variant; +begin + Result := (Follower.RendererData as TBoldVariantRendererData).CurrentVariantValue; +end; + +function TBoldVariantFollowerController.GetRenderer: TBoldCustomAsVariantRenderer; +begin + Result := UntypedRenderer as TBoldCustomAsVariantRenderer; +end; + +function TBoldVariantFollowerController.GetEffectiveAsVariantRenderer: TBoldCustomAsVariantRenderer; +begin + Result := Renderer; + if not Assigned(Result) then + Result := TBoldCustomAsVariantRenderer.DefaultRenderer; +end; + +function TBoldVariantFollowerController.GetEffectiveRenderer: TBoldRenderer; +begin + Result := EffectiveAsVariantRenderer; +end; + +function TBoldVariantFollowerController.GetSupportsMultiEnsure: Boolean; +begin + Result := (EffectiveRenderer = DefaultAsVariantRenderer) and (pos('+', expression) = 0); +end; + +procedure TBoldVariantFollowerController.MakeClean( + Follower: TBoldFollower); +var + el: TBoldDomainElement; + FailureReason: TBoldFailureReason; + lValue: Variant; +begin + lValue := GetCurrentAsVariant(Follower); + if EffectiveAsVariantRenderer.IsChanged(Follower, lValue) then + begin + if ValidateVariant(lValue, Follower) then + begin + ReleaseChangedValue(Follower); // note, must do first, since set can change element + SetAsVariant(lValue, Follower); + end + else + begin + if follower.Element is TBoldDomainElement then + el := follower.Element as TBoldDomainElement + else + el := nil; + FailureReason := GetBoldLastFailureReason; + if assigned(FailureReason) then + GetBoldLastFailureReason.MessageFormatStr := sVariantValidationFailedExtended; + BoldRaiseLastFailure(el, '', sUnknownReason); + end; + end + else + ReleaseChangedValue(Follower); +end; + +function TBoldVariantFollowerController.MayHaveChanged( + const NewValue: Variant; Follower: TBoldFollower): boolean; +var + lBoldVariantRendererData: TBoldVariantRendererData; +begin + if Follower.State in bfsDisplayable then + begin + lBoldVariantRendererData := Follower.RendererData as TBoldVariantRendererData; + lBoldVariantRendererData.CurrentVariantValue := NewValue; + result := EffectiveAsVariantRenderer.IsChanged(Follower, NewValue); + if result then + begin + Follower.ControlledValueChanged; + end; + end + else + result := false; +end; + +procedure TBoldVariantFollowerController.SetAsVariant(const Value: Variant; + Follower: TBoldFollower); +begin + EffectiveAsVariantRenderer.SetAsVariant(Follower, Value); +end; + +procedure TBoldVariantFollowerController.SetColor( + var EffectiveColor: TColor; Color: TColor; Follower: TBoldFollower); +begin + EffectiveAsVariantRenderer.SetColor(Follower, EffectiveColor, Color); +end; + +procedure TBoldVariantFollowerController.SetFont(EffectiveFont, + Font: TFont; Follower: TBoldFollower); +begin + EffectiveAsVariantRenderer.SetFont(Follower, EffectiveFont, Font); +end; + +function TBoldVariantFollowerController.IsNilRepresentationStored: boolean; +begin + result := not VarIsNull(FNilRepresentation); +end; + +procedure TBoldVariantFollowerController.SetNilRepresentation( + const Value: Variant); +begin + if (FNilRepresentation <> Value) then + begin + FNilRepresentation := Value; + Changed; + end; +end; + +procedure TBoldVariantFollowerController.SetRenderer( + Value: TBoldCustomAsVariantRenderer); +begin + Assert(not Assigned(Value) or (Value is TBoldCustomAsVariantRenderer), Value.Classname + ' is not a ' + TBoldCustomAsVariantRenderer.ClassName); + UntypedRenderer := Value; +end; + +function TBoldVariantFollowerController.ValidateVariant( + const Value: Variant; Follower: TBoldFollower): Boolean; +begin + Result := EffectiveAsVariantRenderer.ValidateVariant(Follower, Value); +end; + +function TBoldVariantFollowerController.ValidateCharacter(C: Char; aFollower: TBoldFollower): Boolean; +begin + Result := EffectiveAsVariantRenderer.ValidateCharacter(aFollower, c); +end; + +{ TBoldCustomAsVariantRenderer } + +procedure TBoldCustomAsVariantRenderer.Assign(Source: TPersistent); +begin + inherited; + With Source as TBoldCustomAsVariantRenderer do + begin + self.OnGetAsVariant := OnGetAsVariant; + self.OnSetAsVariant := OnSetAsVariant; + self.OnValidateVariant := OnValidateVariant; + self.OnSetFont := OnSetFont; + self.OnSetColor := OnSetColor; + self.OnIsChanged := OnIsChanged; + self.OnValidateCharacter := OnValidateCharacter; + end; +end; + +procedure TBoldCustomAsVariantRenderer.AssignTo(Dest: TPersistent); +begin + if Dest is TBoldCustomAsVariantRenderer then + with Dest as TBoldCustomAsVariantRenderer do + begin + OnGetAsVariant := self.OnGetAsVariant; + OnSetAsVariant := self.OnSetAsVariant; + OnValidateVariant := self.OnValidateVariant; + OnSetFont := self.OnSetFont; + OnSetColor := self.OnSetColor; + OnIsChanged := self.OnIsChanged; + OnValidateCharacter := self.OnValidateCharacter; + end + else + inherited; +end; + +function TBoldCustomAsVariantRenderer.DefaultDisplayString: string; +begin + if Name <> '' then + Result := '(' + Name + ')' + else + Result := '(' + ClassName + ')'; +end; + +function TBoldCustomAsVariantRenderer.DefaultGetAsVariantAndSubscribe( + aFollower: TBoldFollower; Subscriber: TBoldSubscriber + ): Variant; +var + lFollowerController: TBoldVariantFollowerController; + lResultElement: TBoldElement; +begin + Result := ''; + if (csDesigning in ComponentState) and (Self <> DefaultRenderer) then + begin + Result := DefaultDisplayString; + end + else + begin + lFollowerController := aFollower.AssertedController as TBoldVariantFollowerController; + lResultElement := aFollower.Value; + if Assigned(lResultElement) then + begin + if (lResultElement is TBoldObjectReference) and not assigned((lResultElement as TBoldObjectReference).BoldObject) then + begin + result := lFollowerController.NilRepresentation; + if Assigned(Subscriber) then + lResultElement.SubscribeToStringRepresentation(lFollowerController.Representation, Subscriber, breReEvaluate); + end + else if Assigned(lResultElement) then + begin + Result := lResultElement.AsVariant; + if Assigned(Subscriber) then + lResultElement.SubscribeToStringRepresentation(lFollowerController.Representation, Subscriber, breReEvaluate); + if VarIsNull(Result) then + Result := lFollowerController.NilRepresentation; + end + else + Result := lFollowerController.NilRepresentation; + end + else + Result := lFollowerController.NilRepresentation; + end; +end; + +function TBoldCustomAsVariantRenderer.DefaultIsChanged(aFollower: TBoldFollower; + const NewValue: Variant): Boolean; +var + lOldValue: variant; +begin + lOldValue := TBoldVariantRendererData(aFollower.RendererData).OldVariantValue; + Result := not (((VarIsNumeric(NewValue) and VarIsNumeric(lOldValue)) or (VarType(NewValue) = VarType(lOldValue))) and + (NewValue = lOldValue)); +end; + +procedure TBoldCustomAsVariantRenderer.DefaultMakeUptodateAndSetMayModifyAndSubscribe( + aFollower: TBoldFollower; Subscriber: TBoldSubscriber); +var + lValue: Variant; + lFollowerController: TBoldVariantFollowerController; + lRendererData: TBoldVariantRendererData; + lRepresentation: integer; + lResultElement: TBoldElement; +begin + lRendererData:= aFollower.RendererData as TBoldVariantRendererData; + if (csDesigning in ComponentState) and (Self <> DefaultRenderer) then + begin + lValue := DefaultDisplayString; + end + else + begin + lFollowerController := aFollower.AssertedController as TBoldVariantFollowerController; + lRepresentation := lFollowerController.Representation; + lResultElement := aFollower.Value; + if (lResultElement is TBoldObjectReference) and not assigned((lResultElement as TBoldObjectReference).BoldObject) then + begin + lValue := lFollowerController.NilRepresentation; + if Assigned(Subscriber) then + lResultElement.SubscribeToStringRepresentation(lRepresentation, Subscriber, breReEvaluate); + lRendererData.MaxStringLength := -1; + end + else if Assigned(lResultElement) then + begin + lValue := lResultElement.AsVariant; + if VarIsNull(lValue) then + lValue := lFollowerController.NilRepresentation; + if Assigned(Subscriber) then + lResultElement.SubscribeToStringRepresentation(lRepresentation, Subscriber, breReEvaluate); + if (lResultElement is TBoldAttribute) and assigned((lResultElement as TBoldAttribute).BoldAttributeRTInfo) then + lRendererData.MaxStringLength := (lResultElement as TBoldAttribute).BoldAttributeRTInfo.Length + else + lRendererData.MaxStringLength := -1; + end + else + lValue := lFollowerController.NilRepresentation + end; + lRendererData.OldVariantValue := lValue; + lRendererData.CurrentVariantValue := lValue; +end; + +class function TBoldCustomAsVariantRenderer.DefaultRenderer: TBoldCustomAsVariantRenderer; +begin + Result := DefaultAsVariantRenderer; +end; + +procedure TBoldCustomAsVariantRenderer.DefaultSetAsVariant( + aFollower: TBoldFollower; const Value: Variant); +var + ValueElement: TBoldElement; +begin + ValueElement := aFollower.Value; + if Assigned(ValueElement) then + ValueElement.AsVariant := Value + else + raise EBold.CreateFmt(sCannotSetVariantValue, [ClassName]); +end; + +function TBoldCustomAsVariantRenderer.DefaultValidateVariant( + aFollower: TBoldFollower; const Value: Variant): Boolean; +var + ValueElement: TBoldElement; +begin + ValueElement := aFollower.Value; + if Assigned(ValueElement) then + result := ValueElement.ValidateVariant(Value, TBoldFollowerControllerAccess(aFollower.Controller).Representation) + else + Result := true; +end; + +procedure TBoldCustomAsVariantRenderer.DrawOnCanvas(Follower: TBoldFollower; + Canvas: TCanvas; Rect: TRect; Alignment: TAlignment; Margins: TPoint); +begin + if (not Follower.Displayable) and (Follower.State <> bfsInactiveInvalidElement) then + Follower.EnsureDisplayable; + DrawValueOnCanvas(Canvas, Rect, Alignment, Margins, TBoldVariantRendererData(Follower.RendererData).CurrentVariantValue); +end; + +class procedure TBoldCustomAsVariantRenderer.DrawValueOnCanvas(Canvas: TCanvas; + Rect: TRect; Alignment: TAlignment; Margins: TPoint; const aValue: Variant); +var + Left: Integer; + s: string; +begin + s := aValue; + // Adjust for alignment + case Alignment of + taLeftJustify: Left := Margins.X + Rect.Left; + taRightJustify: Left := (Rect.Right - Rect.Left) - Canvas.TextWidth(S) + Rect.Left - 1 - Margins.X; + else + Left := Rect.Left + ((Rect.Right - Rect.Left) - Canvas.TextWidth(S)) div 2; + end; + Canvas.TextRect(Rect, Left, Rect.Top + Margins.Y, S); +end; + +function TBoldCustomAsVariantRenderer.EffectiveRenderer: TBoldCustomAsVariantRenderer; +begin + result := self; +end; + +function TBoldCustomAsVariantRenderer.GetAsVariantAndSubscribe( + aFollower: TBoldFollower; Subscriber: TBoldSubscriber + ): Variant; +begin + if Assigned(OnSubscribe) and Assigned(Subscriber) then + begin + if Assigned(aFollower.Element) then + OnSubscribe(aFollower, Subscriber); + Subscriber := nil; + end; + if Assigned(OnGetAsVariant) then + Result := OnGetAsVariant(aFollower) + else + Result := DefaultGetAsVariantAndSubscribe(aFollower, Subscriber); +end; + +function TBoldCustomAsVariantRenderer.DefaultGetAsString( + AFollower: TBoldFollower): string; +begin + // what about Subscriber should it be a param ? + try + result := VarToStr(GetAsVariantAndSubscribe(AFollower, nil)); + except + on EVariantError do + Result := ''; + end; +end; + +function TBoldCustomAsVariantRenderer.GetAsString( + aFollower: TBoldFollower): string; +begin + if Assigned(FOnGetAsString) then + result := FOnGetAsString(AFollower) + else + result := DefaultGetAsString(AFollower); +end; + +function TBoldCustomAsVariantRenderer.GetRendererDataClass: TBoldRendererDataClass; +begin + Result := TBoldVariantRendererData; +end; + +function TBoldCustomAsVariantRenderer.GetSupportsMulti: Boolean; +begin + Result := False; +end; + +function TBoldCustomAsVariantRenderer.HasSetValueEventOverrides: boolean; +begin + result := Assigned(FOnSetAsVariant); +end; + +function TBoldCustomAsVariantRenderer.IsChanged(aFollower: TBoldFollower; + const NewValue: Variant): Boolean; +begin + if Assigned(fOnIsChanged) then + Result := fOnIsChanged(aFollower, NewValue) + else + Result := DefaultIsChanged(aFollower, NewValue); +end; + + +procedure TBoldCustomAsVariantRenderer.MakeUpToDateAndSubscribe +(aFollower: TBoldFollower; Subscriber: TBoldSubscriber); +var + lValue: Variant; + lRendererData: TBoldVariantRendererData; +begin + lValue := GetAsVariantAndSubscribe(aFollower, Subscriber); + lRendererData := (aFollower.RendererData as TBoldVariantRendererData); + lRendererData.OldVariantValue := lValue; + lRendererData.CurrentVariantValue := lValue; +end; + +{procedure TBoldCustomAsVariantRenderer.MultiMakeUpToDateAndSubscribe( + Elements: TBoldClientableList; Subscribers, + RendererData: TBoldObjectArray; + FollowerController: TBoldFollowerController); +begin +// do nothing +end;} + +procedure TBoldCustomAsVariantRenderer.SetAsVariant(aFollower: TBoldFollower; + const Value: Variant); +begin + if Assigned(FOnSetAsVariant) then + OnSetAsVariant(aFollower, Value) + else + DefaultSetAsVariant(aFollower, Value) +end; + +procedure TBoldCustomAsVariantRenderer.SetColor(aFollower: TBoldFollower; + var EffectiveColor: TColor; Color: TColor); +begin + EffectiveColor := Color; + if Assigned(fOnSetColor) then + fOnSetColor(aFollower, EffectiveColor); +end; + +procedure TBoldCustomAsVariantRenderer.SetFont(aFollower: TBoldFollower; + EffectiveFont, Font: TFont); +begin + EffectiveFont.Assign(Font); + if Assigned(fOnSetFont) then + fOnSetFont(aFollower, EffectiveFont); +end; + +function TBoldCustomAsVariantRenderer.ValidateVariant(aFollower: TBoldFollower; + const Value: Variant): Boolean; +begin + if Assigned(FOnValidateVariant) then + Result := OnValidateVariant(aFollower, Value) + else + Result := DefaultValidateVariant(aFollower, Value); +end; + +{ TBoldVariantRendererData } + +constructor TBoldVariantRendererData.Create(OwningFollower: TBoldFollower); +begin + inherited; + fMaxStringLength := -1; + OldVariantValue := Null; + CurrentVariantValue := Null; +end; + +initialization + DefaultAsVariantRenderer := TBoldAsVariantRenderer.Create(nil); + +finalization + FreeAndNil(DefaultAsVariantRenderer); + +end. + + diff --git a/Source/BoldAwareGUI/ControlPacks/BoldViewerControlPack.pas b/Source/BoldAwareGUI/ControlPacks/BoldViewerControlPack.pas index f3d2226..cc92180 100644 --- a/Source/BoldAwareGUI/ControlPacks/BoldViewerControlPack.pas +++ b/Source/BoldAwareGUI/ControlPacks/BoldViewerControlPack.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldViewerControlPack; {$UNDEF BOLDCOMCLIENT} @@ -32,10 +35,10 @@ TBoldAbstractViewAdapter = class; TBoldGetAsViewer = procedure (Element: TBoldElement; Representation: TBoldRepresentation; Expression: TBoldExpression; var AbstractViewAdapter: TBoldAbstractViewAdapter) of object; {$ENDIF} {$IFDEF BOLD_DELPHI} - TBoldGetAsViewer = function (Element: TBoldElement; Representation: TBoldRepresentation; Expression: TBoldExpression): TBoldAbstractViewAdapter of object; + TBoldGetAsViewer = function (aFollower: TBoldFollower): TBoldAbstractViewAdapter of object; {$ENDIF} - TBoldSetAsViewer = procedure (Element: TBoldElement; Value: TBoldAbstractViewAdapter; Representation: TBoldRepresentation; Expression: TBoldExpression) of object; - TBoldViewerIsChanged = function (RendererData: TBoldViewerRendererData; NewValue: TBoldAbstractViewAdapter; Representation: TBoldRepresentation; Expression: TBoldExpression): Boolean of object; + TBoldSetAsViewer = procedure (aFollower: TBoldFollower; Value: TBoldAbstractViewAdapter) of object; + TBoldViewerIsChanged = function (aFollower: TBoldFollower; NewValue: TBoldAbstractViewAdapter): Boolean of object; { TBoldViewerRendererData } TBoldViewerRendererData = class(TBoldRendererData) @@ -57,15 +60,16 @@ TBoldAsViewerRenderer = class(TBoldSingleRenderer) fOnIsChanged: TBoldViewerIsChanged; protected function GetRendererDataClass: TBoldRendererDataClass; override; - function GetAsViewerAndSubscribe(Element: TBoldElement; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList; Subscriber: TBoldSubscriber): TBoldAbstractViewAdapter; virtual; - procedure SetAsViewer(Element: TBoldElement; Value: TBoldAbstractViewAdapter; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList); virtual; + function GetAsViewerAndSubscribe(aFollower: TBoldFollower; Subscriber: TBoldSubscriber): TBoldAbstractViewAdapter; virtual; + procedure SetAsViewer(aFollower: TBoldFollower; Value: TBoldAbstractViewAdapter); virtual; + function HasSetValueEventOverrides: boolean; override; public class function DefaultRenderer: TBoldAsViewerRenderer; - function DefaultGetAsViewerAndSubscribe(Element: TBoldElement; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList; Subscriber: TBoldSubscriber): TBoldAbstractViewAdapter; virtual; - procedure DefaultSetAsViewer(Element: TBoldElement; Value: TBoldAbstractViewAdapter; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList); virtual; - function DefaultIsChanged(RendererData: TBoldViewerRendererData; NewValue: TBoldAbstractViewAdapter; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList): Boolean; - function IsChanged(RendererData: TBoldViewerRendererData; NewValue: TBoldAbstractViewAdapter; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList): Boolean; - procedure MakeUptodateAndSubscribe(Element: TBoldElement; RendererData: TBoldRendererData; FollowerController: TBoldFollowerController; Subscriber: TBoldSubscriber); override; + function DefaultGetAsViewerAndSubscribe(aFollower: TBoldFollower; Subscriber: TBoldSubscriber): TBoldAbstractViewAdapter; virtual; + procedure DefaultSetAsViewer(aFollower: TBoldFollower; Value: TBoldAbstractViewAdapter); virtual; + function DefaultIsChanged(aFollower: TBoldFollower; NewValue: TBoldAbstractViewAdapter): Boolean; + function IsChanged(aFollower: TBoldFollower; NewValue: TBoldAbstractViewAdapter): Boolean; + procedure MakeUptodateAndSubscribe(aFollower: TBoldFollower; Subscriber: TBoldSubscriber); override; published property OnGetAsViewer: TBoldGetAsViewer read FOnGetAsViewer write FOnGetAsViewer; property OnSetAsViewer: TBoldSetAsViewer read FOnSetAsViewer write FOnSetAsViewer; @@ -92,8 +96,6 @@ TBoldViewerFollowerController = class(TBoldSingleFollowerController) {-- TBoldAbstractViewAdapter --} TBoldViewAdapterClass = class of TBoldAbstractViewAdapter; - - // BCB does not support abstract class methods TBoldAbstractViewAdapter = class(TBoldMemoryManagedObject) public constructor Create; virtual; @@ -104,19 +106,19 @@ TBoldAbstractViewAdapter = class(TBoldMemoryManagedObject) function Empty: Boolean; virtual; abstract; procedure Clear; virtual; abstract; function HasChanged: Boolean; virtual; abstract; - class function CanReadContent(const ContentType: string): Boolean; virtual; + class function CanReadContent(const ContentType: string): Boolean; virtual; function ContentType: string; virtual; abstract; - class function Description: string; virtual; // How to handle Localizastion? + class function Description: string; virtual; {Clipboard} procedure CopyToClipboard; virtual; abstract; - class function CanPasteFromClipboard(const AcceptedContentType: string): Boolean; virtual; + class function CanPasteFromClipboard(const AcceptedContentType: string): Boolean; virtual; procedure PasteFromClipboard; virtual; abstract; {Streams} procedure LoadFromStream(Stream: TStream); virtual; abstract; procedure SaveToStream(Stream: TStream); virtual; abstract; {Files} - class function DefaultExtension: string; virtual; - class function FileFilter: string; virtual; // How to handle Localizastion? + class function DefaultExtension: string; virtual; + class function FileFilter: string; virtual; class function CanLoadFromFile(const Filename: string): Boolean; virtual; procedure LoadFromFile(const Filename: string); virtual; abstract; procedure SaveToFile(const Filename: string); virtual; abstract; @@ -131,9 +133,9 @@ implementation uses SysUtils, - BoldGuiResourceStrings, BoldUtils, - BoldImageBitmap; //FIXME Temp! + BoldImageBitmap, + BoldGuard; var DefaultAsViewerRenderer: TBoldAsViewerRenderer; @@ -159,13 +161,13 @@ procedure TBoldViewerRendererData.SetViewAdapter(Value: TBoldAbstractViewAdapter { TBoldAsViewerRenderer } -procedure TBoldAsViewerRenderer.MakeUpToDateAndSubscribe(Element: TBoldElement; RendererData: TBoldRendererData; FollowerController: TBoldFollowerController; Subscriber: TBoldSubscriber); +procedure TBoldAsViewerRenderer.MakeUpToDateAndSubscribe(aFollower: TBoldFollower; Subscriber: TBoldSubscriber); var - Controller: TBoldViewerFollowerController; + lRendererData: TBoldViewerRendererData; begin - Controller := FollowerController as TBoldViewerFollowerController; - (RendererData as TBoldViewerRendererData).ViewAdapter := GetAsViewerAndSubscribe(Element, Controller.Representation, Controller.Expression, Controller.GetVariableListAndSubscribe(Subscriber), Subscriber); - (RendererData as TBoldViewerRendererData).HasChanged := False; + lRendererData := aFollower.RendererData as TBoldViewerRendererData; + lRendererData.ViewAdapter := GetAsViewerAndSubscribe(aFollower, Subscriber); + lRendererData.HasChanged := False; end; class function TBoldAsViewerRenderer.DefaultRenderer: TBoldAsViewerRenderer; @@ -178,15 +180,21 @@ function TBoldAsViewerRenderer.GetRendererDataClass: TBoldRendererDataClass; Result := TBoldViewerRendererData; end; -function TBoldAsViewerRenderer.DefaultGetAsViewerAndSubscribe(Element: TBoldElement; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList; Subscriber: TBoldSubscriber): TBoldAbstractViewAdapter; +function TBoldAsViewerRenderer.HasSetValueEventOverrides: boolean; +begin + result := Assigned(FOnSetAsViewer); +end; + +function TBoldAsViewerRenderer.DefaultGetAsViewerAndSubscribe(aFollower: TBoldFollower; Subscriber: TBoldSubscriber): TBoldAbstractViewAdapter; var e: TBoldElement; - Stream: TStream; - {$IFDEF BOLDCOMCLIENT} // defaultGet + {$IFDEF BOLDCOMCLIENT} attr: IBoldAttribute; {$ELSE} IndirectElement: TBoldIndirectElement; blob: TBABlob; + lResultElement: TBoldElement; + lGuard: IBoldGuard; {$ENDIF} function GetViewer: TBoldAbstractViewAdapter; @@ -204,9 +212,9 @@ function TBoldAsViewerRenderer.DefaultGetAsViewerAndSubscribe(Element: TBoldElem begin Result := nil; - if Assigned(Element) then + if Assigned(aFollower.Element) then begin - {$IFDEF BOLDCOMCLIENT} // defaultGet + {$IFDEF BOLDCOMCLIENT} if assigned(Subscriber) then e := Element.EvaluateAndSubscribeToExpression(Expression, Subscriber.ClientId, Subscriber.SubscriberId, false, false) else @@ -227,55 +235,51 @@ function TBoldAsViewerRenderer.DefaultGetAsViewerAndSubscribe(Element: TBoldElem end; end else - raise EBold.CreateFmt(sViewerNotAvailable, [attr.StringRepresentation[brShort]]) + raise EBold.CreateFmt('Viewer not available (%s)', [attr.StringRepresentation[brShort]]) end else Result := nil; {$ELSE} - IndirectElement := TBoldIndirectElement.Create; - try - Element.EvaluateAndSubscribeToExpression(Expression, Subscriber, IndirectElement, False, false, VariableList); - e := IndirectElement.Value; - if e is TBABlob then + lResultElement := aFollower.Value; + if not Assigned(lResultElement) then + begin + lGuard:= TBoldGuard.Create(IndirectElement); + IndirectElement := TBoldIndirectElement.Create; + aFollower.Element.EvaluateAndSubscribeToExpression(aFollower.AssertedController.Expression, Subscriber, IndirectElement, False, False, aFollower.Controller.GetVariableListAndSubscribe(Subscriber)); + lResultElement := IndirectElement.Value; + end; + if lResultElement is TBABlob then + begin + blob := TBABlob(lResultElement); + if not Blob.IsNull then begin - blob := TBABlob(e); - if not Blob.IsNull then + e := Blob; + Result := GetViewer; + if Assigned(Result) then begin - Result := GetViewer; - if Assigned(Result) then - begin - Stream := blob.CreateBlobStream(bmRead); - try - Result.LoadFromStream(Stream); - finally - Stream.Free; - end; - end - else - raise EBold.CreateFmt(sViewerNotAvailable, [Blob.ContentType]) + Result.LoadFromStream(blob.AsStream); end else - Result := nil; - end; - finally - IndirectElement.Free; + raise EBold.CreateFmt('Viewer not available (%s)', [Blob.ContentType]) + end + else + Result := nil; end; {$ENDIF} end; end; -procedure TBoldAsViewerRenderer.DefaultSetAsViewer(Element: TBoldElement; Value: TBoldAbstractViewAdapter; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList); +procedure TBoldAsViewerRenderer.DefaultSetAsViewer(aFollower: TBoldFollower; Value: TBoldAbstractViewAdapter); var ValueElement: TBoldElement; - Stream: TStream; - {$IFDEF BOLDCOMCLIENT} // defaultSet + {$IFDEF BOLDCOMCLIENT} Attr: IBoldAttribute; {$ENDIF} begin - ValueElement := GetExpressionAsDirectElement(Element, Expression, VariableList); + ValueElement := aFollower.Value; if Assigned(ValueElement) then begin - {$IFDEF BOLDCOMCLIENT} // DefaultSet + {$IFDEF BOLDCOMCLIENT} ValueElement.QueryInterface(IBoldAttribute, Attr); if Assigned(Value) then begin @@ -293,28 +297,23 @@ procedure TBoldAsViewerRenderer.DefaultSetAsViewer(Element: TBoldElement; Value: {$ELSE} if Assigned(Value) then begin - Stream := (ValueElement as TBABlob).CreateBlobStream(bmWrite); - try - Value.SaveToStream(Stream); - (ValueElement as TBABlob).ContentType := Value.ContentType; - finally - Stream.Free; - end; + Value.SaveToStream((ValueElement as TBABlob).AsStream); + (ValueElement as TBABlob).ContentType := Value.ContentType; end else (ValueElement as TBABlob).SetToNull; {$ENDIF} end else - raise EBold.CreateFmt(sCannotSetValue, [ClassName]); + raise EBold.CreateFmt('%s.DefaultSetAsViewer: Can''t set value', [ClassName]); end; -function TBoldAsViewerRenderer.GetAsViewerAndSubscribe(Element: TBoldElement; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList; Subscriber: TBoldSubscriber): TBoldAbstractViewAdapter; +function TBoldAsViewerRenderer.GetAsViewerAndSubscribe(aFollower: TBoldFollower; Subscriber: TBoldSubscriber): TBoldAbstractViewAdapter; begin if Assigned(OnSubscribe) and Assigned(Subscriber) then begin - if Assigned(Element) then - OnSubscribe(Element, Representation, Expression, Subscriber); + if Assigned(aFollower.Element) then + OnSubscribe(aFollower, Subscriber); Subscriber := nil; end; if Assigned(OnGetAsViewer) then @@ -324,32 +323,32 @@ function TBoldAsViewerRenderer.GetAsViewerAndSubscribe(Element: TBoldElement; Re OnGetAsViewer(Element, Representation, Expression, Result); {$ENDIF} {$IFDEF BOLD_DELPHI} - Result := OnGetAsViewer(Element, Representation, Expression); + Result := OnGetAsViewer(aFollower); {$ENDIF} end else - Result := DefaultGetAsViewerAndSubscribe(Element, Representation, Expression, VariableList, Subscriber); + Result := DefaultGetAsViewerAndSubscribe(aFollower, Subscriber); end; -procedure TBoldAsViewerRenderer.SetAsViewer(Element: TBoldElement; Value: TBoldAbstractViewAdapter; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList); +procedure TBoldAsViewerRenderer.SetAsViewer(aFollower: TBoldFollower; Value: TBoldAbstractViewAdapter); begin if Assigned(FOnSetAsViewer) then - OnSetAsViewer(Element, Value, Representation, Expression) + OnSetAsViewer(aFollower, Value) else - DefaultSetAsViewer(Element, Value, Representation, Expression, VariableList); + DefaultSetAsViewer(aFollower, Value); end; -function TBoldAsViewerRenderer.DefaultIsChanged(RendererData: TBoldViewerRendererData; NewValue: TBoldAbstractViewAdapter; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList): Boolean; +function TBoldAsViewerRenderer.DefaultIsChanged(aFollower: TBoldFollower; NewValue: TBoldAbstractViewAdapter): Boolean; begin - Result := (RendererData.HasChanged) or (Assigned(NewValue) and NewValue.HasChanged); + Result := (TBoldViewerRendererData(aFollower.RendererData).HasChanged) or (Assigned(NewValue) and NewValue.HasChanged); end; -function TBoldAsViewerRenderer.IsChanged(RendererData: TBoldViewerRendererData; NewValue: TBoldAbstractViewAdapter; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList): Boolean; +function TBoldAsViewerRenderer.IsChanged(aFollower: TBoldFollower; NewValue: TBoldAbstractViewAdapter): Boolean; begin if Assigned(fOnIsChanged) then - Result := fOnIsChanged(RendererData, NewValue, Representation, Expression) + Result := fOnIsChanged(aFollower, NewValue) else - Result := DefaultIsChanged(RendererData, NewValue, Representation, Expression, VariableList); + Result := DefaultIsChanged(aFollower, NewValue); end; { TBoldViewerFollowerController } @@ -384,15 +383,23 @@ function TBoldViewerFollowerController.GetCurrentViewer(Follower: TBoldFollower) procedure TBoldViewerFollowerController.SetAsViewer(Value: TBoldAbstractViewAdapter; Follower: TBoldFollower); begin - EffectiveAsViewerRenderer.SetAsViewer(Follower.Element, Value, Representation, Expression, VariableList); + EffectiveAsViewerRenderer.SetAsViewer(Follower, Value); end; procedure TBoldViewerFollowerController.MayHaveChanged(NewValue: TBoldAbstractViewAdapter; Follower: TBoldFollower); +var + lIsChanged: boolean; + lRendererData: TBoldViewerRendererData; begin if Follower.State in bfsDisplayable then begin - (Follower.RendererData as TBoldViewerRendererData).ViewAdapter := NewValue; - Follower.ControlledValueChanged(EffectiveAsViewerRenderer.IsChanged(Follower.RendererData as TBoldViewerRendererData, NewValue, Representation, Expression, VariableList)); + lRendererData := Follower.RendererData as TBoldViewerRendererData; + lRendererData.ViewAdapter := NewValue; + lIsChanged := EffectiveAsViewerRenderer.IsChanged(Follower, NewValue); + if lIsChanged then + begin + Follower.ControlledValueChanged; + end; end; end; @@ -406,7 +413,6 @@ procedure TBoldViewerFollowerController.MakeClean(Follower: TBoldFollower); constructor TBoldAbstractViewAdapter.Create; begin - // Left for subclasses to implement end; class procedure TBoldAbstractViewAdapter.RegisterViewAdapter(ViewAdapterClass: TBoldViewAdapterClass); @@ -467,6 +473,5 @@ initialization finalization FreeAndNil(DefaultAsViewerRenderer); FreeAndNil(ViewAdapterList); - + end. - diff --git a/Source/BoldAwareGUI/Core/BoldExceptionHandlers.pas b/Source/BoldAwareGUI/Core/BoldExceptionHandlers.pas index b3f0d50..816c97e 100644 --- a/Source/BoldAwareGUI/Core/BoldExceptionHandlers.pas +++ b/Source/BoldAwareGUI/Core/BoldExceptionHandlers.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldExceptionHandlers; interface @@ -12,7 +15,7 @@ interface TBoldExceptionHandler = class; { prototypes } - TBoldApplyExceptionEvent = procedure (E: Exception; Component: TComponent; Elem: TBoldElement; var Discard: Boolean) of object; + TBoldApplyExceptionEvent = procedure (E: Exception; Component: TComponent; Elem: TBoldElement; var Discard: Boolean; var HandledByUser: boolean) of object; TBoldDisplayExceptionEvent = procedure (E: Exception; Component: TComponent; Elem: TBoldElement) of object; { TBoldExceptionHandler } @@ -20,6 +23,8 @@ TBoldExceptionHandler = class(TComponent) private fOnApplyException: TBoldApplyExceptionEvent; fOnDisplayException: TBoldDisplayExceptionEvent; + fGlobal: boolean; + procedure SetGlobal(const Value: boolean); public constructor Create(AOwner: TComponent); override; destructor Destroy; override; @@ -29,14 +34,13 @@ TBoldExceptionHandler = class(TComponent) published property OnApplyException: TBoldApplyExceptionEvent read fOnApplyException write fOnApplyException; property OnDisplayException: TBoldDisplayExceptionEvent read fOnDisplayException write fOnDisplayException; - end; + property Global: boolean read fGlobal write SetGlobal default false; + end; implementation - uses - Controls, - BoldUtils; + BoldRev; var G_BoldExceptionHandlers: TList = nil; @@ -64,56 +68,35 @@ destructor TBoldExceptionHandler.Destroy; end; class function TBoldExceptionHandler.FindExceptionHandler(Component: TComponent): TBoldExceptionHandler; -function OwningComponent(Component: TComponent): TComponent; -begin -//Find topmost owning component - Result := Component; - while Assigned(Result) and Assigned(Result.Owner) do - Result := Result.Owner; -end; - -function ParentControl(Component: TComponent): TWinControl; -begin -//Find topmost parent control - Result := nil; - if Component is TWinControl then - begin - Result := TWinControl(Component); - while Assigned(Result.Parent) do - Result := Result.Parent; - end; -end; - var i: integer; - ExceptionHandlerOwner: TComponent; begin - //Find matching exception handler - result := nil; - if assigned(G_BoldExceptionHandlers) then + if assigned(G_BoldExceptionHandlers) and (G_BoldExceptionHandlers.Count > 0) then + begin for i := 0 to G_BoldExceptionHandlers.Count - 1 do begin - ExceptionHandlerOwner := TBoldExceptionHandler(G_BoldExceptionHandlers[i]).Owner; - if (ExceptionHandlerOwner = OwningComponent(Component)) or - (ExceptionHandlerOwner = ParentControl(Component)) then - begin - result := TBoldExceptionHandler(G_BoldExceptionHandlers[i]); + result := TBoldExceptionHandler(G_BoldExceptionHandlers[i]); + if (result.Owner = Component.Owner) then exit; - end; end; + for i := 0 to G_BoldExceptionHandlers.Count - 1 do + begin + result := TBoldExceptionHandler(G_BoldExceptionHandlers[i]); + if Result.Global then + exit; + end; + end; + result := nil; end; procedure TBoldExceptionHandler.HandleApplyException(E: Exception; Component: TComponent; Elem: TBoldElement; var Discard: Boolean; var HandledByUser: boolean); begin - // Note: Discard must be set by caller, as there might be no matching exception handler - // to set discard! - HandledByUser := Assigned(fOnApplyException); - if HandledByUser then - OnApplyException(E, Component, Elem, Discard); + if Assigned(fOnApplyException) then + OnApplyException(E, Component, Elem, Discard, HandledByUser); end; -procedure TBoldExceptionHandler.HandleDisplayException(E: Exception; +procedure TBoldExceptionHandler.HandleDisplayException(E: Exception; Component: TComponent; Elem: TBoldElement; var HandledByUser: boolean); begin HandledByUser := Assigned(fOnDisplayException); @@ -121,6 +104,19 @@ procedure TBoldExceptionHandler.HandleDisplayException(E: Exception; OnDisplayException(E, Component, Elem); end; +procedure TBoldExceptionHandler.SetGlobal(const Value: boolean); +var + i: integer; +begin + if Value = Global then + exit; + if value and assigned(G_BoldExceptionHandlers) then + for i := 0 to G_BoldExceptionHandlers.Count - 1 do + if TBoldExceptionHandler(G_BoldExceptionHandlers[i]).Global then + exit; + fGlobal := Value; +end; + initialization finalization diff --git a/Source/BoldAwareGUI/Core/BoldGUI.pas b/Source/BoldAwareGUI/Core/BoldGUI.pas index 5711b7b..2e36b95 100644 --- a/Source/BoldAwareGUI/Core/BoldGUI.pas +++ b/Source/BoldAwareGUI/Core/BoldGUI.pas @@ -1,18 +1,22 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldGUI; interface uses + // VCL Classes, - Menus, - Forms, Controls, - BoldSystem, - BoldDefs, - BoldControlPackDefs, + Forms, + Menus, + + // Bold BoldBase, + BoldControlPackDefs, BoldElements, - BoldControlPack; + BoldSystem; type TBoldGUIHandler = class; @@ -46,7 +50,6 @@ implementation uses SysUtils, - BoldUtils, BoldSystemRT; var @@ -118,7 +121,6 @@ function TBoldGUIHandler.DraggedObjectsAssignable(element: TBoldElement; dropMod procedure TBoldGUIHandler.DoPopUp; begin - // FIXME fill in items in popup menu, etc, etc end; function TBoldGUIHandler.FindHostingForm(Component: TComponent): TForm; @@ -126,23 +128,28 @@ function TBoldGUIHandler.FindHostingForm(Component: TComponent): TForm; temp: TComponent; Control: TControl; begin - result := nil; - if Component is TControl then - begin - Control := Component as TControl; - while assigned(Control) and not (Control is TForm) do - Control := Control.Parent; - if Control is TForm then - result := Control as TForm; - end; - - if not assigned(result) then + if Component is TForm then + result := Component as TForm + else begin - temp := Component; - while assigned(temp) and not (temp is TForm) do - temp := temp.Owner; - if temp is TForm then - result := temp as TForm; + result := nil; + if Component is TControl then + begin + Control := Component as TControl; + while assigned(Control) and not (Control is TForm) do + Control := Control.Parent; + if Control is TForm then + result := Control as TForm; + end; + + if not assigned(result) then + begin + temp := Component; + while assigned(temp) and not (temp is TForm) do + temp := temp.Owner; + if temp is TForm then + result := temp as TForm; + end; end; end; @@ -160,6 +167,7 @@ function TBoldGUIHandler.TryToFocusHostingForm(Component: TComponent): Boolean; end; initialization + BoldPopupMenu := TPopupMenu.Create(nil); BoldPopupMenu.OnPopup := BoldGUIHandler.DoPopUp; diff --git a/Source/BoldAwareGUI/Core/BoldGuiResourceStrings.pas b/Source/BoldAwareGUI/Core/BoldGuiResourceStrings.pas index ee3c725..fc1c690 100644 --- a/Source/BoldAwareGUI/Core/BoldGuiResourceStrings.pas +++ b/Source/BoldAwareGUI/Core/BoldGuiResourceStrings.pas @@ -1,3 +1,13 @@ + +///////////////////////////////////////////////////////// +// // +// Bold for Delphi // +// Copyright (c) 1996-2002 Boldsoft AB // +// (c) 2002-2005 Borland Software Corp // +// // +///////////////////////////////////////////////////////// + + unit BoldGuiResourceStrings; interface diff --git a/Source/BoldAwareGUI/FormGen/BoldAFPDefault.pas b/Source/BoldAwareGUI/FormGen/BoldAFPDefault.pas index f3cab18..2d257d0 100644 --- a/Source/BoldAwareGUI/FormGen/BoldAFPDefault.pas +++ b/Source/BoldAwareGUI/FormGen/BoldAFPDefault.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldAFPDefault; interface @@ -37,6 +40,8 @@ TBoldDefaultSystemAutoFormProvider = class; TBoldDefaultAttributeListAutoFormProvider = class; TBoldDefaultObjectListAutoFormProvider = class; + TFormAFPDefault = class(TForm); + {---TBoldDefaultFormProvider---} TBoldDefaultFormProvider = class(TBoldUserFormProvider) private @@ -201,11 +206,10 @@ TRoleMenu = class(TPopupMenu) implementation -{$R BoldAFPDefault.res} - uses SysUtils, Dialogs, + {$IFDEF BOLD_DELPHI16_OR_LATER}UITypes,{$ENDIF} BoldGuiResourceStrings, BoldUtils, BoldBase, @@ -222,7 +226,11 @@ implementation BoldEdit, BoldStringControlPack, BoldCondition, - BoldId; + BoldId, + BoldIndex, + BoldIndexableList, + BoldMetaElementList, + BoldDomainElement; const BOXMARGIN = 8; @@ -366,11 +374,18 @@ procedure TMethodButton.Click; {--TBoldAFEdit---} procedure TBoldAFEdit.DblClick; +var + AForm : TForm; begin if Assigned(BoldHandle) and (BoldHandle.Value is TBoldObjectReference) and assigned((BoldHandle.Value as TBoldObjectReference).BoldObject) then - AutoFormProviderRegistry.FormForElement(TBoldObjectReference(BoldHandle.Value).BoldObject).Show; + begin + AForm := AutoFormProviderRegistry.FormForElement(TBoldObjectReference(BoldHandle.Value).BoldObject); + if Assigned(AForm) then begin + AForm.Show; + end; + end; end; {---TAFPPageControl---} @@ -423,17 +438,22 @@ class procedure TBoldDefaultFormProvider.DefaultFormDragOver(Sender, Source: TOb class procedure TBoldDefaultFormProvider.DefaultFormOnClose(Sender: TObject; var Action: TCloseAction); var Form: TForm; + AFormIndex : Integer; StoredCloseEvent: TCloseEvent; begin Action := caFree; - if Sender is TForm then - begin + if Sender is TForm then begin Form := Sender as TForm; Form.ActiveControl.Perform(CM_EXIT, 0, 0); - StoredCloseEvent := G_BoldActiveAutoForms.Entries[G_BoldActiveAutoForms.IndexOfForm(Form)].OnClose; - if Assigned(StoredCloseEvent) then - StoredCloseEvent(Sender, Action); - G_BoldActiveAutoForms.RemoveByForm(Form); + + AFormIndex := G_BoldActiveAutoForms.IndexOfForm(Form); + if (AFormIndex > -1) and (AFormIndex < G_BoldActiveAutoForms.Count) then begin + StoredCloseEvent := G_BoldActiveAutoForms.Entries[AFormIndex].OnClose; + if Assigned(StoredCloseEvent) then begin + StoredCloseEvent(Sender, Action); + end; + G_BoldActiveAutoForms.RemoveByForm(Form); + end; end; end; @@ -458,7 +478,7 @@ procedure TBoldDefaultFormProvider.PostGenerateAutoForm; function TBoldDefaultFormProvider.GetFormClass: TFormClass; begin - Result := TForm; + Result := TFormAFPDefault; end; procedure TBoldDefaultFormProvider.PreGenerateAutoForm; @@ -489,11 +509,19 @@ procedure TBoldDefaultFormProvider.PostEnsureForm; begin Form.Position := poDefaultPosOnly; Form.BoundsRect := Rect(0, 0, 440, 360); + Form.Constraints.MinHeight := MINFORMHEIGHT; end; procedure TBoldDefaultFormProvider.EnsureForm; begin - inherited; +// inherited; + // No inherited, because form needs to be created with CreateNew. + // In this way, no resources are needed (because its not inherited from TForm anymore) + if Assigned(FormClass) then + Form := FormClass.CreateNew(Application) + else + Form := nil; + if Assigned(Form) then begin G_BoldActiveAutoForms.AddPair(Form, Element); @@ -922,6 +950,9 @@ function TBoldDefaultObjectAutoFormProvider.GetGoodStringRepresentationForSingle end; end; +type + TWinControlAccess = class(TWinControl); + procedure TBoldDefaultObjectAutoFormProvider.EnsureSingleMemberControls; var TabSheet: TTabSheet; @@ -945,6 +976,8 @@ procedure TBoldDefaultObjectAutoFormProvider.EnsureSingleMemberControls; TabSheet := CreateTabSheet(ClassTypeInfo.ModelName, MakeComponentName('Tab', ClassTypeInfo, nil)); // do not localize ScrollBox := CreateScrollBox(TabSheet); + ScrollBox.Align := alNone; + ScrollBox.SetBounds(0, 0, ScrollBox.Parent.Width, 10000{ScrollBox.Parent.Height}); MaxLabelWidth := GetLargestWidth; Box1NextLeft := CONTROLMARGIN; @@ -966,12 +999,12 @@ procedure TBoldDefaultObjectAutoFormProvider.EnsureSingleMemberControls; (Orientation = orHorizontal) then begin Inc(Box1NextTop, 24); - Box1NextLeft := 10; + Box1NextLeft := CONTROLMARGIN; end; Left := Box1NextLeft; Top := Box1NextTop + 4; Parent := ScrollBox; - Inc(Box1NextLeft, Width + 10); + Inc(Box1NextLeft, Width + CONTROLMARGIN); end; if Member.BoldType.ConformsTo((Member.BoldType.SystemTypeInfo as TBoldSystemTypeInfo).AttributeTypeInfoByExpressionName['ValueSet']) then // do not localize @@ -1016,7 +1049,7 @@ procedure TBoldDefaultObjectAutoFormProvider.EnsureSingleMemberControls; ExpressionHandle.RootHandle := Self.BoldHandle; ExpressionHandle.Expression := Member.ExpressionName; ExpressionHandle.Name := MakeComponentName('Handle', ClassTypeInfo, Member); // do not localize - BoldEdit.Color := clInactiveCaptionText; + BoldEdit.Color := clBtnShadow; BoldEdit.ReadOnly := true; BoldEdit.BoldHandle := ExpressionHandle; BoldEdit.BoldProperties.DragMode := bdgSelection; @@ -1057,6 +1090,11 @@ procedure TBoldDefaultObjectAutoFormProvider.EnsureSingleMemberControls; else Form.Height := Box1NextTop + 100 + PANELHEIGHT; + Form.Constraints.MinWidth := MaxLabelWidth + CONTROLMARGIN * 2 + 100; + + TWinControlAccess(Form).AdjustSize; + ScrollBox.Align := alClient; + // Move all handles and stuff to the bottom of the window. Box1NextLeft := CONTROLMARGIN; for i := 0 to Form.ComponentCount - 1 do @@ -1129,7 +1167,7 @@ class procedure TBoldDefaultObjectAutoFormProvider.BoldAsStringRenderer1SetColor Element.EvaluateExpression(Expression, Result); if (Result.Value is TBoldMember) and not (Result.Value as TBoldMember).CanModify then - AColor := clInactiveCaptionText; + AColor := clBtnShadow; finally Result.Free; end; @@ -1201,12 +1239,17 @@ procedure TRoleButton.MouseDown(Button: TMouseButton; Shift: TShiftState; procedure TRoleButton.NavigateToSingleRole(Sender: TObject); var anObject: TBoldObject; + AForm : TForm; begin if Assigned(BoldHandle) and (BoldHandle.Value is TBoldObjectReference) then begin anObject := (BoldHandle.Value as TBoldObjectReference).BoldObject; - if Assigned(anObject) then - AutoFormProviderRegistry.FormForElement(anObject).Show; + if Assigned(anObject) then begin + AForm := AutoFormProviderRegistry.FormForElement(anObject); + if Assigned(AForm) then begin + AForm.Show; + end; + end; end end; @@ -1299,7 +1342,11 @@ procedure TAutoFormList.AddPair(Form: TForm; Element: TBoldElement); function TAutoFormList.GetEntries( const index: integer): TAutoFormListEntry; begin - Result := TAutoFormListEntry(Items[index]); + if index < Count then begin + Result := TAutoFormListEntry(Items[index]); + end else begin + Result := nil; + end; end; function TAutoFormList.GetForms(const index: integer): TForm; @@ -1324,8 +1371,14 @@ function TAutoFormList.IndexOfElement(anObject: TObject): integer; end; procedure TAutoFormList.RemoveByForm(Form: TForm); +var + i: Integer; begin - Delete(IndexOfForm(Form)); + i := IndexOfForm(Form); + if i > -1 then begin + Entries[i].Free; + Delete(i); + end; end; constructor TBoldDefaultFormProvider.Create(BoldElement: TBoldElement); @@ -1709,7 +1762,7 @@ function TBoldDefaultObjectAutoFormProvider.CompareObjectsOnTimeStamp( initialization G_BoldActiveAutoForms := TAutoFormList.Create; fReadOnlyStringRenderer := TBoldAsStringRenderer.Create(nil); - fReadOnlyStringRenderer.OnSetColor := TBoldDefaultObjectAutoFormProvider.BoldAsStringRenderer1SetColor; +// fReadOnlyStringRenderer.OnSetColor := TBoldDefaultObjectAutoFormProvider.BoldAsStringRenderer1SetColor; //FIX AutoFormProviderRegistry.RegisterProvider(bvtClass, TBoldObject, TBoldDefaultObjectAutoFormProvider); AutoFormProviderRegistry.RegisterProvider(bvtSystem, TBoldSystem, TBoldDefaultSystemAutoFormProvider); diff --git a/Source/BoldAwareGUI/FormGen/BoldAFPPluggableReg.pas b/Source/BoldAwareGUI/FormGen/BoldAFPPluggableReg.pas index c489c6d..cde91b7 100644 --- a/Source/BoldAwareGUI/FormGen/BoldAFPPluggableReg.pas +++ b/Source/BoldAwareGUI/FormGen/BoldAFPPluggableReg.pas @@ -11,8 +11,6 @@ implementation BoldAFPPluggable, BoldIDEConsts; -{$R *.res} - procedure Register; begin RegisterComponents(BOLDPAGENAME_MISC, [TBoldPlaceableAFP]); diff --git a/Source/BoldAwareGUI/IDE/BoldAwareGuiReg.pas b/Source/BoldAwareGUI/IDE/BoldAwareGuiReg.pas index 9bf8ca9..fa2d6ca 100644 --- a/Source/BoldAwareGUI/IDE/BoldAwareGuiReg.pas +++ b/Source/BoldAwareGUI/IDE/BoldAwareGuiReg.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldAwareGuiReg; {$UNDEF BOLDCOMCLIENT} @@ -9,29 +12,27 @@ procedure Register; implementation uses - SysUtils, Classes, DesignIntf, BoldDefs, BoldAbstractPropertyEditors, BoldPropertyEditors, BoldGridPropertyEditors, -{$IFNDEF BOLDCOMCLIENT} // uses - BoldHandles, // IFNDEF BOLDCOMCLIENT - BoldExceptionHandlers, // IFNDEF BOLDCOMCLIENT - BoldAbstractListHandle, // IFNDEF BOLDCOMCLIENT - BoldComboBoxPropertyEditors, // IFNDEF BOLDCOMCLIENT - BoldControlPackPropertyEditors, // IFNDEF BOLDCOMCLIENT - - BoldMLRenderers, // fixthis // IFNDEF BOLDCOMCLIENT - BoldDataSet, // IFNDEF BOLDCOMCLIENT - BoldDataSetPropertyEditors, // IFNDEF BOLDCOMCLIENT - BoldDragDropTarget, // IFNDEF BOLDCOMCLIENT +{$IFNDEF BOLDCOMCLIENT} + BoldHandles, + BoldExceptionHandlers, + BoldAbstractListHandle, + BoldComboBoxPropertyEditors, + BoldControlPackPropertyEditors, + + BoldMLRenderers, + BoldDragDropTarget, {$ENDIF} BoldPropertiesControllerPropertyEditors, BoldPropertiesController, BoldStringsPropertyController, BoldControlPack, + BoldVariantControlPack, BoldGenericListControlPack, BoldStringControlPack, BoldCheckBoxStateControlPack, @@ -56,57 +57,45 @@ implementation BoldPageControl, BoldIDEConsts; -{$R BoldAwareGUIReg.res} - procedure RegisterEditors; begin - //TBoldRenderer RegisterPropertyEditor(TypeInfo(TBoldSubscribe), nil, '', TBoldElementSubscribeMethodProperty); RegisterPropertyEditor(TypeInfo(TBoldHoldsChangedValue), nil, '', TBoldHoldsChangedValueMethodProperty); RegisterPropertyEditor(TypeInfo(TBoldReleaseChangedValue), nil, '', TBoldReleaseChangedValueMethodProperty); RegisterPropertyEditor(TypeInfo(TBoldMayModify), nil, '', TBoldMayModifyMethodProperty); - {$IFNDEF BOLDCOMCLIENT} // register editors + {$IFNDEF BOLDCOMCLIENT} + + + RegisterPropertyEditor(TypeInfo(TBoldElementHandle), TPersistent, 'BoldHandle', TBoldComponentPropertyIndicateMissing); + RegisterPropertyEditor(TypeInfo(TBoldAbstractListHandle), TBoldComboBox, 'BoldListHandle', TBoldComponentPropertyIndicateMissing); - // Register property editors - // All properties of type TBoldElementHandle named BoldHandle will be displayed RED if prop not set - RegisterPropertyEditor(TypeInfo(TBoldElementHandle), TPersistent, 'BoldHandle', TBoldComponentPropertyIndicateMissing); // do not localize - RegisterPropertyEditor(TypeInfo(TBoldAbstractListHandle), TBoldComboBox, 'BoldListHandle', TBoldComponentPropertyIndicateMissing); // do not localize + RegisterPropertyEditor(TypeInfo(integer), TBoldFollowerController, 'Representation', TBoldRepresentationProperty); + RegisterPropertyEditor(TypeInfo(TBoldRenderer), TBoldFollowerController, 'Renderer', TBoldRendererComponentProperty); - RegisterPropertyEditor(TypeInfo(integer), TBoldFollowerController, 'Representation', TBoldRepresentationProperty); // do not localize - RegisterPropertyEditor(TypeInfo(TBoldRenderer), TBoldFollowerController, 'Renderer', TBoldRendererComponentProperty); // do not localize - // Note: registering for TPersistent screws up, as all string-properties will get an ellipsis! - // v the below line doesn't work, but is left as a reminder. - // RegisterPropertyEditor(TypeInfo(TBoldExpression), TPersistent, '', TBoldOCLExpressionProperty); - // ^ the above line doesn't work, but is left as a reminder. - RegisterPropertyEditor(TypeInfo(TBoldExpression), TBoldFollowerController, 'Expression', TBoldOCLExpressionForFollowerControllersProperty); // do not localize + + RegisterPropertyEditor(TypeInfo(TBoldExpression), TBoldFollowerController, 'Expression', TBoldOCLExpressionForFollowerControllersProperty); RegisterPropertyEditor(TypeInfo(TBoldSingleFollowerController), nil, '', TBoldSingleFollowerControllerEditor); RegisterPropertyEditor(TypeInfo(TBoldTreeFollowerController), nil, '', TBoldTreeFollowerControllerEditor); - - //TBoldAsStringRenderer RegisterPropertyEditor(TypeInfo(TBoldGetAsString), nil, '', TBoldGetAsStringMethodProperty); - //TBoldAsCheckBoxRenderer RegisterPropertyEditor(TypeInfo(TBoldGetAsCheckBoxState), nil, '', TBoldGetAsCheckBoxStateMethodProperty); - //TBoldAsIntegerRenderer RegisterPropertyEditor(TypeInfo(TBoldGetAsIntegerEvent), nil, '', TBoldGetAsIntegerEventMethodProperty); - //TBoldAsFloatRenderer RegisterPropertyEditor(TypeInfo(TBoldGetAsFloatEvent), nil, '', TBoldGetAsFloatEventMethodProperty); - //TBoldAsViewerRenderer RegisterPropertyEditor(TypeInfo(TBoldGetAsViewer), nil, '', TBoldGetAsViewerMethodProperty); - RegisterPropertyEditor(TypeInfo(String), TBoldNodeDescription, 'ContextTypeName', TBoldTypeNameSelectorPropertyForTreeFollowerController); // do not localize + RegisterPropertyEditor(TypeInfo(String), TBoldNodeDescription, 'ContextTypeName', TBoldTypeNameSelectorPropertyForTreeFollowerController); - RegisterPropertyEditor(TypeInfo(String), TBoldGenericListPart, 'ControllerExpression', TBoldOCLExpressionForGenericListPart); // do not localize - RegisterPropertyEditor(TypeInfo(String), TBoldGenericListPart, 'ElementExpression', TBoldOCLExpressionForGenericListPart); // do not localize + RegisterPropertyEditor(TypeInfo(String), TBoldGenericListPart, 'ControllerExpression', TBoldOCLExpressionForGenericListPart); + RegisterPropertyEditor(TypeInfo(String), TBoldGenericListPart, 'ElementExpression', TBoldOCLExpressionForGenericListPart); - RegisterPropertyEditor(TypeInfo(String), TBoldComboBox, 'BoldSetValueExpression', TBoldOCLExpressionForComboBoxSetValueExpression); // do not localize - RegisterPropertyEditor(TypeInfo(String), TBoldDropTarget, 'NodeSelectionExpression', TBoldOCLExpressionForOCLComponent); // do not localize - - // Register Component editors + RegisterPropertyEditor(TypeInfo(String), TBoldComboBox, 'BoldSetValueExpression', TBoldOCLExpressionForComboBoxSetValueExpression); + RegisterPropertyEditor(TypeInfo(String), TBoldDropTarget, 'NodeSelectionExpression', TBoldOCLExpressionForOCLComponent); + RegisterPropertyEditor(TypeInfo(TBoldGetAsVariant), nil, '', TBoldGetAsVariantMethodProperty); {Renderer editors} + RegisterComponentEditor(TBoldAsVariantRenderer, TBoldAsVariantRendererEditor); RegisterComponentEditor(TBoldAsStringRenderer, TBoldAsStringRendererEditor); RegisterComponentEditor(TBoldAsCheckboxStateRenderer, TBoldAsCheckboxStateRendererEditor); RegisterComponentEditor(TBoldAsIntegerRenderer, TBoldAsIntegerRendererEditor); @@ -126,25 +115,21 @@ procedure RegisterEditors; {$ENDIF} RegisterComponentEditor(TBoldCustomGrid, TBoldColumnsEditor); RegisterComponentEditor(TBoldPropertiesController,TBoldPropertiesControllerComponentEditor); - RegisterPropertyEditor(TypeInfo(String), TBoldDrivenProperty, 'PropertyName', TPropertyNameProperty); // do not localize - RegisterPropertyEditor(TypeInfo(TComponent), TBoldDrivenProperty, 'VCLComponent', TVCLComponentProperty); // do not localize -{$IFNDEF BOLDCOMCLIENT} // registerEditors - RegisterComponentEditor(TBoldAbstractDataset, TBoldDataSetEditor); -{$ENDIF} + RegisterPropertyEditor(TypeInfo(String), TBoldDrivenProperty, 'PropertyName', TPropertyNameProperty); + RegisterPropertyEditor(TypeInfo(TComponent), TBoldDrivenProperty, 'VCLComponent', TVCLComponentProperty); end; procedure RegisterComponentsOnPalette; begin -{$IFNDEF BOLDCOMCLIENT} // RegisterComponents +{$IFNDEF BOLDCOMCLIENT} RegisterComponents(BOLDPAGENAME_MISC, [ - TBoldDataSet, TBoldExceptionHandler ]); {$ENDIF} -{$IFDEF BOLDCOMCLIENT} // RegisterComponents - RegisterComponents(BOLDPAGENAME_COMCONTROLS, +{$IFDEF BOLDCOMCLIENT} + RegisterComponents('Bold COM Controls', {$ELSE} RegisterComponents(BOLDPAGENAME_CONTROLS, {$ENDIF} @@ -167,12 +152,12 @@ procedure RegisterComponentsOnPalette; TBoldImage, TBoldPropertiesController, TBoldStringsPropertyController, - //Renderers TBoldAsStringRenderer, TBoldAsCheckboxStateRenderer, TBoldAsIntegerRenderer, + TBoldAsVariantRenderer, TBoldAsFloatRenderer, - {$IFNDEF BOLDCOMCLIENT} // Register Components + {$IFNDEF BOLDCOMCLIENT} TBoldAsMLStringRenderer, TBoldDropTarget, {$ENDIF} @@ -182,7 +167,7 @@ procedure RegisterComponentsOnPalette; procedure Register; begin - RegisterComponentsOnPalette; + RegisterComponentsOnPalette; RegisterEditors; end; diff --git a/Source/BoldAwareGUI/IDE/BoldComboBoxPropertyEditors.pas b/Source/BoldAwareGUI/IDE/BoldComboBoxPropertyEditors.pas index bd44a13..6a5bc37 100644 --- a/Source/BoldAwareGUI/IDE/BoldComboBoxPropertyEditors.pas +++ b/Source/BoldAwareGUI/IDE/BoldComboBoxPropertyEditors.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldComboBoxPropertyEditors; interface @@ -17,7 +20,6 @@ implementation uses SysUtils, - BoldGuiResourceStrings, BoldDefs, BoldComboBox; @@ -32,7 +34,8 @@ function TBoldOCLExpressionForComboBoxSetValueExpression.GetContextType( else Result := nil else - raise EBold.CreateFmt(sComponentNotComboBox, [ClassName]); + raise EBold.CreateFmt('%s.GetContextType: Incoming component is not a BoldComboBox', [ClassName]); end; +initialization end. diff --git a/Source/BoldAwareGUI/IDE/BoldControlPackPropertyEditors.pas b/Source/BoldAwareGUI/IDE/BoldControlPackPropertyEditors.pas index 6252d8c..d611e97 100644 --- a/Source/BoldAwareGUI/IDE/BoldControlPackPropertyEditors.pas +++ b/Source/BoldAwareGUI/IDE/BoldControlPackPropertyEditors.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldControlPackPropertyEditors; interface @@ -37,12 +40,12 @@ TBoldTypeNameSelectorPropertyForTreeFollowerController = class(TBoldTypeNameSe function GetApprovedTypes: TBoldValueTypes; override; function GetContextType(Component: TPersistent): TBoldSystemTypeInfo; override; public - //procedure Edit; override; end; {---TBoldSingleFollowerControllerEditor---} TBoldSingleFollowerControllerEditor = class(TBoldClassProperty) public + function GetValue: string; override; function GetAttributes: TPropertyAttributes; override; procedure Edit; override; end; @@ -153,6 +156,20 @@ TBoldMayModifyMethodProperty = class(TBoldOneLinerWithEvalMethodProperty) function GetDeltaLines: integer; override; end; + {---TBoldAsVariantRendererEditor---} + TBoldAsVariantRendererEditor = class(TBoldComponentDblClickEditor) + protected + function GetDefaultMethodName: string; override; + end; + + {---TBoldGetAsVariantMethodProperty---} + TBoldGetAsVariantMethodProperty = class(TBoldOTAModifyingMethodProperty) + public + function TextToInsert: string; override; + function GetDeltaLines: integer; override; + function GetColPos: integer; override; + end; + implementation uses @@ -160,7 +177,6 @@ implementation BoldUtils, TypInfo, Controls, - BoldGuiResourceStrings, BoldControlPack, BoldTreeView, BoldDefs, @@ -179,6 +195,21 @@ function TBoldSingleFollowerControllerEditor.GetAttributes: TPropertyAttributes; Result := inherited GetAttributes + [paDialog] - [paMultiSelect]; end; +function TBoldSingleFollowerControllerEditor.GetValue: string; +var + P: TPersistent; +begin + p := TPersistent(GetOrdValue); + if Assigned(P) and (P is TBoldFollowerController) then + begin + Result := TBoldFollowerControllerHack(P).Expression; + if Result = '' then + Result := '('+TBoldFollowerControllerHack(P).EffectiveRenderer.Name+')'; + end + else + Result := inherited GetValue; +end; + procedure TBoldSingleFollowerControllerEditor.Edit; var FollowerController: TBoldSingleFollowerController; @@ -206,19 +237,19 @@ procedure TBoldSingleFollowerControllerEditor.Edit; {---TBoldAsStringRendererEditor---} function TBoldAsStringRendererEditor.GetDefaultMethodName: string; begin - Result := 'OnGetAsString'; // do not localize + Result := 'OnGetAsString'; end; {---TBoldAsIntegerRendererEditor---} function TBoldAsIntegerRendererEditor.GetDefaultMethodName: string; begin - Result := 'OnGetAsInteger'; // do not localize + Result := 'OnGetAsInteger'; end; {---TBoldAsCheckBoxStateRendererEditor---} function TBoldAsCheckBoxStateRendererEditor.GetDefaultMethodName: string; begin - Result := 'OnGetAsCheckBoxState';// do not localize + Result := 'OnGetAsCheckBoxState'; end; {---TBoldGetAsStringMethodProperty---} @@ -226,11 +257,11 @@ function TBoldGetAsStringMethodProperty.TextToInsert: string; begin Result := ''; {$IFDEF BOLD_DELPHI} - Result := ' Result := '''';' + BOLDCRLF; // do not localize + Result := ' Result := '''';' + BOLDCRLF; {$ENDIF} - Result := Result + Format(' if %s(Element) %s', [BOLDSYM_ASSIGNED, BOLDSYM_THEN]) + BOLDCRLF; // do not localize - Result := Result + Format(' %s', [BOLDSYM_BEGIN]) + BOLDCRLF + BOLDCRLF; // do not localize - Result := Result + Format(' %s', [BOLDSYM_END]); // do not localize + Result := Result + Format(' if %s(AFollower.Element) %s', [BOLDSYM_ASSIGNED, BOLDSYM_THEN]) + BOLDCRLF; + Result := Result + Format(' %s', [BOLDSYM_BEGIN]) + BOLDCRLF + BOLDCRLF; + Result := Result + Format(' %s', [BOLDSYM_END]); end; function TBoldGetAsStringMethodProperty.GetDeltaLines: integer; @@ -248,9 +279,9 @@ function TBoldGetAsCheckBoxStateMethodProperty.TextToInsert: string; begin Result := ''; {$IFDEF BOLD_DELPHI} - Result := ' Result := cbGrayed;' + BOLDCRLF; // do not localize + Result := ' Result := cbGrayed;' + BOLDCRLF; {$ENDIF} - Result := Result + Format(' if %s(Element) %s', [BOLDSYM_ASSIGNED, BOLDSYM_THEN]) + BOLDCRLF; // do not localize + Result := Result + Format(' if %s(AFollower.Element) %s', [BOLDSYM_ASSIGNED, BOLDSYM_THEN]) + BOLDCRLF; Result := Result + Format(' %s', [BOLDSYM_BEGIN]) + BOLDCRLF + BOLDCRLF; Result := Result + Format(' %s', [BOLDSYM_END]); end; @@ -270,9 +301,9 @@ function TBoldGetAsIntegerEventMethodProperty.TextToInsert: string; begin Result := ''; {$IFDEF BOLD_DELPHI} - Result := ' Result := 0;' + BOLDCRLF; // do not localize + Result := ' Result := 0;' + BOLDCRLF; {$ENDIF} - Result := Result + Format(' if %s(Element) %s', [BOLDSYM_ASSIGNED, BOLDSYM_THEN]) + BOLDCRLF; // do not localize + Result := Result + Format(' if %s(AFollower.Element) %s', [BOLDSYM_ASSIGNED, BOLDSYM_THEN]) + BOLDCRLF; Result := Result + Format(' %s', [BOLDSYM_BEGIN]) + BOLDCRLF + BOLDCRLF; Result := Result + Format(' %s', [BOLDSYM_END]); end; @@ -291,7 +322,7 @@ function TBoldGetAsIntegerEventMethodProperty.GetColPos: integer; function TBoldHoldsChangedValueMethodProperty.TextToInsert: string; begin - result := Format(' Element%sEvaluateExpressionAsDirectElement(%s%s).RegisterModifiedValueHolder(Subscriber);', // do not localize + result := Format(' AFollower.Element%sEvaluateExpressionAsDirectElement(%s%s).RegisterModifiedValueHolder(AFollower.Subscriber);', [BOLDSYM_POINTERDEREFERENCE, BOLDSYM_QUOTECHAR, BOLDSYM_QUOTECHAR]); end; @@ -299,13 +330,13 @@ function TBoldHoldsChangedValueMethodProperty.TextToInsert: string; function TBoldReleaseChangedValueMethodProperty.TextToInsert: string; begin - result := Format(' Element%sEvaluateExpressionAsDirectElement(%s%s).UnRegisterModifiedValueHolder(Subscriber);', // do not localize + result := Format(' AFollower.Element%sEvaluateExpressionAsDirectElement(%s%s).UnRegisterModifiedValueHolder(AFollower.Subscriber);', [BOLDSYM_POINTERDEREFERENCE, BOLDSYM_QUOTECHAR, BOLDSYM_QUOTECHAR]); end; function TBoldMayModifyMethodProperty.TextToInsert: string; begin - result := Format(' %sresult %s Element%sEvaluateExpressionAsDirectElement(%s%s).ObserverMayModify(subscriber);', // do not localize + result := Format(' %sresult %s AFollower.Element%sEvaluateExpressionAsDirectElement(%s%s).ObserverMayModify(AFollower.subscriber);', [BOLDSYM_TYPEINTEGER, BOLDSYM_ASSIGNMENT, BOLDSYM_POINTERDEREFERENCE, BOLDSYM_QUOTECHAR, BOLDSYM_QUOTECHAR]); Result := Result + BOLDSYM_RETURNRESULT; end; @@ -320,9 +351,9 @@ function TBoldGetAsViewerMethodProperty.TextToInsert: string; begin Result := ''; {$IFDEF BOLD_DELPHI} - Result := ' Result := nil;' + BOLDCRLF; // do not localize + Result := ' Result := nil;' + BOLDCRLF; {$ENDIF} - Result := Result + Format(' if %s(Element) %s', [BOLDSYM_ASSIGNED, BOLDSYM_THEN]) + BOLDCRLF; // do not localize + Result := Result + Format(' if %s(AFollower.Element) %s', [BOLDSYM_ASSIGNED, BOLDSYM_THEN]) + BOLDCRLF; Result := Result + Format(' %s', [BOLDSYM_BEGIN]) + BOLDCRLF + BOLDCRLF; Result := Result + Format(' %s', [BOLDSYM_END]); end; @@ -367,7 +398,7 @@ function TBoldRepresentationProperty.GetValue: string; I := GetOrdValue; S := IntToStr(I); with TBoldFollowerControllerHack(P).EffectiveRenderer do - if Representations.Values[S] <> '' then + if Representations.Values[S]<>'' then Result := Format('%d=%s', [I, Representations.Values[S]]) else Result := inherited GetValue; @@ -391,13 +422,13 @@ procedure TBoldRepresentationProperty.SetValue(const value: string); function TBoldRendererComponentProperty.GetValue: string; begin Result := Designer.GetComponentName(TComponent(GetOrdValue)); - if (Result = '') then - Result := '(default)'; // do not localize + if (Result='') then + Result := '(default)'; end; procedure TBoldRendererComponentProperty.GetValues(Proc: TGetStrProc); begin - Proc('(default)'); // do not localize + Proc('(default)'); Designer.GetComponentNames(GetTypeData(GetPropType), Proc); end; @@ -405,13 +436,13 @@ procedure TBoldRendererComponentProperty.SetValue(const Value: string); var Component: TComponent; begin - if (Value = '') or (Value[1] = '(') then + if (Value = '') or (Value[1]='(') then Component := nil else begin Component := Designer.GetComponent(Value); if not (Component is GetTypeData(GetPropType)^.ClassType) then - raise EPropertyError.Create(sInvalidPropertyValue); + raise EPropertyError.Create('Invalid property value'); end; SetOrdValue(Longint(Component)); end; @@ -429,7 +460,7 @@ procedure TBoldNodeDescriptionEditor.ExecuteVerb(Index: Integer); function TBoldNodeDescriptionEditor.GetVerb(Index: Integer): string; begin - Result := sEditNodeDescriptions; + Result := '&Edit Node Descriptions...'; end; function TBoldNodeDescriptionEditor.GetVerbCount: Integer; @@ -483,7 +514,7 @@ function TBoldTypeNameSelectorPropertyForTreeFollowerController.GetContextType( function TBoldAsFloatRendererEditor.GetDefaultMethodName: string; begin - Result := 'OnGetAsFloat'; // do not localize + Result := 'OnGetAsFloat'; end; { TBoldGetAsFloatEventMethodProperty } @@ -502,9 +533,9 @@ function TBoldGetAsFloatEventMethodProperty.TextToInsert: string; begin Result := ''; {$IFDEF BOLD_DELPHI} - Result := ' Result := 0;' + BOLDCRLF; // do not localize + Result := ' Result := 0;' + BOLDCRLF; {$ENDIF} - Result := Result + Format(' if %s(Element) %s', [BOLDSYM_ASSIGNED, BOLDSYM_THEN]) + BOLDCRLF; // do not localize + Result := Result + Format(' if %s(AFollower.Element) %s', [BOLDSYM_ASSIGNED, BOLDSYM_THEN]) + BOLDCRLF; Result := Result + Format(' %s', [BOLDSYM_BEGIN]) + BOLDCRLF + BOLDCRLF; Result := Result + Format(' %s', [BOLDSYM_END]); end; @@ -523,7 +554,7 @@ procedure TBoldTreeFollowerControllerEditor.Edit; Designer.Modified; end else - raise EPropertyError.Create(sInvalidPropertyValue); + raise EPropertyError.Create('Invalid property value'); end; function TBoldTreeFollowerControllerEditor.GetAttributes: TPropertyAttributes; @@ -531,4 +562,36 @@ function TBoldTreeFollowerControllerEditor.GetAttributes: TPropertyAttributes; Result := inherited GetAttributes + [paDialog] - [paMultiSelect]; end; +{ TBoldAsVariantRendererEditor } + +function TBoldAsVariantRendererEditor.GetDefaultMethodName: string; +begin + Result := 'OnGetAsVariant'; // do not localize +end; + +{ TBoldGetAsVariantMethodProperty } + +function TBoldGetAsVariantMethodProperty.GetColPos: integer; +begin + Result := 5; +end; + +function TBoldGetAsVariantMethodProperty.GetDeltaLines: integer; +begin + Result := -1; +end; + +function TBoldGetAsVariantMethodProperty.TextToInsert: string; +begin + Result := ''; +{$IFDEF BOLD_DELPHI} + Result := ' Result := Null;' + BOLDCRLF; // do not localize +{$ENDIF} + Result := Result + Format(' if %s(AFollower.Element) %s', [BOLDSYM_ASSIGNED, BOLDSYM_THEN]) + BOLDCRLF; // do not localize + Result := Result + Format(' %s', [BOLDSYM_BEGIN]) + BOLDCRLF + BOLDCRLF; // do not localize + Result := Result + Format(' %s', [BOLDSYM_END]); // do not localize +end; + +initialization + end. diff --git a/Source/BoldAwareGUI/IDE/BoldDataSetPropertyEditors.pas b/Source/BoldAwareGUI/IDE/BoldDataSetPropertyEditors.pas deleted file mode 100644 index b3edb4e..0000000 --- a/Source/BoldAwareGUI/IDE/BoldDataSetPropertyEditors.pas +++ /dev/null @@ -1,96 +0,0 @@ -unit BoldDataSetPropertyEditors; - -interface - -uses - DesignEditors, - DesignIntf; - -type - { forward declarations } - TBoldDataSetEditor = class; - - { TBoldDataSetEditor } - TBoldDataSetEditor = class(TComponentEditor) - private - procedure GetPropEditProc(const Prop: IProperty); - protected - procedure EditFields; - procedure ClearFields; - procedure CreateDefaultFields; - public - procedure ExecuteVerb(Index: Integer); override; - function GetVerb(Index: Integer): string; override; - function GetVerbCount: Integer; override; - end; - -implementation - -uses - BoldGuiResourceStrings, - BoldDataset, - TypInfo; - -type - TBoldExposedAbstractDataSet = class(TBoldAbstractDataset); - -{ TBoldDataSetEditor } - -procedure TBoldDataSetEditor.CreateDefaultFields; -begin - if Component is TBoldAbstractDataSet and - Assigned(TBoldExposedAbstractDataSet(Component).BoldHandle) then - with TBoldAbstractDataSet(Component) do - CreateDefaultFields; -end; - -procedure TBoldDataSetEditor.ClearFields; -begin - if Component is TBoldAbstractDataSet then - with TBoldExposedAbstractDataSet(Component) do - DeleteAllFields; -end; - -procedure TBoldDataSetEditor.ExecuteVerb(Index: Integer); -begin - case Index of - 0: EditFields; - 1: CreateDefaultFields; - 2: ClearFields; - end; -end; - -function TBoldDataSetEditor.GetVerb(Index: Integer): string; -begin - case Index of - 0: Result := sFieldsEditor; - 1: Result := sCreateDefaultFields; - 2: Result := sClearAllFields; - end; -end; - -function TBoldDataSetEditor.GetVerbCount: Integer; -begin - Result := 3; -end; - -procedure TBoldDataSetEditor.EditFields; -var - Components: IDesignerSelections; -begin - Components := TDesignerSelections.Create; - Components.Add(Component); - - GetComponentProperties(Components, - [tkClass], - Designer, - GetPropEditProc, nil); -end; - -procedure TBoldDataSetEditor.GetPropEditProc(const Prop: IProperty); -begin - if Prop.GetName = 'FieldDescriptions' then // do not localize - Prop.Edit; -end; - -end. diff --git a/Source/BoldAwareGUI/IDE/BoldGridPropertyEditors.pas b/Source/BoldAwareGUI/IDE/BoldGridPropertyEditors.pas index 6f099e8..bb7a76c 100644 --- a/Source/BoldAwareGUI/IDE/BoldGridPropertyEditors.pas +++ b/Source/BoldAwareGUI/IDE/BoldGridPropertyEditors.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldGridPropertyEditors; {$UNDEF BOLDCOMCLIENT} @@ -28,7 +31,6 @@ TBoldColumnsEditor = class(TComponentEditor) implementation uses - BoldGuiResourceStrings, SysUtils, BoldGrid, TypInfo; @@ -39,7 +41,7 @@ TBoldExposedCustomGrid = class(TBoldCustomGrid); {---TBoldColumnsEditor---} procedure TBoldColumnsEditor.EditPropertyColumns(const PropertyEditor: IProperty); begin - if AnsiSameText(PropertyEditor.GetName, 'Columns') then // do not localize + if SameText(PropertyEditor.GetName, 'Columns') then PropertyEditor.Edit; end; @@ -74,7 +76,6 @@ procedure TBoldColumnsEditor.EmptyColumns; begin DeleteAllColumns; AddColumn; - // This is done because the grid screws up the column widths AddColumn; Columns[1].Free; end; @@ -92,9 +93,9 @@ procedure TBoldColumnsEditor.ExecuteVerb(Index: Integer); function TBoldColumnsEditor.GetVerb(Index: Integer): string; begin case index of - 0: Result := sEditColumns; - 1: Result := sCreateDefaultColumns; - 2: Result := sClearAllColumns; + 0: Result := '&Edit Columns'; + 1: Result := 'Create Default Columns'; + 2: Result := 'Clear all Columns'; end; end; @@ -103,4 +104,6 @@ function TBoldColumnsEditor.GetVerbCount: Integer; Result := 3; end; + +initialization end. diff --git a/Source/BoldAwareGUI/IDE/BoldNodeDescriptionEditor.pas b/Source/BoldAwareGUI/IDE/BoldNodeDescriptionEditor.pas index 7aa48b7..cd54146 100644 --- a/Source/BoldAwareGUI/IDE/BoldNodeDescriptionEditor.pas +++ b/Source/BoldAwareGUI/IDE/BoldNodeDescriptionEditor.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldNodeDescriptionEditor; interface @@ -14,13 +17,11 @@ interface DesignEditors, DesignIntf, BoldNodeControlPack, -// BoldTreeView, Menus, BoldSubscription, ImgList; type -// TBoldCustomTreeViewHack = class(TBoldCustomTreeView) -// end; + TFormNodeEditor = class(TForm) TreeView: TTreeView; @@ -74,7 +75,6 @@ implementation uses SysUtils, - BoldGuiResourceStrings, BoldDefs, BoldControlPack, BoldGenericListControlPack; @@ -225,7 +225,6 @@ procedure TFormNodeEditor.UpdateTree; end; begin - //Init list pointer to first node CurrentNode := TreeView.items.GetFirstNode; Inc(FUpdateCount); @@ -256,7 +255,7 @@ procedure TFormNodeEditor.UpdateTree; end; end; PurgeEnd; - RootNode.Expand(False); //CHANGED + RootNode.Expand(False); finally Dec(FUpdateCount); end; @@ -284,7 +283,7 @@ procedure TFormNodeEditor.UpdateNode(Node: TTreeNode); {Add subscrption} if TObject(Node.Data) is TBoldFollowerController then begin - TBoldFollowerController(Node.Data).AddSmallSubscription(FSubscriber, [beDestroying, beValueChanged], breReEvaluate); //CHANGED + TBoldFollowerController(Node.Data).AddSmallSubscription(FSubscriber, [beDestroying, beValueChanged], breReEvaluate); end; {Update caption and icon} if TObject(Node.Data) is TComponent then @@ -294,7 +293,7 @@ procedure TFormNodeEditor.UpdateNode(Node: TTreeNode); else if TObject(Node.Data) is TBoldTreeFollowerController then begin TBoldTreeFollowerController(Node.Data).AddSmallSubscription(FSubscriber, [beDestroying, beValueChanged], breReEvaluate); - SetTextAndImage( 'Root', 8); // do not localize + SetTextAndImage( 'Root', 8); end else if TObject(Node.Data) is TBoldNodeDescription then begin @@ -313,7 +312,7 @@ procedure TFormNodeEditor.UpdateNode(Node: TTreeNode); ImageIndex := 2 else ImageIndex := 4; - SetTextAndImage(Format('Parts[%d] Element: ''%s'' Controller: ''%s''', [Index, ElementExpression, ControllerExpression]), ImageIndex); // do not localize + SetTextAndImage(Format('Parts[%d] Element: ''%s'' Controller: ''%s''', [Index, ElementExpression, ControllerExpression]), ImageIndex); end; end else @@ -488,4 +487,6 @@ procedure TFormNodeEditor.cmdSortClick(Sender: TObject); UpdateTree; end; +initialization + end. diff --git a/Source/BoldAwareGUI/IDE/BoldPropertiesControllerPropertyEditors.pas b/Source/BoldAwareGUI/IDE/BoldPropertiesControllerPropertyEditors.pas index 9499dd2..428872a 100644 --- a/Source/BoldAwareGUI/IDE/BoldPropertiesControllerPropertyEditors.pas +++ b/Source/BoldAwareGUI/IDE/BoldPropertiesControllerPropertyEditors.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldPropertiesControllerPropertyEditors; interface @@ -5,31 +8,25 @@ interface uses Classes, DesignEditors, - DesignIntf, + DesignIntf, BoldAbstractPropertyEditors; type - // A Property editor for the PropertyName property. - // It lists all meaningful properties of "Component" including properties of "sub-components" - // It has currently some trouble with collections and will not show panels[0] for example - { TPropertyNameProperty } + + TPropertyNameProperty = class(TBoldStringProperty) public function GetAttributes: TPropertyAttributes; override; procedure GetValues(Proc: TGetStrProc); override; end; - // A Property editor for VCLComponent property - // It is based on the TComponentProperty which lists all components of the form - // In addition to those it will also list the form so we can control its properties ! - { TVCLComponentProperty } + TVCLComponentProperty = class(TBoldComponentProperty) public procedure GetValues(Proc: TGetStrProc); override; procedure SetValue(const Value: string); override; end; - { TBoldPropertiesControllerComponentEditor } TBoldPropertiesControllerComponentEditor = class(TDefaultEditor) protected procedure EditProperty(const PropertyEditor: IProperty; var Continue: Boolean); override; @@ -43,7 +40,6 @@ implementation uses SysUtils, - BoldGuiResourceStrings, TypInfo, BoldControlsDefs, BoldPropertiesController; @@ -72,9 +68,9 @@ procedure TPropertyNameProperty.GetValues(Proc: TGetStrProc); for I := 0 to Count - 1 do begin if Path = '' then - NewPath := PropList[I]^.Name + NewPath := String(PropList[I]^.Name) else - NewPath := Path + '.' + PropList[I]^.Name; + NewPath := Path + '.' + String(PropList[I]^.Name); if (PropList[I]^.PropType^.Kind <> tkClass) then begin @@ -84,7 +80,7 @@ procedure TPropertyNameProperty.GetValues(Proc: TGetStrProc); else begin if Assigned(LastObject) then - NewObj := TObject(GetOrdProp(LastObject, PropList[I]^.Name)); + NewObj := TObject(GetOrdProp(LastObject, String(PropList[I]^.Name))); if NewObj is TCollection then for J := 0 to TCollection(NewObj).Count - 1 do @@ -102,7 +98,7 @@ procedure TPropertyNameProperty.GetValues(Proc: TGetStrProc); begin if PropCount < 1 then exit; - SelectedComponent := GetComponent(0) as TBoldDrivenProperty; //we don't allow multiselect + SelectedComponent := GetComponent(0) as TBoldDrivenProperty; if Assigned(SelectedComponent) and Assigned(SelectedComponent.VCLComponent) then DeclareProperties(SelectedComponent.VCLComponent,SelectedComponent.VCLComponent.ClassInfo,''); end; @@ -111,7 +107,7 @@ procedure TPropertyNameProperty.GetValues(Proc: TGetStrProc); procedure TVCLComponentProperty.GetValues(Proc: TGetStrProc); begin - Proc(TBoldDrivenProperty(GetComponent(0)).PropertiesController.Owner.Name); // Add the Form's name to available components + Proc(TBoldDrivenProperty(GetComponent(0)).PropertiesController.Owner.Name); inherited; end; @@ -119,7 +115,6 @@ procedure TVCLComponentProperty.SetValue(const Value: string); var Component: TComponent; begin - // Special case for the form if Value = TBoldDrivenProperty(GetComponent(0)).PropertiesController.Owner.Name then begin Component := TBoldDrivenProperty(GetComponent(0)).PropertiesController.Owner; @@ -133,7 +128,7 @@ procedure TVCLComponentProperty.SetValue(const Value: string); procedure TBoldPropertiesControllerComponentEditor.EditProperty(const PropertyEditor: IProperty; var Continue: Boolean); begin - if PropertyEditor.GetName = 'DrivenProperties' then //do not localize + if PropertyEditor.GetName = 'DrivenProperties' then begin PropertyEditor.Edit; Continue := False; @@ -151,7 +146,7 @@ procedure TBoldPropertiesControllerComponentEditor.ExecuteVerb(Index: Integer); function TBoldPropertiesControllerComponentEditor.GetVerb(Index: Integer): string; begin case Index of - 0: Result := sEditDrivenProperties; + 0: Result := 'Edit driven properties...'; end; end; @@ -160,4 +155,5 @@ function TBoldPropertiesControllerComponentEditor.GetVerbCount: Integer; Result := 1; end; +initialization end. diff --git a/Source/BoldQAwareGUI/BoldControls/BoldQEdit.pas b/Source/BoldQAwareGUI/BoldControls/BoldQEdit.pas index 5665b1f..5f33333 100644 --- a/Source/BoldQAwareGUI/BoldControls/BoldQEdit.pas +++ b/Source/BoldQAwareGUI/BoldControls/BoldQEdit.pas @@ -205,7 +205,6 @@ implementation uses SysUtils, - BoldRev, BoldUtils; { TBoldComboButton } diff --git a/Source/BoldQAwareGUI/BoldControls/BoldQLabel.pas b/Source/BoldQAwareGUI/BoldControls/BoldQLabel.pas index 4b5745e..10f0540 100644 --- a/Source/BoldQAwareGUI/BoldControls/BoldQLabel.pas +++ b/Source/BoldQAwareGUI/BoldControls/BoldQLabel.pas @@ -116,7 +116,6 @@ implementation uses SysUtils, - BoldRev, BoldUtils; type diff --git a/Source/BoldQAwareGUI/ControlPacks/BoldQControlPack.pas b/Source/BoldQAwareGUI/ControlPacks/BoldQControlPack.pas index e217d3c..1fecac2 100644 --- a/Source/BoldQAwareGUI/ControlPacks/BoldQControlPack.pas +++ b/Source/BoldQAwareGUI/ControlPacks/BoldQControlPack.pas @@ -342,7 +342,6 @@ function BoldTestType(element: TObject; TypeOrInterface: TClass): Boolean; implementation uses - BoldRev, BoldUtils, BoldExceptionHandlers, {$IFNDEF BOLDCOMCLIENT} // uses diff --git a/Source/BoldQAwareGUI/ControlPacks/BoldQElementHandleFollower.pas b/Source/BoldQAwareGUI/ControlPacks/BoldQElementHandleFollower.pas index 48d9cf0..21c4d7e 100644 --- a/Source/BoldQAwareGUI/ControlPacks/BoldQElementHandleFollower.pas +++ b/Source/BoldQAwareGUI/ControlPacks/BoldQElementHandleFollower.pas @@ -46,7 +46,6 @@ implementation uses SysUtils, - BoldRev, BoldUtils, BoldDefs; diff --git a/Source/BoldQAwareGUI/ControlPacks/BoldQStringControlPack.pas b/Source/BoldQAwareGUI/ControlPacks/BoldQStringControlPack.pas index 89583d4..f6c82c2 100644 --- a/Source/BoldQAwareGUI/ControlPacks/BoldQStringControlPack.pas +++ b/Source/BoldQAwareGUI/ControlPacks/BoldQStringControlPack.pas @@ -122,7 +122,6 @@ implementation uses SysUtils, - BoldRev, BoldUtils; var diff --git a/Source/BoldQAwareGUI/Core/BoldQGUI.pas b/Source/BoldQAwareGUI/Core/BoldQGUI.pas index ca42b3f..712ca9d 100644 --- a/Source/BoldQAwareGUI/Core/BoldQGUI.pas +++ b/Source/BoldQAwareGUI/Core/BoldQGUI.pas @@ -46,7 +46,6 @@ implementation uses SysUtils, - BoldRev, BoldUtils, BoldSystemRT; diff --git a/Source/ClientGuiCom/BoldControls/BoldCaptionControllerCom.pas b/Source/ClientGuiCom/BoldControls/BoldCaptionControllerCom.pas index d97f1d3..6c630b5 100644 --- a/Source/ClientGuiCom/BoldControls/BoldCaptionControllerCom.pas +++ b/Source/ClientGuiCom/BoldControls/BoldCaptionControllerCom.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldCaptionControllerCom; {$DEFINE BOLDCOMCLIENT} {Clientified 2002-08-05 13:13:02} @@ -7,7 +10,7 @@ interface uses Classes, Controls, - BoldEnvironmentVCL, // Make sure VCL environement loaded, and finalized after + BoldEnvironmentVCL, BoldHandlesCom, BoldElementHandleFollowerCom, BoldComObjectSpace_TLB, BoldClientElementSupport, BoldComClient, @@ -111,7 +114,7 @@ procedure TBoldCustomCaptionControllerCom.SetCaption(s: TCaption); (s <> TrackedCaption) then begin fCaption := s; - TrackedCaption := Caption; //TrackedCaption ensures valid fTrackControl + TrackedCaption := Caption; end; end; @@ -120,7 +123,7 @@ procedure TBoldCustomCaptionControllerCom.SetTrackControl(Control: TWinControl); if Control <> fTrackControl then begin fTrackControl := Control; - Caption := Caption; //Update caption if new Control; + Caption := Caption; end; end; @@ -187,4 +190,3 @@ function TBoldCustomCaptionControllerCom.GetVariableList: IBoldExternalVariableL initialization end. - diff --git a/Source/ClientGuiCom/BoldControls/BoldCheckBoxCom.pas b/Source/ClientGuiCom/BoldControls/BoldCheckBoxCom.pas index 9ec9a40..0b339a5 100644 --- a/Source/ClientGuiCom/BoldControls/BoldCheckBoxCom.pas +++ b/Source/ClientGuiCom/BoldControls/BoldCheckBoxCom.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldCheckBoxCom; {$DEFINE BOLDCOMCLIENT} {Clientified 2002-08-05 13:13:02} @@ -5,16 +8,19 @@ interface uses - Messages, + // VCL Classes, Controls, + Messages, StdCtrls, - BoldEnvironmentVCL, // Make sure VCL environement loaded, and finalized after - BoldHandlesCom, - BoldElementHandleFollowerCom, - BoldComObjectSpace_TLB, BoldClientElementSupport, BoldComClient, + + // Bold + BoldCheckboxStateControlPackCom, + BoldClientElementSupport, + BoldComObjectSpace_TLB, BoldControlPackCom, - BoldCheckboxStateControlPackCom; + BoldElementHandleFollowerCom, + BoldHandlesCom; type TBoldCustomCheckBoxCom = class; @@ -116,7 +122,6 @@ implementation uses SysUtils, - BoldRev, BoldDefs, BoldControlPackDefs; diff --git a/Source/ClientGuiCom/BoldControls/BoldComboBoxCom.pas b/Source/ClientGuiCom/BoldControls/BoldComboBoxCom.pas index 637fbbc..1bcce6c 100644 --- a/Source/ClientGuiCom/BoldControls/BoldComboBoxCom.pas +++ b/Source/ClientGuiCom/BoldControls/BoldComboBoxCom.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldComboBoxCom; {$DEFINE BOLDCOMCLIENT} {Clientified 2002-08-05 13:13:02} @@ -5,32 +8,29 @@ interface uses - Windows, - Messages, + // VCL Classes, - Graphics, Controls, - SysUtils, + Graphics, Menus, + Messages, StdCtrls, - BoldEnvironmentVCL, // Make sure VCL environement loaded, and finalized after - BoldDefs, - BoldControlsDefs, - BoldHandlesCom, - BoldComObjectSpace_TLB, BoldClientElementSupport, BoldComClient, + SysUtils, + Windows, + + // Bold BoldAbstractListHandleCom, - BoldElementHandleFollowerCom, - BoldListHandleFollowerCom, + BoldComObjectSpace_TLB, BoldComponentValidatorCom, BoldControlPackCom, + BoldControlsDefs, + BoldDefs, + BoldElementHandleFollowerCom, + BoldHandlesCom, + BoldListHandleFollowerCom, BoldListListControlPackCom, BoldStringControlPackCom; -{TODO 3 -ofrha -cfeature: WM_PAINT} -{TODO 3 -ofrha -cbug: Alignment not compleatly implemented} -{TODO 3 -ofrha -ccheckme: CB_GETEXTENDEDUI} -{TODO 3 -ofrha -cbug: AfterMakeUptodate when DroppedDown} - type {Forward declarations of all classes} TBoldCustomComboBoxCom = class; @@ -135,7 +135,6 @@ TBoldCustomComboBoxCom = class(TCustomComboBox, IBoldValidateableComponentCom) property EffectiveFont: TFont read GetEffectiveFont; property EffectiveReadOnly: Boolean read FEffectiveReadOnly; property Font: TFont read FFont write SetFont stored IsFontStored; -// property Items write SetItems; property ReadOnly: Boolean read FReadOnly write SetReadOnly default False; property Text: string read GetText write SetText; public @@ -162,12 +161,11 @@ TBoldComboBoxCom = class(TBoldCustomComboBoxCom) property BoldSetValueExpression; property BoldSelectChangeAction; property OnSelectChanged; - property CharCase; {Must be published before ReadOnly} //From TBoldCutomCombBox + property CharCase; {Must be published before ReadOnly} property ReadOnly; {Properties in standard TComboBox} - property Style; {Must be published before Items} {TODO 3 -ofrha -cbug: Create own styles!} + property Style; {Must be published before Items} property Anchors; - // property BiDiMode; property Color; property Constraints; property Ctl3D; @@ -177,10 +175,8 @@ TBoldComboBoxCom = class(TBoldCustomComboBoxCom) property DropDownCount; property Enabled; property Font; -// property ImeMode; -// property ImeName; + property ItemHeight; -// property Items; property MaxLength; property ParentBiDiMode; property ParentColor; @@ -192,7 +188,6 @@ TBoldComboBoxCom = class(TBoldCustomComboBoxCom) property Sorted; property TabOrder; property TabStop; -// property Text; Text is only public! property Visible; property OnChange; property OnClick; @@ -218,7 +213,6 @@ TBoldComboBoxCom = class(TBoldCustomComboBoxCom) implementation uses - BoldRev, BoldExceptionHandlersCom, BoldReferenceHandleCom, {$IFNDEF BOLDCOMCLIENT} @@ -252,7 +246,6 @@ procedure TBoldCustomComboBoxCom._RowAfterMakeUptoDate(Follower: TBoldFollowerCo if (index > -1) and (index < Items.Count) then Items[index] := TBoldStringFollowerControllerCom(Follower.Controller).GetCurrentAsString(Follower); Invalidate; - // forces a redisplay of the edit-area, the windows component might go blank if the active row is removed and then reinserted fHandleFollower.Follower.MarkValueOutOfDate; end; @@ -260,10 +253,8 @@ procedure TBoldCustomComboBoxCom._AfterMakeUptoDate(Follower: TBoldFollowerCom); var NewText: string; begin -// Code below removed to avoid closeup when moving in dropped down combo. suggested by Hans Karlsen -// if not (Style = csSimple) and DroppedDown then -// PostMessage(Handle, CB_SHOWDROPDOWN, 0, 0); //FIXME Bad solution! CloseUp if changed while dropped down! + UpdateEffectiveColor; UpdateEffectiveReadOnly; @@ -337,7 +328,7 @@ procedure TBoldCustomComboBoxCom.ComboWndProc(var Message: TMessage; ComboWnd: H if (Style = csSimple) and (ComboWnd <> EditHandle) then if EffectiveReadOnly then Exit; end; - fIsEditEvent := True; // Flag to know we're already in the event + fIsEditEvent := True; inherited ComboWndProc(Message, ComboWnd, ComboProc); fIsEditEvent := False; end; @@ -499,7 +490,7 @@ procedure TBoldCustomComboBoxCom.KeyPress(var Key: Char); begin if (Style <> csDropDownList) and (BoldSelectChangeAction <> bdcsSetReference) and - not BoldProperties.ValidateCharacter(Key, Follower) then + not BoldProperties.ValidateCharacter(AnsiChar(Key), Follower) then begin MessageBeep(0); Key := BOLDNULL; @@ -535,7 +526,6 @@ procedure TBoldCustomComboBoxCom.SetCharCase(const Value: TEditCharCase); begin if CharCase <> Value then begin - //FIXME Investigate and fix problems with CharCase and non readonly inherited CharCase := Value; end; end; @@ -561,7 +551,6 @@ procedure TBoldCustomComboBoxCom.SetEffectiveReadOnly(Value: Boolean); end; procedure TBoldCustomComboBoxCom.SetEffectiveText(Value: string); -// This mess is needed prevent flickering and allow changes to Text before the controls handle is allocated! /frha var I: Integer; Redraw: Boolean; @@ -612,7 +601,7 @@ procedure TBoldCustomComboBoxCom.SetFocused(Value: Boolean); procedure TBoldCustomComboBoxCom.SetFont(Value: TFont); begin FFont.Assign(Value); -end; +end; procedure TBoldCustomComboBoxCom.SetReadOnly(Value: Boolean); begin @@ -639,14 +628,14 @@ procedure TBoldCustomComboBoxCom.UpdateEffectiveColor; NewColor: TColor; begin NewColor := Color; - BoldProperties.SetColor(NewColor, Color, Follower); //FIXME FC should only take ONE color and a Follower! /frha + BoldProperties.SetColor(NewColor, Color, Follower); inherited Color := NewColor; end; procedure TBoldCustomComboBoxCom.UpdateEffectiveFont; begin EffectiveFont.Assign(Font); - BoldProperties.SetFont(EffectiveFont, Font, Follower); //FIXME FC should only take ONE font and a Follower! /frha + BoldProperties.SetFont(EffectiveFont, Font, Follower); end; procedure TBoldCustomComboBoxCom.UpdateEffectiveReadOnly; @@ -659,7 +648,6 @@ procedure TBoldCustomComboBoxCom.UpdateEffectiveReadOnly; procedure TBoldCustomComboBoxCom.WMPaint(var Message: TWMPaint); begin - //FIXME Own painting with call to renderers paint isn't done yet... inherited; end; @@ -667,9 +655,7 @@ procedure TBoldCustomComboBoxCom.WndProc(var Message: TMessage); var CallInherited: Boolean; ElementToAssignTo: IBoldElement; - {$IFNDEF BOLDCOMCLIENT} Discard: Boolean; - {$ENDIF} begin CallInherited := True; if not (csDesigning in ComponentState) then @@ -686,13 +672,13 @@ procedure TBoldCustomComboBoxCom.WndProc(var Message: TMessage); Follower.DiscardChange; if Assigned(BoldHandle) and Assigned(BoldHandle.value) then begin - {$IFDEF BOLDCOMCLIENT} // BoldSetValueExpression + {$IFDEF BOLDCOMCLIENT} if trim(BoldSetValueExpression) <> '' then ElementToAssignTo := BoldHandle.Value.EvaluateExpression(BoldSetValueExpression) else elementToAssignTo := BoldHandle.Value; if assigned(ElementToAssignTo) then - ElementToAssignTo.AssignElement(SelectedElement); // checkme take from follwer instead? + ElementToAssignTo.AssignElement(SelectedElement); {$ELSE} if trim(BoldSetValueExpression) <> '' then ElementToAssignTo := BoldHandle.Value.EvaluateExpressionAsDirectElement(BoldSetValueExpression) @@ -700,11 +686,10 @@ procedure TBoldCustomComboBoxCom.WndProc(var Message: TMessage); elementToAssignTo := BoldHandle.Value; if assigned(ElementToAssignTo) and ElementToAssignTo.Mutable and - // must check the element (and not the follower) since we might have a BoldSetValueExpression... (not (elementToAssignTo is IBoldMember) or IBoldMember(ElementTOAssignTo).CanModify) then try - ElementToAssignTo.Assign(SelectedElement); // checkme take from follwer instead? + ElementToAssignTo.Assign(SelectedElement); except on E: Exception do begin @@ -740,7 +725,6 @@ procedure TBoldCustomComboBoxCom.WndProc(var Message: TMessage); end; if assigned(OnSelectChanged) then fOnSelectChanged(Self); -// Code below removed to avoid closing dropdown, suggested by Hans Karlsen if (not CallInherited) and (Style <> csSimple) and not fIsEditEvent then @@ -757,7 +741,7 @@ procedure TBoldCustomComboBoxCom.WndProc(var Message: TMessage); CB_SHOWDROPDOWN: if (Message.WParam=0) and EffectiveReadOnly then - _AfterMakeUptoDate(Follower); {Restore text} //FIXME Maybe an UpdateEffectiveText? + _AfterMakeUptoDate(Follower); {Restore text} end; end; if CallInherited then @@ -819,7 +803,6 @@ function TBoldCustomComboBoxCom.GetContextForBoldRowProperties: IBoldElementType {$IFNDEF BOLDCOMCLIENT} function TBoldCustomComboBoxCom.ValidateComponent(ComponentValidator: TBoldComponentValidatorCom; NamePrefix: String): Boolean; begin - // We want to evaluate everything. Thus suboptimized expressions. Result := ComponentValidator.ValidateExpressionInContext( BoldProperties.Expression, GetContextForBoldProperties, @@ -847,8 +830,7 @@ function TBoldCustomComboBoxCom.ComboAllowsTextEditing( BoldProperties: TBoldStringFollowerControllerCom; Follower: TBoldFollowerCom): Boolean; begin - // this method is primarily intended for subclasses to stop editing of string-attributes - // due to bad combo configuration (needed at SVT) + result := true; end; diff --git a/Source/ClientGuiCom/BoldControls/BoldDragDropTargetCom.pas b/Source/ClientGuiCom/BoldControls/BoldDragDropTargetCom.pas index 48bd05c..9bba947 100644 --- a/Source/ClientGuiCom/BoldControls/BoldDragDropTargetCom.pas +++ b/Source/ClientGuiCom/BoldControls/BoldDragDropTargetCom.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldDragDropTargetCom; {$DEFINE BOLDCOMCLIENT} {Clientified 2002-08-05 13:13:02} @@ -7,7 +10,7 @@ interface Classes, Controls, ExtCtrls, - BoldEnvironmentVCL, // Make sure VCL environement loaded, and finalized after + BoldEnvironmentVCL, BoldComObjectSpace_TLB, BoldClientElementSupport, BoldComClient, {$IFNDEF BOLDCOMCLIENT} BoldComObjectSpace_TLB, @@ -50,8 +53,8 @@ TBoldDropTargetCom = class(TImage, IBoldOCLComponentCom) property Element: IBoldElement read GetElement; procedure Notification(AComponent: TComponent; Operation: TOperation); override; public - constructor Create(owner: TComponent); override; - destructor Destroy; override; + constructor create(owner: TComponent); override; + destructor destroy; override; procedure DoStartDrag(var DragObject: TDragObject); override; procedure DoEndDrag(Target:TObject; X, Y: Integer); override; procedure MouseDown(BUTTON: TMouseButton; Shift: TShiftState; X, Y: Integer); override; @@ -115,7 +118,7 @@ constructor TBoldDropTargetCom.create(owner: TComponent); AfterMakeUptoDate(fHandleFollower.Follower); end; -destructor TBoldDropTargetCom.Destroy; +destructor TBoldDropTargetCom.destroy; begin FreeAndNil(FHandleFollower); FreeAndNil(FRepresentations); @@ -151,12 +154,9 @@ procedure TBoldDropTargetCom.DragDrop(Source: TObject; X, Y: Integer); procedure TBoldDropTargetCom.DragOver(Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean); begin - // First set the hard accept value Accept := IsDropTarget and CanAcceptDraggedObject; - // Then, if we accept, invoke user code if Accept and Assigned(OnDragOver) then OnDragOver(Self, Source, X, Y, State, Accept); - // Make sure we only accept if hard conditions are true. Accept := Accept and IsDropTarget and CanAcceptDraggedObject; end; @@ -185,7 +185,6 @@ function TBoldDropTargetCom.GetCurrentNodeDescription: TBoldNodeDescriptionCom; begin ie := TBoldIndirectElement.create; try - // this code should move to the treeview support classes (or is it already there???) Element.EvaluateAndSubscribeToExpression(NodeSelectionExpression, fHandleFollower.Follower.Subscriber, ie); if ie.value is IBoldList then begin list := ie.value as IBoldList; diff --git a/Source/ClientGuiCom/BoldControls/BoldEditCom.pas b/Source/ClientGuiCom/BoldControls/BoldEditCom.pas index b13e7b7..7b15c30 100644 --- a/Source/ClientGuiCom/BoldControls/BoldEditCom.pas +++ b/Source/ClientGuiCom/BoldControls/BoldEditCom.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldEditCom; {$DEFINE BOLDCOMCLIENT} {Clientified 2002-08-05 13:13:02} @@ -5,20 +8,23 @@ interface uses + // VCL + Buttons, Classes, - StdCtrls, Controls, - Windows, - Messages, - Menus, Graphics, - Buttons, - BoldEnvironmentVCL, // Make sure VCL environement loaded, and finalized after - BoldControlsDefs, - BoldHandlesCom, - BoldComObjectSpace_TLB, BoldClientElementSupport, BoldComClient, + Menus, + Messages, + StdCtrls, + Windows, + + // Bold + BoldClientElementSupport, + BoldComObjectSpace_TLB, BoldControlPackCom, + BoldControlsDefs, BoldElementHandleFollowerCom, + BoldHandlesCom, BoldStringControlPackCom; type @@ -48,7 +54,7 @@ TBoldCustomEditCom = class(TCustomEdit, IBoldOCLComponentCom) procedure SetExpression(Expression: String); function GetExpression: String; function GetVariableList: IBoldExternalVariableList; - + function GetBoldHandle: TBoldElementHandleCom; procedure SetBoldHandle(value: TBoldElementHandleCom); function GetFollower: TBoldFollowerCom; @@ -99,7 +105,7 @@ TBoldCustomEditCom = class(TCustomEdit, IBoldOCLComponentCom) property BeepOnInvalidKey: boolean read fBeepOnInvalidKey write fBeepOnInvalidKey default True; property Button: TSpeedButton read GetButton; - property ButtonControl: TWinControl read fBtnControl; //NOTE Do not publish. + property ButtonControl: TWinControl read fBtnControl; property EffectiveReadOnly: Boolean read GetEffectiveReadOnly; property EffectiveFont: TFont read GetEffectiveFont; property EffectiveColor: TColor read GetEffectiveColor write SetEffectiveColor; @@ -143,20 +149,16 @@ TBoldEditCom = class(TBoldCustomEditCom) property Anchors; property AutoSelect; property AutoSize; -// property BiDiMode; property BorderStyle; property CharCase; -// property Color; property Constraints; property Ctl3D; property DragCursor; property DragKind; property DragMode; property Enabled; -// property Font; property HideSelection; -// property ImeMode; -// property ImeName; + property MaxLength; property ParentColor; property ParentCtl3D; @@ -164,11 +166,9 @@ TBoldEditCom = class(TBoldCustomEditCom) property ParentShowHint; property PasswordChar; property PopupMenu; -// property ReadOnly; property ShowHint; property TabOrder; property TabStop; -// property Text; property Visible; property OnChange; property OnClick; @@ -196,11 +196,10 @@ implementation uses BoldControlPackDefs, SysUtils, - BoldRev, - Forms, // bssingle - {$IFNDEF BOLDCOMCLIENT} // uses - BoldComObjectSpace_TLB, // For Specialized Drag/Drop in EditBox - BoldGUI, // For Specialized Drag/Drop in EditBox + Forms, + {$IFNDEF BOLDCOMCLIENT} + BoldComObjectSpace_TLB, + BoldGUI, BoldReferenceHandleCom, BoldRootedHandlesCom, {$ENDIF} @@ -272,7 +271,7 @@ procedure TBoldCustomEditCom.DoEndDrag(Target: TObject; X, Y: Integer); procedure TBoldCustomEditCom.DragOver(Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean); begin - {$IFNDEF BOLDCOMCLIENT} //dragdrop + {$IFNDEF BOLDCOMCLIENT} if (BoldProperties.DropMode = bdpReplace) and (assigned(BoldHandle)) and (not assigned(BoldHandle.Value) or (BoldHandle.Value is IBoldObject)) and @@ -291,7 +290,7 @@ procedure TBoldCustomEditCom.DragOver(Source: TObject; X, Y: Integer; State: TDr procedure TBoldCustomEditCom.DragDrop(Source: TObject; X, Y: Integer); begin - {$IFNDEF BOLDCOMCLIENT} //dragdrop + {$IFNDEF BOLDCOMCLIENT} if (BoldProperties.DropMode = bdpReplace) and (assigned(BoldHandle)) and (not assigned(BoldHandle.Value) or (BoldHandle.Value is IBoldObject)) and @@ -378,7 +377,7 @@ procedure TBoldCustomEditCom.SetEffectiveColor(v: TColor); inherited Color := v; end; -procedure TBoldCustomEditCom.SetText(value: string); //CHECKME Remove? Text is not published any longer! +procedure TBoldCustomEditCom.SetText(value: string); begin if not (csLoading in ComponentState) then if not EffectiveReadOnly then @@ -413,12 +412,12 @@ procedure TBoldCustomEditCom.KeyPress(var Key: Char); begin inherited KeyPress(Key); if (Key in [#32..#255]) and - not BoldProperties.ValidateCharacter(Key, Follower) then + not BoldProperties.ValidateCharacter(AnsiChar(Key), Follower) then begin InvalidKey(Key); Key := BOLDNULL; end - else if Key = #1 then // CTRL-A + else if Key = #1 then begin SelectAll; end @@ -665,7 +664,6 @@ procedure TBoldCustomEditCom.SetEditRect; var Loc: TRect; begin -// SendMessage(Handle, EM_GETRECT, 0, LongInt(@Loc)); Loc.Bottom := ClientHeight+1; Loc.Right := ClientWidth-1; Loc.Top := 0; @@ -684,15 +682,13 @@ procedure TBoldCustomEditCom.SetEditRect; end; procedure TBoldCustomEditCom.WMSize(var message: TWMSize); -//var -// MinHeight: Integer; + begin inherited; -// if (csDesigning in ComponentState) then -// FGrid.SetBounds(0, Height + 1, 10, 10); -// MinHeight := GetMinHeight; -// if Height < MinHeight then Height := MinHeight -// else begin + + + + if Assigned(fBtnControl) and Assigned(fButton) then SetEditRect; end; @@ -708,7 +704,6 @@ procedure TBoldCustomEditCom.SetButtonStyle(const Value: TBoldEditButtonStyle); begin if Assigned(fBtnControl) then fBtnControl.Visible := False; - //NOTE Skip destruction of button and recreation of control in runtime to eliminate flicker. if (csDesigning in ComponentState) then RecreateWnd; end @@ -747,7 +742,6 @@ procedure TBoldComboButton.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin with TBoldCustomEditCom(Parent.Parent) do - //CHECKME We may need to skip the change of focus if the popupcontrol is visible! if (Handle <> GetFocus) and CanFocus then begin SetFocus; @@ -761,8 +755,7 @@ procedure TBoldComboButton.MouseDown(Button: TMouseButton; Shift: TShiftState; procedure TBoldComboButton.MouseMove(Shift: TShiftState; X, Y: Integer); begin inherited MouseMove (Shift, X, Y); -// if (ssLeft in Shift) and (GetCapture = Parent.Handle) then -// MouseDragToGrid(Self, TDBLookupCombo(Parent.Parent).FGrid, X, Y); + end; function TBoldCustomEditCom.GetBoldHandle: TBoldElementHandleCom; @@ -800,5 +793,5 @@ function TBoldCustomEditCom.GetVariableList: IBoldExternalVariableList; end; initialization - + end. diff --git a/Source/ClientGuiCom/BoldControls/BoldGridCom.pas b/Source/ClientGuiCom/BoldControls/BoldGridCom.pas index b1e9ecc..aaa13a7 100644 --- a/Source/ClientGuiCom/BoldControls/BoldGridCom.pas +++ b/Source/ClientGuiCom/BoldControls/BoldGridCom.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldGridCom; {$DEFINE BOLDCOMCLIENT} {Clientified 2002-08-05 13:13:02} @@ -5,33 +8,31 @@ interface uses + // VCL {$IFDEF DELPHI6_OR_LATER} - Types, // IFDEF DELPHI6_OR_LATER + Types, {$ELSE} - Windows, // else-part of IFDEF DELPHI6_OR_LATER + Windows, {$ENDIF} - Messages, - Graphics, + Classes, Controls, + Graphics, Grids, Menus, - StdCtrls, - Classes, - BoldEnvironmentVCL, // Make sure VCL environement loaded, and finalized after - {$IFNDEF BOLDCOMCLIENT} // uses + + // Bold + {$IFNDEF BOLDCOMCLIENT} BoldComObjectSpace_TLB, {$ENDIF} - BoldCommonBitmaps, - BoldControlPackDefs, - BoldControlsDefs, - BoldComObjectSpace_TLB, BoldClientElementSupport, BoldComClient, BoldAbstractListHandleCom, - BoldListHandleFollowerCom, - BoldControlPackCom, + BoldComClient, + BoldComObjectSpace_TLB, + BoldComponentValidatorCom, BoldControllerListControlPackCom, + BoldControlPackCom, + BoldControlsDefs, + BoldListHandleFollowerCom, BoldListListControlPackCom, - BoldComponentValidatorCom, - BoldSubscription, BoldStringControlPackCom; type @@ -95,7 +96,6 @@ TBoldGridColumnsCom = class(TCollection) end; { TBoldColumnTitleCom } - // Borrowed from TDBGrid TBoldColumnTitleCom = class(TPersistent) private fAlignment: TAlignment; @@ -267,11 +267,9 @@ TBoldCustomGridCom = class(TCustomGrid, IBoldValidateableComponentCom) procedure SetOptions(val: TGridOptions); procedure SetSelection(aRow: Integer; Shift: TShiftState; ForceClearOfOtherRows: Boolean; IgnoreToggles: Boolean); procedure TypeMayHaveChanged; - // DRAW FUNCTIONS function CellFont(Column: TBoldGridColumnCom): TFont; function GetString(GridCol, DataRow: Integer): string; function HighlightCell(AState: TGridDrawState; aRow: integer): Boolean; - // EDIT FUNCTIONS procedure _AfterMakeCellUptoDate(Follower: TBoldFollowerCom); procedure _DeleteRow(index: Integer; owningFollower: TBoldFollowerCom); procedure _InsertRow(Follower: TBoldFollowerCom); @@ -393,7 +391,7 @@ TBoldCustomGridCom = class(TCustomGrid, IBoldValidateableComponentCom) procedure DisplayAllCells; function AsClipBoardText: String; procedure ActivateAllCells; - property ColCount;// read GetColCount; + property ColCount; property CellText[col, row: integer]: string read GetCellText; property MutableList: IBoldList read GetMutableList; end; @@ -431,7 +429,7 @@ TBoldGridCom = class(TBoldCustomGridCom) property Color; property Constraints; property Columns; - {$IFNDEF BCB} // for some reason, the below line gives an error in the generated .hpp-file + {$IFNDEF BCB} property Ctl3d; {$ENDIF} property DefaultColWidth; @@ -484,7 +482,6 @@ TBoldGridCom = class(TBoldCustomGridCom) end; { TBoldInplaceEditCom } - // Used to access Font property of InplaceEditor TBoldInplaceEditCom = class(TInplaceEdit) private {$IFNDEF BOLDCOMCLIENT} @@ -530,21 +527,23 @@ TBoldInplaceEditCom = class(TInplaceEdit) implementation uses + Messages, + StdCtrls, SysUtils, Forms, - {$IFNDEF BOLDCOMCLIENT} // uses + {$IFNDEF BOLDCOMCLIENT} {!! DO NOT REMOVE !! BoldAttributes ,} {!! DO NOT REMOVE !! BoldSystemRT ,} BoldAFP, BoldGUI, {$ENDIF} -// BoldGridRTColEditorCom - BoldEnvironment, - BoldRev, + BoldCommonBitmaps, + BoldControlPackDefs, BoldDefs, + BoldEnvironment, BoldListControlPackCom, - TypInfo, - BoldMath; + BoldMath, + TypInfo; const ColumnTitleValues = [cvTitleColor..cvTitleFont]; @@ -619,7 +618,6 @@ procedure TBoldInplaceEditCom.BoundsChanged; var R: TRect; begin - // This method replaces ancestor method, as it doesn't seem to do the right thING Assert(Assigned(Grid)); R := Rect(2, 2, TBoldCustomGridCom(Grid).Columns[TBoldCustomGridCom(Grid).Col].Width - 2, Height); SendMessage(Handle, EM_SETRECTNP, 0, LongInt(@R)); @@ -632,7 +630,6 @@ procedure TBoldInplaceEditCom.KeyPress(var Key: Char); begin inherited KeyPress(Key); Grid := TBoldCustomGridCom(Owner); - // when editing, clear all other selected rows Grid.SetSelection(grid.DataRow(grid.Row), [], true, false); if (Key in [#32..#255]) and not Grid.Columns[Grid.Col].BoldProperties.ValidateCharacter(Key, Grid.CurrentCellFollower) then @@ -774,7 +771,7 @@ procedure TBoldColumnTitleCom._FontChanged(Sender: TObject); Exclude(fColumn.fAssignedValues, cvTitleFont) else Include(fColumn.fAssignedValues, cvTitleFont); - Changed; // ??? + Changed; end; function TBoldColumnTitleCom.GetAlignment: TAlignment; @@ -937,7 +934,6 @@ constructor TBoldGridColumnCom.Create(theCollection: TCollection); end; destructor TBoldGridColumnCom.Destroy; - // CollectionItem removes itself from collection when destroyed begin if fGrid.fFixedColumn = self then fGrid.fFixedColumn := nil; @@ -955,7 +951,6 @@ destructor TBoldGridColumnCom.Destroy; procedure TBoldGridColumnCom.Assign(Source: TPersistent); -// Code mainly from DBGrids var SourceCol: TBoldGridColumnCom; begin @@ -976,12 +971,11 @@ procedure TBoldGridColumnCom.Assign(Source: TPersistent); if cvAlignment in SourceCol.AssignedValues then Alignment := SourceCol.Alignment; Title := SourceCol.Title; -// if cvReadOnly in SourceCol.AssignedValues then -// ReadOnly := SourceCol.ReadOnly; -// DropDownRows := SourceCol.DropDownRows; -// ButtonStyle := SourceCol.ButtonStyle; -// PickList := SourceCol.PickList; -// PopupMenu := SourceCol.PopupMenu; + + + + + finally if Assigned(Collection) then Collection.EndUpdate; @@ -1012,8 +1006,7 @@ procedure TBoldGridColumnCom.RestoreDefaults; FTitle.RestoreDefaults; FAssignedValues := []; RefreshDefaultFont; -// FreeAndNil(FPickList); -// ButtonStyle := cbsAuto; + Changed(FontAssigned); end; @@ -1159,7 +1152,6 @@ constructor TBoldCustomGridCom.Create(AOwner: TComponent); fBoldProperties.BeforeMakeUptoDate := _BeforeMakeListUptoDate; fBoldProperties.OnGetContextType := GetHandleStaticType; fHandleFollower := TBoldListHandleFollowerCom.Create(Owner, fBoldProperties); - // fHandleFollower.OnHandleIndexChanged := HandleIndexChanged; FColumns := CreateColumns; fAnchor := 0; Options := [goFixedVertLine, goFixedHorzLine, goVertLine, @@ -1209,7 +1201,7 @@ procedure TBoldCustomGridCom.TypeMayHaveChanged; {$ENDIF} begin if BoldEffectiveEnvironment.RunningInIDE and (not Assigned(BoldHandle.List) or (BoldHandle.List.Count = 0)) then - Exit; // only update at runtime if there are values, avoids update on every UML model change. + Exit; NewListElementType := GetHandleListElementType; if (NewListElementType <> fCurrentListElementType) then @@ -1242,12 +1234,11 @@ procedure TBoldCustomGridCom.DeleteAllColumns; Columns[ColCount - 1].Free; if columns.count = 0 then AddColumn; - // ensure column 0 EnsureOneFixedCol; end; procedure TBoldCustomGridCom.CreateDefaultColumns; -{$IFNDEF BOLDCOMCLIENT} // defaultcolumns +{$IFNDEF BOLDCOMCLIENT} var i: integer; ListElementType: IBoldElementTypeInfo; @@ -1266,7 +1257,7 @@ procedure TBoldCustomGridCom.CreateDefaultColumns; {$ENDIF} begin - {$IFNDEF BOLDCOMCLIENT} // defaultcolumns + {$IFNDEF BOLDCOMCLIENT} ListElementType := GetHandleListElementType; DeleteAllColumns; UsedFirstCol := false; @@ -1370,7 +1361,6 @@ procedure TBoldCustomGridCom.ColumnMoved(FromIndex, ToIndex: Longint); begin Columns.MoveColumn(FromIndex, ToIndex); inherited ColumnMoved(FromIndex, ToIndex); - // Redraw affected columns for Col := MinIntValue([FromIndex, ToIndex]) to MaxIntValue([FromIndex, ToIndex]) do Columns.Update(Columns[Col]); end; @@ -1406,21 +1396,17 @@ procedure TBoldCustomGridCom.EnsureOneFixedCol; not fIsEnsuringFixedCol then begin fIsEnsuringFixedCol := true; - // there must be atleast one column more than the fixed column while Columns.Count < 2 do if not FirstIsOK then Columns.Insert(0) else Columns.Add; - - // see if the existing first column can be used as our fixed column... if not FirstIsOk then Columns.Insert(0); fFixedColumn := Columns[0]; - // make this column the fixed column. fFixedColumn.BoldProperties.Expression := ''; - fFixedColumn.Title.Caption := ''; // Clear the title + fFixedColumn.Title.Caption := ''; fFixedColumn.Color := Self.FixedColor; if not (csDesigning in componentstate) then fFixedColumn.BoldProperties.Renderer := fFirstColumnRenderer; @@ -1460,13 +1446,11 @@ function TBoldCustomGridCom.CreateEditor: TInplaceEdit; end; procedure TBoldCustomGridCom.EditStop; - // Same as OnExit for each cell var CellFollower: TBoldFollowerCom; begin CellFollower := CurrentCellFollower; - // if the grid is changed under our feet (for example because it is sorted, and we just changed the sort order) - // then ignore the edit stop + if assigned(CellFollower) and (CellFollower.Controller.ApplyPolicy = bapExit) then CellFollower.Apply; @@ -1486,9 +1470,8 @@ function TBoldCustomGridCom.GetEditText(GridCol, GridRow: Longint): string; end; procedure TBoldCustomGridCom.SetEditText(GridCol, GridRow: Longint; const Value: string); - // called for each change == OnChange begin - if not (csDesigning in ComponentState) and Editormode and assigned(CurrentCellFollower) then // CHECKME heeded? + if not (csDesigning in ComponentState) and Editormode and assigned(CurrentCellFollower) then TBoldStringFollowerControllerCom(CurrentCellFollower.Controller).MayHaveChanged(Value, CurrentCellFollower) end; @@ -1510,7 +1493,7 @@ procedure TBoldCustomGridCom.DblClick; else if BoldProperties.DefaultDblClick and Assigned(CurrentBoldElement) then begin - {$IFDEF BOLDCOMCLIENT} // autoform + {$IFDEF BOLDCOMCLIENT} AutoForm := nil; {$ELSE} AutoForm := AutoFormProviderRegistry.FormForElement(CurrentBoldElement); @@ -1586,8 +1569,6 @@ procedure TBoldCustomGridCom.SetSelection(aRow: Integer; Shift: TShiftState; For Exit; fIsMultiSelecting := MultiSelect and ((ssShift in Shift) or (ssCtrl in Shift)); - - // Clear previous selection, Select one item if not ((ssShift in Shift) or (ssCtrl in Shift)) or not MultiSelect then begin if (not Follower.SubFollowers[aRow].Selected) or ForceClearOfOtherRows then @@ -1596,22 +1577,15 @@ procedure TBoldCustomGridCom.SetSelection(aRow: Integer; Shift: TShiftState; For fBoldProperties.SetSelected(Follower, aRow, True); end; end; - - // Select range from first selected item if (ssShift in Shift) and MultiSelect then begin fBoldProperties.SelectRange(Follower, aRow); end; - - - // Toggle selection on current item if (ssCtrl in Shift) and MultiSelect and (not IgnoreToggles) then begin fBoldProperties.ToggleSelected(Follower, aRow); end; - // At this point we would rather have invalidated col 0, - // but that does not yield desired redraw WHEN THE GRID SCROLLS. Invalidate; AdjustActiveRange; @@ -1700,9 +1674,8 @@ function TBoldCustomGridCom.DefaultTitlePopup(Col: Integer): TPopupMenu; M.Caption := '&Close Popup'; M.name := '__mnuBoldGridCancel'; Items.Add(M); - // Additional possibilities: - // M := nil; - // * Alignment + + end; end; Result := TheDefaultTitlePopup; @@ -1753,11 +1726,10 @@ procedure TBoldCustomGridCom.MouseUp(BUTTON: TMouseButton; Shift: TShiftState; X if (Button = mbLeft) then begin if not fIsDragging then - SetSelection(DataRow(Row), Shift, true, false) // Call setselection with currentrow and shiftstate + SetSelection(DataRow(Row), Shift, true, false) else begin - // starting a drag on a nonselected row with ctrl pressed should select the row - // odd behaviour cuases VCL to clear the shiftstate when we expect a ssCTRL, so we check the MouseDownstate instead + if not selected[DataRow(Row)] and (ssCtrl in fLastMouseDownShiftState) then SetSelection(DataRow(Row), fLastMouseDownShiftState, true, false) end; @@ -1793,14 +1765,13 @@ procedure TBoldCustomGridCom.MouseDown(BUTTON: TMouseButton; Shift: TShiftState; {$ENDIF} inherited; - // Top Left cell marks all rows - // FIXME FIXEDROW handling + if (fLastMouseDownGridCoord.y <> -1) and (fLastMouseDownGridCoord.Y = TitleRow) then begin if fLastMouseDownGridCoord.X = Pred(FixedCols) then begin fBoldProperties.SelectAll(Follower, True); - ReallyInvalidateCol(Pred(FixedCols)); // FIXME InvalidateCol doesn't invalidate last when scrolling + ReallyInvalidateCol(Pred(FixedCols)); AdjustActiveRange; end else @@ -1810,17 +1781,15 @@ procedure TBoldCustomGridCom.MouseDown(BUTTON: TMouseButton; Shift: TShiftState; fLastMouseDownScreenCoord := Point(-1, -1); end; end - else //mark clicked row + else begin - if (Button = mbLeft) and (fLastMouseDownGridCoord.Y >= FixedRows) then // if clicking outside datacells, y is -1 + if (Button = mbLeft) and (fLastMouseDownGridCoord.Y >= FixedRows) then begin Row := fLastMouseDownGridCoord.Y; - // if the click is in column 0 and it is already selected, don't reselect anything if not ((fLastMouseDownGridCoord.x = pred(FixedCols)) and Selected[fLastMouseDownGridCoord.y]) then - SetSelection(DataRow(Row), Shift, false, true) // SetSelection Invalidates entire grid + SetSelection(DataRow(Row), Shift, false, true) end; end; - // drag if on col 0 if (Button = mbLeft) and (fLastMouseDownGridCoord.X = Pred(FixedCols)) then begin try @@ -1846,20 +1815,22 @@ procedure TBoldCustomGridCom.KeyDown(var KEY: Word; Shift: TShiftState); if (Key = VK_DELETE) and (Shift = []) then begin - ShowEditor; - InplaceEditor.Text := ''; - SetEditText(Col, Row, ''); + if (goEditing in Options) and not (BoldHandle.List.Count = 0) then begin + ShowEditor; + InplaceEditor.Text := ''; + SetEditText(Col, Row, ''); + end; end; - + if (Row = RowCount - 1) and (KEY = 40) then {40 = KeyDown} begin if AddNewAtEnd and (fBoldProperties.NilElementMode<>neAddLast) then begin BoldHandle.List.AddNew; - Follower.EnsureDisplayable; // Force control to get in sync with Object Layer + Follower.EnsureDisplayable; end else - KEY := 0; // Avoid walking below last row + KEY := 0; end; {$IFNDEF BOLDCOMCLIENT} if not (Key in RowMovementKeys) and not (Key in [VK_LEFT, VK_RIGHT]) and ColumnIsCheckBox(Col) then @@ -1871,13 +1842,12 @@ procedure TBoldCustomGridCom.KeyDown(var KEY: Word; Shift: TShiftState); procedure TBoldCustomGridCom.KeyUp(var KEY: Word; Shift: TShiftState); begin - if KEY in [33..40] then //PGUP..DOWN + if KEY in [33..40] then begin - //FIXME: It *is* possible to make non-consecutive selections with keyboard. - // I think the algorithm has to be rewritten to accommodate this. - // Also: Check how Delphi/Windows implements keyboard selections (keys/combinations) - Exclude(Shift, ssCtrl); // Cannot make non-consecutive selections with keyboard - SetSelection(DataRow(Row), Shift, true, true); // Call setselection with currentrow and shiftstate + + + Exclude(Shift, ssCtrl); + SetSelection(DataRow(Row), Shift, true, true); end; inherited; end; @@ -1889,7 +1859,6 @@ function TBoldCustomGridCom.GetString(GridCol, DataRow: Integer): string; else begin EnsureRowActive(DataRow); - // if a cell's controller has not be created yet then you'll get an AV (ex: setting the CWAdjust flag) if Assigned(CellFollowers[GridCol, DataRow]) and Assigned(CellFollowers[GridCol, DataRow].Controller) then Result := TBoldStringFollowerControllerCom(CellFollowers[GridCol, DataRow].Controller).GetCurrentAsString(CellFollowers[GridCol, DataRow]); end; @@ -1942,9 +1911,8 @@ procedure TBoldCustomGridCom.AdjustCol(Col: Integer); procedure TBoldCustomGridCom.ColWidthsChanged; begin inherited; - // By including TopLeftChanged, [caAllowGrow, caAllowShrink] - // effectively freezes the column width - // TopLeftChanged; + + end; function TBoldCustomGridCom.CanEditAcceptKey(KEY: Char): Boolean; @@ -1966,7 +1934,6 @@ function TBoldCustomGridCom.CanEditShow: Boolean; begin Result := (inherited CanEditShow) and Assigned(CurrentCellFollower) and not Columns[Col].ColReadOnly; - // editable if we have a write-allowing renderer or a lookup-handle result := result and (CurrentCellFollower.RendererData.MayModify {$IFNDEF BOLDCOMCLIENT} or assigned(Columns[Col].LookupHandle) @@ -2004,8 +1971,7 @@ procedure TBoldCustomGridCom.DrawCell(ACol, aRow: Longint; ARect: TRect; AState: FrameFlags1, FrameFlags2: DWORD; begin -// if (csDesigning in ComponentState) and (aRow > 0) then -// Exit; //FIXME Removed to test Grids in designtime + aListRow := DataRow(aRow); if (ACol > Columns.Count - 1) then @@ -2037,7 +2003,7 @@ procedure TBoldCustomGridCom.DrawCell(ACol, aRow: Longint; ARect: TRect; AState: begin if (aRow = TitleRow) then {Title row} begin - if Assigned(DrawColumn.Title) then // Attempts to redraw before column is done creating + if Assigned(DrawColumn.Title) then begin Font.Assign(DrawColumn.Title.Font); Align := DrawColumn.Title.Alignment; @@ -2049,7 +2015,6 @@ procedure TBoldCustomGridCom.DrawCell(ACol, aRow: Longint; ARect: TRect; AState: begin with Columns[ACol].BoldProperties do begin - // Render font and color SetFont(Canvas.Font, CellFont(DrawColumn), CellFollowers[ACol, aListRow]); SetColor(cl, DrawColumn.Color, CellFollowers[ACol, aListRow]) end; @@ -2127,8 +2092,8 @@ procedure TBoldCustomGridCom._DeleteRow(index: Integer; owningFollower: TBoldFol procedure TBoldCustomGridCom.SetCurrentRow(DataRow: Integer); begin - Row := GridRow(MaxIntValue([0, DataRow])); // Need to make sure we never focus on row 0 - ReallyInvalidateCol(0); // Need to redraw first column FIXME let renderer to this too + Row := GridRow(MaxIntValue([0, DataRow])); + ReallyInvalidateCol(0); end; function TBoldCustomGridCom.GetRowFollower(DataRow: Integer): TBoldFollowerCom; @@ -2180,12 +2145,9 @@ procedure TBoldCustomGridCom._AfterMakeListUptoDate(Follower: TBoldFollowerCom); RowCount := FixedRows + 1 else RowCount := Follower.SubFollowerCount + FixedRows; - - // if exactly one row has been inserted, then select it. if AutoSelectNewRows and (fSubFollowerCountBeforeMakeUpToDate = Follower.SubFollowerCount - 1) then begin - // perhaps this is a bit overkill, but it works. anyone with a better suggestion? BoldHandle.CurrentIndex := fLastInsertedRowIndex; Follower.CurrentIndex := fLastInsertedRowIndex; SetCurrentRow(Follower.CurrentIndex); @@ -2207,8 +2169,6 @@ procedure TBoldCustomGridCom._AfterMakeListUptoDate(Follower: TBoldFollowerCom); AdjustActiveRange; if fInvalidateFrom <> MAXINT then InvalidateFromRow(fInvalidateFrom); - - // setting the currentRow will reset the LeftCol if GridRow(Follower.CurrentIndex) < RowCount then begin OldLeftCol := LeftCol; @@ -2242,7 +2202,7 @@ function TBoldCustomGridCom.GetFollower: TBoldFollowerCom; procedure TBoldCustomGridCom._BeforeMakeListUpToDate(Follower: TBoldFollowerCom); begin - TypeMayHaveChanged; // IMPROVEME, subscribe to listidentitychanged instead. + TypeMayHaveChanged; fMakingListUpToDate := True; AdjustActiveRange; fInvalidateFrom := MAXINT; @@ -2311,8 +2271,7 @@ function TBoldInplaceEditCom.GetDestElement(CellFollower: TBoldFollowerCom; Colu result := nil; if assigned(cellFollower) and assigned(CellFollower.Element) then begin - // if the event is active, then return the element in the grid, otherwise - // see if we get any useful element from the cell. + if assigned(Column.OnLookupChange) then result := CellFollower.Element else @@ -2466,14 +2425,11 @@ procedure TBoldCustomGridCom._FontChanged(Sender: TObject); end; function TBoldCustomGridCom.GetEditLimit: Integer; -{$IFNDEF BOLDCOMCLIENT} var El: IBoldElement; -{$ENDIF} begin result := 0; {$IFNDEF BOLDCOMCLIENT} - // set the maxlength of the editor; El := TBoldInplaceEditCom(InplaceEditor).GetDestElement(CurrentCellFollower, Columns[Col]); if (el is TBAString) and assigned((el as TBAString).BoldAttributeRTInfo) then Result := (el as TBAString).BoldAttributeRTInfo.Length; @@ -2564,7 +2520,6 @@ procedure TBoldGridCheckBoxPainterRenderer.CheckBoxClick(BUTTON: TMouseButton; S begin GridCoord := GRid.MouseCoord(X, Y); CellRect.Left := 0; - // sum the column widths of the fixed cols and then the visible cols. for i := 0 to Grid.FixedCols - 1 do CellRect.Left := CellRect.Left + Grid.Columns[i].Width + Grid.GridLineWidth; for i := GRid.LeftCol to GridCoord.x - 1 do @@ -2783,7 +2738,7 @@ procedure TBoldGridColumnCom.SetIndex(Value: Integer); begin fGrid.fBoldColumnsProperties.Move(index, value); inherited; - fGrid.Invalidate; // Fixes a bug in Borland grid to invalidate col that does not handle scrolled grids + fGrid.Invalidate; end; procedure TBoldCustomGridCom.ReallyInvalidateCol(Column: integer); @@ -2923,7 +2878,6 @@ function TBoldCustomGridCom.AsClipBoardText: String; var Col, Row: integer; begin - // as the grid is optimizing the active followers, we need to activate them manually ActivateAllCells; Result := ''; for row := 0 to RowCount - 1 do @@ -2975,13 +2929,11 @@ function TBoldGridColumnCom.ColumnHasCheckBoxOverrides: Boolean; function TBoldGridColumnCom.GetCurrentCheckBoxState( Follower: TBoldFollowerCom): TCheckBoxState; begin - // will only be called if ColumnHasCheckBoxOverrides returns true result := cbGrayed; end; procedure TBoldGridColumnCom.SetCurrentCheckBoxState(Follower: TBoldFollowerCom; NewValue: TCheckBoxState); begin - // will only be called if ColumnHasCheckBoxOverrides returns true end; function TBoldGridColumnCom.GetLookupContext: IBoldElementTypeInfo; @@ -3043,7 +2995,6 @@ procedure TBoldCustomGridCom.GetActiveRange(var FirstActive, LastActive: integer begin firstActive := DataRow(TopRow) - 1; LastActive := DataRow(TopRow + VisibleRowCount) + 1; - // extend range to include all selected elements for i := 0 to FirstActive - 1 do if Selected[i] then begin @@ -3073,7 +3024,6 @@ procedure TBoldCustomGridCom.EnsureRowActive(DataRow: integer); else if DataRow > LastActive then LastActive := DataRow; BoldProperties.SetActiveRange(Follower, firstActive, lastActive, 10); - // this can fail if the FollowerHandle is invalid... Follower.EnsureDisplayable; end; end; @@ -3097,7 +3047,7 @@ procedure TBoldCustomGridCom.DisplayAllCells; BoldProperties.SelectAll(Follower, true); Invalidate; AdjustActiveRange; - EnsureActiveCellFollowerExpressions; {TODO: Remove? AdjustActiveRange already calls this method, why call it again??} + EnsureActiveCellFollowerExpressions; Follower.EnsureDisplayable; BoldProperties.SelectAll(Follower, false); BoldProperties.SetSelected(Follower, DataRow(Row), true); @@ -3120,6 +3070,3 @@ procedure TBoldCustomGridCom.EnsureActiveCellFollowerExpressions; initialization end. - - - diff --git a/Source/ClientGuiCom/BoldControls/BoldGridRTColEditorCom.pas b/Source/ClientGuiCom/BoldControls/BoldGridRTColEditorCom.pas index 99a58c3..355db34 100644 --- a/Source/ClientGuiCom/BoldControls/BoldGridRTColEditorCom.pas +++ b/Source/ClientGuiCom/BoldControls/BoldGridRTColEditorCom.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldGridRTColEditorCom; {$DEFINE BOLDCOMCLIENT} {Clientified 2002-08-05 13:13:02} @@ -12,7 +15,7 @@ interface Classes, BoldDefs, BoldGridCom, - {$IFNDEF BOLDCOMCLIENT} // uses + {$IFNDEF BOLDCOMCLIENT} BoldOclPropEditor, {$ENDIF} {!! DO NOT REMOVE !! BoldSystemRT ,} @@ -69,7 +72,6 @@ implementation uses SysUtils, - BoldRev, BoldUtils; {$R *.dfm} @@ -192,12 +194,12 @@ procedure TfrmRTColEditorCom.cmdDeleteColumnClick(Sender: TObject); procedure TfrmRTColEditorCom.PropertyKeyPress(Sender: TObject; var Key: Char); begin if not Assigned(CurrentGridColumn) then - Key := BOLDNULL; + Key := BOLDNULL; end; procedure TfrmRTColEditorCom.cmdOCLEditorClick(Sender: TObject); begin - {$IFNDEF BOLDCOMCLIENT} // ocleditor + {$IFNDEF BOLDCOMCLIENT} with TBoldOCLPropEditForm.Create(nil) do try Context := EGrid.GetHandleListElementType; diff --git a/Source/ClientGuiCom/BoldControls/BoldImageBitmapCom.pas b/Source/ClientGuiCom/BoldControls/BoldImageBitmapCom.pas index df54f88..6ab0fb4 100644 --- a/Source/ClientGuiCom/BoldControls/BoldImageBitmapCom.pas +++ b/Source/ClientGuiCom/BoldControls/BoldImageBitmapCom.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldImageBitmapCom; {$DEFINE BOLDCOMCLIENT} {Clientified 2002-08-05 13:13:02} @@ -5,7 +8,7 @@ interface uses - Windows, // Delphi Units + Windows, Classes, Graphics, Clipbrd, @@ -29,7 +32,7 @@ TBoldViewBitmapAdapterCom = class(TBoldAbstractViewAdapterCom) function HasChanged: Boolean; override; class function CanReadContent(const ContentType: string): Boolean; override; function ContentType: string; override; - class function Description: string; override; // How to handle Localizastion? + class function Description: string; override; {Clipboard} procedure CopyToClipboard; override; class function CanPasteFromClipboard(const AcceptedContentType: string): Boolean; override; @@ -39,7 +42,7 @@ TBoldViewBitmapAdapterCom = class(TBoldAbstractViewAdapterCom) procedure SaveToStream(Stream: TStream); override; {Files} class function DefaultExtension: string; override; - class function FileFilter: string; override; // How to handle Localizastion? + class function FileFilter: string; override; class function CanLoadFromFile(const Filename: string): Boolean; override; procedure LoadFromFile(const Filename: string); override; procedure SaveToFile(const Filename: string); override; @@ -230,5 +233,5 @@ function TBoldViewBitmapAdapterCom.Height: Integer; initialization TBoldViewBitmapAdapterCom.RegisterViewAdapter(TBoldViewBitmapAdapterCom); - + end. diff --git a/Source/ClientGuiCom/BoldControls/BoldImageCom.pas b/Source/ClientGuiCom/BoldControls/BoldImageCom.pas index 6c4888b..fc0424e 100644 --- a/Source/ClientGuiCom/BoldControls/BoldImageCom.pas +++ b/Source/ClientGuiCom/BoldControls/BoldImageCom.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldImageCom; {$DEFINE BOLDCOMCLIENT} {Clientified 2002-08-05 13:13:02} @@ -10,8 +13,8 @@ interface Classes, Graphics, Controls, - Forms, // TBorderStyle - BoldEnvironmentVCL, // Make sure VCL environement loaded, and finalized after + Forms, + BoldEnvironmentVCL, BoldControlsDefs, BoldHandlesCom, BoldElementHandleFollowerCom, @@ -38,7 +41,7 @@ TBoldImageCom = class(TCustomControl, IBoldOCLComponentCom) fQuickDraw: Boolean; fScale: Double; fDisplayRect: TRect; - FOnResize: TNotifyEvent; + FOnResize: TNotifyEvent; function GetContextType: IBoldElementTypeInfo; procedure SetExpression(Expression: String); function GetExpression: String; @@ -95,7 +98,6 @@ TBoldImageCom = class(TCustomControl, IBoldOCLComponentCom) property Scale: Integer read GetScale write SetScale default 100; property Center: Boolean read fCenter write fCenter; property QuickDraw: Boolean read fQuickDraw write fQuickDraw; -// property ContentType: string //Use this property to specify property BorderStyle: TBorderStyle read FBorderStyle write SetBorderStyle default bsSingle; property OnResize: TNotifyEvent read FOnResize write FOnResize; {Standard properties} @@ -138,7 +140,6 @@ implementation uses SysUtils, - BoldRev, BoldDefs, BoldControlPackDefs; @@ -205,7 +206,6 @@ function TBoldImageCom.GetViewer: TBoldAbstractViewAdapterCom; procedure TBoldImageCom.SetViewer(Value: TBoldAbstractViewAdapterCom); begin fBoldProperties.MayHaveChanged(Value, Follower); -// Invalidate; end; procedure TBoldImageCom.SetBorderStyle(Value: TBorderStyle); @@ -314,12 +314,10 @@ procedure TBoldImageCom.WMSize(var Message: TMessage); procedure TBoldImageCom.CMTextChanged(var Message: TMessage); begin inherited; -// FIXME Invalidate to redraw Caption when there is no picture end; procedure TBoldImageCom.WMEraseBkgnd(var Message: TWMEraseBkgnd); begin -//Ignore erase background to prevent flicker end; {} @@ -447,7 +445,7 @@ procedure TBoldImageCom.Paint; if (csDesigning in ComponentState) then S := '(' + Name + ')' else - S := ''; //FIXME Some text in runtime? + S := ''; Size := TextExtent(S); R := ClientRect; TextRect(R, (R.Right - Size.cx) div 2, (R.Bottom - Size.cy) div 2, S); @@ -536,8 +534,7 @@ procedure TBoldImageCom.PasteFromClipboard; aViewer: TBoldAbstractViewAdapterCom; function GetViewer: TBoldAbstractViewAdapterCom; - // FixMe: Could be a classmethod on TBoldAbstractViewAdapterCom - // reuse in method above aswell /JoHo + var I: Integer; begin diff --git a/Source/ClientGuiCom/BoldControls/BoldImageJPEGCom.pas b/Source/ClientGuiCom/BoldControls/BoldImageJPEGCom.pas index bc0de2b..895068a 100644 --- a/Source/ClientGuiCom/BoldControls/BoldImageJPEGCom.pas +++ b/Source/ClientGuiCom/BoldControls/BoldImageJPEGCom.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldImageJPEGCom; {$DEFINE BOLDCOMCLIENT} {Clientified 2002-08-05 13:13:02} @@ -30,7 +33,7 @@ TBoldViewJPEGAdapterCom = class(TBoldAbstractViewAdapterCom) function HasChanged: Boolean; override; class function CanReadContent(const ContentType: string): Boolean; override; function ContentType: string; override; - class function Description: string; override; // How to handle Localizastion? + class function Description: string; override; {Clipboard} procedure CopyToClipboard; override; class function CanPasteFromClipboard(const AcceptedContentType: string): Boolean; override; @@ -40,7 +43,7 @@ TBoldViewJPEGAdapterCom = class(TBoldAbstractViewAdapterCom) procedure SaveToStream(Stream: TStream); override; {Files} class function DefaultExtension: string; override; - class function FileFilter: string; override; // How to handle Localizastion? + class function FileFilter: string; override; class function CanLoadFromFile(const Filename: string): Boolean; override; procedure LoadFromFile(const Filename: string); override; procedure SaveToFile(const Filename: string); override; @@ -135,7 +138,7 @@ class function TBoldViewJPEGAdapterCom.CanPasteFromClipboard(const AcceptedConte type THack = class(TJPEGImage) - end; //FIX to access NewBitmap so LoadFromClipboardFormat does not return an exception. + end; procedure TBoldViewJPEGAdapterCom.PasteFromClipboard; var diff --git a/Source/ClientGuiCom/BoldControls/BoldLabelCom.pas b/Source/ClientGuiCom/BoldControls/BoldLabelCom.pas index a4ed459..c0a6dd1 100644 --- a/Source/ClientGuiCom/BoldControls/BoldLabelCom.pas +++ b/Source/ClientGuiCom/BoldControls/BoldLabelCom.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldLabelCom; {$DEFINE BOLDCOMCLIENT} {Clientified 2002-08-05 13:13:02} @@ -5,17 +8,20 @@ interface uses - Messages, + // VCL Classes, - Graphics, Controls, + Graphics, + Messages, StdCtrls, - BoldEnvironmentVCL, // Make sure VCL environement loaded, and finalized after - BoldHandlesCom, + + // Bold + BoldClientElementSupport, + BoldComObjectSpace_TLB, BoldControlPackCom, - BoldComObjectSpace_TLB, BoldClientElementSupport, BoldComClient, - BoldStringControlPackCom, - BoldElementHandleFollowerCom; + BoldElementHandleFollowerCom, + BoldHandlesCom, + BoldStringControlPackCom; type {Forward declaration of classes} @@ -121,7 +127,6 @@ implementation uses SysUtils, - BoldRev, BoldControlPackDefs; type @@ -139,7 +144,7 @@ constructor TBoldCustomLabelCom.Create(AOwner: TComponent); fMyFont.OnChange := _FontChanged; fMyColor := EffectiveColor; if (csDesigning in ComponentState) then - ParentColor := True; //CHECKME This should not be necesary... + ParentColor := True; end; destructor TBoldCustomLabelCom.Destroy; @@ -237,7 +242,6 @@ procedure TBoldCustomLabelCom.AfterMakeUptoDate(Follower: TBoldFollowerCom); begin if (csDesigning in ComponentState) then begin - // caption during design-time with BoldProperties do if Assigned(Renderer) then NewText := Format('%s.%s', [Renderer.name, Expression]) @@ -247,7 +251,6 @@ procedure TBoldCustomLabelCom.AfterMakeUptoDate(Follower: TBoldFollowerCom); NewText := name; end else - // Caption at run-time newText := BoldProperties.GetCurrentAsString(Follower); if Text <> newText then @@ -257,7 +260,7 @@ procedure TBoldCustomLabelCom.AfterMakeUptoDate(Follower: TBoldFollowerCom); ec := EffectiveColor; BoldProperties.SetColor(ec, Color, Follower); EffectiveColor := ec; -end; +end; function TBoldCustomLabelCom.GetText: TCaption; begin @@ -327,4 +330,3 @@ procedure TBoldCustomLabelCom.DragDrop(Source: TObject; X, Y: Integer); initialization end. - diff --git a/Source/ClientGuiCom/BoldControls/BoldListBoxCom.pas b/Source/ClientGuiCom/BoldControls/BoldListBoxCom.pas index 5f6d80a..209777b 100644 --- a/Source/ClientGuiCom/BoldControls/BoldListBoxCom.pas +++ b/Source/ClientGuiCom/BoldControls/BoldListBoxCom.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldListBoxCom; {$DEFINE BOLDCOMCLIENT} {Clientified 2002-08-05 13:13:02} @@ -5,28 +8,28 @@ interface uses + // VCL Classes, - StdCtrls, Controls, - Windows, - Menus, Graphics, + Menus, Messages, - BoldEnvironmentVCL, // Make sure VCL environement loaded, and finalized after - BoldComObjectSpace_TLB, BoldClientElementSupport, BoldComClient, - {$IFNDEF BOLDCOMCLIENT} // uses + StdCtrls, + Windows, + + // Bold + {$IFNDEF BOLDCOMCLIENT} BoldComObjectSpace_TLB, BoldAFP, {$ENDIF} BoldAbstractListHandleCom, + BoldClientElementSupport, + BoldComObjectSpace_TLB, BoldControlPackCom, BoldListHandleFollowerCom, BoldListListControlPackCom, BoldStringControlPackCom; -// CHECKME is a destroywind needed that saves the extra list. -// when is DestroyWnd actually called. - type {Forward declarations of all classes} TBoldCustomListBoxCom = class; @@ -173,9 +176,8 @@ implementation uses SysUtils, Forms, - BoldRev, - {$IFNDEF BOLDCOMCLIENT} // uses - BoldGui, // IFNDEF BOLDCOMCLIENT + {$IFNDEF BOLDCOMCLIENT} + BoldGui, {$ENDIF} BoldControlPackDefs, BoldListControlPackCom; @@ -210,7 +212,6 @@ destructor TBoldCustomListBoxCom.Destroy; procedure TBoldCustomListBoxCom._BeforeMakeUptoDate(Follower: TBoldFollowerCom); begin - // Will fetch all if assigned(BoldHandle) and assigned(Boldhandle.list) then BoldHandle.list.EnsureRange(0, BoldHandle.list.Count-1); Items.BeginUpdate; @@ -231,7 +232,6 @@ procedure TBoldCustomListBoxCom.SetAlignment(Value: TAlignment); if Value <> FAlignment then begin FAlignment := Value; - // Enough to invalidate drawing surface Invalidate; end; end; @@ -249,7 +249,7 @@ function TBoldCustomListBoxCom.GetItemIndex: Integer; procedure TBoldCustomListBoxCom.SetItemIndex(Value: Integer); begin fHandleFollower.SetFollowerIndex(value); - inherited ItemIndex := Value; // FIXME; + inherited ItemIndex := Value; end; procedure TBoldCustomListBoxCom.SetBoldProperties(Value: TBoldListAsFollowerListControllerCom); @@ -274,18 +274,13 @@ procedure TBoldCustomListBoxCom.SetSelection(aRow: Integer; Shift: TShiftState); begin if aRow = -1 then Exit; - // Clear previous selection, Select one item if not ((ssShift in Shift) or (ssCtrl in Shift)) or not MultiSelect then begin fBoldProperties.SelectAll(Follower, False); fBoldProperties.SetSelected(Follower, aRow, True); end; - - // Select range from first selected item if (ssShift in Shift) and MultiSelect then fBoldProperties.SelectRange(Follower, aRow); - - // Toggle selection on current item if (ssCtrl in Shift) and MultiSelect then fBoldProperties.ToggleSelected(Follower, aRow); Invalidate; @@ -311,7 +306,7 @@ procedure TBoldCustomListBoxCom.DblClick; inherited else if BoldProperties.DefaultDblClick and Assigned(CurrentBoldElement) then begin - {$IFDEF BOLDCOMCLIENT} // autoform + {$IFDEF BOLDCOMCLIENT} Autoform := nil; {$ELSE} AutoForm := AutoFormProviderRegistry.FormForElement(CurrentBoldElement); @@ -371,7 +366,6 @@ function TBoldCustomListBoxCom.GetCurrentBoldElement: IBoldElement; function TBoldCustomListBoxCom.GetBoldList: IBoldList; begin - //CHECKME We may have to remove this because the list is not necessarily equal with the rendered list!!! /FH if Assigned(BoldHandle) then Result := BoldHandle.List else @@ -394,11 +388,10 @@ procedure TBoldCustomListBoxCom._RowAfterMakeUptoDate(Follower: TBoldFollowerCom var index: Integer; begin -// This shouldn't be needed... -// if Assigned(BoldHandle) then -// inherited ItemIndex := BoldHandle.CurrentIndex; + + index := Follower.index; - if (index > -1) and (index < Items.Count) then //FIXME: How come index sometimes is > Items.Count? + if (index > -1) and (index < Items.Count) then Items[index] := TBoldStringFollowerControllerCom(Follower.Controller).GetCurrentAsString(Follower); end; @@ -428,10 +421,10 @@ function TBoldCustomListBoxCom.GetSelectedCount: Integer; I: Integer; begin Result := 0; - if MultiSelect then // if not MultiSelect SelCount is always -1! + if MultiSelect then Result := SelCount else - for I := 0 to Items.Count - 1 do // Set result to 1 if something is selected + for I := 0 to Items.Count - 1 do if Selected[I] then begin Result := 1; @@ -441,10 +434,10 @@ function TBoldCustomListBoxCom.GetSelectedCount: Integer; procedure TBoldCustomListBoxCom.KeyUp(var Key: Word; Shift: TShiftState); begin - if Key in [33..40] then //PGUP..DOWN + if Key in [33..40] then begin - Exclude(Shift, ssCtrl); // Cannot make non-consecutive selections with keyboard - SetSelection(ItemIndex, Shift); // Call setselection with currentrow and shiftstate + Exclude(Shift, ssCtrl); + SetSelection(ItemIndex, Shift); end; inherited; end; @@ -452,7 +445,7 @@ procedure TBoldCustomListBoxCom.KeyUp(var Key: Word; Shift: TShiftState); procedure TBoldCustomListBoxCom.CNDrawItem(var Message: TWMDrawItem); var State: TOwnerDrawState; - SignedItemId: integer; // this variable is used to suppress warning from D4 when comparing signed and unsigned values + SignedItemId: integer; begin with Message.DrawItemStruct^ do begin @@ -465,7 +458,6 @@ procedure TBoldCustomListBoxCom.CNDrawItem(var Message: TWMDrawItem); SignedItemId := -1; end; if Assigned(BoldHandle) and (SigneditemID = Follower.CurrentIndex) then - //FIXME Apperens of selected and current... Canvas.DrawFocusRect(rcItem); end; end; @@ -478,7 +470,6 @@ procedure TBoldCustomListBoxCom.DefaultSetFontAndColor(index: Integer); BoldRowProperties.SetFont(Canvas.Font, Font, Follower.SubFollowers[index]); BoldRowProperties.SetColor(ec, Color, Follower.SubFollowers[index]); Canvas.Brush.Color := ec; - // Selected state yields default highlight colors SubFollower := Follower.SubFollowers[index]; if assigned(Subfollower) and Subfollower.Selected then with Canvas do @@ -498,9 +489,7 @@ procedure TBoldCustomListBoxCom.MeasureItem(index: Integer; var Height: Integer) var S: string; begin - // Need to get the font to use BoldRowProperties.SetFont(Canvas.Font, Font, Follower.SubFollowers[index]); - // And measure using current data S := ''; if Assigned(Follower) and Assigned(Follower.Controller) then @@ -509,14 +498,11 @@ procedure TBoldCustomListBoxCom.MeasureItem(index: Integer; var Height: Integer) Height := 2 + Abs(Canvas.Font.Height) else Height := Canvas.TextHeight(S); - - // Now allow user to remeasure, using updated height-value inherited; end; procedure TBoldCustomListBoxCom.WMSize(var Message: TWMSize); begin - // Redraw when resising if aligment is not taLeftJustify inherited; if Alignment <> taLeftJustify then Invalidate; @@ -596,4 +582,3 @@ procedure TBoldCustomListBoxCom.InternalSetSelected(index: integer; v: Boolean); initialization end. - diff --git a/Source/ClientGuiCom/BoldControls/BoldMemoCom.pas b/Source/ClientGuiCom/BoldControls/BoldMemoCom.pas index 827475f..6298663 100644 --- a/Source/ClientGuiCom/BoldControls/BoldMemoCom.pas +++ b/Source/ClientGuiCom/BoldControls/BoldMemoCom.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldMemoCom; {$DEFINE BOLDCOMCLIENT} {Clientified 2002-08-05 13:13:02} @@ -5,18 +8,21 @@ interface uses - Windows, + // VCL Classes, - Graphics, Controls, - StdCtrls, + Graphics, Menus, - BoldEnvironmentVCL, // Make sure VCL environement loaded, and finalized after - BoldHandlesCom, - BoldComObjectSpace_TLB, BoldClientElementSupport, BoldComClient, + StdCtrls, + Windows, + + // Bold + BoldClientElementSupport, + BoldComObjectSpace_TLB, BoldControlPackCom, - BoldStringControlPackCom, - BoldElementHandleFollowerCom; + BoldElementHandleFollowerCom, + BoldHandlesCom, + BoldStringControlPackCom; type TBoldCustomMemoCom = class; @@ -151,7 +157,6 @@ implementation uses SysUtils, - BoldRev, BoldDefs, BoldControlPackDefs; @@ -181,7 +186,7 @@ destructor TBoldCustomMemoCom.Destroy; end; bapDemand: Follower.DiscardChange; end; - + FreeAndNil(fHandleFollower); FreeAndNil(fCanvas); FreeAndNil(fBoldProperties); @@ -324,7 +329,7 @@ procedure TBoldCustomMemoCom.KeyPress(var Key: Char); MessageBeep(0); Key := BOLDNULL; end; - + if Key = BOLDESC then begin Follower.DiscardChange; @@ -370,7 +375,9 @@ procedure TBoldCustomMemoCom.AfterMakeUptoDate(Follower: TBoldFollowerCom); RendererDataMaxLength := (Follower.RendererData as TBoldStringRendererDataCom).MaxStringLength; if RendererDataMaxLength <> -1 then - EffectiveMaxLength := RendererDataMaxLength; + EffectiveMaxLength := RendererDataMaxLength + else + EffectiveMaxLength := MaxLength; if (MaxLength > 0) and (MaxLength < EffectiveMaxLength) then EffectiveMaxLength := MaxLength; @@ -387,7 +394,7 @@ procedure TBoldCustomMemoCom.CMEnter(var Message: TCMEnter); procedure TBoldCustomMemoCom.CMExit(var Message: TCMExit); begin if (Follower.Controller.ApplyPolicy = bapExit) then - Follower.Apply; + Follower.Apply; SetFocused(False); DoExit; end; @@ -428,4 +435,3 @@ function TBoldCustomMemoCom.GetVariableList: IBoldExternalVariableList; initialization end. - diff --git a/Source/ClientGuiCom/BoldControls/BoldNavigatorCom.pas b/Source/ClientGuiCom/BoldControls/BoldNavigatorCom.pas index fed9c93..d4f6027 100644 --- a/Source/ClientGuiCom/BoldControls/BoldNavigatorCom.pas +++ b/Source/ClientGuiCom/BoldControls/BoldNavigatorCom.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldNavigatorCom; {$DEFINE BOLDCOMCLIENT} {Clientified 2002-08-05 14:59:57} @@ -5,25 +8,22 @@ interface uses + // VCL Windows, Messages, Classes, Controls, - ExtCtrls, - Buttons, - BoldEnvironmentVCL, // Make sure VCL environement loaded, and finalized after - BoldComObjectSpace_TLB, BoldClientElementSupport, BoldComClient, - {$IFNDEF BOLDCOMCLIENT} // uses + + // Bold + {$IFNDEF BOLDCOMCLIENT} BoldComObjectSpace_TLB, {$ENDIF} - BoldDefs, + BoldComObjectSpace_TLB, BoldNavigatorDefs, BoldAbstractListHandleCom, BoldListHandleFollowerCom, BoldStringControlPackCom, BoldControlPackCom, - BoldCommonBitmaps, - BoldListControlPackCom, BoldListListControlPackCom; type @@ -96,7 +96,7 @@ TBoldCustomNavigatorCom = class(TBoldNavigateBtnImageIndexOwner) public constructor Create(AOwner: TComponent); override; destructor Destroy; override; - procedure Assign(Source: TPersistent); override; + procedure assign(Source: TPersistent); override; procedure BtnClick(index: TBoldNavigateBtn); procedure SetBounds(ALeft, ATop, AWidth, AHeight: Integer); override; end; @@ -152,16 +152,19 @@ TBoldNavigatorCom = class(TBoldCustomNavigatorCom) implementation uses - SysUtils, - BoldRev, + // VCL + Buttons, Dialogs, + ExtCtrls, + SysUtils, + + // Bold + BoldDefs, + BoldCommonBitmaps, {!! DO NOT REMOVE !! BoldSystemRT ,} - BoldUtils, - BoldGuiResourceStringsCom, - BoldControlsDefs; + BoldGuiResourceStringsCom; var -// BtnTypeName: array[TBoldNavigateBtn] of PChar = ('FIRST', 'PRIOR', 'NEXT', 'LAST', 'INSERT', 'DELETE', 'MOVEUP', 'MOVEDOWN'); //Do not localize BtnHintId: array[TBoldNavigateBtn] of Pointer = (@SNavHintFirst, @SNavHintPrior, @SNavHintNext, @SNavHintLast, @SNavHintNew, @SNavHintDelete, @SNavHintMoveUp, @SNavHintMoveDown); procedure TBoldCustomNavigatorCom.InitHints; @@ -202,8 +205,7 @@ procedure TBoldCustomNavigatorCom.SetHints(Value: TStrings); procedure TBoldCustomNavigatorCom.GetChildren(Proc: TGetChildProc; ROOT: TComponent); begin - // Implementation is empty to prevent control - // from behaving like a TPanel + end; procedure TBoldCustomNavigatorCom.SetVisible(Value: TBoldButtonSet); @@ -501,7 +503,6 @@ procedure TBoldCustomNavigatorCom.BtnClick(index: TBoldNavigateBtn); if BoldDeleteMode = dmDefault then begin - // Delete from classlists, remove from other lists if assigned(BoldHandle.ObjectList) and (BoldHandle.ObjectList.OwningElement is IBoldSystem) then EffectiveDeleteMode := dmDelete else @@ -514,7 +515,6 @@ procedure TBoldCustomNavigatorCom.BtnClick(index: TBoldNavigateBtn); begin if assigned(RoleRTInfo) then begin - // linkobjects will be deleted... other objects will be unlinked if RoleRTInfo.RoleType = rtLinkRole then EffectiveDeleteMode := dmDelete else @@ -580,7 +580,7 @@ procedure TBoldCustomNavigatorCom.BtnClick(index: TBoldNavigateBtn); nbInsert: CurrentIndex := List.IndexOf(MutableList.AddNew); nbDelete: - Delete(fConfirmDelete); //FIXME Localize + Delete(fConfirmDelete); nbMoveUp: List.Move(CurrentIndex, CurrentIndex - 1); nbMoveDown: @@ -617,8 +617,8 @@ procedure TBoldCustomNavigatorCom.InitButtons; end; FixButtonGlyphs; InitHints; - Buttons[nbPrior].NavStyle := Buttons[nbPrior].NavStyle + [nsAllowTimer]; - Buttons[nbNext].NavStyle := Buttons[nbNext].NavStyle + [nsAllowTimer]; +// Buttons[nbPrior].NavStyle := Buttons[nbPrior].NavStyle + [nsAllowTimer]; +// Buttons[nbNext].NavStyle := Buttons[nbNext].NavStyle + [nsAllowTimer]; end; procedure TBoldCustomNavigatorCom.SetActiveButtons; @@ -739,5 +739,3 @@ procedure TBoldCustomNavigatorCom.SetImages(const Value: TImageList); initialization end. - - diff --git a/Source/ClientGuiCom/BoldControls/BoldPageControlCom.pas b/Source/ClientGuiCom/BoldControls/BoldPageControlCom.pas index b8aa137..3432f9e 100644 --- a/Source/ClientGuiCom/BoldControls/BoldPageControlCom.pas +++ b/Source/ClientGuiCom/BoldControls/BoldPageControlCom.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldPageControlCom; {$DEFINE BOLDCOMCLIENT} {Clientified 2002-08-05 13:13:02} @@ -7,7 +10,7 @@ interface uses Classes, Controls, - BoldEnvironmentVCL, // Make sure VCL environement loaded, and finalized after + BoldEnvironmentVCL, BoldHandlesCom, BoldControlPackCom, BoldElementHandleFollowerCom, @@ -32,8 +35,8 @@ TBoldPageControlCom = class(TPageControl) property Follower: TBoldFollowerCom read GetFollower; public { Public declarations } - constructor Create(owner: TComponent); override; - destructor Destroy; override; + constructor create(owner: TComponent); override; + destructor destroy; override; published { Published declarations } property BoldHandle: TBoldElementHandleCom read GetBoldHandle write SetBoldHandle; @@ -44,7 +47,6 @@ implementation uses SysUtils, - BoldRev, BoldUtils; { TBoldPageControlCom } @@ -58,7 +60,7 @@ constructor TBoldPageControlCom.create(owner: TComponent); fBoldProperties.OnGetContextType := _GetContextType; end; -destructor TBoldPageControlCom.Destroy; +destructor TBoldPageControlCom.destroy; begin FreeAndNil(fHandleFollower); FreeAndNil(fBoldProperties); diff --git a/Source/ClientGuiCom/BoldControls/BoldProgressBarCom.pas b/Source/ClientGuiCom/BoldControls/BoldProgressBarCom.pas index 0e65a78..6fda2b7 100644 --- a/Source/ClientGuiCom/BoldControls/BoldProgressBarCom.pas +++ b/Source/ClientGuiCom/BoldControls/BoldProgressBarCom.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldProgressBarCom; {$DEFINE BOLDCOMCLIENT} {Clientified 2002-08-05 14:59:57} @@ -5,16 +8,19 @@ interface uses + // VCL Classes, - Controls, ComCtrls, + Controls, Menus, - BoldEnvironmentVCL, // Make sure VCL environement loaded, and finalized after - BoldComObjectSpace_TLB, BoldClientElementSupport, BoldComClient, - BoldHandlesCom, + + // Bold + BoldClientElementSupport, + BoldComObjectSpace_TLB, BoldControlPackCom, - BoldNumericControlPackCom, - BoldElementHandleFollowerCom; + BoldElementHandleFollowerCom, + BoldHandlesCom, + BoldNumericControlPackCom; type { forward declarations } @@ -63,9 +69,7 @@ implementation BoldControlPackDefs, BoldDefs, SysUtils, - BoldRev, - BoldGuiResourceStringsCom, - BoldControlsDefs; + BoldGuiResourceStringsCom; { TBoldProgressBarCom } constructor TBoldProgressBarCom.Create(AOwner: TComponent); diff --git a/Source/ClientGuiCom/BoldControls/BoldPropertiesControllerCom.pas b/Source/ClientGuiCom/BoldControls/BoldPropertiesControllerCom.pas index 84b5583..8e86605 100644 --- a/Source/ClientGuiCom/BoldControls/BoldPropertiesControllerCom.pas +++ b/Source/ClientGuiCom/BoldControls/BoldPropertiesControllerCom.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldPropertiesControllerCom; {$DEFINE BOLDCOMCLIENT} {Clientified 2002-08-05 13:13:02} @@ -6,7 +9,7 @@ interface uses Classes, - BoldEnvironmentVCL, // Make sure VCL environement loaded, and finalized after + BoldEnvironmentVCL, BoldComObjectSpace_TLB, BoldClientElementSupport, BoldComClient, BoldHandlesCom, BoldControlPackCom, @@ -98,9 +101,8 @@ implementation TypInfo, BoldControlPackDefs, BoldControlsDefs, - BoldRev, {$IFNDEF BOLDCOMCLIENT} - BoldComObjectSpace_TLB, // IFNDEF BOLDCOMCLIENT + BoldComObjectSpace_TLB, {$ENDIF} Variants, BoldGuard; @@ -177,20 +179,16 @@ constructor TBoldDrivenPropertyCom.Create(Collection: TCollection); end; procedure TBoldDrivenPropertyCom.EnsureValidPropertyName; -// Searches through the list of properties of the assigned component to check that PropertyName -// is valid for this particular component type. If not, it empties Property Name. -// This is called by the Component property setter SetVCLComponent. -// This is not used anymore at the moment. It was easy when we did not cater for property paths ! + + + var PropList: TPropList; Count, I: Integer; Found: Boolean; begin - // At least clear the property when we clear the component if not Assigned(VCLComponent) then PropertyName := ''; - - // Original code below exit; Found := False; I := 0; @@ -211,7 +209,6 @@ procedure TBoldDrivenPropertyCom.SetVCLComponent(const Value: TComponent); var AllowHookUnHook: Boolean; begin - //We don't support the two way update for collections of more than one driven property AllowHookUnHook := assigned(value) and not ((csDesigning in Value.ComponentState) or (Collection.Count > 1)); @@ -237,7 +234,6 @@ procedure TBoldDrivenPropertyCom.SetReadOnly(const Value: Boolean); end; procedure TBoldDrivenPropertyCom.DoOnExit(Sender: TObject); -// Event that we have assigned as the OnExit of VCLComponent (Hooked) begin if (not ReadOnly) and PropertiesController.BoldProperties.MayModify(PropertiesController.HandleFollower.Follower) then begin @@ -245,18 +241,15 @@ procedure TBoldDrivenPropertyCom.DoOnExit(Sender: TObject); if PropertiesController.BoldProperties.ApplyPolicy = bapExit then PropertiesController.HandleFollower.Follower.Apply; end; - //Call the original event if Assigned(FOnExit) then FOnExit(Sender); end; procedure TBoldDrivenPropertyCom.HookOnExit; -// This method, replaces any existing OnExit event of VCLComponent with ours var DoOnExitMethod: TNotifyEvent; begin - // We could have simply used TWinControl(VCLComponent).OnExit := ... if only it was not protected ! - // Has the VCLComponent got an OnExit event ? + if Assigned(VCLComponent) and Assigned(GetPropInfo(VCLComponent.ClassInfo, 'OnExit')) then begin FOnExit := TNotifyEvent(Typinfo.GetMethodProp(VCLComponent, 'OnExit')); @@ -267,7 +260,6 @@ procedure TBoldDrivenPropertyCom.HookOnExit; procedure TBoldDrivenPropertyCom.UnhookOnExit; begin - // Reassign the original event if Assigned(VCLComponent) and Assigned(GetPropInfo(VCLComponent.ClassInfo, 'OnExit')) then Typinfo.SetMethodProp(VCLComponent, 'OnExit', TMethod(FOnExit)); end; @@ -311,11 +303,10 @@ function TBoldDrivenPropertyCom.GetPropertiesController: TBoldPropertiesControll procedure TBoldDrivenPropertyCom.ConvertRelativeProp(StartInstance: TObject; PropNamePath: String; var LastObject: TObject; var PropName: String); -// This method will follow the objects specified in the PropNamePath starting from StartInstance -// and set the LastObject and PropName -// E.g: ConvertRelativeProp(Label1,'FocusControl.Font.Size') will return -// LastObject points to instance of Font -// LastProp : Size + + + + var I, ColIndex, OpenBracketPos: Integer; @@ -325,22 +316,19 @@ procedure TBoldDrivenPropertyCom.ConvertRelativeProp(StartInstance: TObject; begin BoldGuard := TBoldGuard.Create(Path); Path := TStringList.Create; - - //convert . notation to commas so we can use CommaText function Path.CommaText := StringReplace(PropNamePath, '.', ',', [rfReplaceAll]); LastObject := StartInstance; for I := 0 to Path.Count - 1 do begin - // The path may very well follow unassigned links. This check prevents an AV if not Assigned(LastObject) then Exit; PathItem := Path[I]; OpenBracketPos := Pos('[', PathItem); if OpenBracketPos = 0 then begin - if (I < Path.Count - 1) //Special case for when the last property is of tkClass we don't want - //to loose LastObject to be in fact the Previous before Last ! + if (I < Path.Count - 1) + and (GetPropInfo(LastObject.ClassInfo, PathItem)^.PropType^.Kind = tkClass) then begin LastObject := TObject(Typinfo.GetOrdProp(LastObject, PathItem)) @@ -370,16 +358,13 @@ procedure TBoldDrivenPropertyCom.SetRelativePropValue(StartInstance: TObject; TypeKind: TTypeKind; PropInfo: PPropInfo; begin - // No property specified if PropNamePath = '' then Exit; ConvertRelativeProp(StartInstance, PropNamePath, LastObject, PropName); - // Property path followed unassigned links if not Assigned(LastObject) then Exit; PropInfo := GetPropInfo(LastObject.ClassInfo, PropName); - // Property name misspelled if not Assigned(PropInfo) then Exit; TypeKind := PropInfo^.PropType^.Kind; @@ -393,14 +378,11 @@ procedure TBoldDrivenPropertyCom.SetRelativePropValue(StartInstance: TObject; {$ENDIF} end else - // Handle nil equivalents for various property types case TypeKind of tkEnumeration: VarValue := 0; tkInteger: VarValue := 0; else VarValue := PropertiesController.BoldProperties.NilStringRepresentation; end; - - // Special case for booleans that don't seem to be handled properly by SetPropValue if VarType(VarValue) = varBoolean then begin if VarValue then @@ -411,7 +393,6 @@ procedure TBoldDrivenPropertyCom.SetRelativePropValue(StartInstance: TObject; if TypeKind = tkClass then begin - // Special case for objects PropertyObj := TObject(Typinfo.GetOrdProp(LastObject, PropName)); if PropertyObj is TStrings then begin @@ -433,7 +414,6 @@ procedure TBoldDrivenPropertyCom.SetRelativePropValue(StartInstance: TObject; end; end else if TypeKind = tkInteger then - // This is needed to handle an error in TypInfo when setting CARDINAL properties try SetOrdProp(LastObject, PropName, VarValue) except diff --git a/Source/ClientGuiCom/BoldControls/BoldRichEditCom.pas b/Source/ClientGuiCom/BoldControls/BoldRichEditCom.pas index 131d89d..e58dccb 100644 --- a/Source/ClientGuiCom/BoldControls/BoldRichEditCom.pas +++ b/Source/ClientGuiCom/BoldControls/BoldRichEditCom.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldRichEditCom; {$DEFINE BOLDCOMCLIENT} {Clientified 2002-08-05 13:13:02} diff --git a/Source/ClientGuiCom/BoldControls/BoldStringsPropertyControllerCom.pas b/Source/ClientGuiCom/BoldControls/BoldStringsPropertyControllerCom.pas index 8f0589d..d0bc8f1 100644 --- a/Source/ClientGuiCom/BoldControls/BoldStringsPropertyControllerCom.pas +++ b/Source/ClientGuiCom/BoldControls/BoldStringsPropertyControllerCom.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldStringsPropertyControllerCom; {$DEFINE BOLDCOMCLIENT} {Clientified 2002-08-05 13:13:02} @@ -6,7 +9,7 @@ interface uses Classes, - BoldEnvironmentVCL, // Make sure VCL environement loaded, and finalized after + BoldEnvironmentVCL, BoldComObjectSpace_TLB, BoldClientElementSupport, BoldComClient, BoldAbstractListHandleCom, BoldControlPackCom, @@ -82,7 +85,6 @@ implementation SysUtils, BoldListControlPackCom, BoldDefs, - BoldRev, TypInfo; {-- TBoldStringsPropertyControllerCom ----------------------------------------------------------} @@ -92,7 +94,7 @@ constructor TBoldStringsPropertyControllerCom.Create(AOwner: TComponent); inherited; fBoldRowProperties := TBoldStringFollowerControllerCom.Create(Self); fBoldRowProperties.AfterMakeUptoDate := _ItemAfterMakeUptoDate; - fBoldRowProperties.BeforeMakeUptoDate := _ItemBeforeMakeUptoDate; + fBoldRowProperties.BeforeMakeUptoDate := _ItemBeforeMakeUptoDate; fBoldRowProperties.OnGetContextType := GetContextType; fBoldProperties := TBoldListAsFollowerListControllerCom.Create(Self, fBoldRowProperties); with fBoldProperties do @@ -136,7 +138,7 @@ procedure TBoldStringsPropertyControllerCom.Notification(AComponent: TComponent; if Assigned(VCLComponent) and (not (csDestroying in ComponentState)) then if (AComponent = VCLComponent) and (Operation = opRemove) then VCLComponent := nil; -end; +end; procedure TBoldStringsPropertyControllerCom._ListAfterMakeUptoDate(Follower: TBoldFollowerCom); var @@ -222,7 +224,6 @@ function TBoldStringsPropertyControllerCom.GetContextType: IBoldElementTypeInfo; function TBoldStringsPropertyControllerCom.GetStringsProperty: TStrings; begin - // fixme code for properties not at top level Result := nil; if Assigned(VCLComponent) and (PropertyName <> '') then begin @@ -251,7 +252,6 @@ procedure TBoldStringsPropertyControllerCom._ItemBeforeMakeUptoDate(Follower: TB procedure TBoldStringsPropertyControllerCom.SetVCLComponent(const Value: TComponent); begin - //FIXME: Add code to validate PropertyName in new component fVCLComponent := Value; if Assigned(fVCLComponent) then FreeNotification(fVCLComponent); diff --git a/Source/ClientGuiCom/BoldControls/BoldTrackBarCom.pas b/Source/ClientGuiCom/BoldControls/BoldTrackBarCom.pas index d13363c..d21db54 100644 --- a/Source/ClientGuiCom/BoldControls/BoldTrackBarCom.pas +++ b/Source/ClientGuiCom/BoldControls/BoldTrackBarCom.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldTrackBarCom; {$DEFINE BOLDCOMCLIENT} {Clientified 2002-08-05 14:59:57} @@ -13,7 +16,7 @@ interface CommCtrl, Menus, BoldDefs, - BoldEnvironmentVCL, // Make sure VCL environement loaded, and finalized after + BoldEnvironmentVCL, BoldControlPackDefs, BoldHandlesCom, BoldComObjectSpace_TLB, BoldClientElementSupport, BoldComClient, @@ -71,7 +74,6 @@ implementation uses SysUtils, - BoldRev, BoldUtils, BoldGuiResourceStringsCom, BoldControlsDefs; diff --git a/Source/ClientGuiCom/BoldControls/BoldTreeViewCom.pas b/Source/ClientGuiCom/BoldControls/BoldTreeViewCom.pas index 40c14b2..33de1df 100644 --- a/Source/ClientGuiCom/BoldControls/BoldTreeViewCom.pas +++ b/Source/ClientGuiCom/BoldControls/BoldTreeViewCom.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldTreeViewCom; {$DEFINE BOLDCOMCLIENT} {Clientified 2002-08-05 13:13:02} @@ -5,29 +8,26 @@ interface uses - Windows, - Messages, + // VCL Classes, - Graphics, - Menus, - Controls, ComCtrls, CommCtrl, - BoldEnvironmentVCL, // Make sure VCL environement loaded, and finalized after - {$IFNDEF BOLDCOMCLIENT} // uses - BoldComObjectSpace_TLB, // IFNDEF BOLDCOMCLIENT - BoldGui, // IFNDEF BOLDCOMCLIENT + Controls, + Menus, + Windows, + + // Bold + {$IFNDEF BOLDCOMCLIENT} + BoldComObjectSpace_TLB, + BoldGui, {$ENDIF} - BoldComObjectSpace_TLB, BoldClientElementSupport, BoldComClient, - BoldHandlesCom, + BoldComObjectSpace_TLB, + BoldComponentValidatorCom, + BoldControlPackCom, BoldControlsDefs, - BoldControlPackDefs, BoldElementHandleFollowerCom, - BoldControlPackCom, - BoldNumericControlPackCom, - BoldStringControlPackCom, BoldGenericListControlPackCom, - BoldComponentValidatorCom, + BoldHandlesCom, BoldNodeControlPackCom; type @@ -47,7 +47,7 @@ TBoldTreeNodeCom = class(TTreeNode) procedure UpdateIcon; function GetTreeView: TBoldTreeViewCom; public - destructor Destroy; override; + destructor destroy; override; function ExistsInParent: Boolean; property Follower: TBoldFollowerCom read FFollower write FFollower; property NodeDescription: TBoldNodeDescriptionCom read GetNodeDescription; @@ -239,22 +239,22 @@ TBoldTreeViewCom = class(TBoldCustomTreeViewCom) {$ENDIF} end; - - implementation uses + // VCL + Graphics, SysUtils, - BoldRev, - BoldUtils; + BoldControlPackDefs, + BoldNumericControlPackCom, + BoldStringControlPackCom; {---TBoldTreeNodeCom---} function TBoldTreeNodeCom.GetNodeDescription: TBoldNodeDescriptionCom; var I: Integer; begin - // Check if cache is accurate. if Assigned(FNodeDescription) and (FNodeDescription.NodeFollowerController = Follower.Controller) then begin Result := FNodeDescription; @@ -347,12 +347,10 @@ procedure TBoldCustomTreeViewCom.SetMaxLevels(Value: Integer); begin for I := 0 to Follower.SubFollowerCount-1 do begin - //Update this node if (Follower.SubFollowers[I].Controller as TBoldNodeFollowerControllerCom).HideNodeWithNoChildren then DoInsertHiddenNode(Follower.SubFollowers[I]) else SetNodeState(TBoldTreeNodeCom(Follower.SubFollowers[I].ControlData)); - //Recurse through subfollowers if Follower.SubFollowers[I].Active and (Follower.SubFollowers[I].SubFollowerCount>=BoldNodeListIndex) and Follower.SubFollowers[I].SubFollowers[BoldNodeListIndex].Active then DoList(Level+1, Follower.SubFollowers[I].SubFollowers[BoldNodeListIndex]) end; @@ -462,13 +460,11 @@ procedure TBoldCustomTreeViewCom.SetSelected(Value: TBoldTreeNodeCom); procedure TBoldCustomTreeViewCom.BeginUpdate; begin -// Items.BeginUpdate; Inc(FUpdateCount); end; procedure TBoldCustomTreeViewCom.EndUpdate; begin -// Items.EndUpdate; Dec(FUpdateCount); end; @@ -503,8 +499,6 @@ procedure TBoldCustomTreeViewCom.DisplayIcon(Follower: TBoldFollowerCom); SelectedIndex := SelectedImageIndex else SelectedIndex := ImageIndex; - - // Make a multiselected node appear selected even thjough the treeview does not know this if Follower.Selected and not node.Selected then ImageIndex := SelectedIndex; @@ -529,9 +523,8 @@ function TBoldCustomTreeViewCom.CreateNode: TTreeNode; procedure TBoldCustomTreeViewCom.AfterMakeUptoDate(Follower: TBoldFollowerCom); begin - // for some reason, the pointer to this event seems to get lost after a while. - // the variables below might contain space pointers outside of an update operation - // if this method is not executed. + + fSelectedNodePreUpdate := nil; fSelectedElementPreUpdate := nil; fSelectedNodeDescriptionPreUpdate := nil; @@ -612,16 +605,14 @@ procedure TBoldCustomTreeViewCom.DoInsertHiddenNode(Follower: TBoldFollowerCom); Follower.Active := True; (Follower.Controller as TBoldNodeFollowerControllerCom).SetActiveRange(Follower, BoldNodeListIndex, BoldNodeListIndex); Follower.EnsureDisplayable; - //If EnsureDisplayable creates childnodes they will create a node to this follower too. if (Level <= AutoExpandLevels) and Assigned(Follower.ControlData) then - (Follower.ControlData as TBoldTreeNodeCom).Expand(False); //CHECKME behövs detta? + (Follower.ControlData as TBoldTreeNodeCom).Expand(False); finally EndUpdate; end; end else begin - //Dont show it if we can't show any children! Follower.Active := False; if Assigned(Follower.ControlData) then begin @@ -641,7 +632,6 @@ procedure TBoldCustomTreeViewCom.SetNodeState(Node: TBoldTreeNodeCom); Controller := (Follower.Controller as TBoldNodeFollowerControllerCom); if Controller.HideNodeWithNoChildren then begin - //Nodes with HideNodeWithNoChildren is always fully shown Controller.SetActiveRange(Follower, BoldNodeListIndex, BoldNodeTextIndex); end else @@ -673,7 +663,6 @@ procedure TBoldCustomTreeViewCom.SetNodeState(Node: TBoldTreeNodeCom); if ((Follower.SubFollowerCount = 0) or (not Follower.SubFollowers[BoldNodeListIndex].Active)) then begin - //Only set node in "ExpandOnDemand" mode if it's not expanded already! Node.HasChildren := (Controller.Items[BoldNodeListIndex] as TBoldGenericListControllerCom).CanHaveSubFollowers; Controller.SetActiveRange(Follower, BoldNodeIconIndex, BoldNodeTextIndex); Follower.EnsureDisplayable; @@ -682,7 +671,6 @@ procedure TBoldCustomTreeViewCom.SetNodeState(Node: TBoldTreeNodeCom); end else begin - //Don't allow expansion Node.DeleteChildren; (Follower.Controller as TBoldNodeFollowerControllerCom).SetActiveRange(Follower, BoldNodeIconIndex, BoldNodeTextIndex); Follower.EnsureDisplayable; @@ -800,7 +788,6 @@ procedure TBoldCustomTreeViewCom.MouseUp(Button: TMouseButton; Shift: TShiftStat HitTests: THitTests; begin HitTests := GetHitTestInfoAt(x, y); - // skip the MouseUp if this is a drag... if abs(x - fMouseDownPos.x) + abs(y - fMouseDownPos.y) < Mouse.DragThreshold then begin if (Button = mbLeft) and (htOnItem in HitTests) then @@ -829,7 +816,6 @@ procedure TBoldCustomTreeViewCom.MouseDown(Button: TMouseButton; Shift: TShiftSt if (Button = mbLeft) and (htOnItem in HitTests) then UpdateMultiSelect(fMouseDownNode, Shift, DirMouseDown); - // for some reason, the shiftstate is not preserved until mouse up fMouseDownShiftState := Shift; inherited; end; @@ -1037,7 +1023,6 @@ function TBoldCustomTreeViewCom.ValidateComponent(ComponentValidator: TBoldCompo BaseName: String; Context: IBoldElementTypeInfo; begin - // We want to evaluate everything. Thus suboptimized expressions. Result := True; Context := GetContextType; ComponentValidator.ValidateExpressionInContext('', Context, NamePrefix + name); @@ -1089,7 +1074,6 @@ procedure TBoldCustomTreeViewCom.SetMultiSelect(NewValue: Boolean); procedure TBoldCustomTreeViewCom.UpdateMultiSelect(Node: TBoldTreeNodeCom; Shift: TShiftState; MouseDirection: TBoldMouseDirection); procedure RestoreLastSelectedNode; begin - // restore the selectedstate of the previous node... if assigned(fLastSelectedNode) and (fLastSelectedNode <> Node) then fLastSelectedNode.SetSelected(fLastSelectedNode.Follower.Selected); end; @@ -1106,9 +1090,8 @@ procedure TBoldCustomTreeViewCom.UpdateMultiSelect(Node: TBoldTreeNodeCom; Shift if (MouseDirection = DirMouseDown) and Node.Follower.Selected then begin - // a MouseDown occured on a node that was already selected, - // make sure that the previous node is not unselected until - // mouseup if this is a drag. + + RestoreLastSelectedNode; end; @@ -1262,7 +1245,6 @@ procedure TBoldCustomTreeViewCom._CustomDrawItem(Sender: TCustomTreeView; Node: TextController: TBoldStringFollowerControllerCom; begin Follower := (Node as TBoldTreeNodeCom).Follower; -// TextController := (Follower.Controller as TBoldNodeFollowerControllerCom).Items[2] as TBoldStringFollowerControllerCom; TextController := (Follower.Controller as TBoldNodeFollowerControllerCom).TextFollowerController; if not (cdsSelected in State) then begin diff --git a/Source/ClientGuiCom/BoldControls/BoldTreeViewConfigCom.pas b/Source/ClientGuiCom/BoldControls/BoldTreeViewConfigCom.pas index a25c0d0..84e32b7 100644 --- a/Source/ClientGuiCom/BoldControls/BoldTreeViewConfigCom.pas +++ b/Source/ClientGuiCom/BoldControls/BoldTreeViewConfigCom.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldTreeViewConfigCom; {$DEFINE BOLDCOMCLIENT} {Clientified 2002-08-05 13:13:02} @@ -9,8 +12,8 @@ interface BoldGenericListControlPackCom, BoldNodeControlPackCom, {!! DO NOT REMOVE !! BoldSystemRT ,} - {$IFDEF BOLDCOMCLIENT} // uses - BoldComObjectSpace_TLB, // to get the ObjectSpace interfaces + {$IFDEF BOLDCOMCLIENT} + BoldComObjectSpace_TLB, {$ENDIF} BoldTreeViewCom; @@ -20,10 +23,9 @@ implementation uses SysUtils, - BoldRev, BoldUtils; -{$IFDEF BOLDCOMCLIENT} // BoldGenericTreeView +{$IFDEF BOLDCOMCLIENT} procedure BoldGenericTreeView(SystemTypeInfo: IBoldSystemTypeInfo; TreeView: TBoldTreeViewCom); begin end; diff --git a/Source/ClientGuiCom/BoldControls/BoldXCVTreeViewCom.pas b/Source/ClientGuiCom/BoldControls/BoldXCVTreeViewCom.pas index 12a1cfb..761fabc 100644 --- a/Source/ClientGuiCom/BoldControls/BoldXCVTreeViewCom.pas +++ b/Source/ClientGuiCom/BoldControls/BoldXCVTreeViewCom.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldXCVTreeViewCom; interface diff --git a/Source/ClientGuiCom/ControlPacks/BoldCheckboxStateControlPackCom.pas b/Source/ClientGuiCom/ControlPacks/BoldCheckboxStateControlPackCom.pas index e59746b..cb5cafe 100644 --- a/Source/ClientGuiCom/ControlPacks/BoldCheckboxStateControlPackCom.pas +++ b/Source/ClientGuiCom/ControlPacks/BoldCheckboxStateControlPackCom.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldCheckboxStateControlPackCom; {$DEFINE BOLDCOMCLIENT} {Clientified 2002-08-05 13:13:02} @@ -5,11 +8,12 @@ interface uses - StdCtrls, // TCheckBoxState - BoldDefs, - BoldComObjectSpace_TLB, BoldClientElementSupport, BoldComClient, + StdCtrls, + BoldClientElementSupport, + BoldComClient, + BoldComObjectSpace_TLB, BoldControlPackCom, - BoldSubscription; + BoldDefs; type @@ -48,7 +52,7 @@ TBoldAsCheckBoxStateRendererCom = class(TBoldSingleRendererCom) class function DefaultGetAsCheckBoxStateAndSubscribe(Element: IBoldElement; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: IBoldExternalVariableList; Subscriber: TBoldComClientSubscriber): TCheckBoxState; virtual; class procedure DefaultSetAsCheckBoxState(Element: IBoldElement; newValue: TCheckBoxState; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: IBoldExternalVariableList); virtual; class function DefaultValidateCheckBoxState(Element: IBoldElement; Value: TCheckBoxState; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: IBoldExternalVariableList): Boolean; virtual; - procedure MakeUptodateAndSubscribe(Element: IBoldElement; RendererData: TBoldFollowerDataCom; FollowerController: TBoldFollowerControllerCom; Subscriber: TBoldComClientSubscriber); override; + procedure MakeUpToDateAndSubscribe(Element: IBoldElement; RendererData: TBoldFollowerDataCom; FollowerController: TBoldFollowerControllerCom; Subscriber: TBoldComClientSubscriber); override; function DefaultIsChanged(RendererData: TBoldCheckBoxRendererDataCom; NewValue: TCheckBoxState; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: IBoldExternalVariableList): Boolean; function GetAsCheckBoxStateAndSubscribe(Element: IBoldElement; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: IBoldExternalVariableList; Subscriber: TBoldComClientSubscriber): TCheckBoxState; virtual; procedure SetAsCheckBoxState(Element: IBoldElement; Value: TCheckBoxState; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: IBoldExternalVariableList); virtual; @@ -84,9 +88,7 @@ implementation uses SysUtils, - BoldRev, - BoldControlPackDefs, - BoldAttributes; + BoldControlPackDefs; var DefaultAsCheckBoxStateRenderer: TBoldAsCheckBoxStateRendererCom; @@ -142,7 +144,7 @@ procedure TBoldCheckBoxStateFollowerControllerCom.MayHaveChanged(NewValue: TChec procedure TBoldCheckBoxStateFollowerControllerCom.MakeClean(Follower: TBoldFollowerCom); begin - ReleaseChangedValue(Follower); // note, must do first, since set can change element + ReleaseChangedValue(Follower); SetAsCheckBoxState(GetCurrentAsCheckBoxState(Follower), Follower); end; @@ -160,7 +162,7 @@ procedure TBoldAsCheckBoxStateRendererCom.MakeUpToDateANdSubscribe(Element: IBol class function TBoldAsCheckBoxStateRendererCom.DefaultGetAsCheckBoxStateAndSubscribe(Element: IBoldElement; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: IBoldExternalVariableList; Subscriber: TBoldComClientSubscriber): TCheckBoxState; var - {$IFDEF BOLDCOMCLIENT} // DefaultGet + {$IFDEF BOLDCOMCLIENT} e: IBoldElement; Attribute: IBoldAttribute; {$ELSE} @@ -170,7 +172,7 @@ class function TBoldAsCheckBoxStateRendererCom.DefaultGetAsCheckBoxStateAndSubsc Result := cbGrayed; if Assigned(Element) then begin - {$IFDEF BOLDCOMCLIENT} // defaultGet + {$IFDEF BOLDCOMCLIENT} if assigned(Subscriber) then e := Element.EvaluateAndSubscribeToExpression(Expression, Subscriber.ClientId, Subscriber.SubscriberId, false, false) else @@ -206,12 +208,12 @@ class function TBoldAsCheckBoxStateRendererCom.DefaultGetAsCheckBoxStateAndSubsc class procedure TBoldAsCheckBoxStateRendererCom.DefaultSetAsCheckBoxState(Element: IBoldElement; newValue: TCheckBoxState; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: IBoldExternalVariableList); var ValueElement: IBoldElement; - {$IFDEF BOLDCOMCLIENT} // defaulSet + {$IFDEF BOLDCOMCLIENT} Attribute: IBoldAttribute; {$ENDIF} begin ValueElement := GetExpressionAsDirectElement(Element, Expression, VariableList); - {$IFDEF BOLDCOMCLIENT} // defaultSet + {$IFDEF BOLDCOMCLIENT} if valueElement.QueryInterface(IBoldAttribute, Attribute) = S_OK then begin if NewValue = cbGrayed then @@ -302,5 +304,5 @@ initialization finalization FreeAndNil(DefaultAsCheckBoxStateRenderer); - + end. diff --git a/Source/ClientGuiCom/ControlPacks/BoldControlPackCom.pas b/Source/ClientGuiCom/ControlPacks/BoldControlPackCom.pas index 6203cee..2c0f20d 100644 --- a/Source/ClientGuiCom/ControlPacks/BoldControlPackCom.pas +++ b/Source/ClientGuiCom/ControlPacks/BoldControlPackCom.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldControlPackCom; {$DEFINE BOLDCOMCLIENT} {Clientified 2002-08-05 14:59:57} @@ -9,7 +12,7 @@ interface SysUtils, Controls, {$IFDEF BOLD_DELPH6_OR_LATER} - Types, // IFDEF BOLD_DELPH6_OR_LATER + Types, {$ENDIF} Menus, Graphics, @@ -53,7 +56,6 @@ TBoldFollowerSubscriberCom = class(TBoldComClientSubscriber) end; { TBoldFollowerDataCom } - // Abstract class, concrete versions defined with typed renderer TBoldFollowerDataCom = class(TBoldMemoryManagedObject) private fOwningFollower: TBoldFollowerCom; @@ -140,7 +142,6 @@ TBoldFollowerCom = class(TBoldQueueable) private fIndex: Integer; fOwningFollower: TBoldFollowerCom; -// fSelected: Boolean; fState: TBoldFollowerState; fElement: IBoldElement; fRendererData: TBoldFollowerDataCom; @@ -164,9 +165,9 @@ TBoldFollowerCom = class(TBoldQueueable) procedure AddToDisplayList; override; procedure Receive(Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent); {The following two are virtual to allow overriden in the old hierarchy} - procedure MakeUptodateAndSubscribe; // Displays, i.e. moves from B.O. to RendereData, also resubscribes if needed + procedure MakeUptodateAndSubscribe; class procedure MultiMakeUptodateAndSubscribe(Followers: TBoldObjectArray); - procedure MakeClean; // Applies, i.e. moves from rendererdata to B.O. + procedure MakeClean; {State handling} procedure MarkDirty; procedure MarkClean; @@ -285,7 +286,6 @@ TBoldFollowerControllerCom = class(TBoldSubscribablePersistent) published property DragMode: TBoldDragMode read FDragMode write FDragMode default bdgNone; property DropMode: TBoldDropMode read FDropMode write FDropMode default bdpNone; - // property Popup: TBoldPopupCom read fPopup write fPopup; end; { TBoldSingleRendererCom } @@ -312,7 +312,7 @@ TBoldSingleFollowerControllerCom = class(TBoldFollowerControllerCom) { TBoldPopupCom } TBoldPopupCom = class(TPersistent) private - FEnable: Boolean; // FIXME notify owner of change here + FEnable: Boolean; FInsertNew: Boolean; FDelete: TBoldPopupDeleteType; FMove: Boolean; @@ -326,7 +326,7 @@ TBoldPopupCom = class(TPersistent) property Move: Boolean read FMove write FMove default False; end; -{$IFDEF BOLDCOMCLIENT} // List/InterfaceArray +{$IFDEF BOLDCOMCLIENT} type TBoldClientableListCom = TBoldInterfaceArray; @@ -341,10 +341,9 @@ function BoldTestType(element: TObject; TypeOrInterface: TClass): Boolean; implementation uses - BoldRev, BoldExceptionHandlersCom, BoldGuiResourceStringsCom, -{$IFNDEF BOLDCOMCLIENT} // uses +{$IFNDEF BOLDCOMCLIENT} BoldComObjectSpace_TLB, {!! DO NOT REMOVE !! BoldSystemRT ,} BoldGUI, @@ -361,7 +360,7 @@ implementation var DefaultRenderer: TBoldRendererCom; -{$IFDEF BOLDCOMCLIENT} // BoldTestType +{$IFDEF BOLDCOMCLIENT} function BoldTestType(element: IUnknown; const TypeOrInterface: TGUID): Boolean; var Res: IUnknown; @@ -611,7 +610,6 @@ procedure TBoldRendererCom.SetRepresentations(Value: TStrings); end; function TBoldRendererCom.StoreRepresentations: Boolean; - // Don't store the stringlist if it's empty or if it's equal to the default representation stringlist. begin Result := False; if Assigned(FRepresentations) and (FRepresentations.Count > 0) then @@ -627,7 +625,7 @@ class function TBoldRendererCom.GetExpressionAsDirectElement(Element: IBoldEleme begin Result := nil; if Assigned(Element) then - {$IFDEF BOLDCOMCLIENT} // GetAsDirectElement // FIXME: VariableList is lost + {$IFDEF BOLDCOMCLIENT} Result := Element.EvaluateExpression(Expression); {$ELSE} Result := Element.EvaluateExpressionAsDirectElement(Expression, VariableList); @@ -661,7 +659,7 @@ function TBoldRendererCom.DefaultMayModify(Element: IBoldElement; Representation begin ValueElement := GetExpressionAsDirectElement(Element, Expression, VariableList); if Assigned(ValueElement) then - {$IFDEF BOLDCOMCLIENT} // DefaultMayModify // fixme + {$IFDEF BOLDCOMCLIENT} result := ValueElement.mutable {$ELSE} Result := ValueElement.ObserverMayModify(Subscriber) @@ -671,7 +669,7 @@ function TBoldRendererCom.DefaultMayModify(Element: IBoldElement; Representation end; procedure TBoldRendererCom.DefaultHoldsChangedValue(Element: IBoldElement; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: IBoldExternalVariableList; Subscriber: TBoldComClientSubscriber); -{$IFNDEF BOLDCOMCLIENT} // DefaultHoldsChangedValue +{$IFNDEF BOLDCOMCLIENT} var ValueElement: IBoldElement; begin @@ -687,7 +685,7 @@ procedure TBoldRendererCom.DefaultHoldsChangedValue(Element: IBoldElement; Repre {$ENDIF} procedure TBoldRendererCom.DefaultReleaseChangedValue(Element: IBoldElement; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: IBoldExternalVariableList; Subscriber: TBoldComClientSubscriber); -{$IFNDEF BOLDCOMCLIENT} // defaultReleaseChangedValue +{$IFNDEF BOLDCOMCLIENT} var ValueElement: IBoldElement; begin @@ -706,8 +704,7 @@ function TBoldRendererCom.MayModify(Element: IBoldElement; Representation: TBold Assigned(Element) then Result := OnMayModify(Element, Representation, Expression, Subscriber) else if HasEventOverrides then - // this forces readonly of renderers that has an OnSubscribeEvent but no OnMayModify - // OnMayModify is mandatory for a writeable renderer. + result := false else Result := DefaultMayModify(Element, Representation, Expression, VariableList, Subscriber) @@ -722,7 +719,7 @@ procedure TBoldRendererCom.HoldsChangedValue(Element: IBoldElement; Representati begin if Assigned(FOnHoldsChangedValue) then OnHoldsChangedValue(Element, Representation, Expression, Subscriber) - else + else DefaultHoldsChangedValue(Element, Representation, Expression, VariableList, Subscriber) end; @@ -735,14 +732,14 @@ procedure TBoldRendererCom.ReleaseChangedValue(Element: IBoldElement; Representa end; procedure TBoldRendererCom.DefaultStartDrag(Element: IBoldElement; DragMode: TBoldDragMode; RendererData: TBoldFollowerDataCom); -{$IFNDEF BOLDCOMCLIENT} // DragDrop +{$IFNDEF BOLDCOMCLIENT} var Obj: IBoldObject; -{$ENDIF} +{$ENDIF} begin - {$IFNDEF BOLDCOMCLIENT} // DragDrop + {$IFNDEF BOLDCOMCLIENT} if BoldGUIHandler.DraggedObjects.Count <> 0 then - raise EBold.CreateFmt(SDraggedObjectsNotCleared, [ClassName]); + raise EBold.Create(SDraggedObjectsNotCleared); if DragMode = bdgSelection then begin @@ -761,14 +758,14 @@ procedure TBoldRendererCom.DefaultStartDrag(Element: IBoldElement; DragMode: TBo procedure TBoldRendererCom.DefaultEndDrag(DragMode: TBoldDragMode; InternalDrag: Boolean); begin - {$IFNDEF BOLDCOMCLIENT} // dragdrop + {$IFNDEF BOLDCOMCLIENT} BoldGUIHandler.DraggedObjects.Clear; {$ENDIF} end; function TBoldRendererCom.DefaultDragOver(Element: IBoldElement; DropMode: TBoldDropMode; InternalDrag: Boolean; RendererData: TBoldFollowerDataCom; dropindex: Integer): Boolean; begin - {$IFDEF BOLDCOMCLIENT} // dragdrop + {$IFDEF BOLDCOMCLIENT} result := false; {$ELSE} Result := Assigned(Element) and Element.ObserverMayModify(Self) and @@ -778,7 +775,7 @@ function TBoldRendererCom.DefaultDragOver(Element: IBoldElement; DropMode: TBold end; procedure TBoldRendererCom.DefaultDragDrop(Element: IBoldElement; DropMode: TBoldDropMode; dropindex: Integer); -{$IFNDEF BOLDCOMCLIENT} // dragdrop +{$IFNDEF BOLDCOMCLIENT} var i: integer; offset, @@ -1009,7 +1006,7 @@ procedure TBoldFollowerCom.SetActive(Value: Boolean); begin Assert(State <> bfsInactiveInvalidElement); SetState(bfsActivating); - MakeUptodateAndSubscribe; //CHECKME This could cause errors if an owning follower is in bfsOutOfDate + MakeUptodateAndSubscribe; MarkClean; end else @@ -1064,9 +1061,9 @@ procedure TBoldFollowerCom.DiscardChange; procedure TBoldFollowerCom.Receive(Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent); begin -{$IFNDEF BOLDCOMCLIENT} // CHECKME +{$IFNDEF BOLDCOMCLIENT} if (OriginalEvent = beDestroying) and (Originator = Element) then - FElement := nil; //CHECKME Is this necesary? /frha + FElement := nil; {$ENDIF} case RequestedEvent of breReEvaluate: @@ -1116,9 +1113,9 @@ procedure TBoldFollowerCom.ControlledValueChanged(IsChanged: Boolean); begin AssertedController.HoldsChangedValue(Self); MarkDirty; - end; - if AssertedController.ApplyPolicy = bapChange then - Apply; + if AssertedController.ApplyPolicy = bapChange then + Apply; + end end else begin @@ -1129,9 +1126,8 @@ procedure TBoldFollowerCom.ControlledValueChanged(IsChanged: Boolean); procedure TBoldFollowerCom.SetElement(theElement: IBoldElement); begin - // if the fElement is nil and the new element is nil aswell we still need - // to mark the follower out of date since other properties of the controller - // might have changed (especially the nilstringrepresentation) + + if not assigned(theElement) or (theElement <> fElement) then begin fElement := theElement; @@ -1146,7 +1142,7 @@ procedure TBoldFollowerCom.MarkValueOutOfDate; bfsEmpty, bfsCurrent, bfsDirty: SetState(bfsValueOutOfDate); bfsInactiveValidElement, bfsValueOutOfDate, - bfsSubscriptionOutOfDate, bfsActivating: // FIXME bfsActivating is a temporary fix for the delayd fetch problem + bfsSubscriptionOutOfDate, bfsActivating: {no action} else raise EBoldInternal.CreateFmt('%s.MarkOutOfDate: Follower state error', [ClassName]); @@ -1162,12 +1158,9 @@ procedure TBoldFollowerCom.MarkSubscriptionOutOfDate; bfsSubscriptionOutOfDate, bfsActivating : {no action}; - // these two should not happen, but it is safe to ignore them - // a bug in the grid seems to cause these when the grid is not displayed - // right after creation (if it is on an invisible pagecontrol) + bfsInactiveValidElement, bfsInactiveInvalidElement: begin - // DebugCode below - can safely be removed SetState(State);{no action} end else @@ -1202,7 +1195,7 @@ procedure TBoldFollowerCom.SetState(Value: TBoldFollowerState); {action when leaving state} case State of bfsValueOutOfDate, bfsSubscriptionOutOfDate: {bfsOutOfDate} - RemoveFromDisplayList; + RemoveFromDisplayList(false); bfsDirty: RemoveFromApplyList; end; @@ -1276,7 +1269,6 @@ procedure TBoldFollowerCom.Display; on E: Exception do begin if assigned(Controller) and Controller.HandleDisplayException(E, Element) then - // don't re-raise else begin if assigned(Controller) then @@ -1300,12 +1292,11 @@ procedure TBoldFollowerCom.EnsureMulti; try Controller.MultiMakeEnsure(Followers); except - ; // silence any exceptions + ; end end; procedure TBoldFollowerCom.EnsureDisplayable; -//EnsureDisplayable may only be called when within Display or when ALL owning followers not is in bfsOutOfDate! begin if not Displayable then begin @@ -1341,10 +1332,9 @@ procedure TBoldFollowerCom.Apply; function TBoldPopupCom.GetMenu(CONTROL: TControl; Element: IBoldElement): TPopupMenu; begin Result := nil; - {$IFNDEF BOLDCOMCLIENT} // popup + {$IFNDEF BOLDCOMCLIENT} BoldGUIHandler.PopupElement := Element; BoldGUIHandler.PopupControl := CONTROL; - // fixme build actual menu if not Enable then Result := BoldPopupMenu; {$ENDIF} @@ -1395,7 +1385,6 @@ procedure TBoldFollowerCom.SetCurrentIndex(index: integer); procedure TBoldFollowerDataCom.SetCurrentSubFollowerIndex(index: integer); begin - // just ignore; end; function TBoldFollowerControllerCom.GetContextType: IBoldElementTypeInfo; @@ -1467,7 +1456,7 @@ function TBoldFollowerControllerCom.GetVariableListAndSubscribe(Subscriber: TBol result := GetVariableList; {$IFNDEF BOLDCOMCLIENT} if assigned(Subscriber) and assigned(Variables) then - Variables.SubscribeToHandles(Subscriber); + Variables.SubscribeToHandles(Subscriber, Expression); {$ENDIF} end; @@ -1511,7 +1500,7 @@ class procedure TBoldFollowerCom.MultiMakeUptodateAndSubscribe( for I := 0 to Followers.Count - 1 do if TBoldFollowerCom(Followers[i]).State in bfdNeedResubscribe then begin - TBoldFollowerCom(Followers[i]).Subscriber.CancelAllSubscriptions; // CHECKME ever needed? + TBoldFollowerCom(Followers[i]).Subscriber.CancelAllSubscriptions; Controller.AddSmallSubscription(TBoldFollowerCom(Followers[i]).Subscriber, [beValueChanged, beDestroying], breControllerChanged); end; Controller.MultiMakeUptodateAndSubscribe(Followers); @@ -1571,7 +1560,6 @@ function TBoldFollowerControllerCom.HandleApplyException(E: Exception; Elem: IBo procedure TBoldFollowerControllerCom.CleanRendererData(RendererData: TBoldFollowerDataCom); begin - // do nothing end; function TBoldFollowerControllerCom.HandleDisplayException(E: Exception; @@ -1658,4 +1646,3 @@ finalization FreeAndNil(DefaultRenderer); end. - diff --git a/Source/ClientGuiCom/ControlPacks/BoldControllerListControlPackCom.pas b/Source/ClientGuiCom/ControlPacks/BoldControllerListControlPackCom.pas index 470b1af..8f23f47 100644 --- a/Source/ClientGuiCom/ControlPacks/BoldControllerListControlPackCom.pas +++ b/Source/ClientGuiCom/ControlPacks/BoldControllerListControlPackCom.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldControllerListControlPackCom; {$DEFINE BOLDCOMCLIENT} {Clientified 2002-08-05 13:13:02} @@ -7,7 +10,7 @@ interface uses Classes, BoldControlPackDefs, - BoldComObjectSpace_TLB, BoldClientElementSupport, BoldComClient, + BoldComObjectSpace_TLB, BoldControlPackCom, BoldListControlPackCom; @@ -79,7 +82,7 @@ procedure TBoldControllerListCom.DoMakeUptodateAndSubscribe(Follower: TBoldFollo inherited DoMakeUptodateAndSubscribe(Follower, Subscribe); (EffectiveRenderer as TBoldControllerListAsFollowerListRendererCom).MakeUptodate(Follower, Follower.Element); if Subscribe and Assigned(Follower.Element) then - {$IFDEF BOLDCOMCLIENT} // MakeUpToDate + {$IFDEF BOLDCOMCLIENT} Follower.Element.SubscribeToExpression('', Follower.Subscriber.ClientId, Follower.Subscriber.SubscriberId, False, true); {$ELSE} Follower.Element.SubscribeToExpression('', Follower.Subscriber, False); @@ -128,7 +131,7 @@ function TBoldControllerListCom.GetEffectiveRenderer: TBoldRendererCom; function TBoldControllerListCom.GetEffectiveDisplayPropertyListRenderer: TBoldControllerListAsFollowerListRendererCom; begin - Result := TBoldControllerListAsFollowerListRendererCom.DefaultRenderer; // currently always uses default. + Result := TBoldControllerListAsFollowerListRendererCom.DefaultRenderer; end; {---TBoldControllerListAsFollowerListRendererCom---} @@ -158,4 +161,3 @@ finalization FreeAndNil(DefaultDisplayPropertyListRenderer); end. - diff --git a/Source/ClientGuiCom/ControlPacks/BoldDateTimeControlPackCom.pas b/Source/ClientGuiCom/ControlPacks/BoldDateTimeControlPackCom.pas index d6583fd..692b4a4 100644 --- a/Source/ClientGuiCom/ControlPacks/BoldDateTimeControlPackCom.pas +++ b/Source/ClientGuiCom/ControlPacks/BoldDateTimeControlPackCom.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldDateTimeControlPackCom; {$DEFINE BOLDCOMCLIENT} {Clientified 2002-08-05 13:13:02} @@ -5,10 +8,11 @@ interface uses - BoldDefs, - BoldSubscription, - BoldComObjectSpace_TLB, BoldClientElementSupport, BoldComClient, - BoldControlPackCom; + BoldClientElementSupport, + BoldComClient, + BoldComObjectSpace_TLB, + BoldControlPackCom, + BoldDefs; type { Forward declarations } @@ -65,7 +69,6 @@ TBoldDateTimeFollowerControllerCom = class(TBoldSingleFollowerControllerCom) function GetEffectiveRenderer: TBoldRendererCom; override; property EffectiveAsDateTimeRenderer: TBoldAsDateTimeRendererCom read GetEffectiveAsDateTimeRenderer; public -// procedure Assign(Source: TPersistent); override; function GetCurrentAsDateTime(Follower: TBoldFollowerCom): TDateTime; procedure MakeClean(Follower: TBoldFollowerCom); override; procedure MayHaveChanged(NewValue: TDateTime; Follower: TBoldFollowerCom); @@ -78,10 +81,7 @@ implementation uses SysUtils, - BoldRev, - BoldControlPackDefs, - {!! DO NOT REMOVE !! BoldAttributes ,} - BoldGuard; + BoldControlPackDefs; var DefaultAsDateTimeRenderer: TBoldAsDateTimeRendererCom = nil; @@ -98,15 +98,14 @@ function TBoldAsDateTimeRendererCom.GetRendererDataClass: TBoldRendererDataClass end; function TBoldAsDateTimeRendererCom.DefaultMayModify(Element: IBoldElement; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: IBoldExternalVariableList; Subscriber: TBoldComClientSubscriber): Boolean; -{$IFNDEF BOLDCOMCLIENT} // defaultMayModify +{$IFNDEF BOLDCOMCLIENT} var ValueElement: IBoldElement; -{$ENDIF} +{$ENDIF} begin - {$IFDEF BOLDCOMCLIENT} // defaultMayModify + {$IFDEF BOLDCOMCLIENT} result := inherited DefaultMayModify(Element, Representation, Expression, VariableList, Subscriber); {$ELSE} - // Note! We don't call inherited DefaultMayModify to prevent evaluation of expression two times! ValueElement := GetExpressionAsDirectElement(Element, Expression, VariableList); result := (ValueElement is TBAMoment) and ValueElement.ObserverMayModify(Subscriber); {$ENDIF} @@ -114,7 +113,7 @@ function TBoldAsDateTimeRendererCom.DefaultMayModify(Element: IBoldElement; Repr function TBoldAsDateTimeRendererCom.DefaultGetAsDateTimeAndSubscribe(Element: IBoldElement; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: IBoldExternalVariableList; Subscriber: TBoldComClientSubscriber): TDateTime; var - {$IFDEF BOLDCOMCLIENT} // DefaultGet + {$IFDEF BOLDCOMCLIENT} el: IBoldElement; attr: IBoldAttribute; {$ELSE} @@ -125,7 +124,7 @@ function TBoldAsDateTimeRendererCom.DefaultGetAsDateTimeAndSubscribe(Element: IB Result := 0; if Assigned(Element) then begin - {$IFDEF BOLDCOMCLIENT} //defaultGet + {$IFDEF BOLDCOMCLIENT} if assigned(Subscriber) then el := Element.EvaluateAndSubscribeToExpression(Expression, Subscriber.ClientId, Subscriber.SubscriberId, false, false) else @@ -158,13 +157,13 @@ function TBoldAsDateTimeRendererCom.DefaultGetAsDateTimeAndSubscribe(Element: IB procedure TBoldAsDateTimeRendererCom.DefaultSetAsDateTime(Element: IBoldElement; const Value: TDateTime; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: IBoldExternalVariableList); var - {$IFDEF BOLDCOMCLIENT} // defaultSet + {$IFDEF BOLDCOMCLIENT} Attr: IBoldAttribute; {$ENDIF} ValueElement: IBoldElement; begin ValueElement := GetExpressionAsDirectElement(Element, Expression, VariableList); - {$IFDEF BOLDCOMCLIENT} // defaultSet + {$IFDEF BOLDCOMCLIENT} if assigned(ValueElement) and (ValueElement.QueryInterface(IBoldAttribute, Attr) = S_OK) then Attr.AsVariant := Value else @@ -260,7 +259,7 @@ function TBoldDateTimeFollowerControllerCom.GetEffectiveAsDateTimeRenderer: TBol if Assigned(Renderer) then Result := Renderer else - Result := DefaultAsDateTimeRenderer; //FIXME + Result := DefaultAsDateTimeRenderer; end; procedure TBoldDateTimeFollowerControllerCom.MakeClean(Follower: TBoldFollowerCom); @@ -286,7 +285,7 @@ procedure TBoldDateTimeFollowerControllerCom.MayHaveChanged(NewValue: TDateTime; (Follower.RendererData as TBoldDateTimeRendererDataCom).CurrentDateTimeValue := NewValue; Follower.ControlledValueChanged(EffectiveAsDateTimeRenderer.IsChanged(Follower.RendererData as TBoldDateTimeRendererDataCom, NewValue, Representation, Expression, VariableList)); end; -end; +end; initialization DefaultAsDateTimeRenderer := TBoldAsDateTimeRendererCom.Create(nil); diff --git a/Source/ClientGuiCom/ControlPacks/BoldElementHandleFollowerCom.pas b/Source/ClientGuiCom/ControlPacks/BoldElementHandleFollowerCom.pas index 1e38dbb..157b47c 100644 --- a/Source/ClientGuiCom/ControlPacks/BoldElementHandleFollowerCom.pas +++ b/Source/ClientGuiCom/ControlPacks/BoldElementHandleFollowerCom.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldElementHandleFollowerCom; {$DEFINE BOLDCOMCLIENT} {Clientified 2002-08-05 13:13:02} @@ -44,11 +47,9 @@ TBoldElementHandleFollowerCom = class(TBoldQueueable) implementation uses - SysUtils, - BoldRev, - BoldUtils, BoldControlPackDefs, - BoldDefs; + BoldDefs, + SysUtils; { TBoldElementHandleFollowerCom } @@ -83,7 +84,6 @@ procedure TBoldElementHandleFollowerCom.SetBoldHandle(value: TBoldElementHandleC if (value <> BoldHandle) then begin fBoldHandle := Value; - // will force subscription on Handle FollowerValueCurrent := false; end; end; @@ -130,7 +130,7 @@ procedure TBoldElementHandleFollowerCom.SetFollowerValueCurrent(value: Boolean); begin if Value then begin - RemoveFromDisplayList; + RemoveFromDisplayList(false); PropagateValue; Subscribe; end @@ -148,4 +148,3 @@ procedure TBoldElementHandleFollowerCom.SetFollowerValueCurrent(value: Boolean); initialization end. - diff --git a/Source/ClientGuiCom/ControlPacks/BoldFloatControlPackCom.pas b/Source/ClientGuiCom/ControlPacks/BoldFloatControlPackCom.pas index 1d7234b..2c31dd5 100644 --- a/Source/ClientGuiCom/ControlPacks/BoldFloatControlPackCom.pas +++ b/Source/ClientGuiCom/ControlPacks/BoldFloatControlPackCom.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldFloatControlPackCom; {$DEFINE BOLDCOMCLIENT} {Clientified 2002-08-05 13:13:02} @@ -65,7 +68,6 @@ TBoldFloatFollowerControllerCom = class(TBoldSingleFollowerControllerCom) property EffectiveAsFloatRenderer: TBoldAsFloatRendererCom read GetEffectiveAsFloatRenderer; function GetEffectiveRenderer: TBoldRendererCom; override; public -// procedure Assign(Source: TPersistent); override; function GetCurrentAsFloat(Follower: TBoldFollowerCom): double; procedure MakeClean(Follower: TBoldFollowerCom); override; procedure MayHaveChanged(NewValue: double; Follower: TBoldFollowerCom); @@ -78,10 +80,9 @@ implementation uses SysUtils, - BoldRev, BoldUtils, {!! DO NOT REMOVE !! BoldAttributes ,} - BoldControlPackDefs, + BoldControlPackDefs, BoldGuard; var @@ -99,15 +100,14 @@ function TBoldAsFloatRendererCom.GetRendererDataClass: TBoldRendererDataClassCom end; function TBoldAsFloatRendererCom.DefaultMayModify(Element: IBoldElement; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: IBoldExternalVariableList; Subscriber: TBoldComClientSubscriber): Boolean; -{$IFNDEF BOLDCOMCLIENT} // defaultMayModify +{$IFNDEF BOLDCOMCLIENT} var ValueElement: IBoldElement; {$ENDIF} begin - {$IFDEF BOLDCOMCLIENT} // defaultMayModify + {$IFDEF BOLDCOMCLIENT} result := inherited DefaultMayModify(Element, Representation, Expression, VariableList, Subscriber); {$ELSE} - // Note! We don't call inherited DefaultMayModify to prevent evaluation of expression two times! ValueElement := GetExpressionAsDirectElement(Element, Expression, VariableList); result := ((ValueElement is TBAFloat) or (ValueElement is TBADateTime)) and ValueElement.ObserverMayModify(Subscriber) {$ENDIF} @@ -115,7 +115,7 @@ function TBoldAsFloatRendererCom.DefaultMayModify(Element: IBoldElement; Represe function TBoldAsFloatRendererCom.DefaultGetAsFloatAndSubscribe(Element: IBoldElement; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: IBoldExternalVariableList; Subscriber: TBoldComClientSubscriber): double; var - {$IFDEF BOLDCOMCLIENT} // defaultGet + {$IFDEF BOLDCOMCLIENT} el: IBoldElement; attr: IBoldAttribute; {$ELSE} @@ -126,7 +126,7 @@ function TBoldAsFloatRendererCom.DefaultGetAsFloatAndSubscribe(Element: IBoldEle Result := 0; if Assigned(Element) then begin - {$IFDEF BOLDCOMCLIENT} // defaultGet + {$IFDEF BOLDCOMCLIENT} if assigned(Subscriber) then el := Element.EvaluateAndSubscribeToExpression(Expression, Subscriber.ClientId, Subscriber.SubscriberId, false, false) else @@ -159,12 +159,12 @@ function TBoldAsFloatRendererCom.DefaultGetAsFloatAndSubscribe(Element: IBoldEle procedure TBoldAsFloatRendererCom.DefaultSetAsFloat(Element: IBoldElement; const Value: double; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: IBoldExternalVariableList); var ValueElement: IBoldElement; - {$IFDEF BOLDCOMCLIENT} // defaultSet + {$IFDEF BOLDCOMCLIENT} attr: IBoldAttribute; {$ENDIF} begin ValueElement := GetExpressionAsDirectElement(Element, Expression , VariableList); - {$IFDEF BOLDCOMCLIENT} // defaultSet + {$IFDEF BOLDCOMCLIENT} if assigned(ValueElement) and (ValueElement.QueryInterface(IBoldAttribute, attr) = S_OK) then Attr.AsVariant := Value else diff --git a/Source/ClientGuiCom/ControlPacks/BoldGenericListControlPackCom.pas b/Source/ClientGuiCom/ControlPacks/BoldGenericListControlPackCom.pas index fef43bf..bc1efc0 100644 --- a/Source/ClientGuiCom/ControlPacks/BoldGenericListControlPackCom.pas +++ b/Source/ClientGuiCom/ControlPacks/BoldGenericListControlPackCom.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldGenericListControlPackCom; {$DEFINE BOLDCOMCLIENT} {Clientified 2002-08-05 13:13:02} @@ -5,12 +8,16 @@ interface uses + // VCL Classes, - BoldDefs, - BoldSubscription, - BoldComObjectSpace_TLB, BoldClientElementSupport, BoldComClient, + + // Bold + BoldComClient, + BoldComObjectSpace_TLB, BoldControlPackCom, - BoldListControlPackCom; + BoldDefs, + BoldListControlPackCom, + BoldSubscription; type { forward declarations } @@ -30,9 +37,9 @@ TBoldFollowerListWithOwnedListCom = class; TGetFollowerControllerEventCom = function (Element: IBoldElement; Subscriber: TBoldComClientSubscriber; GetFollowerControllerByName: TGetFollowerControllerByNameEventCom): TBoldFollowerControllerCom of object; {$ENDIF} - {$IFNDEF BOLDCOMCLIENT} // GetElementEvent + {$IFNDEF BOLDCOMCLIENT} TGetElementEvent = procedure (Sender: TBoldGenericListPartCom; Element: IBoldElement; Subscriber: TBoldComClientSubscriber; ResultElement: TBoldIndirectElement; Resubscribe: Boolean) of object; - {$ENDIF} + {$ENDIF} { TBoldFollowerListWithOwnedListCom } TBoldFollowerListWithOwnedListCom = class (TBoldFollowerListCom) @@ -51,7 +58,7 @@ TBoldGenericListPartCom = class(TCollectionItem) FElementExpression: TBoldExpression; FControllerExpression: TBoldExpression; FInterpretAsList: Boolean; - {$IFNDEF BOLDCOMCLIENT} // GetElementEvent + {$IFNDEF BOLDCOMCLIENT} FOnGetElement: TGetElementEvent; {$ENDIF} FOnGetFollowerController: TGetFollowerControllerEventCom; @@ -68,9 +75,9 @@ TBoldGenericListPartCom = class(TCollectionItem) property Publisher: TBoldPublisher read GetPublisher; public constructor Create(Collection: TCollection); override; - destructor Destroy; override; + destructor destroy; override; procedure Assign(Source: TPersistent); override; - {$IFDEF BOLDCOMCLIENT} // GetElementEvent + {$IFDEF BOLDCOMCLIENT} function GetElement(Element: IBoldElement; Subscriber: TBoldComClientSubscriber; Resubscribe: Boolean): IBoldElement; {$ELSE} procedure DefaultGetElement(Element: IBoldElement; Subscriber: TBoldComClientSubscriber; ResultElement: TBoldIndirectElement; Resubscribe: Boolean); @@ -85,7 +92,7 @@ TBoldGenericListPartCom = class(TCollectionItem) property InterpretAsList: Boolean read FInterpretAsList write SetInterpretAsList; property Name: String read fName write fName; property Enabled: Boolean read fEnabled write SetEnabled default true; - {$IFNDEF BOLDCOMCLIENT} // GetElementEvent + {$IFNDEF BOLDCOMCLIENT} property OnGetElement: TGetElementEvent read FOnGetElement write FOnGetElement; {$ENDIF} property OnGetFollowerController: TGetFollowerControllerEventCom read FOnGetFollowerController write FOnGetFollowerController; @@ -145,15 +152,12 @@ TBoldGenericListControllerCom = class(TBoldAsFollowerListControllerCom) implementation uses - SysUtils, - BoldRev, - BoldUtils, - BoldContainers, - BoldControlPackDefs, - {$IFNDEF BOLDCOMCLIENT} // uses + {$IFNDEF BOLDCOMCLIENT} BoldComObjectSpace_TLB, {$ENDIF} - BoldNodeControlPackCom; + SysUtils, + BoldContainers, + BoldControlPackDefs; var DefaultGenericAsListRenderer: TBoldGenericAsListRendererCom; @@ -197,7 +201,7 @@ procedure TBoldGenericListPartCom.Assign(Source: TPersistent); ElementExpression := TBoldGenericListPartCom(Source).ElementExpression; ControllerExpression := TBoldGenericListPartCom(Source).ControllerExpression; InterpretAsList := TBoldGenericListPartCom(Source).InterpretAsList; - {$IFNDEF BOLDCOMCLIENT} // GetElementEvent + {$IFNDEF BOLDCOMCLIENT} OnGetElement := TBoldGenericListPartCom(Source).OnGetElement; {$ENDIF} OnGetFollowerController := TBoldGenericListPartCom(Source).OnGetFollowerController; @@ -233,7 +237,7 @@ procedure TBoldGenericListPartCom.SetInterpretAsList(Value: Boolean); end; end; -{$IFDEF BOLDCOMCLIENT} // GetElementEvent +{$IFDEF BOLDCOMCLIENT} function TBoldGenericListPartCom.GetElement(Element: IBoldElement; Subscriber: TBoldComClientSubscriber; Resubscribe: Boolean): IBoldElement; begin if Assigned(Element) then @@ -268,7 +272,7 @@ procedure TBoldGenericListPartCom.GetElement(Element: IBoldElement; Subscriber: function TBoldGenericListPartCom.DefaultGetFollowerController(Element: IBoldElement; Subscriber: TBoldComClientSubscriber; GetFollowerControllerByName: TGetFollowerControllerByNameEventCom): TBoldFollowerControllerCom; var -{$IFDEF BOLDCOMCLIENT} // DefaultGet +{$IFDEF BOLDCOMCLIENT} e: IBoldElement; {$ELSE} E: TBoldIndirectElement; @@ -296,7 +300,7 @@ function LoopList(List: IBoldList): TBoldFollowerControllerCom; begin Result := nil; - {$IFDEF BOLDCOMCLIENT} // DefaultGet + {$IFDEF BOLDCOMCLIENT} e := Element.EvaluateAndSubscribeToExpression(ControllerExpression, Subscriber.ClientId, Subscriber.SubscriberId, False, false); if Assigned(E) then begin @@ -466,7 +470,7 @@ procedure TBoldGenericAsListRendererCom.MakeUptodate(Follower: TBoldFollowerCom; {$IFDEF BOLDCOMCLIENT} begin element := part.GetElement(Follower.Element, Follower.Subscriber, False); - result := assigned(element); // fixme: true or false? + result := assigned(element); end; {$ELSE} var @@ -499,7 +503,7 @@ procedure TBoldGenericAsListRendererCom.MakeUptodate(Follower: TBoldFollowerCom; DestList.AddOwnedElement(Element); if Assigned(Element) then begin - {$IFDEF BOLDCOMCLIENT} // listconverting + {$IFDEF BOLDCOMCLIENT} Element.QueryInterface(IBoldList, SourceList); {$ELSE} if element is IBoldList then @@ -553,7 +557,7 @@ procedure TBoldGenericListPartCom.SetEnabled(const Value: Boolean); end; end; -destructor TBoldGenericListPartCom.Destroy; +destructor TBoldGenericListPartCom.destroy; begin if assigned(fPublisher) then fPublisher.NotifySubscribersAndClearSubscriptions(self); diff --git a/Source/ClientGuiCom/ControlPacks/BoldListControlPackCom.pas b/Source/ClientGuiCom/ControlPacks/BoldListControlPackCom.pas index fe4be01..c77a121 100644 --- a/Source/ClientGuiCom/ControlPacks/BoldListControlPackCom.pas +++ b/Source/ClientGuiCom/ControlPacks/BoldListControlPackCom.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldListControlPackCom; {$DEFINE BOLDCOMCLIENT} {Clientified 2002-08-05 13:13:02} @@ -5,13 +8,11 @@ interface uses - BoldDefs, Classes, - BoldComObjectSpace_TLB, BoldClientElementSupport, BoldComClient, - {$IFNDEF BOLDCOMCLIENT} // uses + BoldComObjectSpace_TLB, + {$IFNDEF BOLDCOMCLIENT} BoldComObjectSpace_TLB, {$ENDIF} - BoldSubscription, BoldControlPackCom; type @@ -65,7 +66,6 @@ TBoldFollowerListCom = class(TBoldFollowerDataCom) function GetSelectedCount: Integer; procedure SetSelected(index: Integer; V: Boolean); function GetSelected(index: Integer): Boolean; -// procedure UnselectPrev; procedure Insert(ListFollowerController: TBoldAsFollowerListControllerCom; Index: Integer; Follower: TBoldFollowerCom); procedure Delete(ListFollowerController: TBoldAsFollowerListControllerCom; index: Integer); protected @@ -99,7 +99,7 @@ implementation uses SysUtils, - BoldRev, + BoldSubscription, BoldUtils; {---TBoldAsFollowerListControllerCom---} @@ -135,7 +135,7 @@ procedure TBoldAsFollowerListControllerCom.DoAfterDeleteItem(index: Integer; Own procedure TBoldAsFollowerListControllerCom.SetActiveRange(Follower: TBoldFollowerCom; FirstActive, LastActive: Integer; RangeBuffer: Integer = 1); begin - if Assigned(EffectiveRenderer) then // may be nil after finalization + if Assigned(EffectiveRenderer) then (EffectiveRenderer as TBoldAsFollowerListRendererCom).SetActiveRange(Follower, FirstActive, LastActive, RangeBuffer); end; @@ -370,4 +370,3 @@ procedure TBoldAsFollowerListControllerCom.CleanRendererData(RendererData: TBold initialization end. - diff --git a/Source/ClientGuiCom/ControlPacks/BoldListHandleFollowerCom.pas b/Source/ClientGuiCom/ControlPacks/BoldListHandleFollowerCom.pas index 343dbd3..c3b5e95 100644 --- a/Source/ClientGuiCom/ControlPacks/BoldListHandleFollowerCom.pas +++ b/Source/ClientGuiCom/ControlPacks/BoldListHandleFollowerCom.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldListHandleFollowerCom; {$DEFINE BOLDCOMCLIENT} {Clientified 2002-08-05 13:13:02} @@ -14,8 +17,6 @@ interface BoldListListControlPackCom, BoldAbstractListHandleCom; -// Note, Currently subscibes to value-identity-change via element of handle, until -// subscribability has been added to the handle. type { forward declarations } @@ -45,15 +46,13 @@ TBoldListHandleFollowerCom = class(TBoldQueueable) property Follower: TBoldFollowerCom read fFollower; constructor Create(MatchObject: TObject; Controller: TBoldAbstractListAsFollowerListControllerCom); destructor Destroy; override; - end; + end; implementation uses SysUtils, BoldControlPackDefs, - BoldRev, - BoldUtils, BoldDefs; { TBoldElementHandleFollowerCom } @@ -84,7 +83,7 @@ constructor TBoldListHandleFollowerCom.Create(MatchObject: TObject; destructor TBoldListHandleFollowerCom.Destroy; begin FreeAndNil(fFollower); - FreeAndNil(fSubscriber); + FreeAndNil(fSubscriber); inherited; end; @@ -94,7 +93,6 @@ procedure TBoldListHandleFollowerCom.SetBoldHandle( if (value <> BoldHandle) then begin fBoldHandle := Value; - // will force subscription on Handle FollowerValueCurrent := false; end; end; @@ -134,8 +132,8 @@ procedure TBoldListHandleFollowerCom.SetFollowerValueCurrent(value: Boolean); begin if Assigned(BoldHandle) then begin - BoldHandle.AddSmallSubscription(Subscriber, [beValueIdentityChanged], breListIdentityChanged); // FIXME - BoldHandle.AddSmallSubscription(Subscriber, [beValueIdentityChanged], breHandleIndexChanged); // FIXME + BoldHandle.AddSmallSubscription(Subscriber, [beValueIdentityChanged], breListIdentityChanged); + BoldHandle.AddSmallSubscription(Subscriber, [beValueIdentityChanged], breHandleIndexChanged); end; end; @@ -151,7 +149,7 @@ procedure TBoldListHandleFollowerCom.SetFollowerValueCurrent(value: Boolean); if Value then begin PropagateValue; - RemoveFromDisplayList; + RemoveFromDisplayList(false); Subscribe; end else @@ -181,4 +179,3 @@ procedure TBoldListHandleFollowerCom.SetFollowerIndex(index: integer); initialization end. - diff --git a/Source/ClientGuiCom/ControlPacks/BoldListListControlPackCom.pas b/Source/ClientGuiCom/ControlPacks/BoldListListControlPackCom.pas index 8c10263..1ef31c8 100644 --- a/Source/ClientGuiCom/ControlPacks/BoldListListControlPackCom.pas +++ b/Source/ClientGuiCom/ControlPacks/BoldListListControlPackCom.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldListListControlPackCom; {$DEFINE BOLDCOMCLIENT} {Clientified 2002-08-05 13:13:02} @@ -6,10 +9,11 @@ interface uses Classes, - BoldDefs, - BoldComObjectSpace_TLB, BoldClientElementSupport, BoldComClient, - BoldControlPackDefs, + + // Bold + BoldComObjectSpace_TLB, BoldControlPackCom, + BoldControlPackDefs, BoldListControlPackCom; type @@ -42,8 +46,7 @@ TBoldAbstractListAsFollowerListControllerCom = class(TBoldAsFollowerListContro property NilElementMode: TBoldNilElementMode read fNilElementMode write SetNilElementMode; public constructor Create(aOwningComponent: TComponent; FollowerController: TBoldFollowerControllerCom); -// procedure DragDrop(Follower: TBoldFollowerCom; ReceivingElement: IBoldElement; dropindex: Integer); override; -// function DragOver(Follower: TBoldFollowerCom; ReceivingElement: IBoldElement; dropindex: Integer): Boolean; override; + function GetListIndex(Follower: TBoldFollowerCom): Integer; function ListIndexToIndex(Follower: TBoldFollowerCom; ListIndex: Integer): integer; function ListIndex(index: integer): integer; @@ -75,13 +78,11 @@ implementation uses SysUtils, - BoldRev, - BoldUtils, - {$IFNDEF BOLDCOMCLIENT} // uses + {$IFNDEF BOLDCOMCLIENT} BoldComObjectSpace_TLB, BoldGUI, {$ENDIF} - BoldMath; + BoldRev; var DefaultListAsFollowerListRenderer: TBoldListAsFollowerListRendererCom; @@ -135,7 +136,7 @@ procedure TBoldAbstractListAsFollowerListControllerCom.DoMakeUptodateAndSubscrib begin inherited DoMakeUptodateAndSubscribe(Follower, Subscribe); (EffectiveRenderer as TBoldListAsFollowerListRendererCom).MakeUptodate(Follower, fFollowerController); - {$IFDEF BOLDCOMCLIENT} // MakeUptodateAndSubscribe + {$IFDEF BOLDCOMCLIENT} if Subscribe and Assigned(Follower.Element) then Follower.Element.SubscribeToExpression('', Follower.Subscriber.ClientId, Follower.Subscriber.SubscriberId, false, false); {$ELSE} @@ -291,7 +292,7 @@ procedure TBoldListAsFollowerListRendererCom.MakeUptodate(Follower: TBoldFollowe unk := SourceVariant[SourceIndex]; ElementInterface := unk as IBoldElement; AddElement(ElementInterface); - end + end {$ENDIF} else begin @@ -305,12 +306,12 @@ procedure TBoldListAsFollowerListRendererCom.MakeUptodate(Follower: TBoldFollowe end; procedure TBoldListAsFollowerListRendererCom.DefaultStartDrag(Element: IBoldElement; DragMode: TBoldDragMode; RendererData: TBoldFollowerDataCom); -{$IFNDEF BOLDCOMCLIENT} // dragdrop - DefaultStartDrag +{$IFNDEF BOLDCOMCLIENT} var FollowerList: TBoldFollowerListCom; {$ENDIF} begin - {$IFNDEF BOLDCOMCLIENT} // dragdrop - DefaultStartDrag + {$IFNDEF BOLDCOMCLIENT} if (DragMode = bdgSelection) then begin if BoldGUIHandler.DraggedObjects.Count <> 0 then @@ -324,16 +325,16 @@ procedure TBoldListAsFollowerListRendererCom.DefaultStartDrag(Element: IBoldElem function TBoldListAsFollowerListRendererCom.DefaultDragOver(Element: IBoldElement; DropMode: TBoldDropMode; InternalDrag: Boolean; RendererData: TBoldFollowerDataCom; dropindex: Integer): Boolean; begin - {$IFNDEF BOLDCOMCLIENT} // dragdrop - DefaultDragOver + {$IFNDEF BOLDCOMCLIENT} Result := (BoldGUIHandler.DraggedObjects.Count > 0) and - BoldGUIHandler.DraggedObjectsAssignable(Element, DropMode); // FIXME move here + BoldGUIHandler.DraggedObjectsAssignable(Element, DropMode); {$ELSE} result := false; {$ENDIF} end; procedure TBoldListAsFollowerListRendererCom.DefaultDragDrop(Element: IBoldElement; DropMode: TBoldDropMode; dropindex: Integer); -{$IFNDEF BOLDCOMCLIENT} // dragdrop - DefaultDragDrop +{$IFNDEF BOLDCOMCLIENT} var prevIndex, Offset, @@ -344,7 +345,7 @@ procedure TBoldListAsFollowerListRendererCom.DefaultDragDrop(Element: IBoldEleme (* if (NilElementMode=neInsertFirst) then Offset := 1 - else*) //FIXME + else*) Offset := 0; case DropMode of bdpInsert: @@ -376,7 +377,6 @@ procedure TBoldListAsFollowerListRendererCom.DefaultDragDrop(Element: IBoldEleme bdpAppend: for I := 0 to BoldGUIHandler.DraggedObjects.Count - 1 do - // Dupe checking by the ObjectList ObjectList.Add(BoldGUIHandler.DraggedObjects[I]); bdpReplace: @@ -399,7 +399,7 @@ function TBoldAbstractListAsFollowerListControllerCom.ListIndexToIndex(Follower: function TBoldAbstractListAsFollowerListControllerCom.ListIndex(index: integer): integer; begin if index = MaxInt then - result := index // otherwise the result will overflow to -maxint + result := index else if NilElementMode = neInsertFirst then Result := index + 1 else @@ -411,6 +411,5 @@ initialization finalization FreeAndNil(DefaultListAsFollowerListRenderer); - + end. - diff --git a/Source/ClientGuiCom/ControlPacks/BoldNodeControlPackCom.pas b/Source/ClientGuiCom/ControlPacks/BoldNodeControlPackCom.pas index 16ad204..540b856 100644 --- a/Source/ClientGuiCom/ControlPacks/BoldNodeControlPackCom.pas +++ b/Source/ClientGuiCom/ControlPacks/BoldNodeControlPackCom.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldNodeControlPackCom; {$DEFINE BOLDCOMCLIENT} {Clientified 2002-08-05 14:59:57} @@ -6,17 +9,13 @@ interface uses Classes, - BoldDefs, - BoldControlPackDefs, BoldControlPackCom, BoldStringControlPackCom, BoldNumericControlPackCom, - BoldListControlPackCom, BoldControllerListControlPackCom, BoldGenericListControlPackCom, - BoldComObjectSpace_TLB, BoldClientElementSupport, BoldComClient, + BoldComObjectSpace_TLB; {!! DO NOT REMOVE !! BoldSystemRT ,} - BoldSubscription; type { Forward declarations } @@ -143,9 +142,11 @@ implementation uses SysUtils, - BoldRev, + BoldControlPackDefs, + BoldDefs, BoldGuiResourceStringsCom, - BoldUtils; + BoldListControlPackCom, + BoldSubscription; {-- TBoldTreeFollowerControllerCom --} @@ -320,7 +321,6 @@ function TBoldNodeDescriptionCom.GetBoldNodeFollowerControllerClass:TBoldNodeFol destructor TBoldNodeDescriptionCom.Destroy; begin - // FIXME ??? FreePublisher; //CHECKME Is this really needed? FreeAndNil(FNodeFollowerController); inherited Destroy; end; @@ -442,7 +442,7 @@ procedure TBoldNodeFollowerControllerCom.SetHideNodeWithNoChildren(Value: Boolea destructor TBoldNodeFollowerControllerCom.Destroy; begin - FreePublisher; //CHECKME Is this really needed? + FreePublisher; inherited Destroy; end; @@ -501,5 +501,3 @@ function TBoldNodeDescriptionCom.GetContextType: IBoldElementTypeInfo; initialization end. - - diff --git a/Source/ClientGuiCom/ControlPacks/BoldNumericControlPackCom.pas b/Source/ClientGuiCom/ControlPacks/BoldNumericControlPackCom.pas index f5703dc..85d7d0f 100644 --- a/Source/ClientGuiCom/ControlPacks/BoldNumericControlPackCom.pas +++ b/Source/ClientGuiCom/ControlPacks/BoldNumericControlPackCom.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldNumericControlPackCom; {$DEFINE BOLDCOMCLIENT} {Clientified 2002-08-05 14:59:57} @@ -5,15 +8,13 @@ interface uses - BoldDefs, - BoldSubscription, - BoldComObjectSpace_TLB, BoldClientElementSupport, BoldComClient, - BoldControlPackCom; - -//TODO: Implement AsFloatRenderer. -//TODO: Find default numeric representation for class + BoldClientElementSupport, + BoldComClient, + BoldComObjectSpace_TLB, + BoldControlPackCom, + BoldDefs; -type +type {Forward declarations} TBoldIntegerRendererDataCom = class; TBoldAsIntegerRendererCom = class; @@ -50,7 +51,7 @@ TBoldAsIntegerRendererCom = class(TBoldSingleRendererCom) class function DefaultRenderer: TBoldAsIntegerRendererCom; function DefaultIsChanged(RendererData: TBoldIntegerRendererDataCom; const NewValue: Integer; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: IBoldExternalVariableList): Boolean; function DefaultMayModify(Element: IBoldElement; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: IBoldExternalVariableList; Subscriber: TBoldComClientSubscriber): Boolean; override; - procedure MakeUptodateAndSubscribe(Element: IBoldElement; RendererData: TBoldFollowerDataCom; FollowerController: TBoldFollowerControllerCom; Subscriber: TBoldComClientSubscriber); override; + procedure MakeUpToDateAndSubscribe(Element: IBoldElement; RendererData: TBoldFollowerDataCom; FollowerController: TBoldFollowerControllerCom; Subscriber: TBoldComClientSubscriber); override; function IsChanged(RendererData: TBoldIntegerRendererDataCom; const NewValue: Integer; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: IBoldExternalVariableList): Boolean; published property OnGetAsInteger: TBoldGetAsIntegerEventCom read FOnGetAsInteger write FOnGetAsInteger; @@ -80,8 +81,6 @@ implementation uses SysUtils, - BoldRev, - BoldUtils, BoldGuiResourceStringsCom, {!! DO NOT REMOVE !! BoldAttributes ,} BoldControlPackDefs; @@ -101,11 +100,10 @@ function TBoldAsIntegerRendererCom.GetRendererDataClass: TBoldRendererDataClassC end; function TBoldAsIntegerRendererCom.DefaultMayModify(Element: IBoldElement; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: IBoldExternalVariableList; Subscriber: TBoldComClientSubscriber): Boolean; -{$IFNDEF BOLDCOMCLIENT} // defaultMayModify +{$IFNDEF BOLDCOMCLIENT} var ValueElement: IBoldElement; begin - // Note! We don't call inherited DefaultMayModify to prevent evaluation of expression two times! ValueElement := GetExpressionAsDirectElement(Element, Expression, VariableList); result := (ValueElement is TBANumeric) and ValueElement.ObserverMayModify(Subscriber) end; @@ -117,7 +115,7 @@ function TBoldAsIntegerRendererCom.DefaultMayModify(Element: IBoldElement; Repre function TBoldAsIntegerRendererCom.DefaultGetAsIntegerAndSubscribe(Element: IBoldElement; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: IBoldExternalVariableList; Subscriber: TBoldComClientSubscriber): Integer; var - {$IFDEF BOLDCOMCLIENT} // defaultGet + {$IFDEF BOLDCOMCLIENT} el: IBoldElement; attr: IBoldAttribute; {$ELSE} @@ -127,7 +125,7 @@ function TBoldAsIntegerRendererCom.DefaultGetAsIntegerAndSubscribe(Element: IBol Result := 0; if Assigned(Element) then begin - {$IFDEF BOLDCOMCLIENT} // defaultGet + {$IFDEF BOLDCOMCLIENT} if assigned(Subscriber) then el := Element.EvaluateAndSubscribeToExpression(Expression, Subscriber.ClientId, Subscriber.SubscriberId, false, false) else @@ -159,12 +157,12 @@ function TBoldAsIntegerRendererCom.DefaultGetAsIntegerAndSubscribe(Element: IBol procedure TBoldAsIntegerRendererCom.DefaultSetAsInteger(Element: IBoldElement; const Value: Integer; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: IBoldExternalVariableList); var ValueElement: IBoldElement; - {$IFDEF BOLDCOMCLIENT} // defaultSet + {$IFDEF BOLDCOMCLIENT} Attr: IBoldAttribute; {$ENDIF} begin ValueElement := GetExpressionAsDirectElement(Element, Expression, VariableList); - {$IFDEF BOLDCOMCLIENT} // defaultSet + {$IFDEF BOLDCOMCLIENT} if assigned(ValueElement) and (ValueElement.QueryInterface(IBoldAttribute, attr) = S_OK) then attr.AsVariant := Value else @@ -248,7 +246,7 @@ function TBoldIntegerFollowerControllerCom.GetEffectiveAsIntegerRenderer: TBoldA if Assigned(Renderer) then Result := Renderer else - Result := DefaultAsIntegerRenderer; //FIXME + Result := DefaultAsIntegerRenderer; end; procedure TBoldIntegerFollowerControllerCom.MakeClean(Follower: TBoldFollowerCom); @@ -283,4 +281,3 @@ finalization FreeAndNil(DefaultAsIntegerRenderer); end. - diff --git a/Source/ClientGuiCom/ControlPacks/BoldStringControlPackCom.pas b/Source/ClientGuiCom/ControlPacks/BoldStringControlPackCom.pas index 2367cb4..333a194 100644 --- a/Source/ClientGuiCom/ControlPacks/BoldStringControlPackCom.pas +++ b/Source/ClientGuiCom/ControlPacks/BoldStringControlPackCom.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldStringControlPackCom; {$DEFINE BOLDCOMCLIENT} {Clientified 2002-08-05 13:13:02} @@ -5,14 +8,18 @@ interface uses - Graphics, + // VCL Classes, + Graphics, Windows, - BoldDefs, + + // Bold + BoldClientElementSupport, + BoldComClient, + BoldComObjectSpace_TLB, BoldContainers, - BoldComObjectSpace_TLB, BoldClientElementSupport, BoldComClient, BoldControlPackCom, - BoldSubscription; + BoldDefs; type {Forward declaration of classes} @@ -70,7 +77,7 @@ TBoldAsStringRendererCom = class(TBoldSingleRendererCom) function IsChanged(RendererData: TBoldStringRendererDataCom; NewValue: string; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: IBoldExternalVariableList): Boolean; procedure SetFont(Element: IBoldElement; EffectiveFont, Font: TFont; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: IBoldExternalVariableList); procedure SetColor(Element: IBoldElement; var EffectiveColor: TColor; Color: TColor; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: IBoldExternalVariableList); - procedure MakeUptodateAndSubscribe(Element: IBoldElement; RendererData: TBoldFollowerDataCom; FollowerController: TBoldFollowerControllerCom; Subscriber: TBoldComClientSubscriber); override; + procedure MakeUpToDateAndSubscribe(Element: IBoldElement; RendererData: TBoldFollowerDataCom; FollowerController: TBoldFollowerControllerCom; Subscriber: TBoldComClientSubscriber); override; procedure MultiMakeUpToDateAndSubscribe(Elements: TBoldClientableListCom; Subscribers: TBoldObjectArray; RendererData: TBoldObjectArray; FollowerController: TBoldFollowerControllerCom); procedure DefaultMakeUptodateAndSetMayModifyAndSubscribe(Element: IBoldElement; RendererData: TBoldFollowerDataCom; FollowerController: TBoldStringFollowerControllerCom; Subscriber: TBoldComClientSubscriber); virtual; published @@ -101,7 +108,7 @@ TBoldStringFollowerControllerCom = class(TBoldSingleFollowerControllerCom) function GetCurrentAsString(Follower: TBoldFollowerCom): string; procedure SetAsString(Value: string; Follower: TBoldFollowerCom); function ValidateCharacter(C: AnsiChar; Follower: TBoldFollowerCom): Boolean; - function ValidateString(Value: string; Follower: TBoldFollowerCom): Boolean; + function ValidateString(const Value: string; Follower: TBoldFollowerCom): Boolean; procedure SetFont(EffectiveFont, Font: tFont; Follower: TBoldFollowerCom); procedure SetColor(var EffectiveColor: tColor; COLOR: tColor; Follower: TBoldFollowerCom); procedure MayHaveChanged(NewValue: string; Follower: TBoldFollowerCom); @@ -116,12 +123,13 @@ implementation uses SysUtils, + BoldSubscription, BoldControlPackDefs, {$IFNDEF BOLDCOMCLIENT} - BoldComObjectSpace_TLB, // IFNDEF BOLDCOMCLIENT + BoldComObjectSpace_TLB, BoldDomainElement, {$ELSE} - Variants, // IFDEF BOLDCOMCLIENT + Variants, {$ENDIF} BoldRev; @@ -168,7 +176,7 @@ function TBoldStringFollowerControllerCom.ValidateCharacter(C: AnsiChar; Followe Result := EffectiveAsStringRenderer.ValidateCharacter(Follower.Element, C, Representation, Expression, VariableList); end; -function TBoldStringFollowerControllerCom.ValidateString(Value: string; Follower: TBoldFollowerCom): Boolean; +function TBoldStringFollowerControllerCom.ValidateString(const Value: string; Follower: TBoldFollowerCom): Boolean; begin Result := EffectiveAsStringRenderer.ValidateString(Follower.Element, Value, Representation, Expression, VariableList); end; @@ -201,7 +209,7 @@ procedure TBoldStringFollowerControllerCom.MakeClean(Follower: TBoldFollowerCom) begin if ValidateString(GetCurrentAsString(Follower), Follower) then begin - ReleaseChangedValue(Follower); // note, must do first, since set can change element + ReleaseChangedValue(Follower); SetAsString(GetCurrentAsString(Follower), Follower); end else @@ -252,7 +260,6 @@ procedure TBoldStringFollowerControllerCom.SetNilStringRepresentation(const Valu var Left: Integer; begin - // Adjust for alignment case Alignment of taLeftJustify: Left := Margins.X + Rect.Left; taRightJustify: Left := (Rect.Right - Rect.Left) - Canvas.TextWidth(S) + Rect.Left - 1 - Margins.X; @@ -278,7 +285,7 @@ procedure TBoldAsStringRendererCom.MakeUpToDateAndSubscribe(Element: IBoldElemen procedure TBoldAsStringRendererCom.DefaultMakeUptodateAndSetMayModifyAndSubscribe(Element: IBoldElement; RendererData: TBoldFollowerDataCom; FollowerController: TBoldStringFollowerControllerCom; Subscriber: TBoldComClientSubscriber); var - {$IFDEF BOLDCOMCLIENT} // defaultMakeUpToDate + {$IFDEF BOLDCOMCLIENT} e: IBoldElement; {$ELSE} E: TBoldIndirectElement; @@ -298,12 +305,12 @@ procedure TBoldAsStringRendererCom.DefaultMakeUptodateAndSetMayModifyAndSubscrib begin if Assigned(Element) then begin - {$IFDEF BOLDCOMCLIENT} // defaultMakeUpToDate + {$IFDEF BOLDCOMCLIENT} if assigned(Subscriber) then e := Element.EvaluateAndSubscribeToExpression(FollowerController.Expression, Subscriber.ClientId, Subscriber.SubscriberId, False, false) else e := Element.EvaluateExpression(FollowerController.Expression); - + if Assigned(E) then begin S := E.StringRepresentation[FollowerController.Representation]; @@ -357,7 +364,7 @@ function TBoldAsStringRendererCom.GetRendererDataClass: TBoldRendererDataClassCo function TBoldAsStringRendererCom.DefaultGetAsStringAndSubscribe(Element: IBoldElement; FollowerController: TBoldStringFollowerControllerCom; Subscriber: TBoldComClientSubscriber): string; var - {$IFDEF BOLDCOMCLIENT} // DefaultGet + {$IFDEF BOLDCOMCLIENT} e: IBoldElement; {$ELSE} E: TBoldIndirectElement; @@ -375,7 +382,7 @@ function TBoldAsStringRendererCom.DefaultGetAsStringAndSubscribe(Element: IBoldE begin if Assigned(Element) then begin - {$IFDEF BOLDCOMCLIENT} // defaultGet + {$IFDEF BOLDCOMCLIENT} if assigned(Subscriber) then e := Element.EvaluateAndSubscribeToExpression(FollowerController.Expression, Subscriber.ClientId, Subscriber.SubscriberId, False, false) else @@ -638,4 +645,3 @@ finalization FreeAndNil(DefaultAsStringRenderer); end. - diff --git a/Source/ClientGuiCom/ControlPacks/BoldViewerControlPackCom.pas b/Source/ClientGuiCom/ControlPacks/BoldViewerControlPackCom.pas index bfec242..a899973 100644 --- a/Source/ClientGuiCom/ControlPacks/BoldViewerControlPackCom.pas +++ b/Source/ClientGuiCom/ControlPacks/BoldViewerControlPackCom.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldViewerControlPackCom; {$DEFINE BOLDCOMCLIENT} {Clientified 2002-08-05 13:13:02} @@ -65,7 +68,7 @@ TBoldAsViewerRendererCom = class(TBoldSingleRendererCom) procedure DefaultSetAsViewer(Element: IBoldElement; Value: TBoldAbstractViewAdapterCom; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: IBoldExternalVariableList); virtual; function DefaultIsChanged(RendererData: TBoldViewerRendererDataCom; NewValue: TBoldAbstractViewAdapterCom; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: IBoldExternalVariableList): Boolean; function IsChanged(RendererData: TBoldViewerRendererDataCom; NewValue: TBoldAbstractViewAdapterCom; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: IBoldExternalVariableList): Boolean; - procedure MakeUptodateAndSubscribe(Element: IBoldElement; RendererData: TBoldFollowerDataCom; FollowerController: TBoldFollowerControllerCom; Subscriber: TBoldComClientSubscriber); override; + procedure MakeUpToDateAndSubscribe(Element: IBoldElement; RendererData: TBoldFollowerDataCom; FollowerController: TBoldFollowerControllerCom; Subscriber: TBoldComClientSubscriber); override; published property OnGetAsViewer: TBoldGetAsViewerCom read FOnGetAsViewer write FOnGetAsViewer; property OnSetAsViewer: TBoldSetAsViewerCom read FOnSetAsViewer write FOnSetAsViewer; @@ -92,8 +95,6 @@ TBoldViewerFollowerControllerCom = class(TBoldSingleFollowerControllerCom) {-- TBoldAbstractViewAdapterCom --} TBoldViewAdapterClassCom = class of TBoldAbstractViewAdapterCom; - - // BCB does not support abstract class methods TBoldAbstractViewAdapterCom = class(TBoldMemoryManagedObject) public constructor Create; virtual; @@ -104,19 +105,19 @@ TBoldAbstractViewAdapterCom = class(TBoldMemoryManagedObject) function Empty: Boolean; virtual; abstract; procedure Clear; virtual; abstract; function HasChanged: Boolean; virtual; abstract; - class function CanReadContent(const ContentType: string): Boolean; virtual; + class function CanReadContent(const ContentType: string): Boolean; virtual; function ContentType: string; virtual; abstract; - class function Description: string; virtual; // How to handle Localizastion? + class function Description: string; virtual; {Clipboard} procedure CopyToClipboard; virtual; abstract; - class function CanPasteFromClipboard(const AcceptedContentType: string): Boolean; virtual; + class function CanPasteFromClipboard(const AcceptedContentType: string): Boolean; virtual; procedure PasteFromClipboard; virtual; abstract; {Streams} procedure LoadFromStream(Stream: TStream); virtual; abstract; procedure SaveToStream(Stream: TStream); virtual; abstract; {Files} - class function DefaultExtension: string; virtual; - class function FileFilter: string; virtual; // How to handle Localizastion? + class function DefaultExtension: string; virtual; + class function FileFilter: string; virtual; class function CanLoadFromFile(const Filename: string): Boolean; virtual; procedure LoadFromFile(const Filename: string); virtual; abstract; procedure SaveToFile(const Filename: string); virtual; abstract; @@ -131,9 +132,8 @@ implementation uses SysUtils, - BoldRev, BoldUtils, - BoldImageBitmapCom; //FIXME Temp! + BoldImageBitmapCom; var DefaultAsViewerRenderer: TBoldAsViewerRendererCom; @@ -182,7 +182,7 @@ function TBoldAsViewerRendererCom.DefaultGetAsViewerAndSubscribe(Element: IBoldE var e: IBoldElement; Stream: TStream; - {$IFDEF BOLDCOMCLIENT} // defaultGet + {$IFDEF BOLDCOMCLIENT} attr: IBoldAttribute; {$ELSE} IndirectElement: TBoldIndirectElement; @@ -206,7 +206,7 @@ function TBoldAsViewerRendererCom.DefaultGetAsViewerAndSubscribe(Element: IBoldE Result := nil; if Assigned(Element) then begin - {$IFDEF BOLDCOMCLIENT} // defaultGet + {$IFDEF BOLDCOMCLIENT} if assigned(Subscriber) then e := Element.EvaluateAndSubscribeToExpression(Expression, Subscriber.ClientId, Subscriber.SubscriberId, false, false) else @@ -268,14 +268,14 @@ procedure TBoldAsViewerRendererCom.DefaultSetAsViewer(Element: IBoldElement; Val var ValueElement: IBoldElement; Stream: TStream; - {$IFDEF BOLDCOMCLIENT} // defaultSet + {$IFDEF BOLDCOMCLIENT} Attr: IBoldAttribute; {$ENDIF} begin ValueElement := GetExpressionAsDirectElement(Element, Expression, VariableList); if Assigned(ValueElement) then begin - {$IFDEF BOLDCOMCLIENT} // DefaultSet + {$IFDEF BOLDCOMCLIENT} ValueElement.QueryInterface(IBoldAttribute, Attr); if Assigned(Value) then begin @@ -406,7 +406,6 @@ procedure TBoldViewerFollowerControllerCom.MakeClean(Follower: TBoldFollowerCom) constructor TBoldAbstractViewAdapterCom.Create; begin - // Left for subclasses to implement end; class procedure TBoldAbstractViewAdapterCom.RegisterViewAdapter(ViewAdapterClass: TBoldViewAdapterClassCom); @@ -467,6 +466,5 @@ initialization finalization FreeAndNil(DefaultAsViewerRenderer); FreeAndNil(ViewAdapterList); - + end. - diff --git a/Source/ClientGuiCom/Core/BoldExceptionHandlersCom.pas b/Source/ClientGuiCom/Core/BoldExceptionHandlersCom.pas index c6bdca6..eca5dda 100644 --- a/Source/ClientGuiCom/Core/BoldExceptionHandlersCom.pas +++ b/Source/ClientGuiCom/Core/BoldExceptionHandlersCom.pas @@ -1,10 +1,13 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldExceptionHandlersCom; interface uses Classes, - BoldComObjectSpace_TLB, BoldClientElementSupport, BoldComClient, + BoldComObjectSpace_TLB, SysUtils; type @@ -29,14 +32,12 @@ TBoldExceptionHandlerCom = class(TComponent) published property OnApplyException: TBoldApplyExceptionEventCom read fOnApplyException write fOnApplyException; property OnDisplayException: TBoldDisplayExceptionEventCom read fOnDisplayException write fOnDisplayException; - end; + end; implementation uses - BoldRev, - BoldUtils, - Controls; + BoldRev; var G_BoldExceptionHandlers: TList = nil; @@ -64,48 +65,23 @@ destructor TBoldExceptionHandlerCom.Destroy; end; class function TBoldExceptionHandlerCom.FindExceptionHandler(Component: TComponent): TBoldExceptionHandlerCom; -function OwningComponent(Component: TComponent): TComponent; -begin -//Find topmost owning component - Result := Component; - while Assigned(Result) and Assigned(Result.Owner) do - Result := Result.Owner; -end; -function ParentControl(Component: TComponent): TWinControl; -begin -//Find topmost parent control - Result := nil; - if Component is TWinControl then - begin - Result := TWinControl(Component); - while Assigned(Result.Parent) do - Result := Result.Parent; - end; -end; var i: integer; - ExceptionHandlerOwner: TComponent; begin - //Find matching exception handler result := nil; if assigned(G_BoldExceptionHandlers) then for i := 0 to G_BoldExceptionHandlers.Count - 1 do - begin - ExceptionHandlerOwner := TBoldExceptionHandlerCom(G_BoldExceptionHandlers[i]).Owner; - if (ExceptionHandlerOwner = OwningComponent(Component)) or - (ExceptionHandlerOwner = ParentControl(Component)) then + if TBoldExceptionHandlerCom(G_BoldExceptionHandlers[i]).Owner = Component.Owner then begin result := TBoldExceptionHandlerCom(G_BoldExceptionHandlers[i]); exit; end; - end; end; procedure TBoldExceptionHandlerCom.HandleApplyException(E: Exception; Component: TComponent; Elem: IBoldElement; var Discard: Boolean; var HandledByUser: boolean); begin - // Note: Discard must be set by caller, as there might be no matching exception handler - // to set discard! + HandledByUser := Assigned(fOnApplyException); if HandledByUser then OnApplyException(E, Component, Elem, Discard); diff --git a/Source/ClientGuiCom/Core/BoldGuiResourceStringsCom.pas b/Source/ClientGuiCom/Core/BoldGuiResourceStringsCom.pas index 8726330..d2dd6fe 100644 --- a/Source/ClientGuiCom/Core/BoldGuiResourceStringsCom.pas +++ b/Source/ClientGuiCom/Core/BoldGuiResourceStringsCom.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldGuiResourceStringsCom; interface @@ -19,8 +22,6 @@ interface SCannotChangeStateWithModifiedValue = 'Can''t Change State with Modified Value'; SValueReadOnly = 'Can''t change value. Value is read only'; - -// Navigator hints SNavHintFirst = 'First'; SNavHintPrior = 'Prior'; SNavHintNext = 'Next'; diff --git a/Source/ClientGuiCom/IDE/BoldAwareGuiComReg.pas b/Source/ClientGuiCom/IDE/BoldAwareGuiComReg.pas index 4ba8e75..359e2d1 100644 --- a/Source/ClientGuiCom/IDE/BoldAwareGuiComReg.pas +++ b/Source/ClientGuiCom/IDE/BoldAwareGuiComReg.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldAwareGuiComReg; {$DEFINE BOLDCOMCLIENT} {Clientified 2002-08-05 13:13:02} @@ -9,24 +12,23 @@ procedure Register; implementation uses - BoldRev, Classes, DesignIntf, BoldDefs, BoldAbstractPropertyEditors, BoldComPropertyEditors, BoldGridPropertyEditorsCom, -{$IFNDEF BOLDCOMCLIENT} // uses - BoldHandlesCom, // IFNDEF BOLDCOMCLIENT - BoldExceptionHandlersCom, // IFNDEF BOLDCOMCLIENT - BoldAbstractListHandleCom, // IFNDEF BOLDCOMCLIENT - BoldComboBoxPropertyEditors, // IFNDEF BOLDCOMCLIENT - BoldControlPackPropertyEditors, // IFNDEF BOLDCOMCLIENT - - BoldMLRenderersCom, // fixthis // IFNDEF BOLDCOMCLIENT - BoldDataSetCom, // IFNDEF BOLDCOMCLIENT - BoldDataSetPropertyEditors, // IFNDEF BOLDCOMCLIENT - BoldDragDropTargetCom, // IFNDEF BOLDCOMCLIENT +{$IFNDEF BOLDCOMCLIENT} + BoldHandlesCom, + BoldExceptionHandlersCom, + BoldAbstractListHandleCom, + BoldComboBoxPropertyEditors, + BoldControlPackPropertyEditors, + + BoldMLRenderersCom, + BoldDataSetCom, + BoldDataSetPropertyEditors, + BoldDragDropTargetCom, {$ENDIF} BoldPropertiesControllerPropertyEditorsCom, BoldPropertiesControllerCom, @@ -60,16 +62,14 @@ implementation procedure RegisterEditors; begin - //TBoldRendererCom RegisterPropertyEditor(TypeInfo(TBoldSubscribeCom), nil, '', TBoldElementCOMSubscribeMethodProperty); RegisterPropertyEditor(TypeInfo(TBoldHoldsChangedValueCom), nil, '', TBoldCOMMethodNoPurposeProperty); RegisterPropertyEditor(TypeInfo(TBoldReleaseChangedValueCom), nil, '', TBoldCOMMethodNoPurposeProperty); RegisterPropertyEditor(TypeInfo(TBoldMayModifyCom), nil, '', TBoldCOMMethodNoPurposeProperty); - {$IFNDEF BOLDCOMCLIENT} // register editors + {$IFNDEF BOLDCOMCLIENT} + - // Register property editors - // All properties of type TBoldElementHandleCom named BoldHandle will be displayed RED if prop not set RegisterPropertyEditor(TypeInfo(TBoldElementHandleCom), TPersistent, 'BoldHandle', TBoldComponentPropertyIndicateMissing); RegisterPropertyEditor(TypeInfo(TBoldAbstractListHandleCom), TBoldComboBoxCom, 'BoldListHandleCom', TBoldComponentPropertyIndicateMissing); @@ -77,25 +77,17 @@ procedure RegisterEditors; RegisterPropertyEditor(TypeInfo(integer), TBoldFollowerControllerCom, 'Representation', TBoldRepresentationProperty); RegisterPropertyEditor(TypeInfo(TBoldRendererCom), TBoldFollowerControllerCom, 'Renderer', TBoldRendererComponentProperty); - // Note: registering for TPersistent screws up, as all string-properties will get an ellipsis! - // v the below line doesn't work, but is left as a reminder. - // RegisterPropertyEditor(TypeInfo(TBoldExpression), TPersistent, '', TBoldOCLExpressionProperty); - // ^ the above line doesn't work, but is left as a reminder. + + RegisterPropertyEditor(TypeInfo(TBoldExpression), TBoldFollowerControllerCom, 'Expression', TBoldOCLExpressionForFollowerControllersProperty); RegisterPropertyEditor(TypeInfo(TBoldSingleFollowerControllerCom), nil, '', TBoldSingleFollowerControllerEditor); RegisterPropertyEditor(TypeInfo(TBoldTreeFollowerControllerCom), nil, '', TBoldTreeFollowerControllerEditor); - - //TBoldAsStringRendererCom RegisterPropertyEditor(TypeInfo(TBoldGetAsStringCom), nil, '', TBoldGetAsStringMethodProperty); - //TBoldAsCheckBoxRenderer RegisterPropertyEditor(TypeInfo(TBoldGetAsCheckBoxStateCom), nil, '', TBoldGetAsCheckBoxStateMethodProperty); - //TBoldAsIntegerRendererCom RegisterPropertyEditor(TypeInfo(TBoldGetAsIntegerEventCom), nil, '', TBoldGetAsIntegerEventMethodProperty); - //TBoldAsFloatRendererCom RegisterPropertyEditor(TypeInfo(TBoldGetAsFloatEventCom), nil, '', TBoldGetAsFloatEventMethodProperty); - //TBoldAsViewerRendererCom RegisterPropertyEditor(TypeInfo(TBoldGetAsViewerCom), nil, '', TBoldGetAsViewerMethodProperty); RegisterPropertyEditor(TypeInfo(String), TBoldNodeDescriptionCom, 'ContextTypeName', TBoldTypeNameSelectorPropertyForTreeFollowerController); @@ -104,8 +96,6 @@ procedure RegisterEditors; RegisterPropertyEditor(TypeInfo(String), TBoldComboBoxCom, 'BoldSetValueExpression', TBoldOCLExpressionForComboBoxSetValueExpression); RegisterPropertyEditor(TypeInfo(String), TBoldDropTargetCom, 'NodeSelectionExpression', TBoldOCLExpressionForOCLComponent); - - // Register Component editors {Renderer editors} RegisterComponentEditor(TBoldAsStringRendererCom, TBoldAsStringRendererEditor); RegisterComponentEditor(TBoldAsCheckBoxStateRendererCom, TBoldAsCheckboxStateRendererEditor); @@ -128,14 +118,14 @@ procedure RegisterEditors; RegisterComponentEditor(TBoldPropertiesControllerCom,TBoldPropertiesControllerComponentEditorCom); RegisterPropertyEditor(TypeInfo(String), TBoldDrivenPropertyCom, 'PropertyName', TPropertyNamePropertyCom); RegisterPropertyEditor(TypeInfo(TComponent), TBoldDrivenPropertyCom, 'VCLComponent', TVCLComponentPropertyCom); -{$IFNDEF BOLDCOMCLIENT} // registerEditors +{$IFNDEF BOLDCOMCLIENT} RegisterComponentEditor(TBoldAbstractDataset, TBoldDataSetEditor); {$ENDIF} end; procedure RegisterComponentsOnPalette; begin -{$IFNDEF BOLDCOMCLIENT} // RegisterComponents +{$IFNDEF BOLDCOMCLIENT} RegisterComponents(BOLDPAGENAME_MISC, [ TBoldDataSetCom, @@ -143,7 +133,7 @@ procedure RegisterComponentsOnPalette; ]); {$ENDIF} -{$IFDEF BOLDCOMCLIENT} // RegisterComponents +{$IFDEF BOLDCOMCLIENT} RegisterComponents('Bold COM Controls', {$ELSE} RegisterComponents(BOLDPAGENAME_CONTROLS, @@ -167,12 +157,11 @@ procedure RegisterComponentsOnPalette; TBoldImageCom, TBoldPropertiesControllerCom, TBoldStringsPropertyControllerCom, - //Renderers TBoldAsStringRendererCom, TBoldAsCheckBoxStateRendererCom, TBoldAsIntegerRendererCom, TBoldAsFloatRendererCom, - {$IFNDEF BOLDCOMCLIENT} // Register Components + {$IFNDEF BOLDCOMCLIENT} TBoldAsMLStringRendererCom, TBoldDropTargetCom, {$ENDIF} @@ -182,10 +171,8 @@ procedure RegisterComponentsOnPalette; procedure Register; begin - begin - RegisterComponentsOnPalette; - RegisterEditors; - end; + RegisterComponentsOnPalette; + RegisterEditors; end; end. diff --git a/Source/ClientGuiCom/IDE/BoldCOMPropertyEditors.pas b/Source/ClientGuiCom/IDE/BoldCOMPropertyEditors.pas index b955d18..c1bac76 100644 --- a/Source/ClientGuiCom/IDE/BoldCOMPropertyEditors.pas +++ b/Source/ClientGuiCom/IDE/BoldCOMPropertyEditors.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldCOMPropertyEditors; interface diff --git a/Source/ClientGuiCom/IDE/BoldGridPropertyEditorsCom.pas b/Source/ClientGuiCom/IDE/BoldGridPropertyEditorsCom.pas index 873c45d..e5f4e23 100644 --- a/Source/ClientGuiCom/IDE/BoldGridPropertyEditorsCom.pas +++ b/Source/ClientGuiCom/IDE/BoldGridPropertyEditorsCom.pas @@ -1,18 +1,31 @@ -// MANUALLY UPDATED + +{ Global compiler directives } +{$include bold.inc} unit BoldGridPropertyEditorsCom; interface uses + {$IFDEF BOLD_DELPHI5_OR_LATER} + Contnrs, + {$ENDIF} + {$IFDEF BOLD_DELPHI6_OR_LATER} DesignIntf, DesignEditors, + {$ELSE} + DsgnIntf, + {$ENDIF} TypInfo; type { TBoldColumnsEditor } TBoldColumnsEditorCom = class(TComponentEditor) private + {$IFDEF BOLD_DELPHI6_OR_LATER} procedure EditPropertyColumns(const PropertyEditor: IProperty); + {$ELSE} + procedure EditPropertyColumns(PropertyEditor: TPropertyEditor); + {$ENDIF} public procedure EmptyColumns; procedure CreateDefaultColumns; @@ -26,7 +39,6 @@ implementation uses SysUtils, - BoldRev, BoldUtils, BoldGridCom; @@ -35,7 +47,11 @@ TBoldExposedCustomGridCom = class(TBoldCustomGridCom); {---TBoldColumnsEditor---} +{$IFDEF BOLD_DELPHI6_OR_LATER} procedure TBoldColumnsEditorCom.EditPropertyColumns(const PropertyEditor: IProperty); +{$ELSE} +procedure TBoldColumnsEditorCom.EditPropertyColumns(PropertyEditor: TPropertyEditor); +{$ENDIF} begin if SameText(PropertyEditor.GetName, 'Columns') then PropertyEditor.Edit; @@ -43,18 +59,30 @@ procedure TBoldColumnsEditorCom.EditPropertyColumns(const PropertyEditor: IPrope procedure TBoldColumnsEditorCom.Edit; var +{$IFDEF BOLD_DELPHI6_OR_LATER} Components: IDesignerSelections; +{$ELSE} + Components: TDesignerSelectionList; +{$ENDIF} begin +{$IFDEF BOLD_DELPHI6_OR_LATER} Components := TDesignerSelections.Create; +{$ELSE} + Components := TDesignerSelectionList.Create; +{$ENDIF} try Components.Add(Component); GetComponentProperties(Components, tkProperties, Designer, - EditPropertyColumns, - nil); + EditPropertyColumns + {$IFDEF BOLD_DELPHI6_OR_LATER}, nil{$ENDIF}); finally + {$IFDEF BOLD_DELPHI6_OR_LATER} Components := nil; + {$ELSE} + Components.Free; + {$ENDIF} end; end; @@ -72,7 +100,6 @@ procedure TBoldColumnsEditorCom.EmptyColumns; begin DeleteAllColumns; AddColumn; - // This is done because the grid screws up the column widths AddColumn; Columns[1].Free; end; @@ -83,7 +110,7 @@ procedure TBoldColumnsEditorCom.ExecuteVerb(Index: Integer); case Index of 0: Edit; 1:{ CreateDefaultColumns; - 2: }EmptyColumns; // manual fix + 2: }EmptyColumns; end; end; @@ -92,13 +119,13 @@ function TBoldColumnsEditorCom.GetVerb(Index: Integer): string; case index of 0: Result := '&Edit Columns'; 1:{ Result := 'Create Default Columns'; - 2: }Result := 'Clear all Columns'; // manual fix + 2: }Result := 'Clear all Columns'; end; end; function TBoldColumnsEditorCom.GetVerbCount: Integer; begin - Result := 2; // manual fix + Result := 2; end; initialization diff --git a/Source/ClientGuiCom/IDE/BoldPropertiesControllerPropertyEditorsCom.pas b/Source/ClientGuiCom/IDE/BoldPropertiesControllerPropertyEditorsCom.pas index d96f31a..0727c28 100644 --- a/Source/ClientGuiCom/IDE/BoldPropertiesControllerPropertyEditorsCom.pas +++ b/Source/ClientGuiCom/IDE/BoldPropertiesControllerPropertyEditorsCom.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldPropertiesControllerPropertyEditorsCom; interface @@ -5,22 +8,19 @@ interface uses Classes, DesignEditors, - DesignIntf, + DesignIntf, BoldAbstractPropertyEditors; type - // A Property editor for the PropertyName property. - // It lists all meaningful properties of "Component" including properties of "sub-components" - // It has currently some trouble with collections and will not show panels[0] for example + + TPropertyNamePropertyCom = class(TBoldStringProperty) public function GetAttributes: TPropertyAttributes; override; procedure GetValues(Proc: TGetStrProc); override; end; - // A Property editor for VCLComponent property - // It is based on the TComponentProperty which lists all components of the form - // In addition to those it will also list the form so we can control its properties ! + TVCLComponentPropertyCom = class(TBoldComponentProperty) public procedure GetValues(Proc: TGetStrProc); override; @@ -40,7 +40,6 @@ implementation uses SysUtils, - BoldRev, TypInfo, BoldControlsDefs, BoldPropertiesControllerCom; @@ -99,7 +98,7 @@ procedure TPropertyNamePropertyCom.GetValues(Proc: TGetStrProc); begin if PropCount < 1 then exit; - SelectedComponent := GetComponent(0) as TBoldDrivenPropertyCom; //we don't allow multiselect + SelectedComponent := GetComponent(0) as TBoldDrivenPropertyCom; if Assigned(SelectedComponent) and Assigned(SelectedComponent.VCLComponent) then DeclareProperties(SelectedComponent.VCLComponent,SelectedComponent.VCLComponent.ClassInfo,''); end; @@ -108,7 +107,7 @@ procedure TPropertyNamePropertyCom.GetValues(Proc: TGetStrProc); procedure TVCLComponentPropertyCom.GetValues(Proc: TGetStrProc); begin - Proc(TBoldDrivenPropertyCom(GetComponent(0)).PropertiesController.Owner.Name); // Add the Form's name to available components + Proc(TBoldDrivenPropertyCom(GetComponent(0)).PropertiesController.Owner.Name); inherited; end; @@ -116,7 +115,6 @@ procedure TVCLComponentPropertyCom.SetValue(const Value: string); var Component: TComponent; begin - // Special case for the form if Value = TBoldDrivenPropertyCom(GetComponent(0)).PropertiesController.Owner.Name then begin Component := TBoldDrivenPropertyCom(GetComponent(0)).PropertiesController.Owner; diff --git a/Source/ClientHandlesCom/Core/BoldAbstractListHandleCom.pas b/Source/ClientHandlesCom/Core/BoldAbstractListHandleCom.pas index cf69da8..dd9f8c4 100644 --- a/Source/ClientHandlesCom/Core/BoldAbstractListHandleCom.pas +++ b/Source/ClientHandlesCom/Core/BoldAbstractListHandleCom.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldAbstractListHandleCom; interface @@ -50,7 +53,6 @@ implementation uses SysUtils, - BoldComHandlesConst, BoldDefs; {-- TBoldAbstractListHandleCom ------------------------------------------------} @@ -117,7 +119,7 @@ procedure TBoldAbstractListHandleCom.Next; if GetHasNext then CurrentIndex := CurrentIndex + 1 else - raise EBold.Create(sNoNextElement); + raise EBold.Create('No next element'); end; procedure TBoldAbstractListHandleCom.Prior; @@ -125,13 +127,13 @@ procedure TBoldAbstractListHandleCom.Prior; if GetHasPrior then CurrentIndex := CurrentIndex - 1 else - raise EBold.Create(sNoPrevElement); + raise EBold.Create('No previous element'); end; procedure TBoldAbstractListHandleCom.RemoveCurrentElement; begin if CurrentIndex = -1 then - raise EBold.Create(sNoCurrentElement) + raise EBold.Create('No current element') else if HasHandleOnServer then List.RemoveByIndex(CurrentIndex); @@ -154,4 +156,6 @@ function TBoldAbstractListHandleCom.GetMutableList: IBoldList; result := nil; end; +initialization + end. diff --git a/Source/ClientHandlesCom/Core/BoldClientElementSupport.pas b/Source/ClientHandlesCom/Core/BoldClientElementSupport.pas index c9757be..e528b34 100644 --- a/Source/ClientHandlesCom/Core/BoldClientElementSupport.pas +++ b/Source/ClientHandlesCom/Core/BoldClientElementSupport.pas @@ -1,12 +1,16 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldClientElementSupport; interface - uses BoldSubscription, BoldComObjectSpace_TLB; type + + TBoldElementCompareCom = function (Item1, Item2: IBoldElement): Integer of object; TBoldElementSubscribeCom = procedure (Element: IBoldElement; Subscriber: TBoldSubscriber) of object; TBoldElementFilterCom = function (Element: IBoldElement): Boolean of object; @@ -24,8 +28,13 @@ interface property ContextType: IBoldElementTypeInfo read GetContextType; property Expression: String read GetExpression write SetExpression; end; - + implementation +uses + BoldRev; + +initialization + end. diff --git a/Source/ClientHandlesCom/Core/BoldCursorHandleCom.pas b/Source/ClientHandlesCom/Core/BoldCursorHandleCom.pas index 316d243..3ea90b1 100644 --- a/Source/ClientHandlesCom/Core/BoldCursorHandleCom.pas +++ b/Source/ClientHandlesCom/Core/BoldCursorHandleCom.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldCursorHandleCom; interface @@ -36,8 +39,6 @@ implementation BoldComObjectSpace, BoldComObjectSpace_TLB, BoldDefs, - ComHandlesConst, - BoldComHandlesConst, BoldComUtils; { TBoldCursorHandleCom } @@ -50,16 +51,13 @@ destructor TBoldCursorHandleCom.Destroy; procedure TBoldCursorHandleCom.ClearAllValues; begin - // from TBoldElementHandleCom FDynamicBoldType := nil; FStaticBoldType := nil; FStaticSystemTypeInfo := nil; FValue := nil; FHandleId := 0; - // from TBoldNonSystemHandleCom - // from TBoldRootedHandleCom + FStaticRootType := nil; - // from TBoldAbstractListHandleCom FCount := 0; FCurrentBoldObject := nil; FCurrentIndex := -1; @@ -79,7 +77,7 @@ procedure TBoldCursorHandleCom.SetAutoFirst(Value: Boolean); if Value <> AutoFirst then begin if not OwnsHandleOnServer then - raise EBold.Create(sAutoFirstIsReadOnly); + raise EBold.Create('AutoFirst is read-only'); FAutoFirst := Value; LocalValueChanged; end; @@ -102,16 +100,16 @@ procedure TBoldCursorHandleCom.ValuesFromServer; FListElementType, NamedValues); - FHandleId := BoldGetNamedValue(NamedValues, nv_HandleId); - FCount := BoldGetNamedValue(NamedValues, nv_Count); + FHandleId := BoldGetNamedValue(NamedValues, 'HandleId'); + FCount := BoldGetNamedValue(NamedValues, 'Count'); if not OwnsHandleOnServer then begin - FEnabled := BoldGetNamedValue(NamedValues, nv_Enabled); - FRootTypeName := BoldGetNamedValue(NamedValues, nv_RootTypeName); - FSubscribe := BoldGetNamedValue(NamedValues, nv_Subscribe); - FCurrentIndex := BoldGetNamedValue(NamedValues, nv_CurrentIndex); - FAutoFirst := BoldGetNamedValue(NamedValues, nv_AutoFirst); + FEnabled := BoldGetNamedValue(NamedValues, 'Enabled'); + FRootTypeName := BoldGetNamedValue(NamedValues, 'RootTypeName'); + FSubscribe := BoldGetNamedValue(NamedValues, 'Subscribe'); + FCurrentIndex := BoldGetNamedValue(NamedValues, 'CurrentIndex'); + FAutoFirst := BoldGetNamedValue(NamedValues, 'AutoFirst'); end else AdjustCurrentIndex; @@ -142,13 +140,13 @@ procedure TBoldCursorHandleCom.ValuesToServer; else RootHandleId := 0; NamedValues := BoldCreateNamedValues( - [nv_StaticSystemHandle, - nv_Enabled, - nv_RootHandle, - nv_RootTypeName, - nv_Subscribe, - nv_CurrentIndex, - nv_AutoFirst], + ['StaticSystemHandle', + 'Enabled', + 'RootHandle', + 'RootTypeName', + 'Subscribe', + 'CurrentIndex', + 'AutoFirst'], [StaticSystemHandleId, FEnabled, RootHandleId, @@ -161,7 +159,7 @@ procedure TBoldCursorHandleCom.ValuesToServer; function TBoldCursorHandleCom.ServerHandleClassName: string; begin - result := ServerHandleClassName_CursorHandle; + result := 'TBoldCursorHandle'; end; constructor TBoldCursorHandleCom.Create(Owner: TComponent); @@ -180,4 +178,6 @@ procedure TBoldCursorHandleCom.AdjustCurrentIndex; fCurrentIndex := fList.Count-1; end; +initialization + end. diff --git a/Source/ClientHandlesCom/Core/BoldDerivedHandleCom.pas b/Source/ClientHandlesCom/Core/BoldDerivedHandleCom.pas index 058af4f..bb0afc9 100644 --- a/Source/ClientHandlesCom/Core/BoldDerivedHandleCom.pas +++ b/Source/ClientHandlesCom/Core/BoldDerivedHandleCom.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldDerivedHandleCom; interface @@ -25,7 +28,6 @@ implementation uses BoldComObjectSpace, BoldComObjectSpace_TLB, - ComHandlesConst, BoldComUtils; {-- TBoldDerivedHandleCom --------------------------------------------------------} @@ -38,16 +40,13 @@ destructor TBoldDerivedHandleCom.Destroy; procedure TBoldDerivedHandleCom.ClearAllValues; begin - // from TBoldElementHandleCom FDynamicBoldType := nil; FStaticBoldType := nil; FStaticSystemTypeInfo := nil; FValue := nil; FHandleId := 0; - // from TBoldNonSystemHandleCom - // from TBoldRootedHandleCom + FStaticRootType := nil; - // from TBoldDerivedHandleCom end; @@ -70,12 +69,12 @@ procedure TBoldDerivedHandleCom.ValuesFromServer; DummyList, DummyListType, NamedValues); - FHandleId := BoldGetNamedValue(NamedValues, nv_HandleId); + FHandleId := BoldGetNamedValue(NamedValues,'HandleId'); if not OwnsHandleOnServer then begin - FEnabled := BoldGetNamedValue(NamedValues, nv_Enabled); - FRootTypeName := BoldGetNamedValue(NamedValues, nv_RootTypeName); - FSubscribe := BoldGetNamedValue(NamedValues, nv_Subscribe); + FEnabled := BoldGetNamedValue(NamedValues,'Enabled'); + FRootTypeName := BoldGetNamedValue(NamedValues,'RootTypeName'); + FSubscribe := BoldGetNamedValue(NamedValues,'Subscribe'); end; end; @@ -96,11 +95,11 @@ procedure TBoldDerivedHandleCom.ValuesToServer; else RootHandleId := 0; NamedValues := BoldCreateNamedValues( - [nv_StaticSystemHandle, - nv_Enabled, - nv_RootHandle, - nv_RootTypeName, - nv_Subscribe], + ['StaticSystemHandle', + 'Enabled', + 'RootHandle', + 'RootTypeName', + 'Subscribe'], [StaticSystemHandleId, FEnabled, RootHandleId, @@ -111,7 +110,9 @@ procedure TBoldDerivedHandleCom.ValuesToServer; function TBoldDerivedHandleCom.ServerHandleClassName: string; begin - result := ServerHandleClassName_DerivedHandle; + result := 'TBoldDerivedHandle'; end; +initialization + end. diff --git a/Source/ClientHandlesCom/Core/BoldExpressionHandleCom.pas b/Source/ClientHandlesCom/Core/BoldExpressionHandleCom.pas index d9d8b42..065470f 100644 --- a/Source/ClientHandlesCom/Core/BoldExpressionHandleCom.pas +++ b/Source/ClientHandlesCom/Core/BoldExpressionHandleCom.pas @@ -1,10 +1,11 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldExpressionHandleCom; interface uses - BoldComObjectSpace, - BoldComObjectSpace_TLB, BoldRootedHandlesCom, BoldVariableDefinitionCom; @@ -42,11 +43,11 @@ implementation uses SysUtils, - ComHandlesConst, - BoldComHandlesConst, - BoldUtils, + BoldComObjectSpace, + BoldComObjectSpace_TLB, + BoldComUtils, BoldDefs, - BoldComUtils; + BoldRev; {-- TBoldExpressionHandleCom --------------------------------------------------} @@ -58,18 +59,16 @@ destructor TBoldExpressionHandleCom.Destroy; procedure TBoldExpressionHandleCom.ClearAllValues; begin - // from TBoldElementHandleCom FDynamicBoldType := nil; FStaticBoldType := nil; FStaticSystemTypeInfo := nil; FValue := nil; FHandleId := 0; - // from TBoldNonSystemHandleCom - // from TBoldRootedHandleCom + FStaticRootType := nil; - // from TBoldExpressionHandleCom end; + function TBoldExpressionHandleCom.GetExpression: string; begin if not OwnsHandleOnServer then @@ -103,14 +102,14 @@ procedure TBoldExpressionHandleCom.ValuesFromServer; DummyList, DummyListType, NamedValues); - FHandleId := BoldGetNamedValue(NamedValues, nv_HandleId); + FHandleId := BoldGetNamedValue(NamedValues,'HandleId'); if not OwnsHandleOnServer then begin - FEnabled := BoldGetNamedValue(NamedValues, nv_Enabled); - FRootTypeName := BoldGetNamedValue(NamedValues, nv_RootTypeName); - FSubscribe := BoldGetNamedValue(NamedValues, nv_Subscribe); - FExpression := BoldGetNamedValue(NamedValues, nv_Expression); - fEvaluateInPS := BoldGetNamedValue(NamedValues, nv_EvaluateInPS); + FEnabled := BoldGetNamedValue(NamedValues,'Enabled'); + FRootTypeName := BoldGetNamedValue(NamedValues,'RootTypeName'); + FSubscribe := BoldGetNamedValue(NamedValues,'Subscribe'); + FExpression := BoldGetNamedValue(NamedValues,'Expression'); + fEvaluateInPS := BoldGetNamedValue(NamedValues, 'EvaluateInPS'); end; end; @@ -131,29 +130,30 @@ procedure TBoldExpressionHandleCom.ValuesToServer; else RootHandleId := 0; NamedValues := BoldCreateNamedValues( - [nv_StaticSystemHandle, - nv_Enabled, - nv_RootHandle, - nv_RootTypeName, - nv_Subscribe, - nv_Expression, - nv_EvaluateInPS], + ['StaticSystemHandle', + 'Enabled', + 'RootHandle', + 'RootTypeName', + 'Subscribe', + 'Expression', + 'EvaluateInPS'], [StaticSystemHandleId, - FEnabled, - RootHandleId, - FRootTypeName, - FSubscribe, - FExpression, - fEvaluateInPS]); - ServerElementHandle.SetData(DataFlags, nil, NamedValues); + FEnabled, + RootHandleId, + FRootTypeName, + FSubscribe, + FExpression, + fEvaluateInPS]); + ServerElementHandle.SetData(DataFlags,nil,NamedValues); end; + procedure TBoldExpressionHandleCom.SetExpression(const Value: string); begin if Value <> FExpression then begin if not OwnsHandleOnServer then - raise EBold.CreateFmt(sPropertyIsReadOnly, ['Expression']); // do not localize + raise EBold.Create('Expression is read-only'); FExpression := Value; LocalValueChanged; end; @@ -164,15 +164,16 @@ procedure TBoldExpressionHandleCom.SetVariables(Value: TBoldVariableDefinitionCo if Value <> Variables then begin if not OwnsHandleOnServer then - raise EBold.CreateFmt(sPropertyIsReadOnly, ['Variables']); // do not localize + raise EBold.Create('Variables is read-only'); FVariables := Value; LocalValueChanged; end; end; + function TBoldExpressionHandleCom.ServerHandleClassName: string; begin - result := ServerHandleClassName_ExpressionHandle; + result := 'TBoldExpressionHandle'; end; function TBoldExpressionHandleCom.GetEvaluateInPS: boolean; @@ -187,10 +188,11 @@ procedure TBoldExpressionHandleCom.SetEvaluateInPS(const Value: boolean); if Value <> fEvaluateInPS then begin if not OwnsHandleOnServer then - raise EBold.CreateFmt(sPropertyIsReadOnly, ['EvaluateInPs']); // do not localize + raise EBold.Create('EvaluateInPs is read-only'); fEvaluateInPS := Value; LocalValueChanged; end; end; +initialization end. diff --git a/Source/ClientHandlesCom/Core/BoldHandlesCom.pas b/Source/ClientHandlesCom/Core/BoldHandlesCom.pas index 523f7a5..51c6a35 100644 --- a/Source/ClientHandlesCom/Core/BoldHandlesCom.pas +++ b/Source/ClientHandlesCom/Core/BoldHandlesCom.pas @@ -1,10 +1,12 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldHandlesCom; interface uses Classes, - BoldDefs, BoldSubscription, BoldComObjectSpace, BoldComObjectSpace_TLB, @@ -35,7 +37,6 @@ TBoldElementHandleCom = class(TBoldComImportHandle) OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent); procedure SetServerElementHandle(const ElementHandle: IBoldElementHandle); protected - // server values FDynamicBoldType: IBoldElementTypeInfo; FHandleId: Integer; FStaticBoldType: IBoldElementTypeInfo; @@ -74,7 +75,6 @@ TBoldAbstractSystemHandleCom = class(TBoldElementHandleCom) function GetSystemActive: Boolean; procedure SetIsDefault(Value: Boolean); protected - // server values FBoldSystem: IBoldSystem; FSystemActive: Boolean; function GetOwnsHandleOnServer: Boolean; override; @@ -109,8 +109,6 @@ implementation uses SysUtils, - ComHandlesConst, - BoldUtils, BoldComUtils; const @@ -120,6 +118,7 @@ implementation var G_DefaultBoldSystemHandle: TBoldAbstractSystemHandleCom = nil; + {-- TBoldElementHandleCom -----------------------------------------------------} procedure TBoldElementHandleCom.ConnectionClosing; @@ -200,7 +199,7 @@ function TBoldElementHandleCom.GetHandleId: Integer; DummyList, DummyType, NamedValues); - FHandleId := BoldGetNamedValue(NamedValues, nv_HandleId); + FHandleId := BoldGetNamedValue(NamedValues,'HandleId'); end; Result := FHandleId; end; @@ -377,4 +376,5 @@ procedure TBoldNonSystemHandleCom.StaticSystemHandleSubscriber_Receive( end; end; +initialization end. diff --git a/Source/ClientHandlesCom/Core/BoldListHandleCom.pas b/Source/ClientHandlesCom/Core/BoldListHandleCom.pas index dad31a7..93297aa 100644 --- a/Source/ClientHandlesCom/Core/BoldListHandleCom.pas +++ b/Source/ClientHandlesCom/Core/BoldListHandleCom.pas @@ -1,10 +1,11 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldListHandleCom; interface uses - BoldComObjectSpace, - BoldComObjectSpace_TLB, BoldCursorHandleCom; type @@ -36,11 +37,11 @@ implementation uses SysUtils, - ComHandlesConst, - BoldComHandlesConst, - BoldUtils, + BoldComObjectSpace, + BoldComObjectSpace_TLB, + BoldComUtils, BoldDefs, - BoldComUtils; + BoldRev; {-- TBoldListHandleCom --------------------------------------------------------} @@ -52,16 +53,13 @@ destructor TBoldListHandleCom.Destroy; procedure TBoldListHandleCom.ClearAllValues; begin - // from TBoldElementHandleCom FDynamicBoldType := nil; FStaticBoldType := nil; FStaticSystemTypeInfo := nil; FValue := nil; FHandleId := 0; - // from TBoldNonSystemHandleCom - // from TBoldRootedHandleCom + FStaticRootType := nil; - // from TBoldAbstractListHandleCom FCount := 0; FCurrentBoldObject := nil; FCurrentIndex := -1; @@ -92,7 +90,7 @@ procedure TBoldListHandleCom.SetExpression(const Value: string); if Value <> FExpression then begin if not OwnsHandleOnServer then - raise EBold.CreateFmt(sPropertyIsReadOnly, ['Expression']); // do not localize + raise EBold.Create('Expression is read-only'); FExpression := Value; LocalValueChanged; end; @@ -125,17 +123,17 @@ procedure TBoldListHandleCom.ValuesFromServer; FList, FListElementType, NamedValues); - FHandleId := BoldGetNamedValue(NamedValues, nv_HandleId); - FCount := BoldGetNamedValue(NamedValues, nv_Count); + FHandleId := BoldGetNamedValue(NamedValues,'HandleId'); + FCount := BoldGetNamedValue(NamedValues,'Count'); if not OwnsHandleOnServer then begin - FEnabled := BoldGetNamedValue(NamedValues, nv_Enabled); - FRootTypeName := BoldGetNamedValue(NamedValues, nv_RootTypeName); - FSubscribe := BoldGetNamedValue(NamedValues, nv_Subscribe); - FCurrentIndex := BoldGetNamedValue(NamedValues, nv_CurrentIndex); - FAutoFirst := BoldGetNamedValue(NamedValues, nv_AutoFirst); - FExpression := BoldGetNamedValue(NamedValues, nv_Expression); - fEvaluateInPS := BoldGetNamedValue(NamedValues, nv_EvaluateInPS); + FEnabled := BoldGetNamedValue(NamedValues,'Enabled'); + FRootTypeName := BoldGetNamedValue(NamedValues,'RootTypeName'); + FSubscribe := BoldGetNamedValue(NamedValues,'Subscribe'); + FCurrentIndex := BoldGetNamedValue(NamedValues,'CurrentIndex'); + FAutoFirst := BoldGetNamedValue(NamedValues,'AutoFirst'); + FExpression := BoldGetNamedValue(NamedValues,'Expression'); + fEvaluateInPS := BoldGetNamedValue(NamedValues, 'EvaluateInPS'); end else AdjustCurrentIndex; @@ -159,30 +157,30 @@ procedure TBoldListHandleCom.ValuesToServer; else RootHandleId := 0; NamedValues := BoldCreateNamedValues( - [nv_StaticSystemHandle, - nv_Enabled, - nv_RootHandle, - nv_RootTypeName, - nv_Subscribe, - nv_CurrentIndex, - nv_AutoFirst, - nv_Expression, - nv_EvaluateInPS], + ['StaticSystemHandle', + 'Enabled', + 'RootHandle', + 'RootTypeName', + 'Subscribe', + 'CurrentIndex', + 'AutoFirst', + 'Expression', + 'EvaluateInPS'], [StaticSystemHandleId, - FEnabled, - RootHandleId, - FRootTypeName, - FSubscribe, - FCurrentIndex, - FAutoFirst, - FExpression, - fEvaluateInPS]); + FEnabled, + RootHandleId, + FRootTypeName, + FSubscribe, + FCurrentIndex, + FAutoFirst, + FExpression, + fEvaluateInPS]); ServerElementHandle.SetData(DataFlags,nil,NamedValues); end; function TBoldListHandleCom.ServerHandleClassName: string; begin - result := ServerHandleClassName_ListHandle; + result := 'TBoldListHandle'; end; function TBoldListHandleCom.GetEvaluateInPS: boolean; @@ -197,10 +195,11 @@ procedure TBoldListHandleCom.SetEvaluateInPS(const Value: boolean); if Value <> fEvaluateInPS then begin if not OwnsHandleOnServer then - raise EBold.CreateFmt(sPropertyIsReadOnly, ['EvaluateInPS']); // do not localize + raise EBold.Create('EvaluateInPS is read-only'); fEvaluateInPS := Value; LocalValueChanged; end; end; +initialization end. diff --git a/Source/ClientHandlesCom/Core/BoldPlaceableSubscriberCom.pas b/Source/ClientHandlesCom/Core/BoldPlaceableSubscriberCom.pas index fb2d631..ea94fa5 100644 --- a/Source/ClientHandlesCom/Core/BoldPlaceableSubscriberCom.pas +++ b/Source/ClientHandlesCom/Core/BoldPlaceableSubscriberCom.pas @@ -1,51 +1,10 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldPlaceableSubscriberCom; interface -(* - -uses - Classes, - - BoldSubscription, - BoldComObjectSpace, - BoldHandlesCom; -type -{ TODO: Not implemented at all yet } -{---forward declarations---} - TBoldPlaceableSubscriberCom = class; - {---method types---} -// TBoldSubscribeToElementEvent = procedure (element: IBoldElement; Subscriber: TBoldComClientSubscriber) of object; - TBoldPlaceableSubcriberReceive = procedure(sender: TBoldPlaceableSubscriberCom; Originator: TObject; OriginalEvent: TBoldEvent; - RequestedEvent: TBoldRequestedEvent) of object; - - {---TBoldPlaceableSubscriberCom---} - TBoldPlaceableSubscriberCom = class(TBoldSubscribableComponent) - private - FBoldHandle: TBoldElementHandleCom; - FOnReceive: TBoldPlaceableSubcriberReceive; - FOnSubscribeToElement: TBoldSubscribeToElementEvent; - FHandleSubscriber: TBoldPassthroughSubscriber; - FValueSubscriber: TBoldPassthroughSubscriber; - procedure SetBoldHandle(Value: TBoldElementHandleCom); - procedure HandleSubscriberReceive(Originator: TObject; OriginalEvent: TBoldEvent; - RequestedEvent: TBoldRequestedEvent); - procedure HandleValueChanged; - procedure ValueSubscriberReceive(Originator: TObject; OriginalEvent: TBoldEvent; - RequestedEvent: TBoldRequestedEvent); - protected - procedure Notification(AComponent: TComponent; Operation: TOperation); override; - procedure SubscribeToElement(element: IBoldElement; Subscriber: TBoldComClientSubscriber); virtual; - procedure Receive(Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent); virtual; - public - constructor Create(Owner: TComponent); override; - destructor Destroy; override; - published - property BoldHandle: TBoldElementHandleCom read FBoldHandle write SetBoldHandle; - property OnReceive: TBoldPlaceableSubcriberReceive read FOnReceive write fOnReceive; - property OnSubscribeToElement: TBoldSubscribeToElementEvent read FOnSubscribeToElement write FOnSubscribeToElement; - end; -*) implementation (* uses @@ -118,5 +77,8 @@ procedure TBoldPlaceableSubscriberCom.Receive(Originator: TObject; OriginalEvent if Assigned(FOnReceive) then fOnReceive(Self, Originator, OriginalEvent, RequestedEvent); end; + + +initialization *) end. diff --git a/Source/ClientHandlesCom/Core/BoldReferenceHandleCom.pas b/Source/ClientHandlesCom/Core/BoldReferenceHandleCom.pas index 465b05a..8a5c88d 100644 --- a/Source/ClientHandlesCom/Core/BoldReferenceHandleCom.pas +++ b/Source/ClientHandlesCom/Core/BoldReferenceHandleCom.pas @@ -1,9 +1,11 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldReferenceHandleCom; interface uses - BoldComObjectSpace, BoldComObjectSpace_TLB, BoldHandlesCom; @@ -35,11 +37,10 @@ implementation uses SysUtils, - ComHandlesConst, - BoldComHandlesConst, - BoldUtils, + BoldComObjectSpace, + BoldComUtils, BoldDefs, - BoldComUtils; + BoldRev; {-- TBoldReferenceHandleCom ---------------------------------------------------} @@ -51,14 +52,12 @@ destructor TBoldReferenceHandleCom.Destroy; procedure TBoldReferenceHandleCom.ClearAllValues; begin - // from TBoldElementHandleCom FDynamicBoldType := nil; FStaticBoldType := nil; FStaticSystemTypeInfo := nil; FValue := nil; FHandleId := 0; - // from TBoldNonSystemHandleCom - // from TBoldReferenceHandleCom + end; @@ -81,7 +80,7 @@ procedure TBoldReferenceHandleCom.SetStaticValueTypeName(const Value: string); if Value <> StaticValueTypeName then begin if not OwnsHandleOnServer then - raise EBold.CreateFmt(sPropertyIsReadOnly, ['StaticValueTypeName']); // do not localize + raise EBold.Create('StaticValueTypeName is read-only'); FStaticValueTypeName := Value; LocalValueChanged; end; @@ -92,13 +91,13 @@ procedure TBoldReferenceHandleCom.SetValue(NewValue: IBoldElement); if NewValue <> FValue then begin if not assigned(EffectiveConnectionHandle) then - raise EBold.Createfmt(sSetValueNotAllowedWithoutConnectionHandle, [Classname]); + raise EBold.Createfmt('%s.Setvalue: Now allowed without a connectionHandle', [Classname]); if not EffectiveConnectionHandle.Connected then - raise EBold.Createfmt(sSetValueNotAllowedWithInactiveConnectionHandle, [ClassName]); + raise EBold.Createfmt('%s.Setvalue: Now allowed with an inactive ConnectionHandle', [ClassName]); if not OwnsHandleOnServer then - raise EBold.CreateFmt(sPropertyIsReadOnly, ['Value']); // do not localize + raise EBold.Create('Value is read-only'); FValue := NewValue; LocalValueChanged; end; @@ -124,9 +123,9 @@ procedure TBoldReferenceHandleCom.ValuesFromServer; DummyList, DummyListType, NamedValues); - FHandleId := BoldGetNamedValue(NamedValues, nv_HandleId); + FHandleId := BoldGetNamedValue(NamedValues,'HandleId'); if not OwnsHandleOnServer then - FStaticValueTypeName := BoldGetNamedValue(NamedValues, nv_StaticValueTypeName); + FStaticValueTypeName := BoldGetNamedValue(NamedValues,'StaticValueTypeName'); end; procedure TBoldReferenceHandleCom.ValuesToServer; @@ -141,16 +140,18 @@ procedure TBoldReferenceHandleCom.ValuesToServer; else StaticSystemHandleId := 0; NamedValues := BoldCreateNamedValues( - [nv_StaticSystemHandle, - nv_StaticValueTypeName], + ['StaticSystemHandle', + 'StaticValueTypeName'], [StaticSystemHandleId, - FStaticValueTypeName]); + FStaticValueTypeName]); ServerElementHandle.SetData(DataFlags,FValue,NamedValues); end; function TBoldReferenceHandleCom.ServerHandleClassName: string; begin - result := ServerHandleClassName_ReferenceHandle; + result := 'TBoldReferenceHandle'; end; +initialization + end. diff --git a/Source/ClientHandlesCom/Core/BoldRootedHandlesCom.pas b/Source/ClientHandlesCom/Core/BoldRootedHandlesCom.pas index 47d426d..b122c38 100644 --- a/Source/ClientHandlesCom/Core/BoldRootedHandlesCom.pas +++ b/Source/ClientHandlesCom/Core/BoldRootedHandlesCom.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldRootedHandlesCom; interface @@ -54,19 +57,12 @@ implementation uses SysUtils, - BoldComConst, - BoldUtils, BoldDefs, BoldComClient; -resourcestring - sPropertyIsReadOnly = '% is Read Only'; - sCircularReference = 'Circular reference in RootHandle'; - - const breFreeHandle = 42; - + {-- TBoldRootedHandleCom ------------------------------------------------------} constructor TBoldRootedHandleCom.Create(Owner: TComponent); @@ -156,15 +152,14 @@ procedure TBoldRootedHandleCom.RootHandleSubscriber_Receive(Originator: TObject; procedure TBoldRootedHandleCom.SetConnectionHandle(Value: TBoldComConnectionHandle); begin - // if ConnectionHandle is set to nil we must subscribe to RootHandle instead if (Value <> ConnectionHandle) then begin - inherited; // does the actual setting + inherited; if not Assigned(ConnectionHandle) then begin if Assigned(RootHandle) then begin - RootHandle.AddSmallSubscription(ConnectionSubscriber, [bceHandleInit,bceHandleTerm], 0); + RootHandle.AddSmallSubscription(ConnectionSubscriber,[bceHandleInit,bceHandleTerm],0); if Connected then DoConnect; end; @@ -177,11 +172,10 @@ procedure TBoldRootedHandleCom.SetRootHandle(Value: TBoldElementHandleCom); if (Value <> RootHandle) then begin if (Value = Self) or ((Value is TBoldRootedHandleCom) and TBoldRootedHandleCom(Value).IsRootLinkedTo(Self)) then - raise EBold.Create(sCircularReference); + raise EBold.Create('Circular reference in RootHandle'); RootHandleSubscriber.CancelAllSubscriptions; if not Assigned(ConnectionHandle) then begin - // if we were connected through this RootHandle ConnectionSubscriber.CancelAllSubscriptions; if Connected then DoDisconnect; @@ -206,7 +200,7 @@ procedure TBoldRootedHandleCom.SetEnabled(Value: Boolean); if Value <> FEnabled then begin if not OwnsHandleOnServer then - raise EBold.CreateFmt(sPropertyIsReadOnly, ['Enabled']); // do not localize + raise EBold.Create('Enabled is read-only'); FEnabled := Value; LocalValueChanged; end; @@ -217,7 +211,7 @@ procedure TBoldRootedHandleCom.SetSubscribe(Value: Boolean); if FSubscribe <> Value then begin if not OwnsHandleOnServer then - raise EBold.CreateFmt(sPropertyIsReadOnly, ['Subscribe']); // do not localize + raise EBold.Create('Subscribe is read-only'); FSubscribe := Value; LocalValueChanged; end; @@ -228,10 +222,12 @@ procedure TBoldRootedHandleCom.SetRootTypeName(const Value: string); if Value <> RootTypeName then begin if not OwnsHandleOnServer then - raise EBold.CreateFmt(sPropertyIsReadOnly, ['RootTypeName']); // do not localize + raise EBold.Create('RootTypeName is read-only'); FRootTypeName := Value; LocalValueChanged; end; end; +initialization + end. diff --git a/Source/ClientHandlesCom/Core/BoldSQLHandleCom.pas b/Source/ClientHandlesCom/Core/BoldSQLHandleCom.pas index 1ae1f8f..329cbea 100644 --- a/Source/ClientHandlesCom/Core/BoldSQLHandleCom.pas +++ b/Source/ClientHandlesCom/Core/BoldSQLHandleCom.pas @@ -1,11 +1,12 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldSQLHandleCom; interface uses Classes, - BoldComObjectSpace, - BoldComObjectSpace_TLB, BoldHandlesCom; type @@ -44,15 +45,16 @@ TBoldSQLHandleCom = class(TBoldNonSystemHandleCom) property SQLWhereClause: string read GetSQLWhereClause write SetSQLWhereClause; end; + implementation uses SysUtils, - BoldComHandlesConst, - ComHandlesConst, - BoldUtils, + BoldComObjectSpace, + BoldComObjectSpace_TLB, + BoldComUtils, BoldDefs, - BoldComUtils; + BoldRev; constructor TBoldSQLHandleCom.Create(Owner: TComponent); begin @@ -68,24 +70,22 @@ destructor TBoldSQLHandleCom.Destroy; procedure TBoldSQLHandleCom.ClearAllValues; begin - // from TBoldElementHandleCom FDynamicBoldType := nil; FStaticBoldType := nil; FStaticSystemTypeInfo := nil; FValue := nil; FHandleId := 0; - // from TBoldNonSystemHandleCom - // from TBoldSQLHandleCom + end; procedure TBoldSQLHandleCom.ClearList; begin - ServerElementHandle.SetData(-1, nil, BoldCreateNamedValues([nv_Action], [nv_ClearList])); + ServerElementHandle.SetData(-1, nil, BoldCreateNamedValues(['Action'], ['ClearList'])); end; procedure TBoldSQLHandleCom.ExecuteSQL; begin - ServerElementHandle.SetData(-1, nil, BoldCreateNamedValues([nv_Action], [nv_ExecuteSQL])); + ServerElementHandle.SetData(-1, nil, BoldCreateNamedValues(['Action'], ['ExecuteSQL'])); end; function TBoldSQLHandleCom.GetClassExpressionName: string; @@ -118,7 +118,7 @@ function TBoldSQLHandleCom.GetSQLWhereClause: string; function TBoldSQLHandleCom.ServerHandleClassName: string; begin - Result := ServerHandleClassName_SQLHandle; + Result := 'TBoldSQLHandle'; end; procedure TBoldSQLHandleCom.SetClassExpressionName(const Value: string); @@ -126,7 +126,7 @@ procedure TBoldSQLHandleCom.SetClassExpressionName(const Value: string); if Value <> FClassExpressionName then begin if not OwnsHandleOnServer then - raise EBold.CreateFmt(sPropertyIsReadOnly, ['ClassExpressionName']); // do not localize + raise EBold.Create('ClassExpressionName is read-only'); FClassExpressionName := Value; LocalValueChanged; end; @@ -137,7 +137,7 @@ procedure TBoldSQLHandleCom.SetClearBeforeExecute(Value: Boolean); if Value <> FClearBeforeExecute then begin if not OwnsHandleOnServer then - raise EBold.CreateFmt(sPropertyIsReadOnly, ['ClearBeforeExecute']); // do not localize + raise EBold.Create('ClearBeforeExecute is read-only'); FClearBeforeExecute := Value; LocalValueChanged; end; @@ -148,7 +148,7 @@ procedure TBoldSQLHandleCom.SetSQLOrderByClause(const Value: string); if Value <> FSQLOrderByClause then begin if not OwnsHandleOnServer then - raise EBold.CreateFmt(sPropertyIsReadOnly, ['SQLOrderByClause']); // do not localize + raise EBold.Create('SQLOrderByClause is read-only'); FSQLOrderByClause := Value; LocalValueChanged; end; @@ -159,7 +159,7 @@ procedure TBoldSQLHandleCom.SetSQLWhereClause(const Value: string); if Value <> FSQLWhereClause then begin if not OwnsHandleOnServer then - raise EBold.CreateFmt(sPropertyIsReadOnly, ['SQLWhereClause']); // do not localize + raise EBold.Create('SQLWhereClause is read-only'); FSQLWhereClause := Value; LocalValueChanged; end; @@ -185,13 +185,13 @@ procedure TBoldSQLHandleCom.ValuesFromServer; DummyList, DummyListType, NamedValues); - FHandleId := BoldGetNamedValue(NamedValues, nv_HandleId); + FHandleId := BoldGetNamedValue(NamedValues,'HandleId'); if not OwnsHandleOnServer then begin - FClassExpressionName := BoldGetNamedValue(NamedValues, nv_ClassExpressionName); - FClearBeforeExecute := BoldGetNamedValue(NamedValues, nv_ClearBeforeExecute); - FSQLOrderByClause := BoldGetNamedValue(NamedValues, nv_SQLOrderByClause); - FSQLWhereClause := BoldGetNamedValue(NamedValues, nv_SQLWhereClause); + FClassExpressionName := BoldGetNamedValue(NamedValues,'ClassExpressionName'); + FClearBeforeExecute := BoldGetNamedValue(NamedValues,'ClearBeforeExecute'); + FSQLOrderByClause := BoldGetNamedValue(NamedValues,'SQLOrderByClause'); + FSQLWhereClause := BoldGetNamedValue(NamedValues,'SQLWhereClause'); end; end; @@ -208,17 +208,18 @@ procedure TBoldSQLHandleCom.ValuesToServer; else StaticSystemHandleId := 0; NamedValues := BoldCreateNamedValues( - [nv_StaticSystemHandle, - nv_ClassExpressionName, - nv_ClearBeforeExecute, - nv_SQLOrderByClause, - nv_SQLWhereClause], + ['StaticSystemHandle', + 'ClassExpressionName', + 'ClearBeforeExecute', + 'SQLOrderByClause', + 'SQLWhereClause'], [StaticSystemHandleId, - FClassExpressionName, - FClearBeforeExecute, - FSQLOrderByClause, - FSQLWhereClause]); + FClassExpressionName, + FClearBeforeExecute, + FSQLOrderByClause, + FSQLWhereClause]); ServerElementHandle.SetData(DataFlags,nil,NamedValues); end; +initialization end. diff --git a/Source/ClientHandlesCom/Core/BoldSystemHandleCom.pas b/Source/ClientHandlesCom/Core/BoldSystemHandleCom.pas index 607ef81..a9e3762 100644 --- a/Source/ClientHandlesCom/Core/BoldSystemHandleCom.pas +++ b/Source/ClientHandlesCom/Core/BoldSystemHandleCom.pas @@ -1,10 +1,11 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldSystemHandleCom; interface uses - BoldComObjectSpace, - BoldComObjectSpace_TLB, BoldHandlesCom; type @@ -18,6 +19,7 @@ TBoldSystemHandleCom = class(TBoldAbstractSystemHandleCom) function GetPersistent: Boolean; protected function ServerHandleClassName: string; override; + procedure ClearAllValues; override; procedure ValuesFromServer; override; procedure ValuesToServer; override; @@ -31,11 +33,10 @@ implementation uses SysUtils, - ComHandlesConst, - BoldComHandlesConst, - BoldUtils, + BoldComObjectSpace_TLB, + BoldComUtils, BoldDefs, - BoldComUtils; + BoldRev; {-- TBoldSystemHandleCom ------------------------------------------------------} @@ -47,19 +48,17 @@ destructor TBoldSystemHandleCom.Destroy; procedure TBoldSystemHandleCom.ClearAllValues; begin - // from TBoldElementHandleCom FDynamicBoldType := nil; FStaticBoldType := nil; FStaticSystemTypeInfo := nil; FValue := nil; FHandleId := 0; - // from TBoldAbstractSystemHandleCom FBoldSystem := nil; FSystemActive := False; - // from TBoldSystemHandleCom FPersistent := False; end; + function TBoldSystemHandleCom.GetPersistent: Boolean; begin EnsureCurrent; @@ -72,7 +71,7 @@ procedure TBoldSystemHandleCom.UpdateDatabase; if Assigned(System) then System.UpdateDatabase else - raise EBold.Create(sNotConnected); + raise EBold.Create('UpdateDatabase: Not connected'); end; procedure TBoldSystemHandleCom.ValuesFromServer; @@ -94,19 +93,21 @@ procedure TBoldSystemHandleCom.ValuesFromServer; DummyList, DummyListType, NamedValues); - FHandleId := BoldGetNamedValue(NamedValues, nv_HandleId); - FSystemActive := BoldGetNamedValue(NamedValues, nv_Active); - FPersistent := BoldGetNamedValue(NamedValues, nv_Persistent); + FHandleId := BoldGetNamedValue(NamedValues,'HandleId'); + FSystemActive := BoldGetNamedValue(NamedValues,'Active'); + FPersistent := BoldGetNamedValue(NamedValues,'Persistent'); end; procedure TBoldSystemHandleCom.ValuesToServer; begin - // Nothing to set, the SystemHandle is always read-only. end; + function TBoldSystemHandleCom.ServerHandleClassName: string; begin - result := ServerHandleClassName_SystemHandle; + result := 'TBoldServerHandle'; end; +initialization + end. diff --git a/Source/ClientHandlesCom/Core/BoldVariableDefinitionCom.pas b/Source/ClientHandlesCom/Core/BoldVariableDefinitionCom.pas index 2f5f670..c6aa3bc 100644 --- a/Source/ClientHandlesCom/Core/BoldVariableDefinitionCom.pas +++ b/Source/ClientHandlesCom/Core/BoldVariableDefinitionCom.pas @@ -1,23 +1,21 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldVariableDefinitionCom; interface uses Classes, - BoldDefs, BoldSubscription, - BoldHandlesCom, - BoldComObjectSpace, - BoldComObjectSpace_TLB; + BoldHandlesCom; type -{ TODO: Create proxy, stuff values, etc. } TBoldVariableDefinitionCom = class; TBoldVariableTupleListCom = class; TBoldVariableTupleCom = class; - { TBoldVariableDefinitionCom } TBoldVariableDefinitionCom = class(TBoldSubscribableComponent) private fVariableTupleList: TBoldVariableTupleListCom; @@ -30,7 +28,6 @@ TBoldVariableDefinitionCom = class(TBoldSubscribableComponent) property Variables: TBoldVariableTupleListCom read fVariableTupleList write SetVariableTupleList; end; - { TBoldVariableTupleListCom } TBoldVariableTupleListCom = class(TCollection) private fOwner: TBoldVariableDefinitionCom; @@ -46,7 +43,6 @@ TBoldVariableTupleListCom = class(TCollection) property Items[Index: integer]: TBoldVariableTupleCom read GetItems; default; end; - { TBoldVariableTupleCom } TBoldVariableTupleCom = class(TCollectionItem) private FVariableName: String; @@ -62,19 +58,19 @@ TBoldVariableTupleCom = class(TCollectionItem) function GetDisplayName: string; override; public constructor Create(Collection: TCollection); override; - destructor Destroy; override; + destructor destroy; override; published property BoldHandle: TBoldElementHandleCom read FBoldHandle write SetBoldHandle; property VariableName: String read FVariableName write SetVariableName; property UseListElement: Boolean read FUseListElement write SetUseListElement; end; + implementation uses SysUtils, - BoldComHandlesConst, - BoldUtils; + BoldDefs; { TBoldVariableDefinitionCom } constructor TBoldVariableDefinitionCom.create(Owner: TComponent); @@ -121,7 +117,7 @@ function TBoldVariableTupleListCom.GetUniqueName: String; begin i := 1; repeat - result := 'Variable' + IntToStr(i); // do not translate + result := 'Variable'+IntToStr(i); Inc(i); until NameIsUnique(result); end; @@ -167,7 +163,7 @@ constructor TBoldVariableTupleCom.Create(Collection: TCollection); fBoldHandleSubscriber := TBoldPassthroughSubscriber.Create(_ReceiveHandleEvent); end; -destructor TBoldVariableTupleCom.Destroy; +destructor TBoldVariableTupleCom.destroy; begin FreeAndNil(fBoldHandleSubscriber); inherited; @@ -179,9 +175,9 @@ function TBoldVariableTupleCom.GetDisplayName: string; if assigned(BoldHandle) then Result := result + ': ' + BoldHandle.Name else - result := result + ': Not Connected'; // do not localize + result := result + ': Not Connected'; if UseListElement then - result := result + ' (list)'; // do not localize + result := result + ' (list)'; end; procedure TBoldVariableTupleCom.SetBoldHandle(const Value: TBoldElementHandleCom); @@ -189,17 +185,14 @@ procedure TBoldVariableTupleCom.SetBoldHandle(const Value: TBoldElementHandleCom FBoldHandle := Value; fBoldHandleSubscriber.CancelAllSubscriptions; if assigned(value) then - Value.AddSmallSubscription(fBoldHandleSubscriber, [beDestroying], beDestroying); - { TODO: Reeanable when AbstractListHandleCom fixed } -// if not (BoldHandle is TBoldAbstractListHandleCom) then -// UseListElement := false; + Value.AddSmallSubscription(fBoldHandleSubscriber, [beDestroying], beDestroying); + Changed; + end; procedure TBoldVariableTupleCom.SetUseListElement(const Value: Boolean); -begin - { TODO: Reeanable when AbstractListHandleCom fixed } -// FUseListElement := Value and (BoldHandle is TBoldAbstractListHandleCom); +begin Changed; end; @@ -207,14 +200,15 @@ procedure TBoldVariableTupleCom.SetVariableName(const Value: String); begin if FVariableName <> Value then begin if not (Collection as TBoldVariableTupleListCom).NameIsUnique(Value) then - raise EBold.CreateFmt(sNameNotUnique, [Value]); + raise EBold.CreateFmt('Can''t rename variable to "%s", name already exists', [Value]); if not (Collection as TBoldVariableTupleListCom).NameIsValid(Value) then - raise EBold.Create(sInvalidCharsInName); + raise EBold.Create('Invalid variable name, only alphanum characters and underscore valid'); FVariableName := Value; Changed; end; end; + procedure TBoldVariableTupleCom._ReceiveHandleEvent(Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent); begin @@ -223,8 +217,8 @@ procedure TBoldVariableTupleCom._ReceiveHandleEvent(Originator: TObject; end; procedure TBoldVariableDefinitionCom.VariablesChanged; -begin - { TODO: Stuff Values } +begin end; +initialization end. diff --git a/Source/ClientHandlesCom/Core/BoldVariableHandleCom.pas b/Source/ClientHandlesCom/Core/BoldVariableHandleCom.pas index 8a44b05..f4036cf 100644 --- a/Source/ClientHandlesCom/Core/BoldVariableHandleCom.pas +++ b/Source/ClientHandlesCom/Core/BoldVariableHandleCom.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldVariableHandleCom; interface @@ -41,8 +44,6 @@ implementation uses SysUtils, - BoldComHandlesConst, - ComHandlesConst, BoldUtils, BoldDefs, BoldComUtils; @@ -65,14 +66,12 @@ destructor TBoldVariableHandleCom.Destroy; procedure TBoldVariableHandleCom.ClearAllValues; begin - // from TBoldElementHandleCom FDynamicBoldType := nil; FStaticBoldType := nil; FStaticSystemTypeInfo := nil; FValue := nil; FHandleId := 0; - // from TBoldNonSystemHandleCom - // from TBoldVariableHandleCom + end; function TBoldVariableHandleCom.GetValueTypeName: string; @@ -99,7 +98,7 @@ procedure TBoldVariableHandleCom.SetValueTypeName(const Value: string); if Value <> FValueTypeName then begin if not OwnsHandleOnServer then - raise EBold.CreateFmt(sPropertyIsReadOnly, [ValueTypeName]); + raise EBold.CreateFmt('%s.ValueTypeName is read-only', [ClassName]); FValueTypeName := Value; LocalValueChanged; end; @@ -110,7 +109,7 @@ procedure TBoldVariableHandleCom.SetInitialValues(Value: TStrings); if Value <> FInitialValues then begin if not OwnsHandleOnServer then - raise EBold.CreateFmt(sPropertyIsReadOnly, [InitialValues]); + raise EBold.CreateFmt('%s.InitialValues is read-only', [ClassName]); FInitialValues.Assign(Value); LocalValueChanged; end; @@ -137,13 +136,13 @@ procedure TBoldVariableHandleCom.ValuesFromServer; DummyList, DummyListType, NamedValues); - FHandleId := BoldGetNamedValue(NamedValues, nv_HandleId); + FHandleId := BoldGetNamedValue(NamedValues, 'HandleId'); if not OwnsHandleOnServer then begin - FValueTypeName := BoldGetNamedValue(NamedValues, nv_ValueTypeName); + FValueTypeName := BoldGetNamedValue(NamedValues, 'ValueTypeName'); Temp := TStringList.Create; try - BoldVariantToStrings(BoldGetNamedValue(NamedValues, nv_InitialValues),Temp); + BoldVariantToStrings(BoldGetNamedValue(NamedValues, 'InitialValues'),Temp); FInitialValues.Assign(Temp); finally Temp.Free; @@ -163,25 +162,24 @@ procedure TBoldVariableHandleCom.ValuesToServer; else StaticSystemHandleId := 0; NamedValues := BoldCreateNamedValues( - [nv_StaticSystemHandle, - nv_ValueTypeName, - nv_InitialValues], + ['StaticSystemHandle', + 'ValueTypeName', + 'InitialValues'], [StaticSystemHandleId, - FValueTypeName, - BoldStringsToVariant(FInitialValues)]); + FValueTypeName, + BoldStringsToVariant(FInitialValues)]); ServerElementHandle.SetData(DataFlags, nil, NamedValues); end; function TBoldVariableHandleCom.ServerHandleClassName: string; begin - result := ServerHandleClassName_VariableHandle; + result := 'TBoldVariableHandle'; end; procedure TBoldVariableHandleCom.DefineProperties(Filer: TFiler); begin inherited DefineProperties(Filer); - // ExpressionName changed name to ValueTypeName after 2.5 - Filer.DefineProperty('ExpressionName', ReadExpressionName, nil, True); // do not localize + Filer.DefineProperty('ExpressionName', ReadExpressionName, nil, True); end; procedure TBoldVariableHandleCom.ReadExpressionName(Reader: TReader); @@ -189,4 +187,6 @@ procedure TBoldVariableHandleCom.ReadExpressionName(Reader: TReader); ValueTypeName := Reader.ReadString; end; +initialization + end. diff --git a/Source/ClientHandlesCom/Core/ComHandlesConst.pas b/Source/ClientHandlesCom/Core/ComHandlesConst.pas index 4e4950d..203c119 100644 --- a/Source/ClientHandlesCom/Core/ComHandlesConst.pas +++ b/Source/ClientHandlesCom/Core/ComHandlesConst.pas @@ -38,4 +38,4 @@ interface implementation -end. \ No newline at end of file +end. diff --git a/Source/ClientHandlesCom/IDE/BoldHandleComReg.pas b/Source/ClientHandlesCom/IDE/BoldHandleComReg.pas index db22903..f788d77 100644 --- a/Source/ClientHandlesCom/IDE/BoldHandleComReg.pas +++ b/Source/ClientHandlesCom/IDE/BoldHandleComReg.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldHandleComReg; interface @@ -11,7 +14,6 @@ implementation BoldUtils, Classes, DesignIntf, - BoldIDEConsts, BoldGuard, BoldSystemHandleCom, BoldDerivedHandleCom, @@ -26,31 +28,30 @@ implementation {$R BoldHandleComReg.res} -const - prop_ObjectName = 'Objectname'; - procedure Register; begin - RegisterComponents('Bold COM Handles', // do not localize - [ - TBoldSystemHandleCom, - TBoldDerivedHandleCom, - TBoldExpressionHandleCom, - TBoldCursorHandleCom, - TBoldListHandleCom, - TBoldReferenceHandleCom, - TBoldSQLHandleCom, - //TBoldVariableDefinitionCom, - TBoldVariableHandleCom - ]); - RegisterPropertyEditor(TypeInfo(String), TBoldSystemHandleCom, prop_ObjectName, TBoldObjectNameProperty); - RegisterPropertyEditor(TypeInfo(String), TBoldDerivedHandleCom, prop_ObjectName, TBoldObjectNameProperty); - RegisterPropertyEditor(TypeInfo(String), TBoldExpressionHandleCom, prop_ObjectName, TBoldObjectNameProperty); - RegisterPropertyEditor(TypeInfo(String), TBoldCursorHandleCom, prop_ObjectName, TBoldObjectNameProperty); - RegisterPropertyEditor(TypeInfo(String), TBoldListHandleCom, prop_ObjectName, TBoldObjectNameProperty); - RegisterPropertyEditor(TypeInfo(String), TBoldReferenceHandleCom, prop_ObjectName, TBoldObjectNameProperty); - RegisterPropertyEditor(TypeInfo(String), TBoldSQLHandleCom, prop_ObjectName, TBoldObjectNameProperty); - RegisterPropertyEditor(TypeInfo(String), TBoldVariableHandleCom, prop_ObjectName, TBoldObjectNameProperty); + + begin + RegisterComponents('Bold COM Handles', + [ + TBoldSystemHandleCom, + TBoldDerivedHandleCom, + TBoldExpressionHandleCom, + TBoldCursorHandleCom, + TBoldListHandleCom, + TBoldReferenceHandleCom, + TBoldSQLHandleCom, + TBoldVariableHandleCom + ]); + RegisterPropertyEditor(TypeInfo(String), TBoldSystemHandleCom, 'Objectname', TBoldObjectNameProperty); + RegisterPropertyEditor(TypeInfo(String), TBoldDerivedHandleCom, 'Objectname', TBoldObjectNameProperty); + RegisterPropertyEditor(TypeInfo(String), TBoldExpressionHandleCom, 'Objectname', TBoldObjectNameProperty); + RegisterPropertyEditor(TypeInfo(String), TBoldCursorHandleCom, 'Objectname', TBoldObjectNameProperty); + RegisterPropertyEditor(TypeInfo(String), TBoldListHandleCom, 'Objectname', TBoldObjectNameProperty); + RegisterPropertyEditor(TypeInfo(String), TBoldReferenceHandleCom, 'Objectname', TBoldObjectNameProperty); + RegisterPropertyEditor(TypeInfo(String), TBoldSQLHandleCom, 'Objectname', TBoldObjectNameProperty); + RegisterPropertyEditor(TypeInfo(String), TBoldVariableHandleCom, 'Objectname', TBoldObjectNameProperty); + end; end; end. diff --git a/Source/Common/COM/BoldApartmentThread.pas b/Source/Common/COM/BoldApartmentThread.pas index e0ccb2e..89171c9 100644 --- a/Source/Common/COM/BoldApartmentThread.pas +++ b/Source/Common/COM/BoldApartmentThread.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldApartmentThread; interface @@ -12,10 +15,8 @@ interface BM_CREATEOBJECTINTHREAD = WM_USER + $1234; type - { forward declarations } TBoldApartmentThread = class; - { prototypes } TCreateInstanceProc = function(const UnkOuter: IUnknown; const IID: TGUID; out Obj): HResult of object; stdcall; TBoldApartmentType = (batMTA, batSTA); @@ -25,7 +26,6 @@ TCreateInstanceInfo = record ApartmentThread: TBoldApartmentThread; end; - { TBoldApartmentThread } TBoldApartmentThread = class(TBoldNotifiableThread) private FCreateInstanceProc: TCreateInstanceProc; @@ -59,8 +59,8 @@ implementation uses SysUtils, ActiveX, - BoldThreadSafeLog, - BoldComConst; + BoldThreadSafeLog + ; { apartment handler window } function ApartmentThreadWndProc (hWndTarget: HWND; iMessage, wParam, lParam: longint): longint; stdcall; @@ -79,10 +79,10 @@ function ApartmentThreadWndProc (hWndTarget: HWND; iMessage, wParam, lParam: lon if Succeeded (at.CreateResult) then at.CreateResult := at.MarshalInterface (pUnk); ReleaseSemaphore(at.ObjectCreatedEvent, 1, nil); - pUnk := nil; // get rid of own reference, MarshalInterface already added one + pUnk := nil; Result := 0; except - BoldLogError(spciInfoNotInitialized); + BoldLogError('ApartmentThreadWndProc: pciInfo not initialized'); end; end else @@ -94,7 +94,6 @@ function ApartmentThreadWndProc (hWndTarget: HWND; iMessage, wParam, lParam: lon end; var - // this variable is initialized (zeroed) in the initializationsection) cApartmentThreadWindowClass: TWndClass; { TBoldApartmentThread } @@ -140,7 +139,7 @@ procedure TBoldApartmentThread.Execute; res: integer; begin InitServerWindow (TRUE); - BoldLogThread('ID=AptThread'); // do not localize + BoldLogThread('ID=AptThread'); case ApartmentType of batSTA: CoInitializeEx(nil, COINIT_APARTMENTTHREADED); @@ -187,7 +186,7 @@ function TBoldApartmentThread.UnmarshalInterface (out pObject): HResult; Result := CoGetInterfaceAndReleaseStream (IStream (FStream), iid, pObject); FStream := NIL; except on E: Exception do - BoldLogError('%s.UnmarshalInterface: %s', [ClassName, E.Message]); // do not localize + BoldLogError('%s.UnmarshalInterface: %s', [ClassName, E.Message]); end; end; @@ -207,5 +206,5 @@ initialization cApartmentThreadWindowClass.hCursor := 0; cApartmentThreadWindowClass.hbrBackground := 0; cApartmentThreadWindowClass.lpszMenuName := NIL; - cApartmentThreadWindowClass.lpszClassName := 'TBoldApartmentThreadWindow'; // do not localize + cApartmentThreadWindowClass.lpszClassName := 'TBoldApartmentThreadWindow' end. diff --git a/Source/Common/COM/BoldComAdapter.pas b/Source/Common/COM/BoldComAdapter.pas index c388b46..d0bc659 100644 --- a/Source/Common/COM/BoldComAdapter.pas +++ b/Source/Common/COM/BoldComAdapter.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldComAdapter; interface @@ -18,7 +21,7 @@ TBoldComAdapterFactory = class; TBoldAdaptableObject = TObject; TBoldAdaptableClass = class of TObject; - + TBoldComAdapterClass = class of TBoldComAdapter; {--- IBoldComAdapter ---} @@ -37,10 +40,10 @@ TBoldComAdapterContext = class(TBoldNonRefCountedObject) {--- TBoldComAdapter ---} TBoldComAdapter = class(TBoldAutoInterfacedObject, IBoldComAdapter) private - FAdaptee: TBoldAdaptableObject; - FIsOwner: Boolean; - FSubscriber: TBoldPassthroughSubscriber; + fIsOwner: Boolean; + fSubscriber: TBoldPassthroughSubscriber; protected + fAdaptee: TBoldAdaptableObject; function GetEnsuredAdaptee: TBoldAdaptableObject; { IBoldComAdapter } function GetAdaptee: TBoldAdaptableObject; @@ -73,24 +76,24 @@ TBoldComAdapterFactory = class(TBoldNonRefCountedObject) AdaptableClass: TBoldAdaptableClass); end; -procedure BoldComRegisterAdapter(AdapterClass: TBoldComAdapterClass; - AdaptableClass: TBoldAdaptableClass); -procedure BoldComCreateAdapter(Adaptee: TBoldAdaptableObject; - Owner: Boolean; const IID: TGUID; out Obj); +procedure BoldComRegisterAdapter(AdapterClass: TBoldComAdapterClass; AdaptableClass: TBoldAdaptableClass); +{ril}procedure BoldComCreateAdapter(Adaptee: TBoldAdaptableObject; Owner: Boolean; const IID: TGUID; out Obj); function BoldComInterfaceToObject(const Unk: IUnknown): TBoldAdaptableObject; +//PATCH +function GetDebugInfo: string; + implementation uses SysUtils, + Classes, //PATCH BoldDefs, BoldIndexableList, BoldHashIndexes, - BoldComUtils, - BoldComConst; + BoldComUtils; type - { TBoldAdapterCache } TBoldAdapterCache = class(TBoldUnorderedIndexableList) private function GetAdapterByAdaptee(Adaptee: TBoldAdaptableObject): TBoldComAdapter; @@ -102,9 +105,10 @@ TBoldAdapterCache = class(TBoldUnorderedIndexableList) {---TBoldObjectHashIndex---} TBoldAdapterCacheIndex = class(TBoldObjectHashIndex) protected - function ItemAsKeyObject(Item: TObject): TObject; override; + function ItemASKeyObject(Item: TObject): TObject; override; end; + var G_BoldComAdapterFactory: TBoldComAdapterFactory = nil; G_AdapterCache: TBoldAdapterCache = nil; @@ -120,6 +124,57 @@ function AdapterCache: TBoldAdapterCache; result := G_AdapterCache; end; +//PATCH +function GetDebugInfo: string; +var + vAdapterCache: TBoldAdapterCache; + vTraverser: TBoldIndexableListTraverser; + vAdapter: TBoldComAdapter; + vNoAdapteeCnt: Integer; + vAdapterRefCount: array [0..255] of Integer; + I: Integer; + vClasses: TStringList; +begin + vAdapterCache := AdapterCache; + vClasses := TStringList.Create; + vClasses.Sorted := True; + + Result := 'AdapterCache.Count:'+IntToStr(vAdapterCache.Count); + vTraverser := vAdapterCache.CreateTraverser; + try + vNoAdapteeCnt := 0; + FillChar(vAdapterRefCount,SizeOf(vAdapterRefCount),0); + while vTraverser.MoveNext do + begin + vAdapter := vTraverser.Item as TBoldComAdapter; + if Assigned(vAdapter.fAdaptee) then + begin + I := vClasses.Add(vAdapter.fAdaptee.ClassName); + vClasses.Objects[I] := TObject(Integer(vClasses.Objects[I])+1); + end + else + Inc(vNoAdapteeCnt); + + Inc(vAdapterRefCount[vAdapter.RefCount]); + + //Annat intressant som kan mätas och användas för klassning: + // + //vAdapter.RefCount + end; + Result := Result+' HasNoAdaptee:'+IntToStr(vNoAdapteeCnt)+#13#10; + for I:=0 to vClasses.Count-1 do + Result := Result+vClasses[I]+'='+IntToStr(Integer(vClasses.Objects[I]))+#13#10; + Result := Result+' RefCount=AdapterCount:'; + for I:=Low(vAdapterRefCount) to High(vAdapterRefCount) do + if vAdapterRefCount[I]<>0 then + Result := Result+IntToStr(I)+'='+IntToStr(vAdapterRefCount[I])+', '; + + finally + FreeAndNil(vTraverser); + FreeAndNil(vClasses); + end; +end; + procedure BoldComRegisterAdapter(AdapterClass: TBoldComAdapterClass; AdaptableClass: TBoldAdaptableClass); @@ -127,11 +182,13 @@ procedure BoldComRegisterAdapter(AdapterClass: TBoldComAdapterClass; TBoldComAdapterFactory.Instance.RegisterAdapterClass(AdapterClass,AdaptableClass); end; -procedure BoldComCreateAdapter(Adaptee: TBoldAdaptableObject; - Owner: Boolean; const IID: TGUID; out Obj); +procedure BoldComCreateAdapter(Adaptee: TBoldAdaptableObject; Owner: Boolean; const IID: TGUID; out Obj); +{ril} var Adapter: TBoldComAdapter; +{ UnknownAdapter: IUnknown; +} begin Pointer(Obj) := nil; if Assigned(Adaptee) then @@ -141,13 +198,19 @@ procedure BoldComCreateAdapter(Adaptee: TBoldAdaptableObject; Adapter := TBoldComAdapterFactory.Instance.CreateAdapterForObject(Adaptee,Owner); if not Assigned(Adapter) then - raise EBoldCom.CreateFmt(sNoAdapterRegistered,[Adaptee.ClassName]); - UnknownAdapter := Adapter; // AddRef + raise EBoldCom.CreateFmt('No adapter registered for %s',[Adaptee.ClassName]); +{ + UnknownAdapter := Adapter; if UnknownAdapter.QueryInterface(IID,Obj) <> 0 then - begin - UnknownAdapter := nil; // Release - raise EBoldCom.CreateFmt(sUnsupportedInterface,[Adapter.ClassName]); +} + if Adapter.QueryInterface(IID,Obj) <> 0 then +{ begin + UnknownAdapter := nil; +} + raise EBoldCom.CreateFmt('%s: Unsupported interface',[Adapter.ClassName]); +{ end; +} end; end; @@ -155,10 +218,8 @@ function BoldComInterfaceToObject(const Unk: IUnknown): TBoldAdaptableObject; begin Result := nil; if Assigned(Unk) then - begin - with Unk as IBoldComAdapter do - Result := GetAdaptee; - end; +// Result := (Unk as IBoldComAdapter).GetAdaptee; + Result := (Unk as IBoldComAdapter).GetAdaptee; end; {-- TBoldComAdapter -----------------------------------------------------------} @@ -166,7 +227,7 @@ function BoldComInterfaceToObject(const Unk: IUnknown): TBoldAdaptableObject; constructor TBoldComAdapter.Create(AdaptableObject: TBoldAdaptableObject; Owner: Boolean; const TypeLib: ITypeLib; const DispIntf: TGUID); begin - FSubscriber := TBoldPassthroughSubscriber.Create(ReceiveEvent); + fSubscriber := TBoldPassthroughSubscriber.Create(ReceiveEvent); SetAdaptee(AdaptableObject,Owner); inherited Create(TypeLib, DispIntf); end; @@ -175,9 +236,9 @@ destructor TBoldComAdapter.Destroy; begin if assigned(Adaptee) then AdapterCache.remove(self); - FreeAndNil(FSubscriber); - if FIsOwner and Assigned(FAdaptee) then - FreeAndNil(FAdaptee) + FreeAndNil(fSubscriber); + if fIsOwner and Assigned(fAdaptee) then + FreeAndNil(fAdaptee) else fAdaptee := nil; inherited Destroy; @@ -185,57 +246,57 @@ destructor TBoldComAdapter.Destroy; function TBoldComAdapter.GetAdaptee: TBoldAdaptableObject; begin - Result := FAdaptee; + Result := fAdaptee; end; function TBoldComAdapter.GetIsOwner: Boolean; begin - Result := FIsOwner; + Result := fIsOwner; end; function TBoldComAdapter.GetEnsuredAdaptee: TBoldAdaptableObject; begin - Result := FAdaptee; - if not Assigned(Result) then - raise EBoldCom.CreateFmt(sNoAdaptee, [ClassName]); + Result := fAdaptee; + if Result=nil then + raise EBoldCom.CreateFmt('%s: No adaptee',[ClassName]); end; procedure TBoldComAdapter.ReceiveEvent(Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent); begin - if (Originator = FAdaptee) and (OriginalEvent = beDestroying) then + if (Originator = fAdaptee) and (OriginalEvent = beDestroying) then begin AdapterCache.Remove(self); - FAdaptee := nil; + fAdaptee := nil; end; end; procedure TBoldComAdapter.SetAdaptee(Value: TBoldAdaptableObject; Owner: Boolean); begin - if FAdaptee <> Value then + if fAdaptee <> Value then begin if assigned(fAdaptee) then AdapterCache.remove(self); - FSubscriber.CancelAllSubscriptions; - if FIsOwner and Assigned(FAdaptee) then - FreeAndNil(FAdaptee); - - FAdaptee := Value; - - if FAdaptee is TBoldSubscribableObject then - TBoldSubscribableObject(FAdaptee).AddSubscription(FSubscriber, beDestroying, beDestroying) - else if FAdaptee is TBoldSubscribableComponent then - TBoldSubscribableComponent(FAdaptee).AddSubscription(FSubscriber, beDestroying, beDestroying) - else if FAdaptee is TBoldSubscribablePersistent then - TBoldSubscribablePersistent(FAdaptee).AddSubscription(FSubscriber, beDestroying, beDestroying) + fSubscriber.CancelAllSubscriptions; + if fIsOwner and Assigned(fAdaptee) then + FreeAndNil(fAdaptee); + + fAdaptee := Value; + + if fAdaptee is TBoldSubscribableObject then + TBoldSubscribableObject(fAdaptee).AddSubscription(fSubscriber, beDestroying, beDestroying) + else if fAdaptee is TBoldSubscribableComponent then + TBoldSubscribableComponent(fAdaptee).AddSubscription(fSubscriber, beDestroying, beDestroying) + else if fAdaptee is TBoldSubscribablePersistent then + TBoldSubscribablePersistent(fAdaptee).AddSubscription(fSubscriber, beDestroying, beDestroying) else if assigned(fAdaptee) then - raise EBold.CreateFmt(sCannotAdaptNonSubscribables, [className, value.ClassName]); + raise EBold.CreateFmt('%s.SetAdaptee: Can not adapt objects that are not subscribable (such as %s)', [className, value.ClassName]); if assigned(fAdaptee) then AdapterCache.Add(self); end; - if FIsOwner <> Owner then - FIsOwner := Owner; + if fIsOwner <> Owner then + fIsOwner := Owner; end; {-- TBoldComAdapterFactory ----------------------------------------------------} @@ -333,12 +394,10 @@ function TBoldAdapterCacheIndex.ItemASKeyObject(Item: TObject): TObject; result := (item as TBoldComAdapter).Adaptee; end; -initialization // empty +initialization finalization FreeAndNil(G_BoldComAdapterFactory); FreeAndNil(G_AdapterCache); end. - - diff --git a/Source/Common/COM/BoldComEventQueue.pas b/Source/Common/COM/BoldComEventQueue.pas index 6c5b2b5..4171c20 100644 --- a/Source/Common/COM/BoldComEventQueue.pas +++ b/Source/Common/COM/BoldComEventQueue.pas @@ -1,9 +1,13 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldComEventQueue; + interface uses - SyncObjs, + SyncObjs, //NEW BoldBase; type @@ -35,7 +39,7 @@ TBoldComEventQueue = class(TBoldMemoryManagedObject) FOnEvent: TBoldComEventQueueEvent; FPopMode: TBoldComEventQueuePopMode; FTail: PBoldComEventQueueItem; - FCriticalSection: TCriticalSection; +//TODO FCriticalSection: TCriticalSection; //TODO Remove comment when interface change is allowed class procedure CreateQueueWindow; class procedure FreeQueueWindow; protected @@ -52,14 +56,29 @@ TBoldComEventQueue = class(TBoldMemoryManagedObject) property PopMode: TBoldComEventQueuePopMode read FPopMode; end; + TBoldComEventQueue2 = class(TBoldComEventQueue) + FCriticalSection: TCriticalSection; + end; + + implementation uses BoldEnvironment, - BoldMemoryManager, - SysUtils, + SysUtils, //NEW Windows; +var + G_FCriticalSection: TCriticalSection = nil; //TODO Remove when interface change is allowed + +function FCriticalSection: TCriticalSection; //TODO Remove when interface change is allowed +begin + if not Assigned(G_FCriticalSection) then + G_FCriticalSection := TCriticalSection.Create; + Result := G_FCriticalSection; +end; + + const BM_POPEVENTQUEUE = $8FFF; BM_DESTROYWINDOW = $8FFE; @@ -99,16 +118,15 @@ function BoldComEventQueueWndProc(Window: HWND; hCursor: 0; hbrBackground: 0; lpszMenuName: nil; - lpszClassName: 'TBoldComEventQueueWindow'); // do not localize + lpszClassName: 'TBoldComEventQueueWindow'); constructor TBoldComEventQueue.Create(PopMode: TBoldComEventQueuePopMode); begin inherited Create; - FCriticalSection := TCriticalSection.Create; +//TODO FCriticalSection := TCriticalSection.Create; //TODO Remove comment when interface change is allowed FPopMode := PopMode; Inc(BoldComEventQueueWindowCount); if BoldComEventQueueWindowCount = 1 then - // first queue instance creates the window CreateQueueWindow; end; @@ -119,9 +137,8 @@ destructor TBoldComEventQueue.Destroy; BoldEffectiveEnvironment.ProcessMessages; Dec(BoldComEventQueueWindowCount); if BoldComEventQueueWindowCount = 0 then - // last queue instance destroys window SendMessage(BoldComEventQueueWindow, BM_DESTROYWINDOW, 0, 0); - FreeAndNil(FCriticalSection); +//TODO FreeAndNil(FCriticalSection); //TODO Remove comment when interface change is allowed inherited Destroy; end; @@ -159,8 +176,8 @@ procedure TBoldComEventQueue.Clear; Item := PopItem; while Assigned(Item) do begin - BoldMemoryManager_.DeAllocateMemory(Item, SizeOf(TBoldComEventQueueItem)); - Item := PopItem; + FreeMem(Item, sizeof(TBoldComEventQueueItem)); + Item := PopItem; end; FCount := 0; end; @@ -182,7 +199,8 @@ procedure TBoldComEventQueue.Pop; try HandleEvent(Item^.EventData); finally - BoldMemoryManager_.DeAllocateMemory(Item, SizeOf(TBoldComEventQueueItem)); + FreeMem(Item, sizeof(TBoldComEventQueueItem)); +//OLD Dispose(Item); end; Item := PopItem; end; @@ -192,53 +210,54 @@ procedure TBoldComEventQueue.Pop; try HandleEvent(Item^.EventData); finally - BoldMemoryManager_.DeAllocateMemory(Item, SizeOf(TBoldComEventQueueItem)); + FreeMem(Item, sizeof(TBoldComEventQueueItem)); +//OLD Dispose(Item); end; end; end; function TBoldComEventQueue.PopItem: PBoldComEventQueueItem; begin - // get first item in list Result := nil; if Assigned(FHead) then begin - FCriticalSection.Enter; + FCriticalSection.Enter; //NEW Result := FHead; - // remove from list FHead := Result^.Next; if not Assigned(FHead) then FTail := nil; Dec(FCount); - FCriticalSection.Leave; + FCriticalSection.Leave; //NEW end; end; procedure TBoldComEventQueue.Push(const EventData: TBoldComEventData); var Item: PBoldComEventQueueItem; - PostMessagePopEventQueueMessage: Boolean; + PostMessagePopEventQueueMessage: Boolean; //NEW begin - // allocate new list item - Item := BoldMemoryManager_.AllocateMemory(SizeOf(TBoldComEventQueueItem)); - // copy event data between structures + GetMem(Item, sizeof(TBoldComEventQueueItem)); +//OLD New(Item); Move(EventData,Item^.EventData,SizeOf(EventData)); - // no next item, since this will be the last item Item^.Next := nil; - // add to end of list - FCriticalSection.Enter; + FCriticalSection.Enter; //NEW if not Assigned(FHead) then FHead := Item; if Assigned(FTail) then FTail^.Next := Item; FTail := Item; Inc(FCount); - PostMessagePopEventQueueMessage := (popMode=pmSingleEvent) or (FCount=1); - FCriticalSection.Leave; - if PostMessagePopEventQueueMessage then - PostMessage(BoldComEventQueueWindow,BM_POPEVENTQUEUE,0,Integer(Self)); + PostMessagePopEventQueueMessage := (popMode=pmSingleEvent) or (FCount=1); //NEW + FCriticalSection.Leave; //NEW + if PostMessagePopEventQueueMessage then //NEW + PostMessage(BoldComEventQueueWindow,BM_POPEVENTQUEUE,0,Integer(Self)); //NEW +//OLD case popMode of +//OLD pmSingleEvent: PostMessage(BoldComEventQueueWindow,BM_POPEVENTQUEUE,0,Integer(Self)); +//OLD pmAllEvents: if Count = 1 then PostMessage(BoldComEventQueueWindow,BM_POPEVENTQUEUE,0,Integer(Self)); +//OLD end; end; +initialization +finalization + FreeAndNil(G_FCriticalSection); //TODO Remove when interface change is allowed end. - - diff --git a/Source/Common/COM/BoldComObj.pas b/Source/Common/COM/BoldComObj.pas index b895ccd..db9a377 100644 --- a/Source/Common/COM/BoldComObj.pas +++ b/Source/Common/COM/BoldComObj.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldComObj; interface @@ -47,6 +50,7 @@ TBoldVariantEnumerator = class(TBoldRefCountedObject, IEnumVariant) function Clone(out Enum: IEnumVariant): HResult; stdcall; public constructor Create(Collection: IBoldVariantCollection); + destructor Destroy; override; end; {-- TBoldAutoInterfacedObject --} @@ -111,6 +115,11 @@ constructor TBoldVariantEnumerator.Create(Collection: IBoldVariantCollection); FCollection := Collection; end; +destructor TBoldVariantEnumerator.Destroy; +begin + inherited; +end; + function TBoldVariantEnumerator.Next(celt: LongWord; var rgvar: OleVariant; pceltFetched: PLongWord): HResult; type @@ -277,4 +286,7 @@ function TBoldAggregatedAutoInterfacedObject.QueryInterface(const IID: TGUID; ou Result := IUnknown(FController).QueryInterface(IID,Obj); end; + +initialization + end. diff --git a/Source/Common/COM/BoldComThreads.pas b/Source/Common/COM/BoldComThreads.pas index 27cdad3..861761c 100644 --- a/Source/Common/COM/BoldComThreads.pas +++ b/Source/Common/COM/BoldComThreads.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldComThreads; interface @@ -22,6 +25,7 @@ TBoldComConnectionThread = class(TBoldMemoryManagedObject) FConnectRes: HResult; public constructor Create(const HostName: string; const CLSID, IID: TGUID); + destructor Destroy; override; function Connect(out Obj): Boolean; property Busy: Boolean read FBusy; property ConnectRes: HResult read fConnectRes; @@ -65,6 +69,7 @@ TBoldComCreateObjectThread = class(TThread) procedure Execute; override; public constructor Create(Owner: TBoldComConnectionThread; CreateSuspended: Boolean); + destructor Destroy; override; property InterfaceStream: Pointer read FInterfaceStream; property CreateRes: HResult read fCreateRes; end; @@ -77,6 +82,11 @@ constructor TBoldComCreateObjectThread.Create(Owner: TBoldComConnectionThread; FCreateRes := NOERROR; end; +destructor TBoldComCreateObjectThread.Destroy; +begin + inherited; +end; + procedure TBoldComCreateObjectThread.Execute; var Unk: IUnknown; @@ -110,6 +120,11 @@ constructor TBoldComConnectionThread.Create(const HostName: string; fConnectRes := NOERROR; end; +destructor TBoldComConnectionThread.Destroy; +begin + inherited; +end; + function TBoldComConnectionThread.Connect(out Obj): Boolean; var ThreadObject: TBoldComCreateObjectThread; @@ -147,7 +162,6 @@ function TBoldComConnectionThread.Connect(out Obj): Boolean; end; end; else - // Error Break; end; end; @@ -231,4 +245,6 @@ procedure TBoldComWorkerThread.Release; SetEvent(FWaitEvent); end; +initialization + end. diff --git a/Source/Common/COM/BoldComUtils.pas b/Source/Common/COM/BoldComUtils.pas index 2fbbbba..b6551b8 100644 --- a/Source/Common/COM/BoldComUtils.pas +++ b/Source/Common/COM/BoldComUtils.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldComUtils; interface @@ -215,25 +218,21 @@ function BoldVariantIsNamedValues(V: OleVariant): Boolean; var Va: OleVariant; begin - // Variant must be array Result := VarIsArray(V); if Result then begin - // Array must contain two elements, index 0 and 1 Result := VarArrayDimCount(V) = 1; Result := Result and (VarArrayLowBound(V,1) = 0); Result := Result and (VarArrayHighBound(V,1) = 1); end; if Result then begin - // First element must be string array Va := V[0]; Result := VarIsArray(Va) and ((VarType(Va) and varTypeMask) = varOleStr) and (VarArrayDimCount(Va) = 1); end; if Result then begin - // Second element must be variant array Va := V[1]; Result := VarIsArray(Va) and ((VarType(Va) and varTypeMask) = varVariant) and (VarArrayDimCount(Va) = 1); @@ -343,12 +342,11 @@ procedure BoldInitializeComSecurity(AuthenticationLevel, ImpersonationLevel: lon procedure BoldSetSecurityForInterface(AuthenticationLevel, ImpersonationLevel: longint; Unk: IUnknown); begin - //TODO: this doens't seem to work CoSetProxyBlanket(Unk, RPC_C_AUTHN_LEVEL_NONE, RPC_C_AUTHNZ_NONE, nil, AuthenticationLevel, ImpersonationLevel, nil, EOAC_NONE); end; -initialization // empty +initialization finalization if NeedToUninitialize then CoUninitialize; diff --git a/Source/Common/COM/BoldThreadedComObjectFactory.pas b/Source/Common/COM/BoldThreadedComObjectFactory.pas index 9b19f50..8bad89c 100644 --- a/Source/Common/COM/BoldThreadedComObjectFactory.pas +++ b/Source/Common/COM/BoldThreadedComObjectFactory.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldThreadedComObjectFactory; interface @@ -10,11 +13,10 @@ interface BoldDefs; type - { forward declarations } + TBoldThreadedComObjectFactory = class; TBoldComObject = class; - { TBoldThreadedComObjectFactory } TBoldThreadedComObjectFactory = class(TComObjectFactory, IClassFactory) private FApartmentType: TBoldApartmentType; @@ -32,7 +34,6 @@ TBoldThreadedComObjectFactory = class(TComObjectFactory, IClassFactory) property ApartmentType: TBoldApartmentType read FApartmentType write FApartmentType; end; - { TBoldComObject } TBoldComObject = class(TComObject) public procedure Disconnect; virtual; @@ -46,8 +47,7 @@ implementation BoldUtils, Windows, BoldPropagatorConstants, - Messages, - BoldComConst; + Messages; { TBoldThreadedComObjectFactory } @@ -74,7 +74,7 @@ function TBoldThreadedComObjectFactory.CreateInstance(const UnkOuter: IUnknown; FApartmentThread := TBoldApartmentThread.Create(ApartmentType, DoCreateInstance, UnkOuter, IID); FApartmentThread.Resume; if not FApartmentThread.WaitUntilReady(TIMEOUT*10) then - raise EBold.Create(sApartmentThreadTimedOut); + raise EBold.Create('Appartment thread timed out'); end else FApartmentThread.Init(UnkOuter, IID); @@ -117,4 +117,6 @@ procedure TBoldComObject.Disconnect; CoDisconnectObject(self, 0); end; +initialization + end. diff --git a/Source/Common/Connection/BoldClient.pas b/Source/Common/Connection/BoldClient.pas index 5c0701a..d35a891 100644 --- a/Source/Common/Connection/BoldClient.pas +++ b/Source/Common/Connection/BoldClient.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldClient; interface @@ -38,7 +41,8 @@ TBoldClientApplication = class(TBoldNonRefCountedObject) implementation uses - SysUtils; + SysUtils, + BoldRev; var G_BoldClientApplication: TBoldClientApplication = nil; diff --git a/Source/Common/Connection/BoldServer.pas b/Source/Common/Connection/BoldServer.pas index 88fac1c..44915a0 100644 --- a/Source/Common/Connection/BoldServer.pas +++ b/Source/Common/Connection/BoldServer.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldServer; interface @@ -38,7 +41,8 @@ TBoldServerApplication = class(TBoldNonRefCountedObject) implementation uses - SysUtils; + SysUtils, + BoldRev; var G_BoldServerApplication: TBoldServerApplication = nil; diff --git a/Source/Common/ConnectionCOM/BoldComClient.pas b/Source/Common/ConnectionCOM/BoldComClient.pas index 769953f..632a34d 100644 --- a/Source/Common/ConnectionCOM/BoldComClient.pas +++ b/Source/Common/ConnectionCOM/BoldComClient.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldComClient; interface @@ -134,7 +137,7 @@ implementation uses Windows, - SysUtils, // InterlockedIncrement/Decrement for non-WIN32 + SysUtils, ActiveX, Variants, ComObj, @@ -142,8 +145,7 @@ implementation BoldHashIndexes, BoldGUIDUtils, BoldComUtils, - BoldComThreads, - BoldComConst; + BoldComThreads; type TBoldProtectedAccessSubscriber = class(TBoldSubscriber) @@ -161,7 +163,7 @@ TBoldComClientSubscriberHashIndex = class(TBoldCardinalHashIndex) function FindSubscriberBySubscriberId(SubscriberId: integer): TBoldComClientSubscriber; end; - + {-- TBoldComClientSubscriber --------------------------------------------------} constructor TBoldComClientSubscriber.create; @@ -272,7 +274,7 @@ function TBoldComClientConnection.Connect(const HostName: string; Result := True; if (ConnectionState = bceConnected) then Exit; if (ConnectionState <> bceDisconnected) then - raise EBoldCom.Create(sConnectionStateError); + raise EBoldCom.Create('Connection state error.'); FConnectClientInterface := ConnectClientInterface; Connecting; try @@ -355,7 +357,7 @@ function TBoldComClientConnection.Disconnect: Boolean; Result := True; if (ConnectionState = bceDisconnected) then Exit; if (ConnectionState <> bceConnected) then - raise EBoldCom.Create(sConnectionStateError); + raise EBoldCom.Create('Connection state error.'); try Disconnecting; finally @@ -433,15 +435,13 @@ procedure TBoldComClient.AddConnection(Connection: TBoldComClientConnection); end; procedure TBoldComClient.CancelSubscriptions(SubscriberId: Integer; Connection: TBoldComClientConnection = nil); -const - Meth_CancelSubscriptions = 'CancelSubscriptions'; var I: Integer; Conn: TBoldComClientConnection; begin if Assigned(Connection) and Assigned(Connection.BoldServer) and (Connection.ConnectionState = bceConnected) then - Connection.BoldServer.Execute(Meth_CancelSubscriptions,SubscriberId) + Connection.BoldServer.Execute('CancelSubscriptions',SubscriberId) else begin for I := 0 to ConnectionCount - 1 do @@ -449,7 +449,7 @@ procedure TBoldComClient.CancelSubscriptions(SubscriberId: Integer; Connection: Conn := Connections[I]; if Assigned(Conn) and Assigned(Conn.BoldServer) and (Conn.ConnectionState = bceConnected) then - Conn.BoldServer.Execute(Meth_CancelSubscriptions,SubscriberId) + Conn.BoldServer.Execute('CancelSubscriptions',SubscriberId) end; end; end; @@ -467,12 +467,12 @@ procedure TBoldComClient.RemoveSubscriber(Subscriber: TBoldComClientSubscriber); Connection := Connections[I]; if Assigned(Connection) and Assigned(Connection.BoldServer) and (Connection.ConnectionState = bceConnected) then - Connection.BoldServer.Execute('RemoveSubscriber', Subscriber.SubscriberId) // do not localize + Connection.BoldServer.Execute('RemoveSubscriber', Subscriber.SubscriberId) end; end else FUnusedSubscriberIds.Add(Subscriber.SubscriberId); - + fSubscribers.remove(Subscriber); end; @@ -569,5 +569,3 @@ finalization G_BoldComClient.Free; end. - - diff --git a/Source/Common/ConnectionCOM/BoldComConnection.pas b/Source/Common/ConnectionCOM/BoldComConnection.pas index 851f1fa..932f64b 100644 --- a/Source/Common/ConnectionCOM/BoldComConnection.pas +++ b/Source/Common/ConnectionCOM/BoldComConnection.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldComConnection; interface @@ -14,19 +17,15 @@ interface function BoldComConnectionTypeLibrary: ITypeLib; -// ----------------------------------------------------------------------------- -// Type Library -// ----------------------------------------------------------------------------- - -// *********************************************************************// -// GUIDS declared in the TypeLibrary. Following prefixes are used: -// Type Libraries : LIBID_xxxx -// CoClasses : CLASS_xxxx -// DISPInterfaces : DIID_xxxx -// Non-DISP interfaces: IID_xxxx -// *********************************************************************// + + + + + + + + const - // TypeLibrary Major and minor versions BoldComConnectionMajorVersion = 1; BoldComConnectionMinorVersion = 0; @@ -37,9 +36,7 @@ function BoldComConnectionTypeLibrary: ITypeLib; IID_IBoldProvider: TGUID = '{E07B7DF5-77D2-11D2-B7E0-00600871B01B}'; type -// *********************************************************************// -// Forward declaration of types defined in TypeLibrary -// *********************************************************************// + IBoldClient = interface; IBoldClientDisp = dispinterface; IBoldServer = interface; @@ -47,31 +44,25 @@ function BoldComConnectionTypeLibrary: ITypeLib; IBoldProvider = interface; IBoldProviderDisp = dispinterface; -// *********************************************************************// -// Interface: IBoldClient -// Flags: (4416) Dual OleAutomation Dispatchable -// GUID: {E07B7DF3-77D2-11D2-B7E0-00600871B01B} -// *********************************************************************// + + + IBoldClient = interface(IDispatch) ['{E07B7DF3-77D2-11D2-B7E0-00600871B01B}'] function OnServerEvent(Event: Integer; Data: OleVariant): OleVariant; safecall; end; -// *********************************************************************// -// DispIntf: IBoldClientDisp -// Flags: (4416) Dual OleAutomation Dispatchable -// GUID: {E07B7DF3-77D2-11D2-B7E0-00600871B01B} -// *********************************************************************// + + + IBoldClientDisp = dispinterface ['{E07B7DF3-77D2-11D2-B7E0-00600871B01B}'] function OnServerEvent(Event: Integer; Data: OleVariant): OleVariant; dispid 1; end; -// *********************************************************************// -// Interface: IBoldServer -// Flags: (4416) Dual OleAutomation Dispatchable -// GUID: {E07B7DF4-77D2-11D2-B7E0-00600871B01B} -// *********************************************************************// + + + IBoldServer = interface(IDispatch) ['{E07B7DF4-77D2-11D2-B7E0-00600871B01B}'] function Connect(const ClientId: WideString; Flags: Integer; const Client: IBoldClient): WordBool; safecall; @@ -79,11 +70,9 @@ function BoldComConnectionTypeLibrary: ITypeLib; function Execute(const Name: WideString; Params: OleVariant): OleVariant; safecall; end; -// *********************************************************************// -// DispIntf: IBoldServerDisp -// Flags: (4416) Dual OleAutomation Dispatchable -// GUID: {E07B7DF4-77D2-11D2-B7E0-00600871B01B} -// *********************************************************************// + + + IBoldServerDisp = dispinterface ['{E07B7DF4-77D2-11D2-B7E0-00600871B01B}'] function Connect(const ClientId: WideString; Flags: Integer; const Client: IBoldClient): WordBool; dispid 1; @@ -91,11 +80,9 @@ function BoldComConnectionTypeLibrary: ITypeLib; function Execute(const Name: WideString; Params: OleVariant): OleVariant; dispid 3; end; -// *********************************************************************// -// Interface: IBoldProvider -// Flags: (4416) Dual OleAutomation Dispatchable -// GUID: {E07B7DF5-77D2-11D2-B7E0-00600871B01B} -// *********************************************************************// + + + IBoldProvider = interface(IDispatch) ['{E07B7DF5-77D2-11D2-B7E0-00600871B01B}'] function CreateObject(const ClassName: WideString): IUnknown; safecall; @@ -104,11 +91,9 @@ function BoldComConnectionTypeLibrary: ITypeLib; property ObjectInfo: OleVariant read Get_ObjectInfo; end; -// *********************************************************************// -// DispIntf: IBoldProviderDisp -// Flags: (4416) Dual OleAutomation Dispatchable -// GUID: {E07B7DF5-77D2-11D2-B7E0-00600871B01B} -// *********************************************************************// + + + IBoldProviderDisp = dispinterface ['{E07B7DF5-77D2-11D2-B7E0-00600871B01B}'] function CreateObject(const ClassName: WideString): IUnknown; dispid 1; @@ -116,15 +101,12 @@ function BoldComConnectionTypeLibrary: ITypeLib; property ObjectInfo: OleVariant readonly dispid 3; end; -// ----------------------------------------------------------------------------- -// Type Library End -// ----------------------------------------------------------------------------- + implementation uses SysUtils, - BoldComConst, BoldComUtils; var @@ -135,9 +117,11 @@ function BoldComConnectionTypeLibrary: ITypeLib; if not Assigned(G_TypeLibrary) then begin if LoadRegTypeLib(LIBID_BoldComConnection,1,0,0,G_TypeLibrary) <> 0 then - raise EBoldCom.Create(sUnableToLoadTypeLib); + raise EBoldCom.Create('Unable to load type library (BoldComConnection)'); end; Result := G_TypeLibrary; end; +initialization + end. diff --git a/Source/Common/ConnectionCOM/BoldComServ.pas b/Source/Common/ConnectionCOM/BoldComServ.pas index 80087b6..1ea711a 100644 --- a/Source/Common/ConnectionCOM/BoldComServ.pas +++ b/Source/Common/ConnectionCOM/BoldComServ.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldComServ; interface @@ -10,6 +13,8 @@ function Bold_TheComServer: TComServerObject; implementation uses + SysUtils, + BoldUtils, ComServ; function Bold_TheComServer: TComServerObject; @@ -17,4 +22,7 @@ function Bold_TheComServer: TComServerObject; result := ComServer; end; + +initialization + end. diff --git a/Source/Common/ConnectionCOM/BoldComServer.pas b/Source/Common/ConnectionCOM/BoldComServer.pas index 44bd88b..6e7a990 100644 --- a/Source/Common/ConnectionCOM/BoldComServer.pas +++ b/Source/Common/ConnectionCOM/BoldComServer.pas @@ -1,3 +1,7 @@ + +{ Global compiler directives } +{$include bold.inc} + unit BoldComServer; interface @@ -14,7 +18,8 @@ interface BoldIndexableList, BoldComObj, BoldComConnection, - BoldThreadedComObjectFactory; + BoldThreadedComObjectFactory + ; const // Server events @@ -34,6 +39,7 @@ TBoldComServerThreadedConnectionFactory = class; TBoldComServer = class; TBoldComServerConnectionClass = class of TBoldComServerConnection; + TBoldComServerConnectionEvent = procedure(Sender: TBoldComServerConnection; var Disconnect: Boolean); {-- TBoldComServerSubscriber --} @@ -101,11 +107,13 @@ TBoldComServerSubscriberList = class(TBoldUnorderedIndexableList) TBoldComServerEventSenderThread = class(TThread) private FOwner: TBoldComServerConnection; + FClientInterfaceCookie: Cardinal; protected procedure Execute; override; procedure SendEventFailure; public - constructor Create(aOwner: TBoldComServerConnection); + constructor Create(aOwner: TBoldComServerConnection; aClientInterfaceCookie: Cardinal); + property ClientInterfaceCookie: Cardinal read FClientInterfaceCookie; end; {-- TBoldComServerConnection --} @@ -113,9 +121,9 @@ TBoldComServerConnection = class(TComObject) private FActive: Boolean; FClientId: string; - FClientInterface: IBoldClient; - FSenderThread: TBoldComServerEventSenderThread; - FClientInterfaceCookie: DWORD; + FClientInterface: IBoldClient; //TODO WARNING! Contains InterfaceCookie +//TODO FSenderThread: TBoldComServerEventSenderThread; //NEW +//TODO FHasClientInterface: Boolean; //NEW//TODO FClientInterfaceCookie: DWORD; //NEW FConnected: Boolean; FDestroying: Boolean; FEventQueue: TBoldComServerEventQueue; @@ -130,13 +138,12 @@ TBoldComServerConnection = class(TComObject) function GetSubscriber(SubscriberId: Integer): TBoldComServerSubscriber; procedure RemoveSubscriber(SubscriberId: Integer); procedure PushEvent(SubscriberId: integer; Originator: TObject; OriginalEvent, RequestedEvent: TBoldevent); - function GetSenderThread: TBoldComServerEventSenderThread; - function GetClientInterfaceFromGIT(out aClient: IBoldClient): Boolean; +//TODO function GetClientInterface: IBoldClient; +//TODO function GetClientInterface(out aClient: IBoldClient): Boolean; +//TODO function DoSendQueuedEvents: Boolean; //NEW +//TODO procedure DoSendEventFailure; //NEW property Subscribers: TBoldComServerSubscriberList read FSubscribers; - property SenderThread: TBoldComServerEventSenderThread read GetSenderThread; - protected - procedure DoSendEventFailure; - function DoSendQueuedEvents(aClient: IBoldClient): Boolean; + public destructor Destroy; override; procedure Disconnect; @@ -145,7 +152,7 @@ TBoldComServerConnection = class(TComObject) procedure SendQueuedEvents; property Active: Boolean read FActive; property ClientId: string read FClientId; - property ClientInterface: IBoldClient read FClientInterface; + property ClientInterface: IBoldClient read FClientInterface; //TODO WARNING! Contains InterfaceCookie property Connected: Boolean read FConnected; property EventQueue: TBoldComServerEventQueue read FEventQueue; property OnSendEventFailure: TBoldComServerConnectionEvent read fOnSendEventFailure write fOnSendEventFailure; @@ -192,6 +199,7 @@ TBoldComServer = class(TBoldServer) procedure GetObjectInfo(const ClassId: TGUID; ObjectNames, ClassNames: TStrings); procedure RemoveConnection(Connection: TBoldComServerConnection); procedure SendQueuedEvents; + protected public constructor Create; destructor Destroy; override; @@ -207,7 +215,7 @@ TBoldComServer = class(TBoldServer) //Set to true to enable client callbacks in separate worker threads. BoldAsynchronousClientCallbackOnServerEvent: Boolean = False; -{.$DEFINE BOLDCOMCALLBACKDEBUG} +{$DEFINE BOLDCOMCALLBACKDEBUG} {$IFDEF BOLDCOMCALLBACKDEBUG} //Functions used for performance testing of callbacks function CallStats: string; @@ -222,9 +230,7 @@ implementation BoldHashIndexes, BoldComUtils, Variants, - BoldMemoryManager, - BoldApartmentThread, - BoldComConst; + BoldApartmentThread; const CLSID_StdGlobalInterfaceTable: TGUID = '{00000323-0000-0000-C000-000000000046}'; //NEW (Missing in ActiveX) @@ -239,8 +245,19 @@ implementation out ppv): HResult; stdcall; end; + TBoldEventSenderThreadList = class(TBoldCardinalHashIndex) + protected + function ItemAsKeyCardinal(Item: TObject): Cardinal; override; + public + function FindEventSenderThreadByCookie(ClientInterfaceCookie: Cardinal): TBoldComServerEventSenderThread; + function FindClientInterfaceByCookie(ClientInterfaceCookie: Cardinal): IBoldClient; + procedure ConnectClient(const ServerConnection: TBoldComServerConnection; const Client: IBoldClient; var ClientInterfaceCookie: Cardinal); + procedure DisconnectClient(var ClientInterfaceCookie: Cardinal); + end; + var G_GlobalInterfaceTable: IGlobalInterfaceTable; + G_BoldEventSenderThreadList: TBoldEventSenderThreadList; function GlobalInterfaceTable: IGlobalInterfaceTable; begin @@ -249,6 +266,14 @@ function GlobalInterfaceTable: IGlobalInterfaceTable; Result := G_GlobalInterfaceTable; end; +function BoldEventSenderThreadList: TBoldEventSenderThreadList; + +begin + if not Assigned(G_BoldEventSenderThreadList) then + G_BoldEventSenderThreadList := TBoldEventSenderThreadList.Create;; + Result := G_BoldEventSenderThreadList; +end; + {$IFDEF BOLDCOMCALLBACKDEBUG} var CallCount: Integer = 0; @@ -259,7 +284,7 @@ function GlobalInterfaceTable: IGlobalInterfaceTable; function CallStats: string; begin if CallCount>0 then - Result := Format(sCallStats, + Result := Format('Total:%.1fs Min:%.0fms Max:%.0fms Avg:%.0fms Count:%d', [CallTime, CallMin*1000, CallMax*1000, CallTime/CallCount*1000, CallCount]); end; @@ -352,7 +377,7 @@ function TBoldComServerEventQueue.GetAllEvents: OleVariant; Result[J+2] := Item^.EventData.OriginalEvent; Result[J+3] := Item^.EventData.RequestedEvent; Inc(J,4); - BoldMemoryManager_.DeAllocateMemory(Item, SizeOf(TBoldComEventQueueItem)); + FreeMem(Item, sizeof(TBoldComEventQueueItem)); end; end else @@ -437,17 +462,18 @@ destructor TBoldComServerConnection.Destroy; FConnected := False; FActive := False; TBoldComServer.Instance.RemoveConnection(Self); - if Assigned(FSenderThread) then - begin - FSenderThread.Terminate; - FSenderThread.FOwner := nil; - FSenderThread.Resume; - end; - if Assigned(FClientInterface) and BoldAsynchronousClientCallbackOnServerEvent then - begin - GlobalInterfaceTable.RevokeInterfaceFromGlobal(FClientInterfaceCookie); - FClientInterfaceCookie := 0; - end; + BoldEventSenderThreadList.DisconnectClient(Cardinal(FClientInterface)); +// if Assigned(FSenderThread) then +// begin +// FSenderThread.Terminate; +// FSenderThread.FOwner := nil; +// FSenderThread.Resume; +// end; +// if Assigned(FClientInterface) then +// begin +// GlobalInterfaceTable.RevokeInterfaceFromGlobal(FClientInterfaceCookie); +// FClientInterfaceCookie := 0; +// end; FClientInterface := nil; FClientId := ''; RemoveSubscriber(-1); @@ -490,20 +516,24 @@ function TBoldComServerConnection.ObjQueryInterface(const IID: TGUID; out Obj): end; end; -procedure TBoldComServerConnection.DoSendEventFailure; +procedure {TBoldComServerConnection.}DoSendEventFailure(Self: TBoldComServerConnection); var AskDisconnect: Boolean; begin - AskDisconnect := True; - if Assigned(FOnSendEventFailure) then - OnSendEventFailure(Self, AskDisconnect); - if AskDisconnect then - ClientDisconnect; + with Self do + begin + AskDisconnect := True; + if Assigned(FOnSendEventFailure) then + OnSendEventFailure(Self, AskDisconnect); + if AskDisconnect then + ClientDisconnect; + end; end; -function TBoldComServerConnection.DoSendQueuedEvents(aClient: IBoldClient): Boolean; +function {TBoldComServerConnection.}DoSendQueuedEvents(Self: TBoldComServerConnection): Boolean; var Data: OleVariant; + vClient: IBoldClient; {$IFDEF BOLDCOMCALLBACKDEBUG} CounterStart, CounterStop, CounterFreq: Int64; //TEST ElapsedTime: Double; //TEST @@ -511,51 +541,60 @@ function TBoldComServerConnection.DoSendQueuedEvents(aClient: IBoldClient): Bool begin //NOTE This method can be called from a worker thread and must be threadsafe! Result := False; - if Connected and Assigned(aClient) then + if Self.Connected and (Cardinal(Self.FClientInterface)<>0) then begin - Data := FEventQueue.GetAllEvents; + Data := Self.FEventQueue.GetAllEvents; if not VarIsEmpty(Data) then begin + vClient := BoldEventSenderThreadList.FindClientInterfaceByCookie(Cardinal(Self.FClientInterface)); + if Assigned(vClient) then + begin {$IFDEF BOLDCOMCALLBACKDEBUG} - QueryPerformanceCounter(CounterStart); + QueryPerformanceCounter(CounterStart); {$ENDIF} - aClient.OnServerEvent(EVENT_SUBSCRIPTION,Data); + vClient.OnServerEvent(EVENT_SUBSCRIPTION,Data); {$IFDEF BOLDCOMCALLBACKDEBUG} - QueryPerformanceCounter(CounterStop); - QueryPerformanceFrequency(CounterFreq); - ElapsedTime := ((CounterStop-CounterStart)/CounterFreq); - CallTime := CallTime+ElapsedTime; - if ElapsedTimeCallMax then - CallMax := ElapsedTime; - InterlockedIncrement(CallCount); + QueryPerformanceCounter(CounterStop); + QueryPerformanceFrequency(CounterFreq); + ElapsedTime := ((CounterStop-CounterStart)/CounterFreq); + CallTime := CallTime+ElapsedTime; + if ElapsedTimeCallMax then + CallMax := ElapsedTime; + InterlockedIncrement(CallCount); {$ENDIF} + end; Result := True; end; end else - FEventQueue.Clear; + Self.FEventQueue.Clear; end; + procedure TBoldComServerConnection.SendQueuedEvents; +var + vSenderThread: TBoldComServerEventSenderThread; begin if FEventQueue.Count>0 then begin if BoldAsynchronousClientCallbackOnServerEvent then begin - SenderThread.Resume; + vSenderThread := BoldEventSenderThreadList.FindEventSenderThreadByCookie(Cardinal(FClientInterface)); + if Assigned(vSenderThread) then + vSenderThread.Resume; end else begin try - DoSendQueuedEvents(FClientInterface); + DoSendQueuedEvents(Self); except - DoSendEventFailure; + DoSendEventFailure(Self); end; end; end; @@ -571,11 +610,10 @@ procedure TBoldComServerConnection.CancelSubscriptions(SubscriberId: Integer); // cancel all subscriptions... Traverser := Subscribers.CreateTraverser; try - while not Traverser.EndOfList do + while Traverser.MoveNext do begin Subscriber := TBoldComServerSubscriber(Traverser.item); Subscriber.CancelAllSubscriptions; - Traverser.Next; end; finally Traverser.Free; @@ -625,12 +663,6 @@ procedure TBoldComServerConnection.PushEvent(SubscriberId: integer; Originator: EventQueue.Push(EventData); end; -function TBoldComServerConnection.GetClientInterfaceFromGIT(out aClient: IBoldClient): Boolean; -begin - Result := False; - if Assigned(FClientInterface) and BoldAsynchronousClientCallbackOnServerEvent then - Result := Succeeded(GlobalInterfaceTable.GetInterfaceFromGlobal(FClientInterfaceCookie, IID_IBoldClient, aClient)); -end; function TBoldComServerConnection.ClientConnect(const ClientId: string; Flags: Integer; const Client: IBoldClient): Boolean; @@ -641,10 +673,7 @@ function TBoldComServerConnection.ClientConnect(const ClientId: string; if Active and (not Assigned(C) or (C = Self)) then begin FClientId := ClientId; - FClientInterfaceCookie := 0; - if BoldAsynchronousClientCallbackOnServerEvent then - GlobalInterfaceTable.RegisterInterfaceInGlobal(Client, IID_IBoldClient, FClientInterfaceCookie); - FClientInterface := Client; + BoldEventSenderThreadList.ConnectClient(Self, Client, Cardinal(FClientInterface)); //NEW FConnected := True; Result := True; end @@ -659,9 +688,12 @@ function TBoldComServerConnection.ClientDisconnect: Boolean; FConnected := False; RemoveSubscriber(-1); FEventQueue.Clear; - if Assigned(FClientInterface) and BoldAsynchronousClientCallbackOnServerEvent then - GlobalInterfaceTable.RevokeInterfaceFromGlobal(FClientInterfaceCookie); - FClientInterfaceCookie := 0; + BoldEventSenderThreadList.DisconnectClient(Cardinal(FClientInterface)); +// if Assigned(FClientInterface) then +// begin +// GlobalInterfaceTable.RevokeInterfaceFromGlobal(FClientInterfaceCookie); +// FClientInterfaceCookie := 0; +// end; FClientInterface := nil; FClientId := ''; Result := True; @@ -678,9 +710,9 @@ procedure TBoldComServerConnection.Disconnect; function TBoldComServerConnection.Execute(const Name: string; Params: OleVariant): OleVariant; begin - if CompareText(Name,'CancelSubscriptions') = 0 then // do not localize + if CompareText(Name,'CancelSubscriptions') = 0 then CancelSubscriptions(Params) - else if CompareText(Name,'RemoveSubscriber') = 0 then // do not localize + else if CompareText(Name,'RemoveSubscriber') = 0 then RemoveSubscriber(Params); end; @@ -689,13 +721,6 @@ function TBoldComServerConnection.GetSubscriber(SubscriberId: Integer): TBoldCom Result := Subscribers.SubscriberById[SubscriberId]; end; -function TBoldComServerConnection.GetSenderThread: TBoldComServerEventSenderThread; -begin - if not Assigned(FSenderThread) then - FSenderThread := TBoldComServerEventSenderThread.Create(Self); - Result := FSenderThread; -end; - {-- TBoldServerConnectionFactory ----------------------------------------------} constructor TBoldComServerConnectionFactory.Create(ComServer: TComServerObject; @@ -728,7 +753,7 @@ procedure TBoldComServerConnectionFactory.UpdateRegistry(Register: Boolean); // create the category CatInfo.catid := CATID_BoldServer; CatInfo.lcid := 409; - StringToWideChar('BoldServer Classes', CatInfo.szDescription,127); // do not localize + StringToWideChar('BoldServer Classes',CatInfo.szDescription,127); Reg.RegisterCategories(1,@CatInfo); end; if Assigned(CatDesc) then @@ -895,7 +920,7 @@ procedure TBoldComServerThreadedConnectionFactory.UpdateRegistry( // create the category CatInfo.catid := CATID_BoldServer; CatInfo.lcid := 409; - StringToWideChar('BoldServer Classes',CatInfo.szDescription,127); // do not localize + StringToWideChar('BoldServer Classes',CatInfo.szDescription,127); Reg.RegisterCategories(1,@CatInfo); end; if Assigned(CatDesc) then @@ -938,11 +963,13 @@ function TBoldComServerSubscriberHashIndex.ItemAsKeyCardinal(Item: TObject): car Result := TBoldComServerSubscriber(Item).SubscriberId; end; +//NEW Class { TBoldComServerEventSenderThread } -constructor TBoldComServerEventSenderThread.Create(aOwner: TBoldComServerConnection); +constructor TBoldComServerEventSenderThread.Create(aOwner: TBoldComServerConnection; aClientInterfaceCookie: Cardinal); begin FOwner := aOwner; + FClientInterfaceCookie := aClientInterfaceCookie; FreeOnTerminate := True; inherited Create(True); end; @@ -950,22 +977,18 @@ constructor TBoldComServerEventSenderThread.Create(aOwner: TBoldComServerConnect procedure TBoldComServerEventSenderThread.SendEventFailure; begin if not Terminated then - FOwner.DoSendEventFailure; + DoSendEventFailure(FOwner); end; procedure TBoldComServerEventSenderThread.Execute; -var - vClient: IBoldClient; begin CoInitialize(nil); repeat try - if (not Terminated) and FOwner.GetClientInterfaceFromGIT(vClient) then - while (not Terminated) and FOwner.DoSendQueuedEvents(vClient) do {loop}; - vClient := nil; + while (not Terminated) and {FOwner.}DoSendQueuedEvents(FOwner) do {loop}; except if not Terminated then - Synchronize(SendEventFailure); + Synchronize(SendEventFailure); end; if not Terminated then Suspend; @@ -973,10 +996,64 @@ procedure TBoldComServerEventSenderThread.Execute; CoUninitialize; end; +{ TBoldEventSenderThreadList } +procedure TBoldEventSenderThreadList.ConnectClient(const ServerConnection: TBoldComServerConnection; const Client: IBoldClient; var ClientInterfaceCookie: Cardinal); +var + vSenderThread: TBoldComServerEventSenderThread; +begin + if ClientInterfaceCookie<>0 then + DisconnectClient(ClientInterfaceCookie); + if Assigned(Client) then + begin + OleCheck(GlobalInterfaceTable.RegisterInterfaceInGlobal(Client, IID_IBoldClient, ClientInterfaceCookie)); + vSenderThread := TBoldComServerEventSenderThread.Create(ServerConnection, ClientInterfaceCookie); + Add(vSenderThread); + end; +end; + +procedure TBoldEventSenderThreadList.DisconnectClient(var ClientInterfaceCookie: Cardinal); +var + vSenderThread: TBoldComServerEventSenderThread; +begin + if ClientInterfaceCookie<>0 then + begin + vSenderThread := FindEventSenderThreadByCookie(ClientInterfaceCookie); + if Assigned(vSenderThread) then + begin + Remove(vSenderThread); + vSenderThread.Terminate; + vSenderThread.FOwner := nil; + vSenderThread.FClientInterfaceCookie := 0; + vSenderThread.Resume; + end; + OleCheck(GlobalInterfaceTable.RevokeInterfaceFromGlobal(ClientInterfaceCookie)); + ClientInterfaceCookie := 0; + end; +end; + +function TBoldEventSenderThreadList.FindClientInterfaceByCookie(ClientInterfaceCookie: Cardinal): IBoldClient; +begin + Result := nil; + if ClientInterfaceCookie<>0 then + OleCheck(GlobalInterfaceTable.GetInterfaceFromGlobal(ClientInterfaceCookie, IID_IBoldClient, Result)); +end; + +function TBoldEventSenderThreadList.FindEventSenderThreadByCookie(ClientInterfaceCookie: Cardinal): TBoldComServerEventSenderThread; +begin + Result := TBoldComServerEventSenderThread(Find(ClientInterfaceCookie)); + Assert(not Assigned(Result) or (Result is TBoldComServerEventSenderThread)); +end; + +function TBoldEventSenderThreadList.ItemAsKeyCardinal(Item: TObject): Cardinal; +begin + Assert(Item is TBoldComServerEventSenderThread); + Result := TBoldComServerEventSenderThread(Item).ClientInterfaceCookie; +end; + initialization finalization - FreeAndNil(G_BoldComServer); + FreeAndNil(G_BoldComServer); //CHANGED + FreeAndNil(G_BoldEventSenderThreadList); //NEW end. - diff --git a/Source/Common/ConnectionHandles/BoldClientHandles.pas b/Source/Common/ConnectionHandles/BoldClientHandles.pas index 4904ce9..606bd93 100644 --- a/Source/Common/ConnectionHandles/BoldClientHandles.pas +++ b/Source/Common/ConnectionHandles/BoldClientHandles.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldClientHandles; interface @@ -35,6 +38,9 @@ TBoldImportHandle = class(TBoldClientHandle) implementation +uses + BoldRev; + {-- TBoldClientHandle ---------------------------------------------------------} constructor TBoldClientHandle.Create(AOwner: TComponent); @@ -69,4 +75,6 @@ procedure TBoldImportHandle.SetObjectName(const Value: string); end; end; +initialization + end. diff --git a/Source/Common/ConnectionHandles/BoldServerHandles.pas b/Source/Common/ConnectionHandles/BoldServerHandles.pas index 758216e..b4a505c 100644 --- a/Source/Common/ConnectionHandles/BoldServerHandles.pas +++ b/Source/Common/ConnectionHandles/BoldServerHandles.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldServerHandles; interface @@ -34,7 +37,8 @@ TBoldExportHandle = class(TBoldServerHandle) implementation uses - SysUtils; + SysUtils, + BoldRev; {-- TBoldServerHandle ---------------------------------------------------------} @@ -79,4 +83,6 @@ procedure TBoldExportHandle.SetObjectName(const Value: string); end; end; +initialization + end. diff --git a/Source/Common/ConnectionHandlesCOM/BoldComClientHandles.pas b/Source/Common/ConnectionHandlesCOM/BoldComClientHandles.pas index 9e5686a..a9d179e 100644 --- a/Source/Common/ConnectionHandlesCOM/BoldComClientHandles.pas +++ b/Source/Common/ConnectionHandlesCOM/BoldComClientHandles.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldComClientHandles; interface @@ -31,12 +34,13 @@ TBoldComConnectionHandle = class(TBoldClientHandle) FServerEvents: Boolean; FServerHost: string; FServerName: string; - FSubscriber: TBoldPassthroughSubscriber; + FSubscriber: TBoldExtendedPassthroughSubscriber; FThreaded: Boolean; - FECode: HResult; function GetBoldProvider: IBoldProvider; + FECode: HResult; + function GetBoldProvider: IBoldProvider; function GetConnected: Boolean; function GetServerCLSID: string; - function GetSubscriber: TBoldPassthroughSubscriber; + function GetSubscriber: TBoldExtendedPassthroughSubscriber; procedure ReceiveExtended(Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent; const Args: array of const); procedure SetConnected(Value: Boolean); @@ -45,7 +49,7 @@ TBoldComConnectionHandle = class(TBoldClientHandle) procedure SetServerHost(const Value: string); procedure SetServerName(const Value: string); procedure SetThreaded(Value: Boolean); - property Subscriber: TBoldPassthroughSubscriber read GetSubscriber; + property Subscriber: TBoldExtendedPassthroughSubscriber read GetSubscriber; protected function GetHandledObject: TObject; override; procedure Loaded; override; @@ -54,7 +58,7 @@ TBoldComConnectionHandle = class(TBoldClientHandle) destructor Destroy; override; property BoldProvider: IBoldProvider read GetBoldProvider; property Connected: Boolean read GetConnected write SetConnected; - property ECode: HResult read FECode; + property ECode: HResult read FECode; published property AfterConnect: TNotifyEvent read FAfterConnect write FAfterConnect; property AfterDisconnect: TNotifyEvent read FAfterDisconnect write FAfterDisconnect; @@ -116,7 +120,6 @@ implementation uses SysUtils, ComObj, - BoldComConst, BoldComUtils; {-- TBoldComConnectionHandle -----------------------------------------------------} @@ -132,7 +135,6 @@ constructor TBoldComConnectionHandle.Create(AOwner: TComponent); destructor TBoldComConnectionHandle.Destroy; begin - // if constructor fails because typelib not loaded, then we have no fConnection) if assigned(fConnection) then Connected := False; FreeAndNil(FConnection); @@ -168,10 +170,10 @@ function TBoldComConnectionHandle.GetServerCLSID: string; Result := ''; end; -function TBoldComConnectionHandle.GetSubscriber: TBoldPassthroughSubscriber; +function TBoldComConnectionHandle.GetSubscriber: TBoldExtendedPassthroughSubscriber; begin if not Assigned(FSubscriber) then - FSubscriber := TBoldPassthroughSubscriber.CreateWithExtendedReceive(ReceiveExtended); + FSubscriber := TBoldExtendedPassthroughSubscriber.CreateWithExtendedReceive(ReceiveExtended); Result := FSubscriber; end; @@ -190,7 +192,7 @@ procedure TBoldComConnectionHandle.ReceiveExtended(Originator: TObject; Original case VR.VType of vtInteger: result := VR.VInteger; else - raise Exception.Create(sUnknownHResultType); + raise Exception.Create('unknown type in GetHResult'); end; end; @@ -211,7 +213,6 @@ procedure TBoldComConnectionHandle.ReceiveExtended(Originator: TObject; Original bceConnecting: begin SendEvent(Self,OriginalEvent); -// if Assigned(BeforeConnect) then BeforeConnect(Self); end; bceConnectFailed: begin @@ -240,17 +241,16 @@ procedure TBoldComConnectionHandle.SetConnected(Value: Boolean); begin if Value then begin - // Connect if FConnection.ConnectionState <> bceDisconnected then Exit; if ServerCLSID = '' then begin if ServerName = '' then - raise EBoldCom.Create(sUnspecifiedServer); + raise EBoldCom.Create('Cannot connect, no server specified.'); try ClassID := ProgIDToClassId(ServerName); except on Exception do - raise EBoldCom.Create(sInvalidServerName); + raise EBoldCom.Create('Cannot connect, invalid server name.'); end; end else @@ -260,7 +260,6 @@ procedure TBoldComConnectionHandle.SetConnected(Value: Boolean); end else begin - // Disconnect if FConnection.ConnectionState <> bceConnected then Exit; FConnection.Disconnect; @@ -272,7 +271,7 @@ procedure TBoldComConnectionHandle.SetServerCLSID(const Value: string); if Value <> ServerCLSID then begin if FConnection.ConnectionState <> bceDisconnected then - raise EBoldCom.CreateFmt(sCannotChangePropertyWhenActive, ['ServerCLSID']); // do not localize + raise EBoldCom.Create('Cannot change ServerCLSID on active connection.'); if Value = '' then FillChar(FServerCLSID, SizeOf(FServerCLSID), 0) else begin @@ -304,7 +303,7 @@ procedure TBoldComConnectionHandle.SetServerHost(const Value: string); if Value <> FServerHost then begin if FConnection.ConnectionState <> bceDisconnected then - raise EBoldCom.CreateFmt(sCannotChangePropertyWhenActive, ['ServerHost']); // do not localize + raise EBoldCom.Create('Cannot change ServerHost on active connection.'); FServerHost := Value; end; end; @@ -314,7 +313,7 @@ procedure TBoldComConnectionHandle.SetServerName(const Value: string); if Value <> ServerName then begin if FConnection.ConnectionState <> bceDisconnected then - raise EBoldCom.CreateFmt(sCannotChangePropertyWhenActive, ['ServerName']); // do not localize + raise EBoldCom.Create('Cannot change ServerName on active connection.'); FServerName := Value; if (FServerName <> '') and not (csReading in ComponentState) then begin @@ -332,7 +331,7 @@ procedure TBoldComConnectionHandle.SetThreaded(Value: Boolean); if Value <> FThreaded then begin if FConnection.ConnectionState <> bceDisconnected then - raise EBoldCom.CreateFmt(sCannotChangePropertyWhenActive, ['Threaded']); // do not localize + raise EBoldCom.Create('Cannot change Threaded on active connection.'); FThreaded := Value; end; end; @@ -428,7 +427,7 @@ procedure TBoldComImportHandle.SetActive(Value: Boolean); begin if Value then begin - inherited; // does the actual setting + inherited; if Connected then DoConnect; end @@ -436,7 +435,7 @@ procedure TBoldComImportHandle.SetActive(Value: Boolean); begin if Connected then DoDisconnect; - inherited; // does the actual setting + inherited; end; end; end; @@ -465,11 +464,11 @@ procedure TBoldComImportHandle.SetObjectName(const Value: string); if Connected then begin DoDisconnect; - inherited; // does the actual setting + inherited; DoConnect; end else - inherited; // does the actual setting + inherited; end; end; @@ -490,4 +489,6 @@ function TBoldComClientObjectHandle.GetComObject: IUnknown; Result := FComObject; end; +initialization + end. diff --git a/Source/Common/ConnectionHandlesCOM/BoldComServerHandles.pas b/Source/Common/ConnectionHandlesCOM/BoldComServerHandles.pas index 83c0d38..76afe23 100644 --- a/Source/Common/ConnectionHandlesCOM/BoldComServerHandles.pas +++ b/Source/Common/ConnectionHandlesCOM/BoldComServerHandles.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldComServerHandles; interface @@ -131,7 +134,7 @@ TBoldComExportHandle = class(TBoldExportHandle) end; TBoldComGetComObjectEvent = procedure(Sender: TObject; out Obj: IUnknown) of object; - + {-- TBoldComServerObjectHandle --} TBoldComServerObjectHandle = class(TBoldComExportHandle) private @@ -147,7 +150,6 @@ implementation uses SysUtils, - BoldComConst, ActiveX, ComObj, BoldHandle, @@ -212,14 +214,14 @@ procedure TBoldComClass.SetCLSID(const Value: string); begin if not IsLoading and not IsDesignTime then if Active then - raise EBoldCom.CreateFmt(sCannotChangeCLSIDAtRT,[ClassName]); + raise EBoldCom.CreateFmt('%s: Cannot change CLSID at run-time',[ClassName]); try GUID := StringToGUID(Value); FCLSID := Value; Changed(False); except on Exception do - raise EBoldCom.CreateFmt(sInvalidCLSID,[ClassName]); + raise EBoldCom.CreateFmt('%s: Invalid CLSID',[ClassName]); end; end; end; @@ -229,7 +231,7 @@ procedure TBoldComClass.SetDescription(const Value: string); if FDescription <> Value then begin if not IsLoading and not IsDesignTime then - raise EBoldCom.CreateFmt(sCannotChangeDescAtRT,[ClassName]); + raise EBoldCom.CreateFmt('%s: Cannot change Description at run-time',[ClassName]); FDescription := Value; Changed(False); end; @@ -246,14 +248,14 @@ procedure TBoldComClass.SetName(const Value: string); if FName <> Value then begin if not IsLoading and not IsDesignTime then - raise EBoldCom.CreateFmt(sCannotChangeNameAtRT,[ClassName]); + raise EBoldCom.CreateFmt('%s: Cannot change Name at run-time',[ClassName]); if IsValidIdent(Value) then begin FName := Value; Changed(False); end else - raise EBoldCom.CreateFmt(sInvalidName,[ClassName]); + raise EBoldCom.CreateFmt('%s: Invalid Name',[ClassName]); end; end; @@ -323,7 +325,7 @@ function TBoldComClasses.GetUniqueName: string; I := 0; repeat Inc(I); - Result := Format('Class%d',[I]); // do not localize + Result := Format('Class%d',[I]); until not ClassExists(Result); end; @@ -335,9 +337,7 @@ procedure TBoldComClasses.SetItem(Index: Integer; Value: TBoldComClass); procedure TBoldComClasses.Update(Item: TCollectionItem); begin if Item <> nil then - // updating item else - // update all end; {-- TBoldComObjectProvider ----------------------------------------------------} @@ -582,4 +582,6 @@ function TBoldComServerObjectHandle.GetHandledObject: TObject; Result := nil; end; +initialization + end. diff --git a/Source/Common/ConnectionHandlesCOM/BoldXMLDispatcher.pas b/Source/Common/ConnectionHandlesCOM/BoldXMLDispatcher.pas index 5fb1a74..73e4eef 100644 --- a/Source/Common/ConnectionHandlesCOM/BoldXMLDispatcher.pas +++ b/Source/Common/ConnectionHandlesCOM/BoldXMLDispatcher.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldXMLDispatcher; interface @@ -36,7 +39,7 @@ TBoldXMLSOAPService = class(TAutoIntfObject, IBoldSOAPService) end; TBoldXMLDispatchErrorEvent = procedure (const E: Exception; out response: string) of object; - + TBoldGetXMLRequestEvent = procedure (const XML: string; out Request: TBoldXMLRequest) of object; TBoldXMLDispatcher = class(TBoldComExportHandle) private @@ -75,7 +78,6 @@ TBoldXMLActionItem = class(TBoldUniquelyNamedCollectionItemWithNameStorage) constructor Create(Collection: TCollection); override; destructor Destroy; override; procedure DispatchAction(const request: TBoldXMLRequest; out response: string); -// function GetActionNode(const DomDocument: IXMLDomDocument; out DomNode: IXMLDomNode): Boolean; published property Default: Boolean read FDefault write SetDefault default False; property ActionName: string read getActionName write setActionName; @@ -98,12 +100,10 @@ TBoldXMLActions = class(TBoldCollectionWithUniquelyNamedItems) implementation -{$R *.res} - uses ActiveX, - windows, - BoldComConst; + windows + ; const breProducerDestroying = 100; @@ -113,14 +113,16 @@ implementation constructor TBoldXMLSOAPService.Create(Owner: TObject); var typelib: ITypeLib; + Res: HResult; begin - if (LoadRegTypeLib(LIBID_BoldSOAP, 1, 0, 0, typelib) = S_OK) then + Res := LoadRegTypeLib(LIBID_BoldSOAP, 1, 0, 0, typelib); + if (Res = S_OK) then begin inherited Create(typelib, IBoldSOAPService); FOwner := Owner; - end + end else - raise EBold.CreateFmt(sUnableToLoadTypeLibBoldSoap, [ClassName]); + raise EBold.CreateFmt('%s.Create: Unable to load type library LIBID_BoldSOAP. (LoadRegTypeLib Result: %d)', [ClassName, Res]); end; procedure TBoldXMLSOAPService.Get(const request: WideString; @@ -134,7 +136,7 @@ procedure TBoldXMLSOAPService.Get(const request: WideString; else XMLRequest := TBoldXMLRequest.CreateFromXML(request); if not Assigned(XMLRequest) then - raise EBold.CreateFmt(sXMLRequestNotAssigned, [ClassName]); + raise EBold.CreateFmt('%s.Get: XMLRequest not assigned', [ClassName]); (Owner as TBoldXMLDispatcher).DispatchAction(XMLRequest, ResponseXML); reply := ResponseXML; end; @@ -162,7 +164,7 @@ procedure TBoldXMLDispatcher.DispatchAction(const request: TBoldXMLRequest; begin try if not Assigned(request) then - raise EBold.CreateFmt(sXMLRequestIsNil, [ClassName]); + raise EBold.CreateFmt('%s.DispatchAction: request is nil', [ClassName]); I := 0; Default := nil; ActionName := request.ActionName; @@ -210,8 +212,8 @@ procedure TBoldXMLDispatcher.HandleDispatchError(const E: Exception; begin xmlresponse := TBoldXMLRequest.CreateInitialized; try - xmlresponse.SetAction('SOAP:Fault'); // do not localize - xmlresponse.AddParam('SOAP:faultstring', E.Message); // do not localize + xmlresponse.SetAction('SOAP:Fault'); + xmlresponse.AddParam('SOAP:faultstring', E.Message); response := xmlresponse.DomDocument.XML; finally FreeAndNil(xmlresponse); @@ -235,7 +237,7 @@ constructor TBoldXMLActionItem.Create(Collection: TCollection); s := Copy(ClassName, 2, MaxInt); repeat Inc(I); - aName := Format('%s%d',[s, I]); // do not localize + aName := Format('%s%d',[s, I]); until not Assigned(self.Collection.ItemByName[aName]); ActionName := aName; FSubscriber := TBoldPassThroughSubscriber.Create(_Receive); @@ -345,4 +347,5 @@ procedure TBoldXMLActionItem._Receive(Originator: TObject; Producer := nil; end; +initialization end. diff --git a/Source/Common/ConnectionHandlesCOM/BoldXMLDispatcherVB.pas b/Source/Common/ConnectionHandlesCOM/BoldXMLDispatcherVB.pas index c7269e6..5f03cc5 100644 --- a/Source/Common/ConnectionHandlesCOM/BoldXMLDispatcherVB.pas +++ b/Source/Common/ConnectionHandlesCOM/BoldXMLDispatcherVB.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldXMLDispatcherVB; interface @@ -8,8 +11,9 @@ interface BoldXMLRequests, comobj, BoldXMLDispatcher; - type + + TBoldXMLSOAPService2 = class(TAutoIntfObject, IBoldSOAPService2) private FOwner: TObject; @@ -20,20 +24,17 @@ TBoldXMLSOAPService2 = class(TAutoIntfObject, IBoldSOAPService2) constructor Create(Owner: TObject); property Owner: TObject read FOwner; end; - TBoldXMLDispatcherVB = class(TBoldXMLDispatcher) protected function GetComObject: IUnknown; override; end; -implementation -{$R *.res} +implementation uses ActiveX, - windows, - BoldComConst; + windows; { TBoldXMLSOAPService2 } @@ -47,7 +48,7 @@ constructor TBoldXMLSOAPService2.Create(Owner: TObject); FOwner := Owner; end else - raise EBold.CreateFmt(sUnableToLoadTypeLibBoldSoap, [ClassName]); + raise EBold.CreateFmt('%s.Create: Unable to load type library LIBID_BoldSOAP', [ClassName]); end; procedure TBoldXMLSOAPService2.Get(const request: WideString; @@ -61,11 +62,12 @@ procedure TBoldXMLSOAPService2.Get(const request: WideString; else XMLRequest := TBoldXMLRequest.CreateFromXML(request); if not Assigned(XMLRequest) then - raise EBold.CreateFmt(sXMLRequestNotAssigned, [ClassName]); + raise EBold.CreateFmt('%s.Get: XMLRequest not assigned', [ClassName]); (Owner as TBoldXMLDispatcher).DispatchAction(XMLRequest, ResponseXML); reply := ResponseXML; end; + function TBoldXMLSOAPService2.Get2(const request: WideString): WideString; begin Get(request, Result); @@ -78,5 +80,8 @@ function TBoldXMLDispatcherVB.GetComObject: IUnknown; Result := TBoldXMLSOAPService2.Create(self) as IUnknown; end; -end. + + + +end. diff --git a/Source/Common/Core/BoldBase.pas b/Source/Common/Core/BoldBase.pas index 7b46ce9..621863c 100644 --- a/Source/Common/Core/BoldBase.pas +++ b/Source/Common/Core/BoldBase.pas @@ -1,8 +1,16 @@ + +{ Global compiler directives } +{$include bold.inc} + unit BoldBase; interface uses +{$IFDEF DebugInstanceCounter} + Classes, + SysUtils, +{$ENDIF} BoldDefs; type @@ -12,12 +20,18 @@ TBoldRefCountedObject = class; TBoldNonRefCountedObject = class; {-- TBoldMemoryManagedObject --} +// TBoldMemoryManagedObject = TObject; // Just an alias, to avoid 1 level deeper inheritance for no reason TBoldMemoryManagedObject = class(TObject) + protected + function GetDebugInfo: string; virtual; + function ContextObject: TObject; virtual; public class function NewInstance: TObject; override; procedure FreeInstance; override; + property DebugInfo: string read GetDebugInfo; end; + {-- TBoldInterfacedObject --} TBoldInterfacedObject = class(TBoldMemoryManagedObject, IInterface) protected @@ -35,7 +49,7 @@ TBoldRefCountedObject = class(TBoldInterfacedObject) function _AddRef: Integer; override; function _Release: Integer; override; public - {$IFNDEF BOLD_BCB} { TODO : Check if needed in BCB6 } + {$IFNDEF BOLD_BCB} procedure AfterConstruction; override; class function NewInstance: TObject; override; {$ENDIF} @@ -79,27 +93,89 @@ TBoldNonRefCountedObject = class(TBoldInterfacedObject) BoldElementFlag22 = 1 shl 22; BoldElementFlag23 = 1 shl 23; - type +type + {---TBoldFlaggedObject---} TBoldFlaggedObject = class(TBoldMemoryManagedObject) private fStateAndFlagBank: cardinal; protected - procedure SetInternalState(Mask, shift, value: cardinal); - function GetInternalState(Mask, shift: cardinal): cardinal; - procedure SetElementFlag(Flag: TBoldElementFlag; Value: Boolean); - function GetElementFlag(Flag: TBoldElementFlag): Boolean; + procedure SetInternalState(Mask, shift, value: cardinal); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetInternalState(Mask, shift: cardinal): cardinal; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure SetElementFlag(Flag: TBoldElementFlag; Value: Boolean); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetElementFlag(Flag: TBoldElementFlag): Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + property StateAndFlagBank: cardinal read fStateAndFlagBank; // allow reading in subclasses end; +{$IFDEF DebugInstanceCounter} +const + cDefaultInstanceLimit = 1000; +var + DebugInstanceCounter: boolean = false; + +procedure GetInstaceList(AStringList: TStringList; ASort: boolean = true; AInstanceLimit: integer = cDefaultInstanceLimit); +procedure ClearInstanceLog; +{$ENDIF} + implementation uses BoldCommonConst, + + {$IFDEF DebugInstanceCounter} + BoldIndexableList, + BoldHashIndexes, + {$ENDIF} {$IFNDEF BOLD_DISABLEMEMORYMANAGER} BoldMemoryManager, {$ENDIF} Windows; +var + Finalized: boolean; + +{$IFDEF DebugInstanceCounter} +type + TBoldClassStats = class(TObject) + strict private + fClass: TClass; + fCreatedInstances: int64; + fDestroyedInstances: int64; + private + fChanged: boolean; + public + function LiveInstances: int64; + function MemoryUsage: int64; + procedure InstanceCreated; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure InstanceDestroyed; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + property BoldClass: TClass read fClass; + property CreatedInstances: int64 read fCreatedInstances; + property DestroyedInstances: int64 read fDestroyedInstances; + constructor Create(AClass: TClass); + end; + + TBoldClassStatsList = class(TBoldIndexableList) + private + function GetClassStats(const index: integer): TBoldClassStats; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + class var IX_Class: integer; + public + constructor Create; + function StatsForClass(AClassType: TClass): TBoldClassStats; + property ClassStats[const index: integer]: TBoldClassStats read GetClassStats; default; + property Count; + end; + + TClassIndex = class(TBoldClassHashIndex) + protected + function ItemAsKeyClass(Item: TObject): TClass; override; + end; + +var + gClassStatsList: TBoldClassStatsList; + gInternalUpdate: integer = 0; + +{$ENDIF} + {-- TBoldInterfacedObject -----------------------------------------------------} function TBoldInterfacedObject.QueryInterface(const IID: TGUID; out Obj): HResult; @@ -185,32 +261,218 @@ procedure TBoldFlaggedObject.SetInternalState(Mask, shift, value: cardinal); cardinal(Value shl Shift); end; +// warning, this code is duplicated in TBoldMember since inlining does not work as it should function TBoldFlaggedObject.GetInternalState(Mask, shift: cardinal): cardinal; begin result := (fStateAndFlagBank and mask) shr shift; end; -{-- TBoldMemoryManagedObject -----------------------------------------------------} +{$IFDEF DebugInstanceCounter} -procedure TBoldMemoryManagedObject.FreeInstance; +{ TBoldClassStatsList } + +constructor TBoldClassStatsList.Create; begin - {$IFNDEF BOLD_DISABLEMEMORYMANAGER} - CleanUpInstance; - BoldMemoryManager_.DeAllocateMemory(Pointer(self), InstanceSize); - {$ELSE} inherited; - {$ENDIF} + SetIndexCapacity(1); + IX_Class := -1; + SetIndexVariable(IX_Class, AddIndex(TClassIndex.Create)); +end; + +function TBoldClassStatsList.GetClassStats( + const index: integer): TBoldClassStats; +begin + Result := TBoldClassStats(inherited Items[index]); +end; + +function TBoldClassStatsList.StatsForClass(AClassType: TClass): TBoldClassStats; +begin + Result := TBoldClassStats(TClassIndex(Indexes[IX_Class]).FindByClass(AClassType)); + if not Assigned(Result) then + begin + Result := TBoldClassStats.Create(AClassType); + self.Add(result); + end; +end; + +{ TClassIndex } + +function TClassIndex.ItemAsKeyClass(Item: TObject): TClass; +begin + Result := TBoldClassStats(Item).BoldClass; +end; + +{ TBoldClassStats } + +constructor TBoldClassStats.Create(AClass: TClass); +begin + fClass := AClass; +end; + +procedure TBoldClassStats.InstanceCreated; +begin + inc(fCreatedInstances); + fChanged := true; +end; + +procedure TBoldClassStats.InstanceDestroyed; +begin + inc(fDestroyedInstances); + fChanged := true; +end; + +function TBoldClassStats.LiveInstances: int64; +begin + result := fCreatedInstances - fDestroyedInstances; +end; + +function TBoldClassStats.MemoryUsage: int64; +begin + result := LiveInstances * BoldClass.InstanceSize; +end; + +procedure GetInstaceList(AStringList: TStringList; ASort: boolean = true; AInstanceLimit: integer = cDefaultInstanceLimit); +var + vSl: TStringList; + i: integer; + vBoldClassStats: TBoldClassStats; + vTotalCreated, vTotalDestroyed, vTotalMemoryUsage: int64; +begin + vTotalCreated := 0; + vTotalDestroyed := 0; + vTotalMemoryUsage := 0; + vSl := TStringList.Create; + vSl.sorted := ASort; + try + for I := 0 to gClassStatsList.Count - 1 do + begin + vBoldClassStats := gClassStatsList[i]; + vBoldClassStats.fChanged := false; + Inc(vTotalCreated, vBoldClassStats.CreatedInstances); + inc(vTotalDestroyed, vBoldClassStats.DestroyedInstances); + Inc(vTotalMemoryUsage, vBoldClassStats.MemoryUsage); + if vBoldClassStats.LiveInstances > AInstanceLimit then + vSl.Add( Format('%10d - %10d = %10d: %s (%d bytes)', [vBoldClassStats.CreatedInstances, vBoldClassStats.DestroyedInstances, vBoldClassStats.LiveInstances, vBoldClassStats.BoldClass.ClassName, vBoldClassStats.MemoryUsage])); + end; + AStringList.Add(StringOfChar('-', 37)); + AStringList.Add(' Created - Destroyed = Live : ClassName (Minimal Memory usage in bytes)'); + AStringList.Add(StringOfChar('-', 37)); + AStringList.AddStrings(vSl); + AStringList.Add(StringOfChar('-', 37)); + AStringList.Add( Format('%10d - %10d = %10d: (%d bytes)', [vTotalCreated, vTotalDestroyed, vTotalCreated - vTotalDestroyed, vTotalMemoryUsage])); + AStringList.Add(StringOfChar('-', 37)); + finally + vSl.free; + end; +end; + +procedure ClearInstanceLog; +begin + gClassStatsList.Clear; +end; + +procedure CheckForLiveInstances; +var + i: integer; + vBoldClassStats: TBoldClassStats; + sl: TStringList; +begin + sl := TStringList.Create; + try + for I := 0 to gClassStatsList.Count - 1 do + begin + vBoldClassStats := gClassStatsList[i]; + if vBoldClassStats.LiveInstances > 0 then + sl.Add(Format('%d instances of %s', [vBoldClassStats.LiveInstances, vBoldClassStats.BoldClass.ClassName])); + end; + if sl.count > 0 then + raise Exception.Create(sl.text); + finally + sl.free; + end; +end; +{$ENDIF} + + +{ TBoldMemoryManagedObject } + +function TBoldMemoryManagedObject.GetDebugInfo: string; +begin + if ContextObject <> nil then + result := ContextObject.ClassName + else + result := ClassName; +end; + +function TBoldMemoryManagedObject.ContextObject: TObject; +begin + result := self; end; class function TBoldMemoryManagedObject.NewInstance: TObject; begin - {$IFNDEF BOLD_DISABLEMEMORYMANAGER} +{$IFNDEF BOLD_DISABLEMEMORYMANAGER} result := TObject(BoldMemoryManager_.AllocateMemory(InstanceSize)); InitInstance(result); - {$ELSE} +{$ELSE} result := inherited NewInstance; +{$ENDIF} +{$IFDEF DebugInstanceCounter} + if DebugInstanceCounter and (gInternalUpdate = 0) then + gClassStatsList.StatsForClass(self).InstanceCreated; +{$ENDIF} +end; + +procedure TBoldMemoryManagedObject.FreeInstance; + + procedure InternalRaise; + begin + raise EBold.Create('TBoldMemoryManagedObject.FreeInstance: Attempt to destroy object after BoldBase Finalization. Inspect/revert recent Uses clause changes.'); + end; + +begin + if Finalized then + InternalRaise; + {$IFDEF DebugInstanceCounter} + if DebugInstanceCounter and (gInternalUpdate = 0) then + gClassStatsList.StatsForClass(ClassType).InstanceDestroyed; {$ENDIF} +{$IFNDEF BOLD_DISABLEMEMORYMANAGER} + CleanUpInstance; + BoldMemoryManager_.DeAllocateMemory(Pointer(self), InstanceSize); +{$ELSE} + inherited; +{$ENDIF} end; +procedure InitDebugMethods; +begin + exit; +{$IFDEF BOLD_DISABLEMEMORYMANAGER} + with TBoldMemoryManagedObject(nil) do + begin + DebugInfo; + GetDebugInfo; + end; +{$ENDIF} +end; + +initialization +{$IFDEF DebugInstanceCounter} + inc(gInternalUpdate); + gClassStatsList := TBoldClassStatsList.Create; + dec(gInternalUpdate); +{$ENDIF} +InitDebugMethods; + +finalization +{$IFDEF DebugInstanceCounter} + CheckForLiveInstances; + inc(gInternalUpdate); + gClassStatsList.free; + dec(gInternalUpdate); +{$ENDIF} + Finalized := true; + end. diff --git a/Source/Common/Core/BoldContainers.pas b/Source/Common/Core/BoldContainers.pas index 67b0ee7..68fd40c 100644 --- a/Source/Common/Core/BoldContainers.pas +++ b/Source/Common/Core/BoldContainers.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldContainers; interface @@ -48,13 +51,13 @@ TBoldArray = class(TBoldContainer) procedure AddItems(const Items; NumItems: Integer); procedure EnsureCapacity; function GetCapacity: Integer; - procedure MoveItems(FromIndex, ToIndex, NumItems: Integer); + procedure MoveItems(FromIndex, ToIndex, NumItems: Integer); {$IFDEF BOLD_INLINE}inline;{$ENDIF} procedure SetCapacity(Value: Integer); protected - function Add(const Item): Integer; + function Add(const Item): Integer; {$IFDEF BOLD_INLINE}inline;{$ENDIF} function AddArray(BoldArray: TBoldArray): Integer; procedure Dispose(Index: Integer); virtual; - procedure Get(Index: Integer; var Item); + procedure Get(Index: Integer; var Item); {$IFDEF BOLD_INLINE}inline;{$ENDIF} function GetCount: Integer; override; function GetGrowDelta: Integer; virtual; function GetItemSize: Integer; virtual; abstract; @@ -73,8 +76,11 @@ TBoldArray = class(TBoldContainer) procedure DeleteRange(FromIndex, ToIndex: integer); procedure Exchange(Index1, Index2: Integer); procedure Move(FromIndex, ToIndex: Integer); - procedure Pack; - procedure Sort(Compare: TBoldArraySortCompare); + procedure Pack; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + procedure Sort(Compare: TBoldArraySortCompare; SortMode: TBoldSortMode = + BoldDefaultSortMode); overload; + procedure Sort(CompareFunc: TBoldArraySortCompare; FirstIndex, LastIndex: + Integer; SortMode: TBoldSortMode = BoldDefaultSortMode); overload; property Capacity: Integer read GetCapacity write SetCapacity; property ItemSize: Integer read GetItemSize; end; @@ -82,33 +88,47 @@ TBoldArray = class(TBoldContainer) { TBoldPointerArray } TBoldPointerArray = class(TBoldArray) private - function Get(Index: Integer): Pointer; - procedure Put(Index: Integer; Item: Pointer); + function Get(Index: Integer): Pointer; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + procedure Put(Index: Integer; Item: Pointer); {$IFDEF BOLD_INLINE}inline;{$ENDIF} protected function GetItemSize: Integer; override; public - function Add(Item: Pointer): Integer; - function IndexOf(Item: Pointer): Integer; - procedure Insert(Index: Integer; Item: Pointer); - function Remove(Item: Pointer): Integer; - function RemoveWithNil(Item: Pointer): Integer; + function Add(Item: Pointer): Integer; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function IndexOf(Item: Pointer): Integer; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + procedure Insert(Index: Integer; Item: Pointer); {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function Remove(Item: Pointer): Integer; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function RemoveWithNil(Item: Pointer): Integer; {$IFDEF BOLD_INLINE}inline;{$ENDIF} property Items[Index: Integer]: Pointer read Get write Put; default; end; + TBoldArrayTraverser = class(TBoldMemoryManagedObject) + private + FIndex: Integer; + FArray: TBoldObjectArray; + protected + property Index: Integer read fIndex; + property ObjectArray: TBoldObjectArray read fArray; + public + constructor Create(AArray: TBoldObjectArray); + function GetCurrent: TObject; + function MoveNext: Boolean; + end; + { TBoldObjectArray } TBoldObjectArray = class(TBoldArray) private - function Get(Index: Integer): TObject; - procedure Put(Index: Integer; Item: TObject); + function Get(Index: Integer): TObject; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + procedure Put(Index: Integer; Item: TObject); {$IFDEF BOLD_INLINE}inline;{$ENDIF} protected procedure Dispose(Index: Integer); override; function GetItemSize: Integer; override; public - function Add(Item: TObject): Integer; - function IndexOf(Item: TObject): Integer; - procedure Insert(Index: Integer; Item: TObject); - function Remove(Item: TObject): Integer; - function RemoveWithNil(Item: TObject): Integer; + function GetEnumerator: TBoldArrayTraverser; + function Add(Item: TObject): Integer; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function IndexOf(Item: TObject): Integer; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + procedure Insert(Index: Integer; Item: TObject); {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function Remove(Item: TObject): Integer; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function RemoveWithNil(Item: TObject): Integer; {$IFDEF BOLD_INLINE}inline;{$ENDIF} property Items[Index: Integer]: TObject read Get write Put; default; end; @@ -122,25 +142,25 @@ TBoldInterfaceArray = class(TBoldArray) function GetItemSize: Integer; override; public function Add(const Item: IUnknown): Integer; - function IndexOf(const Item: IUnknown): Integer; + function IndexOf(const Item: IUnknown): Integer; {$IFDEF BOLD_INLINE}inline;{$ENDIF} procedure Insert(Index: Integer; const Item: IUnknown); - function Remove(const Item: IUnknown): Integer; - function RemoveWithNil(const Item: IUnknown): Integer; + function Remove(const Item: IUnknown): Integer; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function RemoveWithNil(const Item: IUnknown): Integer; {$IFDEF BOLD_INLINE}inline;{$ENDIF} property Items[Index: Integer]: IUnknown read Get write Put; default; end; { TBoldIntegerArray } TBoldIntegerArray = class(TBoldArray) private - function Get(Index: Integer): integer; - procedure Put(Index: Integer; const Item: integer); + function Get(Index: Integer): integer; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + procedure Put(Index: Integer; const Item: integer); {$IFDEF BOLD_INLINE}inline;{$ENDIF} protected procedure Dispose(Index: Integer); override; function GetItemSize: Integer; override; public - function Add(const Item: integer): Integer; + function Add(const Item: integer): Integer; {$IFDEF BOLD_INLINE}inline;{$ENDIF} function IndexOf(const Item: integer): Integer; - procedure Insert(Index: Integer; const Item: integer); + procedure Insert(Index: Integer; const Item: integer); {$IFDEF BOLD_INLINE}inline;{$ENDIF} function Remove(const Item: integer): Integer; property Items[Index: Integer]: integer read Get write Put; default; end; @@ -153,47 +173,8 @@ TBoldIntegerArray = class(TBoldArray) implementation uses - SysUtils; - -procedure QuickSort(SortList: TBoldArray; L, R: Integer; - SCompare: TBoldArraySortCompare); -var - I, J: Integer; - P, T: Pointer; -begin - repeat - I := L; - J := R; - SortList.Get((L + R) shr 1, P); - repeat - SortList.Get(I, T); - while SCompare(T, P) < 0 do - begin - Inc(I); - SortList.Get(I, T); - end; - - SortList.Get(J, T); - while SCompare(T, P) > 0 do - begin - Dec(J); - SortList.Get(J, T); - end; - - if I <= J then - begin - SortList.Exchange(i, j); -{ SortList^[I] := SortList^[J]; - SortList^[J] := T;} - Inc(I); - Dec(J); - end; - until I > J; - if L < J then - QuickSort(SortList, L, J, SCompare); - L := I; - until I >= R; -end; + SysUtils, + BoldRev; {-- TBoldContainer ------------------------------------------------------------} @@ -217,12 +198,309 @@ destructor TBoldArray.Destroy; inherited; end; -procedure TBoldArray.Sort(Compare: TBoldArraySortCompare); +procedure TBoldArray.Sort(CompareFunc: TBoldArraySortCompare; FirstIndex, + LastIndex: Integer; SortMode: TBoldSortMode = BoldDefaultSortMode); + + ////////////////////////////////////////////////////////////////////////////// + // Insertion Sort: // + // stable, inplace, but only fast on small lists // + ////////////////////////////////////////////////////////////////////////////// + procedure InsertSort(L, R: Integer; SCompare: TBoldArraySortCompare); + var + I, J: Integer; + T: Pointer; + begin + GetMem(T, ItemSize); + for I := L + 1 to R do begin + if SCompare(@FArray^[I * ItemSize], + @FArray^[(I - 1) * ItemSize]) < 0 then + begin + J := I; + Get(J, T^); + while (J > L) and + (SCompare(T, @FArray^[(J - 1) * ItemSize]) < 0) do + begin + System.Move(FArray^[(J - 1) * ItemSize], + FArray^[J * ItemSize], + ItemSize); + Dec(J); + end; + Put(J, T^); + end; + end; + FreeMem(T, ItemSize); + end; + + ////////////////////////////////////////////////////////////////////////////// + // Quick Sort: // + // fast, inplace (without help array), // + // but NOT stable (sorting changes within same elements) // + ////////////////////////////////////////////////////////////////////////////// + procedure QuickSort(Left, Right: Integer; SCompare: TBoldArraySortCompare); + var + TempSize: Integer; + I, J: Integer; + P: Pointer; + begin + TempSize := ItemSize; + GetMem(P, TempSize); + try + repeat + I := Left; + J := Right; + System.Move(FArray^[((Left + Right) shr 1) * TempSize], P^, TempSize); + repeat + while SCompare(@FArray^[I * ItemSize], P) < 0 do + Inc(I); + while SCompare(@FArray^[J * ItemSize], P) > 0 do + Dec(J); + if I <= J then + begin + if I <> J then + begin + Exchange(I, J); + end; + Inc(I); + Dec(J); + end; + until I > J; + if Left < J then + QuickSort(Left, J, SCompare); + Left := I; + until I >= Right; + finally + FreeMem(P); + end; + end; +{ + ////////////////////////////////////////////////////////////////////////////// + // Merge Sort - Inplace Variant: // + // http://thomas.baudel.name/Visualisation/VisuTri/inplacestablesort.html // + // stable, inplace, but slower than Quicksort and normal Mergesort // + ////////////////////////////////////////////////////////////////////////////// + function Lower(Left, Right, Val: Integer; SCompare: TBoldElementCompare): + Integer; + var + iLen: Integer; + iHalf: Integer; + iMid: Integer; + begin + iLen := Right - Left; + while iLen > 0 do begin + iHalf := iLen div 2; + iMid := Left + iHalf; + if SCompare(Elements[iMid], Elements[Val]) < 0 then begin + Left := iMid + 1; + iLen := iLen - iHalf - 1; + end else begin + iLen := iHalf; + end; + end; + Result := Left; + end; + + function Upper(Left, Right, Val: Integer; SCompare: TBoldElementCompare): + Integer; + var + iLen: Integer; + iHalf: Integer; + iMid: Integer; + begin + iLen := Right - Left; + while iLen > 0 do begin + iHalf := iLen div 2; + iMid := Left + iHalf; + if SCompare(Elements[Val], Elements[iMid]) < 0 then begin + iLen := iHalf; + end else begin + Left := iMid + 1; + iLen := iLen - iHalf - 1; + end; + end; + Result := Left; + end; + + function GCD(M, N: Integer): Integer; + var + T: Integer; + begin + while (N <> 0) do begin + T := M mod N; + M := N; N := T; + end; + Result := M; + end; + + procedure Rotate(Left, Middle, Right: Integer; SCompare: TBoldElementCompare); + var + N: Integer; + SavedElement: TBoldElement; + Shift: Integer; + P1, P2: Integer; + begin + if (Left <> Middle) and (Right <> Middle) then begin + N := GCD(Right - Left, Middle - Left); + while N <> 0 do begin + Dec(N); + SavedElement := Elements[Left + N]; + Shift := Middle - Left; + P1 := Left + N; + P2 := Left + N + Shift; + while (P2 <> Left + N) do begin + Elements[P1] := Elements[P2]; + P1 := P2; + if Right - P2 > Shift then begin + Inc(P2, Shift); + end else begin + P2 := Left + (Shift - (Right - P2)); + end; + end; + Elements[P1] := SavedElement; + end; + end; + end; + + procedure MergeInplace(Left, Pivot, Right, Len1, Len2: Integer; SCompare: + TBoldElementCompare); + var + iFirstCut, iSecondCut: Integer; + iLen11, iLen22: Integer; + iNewMid: Integer; + begin + if (Len1 <> 0) and (Len2 <> 0) then begin + if Len1 + Len2 = 2 then begin + if SCompare(Elements[Pivot], Elements[Left]) < 0 then begin + if Pivot < Left then begin + Move(Pivot, Left); + Move(Left - 1, Pivot); + end else begin + Move(Left, Pivot); + Move(Pivot - 1, Left); + end; + end; + end else begin + if Len1 > Len2 then begin + iLen11 := Len1 div 2; + iFirstCut := Left + iLen11; + iSecondCut := Lower(Pivot, Right, iFirstCut, SCompare); + iLen22 := iSecondCut - Pivot; + end else begin + iLen22 := Len2 div 2; + iSecondCut := Pivot + iLen22; + iFirstCut := Upper(Left, Pivot, iSecondCut, SCompare); + iLen11 := iFirstCut - Left; + end; + Rotate(iFirstCut, Pivot, iSecondCut, SCompare); + iNewMid := iFirstCut + iLen22; + MergeInplace(Left, iFirstCut, iNewMid, iLen11, iLen22, SCompare); + MergeInplace(iNewMid, iSecondCut, Right, Len1 - iLen11, Len2 - iLen22, SCompare); + end; + end; + end; + + procedure MergeSortInplace(Left, Right: Integer; SCompare: TBoldElementCompare); + var + Middle: Integer; + begin + if Right - Left < 8 then begin + InsertSort(Left, Right, SCompare); + end else begin + Middle := (Left + Right) div 2; + MergeSortInplace(Left, Middle, SCompare); + MergeSortInplace(Middle, Right, SCompare); + MergeInplace(Left, Middle, Right, Middle - Left, Right - Middle, SCompare); + end; + end; +} + ////////////////////////////////////////////////////////////////////////////// + // Merge Sort: // + // http://www.iti.fh-flensburg.de/lang/algorithmen/sortieren/merge/merge.htm// + // fastest, stable, // + // but not fully inplace (help array with only n/2 is needed) // + ////////////////////////////////////////////////////////////////////////////// + procedure MergeSort(Left, Right: Integer; SCompare: TBoldArraySortCompare); + var + HelpArray: PByteArray; + + procedure DoMergeSort(Left, Right: Integer; SCompare: TBoldArraySortCompare); + var + m: Integer; + i, j, k: Integer; + begin + if Left < Right then begin + if Right - Left < 8 then begin + InsertSort(Left, Right, SCompare); + end else begin + m := (Left + Right) div 2; + DoMergeSort(Left, m, SCompare); + DoMergeSort(m + 1, Right, SCompare); + + j := m + 1; + // Copy first half of elements in help array + System.Move(FArray^[Left * ItemSize], + HelpArray^[0], + (j - Left) * ItemSize); + + i := 0; + k := Left; + // Copy back the next largest element + while (k < j) and (j <= Right) do begin + if SCompare(@HelpArray^[i * ItemSize], + @FArray^[J * ItemSize]) <= 0 then + begin + System.Move(HelpArray^[i * ItemSize], + FArray^[k * ItemSize], + ItemSize); + Inc(i); + end else begin + System.Move(FArray^[j * ItemSize], + FArray^[k * ItemSize], + ItemSize); + Inc(j); + end; + Inc(k); + end; + + // Copy back the rest of help array if existing + if k < j then begin + System.Move(HelpArray^[i * ItemSize], + FArray^[k * ItemSize], + (j - k) * ItemSize); + end; + end; + end; + end; + + var + TempSize: Integer; + begin + TempSize := ((Count + 1) div 2) * ItemSize; + GetMem(HelpArray, TempSize); + try + DoMergeSort(FirstIndex, LastIndex, CompareFunc); + finally + FreeMem(HelpArray); + end; + end; + begin - if Count > 0 then - QuickSort(self, 0, Count - 1, Compare); + if Assigned(Self) and (Count > 1) then begin + case SortMode of + smQuickSort: QuickSort(FirstIndex, LastIndex, CompareFunc); + smMergeSort: MergeSort(FirstIndex, LastIndex, CompareFunc); + smMergeSortInplace: begin +// MergeSortInplace(FirstIndex, LastIndex, CompareFunc); + raise EBoldInternal.Create('TBoldArray.Sort: smMergeSortInplace is not supported here'); + end; + end; + end; end; +procedure TBoldArray.Sort(Compare: TBoldArraySortCompare; SortMode: + TBoldSortMode = BoldDefaultSortMode); +begin + Sort(Compare, 0, Count - 1, SortMode); +end; function TBoldArray.Add(const Item): Integer; begin @@ -259,6 +537,20 @@ procedure TBoldArray.Clear; SetCapacity(0); end; +procedure TBoldArray.MoveItems(FromIndex, ToIndex, NumItems: Integer); +begin + if (FromIndex < 0) or (ToIndex < 0) or + (FromIndex + NumItems > FCapacity) or + (ToIndex + NumItems > FCapacity) then + begin + raise Exception.Create('Bad parameters to TBoldArray.MoveItems'); + end; + + System.Move(FArray^[FromIndex * ItemSize], + FArray^[ToIndex * ItemSize], + NumItems * ItemSize); +end; + procedure TBoldArray.Delete(Index: Integer); begin if (Index < 0) or (Index >= FCount) then @@ -293,11 +585,8 @@ procedure TBoldArray.Exchange(Index1, Index2: Integer); TempSize := ItemSize; GetMem(Item, TempSize); try - // copy item at Index 1 System.Move(FArray^[Index1 * TempSize], Item^, TempSize); - // copy Index2 to Index 1 System.Move(FArray^[Index2 * TempSize], FArray^[Index1 * TempSize], TempSize); - // copy copied item (Index1) to Index2 System.Move(Item^, FArray^[Index2 * TempSize], TempSize); finally FreeMem(Item); @@ -371,13 +660,6 @@ procedure TBoldArray.Move(FromIndex, ToIndex: Integer); end; end; -procedure TBoldArray.MoveItems(FromIndex, ToIndex, NumItems: Integer); -begin - System.Move(FArray^[FromIndex * ItemSize], - FArray^[ToIndex * ItemSize], - NumItems * ItemSize); -end; - procedure TBoldArray.Pack; begin SetCapacity(FCount); @@ -495,12 +777,8 @@ function TBoldObjectArray.Add(Item: TObject): Integer; end; procedure TBoldObjectArray.Dispose(Index: Integer); -var - Obj: TObject; begin - Obj := Get(Index); - if Assigned(Obj) then - Obj.Free; + Get(Index).Free; end; function TBoldObjectArray.Get(Index: Integer): TObject; @@ -508,6 +786,11 @@ function TBoldObjectArray.Get(Index: Integer): TObject; inherited Get(Index,Result); end; +function TBoldObjectArray.GetEnumerator: TBoldArrayTraverser; +begin + result := TBoldArrayTraverser.Create(self); +end; + function TBoldObjectArray.GetItemSize: Integer; begin Result := SizeOf(TObject); @@ -608,7 +891,6 @@ function TBoldIntegerArray.Add(const Item: integer): Integer; procedure TBoldIntegerArray.Dispose(Index: Integer); begin - // do nothing end; function TBoldIntegerArray.Get(Index: Integer): integer; @@ -663,4 +945,28 @@ procedure TBoldArray.DeleteRange(FromIndex, ToIndex: integer); MoveItems(ToIndex + 1, FromIndex, FCount - ToIndex); end; +{ TBoldArrayTraverser } + +constructor TBoldArrayTraverser.Create(AArray: TBoldObjectArray); +begin + inherited Create; + FIndex := -1; + FArray := AArray; +end; + +function TBoldArrayTraverser.GetCurrent: TObject; +begin + result := fArray[Index]; +end; + +function TBoldArrayTraverser.MoveNext: Boolean; +begin + Result := Index < fArray.Count - 1; + if Result then + Inc(FIndex); +end; + + +initialization + end. diff --git a/Source/Common/Core/BoldDefs.pas b/Source/Common/Core/BoldDefs.pas index b31c0a7..55f82f8 100644 --- a/Source/Common/Core/BoldDefs.pas +++ b/Source/Common/Core/BoldDefs.pas @@ -1,15 +1,19 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldDefs; interface uses + Classes, SysUtils; const NO_CLASS = -1; - INTERNALNULLKEY = -1; // used for 'databases' without NULL such as paradox and DBase - UNASSIGNEDID = -1; // indicating newly created DefaultID without DBValue + INTERNALNULLKEY = -1; + UNASSIGNEDID = -1; NOTVALIDCLIENTID = -1; @@ -19,14 +23,12 @@ interface BOLDCR = #13; BOLDLF = #10; - BOLDDIRSEPARATOR = '\'; // Prepare for other directory separator + BOLDDIRSEPARATOR = '\'; ALLFILESFILTER: string = 'All files (*.*)|*.*'; IDCOLUMN_NAME: string = 'BOLD_ID'; -// IDCOLUMN_SQLTYPE: string = 'INTEGER'; TYPECOLUMN_NAME: string = 'BOLD_TYPE'; -// TYPECOLUMN_SQLTYPE: string = 'SMALLINT'; TABLEPREFIXTAG = ''; DEFAULTTABLEPREFIX: string = 'Bold'; OBJECTTABLE_NAME: string = TABLEPREFIXTAG+'_OBJECT'; @@ -43,6 +45,7 @@ interface MMT_TABLENAME_COLUMN: String = 'TABLENAME'; MMT_COLUMNS_COLUMN: String = 'COLUMNS'; MMT_MAPPERNAME_COLUMN: String = 'MAPPERNAME'; + MMT_INDEX_COLUMN: string = 'COLUMNINDEX'; AllInstancesMappingTable_NAME: string = TABLEPREFIXTAG+'_R_CLSMAP'; AID_CLASSNAME_COLUMN: String = 'CLASSNAME'; @@ -59,17 +62,24 @@ interface TIMESTAMPCOLUMN_NAME: string = 'BOLD_TIME_STAMP'; GLOBALIDCOLUMN_NAME: string = 'EXTERNAL_ID'; TIMESTAMPSTARTCOLUMNNAME: String = 'TimeStampStart'; + TIMESTAMPSTARTCOLUMNNAMEUPPER: String = 'TIMESTAMPSTART'; TIMESTAMPSTOPCOLUMNNAME: String = 'TimeStampStop'; LASTTIMESTAMPCOLUMN_NAME: string = 'LastTimestamp'; THISTIMESTAMPCOLUMN_NAME: string = 'ThisTimestamp'; LASTCLOCKCOLUMN_NAME: string = 'LastClockTime'; THISCLOCKCOLUMN_NAME: string = 'ThisClockTime'; MODELVERSIONCOLUMN_NAME: string = 'MODEL_VERSION'; + ORDERCOLUMN_SUFFIX: string = '_O'; + ORDERCOLUMN_INDEX: integer = 1; {values for TBoldRepresentation} brDefault = 1; brShort = 2; brLong = 3; + brJson = 4; + brXml = 5; + brHtml = 6; + fmNormal = 0; fmDistributable = 1; @@ -86,12 +96,20 @@ interface PROPAGATOR_PARAMETER_DELIMITER_CHAR = '|'; + BOLD_DATABASE_ERROR_UNKNOWN = 'Unknown Error: %s'; + BOLD_DATABASE_ERROR_CONNECTION = 'Can not connect to Server %s '; + BOLD_DATABASE_ERROR_LOGIN = 'User %s failed to logon to database %s on server %s'; + BOLD_DATABASE_ERROR_LOGIN_WINDOWS_AUTH = '(Windows Authentication error)'; + BOLD_DATABASE_ERROR_SQL = 'Syntax of SQL "%s" is not correct. (%s)'; + BOLD_DATABASE_ERROR_UPDATE = 'Failed to update database'; + BOLD_DATABASE_ERROR_DEADLOCK = 'Deadlock occured. (%s)'; type TBoldRoleType= (rtRole, rtLinkRole, rtInnerLinkRole); + TBoldRoleSet = set of TBoldRoleType; TBoldDataBaseGenerationMode = (dbgTable, dbgQuery); TBoldStorage = (bsInternal, bsPartiallyExternal, bsExternal, bsExternalKey); - + TBoldTimeStampType = integer; TBoldClientID = Integer; @@ -106,25 +124,25 @@ interface TBoldDbType = integer; TBoldRepresentation = integer; TBoldExpression = string; - TBoldCompareType = (ctDefault, ctAsString, ctAsText, ctAsAnsiString, ctAsAnsiText, ctAsDate, ctAsTime); + TBoldCompareType = (ctDefault, ctAsString, ctCaseSensitive, ctCaseInsensitive, ctAsDate, ctAsTime); TBoldOrientation = (orHorizontal, orVertical, orGrid); TBoldSQLStyle = (ssColumns, ssParameters, ssValues); TBoldAbstractionLevel = (alAbstract, alConcrete); + TBoldAnsiString = {$IFDEF BOLD_UNICODE}AnsiString{$ELSE}string{$ENDIF}; + TBoldUnicodeString = {$IFDEF BOLD_UNICODE}string{$ELSE}WideString{$ENDIF}; - // Exception types - EBold = class(Exception); // General Bold Exception class - - EBoldDesignTime = class(EBold); // Raised for designtime errors - EBoldImport = class(EBold); // Raised for errors during import + EBold = class(Exception); + EBoldDesignTime = class(EBold); + EBoldImport = class(EBold); EBoldBadRepresentation = class(EBold); - EBoldInternal = class(EBold); // Raised for internal errors - EBoldFeatureNotImplementedYet = class(EBoldInternal); // Not yet... - EBoldBadColumnIndex = class(EBoldInternal); // Raised for column index "out of bound". + EBoldInternal = class(EBold); + EBoldFeatureNotImplementedYet = class(EBoldInternal); + EBoldBadColumnIndex = class(EBoldInternal); - EBoldAssertionFailed = class(EBold); // raised when a user defined constraint (ie May-operation) is violated. + EBoldAssertionFailed = class(EBold); EBoldXMLLoadError = class(EBold); EBoldXMLIncorrectXPath = class(EBold); @@ -134,18 +152,50 @@ EBoldEnsureDatabaseLockError = class(EBold); EBoldLockManagerError = class(EBold); EBoldLicenseError = class(EBold); + EBoldObjectIDError = class(EBold); + + EBoldMissingID = class(EBold); + + EBoldObjectNotInPs = class(EBold); + EBoldDuplicateSingleLinkValueInDb = class(EBold); + TBoldValuePersistenceState = (bvpsCurrent, bvpsModified, bvpsInvalid, bvpsTransient); TBoldValuePersistenceStateSet = set of TBoldValuePersistenceState; + TBoldDatabaseErrorType = (bdetError, bdetConnection, bdetUpdate, bdetSQL, + bdetDeadlock, bdetLogin); + EBoldDatabaseError = class(EBold) + private + FOriginalExceptionClass: string; + FOriginalExceptionMessage: string; + procedure SetOriginalExceptionClass(const Value: string); + procedure SetOriginalExceptionMessage(const Value: string); + public + property OriginalExceptionClass: string read FOriginalExceptionClass write SetOriginalExceptionClass; + property OriginalExceptionMessage: string read FOriginalExceptionMessage write SetOriginalExceptionMessage; + end; + + EBoldDatabaseConnectionError = class(EBoldDatabaseError); + EBoldDatabaseUpdateError = class(EBoldDatabaseError); + EBoldDatabaseSQLError = class(EBoldDatabaseError); + EBoldDatabaseDeadlockError = class(EBoldDatabaseError); + EBoldDatabaseLoginError = class(EBoldDatabaseError); // Log stuff TBoldLogType = (ltInfo, ltDetail, ltWarning, ltError, ltSeparator); TBoldModuleType = (mtUnit, mtText, mtIncFile); + TBoldSortMode = (smQuickSort, smMergeSort, smMergeSortInplace); const BOLDMAXTIMESTAMP = high(TBoldTimeStampType); BOLDINVALIDTIMESTAMP = -1; + {$IFDEF BOLD_DELPHI16_OR_LATER} + BOLDMAXLISTSIZE = MaxInt div 16; + {$ELSE} + BOLDMAXLISTSIZE = Classes.MaxListSize; + {$ENDIF} + {$IFDEF BOLD_DELPHI} BOLD_HOST_IDE = 'Delphi'; {$ENDIF} @@ -153,6 +203,73 @@ EBoldLicenseError = class(EBold); BOLD_HOST_IDE = 'C++Builder'; {$ENDIF} + {$IFDEF BOLD_DELPHI6} + BOLD_HOST_IDE_REGISTRYPATH = '\Software\Borland\' + BOLD_HOST_IDE + '\6.0\'; + {$ENDIF} + {$IFDEF BOLD_DELPHI7} + BOLD_HOST_IDE_REGISTRYPATH = '\Software\Borland\' + BOLD_HOST_IDE + '\7.0\'; + {$ENDIF} + {$IFDEF BOLD_DELPHI8} + BOLD_HOST_IDE_REGISTRYPATH = '\Software\Borland\BDS\1.0\'; + {$ENDIF} + {$IFDEF BOLD_DELPHI9} + BOLD_HOST_IDE_REGISTRYPATH = '\Software\Borland\BDS\2.0\'; + {$ENDIF} + {$IFDEF BOLD_DELPHI10} + BOLD_HOST_IDE_REGISTRYPATH = '\Software\Borland\BDS\3.0\'; + {$ENDIF} + {$IFDEF BOLD_DELPHI11} + BOLD_HOST_IDE_REGISTRYPATH = '\Software\Borland\BDS\4.0\'; + {$ENDIF} + {$IFDEF BOLD_DELPHI12} + BOLD_HOST_IDE_REGISTRYPATH = '\Software\Borland\BDS\5.0\'; + {$ENDIF} + {$IFDEF BOLD_DELPHI13} + BOLD_HOST_IDE_REGISTRYPATH = '\Software\CodeGear\BDS\6.0\'; + {$ENDIF} + {$IFDEF BOLD_DELPHI14} + BOLD_HOST_IDE_REGISTRYPATH = '\Software\CodeGear\BDS\7.0\'; + {$ENDIF} + {$IFDEF BOLD_DELPHI15} + BOLD_HOST_IDE_REGISTRYPATH = '\Software\Embarcadero\BDS\8.0\'; + {$ENDIF} + {$IFDEF BOLD_DELPHI16} + BOLD_HOST_IDE_REGISTRYPATH = '\Software\Embarcadero\BDS\9.0\'; + {$ENDIF} + {$IFDEF BOLD_DELPHI17} + BOLD_HOST_IDE_REGISTRYPATH = '\Software\Embarcadero\BDS\10.0\'; + {$ENDIF} + {$IFDEF BOLD_DELPHI18} + BOLD_HOST_IDE_REGISTRYPATH = '\Software\Embarcadero\BDS\11.0\'; + {$ENDIF} + {$IFDEF BOLD_DELPHI19} + BOLD_HOST_IDE_REGISTRYPATH = '\Software\Embarcadero\BDS\12.0\'; + {$ENDIF} + {$IFDEF BOLD_DELPHI20} + BOLD_HOST_IDE_REGISTRYPATH = '\Software\Embarcadero\BDS\13.0\'; + {$ENDIF} + {$IFDEF BOLD_DELPHI21} + BOLD_HOST_IDE_REGISTRYPATH = '\Software\Embarcadero\BDS\14.0\'; + {$ENDIF} + {$IFDEF BOLD_DELPHI22} + BOLD_HOST_IDE_REGISTRYPATH = '\Software\Embarcadero\BDS\15.0\'; + {$ENDIF} + {$IFDEF BOLD_DELPHI23} + BOLD_HOST_IDE_REGISTRYPATH = '\Software\Embarcadero\BDS\16.0\'; // check + {$ENDIF} + {$IFDEF BOLD_DELPHI24} + BOLD_HOST_IDE_REGISTRYPATH = '\Software\Embarcadero\BDS\18.0\'; + {$ENDIF} + {$IFDEF BOLD_DELPHI25} + BOLD_HOST_IDE_REGISTRYPATH = '\Software\Embarcadero\BDS\19.0\'; + {$ENDIF} + {$IFDEF BOLD_DELPHI26} + BOLD_HOST_IDE_REGISTRYPATH = '\Software\Embarcadero\BDS\20.0\'; + {$ENDIF} + {$IFDEF BOLD_DELPHI27} + BOLD_HOST_IDE_REGISTRYPATH = '\Software\Embarcadero\BDS\21.0\'; + {$ENDIF} + const ONE_SECOND = 1000; SIXTY_SECONDS = 60 * ONE_SECOND; @@ -164,8 +281,23 @@ EBoldLicenseError = class(EBold); beDisconnecting = 62; beModified = 63; +const + BoldDefaultSortMode = smMergeSort; // smQuickSort; implementation -end. +uses + BoldRev; + +{ EBoldDatabaseError } +procedure EBoldDatabaseError.SetOriginalExceptionClass(const Value: string); +begin + FOriginalExceptionClass := Value; +end; +procedure EBoldDatabaseError.SetOriginalExceptionMessage(const Value: string); +begin + FOriginalExceptionMessage := Value; +end; + +end. diff --git a/Source/Common/Core/BoldStreams.pas b/Source/Common/Core/BoldStreams.pas index 7028613..bbdacb9 100644 --- a/Source/Common/Core/BoldStreams.pas +++ b/Source/Common/Core/BoldStreams.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldStreams; interface @@ -15,4 +18,9 @@ interface implementation +uses + BoldRev; + +initialization + end. diff --git a/Source/Common/Core/BoldThreadSafeQueue.pas b/Source/Common/Core/BoldThreadSafeQueue.pas index 24669f3..d327adc 100644 --- a/Source/Common/Core/BoldThreadSafeQueue.pas +++ b/Source/Common/Core/BoldThreadSafeQueue.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldThreadSafeQueue; interface @@ -14,7 +17,6 @@ TBoldThreadSafeQueue = class; TBoldThreadSafeQueueEntry = class; TBoldThreadSafeStringQueue = class; - { prototypes } TBoldQueueEvent = procedure(Queue: TBoldThreadSafeQueue) of Object; {ring queue with marker} @@ -47,7 +49,7 @@ TBoldThreadSafeQueue = class(TBoldMemoryManagedObject) procedure NotifyQueueNotEmpty; function UnsafeIsEmpty: Boolean; {not threadsafe, for internal use only} public - constructor Create(Name: String); + constructor Create(const Name: String); destructor Destroy; override; procedure Clear; property Count: integer read GetCount; @@ -62,30 +64,32 @@ TBoldThreadSafeObjectQueue = class(TBoldThreadSafeQueue) fCount: integer; fMaxCount: integer; function GetMaxCount: integer; + procedure SetOwnsObjects(const Value: boolean); protected function GetCount: integer; override; procedure UnsafeEnqueue(anObject: TObject); function UnsafeDequeue: TObject; public - constructor Create(Name: String; OwnsObjects: Boolean = true); + constructor Create(const Name: String; OwnsObjects: Boolean = true); procedure Enqueue(anObject: TObject); procedure DequeueList(ResultList: TObjectList; Max: integer); function Dequeue: TObject; // returns nil if queue empty - property OwnsObjects: boolean read fOwnsObjects; + property OwnsObjects: boolean read fOwnsObjects write SetOwnsObjects; property MaxCount: integer read GetMaxCount; end; { TBoldThreadSafeInterfaceQueue } TBoldThreadSafeInterfaceQueue = class(TBoldThreadSafeQueue) public - procedure Enqueue(anInterface: IInterface); + procedure Enqueue(const anInterface: IInterface); function Dequeue: IInterface; // returns nil if queue empty end; { TBoldThreadSafeStringQueue } TBoldThreadSafeStringQueue = class(TBoldThreadSafeQueue) public - procedure Enqueue(aString: string); + procedure Enqueue(const aString: string); + procedure EnqueueList(aList: TStrings); function Dequeue: string; // returns '' string if queue empty procedure AppendToStringList(aList: TStrings); end; @@ -93,7 +97,8 @@ TBoldThreadSafeStringQueue = class(TBoldThreadSafeQueue) implementation uses - SysUtils; + SysUtils, + BoldRev; type { TBoldThreadSafeQueueObjectEntry } @@ -113,7 +118,7 @@ TBoldThreadSafeQueueStringEntry = class(TBoldThreadSafeQueueEntry) private faString: string; public - constructor CreateAfter(aString: string; Entry: TBoldThreadSafeQueueEntry); + constructor CreateAfter(const aString: string; Entry: TBoldThreadSafeQueueEntry); property aString: string read fAString; end; @@ -128,7 +133,7 @@ TBoldThreadSafeQueueInterfaceEntry = class(TBoldThreadSafeQueueEntry) { TBoldThreadSafeQueue } -constructor TBoldThreadSafeQueue.Create(Name: String); +constructor TBoldThreadSafeQueue.Create(const Name: String); begin inherited create; fLocker := TBoldLoggableCriticalSection.Create(Name); @@ -253,7 +258,7 @@ function TBoldThreadSafeQueueObjectEntry.GetObject: TObject; { TBoldThreadSafeObjectQueue } -constructor TBoldThreadSafeObjectQueue.Create(Name: String; OwnsObjects: Boolean); +constructor TBoldThreadSafeObjectQueue.Create(const Name: String; OwnsObjects: Boolean); begin inherited Create(Name); fOwnsObjects := OwnsObjects; @@ -311,6 +316,16 @@ function TBoldThreadSafeObjectQueue.GetMaxCount: integer; end; end; +procedure TBoldThreadSafeObjectQueue.SetOwnsObjects(const Value: boolean); +begin + Lock; + try + fOwnsObjects := Value; + finally + Unlock; + end; +end; + function TBoldThreadSafeObjectQueue.UnsafeDequeue: TObject; var Head: TBoldThreadSafeQueueEntry; @@ -343,7 +358,7 @@ procedure TBoldThreadSafeObjectQueue.UnsafeEnqueue(anObject: TObject); { TBoldThreadSafeQueueStringEntry } -constructor TBoldThreadSafeQueueStringEntry.CreateAfter(aString: string; +constructor TBoldThreadSafeQueueStringEntry.CreateAfter(const aString: string; Entry: TBoldThreadSafeQueueEntry); begin inherited CreateAfter(Entry); @@ -391,7 +406,7 @@ function TBoldThreadSafeStringQueue.Dequeue: string; end; end; -procedure TBoldThreadSafeStringQueue.Enqueue(aString: string); +procedure TBoldThreadSafeStringQueue.Enqueue(const aString: string); var WasEmpty: Boolean; begin @@ -407,6 +422,29 @@ procedure TBoldThreadSafeStringQueue.Enqueue(aString: string); end; end; +procedure TBoldThreadSafeStringQueue.EnqueueList(aList: TStrings); +var + WasEmpty: Boolean; + i: integer; + s: string; +begin + if (aList.Count = 0) then exit; + Lock; + try + WasEmpty := UnsafeIsEmpty; + for I := 0 to aList.Count - 1 do + begin + s := aList[i]; + assert(s <> ''); + TBoldThreadSafeQueueStringEntry.CreateAfter(s, fMarker); + end; + if (WasEmpty) then + NotifyQueueNotEmpty; + finally + Unlock; + end; +end; + { TBoldThreadSafeInterfaceQueue } function TBoldThreadSafeInterfaceQueue.Dequeue: IInterface; @@ -429,7 +467,7 @@ function TBoldThreadSafeInterfaceQueue.Dequeue: IInterface; end; end; -procedure TBoldThreadSafeInterfaceQueue.Enqueue(anInterface: IInterface); +procedure TBoldThreadSafeInterfaceQueue.Enqueue(const anInterface: IInterface); var WasEmpty: Boolean; begin @@ -443,7 +481,7 @@ procedure TBoldThreadSafeInterfaceQueue.Enqueue(anInterface: IInterface); finally Unlock; end; -end; +end; { TBoldThreadSafeQueueInterfaceEntry } @@ -454,4 +492,6 @@ constructor TBoldThreadSafeQueueInterfaceEntry.CreateAfter( fanInterface := anInterface; end; +initialization + end. diff --git a/Source/Common/Environment/BoldEnvironment.pas b/Source/Common/Environment/BoldEnvironment.pas index ffd7abc..cef86a6 100644 --- a/Source/Common/Environment/BoldEnvironment.pas +++ b/Source/Common/Environment/BoldEnvironment.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldEnvironment; interface @@ -31,10 +34,9 @@ TBoldEnvironmentConfiguration = class fApplicationSubscriber: TBoldApplicationSubscriber; fQueueFinalized: Boolean; procedure FinalizeQueue; -// this procedure should be called _ApplicationDestroyed - procedure DeactivateQueue; + procedure _ApplicationDestroyed; - function GetRunningInIDE: Boolean; + class function GetRunningInIDE: Boolean; protected function GetQueue: TBoldQueue; function GetQueueClass: TBoldQueueClass; virtual; @@ -42,6 +44,7 @@ TBoldEnvironmentConfiguration = class function GetName: string; virtual; abstract; function GetRootComponent: TComponent; virtual; public + procedure AfterConstruction; override; destructor Destroy; override; procedure HandleDesigntimeException(Sender: TObject); virtual; procedure UpdateDesigner(Sender: TObject); virtual; @@ -62,7 +65,7 @@ TBoldEnvironmentConfiguration = class TBoldFreestandingEnvironmentConfiguration = class(TBoldEnvironmentConfiguration) protected function GetName: string; override; - public + public procedure BringToFront; override; procedure FocusMainForm; override; end; @@ -79,20 +82,23 @@ TBoldFreestandingEnvironmentConfiguration = class(TBoldEnvironmentConfiguratio function BoldEffectiveEnvironment: TBoldEnvironmentConfiguration; function BoldEnvironmentsFinalized: Boolean; + function BoldInstalledQueue: TBoldQueue; {$IFDEF BOLD_INLINE} inline; {$ENDIF} implementation uses SysUtils, - BoldEnvironmentVCL; //Temporary fix + BoldEnvironmentVCL, // Don't remove this! + BoldRev; const UnsupportedFunction = '%s: function unsupported in environment configuration %s'; var G_EnvironmentsFinalized: Boolean = false; + G_BoldEffectiveEnvironment: TBoldEnvironmentConfiguration; -function BoldEffectiveEnvironment: TBoldEnvironmentConfiguration; +function GetBoldEffectiveEnvironment: TBoldEnvironmentConfiguration; begin if Assigned(BoldInternalCustomConfiguration) then Result := BoldInternalCustomConfiguration @@ -109,6 +115,21 @@ function BoldEffectiveEnvironment: TBoldEnvironmentConfiguration; raise EBoldInternal.Create('BoldEffectiveEnvironment, no environment available. Unit BoldEnvironment either not initialized, or already finalized'); end; +function BoldEffectiveEnvironment: TBoldEnvironmentConfiguration; +begin + if not Assigned(G_BoldEffectiveEnvironment) then + G_BoldEffectiveEnvironment := GetBoldEffectiveEnvironment; + result := G_BoldEffectiveEnvironment; +end; + +function BoldInstalledQueue: TBoldQueue; +begin + if BoldEnvironmentsFinalized then + result := nil + else + result := BoldEffectiveEnvironment.Queue; +end; + function BoldEnvironmentsFinalized: Boolean; begin result := G_EnvironmentsFinalized; @@ -116,6 +137,12 @@ function BoldEnvironmentsFinalized: Boolean; { TBoldEnvironmentConfiguration } +procedure TBoldEnvironmentConfiguration.AfterConstruction; +begin + inherited; + G_BoldEffectiveEnvironment := nil; +end; + function TBoldEnvironmentConfiguration.AskUser(const Text: string): Boolean; begin raise EBoldInternal.CreateFmt(UnsupportedFunction, ['AskUser', Name]); @@ -147,7 +174,7 @@ procedure TBoldEnvironmentConfiguration.ProcessMessages; raise EBoldInternal.CreateFmt(UnsupportedFunction, ['ProcessMessages', Name]) end; -function TBoldEnvironmentConfiguration.GetRunningInIDE: Boolean; +class function TBoldEnvironmentConfiguration.GetRunningInIDE: Boolean; begin Result := BoldInternalRunningInIDE; end; @@ -168,14 +195,13 @@ function TBoldEnvironmentConfiguration.GetQueue: TBoldQueue; begin fQueue := GetQueueClass.Create; fApplicationSubscriber := TBoldApplicationSubscriber.Create(RootComponent); - fApplicationSubscriber.OnApplicationDestroyed := DeactivateQueue; + fApplicationSubscriber.OnApplicationDestroyed := _ApplicationDestroyed; end; Result := fQueue; end; procedure TBoldEnvironmentConfiguration.FinalizeQueue; begin - //NOTE: Cannot use FreeAndNil, as it does things in the wrong order. if Assigned(fQueue) then begin fQueue.Free; @@ -198,6 +224,7 @@ destructor TBoldEnvironmentConfiguration.Destroy; begin if not QueueFinalized then FinalizeQueue; + G_BoldEffectiveEnvironment := nil; inherited; end; @@ -216,8 +243,7 @@ procedure TBoldEnvironmentConfiguration.TriggerQueueMechanism; raise EBoldInternal.CreateFmt(UnsupportedFunction, ['TriggerQueueMechanism', Name]); end; -// this procedure should be called _ApplicationDestroyed -procedure TBoldEnvironmentConfiguration.DeactivateQueue; +procedure TBoldEnvironmentConfiguration._ApplicationDestroyed; begin fApplicationSubscriber := nil; if assigned(fQueue) and not QueueFinalized then @@ -228,19 +254,17 @@ procedure TBoldEnvironmentConfiguration.DeactivateQueue; procedure TBoldFreestandingEnvironmentConfiguration.BringToFront; begin - // Don't call inherited - // Ignore silently + end; procedure TBoldFreestandingEnvironmentConfiguration.FocusMainForm; begin - // Don't call inherited - // Ignore silently + end; function TBoldFreestandingEnvironmentConfiguration.GetName: string; begin - Result := 'Freestanding'; // do not localize + Result := 'Freestanding'; end; { TBoldApplicationSubscriber } @@ -263,6 +287,7 @@ finalization FreeAndNil(BoldInternalCLXConfiguration); FreeAndNil(BoldInternalCustomConfiguration); FreeAndNil(BoldInternalFreestandingConfiguration); + G_BoldEffectiveEnvironment := nil; G_EnvironmentsFinalized := true; end. diff --git a/Source/Common/Environment/BoldEnvironmentAllowBothUseCLX.pas b/Source/Common/Environment/BoldEnvironmentAllowBothUseCLX.pas index 272c2e4..486ebd2 100644 --- a/Source/Common/Environment/BoldEnvironmentAllowBothUseCLX.pas +++ b/Source/Common/Environment/BoldEnvironmentAllowBothUseCLX.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldEnvironmentAllowBothUseCLX; interface @@ -7,9 +10,9 @@ implementation uses BoldEnvironmentVCL, BoldEnvironmentCLX, - BoldEnvironment; + BoldEnvironment, + BoldRev; initialization BoldInternalAllowBothUseCLX := true; end. - diff --git a/Source/Common/Environment/BoldEnvironmentAllowBothUseVCL.pas b/Source/Common/Environment/BoldEnvironmentAllowBothUseVCL.pas index 998a2f0..76565f4 100644 --- a/Source/Common/Environment/BoldEnvironmentAllowBothUseVCL.pas +++ b/Source/Common/Environment/BoldEnvironmentAllowBothUseVCL.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldEnvironmentAllowBothUseVCL; interface @@ -7,9 +10,9 @@ implementation uses BoldEnvironmentVCL, BoldEnvironmentCLX, - BoldEnvironment; + BoldEnvironment, + BoldRev; initialization BoldInternalAllowBothUseVCL := true; end. - diff --git a/Source/Common/Environment/BoldEnvironmentCLX.pas b/Source/Common/Environment/BoldEnvironmentCLX.pas index 77b16db..1254805 100644 --- a/Source/Common/Environment/BoldEnvironmentCLX.pas +++ b/Source/Common/Environment/BoldEnvironmentCLX.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldEnvironmentCLX; interface @@ -14,14 +17,14 @@ implementation QExtCtrls, BoldEnvironment, BoldQueue, - BoldCommonConst; + BoldRev; type TBoldCLXEnvironmentConfiguration = class(TBoldEnvironmentConfiguration) protected function GetName: string; override; function GetRootComponent: TComponent; override; - function GetQueueClass: TBoldQueueClass; override; + function GetQueueClass: TBoldQueueClass; override; public procedure HandleDesigntimeException(Sender: TObject); override; procedure UpdateDesigner(Sender: TObject);override; @@ -32,8 +35,6 @@ TBoldCLXEnvironmentConfiguration = class(TBoldEnvironmentConfiguration) procedure FocusMainForm; override; end; - // Use the fact the a timer with 0 time will be placed last in queue - // This was communicated by Chuck J, does not seem to be documented, but is used in QForms.Application TBoldTimerQueue = class(TBoldQueue) private @@ -53,26 +54,23 @@ TBoldTimerQueue = class(TBoldQueue) function TBoldCLXEnvironmentConfiguration.AskUser(const Text: string): Boolean; begin - // Don't call inherited Result := MessageDlg(Text, mtWarning, [mbYes, mbNo], 0) = mrYes; end; procedure TBoldCLXEnvironmentConfiguration.BringToFront; begin - // Don't call inherited Application.BringToFront end; procedure TBoldCLXEnvironmentConfiguration.FocusMainForm; begin - // Don't call inherited if Assigned(Application) and Assigned(Application.MainForm) then Application.MainForm.SetFocus; end; function TBoldCLXEnvironmentConfiguration.GetName: string; begin - Result := 'CLX'; // do not localize + Result := 'CLX'; end; function TBoldCLXEnvironmentConfiguration.GetQueueClass: TBoldQueueClass; @@ -82,27 +80,23 @@ function TBoldCLXEnvironmentConfiguration.GetQueueClass: TBoldQueueClass; function TBoldCLXEnvironmentConfiguration.GetRootComponent: TComponent; begin - // Don't call inherited Result := Application; end; procedure TBoldCLXEnvironmentConfiguration.HandleDesigntimeException( Sender: TObject); begin - // Don't call inherited Application.HandleException(Sender); end; function TBoldCLXEnvironmentConfiguration.IsFormOrDataModule( Sender: TObject): Boolean; begin - // Don't call inherited Result := (Sender is TForm) or (Sender is TDataModule); end; procedure TBoldCLXEnvironmentConfiguration.ProcessMessages; begin - // Don't call inherited; Application.ProcessMessages; end; @@ -112,8 +106,7 @@ procedure TBoldCLXEnvironmentConfiguration.UpdateDesigner(Sender: TObject); Owner: TComponent; begin if not RunningInIDE then - raise EBold.CreateFmt(sNotRunningInIDE, ['UpdateDesigner']); // do not localize - // Don't call inherited + raise EBold.CreateFmt('%s: Not running in IDE', ['UpdateDesigner']); ParentForm := nil; Owner := nil; if (Sender is TControl) then @@ -125,13 +118,10 @@ procedure TBoldCLXEnvironmentConfiguration.UpdateDesigner(Sender: TObject); if Assigned(Owner) then begin if (Owner is TCustomFrame) then - // this happens if the model resides in a frame ParentForm := GetParentForm(TCustomFrame(Owner)) else if (Owner is TCustomForm) then - // this happens if the model resides on a form ParentForm := TCustomForm(Owner) else if (Owner is TDataModule) and Assigned(Owner.Owner) and (Owner.Owner is TCustomForm) then - // this happens if the component resides on a Datamodule, the owner.owner is a TDatamoduleDesigner... ParentForm := TCustomForm(Owner.Owner); end; end; @@ -158,7 +148,7 @@ function TBoldTimerQueue.GetIdleTimer: TTimer; if not Assigned(fIdleTimer) then begin fIdleTimer := TTimer.Create(nil); - fIdleTimer.Interval := MaxInt; + fIdleTimer.Interval := MaxInt; fIdleTimer.OnTimer := IdleTimerEvent; end; Result := fIdleTimer; @@ -176,7 +166,7 @@ procedure TBoldTimerQueue.IdleTimerEvent(Sender: TObject); dmDisplayOne: Done := not DisplayOne; dmDisplayAll: Done := not DisplayAll; else - raise EBoldInternal.CreateFmt(sUnknownDisplayMode, [classname]); + raise EBoldInternal.CreateFmt('%s.ApplicationEventsOnIdle: Unknown displaymode', [classname]); end; end; except @@ -190,18 +180,16 @@ procedure TBoldTimerQueue.IdleTimerEvent(Sender: TObject); procedure TBoldTimerQueue.ActivateDisplayQueue; begin - // Don't call inherited, abstract in parent fBoldQueueActive := true; IdleTimer.Interval := 0; end; procedure TBoldTimerQueue.DeActivateDisplayQueue; begin - // Don't call inherited, abstract in parent fBoldQueueActive := false; IdleTimer.Interval := MaxInt; end; initialization - BoldInternalCLXConfiguration := TBoldCLXEnvironmentConfiguration.Create; // Freed in finalization of BoldEnvironment + BoldInternalCLXConfiguration := TBoldCLXEnvironmentConfiguration.Create; end. diff --git a/Source/Common/Environment/BoldEnvironmentIDE.pas b/Source/Common/Environment/BoldEnvironmentIDE.pas index 35445be..891159c 100644 --- a/Source/Common/Environment/BoldEnvironmentIDE.pas +++ b/Source/Common/Environment/BoldEnvironmentIDE.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldEnvironmentIDE; interface @@ -5,10 +8,15 @@ interface implementation uses + {$IFDEF BOLD_IDEVCL} BoldEnvironmentVCL, - BoldEnvironment; + {$ENDIF} + {$IFDEF BOLD_IDECLX} + BoldEnvironmentCLX, + {$ENDIF} + BoldEnvironment, + BoldRev; initialization BoldInternalRunningInIDE := true; end. - diff --git a/Source/Common/Environment/BoldEnvironmentVCL.pas b/Source/Common/Environment/BoldEnvironmentVCL.pas index 84eda90..5463920 100644 --- a/Source/Common/Environment/BoldEnvironmentVCL.pas +++ b/Source/Common/Environment/BoldEnvironmentVCL.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldEnvironmentVCL; interface @@ -16,7 +19,7 @@ implementation Forms, BoldQueue, BoldEnvironment, - BoldCommonConst; + BoldRev; type { forward declarations } @@ -57,26 +60,23 @@ TBoldVCLEnvironmentConfiguration = class(TBoldEnvironmentConfiguration) function TBoldVCLEnvironmentConfiguration.AskUser(const Text: string): Boolean; begin - // Don't call inherited Result := MessageDlg(Text, mtWarning, [mbYes, mbNo], 0) = mrYes; end; procedure TBoldVCLEnvironmentConfiguration.BringToFront; begin - // Don't call inherited Application.BringToFront end; procedure TBoldVCLEnvironmentConfiguration.FocusMainForm; begin - // Don't call inherited if Assigned(Application) and Assigned(Application.MainForm) then Application.MainForm.SetFocus; end; function TBoldVCLEnvironmentConfiguration.GetName: string; begin - Result := 'VCL'; // do not localize + Result := 'VCL'; end; function TBoldVCLEnvironmentConfiguration.GetQueueClass: TBoldQueueClass; @@ -86,33 +86,28 @@ function TBoldVCLEnvironmentConfiguration.GetQueueClass: TBoldQueueClass; function TBoldVCLEnvironmentConfiguration.GetRootComponent: TComponent; begin - // Don't call inherited Result := Application; end; procedure TBoldVCLEnvironmentConfiguration.HandleDesigntimeException(Sender: TObject); begin - // Don't call inherited Application.HandleException(Sender); end; function TBoldVCLEnvironmentConfiguration.IsFormOrDataModule(Sender: TObject): Boolean; begin - // Don't call inherited Result := (Sender is TForm) or (Sender is TDataModule); end; procedure TBoldVCLEnvironmentConfiguration.ProcessMessages; begin - // Don't call inherited; Application.ProcessMessages; end; procedure TBoldVCLEnvironmentConfiguration.TriggerQueueMechanism; begin - // is there a better message to send to get the applicaiton to exit the idlestate? - // perhaps a timer? - // remember that it might be called from another thread... + + PostMessage(Application.Handle, WM_PAINT, 0, 0); end; @@ -121,9 +116,8 @@ procedure TBoldVCLEnvironmentConfiguration.UpdateDesigner(Sender: TObject); ParentForm: TCustomForm; Owner: TComponent; begin - // Don't call inherited if not RunningInIDE then - raise EBold.CreateFmt(sNotRunningInIDE, ['UpdateDesigner']); // do not localize + raise EBold.CreateFmt('%s: Not running in IDE', ['UpdateDesigner']); ParentForm := nil; Owner := nil; if (Sender is TControl) then @@ -135,13 +129,10 @@ procedure TBoldVCLEnvironmentConfiguration.UpdateDesigner(Sender: TObject); if Assigned(Owner) then begin if (Owner is TCustomFrame) then - // this happens if the model resides in a frame ParentForm := GetParentForm(TCustomFrame(Owner)) else if (Owner is TCustomForm) then - // this happens if the model resides on a form ParentForm := TCustomForm(Owner) else if (Owner is TDataModule) and Assigned(Owner.Owner) and (Owner.Owner is TCustomForm) then - // this happens if the component resides on a Datamodule, the owner.owner is a TDatamoduleDesigner... ParentForm := TCustomForm(Owner.Owner); end; end; @@ -153,7 +144,6 @@ procedure TBoldVCLEnvironmentConfiguration.UpdateDesigner(Sender: TObject); procedure TBoldAppEventQueue.ActivateDisplayQueue; begin - // Don't call inherited, abstract in parent fBoldQueueActive := true; AppEvents.OnIdle := ApplicationEventsOnIdle; end; @@ -168,17 +158,19 @@ procedure TBoldAppEventQueue.ApplicationEventsOnIdle(Sender: TObject; var Done: dmDisplayOne: Done := not DisplayOne; dmDisplayAll: Done := not DisplayAll; else - raise EBoldInternal.CreateFmt(sUnknownDisplayMode, [classname]); + raise EBoldInternal.CreateFmt('%s.ApplicationEventsOnIdle: Unknown displaymode', [classname]); end; + if Done then + PerformPostDisplayQueue; end; except Application.HandleException(nil); end; + end; procedure TBoldAppEventQueue.DeActivateDisplayQueue; begin - // Don't call inherited, abstract in parent fBoldQueueActive := false; AppEvents.OnIdle := nil; end; diff --git a/Source/Common/HTTP/BoldDataBlock.pas b/Source/Common/HTTP/BoldDataBlock.pas index 747b9a7..2cff1d3 100644 --- a/Source/Common/HTTP/BoldDataBlock.pas +++ b/Source/Common/HTTP/BoldDataBlock.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldDataBlock; interface @@ -38,7 +41,8 @@ TBoldDataBlock = class(TBoldMemoryManagedObject) implementation uses - SysUtils; + SysUtils, + BoldRev; { TBoldDataBlock} @@ -96,4 +100,6 @@ function TBoldDataBlock.GetMemory: Pointer; Result := FStream.Memory; end; +initialization + end. diff --git a/Source/Common/HTTP/BoldWebConnection.pas b/Source/Common/HTTP/BoldWebConnection.pas index a80ac4a..de666b4 100644 --- a/Source/Common/HTTP/BoldWebConnection.pas +++ b/Source/Common/HTTP/BoldWebConnection.pas @@ -1,7 +1,9 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldWebConnection; interface - uses BoldWinInet, Classes, @@ -12,6 +14,7 @@ interface SDefaultURL = 'http://server.company.com/scripts/httpsrvr.dll'; type + {forward declarations} TBoldWebConnection = class; @@ -69,7 +72,7 @@ procedure TBoldWebConnection.Check(Error: Boolean); if Error and (ErrCode <> 0) then begin SetLength(S, 256); - FormatMessage(FORMAT_MESSAGE_FROM_HMODULE, Pointer(GetModuleHandle('wininet.dll')), // do not localize + FormatMessage(FORMAT_MESSAGE_FROM_HMODULE, Pointer(GetModuleHandle('wininet.dll')), ErrCode, 0, PChar(S), Length(S), nil); SetLength(S, StrLen(PChar(S))); while (Length(S) > 0) and (S[Length(S)] in [#10, #13]) do @@ -83,7 +86,7 @@ constructor TBoldWebConnection.Create(AOwner: TComponent); inherited Create(AOwner); FInetRoot := nil; FInetConnect := nil; - FAgent := 'Bold Application'; // do not localize + FAgent := 'Bold Application'; URL := SDefaultURL; end; @@ -107,7 +110,7 @@ function TBoldWebConnection.Receive(WaitForInput: Boolean; Context: Integer): TB if BoldHttpQueryInfo(Pointer(Context), BOLD_HTTP_QUERY_STATUS_TEXT, @S[1], Size, Index) then begin SetLength(S, Size); - raise Exception.CreateFmt('%s (%d)', [S, Status]); // do not localize + raise Exception.CreateFmt('%s (%d)', [S, Status]); end; end; Result := TBoldDataBlock.Create; @@ -121,10 +124,8 @@ function TBoldWebConnection.Receive(WaitForInput: Boolean; Context: Integer): TB end; until Size = 0; - // If we want to compare the size of the result with the expected size, we must call httpQueryInfo with the - // flag HTTP_QUERY_CONTENT_LENGTH -// if Assigned(Result) and (Len <> DWord(Result.Size)) then -// raise EBold.Create(SInvalidDataPacket); + + end; function TBoldWebConnection.Send(const Data: TBoldDataBlock): Integer; @@ -135,13 +136,13 @@ function TBoldWebConnection.Send(const Data: TBoldDataBlock): Integer; AcceptTypes: PChararr; begin SetLength(AcceptTypes, 2); - AcceptTypes[0] := PChar('application/octet-stream'); // do not localize + AcceptTypes[0] := PChar('application/octet-stream'); AcceptTypes[1] := nil; Flags := BOLD_INTERNET_FLAG_KEEP_CONNECTION or BOLD_INTERNET_FLAG_NO_CACHE_WRITE; if FURLScheme = BOLD_INTERNET_SCHEME_HTTPS then Flags := Flags or BOLD_INTERNET_FLAG_SECURE; SetConnected(True); - Request := BoldHttpOpenRequest(FInetConnect, 'POST', FURLSite, '', '', AcceptTypes, Flags, Integer(Self)); // do not localize + Request := BoldHttpOpenRequest(FInetConnect, 'POST', FURLSite, '', '', AcceptTypes, Flags, Integer(Self)); Check(not Assigned(Request)); while True do begin @@ -227,4 +228,6 @@ procedure TBoldWebConnection.SetURL(const Value: string); end; end; +initialization + end. diff --git a/Source/Common/Handles/BoldHandle.pas b/Source/Common/Handles/BoldHandle.pas index 5bea5d3..6554ccc 100644 --- a/Source/Common/Handles/BoldHandle.pas +++ b/Source/Common/Handles/BoldHandle.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldHandle; interface @@ -28,7 +31,8 @@ TBoldHandle = class(TBoldSubscribableComponent) implementation uses - SysUtils; + SysUtils, + BoldRev; { TBoldHandle } diff --git a/Source/Common/IDE/BoldAbout.dfm b/Source/Common/IDE/BoldAbout.dfm index 6e9bf1a..33ccef2 100644 --- a/Source/Common/IDE/BoldAbout.dfm +++ b/Source/Common/IDE/BoldAbout.dfm @@ -28,10 +28,6 @@ object frmAboutBold: TfrmAboutBold TabOrder = 0 object TabAbout: TTabSheet Caption = 'About' - ExplicitLeft = 0 - ExplicitTop = 0 - ExplicitWidth = 0 - ExplicitHeight = 0 object BtnUnlock: TSpeedButton Left = 4 Top = 4 @@ -837,10 +833,6 @@ object frmAboutBold: TfrmAboutBold end object tsTeam: TTabSheet Caption = 'Team' - ExplicitLeft = 0 - ExplicitTop = 0 - ExplicitWidth = 0 - ExplicitHeight = 0 object Label9: TLabel Left = 148 Top = 8 @@ -1157,7 +1149,7 @@ object frmAboutBold: TfrmAboutBold Left = 68 Top = 392 Bitmap = { - 494C010101000400080010001000FFFFFFFFFF10FFFFFFFFFFFFFFFF424D3600 + 494C010101000400040010001000FFFFFFFFFF10FFFFFFFFFFFFFFFF424D3600 0000000000003600000028000000400000001000000001002000000000000010 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 @@ -1300,7 +1292,7 @@ object frmAboutBold: TfrmAboutBold Left = 320 Top = 146 Bitmap = { - 494C010106000900080010001000FFFFFFFFFF10FFFFFFFFFFFFFFFF424D3600 + 494C010106000900040010001000FFFFFFFFFF10FFFFFFFFFFFFFFFF424D3600 0000000000003600000028000000400000002000000001002000000000000020 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 diff --git a/Source/Common/IDE/BoldAbout.pas b/Source/Common/IDE/BoldAbout.pas index df28d89..ed2bb7c 100644 --- a/Source/Common/IDE/BoldAbout.pas +++ b/Source/Common/IDE/BoldAbout.pas @@ -18,7 +18,7 @@ interface ExtCtrls, Menus, ImgList, - Graphics; + Graphics, System.ImageList; type TfrmAboutBold = class(TForm) diff --git a/Source/Common/IDE/BoldAbstractPropertyEditors.pas b/Source/Common/IDE/BoldAbstractPropertyEditors.pas index 7a0dfc0..0f988ec 100644 --- a/Source/Common/IDE/BoldAbstractPropertyEditors.pas +++ b/Source/Common/IDE/BoldAbstractPropertyEditors.pas @@ -1,12 +1,20 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldAbstractPropertyEditors; interface uses + {$IFDEF BOLD_CLX} + Types, + QGraphics, + {$ELSE} Windows, Graphics, - DesignEditors, - EditIntf; + {$ENDIF} + DesignEditors{, + EditIntf}; type { forward declarations } @@ -194,14 +202,15 @@ procedure TBoldOTAModifyingMethodProperty.InsertText(const s: string); EditPos: TOTAEditpos; CharPos: TOTACharpos; begin - if Supports(BorlandIDEServices, IOTAEditorServices, EditorServices) then + if (s <> '') and + Supports(BorlandIDEServices, IOTAEditorServices, EditorServices) then begin EditPos := EditorServices.TopBuffer.TopView.CursorPos; EditorServices.TopBuffer.TopView.ConvertPos(True, EditPos, CharPos); CurPos := EditorServices.TopBuffer.TopView.CharPosToPos(CharPos); Writer := EditorServices.TopBuffer.CreateUndoableWriter; Writer.CopyTo(CurPos); - Writer.Insert(PAnsiChar(s)); // marco to be fixed + Writer.Insert(PAnsiChar({$IFDEF BOLD_UNICODE}AnsiString{$ENDIF}(s))); end; end; diff --git a/Source/Common/IDE/BoldDefsDT.pas b/Source/Common/IDE/BoldDefsDT.pas index fb06760..66dc2b5 100644 --- a/Source/Common/IDE/BoldDefsDT.pas +++ b/Source/Common/IDE/BoldDefsDT.pas @@ -1,21 +1,28 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldDefsDT; interface - uses - BoldDefs; // BOLDCRLF for BCB + BoldDefs; const - HelpFile = 'bold90.hlp'; +{$IFDEF BOLD_DELPHI6} + HelpFile = 'boldd6.hlp'; +{$ENDIF} +{$IFDEF BOLD_DELPHI7} + HelpFile = 'boldd7.hlp'; +{$ENDIF} ATTRIBUTEWIZARDHELPFILE = 'boldattributewizard.hlp'; MODELEDITORHELPFILE = 'boldmodeleditor.hlp'; - URLBoldSoft = 'http://www.borland.com'; - URLBoldForDelphi = 'http://www.borland.com'; - URLSupport = 'http://www.borland.com'; + URLBoldSoft = 'http://www.boldsoft.com'; + URLBoldForDelphi = 'http://www.boldsoft.com'; + URLSupport = 'http://www.boldsoft.com'; - GETTINGSTARTEDPATH = '\doc\frames\'; //NOTE: Must end with backslash! + GETTINGSTARTEDPATH = '\doc\frames\'; GETTINGSTARTEDDOCNAME = 'getting_started_f.html'; regPath = 'Path'; @@ -56,4 +63,9 @@ interface implementation +uses + BoldRev; + +initialization + end. diff --git a/Source/Common/IDE/BoldExpert.pas b/Source/Common/IDE/BoldExpert.pas index b11bf6f..bb99d68 100644 --- a/Source/Common/IDE/BoldExpert.pas +++ b/Source/Common/IDE/BoldExpert.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldExpert; interface @@ -15,7 +18,7 @@ TBoldExpertClass = class of TBoldExpert; TBoldExpert = class(TInterfacedObject, IOTANotifier, IOTAWizard) public constructor Create; virtual; - procedure ExecuteEvent(Sender: TObject); //TNotifyEvent compatible. Calls Execute. + procedure ExecuteEvent(Sender: TObject); {IOTANotifier} procedure AfterSave; virtual; procedure BeforeSave; virtual; @@ -37,33 +40,31 @@ TBoldExpert = class(TInterfacedObject, IOTANotifier, IOTAWizard) implementation -{.$R *.res} +uses + BoldRev; + +{$R *.res} { TBoldExpert } procedure TBoldExpert.AfterSave; begin - // Required for interface end; procedure TBoldExpert.BeforeSave; begin - // Required for interface end; constructor TBoldExpert.Create; begin - // To avoid abstract constructor. end; procedure TBoldExpert.Destroyed; begin - // Required for interface end; procedure TBoldExpert.Execute; begin - // Required for interface end; procedure TBoldExpert.ExecuteEvent(Sender: TObject); @@ -73,7 +74,7 @@ procedure TBoldExpert.ExecuteEvent(Sender: TObject); function TBoldExpert.GetAuthor: string; begin - Result := 'BoldSoft'; // do not localize + Result := 'BoldSoft'; end; function TBoldExpert.GetComment: string; @@ -83,12 +84,12 @@ function TBoldExpert.GetComment: string; function TBoldExpert.GetGlyph: HICON; begin - Result := LoadIcon(FindClassHInstance(ClassType), 'BOLDEXPERT'); // do not localize + Result := LoadIcon(FindClassHInstance(ClassType), 'BOLDEXPERT'); end; function TBoldExpert.GetIDString: string; begin - Result := 'BoldSoft.' + GetName; // do not localize + Result := 'BoldSoft.' + GetName; end; function TBoldExpert.GetMenuText: string; @@ -103,7 +104,7 @@ function TBoldExpert.GetName: string; function TBoldExpert.GetPage: string; begin - Result := 'Bold'; // do not localize + Result := 'Bold'; end; function TBoldExpert.GetState: TWizardState; @@ -113,7 +114,8 @@ function TBoldExpert.GetState: TWizardState; procedure TBoldExpert.Modified; begin - // Required for interface end; +initialization + end. diff --git a/Source/Common/IDE/BoldExpertMenus.pas b/Source/Common/IDE/BoldExpertMenus.pas index 96c8e4c..797f4a6 100644 --- a/Source/Common/IDE/BoldExpertMenus.pas +++ b/Source/Common/IDE/BoldExpertMenus.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldExpertMenus; interface @@ -18,6 +21,11 @@ TdmExpertMenus = class(TDataModule) implementation +uses + BoldRev; + {$R *.DFM} +initialization + end. diff --git a/Source/Common/IDE/BoldGettingStartedExpert.pas b/Source/Common/IDE/BoldGettingStartedExpert.pas index b890260..fedfb6d 100644 --- a/Source/Common/IDE/BoldGettingStartedExpert.pas +++ b/Source/Common/IDE/BoldGettingStartedExpert.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldGettingStartedExpert; interface @@ -24,7 +27,7 @@ TBoldGettingStartedExpert = class(TSimpleMenuWizard) function getURLGettingStarted: string; function DoShowGettingStarted: Boolean; procedure OnTimer(Sender: TObject); - property URLGettingStarted: string read getURLGettingStarted; + property URLGettingStarted: string read getURLGettingStarted; protected procedure Initialize; override; public @@ -54,26 +57,22 @@ implementation Toolsapi, ShellAPI, windows, - dialogs, - BoldCommonConst; + dialogs; procedure Register; begin -{$MESSAGE HINT 'Wizard turned off'} -(* RegisterPackageWizard(GettingStartedExpert); -*) end; procedure InitExpert; begin try dmMenus := TDMExpertMenus.Create(nil); - BoldMenuExpert; //ensure "Bold" menu has been created - GettingStartedExpert := TBoldGettingStartedExpert.Create('BoldGettingStartedExpert', sGettingStarted, [], 5, 'Bold'); // do not localize + BoldMenuExpert; + GettingStartedExpert := TBoldGettingStartedExpert.Create('BoldGettingStartedExpert', 'Getting Started', [], 5, 'Bold'); GettingStartedExpert.AddMenuItem(dmMenus.GettingStartedMenu); except on E: Exception do - showmessage(Format('InitExpert: ', [E.Message])); // do not localize + showmessage(Format('InitExpert: ', [E.Message])); end; end; @@ -116,7 +115,7 @@ procedure TBoldGettingStartedExpert.SetRegistryValue(const Show: Boolean); try BoldRegistry.RegistryMode := rmDesignTime; BoldRegistry.OpenKey(BoldGettingStartedRegKey); - BoldRegistry.WriteBool('Show', Show); // do not localize + BoldRegistry.WriteBool('Show', Show); BoldRegistry.CloseKey; finally FreeAndNil(BoldRegistry); @@ -131,7 +130,7 @@ function TBoldGettingStartedExpert.DoShowGettingStarted: Boolean; try BoldRegistry.RegistryMode := rmDesigntime; BoldRegistry.OpenKey(BoldGettingStartedRegKey); - Result := BoldRegistry.ReadBool('Show', True); // do not localize + Result := BoldRegistry.ReadBool('Show', True); BoldRegistry.CloseKey; finally FreeAndNil(BoldRegistry); @@ -142,10 +141,10 @@ procedure TBoldGettingStartedExpert.DisplayGettingStarted(Sender: TObject); begin if not FileExists(UrlGettingStarted) then begin - showmessage(Format(sCouldNotFindGettingStarted, [UrlGettingStarted])); + showmessage(Format('Could not find Bold for Delphi''s GettingStarted document: %s', [UrlGettingStarted])); end else - ShellExecute(0, 'open', PChar(URLGettingStarted), '', '', SW_SHOWNORMAL); // do not localize + ShellExecute(0, 'open', PChar(URLGettingStarted), '', '', SW_SHOWNORMAL); end; procedure TBoldGettingStartedExpert.OnTimer(Sender: TObject); @@ -174,14 +173,9 @@ destructor TBoldGettingStartedExpert.Destroy; inherited; end; -{$MESSAGE HINT 'Getting started expert disabled'} -(***** -// Skip the getting started expert initialization InitExpert; finalization DoneExpert; -***) - end. diff --git a/Source/Common/IDE/BoldGettingStartedForm.pas b/Source/Common/IDE/BoldGettingStartedForm.pas index 8ef665c..781c975 100644 --- a/Source/Common/IDE/BoldGettingStartedForm.pas +++ b/Source/Common/IDE/BoldGettingStartedForm.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldGettingStartedForm; interface @@ -36,6 +39,9 @@ TFGettingStarted = class(TForm) implementation +uses + BoldRev; + {$R *.DFM} procedure TFGettingStarted.btnShowClick(Sender: TObject); @@ -57,4 +63,6 @@ procedure TFGettingStarted.btnCloseClick(Sender: TObject); Close; end; +initialization + end. diff --git a/Source/Common/IDE/BoldIDEConsts.pas b/Source/Common/IDE/BoldIDEConsts.pas index e62f60e..873967f 100644 --- a/Source/Common/IDE/BoldIDEConsts.pas +++ b/Source/Common/IDE/BoldIDEConsts.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldIDEConsts; interface @@ -10,12 +13,14 @@ interface BOLDPAGENAME_CONTROLS = 'Bold Controls'; BOLDPAGENAME_OLLE = 'Bold OLLE'; BOLDPAGENAME_COM = 'Bold COM'; - BOLDPAGENAME_COMHANDLES = 'Bold COM Handles'; - BOLDPAGENAME_COMCONTROLS = 'Bold COM Controls'; BOLDPAGENAME_OSS_CMS = 'Bold OSS/CMS'; BOLDACTIONGROUPNAME = 'Bold Actions'; - LIBSUFFIX = '90'; implementation +uses + BoldRev; + +initialization + end. diff --git a/Source/Common/IDE/BoldIDEMenus.pas b/Source/Common/IDE/BoldIDEMenus.pas index 4130c92..6106bbf 100644 --- a/Source/Common/IDE/BoldIDEMenus.pas +++ b/Source/Common/IDE/BoldIDEMenus.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldIDEMenus; interface @@ -41,9 +44,7 @@ implementation uses SysUtils, Forms, - BoldDefsDT, - BoldAbout, - BoldCommonConst; + BoldDefsDT; var G_BoldMenuExpert: TBoldMenuExpert = nil; @@ -67,12 +68,6 @@ function BoldMenuExpertAssigned: boolean; procedure TBoldMenuExpert.ActionAbout(Sender: TObject); begin - with BoldAbout.TfrmAboutBold.Create(nil) do - try - ShowModal; - finally - Free; - end; end; procedure TBoldMenuExpert.ActionHelp(Sender: TObject); @@ -80,22 +75,22 @@ procedure TBoldMenuExpert.ActionHelp(Sender: TObject); HelpHandle: HWND; begin //FIXME PORT ###What happened to the helpfile property? -//{ -- temproary removed during porting +{ -- temproary removed during porting HelpHandle := Application.Handle; if Application.MainForm <> nil then HelpHandle := Application.MainForm.Handle; WinHelp(HelpHandle, HelpFile, HELP_FINDER, 0); -//} +} end; procedure TBoldMenuExpert.ActionURLBfD(Sender: TObject); begin - ShellExecute(0, 'open', URLBoldForDelphi, '', '', SW_SHOWMAXIMIZED); // do not localize + ShellExecute(0, 'open', URLBoldForDelphi, '', '', SW_SHOWMAXIMIZED); end; procedure TBoldMenuExpert.ActionURLHome(Sender: TObject); begin - ShellExecute(0, 'open', URLBoldSoft, '', '', SW_SHOWMAXIMIZED); // do not localize + ShellExecute(0, 'open', URLBoldSoft, '', '', SW_SHOWMAXIMIZED); end; function TBoldMenuExpert.AddMenuItem(aName, aCaption: string; aClickEvent: TNotifyEvent; first: Boolean = false): TMenuItem; @@ -131,20 +126,19 @@ procedure TBoldMenuExpert.CreateBaseMenuItems; {Main Bold Menu} fBoldMenu := TMenuItem.Create(fOwner); fBoldMenu.Enabled := true; - fBoldMenu.Caption := '&Bold'; // do not localize - fBoldMenu.Name := 'BoldMenu'; // do not localize + fBoldMenu.Caption := '&Bold'; + fBoldMenu.Name := 'BoldMenu'; I := 0; - while (I'ToolsMenu') do // do not localize + while (I'ToolsMenu') do Inc(I); - AddMenuItem('BoldURLDelimiterMenu', '-', nil); // do not localize - AddMenuItem('BoldHomePageMenu', sCompanyHomePage, ActionURLHome); // do not localize - AddMenuItem('BoldBfDHomePageMenu', sProductHomePage, ActionURLBfD); // do not localize - AddMenuItem('BoldHelpDelimiterMenu', '-', nil); // do not localize - AddMenuItem('BoldHelpMenu', sHelp, ActionHelp); // do not localize - AddMenuItem('BoldAboutDelimiterMenu', '-', nil); // do not localize - AddMenuItem('BoldAboutMenu', sAbout, ActionAbout); // do not localize - // in D7, the menu must have items before it is added to the main menu + AddMenuItem('BoldURLDelimiterMenu', '-', nil); + AddMenuItem('BoldHomePageMenu', '&BoldSoft Home Page', ActionURLHome); + AddMenuItem('BoldBfDHomePageMenu', 'Bold for &Delphi Home Page', ActionURLBfD); + AddMenuItem('BoldHelpDelimiterMenu', '-', nil); + AddMenuItem('BoldHelpMenu', '&Help', ActionHelp); + AddMenuItem('BoldAboutDelimiterMenu', '-', nil); + AddMenuItem('BoldAboutMenu', '&About', ActionAbout); MainMenu.Items.Insert(I, fBoldMenu); end; @@ -173,7 +167,7 @@ procedure TBoldMenuExpert.RegisterBoldExpert(aBoldExpertClass: TBoldExpertClass) MenuItem := TMenuItem.Create(fOwner); with MenuItem do begin - Name := Expert.ClassName + 'Menu'; // do not localize + Name := Expert.ClassName + 'Menu'; Caption := Expert.GetMenuText; OnClick := Expert.ExecuteEvent; end; @@ -187,4 +181,6 @@ procedure TBoldMenuExpert.RemoveAndDestroyMenuItem(var anItem: TMenuItem); anItem := nil; end; +initialization + end. diff --git a/Source/Common/IDE/BoldIDESupport.pas b/Source/Common/IDE/BoldIDESupport.pas index 043a2e0..14ba2b6 100644 --- a/Source/Common/IDE/BoldIDESupport.pas +++ b/Source/Common/IDE/BoldIDESupport.pas @@ -1,25 +1,18 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldIDESupport; interface procedure RemovePackageFromDisabledPackagesRegistry(PackageName: String); -function IDEBaseRegistryKey: string; implementation uses + BoldDefs, Classes, - Registry, - ToolsAPI; - -function IDEBaseRegistryKey: string; -var - Service: IOTAServices; -begin - service := (BorlandIDEServices as IOTAServices); - Assert(Assigned(Service), 'Service not assigned'); - Result := Service.GetBaseRegistryKey + '\'; -end; + Registry; procedure RemovePackageFromDisabledPackagesRegistry(PackageName: String); var @@ -28,23 +21,18 @@ procedure RemovePackageFromDisabledPackagesRegistry(PackageName: String); Values: TStringList; begin RegKey := TRegistry.Create; - try - if Regkey.OpenKey(IDEBaseRegistryKey + 'Disabled Packages', false) then // do not localize - begin - Values := TStringList.Create; - try - RegKey.GetValueNames(Values); - - for i := 0 to Values.Count - 1 do - if pos(PackageName, Values[i]) <> 0 then - RegKey.DeleteValue(Values[i]); - finally - Values.Free; - end; - end; - finally - RegKey.Free; - end; + if Regkey.OpenKey(BOLD_HOST_IDE_REGISTRYPATH + 'Disabled Packages', false) then + begin + Values := TStringList.Create; + RegKey.GetValueNames(Values); + + for i := 0 to Values.Count - 1 do + if pos(PackageName, Values[i]) <> 0 then + RegKey.DeleteValue(Values[i]); + Values.Free; + end; end; +initialization + end. diff --git a/Source/Common/IDE/BoldLicenseTextForm.pas b/Source/Common/IDE/BoldLicenseTextForm.pas index b1c1f95..e746fa5 100644 --- a/Source/Common/IDE/BoldLicenseTextForm.pas +++ b/Source/Common/IDE/BoldLicenseTextForm.pas @@ -1,9 +1,12 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldLicenseTextForm; interface uses - Windows, Classes, Controls, Forms, + Windows, Classes, Controls, Forms, BoldRegistry, Dialogs, StdCtrls, ExtCtrls; @@ -34,7 +37,9 @@ implementation uses SysUtils, - BoldUtils; + BoldUtils, + BoldRev; + procedure TfrmLicenseText.FormCloseQuery(Sender: TObject; var CanClose: Boolean); var diff --git a/Source/Common/IDE/BoldModelAwareComponentEditor.pas b/Source/Common/IDE/BoldModelAwareComponentEditor.pas index fecf2a0..02dc19e 100644 --- a/Source/Common/IDE/BoldModelAwareComponentEditor.pas +++ b/Source/Common/IDE/BoldModelAwareComponentEditor.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldModelAwareComponentEditor; interface @@ -29,8 +32,7 @@ implementation SysUtils, TypInfo, BoldDefs, - BoldDefsDT, - BoldCommonConst; + BoldDefsDT; const PropNames: array[0..5] of string = @@ -47,11 +49,10 @@ procedure TBoldModelAwareComponentEditor.EditModel; begin Model := FollowUplinkToModel(Component); if Assigned(Model) then - // create and show the model editor GetComponentEditor(Model, Designer).Edit else - raise EBold.CreateFmt(sNoModel, [Component.Name]); -end; + raise EBold.CreateFmt('%s does not seem to be connected to a model', [Component.Name]); +end; function TBoldModelAwareComponentEditor.GetEditModelMenuCaption: string; begin @@ -108,4 +109,6 @@ function TBoldModelAwareComponentEditor.FollowUplinkToModel( Result := nil; end; +initialization + end. diff --git a/Source/Common/IDE/BoldOTAFileHandler.pas b/Source/Common/IDE/BoldOTAFileHandler.pas index 5b2d359..8e2ce20 100644 --- a/Source/Common/IDE/BoldOTAFileHandler.pas +++ b/Source/Common/IDE/BoldOTAFileHandler.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldOTAFileHandler; interface @@ -35,7 +38,6 @@ TBoldOTAFileHandler = class(TBoldFileHandler) function GetOTAEditWriter: IOTAEditWriter; function GetOTAModule: IOTAModule; function GetOTASourceEditor: IOTASourceEditor; - procedure SetEditorLine(Line: Integer); protected procedure LoadStringList; override; procedure DoFlushFile; override; @@ -46,6 +48,7 @@ TBoldOTAFileHandler = class(TBoldFileHandler) function FileInProject(const name: string): Boolean; function FilePathInProject(const name: string): string; function PositionToTextInEditor(const S: string): Boolean; + procedure SetEditorLine(Line: Integer); property ModuleCreator: TBoldModuleCreator read GetModuleCreator; property OTAEditReader: IOTAEditReader read GetOTAEditReader; property OTAEditWriter: IOTAEditWriter read GetOTAEditWriter; @@ -79,12 +82,12 @@ implementation SysUtils, BoldUtils, BoldLogHandler, - BoldCommonConst; + BoldRev; constructor TBoldOTAFileHandler.create(const FileName: string; ModuleType: TBoldModuleType; ShowFileInGuiIfPossible: Boolean; OnInitializeFileContents: TBoldInitializeFileContents); begin - // in OTA, strip away the path... we will find a new one later. - OTADEBUGLogFmt(sLogCreatingOTAFileHandler, [FileName]); + if OTADEBUG then + BoldLog.LogFmt('Creating an OTA filehandler for file: %s', [FileName]); inherited Create(ExtractFileName(FileName), ModuleType, ShowFileInGuiIfPossible, OnInitializeFileContents); fModuleCreator := nil; end; @@ -112,15 +115,17 @@ function TBoldOTAFileHandler.GetOTAModule: IOTAModule; result := nil; if not assigned(fOTAModule) then begin + if OTADEBUG then + BoldLog.LogFmt('Getting a module for %s', [FileName]); + fOtaModule := EnsuredModule(FileName, ModuleCreator, ModuleType = mttext, fWasOpen); if OTADEBUG then begin if fWasOpen then - BoldLog.LogFmt(sLogModuleWasOpen, [FileName]) + BoldLog.Log(FileName + ' was already open') else - BoldLog.LogFmt(sLogHadToOpenModule, [FileName]); + BoldLog.Log('had to open ' + FileName ); end; -// OTADEBUGLogFmt('Done Creating OTAModule'); end; result := fOTAModule; @@ -142,7 +147,7 @@ function TBoldOTAFileHandler.GetOTASourceEditor: IOTASourceEditor; end; if not Assigned(fOTASourceEditor) then - raise EBoldDesignTime.CreateFmt(sUnableToOpenSourceEditor, [filename]); + raise EBoldDesignTime.CreateFmt('Unable to open Source Editor for %s', [filename]); end; Result := fOTASourceEditor; @@ -157,13 +162,13 @@ procedure TBoldOTAFileHandler.SetEditorLine(Line: Integer); begin EditPos.Col := 0; EditPos.Line := Line; - SetCursorPos(EditPos); // set cursorpos + SetCursorPos(EditPos); EditPos.Col := 1; - SetTopPos(EditPos); // set viewpos + SetTopPos(EditPos); end; except on E: Exception do - Raise EBoldDesignTime.CreateFmt(sUnableToPositionCursor, [FileName, Line]); + Raise EBoldDesignTime.CreateFmt('Unable to position cursor in %s (line %d)', [FileName, Line]); end; end; @@ -171,7 +176,7 @@ procedure TBoldOTAFileHandler.LoadStringList; const ChunkSize = 30000; var - Buf: PChar; + Buf: PAnsiChar; position: integer; s: String; Size, @@ -185,7 +190,7 @@ procedure TBoldOTAFileHandler.LoadStringList; position := 0; while position < Size do begin - //marco ReadChars := OTAEditReader.GetText(position, buf + position, ChunkSize); // bug, must be less that 2**31-1 + ReadChars := OTAEditReader.GetText(position, buf + position, ChunkSize); position := position + ReadChars; end; Buf[Size] := BoldNULL; @@ -196,14 +201,8 @@ procedure TBoldOTAFileHandler.LoadStringList; finally FreeMem(Buf, Size + 1); end; - end - else - begin + end else Stringlist.Clear; - end; -// OTADEBUGLogFmt('Adding to project'); -// Doesn't work well! (BorlandIDEServices as IOTAModuleServices).GetActiveProject.AddFile(FileName, true); -// OTADEBUGLogFmt('DONE - Adding to project'); end; function TBoldOTAFileHandler.PositionToTextInEditor(const S: string): Boolean; @@ -224,13 +223,13 @@ procedure TBoldOTAFileHandler.DoFlushFile; if CheckWriteable(OTAModule.FileName) then begin OTAEditWriter.DeleteTo(GetEditorSize - 2); -//marco OTAEditWriter.Insert(PChar(StringList.Text)); + OTAEditWriter.Insert(PAnsiChar({$IFDEF BOLD_UNICODE}AnsiString{$ENDIF}(StringList.Text))); OTAModule.Save(False, True); end else begin - BoldLog.LogFmt(sModuleReadOnly, [OTAModule.FileName], ltError); - ShowMessage(SysUtils.Format(sModuleReadOnly, [OTAModule.FileName])); + BoldLog.LogFmt('%s is readonly!', [OTAModule.FileName], ltError); + ShowMessage(OTAModule.FileName + ' is readonly!'); end; end; @@ -239,23 +238,24 @@ function TBoldOTAFileHandler.GetModuleCreator: TBoldModuleCreator; if not assigned(fModuleCreator) then begin fModuleCreator := TBoldModuleCreator.Create(FileName, ModuleType, fShowInEditor); - if not FileInProject(Filename) then - OTADEBUGLogFmt('File %s not in Project... ', [Filename]); +{ if not FileInProject(Filename) then + ShowMessage('File not in Project... ' + Filename);} end; result := fModuleCreator; end; + function TBoldOTAFileHandler.GetEditorSize: Integer; const ChunkSize = 30000; var - buf: array[0..ChunkSize] of Char; + buf: array[0..ChunkSize] of AnsiChar; ReadChars: integer; begin result := 0; repeat -//marco ReadChars := OTAEditReader.GetText(Result, buf, ChunkSize); + ReadChars := OTAEditReader.GetText(Result, buf, ChunkSize); Result := Result + ReadChars; until ReadChars < ChunkSize; end; @@ -271,7 +271,7 @@ function TBoldOTAFileHandler.GetOTAEditReader: IOTAEditReader; except on e: exception do begin - BoldLog.LogFmt(sUnableToCreateReader, [e.message], ltError); + BoldLog.LogFmt('Unable to create reader: %s', [e.message], ltError); raise end; end; @@ -289,9 +289,9 @@ function TBoldOTAFileHandler.GetOTAEditWriter: IOTAEditWriter; result := fOTAEditWriter; end; -destructor TBoldOTAFileHandler.Destroy; +destructor TBoldOTAFileHandler.destroy; begin - inherited; // Need to call inherited before freeing interfaces + inherited; fOTAEditReader := nil; fOTAEditWriter := nil; fModuleCreator := nil; @@ -301,12 +301,10 @@ destructor TBoldOTAFileHandler.Destroy; procedure TBoldIOTANotifier.AfterSave; begin - // Nothing implemented here end; procedure TBoldIOTANotifier.BeforeSave; begin - // Nothing implemented here end; constructor TBoldIOTANotifier.create(fileHandler: TBoldOTAFileHandler); @@ -317,7 +315,6 @@ constructor TBoldIOTANotifier.create(fileHandler: TBoldOTAFileHandler); procedure TBoldIOTANotifier.Destroyed; begin - // Nothing implemented here end; procedure TBoldIOTANotifier.Modified; @@ -334,13 +331,11 @@ procedure TBoldIOTANotifier.Modified; procedure TBoldIOTAEditorNotifier.ViewActivated(const View: IOTAEditView); begin - // Nothing implemented here end; procedure TBoldIOTAEditorNotifier.ViewNotification( const View: IOTAEditView; Operation: TOperation); begin - // Nothing implemented here end; procedure TBoldOTAFileHandler.CloseFile; @@ -351,18 +346,21 @@ procedure TBoldOTAFileHandler.CloseFile; fOTAEditWriter := nil; fModuleCreator := nil; - OTADEBUGLogFmt('%s has %d editors', [FileNAme, FOTASourceEditor.GetEditViewCount]); // do not localize + if OTADEBUG then + BoldLog.Log(SysUtils.format('%s has %d editors', [FileNAme, FOTASourceEditor.GetEditViewCount])); fOTASourceEditor := nil; - OTADEBUGLogFmt('Closing %s', [FileName]); // do not localize + if OTADEBUG then + BoldLog.Log('Closing '+FileName); try if OTAModule.Close and OTADEBUG then - BoldLog.Log('Closed '+FileName); // do not localize + BoldLog.Log('Closed '+FileName); except on e: exception do - BoldLog.LogFmt(sFailedToCloseModule, [FileName, e.Message]); // do not localize + BoldLog.Log('Failed to Close '+FileName+': '+e.message); end; - OTADEBUGLogFmt('Done Closing %s', [FileName]); // do not localize + if OTADEBUG then + BoldLog.Log('Done Closing '+FileName); fOTAModule := nil; end; end; @@ -371,3 +369,4 @@ initialization BoldPrefferedFileHandlerClass := TBoldOTAFileHandler; end. + diff --git a/Source/Common/IDE/BoldOTASupport.pas b/Source/Common/IDE/BoldOTASupport.pas index be11226..ff94265 100644 --- a/Source/Common/IDE/BoldOTASupport.pas +++ b/Source/Common/IDE/BoldOTASupport.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldOTASupport; interface @@ -57,54 +60,36 @@ function FindFileModuleInProject(const fileName: String; Project: IOTAProject): function GetProjectPath(Project: IOTAProject): String; function GetProjectOtherPaths(Project: IOTAProject): string; function EnsuredModule(FileName: string; ModuleCreator: TBoldModuleCreator; AllowLoadFromDisk: Boolean; var WasOpen: Boolean): IOTAModule; -procedure OTADEBUGLogFmt(const s: string; args: array of const); var OTAModuleServices: IOTAModuleServices; OTAActionServices: IOTAActionServices; - {$IFDEF DEBUG} - OTADEBUG: boolean = True; - {$ELSE} OTADEBUG: boolean = False; - {$ENDIF} implementation uses - {$IFDEF DEBUG} - Dialogs, - {$ENDIF} SysUtils, IniFiles, Registry, BoldLogHandler, BoldUtils, - BoldCommonConst, - BoldIDESupport; - -procedure OTADEBUGLogFmt(const s: string; args: array of const); -begin - if OTADEBUG then - BoldLog.LogFmt(s, Args); - {$IFDEF DEBUG} - ShowMessage(Format(s, Args)); - {$ENDIF} -end; + BoldRev; function GetProjectSearchPath(Project: IOTAProject): String; var DofFileName: string; begin result := ''; - if assigned(Project) then + if assigned(project) then begin Result := ExtractFilepath(Project.FileName) + ';'; - DofFileName := ChangeFileExt(Project.FileName, '.DOF'); // do not localize + DofFileName := ChangeFileExt(project.FileName, '.DOF'); with TINIFile.Create(DofFileName) do try - Result := Result + ReadString('DIRECTORIES', 'SearchPath', ''); // do not localize + Result := Result + ReadString('DIRECTORIES', 'SearchPath', ''); finally free; end; @@ -117,8 +102,8 @@ function GetDelphiSearchPath: String; with TRegistry.Create do begin try - if OpenKey(IDEBaseRegistryKey + 'Library', False) then // do not localize - Result := ReadString('Search Path'); // do not localize + if OpenKey(BOLD_HOST_IDE_REGISTRYPATH + 'Library', False) then + Result := ReadString('Search Path'); CloseKey; finally Free; @@ -145,7 +130,8 @@ function OpenExistingFileInDelphi(FileName: String; SearchPath: String): IOTAMod begin result := nil; Ensuretrailing(SearchPath, ';'); - OTADEBUGLogFmt('Looking with searchpath: %s', [SearchPath]); // do not localize + if OTADEBUG then + BoldLog.LogFmt('Looking with searchpath: %s', [SearchPath]); while SearchPath <> '' do begin @@ -159,7 +145,8 @@ function OpenExistingFileInDelphi(FileName: String; SearchPath: String): IOTAMod result := FindDelphiModuleForFile(FileName); if assigned(result) then begin - OTADEBUGLogFmt('Loaded and Opened the file %s', [path + filename]); // do not localize + if OTADEBUG then + BoldLog.LogFmt('Loaded and Opened the file %s', [path + filename]); exit; end; end; @@ -171,29 +158,32 @@ function EnsuredModule(FileName: string; ModuleCreator: TBoldModuleCreator; Allo Project: IOTAProject; begin result := nil; - - OTADEBUGLogFmt('Looking in ModuleServices for %s', [FileName]); // do not localize + if OTADEBUG then + BoldLog.LogFmt('Looking in ModuleServices for %s', [FileName]); result := FindDelphiModuleForFile(FileName); WasOpen := assigned(Result); - + if not Assigned(Result) then begin Project := GetOTAProject; if assigned(Project) then begin - OTADEBUGLogFmt('Looking in Project for %s', [FileName]); // do not localize + if OTADEBUG then + BoldLog.LogFmt('Looking in Project for %s', [FileName]); result := FindFileModuleInProject(FileName, Project); if not assigned(result) then begin - OTADEBUGLogFmt('Looking in Project SearchPath for %s', [FileName]); // do not localize + if OTADEBUG then + BoldLog.LogFmt('Looking in Project SearchPath for %s', [FileName]); result := OpenExistingFileInDelphi(FileName, GetProjectSearchPath(Project)); end; if not Assigned(Result) then begin - OTADEBUGLogFmt('Looking in folders of other files in project for %s', [FileName]); // do not localize + if OTADEBUG then + BoldLog.LogFmt('Looking in folders of other files in project for %s', [FileName]); result := OpenExistingFileInDelphi(FileName, GetProjectOtherPaths(Project)); end; end; @@ -201,19 +191,20 @@ function EnsuredModule(FileName: string; ModuleCreator: TBoldModuleCreator; Allo if not assigned(result) then begin - OTADEBUGLogFmt('Looking in Delphi SearchPath for %s', [FileName]); // do not localize + if OTADEBUG then + BoldLog.LogFmt('Looking in Delphi SearchPath for %s', [FileName]); result := OpenExistingFileInDelphi(FileName, GetDelphiSearchPath); end; if not assigned(result) then begin - OTADEBUGLogFmt('Creating New module for %s', [FileName]); // do not localize + if OTADEBUG then + BoldLog.LogFmt('Creating New module for %s', [FileName]); result := OTAModuleServices.CreateModule(ModuleCreator); end; - OTADEBUGLogFmt('New module created: %s', [FileName]); // do not localize if not assigned(result) then - raise EBoldDesignTime.CreateFmt(sUnableToGetModule, [filename]); + raise EBoldDesignTime.CreateFmt('Unable to get module for %s', [filename]); end; function BoldFilePathForComponent(component: TComponent): string; @@ -241,12 +232,10 @@ function BoldFilePathForComponent(component: TComponent): string; begin RootComponent := FormEditor.GetRootComponent; - // if there is a component on the form with the same name - // as the one we are looking for, and the form has the same - // name as the owner of our component + if assigned(FormEditor.FindComponent(Component.Name)) and - RootComponent.GetPropValueByName('Name', RootName) and // do not localize + RootComponent.GetPropValueByName('Name', RootName) and (RootName = Owner.Name) then begin Result := IncludeTrailingPathDelimiter(Trim(ExtractFilePath(Module.FileName))); @@ -262,18 +251,17 @@ function BoldFilePathForComponent(component: TComponent): string; function GetOTAProject: IOTAProject; var i: integer; + CurrentModule: IOTAModule; begin - Result := OTAModuleServices.GetActiveProject; - if not Assigned(Result) then - begin - // find the first project available - for i := 0 to OTAModuleServices.ModuleCount - 1 do - if OTAModuleServices.Modules[i].QueryInterface(IOTAProject, result) = S_OK then - if uppercase(ExtractFileExt(result.GetFileName)) = '.DPR' then // do not localize - exit; - result := nil; - end; -end; + result := (BorlandIDEServices as IOTAModuleServices).GetActiveProject; + if OTADEBUG then + begin + if Assigned(result) then + BoldLog.LogFmt('CurrentModule:', [result.FileName]) + else + BoldLog.Log('CurrentModule not found'); + end; + end; function FindFileModuleInProject(const fileName: String; Project: IOTAProject): IOTAModule; var @@ -282,15 +270,13 @@ function FindFileModuleInProject(const fileName: String; Project: IOTAProject): result := nil; if assigned(Project) then for i := 0 to Project.GetModuleCount - 1 do - begin - OTADEBUGLogFmt('FindFileModuleInProject: %s - %s', [ExtractFileName(Project.GetModule(i).GetFileName), ExtractFileName(FileName)]); if SameFileName(ExtractFileName(Project.GetModule(i).GetFileName), ExtractFileName(FileName)) then begin - OTADEBUGLogFmt('Opening existing file from project: %s', [Project.GetModule(i).FileName]); // do not localize + if OTADEBUG then + BoldLog.Log('Opening existing file from project: '+ Project.GetModule(i).FileName); Result := Project.GetModule(i).OpenModule; Exit; end; - end; end; function GetProjectPath(Project: IOTAProject): String; @@ -328,7 +314,6 @@ function TBoldModuleCreator.GetCreatorType: string; else result := ''; end; - result := ''; end; function TBoldModuleCreator.GetExisting: Boolean; @@ -337,8 +322,8 @@ function TBoldModuleCreator.GetExisting: Boolean; if FileExists(fFilename) then result := true; - if not result then - OTADEBUGLogFmt('TBoldModuleCreator.GetExisting: %s does not exist', [fFileName]); // do not localize + if not result and OTADEBUG then + BoldLog.LogFmt('%s does not exist', [fFileName]); end; function TBoldModuleCreator.GetFileSystem: string; @@ -347,14 +332,18 @@ function TBoldModuleCreator.GetFileSystem: string; end; function TBoldModuleCreator.GetOwner: IOTAModule; +var + Module: IOTAModule; begin - Result := nil; - Exit; case fModuleType of - // IncFiles and units should be owned by the project is possible mtIncFile, - mtUnit: Result := (BorlandIDEServices as IOTAModuleServices).GetActiveProject; - // Other files will not get added to a project (IDL files) + mtUnit: begin + Module := (BorlandIDEServices as IOTAModuleServices).CurrentModule; + if Assigned(Module) and (Module.OwnerCount > 0) then + Result := Module.Owners[0] + else + Result := nil; + end; mtText: result := nil; end; end; @@ -416,7 +405,7 @@ function TBoldModuleCreator.NewIntfSource(const ModuleIdent, FormIdent, Ancestor procedure TBoldModuleCreator.FormCreated(const FormEditor: IOTAFormEditor); begin -end; +end; constructor TBoldUnitFile.Create(const UnitIdent: string); begin @@ -436,7 +425,7 @@ function TBoldUnitFile.GetAge: TDateTime; initialization OTAModuleServices := BorlandIDEServices as IOTAModuleServices; OTAActionServices := BorlandIDEServices as IOTAActionServices; - if assigned(BorlandIDEServices) then + if assigned(OTAModuleServices) and Assigned(OTAActionServices) then BoldRunningAsDesignTimePackage := true; end. diff --git a/Source/Common/IDE/BoldPropertyEditors.pas b/Source/Common/IDE/BoldPropertyEditors.pas index 23f9484..479252d 100644 --- a/Source/Common/IDE/BoldPropertyEditors.pas +++ b/Source/Common/IDE/BoldPropertyEditors.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldPropertyEditors; interface @@ -181,6 +184,8 @@ implementation Controls, Dialogs, BoldHandles, + BoldIndex, + BoldIndexableList, BoldMetaElementList, BoldDefs, BoldDefsDT, diff --git a/Source/Common/IDE/BoldReg.pas b/Source/Common/IDE/BoldReg.pas index 064895f..6f9b35e 100644 --- a/Source/Common/IDE/BoldReg.pas +++ b/Source/Common/IDE/BoldReg.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldReg; interface @@ -22,3 +25,4 @@ procedure Register; end; end. + diff --git a/Source/Common/IDE/BoldTextStream.pas b/Source/Common/IDE/BoldTextStream.pas index 0fcbf05..522f972 100644 --- a/Source/Common/IDE/BoldTextStream.pas +++ b/Source/Common/IDE/BoldTextStream.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldTextStream; interface @@ -16,7 +19,6 @@ interface { forward declarations } TBoldTextStream = class; TITextStream = class; - // For backward comaptibility TTextStream = TBoldTextStream; { TBoldTextStream } @@ -85,14 +87,14 @@ procedure TBoldTextStream.AddString(const s: string); procedure TBoldTextStream.StartBlock; begin - Writeln('begin'); // do not localize + Writeln('begin'); Indent; end; procedure TBoldTextStream.EndBlock(const AddNewLine: boolean); begin Dedent; - Writeln('end;'); // do not localize + Writeln('end;'); if AddNewLine then NewLine; end; @@ -171,4 +173,6 @@ procedure TBoldTextStream.Clear; Size := 0; end; +initialization + end. diff --git a/Source/Common/IDE/BoldWebConnectionReg.pas b/Source/Common/IDE/BoldWebConnectionReg.pas index 86db60e..3a7b5fb 100644 --- a/Source/Common/IDE/BoldWebConnectionReg.pas +++ b/Source/Common/IDE/BoldWebConnectionReg.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldWebConnectionReg; interface @@ -23,3 +26,4 @@ procedure Register; end; end. + diff --git a/Source/Common/IDECOM/BoldComEditors.pas b/Source/Common/IDECOM/BoldComEditors.pas index 2c16130..1086bf1 100644 --- a/Source/Common/IDECOM/BoldComEditors.pas +++ b/Source/Common/IDECOM/BoldComEditors.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldComEditors; interface @@ -76,8 +79,7 @@ implementation SysUtils, DesignIntf, Windows, - Dialogs, - BoldComConst; + Dialogs; constructor TBoldComServerUnitFile.Create(const UnitIdent: string; Creator: TBoldComServerUnitCreator); @@ -94,31 +96,31 @@ function TBoldComServerUnitFile.GetSource: string; with TStringList.Create do begin try - Add(Format('unit %s;', [FUnitIdent])); // do not localize - Add(''); // do not localize - Add('interface'); // do not localize - Add(''); // do not localize - Add('implementation'); // do not localize - Add(''); // do not localize - Add('uses'); // do not localize - Add(' ComServ, BoldComServer;'); // do not localize - Add(''); // do not localize - Add('const'); // do not localize + Add(Format('unit %s;', [FUnitIdent])); + Add(''); + Add('interface'); + Add(''); + Add('implementation'); + Add(''); + Add('uses'); + Add(' ComServ, BoldComServer;'); + Add(''); + Add('const'); for I := 0 to Creator.ServerHandle.Classes.Count - 1 do begin Item := Creator.ServerHandle.Classes[I]; - Add(Format(' %s_CLSID: TGUID = ''%s'';', [Item.Name, Item.CLSID])); // do not localize + Add(Format(' %s_CLSID: TGUID = ''%s'';', [Item.Name, Item.CLSID])); end; Add(''); - Add('initialization'); // do not localize + Add('initialization'); for I := 0 to Creator.ServerHandle.Classes.Count - 1 do begin Item := Creator.ServerHandle.Classes[I]; - Add(' TBoldComServerConnectionFactory.Create(ComServer, '); // do not localize - Add(Format(' %s_CLSID, ''%s'', ''%s'');', [Item.Name, Item.Name, Item.Description])); // do not localize + Add(' TBoldComServerConnectionFactory.Create(ComServer, '); + Add(Format(' %s_CLSID, ''%s'', ''%s'');', [Item.Name, Item.Name, Item.Description])); end; Add(''); - Add('end.'); // do not localize + Add('end.'); Result := Text; finally Free; @@ -238,7 +240,7 @@ procedure TBoldComServerHandleComponentEditor.ExecuteVerb(Index: Integer); ServerHandle := Component as TBoldComServerHandle; if ServerHandle.Classes.Count > 0 then begin - if MessageDlg(sGenerateServerCode, + if MessageDlg('This will generate server code, continue?', mtConfirmation, [mbYes, mbNo], 0) = idYes then begin BorlandIDEServices.QueryInterface(IOTAModuleServices, Ms); @@ -250,7 +252,7 @@ procedure TBoldComServerHandleComponentEditor.ExecuteVerb(Index: Integer); end; end else - MessageDlg(sCannotGenerateServerCode, mtWarning, [mbOK], 0); + MessageDlg('Can''t generate code, no class(es) defined.', mtWarning, [mbOK], 0); end; end; @@ -258,7 +260,7 @@ function TBoldComServerHandleComponentEditor.GetVerb(Index: Integer): string; begin if Index = 0 then begin - Result := sCaptionGenerateServerCode; + Result := 'Generate server code...'; end; end; @@ -295,4 +297,6 @@ procedure TBoldComServerClassPropertyEditor.GetValueList(List: TStrings); ServerHandle.Classes.GetClassNames(List); end; +initialization + end. diff --git a/Source/Common/IDECOM/BoldComReg.pas b/Source/Common/IDECOM/BoldComReg.pas index d7d600c..82f7343 100644 --- a/Source/Common/IDECOM/BoldComReg.pas +++ b/Source/Common/IDECOM/BoldComReg.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldComReg; interface @@ -5,7 +8,7 @@ interface procedure Register; implementation -{$R BoldComReg.Res} + uses Classes, DesignIntf, @@ -13,7 +16,8 @@ implementation BoldComClientHandles, BoldComEditors, BoldIDEConsts, - BoldObjectNamePropertyEditor; + BoldObjectNamePropertyEditor + ; procedure Register; begin @@ -26,8 +30,8 @@ procedure Register; RegisterComponentEditor(TBoldComServerHandle, TBoldComServerHandleComponentEditor); RegisterPropertyEditor(TypeInfo(string), TBoldComExportHandle, - 'ServerClass', TBoldComServerClassPropertyEditor); // do not localize - RegisterPropertyEditor(TypeInfo(String), TBoldComClientObjectHandle, 'Objectname', TBoldObjectNameProperty); // do not localize + 'ServerClass', TBoldComServerClassPropertyEditor); + RegisterPropertyEditor(TypeInfo(String), TBoldComClientObjectHandle, 'Objectname', TBoldObjectNameProperty); end; end. diff --git a/Source/Common/IDECOM/BoldObjectNamePropertyEditor.pas b/Source/Common/IDECOM/BoldObjectNamePropertyEditor.pas index aa9b90d..cab63c9 100644 --- a/Source/Common/IDECOM/BoldObjectNamePropertyEditor.pas +++ b/Source/Common/IDECOM/BoldObjectNamePropertyEditor.pas @@ -1,5 +1,10 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldObjectNamePropertyEditor; +{$Include Bold.inc} + interface uses @@ -73,6 +78,7 @@ TBoldObjectNameProperty = class(TBoldStringProperty) function GetAttributes: TPropertyAttributes; override; end; + var ObjectNamePropEditFrm: TObjectNamePropEditFrm; @@ -81,8 +87,7 @@ implementation uses BoldComUtils, Variants, - dialogs, - BoldComConst; + dialogs; {$R *.DFM} @@ -122,9 +127,9 @@ function TObjectNamePropEditFrm.Display(pConnectionHandle: TObject): Boolean; fConnectionHandle := pConnectionHandle as TBoldComConnectionHandle; if Assigned(ConnectionHandle) then begin - Caption := Format(sObjectsInX, [ConnectionHandle.ServerName]); + Caption := Format('Objects in %s', [ConnectionHandle.ServerName]); if (ObjectServers.IndexOf(ConnectionHandle.ServerCLSID) = -1) and - (MessageDlg(Format(sQueryStartServer, [ConnectionHandle.ServerName]), mtConfirmation, [mbYes, mbNo], 0) = mrYes) then + (MessageDlg(Format('Would you like to start the server %s to get the list of exported objects?', [ConnectionHandle.ServerName]), mtConfirmation, [mbYes, mbNo], 0) = mrYes) then GetObjectsFromServer; CurrentInfo := nil; if (ObjectServers.IndexOf(ConnectionHandle.ServerCLSID) <> -1) then @@ -171,7 +176,7 @@ procedure TObjectNamePropEditFrm.GetObjectsFromServer; FreeAndNil(ObjectNames); FreeAndNil(ClassNames); end; - end; // if connected + end; ConnectionHandle.Connected := false; end; @@ -257,8 +262,7 @@ procedure TObjectNamePropEditFrm.RefreshActionExecute(Sender: TObject); var CurrentInfo: TBoldProviderObjectInfo; begin - //refresh list - if (MessageDlg(Format(sQueryConnectToServer, [ConnectionHandle.ServerName]), mtConfirmation, [mbYes, mbNo], 0) = mrYes) then + if (MessageDlg(Format('Connect to server %s and retrieve exported objects?', [ConnectionHandle.ServerName]), mtConfirmation, [mbYes, mbNo], 0) = mrYes) then begin GetObjectsFromServer; CurrentInfo := nil; @@ -280,7 +284,7 @@ procedure TBoldObjectNameProperty.Edit; SelectedPersistent := nil; for i := 0 to PropCount - 1 do SelectedPersistent := GetComponent(i); - obj := GetObjectProp(SelectedPersistent, 'ConnectionHandle'); // do not localize + obj := GetObjectProp(SelectedPersistent, 'ConnectionHandle'); if Assigned(obj) then begin with TObjectNamePropEditFrm.Create(Application) do @@ -291,7 +295,7 @@ procedure TBoldObjectNameProperty.Edit; end; end else - MessageDlg(sCannotFindConnectionHandle,mtInformation, [mbOk], 0); + MessageDlg('Cannot find a ConnectionHandle.',mtInformation, [mbOk], 0); end; function TBoldObjectNameProperty.FileFilter: string; @@ -304,7 +308,9 @@ function TBoldObjectNameProperty.GetAttributes: TPropertyAttributes; Result := [paDialog, paRevertable]; end; -initialization //empty + + +initialization finalization FreeObjectServers; diff --git a/Source/Common/IDECOM/BoldXMLDispatcherEditor.pas b/Source/Common/IDECOM/BoldXMLDispatcherEditor.pas index d9eebd1..c2b51bb 100644 --- a/Source/Common/IDECOM/BoldXMLDispatcherEditor.pas +++ b/Source/Common/IDECOM/BoldXMLDispatcherEditor.pas @@ -1,10 +1,15 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldXMLDispatcherEditor; interface uses DesignEditors, - DesignIntf; + DesignIntf, + BoldRev; + type { forward declarations } @@ -22,15 +27,12 @@ TBoldXMLDispatcherEditor = class(TDefaultEditor) implementation -uses - BoldComConst; - { TBoldXMLDispatcherEditor } procedure TBoldXMLDispatcherEditor.EditProperty( const PropertyEditor: IProperty; var Continue: Boolean); begin - if PropertyEditor.GetName = 'Actions' then // do not localize + if PropertyEditor.GetName = 'Actions' then begin PropertyEditor.Edit; Continue := False; @@ -48,7 +50,7 @@ procedure TBoldXMLDispatcherEditor.ExecuteVerb(Index: Integer); function TBoldXMLDispatcherEditor.GetVerb(Index: Integer): string; begin case Index of - 0: Result := sEditActions; + 0: Result := 'Edit actions...'; end; end; @@ -57,4 +59,6 @@ function TBoldXMLDispatcherEditor.GetVerbCount: Integer; Result := 1; end; +initialization + end. diff --git a/Source/Common/IDECOM/BoldXMLDispatcherReg.pas b/Source/Common/IDECOM/BoldXMLDispatcherReg.pas index 893aa5e..cd73a3f 100644 --- a/Source/Common/IDECOM/BoldXMLDispatcherReg.pas +++ b/Source/Common/IDECOM/BoldXMLDispatcherReg.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldXMLDispatcherReg; interface @@ -10,11 +13,12 @@ implementation BoldXMLDispatcher, BoldXMLDispatcherEditor, DesignIntf, + BoldGuard, Classes; procedure Register; begin - RegisterComponents('Bold XML', [TBoldXMLDispatcher]); // do not localize + RegisterComponents('Bold XML', [TBoldXMLDispatcher]); RegisterComponentEditor(TBoldXMLDispatcher, TBoldXMLDispatcherEditor); end; diff --git a/Source/Common/IDECOM/BoldXMLDispatcherVBReg.pas b/Source/Common/IDECOM/BoldXMLDispatcherVBReg.pas index e1061d1..cd5e0c1 100644 --- a/Source/Common/IDECOM/BoldXMLDispatcherVBReg.pas +++ b/Source/Common/IDECOM/BoldXMLDispatcherVBReg.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldXMLDispatcherVBReg; interface @@ -8,11 +11,12 @@ implementation uses BoldXMLDispatcherVB, - Classes; + Classes, + BoldGuard; procedure Register; begin - RegisterComponents('Bold XML', [TBoldXMLDispatcherVB]); // do not localize + RegisterComponents('Bold XML', [TBoldXMLDispatcherVB]); end; end. diff --git a/Source/Common/Include/Bold.inc b/Source/Common/Include/Bold.inc index e69de29..d6d4416 100644 --- a/Source/Common/Include/Bold.inc +++ b/Source/Common/Include/Bold.inc @@ -0,0 +1,492 @@ +{$WARNINGS OFF} +{$HINTS OFF} + +{$WARN SYMBOL_PLATFORM OFF} +{$WARN UNIT_PLATFORM OFF} + +{$IFDEF WIN32} + {$DEFINE MSWINDOWS} +{$ENDIF} + +{$IFDEF WIN64} + {$DEFINE MSWINDOWS} +{$ENDIF} + +{$IFDEF BOLD_ARCHITECT} + {$UNDEF BOLD_LICENSE} +{$ENDIF} + +{$IFDEF BOLD_DELPHI_PARSER} + {$DEFINE WIN32} + {$DEFINE VER130} +{$ENDIF} + +// LicenseManager cannot be compiled with BOLD_BCB defined for some reason... +{$IFDEF BOLD_LICENSEMANAGER} + {$DEFINE DELPHI} + {$UNDEF BCB} +{$ENDIF} + +{$IFDEF BCB} + {$DEFINE BOLD_BCB} +{$ENDIF} + +{$IFDEF DELPHI} + {$DEFINE BOLD_DELPHI} +{$ENDIF} + + +{$IFDEF BOLD_DELPHI} {$IFDEF BOLD_BCB} +Illegal symbol combination BOLD_DELPHI and BOLD_BCB +{$ENDIF} {$ENDIF} + +{$IFNDEF BOLD_DELPHI} {$IFNDEF BOLD_BCB} + {$DEFINE BOLD_DELPHI} +{$ENDIF} {$ENDIF} + +// Determine delphi version from compiler version + +{$IFDEF VER140} // Delphi 6 + {$DEFINE BOLD_DELPHI6} + {$DEFINE BOLD_DELPHI6_OR_LATER} +{$ENDIF} + +{$IFDEF VER150} // Delphi 7 + {$DEFINE BOLD_DELPHI7} + {$DEFINE BOLD_DELPHI7_OR_LATER} + {$DEFINE BOLD_DELPHI6_OR_LATER} +{$ENDIF} + +{$IFDEF VER160} // Delphi 8 + {$DEFINE BOLD_DELPHI8} + {$DEFINE BOLD_DELPHI7_OR_LATER} + {$DEFINE BOLD_DELPHI6_OR_LATER} +{$ENDIF} + +{$IFDEF VER170} // Delphi 9 (2005) + {$DEFINE BOLD_DELPHI9} + {$DEFINE BOLD_DELPHI7_OR_LATER} + {$DEFINE BOLD_DELPHI6_OR_LATER} +{$ENDIF} + +{$IFDEF VER180} // Delphi 10 (2006) + {$DEFINE BOLD_DELPHI10} + {$DEFINE BOLD_DELPHI10_OR_LATER} + {$DEFINE BOLD_DELPHI7_OR_LATER} + {$DEFINE BOLD_DELPHI6_OR_LATER} +{$ENDIF} + +{$IFDEF VER185} // Delphi 11 (2007) + {$UNDEF BOLD_DELPHI10} // Delphi 2007 is both VER180 and VER185 + {$DEFINE BOLD_DELPHI11} + {$DEFINE BOLD_DELPHI11_OR_LATER} + {$DEFINE BOLD_DELPHI10_OR_LATER} + {$DEFINE BOLD_DELPHI7_OR_LATER} + {$DEFINE BOLD_DELPHI6_OR_LATER} +{$ENDIF} + +{$IFDEF VER190} // Delphi 12 (2007 .NET) + {$DEFINE BOLD_DELPHI12} + {$DEFINE BOLD_DELPHI10_OR_LATER} + {$DEFINE BOLD_DELPHI7_OR_LATER} + {$DEFINE BOLD_DELPHI6_OR_LATER} +{$ENDIF} + +{$IFDEF VER200} // Delphi 13 (2009) + {$DEFINE BOLD_DELPHI13} + {$DEFINE BOLD_DELPHI13_OR_LATER} + {$DEFINE BOLD_DELPHI11_OR_LATER} + {$DEFINE BOLD_DELPHI10_OR_LATER} + {$DEFINE BOLD_DELPHI7_OR_LATER} + {$DEFINE BOLD_DELPHI6_OR_LATER} +{$ENDIF} + +{$IFDEF VER210} // Delphi 14 (2010) + {$DEFINE BOLD_DELPHI14} + {$DEFINE BOLD_DELPHI13_OR_LATER} + {$DEFINE BOLD_DELPHI11_OR_LATER} + {$DEFINE BOLD_DELPHI10_OR_LATER} + {$DEFINE BOLD_DELPHI7_OR_LATER} + {$DEFINE BOLD_DELPHI6_OR_LATER} +{$ENDIF} + +{$IFDEF VER220} // Delphi 15 (XE) + {$DEFINE BOLD_DELPHI15} + {$DEFINE BOLD_DELPHI15_OR_LATER} + {$DEFINE BOLD_DELPHI14_OR_LATER} + {$DEFINE BOLD_DELPHI13_OR_LATER} + {$DEFINE BOLD_DELPHI11_OR_LATER} + {$DEFINE BOLD_DELPHI10_OR_LATER} + {$DEFINE BOLD_DELPHI7_OR_LATER} + {$DEFINE BOLD_DELPHI6_OR_LATER} +{$ENDIF} + +{$IFDEF VER230} // Delphi 16 (XE2) + {$DEFINE BOLD_DELPHI16} + {$DEFINE BOLD_DELPHI16_OR_LATER} + {$DEFINE BOLD_DELPHI13_OR_LATER} + {$DEFINE BOLD_DELPHI11_OR_LATER} + {$DEFINE BOLD_DELPHI10_OR_LATER} + {$DEFINE BOLD_DELPHI7_OR_LATER} + {$DEFINE BOLD_DELPHI6_OR_LATER} +{$ENDIF} + +{$IFDEF VER240} // Delphi 17 (XE3) + {$DEFINE BOLD_DELPHI17} + {$DEFINE BOLD_DELPHI17_OR_LATER} + {$DEFINE BOLD_DELPHI16_OR_LATER} + {$DEFINE BOLD_DELPHI13_OR_LATER} + {$DEFINE BOLD_DELPHI11_OR_LATER} + {$DEFINE BOLD_DELPHI10_OR_LATER} + {$DEFINE BOLD_DELPHI7_OR_LATER} + {$DEFINE BOLD_DELPHI6_OR_LATER} +{$ENDIF} + +{$IFDEF VER250} // Delphi 18 (XE4) + {$DEFINE BOLD_DELPHI18} + {$DEFINE BOLD_DELPHI18_OR_LATER} + {$DEFINE BOLD_DELPHI17_OR_LATER} + {$DEFINE BOLD_DELPHI16_OR_LATER} + {$DEFINE BOLD_DELPHI13_OR_LATER} + {$DEFINE BOLD_DELPHI11_OR_LATER} + {$DEFINE BOLD_DELPHI10_OR_LATER} + {$DEFINE BOLD_DELPHI7_OR_LATER} + {$DEFINE BOLD_DELPHI6_OR_LATER} +{$ENDIF} + +{$IFDEF VER260} // Delphi 19 (XE5) + {$DEFINE BOLD_DELPHI19} + {$DEFINE BOLD_DELPHI19_OR_LATER} + {$DEFINE BOLD_DELPHI18_OR_LATER} + {$DEFINE BOLD_DELPHI17_OR_LATER} + {$DEFINE BOLD_DELPHI16_OR_LATER} + {$DEFINE BOLD_DELPHI13_OR_LATER} + {$DEFINE BOLD_DELPHI11_OR_LATER} + {$DEFINE BOLD_DELPHI10_OR_LATER} + {$DEFINE BOLD_DELPHI7_OR_LATER} + {$DEFINE BOLD_DELPHI6_OR_LATER} +{$ENDIF} + +{$IFDEF VER270} // Delphi 20 (XE6) + {$DEFINE BOLD_DELPHI20} + {$DEFINE BOLD_DELPHI20_OR_LATER} + {$DEFINE BOLD_DELPHI19_OR_LATER} + {$DEFINE BOLD_DELPHI18_OR_LATER} + {$DEFINE BOLD_DELPHI17_OR_LATER} + {$DEFINE BOLD_DELPHI16_OR_LATER} + {$DEFINE BOLD_DELPHI13_OR_LATER} + {$DEFINE BOLD_DELPHI11_OR_LATER} + {$DEFINE BOLD_DELPHI10_OR_LATER} + {$DEFINE BOLD_DELPHI7_OR_LATER} + {$DEFINE BOLD_DELPHI6_OR_LATER} +{$ENDIF} + +{$IFDEF VER280} // Delphi 21 (XE7) + {$DEFINE BOLD_DELPHI21} + {$DEFINE BOLD_DELPHI21_OR_LATER} + {$DEFINE BOLD_DELPHI20_OR_LATER} + {$DEFINE BOLD_DELPHI19_OR_LATER} + {$DEFINE BOLD_DELPHI18_OR_LATER} + {$DEFINE BOLD_DELPHI17_OR_LATER} + {$DEFINE BOLD_DELPHI16_OR_LATER} + {$DEFINE BOLD_DELPHI13_OR_LATER} + {$DEFINE BOLD_DELPHI11_OR_LATER} + {$DEFINE BOLD_DELPHI10_OR_LATER} + {$DEFINE BOLD_DELPHI7_OR_LATER} + {$DEFINE BOLD_DELPHI6_OR_LATER} +{$ENDIF} + +{$IFDEF VER290} // Delphi 22 (XE8) + {$DEFINE BOLD_DELPHI22} + {$DEFINE BOLD_DELPHI22_OR_LATER} + {$DEFINE BOLD_DELPHI21_OR_LATER} + {$DEFINE BOLD_DELPHI20_OR_LATER} + {$DEFINE BOLD_DELPHI19_OR_LATER} + {$DEFINE BOLD_DELPHI18_OR_LATER} + {$DEFINE BOLD_DELPHI17_OR_LATER} + {$DEFINE BOLD_DELPHI16_OR_LATER} + {$DEFINE BOLD_DELPHI13_OR_LATER} + {$DEFINE BOLD_DELPHI11_OR_LATER} + {$DEFINE BOLD_DELPHI10_OR_LATER} + {$DEFINE BOLD_DELPHI7_OR_LATER} + {$DEFINE BOLD_DELPHI6_OR_LATER} +{$ENDIF} + +{$IFDEF VER300} // Delphi 23 (XE10) Seattle + {$DEFINE BOLD_DELPHI23} + {$DEFINE BOLD_DELPHI23_OR_LATER} + {$DEFINE BOLD_DELPHI22_OR_LATER} + {$DEFINE BOLD_DELPHI21_OR_LATER} + {$DEFINE BOLD_DELPHI20_OR_LATER} + {$DEFINE BOLD_DELPHI19_OR_LATER} + {$DEFINE BOLD_DELPHI18_OR_LATER} + {$DEFINE BOLD_DELPHI17_OR_LATER} + {$DEFINE BOLD_DELPHI16_OR_LATER} + {$DEFINE BOLD_DELPHI13_OR_LATER} + {$DEFINE BOLD_DELPHI11_OR_LATER} + {$DEFINE BOLD_DELPHI10_OR_LATER} + {$DEFINE BOLD_DELPHI7_OR_LATER} + {$DEFINE BOLD_DELPHI6_OR_LATER} +{$ENDIF} + +{$IFDEF VER310} // Delphi 24 (XE10.1) Berlin + {$DEFINE BOLD_DELPHI24} + {$DEFINE BOLD_DELPHI24_OR_LATER} + {$DEFINE BOLD_DELPHI23_OR_LATER} + {$DEFINE BOLD_DELPHI22_OR_LATER} + {$DEFINE BOLD_DELPHI21_OR_LATER} + {$DEFINE BOLD_DELPHI20_OR_LATER} + {$DEFINE BOLD_DELPHI19_OR_LATER} + {$DEFINE BOLD_DELPHI18_OR_LATER} + {$DEFINE BOLD_DELPHI17_OR_LATER} + {$DEFINE BOLD_DELPHI16_OR_LATER} + {$DEFINE BOLD_DELPHI13_OR_LATER} + {$DEFINE BOLD_DELPHI11_OR_LATER} + {$DEFINE BOLD_DELPHI10_OR_LATER} + {$DEFINE BOLD_DELPHI7_OR_LATER} + {$DEFINE BOLD_DELPHI6_OR_LATER} +{$ENDIF} + +{$IFDEF VER320} // Delphi 25 (XE10.2) Tokyo + {$DEFINE BOLD_DELPHI25} + {$DEFINE BOLD_DELPHI25_OR_LATER} + {$DEFINE BOLD_DELPHI24_OR_LATER} + {$DEFINE BOLD_DELPHI23_OR_LATER} + {$DEFINE BOLD_DELPHI22_OR_LATER} + {$DEFINE BOLD_DELPHI21_OR_LATER} + {$DEFINE BOLD_DELPHI20_OR_LATER} + {$DEFINE BOLD_DELPHI19_OR_LATER} + {$DEFINE BOLD_DELPHI18_OR_LATER} + {$DEFINE BOLD_DELPHI17_OR_LATER} + {$DEFINE BOLD_DELPHI16_OR_LATER} + {$DEFINE BOLD_DELPHI13_OR_LATER} + {$DEFINE BOLD_DELPHI11_OR_LATER} + {$DEFINE BOLD_DELPHI10_OR_LATER} + {$DEFINE BOLD_DELPHI7_OR_LATER} + {$DEFINE BOLD_DELPHI6_OR_LATER} +{$ENDIF} + +{$IFDEF VER330} // Delphi 25 (XE10.3) Rio + {$DEFINE BOLD_DELPHI26} + {$DEFINE BOLD_DELPHI26_OR_LATER} + {$DEFINE BOLD_DELPHI25_OR_LATER} + {$DEFINE BOLD_DELPHI24_OR_LATER} + {$DEFINE BOLD_DELPHI23_OR_LATER} + {$DEFINE BOLD_DELPHI22_OR_LATER} + {$DEFINE BOLD_DELPHI21_OR_LATER} + {$DEFINE BOLD_DELPHI20_OR_LATER} + {$DEFINE BOLD_DELPHI19_OR_LATER} + {$DEFINE BOLD_DELPHI18_OR_LATER} + {$DEFINE BOLD_DELPHI17_OR_LATER} + {$DEFINE BOLD_DELPHI16_OR_LATER} + {$DEFINE BOLD_DELPHI13_OR_LATER} + {$DEFINE BOLD_DELPHI11_OR_LATER} + {$DEFINE BOLD_DELPHI10_OR_LATER} + {$DEFINE BOLD_DELPHI7_OR_LATER} + {$DEFINE BOLD_DELPHI6_OR_LATER} +{$ENDIF} + +{$IFDEF VER340} // Delphi 26 (XE10.4) Sydney + {$DEFINE BOLD_DELPHI27} + {$DEFINE BOLD_DELPHI27_OR_LATER} + {$DEFINE BOLD_DELPHI26_OR_LATER} + {$DEFINE BOLD_DELPHI25_OR_LATER} + {$DEFINE BOLD_DELPHI24_OR_LATER} + {$DEFINE BOLD_DELPHI23_OR_LATER} + {$DEFINE BOLD_DELPHI22_OR_LATER} + {$DEFINE BOLD_DELPHI21_OR_LATER} + {$DEFINE BOLD_DELPHI20_OR_LATER} + {$DEFINE BOLD_DELPHI19_OR_LATER} + {$DEFINE BOLD_DELPHI18_OR_LATER} + {$DEFINE BOLD_DELPHI17_OR_LATER} + {$DEFINE BOLD_DELPHI16_OR_LATER} + {$DEFINE BOLD_DELPHI13_OR_LATER} + {$DEFINE BOLD_DELPHI11_OR_LATER} + {$DEFINE BOLD_DELPHI10_OR_LATER} + {$DEFINE BOLD_DELPHI7_OR_LATER} + {$DEFINE BOLD_DELPHI6_OR_LATER} +{$ENDIF} + +{$IFDEF LINUX} + // Our implementation depends on MSXML and is not supported on Linux + {$UNDEF BOLD_XML_SUPPORT} + {DEFINE BOLD_IDECLX} + {$DEFINE BOLD_CLX} +{$ENDIF} + + +{$IFDEF MSWINDOWS} + {DEFINE BOLD_IDEVCL} +{$ENDIF} + +// Edition switches +{$IFNDEF BOLD_PROFESSIONAL} + {$IFNDEF BOLD_LITE} + {$DEFINE BOLD_ENTERPRISE} + {$ENDIF} +{$ENDIF} + + +// Compiler control +{$IFDEF BOLD_DEV} + {$ASSERTIONS ON} + {$DEBUGINFO ON} + {$IOCHECKS ON} + {$LOCALSYMBOLS ON} + {$OPTIMIZATION OFF} + {$OVERFLOWCHECKS ON} + {$RANGECHECKS ON} + {$REFERENCEINFO ON} + {$STACKFRAMES ON} +{$ENDIF} + +{$IFDEF BOLD_RELEASE} + {$ASSERTIONS OFF} + {$DEBUGINFO OFF} + {$IOCHECKS ON} + {$LOCALSYMBOLS OFF} + {$OPTIMIZATION ON} + {$OVERFLOWCHECKS OFF} + {$RANGECHECKS OFF} + {$REFERENCEINFO OFF} + {$STACKFRAMES OFF} +{$ENDIF} + +{$IFDEF BOLD_DEBUG} {$IFDEF BOLD_RELEASE} +Illegal symbol combination +{$ENDIF} {$ENDIF} + + +// If building SLIB, swicth on some flags switched off by BOLD_RELEASE +{$IFDEF BOLD_SLIB} + {$STACKFRAMES ON} + {$OPTIMIZATION OFF} + {$DEBUGINFO ON} + {$LOCALSYMBOLS ON} + {$IOCHECKS ON} + {$OVERFLOWCHECKS ON} + {$RANGECHECKS ON} + {$REFERENCEINFO ON} + {$ASSERTIONS ON} + {$DEFINE BOLD_MEMORYDEBUG} +{$ENDIF} + +{$IFDEF BOLD_MEMORYDEBUG} + {$DEFINE BOLD_DISABLEMEMORYMANAGER} + {$DEFINE BOLD_DISABLESHAREDSTRINGS} +{$ENDIF} + +{$DEFINE BOLD_DISABLEMEMORYMANAGER} +{.$DEFINE BOLDCOMCLIENT} + +{$IFNDEF DEBUG} + {$DEFINE BOLD_INLINE} +{$ENDIF} + +{$UNDEF BOLD_UNICODE} +{$IFDEF BOLD_DELPHI13_OR_LATER} + {$DEFINE BOLD_UNICODE} +{$ENDIF} + +{$IFDEF BOLD_UNICODE} + {$STRINGCHECKS OFF} // http://www.micro-isv.asia/2008/10/needless-string-checks-with-ensureunicodestring/ +{$ENDIF BOLD_UNICODE} + + // Use OXML instead of MSXML for XML operations (faster and can handle larger XML) +{.$DEFINE OXML} + + // Faster Display Queue - Simplified handling of (Most)Prioritized and less iteration of Display List +{$DEFINE BoldQueue_Optimization} + + // When fetching an object which class list is loaded then search there instead of going to db. +{$DEFINE FetchFromClassList} + + // Mechanism to automatically place subscriptions for all derivation code in .inc files +{.$DEFINE NoAutoSubscription} + + // Mechanism for efficient fetching +{.$DEFINE SpanFetch} + + // Turns off query mechanism +{.$DEFINE BOLD_NO_QUERIES} + + // Do not allow creation of transient instances of a persistent class. + // This is rarely used and if explicitly prohibited allows TBoldClassListController to not have to execute AddTransientFromSystem +{.$DEFINE NoTransientInstancesOfPersistentClass} + + // Do not allow adding of objects from different systems to same list +{.$DEFINE AllowCrossSystemLists} + + // Affects EndModify, if the new value is same as Old value mark the object Current instead of modified +{$DEFINE CompareToOldValues} + + // Debug addon to count instances per subclass of TBoldMemoryManagedObject +{.$DEFINE DebugInstanceCounter} + + // It saves memory to use LightMemberDeriver, but FormSaver is not compatible with LightMemberDeriver +{$DEFINE LightMemberDeriver} + + // Define to use string comparison for all attributes. This may be faster, it uses IBoldStringRepresentable + // but assumes each value has distinct string representation. +{.$DEFINE StringAttributeComparison} + + // Turns of ObjectSpace transaction mechanism +{.$DEFINE NoObjectSpaceTransactions} + + // Turns off MayUpdate +{.$DEFINE NoMayUpdate} + + // USEGLOBALCHARBUFFER is an optimization in BoldHashIndexes.pas +{$DEFINE USEGLOBALCHARBUFFER} + +// Shared Strings brings minimal memory savings, but at cost of performance +{$DEFINE BOLD_DISABLESHAREDSTRINGS} + +// Extrenal IDServer used instead of BoldID/Timestamp tables, improves write performance and avoids deadlocks +{.$DEFINE IDServer} + +// Uses StringBuilder for constructing SQL statements +{$DEFINE RIL} + +// All attributes will return emptyValue instead of exception reading nil. +{.$DEFINE NoNilAttributeExceptions} + +// Does not allow setting or storing of negative dates (before 1899) or after (2899-12-30) +{.$DEFINE NoNegativeDates} + +// Converts zero date (1899) to nil when reading from db +{$DEFINE ConvertZeroDateToDateNil} + +// DateTime and Date conform to each other +{.$DEFINE DateTimeConformsToDate} + +// Allows usage of OCL expressions in constraint messages, the context of expression is the constrained element. Expression has to return a string. +{.$DEFINE OCLConstraintMessages} + +// IndexColumn creates an extra Index column in MemberMappingTable +{.$DEFINE IndexColumn} + +//Includes BoldJson and BoldObjectRepresentationJson +{.$DEFINE BoldJson} + +// BoldSystem broadcasts member events - allows getting events from all objects and their members by only placing one subscription on system +{$DEFINE BoldSystemBroadcastMemberEvents} + +// Generates Enum classes for For..In support, available since D2007 +{$IFDEF BOLD_DELPHI11_OR_LATER} // D2007+ + {$DEFINE UseBoldListEnumerator} +{$ENDIF} + +// do not copy old values to Rollback valuespace during fetch +{$DEFINE DisableRollbackDuringFetch} + +// if link object is deleted (but not yet saved) and then same two objects on both ends are linked again, then reuse the deleted link object instead of creating new one. +// This effectively avoids a db delete and insert of logically same object but with new id. +// As a side effect this also avoids DetectLinkClassDuplicates in batch mode detecting false duplicate +{$DEFINE ReuseDeletedLinkObjectOnRelink} + +{$IFDEF ReuseDeletedLinkObjectOnRelink} + {$IFNDEF CompareToOldValues} + ReuseDeletedLinkObjectOnRelink requires CompareToOldValues + {$ENDIF} +{$ENDIF} diff --git a/Source/Common/Logging/BoldLogForm.pas b/Source/Common/Logging/BoldLogForm.pas index 60806a3..30479ef 100644 --- a/Source/Common/Logging/BoldLogForm.pas +++ b/Source/Common/Logging/BoldLogForm.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldLogForm; interface @@ -38,39 +41,41 @@ TBoldLogForm = class(TForm) procedure cmdCloseClick(Sender: TObject); procedure mnuCopyClick(Sender: TObject); procedure mnuShowAllClick(Sender: TObject); - procedure FormCreate(Sender: TObject); - procedure FormDestroy(Sender: TObject); procedure mnuAddSeparatorClick(Sender: TObject); procedure mnuClearLogClick(Sender: TObject); private { Private declarations } - fLogLines: TStringList; function ShowAllLines: boolean; + function GetLogLines: TStrings; public { Public declarations } procedure AddLog(const s: string); procedure Clear; procedure UpdateView; procedure SaveLog; - property LogLines: TStringList read fLogLines; + property LogLines: TStrings read GetLogLines; end; implementation uses SysUtils, - BoldUtils, - BoldCommonConst; + BoldUtils; {$R *.dfm} procedure TBoldLogForm.AddLog(const s: string); +const + cMaxLines = 10000; begin - fLogLines.Add(s); + while LogLines.Count > cMaxLines do + LogLines.Delete(LogLines.Count-1); + + LogLines.Add(s); try UpdateView; except on E:Exception do - if MessageDlg(Format(sClearAndContinue, [E.Message]), + if MessageDlg(Format('Error: "%s". Clear log and continue?', [E.Message]), mtWarning, [mbYes, mbNo], 0) = mrYes then Log.Lines.Clear else @@ -102,20 +107,11 @@ procedure TBoldLogForm.UpdateView; var i: integer; begin - if visible then - begin - Log.Lines.BeginUpdate; - try - Log.Lines.Clear; - if ShowAllLines then - Log.Lines.Assign(fLogLines) - else - for i := MaxIntValue([0, fLogLines.Count - 50]) to fLogLines.Count - 1 do - Log.Lines.Add(fLogLines[i]); - finally - Log.Lines.EndUpdate; - end; - end; + if not Visible then + exit; + Log.SetFocus; + Log.SelStart := Log.GetTextLen; + Log.Perform(EM_SCROLLCARET, 0, 0); end; procedure TBoldLogForm.mnuShowAllClick(Sender: TObject); @@ -129,24 +125,19 @@ function TBoldLogForm.ShowAllLines: boolean; Result := mnuShowAll.Checked; end; -procedure TBoldLogForm.FormCreate(Sender: TObject); +function TBoldLogForm.GetLogLines: TStrings; begin - fLogLines := TStringList.Create; -end; - -procedure TBoldLogForm.FormDestroy(Sender: TObject); -begin - FreeAndNil(fLogLines); + result := Log.Lines; end; procedure TBoldLogForm.SaveLog; begin with TSaveDialog.Create(nil) do try - DefaultExt := 'log'; // do not localize - Filter := Format('%s (*.log)|*.log|%s (*.txt)|*.txt|%s (*.*)|*.*', [sLogFiles, sTextFiles, sAllFiles]); // do not localize + DefaultExt := 'log'; + Filter := 'Log files (*.log)|*.log|Text files (*.txt)|*.txt|All files (*.*)|*.*'; Options := [ofOverwritePrompt, ofHideReadOnly, ofPathMustExist, ofNoReadOnlyReturn]; - Title := sSaveLogAs; + Title := 'Save Log As'; if Execute then LogLines.SaveToFile(FileName); finally @@ -157,11 +148,15 @@ procedure TBoldLogForm.SaveLog; procedure TBoldLogForm.mnuAddSeparatorClick(Sender: TObject); begin BoldLog.Separator; + UpdateView; end; procedure TBoldLogForm.mnuClearLogClick(Sender: TObject); begin - fLogLines.Clear; + LogLines.Clear; + UpdateView; end; +initialization + end. diff --git a/Source/Common/Logging/BoldLogHandler.pas b/Source/Common/Logging/BoldLogHandler.pas index 9edd3d7..5b375a0 100644 --- a/Source/Common/Logging/BoldLogHandler.pas +++ b/Source/Common/Logging/BoldLogHandler.pas @@ -1,11 +1,12 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldLogHandler; interface uses - Classes, BoldDefs, - BoldMath, BoldSubscription, BoldLogReceiverInterface; @@ -20,6 +21,7 @@ TBoldLogHandler = class(TBoldSubscribableObject) fIndent: integer; fInterrupted: Boolean; fInterruptHandled: Boolean; + fLastCommandIsSeparator: Boolean; procedure SetProgress(const Value: integer); procedure SetLogHeader(const Value: string); procedure SetProgressMax(const Value: integer); @@ -44,8 +46,8 @@ TBoldLogHandler = class(TBoldSubscribableObject) procedure Separator; procedure ProgressStep; virtual; procedure Sync; virtual; - procedure RegisterLogReceiver(LogReceiver: IBoldLogReceiver); - procedure UnregisterLogReceiver(LogReceiver: IBoldLogReceiver); + procedure RegisterLogReceiver(const LogReceiver: IBoldLogReceiver); + procedure UnregisterLogReceiver(const LogReceiver: IBoldLogReceiver); procedure InterruptProcess; function ProcessInterruption: Boolean; property ProgressMax: integer write SetProgressMax; @@ -62,7 +64,7 @@ TBoldLogReceiverSubscriber = class(TBoldSubscriber) procedure ReceiveExtended(Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent; const Args: array of const); override; function GetHandlesExtendedEvents: Boolean; override; public - constructor Create(Receiver: IBoldLogreceiver); + constructor Create(const Receiver: IBoldLogreceiver); end; function BoldLog: TBoldLogHandler; @@ -71,26 +73,28 @@ implementation uses SysUtils, - BoldUtils, - BoldCommonConst; + BoldMath, + BoldRev; const bleFirst = 1; - bleSetProgress = 1; // Value: integer - bleSetLogHeader = 2; // Value: string - bleSetProgressMax = 3; // Value: integer + bleSetProgress = 1; + bleSetLogHeader = 2; + bleSetProgressMax = 3; bleClear = 4; bleHide = 5; - bleLog = 6; // s: string; LogType: TBoldLogType + bleLog = 6; bleProgressStep = 7; bleShow = 8; - bleStartLog = 9; //SessionName: String + bleStartLog = 9; bleEndLog = 10; bleProcessInterruption = 11; - bleRemoveReceiver = 12; // LogReceiver; + bleRemoveReceiver = 12; bleSync = 13; bleLast = 13; + + var G_BoldLog: TBoldLogHandler = nil; G_BoldLogHandlerClass: TBoldLogHandlerClass = TBoldLogHandler; @@ -104,6 +108,7 @@ function BoldLog: TBoldLogHandler; constructor TBoldLogHandler.Create; begin + fLastCommandIsSeparator := true; inherited; end; @@ -119,9 +124,12 @@ function TBoldLogHandler.IndentSpaces: string; procedure TBoldLogHandler.Separator; begin + if fLastCommandIsSeparator then + exit; Log('', ltSeparator); Log('-={++++}=-', ltSeparator); Log('', ltSeparator); + fLastCommandIsSeparator := true; end; procedure TBoldLogHandler.Clear; @@ -157,6 +165,7 @@ procedure TBoldLogHandler.EndLog; procedure TBoldLogHandler.Log(const s: string; LogType: TBoldLogType = ltInfo); begin SendExtendedEvent(bleLog, [IndentSpaces + s, Integer(LogType)]); + fLastCommandIsSeparator := false; end; procedure TBoldLogHandler.LogFmt(const s: string; const Args: array of const; LogType: TBoldLogType = ltInfo); @@ -220,12 +229,12 @@ procedure TBoldLoghandler.ProgressStep; SendEvent(bleProgressStep); end; -procedure TBoldLogHandler.RegisterLogReceiver(LogReceiver: IBoldLogReceiver); +procedure TBoldLogHandler.RegisterLogReceiver(const LogReceiver: IBoldLogReceiver); begin TBoldLogReceiverSubscriber.Create(LogReceiver); end; -procedure TBoldLogHandler.UnregisterLogReceiver(LogReceiver: IBoldLogReceiver); +procedure TBoldLogHandler.UnregisterLogReceiver(const LogReceiver: IBoldLogReceiver); begin SendExtendedEvent(bleRemoveReceiver, [LogReceiver]); end; @@ -233,7 +242,7 @@ procedure TBoldLogHandler.UnregisterLogReceiver(LogReceiver: IBoldLogReceiver); procedure TBoldLogHandler.InterruptProcess; begin - Log(sTryingToAbort); + Log('Trying to abort process'); fInterrupted := true; fInterruptHandled := false; end; @@ -245,14 +254,14 @@ function TBoldLogHandler.ProcessInterruption: Boolean; if result then begin if not fInterruptHandled then - Log(sProcessStopped); + Log('Process stopped'); fInterruptHandled := true; end; end; { TBoldLogReceiverSubscriber } -constructor TBoldLogReceiverSubscriber.Create(Receiver: IBoldLogreceiver); +constructor TBoldLogReceiverSubscriber.Create(const Receiver: IBoldLogreceiver); begin inherited Create; fReceiver := Receiver; @@ -268,31 +277,33 @@ function TBoldLogReceiverSubscriber.GetHandlesExtendedEvents: Boolean; procedure TBoldLogReceiverSubscriber.Receive(Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent); begin - // Do nothing... Handled by Extended end; procedure TBoldLogReceiverSubscriber.ReceiveExtended(Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent; const Args: array of const); - + function GetString(const VR: TVarRec): String; begin case VR.VType of - vtString: result := VR.VString^; - vtAnsiString: result := PChar(VR.VAnsiString); + vtString: Result := string(VR.vString); + vtAnsiString: Result := string(VR.vAnsiString); + {$IFDEF BOLD_UNICODE} + vtUnicodeString: Result := string(VR.vUnicodeString); + {$ENDIF} else - raise Exception.Create(sUnknownTypeInGetString); + raise Exception.Create('unknown type in GetString'); end; end; begin case OriginalEvent of - bleSetProgress: fReceiver.SetProgress(args[0].VInteger); // Value: integer - bleSetLogHeader: fReceiver.SetLogHeader(GetString(Args[0])); // Value: string - bleSetProgressMax: fReceiver.SetProgressMax(args[0].VInteger); // Value: integer - bleLog: fReceiver.Log(GetString(Args[0]), TBoldLogType(args[1].vInteger)) ;// s: string; LogType: TBoldLogType - bleStartLog: fReceiver.StartLog(GetString(Args[0]));//SessionName: String - // commit suicide + bleSetProgress: fReceiver.SetProgress(args[0].VInteger); + bleSetLogHeader: fReceiver.SetLogHeader(GetString(Args[0])); + bleSetProgressMax: fReceiver.SetProgressMax(args[0].VInteger); + bleLog: fReceiver.Log(GetString(Args[0]), TBoldLogType(args[1].vInteger)) ; + bleStartLog: fReceiver.StartLog(GetString(Args[0])); + bleRemoveReceiver: if IUnknown(Args[0].VInterface) = freceiver then free; beDestroying: Free; bleClear: fReceiver.Clear; @@ -307,6 +318,7 @@ procedure TBoldLogReceiverSubscriber.ReceiveExtended(Originator: TObject; end; end; + procedure TBoldLogHandler.Sync; begin SendEvent(bleSync); diff --git a/Source/Common/Logging/BoldLogHandlerForm.pas b/Source/Common/Logging/BoldLogHandlerForm.pas index 0bb8499..927a29c 100644 --- a/Source/Common/Logging/BoldLogHandlerForm.pas +++ b/Source/Common/Logging/BoldLogHandlerForm.pas @@ -1,11 +1,12 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldLogHandlerForm; interface uses Forms, - Classes, - BoldUtils, BoldDefs, BoldLogHandler, BoldLogReceiverInterface, @@ -19,21 +20,17 @@ TBoldLogHandlerReceiver = class; TBoldLogHandlerReceiver = class(TInterfacedObject, IBoldLogReceiver) private fLogForm: TBoldLogForm; - fLogFormNotifier: TBoldPassthroughNotifier; fSessionName: String; function GetLogForm: TBoldLogForm; procedure HideProgressBar; - function GetLogFormNotifier: TBoldPassthroughNotifier; protected property LogForm: TBoldLogForm read GetLogForm; - property LogFormNotifier: TBoldPassthroughNotifier read GetLogFormNotifier; procedure SetProgress(const Value: integer); procedure SetLogHeader(const Value: string); procedure SetProgressMax(const Value: integer); procedure ProcessInterruption; - procedure Notification(AComponent: TComponent; Operation: TOperation); public - destructor Destroy; override; + destructor destroy; override; procedure Clear; procedure Hide; procedure Log(const s: string; LogType: TBoldLogType = ltInfo); @@ -49,7 +46,8 @@ implementation uses SysUtils, - BoldCommonConst; + BoldUtils, + BoldRev; var LogHandlerForm: TBoldLogHandlerReceiver; @@ -61,26 +59,22 @@ procedure TBoldLogHandlerReceiver.Clear; LogForm.Clear; end; -destructor TBoldLogHandlerReceiver.Destroy; +destructor TBoldLogHandlerReceiver.destroy; begin FreeAndNil(fLogForm); - FreeAndNil(fLogFormNotifier); inherited; end; procedure TBoldLogHandlerReceiver.EndLog; begin - Log(format(sLogDone, [formatDateTime('c', now), fSessionName])); + Log(format('%s: Done %s', [formatDateTime('c', now), fSessionName])); Hideprogressbar; end; function TBoldLogHandlerReceiver.GetLogForm: TBoldLogForm; begin if not Assigned(fLogForm) then - begin fLogForm := TBoldLogForm.Create(nil); - fLogForm.FreeNotification(LogFormNotifier); - end; Result := fLogForm; end; @@ -112,9 +106,7 @@ procedure TBoldLogHandlerReceiver.SetProgress(const Value: integer); procedure TBoldLogHandlerReceiver.SetLogHeader(const Value: string); begin - LogForm.AddLog('=================================='); - LogForm.AddLog('==='+Value); - LogForm.AddLog('=================================='); + LogForm.AddLog(Value); end; procedure TBoldLogHandlerReceiver.SetProgressMax(const Value: integer); @@ -131,9 +123,9 @@ procedure TBoldLogHandlerReceiver.Show; procedure TBoldLogHandlerReceiver.StartLog(const SessionName: String); begin - LogForm.Caption := Format(sLogFormCaption, [SessionName]); + LogForm.Caption := 'Logging Activity: ' + SessionName; fSessionName := SessionName; - Log(format(sLogStarting, [formatDateTime('c', now), SessionName])); // do not localize + Log(format('%s: Starting %s', [formatDateTime('c', now), SessionName])); end; procedure TBoldLogHandlerReceiver.ProcessInterruption; @@ -151,21 +143,8 @@ procedure TBoldLogHandlerReceiver.Sync; Application.ProcessMessages; end; -procedure TBoldLogHandlerReceiver.Notification(AComponent: TComponent; - Operation: TOperation); -begin - if (AComponent = fLogForm) and (Operation = opRemove) then - fLogForm := nil; -end; - -function TBoldLogHandlerReceiver.GetLogFormNotifier: TBoldPassthroughNotifier; -begin - if not assigned(fLogFormNotifier) then - fLogFormNotifier := TBoldPassthroughNotifier.CreateWithEvent(Notification); - result := fLogFormNotifier; -end; - initialization + LogHandlerForm := TBoldLogHandlerReceiver.Create; BoldLog.RegisterLogReceiver(LogHandlerForm as IBoldLogReceiver); diff --git a/Source/Common/Logging/BoldLogHandlerSimple.pas b/Source/Common/Logging/BoldLogHandlerSimple.pas index 9f03fb3..e752d60 100644 --- a/Source/Common/Logging/BoldLogHandlerSimple.pas +++ b/Source/Common/Logging/BoldLogHandlerSimple.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldLogHandlerSimple; interface @@ -16,18 +19,18 @@ TBoldSimpleLogReceiver = class(TInterfacedObject, IBoldLogReceiver) function GetLogLines: TStringList; protected procedure SetProgress(const Value: integer); - procedure SetLogHeader(const Value: string); + procedure SetLogHeader(const Value: string); virtual; procedure SetProgressMax(const Value: integer); procedure ProcessInterruption; public - destructor Destroy; override; + destructor destroy; override; procedure Clear; procedure Hide; - procedure Log(const s: string; LogType: TBoldLogType); + procedure Log(const s: string; LogType: TBoldLogType); virtual; procedure ProgressStep; procedure Show; procedure Sync; - procedure StartLog(const SessionName: string); + procedure StartLog(const SessionName: string); virtual; procedure EndLog; property LogLines: TStringList read GetLogLines; end; @@ -37,7 +40,7 @@ implementation uses SysUtils, BoldUtils, - BoldCommonConst; + BoldRev; { TBoldSimpleLogReceiver } @@ -46,7 +49,7 @@ procedure TBoldSimpleLogReceiver.Clear; LogLines.Clear; end; -destructor TBoldSimpleLogReceiver.Destroy; +destructor TBoldSimpleLogReceiver.destroy; begin FreeAndNil(fLogLines); inherited; @@ -54,7 +57,6 @@ destructor TBoldSimpleLogReceiver.Destroy; procedure TBoldSimpleLogReceiver.EndLog; begin - // intentionally left blank end; function TBoldSimpleLogReceiver.GetLogLines: TStringList; @@ -64,9 +66,9 @@ function TBoldSimpleLogReceiver.GetLogLines: TStringList; Result := fLogLines; end; + procedure TBoldSimpleLogReceiver.Hide; begin - // intentionally left blank end; procedure TBoldSimpleLogReceiver.Log(const s: string; LogType: TBoldLogType); @@ -76,12 +78,10 @@ procedure TBoldSimpleLogReceiver.Log(const s: string; LogType: TBoldLogType); procedure TBoldSimpleLogReceiver.ProgressStep; begin - // intentionally left blank end; procedure TBoldSimpleLogReceiver.SetProgress(const Value: integer); begin - // intentionally left blank end; procedure TBoldSimpleLogReceiver.SetLogHeader(const Value: string); @@ -91,28 +91,25 @@ procedure TBoldSimpleLogReceiver.SetLogHeader(const Value: string); procedure TBoldSimpleLogReceiver.SetProgressMax(const Value: integer); begin - // intentionally left blank end; procedure TBoldSimpleLogReceiver.Show; begin - // intentionally left blank end; procedure TBoldSimpleLogReceiver.StartLog(const SessionName: String); begin - LogLines.Add(Format(sSessionStart, [SessionName])); + LogLines.Add('Session: ' + SessionName); end; procedure TBoldSimpleLogReceiver.ProcessInterruption; begin - // Intentionally left blank end; procedure TBoldSimpleLogReceiver.Sync; begin - // Intentionally left blank end; -end. +initialization +end. diff --git a/Source/Common/Logging/BoldLogReceiverInterface.pas b/Source/Common/Logging/BoldLogReceiverInterface.pas index 488df3c..134073f 100644 --- a/Source/Common/Logging/BoldLogReceiverInterface.pas +++ b/Source/Common/Logging/BoldLogReceiverInterface.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldLogReceiverInterface; interface @@ -31,4 +34,11 @@ interface implementation +uses + BoldRev; + + +initialization + + end. diff --git a/Source/Common/Logging/BoldSmallLogFrame.pas b/Source/Common/Logging/BoldSmallLogFrame.pas index 3784bbc..f0bda65 100644 --- a/Source/Common/Logging/BoldSmallLogFrame.pas +++ b/Source/Common/Logging/BoldSmallLogFrame.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldSmallLogFrame; interface @@ -43,15 +46,15 @@ TBoldLogFrame = class(TFrame, IBoldLogReceiver) procedure Log(const s: string; LogType: TBoldLogType = ltInfo); procedure ProgressStep; procedure Show; - procedure Sync; + procedure Sync; procedure StartLog(const SessionName: String); procedure EndLog; procedure WarningIndicatorClick(Sender: TObject); procedure CalculateTimeLeft; procedure ProcessInterruption; public - constructor Create(Owner: TComponent); override; - destructor Destroy; override; + constructor create(Owner: TComponent); override; + destructor destroy; override; class function CreateSmallLogForm(Caption: string): TForm; { Public declarations } end; @@ -60,8 +63,7 @@ implementation uses SysUtils, - BoldUtils, - BoldCommonConst; + BoldUtils; type TExposedShape = class(TShape) @@ -81,8 +83,8 @@ procedure TBoldLogFrame.CalculateTimeLeft; DonePart := pgLog.Position / pgLog.Max; PartLeft := 1 - DonePart; TimeLeft := (PartLeft * usedTime) / DonePart; - lblTimeLeft.Caption := Format(sLogTimeLeft, [FormatDateTime('hh:mm:ss', timeLeft)]); // do not localize - lblTotTime.Caption := Format(sLogTotalTime, [FormatDateTime('hh:mm:ss', TimeLeft + UsedTime)]); // do not localize + lblTimeLeft.Caption := 'Time left: ' + FormatDateTime('hh:mm:ss', timeLeft); + lblTotTime.Caption := 'Tot time: ' + FormatDateTime('hh:mm:ss', TimeLeft + UsedTime); Refresh; end; end; @@ -103,12 +105,12 @@ constructor TBoldLogFrame.create(Owner: TComponent); lblLogText.Caption := ''; lblLogMainHeader.Caption := ''; lblLogHeader.Caption := ''; - lblTimeLeft.Caption := ''; + lblTimeLeft.Caption := ''; BoldLog.RegisterLogReceiver(self); TExposedShape(WarningIndicator).OnClick := WarningIndicatorClick; end; -destructor TBoldLogFrame.Destroy; +destructor TBoldLogFrame.destroy; begin BoldLog.UnRegisterLogReceiver(self); inherited; @@ -116,17 +118,16 @@ destructor TBoldLogFrame.Destroy; procedure TBoldLogFrame.EndLog; begin -// SetLogHeader(fSessionName); - lblLogText.Caption := sLogSmallDone; + lblLogText.Caption := 'Done...'; pgLog.Position := pgLog.Max + 1; if not WarningPanel.Visible then Timer1.Enabled := true; btnStop.Enabled := false; if fHighestSeverity = ltWarning then - lblLogText.Caption := Format(sLogSmallWarnings, [sLogSmallDone]) + lblLogText.Caption := lblLogText.Caption + ' there were warnings, click the yellow icon for details...' else if fHighestSeverity = ltError then - lblLogText.Caption := Format(sLogSmallErrors, [sLogSmallDone]); + lblLogText.Caption := lblLogText.Caption + ' there were errors, click the red icon for details...'; end; @@ -192,7 +193,7 @@ procedure TBoldLogFrame.StartLog(const SessionName: String); Refresh; Show; fStartTime := now; - Timer1.Enabled := false; + Timer1.Enabled := false; btnStop.Enabled := true; fHighestSeverity := ltInfo; end; @@ -239,4 +240,5 @@ class function TBoldLogFrame.CreateSmallLogForm(Caption: string): TForm; result.Show; end; +initialization end. diff --git a/Source/Common/Logging/BoldThreadSafeLog.pas b/Source/Common/Logging/BoldThreadSafeLog.pas index 621dc29..59f9182 100644 --- a/Source/Common/Logging/BoldThreadSafeLog.pas +++ b/Source/Common/Logging/BoldThreadSafeLog.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldThreadSafeLog; interface @@ -196,7 +199,7 @@ destructor TFileLogging.Destroy; CloseStream; finally fLocker.Release; - end; + end; FreeAndNil(fLocker); inherited; end; @@ -215,7 +218,6 @@ function TFileLogging.OpenStream: Boolean; OpenMode := fmOpenWrite or fmShareDenyWrite; fFileStream := TFileStream.Create(fFileName, OpenMode); FFileStream.Seek(0, soFromEnd); -// fFileStream.Seek(fFileStream.Size, soFromBeginning); // go to end of file Result := true except Result := false; @@ -242,9 +244,9 @@ procedure TFileLogging.Trace(const Entry: string); if IncludeThreadId then begin if ShortThreadId then - line := line + Format(':TID=%d', [GetCurrentThreadID]) // do not localize + line := line + Format(':TID=%d', [GetCurrentThreadID]) else - line := line + Format(' (ThreadID=%d)', [GetCurrentThreadID]); // do not localize + line := line + Format(' (ThreadID=%d)', [GetCurrentThreadID]); end; Line := Line + BOLDCRLF; @@ -262,7 +264,7 @@ procedure TFileLogging.CloseStream; procedure TFileLogging.FlushStream; begin - fFileStream.Size := 0; // go to end of file + fFileStream.Size := 0; end; procedure TFileLogging.SetOpen(const Value: Boolean); @@ -288,4 +290,6 @@ procedure TFileLogging.Trace(const Msg: string; self.Trace(Format(Msg, Args)); end; +initialization + end. diff --git a/Source/Common/MsXml/MSXML_TLB.pas b/Source/Common/MsXml/MSXML_TLB.pas index 3d5b376..85b2482 100644 --- a/Source/Common/MsXml/MSXML_TLB.pas +++ b/Source/Common/MsXml/MSXML_TLB.pas @@ -1,57 +1,53 @@ + +{ Global compiler directives } +{$include bold.inc} unit MSXML_TLB; -// ************************************************************************ // -// WARNING -// ------- -// The types declared in this file were generated from data read from a -// Type Library. If this type library is explicitly or indirectly (via -// another type library referring to this type library) re-imported, or the -// 'Refresh' command of the Type Library Editor activated while editing the -// Type Library, the contents of this file will be regenerated and all -// manual modifications will be lost. -// ************************************************************************ // - -// PASTLWTR: 1.1 -// File generated on 2000-04-28 11:35:52 from Type Library described below. - -// *************************************************************************// -// NOTE: -// Items guarded by $IFDEF_LIVE_SERVER_AT_DESIGN_TIME are used by properties -// which return objects that may need to be explicitly created via a function -// call prior to any access via the property. These items have been disabled -// in order to prevent accidental use from within the object inspector. You -// may enable them by defining LIVE_SERVER_AT_DESIGN_TIME or by selectively -// removing them from the $IFDEF blocks. However, such items must still be -// programmatically created via a method of the appropriate CoClass before -// they can be used. -// ************************************************************************ // -// Type Lib: C:\WINNT\system32\msxml.dll (1) -// IID\LCID: {D63E0CE2-A0A2-11D0-9C02-00C04FC99C8E}\0 -// Helpfile: -// DepndLst: -// (1) v2.0 stdole, (C:\WINNT\System32\stdole2.tlb) -// (2) v4.0 StdVCL, (C:\WINNT\System32\STDVCL40.DLL) -// Errors: -// Hint: Parameter 'type' of IXMLDOMNode.nodeType changed to 'type_' -// Hint: Member 'implementation' of 'IXMLDOMDocument' changed to 'implementation_' -// Hint: Parameter 'type' of IXMLDOMDocument.createNode changed to 'type_' -// Hint: Member 'type' of 'IXMLElement' changed to 'type_' -// Hint: Member 'type' of 'IXMLElement2' changed to 'type_' -// ************************************************************************ // -{$TYPEDADDRESS OFF} // Unit must be compiled without type-checked pointers. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +{$TYPEDADDRESS OFF} interface uses Windows, ActiveX, Classes, Graphics, OleServer, OleCtrls, StdVCL; -// *********************************************************************// -// GUIDS declared in the TypeLibrary. Following prefixes are used: -// Type Libraries : LIBID_xxxx -// CoClasses : CLASS_xxxx -// DISPInterfaces : DIID_xxxx -// Non-DISP interfaces: IID_xxxx -// *********************************************************************// + + + + + const - // TypeLibrary Major and minor versions MSXMLMajorVersion = 2; MSXMLMinorVersion = 0; @@ -92,10 +88,8 @@ interface IID_IXMLError: TGUID = '{948C5AD3-C58D-11D0-9C0B-00C04FC99C8E}'; CLASS_XMLDocument: TGUID = '{CFC399AF-D876-11D0-9C10-00C04FC99C8E}'; -// *********************************************************************// -// Declaration of Enumerations defined in Type Library -// *********************************************************************// -// Constants for enum tagDOMNodeType + + type tagDOMNodeType = TOleEnum; const @@ -112,8 +106,6 @@ interface NODE_DOCUMENT_TYPE = $0000000A; NODE_DOCUMENT_FRAGMENT = $0000000B; NODE_NOTATION = $0000000C; - -// Constants for enum tagXMLEMEM_TYPE type tagXMLEMEM_TYPE = TOleEnum; const @@ -127,9 +119,7 @@ interface type -// *********************************************************************// -// Forward declaration of types defined in TypeLibrary -// *********************************************************************// + IXMLDOMImplementation = interface; IXMLDOMImplementationDisp = dispinterface; IXMLDOMNode = interface; @@ -186,10 +176,8 @@ interface IXMLAttributeDisp = dispinterface; IXMLError = interface; -// *********************************************************************// -// Declaration of CoClasses defined in Type Library -// (NOTE: Here we map each CoClass to its Default Interface) -// *********************************************************************// + + DOMDocument = IXMLDOMDocument; DOMFreeThreadedDocument = IXMLDOMDocument; XMLHTTPRequest = IXMLHttpRequest; @@ -197,9 +185,6 @@ interface XMLDocument = IXMLDocument2; -// *********************************************************************// -// Declaration of structures, unions and aliases. -// *********************************************************************// PUserType1 = ^_xml_error; {*} DOMNodeType = tagDOMNodeType; @@ -215,33 +200,27 @@ interface _reserved2: LongWord; end; - XMLELEM_TYPE = tagXMLEMEM_TYPE; + XMLELEM_TYPE = tagXMLEMEM_TYPE; + + + -// *********************************************************************// -// Interface: IXMLDOMImplementation -// Flags: (4544) Dual NonExtensible OleAutomation Dispatchable -// GUID: {2933BF8F-7B36-11D2-B20E-00C04F983E60} -// *********************************************************************// IXMLDOMImplementation = interface(IDispatch) ['{2933BF8F-7B36-11D2-B20E-00C04F983E60}'] function hasFeature(const feature: WideString; const version: WideString): WordBool; safecall; end; -// *********************************************************************// -// DispIntf: IXMLDOMImplementationDisp -// Flags: (4544) Dual NonExtensible OleAutomation Dispatchable -// GUID: {2933BF8F-7B36-11D2-B20E-00C04F983E60} -// *********************************************************************// + + + IXMLDOMImplementationDisp = dispinterface ['{2933BF8F-7B36-11D2-B20E-00C04F983E60}'] function hasFeature(const feature: WideString; const version: WideString): WordBool; dispid 145; end; -// *********************************************************************// -// Interface: IXMLDOMNode -// Flags: (4544) Dual NonExtensible OleAutomation Dispatchable -// GUID: {2933BF80-7B36-11D2-B20E-00C04F983E60} -// *********************************************************************// + + + IXMLDOMNode = interface(IDispatch) ['{2933BF80-7B36-11D2-B20E-00C04F983E60}'] function Get_nodeName: WideString; safecall; @@ -303,11 +282,9 @@ interface property baseName: WideString read Get_baseName; end; -// *********************************************************************// -// DispIntf: IXMLDOMNodeDisp -// Flags: (4544) Dual NonExtensible OleAutomation Dispatchable -// GUID: {2933BF80-7B36-11D2-B20E-00C04F983E60} -// *********************************************************************// + + + IXMLDOMNodeDisp = dispinterface ['{2933BF80-7B36-11D2-B20E-00C04F983E60}'] property nodeName: WideString readonly dispid 2; @@ -344,11 +321,9 @@ interface procedure transformNodeToObject(const stylesheet: IXMLDOMNode; outputObject: OleVariant); dispid 35; end; -// *********************************************************************// -// Interface: IXMLDOMNodeList -// Flags: (4544) Dual NonExtensible OleAutomation Dispatchable -// GUID: {2933BF82-7B36-11D2-B20E-00C04F983E60} -// *********************************************************************// + + + IXMLDOMNodeList = interface(IDispatch) ['{2933BF82-7B36-11D2-B20E-00C04F983E60}'] function Get_item(index: Integer): IXMLDOMNode; safecall; @@ -361,11 +336,9 @@ interface property _newEnum: IUnknown read Get__newEnum; end; -// *********************************************************************// -// DispIntf: IXMLDOMNodeListDisp -// Flags: (4544) Dual NonExtensible OleAutomation Dispatchable -// GUID: {2933BF82-7B36-11D2-B20E-00C04F983E60} -// *********************************************************************// + + + IXMLDOMNodeListDisp = dispinterface ['{2933BF82-7B36-11D2-B20E-00C04F983E60}'] property item[index: Integer]: IXMLDOMNode readonly dispid 0; default; @@ -375,11 +348,9 @@ interface property _newEnum: IUnknown readonly dispid -4; end; -// *********************************************************************// -// Interface: IXMLDOMNamedNodeMap -// Flags: (4544) Dual NonExtensible OleAutomation Dispatchable -// GUID: {2933BF83-7B36-11D2-B20E-00C04F983E60} -// *********************************************************************// + + + IXMLDOMNamedNodeMap = interface(IDispatch) ['{2933BF83-7B36-11D2-B20E-00C04F983E60}'] function getNamedItem(const name: WideString): IXMLDOMNode; safecall; @@ -397,11 +368,9 @@ interface property _newEnum: IUnknown read Get__newEnum; end; -// *********************************************************************// -// DispIntf: IXMLDOMNamedNodeMapDisp -// Flags: (4544) Dual NonExtensible OleAutomation Dispatchable -// GUID: {2933BF83-7B36-11D2-B20E-00C04F983E60} -// *********************************************************************// + + + IXMLDOMNamedNodeMapDisp = dispinterface ['{2933BF83-7B36-11D2-B20E-00C04F983E60}'] function getNamedItem(const name: WideString): IXMLDOMNode; dispid 83; @@ -416,11 +385,9 @@ interface property _newEnum: IUnknown readonly dispid -4; end; -// *********************************************************************// -// Interface: IXMLDOMDocument -// Flags: (4544) Dual NonExtensible OleAutomation Dispatchable -// GUID: {2933BF81-7B36-11D2-B20E-00C04F983E60} -// *********************************************************************// + + + IXMLDOMDocument = interface(IXMLDOMNode) ['{2933BF81-7B36-11D2-B20E-00C04F983E60}'] function Get_doctype: IXMLDOMDocumentType; safecall; @@ -471,11 +438,9 @@ interface property ontransformnode: OleVariant write Set_ontransformnode; end; -// *********************************************************************// -// DispIntf: IXMLDOMDocumentDisp -// Flags: (4544) Dual NonExtensible OleAutomation Dispatchable -// GUID: {2933BF81-7B36-11D2-B20E-00C04F983E60} -// *********************************************************************// + + + IXMLDOMDocumentDisp = dispinterface ['{2933BF81-7B36-11D2-B20E-00C04F983E60}'] property doctype: IXMLDOMDocumentType readonly dispid 38; @@ -540,11 +505,9 @@ interface procedure transformNodeToObject(const stylesheet: IXMLDOMNode; outputObject: OleVariant); dispid 35; end; -// *********************************************************************// -// Interface: IXMLDOMDocumentType -// Flags: (4544) Dual NonExtensible OleAutomation Dispatchable -// GUID: {2933BF8B-7B36-11D2-B20E-00C04F983E60} -// *********************************************************************// + + + IXMLDOMDocumentType = interface(IXMLDOMNode) ['{2933BF8B-7B36-11D2-B20E-00C04F983E60}'] function Get_name: WideString; safecall; @@ -555,11 +518,9 @@ interface property notations: IXMLDOMNamedNodeMap read Get_notations; end; -// *********************************************************************// -// DispIntf: IXMLDOMDocumentTypeDisp -// Flags: (4544) Dual NonExtensible OleAutomation Dispatchable -// GUID: {2933BF8B-7B36-11D2-B20E-00C04F983E60} -// *********************************************************************// + + + IXMLDOMDocumentTypeDisp = dispinterface ['{2933BF8B-7B36-11D2-B20E-00C04F983E60}'] property name: WideString readonly dispid 131; @@ -599,11 +560,9 @@ interface procedure transformNodeToObject(const stylesheet: IXMLDOMNode; outputObject: OleVariant); dispid 35; end; -// *********************************************************************// -// Interface: IXMLDOMElement -// Flags: (4544) Dual NonExtensible OleAutomation Dispatchable -// GUID: {2933BF86-7B36-11D2-B20E-00C04F983E60} -// *********************************************************************// + + + IXMLDOMElement = interface(IXMLDOMNode) ['{2933BF86-7B36-11D2-B20E-00C04F983E60}'] function Get_tagName: WideString; safecall; @@ -618,11 +577,9 @@ interface property tagName: WideString read Get_tagName; end; -// *********************************************************************// -// DispIntf: IXMLDOMElementDisp -// Flags: (4544) Dual NonExtensible OleAutomation Dispatchable -// GUID: {2933BF86-7B36-11D2-B20E-00C04F983E60} -// *********************************************************************// + + + IXMLDOMElementDisp = dispinterface ['{2933BF86-7B36-11D2-B20E-00C04F983E60}'] property tagName: WideString readonly dispid 97; @@ -668,11 +625,9 @@ interface procedure transformNodeToObject(const stylesheet: IXMLDOMNode; outputObject: OleVariant); dispid 35; end; -// *********************************************************************// -// Interface: IXMLDOMAttribute -// Flags: (4544) Dual NonExtensible OleAutomation Dispatchable -// GUID: {2933BF85-7B36-11D2-B20E-00C04F983E60} -// *********************************************************************// + + + IXMLDOMAttribute = interface(IXMLDOMNode) ['{2933BF85-7B36-11D2-B20E-00C04F983E60}'] function Get_name: WideString; safecall; @@ -682,11 +637,9 @@ interface property value: OleVariant read Get_value write Set_value; end; -// *********************************************************************// -// DispIntf: IXMLDOMAttributeDisp -// Flags: (4544) Dual NonExtensible OleAutomation Dispatchable -// GUID: {2933BF85-7B36-11D2-B20E-00C04F983E60} -// *********************************************************************// + + + IXMLDOMAttributeDisp = dispinterface ['{2933BF85-7B36-11D2-B20E-00C04F983E60}'] property name: WideString readonly dispid 118; @@ -725,20 +678,16 @@ interface procedure transformNodeToObject(const stylesheet: IXMLDOMNode; outputObject: OleVariant); dispid 35; end; -// *********************************************************************// -// Interface: IXMLDOMDocumentFragment -// Flags: (4544) Dual NonExtensible OleAutomation Dispatchable -// GUID: {3EFAA413-272F-11D2-836F-0000F87A7782} -// *********************************************************************// + + + IXMLDOMDocumentFragment = interface(IXMLDOMNode) ['{3EFAA413-272F-11D2-836F-0000F87A7782}'] end; -// *********************************************************************// -// DispIntf: IXMLDOMDocumentFragmentDisp -// Flags: (4544) Dual NonExtensible OleAutomation Dispatchable -// GUID: {3EFAA413-272F-11D2-836F-0000F87A7782} -// *********************************************************************// + + + IXMLDOMDocumentFragmentDisp = dispinterface ['{3EFAA413-272F-11D2-836F-0000F87A7782}'] property nodeName: WideString readonly dispid 2; @@ -775,11 +724,9 @@ interface procedure transformNodeToObject(const stylesheet: IXMLDOMNode; outputObject: OleVariant); dispid 35; end; -// *********************************************************************// -// Interface: IXMLDOMCharacterData -// Flags: (4544) Dual NonExtensible OleAutomation Dispatchable -// GUID: {2933BF84-7B36-11D2-B20E-00C04F983E60} -// *********************************************************************// + + + IXMLDOMCharacterData = interface(IXMLDOMNode) ['{2933BF84-7B36-11D2-B20E-00C04F983E60}'] function Get_data: WideString; safecall; @@ -794,11 +741,9 @@ interface property length: Integer read Get_length; end; -// *********************************************************************// -// DispIntf: IXMLDOMCharacterDataDisp -// Flags: (4544) Dual NonExtensible OleAutomation Dispatchable -// GUID: {2933BF84-7B36-11D2-B20E-00C04F983E60} -// *********************************************************************// + + + IXMLDOMCharacterDataDisp = dispinterface ['{2933BF84-7B36-11D2-B20E-00C04F983E60}'] property data: WideString dispid 109; @@ -842,21 +787,17 @@ interface procedure transformNodeToObject(const stylesheet: IXMLDOMNode; outputObject: OleVariant); dispid 35; end; -// *********************************************************************// -// Interface: IXMLDOMText -// Flags: (4544) Dual NonExtensible OleAutomation Dispatchable -// GUID: {2933BF87-7B36-11D2-B20E-00C04F983E60} -// *********************************************************************// + + + IXMLDOMText = interface(IXMLDOMCharacterData) ['{2933BF87-7B36-11D2-B20E-00C04F983E60}'] function splitText(offset: Integer): IXMLDOMText; safecall; end; -// *********************************************************************// -// DispIntf: IXMLDOMTextDisp -// Flags: (4544) Dual NonExtensible OleAutomation Dispatchable -// GUID: {2933BF87-7B36-11D2-B20E-00C04F983E60} -// *********************************************************************// + + + IXMLDOMTextDisp = dispinterface ['{2933BF87-7B36-11D2-B20E-00C04F983E60}'] function splitText(offset: Integer): IXMLDOMText; dispid 123; @@ -901,20 +842,16 @@ interface procedure transformNodeToObject(const stylesheet: IXMLDOMNode; outputObject: OleVariant); dispid 35; end; -// *********************************************************************// -// Interface: IXMLDOMComment -// Flags: (4544) Dual NonExtensible OleAutomation Dispatchable -// GUID: {2933BF88-7B36-11D2-B20E-00C04F983E60} -// *********************************************************************// + + + IXMLDOMComment = interface(IXMLDOMCharacterData) ['{2933BF88-7B36-11D2-B20E-00C04F983E60}'] end; -// *********************************************************************// -// DispIntf: IXMLDOMCommentDisp -// Flags: (4544) Dual NonExtensible OleAutomation Dispatchable -// GUID: {2933BF88-7B36-11D2-B20E-00C04F983E60} -// *********************************************************************// + + + IXMLDOMCommentDisp = dispinterface ['{2933BF88-7B36-11D2-B20E-00C04F983E60}'] property data: WideString dispid 109; @@ -958,20 +895,16 @@ interface procedure transformNodeToObject(const stylesheet: IXMLDOMNode; outputObject: OleVariant); dispid 35; end; -// *********************************************************************// -// Interface: IXMLDOMCDATASection -// Flags: (4544) Dual NonExtensible OleAutomation Dispatchable -// GUID: {2933BF8A-7B36-11D2-B20E-00C04F983E60} -// *********************************************************************// + + + IXMLDOMCDATASection = interface(IXMLDOMText) ['{2933BF8A-7B36-11D2-B20E-00C04F983E60}'] end; -// *********************************************************************// -// DispIntf: IXMLDOMCDATASectionDisp -// Flags: (4544) Dual NonExtensible OleAutomation Dispatchable -// GUID: {2933BF8A-7B36-11D2-B20E-00C04F983E60} -// *********************************************************************// + + + IXMLDOMCDATASectionDisp = dispinterface ['{2933BF8A-7B36-11D2-B20E-00C04F983E60}'] function splitText(offset: Integer): IXMLDOMText; dispid 123; @@ -1016,11 +949,9 @@ interface procedure transformNodeToObject(const stylesheet: IXMLDOMNode; outputObject: OleVariant); dispid 35; end; -// *********************************************************************// -// Interface: IXMLDOMProcessingInstruction -// Flags: (4544) Dual NonExtensible OleAutomation Dispatchable -// GUID: {2933BF89-7B36-11D2-B20E-00C04F983E60} -// *********************************************************************// + + + IXMLDOMProcessingInstruction = interface(IXMLDOMNode) ['{2933BF89-7B36-11D2-B20E-00C04F983E60}'] function Get_target: WideString; safecall; @@ -1030,11 +961,9 @@ interface property data: WideString read Get_data write Set_data; end; -// *********************************************************************// -// DispIntf: IXMLDOMProcessingInstructionDisp -// Flags: (4544) Dual NonExtensible OleAutomation Dispatchable -// GUID: {2933BF89-7B36-11D2-B20E-00C04F983E60} -// *********************************************************************// + + + IXMLDOMProcessingInstructionDisp = dispinterface ['{2933BF89-7B36-11D2-B20E-00C04F983E60}'] property target: WideString readonly dispid 127; @@ -1073,20 +1002,16 @@ interface procedure transformNodeToObject(const stylesheet: IXMLDOMNode; outputObject: OleVariant); dispid 35; end; -// *********************************************************************// -// Interface: IXMLDOMEntityReference -// Flags: (4544) Dual NonExtensible OleAutomation Dispatchable -// GUID: {2933BF8E-7B36-11D2-B20E-00C04F983E60} -// *********************************************************************// + + + IXMLDOMEntityReference = interface(IXMLDOMNode) ['{2933BF8E-7B36-11D2-B20E-00C04F983E60}'] end; -// *********************************************************************// -// DispIntf: IXMLDOMEntityReferenceDisp -// Flags: (4544) Dual NonExtensible OleAutomation Dispatchable -// GUID: {2933BF8E-7B36-11D2-B20E-00C04F983E60} -// *********************************************************************// + + + IXMLDOMEntityReferenceDisp = dispinterface ['{2933BF8E-7B36-11D2-B20E-00C04F983E60}'] property nodeName: WideString readonly dispid 2; @@ -1123,11 +1048,9 @@ interface procedure transformNodeToObject(const stylesheet: IXMLDOMNode; outputObject: OleVariant); dispid 35; end; -// *********************************************************************// -// Interface: IXMLDOMParseError -// Flags: (4544) Dual NonExtensible OleAutomation Dispatchable -// GUID: {3EFAA426-272F-11D2-836F-0000F87A7782} -// *********************************************************************// + + + IXMLDOMParseError = interface(IDispatch) ['{3EFAA426-272F-11D2-836F-0000F87A7782}'] function Get_errorCode: Integer; safecall; @@ -1146,11 +1069,9 @@ interface property filepos: Integer read Get_filepos; end; -// *********************************************************************// -// DispIntf: IXMLDOMParseErrorDisp -// Flags: (4544) Dual NonExtensible OleAutomation Dispatchable -// GUID: {3EFAA426-272F-11D2-836F-0000F87A7782} -// *********************************************************************// + + + IXMLDOMParseErrorDisp = dispinterface ['{3EFAA426-272F-11D2-836F-0000F87A7782}'] property errorCode: Integer readonly dispid 0; @@ -1162,11 +1083,9 @@ interface property filepos: Integer readonly dispid 184; end; -// *********************************************************************// -// Interface: IXMLDOMNotation -// Flags: (4544) Dual NonExtensible OleAutomation Dispatchable -// GUID: {2933BF8C-7B36-11D2-B20E-00C04F983E60} -// *********************************************************************// + + + IXMLDOMNotation = interface(IXMLDOMNode) ['{2933BF8C-7B36-11D2-B20E-00C04F983E60}'] function Get_publicId: OleVariant; safecall; @@ -1175,11 +1094,9 @@ interface property systemId: OleVariant read Get_systemId; end; -// *********************************************************************// -// DispIntf: IXMLDOMNotationDisp -// Flags: (4544) Dual NonExtensible OleAutomation Dispatchable -// GUID: {2933BF8C-7B36-11D2-B20E-00C04F983E60} -// *********************************************************************// + + + IXMLDOMNotationDisp = dispinterface ['{2933BF8C-7B36-11D2-B20E-00C04F983E60}'] property publicId: OleVariant readonly dispid 136; @@ -1218,11 +1135,9 @@ interface procedure transformNodeToObject(const stylesheet: IXMLDOMNode; outputObject: OleVariant); dispid 35; end; -// *********************************************************************// -// Interface: IXMLDOMEntity -// Flags: (4544) Dual NonExtensible OleAutomation Dispatchable -// GUID: {2933BF8D-7B36-11D2-B20E-00C04F983E60} -// *********************************************************************// + + + IXMLDOMEntity = interface(IXMLDOMNode) ['{2933BF8D-7B36-11D2-B20E-00C04F983E60}'] function Get_publicId: OleVariant; safecall; @@ -1233,11 +1148,9 @@ interface property notationName: WideString read Get_notationName; end; -// *********************************************************************// -// DispIntf: IXMLDOMEntityDisp -// Flags: (4544) Dual NonExtensible OleAutomation Dispatchable -// GUID: {2933BF8D-7B36-11D2-B20E-00C04F983E60} -// *********************************************************************// + + + IXMLDOMEntityDisp = dispinterface ['{2933BF8D-7B36-11D2-B20E-00C04F983E60}'] property publicId: OleVariant readonly dispid 140; @@ -1277,11 +1190,9 @@ interface procedure transformNodeToObject(const stylesheet: IXMLDOMNode; outputObject: OleVariant); dispid 35; end; -// *********************************************************************// -// Interface: IXTLRuntime -// Flags: (4544) Dual NonExtensible OleAutomation Dispatchable -// GUID: {3EFAA425-272F-11D2-836F-0000F87A7782} -// *********************************************************************// + + + IXTLRuntime = interface(IXMLDOMNode) ['{3EFAA425-272F-11D2-836F-0000F87A7782}'] function uniqueID(const pNode: IXMLDOMNode): Integer; safecall; @@ -1297,11 +1208,9 @@ interface varDestLocale: OleVariant): WideString; safecall; end; -// *********************************************************************// -// DispIntf: IXTLRuntimeDisp -// Flags: (4544) Dual NonExtensible OleAutomation Dispatchable -// GUID: {3EFAA425-272F-11D2-836F-0000F87A7782} -// *********************************************************************// + + + IXTLRuntimeDisp = dispinterface ['{3EFAA425-272F-11D2-836F-0000F87A7782}'] function uniqueID(const pNode: IXMLDOMNode): Integer; dispid 187; @@ -1349,22 +1258,18 @@ interface procedure transformNodeToObject(const stylesheet: IXMLDOMNode; outputObject: OleVariant); dispid 35; end; -// *********************************************************************// -// DispIntf: XMLDOMDocumentEvents -// Flags: (4112) Hidden Dispatchable -// GUID: {3EFAA427-272F-11D2-836F-0000F87A7782} -// *********************************************************************// + + + XMLDOMDocumentEvents = dispinterface ['{3EFAA427-272F-11D2-836F-0000F87A7782}'] procedure ondataavailable; dispid 198; procedure onreadystatechange; dispid -609; end; -// *********************************************************************// -// Interface: IXMLHttpRequest -// Flags: (4416) Dual OleAutomation Dispatchable -// GUID: {ED8C108D-4349-11D2-91A4-00C04F7969E8} -// *********************************************************************// + + + IXMLHttpRequest = interface(IDispatch) ['{ED8C108D-4349-11D2-91A4-00C04F7969E8}'] procedure open(const bstrMethod: WideString; const bstrUrl: WideString; varAsync: OleVariant; @@ -1392,11 +1297,9 @@ interface property onreadystatechange: IDispatch write Set_onreadystatechange; end; -// *********************************************************************// -// DispIntf: IXMLHttpRequestDisp -// Flags: (4416) Dual OleAutomation Dispatchable -// GUID: {ED8C108D-4349-11D2-91A4-00C04F7969E8} -// *********************************************************************// + + + IXMLHttpRequestDisp = dispinterface ['{ED8C108D-4349-11D2-91A4-00C04F7969E8}'] procedure open(const bstrMethod: WideString; const bstrUrl: WideString; varAsync: OleVariant; @@ -1416,11 +1319,9 @@ interface property onreadystatechange: IDispatch writeonly dispid 14; end; -// *********************************************************************// -// Interface: IXMLDSOControl -// Flags: (4560) Hidden Dual NonExtensible OleAutomation Dispatchable -// GUID: {310AFA62-0575-11D2-9CA9-0060B0EC3D39} -// *********************************************************************// + + + IXMLDSOControl = interface(IDispatch) ['{310AFA62-0575-11D2-9CA9-0060B0EC3D39}'] function Get_XMLDocument: IXMLDOMDocument; safecall; @@ -1433,11 +1334,9 @@ interface property readyState: Integer read Get_readyState; end; -// *********************************************************************// -// DispIntf: IXMLDSOControlDisp -// Flags: (4560) Hidden Dual NonExtensible OleAutomation Dispatchable -// GUID: {310AFA62-0575-11D2-9CA9-0060B0EC3D39} -// *********************************************************************// + + + IXMLDSOControlDisp = dispinterface ['{310AFA62-0575-11D2-9CA9-0060B0EC3D39}'] property XMLDocument: IXMLDOMDocument dispid 65537; @@ -1445,11 +1344,9 @@ interface property readyState: Integer readonly dispid -525; end; -// *********************************************************************// -// Interface: IXMLElementCollection -// Flags: (4432) Hidden Dual OleAutomation Dispatchable -// GUID: {65725580-9B5D-11D0-9BFE-00C04FC99C8E} -// *********************************************************************// + + + IXMLElementCollection = interface(IDispatch) ['{65725580-9B5D-11D0-9BFE-00C04FC99C8E}'] procedure Set_length(p: Integer); safecall; @@ -1460,11 +1357,9 @@ interface property _newEnum: IUnknown read Get__newEnum; end; -// *********************************************************************// -// DispIntf: IXMLElementCollectionDisp -// Flags: (4432) Hidden Dual OleAutomation Dispatchable -// GUID: {65725580-9B5D-11D0-9BFE-00C04FC99C8E} -// *********************************************************************// + + + IXMLElementCollectionDisp = dispinterface ['{65725580-9B5D-11D0-9BFE-00C04FC99C8E}'] property length: Integer dispid 65537; @@ -1472,11 +1367,9 @@ interface function item(var1: OleVariant; var2: OleVariant): IDispatch; dispid 65539; end; -// *********************************************************************// -// Interface: IXMLDocument -// Flags: (4432) Hidden Dual OleAutomation Dispatchable -// GUID: {F52E2B61-18A1-11D1-B105-00805F49916B} -// *********************************************************************// + + + IXMLDocument = interface(IDispatch) ['{F52E2B61-18A1-11D1-B105-00805F49916B}'] function Get_root: IXMLElement; safecall; @@ -1506,11 +1399,9 @@ interface property dtdURL: WideString read Get_dtdURL; end; -// *********************************************************************// -// DispIntf: IXMLDocumentDisp -// Flags: (4432) Hidden Dual OleAutomation Dispatchable -// GUID: {F52E2B61-18A1-11D1-B105-00805F49916B} -// *********************************************************************// + + + IXMLDocumentDisp = dispinterface ['{F52E2B61-18A1-11D1-B105-00805F49916B}'] property root: IXMLElement readonly dispid 65637; @@ -1527,11 +1418,9 @@ interface function createElement(vType: OleVariant; var1: OleVariant): IXMLElement; dispid 65644; end; -// *********************************************************************// -// Interface: IXMLElement -// Flags: (4432) Hidden Dual OleAutomation Dispatchable -// GUID: {3F7F31AC-E15F-11D0-9C25-00C04FC99C8E} -// *********************************************************************// + + + IXMLElement = interface(IDispatch) ['{3F7F31AC-E15F-11D0-9C25-00C04FC99C8E}'] function Get_tagName: WideString; safecall; @@ -1553,11 +1442,9 @@ interface property text: WideString read Get_text write Set_text; end; -// *********************************************************************// -// DispIntf: IXMLElementDisp -// Flags: (4432) Hidden Dual OleAutomation Dispatchable -// GUID: {3F7F31AC-E15F-11D0-9C25-00C04FC99C8E} -// *********************************************************************// + + + IXMLElementDisp = dispinterface ['{3F7F31AC-E15F-11D0-9C25-00C04FC99C8E}'] property tagName: WideString dispid 65737; @@ -1572,11 +1459,9 @@ interface procedure removeChild(const pChildElem: IXMLElement); dispid 65746; end; -// *********************************************************************// -// Interface: IXMLDocument2 -// Flags: (4112) Hidden Dispatchable -// GUID: {2B8DE2FE-8D2D-11D1-B2FC-00C04FD915A9} -// *********************************************************************// + + + IXMLDocument2 = interface(IDispatch) ['{2B8DE2FE-8D2D-11D1-B2FC-00C04FD915A9}'] function Get_root(out p: IXMLElement2): HResult; stdcall; @@ -1597,11 +1482,9 @@ interface function Set_async(pf: WordBool): HResult; stdcall; end; -// *********************************************************************// -// Interface: IXMLElement2 -// Flags: (4432) Hidden Dual OleAutomation Dispatchable -// GUID: {2B8DE2FF-8D2D-11D1-B2FC-00C04FD915A9} -// *********************************************************************// + + + IXMLElement2 = interface(IDispatch) ['{2B8DE2FF-8D2D-11D1-B2FC-00C04FD915A9}'] function Get_tagName: WideString; safecall; @@ -1625,11 +1508,9 @@ interface property attributes: IXMLElementCollection read Get_attributes; end; -// *********************************************************************// -// DispIntf: IXMLElement2Disp -// Flags: (4432) Hidden Dual OleAutomation Dispatchable -// GUID: {2B8DE2FF-8D2D-11D1-B2FC-00C04FD915A9} -// *********************************************************************// + + + IXMLElement2Disp = dispinterface ['{2B8DE2FF-8D2D-11D1-B2FC-00C04FD915A9}'] property tagName: WideString dispid 65737; @@ -1645,11 +1526,9 @@ interface property attributes: IXMLElementCollection readonly dispid 65747; end; -// *********************************************************************// -// Interface: IXMLAttribute -// Flags: (4432) Hidden Dual OleAutomation Dispatchable -// GUID: {D4D4A0FC-3B73-11D1-B2B4-00C04FB92596} -// *********************************************************************// + + + IXMLAttribute = interface(IDispatch) ['{D4D4A0FC-3B73-11D1-B2B4-00C04FB92596}'] function Get_name: WideString; safecall; @@ -1658,49 +1537,40 @@ interface property value: WideString read Get_value; end; -// *********************************************************************// -// DispIntf: IXMLAttributeDisp -// Flags: (4432) Hidden Dual OleAutomation Dispatchable -// GUID: {D4D4A0FC-3B73-11D1-B2B4-00C04FB92596} -// *********************************************************************// + + + IXMLAttributeDisp = dispinterface ['{D4D4A0FC-3B73-11D1-B2B4-00C04FB92596}'] property name: WideString readonly dispid 65937; property value: WideString readonly dispid 65938; end; -// *********************************************************************// -// Interface: IXMLError -// Flags: (16) Hidden -// GUID: {948C5AD3-C58D-11D0-9C0B-00C04FC99C8E} -// *********************************************************************// + + + IXMLError = interface(IUnknown) ['{948C5AD3-C58D-11D0-9C0B-00C04FC99C8E}'] function GetErrorInfo(var pErrorReturn: _xml_error): HResult; stdcall; end; -// *********************************************************************// -// The Class CoDOMDocument provides a Create and CreateRemote method to -// create instances of the default interface IXMLDOMDocument exposed by -// the CoClass DOMDocument. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoDOMDocument = class class function Create: IXMLDOMDocument; class function CreateRemote(const MachineName: string): IXMLDOMDocument; end; -// *********************************************************************// -// OLE Server Proxy class declaration -// Server Object : TDOMDocument -// Help String : W3C-DOM XML Document -// Default Interface: IXMLDOMDocument -// Def. Intf. DISP?: No -// Event Interface: XMLDOMDocumentEvents -// TypeFlags : (2) CanCreate -// *********************************************************************// + + + + + + {$IFDEF LIVE_SERVER_AT_DESIGN_TIME} TDOMDocumentProperties= class; {$ENDIF} @@ -1779,12 +1649,11 @@ TDOMDocument = class(TOleServer) end; {$IFDEF LIVE_SERVER_AT_DESIGN_TIME} -// *********************************************************************// -// OLE Server Properties Proxy Class -// Server Object : TDOMDocument -// (This object is used by the IDE's Property Inspector to allow editing -// of the properties of this server) -// *********************************************************************// + + + + + TDOMDocumentProperties = class(TPersistent) private FServer: TDOMDocument; @@ -1820,28 +1689,22 @@ TDOMDocumentProperties = class(TPersistent) {$ENDIF} -// *********************************************************************// -// The Class CoDOMFreeThreadedDocument provides a Create and CreateRemote method to -// create instances of the default interface IXMLDOMDocument exposed by -// the CoClass DOMFreeThreadedDocument. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + CoDOMFreeThreadedDocument = class class function Create: IXMLDOMDocument; class function CreateRemote(const MachineName: string): IXMLDOMDocument; end; -// *********************************************************************// -// OLE Server Proxy class declaration -// Server Object : TDOMFreeThreadedDocument -// Help String : W3C-DOM XML Document (Apartment) -// Default Interface: IXMLDOMDocument -// Def. Intf. DISP?: No -// Event Interface: XMLDOMDocumentEvents -// TypeFlags : (2) CanCreate -// *********************************************************************// + + + + + + {$IFDEF LIVE_SERVER_AT_DESIGN_TIME} TDOMFreeThreadedDocumentProperties= class; {$ENDIF} @@ -1920,12 +1783,11 @@ TDOMFreeThreadedDocument = class(TOleServer) end; {$IFDEF LIVE_SERVER_AT_DESIGN_TIME} -// *********************************************************************// -// OLE Server Properties Proxy Class -// Server Object : TDOMFreeThreadedDocument -// (This object is used by the IDE's Property Inspector to allow editing -// of the properties of this server) -// *********************************************************************// + + + + + TDOMFreeThreadedDocumentProperties = class(TPersistent) private FServer: TDOMFreeThreadedDocument; @@ -1961,28 +1823,22 @@ TDOMFreeThreadedDocumentProperties = class(TPersistent) {$ENDIF} -// *********************************************************************// -// The Class CoXMLHTTPRequest provides a Create and CreateRemote method to -// create instances of the default interface IXMLHttpRequest exposed by -// the CoClass XMLHTTPRequest. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + CoXMLHTTPRequest = class class function Create: IXMLHttpRequest; class function CreateRemote(const MachineName: string): IXMLHttpRequest; end; -// *********************************************************************// -// OLE Server Proxy class declaration -// Server Object : TXMLHTTPRequest -// Help String : XML HTTP Request class. -// Default Interface: IXMLHttpRequest -// Def. Intf. DISP?: No -// Event Interface: -// TypeFlags : (2) CanCreate -// *********************************************************************// + + + + + + {$IFDEF LIVE_SERVER_AT_DESIGN_TIME} TXMLHTTPRequestProperties= class; {$ENDIF} @@ -2038,12 +1894,11 @@ TXMLHTTPRequest = class(TOleServer) end; {$IFDEF LIVE_SERVER_AT_DESIGN_TIME} -// *********************************************************************// -// OLE Server Properties Proxy Class -// Server Object : TXMLHTTPRequest -// (This object is used by the IDE's Property Inspector to allow editing -// of the properties of this server) -// *********************************************************************// + + + + + TXMLHTTPRequestProperties = class(TPersistent) private FServer: TXMLHTTPRequest; @@ -2065,28 +1920,22 @@ TXMLHTTPRequestProperties = class(TPersistent) {$ENDIF} -// *********************************************************************// -// The Class CoXMLDSOControl provides a Create and CreateRemote method to -// create instances of the default interface IXMLDSOControl exposed by -// the CoClass XMLDSOControl. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + CoXMLDSOControl = class class function Create: IXMLDSOControl; class function CreateRemote(const MachineName: string): IXMLDSOControl; end; -// *********************************************************************// -// OLE Server Proxy class declaration -// Server Object : TXMLDSOControl -// Help String : XML Data Source Object -// Default Interface: IXMLDSOControl -// Def. Intf. DISP?: No -// Event Interface: -// TypeFlags : (2) CanCreate -// *********************************************************************// + + + + + + {$IFDEF LIVE_SERVER_AT_DESIGN_TIME} TXMLDSOControlProperties= class; {$ENDIF} @@ -2122,12 +1971,11 @@ TXMLDSOControl = class(TOleServer) end; {$IFDEF LIVE_SERVER_AT_DESIGN_TIME} -// *********************************************************************// -// OLE Server Properties Proxy Class -// Server Object : TXMLDSOControl -// (This object is used by the IDE's Property Inspector to allow editing -// of the properties of this server) -// *********************************************************************// + + + + + TXMLDSOControlProperties = class(TPersistent) private FServer: TXMLDSOControl; @@ -2148,28 +1996,22 @@ TXMLDSOControlProperties = class(TPersistent) {$ENDIF} -// *********************************************************************// -// The Class CoXMLDocument provides a Create and CreateRemote method to -// create instances of the default interface IXMLDocument2 exposed by -// the CoClass XMLDocument. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + CoXMLDocument = class class function Create: IXMLDocument2; class function CreateRemote(const MachineName: string): IXMLDocument2; end; -// *********************************************************************// -// OLE Server Proxy class declaration -// Server Object : TXMLDocument -// Help String : XMLDocument extends IXML Document. It is obsolete. You should use DOMDocument. This object should not be confused with the XMLDocument property on the XML data island. -// Default Interface: IXMLDocument2 -// Def. Intf. DISP?: No -// Event Interface: -// TypeFlags : (2) CanCreate -// *********************************************************************// + + + + + + {$IFDEF LIVE_SERVER_AT_DESIGN_TIME} TXMLDocumentProperties= class; {$ENDIF} @@ -2208,12 +2050,11 @@ TXMLDocument = class(TOleServer) end; {$IFDEF LIVE_SERVER_AT_DESIGN_TIME} -// *********************************************************************// -// OLE Server Properties Proxy Class -// Server Object : TXMLDocument -// (This object is used by the IDE's Property Inspector to allow editing -// of the properties of this server) -// *********************************************************************// + + + + + TXMLDocumentProperties = class(TPersistent) private FServer: TXMLDocument; @@ -2237,9 +2078,6 @@ TXMLDocumentProperties = class(TPersistent) {$ENDIF} -// XML-components should not be regisgtered in Delphi by this unit. -// procedure Register; - implementation uses ComObj; @@ -2328,7 +2166,7 @@ function TDOMDocument.GetServerProperties: TDOMDocumentProperties; procedure TDOMDocument.InvokeEvent(DispID: TDispID; var Params: TVariantArray); begin case DispID of - -1: Exit; // DISPID_UNKNOWN + -1: Exit; 198: if Assigned(FOnondataavailable) then FOnondataavailable(Self); -609: if Assigned(FOnonreadystatechange) then @@ -2690,7 +2528,7 @@ function TDOMFreeThreadedDocument.GetServerProperties: TDOMFreeThreadedDocumentP procedure TDOMFreeThreadedDocument.InvokeEvent(DispID: TDispID; var Params: TVariantArray); begin case DispID of - -1: Exit; // DISPID_UNKNOWN + -1: Exit; 198: if Assigned(FOnondataavailable) then FOnondataavailable(Self); -609: if Assigned(FOnonreadystatechange) then diff --git a/Source/Common/Queue/BoldAbstractDequeuer.pas b/Source/Common/Queue/BoldAbstractDequeuer.pas index bd93fc2..fa3b9f3 100644 --- a/Source/Common/Queue/BoldAbstractDequeuer.pas +++ b/Source/Common/Queue/BoldAbstractDequeuer.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldAbstractDequeuer; interface @@ -12,22 +15,40 @@ TBoldAbstractDequeuer = class; { TBoldAbstractDequeuer } TBoldAbstractDequeuer = class(TBoldSubscribableComponent) - private - fQueue: TBoldThreadSafeStringQueue; protected - procedure HandleMessage(aMsg: String); virtual; abstract; procedure DequeueMessages(Sender: TObject); public destructor Destroy; override; procedure QueueNotEmpty; - procedure DequeueAll; + procedure DequeueAll; virtual; abstract; + end; + + TBoldObjectDequeuer = class(TBoldAbstractDequeuer) + private + fQueue: TBoldThreadSafeObjectQueue; + protected + procedure HandleMessage(const AOSSMessage: TObject); virtual; abstract; + public + procedure DequeueAll; override; + property Queue: TBoldThreadSafeObjectQueue read fQueue write fQueue; + end; + + TBoldStringDequeuer = class(TBoldAbstractDequeuer) + private + fQueue: TBoldThreadSafeStringQueue; + protected + procedure HandleMessage(const aMsg: String); virtual; abstract; + public + procedure DequeueAll; override; property Queue: TBoldThreadSafeStringQueue read fQueue write fQueue; end; implementation uses - BoldQueue; + Classes, + BoldQueue, + BoldRev; { TBoldDequeuerHandle } @@ -47,19 +68,26 @@ procedure TBoldAbstractDequeuer.QueueNotEmpty; TBoldQueueable.AddToPreDisplayQueue(DequeueMessages, nil, Self); end; -procedure TBoldAbstractDequeuer.DequeueAll; -var - aMsg: String; +{ TBoldObjectDequeuer } + +procedure TBoldObjectDequeuer.DequeueAll; begin - if Assigned(Queue) then - begin - aMsg := Queue.Dequeue; - while aMsg <> '' do - begin - HandleMessage(aMsg); - aMsg := Queue.Dequeue; - end; - end; + if not Assigned(Queue) or Queue.Empty then + exit; + while not Queue.Empty do + HandleMessage(Queue.Dequeue); end; +{ TBoldStringDequeuer } + +procedure TBoldStringDequeuer.DequeueAll; +begin + if not Assigned(Queue) or Queue.Empty then + exit; + while not Queue.Empty do + HandleMessage(Queue.Dequeue); +end; + + +initialization end. diff --git a/Source/Common/Queue/BoldEventQueue.pas b/Source/Common/Queue/BoldEventQueue.pas index fed5d1e..8e4d774 100644 --- a/Source/Common/Queue/BoldEventQueue.pas +++ b/Source/Common/Queue/BoldEventQueue.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldEventQueue; interface @@ -24,20 +27,22 @@ TBoldEventQueueItem = class(TBoldMemoryManagedObject) property Event: TNotifyEvent read fEvent; property Sender: Tobject read fSender; property Receiver: TObject read fReceiver; - procedure SendEvent; + procedure SendEvent; {$IFDEF BOLD_INLINE} inline; {$ENDIF} end; { TBoldEventQueue } TBoldEventQueue = class(TBoldMemoryManagedObject) private fItemIndex: TBoldEventQueueItemReceiverIndex; + function GetCount: integer; {$IFDEF BOLD_INLINE} inline; {$ENDIF} public constructor Create; destructor Destroy; override; procedure Add(Event: TNotifyEvent; Sender: TObject; Receiver: TObject); - procedure DequeueOne; + procedure DequeueOne; {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure DequeueAll; procedure RemoveAllForReceiver(Receiver: TObject); + property Count: integer read GetCount; end; { TBoldEventQueueItemReceiverIndex } @@ -79,26 +84,26 @@ constructor TBoldEventQueue.Create; fItemIndex := TBoldEventQueueItemReceiverIndex.Create; end; -procedure TBoldEventQueue.DequeueAll; -var - InternalCount, - i: Integer; +function TBoldEventQueue.GetCount: integer; begin - InternalCount := fItemIndex.Count; - for i := 0 to InternalCount - 1 do - DequeueOne; + result := fItemIndex.Count; end; procedure TBoldEventQueue.DequeueOne; var item: TBoldEventQueueItem; begin - item := TBoldEventQueueItem(fItemIndex.Any); - fItemIndex.Remove(item); + item := TBoldEventQueueItem(fItemIndex.GetAndRemoveAny); item.SendEvent; Item.Free; end; +procedure TBoldEventQueue.DequeueAll; +begin + while Count > 0 do + DequeueOne; +end; + destructor TBoldEventQueue.Destroy; begin FreeAndNil(fItemIndex); @@ -112,6 +117,8 @@ procedure TBoldEventQueue.RemoveAllForReceiver(Receiver: TObject); MatchingItems: TList; g: IBoldGuard; begin + if fItemIndex.Count = 0 then + exit; g := TBoldGuard.Create(MatchingItems); MatchingItems := TList.Create; fItemIndex.FindAllByObject(Receiver, MatchingItems); @@ -130,4 +137,6 @@ function TBoldEventQueueItemReceiverIndex.ItemASKeyObject(Item: TObject): TObjec result := TBoldEventQueueItem(Item).Receiver; end; +initialization + end. diff --git a/Source/Common/Queue/BoldQueue.pas b/Source/Common/Queue/BoldQueue.pas index b90d04c..f478fd2 100644 --- a/Source/Common/Queue/BoldQueue.pas +++ b/Source/Common/Queue/BoldQueue.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldQueue; interface @@ -11,8 +14,11 @@ interface { Queueable } befIsInDisplayList = BoldElementFlag0; befStronglyDependedOfPrioritized = BoldElementFlag1; +{$IFDEF BoldQueue_Optimization} + befToBeRemovedFromDisplayList = BoldElementFlag2; +{$ENDIF} { Follower } - befFollowerSelected = BoldElementFlag2; + befFollowerSelected = BoldElementFlag3; type { forward declarations } @@ -30,13 +36,17 @@ TBoldQueueable = class(TBoldFlaggedObject) procedure AddToApplyList; procedure RemoveFromApplyList; procedure AddToDisplayList; virtual; - procedure RemoveFromDisplayList; + procedure RemoveFromDisplayList(ADestroying: boolean); function MostPrioritizedQueuable: TBoldQueueable; function MostPrioritizedQueuableOrSelf: TBoldQueueable; function AfterInPriority(Queueable: TBoldQueueable): Boolean; procedure Display; virtual; abstract; function StronglyPrioritizedSibbling(Queueable: TBoldQueueable): Boolean; +{$IFDEF BoldQueue_Optimization} + property ToBeRemovedFromDisplayList: Boolean index befToBeRemovedFromDisplayList read GetElementFlag write SetElementFlag; +{$ENDIF} class function DisplayOne: Boolean; + function GetDebugInfo: string; override; public constructor Create(aMatchObject: TObject); destructor Destroy; override; @@ -45,8 +55,11 @@ TBoldQueueable = class(TBoldFlaggedObject) class procedure ApplyAllMatching(anObject: TObject); class procedure DiscardChangeAll; class procedure DiscardChangeAllMatching(anObject: TObject); - class procedure AddToPreDisplayQueue(Event: TNotifyEvent; Sender: TObject; Receiver: TObject); - class procedure RemoveFromPreDisplayQueue(Receiver: TObject); + class procedure AddToPreDisplayQueue(Event: TNotifyEvent; Sender: TObject; Receiver: TObject); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + class procedure AddToPostDisplayQueue(Event: TNotifyEvent; Sender: TObject; Receiver: TObject); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + class procedure RemoveFromPreDisplayQueue(Receiver: TObject); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + class function IsDisplayQueueEmpty: Boolean; + class function IsDisplaying: Boolean; procedure Apply; virtual; abstract; procedure DiscardChange; virtual; abstract; property MatchObject: TObject read fMatchObject; @@ -61,36 +74,53 @@ TBoldQueue = class(TBoldMemoryManagedObject) fIsDisplaying: Boolean; fDisplayMode: TBoldQueueDisplayMode; fPreDisplayQueue: TBoldEventQueue; + fPostDisplayQueue: TBoldEventQueue; fDisplayList: TList; fApplyList: TList; +{$IFDEF BoldQueue_Optimization} + fDisplayListIndex: Integer; +{$ENDIF} + function GetApplyCount: integer; + function GetDisplayCount: integer; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetPostDisplayCount: integer; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetPreDisplayCount: integer; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetEmpty: boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} protected function DisplayOne: Boolean; function DisplayAll: Boolean; procedure AddToApplyList(Queueable: TBoldQueueable); procedure RemoveFromApplyList(Queueable: TBoldQueueable); procedure AddToDisplayList(Queueable: TBoldQueueable); - procedure RemoveFromDisplayList(Queueable: TBoldQueueable); + procedure RemoveFromDisplayList(Queueable: TBoldQueueable; ADestroying: boolean); procedure EnsureDequeing; virtual; public constructor Create; virtual; destructor Destroy; override; procedure AddEventToPredisplayQueue(Event: TNotifyEvent; Sender: TObject; Receiver: TObject); - procedure RemoveFromPreDisplayQueue(Receiver: TObject); + procedure AddEventToPostDisplayQueue(Event: TNotifyEvent; Sender: TObject; Receiver: TObject); + procedure RemoveFromPreDisplayQueue(Receiver: TObject); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure RemoveFromPostDisplayQueue(Receiver: TObject); procedure PerformPreDisplayQueue; + procedure PerformPostDisplayQueue; procedure DeActivateDisplayQueue; virtual; abstract; procedure ActivateDisplayQueue; virtual; abstract; property DisplayMode: TBoldQueueDisplayMode read fDisplayMode write fDisplayMode; + property DisplayCount: integer read GetDisplayCount; + property ApplyCount: integer read GetApplyCount; + property PreDisplayCount: integer read GetPreDisplayCount; + property PostDisplayCount: integer read GetPostDisplayCount; + property Empty: boolean read GetEmpty; end; - function BoldQueueFinalized: Boolean; - function BoldInstalledQueue: TBoldQueue; + function BoldQueueFinalized: Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function BoldInstalledQueue: TBoldQueue; {$IFDEF BOLD_INLINE} inline; {$ENDIF} implementation uses SysUtils, BoldUtils, - Forms, // Application object + Forms, BoldEnvironment, BoldGuard; @@ -101,10 +131,7 @@ function BoldQueueFinalized: Boolean; function BoldInstalledQueue: TBoldQueue; begin - if not BoldEnvironmentsFinalized then - Result := BoldEffectiveEnvironment.Queue - else - Result := nil; + result := BoldEnvironment.BoldInstalledQueue; end; { TBoldQuable } @@ -118,11 +145,22 @@ constructor TBoldQueueable.Create(aMatchObject: TObject); destructor TBoldQueueable.Destroy; begin RemoveFromApplyList; - if IsInDisplayList then - RemoveFromDisplayList; + RemoveFromDisplayList(true); +{$IFDEF BoldQueue_Optimization} + Assert(not (IsInDisplayList or ToBeRemovedFromDisplayList)); +{$ELSE} + Assert(not IsInDisplayList); +{$ENDIF} inherited Destroy; end; +function TBoldQueueable.GetDebugInfo: string; +begin + result := Format('%s', [className]); + if Assigned(MatchObject) then + result := result + ' (' + MatchObject.ClassName + ')'; +end; + procedure TBoldQueueable.AddToApplyList; begin if not (BoldQueueFinalized) then @@ -140,16 +178,27 @@ procedure TBoldQueueable.AddToDisplayList; if not BoldQueueFinalized then begin Assert(not IsInDisplayList); - BoldInstalledQueue.AddToDisplayList(self); +{$IFDEF BoldQueue_Optimization} + if ToBeRemovedFromDisplayList then + ToBeRemovedFromDisplayList := false + else +{$ENDIF} + BoldInstalledQueue.AddToDisplayList(self); SetElementflag(befIsInDisplayList, True); end; end; -procedure TBoldQueueable.RemoveFromDisplayList; +procedure TBoldQueueable.RemoveFromDisplayList(ADestroying: boolean); begin - if not (BoldQueueFinalized) then - BoldInstalledQueue.RemoveFromDisplayList(self); - SetElementflag(befIsInDisplayList, False); +{$IFDEF BoldQueue_Optimization} + if not (BoldQueueFinalized) and (IsInDisplayList or ToBeRemovedFromDisplayList) then +{$ELSE} + if not BoldQueueFinalized and IsInDisplayList then +{$ENDIF} + begin + BoldInstalledQueue.RemoveFromDisplayList(self, ADestroying); + SetElementflag(befIsInDisplayList, False); + end; end; function TBoldQueueable.MostPrioritizedQueuableOrSelf: TBoldQueueable; @@ -168,13 +217,17 @@ function TBoldQueueable.MostPrioritizedQueuable: TBoldQueueable; begin Result := PrioritizedQueuable.MostPrioritizedQueuableOrSelf; if not Assigned(Result) and StronglyDependedOfPrioritized then - for i := 0 to BoldInstalledQueue.fDisplayList.Count - 1 do + with BoldInstalledQueue do + for i := fDisplayList.Count - 1 downto 0 do begin - Queueable := BoldInstalledQueue.fDisplayList[i]; + Queueable := fDisplayList[i]; if assigned(Queueable) and +{$IFDEF BoldQueue_Optimization} + Queueable.IsInDisplayList and +{$ENDIF} Queueable.AfterInPriority(PrioritizedQueuable) and not StronglyPrioritizedSibbling(Queueable) and - not Queueable.AfterInPriority(self) then // will also eliminate self + not Queueable.AfterInPriority(self) then begin Result := Queueable.MostPrioritizedQueuableOrSelf; break; @@ -187,50 +240,59 @@ function TBoldQueueable.MostPrioritizedQueuable: TBoldQueueable; class function TBoldQueueable.DisplayOne: Boolean; begin - if BoldInstalledQueue <> nil then - Result := BoldInstalledQueue.DisplayOne - else - Result := False; + Result := (BoldInstalledQueue <> nil) and BoldInstalledQueue.DisplayOne; end; class function TBoldQueueable.DisplayAll: Boolean; begin - Result := (BoldInstalledQueue <> nil) and (BoldInstalledQueue.fDisplayList.Count <> 0); + Result := DisplayOne; if Result then while DisplayOne do {nothing}; end; +class function TBoldQueueable.IsDisplaying: Boolean; +begin + Result := (BoldInstalledQueue <> nil) and BoldInstalledQueue.fIsDisplaying; +end; + +class function TBoldQueueable.IsDisplayQueueEmpty: Boolean; +begin + Result := (BoldInstalledQueue = nil) or (BoldInstalledQueue.fDisplayList.Count = 0); +end; + class procedure TBoldQueueable.ApplyAll; var Queueable: TBoldQueueable; tempList: TList; i: integer; g: IBoldGuard; + vApplyList: TList; begin g := TBoldGuard.Create(TempList); if BoldInstalledQueue <> nil then begin tempList := TList.Create; - while BoldInstalledQueue.fApplyList.Count > 0 do + vApplyList := BoldInstalledQueue.fApplyList; + while vApplyList.Count > 0 do begin - Queueable := BoldInstalledQueue.fApplyList.Last; + Queueable := vApplyList.Last; if Assigned(Queueable) then begin - Queueable.Apply; // This will remove object from list - if (BoldInstalledQueue.fApplyList.Count > 0) and (Queueable = BoldInstalledQueue.fApplyList.LAst) then + Queueable.Apply; + if (vApplyList.Count > 0) and (Queueable = vApplyList.Last) then begin // for some reason the apply failed, // remove the queueable from the applylist and put it back when it is empty... TempList.Add(Queueable); - BoldInstalledQueue.fApplyList.Count := BoldInstalledQueue.fApplyList.Count - 1; + vApplyList.Count := vApplyList.Count - 1; end; end else - BoldInstalledQueue.fApplyList.Count := BoldInstalledQueue.fApplyList.Count - 1; //Skip nil items + vApplyList.Count := vApplyList.Count - 1; end; for i := 0 to TempList.Count - 1 do - BoldInstalledQueue.fApplyList.Add(TempList[i]); + vApplyList.Add(TempList[i]); end; end; @@ -240,11 +302,12 @@ class procedure TBoldQueueable.ApplyAllMatching(anObject: TObject); I: Integer; begin if BoldInstalledQueue <> nil then - for I := BoldInstalledQueue.fApplyList.Count - 1 downto 0 do + with BoldInstalledQueue do + for I := fApplyList.Count - 1 downto 0 do begin - Queueable := TBoldQueueable(BoldInstalledQueue.fApplyList[I]); + Queueable := TBoldQueueable(fApplyList[I]); if Assigned(Queueable) and (Queueable.MatchObject = anObject) then - Queueable.Apply; // This will remove from list + Queueable.Apply; end; end; @@ -254,11 +317,12 @@ class procedure TBoldQueueable.DiscardChangeAll; I: Integer; begin if BoldInstalledQueue <> nil then - for I := BoldInstalledQueue.fApplyList.Count - 1 downto 0 do + with BoldInstalledQueue do + for I := fApplyList.Count - 1 downto 0 do begin - Queueable := TBoldQueueable(BoldInstalledQueue.fApplyList[I]); + Queueable := TBoldQueueable(fApplyList[I]); if Assigned(Queueable) then - Queueable.DiscardChange; // This will remove from list + Queueable.DiscardChange; end; end; @@ -268,14 +332,22 @@ class procedure TBoldQueueable.DiscardChangeAllMatching(anObject: TObject); I: Integer; begin if BoldInstalledQueue <> nil then - for I := BoldInstalledQueue.fApplyList.Count - 1 downto 0 do + with BoldInstalledQueue do + for I := fApplyList.Count - 1 downto 0 do begin - Queueable := TBoldQueueable(BoldInstalledQueue.fApplyList[I]); + Queueable := TBoldQueueable(fApplyList[I]); if Assigned(Queueable) and (Queueable.MatchObject = anObject) then - Queueable.DiscardChange; // This will remove from list + Queueable.DiscardChange; end; end; +class procedure TBoldQueueable.AddToPostDisplayQueue(Event: TNotifyEvent; + Sender, Receiver: TObject); +begin + if not BoldQueueFinalized then + BoldInstalledQueue.AddEventToPostDisplayQueue(Event, Sender, Receiver); +end; + class procedure TBoldQueueable.AddToPreDisplayQueue(Event: TNotifyEvent; Sender, Receiver: TObject); begin @@ -291,6 +363,13 @@ class procedure TBoldQueueable.RemoveFromPreDisplayQueue(Receiver: TObject); { TBoldQueue } +procedure TBoldQueue.AddEventToPostDisplayQueue(Event: TNotifyEvent; Sender, + Receiver: TObject); +begin + fPostDisplayQueue.Add(Event, Sender, Receiver); + EnsureDequeing; +end; + procedure TBoldQueue.AddEventToPredisplayQueue(Event: TNotifyEvent; Sender, Receiver: TObject); begin @@ -313,12 +392,10 @@ constructor TBoldQueue.Create; begin inherited; fPreDisplayQueue := TBoldEventQueue.Create; + fPostDisplayQueue := TBoldEventQueue.Create; fDisplayList := TList.Create; fApplyList := TList.Create; - if BoldRunningAsDesignTimePackage then - DisplayMode := dmDisplayAll - else - DisplayMode := dmDisplayOne; + DisplayMode := dmDisplayAll; ActivateDisplayQueue; end; @@ -327,6 +404,7 @@ destructor TBoldQueue.Destroy; FreeAndNil(fDisplayList); FreeAndNil(fApplyList); FreeAndNil(fPreDisplayQueue); + FreeAndNil(fPostDisplayQueue); inherited; end; @@ -336,39 +414,87 @@ function TBoldQueue.DisplayAll: Boolean; end; function TBoldQueue.DisplayOne: Boolean; +{$IFDEF BoldQueue_Optimization} +var + Queueable, vPrioritizedQueuable: TBoldQueueable; +begin + result := not fIsDisplaying and (fDisplayList.Count > 0); + if result then + begin + Queueable := nil; + fIsDisplaying := true; + try + while (fDisplayListIndex < fDisplayList.Count) do + begin + Queueable := TBoldQueueable(fDisplayList[fDisplayListIndex]); + + if not Assigned(Queueable) then + inc(fDisplayListIndex) + else + if not Queueable.IsInDisplayList then + begin + fDisplayList[fDisplayListIndex] := nil; + Queueable.ToBeRemovedFromDisplayList := false; + inc(fDisplayListIndex); + end + else + break; + end; + if fDisplayListIndex < fDisplayList.Count then + begin + vPrioritizedQueuable := Queueable.MostPrioritizedQueuableOrSelf; + if Queueable = vPrioritizedQueuable then + begin + Queueable.Display; + if Queueable.ToBeRemovedFromDisplayList and (fDisplayList[fDisplayListIndex] = Queueable) then + begin + fDisplayList[fDisplayListIndex] := nil; + Queueable.ToBeRemovedFromDisplayList := false; + end; + end + else + vPrioritizedQueuable.Display; + end; + finally + fIsDisplaying := false; + if fDisplayListIndex >= fDisplayList.Count then + begin + fDisplayListIndex := 0; + fDisplayList.Count := 0; + end; + end; + end; +end; +{$ELSE} var Index: Integer; ExchangeWith, Queueable: TBoldQueueable; begin - if fIsDisplaying then + if fIsDisplaying or (fDisplayList.Count = 0) then result := false else begin fIsDisplaying := true; try Queueable := nil; - //Remove Empty slots from the end of the queue. while (fDisplayList.Count>0) and (fDisplayList.Last=nil) do fDisplayList.Count := fDisplayList.Count - 1; Result := fDisplayList.Count>0; if Result then begin try - //Check if there is a queueable that must be displayed before. ExchangeWith := TBoldQueueable(fDisplayList.Last).MostPrioritizedQueuable; if Assigned(ExchangeWith) then begin - //Exchange place Index := fDisplayList.IndexOf(ExchangeWith); if Index <> -1 then fDisplayList.Exchange(Index, fDisplayList.Count - 1); end; - //Display Last queueable in list. Queueable := TBoldQueueable(fDisplayList.Last); Queueable.Display; except - Application.HandleException(Queueable); + raise; // patch this used to directly call Application.HandleException(Queueable); end; end; finally @@ -376,6 +502,7 @@ function TBoldQueue.DisplayOne: Boolean; end; end; end; +{$ENDIF} function TBoldQueueable.AfterInPriority(Queueable: TBoldQueueable): Boolean; begin @@ -399,6 +526,36 @@ procedure TBoldQueue.EnsureDequeing; end; +function TBoldQueue.GetApplyCount: integer; +begin + result := fApplyList.Count; +end; + +function TBoldQueue.GetDisplayCount: integer; +begin + result := fDisplayList.Count; +end; + +function TBoldQueue.GetPreDisplayCount: integer; +begin + result := fPreDisplayQueue.Count; +end; + +function TBoldQueue.GetPostDisplayCount: integer; +begin + result := fPostDisplayQueue.Count; +end; + +function TBoldQueue.GetEmpty: boolean; +begin + result := (DisplayCount = 0) and (ApplyCount = 0) and (PreDisplayCount = 0) and (PostDisplayCount = 0); +end; + +procedure TBoldQueue.PerformPostDisplayQueue; +begin + fPostDisplayQueue.DequeueAll; +end; + procedure TBoldQueue.PerformPreDisplayQueue; begin fPreDisplayQueue.DequeueAll; @@ -408,11 +565,9 @@ procedure TBoldQueue.RemoveFromApplyList(Queueable: TBoldQueueable); var index: integer; begin - //Implemented own IndexOf because it is more effective to search the list from the end in this case. Index := fApplyList.Count - 1; - while (Index >= 0) and (fApplyList.List[Index] <> Queueable) do // marco + while (Index >= 0) and (fApplyList.List[Index] <> Queueable) do Dec(Index); - //Insert nil element in list or decrement count if it's the last object if Index > -1 then if Index = fApplyList.Count - 1 then fApplyList.Count := fApplyList.Count - 1 @@ -420,25 +575,49 @@ procedure TBoldQueue.RemoveFromApplyList(Queueable: TBoldQueueable); fApplyList[Index] := nil; end; -procedure TBoldQueue.RemoveFromDisplayList(Queueable: TBoldQueueable); +procedure TBoldQueue.RemoveFromDisplayList(Queueable: TBoldQueueable; ADestroying: boolean); var index: integer; begin - //Implemented own IndexOf because it is more effective to search the list from the end in this case. - Index := fdisplayList.Count - 1; - while (Index >=0 ) and (fdisplayList.List[Index] <> Queueable) do // marco removed ^ (also above) +// Log('R:'+Queueable.ClassName); +{$IFDEF BoldQueue_Optimization} + if (fDisplayList.Last = Queueable) then + begin + Queueable.ToBeRemovedFromDisplayList := false; + fDisplayList.Delete(fDisplayList.Count-1); + exit; + end; + if not ADestroying then + begin + Queueable.ToBeRemovedFromDisplayList := true; + exit; + end; +{$ENDIF} + Index := fDisplayList.Count - 1; + while (Index >=0 ) and (fDisplayList.List[Index] <> Queueable) do Dec(Index); - //Insert nil element in list or decrement count if it's the last object if Index > -1 then + begin +{$IFDEF BoldQueue_Optimization} + Queueable.ToBeRemovedFromDisplayList := false; +{$ENDIF} if Index = fdisplayList.Count - 1 then - fdisplayList.Count := fdisplayList.Count - 1 + fDisplayList.Count := fDisplayList.Count - 1 else - fdisplayList[Index] := nil; + fDisplayList[Index] := nil; + end; +end; + +procedure TBoldQueue.RemoveFromPostDisplayQueue(Receiver: TObject); +begin + fPostDisplayQueue.RemoveAllForReceiver(Receiver); end; procedure TBoldQueue.RemoveFromPreDisplayQueue(Receiver: TObject); begin - fPreDisplayQueue.RemoveAllForReceiver(Receiver); + fPreDisplayQueue.RemoveAllForReceiver(Receiver); end; +initialization + end. diff --git a/Source/Common/Rose2000/BoldRose2000Support.pas b/Source/Common/Rose2000/BoldRose2000Support.pas index 2638f26..e27a797 100644 --- a/Source/Common/Rose2000/BoldRose2000Support.pas +++ b/Source/Common/Rose2000/BoldRose2000Support.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldRose2000Support; interface @@ -70,27 +73,29 @@ implementation BoldLogHandler, BoldDefs, BoldUtils, - BoldDefaultTaggedValues, - BoldCommonConst; + BoldDefaultTaggedValues; function StringToBoolean(inString: String): Boolean; begin Result := False; - if (UpperCase(inString)= 'Y') or (UpperCase(inString) = 'T') or (UpperCase(inString) = 'TRUE') then // do not localize + if (UpperCase(inString)= 'Y') or (UpperCase(inString) = 'T') or (UpperCase(inString) = 'TRUE') then Result := True; end; function BooleanToString(inValue: Boolean): String; begin if inValue then - Result := 'True' // do not localize + Result := 'True' else - Result := 'False'; // do not localize + Result := 'False'; end; class function TBoldRose2000Support.BooleanToString(Value: Boolean): string; begin - Result := BooleanToString(Value); + if Value then + Result := 'True' + else + Result := 'False'; end; class function TBoldRose2000Support.FindClassByName(RoseModel: IRoseModel; const Name: string): IRoseClass; @@ -104,7 +109,7 @@ class function TBoldRose2000Support.FindClassByName(RoseModel: IRoseModel; const begin Result := ClsCol.GetAt(1); if ClsCol.Count > 1 then - raise EBoldImport.CreateFmt(sClassNameNotUnique, [Name]); + raise EBoldImport.CreateFmt('Found multiple classes with name %s, don''t know which one to use', [Name]); end; end; @@ -129,7 +134,7 @@ class function TBoldRose2000Support.GetApplication: IRoseApplication; class function TBoldRose2000Support.GetCalculatedAssociationName(RoseAssociation: IRoseAssociation; const PluralSuffix: string): string; begin - Result := Format('%s%s', // do not localize + Result := Format('%s%s', [GetEffectiveRoleName(RoseAssociation.Role1,PluralSuffix), GetEffectiveRoleName(RoseAssociation.Role2,PluralSuffix)]); end; @@ -145,9 +150,9 @@ class function TBoldRose2000Support.GetCalculatedRoleName(RoseRole: IRoseRole; c else otherRole := RoseRole.Association.Role1; if assigned(RoseRole) and assigned(RoseRole.Class_) then - result := 'x_' + otherRole.Name + '_' + RoseRole.Class_.Name // do not localize + result := 'x_' + otherRole.Name + '_' + RoseRole.Class_.Name else - result := 'x_' + otherRole.Name + '_unknown'; // do not localize + result := 'x_' + otherRole.Name + '_unknown'; end else begin @@ -179,12 +184,12 @@ class function TBoldRose2000Support.GetEffectiveMultiplicity(RoseRole: IRoseRole Result := RoseRole.Cardinality; Trim(Result); if Result = '' then - Result := '0..1' // do not localize + Result := '0..1' else Result := StringReplace(Result, 'n', '*', [rfReplaceAll]); if Length(Result) < 2 then - Result := '0..' + Result; // do not localize + Result := '0..' + Result; end; class function TBoldRose2000Support.ParametersToSignature(Parameters: IRoseParameterCollection): string; @@ -202,7 +207,7 @@ class function TBoldRose2000Support.ParametersToSignature(Parameters: IRoseParam else Result := Result + '; '; Parameter := Parameters.GetAt(P) as IRoseParameter; - Result := Result + Format('%s: %s',[Parameter.Name, Parameter.Type_]); // do not localize + Result := Result + Format('%s: %s',[Parameter.Name, Parameter.Type_]); end; end; @@ -236,7 +241,7 @@ function TBoldRose2000Properties.GetBooleanString(RoseItem: IRoseItem; const Nam Result := DefaultValue else begin - if AnsiCompareText(Value, 'True') = 0 then // do not localize + if AnsiCompareText(Value, 'True') = 0 then Result := TV_TRUE else Result := TV_FALSE; @@ -254,7 +259,7 @@ function TBoldRose2000Properties.GetBoolean(RoseItem: IRoseItem; const Name: str if Value = '' then Result := DefaultValue else - Result := (AnsiCompareText(Value, 'True') = 0); // do not localize + Result := (AnsiCompareText(Value, 'True') = 0); end; function TBoldRose2000Properties.GetDefaultPropertyBoolean(RoseModel: IRoseModel; PropName: String): Boolean; @@ -265,7 +270,7 @@ function TBoldRose2000Properties.GetDefaultPropertyBoolean(RoseModel: IRoseModel Prop: IRoseProperty; begin DefaultProps := RoseModel.DefaultProperties; - PropCollection := DefaultProps.GetDefaultPropertySet(RoseModel.GetPropertyClassName, ToolName, DEFAULTVALUE); + PropCollection := DefaultProps.GetDefaultPropertySet(RoseModel.GetPropertyClassName, ToolName, 'default'); Index := PropCollection.FindFirst(PropName); if Index > 0 then @@ -286,7 +291,7 @@ function TBoldRose2000Properties.GetDefaultPropertyString(RoseModel: IRoseModel; Prop: IRoseProperty; begin DefaultProps := RoseModel.DefaultProperties; - PropCollection := DefaultProps.GetDefaultPropertySet(RoseModel.GetPropertyClassName, ToolName, DEFAULTVALUE); + PropCollection := DefaultProps.GetDefaultPropertySet(RoseModel.GetPropertyClassName, ToolName, 'default'); Index := PropCollection.FindFirst(PropName); if Index > 0 then @@ -305,14 +310,13 @@ procedure TBoldRose2000Properties.SetDefaultPropertyBoolean(RoseModel: IRoseMode Prop: IRoseProperty; begin DefaultProps := RoseModel.DefaultProperties; - PropCollection := DefaultProps.GetDefaultPropertySet(RoseModel.GetPropertyClassName, ToolName, DEFAULTVALUE); + PropCollection := DefaultProps.GetDefaultPropertySet(RoseModel.GetPropertyClassName, ToolName, 'default'); Index := PropCollection.FindFirst(PropName); if Index > 0 then Prop := PropCollection.GetAt(Index) else Exit; - //ShowMessage('Fel'); Prop.Value := BooleanToString(PropValue); end; @@ -325,7 +329,7 @@ procedure TBoldRose2000Properties.SetDefaultPropertyString(RoseModel: IRoseModel Prop: IRoseProperty; begin DefaultProps := RoseModel.DefaultProperties; - PropCollection := DefaultProps.GetDefaultPropertySet(RoseModel.GetPropertyClassName, ToolName, DEFAULTVALUE); + PropCollection := DefaultProps.GetDefaultPropertySet(RoseModel.GetPropertyClassName, ToolName, 'default'); Index := PropCollection.FindFirst(PropName); if Index > 0 then @@ -374,7 +378,7 @@ procedure TBoldRose2000Properties.SetBooleanString(RoseItem: IRoseItem; const Na begin if GetBooleanString(RoseItem, Name, DefaultValue) <> Value then begin - BoldLog.LogFmt(sSettingValue, [LoggString, Name, Value]); + BoldLog.LogFmt('Setting %s.%s to %s', [LoggString, Name, Value]); RoseItem.OverrideProperty(ToolName, Name, Value); end; end; @@ -387,7 +391,7 @@ procedure TBoldRose2000Properties.SetBoolean(RoseItem: IRoseItem; begin if GetBoolean(RoseItem, Name, DefaultValue) <> Value then begin - BoldLog.LogFmt(sSettingValue, [LoggString, Name, TBoldRose2000Support.BooleanToString(Value)]); + BoldLog.LogFmt('Setting %s.%s to %s', [LoggString, Name, TBoldRose2000Support.BooleanToString(Value)]); RoseItem.OverrideProperty(ToolName, Name, TBoldRose2000Support.BooleanToString(Value)); end; end; @@ -400,7 +404,7 @@ procedure TBoldRose2000Properties.SetInteger(RoseItem: IRoseItem; begin if GetInteger(RoseItem, Name, DefaultValue) <> Value then begin - BoldLog.LogFmt(sSettingValue, [LoggString, Name, IntToStr(Value)]); + BoldLog.LogFmt('Setting %s.%s to %s', [LoggString, Name, IntToStr(Value)]); RoseItem.OverrideProperty(ToolName, Name, IntToStr(Value)); end end; @@ -410,7 +414,7 @@ procedure TBoldRose2000Properties.SetString(RoseItem: IRoseItem; const Name, Def begin if AnsiCompareText(GetString(RoseItem, Name, DefaultValue),Value) <> 0 then begin - BoldLog.LogFmt(sSettingValue, [LoggString, Name, Value]); + BoldLog.LogFmt('Setting %s.%s to %s', [LoggString, Name, Value]); RoseItem.OverrideProperty(ToolName, Name, Value); end; end; @@ -420,7 +424,7 @@ procedure TBoldRose2000Properties.SetText(RoseItem: IRoseItem; const Name, Defau begin if AnsiCompareText(GetString(RoseItem, Name, DefaultValue),Value) <> 0 then begin - BoldLog.LogFmt(sSettingValue, [LoggString, Name, Value]); + BoldLog.LogFmt('Setting %s.%s to %s', [LoggString, Name, Value]); RoseItem.OverrideProperty(ToolName, Name, Value); end; end; @@ -467,7 +471,7 @@ class function TBoldRose2000Support.RoseExportControlToVisibility(ExportControl: 1: Result := vkProtected; 2: Result := vkPrivate; else - BoldLog.Log(sUnknownVisibility); + BoldLog.Log('Unknown visibility, public is set.'); end; end; @@ -481,4 +485,6 @@ class procedure TBoldRose2000Support.SetExportControl(Visibility: TVisibilityKin end; end; +initialization + end. diff --git a/Source/Common/Rose2000/RationalRose2000_TLB.pas b/Source/Common/Rose2000/RationalRose2000_TLB.pas index 972701b..2597a78 100644 --- a/Source/Common/Rose2000/RationalRose2000_TLB.pas +++ b/Source/Common/Rose2000/RationalRose2000_TLB.pas @@ -1,45 +1,41 @@ + +{ Global compiler directives } +{$include bold.inc} unit RationalRose2000_TLB; +{$INCLUDE Bold.inc} {$WARNINGS OFF} {$WARN SYMBOL_PLATFORM OFF} -// ************************************************************************ // -// WARNING -// ------- -// The types declared in this file were generated from data read from a -// Type Library. If this type library is explicitly or indirectly (via -// another type library referring to this type library) re-imported, or the -// 'Refresh' command of the Type Library Editor activated while editing the -// Type Library, the contents of this file will be regenerated and all -// manual modifications will be lost. -// ************************************************************************ // - -// PASTLWTR: 1.1 -// File generated on 2000-03-16 14:06:15 from Type Library described below. - -// ************************************************************************ // -// Type Lib: C:\Program Files\Rational\Rose 2000\rationalrose.tlb (1) -// IID\LCID: {860CC660-1C2B-11D0-B1B1-444553540000}\0 -// Helpfile: -// DepndLst: -// (1) v1.0 stdole, (C:\WINNT\System32\stdole32.tlb) -// (2) v1.0 StdVCL, (C:\WINNT\System32\STDVCL32.DLL) -// ************************************************************************ // -{$TYPEDADDRESS OFF} // Unit must be compiled without type-checked pointers. + + + + + + + + + + + + + + + + + +{$TYPEDADDRESS OFF} interface uses Windows, ActiveX, Classes, Graphics, OleCtrls, StdVCL; -// *********************************************************************// -// GUIDS declared in the TypeLibrary. Following prefixes are used: -// Type Libraries : LIBID_xxxx -// CoClasses : CLASS_xxxx -// DISPInterfaces : DIID_xxxx -// Non-DISP interfaces: IID_xxxx -// *********************************************************************// + + + + + const - // TypeLibrary Major and minor versions RationalRoseMajorVersion = 4; RationalRoseMinorVersion = 2; @@ -318,16 +314,12 @@ interface DIID_IRoseExternalDocument: TGUID = '{906FF583-276B-11D0-8980-00A024774419}'; CLASS_RoseExternalDocument: TGUID = '{86652277-EBF7-11D0-BC10-00A024C67143}'; -// *********************************************************************// -// Declaration of Enumerations defined in Type Library -// *********************************************************************// -// Constants for enum RoseAddinEventTypes + + type RoseAddinEventTypes = TOleEnum; const rsOnNewModel = $00000002; - -// Constants for enum RoseContextMenuItemType type RoseContextMenuItemType = TOleEnum; const @@ -350,30 +342,22 @@ interface rsSynchronization = $00000010; rsDecision = $00000011; rsSwimlane = $00000012; - -// Constants for enum RoseNotationTypes type RoseNotationTypes = TOleEnum; const BoochNotation = $00000000; OMTNotation = $00000001; UMLNotation = $00000002; - -// Constants for enum RoseClientRelKind type RoseClientRelKind = TOleEnum; const rsAnyKind = $00000000; rsFriend = $00000001; - -// Constants for enum RosePersistence type RosePersistence = TOleEnum; const rsPersistent = $00000000; rsTransient = $00000001; - -// Constants for enum RoseSynchronization type RoseSynchronization = TOleEnum; const @@ -382,15 +366,11 @@ interface rsBalking = $00000002; rsTimeout = $00000003; rsAsynchronous = $00000004; - -// Constants for enum RoseFrequency type RoseFrequency = TOleEnum; const rsAperiodic = $00000000; rsPeriodic = $00000001; - -// Constants for enum RoseClientRelType type RoseClientRelType = TOleEnum; const @@ -401,8 +381,6 @@ interface rsTypeAssociation = $00000004; rsTypeDependency = $00000005; rsTypeRealizes = $00000006; - -// Constants for enum RoseMenuState type RoseMenuState = TOleEnum; const @@ -415,9 +393,7 @@ interface type -// *********************************************************************// -// Forward declaration of types defined in TypeLibrary -// *********************************************************************// + IRoseActivityViewCollection = dispinterface; IRoseProcessorCollection = dispinterface; IRoseCategoryCollection = dispinterface; @@ -555,10 +531,8 @@ interface IRosePackageCollection = dispinterface; IRoseExternalDocument = dispinterface; -// *********************************************************************// -// Declaration of CoClasses defined in Type Library -// (NOTE: Here we map each CoClass to its Default Interface) -// *********************************************************************// + + RoseActivityViewCollection = IRoseActivityViewCollection; RoseProcessorCollection = IRoseProcessorCollection; RoseCategoryCollection = IRoseCategoryCollection; @@ -697,11 +671,8 @@ interface RoseExternalDocument = IRoseExternalDocument; -// *********************************************************************// -// DispIntf: IRoseActivityViewCollection -// Flags: (4096) Dispatchable -// GUID: {BEAED5FE-578D-11D2-92AA-004005141253} -// *********************************************************************// + + IRoseActivityViewCollection = dispinterface ['{BEAED5FE-578D-11D2-92AA-004005141253}'] property Count: Smallint dispid 202; @@ -718,11 +689,9 @@ interface function GetWithUniqueID(const UniqueID: WideString): IRoseActivityView; dispid 213; end; -// *********************************************************************// -// DispIntf: IRoseProcessorCollection -// Flags: (4096) Dispatchable -// GUID: {97B3835C-A4E3-11D0-BFF0-00AA003DEF5B} -// *********************************************************************// + + + IRoseProcessorCollection = dispinterface ['{97B3835C-A4E3-11D0-BFF0-00AA003DEF5B}'] property Count: Smallint dispid 202; @@ -739,11 +708,9 @@ interface function GetWithUniqueID(const UniqueID: WideString): IRoseProcessor; dispid 213; end; -// *********************************************************************// -// DispIntf: IRoseCategoryCollection -// Flags: (4096) Dispatchable -// GUID: {97B3835B-A4E3-11D0-BFF0-00AA003DEF5B} -// *********************************************************************// + + + IRoseCategoryCollection = dispinterface ['{97B3835B-A4E3-11D0-BFF0-00AA003DEF5B}'] property Count: Smallint dispid 202; @@ -760,11 +727,9 @@ interface function GetWithUniqueID(const UniqueID: WideString): IRoseCategory; dispid 213; end; -// *********************************************************************// -// DispIntf: IRoseDeploymentUnit -// Flags: (4096) Dispatchable -// GUID: {4335FBE3-F0A0-11D1-9FAD-0060975306FE} -// *********************************************************************// + + + IRoseDeploymentUnit = dispinterface ['{4335FBE3-F0A0-11D1-9FAD-0060975306FE}'] property Name: WideString dispid 100; @@ -777,7 +742,7 @@ interface property StateMachineOwner: IRoseStateMachineOwner dispid 12790; function GetUniqueID: WideString; dispid 102; function GetCurrentPropertySetName(const ToolName: WideString): WideString; dispid 109; - function OverrideProperty(const theToolName: WideString; const thePropName: WideString; + function OverrideProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString): WordBool; dispid 110; function InheritProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 111; function GetPropertyValue(const theToolName: WideString; const thePropName: WideString): WideString; dispid 119; @@ -788,7 +753,7 @@ interface function IsOverriddenProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 124; function IsDefaultProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 125; function FindDefaultProperty(const theToolName: WideString; const thePropName: WideString): IRoseProperty; dispid 126; - function CreateProperty(const theToolName: WideString; const thePropName: WideString; + function CreateProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString; const theType: WideString): WordBool; dispid 127; function GetPropertyClassName: WideString; dispid 128; function GetDefaultSetNames(const ToolName: WideString): IRoseStringCollection; dispid 129; @@ -825,11 +790,9 @@ interface function GetIconIndex: Smallint; dispid 12824; end; -// *********************************************************************// -// DispIntf: IRoseItem -// Flags: (4096) Dispatchable -// GUID: {BC57D1C2-863E-11CF-B3D4-00A0241DB1D0} -// *********************************************************************// + + + IRoseItem = dispinterface ['{BC57D1C2-863E-11CF-B3D4-00A0241DB1D0}'] property Name: WideString dispid 100; @@ -842,7 +805,7 @@ interface property StateMachineOwner: IRoseStateMachineOwner dispid 12790; function GetUniqueID: WideString; dispid 102; function GetCurrentPropertySetName(const ToolName: WideString): WideString; dispid 109; - function OverrideProperty(const theToolName: WideString; const thePropName: WideString; + function OverrideProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString): WordBool; dispid 110; function InheritProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 111; function GetPropertyValue(const theToolName: WideString; const thePropName: WideString): WideString; dispid 119; @@ -853,7 +816,7 @@ interface function IsOverriddenProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 124; function IsDefaultProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 125; function FindDefaultProperty(const theToolName: WideString; const thePropName: WideString): IRoseProperty; dispid 126; - function CreateProperty(const theToolName: WideString; const thePropName: WideString; + function CreateProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString; const theType: WideString): WordBool; dispid 127; function GetPropertyClassName: WideString; dispid 128; function GetDefaultSetNames(const ToolName: WideString): IRoseStringCollection; dispid 129; @@ -871,11 +834,9 @@ interface function GetIconIndex: Smallint; dispid 12824; end; -// *********************************************************************// -// DispIntf: IRoseContextMenuItemCollection -// Flags: (4096) Dispatchable -// GUID: {EE0B16E2-FF91-11D1-9FAD-0060975306FE} -// *********************************************************************// + + + IRoseContextMenuItemCollection = dispinterface ['{EE0B16E2-FF91-11D1-9FAD-0060975306FE}'] property Count: Smallint dispid 202; @@ -892,11 +853,9 @@ interface function GetWithUniqueID(const UniqueID: WideString): IRoseContextMenuItem; dispid 213; end; -// *********************************************************************// -// DispIntf: IRoseAddIn -// Flags: (4096) Dispatchable -// GUID: {D5352FC0-346C-11D1-883B-3C8B00C10000} -// *********************************************************************// + + + IRoseAddIn = dispinterface ['{D5352FC0-346C-11D1-883B-3C8B00C10000}'] property EventHandler: IDispatch dispid 12528; @@ -917,23 +876,21 @@ interface procedure Activate; dispid 12543; function IsActive: WordBool; dispid 12553; procedure ExecuteScript(const FileName: WideString); dispid 12595; - function ReadSetting(const Section: WideString; const Entry: WideString; + function ReadSetting(const Section: WideString; const Entry: WideString; const Default: WideString): WideString; dispid 12596; - function WriteSetting(const Section: WideString; const Entry: WideString; + function WriteSetting(const Section: WideString; const Entry: WideString; const Value: WideString): WordBool; dispid 12597; function IdentifyClass: WideString; dispid 12668; function IsClass(const theClassName: WideString): WordBool; dispid 12669; - function AddContextMenuItem(itemType: Smallint; const fullCaption: WideString; + function AddContextMenuItem(itemType: Smallint; const fullCaption: WideString; const internalName: WideString): IRoseContextMenuItem; dispid 12684; function GetContextMenuItems(itemType: Smallint): IRoseContextMenuItemCollection; dispid 12685; function GetDisplayName: WideString; dispid 12689; end; -// *********************************************************************// -// DispIntf: IRoseDecisionViewCollection -// Flags: (4096) Dispatchable -// GUID: {BEAED601-578D-11D2-92AA-004005141253} -// *********************************************************************// + + + IRoseDecisionViewCollection = dispinterface ['{BEAED601-578D-11D2-92AA-004005141253}'] property Count: Smallint dispid 202; @@ -950,11 +907,9 @@ interface function GetWithUniqueID(const UniqueID: WideString): IRoseDecisionView; dispid 213; end; -// *********************************************************************// -// DispIntf: IRoseStateVertex -// Flags: (4096) Dispatchable -// GUID: {BEAED5E2-578D-11D2-92AA-004005141253} -// *********************************************************************// + + + IRoseStateVertex = dispinterface ['{BEAED5E2-578D-11D2-92AA-004005141253}'] property Name: WideString dispid 100; @@ -970,7 +925,7 @@ interface property StateMachineOwner: IRoseStateMachineOwner dispid 12790; function GetUniqueID: WideString; dispid 102; function GetCurrentPropertySetName(const ToolName: WideString): WideString; dispid 109; - function OverrideProperty(const theToolName: WideString; const thePropName: WideString; + function OverrideProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString): WordBool; dispid 110; function InheritProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 111; function GetPropertyValue(const theToolName: WideString; const thePropName: WideString): WideString; dispid 119; @@ -981,7 +936,7 @@ interface function IsOverriddenProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 124; function IsDefaultProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 125; function FindDefaultProperty(const theToolName: WideString; const thePropName: WideString): IRoseProperty; dispid 126; - function CreateProperty(const theToolName: WideString; const thePropName: WideString; + function CreateProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString; const theType: WideString): WordBool; dispid 127; function GetPropertyClassName: WideString; dispid 128; function GetDefaultSetNames(const ToolName: WideString): IRoseStringCollection; dispid 129; @@ -1003,11 +958,9 @@ interface function GetIconIndex: Smallint; dispid 12824; end; -// *********************************************************************// -// DispIntf: IRoseUseCaseCollection -// Flags: (4096) Dispatchable -// GUID: {97B38356-A4E3-11D0-BFF0-00AA003DEF5B} -// *********************************************************************// + + + IRoseUseCaseCollection = dispinterface ['{97B38356-A4E3-11D0-BFF0-00AA003DEF5B}'] property Count: Smallint dispid 202; @@ -1024,11 +977,9 @@ interface function GetWithUniqueID(const UniqueID: WideString): IRoseUseCase; dispid 213; end; -// *********************************************************************// -// DispIntf: IRoseConnectionRelation -// Flags: (4096) Dispatchable -// GUID: {4467F442-F24E-11D2-92AA-004005141253} -// *********************************************************************// + + + IRoseConnectionRelation = dispinterface ['{4467F442-F24E-11D2-92AA-004005141253}'] property Name: WideString dispid 100; @@ -1044,7 +995,7 @@ interface property SupplierIsDevice: WordBool dispid 12816; function GetUniqueID: WideString; dispid 102; function GetCurrentPropertySetName(const ToolName: WideString): WideString; dispid 109; - function OverrideProperty(const theToolName: WideString; const thePropName: WideString; + function OverrideProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString): WordBool; dispid 110; function InheritProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 111; function GetPropertyValue(const theToolName: WideString; const thePropName: WideString): WideString; dispid 119; @@ -1055,7 +1006,7 @@ interface function IsOverriddenProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 124; function IsDefaultProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 125; function FindDefaultProperty(const theToolName: WideString; const thePropName: WideString): IRoseProperty; dispid 126; - function CreateProperty(const theToolName: WideString; const thePropName: WideString; + function CreateProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString; const theType: WideString): WordBool; dispid 127; function GetPropertyClassName: WideString; dispid 128; function GetDefaultSetNames(const ToolName: WideString): IRoseStringCollection; dispid 129; @@ -1077,11 +1028,9 @@ interface function GetIconIndex: Smallint; dispid 12824; end; -// *********************************************************************// -// DispIntf: IRoseRelation -// Flags: (4096) Dispatchable -// GUID: {BA242E02-8961-11CF-B3D4-00A0241DB1D0} -// *********************************************************************// + + + IRoseRelation = dispinterface ['{BA242E02-8961-11CF-B3D4-00A0241DB1D0}'] property Name: WideString dispid 100; @@ -1095,7 +1044,7 @@ interface property StateMachineOwner: IRoseStateMachineOwner dispid 12790; function GetUniqueID: WideString; dispid 102; function GetCurrentPropertySetName(const ToolName: WideString): WideString; dispid 109; - function OverrideProperty(const theToolName: WideString; const thePropName: WideString; + function OverrideProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString): WordBool; dispid 110; function InheritProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 111; function GetPropertyValue(const theToolName: WideString; const thePropName: WideString): WideString; dispid 119; @@ -1106,7 +1055,7 @@ interface function IsOverriddenProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 124; function IsDefaultProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 125; function FindDefaultProperty(const theToolName: WideString; const thePropName: WideString): IRoseProperty; dispid 126; - function CreateProperty(const theToolName: WideString; const thePropName: WideString; + function CreateProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString; const theType: WideString): WordBool; dispid 127; function GetPropertyClassName: WideString; dispid 128; function GetDefaultSetNames(const ToolName: WideString): IRoseStringCollection; dispid 129; @@ -1128,11 +1077,9 @@ interface function GetIconIndex: Smallint; dispid 12824; end; -// *********************************************************************// -// DispIntf: IRoseApplication -// Flags: (4096) Dispatchable -// GUID: {D7BC1B40-8618-11CF-B3D4-00A0241DB1D0} -// *********************************************************************// + + + IRoseApplication = dispinterface ['{D7BC1B40-8618-11CF-B3D4-00A0241DB1D0}'] property Visible: WordBool dispid 202; @@ -1154,7 +1101,7 @@ interface procedure WriteErrorLog(const theMsg: WideString); dispid 213; procedure Save(bSaveUnits: WordBool); dispid 214; procedure SaveAs(const theFile: WideString; bSaveUnits: WordBool); dispid 215; - procedure CompileScriptFile(const FileName: WideString; const BinaryName: WideString; + procedure CompileScriptFile(const FileName: WideString; const BinaryName: WideString; bDebug: WordBool); dispid 218; function OpenModelAsTemplate(const szFileName: WideString): IRoseModel; dispid 223; procedure OpenScript(const FileName: WideString); dispid 225; @@ -1163,9 +1110,9 @@ interface procedure ExecuteScript(const pFileName: WideString); dispid 236; function OpenURL(const theURL: WideString): WordBool; dispid 12587; function OpenExternalDocument(const FileName: WideString): WordBool; dispid 12588; - function GetProfileString(const Section: WideString; const Entry: WideString; + function GetProfileString(const Section: WideString; const Entry: WideString; const Default: WideString): WideString; dispid 12589; - function WriteProfileString(const Section: WideString; const Entry: WideString; + function WriteProfileString(const Section: WideString; const Entry: WideString; const Value: WideString): WordBool; dispid 12590; function UpdateBrowserOverlayImage(const theItem: IRoseItem): WordBool; dispid 12679; function UpdateBrowserDocOverlayImage(const theDocument: IRoseExternalDocument): WordBool; dispid 12688; @@ -1173,11 +1120,9 @@ interface function GetRoseIniPath: WideString; dispid 12698; end; -// *********************************************************************// -// DispIntf: IRoseDecisionCollection -// Flags: (4096) Dispatchable -// GUID: {BEAED5F2-578D-11D2-92AA-004005141253} -// *********************************************************************// + + + IRoseDecisionCollection = dispinterface ['{BEAED5F2-578D-11D2-92AA-004005141253}'] property Count: Smallint dispid 202; @@ -1194,11 +1139,9 @@ interface function GetWithUniqueID(const UniqueID: WideString): IRoseDecision; dispid 213; end; -// *********************************************************************// -// DispIntf: IRoseDecision -// Flags: (4096) Dispatchable -// GUID: {BEAED5E3-578D-11D2-92AA-004005141253} -// *********************************************************************// + + + IRoseDecision = dispinterface ['{BEAED5E3-578D-11D2-92AA-004005141253}'] property Name: WideString dispid 100; @@ -1214,7 +1157,7 @@ interface property StateMachineOwner: IRoseStateMachineOwner dispid 12790; function GetUniqueID: WideString; dispid 102; function GetCurrentPropertySetName(const ToolName: WideString): WideString; dispid 109; - function OverrideProperty(const theToolName: WideString; const thePropName: WideString; + function OverrideProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString): WordBool; dispid 110; function InheritProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 111; function GetPropertyValue(const theToolName: WideString; const thePropName: WideString): WideString; dispid 119; @@ -1225,7 +1168,7 @@ interface function IsOverriddenProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 124; function IsDefaultProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 125; function FindDefaultProperty(const theToolName: WideString; const thePropName: WideString): IRoseProperty; dispid 126; - function CreateProperty(const theToolName: WideString; const thePropName: WideString; + function CreateProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString; const theType: WideString): WordBool; dispid 127; function GetPropertyClassName: WideString; dispid 128; function GetDefaultSetNames(const ToolName: WideString): IRoseStringCollection; dispid 129; @@ -1247,11 +1190,9 @@ interface function GetIconIndex: Smallint; dispid 12824; end; -// *********************************************************************// -// DispIntf: IRoseLineVertexCollection -// Flags: (4096) Dispatchable -// GUID: {11A235B2-3095-11D2-8153-00104B97EBD5} -// *********************************************************************// + + + IRoseLineVertexCollection = dispinterface ['{11A235B2-3095-11D2-8153-00104B97EBD5}'] property Count: Smallint dispid 202; @@ -1268,11 +1209,9 @@ interface function GetWithUniqueID(const UniqueID: WideString): IRoseLineVertex; dispid 213; end; -// *********************************************************************// -// DispIntf: IRoseInstantiateRelationCollection -// Flags: (4096) Dispatchable -// GUID: {B91D8F06-DDBB-11D1-9FAD-0060975306FE} -// *********************************************************************// + + + IRoseInstantiateRelationCollection = dispinterface ['{B91D8F06-DDBB-11D1-9FAD-0060975306FE}'] property Count: Smallint dispid 202; @@ -1289,11 +1228,9 @@ interface function GetWithUniqueID(const UniqueID: WideString): IRoseInstantiateRelation; dispid 213; end; -// *********************************************************************// -// DispIntf: IRoseMessageCollection -// Flags: (4096) Dispatchable -// GUID: {97B38359-A4E3-11D0-BFF0-00AA003DEF5B} -// *********************************************************************// + + + IRoseMessageCollection = dispinterface ['{97B38359-A4E3-11D0-BFF0-00AA003DEF5B}'] property Count: Smallint dispid 202; @@ -1310,11 +1247,9 @@ interface function GetWithUniqueID(const UniqueID: WideString): IRoseMessage; dispid 213; end; -// *********************************************************************// -// DispIntf: IRoseClassDiagramCollection -// Flags: (4096) Dispatchable -// GUID: {97B38343-A4E3-11D0-BFF0-00AA003DEF5B} -// *********************************************************************// + + + IRoseClassDiagramCollection = dispinterface ['{97B38343-A4E3-11D0-BFF0-00AA003DEF5B}'] property Count: Smallint dispid 202; @@ -1331,11 +1266,9 @@ interface function GetWithUniqueID(const UniqueID: WideString): IRoseClassDiagram; dispid 213; end; -// *********************************************************************// -// DispIntf: IRoseScenarioDiagram -// Flags: (4096) Dispatchable -// GUID: {F819833A-FC55-11CF-BBD3-00A024C67143} -// *********************************************************************// + + + IRoseScenarioDiagram = dispinterface ['{F819833A-FC55-11CF-BBD3-00A024C67143}'] property Name: WideString dispid 100; @@ -1350,7 +1283,7 @@ interface property ZoomFactor: Smallint dispid 12690; function GetUniqueID: WideString; dispid 102; function GetCurrentPropertySetName(const ToolName: WideString): WideString; dispid 109; - function OverrideProperty(const theToolName: WideString; const thePropName: WideString; + function OverrideProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString): WordBool; dispid 110; function InheritProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 111; function GetPropertyValue(const theToolName: WideString; const thePropName: WideString): WideString; dispid 119; @@ -1361,7 +1294,7 @@ interface function IsOverriddenProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 124; function IsDefaultProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 125; function FindDefaultProperty(const theToolName: WideString; const thePropName: WideString): IRoseProperty; dispid 126; - function CreateProperty(const theToolName: WideString; const thePropName: WideString; + function CreateProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString; const theType: WideString): WordBool; dispid 127; function GetPropertyClassName: WideString; dispid 128; function GetDefaultSetNames(const ToolName: WideString): IRoseStringCollection; dispid 129; @@ -1387,7 +1320,7 @@ interface function GetSelectedObjects: IRoseObjectInstanceCollection; dispid 412; function GetMessages: IRoseMessageCollection; dispid 413; function GetSelectedMessages: IRoseMessageCollection; dispid 414; - function CreateMessage(const theName: WideString; const theSender: IRoseObjectInstance; + function CreateMessage(const theName: WideString; const theSender: IRoseObjectInstance; const theReceiver: IRoseObjectInstance; theSequence: Smallint): IRoseMessage; dispid 416; function GetSelectedLinks: IRoseLinkCollection; dispid 417; function GetDiagramType: Smallint; dispid 418; @@ -1405,11 +1338,9 @@ interface function GetIconIndex: Smallint; dispid 12824; end; -// *********************************************************************// -// DispIntf: IRoseRealizeRelation -// Flags: (4096) Dispatchable -// GUID: {6AC2BA81-454D-11D1-883B-3C8B00C10000} -// *********************************************************************// + + + IRoseRealizeRelation = dispinterface ['{6AC2BA81-454D-11D1-883B-3C8B00C10000}'] property Name: WideString dispid 100; @@ -1423,7 +1354,7 @@ interface property StateMachineOwner: IRoseStateMachineOwner dispid 12790; function GetUniqueID: WideString; dispid 102; function GetCurrentPropertySetName(const ToolName: WideString): WideString; dispid 109; - function OverrideProperty(const theToolName: WideString; const thePropName: WideString; + function OverrideProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString): WordBool; dispid 110; function InheritProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 111; function GetPropertyValue(const theToolName: WideString; const thePropName: WideString): WideString; dispid 119; @@ -1434,7 +1365,7 @@ interface function IsOverriddenProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 124; function IsDefaultProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 125; function FindDefaultProperty(const theToolName: WideString; const thePropName: WideString): IRoseProperty; dispid 126; - function CreateProperty(const theToolName: WideString; const thePropName: WideString; + function CreateProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString; const theType: WideString): WordBool; dispid 127; function GetPropertyClassName: WideString; dispid 128; function GetDefaultSetNames(const ToolName: WideString): IRoseStringCollection; dispid 129; @@ -1460,11 +1391,9 @@ interface function GetIconIndex: Smallint; dispid 12824; end; -// *********************************************************************// -// DispIntf: IRoseHasRelationship -// Flags: (4096) Dispatchable -// GUID: {BA242E04-8961-11CF-B3D4-00A0241DB1D0} -// *********************************************************************// + + + IRoseHasRelationship = dispinterface ['{BA242E04-8961-11CF-B3D4-00A0241DB1D0}'] property Name: WideString dispid 100; @@ -1483,7 +1412,7 @@ interface property StateMachineOwner: IRoseStateMachineOwner dispid 12790; function GetUniqueID: WideString; dispid 102; function GetCurrentPropertySetName(const ToolName: WideString): WideString; dispid 109; - function OverrideProperty(const theToolName: WideString; const thePropName: WideString; + function OverrideProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString): WordBool; dispid 110; function InheritProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 111; function GetPropertyValue(const theToolName: WideString; const thePropName: WideString): WideString; dispid 119; @@ -1494,7 +1423,7 @@ interface function IsOverriddenProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 124; function IsDefaultProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 125; function FindDefaultProperty(const theToolName: WideString; const thePropName: WideString): IRoseProperty; dispid 126; - function CreateProperty(const theToolName: WideString; const thePropName: WideString; + function CreateProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString; const theType: WideString): WordBool; dispid 127; function GetPropertyClassName: WideString; dispid 128; function GetDefaultSetNames(const ToolName: WideString): IRoseStringCollection; dispid 129; @@ -1518,11 +1447,9 @@ interface function GetIconIndex: Smallint; dispid 12824; end; -// *********************************************************************// -// DispIntf: IRoseClassView -// Flags: (4096) Dispatchable -// GUID: {5F735F36-F9EA-11CF-BBD3-00A024C67143} -// *********************************************************************// + + + IRoseClassView = dispinterface ['{5F735F36-F9EA-11CF-BBD3-00A024C67143}'] property Name: WideString dispid 100; @@ -1548,7 +1475,7 @@ interface property LineVertices: IRoseLineVertexCollection dispid 12696; function GetUniqueID: WideString; dispid 102; function GetCurrentPropertySetName(const ToolName: WideString): WideString; dispid 109; - function OverrideProperty(const theToolName: WideString; const thePropName: WideString; + function OverrideProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString): WordBool; dispid 110; function InheritProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 111; function GetPropertyValue(const theToolName: WideString; const thePropName: WideString): WideString; dispid 119; @@ -1559,7 +1486,7 @@ interface function IsOverriddenProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 124; function IsDefaultProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 125; function FindDefaultProperty(const theToolName: WideString; const thePropName: WideString): IRoseProperty; dispid 126; - function CreateProperty(const theToolName: WideString; const thePropName: WideString; + function CreateProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString; const theType: WideString): WordBool; dispid 127; function GetPropertyClassName: WideString; dispid 128; function GetDefaultSetNames(const ToolName: WideString): IRoseStringCollection; dispid 129; @@ -1586,11 +1513,9 @@ interface function GetDisplayedOperations: IRoseItemCollection; dispid 12827; end; -// *********************************************************************// -// DispIntf: IRoseView_FillColor -// Flags: (4096) Dispatchable -// GUID: {CE5BE563-0380-11D1-BC11-00A024C67143} -// *********************************************************************// + + + IRoseView_FillColor = dispinterface ['{CE5BE563-0380-11D1-BC11-00A024C67143}'] property Red: Smallint dispid 12493; @@ -1601,11 +1526,9 @@ interface function IsClass(const theClassName: WideString): WordBool; dispid 12669; end; -// *********************************************************************// -// DispIntf: IRoseActionCollection -// Flags: (4096) Dispatchable -// GUID: {97B3835F-A4E3-11D0-BFF0-00AA003DEF5B} -// *********************************************************************// + + + IRoseActionCollection = dispinterface ['{97B3835F-A4E3-11D0-BFF0-00AA003DEF5B}'] property Count: Smallint dispid 202; @@ -1622,11 +1545,9 @@ interface function GetWithUniqueID(const UniqueID: WideString): IRoseAction; dispid 213; end; -// *********************************************************************// -// DispIntf: IRoseSyncItemCollection -// Flags: (4096) Dispatchable -// GUID: {94CA188F-5D13-11D2-92AA-004005141253} -// *********************************************************************// + + + IRoseSyncItemCollection = dispinterface ['{94CA188F-5D13-11D2-92AA-004005141253}'] property Count: Smallint dispid 202; @@ -1643,11 +1564,9 @@ interface function GetWithUniqueID(const UniqueID: WideString): IRoseSyncItem; dispid 213; end; -// *********************************************************************// -// DispIntf: IRoseActivityCollection -// Flags: (4096) Dispatchable -// GUID: {BEAED5F0-578D-11D2-92AA-004005141253} -// *********************************************************************// + + + IRoseActivityCollection = dispinterface ['{BEAED5F0-578D-11D2-92AA-004005141253}'] property Count: Smallint dispid 202; @@ -1664,11 +1583,9 @@ interface function GetWithUniqueID(const UniqueID: WideString): IRoseActivity; dispid 213; end; -// *********************************************************************// -// DispIntf: IRoseActivity -// Flags: (4096) Dispatchable -// GUID: {BEAED5E7-578D-11D2-92AA-004005141253} -// *********************************************************************// + + + IRoseActivity = dispinterface ['{BEAED5E7-578D-11D2-92AA-004005141253}'] property Name: WideString dispid 100; @@ -1688,7 +1605,7 @@ interface property SubSynchronizations: IRoseSyncItemCollection dispid 12804; function GetUniqueID: WideString; dispid 102; function GetCurrentPropertySetName(const ToolName: WideString): WideString; dispid 109; - function OverrideProperty(const theToolName: WideString; const thePropName: WideString; + function OverrideProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString): WordBool; dispid 110; function InheritProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 111; function GetPropertyValue(const theToolName: WideString; const thePropName: WideString): WideString; dispid 119; @@ -1699,7 +1616,7 @@ interface function IsOverriddenProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 124; function IsDefaultProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 125; function FindDefaultProperty(const theToolName: WideString; const thePropName: WideString): IRoseProperty; dispid 126; - function CreateProperty(const theToolName: WideString; const thePropName: WideString; + function CreateProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString; const theType: WideString): WordBool; dispid 127; function GetPropertyClassName: WideString; dispid 128; function GetDefaultSetNames(const ToolName: WideString): IRoseStringCollection; dispid 129; @@ -1739,11 +1656,9 @@ interface function GetIconIndex: Smallint; dispid 12824; end; -// *********************************************************************// -// DispIntf: IRoseProcess -// Flags: (4096) Dispatchable -// GUID: {62C43884-DB5A-11CF-B091-00A0241E3F73} -// *********************************************************************// + + + IRoseProcess = dispinterface ['{62C43884-DB5A-11CF-B091-00A0241E3F73}'] property Name: WideString dispid 100; @@ -1758,7 +1673,7 @@ interface property StateMachineOwner: IRoseStateMachineOwner dispid 12790; function GetUniqueID: WideString; dispid 102; function GetCurrentPropertySetName(const ToolName: WideString): WideString; dispid 109; - function OverrideProperty(const theToolName: WideString; const thePropName: WideString; + function OverrideProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString): WordBool; dispid 110; function InheritProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 111; function GetPropertyValue(const theToolName: WideString; const thePropName: WideString): WideString; dispid 119; @@ -1769,7 +1684,7 @@ interface function IsOverriddenProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 124; function IsDefaultProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 125; function FindDefaultProperty(const theToolName: WideString; const thePropName: WideString): IRoseProperty; dispid 126; - function CreateProperty(const theToolName: WideString; const thePropName: WideString; + function CreateProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString; const theType: WideString): WordBool; dispid 127; function GetPropertyClassName: WideString; dispid 128; function GetDefaultSetNames(const ToolName: WideString): IRoseStringCollection; dispid 129; @@ -1787,11 +1702,9 @@ interface function GetIconIndex: Smallint; dispid 12824; end; -// *********************************************************************// -// DispIntf: IRoseAddInCollection -// Flags: (4096) Dispatchable -// GUID: {C87D2BC1-352A-11D1-883B-3C8B00C10000} -// *********************************************************************// + + + IRoseAddInCollection = dispinterface ['{C87D2BC1-352A-11D1-883B-3C8B00C10000}'] property Count: Smallint dispid 202; @@ -1808,11 +1721,9 @@ interface function GetWithUniqueID(const UniqueID: WideString): IRoseAddIn; dispid 213; end; -// *********************************************************************// -// DispIntf: IRoseSwimLaneView -// Flags: (4096) Dispatchable -// GUID: {68F63C21-B047-11D2-92AA-004005141253} -// *********************************************************************// + + + IRoseSwimLaneView = dispinterface ['{68F63C21-B047-11D2-92AA-004005141253}'] property Name: WideString dispid 100; @@ -1832,7 +1743,7 @@ interface property LineVertices: IRoseLineVertexCollection dispid 12696; function GetUniqueID: WideString; dispid 102; function GetCurrentPropertySetName(const ToolName: WideString): WideString; dispid 109; - function OverrideProperty(const theToolName: WideString; const thePropName: WideString; + function OverrideProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString): WordBool; dispid 110; function InheritProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 111; function GetPropertyValue(const theToolName: WideString; const thePropName: WideString): WideString; dispid 119; @@ -1843,7 +1754,7 @@ interface function IsOverriddenProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 124; function IsDefaultProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 125; function FindDefaultProperty(const theToolName: WideString; const thePropName: WideString): IRoseProperty; dispid 126; - function CreateProperty(const theToolName: WideString; const thePropName: WideString; + function CreateProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString; const theType: WideString): WordBool; dispid 127; function GetPropertyClassName: WideString; dispid 128; function GetDefaultSetNames(const ToolName: WideString): IRoseStringCollection; dispid 129; @@ -1868,11 +1779,9 @@ interface function GetIconIndex: Smallint; dispid 12824; end; -// *********************************************************************// -// DispIntf: IRoseControllableUnitCollection -// Flags: (4096) Dispatchable -// GUID: {97B38360-A4E3-11D0-BFF0-00AA003DEF5B} -// *********************************************************************// + + + IRoseControllableUnitCollection = dispinterface ['{97B38360-A4E3-11D0-BFF0-00AA003DEF5B}'] property Count: Smallint dispid 202; @@ -1889,11 +1798,9 @@ interface function GetWithUniqueID(const UniqueID: WideString): IRoseControllableUnit; dispid 213; end; -// *********************************************************************// -// DispIntf: IRoseModuleCollection -// Flags: (4096) Dispatchable -// GUID: {97B3834B-A4E3-11D0-BFF0-00AA003DEF5B} -// *********************************************************************// + + + IRoseModuleCollection = dispinterface ['{97B3834B-A4E3-11D0-BFF0-00AA003DEF5B}'] property Count: Smallint dispid 202; @@ -1910,11 +1817,9 @@ interface function GetWithUniqueID(const UniqueID: WideString): IRoseModule; dispid 213; end; -// *********************************************************************// -// DispIntf: IRoseLinkCollection -// Flags: (4096) Dispatchable -// GUID: {9DE9A9C1-F2D0-11D0-883A-3C8B00C10000} -// *********************************************************************// + + + IRoseLinkCollection = dispinterface ['{9DE9A9C1-F2D0-11D0-883A-3C8B00C10000}'] property Count: Smallint dispid 202; @@ -1931,11 +1836,9 @@ interface function GetWithUniqueID(const UniqueID: WideString): IRoseLink; dispid 213; end; -// *********************************************************************// -// DispIntf: IRoseAction -// Flags: (4096) Dispatchable -// GUID: {13881143-93C1-11D0-A214-00A024FFFE40} -// *********************************************************************// + + + IRoseAction = dispinterface ['{13881143-93C1-11D0-A214-00A024FFFE40}'] property Name: WideString dispid 100; @@ -1950,7 +1853,7 @@ interface property StateMachineOwner: IRoseStateMachineOwner dispid 12790; function GetUniqueID: WideString; dispid 102; function GetCurrentPropertySetName(const ToolName: WideString): WideString; dispid 109; - function OverrideProperty(const theToolName: WideString; const thePropName: WideString; + function OverrideProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString): WordBool; dispid 110; function InheritProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 111; function GetPropertyValue(const theToolName: WideString; const thePropName: WideString): WideString; dispid 119; @@ -1961,7 +1864,7 @@ interface function IsOverriddenProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 124; function IsDefaultProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 125; function FindDefaultProperty(const theToolName: WideString; const thePropName: WideString): IRoseProperty; dispid 126; - function CreateProperty(const theToolName: WideString; const thePropName: WideString; + function CreateProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString; const theType: WideString): WordBool; dispid 127; function GetPropertyClassName: WideString; dispid 128; function GetDefaultSetNames(const ToolName: WideString): IRoseStringCollection; dispid 129; @@ -1979,11 +1882,9 @@ interface function GetIconIndex: Smallint; dispid 12824; end; -// *********************************************************************// -// DispIntf: IRoseParameterCollection -// Flags: (4096) Dispatchable -// GUID: {97B38352-A4E3-11D0-BFF0-00AA003DEF5B} -// *********************************************************************// + + + IRoseParameterCollection = dispinterface ['{97B38352-A4E3-11D0-BFF0-00AA003DEF5B}'] property Count: Smallint dispid 202; @@ -2000,11 +1901,9 @@ interface function GetWithUniqueID(const UniqueID: WideString): IRoseParameter; dispid 213; end; -// *********************************************************************// -// DispIntf: IRoseAttributeCollection -// Flags: (4096) Dispatchable -// GUID: {97B3834C-A4E3-11D0-BFF0-00AA003DEF5B} -// *********************************************************************// + + + IRoseAttributeCollection = dispinterface ['{97B3834C-A4E3-11D0-BFF0-00AA003DEF5B}'] property Count: Smallint dispid 202; @@ -2021,11 +1920,9 @@ interface function GetWithUniqueID(const UniqueID: WideString): IRoseAttribute; dispid 213; end; -// *********************************************************************// -// DispIntf: IRoseDevice -// Flags: (4096) Dispatchable -// GUID: {62C43882-DB5A-11CF-B091-00A0241E3F73} -// *********************************************************************// + + + IRoseDevice = dispinterface ['{62C43882-DB5A-11CF-B091-00A0241E3F73}'] property Name: WideString dispid 100; @@ -2040,7 +1937,7 @@ interface property Connections: IRoseConnectionRelationCollection dispid 12818; function GetUniqueID: WideString; dispid 102; function GetCurrentPropertySetName(const ToolName: WideString): WideString; dispid 109; - function OverrideProperty(const theToolName: WideString; const thePropName: WideString; + function OverrideProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString): WordBool; dispid 110; function InheritProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 111; function GetPropertyValue(const theToolName: WideString; const thePropName: WideString): WideString; dispid 119; @@ -2051,7 +1948,7 @@ interface function IsOverriddenProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 124; function IsDefaultProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 125; function FindDefaultProperty(const theToolName: WideString; const thePropName: WideString): IRoseProperty; dispid 126; - function CreateProperty(const theToolName: WideString; const thePropName: WideString; + function CreateProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString; const theType: WideString): WordBool; dispid 127; function GetPropertyClassName: WideString; dispid 128; function GetDefaultSetNames(const ToolName: WideString): IRoseStringCollection; dispid 129; @@ -2075,11 +1972,9 @@ interface function GetIconIndex: Smallint; dispid 12824; end; -// *********************************************************************// -// DispIntf: IRoseClassDependency -// Flags: (4096) Dispatchable -// GUID: {4ACE1899-6CD3-11D1-BC1E-00A024C67143} -// *********************************************************************// + + + IRoseClassDependency = dispinterface ['{4ACE1899-6CD3-11D1-BC1E-00A024C67143}'] property Name: WideString dispid 100; @@ -2097,7 +1992,7 @@ interface property StateMachineOwner: IRoseStateMachineOwner dispid 12790; function GetUniqueID: WideString; dispid 102; function GetCurrentPropertySetName(const ToolName: WideString): WideString; dispid 109; - function OverrideProperty(const theToolName: WideString; const thePropName: WideString; + function OverrideProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString): WordBool; dispid 110; function InheritProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 111; function GetPropertyValue(const theToolName: WideString; const thePropName: WideString): WideString; dispid 119; @@ -2108,7 +2003,7 @@ interface function IsOverriddenProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 124; function IsDefaultProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 125; function FindDefaultProperty(const theToolName: WideString; const thePropName: WideString): IRoseProperty; dispid 126; - function CreateProperty(const theToolName: WideString; const thePropName: WideString; + function CreateProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString; const theType: WideString): WordBool; dispid 127; function GetPropertyClassName: WideString; dispid 128; function GetDefaultSetNames(const ToolName: WideString): IRoseStringCollection; dispid 129; @@ -2132,11 +2027,9 @@ interface function GetIconIndex: Smallint; dispid 12824; end; -// *********************************************************************// -// DispIntf: IRoseRole -// Flags: (4096) Dispatchable -// GUID: {BA242E00-8961-11CF-B3D4-00A0241DB1D0} -// *********************************************************************// + + + IRoseRole = dispinterface ['{BA242E00-8961-11CF-B3D4-00A0241DB1D0}'] property Name: WideString dispid 100; @@ -2163,7 +2056,7 @@ interface property StateMachineOwner: IRoseStateMachineOwner dispid 12790; function GetUniqueID: WideString; dispid 102; function GetCurrentPropertySetName(const ToolName: WideString): WideString; dispid 109; - function OverrideProperty(const theToolName: WideString; const thePropName: WideString; + function OverrideProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString): WordBool; dispid 110; function InheritProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 111; function GetPropertyValue(const theToolName: WideString; const thePropName: WideString): WideString; dispid 119; @@ -2174,7 +2067,7 @@ interface function IsOverriddenProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 124; function IsDefaultProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 125; function FindDefaultProperty(const theToolName: WideString; const thePropName: WideString): IRoseProperty; dispid 126; - function CreateProperty(const theToolName: WideString; const thePropName: WideString; + function CreateProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString; const theType: WideString): WordBool; dispid 127; function GetPropertyClassName: WideString; dispid 128; function GetDefaultSetNames(const ToolName: WideString): IRoseStringCollection; dispid 129; @@ -2200,11 +2093,9 @@ interface function GetIconIndex: Smallint; dispid 12824; end; -// *********************************************************************// -// DispIntf: IRoseClass -// Flags: (4096) Dispatchable -// GUID: {BC57D1C0-863E-11CF-B3D4-00A0241DB1D0} -// *********************************************************************// + + + IRoseClass = dispinterface ['{BC57D1C0-863E-11CF-B3D4-00A0241DB1D0}'] property Name: WideString dispid 100; @@ -2231,7 +2122,7 @@ interface property StateMachineOwner: IRoseStateMachineOwner dispid 12790; function GetUniqueID: WideString; dispid 102; function GetCurrentPropertySetName(const ToolName: WideString): WideString; dispid 109; - function OverrideProperty(const theToolName: WideString; const thePropName: WideString; + function OverrideProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString): WordBool; dispid 110; function InheritProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 111; function GetPropertyValue(const theToolName: WideString; const thePropName: WideString): WideString; dispid 119; @@ -2242,7 +2133,7 @@ interface function IsOverriddenProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 124; function IsDefaultProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 125; function FindDefaultProperty(const theToolName: WideString; const thePropName: WideString): IRoseProperty; dispid 126; - function CreateProperty(const theToolName: WideString; const thePropName: WideString; + function CreateProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString; const theType: WideString): WordBool; dispid 127; function GetPropertyClassName: WideString; dispid 128; function GetDefaultSetNames(const ToolName: WideString): IRoseStringCollection; dispid 129; @@ -2257,9 +2148,9 @@ interface function GetSuperclasses: IRoseClassCollection; dispid 424; function GetAssociations: IRoseAssociationCollection; dispid 425; function AddOperation(const theName: WideString; const retType: WideString): IRoseOperation; dispid 427; - function AddAttribute(const theName: WideString; const theType: WideString; + function AddAttribute(const theName: WideString; const theType: WideString; const initVal: WideString): IRoseAttribute; dispid 428; - function AddAssociation(const theSupplierRoleName: WideString; + function AddAssociation(const theSupplierRoleName: WideString; const theSupplierRoleType: WideString): IRoseAssociation; dispid 429; function AddHas(const theSupplierName: WideString; const theSupplierType: WideString): IRoseHasRelationship; dispid 430; function DeleteHas(const theHas: IRoseHasRelationship): WordBool; dispid 432; @@ -2290,7 +2181,7 @@ interface function GetClassDependencies: IRoseClassDependencyCollection; dispid 12662; function AddClassDependency(const theSupplerName: WideString; const theSupplierType: WideString): IRoseClassDependency; dispid 12663; function DeleteClassDependency(const theClassDependency: IRoseClassDependency): WordBool; dispid 12664; - function AddParameter(const theName: WideString; const theType: WideString; + function AddParameter(const theName: WideString; const theType: WideString; const theDef: WideString; position: Smallint): IRoseParameter; dispid 12667; function IdentifyClass: WideString; dispid 12668; function IsClass(const theClassName: WideString): WordBool; dispid 12669; @@ -2305,11 +2196,9 @@ interface function GetIconIndex: Smallint; dispid 12824; end; -// *********************************************************************// -// DispIntf: IRoseElement -// Flags: (4096) Dispatchable -// GUID: {D067F15F-6987-11D0-BBF0-00A024C67143} -// *********************************************************************// + + + IRoseElement = dispinterface ['{D067F15F-6987-11D0-BBF0-00A024C67143}'] property Name: WideString dispid 100; @@ -2317,7 +2206,7 @@ interface property Model: IRoseModel dispid 12524; function GetUniqueID: WideString; dispid 102; function GetCurrentPropertySetName(const ToolName: WideString): WideString; dispid 109; - function OverrideProperty(const theToolName: WideString; const thePropName: WideString; + function OverrideProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString): WordBool; dispid 110; function InheritProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 111; function GetPropertyValue(const theToolName: WideString; const thePropName: WideString): WideString; dispid 119; @@ -2328,7 +2217,7 @@ interface function IsOverriddenProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 124; function IsDefaultProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 125; function FindDefaultProperty(const theToolName: WideString; const thePropName: WideString): IRoseProperty; dispid 126; - function CreateProperty(const theToolName: WideString; const thePropName: WideString; + function CreateProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString; const theType: WideString): WordBool; dispid 127; function GetPropertyClassName: WideString; dispid 128; function GetDefaultSetNames(const ToolName: WideString): IRoseStringCollection; dispid 129; @@ -2341,11 +2230,9 @@ interface function GetIconIndex: Smallint; dispid 12824; end; -// *********************************************************************// -// DispIntf: IRoseControllableUnit -// Flags: (4096) Dispatchable -// GUID: {32C862A7-8AA9-11D0-A70B-0000F803584A} -// *********************************************************************// + + + IRoseControllableUnit = dispinterface ['{32C862A7-8AA9-11D0-A70B-0000F803584A}'] property Name: WideString dispid 100; @@ -2358,7 +2245,7 @@ interface property StateMachineOwner: IRoseStateMachineOwner dispid 12790; function GetUniqueID: WideString; dispid 102; function GetCurrentPropertySetName(const ToolName: WideString): WideString; dispid 109; - function OverrideProperty(const theToolName: WideString; const thePropName: WideString; + function OverrideProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString): WordBool; dispid 110; function InheritProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 111; function GetPropertyValue(const theToolName: WideString; const thePropName: WideString): WideString; dispid 119; @@ -2369,7 +2256,7 @@ interface function IsOverriddenProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 124; function IsDefaultProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 125; function FindDefaultProperty(const theToolName: WideString; const thePropName: WideString): IRoseProperty; dispid 126; - function CreateProperty(const theToolName: WideString; const thePropName: WideString; + function CreateProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString; const theType: WideString): WordBool; dispid 127; function GetPropertyClassName: WideString; dispid 128; function GetDefaultSetNames(const ToolName: WideString): IRoseStringCollection; dispid 129; @@ -2406,11 +2293,9 @@ interface function GetIconIndex: Smallint; dispid 12824; end; -// *********************************************************************// -// DispIntf: IRoseModel -// Flags: (4096) Dispatchable -// GUID: {E38942A0-8621-11CF-B3D4-00A0241DB1D0} -// *********************************************************************// + + + IRoseModel = dispinterface ['{E38942A0-8621-11CF-B3D4-00A0241DB1D0}'] property Name: WideString dispid 100; @@ -2432,7 +2317,7 @@ interface property StateMachineOwner: IRoseStateMachineOwner dispid 12790; function GetUniqueID: WideString; dispid 102; function GetCurrentPropertySetName(const ToolName: WideString): WideString; dispid 109; - function OverrideProperty(const theToolName: WideString; const thePropName: WideString; + function OverrideProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString): WordBool; dispid 110; function InheritProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 111; function GetPropertyValue(const theToolName: WideString; const thePropName: WideString): WideString; dispid 119; @@ -2443,7 +2328,7 @@ interface function IsOverriddenProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 124; function IsDefaultProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 125; function FindDefaultProperty(const theToolName: WideString; const thePropName: WideString): IRoseProperty; dispid 126; - function CreateProperty(const theToolName: WideString; const thePropName: WideString; + function CreateProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString; const theType: WideString): WordBool; dispid 127; function GetPropertyClassName: WideString; dispid 128; function GetDefaultSetNames(const ToolName: WideString): IRoseStringCollection; dispid 129; @@ -2509,11 +2394,9 @@ interface function GetIconIndex: Smallint; dispid 12824; end; -// *********************************************************************// -// DispIntf: IRoseTransition -// Flags: (4096) Dispatchable -// GUID: {574130A1-93B8-11D0-A214-00A024FFFE40} -// *********************************************************************// + + + IRoseTransition = dispinterface ['{574130A1-93B8-11D0-A214-00A024FFFE40}'] property Name: WideString dispid 100; @@ -2527,7 +2410,7 @@ interface property StateMachineOwner: IRoseStateMachineOwner dispid 12790; function GetUniqueID: WideString; dispid 102; function GetCurrentPropertySetName(const ToolName: WideString): WideString; dispid 109; - function OverrideProperty(const theToolName: WideString; const thePropName: WideString; + function OverrideProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString): WordBool; dispid 110; function InheritProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 111; function GetPropertyValue(const theToolName: WideString; const thePropName: WideString): WideString; dispid 119; @@ -2538,7 +2421,7 @@ interface function IsOverriddenProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 124; function IsDefaultProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 125; function FindDefaultProperty(const theToolName: WideString; const thePropName: WideString): IRoseProperty; dispid 126; - function CreateProperty(const theToolName: WideString; const thePropName: WideString; + function CreateProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString; const theType: WideString): WordBool; dispid 127; function GetPropertyClassName: WideString; dispid 128; function GetDefaultSetNames(const ToolName: WideString): IRoseStringCollection; dispid 129; @@ -2568,11 +2451,9 @@ interface function GetIconIndex: Smallint; dispid 12824; end; -// *********************************************************************// -// DispIntf: IRoseSubsystemCollection -// Flags: (4096) Dispatchable -// GUID: {97B3834A-A4E3-11D0-BFF0-00AA003DEF5B} -// *********************************************************************// + + + IRoseSubsystemCollection = dispinterface ['{97B3834A-A4E3-11D0-BFF0-00AA003DEF5B}'] property Count: Smallint dispid 202; @@ -2589,11 +2470,9 @@ interface function GetWithUniqueID(const UniqueID: WideString): IRoseSubsystem; dispid 213; end; -// *********************************************************************// -// DispIntf: IRoseProcessor -// Flags: (4096) Dispatchable -// GUID: {62C43886-DB5A-11CF-B091-00A0241E3F73} -// *********************************************************************// + + + IRoseProcessor = dispinterface ['{62C43886-DB5A-11CF-B091-00A0241E3F73}'] property Name: WideString dispid 100; @@ -2610,7 +2489,7 @@ interface property Connections: IRoseConnectionRelationCollection dispid 12819; function GetUniqueID: WideString; dispid 102; function GetCurrentPropertySetName(const ToolName: WideString): WideString; dispid 109; - function OverrideProperty(const theToolName: WideString; const thePropName: WideString; + function OverrideProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString): WordBool; dispid 110; function InheritProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 111; function GetPropertyValue(const theToolName: WideString; const thePropName: WideString): WideString; dispid 119; @@ -2621,7 +2500,7 @@ interface function IsOverriddenProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 124; function IsDefaultProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 125; function FindDefaultProperty(const theToolName: WideString; const thePropName: WideString): IRoseProperty; dispid 126; - function CreateProperty(const theToolName: WideString; const thePropName: WideString; + function CreateProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString; const theType: WideString): WordBool; dispid 127; function GetPropertyClassName: WideString; dispid 128; function GetDefaultSetNames(const ToolName: WideString): IRoseStringCollection; dispid 129; @@ -2647,11 +2526,9 @@ interface function GetIconIndex: Smallint; dispid 12824; end; -// *********************************************************************// -// DispIntf: IRoseCategoryDependencyCollection -// Flags: (4096) Dispatchable -// GUID: {4ACE189D-6CD3-11D1-BC1E-00A024C67143} -// *********************************************************************// + + + IRoseCategoryDependencyCollection = dispinterface ['{4ACE189D-6CD3-11D1-BC1E-00A024C67143}'] property Count: Smallint dispid 202; @@ -2668,11 +2545,9 @@ interface function GetWithUniqueID(const UniqueID: WideString): IRoseCategoryDependency; dispid 213; end; -// *********************************************************************// -// DispIntf: IRoseProperty -// Flags: (4096) Dispatchable -// GUID: {93461A23-8811-11CF-B1B0-D227D5210B2C} -// *********************************************************************// + + + IRoseProperty = dispinterface ['{93461A23-8811-11CF-B1B0-D227D5210B2C}'] property Name: WideString dispid 202; @@ -2681,11 +2556,9 @@ interface property Type_: WideString dispid 206; end; -// *********************************************************************// -// DispIntf: IRoseStateDiagram -// Flags: (4096) Dispatchable -// GUID: {7ADDA701-9B06-11D0-A214-00A024FFFE40} -// *********************************************************************// + + + IRoseStateDiagram = dispinterface ['{7ADDA701-9B06-11D0-A214-00A024FFFE40}'] property Name: WideString dispid 100; @@ -2701,7 +2574,7 @@ interface property IsActivityDiagram: WordBool dispid 12761; function GetUniqueID: WideString; dispid 102; function GetCurrentPropertySetName(const ToolName: WideString): WideString; dispid 109; - function OverrideProperty(const theToolName: WideString; const thePropName: WideString; + function OverrideProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString): WordBool; dispid 110; function InheritProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 111; function GetPropertyValue(const theToolName: WideString; const thePropName: WideString): WideString; dispid 119; @@ -2712,7 +2585,7 @@ interface function IsOverriddenProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 124; function IsDefaultProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 125; function FindDefaultProperty(const theToolName: WideString; const thePropName: WideString): IRoseProperty; dispid 126; - function CreateProperty(const theToolName: WideString; const thePropName: WideString; + function CreateProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString; const theType: WideString): WordBool; dispid 127; function GetPropertyClassName: WideString; dispid 128; function GetDefaultSetNames(const ToolName: WideString): IRoseStringCollection; dispid 129; @@ -2772,11 +2645,9 @@ interface function GetIconIndex: Smallint; dispid 12824; end; -// *********************************************************************// -// DispIntf: IRoseEvent -// Flags: (4096) Dispatchable -// GUID: {A69CAB22-9179-11D0-A214-00A024FFFE40} -// *********************************************************************// + + + IRoseEvent = dispinterface ['{A69CAB22-9179-11D0-A214-00A024FFFE40}'] property Arguments: WideString dispid 215; @@ -2786,7 +2657,7 @@ interface property GuardCondition: WideString dispid 12622; function GetUniqueID: WideString; dispid 102; function GetCurrentPropertySetName(const ToolName: WideString): WideString; dispid 109; - function OverrideProperty(const theToolName: WideString; const thePropName: WideString; + function OverrideProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString): WordBool; dispid 110; function InheritProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 111; function GetPropertyValue(const theToolName: WideString; const thePropName: WideString): WideString; dispid 119; @@ -2797,7 +2668,7 @@ interface function IsOverriddenProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 124; function IsDefaultProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 125; function FindDefaultProperty(const theToolName: WideString; const thePropName: WideString): IRoseProperty; dispid 126; - function CreateProperty(const theToolName: WideString; const thePropName: WideString; + function CreateProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString; const theType: WideString): WordBool; dispid 127; function GetPropertyClassName: WideString; dispid 128; function GetDefaultSetNames(const ToolName: WideString): IRoseStringCollection; dispid 129; @@ -2811,11 +2682,9 @@ interface function GetIconIndex: Smallint; dispid 12824; end; -// *********************************************************************// -// DispIntf: IRoseRichType -// Flags: (4096) Dispatchable -// GUID: {EB7AAB60-939C-11CF-B091-00A0241E3F73} -// *********************************************************************// + + + IRoseRichType = dispinterface ['{EB7AAB60-939C-11CF-B091-00A0241E3F73}'] property Value: Smallint dispid 202; @@ -2825,11 +2694,9 @@ interface function IsClass(const theClassName: WideString): WordBool; dispid 12669; end; -// *********************************************************************// -// DispIntf: IRoseScenarioDiagramCollection -// Flags: (4096) Dispatchable -// GUID: {97B3835E-A4E3-11D0-BFF0-00AA003DEF5B} -// *********************************************************************// + + + IRoseScenarioDiagramCollection = dispinterface ['{97B3835E-A4E3-11D0-BFF0-00AA003DEF5B}'] property Count: Smallint dispid 202; @@ -2846,11 +2713,9 @@ interface function GetWithUniqueID(const UniqueID: WideString): IRoseScenarioDiagram; dispid 213; end; -// *********************************************************************// -// DispIntf: IRoseParameter -// Flags: (4096) Dispatchable -// GUID: {C78E7028-86E4-11CF-B3D4-00A0241DB1D0} -// *********************************************************************// + + + IRoseParameter = dispinterface ['{C78E7028-86E4-11CF-B3D4-00A0241DB1D0}'] property Name: WideString dispid 100; @@ -2866,7 +2731,7 @@ interface property StateMachineOwner: IRoseStateMachineOwner dispid 12790; function GetUniqueID: WideString; dispid 102; function GetCurrentPropertySetName(const ToolName: WideString): WideString; dispid 109; - function OverrideProperty(const theToolName: WideString; const thePropName: WideString; + function OverrideProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString): WordBool; dispid 110; function InheritProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 111; function GetPropertyValue(const theToolName: WideString; const thePropName: WideString): WideString; dispid 119; @@ -2877,7 +2742,7 @@ interface function IsOverriddenProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 124; function IsDefaultProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 125; function FindDefaultProperty(const theToolName: WideString; const thePropName: WideString): IRoseProperty; dispid 126; - function CreateProperty(const theToolName: WideString; const thePropName: WideString; + function CreateProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString; const theType: WideString): WordBool; dispid 127; function GetPropertyClassName: WideString; dispid 128; function GetDefaultSetNames(const ToolName: WideString): IRoseStringCollection; dispid 129; @@ -2895,11 +2760,9 @@ interface function GetIconIndex: Smallint; dispid 12824; end; -// *********************************************************************// -// DispIntf: IRoseOperation -// Flags: (4096) Dispatchable -// GUID: {C78E7020-86E4-11CF-B3D4-00A0241DB1D0} -// *********************************************************************// + + + IRoseOperation = dispinterface ['{C78E7020-86E4-11CF-B3D4-00A0241DB1D0}'] property Name: WideString dispid 100; @@ -2926,7 +2789,7 @@ interface property StateMachineOwner: IRoseStateMachineOwner dispid 12790; function GetUniqueID: WideString; dispid 102; function GetCurrentPropertySetName(const ToolName: WideString): WideString; dispid 109; - function OverrideProperty(const theToolName: WideString; const thePropName: WideString; + function OverrideProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString): WordBool; dispid 110; function InheritProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 111; function GetPropertyValue(const theToolName: WideString; const thePropName: WideString): WideString; dispid 119; @@ -2937,7 +2800,7 @@ interface function IsOverriddenProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 124; function IsDefaultProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 125; function FindDefaultProperty(const theToolName: WideString; const thePropName: WideString): IRoseProperty; dispid 126; - function CreateProperty(const theToolName: WideString; const thePropName: WideString; + function CreateProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString; const theType: WideString): WordBool; dispid 127; function GetPropertyClassName: WideString; dispid 128; function GetDefaultSetNames(const ToolName: WideString): IRoseStringCollection; dispid 129; @@ -2947,7 +2810,7 @@ interface function AddExternalDocument(const szName: WideString; iType: Smallint): IRoseExternalDocument; dispid 214; function DeleteExternalDocument(const pIDispatch: IRoseExternalDocument): WordBool; dispid 215; function OpenSpecification: WordBool; dispid 216; - function AddParameter(const theName: WideString; const theType: WideString; + function AddParameter(const theName: WideString; const theType: WideString; const theDef: WideString; position: Smallint): IRoseParameter; dispid 416; procedure RemoveAllParameters; dispid 417; function DeleteParameter(const theParameter: IRoseParameter): WordBool; dispid 426; @@ -2959,11 +2822,9 @@ interface function GetIconIndex: Smallint; dispid 12824; end; -// *********************************************************************// -// DispIntf: IRoseView_LineColor -// Flags: (4096) Dispatchable -// GUID: {CE5BE565-0380-11D1-BC11-00A024C67143} -// *********************************************************************// + + + IRoseView_LineColor = dispinterface ['{CE5BE565-0380-11D1-BC11-00A024C67143}'] property Blue: Smallint dispid 12502; @@ -2973,11 +2834,9 @@ interface function IsClass(const theClassName: WideString): WordBool; dispid 12669; end; -// *********************************************************************// -// DispIntf: IRoseAddInManager -// Flags: (4096) Dispatchable -// GUID: {D5352FC2-346C-11D1-883B-3C8B00C10000} -// *********************************************************************// + + + IRoseAddInManager = dispinterface ['{D5352FC2-346C-11D1-883B-3C8B00C10000}'] property AddIns: IRoseAddInCollection dispid 12529; @@ -2987,11 +2846,9 @@ interface function EnableEvents(theEvents: Integer): Integer; dispid 12693; end; -// *********************************************************************// -// DispIntf: IRoseStateDiagramCollection -// Flags: (4096) Dispatchable -// GUID: {97B38368-A4E3-11D0-BFF0-00AA003DEF5B} -// *********************************************************************// + + + IRoseStateDiagramCollection = dispinterface ['{97B38368-A4E3-11D0-BFF0-00AA003DEF5B}'] property Count: Smallint dispid 202; @@ -3008,11 +2865,9 @@ interface function GetWithUniqueID(const UniqueID: WideString): IRoseStateDiagram; dispid 213; end; -// *********************************************************************// -// DispIntf: IRoseSwimLaneViewCollection -// Flags: (4096) Dispatchable -// GUID: {7FFC5F46-C0C2-11D2-92AA-004005141253} -// *********************************************************************// + + + IRoseSwimLaneViewCollection = dispinterface ['{7FFC5F46-C0C2-11D2-92AA-004005141253}'] property Count: Smallint dispid 202; @@ -3029,11 +2884,9 @@ interface function GetWithUniqueID(const UniqueID: WideString): IRoseSwimLaneView; dispid 213; end; -// *********************************************************************// -// DispIntf: IRoseSwimLane -// Flags: (4096) Dispatchable -// GUID: {BEAED5EA-578D-11D2-92AA-004005141253} -// *********************************************************************// + + + IRoseSwimLane = dispinterface ['{BEAED5EA-578D-11D2-92AA-004005141253}'] property Name: WideString dispid 100; @@ -3050,7 +2903,7 @@ interface property StateMachineOwner: IRoseStateMachineOwner dispid 12790; function GetUniqueID: WideString; dispid 102; function GetCurrentPropertySetName(const ToolName: WideString): WideString; dispid 109; - function OverrideProperty(const theToolName: WideString; const thePropName: WideString; + function OverrideProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString): WordBool; dispid 110; function InheritProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 111; function GetPropertyValue(const theToolName: WideString; const thePropName: WideString): WideString; dispid 119; @@ -3061,7 +2914,7 @@ interface function IsOverriddenProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 124; function IsDefaultProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 125; function FindDefaultProperty(const theToolName: WideString; const thePropName: WideString): IRoseProperty; dispid 126; - function CreateProperty(const theToolName: WideString; const thePropName: WideString; + function CreateProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString; const theType: WideString): WordBool; dispid 127; function GetPropertyClassName: WideString; dispid 128; function GetDefaultSetNames(const ToolName: WideString): IRoseStringCollection; dispid 129; @@ -3083,11 +2936,9 @@ interface function GetIconIndex: Smallint; dispid 12824; end; -// *********************************************************************// -// DispIntf: IRoseItemViewCollection -// Flags: (4096) Dispatchable -// GUID: {97B38362-A4E3-11D0-BFF0-00AA003DEF5B} -// *********************************************************************// + + + IRoseItemViewCollection = dispinterface ['{97B38362-A4E3-11D0-BFF0-00AA003DEF5B}'] property Count: Smallint dispid 202; @@ -3104,11 +2955,9 @@ interface function GetWithUniqueID(const UniqueID: WideString): IRoseItemView; dispid 213; end; -// *********************************************************************// -// DispIntf: IRosePropertyCollection -// Flags: (4096) Dispatchable -// GUID: {97B3835D-A4E3-11D0-BFF0-00AA003DEF5B} -// *********************************************************************// + + + IRosePropertyCollection = dispinterface ['{97B3835D-A4E3-11D0-BFF0-00AA003DEF5B}'] property Count: Smallint dispid 202; @@ -3125,11 +2974,9 @@ interface function GetWithUniqueID(const UniqueID: WideString): IRoseProperty; dispid 213; end; -// *********************************************************************// -// DispIntf: IRoseOperationCollection -// Flags: (4096) Dispatchable -// GUID: {97B3834D-A4E3-11D0-BFF0-00AA003DEF5B} -// *********************************************************************// + + + IRoseOperationCollection = dispinterface ['{97B3834D-A4E3-11D0-BFF0-00AA003DEF5B}'] property Count: Smallint dispid 202; @@ -3146,11 +2993,9 @@ interface function GetWithUniqueID(const UniqueID: WideString): IRoseOperation; dispid 213; end; -// *********************************************************************// -// DispIntf: IRoseDeviceCollection -// Flags: (4096) Dispatchable -// GUID: {97B38342-A4E3-11D0-BFF0-00AA003DEF5B} -// *********************************************************************// + + + IRoseDeviceCollection = dispinterface ['{97B38342-A4E3-11D0-BFF0-00AA003DEF5B}'] property Count: Smallint dispid 202; @@ -3167,11 +3012,9 @@ interface function GetWithUniqueID(const UniqueID: WideString): IRoseDevice; dispid 213; end; -// *********************************************************************// -// DispIntf: IRoseInstantiateRelation -// Flags: (4096) Dispatchable -// GUID: {B91D8F03-DDBB-11D1-9FAD-0060975306FE} -// *********************************************************************// + + + IRoseInstantiateRelation = dispinterface ['{B91D8F03-DDBB-11D1-9FAD-0060975306FE}'] property Name: WideString dispid 100; @@ -3185,7 +3028,7 @@ interface property StateMachineOwner: IRoseStateMachineOwner dispid 12790; function GetUniqueID: WideString; dispid 102; function GetCurrentPropertySetName(const ToolName: WideString): WideString; dispid 109; - function OverrideProperty(const theToolName: WideString; const thePropName: WideString; + function OverrideProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString): WordBool; dispid 110; function InheritProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 111; function GetPropertyValue(const theToolName: WideString; const thePropName: WideString): WideString; dispid 119; @@ -3196,7 +3039,7 @@ interface function IsOverriddenProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 124; function IsDefaultProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 125; function FindDefaultProperty(const theToolName: WideString; const thePropName: WideString): IRoseProperty; dispid 126; - function CreateProperty(const theToolName: WideString; const thePropName: WideString; + function CreateProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString; const theType: WideString): WordBool; dispid 127; function GetPropertyClassName: WideString; dispid 128; function GetDefaultSetNames(const ToolName: WideString): IRoseStringCollection; dispid 129; @@ -3220,11 +3063,9 @@ interface function GetIconIndex: Smallint; dispid 12824; end; -// *********************************************************************// -// DispIntf: IRoseContextMenuItem -// Flags: (4096) Dispatchable -// GUID: {EE0B16E0-FF91-11D1-9FAD-0060975306FE} -// *********************************************************************// + + + IRoseContextMenuItem = dispinterface ['{EE0B16E0-FF91-11D1-9FAD-0060975306FE}'] property Caption: WideString dispid 12682; @@ -3235,11 +3076,9 @@ interface function IsClass(const theClassName: WideString): WordBool; dispid 12669; end; -// *********************************************************************// -// DispIntf: IRoseLineVertex -// Flags: (4096) Dispatchable -// GUID: {B53888D2-3094-11D2-8153-00104B97EBD5} -// *********************************************************************// + + + IRoseLineVertex = dispinterface ['{B53888D2-3094-11D2-8153-00104B97EBD5}'] function IdentifyClass: WideString; dispid 12668; @@ -3248,22 +3087,18 @@ interface function GetYPosition: Smallint; dispid 12695; end; -// *********************************************************************// -// DispIntf: IRoseObject -// Flags: (4096) Dispatchable -// GUID: {7D8474B2-2C33-11D0-BBDA-00A024C67143} -// *********************************************************************// + + + IRoseObject = dispinterface ['{7D8474B2-2C33-11D0-BBDA-00A024C67143}'] function IdentifyClass: WideString; dispid 12668; function IsClass(const theClassName: WideString): WordBool; dispid 12669; end; -// *********************************************************************// -// DispIntf: IRoseSwimLaneCollection -// Flags: (4096) Dispatchable -// GUID: {7FFC5F42-C0C2-11D2-92AA-004005141253} -// *********************************************************************// + + + IRoseSwimLaneCollection = dispinterface ['{7FFC5F42-C0C2-11D2-92AA-004005141253}'] property Count: Smallint dispid 202; @@ -3280,11 +3115,9 @@ interface function GetWithUniqueID(const UniqueID: WideString): IRoseSwimLane; dispid 213; end; -// *********************************************************************// -// DispIntf: IRoseModuleVisibilityRelationship -// Flags: (4096) Dispatchable -// GUID: {9EF8DDD6-E697-11CF-BBD1-00A024C67143} -// *********************************************************************// + + + IRoseModuleVisibilityRelationship = dispinterface ['{9EF8DDD6-E697-11CF-BBD1-00A024C67143}'] property Name: WideString dispid 100; @@ -3304,7 +3137,7 @@ interface property StateMachineOwner: IRoseStateMachineOwner dispid 12790; function GetUniqueID: WideString; dispid 102; function GetCurrentPropertySetName(const ToolName: WideString): WideString; dispid 109; - function OverrideProperty(const theToolName: WideString; const thePropName: WideString; + function OverrideProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString): WordBool; dispid 110; function InheritProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 111; function GetPropertyValue(const theToolName: WideString; const thePropName: WideString): WideString; dispid 119; @@ -3315,7 +3148,7 @@ interface function IsOverriddenProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 124; function IsDefaultProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 125; function FindDefaultProperty(const theToolName: WideString; const thePropName: WideString): IRoseProperty; dispid 126; - function CreateProperty(const theToolName: WideString; const thePropName: WideString; + function CreateProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString; const theType: WideString): WordBool; dispid 127; function GetPropertyClassName: WideString; dispid 128; function GetDefaultSetNames(const ToolName: WideString): IRoseStringCollection; dispid 129; @@ -3337,11 +3170,9 @@ interface function GetIconIndex: Smallint; dispid 12824; end; -// *********************************************************************// -// DispIntf: IRoseComponentViewCollection -// Flags: (4096) Dispatchable -// GUID: {C640C861-F2D3-11D0-883A-3C8B00C10000} -// *********************************************************************// + + + IRoseComponentViewCollection = dispinterface ['{C640C861-F2D3-11D0-883A-3C8B00C10000}'] property Count: Smallint dispid 202; @@ -3358,11 +3189,9 @@ interface function GetWithUniqueID(const UniqueID: WideString): IRoseComponentView; dispid 213; end; -// *********************************************************************// -// DispIntf: IRoseHasRelationshipCollection -// Flags: (4096) Dispatchable -// GUID: {97B38351-A4E3-11D0-BFF0-00AA003DEF5B} -// *********************************************************************// + + + IRoseHasRelationshipCollection = dispinterface ['{97B38351-A4E3-11D0-BFF0-00AA003DEF5B}'] property Count: Smallint dispid 202; @@ -3379,11 +3208,9 @@ interface function GetWithUniqueID(const UniqueID: WideString): IRoseHasRelationship; dispid 213; end; -// *********************************************************************// -// DispIntf: IRoseClassViewCollection -// Flags: (4096) Dispatchable -// GUID: {97B38341-A4E3-11D0-BFF0-00AA003DEF5B} -// *********************************************************************// + + + IRoseClassViewCollection = dispinterface ['{97B38341-A4E3-11D0-BFF0-00AA003DEF5B}'] property Count: Smallint dispid 202; @@ -3400,13 +3227,11 @@ interface function GetWithUniqueID(const UniqueID: WideString): IRoseClassView; dispid 213; end; -// *********************************************************************// -// DispIntf: IRoseDeploymentDiagram -// Flags: (4096) Dispatchable -// GUID: {C2C15EC4-E028-11CF-B091-00A0241E3F73} -// *********************************************************************// - IRoseDeploymentDiagram = dispinterface - ['{C2C15EC4-E028-11CF-B091-00A0241E3F73}'] + + + + IRoseDeploymentDiagram = dispinterface + ['{C2C15EC4-E028-11CF-B091-00A0241E3F73}'] property Name: WideString dispid 100; property ItemViews: IRoseItemViewCollection dispid 202; property Visible: WordBool dispid 203; @@ -3418,7 +3243,7 @@ interface property ZoomFactor: Smallint dispid 12690; function GetUniqueID: WideString; dispid 102; function GetCurrentPropertySetName(const ToolName: WideString): WideString; dispid 109; - function OverrideProperty(const theToolName: WideString; const thePropName: WideString; + function OverrideProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString): WordBool; dispid 110; function InheritProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 111; function GetPropertyValue(const theToolName: WideString; const thePropName: WideString): WideString; dispid 119; @@ -3429,7 +3254,7 @@ interface function IsOverriddenProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 124; function IsDefaultProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 125; function FindDefaultProperty(const theToolName: WideString; const thePropName: WideString): IRoseProperty; dispid 126; - function CreateProperty(const theToolName: WideString; const thePropName: WideString; + function CreateProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString; const theType: WideString): WordBool; dispid 127; function GetPropertyClassName: WideString; dispid 128; function GetDefaultSetNames(const ToolName: WideString): IRoseStringCollection; dispid 129; @@ -3467,11 +3292,9 @@ interface function GetIconIndex: Smallint; dispid 12824; end; -// *********************************************************************// -// DispIntf: IRoseInstanceView -// Flags: (4096) Dispatchable -// GUID: {348B1AD4-D5C4-11D0-89F8-0020AFD6C181} -// *********************************************************************// + + + IRoseInstanceView = dispinterface ['{348B1AD4-D5C4-11D0-89F8-0020AFD6C181}'] property Name: WideString dispid 100; @@ -3491,7 +3314,7 @@ interface property LineVertices: IRoseLineVertexCollection dispid 12696; function GetUniqueID: WideString; dispid 102; function GetCurrentPropertySetName(const ToolName: WideString): WideString; dispid 109; - function OverrideProperty(const theToolName: WideString; const thePropName: WideString; + function OverrideProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString): WordBool; dispid 110; function InheritProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 111; function GetPropertyValue(const theToolName: WideString; const thePropName: WideString): WideString; dispid 119; @@ -3502,7 +3325,7 @@ interface function IsOverriddenProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 124; function IsDefaultProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 125; function FindDefaultProperty(const theToolName: WideString; const thePropName: WideString): IRoseProperty; dispid 126; - function CreateProperty(const theToolName: WideString; const thePropName: WideString; + function CreateProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString; const theType: WideString): WordBool; dispid 127; function GetPropertyClassName: WideString; dispid 128; function GetDefaultSetNames(const ToolName: WideString): IRoseStringCollection; dispid 129; @@ -3528,11 +3351,9 @@ interface function GetIconIndex: Smallint; dispid 12824; end; -// *********************************************************************// -// DispIntf: IRoseLink -// Flags: (4096) Dispatchable -// GUID: {195D7852-D5B6-11D0-89F8-0020AFD6C181} -// *********************************************************************// + + + IRoseLink = dispinterface ['{195D7852-D5B6-11D0-89F8-0020AFD6C181}'] property Name: WideString dispid 100; @@ -3551,7 +3372,7 @@ interface property StateMachineOwner: IRoseStateMachineOwner dispid 12790; function GetUniqueID: WideString; dispid 102; function GetCurrentPropertySetName(const ToolName: WideString): WideString; dispid 109; - function OverrideProperty(const theToolName: WideString; const thePropName: WideString; + function OverrideProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString): WordBool; dispid 110; function InheritProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 111; function GetPropertyValue(const theToolName: WideString; const thePropName: WideString): WideString; dispid 119; @@ -3562,7 +3383,7 @@ interface function IsOverriddenProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 124; function IsDefaultProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 125; function FindDefaultProperty(const theToolName: WideString; const thePropName: WideString): IRoseProperty; dispid 126; - function CreateProperty(const theToolName: WideString; const thePropName: WideString; + function CreateProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString; const theType: WideString): WordBool; dispid 127; function GetPropertyClassName: WideString; dispid 128; function GetDefaultSetNames(const ToolName: WideString): IRoseStringCollection; dispid 129; @@ -3576,7 +3397,7 @@ interface function DeleteMessage(const TheMessage: IRoseMessage): WordBool; dispid 419; function AssignAssociation(const TheAssoc: IRoseAssociation): WordBool; dispid 420; function UnassignAssociation: WordBool; dispid 421; - function AddMessageTo(const Name: WideString; const ToInstance: IRoseObjectInstance; + function AddMessageTo(const Name: WideString; const ToInstance: IRoseObjectInstance; SequenceNumber: Smallint): IRoseMessage; dispid 422; function GetQualifiedName: WideString; dispid 12555; function IdentifyClass: WideString; dispid 12668; @@ -3587,11 +3408,9 @@ interface function GetIconIndex: Smallint; dispid 12824; end; -// *********************************************************************// -// DispIntf: IRoseObjectInstance -// Flags: (4096) Dispatchable -// GUID: {F8198337-FC55-11CF-BBD3-00A024C67143} -// *********************************************************************// + + + IRoseObjectInstance = dispinterface ['{F8198337-FC55-11CF-BBD3-00A024C67143}'] property Name: WideString dispid 100; @@ -3608,7 +3427,7 @@ interface property StateMachineOwner: IRoseStateMachineOwner dispid 12790; function GetUniqueID: WideString; dispid 102; function GetCurrentPropertySetName(const ToolName: WideString): WideString; dispid 109; - function OverrideProperty(const theToolName: WideString; const thePropName: WideString; + function OverrideProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString): WordBool; dispid 110; function InheritProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 111; function GetPropertyValue(const theToolName: WideString; const thePropName: WideString): WideString; dispid 119; @@ -3619,7 +3438,7 @@ interface function IsOverriddenProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 124; function IsDefaultProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 125; function FindDefaultProperty(const theToolName: WideString; const thePropName: WideString): IRoseProperty; dispid 126; - function CreateProperty(const theToolName: WideString; const thePropName: WideString; + function CreateProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString; const theType: WideString): WordBool; dispid 127; function GetPropertyClassName: WideString; dispid 128; function GetDefaultSetNames(const ToolName: WideString): IRoseStringCollection; dispid 129; @@ -3640,11 +3459,9 @@ interface function GetIconIndex: Smallint; dispid 12824; end; -// *********************************************************************// -// DispIntf: IRoseCategoryDependency -// Flags: (4096) Dispatchable -// GUID: {4ACE189B-6CD3-11D1-BC1E-00A024C67143} -// *********************************************************************// + + + IRoseCategoryDependency = dispinterface ['{4ACE189B-6CD3-11D1-BC1E-00A024C67143}'] property Name: WideString dispid 100; @@ -3658,7 +3475,7 @@ interface property StateMachineOwner: IRoseStateMachineOwner dispid 12790; function GetUniqueID: WideString; dispid 102; function GetCurrentPropertySetName(const ToolName: WideString): WideString; dispid 109; - function OverrideProperty(const theToolName: WideString; const thePropName: WideString; + function OverrideProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString): WordBool; dispid 110; function InheritProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 111; function GetPropertyValue(const theToolName: WideString; const thePropName: WideString): WideString; dispid 119; @@ -3669,7 +3486,7 @@ interface function IsOverriddenProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 124; function IsDefaultProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 125; function FindDefaultProperty(const theToolName: WideString; const thePropName: WideString): IRoseProperty; dispid 126; - function CreateProperty(const theToolName: WideString; const thePropName: WideString; + function CreateProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString; const theType: WideString): WordBool; dispid 127; function GetPropertyClassName: WideString; dispid 128; function GetDefaultSetNames(const ToolName: WideString): IRoseStringCollection; dispid 129; @@ -3693,11 +3510,9 @@ interface function GetIconIndex: Smallint; dispid 12824; end; -// *********************************************************************// -// DispIntf: IRoseInheritRelation -// Flags: (4096) Dispatchable -// GUID: {00C99560-9200-11CF-B1B0-D227D5210B2C} -// *********************************************************************// + + + IRoseInheritRelation = dispinterface ['{00C99560-9200-11CF-B1B0-D227D5210B2C}'] property Name: WideString dispid 100; @@ -3714,7 +3529,7 @@ interface property StateMachineOwner: IRoseStateMachineOwner dispid 12790; function GetUniqueID: WideString; dispid 102; function GetCurrentPropertySetName(const ToolName: WideString): WideString; dispid 109; - function OverrideProperty(const theToolName: WideString; const thePropName: WideString; + function OverrideProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString): WordBool; dispid 110; function InheritProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 111; function GetPropertyValue(const theToolName: WideString; const thePropName: WideString): WideString; dispid 119; @@ -3725,7 +3540,7 @@ interface function IsOverriddenProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 124; function IsDefaultProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 125; function FindDefaultProperty(const theToolName: WideString; const thePropName: WideString): IRoseProperty; dispid 126; - function CreateProperty(const theToolName: WideString; const thePropName: WideString; + function CreateProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString; const theType: WideString): WordBool; dispid 127; function GetPropertyClassName: WideString; dispid 128; function GetDefaultSetNames(const ToolName: WideString): IRoseStringCollection; dispid 129; @@ -3749,11 +3564,9 @@ interface function GetIconIndex: Smallint; dispid 12824; end; -// *********************************************************************// -// DispIntf: IRoseView_Font -// Flags: (4096) Dispatchable -// GUID: {CE5BE567-0380-11D1-BC11-00A024C67143} -// *********************************************************************// + + + IRoseView_Font = dispinterface ['{CE5BE567-0380-11D1-BC11-00A024C67143}'] property Size: Smallint dispid 12497; @@ -3769,11 +3582,9 @@ interface function IsClass(const theClassName: WideString): WordBool; dispid 12669; end; -// *********************************************************************// -// DispIntf: IRoseStateMachine -// Flags: (4096) Dispatchable -// GUID: {A69CAB21-9179-11D0-A214-00A024FFFE40} -// *********************************************************************// + + + IRoseStateMachine = dispinterface ['{A69CAB21-9179-11D0-A214-00A024FFFE40}'] property Name: WideString dispid 100; @@ -3795,7 +3606,7 @@ interface property StateMachineOwner: IRoseStateMachineOwner dispid 12790; function GetUniqueID: WideString; dispid 102; function GetCurrentPropertySetName(const ToolName: WideString): WideString; dispid 109; - function OverrideProperty(const theToolName: WideString; const thePropName: WideString; + function OverrideProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString): WordBool; dispid 110; function InheritProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 111; function GetPropertyValue(const theToolName: WideString; const thePropName: WideString): WideString; dispid 119; @@ -3806,7 +3617,7 @@ interface function IsOverriddenProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 124; function IsDefaultProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 125; function FindDefaultProperty(const theToolName: WideString; const thePropName: WideString): IRoseProperty; dispid 126; - function CreateProperty(const theToolName: WideString; const thePropName: WideString; + function CreateProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString; const theType: WideString): WordBool; dispid 127; function GetPropertyClassName: WideString; dispid 128; function GetDefaultSetNames(const ToolName: WideString): IRoseStringCollection; dispid 129; @@ -3843,11 +3654,9 @@ interface function GetIconIndex: Smallint; dispid 12824; end; -// *********************************************************************// -// DispIntf: IRoseModule -// Flags: (4096) Dispatchable -// GUID: {C78E702A-86E4-11CF-B3D4-00A0241DB1D0} -// *********************************************************************// + + + IRoseModule = dispinterface ['{C78E702A-86E4-11CF-B3D4-00A0241DB1D0}'] property Name: WideString dispid 100; @@ -3867,7 +3676,7 @@ interface property StateMachineOwner: IRoseStateMachineOwner dispid 12790; function GetUniqueID: WideString; dispid 102; function GetCurrentPropertySetName(const ToolName: WideString): WideString; dispid 109; - function OverrideProperty(const theToolName: WideString; const thePropName: WideString; + function OverrideProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString): WordBool; dispid 110; function InheritProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 111; function GetPropertyValue(const theToolName: WideString; const thePropName: WideString): WideString; dispid 119; @@ -3878,7 +3687,7 @@ interface function IsOverriddenProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 124; function IsDefaultProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 125; function FindDefaultProperty(const theToolName: WideString; const thePropName: WideString): IRoseProperty; dispid 126; - function CreateProperty(const theToolName: WideString; const thePropName: WideString; + function CreateProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString; const theType: WideString): WordBool; dispid 127; function GetPropertyClassName: WideString; dispid 128; function GetDefaultSetNames(const ToolName: WideString): IRoseStringCollection; dispid 129; @@ -3906,11 +3715,9 @@ interface function GetIconIndex: Smallint; dispid 12824; end; -// *********************************************************************// -// DispIntf: IRoseUseCase -// Flags: (4096) Dispatchable -// GUID: {7E7F6EE0-16DE-11D0-8976-00A024774419} -// *********************************************************************// + + + IRoseUseCase = dispinterface ['{7E7F6EE0-16DE-11D0-8976-00A024774419}'] property Name: WideString dispid 100; @@ -3929,7 +3736,7 @@ interface property StateMachineOwner: IRoseStateMachineOwner dispid 12790; function GetUniqueID: WideString; dispid 102; function GetCurrentPropertySetName(const ToolName: WideString): WideString; dispid 109; - function OverrideProperty(const theToolName: WideString; const thePropName: WideString; + function OverrideProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString): WordBool; dispid 110; function InheritProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 111; function GetPropertyValue(const theToolName: WideString; const thePropName: WideString): WideString; dispid 119; @@ -3940,7 +3747,7 @@ interface function IsOverriddenProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 124; function IsDefaultProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 125; function FindDefaultProperty(const theToolName: WideString; const thePropName: WideString): IRoseProperty; dispid 126; - function CreateProperty(const theToolName: WideString; const thePropName: WideString; + function CreateProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString; const theType: WideString): WordBool; dispid 127; function GetPropertyClassName: WideString; dispid 128; function GetDefaultSetNames(const ToolName: WideString): IRoseStringCollection; dispid 129; @@ -3957,7 +3764,7 @@ interface function AddInheritRel(const szName: WideString; const szParentName: WideString): IRoseInheritRelation; dispid 421; function DeleteInheritRel(const pIDispatchRelation: IRoseInheritRelation): WordBool; dispid 422; function GetAssociations: IRoseAssociationCollection; dispid 426; - function AddAssociation(const szSupplierRoleName: WideString; + function AddAssociation(const szSupplierRoleName: WideString; const szSupplierRoleType: WideString): IRoseAssociation; dispid 430; function DeleteAssociation(const pDispatchAssociation: IRoseAssociation): WordBool; dispid 431; function GetSuperUseCases: IRoseUseCaseCollection; dispid 432; @@ -3973,11 +3780,9 @@ interface function GetIconIndex: Smallint; dispid 12824; end; -// *********************************************************************// -// DispIntf: IRoseItemCollection -// Flags: (4096) Dispatchable -// GUID: {0DD9ACF8-D06E-11D0-BC0B-00A024C67143} -// *********************************************************************// + + + IRoseItemCollection = dispinterface ['{0DD9ACF8-D06E-11D0-BC0B-00A024C67143}'] property Count: Smallint dispid 202; @@ -3994,11 +3799,9 @@ interface function GetWithUniqueID(const UniqueID: WideString): IRoseItem; dispid 213; end; -// *********************************************************************// -// DispIntf: IRoseNoteViewCollection -// Flags: (4096) Dispatchable -// GUID: {97B38358-A4E3-11D0-BFF0-00AA003DEF5B} -// *********************************************************************// + + + IRoseNoteViewCollection = dispinterface ['{97B38358-A4E3-11D0-BFF0-00AA003DEF5B}'] property Count: Smallint dispid 202; @@ -4015,11 +3818,9 @@ interface function GetWithUniqueID(const UniqueID: WideString): IRoseNoteView; dispid 213; end; -// *********************************************************************// -// DispIntf: IRoseInheritRelationCollection -// Flags: (4096) Dispatchable -// GUID: {97B38354-A4E3-11D0-BFF0-00AA003DEF5B} -// *********************************************************************// + + + IRoseInheritRelationCollection = dispinterface ['{97B38354-A4E3-11D0-BFF0-00AA003DEF5B}'] property Count: Smallint dispid 202; @@ -4036,11 +3837,9 @@ interface function GetWithUniqueID(const UniqueID: WideString): IRoseInheritRelation; dispid 213; end; -// *********************************************************************// -// DispIntf: IRoseDeploymentDiagramCollection -// Flags: (4096) Dispatchable -// GUID: {97B383A1-A4E3-11D0-BFF0-00AA003DEF5B} -// *********************************************************************// + + + IRoseDeploymentDiagramCollection = dispinterface ['{97B383A1-A4E3-11D0-BFF0-00AA003DEF5B}'] property Count: Smallint dispid 202; @@ -4057,22 +3856,18 @@ interface function GetWithUniqueID(const UniqueID: WideString): IRoseDeploymentDiagram; dispid 213; end; -// *********************************************************************// -// DispIntf: IRoseStringCollection -// Flags: (4096) Dispatchable -// GUID: {6A7FC311-C893-11D0-BC0B-00A024C67143} -// *********************************************************************// + + + IRoseStringCollection = dispinterface ['{6A7FC311-C893-11D0-BC0B-00A024C67143}'] property Count: Smallint dispid 50; function GetAt(id: Smallint): WideString; dispid 51; end; -// *********************************************************************// -// DispIntf: IRoseStateViewCollection -// Flags: (4096) Dispatchable -// GUID: {97B3836A-A4E3-11D0-BFF0-00AA003DEF5B} -// *********************************************************************// + + + IRoseStateViewCollection = dispinterface ['{97B3836A-A4E3-11D0-BFF0-00AA003DEF5B}'] property Count: Smallint dispid 202; @@ -4089,11 +3884,9 @@ interface function GetWithUniqueID(const UniqueID: WideString): IRoseStateView; dispid 213; end; -// *********************************************************************// -// DispIntf: IRoseDecisionView -// Flags: (4096) Dispatchable -// GUID: {BEAED5F9-578D-11D2-92AA-004005141253} -// *********************************************************************// + + + IRoseDecisionView = dispinterface ['{BEAED5F9-578D-11D2-92AA-004005141253}'] property Name: WideString dispid 100; @@ -4113,7 +3906,7 @@ interface property LineVertices: IRoseLineVertexCollection dispid 12696; function GetUniqueID: WideString; dispid 102; function GetCurrentPropertySetName(const ToolName: WideString): WideString; dispid 109; - function OverrideProperty(const theToolName: WideString; const thePropName: WideString; + function OverrideProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString): WordBool; dispid 110; function InheritProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 111; function GetPropertyValue(const theToolName: WideString; const thePropName: WideString): WideString; dispid 119; @@ -4124,7 +3917,7 @@ interface function IsOverriddenProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 124; function IsDefaultProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 125; function FindDefaultProperty(const theToolName: WideString; const thePropName: WideString): IRoseProperty; dispid 126; - function CreateProperty(const theToolName: WideString; const thePropName: WideString; + function CreateProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString; const theType: WideString): WordBool; dispid 127; function GetPropertyClassName: WideString; dispid 128; function GetDefaultSetNames(const ToolName: WideString): IRoseStringCollection; dispid 129; @@ -4150,11 +3943,9 @@ interface function GetIconIndex: Smallint; dispid 12824; end; -// *********************************************************************// -// DispIntf: IRoseStateMachineOwner -// Flags: (4096) Dispatchable -// GUID: {94CA1882-5D13-11D2-92AA-004005141253} -// *********************************************************************// + + + IRoseStateMachineOwner = dispinterface ['{94CA1882-5D13-11D2-92AA-004005141253}'] property Name: WideString dispid 100; @@ -4163,7 +3954,7 @@ interface property StateMachines: IRoseStateMachineCollection dispid 12744; function GetUniqueID: WideString; dispid 102; function GetCurrentPropertySetName(const ToolName: WideString): WideString; dispid 109; - function OverrideProperty(const theToolName: WideString; const thePropName: WideString; + function OverrideProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString): WordBool; dispid 110; function InheritProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 111; function GetPropertyValue(const theToolName: WideString; const thePropName: WideString): WideString; dispid 119; @@ -4174,7 +3965,7 @@ interface function IsOverriddenProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 124; function IsDefaultProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 125; function FindDefaultProperty(const theToolName: WideString; const thePropName: WideString): IRoseProperty; dispid 126; - function CreateProperty(const theToolName: WideString; const thePropName: WideString; + function CreateProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString; const theType: WideString): WordBool; dispid 127; function GetPropertyClassName: WideString; dispid 128; function GetDefaultSetNames(const ToolName: WideString): IRoseStringCollection; dispid 129; @@ -4189,11 +3980,9 @@ interface function GetIconIndex: Smallint; dispid 12824; end; -// *********************************************************************// -// DispIntf: IRoseProcessCollection -// Flags: (4096) Dispatchable -// GUID: {97B38366-A4E3-11D0-BFF0-00AA003DEF5B} -// *********************************************************************// + + + IRoseProcessCollection = dispinterface ['{97B38366-A4E3-11D0-BFF0-00AA003DEF5B}'] property Count: Smallint dispid 202; @@ -4210,11 +3999,9 @@ interface function GetWithUniqueID(const UniqueID: WideString): IRoseProcess; dispid 213; end; -// *********************************************************************// -// DispIntf: IRoseAssociationCollection -// Flags: (4096) Dispatchable -// GUID: {97B3834E-A4E3-11D0-BFF0-00AA003DEF5B} -// *********************************************************************// + + + IRoseAssociationCollection = dispinterface ['{97B3834E-A4E3-11D0-BFF0-00AA003DEF5B}'] property Count: Smallint dispid 202; @@ -4231,11 +4018,9 @@ interface function GetWithUniqueID(const UniqueID: WideString): IRoseAssociation; dispid 213; end; -// *********************************************************************// -// DispIntf: IRoseModuleDiagramCollection -// Flags: (4096) Dispatchable -// GUID: {97B38348-A4E3-11D0-BFF0-00AA003DEF5B} -// *********************************************************************// + + + IRoseModuleDiagramCollection = dispinterface ['{97B38348-A4E3-11D0-BFF0-00AA003DEF5B}'] property Count: Smallint dispid 202; @@ -4252,11 +4037,9 @@ interface function GetWithUniqueID(const UniqueID: WideString): IRoseModuleDiagram; dispid 213; end; -// *********************************************************************// -// DispIntf: IRoseDiagram -// Flags: (4096) Dispatchable -// GUID: {3FD9D000-93B0-11CF-B3D4-00A0241DB1D0} -// *********************************************************************// + + + IRoseDiagram = dispinterface ['{3FD9D000-93B0-11CF-B3D4-00A0241DB1D0}'] property Name: WideString dispid 100; @@ -4270,7 +4053,7 @@ interface property ZoomFactor: Smallint dispid 12690; function GetUniqueID: WideString; dispid 102; function GetCurrentPropertySetName(const ToolName: WideString): WideString; dispid 109; - function OverrideProperty(const theToolName: WideString; const thePropName: WideString; + function OverrideProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString): WordBool; dispid 110; function InheritProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 111; function GetPropertyValue(const theToolName: WideString; const thePropName: WideString): WideString; dispid 119; @@ -4281,7 +4064,7 @@ interface function IsOverriddenProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 124; function IsDefaultProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 125; function FindDefaultProperty(const theToolName: WideString; const thePropName: WideString): IRoseProperty; dispid 126; - function CreateProperty(const theToolName: WideString; const thePropName: WideString; + function CreateProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString; const theType: WideString): WordBool; dispid 127; function GetPropertyClassName: WideString; dispid 128; function GetDefaultSetNames(const ToolName: WideString): IRoseStringCollection; dispid 129; @@ -4313,11 +4096,9 @@ interface function GetIconIndex: Smallint; dispid 12824; end; -// *********************************************************************// -// DispIntf: IRoseAbstractStateCollection -// Flags: (4096) Dispatchable -// GUID: {BEAED5EE-578D-11D2-92AA-004005141253} -// *********************************************************************// + + + IRoseAbstractStateCollection = dispinterface ['{BEAED5EE-578D-11D2-92AA-004005141253}'] property Count: Smallint dispid 202; @@ -4334,11 +4115,9 @@ interface function GetWithUniqueID(const UniqueID: WideString): IRoseAbstractState; dispid 213; end; -// *********************************************************************// -// DispIntf: IRoseRichTypeValuesCollection -// Flags: (4096) Dispatchable -// GUID: {BF8C1040-96DD-11CF-B091-00A0241E3F73} -// *********************************************************************// + + + IRoseRichTypeValuesCollection = dispinterface ['{BF8C1040-96DD-11CF-B091-00A0241E3F73}'] property Count: Smallint dispid 202; @@ -4347,11 +4126,9 @@ interface function IsClass(const theClassName: WideString): WordBool; dispid 12669; end; -// *********************************************************************// -// DispIntf: IRoseSubsystemView -// Flags: (4096) Dispatchable -// GUID: {14028C92-C06C-11D0-89F5-0020AFD6C181} -// *********************************************************************// + + + IRoseSubsystemView = dispinterface ['{14028C92-C06C-11D0-89F5-0020AFD6C181}'] property Name: WideString dispid 100; @@ -4371,7 +4148,7 @@ interface property LineVertices: IRoseLineVertexCollection dispid 12696; function GetUniqueID: WideString; dispid 102; function GetCurrentPropertySetName(const ToolName: WideString): WideString; dispid 109; - function OverrideProperty(const theToolName: WideString; const thePropName: WideString; + function OverrideProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString): WordBool; dispid 110; function InheritProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 111; function GetPropertyValue(const theToolName: WideString; const thePropName: WideString): WideString; dispid 119; @@ -4382,7 +4159,7 @@ interface function IsOverriddenProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 124; function IsDefaultProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 125; function FindDefaultProperty(const theToolName: WideString; const thePropName: WideString): IRoseProperty; dispid 126; - function CreateProperty(const theToolName: WideString; const thePropName: WideString; + function CreateProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString; const theType: WideString): WordBool; dispid 127; function GetPropertyClassName: WideString; dispid 128; function GetDefaultSetNames(const ToolName: WideString): IRoseStringCollection; dispid 129; @@ -4408,11 +4185,9 @@ interface function GetIconIndex: Smallint; dispid 12824; end; -// *********************************************************************// -// DispIntf: IRoseComponentView -// Flags: (4096) Dispatchable -// GUID: {14028C94-C06C-11D0-89F5-0020AFD6C181} -// *********************************************************************// + + + IRoseComponentView = dispinterface ['{14028C94-C06C-11D0-89F5-0020AFD6C181}'] property Name: WideString dispid 100; @@ -4432,7 +4207,7 @@ interface property LineVertices: IRoseLineVertexCollection dispid 12696; function GetUniqueID: WideString; dispid 102; function GetCurrentPropertySetName(const ToolName: WideString): WideString; dispid 109; - function OverrideProperty(const theToolName: WideString; const thePropName: WideString; + function OverrideProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString): WordBool; dispid 110; function InheritProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 111; function GetPropertyValue(const theToolName: WideString; const thePropName: WideString): WideString; dispid 119; @@ -4443,7 +4218,7 @@ interface function IsOverriddenProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 124; function IsDefaultProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 125; function FindDefaultProperty(const theToolName: WideString; const thePropName: WideString): IRoseProperty; dispid 126; - function CreateProperty(const theToolName: WideString; const thePropName: WideString; + function CreateProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString; const theType: WideString): WordBool; dispid 127; function GetPropertyClassName: WideString; dispid 128; function GetDefaultSetNames(const ToolName: WideString): IRoseStringCollection; dispid 129; @@ -4469,11 +4244,9 @@ interface function GetIconIndex: Smallint; dispid 12824; end; -// *********************************************************************// -// DispIntf: IRoseAttribute -// Flags: (4096) Dispatchable -// GUID: {C78E7024-86E4-11CF-B3D4-00A0241DB1D0} -// *********************************************************************// + + + IRoseAttribute = dispinterface ['{C78E7024-86E4-11CF-B3D4-00A0241DB1D0}'] property Name: WideString dispid 100; @@ -4493,7 +4266,7 @@ interface property StateMachineOwner: IRoseStateMachineOwner dispid 12790; function GetUniqueID: WideString; dispid 102; function GetCurrentPropertySetName(const ToolName: WideString): WideString; dispid 109; - function OverrideProperty(const theToolName: WideString; const thePropName: WideString; + function OverrideProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString): WordBool; dispid 110; function InheritProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 111; function GetPropertyValue(const theToolName: WideString; const thePropName: WideString): WideString; dispid 119; @@ -4504,7 +4277,7 @@ interface function IsOverriddenProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 124; function IsDefaultProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 125; function FindDefaultProperty(const theToolName: WideString; const thePropName: WideString): IRoseProperty; dispid 126; - function CreateProperty(const theToolName: WideString; const thePropName: WideString; + function CreateProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString; const theType: WideString): WordBool; dispid 127; function GetPropertyClassName: WideString; dispid 128; function GetDefaultSetNames(const ToolName: WideString): IRoseStringCollection; dispid 129; @@ -4522,11 +4295,9 @@ interface function GetIconIndex: Smallint; dispid 12824; end; -// *********************************************************************// -// DispIntf: IRoseClassDiagram -// Flags: (4096) Dispatchable -// GUID: {3FD9D002-93B0-11CF-B3D4-00A0241DB1D0} -// *********************************************************************// + + + IRoseClassDiagram = dispinterface ['{3FD9D002-93B0-11CF-B3D4-00A0241DB1D0}'] property Name: WideString dispid 100; @@ -4541,7 +4312,7 @@ interface property ZoomFactor: Smallint dispid 12690; function GetUniqueID: WideString; dispid 102; function GetCurrentPropertySetName(const ToolName: WideString): WideString; dispid 109; - function OverrideProperty(const theToolName: WideString; const thePropName: WideString; + function OverrideProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString): WordBool; dispid 110; function InheritProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 111; function GetPropertyValue(const theToolName: WideString; const thePropName: WideString): WideString; dispid 119; @@ -4552,7 +4323,7 @@ interface function IsOverriddenProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 124; function IsDefaultProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 125; function FindDefaultProperty(const theToolName: WideString; const thePropName: WideString): IRoseProperty; dispid 126; - function CreateProperty(const theToolName: WideString; const thePropName: WideString; + function CreateProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString; const theType: WideString): WordBool; dispid 127; function GetPropertyClassName: WideString; dispid 128; function GetDefaultSetNames(const ToolName: WideString): IRoseStringCollection; dispid 129; @@ -4600,11 +4371,9 @@ interface function GetIconIndex: Smallint; dispid 12824; end; -// *********************************************************************// -// DispIntf: IRoseNoteView -// Flags: (4096) Dispatchable -// GUID: {015655CA-72DF-11D0-95EB-0000F803584A} -// *********************************************************************// + + + IRoseNoteView = dispinterface ['{015655CA-72DF-11D0-95EB-0000F803584A}'] property Name: WideString dispid 100; @@ -4625,7 +4394,7 @@ interface property LineVertices: IRoseLineVertexCollection dispid 12696; function GetUniqueID: WideString; dispid 102; function GetCurrentPropertySetName(const ToolName: WideString): WideString; dispid 109; - function OverrideProperty(const theToolName: WideString; const thePropName: WideString; + function OverrideProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString): WordBool; dispid 110; function InheritProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 111; function GetPropertyValue(const theToolName: WideString; const thePropName: WideString): WideString; dispid 119; @@ -4636,7 +4405,7 @@ interface function IsOverriddenProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 124; function IsDefaultProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 125; function FindDefaultProperty(const theToolName: WideString; const thePropName: WideString): IRoseProperty; dispid 126; - function CreateProperty(const theToolName: WideString; const thePropName: WideString; + function CreateProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString; const theType: WideString): WordBool; dispid 127; function GetPropertyClassName: WideString; dispid 128; function GetDefaultSetNames(const ToolName: WideString): IRoseStringCollection; dispid 129; @@ -4664,11 +4433,9 @@ interface function GetIconIndex: Smallint; dispid 12824; end; -// *********************************************************************// -// DispIntf: IRosePackage -// Flags: (4096) Dispatchable -// GUID: {47D975C1-8A8D-11D0-A214-444553540000} -// *********************************************************************// + + + IRosePackage = dispinterface ['{47D975C1-8A8D-11D0-A214-444553540000}'] property Name: WideString dispid 100; @@ -4681,7 +4448,7 @@ interface property StateMachineOwner: IRoseStateMachineOwner dispid 12790; function GetUniqueID: WideString; dispid 102; function GetCurrentPropertySetName(const ToolName: WideString): WideString; dispid 109; - function OverrideProperty(const theToolName: WideString; const thePropName: WideString; + function OverrideProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString): WordBool; dispid 110; function InheritProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 111; function GetPropertyValue(const theToolName: WideString; const thePropName: WideString): WideString; dispid 119; @@ -4692,7 +4459,7 @@ interface function IsOverriddenProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 124; function IsDefaultProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 125; function FindDefaultProperty(const theToolName: WideString; const thePropName: WideString): IRoseProperty; dispid 126; - function CreateProperty(const theToolName: WideString; const thePropName: WideString; + function CreateProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString; const theType: WideString): WordBool; dispid 127; function GetPropertyClassName: WideString; dispid 128; function GetDefaultSetNames(const ToolName: WideString): IRoseStringCollection; dispid 129; @@ -4730,11 +4497,9 @@ interface function GetIconIndex: Smallint; dispid 12824; end; -// *********************************************************************// -// DispIntf: IRosePathMap -// Flags: (4096) Dispatchable -// GUID: {4C9E2241-84C5-11D0-A214-444553540000} -// *********************************************************************// + + + IRosePathMap = dispinterface ['{4C9E2241-84C5-11D0-A214-444553540000}'] function DeleteEntry(const Symbol: WideString): WordBool; dispid 50; @@ -4746,11 +4511,9 @@ interface function GetVirtualPathWithContext(const ActualPath: WideString; const Context: WideString): WideString; dispid 12675; end; -// *********************************************************************// -// DispIntf: IRoseSyncItemViewCollection -// Flags: (4096) Dispatchable -// GUID: {94CA1891-5D13-11D2-92AA-004005141253} -// *********************************************************************// + + + IRoseSyncItemViewCollection = dispinterface ['{94CA1891-5D13-11D2-92AA-004005141253}'] property Count: Smallint dispid 202; @@ -4767,11 +4530,9 @@ interface function GetWithUniqueID(const UniqueID: WideString): IRoseSyncItemView; dispid 213; end; -// *********************************************************************// -// DispIntf: IRoseAbstractState -// Flags: (4096) Dispatchable -// GUID: {BEAED5EC-578D-11D2-92AA-004005141253} -// *********************************************************************// + + + IRoseAbstractState = dispinterface ['{BEAED5EC-578D-11D2-92AA-004005141253}'] property Name: WideString dispid 100; @@ -4791,7 +4552,7 @@ interface property SubSynchronizations: IRoseSyncItemCollection dispid 12804; function GetUniqueID: WideString; dispid 102; function GetCurrentPropertySetName(const ToolName: WideString): WideString; dispid 109; - function OverrideProperty(const theToolName: WideString; const thePropName: WideString; + function OverrideProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString): WordBool; dispid 110; function InheritProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 111; function GetPropertyValue(const theToolName: WideString; const thePropName: WideString): WideString; dispid 119; @@ -4802,7 +4563,7 @@ interface function IsOverriddenProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 124; function IsDefaultProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 125; function FindDefaultProperty(const theToolName: WideString; const thePropName: WideString): IRoseProperty; dispid 126; - function CreateProperty(const theToolName: WideString; const thePropName: WideString; + function CreateProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString; const theType: WideString): WordBool; dispid 127; function GetPropertyClassName: WideString; dispid 128; function GetDefaultSetNames(const ToolName: WideString): IRoseStringCollection; dispid 129; @@ -4842,11 +4603,9 @@ interface function GetIconIndex: Smallint; dispid 12824; end; -// *********************************************************************// -// DispIntf: IRoseModuleVisibilityRelationshipCollection -// Flags: (4096) Dispatchable -// GUID: {97B38363-A4E3-11D0-BFF0-00AA003DEF5B} -// *********************************************************************// + + + IRoseModuleVisibilityRelationshipCollection = dispinterface ['{97B38363-A4E3-11D0-BFF0-00AA003DEF5B}'] property Count: Smallint dispid 202; @@ -4863,11 +4622,9 @@ interface function GetWithUniqueID(const UniqueID: WideString): IRoseModuleVisibilityRelationship; dispid 213; end; -// *********************************************************************// -// DispIntf: IRoseClassCollection -// Flags: (4096) Dispatchable -// GUID: {97B38349-A4E3-11D0-BFF0-00AA003DEF5B} -// *********************************************************************// + + + IRoseClassCollection = dispinterface ['{97B38349-A4E3-11D0-BFF0-00AA003DEF5B}'] property Count: Smallint dispid 202; @@ -4884,11 +4641,9 @@ interface function GetWithUniqueID(const UniqueID: WideString): IRoseClass; dispid 213; end; -// *********************************************************************// -// DispIntf: IRoseMessage -// Flags: (4096) Dispatchable -// GUID: {F819833C-FC55-11CF-BBD3-00A024C67143} -// *********************************************************************// + + + IRoseMessage = dispinterface ['{F819833C-FC55-11CF-BBD3-00A024C67143}'] property Name: WideString dispid 100; @@ -4903,7 +4658,7 @@ interface property StateMachineOwner: IRoseStateMachineOwner dispid 12790; function GetUniqueID: WideString; dispid 102; function GetCurrentPropertySetName(const ToolName: WideString): WideString; dispid 109; - function OverrideProperty(const theToolName: WideString; const thePropName: WideString; + function OverrideProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString): WordBool; dispid 110; function InheritProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 111; function GetPropertyValue(const theToolName: WideString; const thePropName: WideString): WideString; dispid 119; @@ -4914,7 +4669,7 @@ interface function IsOverriddenProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 124; function IsDefaultProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 125; function FindDefaultProperty(const theToolName: WideString; const thePropName: WideString): IRoseProperty; dispid 126; - function CreateProperty(const theToolName: WideString; const thePropName: WideString; + function CreateProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString; const theType: WideString): WordBool; dispid 127; function GetPropertyClassName: WideString; dispid 128; function GetDefaultSetNames(const ToolName: WideString): IRoseStringCollection; dispid 129; @@ -4939,11 +4694,9 @@ interface function GetSequenceInformation: WideString; dispid 12825; end; -// *********************************************************************// -// DispIntf: IRoseConnectionRelationCollection -// Flags: (4096) Dispatchable -// GUID: {4467F446-F24E-11D2-92AA-004005141253} -// *********************************************************************// + + + IRoseConnectionRelationCollection = dispinterface ['{4467F446-F24E-11D2-92AA-004005141253}'] property Count: Smallint dispid 202; @@ -4960,11 +4713,9 @@ interface function GetWithUniqueID(const UniqueID: WideString): IRoseConnectionRelation; dispid 213; end; -// *********************************************************************// -// DispIntf: IRoseClassDependencyCollection -// Flags: (4096) Dispatchable -// GUID: {ED042E4F-6CDE-11D1-BC1E-00A024C67143} -// *********************************************************************// + + + IRoseClassDependencyCollection = dispinterface ['{ED042E4F-6CDE-11D1-BC1E-00A024C67143}'] property Count: Smallint dispid 202; @@ -4981,11 +4732,9 @@ interface function GetWithUniqueID(const UniqueID: WideString): IRoseClassDependency; dispid 213; end; -// *********************************************************************// -// DispIntf: IRoseAssociation -// Flags: (4096) Dispatchable -// GUID: {C78E7026-86E4-11CF-B3D4-00A0241DB1D0} -// *********************************************************************// + + + IRoseAssociation = dispinterface ['{C78E7026-86E4-11CF-B3D4-00A0241DB1D0}'] property Name: WideString dispid 100; @@ -5005,7 +4754,7 @@ interface property ParentCategory: IRoseCategory dispid 12798; function GetUniqueID: WideString; dispid 102; function GetCurrentPropertySetName(const ToolName: WideString): WideString; dispid 109; - function OverrideProperty(const theToolName: WideString; const thePropName: WideString; + function OverrideProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString): WordBool; dispid 110; function InheritProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 111; function GetPropertyValue(const theToolName: WideString; const thePropName: WideString): WideString; dispid 119; @@ -5016,7 +4765,7 @@ interface function IsOverriddenProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 124; function IsDefaultProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 125; function FindDefaultProperty(const theToolName: WideString; const thePropName: WideString): IRoseProperty; dispid 126; - function CreateProperty(const theToolName: WideString; const thePropName: WideString; + function CreateProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString; const theType: WideString): WordBool; dispid 127; function GetPropertyClassName: WideString; dispid 128; function GetDefaultSetNames(const ToolName: WideString): IRoseStringCollection; dispid 129; @@ -5041,11 +4790,9 @@ interface function GetIconIndex: Smallint; dispid 12824; end; -// *********************************************************************// -// DispIntf: IRoseEventCollection -// Flags: (4096) Dispatchable -// GUID: {97B38361-A4E3-11D0-BFF0-00AA003DEF5B} -// *********************************************************************// + + + IRoseEventCollection = dispinterface ['{97B38361-A4E3-11D0-BFF0-00AA003DEF5B}'] property Count: Smallint dispid 202; @@ -5062,11 +4809,9 @@ interface function GetWithUniqueID(const UniqueID: WideString): IRoseEvent; dispid 213; end; -// *********************************************************************// -// DispIntf: IRoseStateCollection -// Flags: (4096) Dispatchable -// GUID: {97B38367-A4E3-11D0-BFF0-00AA003DEF5B} -// *********************************************************************// + + + IRoseStateCollection = dispinterface ['{97B38367-A4E3-11D0-BFF0-00AA003DEF5B}'] property Count: Smallint dispid 202; @@ -5083,11 +4828,9 @@ interface function GetWithUniqueID(const UniqueID: WideString): IRoseState; dispid 213; end; -// *********************************************************************// -// DispIntf: IRoseSyncItemView -// Flags: (4096) Dispatchable -// GUID: {94CA1888-5D13-11D2-92AA-004005141253} -// *********************************************************************// + + + IRoseSyncItemView = dispinterface ['{94CA1888-5D13-11D2-92AA-004005141253}'] property Name: WideString dispid 100; @@ -5108,7 +4851,7 @@ interface property Horizontal: WordBool dispid 12789; function GetUniqueID: WideString; dispid 102; function GetCurrentPropertySetName(const ToolName: WideString): WideString; dispid 109; - function OverrideProperty(const theToolName: WideString; const thePropName: WideString; + function OverrideProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString): WordBool; dispid 110; function InheritProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 111; function GetPropertyValue(const theToolName: WideString; const thePropName: WideString): WideString; dispid 119; @@ -5119,7 +4862,7 @@ interface function IsOverriddenProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 124; function IsDefaultProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 125; function FindDefaultProperty(const theToolName: WideString; const thePropName: WideString): IRoseProperty; dispid 126; - function CreateProperty(const theToolName: WideString; const thePropName: WideString; + function CreateProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString; const theType: WideString): WordBool; dispid 127; function GetPropertyClassName: WideString; dispid 128; function GetDefaultSetNames(const ToolName: WideString): IRoseStringCollection; dispid 129; @@ -5145,11 +4888,9 @@ interface function GetIconIndex: Smallint; dispid 12824; end; -// *********************************************************************// -// DispIntf: IRoseActivityView -// Flags: (4096) Dispatchable -// GUID: {BEAED5FC-578D-11D2-92AA-004005141253} -// *********************************************************************// + + + IRoseActivityView = dispinterface ['{BEAED5FC-578D-11D2-92AA-004005141253}'] property Name: WideString dispid 100; @@ -5169,7 +4910,7 @@ interface property LineVertices: IRoseLineVertexCollection dispid 12696; function GetUniqueID: WideString; dispid 102; function GetCurrentPropertySetName(const ToolName: WideString): WideString; dispid 109; - function OverrideProperty(const theToolName: WideString; const thePropName: WideString; + function OverrideProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString): WordBool; dispid 110; function InheritProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 111; function GetPropertyValue(const theToolName: WideString; const thePropName: WideString): WideString; dispid 119; @@ -5180,7 +4921,7 @@ interface function IsOverriddenProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 124; function IsDefaultProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 125; function FindDefaultProperty(const theToolName: WideString; const thePropName: WideString): IRoseProperty; dispid 126; - function CreateProperty(const theToolName: WideString; const thePropName: WideString; + function CreateProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString; const theType: WideString): WordBool; dispid 127; function GetPropertyClassName: WideString; dispid 128; function GetDefaultSetNames(const ToolName: WideString): IRoseStringCollection; dispid 129; @@ -5206,11 +4947,9 @@ interface function GetIconIndex: Smallint; dispid 12824; end; -// *********************************************************************// -// DispIntf: IRoseStateView -// Flags: (4096) Dispatchable -// GUID: {7BD909E1-9AF9-11D0-A214-00A024FFFE40} -// *********************************************************************// + + + IRoseStateView = dispinterface ['{7BD909E1-9AF9-11D0-A214-00A024FFFE40}'] property Name: WideString dispid 100; @@ -5230,7 +4969,7 @@ interface property LineVertices: IRoseLineVertexCollection dispid 12696; function GetUniqueID: WideString; dispid 102; function GetCurrentPropertySetName(const ToolName: WideString): WideString; dispid 109; - function OverrideProperty(const theToolName: WideString; const thePropName: WideString; + function OverrideProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString): WordBool; dispid 110; function InheritProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 111; function GetPropertyValue(const theToolName: WideString; const thePropName: WideString): WideString; dispid 119; @@ -5241,7 +4980,7 @@ interface function IsOverriddenProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 124; function IsDefaultProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 125; function FindDefaultProperty(const theToolName: WideString; const thePropName: WideString): IRoseProperty; dispid 126; - function CreateProperty(const theToolName: WideString; const thePropName: WideString; + function CreateProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString; const theType: WideString): WordBool; dispid 127; function GetPropertyClassName: WideString; dispid 128; function GetDefaultSetNames(const ToolName: WideString): IRoseStringCollection; dispid 129; @@ -5267,11 +5006,9 @@ interface function GetIconIndex: Smallint; dispid 12824; end; -// *********************************************************************// -// DispIntf: IRoseStateVertexCollection -// Flags: (4096) Dispatchable -// GUID: {BEAED5F7-578D-11D2-92AA-004005141253} -// *********************************************************************// + + + IRoseStateVertexCollection = dispinterface ['{BEAED5F7-578D-11D2-92AA-004005141253}'] property Count: Smallint dispid 202; @@ -5288,11 +5025,9 @@ interface function GetWithUniqueID(const UniqueID: WideString): IRoseStateVertex; dispid 213; end; -// *********************************************************************// -// DispIntf: IRoseSubsystemViewCollection -// Flags: (4096) Dispatchable -// GUID: {CA3AD902-BFCE-11D0-89F5-0020AFD6C181} -// *********************************************************************// + + + IRoseSubsystemViewCollection = dispinterface ['{CA3AD902-BFCE-11D0-89F5-0020AFD6C181}'] property Count: Smallint dispid 202; @@ -5309,11 +5044,9 @@ interface function GetWithUniqueID(const UniqueID: WideString): IRoseSubsystemView; dispid 213; end; -// *********************************************************************// -// DispIntf: IRoseModuleDiagram -// Flags: (4096) Dispatchable -// GUID: {3FD9D004-93B0-11CF-B3D4-00A0241DB1D0} -// *********************************************************************// + + + IRoseModuleDiagram = dispinterface ['{3FD9D004-93B0-11CF-B3D4-00A0241DB1D0}'] property Name: WideString dispid 100; @@ -5330,7 +5063,7 @@ interface property ZoomFactor: Smallint dispid 12690; function GetUniqueID: WideString; dispid 102; function GetCurrentPropertySetName(const ToolName: WideString): WideString; dispid 109; - function OverrideProperty(const theToolName: WideString; const thePropName: WideString; + function OverrideProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString): WordBool; dispid 110; function InheritProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 111; function GetPropertyValue(const theToolName: WideString; const thePropName: WideString): WideString; dispid 119; @@ -5341,7 +5074,7 @@ interface function IsOverriddenProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 124; function IsDefaultProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 125; function FindDefaultProperty(const theToolName: WideString; const thePropName: WideString): IRoseProperty; dispid 126; - function CreateProperty(const theToolName: WideString; const thePropName: WideString; + function CreateProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString; const theType: WideString): WordBool; dispid 127; function GetPropertyClassName: WideString; dispid 128; function GetDefaultSetNames(const ToolName: WideString): IRoseStringCollection; dispid 129; @@ -5381,11 +5114,9 @@ interface function GetIconIndex: Smallint; dispid 12824; end; -// *********************************************************************// -// DispIntf: IRoseSubsystem -// Flags: (4096) Dispatchable -// GUID: {C78E702C-86E4-11CF-B3D4-00A0241DB1D0} -// *********************************************************************// + + + IRoseSubsystem = dispinterface ['{C78E702C-86E4-11CF-B3D4-00A0241DB1D0}'] property Name: WideString dispid 100; @@ -5402,7 +5133,7 @@ interface property StateMachineOwner: IRoseStateMachineOwner dispid 12790; function GetUniqueID: WideString; dispid 102; function GetCurrentPropertySetName(const ToolName: WideString): WideString; dispid 109; - function OverrideProperty(const theToolName: WideString; const thePropName: WideString; + function OverrideProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString): WordBool; dispid 110; function InheritProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 111; function GetPropertyValue(const theToolName: WideString; const thePropName: WideString): WideString; dispid 119; @@ -5413,7 +5144,7 @@ interface function IsOverriddenProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 124; function IsDefaultProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 125; function FindDefaultProperty(const theToolName: WideString; const thePropName: WideString): IRoseProperty; dispid 126; - function CreateProperty(const theToolName: WideString; const thePropName: WideString; + function CreateProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString; const theType: WideString): WordBool; dispid 127; function GetPropertyClassName: WideString; dispid 128; function GetDefaultSetNames(const ToolName: WideString): IRoseStringCollection; dispid 129; @@ -5470,11 +5201,9 @@ interface function GetIconIndex: Smallint; dispid 12824; end; -// *********************************************************************// -// DispIntf: IRoseExternalDocumentCollection -// Flags: (4096) Dispatchable -// GUID: {97B38357-A4E3-11D0-BFF0-00AA003DEF5B} -// *********************************************************************// + + + IRoseExternalDocumentCollection = dispinterface ['{97B38357-A4E3-11D0-BFF0-00AA003DEF5B}'] property Count: Smallint dispid 202; @@ -5491,11 +5220,9 @@ interface function GetWithUniqueID(const UniqueID: WideString): IRoseExternalDocument; dispid 213; end; -// *********************************************************************// -// DispIntf: IRoseInstanceViewCollection -// Flags: (4096) Dispatchable -// GUID: {C640C864-F2D3-11D0-883A-3C8B00C10000} -// *********************************************************************// + + + IRoseInstanceViewCollection = dispinterface ['{C640C864-F2D3-11D0-883A-3C8B00C10000}'] property Count: Smallint dispid 202; @@ -5512,11 +5239,9 @@ interface function GetWithUniqueID(const UniqueID: WideString): IRoseInstanceView; dispid 213; end; -// *********************************************************************// -// DispIntf: IRoseItemView -// Flags: (4096) Dispatchable -// GUID: {7DFAFE40-A29D-11CF-B3D4-00A0241DB1D0} -// *********************************************************************// + + + IRoseItemView = dispinterface ['{7DFAFE40-A29D-11CF-B3D4-00A0241DB1D0}'] property Name: WideString dispid 100; @@ -5536,7 +5261,7 @@ interface property LineVertices: IRoseLineVertexCollection dispid 12696; function GetUniqueID: WideString; dispid 102; function GetCurrentPropertySetName(const ToolName: WideString): WideString; dispid 109; - function OverrideProperty(const theToolName: WideString; const thePropName: WideString; + function OverrideProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString): WordBool; dispid 110; function InheritProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 111; function GetPropertyValue(const theToolName: WideString; const thePropName: WideString): WideString; dispid 119; @@ -5547,7 +5272,7 @@ interface function IsOverriddenProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 124; function IsDefaultProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 125; function FindDefaultProperty(const theToolName: WideString; const thePropName: WideString): IRoseProperty; dispid 126; - function CreateProperty(const theToolName: WideString; const thePropName: WideString; + function CreateProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString; const theType: WideString): WordBool; dispid 127; function GetPropertyClassName: WideString; dispid 128; function GetDefaultSetNames(const ToolName: WideString): IRoseStringCollection; dispid 129; @@ -5572,11 +5297,9 @@ interface function GetIconIndex: Smallint; dispid 12824; end; -// *********************************************************************// -// DispIntf: IRoseTransitionCollection -// Flags: (4096) Dispatchable -// GUID: {97B3836B-A4E3-11D0-BFF0-00AA003DEF5B} -// *********************************************************************// + + + IRoseTransitionCollection = dispinterface ['{97B3836B-A4E3-11D0-BFF0-00AA003DEF5B}'] property Count: Smallint dispid 202; @@ -5593,11 +5316,9 @@ interface function GetWithUniqueID(const UniqueID: WideString): IRoseTransition; dispid 213; end; -// *********************************************************************// -// DispIntf: IRoseState -// Flags: (4096) Dispatchable -// GUID: {A69CAB23-9179-11D0-A214-00A024FFFE40} -// *********************************************************************// + + + IRoseState = dispinterface ['{A69CAB23-9179-11D0-A214-00A024FFFE40}'] property Name: WideString dispid 100; @@ -5619,7 +5340,7 @@ interface property SubSynchronizations: IRoseSyncItemCollection dispid 12804; function GetUniqueID: WideString; dispid 102; function GetCurrentPropertySetName(const ToolName: WideString): WideString; dispid 109; - function OverrideProperty(const theToolName: WideString; const thePropName: WideString; + function OverrideProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString): WordBool; dispid 110; function InheritProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 111; function GetPropertyValue(const theToolName: WideString; const thePropName: WideString): WideString; dispid 119; @@ -5630,7 +5351,7 @@ interface function IsOverriddenProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 124; function IsDefaultProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 125; function FindDefaultProperty(const theToolName: WideString; const thePropName: WideString): IRoseProperty; dispid 126; - function CreateProperty(const theToolName: WideString; const thePropName: WideString; + function CreateProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString; const theType: WideString): WordBool; dispid 127; function GetPropertyClassName: WideString; dispid 128; function GetDefaultSetNames(const ToolName: WideString): IRoseStringCollection; dispid 129; @@ -5674,11 +5395,9 @@ interface function GetIconIndex: Smallint; dispid 12824; end; -// *********************************************************************// -// DispIntf: IRoseObjectInstanceCollection -// Flags: (4096) Dispatchable -// GUID: {97B3835A-A4E3-11D0-BFF0-00AA003DEF5B} -// *********************************************************************// + + + IRoseObjectInstanceCollection = dispinterface ['{97B3835A-A4E3-11D0-BFF0-00AA003DEF5B}'] property Count: Smallint dispid 202; @@ -5695,11 +5414,9 @@ interface function GetWithUniqueID(const UniqueID: WideString): IRoseObjectInstance; dispid 213; end; -// *********************************************************************// -// DispIntf: IRoseRoleCollection -// Flags: (4096) Dispatchable -// GUID: {97B38353-A4E3-11D0-BFF0-00AA003DEF5B} -// *********************************************************************// + + + IRoseRoleCollection = dispinterface ['{97B38353-A4E3-11D0-BFF0-00AA003DEF5B}'] property Count: Smallint dispid 202; @@ -5716,11 +5433,9 @@ interface function GetWithUniqueID(const UniqueID: WideString): IRoseRole; dispid 213; end; -// *********************************************************************// -// DispIntf: IRoseClassRelation -// Flags: (4096) Dispatchable -// GUID: {00C99564-9200-11CF-B1B0-D227D5210B2C} -// *********************************************************************// + + + IRoseClassRelation = dispinterface ['{00C99564-9200-11CF-B1B0-D227D5210B2C}'] property Name: WideString dispid 100; @@ -5734,7 +5449,7 @@ interface property StateMachineOwner: IRoseStateMachineOwner dispid 12790; function GetUniqueID: WideString; dispid 102; function GetCurrentPropertySetName(const ToolName: WideString): WideString; dispid 109; - function OverrideProperty(const theToolName: WideString; const thePropName: WideString; + function OverrideProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString): WordBool; dispid 110; function InheritProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 111; function GetPropertyValue(const theToolName: WideString; const thePropName: WideString): WideString; dispid 119; @@ -5745,7 +5460,7 @@ interface function IsOverriddenProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 124; function IsDefaultProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 125; function FindDefaultProperty(const theToolName: WideString; const thePropName: WideString): IRoseProperty; dispid 126; - function CreateProperty(const theToolName: WideString; const thePropName: WideString; + function CreateProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString; const theType: WideString): WordBool; dispid 127; function GetPropertyClassName: WideString; dispid 128; function GetDefaultSetNames(const ToolName: WideString): IRoseStringCollection; dispid 129; @@ -5769,11 +5484,9 @@ interface function GetIconIndex: Smallint; dispid 12824; end; -// *********************************************************************// -// DispIntf: IRoseCategory -// Flags: (4096) Dispatchable -// GUID: {D7BC1B45-8618-11CF-B3D4-00A0241DB1D0} -// *********************************************************************// + + + IRoseCategory = dispinterface ['{D7BC1B45-8618-11CF-B3D4-00A0241DB1D0}'] property Name: WideString dispid 100; @@ -5794,7 +5507,7 @@ interface property StateMachineOwner: IRoseStateMachineOwner dispid 12790; function GetUniqueID: WideString; dispid 102; function GetCurrentPropertySetName(const ToolName: WideString): WideString; dispid 109; - function OverrideProperty(const theToolName: WideString; const thePropName: WideString; + function OverrideProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString): WordBool; dispid 110; function InheritProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 111; function GetPropertyValue(const theToolName: WideString; const thePropName: WideString): WideString; dispid 119; @@ -5805,7 +5518,7 @@ interface function IsOverriddenProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 124; function IsDefaultProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 125; function FindDefaultProperty(const theToolName: WideString; const thePropName: WideString): IRoseProperty; dispid 126; - function CreateProperty(const theToolName: WideString; const thePropName: WideString; + function CreateProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString; const theType: WideString): WordBool; dispid 127; function GetPropertyClassName: WideString; dispid 128; function GetDefaultSetNames(const ToolName: WideString): IRoseStringCollection; dispid 129; @@ -5850,7 +5563,7 @@ interface function GetQualifiedName: WideString; dispid 12555; function IsModified: WordBool; dispid 12654; function Uncontrol: WordBool; dispid 12655; - function AddCategoryDependency(const theName: WideString; + function AddCategoryDependency(const theName: WideString; const theSupplierCategoryName: WideString): IRoseCategoryDependency; dispid 12659; function GetCategoryDependencies: IRoseCategoryDependencyCollection; dispid 12660; function DeleteCategoryDependency(const theDependency: IRoseCategoryDependency): WordBool; dispid 12661; @@ -5869,11 +5582,9 @@ interface function GetIconIndex: Smallint; dispid 12824; end; -// *********************************************************************// -// DispIntf: IRoseDefaultModelProperties -// Flags: (4096) Dispatchable -// GUID: {76ACC49D-FA18-11D0-BC11-00A024C67143} -// *********************************************************************// + + + IRoseDefaultModelProperties = dispinterface ['{76ACC49D-FA18-11D0-BC11-00A024C67143}'] property Name: WideString dispid 100; @@ -5886,7 +5597,7 @@ interface property StateMachineOwner: IRoseStateMachineOwner dispid 12790; function GetUniqueID: WideString; dispid 102; function GetCurrentPropertySetName(const ToolName: WideString): WideString; dispid 109; - function OverrideProperty(const theToolName: WideString; const thePropName: WideString; + function OverrideProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString): WordBool; dispid 110; function InheritProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 111; function GetPropertyValue(const theToolName: WideString; const thePropName: WideString): WideString; dispid 119; @@ -5896,7 +5607,7 @@ interface function GetToolProperties(const theToolName: WideString): IRosePropertyCollection; dispid 123; function IsOverriddenProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 124; function IsDefaultProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 125; - function CreateProperty(const theToolName: WideString; const thePropName: WideString; + function CreateProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString; const theType: WideString): WordBool; dispid 127; function GetPropertyClassName: WideString; dispid 128; function GetToolNames: IRoseStringCollection; dispid 130; @@ -5905,22 +5616,22 @@ interface function AddExternalDocument(const szName: WideString; iType: Smallint): IRoseExternalDocument; dispid 214; function DeleteExternalDocument(const pIDispatch: IRoseExternalDocument): WordBool; dispid 215; function OpenSpecification: WordBool; dispid 216; - function AddDefaultProperty(const ClassName: WideString; const ToolName: WideString; - const SetName: WideString; const PropName: WideString; + function AddDefaultProperty(const ClassName: WideString; const ToolName: WideString; + const SetName: WideString; const PropName: WideString; const PropType: WideString; const Value: WideString): WordBool; dispid 440; - function CloneDefaultPropertySet(const ClassName: WideString; const ToolName: WideString; - const ExistingSetName: WideString; + function CloneDefaultPropertySet(const ClassName: WideString; const ToolName: WideString; + const ExistingSetName: WideString; const NewSetName: WideString): WordBool; dispid 441; - function CreateDefaultPropertySet(const ClassName: WideString; const ToolName: WideString; + function CreateDefaultPropertySet(const ClassName: WideString; const ToolName: WideString; const NewSetName: WideString): WordBool; dispid 442; - function DeleteDefaultPropertySet(const ClassName: WideString; const ToolName: WideString; + function DeleteDefaultPropertySet(const ClassName: WideString; const ToolName: WideString; const SetName: WideString): WordBool; dispid 443; - function GetDefaultPropertySet(const ClassName: WideString; const ToolName: WideString; + function GetDefaultPropertySet(const ClassName: WideString; const ToolName: WideString; const SetName: WideString): IRosePropertyCollection; dispid 444; - function FindDefaultProperty(const ClassName: WideString; const ToolName: WideString; + function FindDefaultProperty(const ClassName: WideString; const ToolName: WideString; const SetName: WideString; const PropName: WideString): IRoseProperty; dispid 445; function GetDefaultSetNames(const ClassName: WideString; const ToolName: WideString): IRoseStringCollection; dispid 447; - function DeleteDefaultProperty(const ClassName: WideString; const ToolName: WideString; + function DeleteDefaultProperty(const ClassName: WideString; const ToolName: WideString; const SetName: WideString; const PropName: WideString): WordBool; dispid 449; function IsControlled: WordBool; dispid 12433; function Control(const Path: WideString): WordBool; dispid 12434; @@ -5951,11 +5662,9 @@ interface function GetIconIndex: Smallint; dispid 12824; end; -// *********************************************************************// -// DispIntf: IRoseStateMachineCollection -// Flags: (4096) Dispatchable -// GUID: {97B38369-A4E3-11D0-BFF0-00AA003DEF5B} -// *********************************************************************// + + + IRoseStateMachineCollection = dispinterface ['{97B38369-A4E3-11D0-BFF0-00AA003DEF5B}'] property Count: Smallint dispid 202; @@ -5972,11 +5681,9 @@ interface function GetWithUniqueID(const UniqueID: WideString): IRoseStateMachine; dispid 213; end; -// *********************************************************************// -// DispIntf: IRoseSyncItem -// Flags: (4096) Dispatchable -// GUID: {94CA188B-5D13-11D2-92AA-004005141253} -// *********************************************************************// + + + IRoseSyncItem = dispinterface ['{94CA188B-5D13-11D2-92AA-004005141253}'] property Name: WideString dispid 100; @@ -5992,7 +5699,7 @@ interface property StateMachineOwner: IRoseStateMachineOwner dispid 12790; function GetUniqueID: WideString; dispid 102; function GetCurrentPropertySetName(const ToolName: WideString): WideString; dispid 109; - function OverrideProperty(const theToolName: WideString; const thePropName: WideString; + function OverrideProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString): WordBool; dispid 110; function InheritProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 111; function GetPropertyValue(const theToolName: WideString; const thePropName: WideString): WideString; dispid 119; @@ -6003,7 +5710,7 @@ interface function IsOverriddenProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 124; function IsDefaultProperty(const theToolName: WideString; const thePropName: WideString): WordBool; dispid 125; function FindDefaultProperty(const theToolName: WideString; const thePropName: WideString): IRoseProperty; dispid 126; - function CreateProperty(const theToolName: WideString; const thePropName: WideString; + function CreateProperty(const theToolName: WideString; const thePropName: WideString; const theValue: WideString; const theType: WideString): WordBool; dispid 127; function GetPropertyClassName: WideString; dispid 128; function GetDefaultSetNames(const ToolName: WideString): IRoseStringCollection; dispid 129; @@ -6025,11 +5732,9 @@ interface function GetIconIndex: Smallint; dispid 12824; end; -// *********************************************************************// -// DispIntf: IRoseRealizeRelationCollection -// Flags: (4096) Dispatchable -// GUID: {67448181-4553-11D1-883B-3C8B00C10000} -// *********************************************************************// + + + IRoseRealizeRelationCollection = dispinterface ['{67448181-4553-11D1-883B-3C8B00C10000}'] property Count: Smallint dispid 202; @@ -6046,11 +5751,9 @@ interface function GetWithUniqueID(const UniqueID: WideString): IRoseRealizeRelation; dispid 213; end; -// *********************************************************************// -// DispIntf: IRosePackageCollection -// Flags: (4096) Dispatchable -// GUID: {97B38364-A4E3-11D0-BFF0-00AA003DEF5B} -// *********************************************************************// + + + IRosePackageCollection = dispinterface ['{97B38364-A4E3-11D0-BFF0-00AA003DEF5B}'] property Count: Smallint dispid 202; @@ -6067,11 +5770,9 @@ interface function GetWithUniqueID(const UniqueID: WideString): IRosePackage; dispid 213; end; -// *********************************************************************// -// DispIntf: IRoseExternalDocument -// Flags: (4096) Dispatchable -// GUID: {906FF583-276B-11D0-8980-00A024774419} -// *********************************************************************// + + + IRoseExternalDocument = dispinterface ['{906FF583-276B-11D0-8980-00A024774419}'] property Path: WideString dispid 1; @@ -6087,1633 +5788,1361 @@ interface function GetIconIndex: Smallint; dispid 12824; end; -// *********************************************************************// -// The Class CoRoseActivityViewCollection provides a Create and CreateRemote method to -// create instances of the default interface IRoseActivityViewCollection exposed by -// the CoClass RoseActivityViewCollection. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseActivityViewCollection = class class function Create: IRoseActivityViewCollection; class function CreateRemote(const MachineName: string): IRoseActivityViewCollection; end; -// *********************************************************************// -// The Class CoRoseProcessorCollection provides a Create and CreateRemote method to -// create instances of the default interface IRoseProcessorCollection exposed by -// the CoClass RoseProcessorCollection. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseProcessorCollection = class class function Create: IRoseProcessorCollection; class function CreateRemote(const MachineName: string): IRoseProcessorCollection; end; -// *********************************************************************// -// The Class CoRoseCategoryCollection provides a Create and CreateRemote method to -// create instances of the default interface IRoseCategoryCollection exposed by -// the CoClass RoseCategoryCollection. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseCategoryCollection = class class function Create: IRoseCategoryCollection; class function CreateRemote(const MachineName: string): IRoseCategoryCollection; end; -// *********************************************************************// -// The Class CoRoseDeploymentUnit provides a Create and CreateRemote method to -// create instances of the default interface IRoseDeploymentUnit exposed by -// the CoClass RoseDeploymentUnit. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseDeploymentUnit = class class function Create: IRoseDeploymentUnit; class function CreateRemote(const MachineName: string): IRoseDeploymentUnit; end; -// *********************************************************************// -// The Class CoRoseItem provides a Create and CreateRemote method to -// create instances of the default interface IRoseItem exposed by -// the CoClass RoseItem. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseItem = class class function Create: IRoseItem; class function CreateRemote(const MachineName: string): IRoseItem; end; -// *********************************************************************// -// The Class CoRoseContextMenuItemCollection provides a Create and CreateRemote method to -// create instances of the default interface IRoseContextMenuItemCollection exposed by -// the CoClass RoseContextMenuItemCollection. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseContextMenuItemCollection = class class function Create: IRoseContextMenuItemCollection; class function CreateRemote(const MachineName: string): IRoseContextMenuItemCollection; end; -// *********************************************************************// -// The Class CoRoseAddIn provides a Create and CreateRemote method to -// create instances of the default interface IRoseAddIn exposed by -// the CoClass RoseAddIn. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseAddIn = class class function Create: IRoseAddIn; class function CreateRemote(const MachineName: string): IRoseAddIn; end; -// *********************************************************************// -// The Class CoRoseDecisionViewCollection provides a Create and CreateRemote method to -// create instances of the default interface IRoseDecisionViewCollection exposed by -// the CoClass RoseDecisionViewCollection. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseDecisionViewCollection = class class function Create: IRoseDecisionViewCollection; class function CreateRemote(const MachineName: string): IRoseDecisionViewCollection; end; -// *********************************************************************// -// The Class CoRoseStateVertex provides a Create and CreateRemote method to -// create instances of the default interface IRoseStateVertex exposed by -// the CoClass RoseStateVertex. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseStateVertex = class class function Create: IRoseStateVertex; class function CreateRemote(const MachineName: string): IRoseStateVertex; end; -// *********************************************************************// -// The Class CoRoseUseCaseCollection provides a Create and CreateRemote method to -// create instances of the default interface IRoseUseCaseCollection exposed by -// the CoClass RoseUseCaseCollection. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseUseCaseCollection = class class function Create: IRoseUseCaseCollection; class function CreateRemote(const MachineName: string): IRoseUseCaseCollection; end; -// *********************************************************************// -// The Class CoRoseConnectionRelation provides a Create and CreateRemote method to -// create instances of the default interface IRoseConnectionRelation exposed by -// the CoClass RoseConnectionRelation. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseConnectionRelation = class class function Create: IRoseConnectionRelation; class function CreateRemote(const MachineName: string): IRoseConnectionRelation; end; -// *********************************************************************// -// The Class CoRoseRelation provides a Create and CreateRemote method to -// create instances of the default interface IRoseRelation exposed by -// the CoClass RoseRelation. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseRelation = class class function Create: IRoseRelation; class function CreateRemote(const MachineName: string): IRoseRelation; end; -// *********************************************************************// -// The Class CoRoseApplication provides a Create and CreateRemote method to -// create instances of the default interface IRoseApplication exposed by -// the CoClass RoseApplication. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseApplication = class class function Create: IRoseApplication; class function CreateRemote(const MachineName: string): IRoseApplication; end; -// *********************************************************************// -// The Class CoRoseDecisionCollection provides a Create and CreateRemote method to -// create instances of the default interface IRoseDecisionCollection exposed by -// the CoClass RoseDecisionCollection. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseDecisionCollection = class class function Create: IRoseDecisionCollection; class function CreateRemote(const MachineName: string): IRoseDecisionCollection; end; -// *********************************************************************// -// The Class CoRoseDecision provides a Create and CreateRemote method to -// create instances of the default interface IRoseDecision exposed by -// the CoClass RoseDecision. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseDecision = class class function Create: IRoseDecision; class function CreateRemote(const MachineName: string): IRoseDecision; end; -// *********************************************************************// -// The Class CoRoseLineVertexCollection provides a Create and CreateRemote method to -// create instances of the default interface IRoseLineVertexCollection exposed by -// the CoClass RoseLineVertexCollection. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseLineVertexCollection = class class function Create: IRoseLineVertexCollection; class function CreateRemote(const MachineName: string): IRoseLineVertexCollection; end; -// *********************************************************************// -// The Class CoRoseInstantiateRelationCollection provides a Create and CreateRemote method to -// create instances of the default interface IRoseInstantiateRelationCollection exposed by -// the CoClass RoseInstantiateRelationCollection. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseInstantiateRelationCollection = class class function Create: IRoseInstantiateRelationCollection; class function CreateRemote(const MachineName: string): IRoseInstantiateRelationCollection; end; -// *********************************************************************// -// The Class CoRoseMessageCollection provides a Create and CreateRemote method to -// create instances of the default interface IRoseMessageCollection exposed by -// the CoClass RoseMessageCollection. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseMessageCollection = class class function Create: IRoseMessageCollection; class function CreateRemote(const MachineName: string): IRoseMessageCollection; end; -// *********************************************************************// -// The Class CoRoseClassDiagramCollection provides a Create and CreateRemote method to -// create instances of the default interface IRoseClassDiagramCollection exposed by -// the CoClass RoseClassDiagramCollection. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseClassDiagramCollection = class class function Create: IRoseClassDiagramCollection; class function CreateRemote(const MachineName: string): IRoseClassDiagramCollection; end; -// *********************************************************************// -// The Class CoRoseScenarioDiagram provides a Create and CreateRemote method to -// create instances of the default interface IRoseScenarioDiagram exposed by -// the CoClass RoseScenarioDiagram. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseScenarioDiagram = class class function Create: IRoseScenarioDiagram; class function CreateRemote(const MachineName: string): IRoseScenarioDiagram; end; -// *********************************************************************// -// The Class CoRoseRealizeRelation provides a Create and CreateRemote method to -// create instances of the default interface IRoseRealizeRelation exposed by -// the CoClass RoseRealizeRelation. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseRealizeRelation = class class function Create: IRoseRealizeRelation; class function CreateRemote(const MachineName: string): IRoseRealizeRelation; end; -// *********************************************************************// -// The Class CoRoseHasRelationship provides a Create and CreateRemote method to -// create instances of the default interface IRoseHasRelationship exposed by -// the CoClass RoseHasRelationship. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseHasRelationship = class class function Create: IRoseHasRelationship; class function CreateRemote(const MachineName: string): IRoseHasRelationship; end; -// *********************************************************************// -// The Class CoRoseClassView provides a Create and CreateRemote method to -// create instances of the default interface IRoseClassView exposed by -// the CoClass RoseClassView. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseClassView = class class function Create: IRoseClassView; class function CreateRemote(const MachineName: string): IRoseClassView; end; -// *********************************************************************// -// The Class CoRoseView_FillColor provides a Create and CreateRemote method to -// create instances of the default interface IRoseView_FillColor exposed by -// the CoClass RoseView_FillColor. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseView_FillColor = class class function Create: IRoseView_FillColor; class function CreateRemote(const MachineName: string): IRoseView_FillColor; end; -// *********************************************************************// -// The Class CoRoseActionCollection provides a Create and CreateRemote method to -// create instances of the default interface IRoseActionCollection exposed by -// the CoClass RoseActionCollection. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseActionCollection = class class function Create: IRoseActionCollection; class function CreateRemote(const MachineName: string): IRoseActionCollection; end; -// *********************************************************************// -// The Class CoRoseSyncItemCollection provides a Create and CreateRemote method to -// create instances of the default interface IRoseSyncItemCollection exposed by -// the CoClass RoseSyncItemCollection. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseSyncItemCollection = class class function Create: IRoseSyncItemCollection; class function CreateRemote(const MachineName: string): IRoseSyncItemCollection; end; -// *********************************************************************// -// The Class CoRoseActivityCollection provides a Create and CreateRemote method to -// create instances of the default interface IRoseActivityCollection exposed by -// the CoClass RoseActivityCollection. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseActivityCollection = class class function Create: IRoseActivityCollection; class function CreateRemote(const MachineName: string): IRoseActivityCollection; end; -// *********************************************************************// -// The Class CoRoseActivity provides a Create and CreateRemote method to -// create instances of the default interface IRoseActivity exposed by -// the CoClass RoseActivity. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseActivity = class class function Create: IRoseActivity; class function CreateRemote(const MachineName: string): IRoseActivity; end; -// *********************************************************************// -// The Class CoRoseProcess provides a Create and CreateRemote method to -// create instances of the default interface IRoseProcess exposed by -// the CoClass RoseProcess. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseProcess = class class function Create: IRoseProcess; class function CreateRemote(const MachineName: string): IRoseProcess; end; -// *********************************************************************// -// The Class CoRoseAddInCollection provides a Create and CreateRemote method to -// create instances of the default interface IRoseAddInCollection exposed by -// the CoClass RoseAddInCollection. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseAddInCollection = class class function Create: IRoseAddInCollection; class function CreateRemote(const MachineName: string): IRoseAddInCollection; end; -// *********************************************************************// -// The Class CoRoseSwimLaneView provides a Create and CreateRemote method to -// create instances of the default interface IRoseSwimLaneView exposed by -// the CoClass RoseSwimLaneView. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseSwimLaneView = class class function Create: IRoseSwimLaneView; class function CreateRemote(const MachineName: string): IRoseSwimLaneView; end; -// *********************************************************************// -// The Class CoRoseControllableUnitCollection provides a Create and CreateRemote method to -// create instances of the default interface IRoseControllableUnitCollection exposed by -// the CoClass RoseControllableUnitCollection. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseControllableUnitCollection = class class function Create: IRoseControllableUnitCollection; class function CreateRemote(const MachineName: string): IRoseControllableUnitCollection; end; -// *********************************************************************// -// The Class CoRoseModuleCollection provides a Create and CreateRemote method to -// create instances of the default interface IRoseModuleCollection exposed by -// the CoClass RoseModuleCollection. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseModuleCollection = class class function Create: IRoseModuleCollection; class function CreateRemote(const MachineName: string): IRoseModuleCollection; end; -// *********************************************************************// -// The Class CoRoseLinkCollection provides a Create and CreateRemote method to -// create instances of the default interface IRoseLinkCollection exposed by -// the CoClass RoseLinkCollection. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseLinkCollection = class class function Create: IRoseLinkCollection; class function CreateRemote(const MachineName: string): IRoseLinkCollection; end; -// *********************************************************************// -// The Class CoRoseAction provides a Create and CreateRemote method to -// create instances of the default interface IRoseAction exposed by -// the CoClass RoseAction. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseAction = class class function Create: IRoseAction; class function CreateRemote(const MachineName: string): IRoseAction; end; -// *********************************************************************// -// The Class CoRoseParameterCollection provides a Create and CreateRemote method to -// create instances of the default interface IRoseParameterCollection exposed by -// the CoClass RoseParameterCollection. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseParameterCollection = class class function Create: IRoseParameterCollection; class function CreateRemote(const MachineName: string): IRoseParameterCollection; end; -// *********************************************************************// -// The Class CoRoseAttributeCollection provides a Create and CreateRemote method to -// create instances of the default interface IRoseAttributeCollection exposed by -// the CoClass RoseAttributeCollection. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseAttributeCollection = class class function Create: IRoseAttributeCollection; class function CreateRemote(const MachineName: string): IRoseAttributeCollection; end; -// *********************************************************************// -// The Class CoRoseDevice provides a Create and CreateRemote method to -// create instances of the default interface IRoseDevice exposed by -// the CoClass RoseDevice. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseDevice = class class function Create: IRoseDevice; class function CreateRemote(const MachineName: string): IRoseDevice; end; -// *********************************************************************// -// The Class CoRoseClassDependency provides a Create and CreateRemote method to -// create instances of the default interface IRoseClassDependency exposed by -// the CoClass RoseClassDependency. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseClassDependency = class class function Create: IRoseClassDependency; class function CreateRemote(const MachineName: string): IRoseClassDependency; end; -// *********************************************************************// -// The Class CoRoseRole provides a Create and CreateRemote method to -// create instances of the default interface IRoseRole exposed by -// the CoClass RoseRole. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseRole = class class function Create: IRoseRole; class function CreateRemote(const MachineName: string): IRoseRole; end; -// *********************************************************************// -// The Class CoRoseClass provides a Create and CreateRemote method to -// create instances of the default interface IRoseClass exposed by -// the CoClass RoseClass. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseClass = class class function Create: IRoseClass; class function CreateRemote(const MachineName: string): IRoseClass; end; -// *********************************************************************// -// The Class CoRoseElement provides a Create and CreateRemote method to -// create instances of the default interface IRoseElement exposed by -// the CoClass RoseElement. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseElement = class class function Create: IRoseElement; class function CreateRemote(const MachineName: string): IRoseElement; end; -// *********************************************************************// -// The Class CoRoseControllableUnit provides a Create and CreateRemote method to -// create instances of the default interface IRoseControllableUnit exposed by -// the CoClass RoseControllableUnit. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseControllableUnit = class class function Create: IRoseControllableUnit; class function CreateRemote(const MachineName: string): IRoseControllableUnit; end; -// *********************************************************************// -// The Class CoRoseModel provides a Create and CreateRemote method to -// create instances of the default interface IRoseModel exposed by -// the CoClass RoseModel. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseModel = class class function Create: IRoseModel; class function CreateRemote(const MachineName: string): IRoseModel; end; -// *********************************************************************// -// The Class CoRoseTransition provides a Create and CreateRemote method to -// create instances of the default interface IRoseTransition exposed by -// the CoClass RoseTransition. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseTransition = class class function Create: IRoseTransition; class function CreateRemote(const MachineName: string): IRoseTransition; end; -// *********************************************************************// -// The Class CoRoseSubsystemCollection provides a Create and CreateRemote method to -// create instances of the default interface IRoseSubsystemCollection exposed by -// the CoClass RoseSubsystemCollection. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseSubsystemCollection = class class function Create: IRoseSubsystemCollection; class function CreateRemote(const MachineName: string): IRoseSubsystemCollection; end; -// *********************************************************************// -// The Class CoRoseProcessor provides a Create and CreateRemote method to -// create instances of the default interface IRoseProcessor exposed by -// the CoClass RoseProcessor. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseProcessor = class class function Create: IRoseProcessor; class function CreateRemote(const MachineName: string): IRoseProcessor; end; -// *********************************************************************// -// The Class CoRoseCategoryDependencyCollection provides a Create and CreateRemote method to -// create instances of the default interface IRoseCategoryDependencyCollection exposed by -// the CoClass RoseCategoryDependencyCollection. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseCategoryDependencyCollection = class class function Create: IRoseCategoryDependencyCollection; class function CreateRemote(const MachineName: string): IRoseCategoryDependencyCollection; end; -// *********************************************************************// -// The Class CoRoseProperty provides a Create and CreateRemote method to -// create instances of the default interface IRoseProperty exposed by -// the CoClass RoseProperty. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseProperty = class class function Create: IRoseProperty; class function CreateRemote(const MachineName: string): IRoseProperty; end; -// *********************************************************************// -// The Class CoRoseStateDiagram provides a Create and CreateRemote method to -// create instances of the default interface IRoseStateDiagram exposed by -// the CoClass RoseStateDiagram. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseStateDiagram = class class function Create: IRoseStateDiagram; class function CreateRemote(const MachineName: string): IRoseStateDiagram; end; -// *********************************************************************// -// The Class CoRoseEvent provides a Create and CreateRemote method to -// create instances of the default interface IRoseEvent exposed by -// the CoClass RoseEvent. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseEvent = class class function Create: IRoseEvent; class function CreateRemote(const MachineName: string): IRoseEvent; end; -// *********************************************************************// -// The Class CoRoseRichType provides a Create and CreateRemote method to -// create instances of the default interface IRoseRichType exposed by -// the CoClass RoseRichType. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseRichType = class class function Create: IRoseRichType; class function CreateRemote(const MachineName: string): IRoseRichType; end; -// *********************************************************************// -// The Class CoRoseScenarioDiagramCollection provides a Create and CreateRemote method to -// create instances of the default interface IRoseScenarioDiagramCollection exposed by -// the CoClass RoseScenarioDiagramCollection. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseScenarioDiagramCollection = class class function Create: IRoseScenarioDiagramCollection; class function CreateRemote(const MachineName: string): IRoseScenarioDiagramCollection; end; -// *********************************************************************// -// The Class CoRoseParameter provides a Create and CreateRemote method to -// create instances of the default interface IRoseParameter exposed by -// the CoClass RoseParameter. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseParameter = class class function Create: IRoseParameter; class function CreateRemote(const MachineName: string): IRoseParameter; end; -// *********************************************************************// -// The Class CoRoseOperation provides a Create and CreateRemote method to -// create instances of the default interface IRoseOperation exposed by -// the CoClass RoseOperation. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseOperation = class class function Create: IRoseOperation; class function CreateRemote(const MachineName: string): IRoseOperation; end; -// *********************************************************************// -// The Class CoRoseView_LineColor provides a Create and CreateRemote method to -// create instances of the default interface IRoseView_LineColor exposed by -// the CoClass RoseView_LineColor. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseView_LineColor = class class function Create: IRoseView_LineColor; class function CreateRemote(const MachineName: string): IRoseView_LineColor; end; -// *********************************************************************// -// The Class CoRoseAddInManager provides a Create and CreateRemote method to -// create instances of the default interface IRoseAddInManager exposed by -// the CoClass RoseAddInManager. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseAddInManager = class class function Create: IRoseAddInManager; class function CreateRemote(const MachineName: string): IRoseAddInManager; end; -// *********************************************************************// -// The Class CoRoseStateDiagramCollection provides a Create and CreateRemote method to -// create instances of the default interface IRoseStateDiagramCollection exposed by -// the CoClass RoseStateDiagramCollection. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseStateDiagramCollection = class class function Create: IRoseStateDiagramCollection; class function CreateRemote(const MachineName: string): IRoseStateDiagramCollection; end; -// *********************************************************************// -// The Class CoRoseSwimLaneViewCollection provides a Create and CreateRemote method to -// create instances of the default interface IRoseSwimLaneViewCollection exposed by -// the CoClass RoseSwimLaneViewCollection. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseSwimLaneViewCollection = class class function Create: IRoseSwimLaneViewCollection; class function CreateRemote(const MachineName: string): IRoseSwimLaneViewCollection; end; -// *********************************************************************// -// The Class CoRoseSwimLane provides a Create and CreateRemote method to -// create instances of the default interface IRoseSwimLane exposed by -// the CoClass RoseSwimLane. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseSwimLane = class class function Create: IRoseSwimLane; class function CreateRemote(const MachineName: string): IRoseSwimLane; end; -// *********************************************************************// -// The Class CoRoseItemViewCollection provides a Create and CreateRemote method to -// create instances of the default interface IRoseItemViewCollection exposed by -// the CoClass RoseItemViewCollection. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseItemViewCollection = class class function Create: IRoseItemViewCollection; class function CreateRemote(const MachineName: string): IRoseItemViewCollection; end; -// *********************************************************************// -// The Class CoRosePropertyCollection provides a Create and CreateRemote method to -// create instances of the default interface IRosePropertyCollection exposed by -// the CoClass RosePropertyCollection. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRosePropertyCollection = class class function Create: IRosePropertyCollection; class function CreateRemote(const MachineName: string): IRosePropertyCollection; end; -// *********************************************************************// -// The Class CoRoseOperationCollection provides a Create and CreateRemote method to -// create instances of the default interface IRoseOperationCollection exposed by -// the CoClass RoseOperationCollection. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseOperationCollection = class class function Create: IRoseOperationCollection; class function CreateRemote(const MachineName: string): IRoseOperationCollection; end; -// *********************************************************************// -// The Class CoRoseDeviceCollection provides a Create and CreateRemote method to -// create instances of the default interface IRoseDeviceCollection exposed by -// the CoClass RoseDeviceCollection. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseDeviceCollection = class class function Create: IRoseDeviceCollection; class function CreateRemote(const MachineName: string): IRoseDeviceCollection; end; -// *********************************************************************// -// The Class CoRoseInstantiateRelation provides a Create and CreateRemote method to -// create instances of the default interface IRoseInstantiateRelation exposed by -// the CoClass RoseInstantiateRelation. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseInstantiateRelation = class class function Create: IRoseInstantiateRelation; class function CreateRemote(const MachineName: string): IRoseInstantiateRelation; end; -// *********************************************************************// -// The Class CoRoseContextMenuItem provides a Create and CreateRemote method to -// create instances of the default interface IRoseContextMenuItem exposed by -// the CoClass RoseContextMenuItem. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseContextMenuItem = class class function Create: IRoseContextMenuItem; class function CreateRemote(const MachineName: string): IRoseContextMenuItem; end; -// *********************************************************************// -// The Class CoRoseLineVertex provides a Create and CreateRemote method to -// create instances of the default interface IRoseLineVertex exposed by -// the CoClass RoseLineVertex. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseLineVertex = class class function Create: IRoseLineVertex; class function CreateRemote(const MachineName: string): IRoseLineVertex; end; -// *********************************************************************// -// The Class CoRoseObject provides a Create and CreateRemote method to -// create instances of the default interface IRoseObject exposed by -// the CoClass RoseObject. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseObject = class class function Create: IRoseObject; class function CreateRemote(const MachineName: string): IRoseObject; end; -// *********************************************************************// -// The Class CoRoseSwimLaneCollection provides a Create and CreateRemote method to -// create instances of the default interface IRoseSwimLaneCollection exposed by -// the CoClass RoseSwimLaneCollection. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseSwimLaneCollection = class class function Create: IRoseSwimLaneCollection; class function CreateRemote(const MachineName: string): IRoseSwimLaneCollection; end; -// *********************************************************************// -// The Class CoRoseModuleVisibilityRelationship provides a Create and CreateRemote method to -// create instances of the default interface IRoseModuleVisibilityRelationship exposed by -// the CoClass RoseModuleVisibilityRelationship. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseModuleVisibilityRelationship = class class function Create: IRoseModuleVisibilityRelationship; class function CreateRemote(const MachineName: string): IRoseModuleVisibilityRelationship; end; -// *********************************************************************// -// The Class CoRoseComponentViewCollection provides a Create and CreateRemote method to -// create instances of the default interface IRoseComponentViewCollection exposed by -// the CoClass RoseComponentViewCollection. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseComponentViewCollection = class class function Create: IRoseComponentViewCollection; class function CreateRemote(const MachineName: string): IRoseComponentViewCollection; end; -// *********************************************************************// -// The Class CoRoseHasRelationshipCollection provides a Create and CreateRemote method to -// create instances of the default interface IRoseHasRelationshipCollection exposed by -// the CoClass RoseHasRelationshipCollection. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseHasRelationshipCollection = class class function Create: IRoseHasRelationshipCollection; class function CreateRemote(const MachineName: string): IRoseHasRelationshipCollection; end; -// *********************************************************************// -// The Class CoRoseClassViewCollection provides a Create and CreateRemote method to -// create instances of the default interface IRoseClassViewCollection exposed by -// the CoClass RoseClassViewCollection. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseClassViewCollection = class class function Create: IRoseClassViewCollection; class function CreateRemote(const MachineName: string): IRoseClassViewCollection; end; -// *********************************************************************// -// The Class CoRoseDeploymentDiagram provides a Create and CreateRemote method to -// create instances of the default interface IRoseDeploymentDiagram exposed by -// the CoClass RoseDeploymentDiagram. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseDeploymentDiagram = class class function Create: IRoseDeploymentDiagram; class function CreateRemote(const MachineName: string): IRoseDeploymentDiagram; end; -// *********************************************************************// -// The Class CoRoseInstanceView provides a Create and CreateRemote method to -// create instances of the default interface IRoseInstanceView exposed by -// the CoClass RoseInstanceView. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseInstanceView = class class function Create: IRoseInstanceView; class function CreateRemote(const MachineName: string): IRoseInstanceView; end; -// *********************************************************************// -// The Class CoRoseLink provides a Create and CreateRemote method to -// create instances of the default interface IRoseLink exposed by -// the CoClass RoseLink. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseLink = class class function Create: IRoseLink; class function CreateRemote(const MachineName: string): IRoseLink; end; -// *********************************************************************// -// The Class CoRoseObjectInstance provides a Create and CreateRemote method to -// create instances of the default interface IRoseObjectInstance exposed by -// the CoClass RoseObjectInstance. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseObjectInstance = class class function Create: IRoseObjectInstance; class function CreateRemote(const MachineName: string): IRoseObjectInstance; end; -// *********************************************************************// -// The Class CoRoseCategoryDependency provides a Create and CreateRemote method to -// create instances of the default interface IRoseCategoryDependency exposed by -// the CoClass RoseCategoryDependency. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseCategoryDependency = class class function Create: IRoseCategoryDependency; class function CreateRemote(const MachineName: string): IRoseCategoryDependency; end; -// *********************************************************************// -// The Class CoRoseInheritRelation provides a Create and CreateRemote method to -// create instances of the default interface IRoseInheritRelation exposed by -// the CoClass RoseInheritRelation. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseInheritRelation = class class function Create: IRoseInheritRelation; class function CreateRemote(const MachineName: string): IRoseInheritRelation; end; -// *********************************************************************// -// The Class CoRoseView_Font provides a Create and CreateRemote method to -// create instances of the default interface IRoseView_Font exposed by -// the CoClass RoseView_Font. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseView_Font = class class function Create: IRoseView_Font; class function CreateRemote(const MachineName: string): IRoseView_Font; end; -// *********************************************************************// -// The Class CoRoseStateMachine provides a Create and CreateRemote method to -// create instances of the default interface IRoseStateMachine exposed by -// the CoClass RoseStateMachine. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseStateMachine = class class function Create: IRoseStateMachine; class function CreateRemote(const MachineName: string): IRoseStateMachine; end; -// *********************************************************************// -// The Class CoRoseModule provides a Create and CreateRemote method to -// create instances of the default interface IRoseModule exposed by -// the CoClass RoseModule. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseModule = class class function Create: IRoseModule; class function CreateRemote(const MachineName: string): IRoseModule; end; -// *********************************************************************// -// The Class CoRoseUseCase provides a Create and CreateRemote method to -// create instances of the default interface IRoseUseCase exposed by -// the CoClass RoseUseCase. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseUseCase = class class function Create: IRoseUseCase; class function CreateRemote(const MachineName: string): IRoseUseCase; end; -// *********************************************************************// -// The Class CoRoseItemCollection provides a Create and CreateRemote method to -// create instances of the default interface IRoseItemCollection exposed by -// the CoClass RoseItemCollection. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseItemCollection = class class function Create: IRoseItemCollection; class function CreateRemote(const MachineName: string): IRoseItemCollection; end; -// *********************************************************************// -// The Class CoRoseNoteViewCollection provides a Create and CreateRemote method to -// create instances of the default interface IRoseNoteViewCollection exposed by -// the CoClass RoseNoteViewCollection. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// - CoRoseNoteViewCollection = class - class function Create: IRoseNoteViewCollection; - class function CreateRemote(const MachineName: string): IRoseNoteViewCollection; - end; -// *********************************************************************// -// The Class CoRoseInheritRelationCollection provides a Create and CreateRemote method to -// create instances of the default interface IRoseInheritRelationCollection exposed by -// the CoClass RoseInheritRelationCollection. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseNoteViewCollection = class + class function Create: IRoseNoteViewCollection; + class function CreateRemote(const MachineName: string): IRoseNoteViewCollection; + end; + + + + + + CoRoseInheritRelationCollection = class class function Create: IRoseInheritRelationCollection; class function CreateRemote(const MachineName: string): IRoseInheritRelationCollection; end; -// *********************************************************************// -// The Class CoRoseDeploymentDiagramCollection provides a Create and CreateRemote method to -// create instances of the default interface IRoseDeploymentDiagramCollection exposed by -// the CoClass RoseDeploymentDiagramCollection. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseDeploymentDiagramCollection = class class function Create: IRoseDeploymentDiagramCollection; class function CreateRemote(const MachineName: string): IRoseDeploymentDiagramCollection; end; -// *********************************************************************// -// The Class CoRoseStringCollection provides a Create and CreateRemote method to -// create instances of the default interface IRoseStringCollection exposed by -// the CoClass RoseStringCollection. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseStringCollection = class class function Create: IRoseStringCollection; class function CreateRemote(const MachineName: string): IRoseStringCollection; end; -// *********************************************************************// -// The Class CoRoseStateViewCollection provides a Create and CreateRemote method to -// create instances of the default interface IRoseStateViewCollection exposed by -// the CoClass RoseStateViewCollection. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseStateViewCollection = class class function Create: IRoseStateViewCollection; class function CreateRemote(const MachineName: string): IRoseStateViewCollection; end; -// *********************************************************************// -// The Class CoRoseDecisionView provides a Create and CreateRemote method to -// create instances of the default interface IRoseDecisionView exposed by -// the CoClass RoseDecisionView. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseDecisionView = class class function Create: IRoseDecisionView; class function CreateRemote(const MachineName: string): IRoseDecisionView; end; -// *********************************************************************// -// The Class CoRoseStateMachineOwner provides a Create and CreateRemote method to -// create instances of the default interface IRoseStateMachineOwner exposed by -// the CoClass RoseStateMachineOwner. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseStateMachineOwner = class class function Create: IRoseStateMachineOwner; class function CreateRemote(const MachineName: string): IRoseStateMachineOwner; end; -// *********************************************************************// -// The Class CoRoseProcessCollection provides a Create and CreateRemote method to -// create instances of the default interface IRoseProcessCollection exposed by -// the CoClass RoseProcessCollection. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseProcessCollection = class class function Create: IRoseProcessCollection; class function CreateRemote(const MachineName: string): IRoseProcessCollection; end; -// *********************************************************************// -// The Class CoRoseAssociationCollection provides a Create and CreateRemote method to -// create instances of the default interface IRoseAssociationCollection exposed by -// the CoClass RoseAssociationCollection. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseAssociationCollection = class class function Create: IRoseAssociationCollection; class function CreateRemote(const MachineName: string): IRoseAssociationCollection; end; -// *********************************************************************// -// The Class CoRoseModuleDiagramCollection provides a Create and CreateRemote method to -// create instances of the default interface IRoseModuleDiagramCollection exposed by -// the CoClass RoseModuleDiagramCollection. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseModuleDiagramCollection = class class function Create: IRoseModuleDiagramCollection; class function CreateRemote(const MachineName: string): IRoseModuleDiagramCollection; end; -// *********************************************************************// -// The Class CoRoseDiagram provides a Create and CreateRemote method to -// create instances of the default interface IRoseDiagram exposed by -// the CoClass RoseDiagram. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseDiagram = class class function Create: IRoseDiagram; class function CreateRemote(const MachineName: string): IRoseDiagram; end; -// *********************************************************************// -// The Class CoRoseAbstractStateCollection provides a Create and CreateRemote method to -// create instances of the default interface IRoseAbstractStateCollection exposed by -// the CoClass RoseAbstractStateCollection. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseAbstractStateCollection = class class function Create: IRoseAbstractStateCollection; class function CreateRemote(const MachineName: string): IRoseAbstractStateCollection; end; -// *********************************************************************// -// The Class CoRoseRichTypeValuesCollection provides a Create and CreateRemote method to -// create instances of the default interface IRoseRichTypeValuesCollection exposed by -// the CoClass RoseRichTypeValuesCollection. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseRichTypeValuesCollection = class class function Create: IRoseRichTypeValuesCollection; class function CreateRemote(const MachineName: string): IRoseRichTypeValuesCollection; end; -// *********************************************************************// -// The Class CoRoseSubsystemView provides a Create and CreateRemote method to -// create instances of the default interface IRoseSubsystemView exposed by -// the CoClass RoseSubsystemView. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseSubsystemView = class class function Create: IRoseSubsystemView; class function CreateRemote(const MachineName: string): IRoseSubsystemView; end; -// *********************************************************************// -// The Class CoRoseComponentView provides a Create and CreateRemote method to -// create instances of the default interface IRoseComponentView exposed by -// the CoClass RoseComponentView. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseComponentView = class class function Create: IRoseComponentView; class function CreateRemote(const MachineName: string): IRoseComponentView; end; -// *********************************************************************// -// The Class CoRoseAttribute provides a Create and CreateRemote method to -// create instances of the default interface IRoseAttribute exposed by -// the CoClass RoseAttribute. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseAttribute = class class function Create: IRoseAttribute; class function CreateRemote(const MachineName: string): IRoseAttribute; end; -// *********************************************************************// -// The Class CoRoseClassDiagram provides a Create and CreateRemote method to -// create instances of the default interface IRoseClassDiagram exposed by -// the CoClass RoseClassDiagram. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseClassDiagram = class class function Create: IRoseClassDiagram; class function CreateRemote(const MachineName: string): IRoseClassDiagram; end; -// *********************************************************************// -// The Class CoRoseNoteView provides a Create and CreateRemote method to -// create instances of the default interface IRoseNoteView exposed by -// the CoClass RoseNoteView. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseNoteView = class class function Create: IRoseNoteView; class function CreateRemote(const MachineName: string): IRoseNoteView; end; -// *********************************************************************// -// The Class CoRosePackage provides a Create and CreateRemote method to -// create instances of the default interface IRosePackage exposed by -// the CoClass RosePackage. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRosePackage = class class function Create: IRosePackage; class function CreateRemote(const MachineName: string): IRosePackage; end; -// *********************************************************************// -// The Class CoRosePathMap provides a Create and CreateRemote method to -// create instances of the default interface IRosePathMap exposed by -// the CoClass RosePathMap. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRosePathMap = class class function Create: IRosePathMap; class function CreateRemote(const MachineName: string): IRosePathMap; end; -// *********************************************************************// -// The Class CoRoseSyncItemViewCollection provides a Create and CreateRemote method to -// create instances of the default interface IRoseSyncItemViewCollection exposed by -// the CoClass RoseSyncItemViewCollection. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseSyncItemViewCollection = class class function Create: IRoseSyncItemViewCollection; class function CreateRemote(const MachineName: string): IRoseSyncItemViewCollection; end; -// *********************************************************************// -// The Class CoRoseAbstractState provides a Create and CreateRemote method to -// create instances of the default interface IRoseAbstractState exposed by -// the CoClass RoseAbstractState. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseAbstractState = class class function Create: IRoseAbstractState; class function CreateRemote(const MachineName: string): IRoseAbstractState; end; -// *********************************************************************// -// The Class CoRoseModuleVisibilityRelationshipCollection provides a Create and CreateRemote method to -// create instances of the default interface IRoseModuleVisibilityRelationshipCollection exposed by -// the CoClass RoseModuleVisibilityRelationshipCollection. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseModuleVisibilityRelationshipCollection = class class function Create: IRoseModuleVisibilityRelationshipCollection; class function CreateRemote(const MachineName: string): IRoseModuleVisibilityRelationshipCollection; end; -// *********************************************************************// -// The Class CoRoseClassCollection provides a Create and CreateRemote method to -// create instances of the default interface IRoseClassCollection exposed by -// the CoClass RoseClassCollection. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseClassCollection = class class function Create: IRoseClassCollection; class function CreateRemote(const MachineName: string): IRoseClassCollection; end; -// *********************************************************************// -// The Class CoRoseMessage provides a Create and CreateRemote method to -// create instances of the default interface IRoseMessage exposed by -// the CoClass RoseMessage. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseMessage = class class function Create: IRoseMessage; class function CreateRemote(const MachineName: string): IRoseMessage; end; -// *********************************************************************// -// The Class CoRoseConnectionRelationCollection provides a Create and CreateRemote method to -// create instances of the default interface IRoseConnectionRelationCollection exposed by -// the CoClass RoseConnectionRelationCollection. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseConnectionRelationCollection = class class function Create: IRoseConnectionRelationCollection; class function CreateRemote(const MachineName: string): IRoseConnectionRelationCollection; end; -// *********************************************************************// -// The Class CoRoseClassDependencyCollection provides a Create and CreateRemote method to -// create instances of the default interface IRoseClassDependencyCollection exposed by -// the CoClass RoseClassDependencyCollection. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseClassDependencyCollection = class class function Create: IRoseClassDependencyCollection; class function CreateRemote(const MachineName: string): IRoseClassDependencyCollection; end; -// *********************************************************************// -// The Class CoRoseAssociation provides a Create and CreateRemote method to -// create instances of the default interface IRoseAssociation exposed by -// the CoClass RoseAssociation. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseAssociation = class class function Create: IRoseAssociation; class function CreateRemote(const MachineName: string): IRoseAssociation; end; -// *********************************************************************// -// The Class CoRoseEventCollection provides a Create and CreateRemote method to -// create instances of the default interface IRoseEventCollection exposed by -// the CoClass RoseEventCollection. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseEventCollection = class class function Create: IRoseEventCollection; class function CreateRemote(const MachineName: string): IRoseEventCollection; end; -// *********************************************************************// -// The Class CoRoseStateCollection provides a Create and CreateRemote method to -// create instances of the default interface IRoseStateCollection exposed by -// the CoClass RoseStateCollection. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseStateCollection = class class function Create: IRoseStateCollection; class function CreateRemote(const MachineName: string): IRoseStateCollection; end; -// *********************************************************************// -// The Class CoRoseSyncItemView provides a Create and CreateRemote method to -// create instances of the default interface IRoseSyncItemView exposed by -// the CoClass RoseSyncItemView. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseSyncItemView = class class function Create: IRoseSyncItemView; class function CreateRemote(const MachineName: string): IRoseSyncItemView; end; -// *********************************************************************// -// The Class CoRoseActivityView provides a Create and CreateRemote method to -// create instances of the default interface IRoseActivityView exposed by -// the CoClass RoseActivityView. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseActivityView = class class function Create: IRoseActivityView; class function CreateRemote(const MachineName: string): IRoseActivityView; end; -// *********************************************************************// -// The Class CoRoseStateView provides a Create and CreateRemote method to -// create instances of the default interface IRoseStateView exposed by -// the CoClass RoseStateView. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseStateView = class class function Create: IRoseStateView; class function CreateRemote(const MachineName: string): IRoseStateView; end; -// *********************************************************************// -// The Class CoRoseStateVertexCollection provides a Create and CreateRemote method to -// create instances of the default interface IRoseStateVertexCollection exposed by -// the CoClass RoseStateVertexCollection. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseStateVertexCollection = class class function Create: IRoseStateVertexCollection; class function CreateRemote(const MachineName: string): IRoseStateVertexCollection; end; -// *********************************************************************// -// The Class CoRoseSubsystemViewCollection provides a Create and CreateRemote method to -// create instances of the default interface IRoseSubsystemViewCollection exposed by -// the CoClass RoseSubsystemViewCollection. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseSubsystemViewCollection = class class function Create: IRoseSubsystemViewCollection; class function CreateRemote(const MachineName: string): IRoseSubsystemViewCollection; end; -// *********************************************************************// -// The Class CoRoseModuleDiagram provides a Create and CreateRemote method to -// create instances of the default interface IRoseModuleDiagram exposed by -// the CoClass RoseModuleDiagram. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseModuleDiagram = class class function Create: IRoseModuleDiagram; class function CreateRemote(const MachineName: string): IRoseModuleDiagram; end; -// *********************************************************************// -// The Class CoRoseSubsystem provides a Create and CreateRemote method to -// create instances of the default interface IRoseSubsystem exposed by -// the CoClass RoseSubsystem. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseSubsystem = class class function Create: IRoseSubsystem; class function CreateRemote(const MachineName: string): IRoseSubsystem; end; -// *********************************************************************// -// The Class CoRoseExternalDocumentCollection provides a Create and CreateRemote method to -// create instances of the default interface IRoseExternalDocumentCollection exposed by -// the CoClass RoseExternalDocumentCollection. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseExternalDocumentCollection = class class function Create: IRoseExternalDocumentCollection; class function CreateRemote(const MachineName: string): IRoseExternalDocumentCollection; end; -// *********************************************************************// -// The Class CoRoseInstanceViewCollection provides a Create and CreateRemote method to -// create instances of the default interface IRoseInstanceViewCollection exposed by -// the CoClass RoseInstanceViewCollection. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseInstanceViewCollection = class class function Create: IRoseInstanceViewCollection; class function CreateRemote(const MachineName: string): IRoseInstanceViewCollection; end; -// *********************************************************************// -// The Class CoRoseItemView provides a Create and CreateRemote method to -// create instances of the default interface IRoseItemView exposed by -// the CoClass RoseItemView. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseItemView = class class function Create: IRoseItemView; class function CreateRemote(const MachineName: string): IRoseItemView; end; -// *********************************************************************// -// The Class CoRoseTransitionCollection provides a Create and CreateRemote method to -// create instances of the default interface IRoseTransitionCollection exposed by -// the CoClass RoseTransitionCollection. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseTransitionCollection = class class function Create: IRoseTransitionCollection; class function CreateRemote(const MachineName: string): IRoseTransitionCollection; end; -// *********************************************************************// -// The Class CoRoseState provides a Create and CreateRemote method to -// create instances of the default interface IRoseState exposed by -// the CoClass RoseState. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseState = class class function Create: IRoseState; class function CreateRemote(const MachineName: string): IRoseState; end; -// *********************************************************************// -// The Class CoRoseObjectInstanceCollection provides a Create and CreateRemote method to -// create instances of the default interface IRoseObjectInstanceCollection exposed by -// the CoClass RoseObjectInstanceCollection. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseObjectInstanceCollection = class class function Create: IRoseObjectInstanceCollection; class function CreateRemote(const MachineName: string): IRoseObjectInstanceCollection; end; -// *********************************************************************// -// The Class CoRoseRoleCollection provides a Create and CreateRemote method to -// create instances of the default interface IRoseRoleCollection exposed by -// the CoClass RoseRoleCollection. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseRoleCollection = class class function Create: IRoseRoleCollection; class function CreateRemote(const MachineName: string): IRoseRoleCollection; end; -// *********************************************************************// -// The Class CoRoseClassRelation provides a Create and CreateRemote method to -// create instances of the default interface IRoseClassRelation exposed by -// the CoClass RoseClassRelation. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseClassRelation = class class function Create: IRoseClassRelation; class function CreateRemote(const MachineName: string): IRoseClassRelation; end; -// *********************************************************************// -// The Class CoRoseCategory provides a Create and CreateRemote method to -// create instances of the default interface IRoseCategory exposed by -// the CoClass RoseCategory. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseCategory = class class function Create: IRoseCategory; class function CreateRemote(const MachineName: string): IRoseCategory; end; -// *********************************************************************// -// The Class CoRoseDefaultModelProperties provides a Create and CreateRemote method to -// create instances of the default interface IRoseDefaultModelProperties exposed by -// the CoClass RoseDefaultModelProperties. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseDefaultModelProperties = class class function Create: IRoseDefaultModelProperties; class function CreateRemote(const MachineName: string): IRoseDefaultModelProperties; end; -// *********************************************************************// -// The Class CoRoseStateMachineCollection provides a Create and CreateRemote method to -// create instances of the default interface IRoseStateMachineCollection exposed by -// the CoClass RoseStateMachineCollection. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseStateMachineCollection = class class function Create: IRoseStateMachineCollection; class function CreateRemote(const MachineName: string): IRoseStateMachineCollection; end; -// *********************************************************************// -// The Class CoRoseSyncItem provides a Create and CreateRemote method to -// create instances of the default interface IRoseSyncItem exposed by -// the CoClass RoseSyncItem. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseSyncItem = class class function Create: IRoseSyncItem; class function CreateRemote(const MachineName: string): IRoseSyncItem; end; -// *********************************************************************// -// The Class CoRoseRealizeRelationCollection provides a Create and CreateRemote method to -// create instances of the default interface IRoseRealizeRelationCollection exposed by -// the CoClass RoseRealizeRelationCollection. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseRealizeRelationCollection = class class function Create: IRoseRealizeRelationCollection; class function CreateRemote(const MachineName: string): IRoseRealizeRelationCollection; end; -// *********************************************************************// -// The Class CoRosePackageCollection provides a Create and CreateRemote method to -// create instances of the default interface IRosePackageCollection exposed by -// the CoClass RosePackageCollection. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRosePackageCollection = class class function Create: IRosePackageCollection; class function CreateRemote(const MachineName: string): IRosePackageCollection; end; -// *********************************************************************// -// The Class CoRoseExternalDocument provides a Create and CreateRemote method to -// create instances of the default interface IRoseExternalDocument exposed by -// the CoClass RoseExternalDocument. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoRoseExternalDocument = class class function Create: IRoseExternalDocument; class function CreateRemote(const MachineName: string): IRoseExternalDocument; @@ -9084,5 +8513,3 @@ class function CoRoseExternalDocument.CreateRemote(const MachineName: string): I end; end. - - diff --git a/Source/Common/Rose98/BoldRose98Support.pas b/Source/Common/Rose98/BoldRose98Support.pas index 924505a..2b5b654 100644 --- a/Source/Common/Rose98/BoldRose98Support.pas +++ b/Source/Common/Rose98/BoldRose98Support.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldRose98Support; interface @@ -12,7 +15,7 @@ interface TBoldRose98Support = class; TBoldRose98Properties = class; TBoldRose98AddIns = class; - + { TBoldRose98Support } TBoldRose98Support = class public @@ -63,8 +66,7 @@ implementation BoldUtils, BoldDefaultTaggedValues, ActiveX, - BoldLogHandler, - BoldCommonConst; + BoldLogHandler; class function TBoldRose98Support.FindClassByName(RoseModel: IRoseModel; const Name: string): IRoseClass; var @@ -77,7 +79,7 @@ class function TBoldRose98Support.FindClassByName(RoseModel: IRoseModel; const N begin Result := ClsCol.GetAt(1); if ClsCol.Count > 1 then - raise EBoldImport.CreateFmt(sClassNameNotUnique, [Name]); + raise EBoldImport.CreateFmt('Found multiple classes with name %s, don''t know which one to use', [Name]); end; end; @@ -120,7 +122,7 @@ function TBoldRose98Properties.GetBooleanString(RoseItem: IRoseItem; const Name: Result := DefaultValue else begin - if AnsiCompareText(Value, 'True') = 0 then // do not localize + if AnsiCompareText(Value, 'True') = 0 then Result := TV_TRUE else Result := TV_FALSE; @@ -138,7 +140,7 @@ function TBoldRose98Properties.GetBoolean(RoseItem: IRoseItem; const Name: strin if Value = '' then Result := DefaultValue else - Result := (AnsiCompareText(Value, 'True') = 0); // do not localize + Result := (AnsiCompareText(Value, 'True') = 0); end; function TBoldRose98Properties.GetDefaultPropertyBoolean(RoseModel: IRoseModel; PropName: String): Boolean; @@ -148,7 +150,7 @@ function TBoldRose98Properties.GetDefaultPropertyBoolean(RoseModel: IRoseModel; Prop: IRoseProperty; begin DefaultProps := RoseModel.DefaultProperties; - PropCollection := DefaultProps.GetDefaultPropertySet(RoseModel.GetPropertyClassName, ToolName, DEFAULTVALUE); + PropCollection := DefaultProps.GetDefaultPropertySet(RoseModel.GetPropertyClassName, ToolName, 'default'); Index := PropCollection.FindFirst(PropName); if Index > 0 then @@ -168,14 +170,13 @@ function TBoldRose98Properties.GetDefaultPropertyString(RoseModel: IRoseModel; P Prop: IRoseProperty; begin DefaultProps := RoseModel.DefaultProperties; - PropCollection := DefaultProps.GetDefaultPropertySet(RoseModel.GetPropertyClassName, ToolName, DEFAULTVALUE); + PropCollection := DefaultProps.GetDefaultPropertySet(RoseModel.GetPropertyClassName, ToolName, 'default'); Index := PropCollection.FindFirst(PropName); if Index > 0 then Prop := PropCollection.GetAt(Index) else Exit; - //ShowMessage('Fel'); Result := Prop.Value; end; @@ -187,14 +188,13 @@ procedure TBoldRose98Properties.SetDefaultPropertyBoolean(RoseModel: IRoseModel; Prop: IRoseProperty; begin DefaultProps := RoseModel.DefaultProperties; - PropCollection := DefaultProps.GetDefaultPropertySet(RoseModel.GetPropertyClassName, ToolName, DEFAULTVALUE); + PropCollection := DefaultProps.GetDefaultPropertySet(RoseModel.GetPropertyClassName, ToolName, 'default'); Index := PropCollection.FindFirst(PropName); if Index > 0 then Prop := PropCollection.GetAt(Index) else Exit; - //ShowMessage('Fel'); Prop.Value := BooleanToString(PropValue); end; @@ -207,14 +207,13 @@ procedure TBoldRose98Properties.SetDefaultPropertyString(RoseModel: IRoseModel; Prop: IRoseProperty; begin DefaultProps := RoseModel.DefaultProperties; - PropCollection := DefaultProps.GetDefaultPropertySet(RoseModel.GetPropertyClassName, ToolName, DEFAULTVALUE); + PropCollection := DefaultProps.GetDefaultPropertySet(RoseModel.GetPropertyClassName, ToolName, 'default'); Index := PropCollection.FindFirst(PropName); if Index > 0 then Prop := PropCollection.GetAt(Index) else Exit; - //ShowMessage('Fel'); Prop.Value := PropValue; end; @@ -255,7 +254,7 @@ procedure TBoldRose98Properties.SetBooleanString(RoseItem: IRoseItem; const Name begin if GetBooleanString(RoseItem, Name, DefaultValue) <> Value then begin - BoldLog.LogFmt(sSettingValue, [LoggString, Name, Value]); + BoldLog.LogFmt('Setting %s.%s to %s', [LoggString, Name, Value]); RoseItem.OverrideProperty(ToolName, Name, Value); end; end; @@ -265,7 +264,7 @@ procedure TBoldRose98Properties.SetBoolean(RoseItem: IRoseItem; const Name: stri begin if GetBoolean(RoseItem, Name, DefaultValue) <> Value then begin - BoldLog.LogFmt(sSettingValue, [LoggString, Name, BooleanToString(Value)]); + BoldLog.LogFmt('Setting %s.%s to %s', [LoggString, Name, BooleanToString(Value)]); RoseItem.OverrideProperty(ToolName, Name, BooleanToString(Value)); end; end; @@ -275,7 +274,7 @@ procedure TBoldRose98Properties.SetInteger(RoseItem: IRoseItem; const Name: stri begin if GetInteger(RoseItem, Name, DefaultValue) <> Value then begin - BoldLog.LogFmt(sSettingValue, [LoggString, Name, IntToStr(Value)]); + BoldLog.LogFmt('Setting %s.%s to %s', [LoggString, Name, IntToStr(Value)]); RoseItem.OverrideProperty(ToolName, Name, IntToStr(Value)); end end; @@ -285,7 +284,7 @@ procedure TBoldRose98Properties.SetString(RoseItem: IRoseItem; const Name, Defau begin if AnsiCompareText(GetString(RoseItem, Name, DefaultValue),Value) <> 0 then begin - BoldLog.LogFmt(sSettingValue, [LoggString, Name, Value]); + BoldLog.LogFmt('Setting %s.%s to %s', [LoggString, Name, Value]); RoseItem.OverrideProperty(ToolName, Name, Value); end; end; @@ -295,7 +294,7 @@ procedure TBoldRose98Properties.SetText(RoseItem: IRoseItem; const Name, Default begin if AnsiCompareText(GetString(RoseItem, Name, DefaultValue),Value) <> 0 then begin - BoldLog.LogFmt(sSettingValue, [LoggString, Name, Value]); + BoldLog.LogFmt('Setting %s.%s to %s', [LoggString, Name, Value]); RoseItem.OverrideProperty(ToolName, Name, Value); end; end; @@ -323,7 +322,7 @@ class function TBoldRose98Support.GetContainment(RoseRole, OtherRole: IRoseRole) 2: Result := akAggregate; end else if RoseRole.Containment.Value = 2 then - BoldLog.Log(sContainmentByValueButNotAggregate); + BoldLog.Log('Warning: containment by value, but not aggregate'); end; class procedure TBoldRose98Support.SetContainment(Aggregation: TAggregationKind; RoseRole, OtherRole: IRoseRole; const LoggString: string); @@ -337,23 +336,23 @@ class procedure TBoldRose98Support.SetContainment(Aggregation: TAggregationKind; begin OtherRole.Aggregate := false; RoseRole.Containment.Value := 0; - ContainmentName := 'None'; // do not localize + ContainmentName := 'None'; end; akComposite: begin OtherRole.Aggregate := true; RoseRole.Containment.Value := 1; - ContainmentName := 'Composite'; // do not localize + ContainmentName := 'Composite'; end; akAggregate: begin OtherRole.Aggregate := true; RoseRole.Containment.Value := 2; - ContainmentName := 'Aggregate'; // do not localize + ContainmentName := 'Aggregate'; end; end; - BoldLog.LogFmt(sSettingValue, [LoggString, 'containment', ContainmentName]); // do not localize - BoldLog.LogFmt(sSettingValue, [LoggString, 'Aggregate', BooleanToString(aggregation <> aknone)]); // do not localize + BoldLog.LogFmt('Setting %s.containment to %s', [LoggString, ContainmentName]); + BoldLog.LogFmt('Setting %s.Aggregate to %s', [LoggString, BooleanToString(aggregation <> aknone)]); end; end; @@ -365,7 +364,7 @@ class function TBoldRose98Support.RoseExportControlToVisibility(ExportControl: I 1: Result := vkProtected; 2: Result := vkPrivate; else - BoldLog.Log(sUnknownVisibility); + BoldLog.Log('Unknown visibility, public is set.'); end; end; @@ -379,22 +378,22 @@ class procedure TBoldRose98Support.SetExportControl(Visibility: TVisibilityKind; vkPublic: begin ExportControl.Value := 0; - VisibilityName := 'public'; // do not localize + VisibilityName := 'public'; end; vkProtected: begin ExportControl.Value := 1; - VisibilityName := 'protected'; // do not localize + VisibilityName := 'protected'; end; vkPrivate: begin ExportControl.Value := 2; - VisibilityName := 'private'; // do not localize + VisibilityName := 'private'; end; end; - BoldLog.LogFmt(sSettingValue, [LoggString, 'Visibility', VisibilityName]); // do not localize + BoldLog.LogFmt('Setting %s.Visibility to %s', [LoggString, VisibilityName]); end; -end; +end; class function TBoldRose98Support.GetVersion: Double; var @@ -410,14 +409,14 @@ class function TBoldRose98Support.GetVersion: Double; for i := 1 to length(VersionStr) do begin case VersionStr[i] of - '0'..'9': if Start = -1 then // The first digit starts the number + '0'..'9': if Start = -1 then Start := i; '.': begin inc(DotCount); - if (start <> -1) and (DotCount = 2) then // The second dot terminates the number + if (start <> -1) and (DotCount = 2) then stop := i; end - else if (start <> -1) and (stop = -1) then // any non-digit/non-dot after the first digit terminates the number + else if (start <> -1) and (stop = -1) then stop := i; end; end; @@ -427,10 +426,13 @@ class function TBoldRose98Support.GetVersion: Double; begin if stop = -1 then stop := length(VersionStr); - OldDecimalSeparator := FormatSettings.DecimalSeparator; - FormatSettings.DecimalSeparator := '.'; - result := StrtoFloat(copy(VersionStr, start, stop-start)); - FormatSettings.DecimalSeparator := OldDecimalSeparator; + OldDecimalSeparator := {$IFDEF BOLD_DELPHI16_OR_LATER}FormatSettings.{$ENDIF}DecimalSeparator; + {$IFDEF BOLD_DELPHI16_OR_LATER}FormatSettings.{$ENDIF}DecimalSeparator := '.'; + try + result := StrToFloat(copy(VersionStr, start, stop-start)); + finally + {$IFDEF BOLD_DELPHI16_OR_LATER}FormatSettings.{$ENDIF}DecimalSeparator := OldDecimalSeparator; + end; end; end; @@ -439,4 +441,6 @@ class function TBoldRose98Support.GetVersionString: String; result := GetApplication.Version; end; +initialization + end. diff --git a/Source/Common/Rose98/RationalRose98_TLB.pas b/Source/Common/Rose98/RationalRose98_TLB.pas index 2dc8a7f..10d77c8 100644 --- a/Source/Common/Rose98/RationalRose98_TLB.pas +++ b/Source/Common/Rose98/RationalRose98_TLB.pas @@ -1,8 +1,11 @@ -{$WARNINGS OFF} -{$WARN SYMBOL_PLATFORM OFF} +{ Global compiler directives } +{$include bold.inc} unit RationalRose98_TLB; +{$WARNINGS OFF} +{$WARN SYMBOL_PLATFORM OFF} + { This file contains pascal declarations imported from a type library. This file will be written during each import or refresh of the type library editor. Changes to this file will be discarded during the diff --git a/Source/Common/SOAP/BoldSOAP2_TLB.pas b/Source/Common/SOAP/BoldSOAP2_TLB.pas index da11801..fa5e0e3 100644 --- a/Source/Common/SOAP/BoldSOAP2_TLB.pas +++ b/Source/Common/SOAP/BoldSOAP2_TLB.pas @@ -1,53 +1,49 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldSOAP2_TLB; -// ************************************************************************ // -// WARNING -// ------- -// The types declared in this file were generated from data read from a -// Type Library. If this type library is explicitly or indirectly (via -// another type library referring to this type library) re-imported, or the -// 'Refresh' command of the Type Library Editor activated while editing the -// Type Library, the contents of this file will be regenerated and all -// manual modifications will be lost. -// ************************************************************************ // - -// PASTLWTR : 1.1 -// File generated on 4/20/2001 2:02:34 PM from Type Library described below. - -// *************************************************************************// -// NOTE: -// Items guarded by $IFDEF_LIVE_SERVER_AT_DESIGN_TIME are used by properties -// which return objects that may need to be explicitly created via a function -// call prior to any access via the property. These items have been disabled -// in order to prevent accidental use from within the object inspector. You -// may enable them by defining LIVE_SERVER_AT_DESIGN_TIME or by selectively -// removing them from the $IFDEF blocks. However, such items must still be -// programmatically created via a method of the appropriate CoClass before -// they can be used. -// ************************************************************************ // -// Type Lib: C:\Work\BfD\Source\Common\SOAP\BoldSOAP2.tlb (1) -// IID\LCID: {430A7A46-55F8-49B7-82A2-539FA3580ABE}\0 -// Helpfile: -// DepndLst: -// (1) v2.0 stdole, (C:\WINNT\System32\stdole2.tlb) -// (2) v4.0 StdVCL, (C:\WINNT\System32\STDVCL40.DLL) -// (3) v1.0 BoldSOAP, (C:\Work\BfD\Source\Common\SOAP\BoldSOAP.tlb) -// ************************************************************************ // -{$TYPEDADDRESS OFF} // Unit must be compiled without type-checked pointers. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +{$TYPEDADDRESS OFF} interface uses Windows, ActiveX, Classes, Graphics, OleServer, OleCtrls, StdVCL, BoldSOAP_TLB; -// *********************************************************************// -// GUIDS declared in the TypeLibrary. Following prefixes are used: -// Type Libraries : LIBID_xxxx -// CoClasses : CLASS_xxxx -// DISPInterfaces : DIID_xxxx -// Non-DISP interfaces: IID_xxxx -// *********************************************************************// + + + + + const - // TypeLibrary Major and minor versions BoldSOAP2MajorVersion = 1; BoldSOAP2MinorVersion = 0; @@ -56,27 +52,21 @@ interface IID_IBoldSOAPService2: TGUID = '{D349D000-EDDB-4F8C-886F-CB00F640DB6A}'; type -// *********************************************************************// -// Forward declaration of types defined in TypeLibrary -// *********************************************************************// + IBoldSOAPService2 = interface; IBoldSOAPService2Disp = dispinterface; -// *********************************************************************// -// Interface: IBoldSOAPService2 -// Flags: (4416) Dual OleAutomation Dispatchable -// GUID: {D349D000-EDDB-4F8C-886F-CB00F640DB6A} -// *********************************************************************// + + + IBoldSOAPService2 = interface(IBoldSOAPService) ['{D349D000-EDDB-4F8C-886F-CB00F640DB6A}'] function Get2(const request: WideString): WideString; safecall; end; -// *********************************************************************// -// DispIntf: IBoldSOAPService2Disp -// Flags: (4416) Dual OleAutomation Dispatchable -// GUID: {D349D000-EDDB-4F8C-886F-CB00F640DB6A} -// *********************************************************************// + + + IBoldSOAPService2Disp = dispinterface ['{D349D000-EDDB-4F8C-886F-CB00F640DB6A}'] function Get2(const request: WideString): WideString; dispid 2; diff --git a/Source/Common/SOAP/BoldSOAP_TLB.pas b/Source/Common/SOAP/BoldSOAP_TLB.pas index bbf50ca..5d2ab46 100644 --- a/Source/Common/SOAP/BoldSOAP_TLB.pas +++ b/Source/Common/SOAP/BoldSOAP_TLB.pas @@ -1,52 +1,48 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldSOAP_TLB; -// ************************************************************************ // -// WARNING -// ------- -// The types declared in this file were generated from data read from a -// Type Library. If this type library is explicitly or indirectly (via -// another type library referring to this type library) re-imported, or the -// 'Refresh' command of the Type Library Editor activated while editing the -// Type Library, the contents of this file will be regenerated and all -// manual modifications will be lost. -// ************************************************************************ // - -// PASTLWTR : 1.1 -// File generated on 4/20/2001 2:02:34 PM from Type Library described below. - -// *************************************************************************// -// NOTE: -// Items guarded by $IFDEF_LIVE_SERVER_AT_DESIGN_TIME are used by properties -// which return objects that may need to be explicitly created via a function -// call prior to any access via the property. These items have been disabled -// in order to prevent accidental use from within the object inspector. You -// may enable them by defining LIVE_SERVER_AT_DESIGN_TIME or by selectively -// removing them from the $IFDEF blocks. However, such items must still be -// programmatically created via a method of the appropriate CoClass before -// they can be used. -// ************************************************************************ // -// Type Lib: C:\Work\BfD\Source\Common\SOAP\BoldSOAP.tlb (1) -// IID\LCID: {9BF07220-6C8A-11D4-BBAC-0010A4F9E114}\0 -// Helpfile: -// DepndLst: -// (1) v2.0 stdole, (C:\WINNT\System32\stdole2.tlb) -// Parent TypeLibrary: -// (0) v1.0 BoldSOAP2, (C:\Work\BfD\Source\Common\SOAP\BoldSOAP2.tlb) -// ************************************************************************ // -{$TYPEDADDRESS OFF} // Unit must be compiled without type-checked pointers. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +{$TYPEDADDRESS OFF} interface uses Windows, ActiveX, Classes, Graphics, OleServer, OleCtrls, StdVCL; -// *********************************************************************// -// GUIDS declared in the TypeLibrary. Following prefixes are used: -// Type Libraries : LIBID_xxxx -// CoClasses : CLASS_xxxx -// DISPInterfaces : DIID_xxxx -// Non-DISP interfaces: IID_xxxx -// *********************************************************************// + + + + + const - // TypeLibrary Major and minor versions BoldSOAPMajorVersion = 1; BoldSOAPMinorVersion = 0; @@ -55,27 +51,21 @@ interface IID_IBoldSOAPService: TGUID = '{9BF07221-6C8A-11D4-BBAC-0010A4F9E114}'; type -// *********************************************************************// -// Forward declaration of types defined in TypeLibrary -// *********************************************************************// + IBoldSOAPService = interface; IBoldSOAPServiceDisp = dispinterface; -// *********************************************************************// -// Interface: IBoldSOAPService -// Flags: (4416) Dual OleAutomation Dispatchable -// GUID: {9BF07221-6C8A-11D4-BBAC-0010A4F9E114} -// *********************************************************************// + + + IBoldSOAPService = interface(IDispatch) ['{9BF07221-6C8A-11D4-BBAC-0010A4F9E114}'] procedure Get(const request: WideString; out reply: WideString); safecall; end; -// *********************************************************************// -// DispIntf: IBoldSOAPServiceDisp -// Flags: (4416) Dual OleAutomation Dispatchable -// GUID: {9BF07221-6C8A-11D4-BBAC-0010A4F9E114} -// *********************************************************************// + + + IBoldSOAPServiceDisp = dispinterface ['{9BF07221-6C8A-11D4-BBAC-0010A4F9E114}'] procedure Get(const request: WideString; out reply: WideString); dispid 1; diff --git a/Source/Common/SOAP/BoldXMLRequests.pas b/Source/Common/SOAP/BoldXMLRequests.pas index 7a1757d..48bce4c 100644 --- a/Source/Common/SOAP/BoldXMLRequests.pas +++ b/Source/Common/SOAP/BoldXMLRequests.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldXMLRequests; interface @@ -62,7 +65,7 @@ TBoldXMLRequest = class procedure AddIdentifiedValue(const IdString: string; const Value: string; const DomElementTag: string = DEFAULT_IDENTIFIEDVALUE_TAG; const AttributeTag: string = DEFAULT_IDSTRING_TAG); - procedure ReloadIdentifiedValues; + procedure ReloadIdentifiedValues; property DomDocument: IXMLDomDocument read FDomDocument; property Params: TBoldStringList read getParams; property IdentifiedValues: TBoldStringList read getIdentifiedValues; @@ -77,7 +80,9 @@ implementation SysUtils, BoldUtils, Windows, - BoldCommonConst; + BoldRev; + + {TBoldXMLRequest} @@ -155,10 +160,10 @@ procedure TBoldXMLRequest.SetIdentifiedValues(const Values: TStrings; if Assigned(ActionElement) then LoadIdentifiedValues(ActionElement, Values, DomElementTag, AttributeTag) else - raise EBold.CreateFmt(sSOAPActionNotSet, [ClassName, 'SetIdentifiedValues']); // do not localize + raise EBold.CreateFmt('%s.SetIdentifiedValues: Action not set', [ClassName]); end else - raise EBold.CreateFmt(sCannotSetPropertyWhenReadOnly, [ClassName, 'SetIdentifiedValues']); // do not localize + raise EBold.CreateFmt('%s.SetIdentifiedValues: cannot set BoldIds in ReadOnly mode', [ClassName]); end; procedure TBoldXMLRequest.SetParams(const Params: TStrings); @@ -168,10 +173,10 @@ procedure TBoldXMLRequest.SetParams(const Params: TStrings); if Assigned(ActionElement) then LoadParams(ActionElement, Params) else - raise EBold.CreateFmt(sSOAPActionNotSet, [ClassName, 'SetParams']); // do not localize + raise EBold.CreateFmt('%s.SetParams: Action not set', [ClassName]); end else - raise EBold.CreateFmt(sCannotSetPropertyWhenReadOnly, [ClassName, 'SetParams']); // do not localize + raise EBold.CreateFmt('%s.SetParams: cannot set Params in ReadOnly mode', [ClassName]); end; function TBoldXMLRequest.getActionName: string; @@ -222,7 +227,7 @@ procedure TBoldXMLRequest.setActionPath(const Value: string); end end else - raise EBold.CreateFmt(sCannotSetPropertyWhenReadOnly, [ClassName, 'ActionPath']);; // do not localize + raise EBold.CreateFmt('%s.ActionPath: property cannot be set', [ClassName]);; end; constructor TBoldXMLRequest.CreateInitialized(const VersionNo: string = DEFAULT_VERSION_NO; const Encoding: string = DEFAULT_ENCODING; @@ -230,9 +235,9 @@ constructor TBoldXMLRequest.CreateInitialized(const VersionNo: string = DEFAULT_ function BooleanToStr(value: Boolean): string; begin if Value then - result := 'yes' // do not localize + result := 'yes' else - result := 'no'; // do not localize + result := 'no'; end; var ProcessingInstruction: IXMLDOMProcessingInstruction; @@ -241,9 +246,9 @@ constructor TBoldXMLRequest.CreateInitialized(const VersionNo: string = DEFAULT_ FIsReadOnly := false; FDomDocument := CoDOMDocument.Create; FDomDocument.async := FALSE; - ProcessingInstruction := FDomDocument.createProcessingInstruction('xml', Format('version="%s" encoding="%s" standalone="%s"', [VersionNo, Encoding, BooleantoStr(StandAlone)])); // do not localize + ProcessingInstruction := FDomDocument.createProcessingInstruction('xml', Format('version="%s" encoding="%s" standalone="%s"', [VersionNo, Encoding, BooleantoStr(StandAlone)])); FDomDocument.appendChild(ProcessingInstruction); - FActionPath := DEFAULT_ACTION_PATH; + FActionPath := DEFAULT_ACTION_PATH; end; function TBoldXMLRequest.SetAction( const ActionName: string; const ActionPath: string = DEFAULT_ACTION_PATH): IXMLDomElement; @@ -259,7 +264,7 @@ function TBoldXMLRequest.SetAction( const ActionName: string; const ActionPath: if (Trim(ActionPath) = '') or (Trim(ActionName) = '') then begin Result := nil; - raise EBold.CreateFmt(sSetActionInvalidArgs, [ClassName]); + raise EBold.CreateFmt('%s.SetAction: Invalid arguments "ActionPath" or "ActionName"', [ClassName]); end; if ((Trim(ActionPath) <> FActionPath) and (ActionName <> self.ActionName)) or not Assigned(ActionElement) then @@ -277,12 +282,10 @@ function TBoldXMLRequest.SetAction( const ActionName: string; const ActionPath: Tag := Copy(temp, p+1, Maxint); temp := Copy(temp, 1, p - 1); NewElement := DomDocument.CreateElement(Tag); - //****************************************************************************// - if IsDefault and (Tag = 'SOAP:Envelope') then // do not localize - NewElement.setAttribute('xmlns:SOAP', 'urn:schemas-xmlssoap-org:soap.v1'); // do not localize - if IsDefault and (AnsiPos('m:', Tag) > 0) then // do not localize - NewElement.setAttribute('xmlns:m', 'www.borland.com/products/boldfordelphi'); // do not localize - //****************************************************************************// + if IsDefault and (Tag = 'SOAP:Envelope') then + NewElement.setAttribute('xmlns:SOAP', 'urn:schemas-xmlssoap-org:soap.v1'); + if IsDefault and (Pos('m:', Tag) > 0) then + NewElement.setAttribute('xmlns:m', 'www.boldsoft.com/products/boldfordelphi'); if Assigned(ChildElement) then NewElement.appendChild(ChildElement); ChildElement := NewElement; @@ -312,7 +315,7 @@ procedure TBoldXMLRequest.EnsureRoot(const TagName: string); if not FIsReadOnly then begin if not assigned(DomDocument) then - raise EBold.CreateFmt(sSOAPDOMDocumentMissing, [classname]); + raise EBold.CreateFmt('%s.EnsureRoot: The XMLRequest has no DomDocument. ', [classname]); RootElement := DomDocument.Get_documentElement; if not Assigned(RootElement) then begin @@ -359,7 +362,7 @@ procedure TBoldXMLRequest.AddParam(const Name, Value: string); NewElement: IXMLDomElement; begin if FIsReadOnly then - raise EBold.CreateFmt(sCannotPerformInReadOnlyMode, [ClassName, 'AddParam']) // do not localize + raise EBold.CreateFmt('%s.AddParam: cannot AddParam in ReadOnly mode', [ClassName]) else if Assigned(ActionElement) then begin NewElement := DomDocument.createElement(Name); @@ -367,7 +370,7 @@ procedure TBoldXMLRequest.AddParam(const Name, Value: string); ActionElement.appendChild(NewElement); end else - raise EBold.CreateFmt(sSOAPActionNotSet, [ClassName, 'AddParam']); // do not localize + raise EBold.CreateFmt('%s.AddParam: no action set', [ClassName]); end; procedure TBoldXMLRequest.DeleteAction; @@ -375,7 +378,7 @@ procedure TBoldXMLRequest.DeleteAction; parentNode: IXMLDomNode; begin if FIsReadOnly then - raise EBold.CreateFmt(sCannotPerformInReadOnlyMode, [ClassName, 'DeleteAction']) // do not localize + raise EBold.CreateFmt('%s.DeleteAction: cannot perform this operation in ReadOnly mode', [ClassName]) else begin parentNode := ActionElement.parentNode; @@ -391,14 +394,16 @@ procedure TBoldXMLRequest.AddIdentifiedValue(const IdString, Value, DomElementTa NewElement: IXMLDomElement; begin if FIsReadOnly then - raise EBold.CreateFmt(sCannotPerformInReadOnlyMode, [ClassName, 'AddIdentifiedValue']); // do not localize - if not Assigned(ActionElement) then - raise EBold.CreateFmt(sSOAPActionNotSet, [ClassName, 'AddIdentifiedValue']); // do not localize - - NewElement := DomDocument.createElement(DomElementTag); - NewElement.setAttribute(AttributeTag, IdString); - NewElement.Set_text(Value); - ActionElement.appendChild(NewElement); + raise EBold.CreateFmt('%s.AddIdentifiedValue: cannot AddParam in ReadOnly mode', [ClassName]) + else if Assigned(ActionElement) then + begin + NewElement := DomDocument.createElement(DomElementTag); + NewElement.setAttribute(AttributeTag, IdString); + NewElement.Set_text(Value); + ActionElement.appendChild(NewElement); + end + else + raise EBold.CreateFmt('%s.AddIdentifiedValue: no action set', [ClassName]); end; procedure TBoldXMLRequest.ReloadIdentifiedValues; @@ -412,7 +417,9 @@ procedure TBoldXMLRequest.ReloadIdentifiedValues; constructor TBoldXMLRequest.Create; begin - raise EBold.CreateFmt(sSOAPBadConstructorToUse, [ClassName]); + raise EBold.CreateFmt('%s.Create: Use the constructors CreateFromXML or CreateInitialized', [ClassName]); end; +initialization + end. diff --git a/Source/Common/Subscription/BoldDeriver.pas b/Source/Common/Subscription/BoldDeriver.pas index cf15636..0395182 100644 --- a/Source/Common/Subscription/BoldDeriver.pas +++ b/Source/Common/Subscription/BoldDeriver.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldDeriver; interface @@ -21,13 +24,15 @@ TBoldDeriver = class; { TBoldAbstractDeriver } TBoldAbstractDeriver = class(TBoldSubscriber) - private - fDerivedObject: TObject; - fSubscribe: Boolean; - procedure SetDeriverState(Value: TBoldDeriverState); - procedure SetSubscribe(value: boolean); + strict private function GetIsDeriving: Boolean; - protected + function GetIsCurrent: Boolean; + procedure DeriveAndSubscribe(subscribe: Boolean); + strict protected + procedure SetSubscribe(value: boolean); virtual; + function GetSubscribe: Boolean; virtual; + function GetDerivedObject: TObject; virtual; abstract; + procedure SetDeriverState(Value: TBoldDeriverState); procedure SetInternalDeriverState(const Value: TBoldDeriverState); virtual; abstract; function GetInternalDeriverState: TBoldDeriverState; virtual; abstract; procedure Receive(Originator: TObject; OriginalEvent: TBoldEvent; @@ -36,28 +41,27 @@ TBoldAbstractDeriver = class(TBoldSubscriber) procedure DoDeriveAndSubscribe(subscribe: Boolean); virtual; abstract; procedure DoNotifyOutOfDate; virtual; procedure DoReverseDerive; virtual; - function GetCanReverseDerive: Boolean; virtual; abstract; + function GetCanReverseDerive: Boolean; virtual; abstract; property InternalDeriverState: TBoldDeriverState read GetInternalDeriverState write SetInternalDeriverState; + function GetContextString: string; override; public - constructor Create(DerivedObject: TObject); procedure MarkSubscriptionOutOfdate; procedure MarkOutOfdate; procedure EnsureCurrent; procedure Derive; procedure ReverseDerive; - property DerivedObject: TObject read fDerivedObject; - property Subscribe: Boolean read fSubscribe write SetSubscribe; + property DerivedObject: TObject read GetDerivedObject; + property Subscribe: Boolean read GetSubscribe write SetSubscribe; property IsDeriving: Boolean read GetIsDeriving; - property CanReverseDerive: Boolean read GetCanReverseDerive; + property IsCurrent: Boolean read GetIsCurrent; end; - { TBoldEventPluggedDeriver } - TBoldEventPluggedDeriver = class(TBoldAbstractDeriver) - private - fOnDeriveAndSubscribe: TBoldDeriveAndResubscribe; + TBoldEventPluggedDeriver = class (TBoldAbstractDeriver) + strict private + fOnderiveAndSubscribe: TBoldDeriveAndResubscribe; fOnReverseDerive: TBoldReverseDerive; fOnNotifyOutOfDate: TBoldJustNotifyEvent; - protected + strict protected procedure DoDeriveAndSubscribe(subscribe: Boolean); override; procedure DoNotifyOutOfDate; override; procedure DoReverseDerive; override; @@ -70,11 +74,18 @@ TBoldEventPluggedDeriver = class(TBoldAbstractDeriver) { TBoldDeriver } TBoldDeriver = class(TBoldEventPluggedDeriver) - private + strict private + fDerivedObject: TObject; fInternalDeriverState: TBoldDeriverState; - protected + fSubscribe: Boolean; + strict protected + procedure SetSubscribe(value: boolean); override; + function GetSubscribe: Boolean; override; procedure SetInternalDeriverState(const Value: TBoldDeriverState); override; function GetInternalDeriverState: TBoldDeriverState; override; + function GetDerivedObject: TObject; override; + public + constructor Create(DerivedObject: TObject); end; const @@ -83,28 +94,27 @@ TBoldDeriver = class(TBoldEventPluggedDeriver) implementation uses -SysUtils, - BoldCommonConst; - + SysUtils, + Classes, + BoldSystem, + BoldRev; { TBoldDeriver } - -constructor TBoldAbstractDeriver.Create(DerivedObject: TObject); -begin - inherited Create; - fDerivedObject := DerivedObject; - Subscribe := True; -end; - procedure TBoldAbstractDeriver.Derive; var NewState: TBoldDeriverState; begin - NewState := bdsSubscriptionOutOfdate; + if Subscribe then + NewState := bdsSubscriptionOutOfdate + else + NewState := bdsOutOfdate; try repeat if (DeriverState = bdsSubscriptionOutOfdate) then + begin + CancelAllSubscriptions; DeriverState := bdsDerivingAndSubscribing + end else DeriverState := bdsDeriving; if not (DeriverState in bdsIsDeriving) then @@ -116,27 +126,54 @@ procedure TBoldAbstractDeriver.Derive; end; end; +procedure TBoldAbstractDeriver.DeriveAndSubscribe(subscribe: Boolean); +begin; + DoDeriveAndSubscribe(Subscribe); +end; + procedure TBoldAbstractDeriver.DoNotifyOutOfDate; begin - // no action end; procedure TBoldAbstractDeriver.DoReverseDerive; begin - raise EBold.CreateFmt(sCannotReverseDerive, [ClassName]); + raise EBold.CreateFmt('%s: can''t reverse derive', [ClassName]); end; procedure TBoldAbstractDeriver.EnsureCurrent; -begin +begin if (DeriverState in [bdsOutOfDate, bdsSubscriptionOutOfDate]) then Derive; end; +function TBoldAbstractDeriver.GetContextString: string; +begin + result := ''; + if Assigned(DerivedObject) then + if DerivedObject is TComponent then + result := TComponent(DerivedObject).Name + else + if DerivedObject is TBoldSubscribableObject then + result := TBoldSubscribableObject(DerivedObject).ContextString + else + Result := DerivedObject.ClassName; +end; + +function TBoldAbstractDeriver.GetIsCurrent: Boolean; +begin + result := DeriverState = bdsCurrent; +end; + function TBoldAbstractDeriver.GetIsDeriving: Boolean; begin Result := DeriverState in bdsIsDeriving; end; +function TBoldAbstractDeriver.GetSubscribe: Boolean; +begin + Result := true; +end; + procedure TBoldAbstractDeriver.MarkSubscriptionOutOfdate; begin DeriverState := bdsSubscriptionOutOfDate; @@ -144,7 +181,6 @@ procedure TBoldAbstractDeriver.MarkSubscriptionOutOfdate; procedure TBoldAbstractDeriver.MarkOutOfdate; begin - // avoids going from Subscriptionoutofdate to OutOfDate if DeriverState = bdsCurrent then DeriverState := bdsOutOfDate; end; @@ -165,7 +201,7 @@ procedure TBoldAbstractDeriver.Receive(Originator: TObject; DeriverState := bdsReverseDerivingSubscriptionOutOfDate; end; else - raise EBold.CreateFmt(sUnknownMessageReceived, [ClassName, RequestedEvent]); + raise EBold.CreateFmt('%s.Receive: Unknown message received (%d)', [ClassName, RequestedEvent]); end; end; @@ -178,15 +214,13 @@ procedure TBoldAbstractDeriver.SetDeriverState(Value: TBoldDeriverState); var OldState: TBoldDeriverState; begin - // FIXME check legal transitions; - if Value <> DeriverState then + OldState := InternalDeriverState; + if Value <> OldState then begin - OldState := InternalDeriverState; - // exit actions - None... + if not (OldState in [bdsCurrent, bdsOutOfDate, bdsSubscriptionOutOfDate, bdsDeriving, bdsDerivingAndSubscribing, bdsReverseDeriving, bdsReverseDerivingSubscriptionOutOfDate]) then + raise Exception.Create('TBoldAbstractDeriver.SetDeriverState old state is ' + IntToStr(Integer(oldState))); InternalDeriverState := Value; - - // entry actions - if (OldState <> bdsOutOfDate) and // Check on OldState is primarily an optimization not to notify multiple times! + if (OldState <> bdsOutOfDate) and (value in [bdsOutOfDate, bdsSubscriptionOutOfDate]) then DoNotifyOutOfDate; @@ -195,14 +229,20 @@ procedure TBoldAbstractDeriver.SetDeriverState(Value: TBoldDeriverState); bdsReverseDerivingSubscriptionOutOfDate: CancelAllSubscriptions; bdsDerivingAndSubscribing: - DoDeriveAndSubscribe(True); + DeriveAndSubscribe(True); bdsDeriving: - DoDeriveAndSubscribe(False); + DeriveAndSubscribe(False); end; end end; procedure TBoldAbstractDeriver.SetSubscribe(value: boolean); +begin + raise Exception.Create('Subscribe not settable for this class'); + +end; + +procedure TBoldDeriver.SetSubscribe(value: boolean); begin if value <> Subscribe then begin @@ -235,10 +275,15 @@ procedure TBoldEventPluggedDeriver.DoNotifyOutOfDate; procedure TBoldEventPluggedDeriver.DoReverseDerive; begin - SetDeriverState(bdsReverseDeriving); - if Assigned(fOnReverseDerive) then + if DeriverState = bdsSubscriptionOutOfDate then begin + SetDeriverState(bdsReverseDerivingSubscriptionOutOfDate); + end else begin + SetDeriverState(bdsReverseDeriving); + end; + if Assigned(fOnReverseDerive) then begin fOnReverseDerive(DerivedObject); - case deriverstate of + end; + case DeriverState of bdsReverseDeriving: SetDeriverState(bdsOutOfDate); bdsReverseDerivingSubscriptionOutOfDate: SetDeriverState(bdsSubscriptionOutOfDate); end; @@ -249,15 +294,34 @@ function TBoldEventPluggedDeriver.GetCanReverseDerive: Boolean; Result := Assigned(OnReverseDerive); end; +function TBoldDeriver.GetSubscribe: Boolean; +begin + Result := fSubscribe; +end; + procedure TBoldDeriver.SetInternalDeriverState( const Value: TBoldDeriverState); begin FInternalDeriverState := Value; end; +constructor TBoldDeriver.Create(DerivedObject: TObject); +begin + inherited Create; + fDerivedObject := DerivedObject; + Subscribe := true; +end; + +function TBoldDeriver.GetDerivedObject: TObject; +begin + Result := fDerivedObject; +end; + function TBoldDeriver.GetInternalDeriverState: TBoldDeriverState; begin Result := FInternalDeriverState; end; +initialization + end. diff --git a/Source/Common/Subscription/BoldSubscribableCollection.pas b/Source/Common/Subscription/BoldSubscribableCollection.pas index eaebb3a..c9c1d76 100644 --- a/Source/Common/Subscription/BoldSubscribableCollection.pas +++ b/Source/Common/Subscription/BoldSubscribableCollection.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldSubscribableCollection; interface @@ -28,7 +31,9 @@ TBoldSubscribableCollection = class(TCollection) OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent); procedure SendEvent(OriginalEvent: TBoldEvent); procedure SendExtendedEvent(OriginalEvent: TBoldEvent; const Args: array of const); +{$IFNDEF BOLD_NO_QUERIES} function SendQuery(OriginalEvent: TBoldEvent; const Args: array of const; Subscriber: TBoldSubscriber): Boolean; +{$ENDIF} property HasSubscribers: Boolean read GetHasSubscribers; end; @@ -49,14 +54,17 @@ TBoldSubscribableCollectionItem = class(TCollectionItem) OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent); procedure SendEvent(OriginalEvent: TBoldEvent); procedure SendExtendedEvent(OriginalEvent: TBoldEvent; const Args: array of const); +{$IFNDEF BOLD_NO_QUERIES} function SendQuery(OriginalEvent: TBoldEvent; const Args: array of const; Subscriber: TBoldSubscriber): Boolean; +{$ENDIF} property HasSubscribers: Boolean read GetHasSubscribers; end; implementation uses - SysUtils; + SysUtils, + BoldRev; {---TBoldSubscribableCollection---} @@ -99,10 +107,12 @@ procedure TBoldSubscribableCollection.SendEvent(OriginalEvent: TBoldEvent); fPublisher.SendExtendedEvent(Self, OriginalEvent, []); end; +{$IFNDEF BOLD_NO_QUERIES} function TBoldSubscribableCollection.SendQuery(OriginalEvent: TBoldEvent; const Args: array of const; Subscriber: TBoldSubscriber): Boolean; begin result := not Assigned(fPublisher) or fPublisher.SendQuery(Self, OriginalEvent, Args, Subscriber); end; +{$ENDIF} procedure TBoldSubscribableCollection.SendExtendedEvent( OriginalEvent: TBoldEvent; @@ -156,11 +166,12 @@ procedure TBoldSubscribableCollectionItem.SendEvent(OriginalEvent: TBoldEvent); if Assigned(fPublisher) then fPublisher.SendExtendedEvent(Self, OriginalEvent, []); end; - +{$IFNDEF BOLD_NO_QUERIES} function TBoldSubscribableCollectionItem.SendQuery(OriginalEvent: TBoldEvent; const Args: array of const; Subscriber: TBoldSubscriber): Boolean; begin result := not Assigned(fPublisher) or fPublisher.SendQuery(Self, OriginalEvent, Args, Subscriber); end; +{$ENDIF} procedure TBoldSubscribableCollectionItem.SendExtendedEvent( OriginalEvent: TBoldEvent; @@ -174,4 +185,7 @@ function TBoldSubscribableCollectionItem.GetHasSubscribers: Boolean; result := assigned(fPublisher) and Publisher.HasSubscribers; end; + + +initialization end. diff --git a/Source/Common/Subscription/BoldSubscription.pas b/Source/Common/Subscription/BoldSubscription.pas index 643d62f..71704cf 100644 --- a/Source/Common/Subscription/BoldSubscription.pas +++ b/Source/Common/Subscription/BoldSubscription.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldSubscription; interface @@ -8,37 +11,48 @@ interface const beMinSmallReserved = 0; - beMaxSmallReserved = 23; - beMinSmallUser = 24; - beMaxSmallUser = 31; + beMaxSmallReserved = 27; + beMinSmallUser = 28; + beMaxSmallUser = 30; beMaxEvent = 32767; beMinUser = 4096; beMaxUser = beMaxEvent; bqMinQuery = beMaxEvent+1; bpeMinReserved = 1024; + bqMaxQuery = 100000; + beDestroying = 0; {General message for all subscribables} - beMemberChanged = 2; beObjectDeleted = 3; beObjectCreated = 11; {Object events} + beMemberChanged = 1; beObjectDeleted = 2; beObjectCreated = 3; {Object events} beItemAdded = 4; beItemDeleted = 5; beItemReplaced = 6; beOrderChanged = 7; {ObjectList events} beValueChanged = 8; {value of attribute or ObjectReference changed} beValueIdentityChanged = 9; {Actual identity of anElement.value changed} + breReSubscribe = 10; + beDirtyListInvalidOrItemDeleted = 11; beValueInvalid = 12; - beDerivedSoonDestroyed = 13; - beLocatorDestroying = 14; - beDirtyListInvalidOrItemDeleted = 15; - beQualifierChanged = 16; - beDeactivating = 17; // sent by persistencehandles - beRolledBack = 18; // sent by TBoldSystem - bePostUpdateId = 19; // send by TBoldObject when the ID is updated to allow regions to rehash themselves - bePreUpdateId = 20; // send by TBoldObject when the ID is updated to allow regions to rehash themselves - beObjectFetched = 21; // sent by TBoldObject when it has been recreated in memory + beLocatorDestroying = 13; + beObjectTimestampChanged = beValueIdentityChanged; // or perhaps use a separate integer ? + beQualifierChanged = 14; + beDeactivating = 15; + beRolledBack = 16; + bePostUpdateId = 17; + bePreUpdateId = 18; + beObjectFetched = 19; + beObjectUnloaded = 20; // sent by TBoldSystem before an object gets unloaded from memory breReEvaluate = beValueChanged; {backwards compatibility} - breReSubscribe = 10; - beServerSubscriberRemoved = 22; + beDefaultRequestedEvent = breReEvaluate; - beValueEvents = [beItemAdded, beItemDeleted, beItemReplaced, beOrderChanged, beValueChanged, beValueInvalid]; + beServerSubscriberRemoved = 21; + + beBeginUpdate = 22; // sent by TBoldObjectList before loops + beEndUpdate = 23; // sent by TBoldObjectList after loops + beObjectBecomingClean = 24; + beObjectBecomingDirty = 25; + beMemberBecomingClean = 26; + beMemberBecomingDirty = 27; + beDirtyListEvents = [beObjectBecomingDirty, beObjectBecomingClean, beMemberBecomingDirty, beMemberBecomingClean]; - // BoldPersistenceEvents + beValueEvents = [beItemAdded, beItemDeleted, beItemReplaced, beOrderChanged, beValueChanged, beValueInvalid]; bpeStartFetch = bpeMinReserved + 0; bpeEndFetch = bpeMinReserved + 1; bpeStartUpdate = bpeMinReserved + 2; @@ -55,22 +69,59 @@ interface bpeProgressEnd = bpeMinReserved + 13; bpeMaxReserved = bpeMinReserved + 13; + // additional persistence events + bpeStartFetchMember = 42; + bpeEndFetchMember = 43; + bpeStartFetchObjectById = 44; + bpeEndFetchObjectById = 45; + bpeStartFetchClass = 46; + bpeEndFetchClass = 47; + bpeStartFetchAllInClassWithRawSQL = 48; + bpeEndFetchAllInClassWithRawSQL = 49; + bpeStartFetchAllInClassWithSQL = 50; + bpeEndFetchAllInClassWithSQL = 51; + + // OSS Events + boeClassChanged = 52; + boeEmbeddedStateOfObjectChanged = 53; + boeObjectCreated = 54; + boeObjectDeleted = 55; + boeNonEmbeddedStateOfObjectChanged = 56; + boeMemberChanged = 57; + beOssEvents = [boeClassChanged, boeEmbeddedStateOfObjectChanged, boeObjectCreated, boeObjectDeleted, boeNonEmbeddedStateOfObjectChanged, boeMemberChanged]; + bePrepareModify = 38; beCompleteModify = 39; bePrepareDelete = 41; - + {$IFNDEF BOLD_NO_QUERIES} bqMayUpdate = bqMinQuery + 1; bqMayModify = bqMinQuery + 2; bqMayDelete = bqMinQuery + 3; bqMayCommit = bqMinQuery + 4; - + {$ENDIF} bqMaxSubscription = bqMinQuery + 6; + const + beBigEventFlag = 1 shl 30; + +{$IFDEF BoldSystemBroadcastMemberEvents} + beBroadcastMemberEvents = beValueEvents + [beCompleteModify] + beDirtyListEvents; +{$ENDIF} + + { Subscription Statistics } +var + PublisherCount: Integer = 0; + SubscriberCount: Integer = 0; + ActiveSubscriptionCount: Integer = 0; + _SendEventMatch: Int64 = 0; + _SendExtendedEvent: Int64 = 0; +{$IFNDEF BOLD_NO_QUERIES} + _SendQuery: Int64 = 0; + _QueryMatch: Int64 = 0; +{$ENDIF} {Forward declarations of all classes} type TBoldPublisher = class; - TBoldSubscription = class; - TBoldSmallEventSubscription = class; TBoldSubscriber = class; TBoldPassthroughSubscriber = class; TBoldSubscribableObject = class; @@ -79,11 +130,11 @@ TBoldSubscribablePersistent = class; {TBoldEvent itself is a Smallint. TBoldEventset is a set of of small values (0..31) It is possible to subscribe either to one particular event, or to a set of small events. Of the small - events, 0..23 are reserved for Bold and 24..31 are available for users. Of the larger events, + events, 0..23 are reserved for Bold and 24..30 are available for users. Of the larger events, 32..64 are reserved for the future use of Bold, the rest are available for user programming} {TBoldEvent} - TBoldEvent = Integer; + TBoldEvent = 0..bqMaxQuery; TBoldRequestedEvent = Integer; TBoldSmallEvent = beMinSmallReserved..beMaxSmallUser; @@ -101,210 +152,316 @@ TBoldSubscribablePersistent = class; TBoldPublisherFlag = (bpfNeedsPacking); TBoldPublisherFlags = set of TBoldPublisherFlag; - TBoldSubscriptionList = TList; + + {---TBoldSubscription---} + TBoldSubscription = record + public + Subscriber: TBoldSubscriber; + IndexInSubscriber: integer; + RequestedEvent: TBoldRequestedEvent; + MatchCondition: Integer; + function GetIsSmallEventSubscription: Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure ClearEntry; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure ReIndexsSubscriber(NewPublisherIndex: integer); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function IsMatchingEvent(OriginalEvent: TBoldEvent): Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure ExtendEvents(Events: TBoldSmallEventSet); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + property IsSmallEventSubscription: Boolean read GetIsSmallEventSubscription; + end; + + TBoldPublisherReference = record + public + Publisher: TBoldPublisher; + Index: integer; // index in the publishers subscriptionarray + end; + + TBoldPublisherReferenceArray = array of TBoldPublisherReference; + + TBoldSubscriptionArray = array of TBoldSubscription; {---TBoldPublisher---} TBoldPublisher = class(TBoldMemoryManagedObject) - private - fSubscriptions: TBoldSubscriptionList; + strict private + fSubscriptionArray: TBoldSubscriptionArray; + fSubscriptionCount: integer; fPublisherFlags: TBoldPublisherFlags; - property Subscriptions: TBoldSubscriptionList read fSubscriptions; - function GetHasSubscribers: Boolean; - procedure AddToSubscriptions(Subscription: TBoldSubscription); {called by TBoldSubcrition} - function GetNeedsPacking: Boolean; + fSubscribableObject: TBoldSubscribableObject; + fHoleCount: Integer; + function GetHasSubscribers: Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure EnsureFreeSpace; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetNeedsPacking: Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure SetNeedsPacking(Value: Boolean); - class procedure DelayTillAfterNotification(Event: TNotifyEvent; Sender: TObject; Receiver: TObject); class procedure RemoveFromPostNotificationQueue(Receiver: TObject); procedure PackSubscriptions(dummy: TObject); property NeedsPacking: Boolean read GetNeedsPacking write SetNeedsPacking; {Set by TBoldSubscription} - protected - procedure SetPublisherFlag(Flag: TBoldPublisherFlag; Value: Boolean); - function GetPublisherFlag(Flag: TBoldPublisherFlag): Boolean; + class var G_NotificationNesting: integer; + class var G_InPostNotification: Boolean; + private // actually unit internal + class procedure DelayTillAfterNotification(Event: TNotifyEvent; Sender: TObject; Receiver: TObject); + procedure ClearEntry(Subscriber: TBoldSubscriber; index: integer); // Do not use inline due to D2007 bug + function GetSubscriptionsAsText: string; + strict protected + procedure SetPublisherFlag(Flag: TBoldPublisherFlag; Value: Boolean); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetPublisherFlag(Flag: TBoldPublisherFlag): Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetContextString: string; virtual; + function GetDebugInfo: string; override; public constructor Create; destructor Destroy; override; - class procedure StartNotify; + class procedure StartNotify; {$IFDEF BOLD_INLINE} inline; {$ENDIF} class procedure EndNotify; - procedure NotifySubscribersAndClearSubscriptions(Originator: TObject); + procedure BoldForcedDequeuePostNotify; + procedure NotifySubscribersAndClearSubscriptions(Originator: TObject); {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure AddSmallSubscription(Subscriber: TBoldSubscriber; - Events: TBoldSmallEventSet; RequestedEvent: TBoldRequestedEvent); + Events: TBoldSmallEventSet; RequestedEvent: TBoldRequestedEvent = beDefaultRequestedEvent); {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure AddSubscription(Subscriber: TBoldSubscriber; - OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent); + OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent = beDefaultRequestedEvent); {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure SendExtendedEvent(Originator: TObject; OriginalEvent: TBoldEvent; const Args: array of const); - function SendQuery(Originator: TObject; OriginalEvent: TBoldEvent; const Args: array of const; Subscriber: TBoldSubscriber): Boolean; +{$IFNDEF BOLD_NO_QUERIES} + function SendQuery(Originator: TObject; OriginalEvent: TBoldEvent; const Args: array of const; Subscriber: TBoldSubscriber): Boolean; +{$ENDIF} + function HasMatchingSubscription(Subscriber: TBoldSubscriber): boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure CancelSubscriptionTo(Subscriber: TBoldSubscriber); property HasSubscribers: Boolean read GetHasSubscribers; - end; - - {---TBoldSubscription---} - TBoldSubscription = class(TBoldMemoryManagedObject) - private - fPublisher: TBoldPublisher; - fRequestedEvent: TBoldRequestedEvent; - fSubscriber: TBoldSubscriber; - protected - constructor Create(Publisher: TBoldPublisher; - Subscriber: TBoldSubscriber; RequestedEvent: TBoldRequestedEvent); - function IsMatchingEvent(OriginalEvent: TBoldEvent): Boolean; virtual; abstract; - procedure CloneTo(Subscriber: TBoldSubscriber; NewRequestedEvent: TBoldRequestedEvent); virtual; abstract; - procedure UnlinkFromSubscriber; - procedure UnlinkFromPublisher; - property Publisher: TBoldPublisher read fPublisher; - property RequestedEvent: TBoldRequestedEvent read fRequestedEvent; - property Subscriber: TBoldSubscriber read fSubscriber; - end; - - {---TBoldEventSubscription---} - TBoldEventSubscription = class(TBoldSubscription) - private - fEvent: TBoldEvent; - protected - function IsMatchingEvent(OriginalEvent: TBoldEvent): Boolean; override; - procedure CloneTo(Subscriber: TBoldSubscriber; NewRequestedEvent: TBoldRequestedEvent); override; - public - constructor Create(Publisher: TBoldPublisher; Subscriber: TBoldSubscriber; - OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent); - end; - - {---TBoldSmallEventSubscription---} - TBoldSmallEventSubscription = class(TBoldSubscription) - private - fEvents: TBoldSmallEventSet; - protected - procedure ExtendEvents(Events: TBoldSmallEventSet); - function IsMatchingEvent(OriginalEvent: TBoldEvent): Boolean; override; - procedure CloneTo(Subscriber: TBoldSubscriber; NewRequestedEvent: TBoldRequestedEvent); override; - public - constructor Create(Publisher: TBoldPublisher; Subscriber: TBoldSubscriber; - Events: TBoldSmallEventSet; RequestedEvent: TBoldRequestedEvent); + property SubscribableObject : TBoldSubscribableObject read fSubscribableObject write fSubscribableObject; + property SubscriptionCount: integer read fSubscriptionCount; + property ContextString: string read GetContextString; + property SubscriptionsAsText: string read GetSubscriptionsAsText; end; {---TBoldSubscriber---} TBoldSubscriber = class(TBoldMemoryManagedObject) - private - fSubscriptions: TList; - function GetSubscriptions: TList; - property Subscriptions: TList read GetSubscriptions; - procedure AddToSubscriptions(Subscription: TBoldSubscription); {called by TBoldSubcrition} + strict private + fSubscriptionArray: TBoldPublisherReferenceArray; + fSubscriptionCount: integer; + private // unit internal + procedure AddToSubscriptions(Publisher: TBoldPublisher; Index: integer); {$IFDEF BOLD_INLINE} inline; {$ENDIF} {called by TBoldSubscription} + procedure ClearEntry(Index: integer); {$IFDEF BOLD_INLINE} inline; {$ENDIF} {called by TBoldSubscription} + function GetSubscriptionsAsText: string; protected procedure Receive(Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent); virtual; abstract; procedure ReceiveExtended(Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent; const Args: array of const); virtual; + {$IFNDEF BOLD_NO_QUERIES} function Answer(Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent; const Args: array of const; Subscriber: TBoldSubscriber): Boolean; virtual; +{$ENDIF} function GetContextString: string; virtual; function GetHandlesExtendedEvents: Boolean; virtual; + function GetDebugInfo: string; override; public - destructor Destroy; override; - procedure CancelAllSubscriptions; - procedure CloneSubscriptions(Subscriber: TBoldSubscriber; OldRequestedEvent: TBoldRequestedEvent; NewRequestedEvent: TBoldRequestedEvent); + procedure AfterConstruction; override; + procedure BeforeDestruction; override; + procedure CancelAllSubscriptions; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function HasMatchingSubscription(APublisher: TBoldPublisher): boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure CancelSubscriptionTo(APublisher: TBoldPublisher); property ContextString: string read GetContextString; property HandlesExtendedEvents: Boolean read GetHandlesExtendedEvents; + property SubscriptionCount: integer read fSubscriptionCount; + property Subscriptions: TBoldPublisherReferenceArray read fSubscriptionArray; + property SubscriptionsAsText: string read GetSubscriptionsAsText; end; {---TBoldPassthroughSubscriber---} TBoldPassthroughSubscriber = class(TBoldSubscriber) - private + strict private fReceiveFunc: TBoldEventHandler; - fExtendedReceiveFunc: TBoldExtendedEventHandler; - fAnswerFunc: TBoldQueryHandler; protected procedure Receive(Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent); override; + function GetHandlesExtendedEvents: Boolean; override; + function GetContextString: string; override; + public + constructor Create(AReceiveFunc: TBoldEventHandler); + property receiveFunc: TBoldEventHandler read fReceiveFunc write fReceiveFunc; + end; + + {---TBoldPassthroughSubscriber---} + TBoldExtendedPassthroughSubscriber = class(TBoldPassthroughSubscriber) + strict private + fExtendedReceiveFunc: TBoldExtendedEventHandler; + {$IFNDEF BOLD_NO_QUERIES} + fAnswerFunc: TBoldQueryHandler; +{$ENDIF} + protected procedure ReceiveExtended(Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent; const Args: array of const); override; + {$IFNDEF BOLD_NO_QUERIES} function Answer(Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent; const Args: array of const; Subscriber: TBoldSubscriber): Boolean; override; +{$ENDIF} function GetHandlesExtendedEvents: Boolean; override; public - constructor Create(receiveFunc: TBoldEventHandler); - constructor CreateWithExtendedReceive(ExtendedReceiveFunc: TBoldExtendedEventHandler); - constructor CreateWithReceiveAndAnswer(ReceiveFunc: TBoldEventHandler; - AnswerFunc: TBoldQueryHandler); - property receiveFunc: TBoldEventHandler read fReceiveFunc write fReceiveFunc; + constructor CreateWithExtendedReceive(AExtendedReceiveFunc: TBoldExtendedEventHandler); +{$IFNDEF BOLD_NO_QUERIES} + constructor CreateWithReceiveAndAnswer(AReceiveFunc: TBoldEventHandler; + AAnswerFunc: TBoldQueryHandler); +{$ENDIF} end; {---TBoldSubscribableObject---} TBoldSubscribableObject = class(TBoldFlaggedObject) - private + strict private fPublisher: TBoldPublisher; - function GetHasSubscribers: Boolean; - function GetPublisher: TBoldPublisher; + function GetHasSubscribers: Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetPublisher: TBoldPublisher; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetSubscriptionsAsText: string; protected - procedure FreePublisher; + function GetDebugInfo: string; override; + procedure FreePublisher; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetContextString: string; virtual; property HasSubscribers: Boolean read GetHasSubscribers; property Publisher: TBoldPublisher read GetPublisher; public destructor Destroy; override; procedure AddSmallSubscription(Subscriber: TBoldSubscriber; - Events: TBoldSmallEventSet; RequestedEvent: TBoldRequestedEvent); + Events: TBoldSmallEventSet; RequestedEvent: TBoldRequestedEvent = beDefaultRequestedEvent); {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure AddSubscription(Subscriber: TBoldSubscriber; - OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent); + OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent = beDefaultRequestedEvent); {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure SendEvent(OriginalEvent: TBoldEvent); virtual; procedure SendExtendedEvent(OriginalEvent: TBoldEvent; const Args: array of const); virtual; - function SendQuery(OriginalEvent: TBoldEvent; const Args: array of const; Subscriber: TBoldSubscriber): Boolean; virtual; - end; +{$IFNDEF BOLD_NO_QUERIES} + function SendQuery(OriginalEvent: TBoldEvent; const Args: array of const; Subscriber: TBoldSubscriber; Originator: TObject = nil): Boolean; virtual; +{$ENDIF} + property ContextString: string read GetContextString; + property SubscriptionsAsText: string read GetSubscriptionsAsText; +end; {---TBoldSubscribableComponent---} TBoldSubscribableComponent = class(TComponent) - private + strict private fPublisher: TBoldPublisher; - function GetPublisher: TBoldPublisher; - protected + function GetPublisher: TBoldPublisher; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetSubscriptionsAsText: string; + strict protected function GetHasSubscribers: Boolean; virtual; property Publisher: TBoldPublisher read GetPublisher; - procedure FreePublisher; + procedure FreePublisher; {$IFDEF BOLD_INLINE} inline; {$ENDIF} public destructor Destroy; override; procedure AddSmallSubscription(Subscriber: TBoldSubscriber; - Events: TBoldSmallEventSet; RequestedEvent: TBoldRequestedEvent); + Events: TBoldSmallEventSet; RequestedEvent: TBoldRequestedEvent = beDefaultRequestedEvent); {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure AddSubscription(Subscriber: TBoldSubscriber; - OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent); - procedure SendEvent(Originator: TObject; OriginalEvent: TBoldEvent); + OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent = beDefaultRequestedEvent); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure SendEvent(Originator: TObject; OriginalEvent: TBoldEvent); {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure SendExtendedEvent(Originator: TObject; OriginalEvent: TBoldEvent; const Args: array of const); + {$IFNDEF BOLD_NO_QUERIES} function SendQuery(Originator: TObject; OriginalEvent: TBoldEvent; const Args: array of const; Subscriber: TBoldSubscriber): Boolean; + {$ENDIF} property HasSubscribers: Boolean read GetHasSubscribers; + property SubscriptionsAsText: string read GetSubscriptionsAsText; end; {--- TBoldSubscribablePersistent ---} TBoldSubscribablePersistent = class(TPersistent) - private + strict private fPublisher: TBoldPublisher; - function GetPublisher: TBoldPublisher; - protected + function GetPublisher: TBoldPublisher; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetSubscriptionsAsText: string; + strict protected function GetHasSubscribers: Boolean; virtual; property Publisher: TBoldPublisher read GetPublisher; - procedure FreePublisher; + protected + procedure FreePublisher; {$IFDEF BOLD_INLINE} inline; {$ENDIF} public - constructor Create; destructor Destroy; override; procedure AddSmallSubscription(Subscriber: TBoldSubscriber; - Events: TBoldSmallEventSet; RequestedEvent: TBoldRequestedEvent); + Events: TBoldSmallEventSet; RequestedEvent: TBoldRequestedEvent = beDefaultRequestedEvent); {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure AddSubscription(Subscriber: TBoldSubscriber; - OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent); - procedure SendEvent(Originator: TObject; OriginalEvent: TBoldEvent); + OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent = beDefaultRequestedEvent); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure SendEvent(Originator: TObject; OriginalEvent: TBoldEvent); {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure SendExtendedEvent(Originator: TObject; OriginalEvent: TBoldEvent; const Args: array of const); +{$IFNDEF BOLD_NO_QUERIES} function SendQuery(Originator: TObject; OriginalEvent: TBoldEvent; const Args: array of const; Subscriber: TBoldSubscriber): Boolean; +{$ENDIF} property HasSubscribers: Boolean read GetHasSubscribers; + property SubscriptionsAsText: string read GetSubscriptionsAsText; end; - - procedure BoldForcedDequeuePostNotify; + procedure BoldAddEventToPostNotifyQueue(Event: TNotifyEvent; Sender: TObject; Receiver: TObject); + function BoldEventToString(aEvent: integer): string; implementation uses SysUtils, BoldDefs, - BoldEventQueue, - BoldCommonConst; + BoldEventQueue; + +function BoldEventToString(aEvent: integer): string; +begin + case aEvent of + beDestroying: result := 'beDestroying'; + beMemberChanged: result := 'beMemberChanged'; + beObjectDeleted: result := 'beObjectDeleted'; + beObjectCreated: result := 'beObjectCreated'; + beItemAdded: result := 'beItemAdded'; + beItemDeleted: result := 'beItemDeleted'; + beItemReplaced: result := 'beItemReplaced'; + beOrderChanged: result := 'beOrderChanged'; + beValueChanged: result := 'beValueChanged'; + beValueIdentityChanged: result := 'beValueIdentityChanged'; + beValueInvalid: result := 'beValueInvalid'; +// beDerivedSoonDestroyed: result := 'beDerivedSoonDestroyed'; + beLocatorDestroying: result := 'beLocatorDestroying'; + beDirtyListInvalidOrItemDeleted: result := 'beDirtyListInvalidOrItemDeleted'; + beQualifierChanged: result := 'beQualifierChanged'; + beDeactivating: result := 'beDeactivating'; + beRolledBack: result := 'beRolledBack'; + bePostUpdateId: result := 'bePostUpdateId'; + bePreUpdateId: result := 'bePreUpdateId'; + beObjectFetched: result := 'beObjectFetched'; + bePrepareModify: result := 'bePrepareModify'; + beCompleteModify: result := 'beCompleteModify'; + bePrepareDelete: result := 'bePrepareDelete'; + breReSubscribe: result := 'breReSubscribe'; + beServerSubscriberRemoved: result := 'beServerSubscriberRemoved'; + bpeStartFetch: result := 'bpeStartFetch'; + bpeEndFetch: result := 'bpeEndFetch'; + bpeStartUpdate: result := 'bpeStartUpdate'; + bpeEndUpdate: result := 'bpeEndUpdate'; + bpeFetchObject: result := 'bpeFetchObject'; + bpeFetchMember: result := 'bpeFetchMember'; + bpeUpdateObject: result := 'bpeUpdateObject'; + bpeDeleteObject: result := 'bpeDeleteObject'; + bpeCreateObject: result := 'bpeCreateObject'; + bpeStartFetchID: result := 'bpeStartFetchID'; + bpeEndFetchID: result := 'bpeEndFetchID'; + bpeFetchId: result := 'bpeFetchId'; + bpeProgressStart: result := 'bpeProgressStart'; + bpeProgressEnd: result := 'bpeProgressEnd'; + {$IFNDEF BOLD_NO_QUERIES} + bqMayUpdate: result := 'bqMayUpdate'; + bqMayModify: result := 'bqMayModify'; + bqMayDelete: result := 'bqMayDelete'; + bqMayCommit: result := 'bqMayCommit'; + {$ENDIF} + else + case aEvent of + beMinSmallReserved..beMaxSmallReserved : result := 'Unknown SmallReserved event: ' + IntToStr(aEvent); + beMinSmallUser..beMaxSmallUser : result := 'Unknown SmallUser event: ' + IntToStr(aEvent); + beMinUser..beMaxEvent : result := 'Unknown UserEvent event: ' + IntToStr(aEvent); + bqMinQuery..bqMaxQuery : result := 'Unknown Query event: ' + IntToStr(aEvent); + else + result:= 'Unknown event: ' + IntToStr(aEvent); + end; + end; +end; var - G_NotificationNesting: integer = 0; G_PostNotifyQueue: TboldEventQueue = nil; - G_InPostNotification: Boolean = false; -procedure BoldForcedDequeuePostNotify; +function GetNewLength(oldLength: integer): integer; {$IFDEF BOLD_INLINE} inline; {$ENDIF} +begin + if oldLength > 64 then + Result := oldLength + oldLength div 4 + else if oldLength > 8 then + Result := oldLength + 16 + else + Result := oldLength + 4; +end; + +procedure TBoldPublisher.BoldForcedDequeuePostNotify; var OldInPostNotification: Boolean; begin @@ -323,154 +480,358 @@ procedure BoldAddEventToPostNotifyQueue(Event: TNotifyEvent; Sender: TObject; Re TBoldPublisher.DelayTillAfterNotification(Event, Sender, Receiver); end; +class procedure TBoldPublisher.StartNotify; +begin + Inc(G_NotificationNesting); +end; + +class procedure TBoldPublisher.EndNotify; +begin + Dec(G_NotificationNesting); + if (G_NotificationNesting = 0) and Assigned(G_PostNotifyQueue) and (not G_InPostNotification) then + begin + G_InPostNotification := True; + G_PostNotifyQueue.DequeueAll; {may add and delete entries, Eventqueue can handle it} + G_InPostNotification := False; + end; +end; + +{---TBoldSubscription---} + +function TBoldSubscription.GetIsSmallEventSubscription: Boolean; +begin + Result := (MatchCondition and beBigEventFlag) = 0; +end; + +function TBoldSubscription.IsMatchingEvent(OriginalEvent: TBoldEvent): Boolean; +begin + if (OriginalEvent <= beMaxSmallUser) then + result := (OriginalEvent in TBoldSmallEventSet(MatchCondition)) and ((MatchCondition and beBigEventFlag) = 0) + else + Result := (OriginalEvent or beBigEventFlag) = MatchCondition; +end; + +procedure TBoldSubscription.ReIndexsSubscriber(NewPublisherIndex: integer); +begin + Subscriber.Subscriptions[IndexInSubscriber].Index := NewPublisherIndex; +end; + +procedure TBoldSubscription.ExtendEvents(Events: TBoldSmallEventSet); +begin + if (MatchCondition and beBigEventFlag) <> 0 then + raise EBoldInternal.Create('TBoldSubscription.ExtendEvents called for big event'); + MatchCondition := Integer(TBoldSmallEventSet(MatchCondition) + Events); +end; + +procedure TBoldSubscriber.ClearEntry(Index: integer); +begin + Subscriptions[Index].Publisher := nil; + // Attempt to reuse empty places + if fSubscriptionCount-1 = index then + begin + while (fSubscriptionCount > 0) and (Subscriptions[fSubscriptionCount-1].Publisher = nil) do + Dec(fSubscriptionCount); + if (fSubscriptionCount < length(fSubscriptionArray) div 2) and (length(fSubscriptionArray) > 4) then + SetLength(fSubscriptionArray, fSubscriptionCount); + end; +end; + +procedure TBoldSubscriber.AddToSubscriptions(Publisher: TBoldPublisher; Index: integer); +begin + if fSubscriptionCount = Length(fSubscriptionArray) then + SetLength(fSubscriptionArray, GetNewLength(fSubscriptionCount)); + fSubscriptionArray[fSubscriptionCount].Publisher := Publisher; + fSubscriptionArray[fSubscriptionCount].Index := Index; + Inc(fSubscriptionCount); + Inc(ActiveSubscriptionCount); +end; + +procedure TBoldSubscription.ClearEntry; +begin + if Assigned(subscriber) then + begin + Subscriber.ClearEntry(IndexInSubscriber); + Subscriber := nil; + Dec(ActiveSubscriptionCount); + end; +end; + {---TBoldPublisher---} -constructor TBoldPublisher.Create; +function TBoldPublisher.GetContextString: string; begin - inherited; - fSubscriptions := TBoldSubscriptionList.Create; + if Assigned(fSubscribableObject) then + result := fSubscribableObject.ClassName + else + result := ClassName; end; -destructor TBoldPublisher.Destroy; +function TBoldPublisher.GetDebugInfo: string; begin - Assert(not Assigned(fSubscriptions)); - if NeedsPacking then - RemoveFromPostNotificationQueue(self); - inherited; + result := GetContextString; end; -procedure TBoldPublisher.NotifySubscribersAndClearSubscriptions(Originator: TObject); +function TBoldPublisher.GetHasSubscribers: Boolean; +begin + result := fSubscriptionCount > 0; +end; + +function TBoldPublisher.GetPublisherFlag(Flag: TBoldPublisherFlag): Boolean; +begin + result := Flag in fPublisherFlags; +end; + +function TBoldPublisher.GetSubscriptionsAsText: string; var - I: Integer; + i,j: integer; begin - if not Assigned(fSubscriptions) then - Exit; - SendExtendedEvent(Originator, beDestroying, []); - for I := 0 to Subscriptions.Count - 1 do - TBoldSubscription(Subscriptions[I]).UnlinkFromPublisher; - FreeAndNil(fSubscriptions); + result := ''; + j := 0; + for I := 0 to Length(fSubscriptionArray) - 1 do + begin + if Assigned(fSubscriptionArray[i].Subscriber) then + begin + result := result + IntToStr(j) + ':' + fSubscriptionArray[i].Subscriber.ContextString+ #13#10; + inc(j); + end; + end; end; -procedure TBoldPublisher.SendExtendedEvent(Originator: TObject; - OriginalEvent: TBoldEvent; - const Args: array of const); +function TBoldPublisher.HasMatchingSubscription( + Subscriber: TBoldSubscriber): boolean; var - I: Integer; - Subscription: TBoldSubscription; + i: integer; begin - if Assigned(Subscriptions) then + if fSubscriptionCount < Subscriber.SubscriptionCount then begin - StartNotify; - for I := 0 to Subscriptions.Count - 1 do + for I := fSubscriptionCount - 1 downto 0 do + if (fSubscriptionArray[I].Subscriber = Subscriber) then + begin + result := true; + exit; + end; + end + else + for I := Subscriber.SubscriptionCount - 1 downto 0 do + if (Subscriber.Subscriptions[I].Publisher = Self) then begin - Subscription := TBoldSubscription(fSubscriptions.Items[I]); - if Assigned(Subscription.Subscriber) and Subscription.IsMatchingEvent(OriginalEvent) then - if Subscription.Subscriber.HandlesExtendedEvents then - Subscription.Subscriber.ReceiveExtended(Originator, OriginalEvent, Subscription.RequestedEvent, Args) - else - Subscription.Subscriber.Receive(Originator, OriginalEvent, Subscription.RequestedEvent); + result := true; + exit; end; + result := false; +end; + +procedure TBoldPublisher.CancelSubscriptionTo(Subscriber: TBoldSubscriber); +var + i: integer; +begin + StartNotify; + try + if fSubscriptionCount <= Subscriber.SubscriptionCount then + begin + for I := 0 to SubscriptionCount-1 do + if (fSubscriptionArray[I].Subscriber = Subscriber) then + ClearEntry(Subscriber, i); + end + else + for I := 0 to Subscriber.SubscriptionCount - 1 do + if (Subscriber.Subscriptions[I].Publisher = Self) then + ClearEntry(Subscriber, Subscriber.Subscriptions[I].Index); + finally EndNotify; end; end; -procedure TBoldPublisher.AddToSubscriptions(Subscription: TBoldSubscription); +procedure TBoldPublisher.SetPublisherFlag(Flag: TBoldPublisherFlag; + Value: Boolean); begin - Subscriptions.Add(Subscription); + if Value then + Include(fPublisherFlags, Flag) + else + Exclude(fPublisherFlags, Flag); +end; + +function TBoldPublisher.GetNeedsPacking: Boolean; +begin + result := GetPublisherFlag(bpfNeedsPacking); +end; + +procedure TBoldPublisher.SetNeedsPacking(Value: Boolean); +begin + if NeedsPacking <> Value then + begin + SetPublisherFlag(bpfNeedsPacking, Value); + // the postnotify queue will be gone if we are in finalization, + // but then we don't need to pack since we will be destroyed soon anyway... + if Value and assigned(G_PostNotifyQueue) then + DelayTillAfterNotification(PackSubscriptions, nil, Self); + end; +end; + +procedure TBoldPublisher.EnsureFreeSpace; +begin + if fSubscriptionCount = Length(fSubscriptionArray) then + SetLength(fSubscriptionArray, GetNewLength(fSubscriptionCount)); +end; + +procedure TBoldPublisher.ClearEntry(Subscriber: TboldSubscriber; index: integer); +begin + if fSubscriptionArray[index].Subscriber <> Subscriber then + begin + if Assigned(fSubscriptionArray[index].Subscriber) and Assigned(Subscriber) then + Assert(false, Format('TBoldPublisher.ClearEntry: %s <> %s; index = %d', [fSubscriptionArray[index].Subscriber.ContextString, Subscriber.ContextString, Index])) + else + Assert(false, Format('TBoldPublisher.ClearEntry: %s; index = %d', [Subscriber.ContextString, Index])); + end; + fSubscriptionArray[index].ClearEntry; + // attempt to rewind empty slots + if fSubscriptionCount - 1 = index then + begin + Dec(fSubscriptionCount); + while (fSubscriptionCount <> 0) and (fSubscriptionArray[fSubscriptionCount-1].Subscriber = nil) do + begin + Dec(fSubscriptionCount); + Dec(fHoleCount); + end; + end + else + Inc(fHoleCount); + if (fSubscriptionCount-fHoleCount < Length(fSubscriptionArray) div 2) then + NeedsPacking := True; end; procedure TBoldPublisher.AddSmallSubscription(Subscriber: TBoldSubscriber; Events: TBoldSmallEventSet; RequestedEvent: TBoldRequestedEvent); var - I: Integer; - Subscription: TBoldSubscription; - LocalSubscriptions: TBoldSubscriptionList; + I, index: Integer; begin if not assigned(Subscriber) then exit; - if Subscriptions.Count < Subscriber.Subscriptions.Count then + if fSubscriptionCount <= Subscriber.SubscriptionCount then begin - localSubscriptions := Subscriptions; - for I := 0 to localSubscriptions.Count - 1 do + for I := 0 to fSubscriptionCount - 1 do begin - Subscription := TBoldSubscription(LocalSubscriptions.Items[I]); - if (Subscription.Subscriber = Subscriber) and - (Subscription.RequestedEvent = RequestedEvent) and - (Subscription is TBoldSmallEventSubscription) then + if (fSubscriptionArray[I].Subscriber = Subscriber) and + (fSubscriptionArray[I].RequestedEvent = RequestedEvent) and + (fSubscriptionArray[I].isSmallEventSubscription) then begin - TBoldSmallEventSubscription(Subscription).ExtendEvents(Events); + fSubscriptionArray[I].ExtendEvents(Events); Exit; end; end; end else - begin - localSubscriptions := Subscriber.Subscriptions; - for I := 0 to localSubscriptions.Count - 1 do + begin + for I := 0 to Subscriber.SubscriptionCount - 1 do begin - Subscription := TBoldSubscription(LocalSubscriptions.Items[I]); - if (Subscription.Publisher = Self) and - (Subscription.RequestedEvent = RequestedEvent) and - (Subscription is TBoldSmallEventSubscription) then + if (Subscriber.Subscriptions[I].Publisher = Self) then begin - TBoldSmallEventSubscription(Subscription).ExtendEvents(Events); - Exit; + Index := Subscriber.Subscriptions[I].Index; + if (fSubscriptionArray[Index].RequestedEvent = RequestedEvent) and + fSubscriptionArray[Index].isSmallEventSubscription then + begin + fSubscriptionArray[Index].ExtendEvents(Events); + Exit; + end; end; end; end; - TBoldSmallEventSubscription.Create(Self, Subscriber, Events, RequestedEvent); + if Events = [] then + Raise EBold.CreateFmt('%s.AddSmallSubscription: Events is empty set, probably event is a not small event.', [ClassName]); + EnsureFreeSpace; + fSubscriptionArray[fSubscriptionCount].Subscriber := Subscriber; + fSubscriptionArray[fSubscriptionCount].IndexInSubscriber := Subscriber.SubscriptionCount; + fSubscriptionArray[fSubscriptionCount].RequestedEvent := RequestedEvent; + fSubscriptionArray[fSubscriptionCount].MatchCondition := Integer(Events); + Subscriber.AddToSubscriptions(self, fSubscriptionCount); + Inc(fSubscriptionCount); end; procedure TBoldPublisher.AddSubscription(Subscriber: TBoldSubscriber; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent); var - I: Integer; - Subscription: TBoldSubscription; - LocalSubscriptions: TBoldSubscriptionList; + I, index: Integer; begin if not assigned(Subscriber) then exit; - if Subscriptions.Count < Subscriber.Subscriptions.Count then + if (OriginalEvent <= beMaxSmallUser) then + begin + AddSmallSubscription(Subscriber, [OriginalEvent], RequestedEvent); + Exit; + end; + if fSubscriptionCount <= Subscriber.SubscriptionCount then begin - LocalSubscriptions := Subscriptions; - for I := 0 to LocalSubscriptions.Count - 1 do + for I := 0 to fSubscriptionCount - 1 do begin - Subscription := TBoldSubscription(LocalSubscriptions.Items[I]); - if (Subscription.Subscriber = Subscriber) and - (Subscription.RequestedEvent = RequestedEvent) and - Subscription.IsMatchingEvent(OriginalEvent) then + if (fSubscriptionArray[I].Subscriber = Subscriber) and + (fSubscriptionArray[I].RequestedEvent = RequestedEvent) and + fSubscriptionArray[I].IsMatchingEvent(OriginalEvent) then Exit; end; end else begin - LocalSubscriptions := Subscriber.Subscriptions; - for I := 0 to localSubscriptions.Count - 1 do + for I := 0 to Subscriber.SubscriptionCount - 1 do begin - Subscription := TBoldSubscription(localSubscriptions.Items[I]); - if (Subscription.Publisher = Self) and - (Subscription.RequestedEvent = RequestedEvent) and - Subscription.IsMatchingEvent(OriginalEvent) then - Exit; + if (Subscriber.Subscriptions[I].Publisher = Self) then + begin + Index := Subscriber.Subscriptions[I].Index; + if (fSubscriptionArray[Index].RequestedEvent = RequestedEvent) and + fSubscriptionArray[Index].IsMatchingEvent(OriginalEvent) then + Exit; + end; + end; + end; + EnsureFreeSpace; + fSubscriptionArray[fSubscriptionCount].Subscriber := Subscriber; + fSubscriptionArray[fSubscriptionCount].IndexInSubscriber := Subscriber.SubscriptionCount; + fSubscriptionArray[fSubscriptionCount].RequestedEvent := RequestedEvent; + fSubscriptionArray[fSubscriptionCount].MatchCondition := OriginalEvent or beBigEventFlag; + Subscriber.AddToSubscriptions(self, fSubscriptionCount); + Inc(fSubscriptionCount); +end; + +procedure TBoldPublisher.SendExtendedEvent(Originator: TObject; + OriginalEvent: TBoldEvent; + const Args: array of const); +var + I: Integer; + Subscriber: TBoldSubscriber; +begin + if fSubscriptionCount = 0 then + Exit; + Inc(_SendExtendedEvent); + StartNotify; + for I := 0 to fSubscriptionCount - 1 do + begin + Subscriber := fSubscriptionArray[I].Subscriber; + if Assigned(Subscriber) and fSubscriptionArray[I].IsMatchingEvent(OriginalEvent) then + begin + if Subscriber.HandlesExtendedEvents then + Subscriber.ReceiveExtended(Originator, OriginalEvent, fSubscriptionArray[I].RequestedEvent, Args) + else + Subscriber.Receive(Originator, OriginalEvent, fSubscriptionArray[I].RequestedEvent); + Inc(_SendEventMatch); end; end; - TBoldEventSubscription.Create(Self, Subscriber, OriginalEvent, RequestedEvent); + EndNotify; end; +{$IFNDEF BOLD_NO_QUERIES} function TBoldPublisher.SendQuery(Originator: TObject; OriginalEvent: TBoldEvent; const Args: array of const; Subscriber: TBoldSubscriber): Boolean; var I: Integer; - Subscription: TBoldSubscription; begin - if Assigned(Subscriptions) then + if fSubscriptionCount > 0 then begin + Inc(_SendQuery); StartNotify; - for I := 0 to Subscriptions.Count - 1 do + for I := 0 to fSubscriptionCount - 1 do begin - Subscription := TBoldSubscription(Subscriptions.Items[I]); - if Assigned(Subscription.Subscriber) and Subscription.IsMatchingEvent(OriginalEvent) then - if not Subscription.Subscriber.Answer(Originator, OriginalEvent, Subscription.RequestedEvent, Args, Subscriber) then + if Assigned( fSubscriptionArray[I].Subscriber) and fSubscriptionArray[I].IsMatchingEvent(OriginalEvent) then + if not fSubscriptionArray[I].Subscriber.Answer(Originator, OriginalEvent, fSubscriptionArray[I].RequestedEvent, Args, Subscriber) then begin + Inc(_QueryMatch); result := false; Exit; end; @@ -479,121 +840,50 @@ function TBoldPublisher.SendQuery(Originator: TObject; OriginalEvent: TBoldEvent end; result := true; end; +{$ENDIF} -function TBoldPublisher.GetHasSubscribers: Boolean; -begin - result := assigned(fSubscriptions) and (Subscriptions.Count > 0); -end; - -{---TBoldSubscription---} - -constructor TBoldSubscription.Create(Publisher: TBoldPublisher; Subscriber: TBoldSubscriber; RequestedEvent: TBoldRequestedEvent); -begin - inherited Create; - fPublisher := Publisher; - fSubscriber := Subscriber; - fRequestedEvent := RequestedEvent; - Publisher.AddToSubscriptions(Self); - Subscriber.AddToSubscriptions(Self); -end; - -procedure TBoldSubscription.UnlinkFromSubscriber; -begin - fSubscriber := nil; - if Assigned(Publisher) then - Publisher.NeedsPacking := True - else - Free; {commit suicide when both links gone} -end; - -procedure TBoldSubscription.UnlinkFromPublisher; -begin - fPublisher := nil; - if not Assigned(Subscriber) then - Free; {commit suicide when both links gone} -end; - -{---TBoldEventSubscription---} - -procedure TBoldEventSubscription.CloneTo(Subscriber: TBoldSubscriber; - NewRequestedEvent: TBoldRequestedEvent); -begin - inherited; - Publisher.AddSubscription(Subscriber,fEvent, NewRequestedEvent); -end; - -constructor TBoldEventSubscription.Create(Publisher: TBoldPublisher; - Subscriber: TBoldSubscriber; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent); -begin - inherited Create(Publisher, Subscriber, RequestedEvent); - fEvent := OriginalEvent; -end; - -function TBoldEventSubscription.IsMatchingEvent(OriginalEvent: TBoldEvent): Boolean; -begin - Result := OriginalEvent = fEvent; -end; - -{---TBoldSmallEventSubscription---} - -procedure TBoldSmallEventSubscription.CloneTo(Subscriber: TBoldSubscriber; NewRequestedEvent: TBoldRequestedEvent); -begin - inherited; - Publisher.AddSmallSubscription(Subscriber,fEvents, NewRequestedEvent); -end; - -constructor TBoldSmallEventSubscription.Create(Publisher: TBoldPublisher; - Subscriber: TBoldSubscriber; Events: TBoldSmallEventSet; RequestedEvent: TBoldRequestedEvent); -begin - inherited Create(Publisher, Subscriber, RequestedEvent); - fEvents := Events; -end; - -procedure TBoldSmallEventSubscription.ExtendEvents(Events: TBoldSmallEventSet); -begin - fEvents := fEvents + Events; -end; - -function TBoldSmallEventSubscription.IsMatchingEvent(OriginalEvent: TBoldEvent): Boolean; -begin - Result := (OriginalEvent < 32) and (OriginalEvent in fEvents); -end; - -{---TBoldSubscriber---} - -destructor TBoldSubscriber.Destroy; +procedure TBoldPublisher.NotifySubscribersAndClearSubscriptions(Originator: TObject); +var + I: Integer; begin - if Assigned(fSubscriptions) then - begin - CancelAllSubscriptions; - FreeAndNil(fSubscriptions); - end; - inherited Destroy; + if fSubscriptionCount = 0 then + Exit; + SendExtendedEvent(Originator, beDestroying, []); + for I := 0 to fSubscriptionCount - 1 do + fSubscriptionArray[I].ClearEntry; + SetLength(fSubscriptionArray, 0); + fSubscriptionCount := 0; end; -function TBoldSubscriber.GetSubscriptions: TList; +constructor TBoldPublisher.Create; begin - if not Assigned(fSubscriptions) then - fSubscriptions := TList.Create; - Result := fSubscriptions; + Inc(PublisherCount); end; -procedure TBoldSubscriber.AddToSubscriptions(Subscription: TBoldSubscription); +destructor TBoldPublisher.Destroy; begin - Subscriptions.Add(Subscription); + Assert(fSubscriptionCount = 0); + if NeedsPacking then + RemoveFromPostNotificationQueue(self); + Dec(PublisherCount); end; procedure TBoldSubscriber.CancelAllSubscriptions; var I: Integer; + Publisher: TBoldPublisher; begin - if Subscriptions.Count = 0 then + if fSubscriptionCount = 0 then Exit; TBoldPublisher.StartNotify; try - for I := 0 to Subscriptions.Count - 1 do - TBoldSubscription(Subscriptions[I]).UnlinkFromSubscriber; - fSubscriptions.Count := 0; {remove entires but retain size} + for I := 0 to fSubscriptionCount - 1 do + begin + Publisher := fSubscriptionArray[I].Publisher; + if Assigned(Publisher) then + Publisher.ClearEntry(self, fSubscriptionArray[I].Index); + end; + fSubscriptionCount := 0; {remove entires but retain size} finally TBoldPublisher.EndNotify; end; @@ -601,18 +891,31 @@ procedure TBoldSubscriber.CancelAllSubscriptions; {---TBoldPassthroughSubscriber---} -constructor TBoldPassthroughSubscriber.Create(receiveFunc: TBoldEventHandler); +constructor TBoldPassthroughSubscriber.Create(AReceiveFunc: TBoldEventHandler); begin inherited Create; - fReceiveFunc := receiveFunc; + fReceiveFunc := AReceiveFunc; end; -constructor TBoldPassthroughSubscriber.CreateWithReceiveAndAnswer(ReceiveFunc: TBoldEventHandler; - AnswerFunc: TBoldQueryHandler); +function TBoldPassthroughSubscriber.GetContextString: string; +var + vObject: TObject; begin - inherited Create; - fReceiveFunc := ReceiveFunc; - fAnswerFunc := AnswerFunc; + vObject := TObject(TMethod(fReceiveFunc).Data); +{$IFNDEF BOLD_DISABLEMEMORYMANAGER} + if vObject is TBoldMemoryManagedObject then + result := TBoldMemoryManagedObject(vObject).DebugInfo + else +{$ENDIF} + if vObject is TComponent then + result := TComponent(vObject).Name + else + Result := vObject.ClassName; +end; + +function TBoldPassthroughSubscriber.GetHandlesExtendedEvents: Boolean; +begin + Result := false; end; procedure TBoldPassthroughSubscriber.Receive(Originator: TObject; OriginalEvent: TBoldEvent; @@ -622,7 +925,18 @@ procedure TBoldPassthroughSubscriber.Receive(Originator: TObject; OriginalEvent: fReceiveFunc(Originator, OriginalEvent, RequestedEvent); end; -function TBoldPassthroughSubscriber.Answer(Originator: TObject; OriginalEvent: TBoldEvent; +{---TBoldExtendedPassthroughSubscriber---} + +{$IFNDEF BOLD_NO_QUERIES} +constructor TBoldExtendedPassthroughSubscriber.CreateWithReceiveAndAnswer(AReceiveFunc: TBoldEventHandler; + AAnswerFunc: TBoldQueryHandler); +begin + inherited Create(nil); + ReceiveFunc := AReceiveFunc; + fAnswerFunc := AAnswerFunc; +end; + +function TBoldExtendedPassthroughSubscriber.Answer(Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent; const Args: array of const; Subscriber: TBoldSubscriber): Boolean; begin if Assigned(fAnswerFunc) then @@ -630,16 +944,25 @@ function TBoldPassthroughSubscriber.Answer(Originator: TObject; OriginalEvent: T else result := true; end; +{$ENDIF} {--- TBoldSubscribableObject ---} function TBoldSubscribableObject.GetPublisher: TBoldPublisher; begin if not Assigned(fPublisher) then + begin fPublisher := TBoldPublisher.Create; + fPublisher.SubscribableObject := self; + end; Result := fPublisher end; +function TBoldSubscribableObject.GetSubscriptionsAsText: string; +begin + result := Publisher.SubscriptionsAsText; +end; + procedure TBoldSubscribableObject.FreePublisher; begin if Assigned(fPublisher) then @@ -649,12 +972,6 @@ procedure TBoldSubscribableObject.FreePublisher; end; end; -destructor TBoldSubscribableObject.Destroy; -begin - FreePublisher; - inherited; -end; - procedure TBoldSubscribableObject.AddSmallSubscription(Subscriber: TBoldSubscriber; Events: TBoldSmallEventSet; RequestedEvent: TBoldRequestedEvent); begin @@ -673,9 +990,29 @@ procedure TBoldSubscribableObject.SendEvent(OriginalEvent: TBoldEvent); fPublisher.SendExtendedEvent(self, OriginalEvent, []); end; -function TBoldSubscribableObject.SendQuery(OriginalEvent: TBoldEvent; const Args: array of const; Subscriber: TBoldSubscriber): Boolean; +destructor TBoldSubscribableObject.Destroy; +begin + FreePublisher; +end; + +{$IFNDEF BOLD_NO_QUERIES} +function TBoldSubscribableObject.SendQuery(OriginalEvent: TBoldEvent; const Args: array of const; Subscriber: TBoldSubscriber; Originator: TObject = nil): Boolean; begin - result := not Assigned(fPublisher) or fPublisher.SendQuery(self, OriginalEvent, Args, Subscriber); + if Assigned(Originator) then + result := not Assigned(fPublisher) or fPublisher.SendQuery(Originator, OriginalEvent, Args, Subscriber) + else + result := not Assigned(fPublisher) or fPublisher.SendQuery(self, OriginalEvent, Args, Subscriber); +end; +{$ENDIF} + +function TBoldSubscribableObject.GetContextString: string; +begin + result := ClassName; +end; + +function TBoldSubscribableObject.GetDebugInfo: string; +begin + result := ContextString; end; function TBoldSubscribableObject.GetHasSubscribers: Boolean; @@ -685,6 +1022,23 @@ function TBoldSubscribableObject.GetHasSubscribers: Boolean; {--- TBoldSubscribableComponent ---} +function TBoldSubscribableComponent.GetPublisher: TBoldPublisher; +begin + if not assigned(fPublisher) then + fPublisher := TBoldPublisher.Create; + result := fPublisher; +end; + +function TBoldSubscribableComponent.GetSubscriptionsAsText: string; +begin + result := Publisher.SubscriptionsAsText; +end; + +function TBoldSubscribableComponent.GetHasSubscribers: Boolean; +begin + result := assigned(fPublisher) and Publisher.HasSubscribers; +end; + procedure TBoldSubscribableComponent.FreePublisher; begin if Assigned(fPublisher) then @@ -718,17 +1072,33 @@ procedure TBoldSubscribableComponent.SendEvent(Originator: TObject; OriginalEven fPublisher.SendExtendedEvent(Originator, OriginalEvent, []); end; +{$IFNDEF BOLD_NO_QUERIES} function TBoldSubscribableComponent.SendQuery(Originator: TObject; OriginalEvent: TBoldEvent; const Args: array of const; Subscriber: TBoldSubscriber): Boolean; begin result := not Assigned(fPublisher) or fPublisher.SendQuery(Originator, OriginalEvent, Args, Subscriber); end; +{$ENDIF} {---TBoldSubscribablePersistent---} -constructor TBoldSubscribablePersistent.Create; +function TBoldSubscribablePersistent.GetPublisher: TBoldPublisher; begin - inherited; - fPublisher := TBoldPublisher.Create; + if not assigned(fPublisher) then + fPublisher := TBoldPublisher.Create; + result := fPublisher; +end; + +function TBoldSubscribablePersistent.GetSubscriptionsAsText: string; +begin + if assigned(fPublisher) then + result := fPublisher.SubscriptionsAsText + else + result := ''; +end; + +function TBoldSubscribablePersistent.GetHasSubscribers: Boolean; +begin + result := assigned(fPublisher) and Publisher.HasSubscribers; end; procedure TBoldSubscribablePersistent.FreePublisher; @@ -764,6 +1134,7 @@ procedure TBoldSubscribablePersistent.SendEvent(Originator: TObject; OriginalEve fPublisher.SendExtendedEvent(Originator, OriginalEvent, []); end; +{$IFNDEF BOLD_NO_QUERIES} function TBoldSubscribablePersistent.SendQuery(Originator: TObject; OriginalEvent: TBoldEvent; const Args: array of const; Subscriber: TBoldSubscriber): Boolean; begin result := not Assigned(fPublisher) or fPublisher.SendQuery(Originator, OriginalEvent, Args, Subscriber); @@ -772,22 +1143,27 @@ function TBoldSubscribablePersistent.SendQuery(Originator: TObject; OriginalEven function TBoldSubscriber.Answer(Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent; const Args: array of const; Subscriber: TBoldSubscriber): Boolean; begin - raise EBold.CreateFmt(sAnswerNotImplemented, [classname, Originator.Classname]); + raise EBold.CreateFmt('%s.Answer: You have subscribed to a query without implementing the virtual Answer method... (triggered by: %s)', [classname, Originator.Classname]); end; +{$ENDIF} function TBoldSubscriber.GetContextString: string; begin - Result := ''; + Result := ClassName; +end; + +function TBoldSubscriber.GetDebugInfo: string; +begin + result := ContextString; end; procedure TBoldSubscriber.ReceiveExtended(Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent; const Args: array of const); begin - // do nothing end; -procedure TBoldPassthroughSubscriber.ReceiveExtended(Originator: TObject; +procedure TBoldExtendedPassthroughSubscriber.ReceiveExtended(Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent; const Args: array of const); begin @@ -800,13 +1176,39 @@ function TBoldSubscriber.GetHandlesExtendedEvents: Boolean; result := false; end; -constructor TBoldPassthroughSubscriber.CreateWithExtendedReceive( - ExtendedReceiveFunc: TBoldExtendedEventHandler); +function TBoldSubscriber.GetSubscriptionsAsText: string; +var + i,j: integer; begin - fExtendedReceiveFunc := ExtendedReceiveFunc; + result := ''; + j := 0; + for I := 0 to Length(fSubscriptionArray) - 1 do + if Assigned(fSubscriptionArray[i].Publisher) and Assigned(fSubscriptionArray[i].Publisher.SubscribableObject) then + begin + result := result + IntToStr(j) + ':' + fSubscriptionArray[i].Publisher.SubscribableObject.ContextString + #13#10; + inc(j); + end; end; -function TBoldPassthroughSubscriber.GetHandlesExtendedEvents: Boolean; +function TBoldSubscriber.HasMatchingSubscription( + APublisher: TBoldPublisher): boolean; +begin + result := APublisher.HasMatchingSubscription(self); +end; + +procedure TBoldSubscriber.CancelSubscriptionTo(APublisher: TBoldPublisher); +begin + APublisher.CancelSubscriptionTo(self); +end; + +constructor TBoldExtendedPassthroughSubscriber.CreateWithExtendedReceive( + AExtendedReceiveFunc: TBoldExtendedEventHandler); +begin + inherited Create(nil); + fExtendedReceiveFunc := AExtendedReceiveFunc; +end; + +function TBoldExtendedPassthroughSubscriber.GetHandlesExtendedEvents: Boolean; begin result := assigned(fExtendedReceiveFunc); end; @@ -833,58 +1235,17 @@ procedure TBoldSubscribablePersistent.SendExtendedEvent(Originator: TObject; Publisher.SendExtendedEvent(Originator, OriginalEvent, Args); end; -function TBoldPublisher.GetPublisherFlag(Flag: TBoldPublisherFlag): Boolean; -begin - result := Flag in fPublisherFlags; -end; - -procedure TBoldPublisher.SetPublisherFlag(Flag: TBoldPublisherFlag; - Value: Boolean); +procedure TBoldSubscriber.AfterConstruction; begin - if Value then - Include(fPublisherFlags, Flag) - else - Exclude(fPublisherFlags, Flag); -end; - -function TBoldPublisher.GetNeedsPacking: Boolean; -begin - result := GetPublisherFlag(bpfNeedsPacking); -end; - -procedure TBoldPublisher.SetNeedsPacking(Value: Boolean); -begin - if not NeedsPacking then - begin - SetPublisherFlag(bpfNeedsPacking, Value); - // the postnotify queue will be gone if we are in finalization, - // but then we don't need to pack since we will be destroyed soon anyway... - if assigned(G_PostNotifyQueue) then - DelayTillAfterNotification(PackSubscriptions, nil, Self); - end - else - SetPublisherFlag(bpfNeedsPacking, Value); -end; - -function TBoldSubscribablePersistent.GetHasSubscribers: Boolean; -begin - result := assigned(fPublisher) and Publisher.HasSubscribers; -end; - -function TBoldSubscribableComponent.GetHasSubscribers: Boolean; -begin - result := assigned(fPublisher) and Publisher.HasSubscribers; + inherited; + Inc(SubscriberCount); end; -procedure TBoldSubscriber.CloneSubscriptions(Subscriber: TBoldSubscriber; - OldRequestedEvent: TBoldRequestedEvent; - NewRequestedEvent: TBoldRequestedEvent); -var - i: integer; +procedure TBoldSubscriber.BeforeDestruction; begin - for i := 0 to Subscriptions.Count - 1 do - if TBoldSubscription(Subscriptions[i]).RequestedEvent = OldRequestedEvent then - TBoldSubscription(Subscriptions[i]).CloneTo(Subscriber, newRequestedEvent); + Dec(SubscriberCount); + CancelAllSubscriptions; + inherited; end; class procedure TBoldPublisher.DelayTillAfterNotification( @@ -895,37 +1256,38 @@ class procedure TBoldPublisher.DelayTillAfterNotification( else if Assigned(G_PostNotifyQueue) then G_PostNotifyQueue.Add(Event, Sender, Receiver) else - raise EBold.CreateFmt(sQueueNotAllocated, [ClassName]); -end; - -class procedure TBoldPublisher.EndNotify; -begin - Dec(G_NotificationNesting); - if (G_NotificationNesting = 0) and Assigned(G_PostNotifyQueue) and (not G_InPostNotification) then - begin - G_InPostNotification := True; - G_PostNotifyQueue.DequeueAll; {may add and delete entries, Eventqueue can handle it} - G_InPostNotification := False; - end; -end; - -class procedure TBoldPublisher.StartNotify; -begin - Inc(G_NotificationNesting); + Raise EBold.CreateFmt('%s.DelayTillAfterNotification: Queue not allocated', [ClassName]); end; procedure TBoldPublisher.PackSubscriptions(dummy: TObject); var - i: integer; + OldCount, i, Gap: integer; begin - for i := Subscriptions.Count - 1 downto 0 do - if TBoldSubscription(Subscriptions[i]).Subscriber = nil then + OldCount := fSubscriptionCount; + Gap := 0; + for i := 0 to OldCount-1 do + begin + if FSubscriptionArray[i].Subscriber = nil then + begin + Inc(Gap); + end + else if gap > 0 then begin - TBoldSubscription(Subscriptions[i]).UnlinkFromPublisher; - Subscriptions[i] := Subscriptions.Last; - Subscriptions.Delete(Subscriptions.Count - 1); + Assert((fSubscriptionArray[i].Subscriber.Subscriptions[fSubscriptionArray[i].IndexInSubscriber].Publisher = Self) and (fSubscriptionArray[i].Subscriber.Subscriptions[fSubscriptionArray[i].IndexInSubscriber].Index = i)); + fSubscriptionArray[i].ReIndexsSubscriber(i-gap); + fSubscriptionArray[i-gap] := fSubscriptionArray[i]; + fSubscriptionArray[i].Subscriber := nil; end; + end; + fSubscriptionCount := fSubscriptionCount-Gap; + if fSubscriptionCount = 0 then + SetLength(FSubscriptionArray, 0) + else + // do not bother if it's less than 9 records + if (Length(FSubscriptionArray) > 8) and (fSubscriptionCount < Length(FSubscriptionArray) div 2) then + SetLength(FSubscriptionArray, fSubscriptionCount); NeedsPacking := false; + fHoleCount := 0; end; class procedure TBoldPublisher.RemoveFromPostNotificationQueue(Receiver: TObject); @@ -934,24 +1296,23 @@ class procedure TBoldPublisher.RemoveFromPostNotificationQueue(Receiver: TObject G_PostNotifyQueue.RemoveAllForReceiver(Receiver); end; -function TBoldSubscribableComponent.GetPublisher: TBoldPublisher; +procedure InitDebugMethods; begin - if not assigned(fPublisher) then - fPublisher := TBoldPublisher.Create; - result := fPublisher; -end; - -function TBoldSubscribablePersistent.GetPublisher: TBoldPublisher; -begin - if not assigned(fPublisher) then - fPublisher := TBoldPublisher.Create; - result := fPublisher; + exit; // intentionally do nothing, but code bellow forces compiler to include these debug methods so they can be inspected + TBoldPublisher.Create.SubscriptionsAsText; + TBoldPassthroughSubscriber.Create(nil).SubscriptionsAsText; + TBoldSubscribableObject.Create.SubscriptionsAsText; + TBoldSubscribablePersistent.Create.SubscriptionsAsText; + TBoldSubscribableComponent.Create(nil).SubscriptionsAsText; end; initialization G_PostNotifyQueue := TboldEventQueue.Create; + InitDebugMethods; finalization FreeAndNil(G_PostNotifyQueue); - + if (DebugHook <> 0) then + if (ActiveSubscriptionCount + PublisherCount + SubscriberCount) > 0 then + Assert(false, Format('ActiveSubscriptionCount = %d, PublisherCount = %d, SubscriberCount = %d', [ActiveSubscriptionCount, PublisherCount, SubscriberCount])); end. diff --git a/Source/Common/Support/BoldBase64.pas b/Source/Common/Support/BoldBase64.pas index 795ca83..e4819e5 100644 --- a/Source/Common/Support/BoldBase64.pas +++ b/Source/Common/Support/BoldBase64.pas @@ -1,3 +1,7 @@ +///////////////////////////////////////////////////////// + +{ Global compiler directives } +{$include bold.inc} unit BoldBase64; // uTBase64 v1.0 - Simple Base64 encoding/decoding class @@ -45,18 +49,20 @@ interface +uses + BoldDefs; + type TBase64 = class(TObject) private ffilterdecodeinput:boolean; function ValueToCharacter(value: Byte; var character: char):boolean; function CharacterToValue(character: char; var value: byte):boolean; - function filterLine(InputData: string):string; - protected + function filterLine(const InputData: string): string; public constructor Create; - function EncodeData(InputData:string; var OutputData: string): Byte; - function DecodeData(InputData:string; var OutputData: string): Byte; + function EncodeData(InputData: TBoldAnsiString; var OutputData: string): Byte; + function DecodeData(InputData: string; var OutputData: TBoldAnsiString): Byte; property FilterdecodeInput: boolean read ffilterdecodeinput write ffilterdecodeinput; end; @@ -70,9 +76,20 @@ TBase64 = class(TObject) implementation +uses + BoldRev; + const AlphabetLength = 64; - Alphabet: string[AlphabetLength] = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; + Alphabet: array[1..AlphabetLength] of AnsiChar = ( + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', + 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', + 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', + 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', + 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', + 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', + 'w', 'x', 'y', 'z', '0', '1', '2', '3', + '4', '5', '6', '7', '8', '9', '+', '/'); Pad = '='; @@ -94,7 +111,7 @@ function TBase64.ValueToCharacter(value: Byte; var character: char): boolean; if (value > AlphabetLength-1) then Result := false else - character := Char (Alphabet[value+1]); // marco + character := Char(Alphabet[value+1]); end; @@ -105,7 +122,7 @@ function TBase64.ValueToCharacter(value: Byte; var character: char): boolean; function TBase64.CharacterToValue(character: char; var value: byte): boolean; begin Result := true; - value := Pos(character, Alphabet); + value := Pos(AnsiChar(character), Alphabet); if value = 0 then Result := false else @@ -117,12 +134,12 @@ function TBase64.CharacterToValue(character: char; var value: byte): boolean; // Encodes a string to its base64 representation in ASCII Format // returns BASE64_OK if conversion was done without errors //****************************************************************** -function TBase64.EncodeData(InputData: string; var OutputData: string): Byte; +function TBase64.EncodeData(InputData: TBoldAnsiString; var OutputData: string): Byte; var i: integer; currentb, prevb: Byte; c: Byte; - s: char; + s: Char; InputLength: integer; begin OutPutData := ''; @@ -135,7 +152,7 @@ function TBase64.EncodeData(InputData: string; var OutputData: string): Byte; end; repeat - // process first group + // process first group currentb := ord(InputData[i]); i := i+1; InputLength := InputLength-1; @@ -212,7 +229,7 @@ function TBase64.EncodeData(InputData: string; var OutputData: string): Byte; // ignores all characters not in base64 alphabet // and returns the filtered string //****************************************************************** -function TBase64.filterLine(InputData: string): string; +function TBase64.filterLine(const InputData: string): string; var f:byte; i:integer; @@ -229,13 +246,13 @@ function TBase64.filterLine(InputData: string): string; // Decodes a base64 representation in ASCII format into a string // returns BASE64_OK if conversion was done without errors //****************************************************************** -function TBase64.DecodeData(InputData: string; var OutputData: string): Byte; +function TBase64.DecodeData(InputData: string; var OutputData: TBoldAnsiString): Byte; var i: integer; InputLength: integer; currentb, prevb: Byte; c: Byte; - s: char; + s: Char; begin if (InputData = '') then @@ -274,7 +291,7 @@ function TBase64.DecodeData(InputData: string; var OutputData: string): Byte; end; c := ((currentb shl 2)+(prevb shr 4)) and 255; - OutPutData := OutPutData+chr(c); + OutPutData := OutPutData + AnsiChar(Chr(c)); // process second Byte i := i+1;s := InputData[i]; @@ -299,7 +316,7 @@ function TBase64.DecodeData(InputData: string; var OutputData: string): Byte; exit; end; c := ((prevb shl 4) + (currentb shr 2)) and 255; - OutPutData := OutPutData + chr(c); + OutPutData := OutPutData + AnsiChar(Chr(c)); end; // process third Byte i := i+1; @@ -320,11 +337,11 @@ function TBase64.DecodeData(InputData: string; var OutputData: string): Byte; exit; end; c := ((currentb shl 6) + (prevb)) and 255; - OutPutData := OutPutData + chr(c); + OutPutData := OutPutData + AnsiChar(Chr(c)); end; until (i >= InputLength); result := BASE64_OK; end; +initialization end. - diff --git a/Source/Common/Support/BoldCollections.pas b/Source/Common/Support/BoldCollections.pas index 9f62d16..3a8fd2c 100644 --- a/Source/Common/Support/BoldCollections.pas +++ b/Source/Common/Support/BoldCollections.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldCollections; interface @@ -18,7 +21,7 @@ TBoldUniquelyNamedCollectionItemClass = class of TBoldUniquelyNamedCollectionI TBoldUniqueNameItemIndex = class(TBoldStringHashIndex) protected - function ItemAsKeyString(Item: TObject): string; override; + function ItemASKeyString(Item: TObject): string; override; end; { TBoldUniquelyNamedCollectionItem } @@ -60,7 +63,7 @@ TBoldCollectionWithUniquelyNamedItems = class(TOwnedCollection) property ItemIndex: TBoldUniqueNameItemIndex read GetItemIndex; public constructor Create(AOwner: TPersistent; ItemClass: TBoldUniquelyNamedCollectionItemClass); - destructor Destroy; override; + destructor destroy; override; property ItemByName[const Name: String]: TBoldUniquelyNamedCollectionItem read GetItemByName; end; @@ -71,14 +74,14 @@ implementation SysUtils, BoldDefs, BoldIndex, - BoldCommonConst; + BoldRev; { TBoldUniquelyNamedCollectionItem } procedure TBoldUniquelyNamedCollectionItem.EnsureNameUnique(const Value: string); begin if assigned(Collection.ItemByName[value]) then - raise EBold.CreateFmt(sDuplicateName, [value]); + raise EBold.CreateFmt('There is already an item with name "%s"', [value]); end; function TBoldUniquelyNamedCollectionItem.GetCollection: TBoldCollectionWithUniquelyNamedItems; @@ -103,7 +106,7 @@ procedure TBoldUniquelyNamedCollectionItem.InternalSetUniqueName(const Value: st begin if Value <> UniqueName then begin - EnsureNameUnique(Value); // will ensure the index as well + EnsureNameUnique(Value); Collection.ItemIndex.Remove(self); SetUniqueName(Value); Collection.ItemIndex.Add(self); @@ -125,7 +128,7 @@ constructor TBoldCollectionWithUniquelyNamedItems.Create(AOwner: TPersistent; It inherited Create(aOwner, ItemClass); end; -destructor TBoldCollectionWithUniquelyNamedItems.Destroy; +destructor TBoldCollectionWithUniquelyNamedItems.destroy; begin FreeAndNil(fItemIndex); inherited; @@ -151,7 +154,6 @@ function TBoldCollectionWithUniquelyNamedItems.GetItemIndex: TBoldUniqueNameItem procedure TBoldCollectionWithUniquelyNamedItems.Update(Item: TCollectionItem); begin - // implementation in superclass is empty FreeAndNil(fItemIndex); end; @@ -167,4 +169,5 @@ procedure TBoldUniquelyNamedCollectionItemWithNameStorage.SetUniqueName(const Va fUniqueName := Value; end; +initialization end. diff --git a/Source/Common/Support/BoldCommonBitmaps.pas b/Source/Common/Support/BoldCommonBitmaps.pas index 80378ac..d5d67f1 100644 --- a/Source/Common/Support/BoldCommonBitmaps.pas +++ b/Source/Common/Support/BoldCommonBitmaps.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldCommonBitmaps; interface @@ -82,3 +85,4 @@ finalization end. + diff --git a/Source/Common/Support/BoldControlPackDefs.pas b/Source/Common/Support/BoldControlPackDefs.pas index 63722e8..c32928c 100644 --- a/Source/Common/Support/BoldControlPackDefs.pas +++ b/Source/Common/Support/BoldControlPackDefs.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldControlPackDefs; interface @@ -33,6 +36,13 @@ interface beListPartEnabledChanged = 100; + DefaultBoldDragMode = bdgSelection; + DefaultBoldDropMode = bdpAppend; + implementation +uses + BoldRev; + +initialization end. diff --git a/Source/Common/Support/BoldControlsDefs.pas b/Source/Common/Support/BoldControlsDefs.pas index b3dd9e8..a685e5d 100644 --- a/Source/Common/Support/BoldControlsDefs.pas +++ b/Source/Common/Support/BoldControlsDefs.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldControlsDefs; interface @@ -26,7 +29,7 @@ interface TBoldComboSelectChangeAction = (bdscSetText, bdcsSetValue, bdcsNone, bdcsSetReference, bdcsSetListIndex); TBoldEditButtonStyle = (bbsNone, bbsCombo, bbsEllipsis, bbsCustom); - + const BoldPropertiesController_SupportedPropertyTypes = [{tkUnknown,} tkInteger, tkChar, tkEnumeration, tkFloat, @@ -35,4 +38,8 @@ interface implementation +uses + BoldRev; + +initialization end. diff --git a/Source/Common/Support/BoldExternalizedReferences.pas b/Source/Common/Support/BoldExternalizedReferences.pas index 8f11050..390ec74 100644 --- a/Source/Common/Support/BoldExternalizedReferences.pas +++ b/Source/Common/Support/BoldExternalizedReferences.pas @@ -1,11 +1,14 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldExternalizedReferences; interface uses + BoldBase, BoldHashIndexes, - BoldIndexableList, - BoldBase; + BoldIndexableList; type { forward declarations } @@ -21,8 +24,8 @@ TBoldExternalizedReferenceList = class(TBoldMemoryManagedObject) function GetReferencedObject(Referee: TObject): TObject; procedure SetReferencedObject(Referee, Referenced: TObject); public - constructor Create; - destructor Destroy; override; + constructor create; + destructor destroy; override; property ManageReferencedObject: Boolean read FManageReferencedObject write SetManageReferencedObject; property ReferencedObjects[Referee: TObject]: TObject read GetReferencedObject write SetReferencedObject; property Count: integer read GetCount; @@ -32,10 +35,7 @@ implementation uses SysUtils, - BoldUtils; - -var - IX_ExternalRef: integer = -1; + BoldRev; type { TBoldExternalLink } @@ -50,24 +50,40 @@ TBoldExternalLink = class(TBoldMemoryManagedObject) { TBoldExternalizedIndexList } TBoldExternalizedIndexList = class(TBoldUnorderedIndexablelist) + private + class var IX_ExternalRef: integer; public - constructor create; - function FindByReferee(Referee: TObject): TBoldExternalLink; + constructor Create; + function FindByReferee(Referee: TObject): TBoldExternalLink; {$IFDEF BOLD_INLINE} inline; {$ENDIF} end; { TBoldExternalizedReferenceHashIndex } TBoldExternalizedReferenceHashIndex = class(TBoldObjectHashIndex) protected - function ItemAsKeyObject(Item: TObject): TObject; override; + function ItemASKeyObject(Item: TObject): TObject; override; end; +{ TBoldExternalizedIndexList } + +constructor TBoldExternalizedIndexList.Create; +begin + inherited; + SetIndexVariable(IX_ExternalRef, AddIndex(TBoldExternalizedReferenceHashIndex.Create)); + OwnsEntries := true; +end; + +function TBoldExternalizedIndexList.FindByReferee(Referee: TObject): TBoldExternalLink; +begin + result := TBoldExternalLink(TBoldExternalizedReferenceHashIndex(Indexes[IX_ExternalRef]).FindByObject(Referee)); +end; + constructor TBoldExternalizedReferenceList.create; begin inherited; flist := TBoldExternalizedIndexList.Create; end; -destructor TBoldExternalizedReferenceList.Destroy; +destructor TBoldExternalizedReferenceList.destroy; begin FreeAndNil(fList); inherited; @@ -103,6 +119,8 @@ procedure TBoldExternalizedReferenceList.SetReferencedObject(Referee, Referenced Link := TBoldExternalizedIndexList(flist).FindByReferee(Referee); if assigned(Link) then begin + if (Link.Referee = Referee) and (Link.Referenced = Referenced) then + exit; if ManageReferencedObject then FreeAndNil(Link.fReferenced); fList.Remove(Link); @@ -124,20 +142,7 @@ function TBoldExternalizedReferenceHashIndex.ItemASKeyObject(Item: TObject): TOb result := TBoldExternalLink(item).Referee; end; -{ TBoldExternalizedIndexList } - -constructor TBoldExternalizedIndexList.create; -begin - inherited; - SetIndexVariable(IX_ExternalRef, AddIndex(TBoldExternalizedReferenceHashIndex.Create)); - OwnsEntries := true; -end; - -function TBoldExternalizedIndexList.FindByReferee(Referee: TObject): TBoldExternalLink; -begin - result := TBoldExternalLink(TBoldExternalizedReferenceHashIndex(Indexes[IX_ExternalRef]).FindByObject(Referee)); -end; +initialization + TBoldExternalizedIndexList.IX_ExternalRef := -1; end. - - diff --git a/Source/Common/Support/BoldFileHandler.pas b/Source/Common/Support/BoldFileHandler.pas index fca1ec9..6119b04 100644 --- a/Source/Common/Support/BoldFileHandler.pas +++ b/Source/Common/Support/BoldFileHandler.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldFileHandler; interface @@ -92,7 +95,7 @@ implementation uses SysUtils, Dialogs, - BoldCommonConst; + BoldRev; var G_FileHandlerList: TBoldObjectArray; @@ -109,7 +112,6 @@ function BoldFileHandlerForFile(path, FileName: String; ModuleType: TBoldModuleT i: integer; begin try - // see if we can find an existing filehandler for i := 0 to BoldFileHandlerList.Count - 1 do begin if AnsiUpperCase((BoldFileHandlerList[i] as TBoldFileHandler).SetFileName) = AnsiUpperCase(Filename) then @@ -123,7 +125,7 @@ function BoldFileHandlerForFile(path, FileName: String; ModuleType: TBoldModuleT result.InitializeStringList; except on e: exception do - raise EBold.CreateFmt(sUnableToCreateFileHandle, [FileName, e.message]); + raise EBold.CreateFmt('Unable to create filehandler for %s: %s', [FileName, e.message]); end; end; @@ -166,7 +168,7 @@ constructor TBoldFileHandler.Create(const FileName: string; ModuleType: TBoldMod fLastWasNewLIne := true; fIndentLevel := 0; FOnInitializeFileContents := OnInitializeFileContents; - fFileFilter := sFileHandlerMask; + fFileFilter := 'Pascal Unit (*.pas)|*.pas|Include files (*.inc)|*.inc|Text files (*.txt)|*.txt|All Files (*.*)|*.*'; BoldFileHandlerList.Add(self); end; @@ -176,7 +178,7 @@ destructor TBoldFileHandler.Destroy; FlushFile; except on e:Exception do - ShowMessage(SysUtils.Format(sFileSaveProblem, [e.Message])); + ShowMessage('File most likely not saved properly: ' + e.Message); end; FreeAndNil(fStringList); BoldFileHandlerList.remove(self); @@ -209,14 +211,14 @@ procedure TBoldfileHandler.AddString(const s: string); procedure TBoldfileHandler.StartBlock; begin - Writeln('begin'); // do not localize + Writeln('begin'); Indent; end; procedure TBoldfileHandler.EndBlock(const AddNewLine: boolean); begin Dedent; - Writeln('end;'); // do not localize + Writeln('end;'); if AddNewLine then NewLine; end; @@ -343,12 +345,12 @@ procedure TBoldDiskFileHandler.DoFlushFile; if CheckWriteable then begin StringList.SaveToFile(FileName); - BoldLog.LogFmt(sSaved, [FileName]); + BoldLog.Log('Saved ' + FileName); end else begin - BoldLog.LogFmt(sModuleReadOnly, [FFileName], ltError); - ShowMessage(SysUtils.Format(sModuleReadOnly, [fFileName])); + BoldLog.LogFmt('%s is readonly!', [FFileName], ltError); + ShowMessage(fFileName + ' is readonly!'); end; end; @@ -360,7 +362,6 @@ procedure TBoldDiskFileHandler.LoadStringList; function TBoldFileHandler.CheckWriteable(FName: string = ''): Boolean; begin - // If parameter is omitted use the FileName property if FName = '' then FName := FileName; Result := not (FileExists(FName) and FileIsReadOnly(FName)); @@ -368,13 +369,11 @@ function TBoldFileHandler.CheckWriteable(FName: string = ''): Boolean; procedure TBoldFileHandler.CloseFile; begin - // do nothing end; -initialization // empty +initialization finalization FreeAndNil(G_FileHandlerList); end. - diff --git a/Source/Common/Support/BoldGuard.pas b/Source/Common/Support/BoldGuard.pas index 53fd7b0..1594b13 100644 --- a/Source/Common/Support/BoldGuard.pas +++ b/Source/Common/Support/BoldGuard.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldGuard; interface @@ -10,7 +13,7 @@ interface type { forward declarations } - TBoldGuard = class; + TBoldGuard = class; TBoldObjectVariableReference = ^TObject; @@ -40,8 +43,7 @@ TBoldGuard = class(TBoldRefCountedObject, IBoldGuard) implementation uses - SysUtils, - BoldUtils; + BoldRev; constructor TBoldGuard.Create(var v0); begin @@ -216,4 +218,6 @@ destructor TBoldGuard.Destroy; inherited; end; +initialization + end. diff --git a/Source/Common/Support/BoldHashIndexes.pas b/Source/Common/Support/BoldHashIndexes.pas index b2d9a77..044a3ce 100644 --- a/Source/Common/Support/BoldHashIndexes.pas +++ b/Source/Common/Support/BoldHashIndexes.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldHashIndexes; interface @@ -19,8 +22,8 @@ TBoldCardinalHashIndex = class; {---TBoldStringKey---} TBoldStringKey = class public - class function HashString(const KeyString: String; CompareMode: TBoldStringCompareMode): Cardinal; - class function HashBuffer(P: PChar; length: integer; CompareMode: TBoldStringCompareMode): Cardinal; + class function HashString(const KeyString: String; CompareMode: TBoldStringCompareMode): Cardinal; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + class function HashBuffer(const P: PChar; const Length: Integer; const CompareMode: TBoldStringCompareMode): Cardinal; end; {---TBoldStringHashIndex---} @@ -31,8 +34,8 @@ TBoldStringHashIndex = class(TBoldHashIndex) function Match(const Key; Item:TObject):Boolean; override; function Hash(const Key): Cardinal; override; public - function FindByString(const KeyString: string): TObject; - procedure FindAllByString(const KeyString: string; List: TList); + function FindByString(const KeyString: string): TObject; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure FindAllByString(const KeyString: string; List: TList); {$IFDEF BOLD_INLINE} inline; {$ENDIF} end; {---TBoldCaseSensitiveStringHashIndex---} @@ -43,7 +46,7 @@ TBoldCaseSensitiveStringHashIndex = class(TBoldHashIndex) function Match(const Key; Item:TObject):Boolean; override; function Hash(const Key): Cardinal; override; public - function FindByString(const KeyString: string): TObject; + function FindByString(const KeyString: string): TObject; {$IFDEF BOLD_INLINE} inline; {$ENDIF} end; {---TBoldObjectHashIndex---} @@ -53,9 +56,10 @@ TBoldObjectHashIndex = class(TBoldHashIndex) function HashItem(Item: TObject): Cardinal; override; function Match(const Key; Item:TObject):Boolean; override; function Hash(const Key): Cardinal; override; - class function HashObject(KeyObject: TObject): Cardinal; - function FindByObject(KeyObject: TObject): TObject; - procedure FindAllByObject(const KeyObject: TObject; List: TList); + class function HashObject(KeyObject: TObject): Cardinal; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + public + function FindByObject(KeyObject: TObject): TObject; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure FindAllByObject(const KeyObject: TObject; List: TList); {$IFDEF BOLD_INLINE} inline; {$ENDIF} end; {---TBoldClassHashIndex---} @@ -65,8 +69,9 @@ TBoldClassHashIndex = class(TBoldHashIndex) function HashItem(Item: TObject): Cardinal; override; function Match(const Key; Item:TObject):Boolean; override; function Hash(const Key): Cardinal; override; - class function HashClass(KeyClass: TClass): Cardinal; - function FindByClass(KeyClass: TClass): TObject; + class function HashClass(KeyClass: TClass): Cardinal; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + public + function FindByClass(KeyClass: TClass): TObject; {$IFDEF BOLD_INLINE} inline; {$ENDIF} end; {---TBoldGuidHashIndex---} @@ -74,12 +79,13 @@ TBoldGUIDHashIndex = class(TBoldHashIndex) private function GuidEqual(const Guid1, Guid2: TGuid): Boolean; protected - function ItemASKeyGUID(O: TObject): TGUID; virtual; abstract; + function ItemASKeyGUID(Item: TObject): TGUID; virtual; abstract; function HashItem(Item: TObject): Cardinal; override; function Match(const Key; Item:TObject):Boolean; override; function Hash(const Key): Cardinal; override; - function HashGUID(const KeyGUID: TGUID): Cardinal; - function FindByGUID(const KeyGUID: TGUID): TObject; + function HashGUID(const KeyGUID: TGUID): Cardinal; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + public + function FindByGUID(const KeyGUID: TGUID): TObject; {$IFDEF BOLD_INLINE} inline; {$ENDIF} end; {---TBoldCardinalHashIndex---} @@ -89,47 +95,68 @@ TBoldCardinalHashIndex = class(TBoldHashIndex) function HashItem(Item: TObject): Cardinal; override; function Match(const Key; Item:TObject):Boolean; override; function Hash(const Key): Cardinal; override; - function FindByCardinal(const KeyCardinal: Cardinal): TObject; + function FindByCardinal(const KeyCardinal: Cardinal): TObject; {$IFDEF BOLD_INLINE} inline; {$ENDIF} end; implementation uses - Windows, // CharUpperBuff, fixme move to BoldUtils. - SysUtils, - BoldUtils; + Windows, + BoldUtils, + BoldRev; + +{$IFDEF USEGLOBALCHARBUFFER} +const + InitialBufferSize = 256; +var + _PBuffer: PChar; + _PBufferLength: integer = InitialBufferSize; +{$ENDIF} -class function TBoldStringKey.HashBuffer(P: PChar; Length: integer; CompareMode: TBoldStringCompareMode): Cardinal; +class function TBoldStringKey.HashBuffer(const P: PChar; const Length: Integer; const CompareMode: TBoldStringCompareMode): Cardinal; +{$IFNDEF USEGLOBALCHARBUFFER} function LIHash: Cardinal; // Separate function to avoid string handling overhead in main func var PUpper: PChar; begin - GetMem(PUpper, Length); + GetMem(PUpper, Length * SizeOf(Char)); try - Move(P^, PUpper^, Length); + Move(P^, PUpper^, Length * SizeOf(Char)); CharUpperBuff(PUpper, Length); // FIXME provide method in BoldUtils Result := HashBuffer(PUpper, Length, bscCaseDependent); finally Freemem(PUpper); end; end; +{$ENDIF} var i: integer; begin - Result := 0; - case CompareMode of - bscCaseDependent: - for i := 0 to Length-1 do - Result := ((Result shl 3) and 2147483647) or - (Result shr (32-3)) xor ord(P[i]); - bscCaseIndependent: - for i := 0 to Length-1 do - Result := ((Result shl 3) and 2147483647) or - (Result shr (32-3)) xor (ord(P[i]) or 32); + Result := 0; + case CompareMode of + bscCaseDependent: + for i := 0 to Length-1 do + Result := ((Result shl 3) and 2147483647) or + (Result shr (32-3)) xor ord(P[i]); + bscCaseIndependent: + for i := 0 to Length-1 do + Result := ((Result shl 3) and 2147483647) or + (Result shr (32-3)) xor (ord(P[i]) or 32); else + {$IFDEF USEGLOBALCHARBUFFER} + if Length > _PBufferLength then begin + Freemem(_PBuffer); + GetMem(_PBuffer, Length * SizeOf(Char)); + _PBufferLength := Length; + end; + Move(P^, _PBuffer^, Length * SizeOf(Char)); + CharUpperBuff(_PBuffer, Length); // FIXME provide method in BoldUtils + Result := HashBuffer(_PBuffer, Length, bscCaseDependent); + {$ELSE} Result := LIHash; - end; + {$ENDIF} + end; end; class function TBoldStringKey.HashString(const KeyString: String; CompareMode: TBoldStringCompareMode): Cardinal; @@ -138,6 +165,12 @@ class function TBoldStringKey.HashString(const KeyString: String; CompareMode: T end; {---TBoldStringHashIndex---} + +function TBoldStringHashIndex.Hash(const Key): Cardinal; +begin + Result := TBoldStringKey.HashString(string(Key), bscLocaleCaseIndependent); +end; + function TBoldStringHashIndex.HashItem(Item: TObject): Cardinal; begin Result := TBoldStringKey.Hashstring(ItemAsKeyString(Item), bscLocaleCaseIndependent); @@ -145,7 +178,7 @@ function TBoldStringHashIndex.HashItem(Item: TObject): Cardinal; function TBoldStringHashIndex.Match(const Key; Item:TObject):Boolean; begin - Result := BoldAnsiEqual(ItemAsKeyString(Item), string(Key)); + Result := BoldAnsiEqual(ItemAsKeyString(Item), string(Key)); end; function TBoldStringHashIndex.FindByString(const KeyString: string): TObject; @@ -154,6 +187,12 @@ function TBoldStringHashIndex.FindByString(const KeyString: string): TObject; end; {---TBoldCaseSensitiveStringHashIndex---} + +function TBoldCaseSensitiveStringHashIndex.Hash(const Key): Cardinal; +begin + Result := TBoldStringKey.HashString(string(Key), bscCaseDependent); +end; + function TBoldCaseSensitiveStringHashIndex.HashItem(Item: TObject): Cardinal; begin Result := TBoldStringKey.Hashstring(ItemAsKeyString(Item), bscCaseDependent); @@ -170,6 +209,17 @@ function TBoldCaseSensitiveStringHashIndex.FindByString(const KeyString: string) end; {---TBoldObjectHashIndex---} + +class function TBoldObjectHashIndex.HashObject(KeyObject: TObject): Cardinal; +begin + Result := Cardinal(KeyObject); +end; + +function TBoldObjectHashIndex.Hash(const Key): Cardinal; +begin + Result := Cardinal(Key); +end; + function TBoldObjectHashIndex.HashItem(Item: TObject): Cardinal; begin Result := HashObject(ItemAsKeyObject(Item)); @@ -186,6 +236,17 @@ function TBoldObjectHashIndex.FindByObject(KeyObject: TObject): TObject; end; {---TBoldClassHashIndex---} + +class function TBoldClassHashIndex.HashClass(KeyClass: TClass): Cardinal; +begin + Result := Cardinal(KeyClass); +end; + +function TBoldClassHashIndex.Hash(const Key): Cardinal; +begin + Result := Cardinal(Key); +end; + function TBoldClassHashIndex.HashItem(Item: TObject): Cardinal; begin Result := HashClass(ItemAsKeyClass(Item)); @@ -202,6 +263,24 @@ function TBoldClassHashIndex.FindByClass(KeyClass: TClass): TObject; end; {---TBoldGUIDHashIndex---} + +function TBoldGUIDHashIndex.HashGUID(const KeyGUID: TGUID): Cardinal; +var + I: integer; +begin + with KeyGUID do + begin + Result := D1 xor d2 xor (d3 shl 8); + for i := 0 to 7 do + result := result xor D4[I]; + end; +end; + +function TBoldGUIDHashIndex.Hash(const Key): Cardinal; +begin + Result := HashGUid(TGuid(Key)); +end; + function TBoldGUIDHashIndex.HashItem(Item: TObject): Cardinal; begin Result := HashGUID(ItemAsKeyGUID(Item)); @@ -218,7 +297,6 @@ function TBoldGUIDHashIndex.GuidEqual(const Guid1, Guid2: TGuid): Boolean; result := result and (Guid1.D4[i] = Guid2.D4[i]); end; - function TBoldGUIDHashIndex.Match(const Key; Item: TObject):Boolean; begin Result := GuidEqual(TGUID(Key), ItemAsKeyGUID(Item)); @@ -230,6 +308,12 @@ function TBoldGUIDHashIndex.FindByGUID(const KeyGUID: TGUID): TObject; end; {---TBoldCardinalHashIndex---} + +function TBoldCardinalHashIndex.Hash(const Key): Cardinal; +begin + Result := Cardinal(Key); +end; + function TBoldCardinalHashIndex.HashItem(Item: TObject): Cardinal; begin Result := ItemAsKeyCardinal(Item); @@ -255,57 +339,15 @@ procedure TBoldObjectHashIndex.FindAllByObject(const KeyObject: TObject; List: T FindAll(KeyObject, List); end; -function TBoldStringHashIndex.Hash(const Key): Cardinal; -begin - Result := TBoldStringKey.HashString(string(Key), bscLocaleCaseIndependent); -end; - -function TBoldCaseSensitiveStringHashIndex.Hash(const Key): Cardinal; -begin - Result := TBoldStringKey.HashString(string(Key), bscCaseDependent); -end; - -function TBoldObjectHashIndex.Hash(const Key): Cardinal; -begin - Result := Cardinal(Key); -end; - -function TBoldClassHashIndex.Hash(const Key): Cardinal; -begin - Result := Cardinal(Key); -end; - -function TBoldGUIDHashIndex.Hash(const Key): Cardinal; -begin - Result := HashGUid(TGuid(Key)); -end; - -function TBoldCardinalHashIndex.Hash(const Key): Cardinal; -begin - Result := Cardinal(Key); -end; - -class function TBoldObjectHashIndex.HashObject( - KeyObject: TObject): Cardinal; -begin - Result := Cardinal(KeyObject); -end; - -class function TBoldClassHashIndex.HashClass(KeyClass: TClass): Cardinal; -begin - Result := Cardinal(KeyClass); -end; - -function TBoldGUIDHashIndex.HashGUID(const KeyGUID: TGUID): Cardinal; -var - I: integer; -begin - with KeyGUID do - begin - Result := D1 xor d2 xor (d3 shl 8); - for i := 0 to 7 do - result := result xor D4[I]; - end; -end; +initialization +{$IFDEF USEGLOBALCHARBUFFER} + GetMem(_PBuffer, InitialBufferSize * SizeOf(Char)); +{$ENDIF} +finalization +{$IFDEF USEGLOBALCHARBUFFER} + Freemem(_PBuffer); + _PBufferLength := 0; +{$ENDIF} end. + diff --git a/Source/Common/Support/BoldIndex.pas b/Source/Common/Support/BoldIndex.pas index e301288..06eb71d 100644 --- a/Source/Common/Support/BoldIndex.pas +++ b/Source/Common/Support/BoldIndex.pas @@ -1,14 +1,24 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldIndex; interface uses BoldBase, - Classes; + Classes, + Contnrs; + +const + {$IFDEF BOLD_DELPHI16_OR_LATER} + MaxListSize = MaxInt div 16; + {$ELSE} + MaxListSize = Classes.MaxListSize; + {$ENDIF} type { forward declaration of classes } - TBoldHashIndexBucketEntry = class; TBoldIndexTraverser = class; TBoldHashIndexTraverser = class; TBoldIndex = class; @@ -18,8 +28,7 @@ TBoldIntegerIndex = class; PItemEntry = ^TBoldHashIndexItemEntryRec; PPItemEntry = ^PItemEntry; - PPItemEntryList = ^TPItemEntryList; - TPItemEntryList = array[0..MaxListSize - 1] of PItemEntry; + TIntegerIndexSortCompare = function (Item1, Item2: TObject): Integer; { TBoldHashIndexItemEntry } TBoldHashIndexItemEntryRec = record @@ -27,21 +36,44 @@ TBoldHashIndexItemEntryRec = record Item: TObject; end; + // Make class so it shows up in AQTime + TBoldItemRecBloc = class + private + fEntries: array[0..4094] of TBoldHashIndexItemEntryRec; + FFirstEntry: PItemEntry; + function GetFirstEntry: PItemEntry; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + public + constructor Create; + property FirstEntry: PItemEntry read GetFirstEntry; + end; - { TBoldHashIndexBucketEntry } - TBoldHashIndexBucketEntry = class(TBoldMemoryManagedObject) - Next: PItemEntry; + TBoldHashIndexItemEntryRecHandler = class + private + fCount: Integer; + fBlocks: TObjectList; + fFirstFree: PItemEntry; + public + function GetRec: PItemEntry; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure ReturnRec(rec: PItemEntry); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + public + constructor Create; + destructor Destroy; override; + property Count: Integer read fCount; end; { TBoldIndexTraverser } TBoldIndexTraverser = class(TBoldMemoryManagedObject) + private + fAutoMoveOnRemoveCurrent: boolean; + procedure ItemDestroyed(AItem: TObject); virtual; abstract; + procedure Clear; virtual; protected function GetItem: TObject; virtual; abstract; - function GetEol: Boolean; virtual; abstract; public - procedure Next; virtual; abstract; + procedure AfterConstruction; override; + function MoveNext: Boolean; virtual; abstract; property Item: TObject read GetItem; - property EndOfList: Boolean read GetEol; + property AutoMoveOnRemoveCurrent: boolean read fAutoMoveOnRemoveCurrent write fAutoMoveOnRemoveCurrent; end; { TBoldIndex } @@ -52,6 +84,8 @@ TBoldIndex = class (TBoldMemoryManagedObject) function Match(const Key; Item: TObject):Boolean; virtual; abstract; function GetSupportsTraverser: Boolean; virtual; function GetSupportsNilItems: Boolean; virtual; + function GetCapacity: integer; virtual; abstract; + procedure SetCapacity(const Value: integer); virtual; abstract; public procedure FillEmptyIndex(BoldIndex: TBoldIndex); virtual; abstract; procedure Add(Item: TObject); virtual; abstract; @@ -63,23 +97,35 @@ TBoldIndex = class (TBoldMemoryManagedObject) procedure Remove(Item: TObject); virtual; abstract; procedure RemoveChanged(Item: TObject); virtual; abstract; function CreateTraverser: TBoldIndexTraverser; virtual; + function GetAndRemoveAny: TObject; virtual; property Count: integer read GetCount; property Any: TObject read GetAny; property SupportsTraverser: Boolean read GetSupportsTraverser; property SupportsNilItems: Boolean read GetSupportsNilItems; + property Capacity: integer read GetCapacity write SetCapacity; end; + TObjectStaticArray = array[0..MaxListSize - 1] of TObject; + PObjectStaticArray = ^TObjectStaticArray; + { TBoldIntegerIndex } TBoldIntegerIndex = class(TBoldIndex) + strict private + FObjectStaticArray: PObjectStaticArray; + FCount: Integer; + FCapacity: Integer; + function GetItems(index: integer): TObject; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure SetItems(index: integer; const Value: TObject); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure Grow; {$IFDEF BOLD_INLINE} inline; {$ENDIF} private - fList: TLIst; - function GetItems(index: integer): TObject; - procedure SetItems(index: integer; const Value: TObject); + procedure RangeError(Index: integer); protected function GetAny: TObject; override; function GetCount: Integer; override; function Match(const key; Item: TObject):Boolean; override; function GetSupportsNilItems: Boolean; override; + function GetCapacity: integer; override; + procedure SetCapacity(const Value: integer); override; public constructor Create; destructor Destroy; override; @@ -92,13 +138,16 @@ TBoldIntegerIndex = class(TBoldIndex) function IsCorrectlyIndexed(Item: TObject): boolean; override; procedure Remove(Item: TObject); override; procedure RemoveChanged(Item: TObject); override; - procedure Move(CurIndex, NewIndex: Integer); - procedure Sort(Compare: TListSortCompare); - procedure Insert(Index: Integer; Item: TObject); - procedure Exchange(Index1, Index2: integer); - procedure RemoveByIndex(Index: Integer); - function IndexOf(Item: TObject): integer; + procedure Move(CurIndex, NewIndex: Integer); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure Sort(Compare: TIntegerIndexSortCompare); + procedure Insert(Index: Integer; Item: TObject); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure Exchange(Index1, Index2: integer); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure RemoveByIndex(Index: Integer); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetAndRemoveAny: TObject; override; + function IndexOf(Item: TObject): integer; {$IFDEF BOLD_INLINE} inline; {$ENDIF} property Items[index: integer]: TObject read GetItems write SetItems; + function Includes(Item: TObject): boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + property FastCount: Integer read fCount; end; { TBoldHashIndexTraverser } @@ -106,16 +155,16 @@ TBoldHashIndexTraverser = class(TBoldIndexTraverser) private fHashIndex: TBoldHashIndex; fCurrentItem: PItemEntry; - fNextItem: PItemEntry; fBucketIndex: integer; - function FirstItemOfNextBucket: PItemEntry; + function FirstItemOfNextBucket: PItemEntry; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure ItemDestroyed(AItem: TObject); override; + procedure Clear; override; protected function GetItem: TObject; override; - function GetEol: Boolean; override; public constructor Create(HashIndex: TBoldHashIndex); destructor Destroy; override; - procedure Next; override; + function MoveNext: Boolean; override; end; { TBoldHashIndexOptions } @@ -123,33 +172,36 @@ TBoldHashIndexTraverser = class(TBoldIndexTraverser) AutoResize: Boolean; PendingResize: Boolean; IsResizing: Boolean; - TraverserCount: Byte; end; { TBoldHashIndex } TBoldHashIndex = class(TBoldIndex) private fOptions: TBoldHashIndexOptions; - fBucketCount: integer; // Number of hashbuckets - fBucketArray: PPItemEntryList; - fItemCount: integer; // number of Items in table + fBucketArray: array of PItemEntry; + fItemCount: integer; fLastIndexForAny: integer; - function GetBucketArray: PPItemEntryList; - procedure InsertEntry(Entry: PItemEntry); - function MinimumBucketCount: integer; - function MaximumBucketCount: integer; - function PrefferedBucketCount: integer; - procedure SetAutoResize(Value: boolean); - procedure DecreaseTraverser; - property BucketArray: PPItemEntryList read GetBucketArray; + fTraverserList: TList; + procedure InsertEntry(Entry: PItemEntry); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function MinimumBucketCount: integer; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function MaximumBucketCount: integer; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function PrefferedBucketCount: integer; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure SetAutoResize(Value: boolean); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure RemoveTraverser(ATraverser: TBoldIndexTraverser); + function GetTraverserCount: Integer; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function EnsuredTraverserList: TList; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetTraverser(AIndex: integer): TBoldIndexTraverser; {$IFDEF BOLD_INLINE} inline; {$ENDIF} protected - function PBucketForHash(Hash: Cardinal): PPItemEntry; - function PBucketForIndex(Index: Integer): PPItemEntry; + function IndexForHash(Hash: Cardinal): integer; {$IFDEF BOLD_INLINE} inline; {$ENDIF} function GetCount: Integer; override; function HashItem(Item: TObject): Cardinal; virtual; abstract; function Hash(const Key): Cardinal; virtual; abstract; function GetAny: TObject; override; function GetSupportsTraverser: Boolean; override; + property Traversers[AIndex: integer]: TBoldIndexTraverser read GetTraverser; + property TraverserCount: Integer read GetTraverserCount; + function GetCapacity: integer; override; + procedure SetCapacity(const Value: integer); override; public constructor Create; destructor Destroy; override; @@ -159,6 +211,7 @@ TBoldHashIndex = class(TBoldIndex) function Find(const Key): TObject; override; procedure FindAll(const Key; Result: TList); override; function IsCorrectlyIndexed(Item: TObject): boolean; override; + procedure ItemChanged(Item: TObject); override; procedure Remove(Item: TObject); override; procedure RemoveChanged(Item: TObject); override; procedure Resize; @@ -167,20 +220,53 @@ TBoldHashIndex = class(TBoldIndex) procedure AssertIndex; end; -procedure ReturnItemEntry(Entry:PItemEntry; DestroyObjects: Boolean=false); +var + G_HashIndexItemEntryRecHandler: TBoldHashIndexItemEntryRecHandler; implementation uses SysUtils, BoldDefs, - BoldMemoryManager; + BoldRev; const AVERAGEBUCKETLENGTH = 2; MINIMUMHASHBUCKETS = 8; -// Utilityfunction +function TBoldIntegerIndex.GetItems(index: integer): TObject; +begin + // No range check, checked by caller + Result := FObjectStaticArray^[Index]; +end; + +function TBoldItemRecBloc.GetFirstEntry: PItemEntry; +begin + Result := @fEntries[0]; +end; + +function TBoldHashIndexItemEntryRecHandler.GetRec: PItemEntry; +var + Block: TBoldItemRecBloc; +begin + INC(fCount); + if not Assigned(fFirstFree) then + begin + Block := TBoldItemRecBloc.Create; + fFirstFree := Block.FirstEntry; + fBlocks.Add(Block) + end; + Result := fFirstFree; + fFirstFree := Result.Next; +end; + +procedure TBoldHashIndexItemEntryRecHandler.ReturnRec(rec: PItemEntry); +begin + DEC(fCount); + rec.Next := fFirstFree; + fFirstFree := rec; +end; + procedure ReturnItemEntry(Entry:PItemEntry; DestroyObjects: Boolean=false); begin if not Assigned(Entry) then @@ -189,7 +275,7 @@ procedure ReturnItemEntry(Entry:PItemEntry; DestroyObjects: Boolean=false); ReturnItemEntry(Entry.Next, DestroyObjects); if DestroyObjects then FreeAndNil(Entry.Item); - BoldMemoryManager_.DeAllocateMemory(entry, sizeof(TBoldHashIndexItemEntryRec)) + G_HashIndexItemEntryRecHandler.ReturnRec(entry); end; { TBoldIndex } @@ -199,6 +285,18 @@ function TBoldIndex.CreateTraverser: TBoldIndexTraverser; result := nil; end; +function TBoldIndex.GetAndRemoveAny: TObject; +begin + result := Any; + if Assigned(result) then + begin + if Count = 1 then + Clear + else + Remove(result); + end; +end; + function TBoldIndex.GetSupportsNilItems: Boolean; begin result := false; @@ -221,80 +319,124 @@ procedure TBoldIndex.ItemChanged(Item: TObject); { TBoldHashIndex } constructor TBoldHashIndex.Create; begin - fBucketCount := MinimumBucketCount; fOptions.AutoResize := True; end; destructor TBoldHashIndex.Destroy; begin Clear; - assert(fOptions.TraverserCount = 0, 'unreleased traversers on hashindex'); + assert(TraverserCount = 0, 'unreleased traversers on hashindex'); + FreeAndNil(fTraverserList); inherited end; +function TBoldHashIndex.EnsuredTraverserList: TList; +begin + if not Assigned(fTraverserList) then + fTraverserList := TList.Create; + result := fTraverserList; +end; + procedure TBoldHashIndex.SetAutoResize(Value: boolean); begin fOptions.AutoResize := Value; if Value then Resize; end; +function TBoldHashIndex.GetCapacity: integer; +begin + result := MaxInt; // Capacity not supported so return MaxInt +end; + +procedure TBoldHashIndex.SetCapacity(const Value: integer); +begin +// do nothing +end; + function TBoldHashIndex.GetCount: Integer; begin Result := fItemCount; end; +function TBoldHashIndex.PrefferedBucketCount: integer; +begin + Result := MINIMUMHASHBUCKETS shl 2 + fItemCount div AVERAGEBUCKETLENGTH; +end; + +function TBoldHashIndex.MinimumBucketCount: integer; +begin + Result := PrefferedBucketCount div 2; +end; + +function TBoldHashIndex.MaximumBucketCount: integer; +begin + Result := PrefferedBucketCount * 4; +end; + +function TBoldHashIndex.IndexForHash(Hash: Cardinal): integer; +begin + result := hash mod Cardinal(Length(fBucketArray)); +end; + +procedure TBoldHashIndex.InsertEntry(Entry: PItemEntry); +var + BucketIndex: integer; +begin + BucketIndex := IndexForHash(HashItem(Entry.Item)); + Entry.next := fBucketArray[BucketIndex]; + fBucketArray[BucketIndex] := Entry; + Inc(fItemCount); +end; + procedure TBoldHashIndex.Resize; -//FIXME: Check this code thouroughly before used!!! var TempChain: PItemEntry; Last: PPItemEntry; Current: PItemEntry; - i: integer; + i, oldBucketCount: integer; begin - if not fOptions.IsResizing and - ((fBucketCount < MinimumBucketCount) or (fBucketCount > MaximumBucketCount)) then + oldBucketCount := Length(fBucketArray); + if fOptions.IsResizing then + Exit; + if ((oldBucketCount >= MinimumBucketCount) and (oldBucketCount <= MaximumBucketCount)) then begin - if fOptions.TraverserCount > 0 then - begin - fOptions.PendingResize := true; - exit; - end; - try - fOptions.IsResizing := true; - - // collect all entries in one chain starting in TempChain - TempChain := Nil; - Last := @TempChain; + fOptions.PendingResize := false; + exit; + end; + if (TraverserCount > 0) and (fItemCount > 0) then + begin + fOptions.PendingResize := true; + exit; + end; + try + fOptions.IsResizing := true; + TempChain := nil; + Last := @TempChain; - for i := 0 to fBucketCount - 1 do - begin - Current := PBucketForIndex(i)^; - if Assigned(Current) then - begin - Last^ := Current; - while Assigned(Current.Next) do - Current := Current.Next; - Last := @Current.Next; - end; - end; - BoldMemoryManager_.DeAllocateMemory(fBucketArray, fBucketCount*sizeof(PItemEntry)); - fBucketArray := nil; - // BucketArray will be recreated through GetBucketArray - // calculate new size - fBucketCount := PrefferedBucketCount; - fItemCount := 0; - // reinsert all the entries; - while Assigned(TempChain) do + for i := 0 to Length(fBucketArray) - 1 do + begin + Current := fBucketArray[i]; + if Assigned(Current) then begin - // take first.next out of the chain and add it - Current := TempChain; - TempChain := TempChain.Next; - InsertEntry(Current); + Last^ := Current; + while Assigned(Current.Next) do + Current := Current.Next; + Last := @Current.Next; end; - - finally - fOptions.IsResizing := False; end; + SetLength(fBucketArray, PrefferedBucketCount); + for i := 0 to PrefferedBucketCount - 1 do + fBucketArray[i] := nil; + fItemCount := 0; + while Assigned(TempChain) do + begin + Current := TempChain; + TempChain := TempChain.Next; + InsertEntry(Current); + end; + + finally + fOptions.IsResizing := False; end; end; @@ -302,12 +444,17 @@ procedure TBoldHashIndex.Remove(Item: TObject); var Pre: PPItemEntry; ToBeRemoved: PItemEntry; + i: integer; begin - Pre := PBucketForHash(HashItem(Item)); + if Length(fBucketArray) = 0 then + exit; + Pre := @(fBucketArray[IndexForHash(HashItem(Item))]); while Assigned(Pre^) do begin if Pre^.Item = Item then begin + for I := 0 to TraverserCount - 1 do + Traversers[i].ItemDestroyed(Item); ToBeRemoved := Pre^; Pre^ := ToBeRemoved.Next; ToBeRemoved.next := nil; @@ -317,29 +464,23 @@ procedure TBoldHashIndex.Remove(Item: TObject); end else Pre := @Pre^.Next; - end; + end; if AutoResize then Resize; end; -procedure TBoldHashIndex.InsertEntry(Entry: PItemEntry); -// inserts the new element first in the hashbucket -var - Bucket: PPItemEntry; -begin - Bucket := PBucketForHash(HashItem(Entry.Item)); - Entry.next := Bucket^; - Bucket^ := Entry; - Inc(fItemCount); -end; - procedure TBoldHashIndex.Add(Item: TObject); var NewEntry: PItemEntry; begin if assigned(item) then begin - NewEntry := BoldMemoryManager_.AllocateMemory(sizeof(TBoldHashIndexItemEntryRec)); + if Length(fBucketArray) = 0 then + begin + Resize; + Assert(Length(fBucketArray) > 0); + end; + NewEntry := G_HashIndexItemEntryRecHandler.GetRec; NewEntry.Item := Item; InsertEntry(NewEntry); end; @@ -351,38 +492,58 @@ function TBoldHashIndex.Find(const Key): TObject; var Current: PItemEntry; begin - Current := PBucketForHash(Hash(Key))^; + Result := nil; + if Length(fBucketArray) = 0 then + Exit; + Current := fBucketArray[IndexForHash(Hash(Key))]; while Assigned(current) and (not Match(Key, Current.Item)) do Current := Current.Next; if Assigned(Current) then Result := Current.Item - else - Result := nil; end; function TBoldHashIndex.IsCorrectlyIndexed(Item: TObject): boolean; var Current: PItemEntry; begin - Current := PBucketForHash(HashItem(Item))^; + Current := fBucketArray[IndexForHash(HashItem(Item))]; while Assigned(Current) and (Item <> Current.Item) do Current := Current.Next; Result := Assigned(Current); end; +procedure TBoldHashIndex.ItemChanged(Item: TObject); +var + StoredAutoResize: boolean; +begin + if not IsCorrectlyIndexed(Item) then + begin + StoredAutoResize := AutoResize; + AutoResize := false; + try + RemoveChanged(Item); + Add(Item); + finally + AutoResize := StoredAutoResize; + end; + end; +end; + procedure TBoldHashIndex.RemoveChanged(Item: TObject); var - i: integer; + i,j: integer; Pre: PPItemEntry; ToBeRemoved: PItemEntry; begin - for i := 0 to fBucketCount - 1 do + for i := 0 to Length(fBucketArray) - 1 do begin - Pre := PBucketForIndex(i); + Pre := @(fBucketArray[i]); while Assigned(Pre^) do begin if Pre^.Item = Item then begin + for j := 0 to TraverserCount - 1 do + Traversers[j].ItemDestroyed(Item); ToBeRemoved := Pre^; Pre^ := ToBeRemoved.Next; ToBeRemoved.Next := nil; @@ -396,7 +557,6 @@ procedure TBoldHashIndex.RemoveChanged(Item: TObject); end; if AutoResize then Resize; - end; procedure TBoldHashIndex.FindAll(const Key; Result: TList); @@ -404,8 +564,9 @@ procedure TBoldHashIndex.FindAll(const Key; Result: TList); current: PItemEntry; begin Assert(Assigned(Result), 'Trying to find Entries to insert in an unassigned list'); - - Current := PBucketForHash(Hash(Key))^; + if Length(fBucketArray) = 0 then + Exit; + Current := fBucketArray[IndexForHash(Hash(Key))]; while Assigned(Current) do begin if Match(Key, Current.Item) then @@ -414,34 +575,18 @@ procedure TBoldHashIndex.FindAll(const Key; Result: TList); end; end; -function TBoldHashIndex.PrefferedBucketCount: integer; -begin - Result := MINIMUMHASHBUCKETS shl 2 + fItemCount div AVERAGEBUCKETLENGTH; -end; - -function TBoldHashIndex.MinimumBucketCount: integer; -begin - Result := PrefferedBucketCount div 2; -end; - -function TBoldHashIndex.GetBucketArray: PPItemEntryList; -begin - if not Assigned(fBucketArray) then - fBucketArray := BoldMemoryManager_.AllocateMemoryZeroFill(fBucketCount*sizeof(PItemEntry)); - result := fBucketArray; -end; - procedure TBoldHashIndex.Clear(DestroyObjects: Boolean=false); var i: integer; begin -// inherited; - if Assigned(fBucketArray) then - for i := 0 to fBucketCount - 1 do - ReturnItemEntry(PBucketForIndex(i)^, DestroyObjects); - BoldMemoryManager_.DeAllocateMemory(fBucketArray, fBucketCount*sizeof(PItemEntry)); - fBucketArray := nil; - fBucketCount := MinimumBucketCount; + if fItemCount = 0 then + exit; +// if DestroyObjects then + for i := 0 to Length(fBucketArray) - 1 do + ReturnItemEntry(fBucketArray[i], DestroyObjects); + for i := 0 to TraverserCount -1 do + Traversers[i].Clear; + SetLength(fBucketArray, 0); fItemCount := 0; end; @@ -450,22 +595,19 @@ function TBoldHashIndex.GetAny: TObject; BucketIndex: integer; begin result := nil; - if Count > 0 then + if Count = 0 then + Exit; + BucketIndex := fLastIndexForAny; + while not assigned(result) do begin - BucketIndex := fLastIndexForAny; - - while not assigned(result) do + if BucketIndex >= Length(fBucketArray) then + BucketIndex := 0; + if assigned(fBucketArray[BucketIndex]) then begin - if assigned(PBucketForHash(BucketIndex)^) then - begin - result := PBucketForHash(BucketIndex)^.Item; - fLastIndexForAny := BucketIndex; - end; - - inc(BucketIndex); - if BucketIndex > fBucketCount then - BucketIndex := 0; + result := fBucketArray[BucketIndex]^.Item; + fLastIndexForAny := BucketIndex; end; + inc(BucketIndex); end; end; @@ -474,9 +616,9 @@ procedure TBoldHashIndex.FillEmptyIndex(BoldIndex: TBoldIndex); i: integer; Current: PItemEntry; begin - for i := 0 to fBucketCount - 1 do + for i := 0 to Length(fBucketArray) - 1 do begin - Current := PBucketForHash(i)^; + Current := fBucketArray[i]; while assigned(Current) do begin BoldIndex.Add(Current.Item); @@ -490,75 +632,98 @@ function TBoldHashIndex.GetSupportsTraverser: Boolean; result := true; end; -function TBoldHashIndex.CreateTraverser: TBoldIndexTraverser; +function TBoldHashIndex.GetTraverser(AIndex: integer): TBoldIndexTraverser; begin - result := TBoldHashIndexTraverser.Create(self); - fOptions.TraverserCount := fOptions.TraverserCount + 1; + result := TBoldIndexTraverser(fTraverserList[AIndex]); end; -procedure TBoldHashIndex.DecreaseTraverser; +function TBoldHashIndex.GetTraverserCount: Integer; begin - fOptions.TraverserCount := fOptions.TraverserCount - 1; - if (fOptions.TraverserCount = 0) and fOptions.PendingResize then - Resize; -end; - -function TBoldHashIndex.MaximumBucketCount: integer; -begin - Result := PrefferedBucketCount * 4; + if Assigned(fTraverserList) then + result := fTraverserList.Count + else + result := 0; end; -function TBoldHashIndex.PBucketForHash( - Hash: Cardinal): PPItemEntry; -var - index: integer; +function TBoldHashIndex.CreateTraverser: TBoldIndexTraverser; begin - index := hash mod Cardinal(fBucketCount); - result := PBucketForIndex(index); + result := TBoldHashIndexTraverser.Create(self); + EnsuredTraverserList.Add(result); end; -function TBoldHashIndex.PBucketForIndex(Index: Integer): PPItemEntry; +procedure TBoldHashIndex.RemoveTraverser(ATraverser: TBoldIndexTraverser); begin - Assert((index>=0) and (Index< fBucketCount)); - result := @(BucketArray[Index]); + if TraverserCount <> 0 then + fTraverserList.Remove(ATraverser); + if (TraverserCount = 0) and fOptions.PendingResize then + Resize; end; procedure TBoldHashIndex.AssertIndex; +{$IFOPT C+} var i: integer; Pre: PPItemEntry; Start: PItemEntry; - {$IFOPT C+} // Assertions Cnt: integer; - {$ENDIF} +{$ENDIF} begin - {$IFOPT C+} // Assertions +{$IFOPT C+} Cnt := 0; - {$ENDIF} - for i := 0 to fBucketCount - 1 do + for i := 0 to Length(fBucketArray) - 1 do begin - Pre := PBucketForIndex(i); + Pre := @(fBucketArray[i]); Start := Pre^; while Assigned(Pre^) do begin - {$IFOPT C+} // Assertions Inc(cnt); - {$ENDIF} Assert(IsCorrectlyIndexed(Pre^.Item)); Pre := @(Pre^.Next); Assert(pre^ <> Start); end; end; - {$IFOPT C+} // Assertions - Assert(Count = Cnt, Format('%d, %d', [Count, cnt])); - {$ENDIF} + Assert(Count=Cnt, Format('%d, %d',[Count, cnt])); +{$ENDIF} end; { TBoldIntegerIndex } +procedure TBoldIntegerIndex.SetCapacity(const Value: integer); +begin + if Value <> FCapacity then + begin + if ((Value = 0) or (Value > Capacity)) and (Value >= fCount) then // only allow growth or set to 0, do not allow reduction in capacity + begin + Assert(Value >= fCount); + ReallocMem(FObjectStaticArray, Value * SizeOf(TObject)); + FCapacity := Value; + end; + end; +end; + +procedure TBoldIntegerIndex.Grow; +var + Delta: Integer; +begin + if FCapacity > 64 then + Delta := FCapacity div 4 + else + if FCapacity > 8 then + Delta := 16 + else + Delta := 4; + SetCapacity(FCapacity + Delta); +end; + procedure TBoldIntegerIndex.Add(Item: TObject); +var + Index: Integer; begin - fList.Add(item); + Index := FCount; + if Index = FCapacity then + Grow; + FObjectStaticArray^[Index] := Item; + Inc(FCount); end; procedure TBoldIntegerIndex.Clear(DestroyObjects: Boolean=false); @@ -568,26 +733,24 @@ procedure TBoldIntegerIndex.Clear(DestroyObjects: Boolean=false); begin if DestroyObjects then begin - for i := 0 to Count - 1 do + for i := 0 to fCount - 1 do begin - temp := fList[i]; - fList[i] := nil; + temp := FObjectStaticArray^[i]; + FObjectStaticArray^[i] := nil; temp.Free; end; end; - fList.Clear; + fCount := 0; end; constructor TBoldIntegerIndex.Create; begin - fList := TList.Create; end; function TBoldIntegerIndex.Find(const Key): TObject; begin - // Note: Count is actually an integer - if Cardinal(Key) < Cardinal(Count) then - result := fList[Cardinal(Key)] + if Cardinal(Key) < Cardinal(FCount) then + result := FObjectStaticArray^[Cardinal(Key)] else result := nil; end; @@ -601,15 +764,31 @@ procedure TBoldIntegerIndex.FindAll(const Key; Result: TList); result.Add(res); end; +function TBoldIntegerIndex.GetCapacity: integer; +begin + result := fCapacity; +end; + function TBoldIntegerIndex.GetCount: Integer; begin - result := fList.Count; + result := fCount; end; function TBoldIntegerIndex.GetAny: TObject; begin - if Count > 0 then - result := fList[0] + if fCount > 0 then + result := FObjectStaticArray[fCount-1] + else + result := nil; +end; + +function TBoldIntegerIndex.GetAndRemoveAny: TObject; +begin + if fCount > 0 then + begin + result := FObjectStaticArray[fCount-1]; + RemoveByIndex(fCount-1); + end else result := nil; end; @@ -621,79 +800,160 @@ function TBoldIntegerIndex.IsCorrectlyIndexed(Item: TObject): boolean; function TBoldIntegerIndex.Match(const Key; Item: TObject): Boolean; begin - // Note: Count is actually an integer - if Cardinal(Key) < Cardinal(Count) then - Result := item = fList[Cardinal(key)] + if Cardinal(Key) < Cardinal(fCount) then + Result := item = FObjectStaticArray[Cardinal(key)] else Result := False; end; -procedure TBoldIntegerIndex.Remove(Item: TObject); +procedure TBoldIntegerIndex.RangeError(Index: integer); begin - fList.Remove(item); + raise EBold.Create('Index out of range ' + IntToStr(Index)); end; -procedure TBoldIntegerIndex.RemoveChanged(Item: TObject); +function TBoldIntegerIndex.IndexOf(Item: TObject): integer; begin - fList.Remove(item); + Result := 0; + while (Result < FCount) and (FObjectStaticArray^[Result] <> Item) do + Inc(Result); + if Result = FCount then + Result := -1; end; -function TBoldIntegerIndex.GetItems(index: integer): TObject; +function TBoldIntegerIndex.Includes(Item: TObject): boolean; begin - result := fList[index]; + Result := IndexOf(Item) <> -1; end; -procedure TBoldIntegerIndex.SetItems(index: integer; const Value: TObject); +procedure TBoldIntegerIndex.RemoveByIndex(Index: Integer); +var + Temp: TObject; begin - fList[index] := value; + if (Index < 0) or (Index >= FCount) then + RangeError(Index); + Temp := FObjectStaticArray^[Index]; + Dec(FCount); + if Index < FCount then + System.Move(FObjectStaticArray^[Index + 1], FObjectStaticArray^[Index], + (FCount - Index) * SizeOf(TObject)); end; -procedure TBoldIntegerIndex.Exchange(Index1, Index2: integer); +procedure TBoldIntegerIndex.Remove(Item: TObject); +var + Index: Integer; begin - fList.Exchange(index1, index2); + Index := IndexOf(Item); + if Index >= 0 then + RemoveByIndex(Index); end; -function TBoldIntegerIndex.IndexOf(Item: TObject): integer; +procedure TBoldIntegerIndex.RemoveChanged(Item: TObject); begin - result := fList.IndexOf(item); + Remove(item); end; -procedure TBoldIntegerIndex.Move(CurIndex, NewIndex: Integer); +procedure TBoldIntegerIndex.SetItems(index: integer; const Value: TObject); begin - fList.Move(curIndex, NewIndex); + // No range check, checked by caller + FObjectStaticArray^[index] := value; end; -procedure TBoldIntegerIndex.Sort(Compare: TListSortCompare); +procedure TBoldIntegerIndex.Exchange(Index1, Index2: integer); +var + Item: TObject; begin - fList.Sort(Compare); + if (Index1 < 0) or (Index1 >= FCount) then + RangeError(Index1); + if (Index2 < 0) or (Index2 >= FCount) then + RangeError(Index2); + Item := FObjectStaticArray^[Index1]; + FObjectStaticArray^[Index1] := FObjectStaticArray^[Index2]; + FObjectStaticArray^[Index2] := Item; end; procedure TBoldIntegerIndex.Insert(Index: Integer; Item: TObject); begin - fList.Insert(index, item); + if (Index < 0) or (Index > FCount) then + RangeError(Index); + if FCount = FCapacity then + Grow; + if Index < FCount then + System.Move(FObjectStaticArray^[Index], FObjectStaticArray^[Index + 1], + (FCount - Index) * SizeOf(TObject)); + FObjectStaticArray^[Index] := Item; + Inc(FCount); end; -procedure TBoldIntegerIndex.RemoveByIndex(Index: Integer); +procedure TBoldIntegerIndex.Move(CurIndex, NewIndex: Integer); +var + Item: Pointer; +begin + if CurIndex <> NewIndex then + begin + if (NewIndex < 0) or (NewIndex >= FCount) then + RangeError(NewIndex); + if (CurIndex < 0) or (CurIndex >= FCount) then + RangeError(CurIndex); + Item := FObjectStaticArray^[CurIndex]; + FObjectStaticArray^[CurIndex] := nil; + RemoveByIndex(CurIndex); + Insert(NewIndex, nil); + FObjectStaticArray^[NewIndex] := Item; + end; +end; + +procedure QuickSort(SortList: PObjectStaticArray; L, R: Integer; + SCompare: TIntegerIndexSortCompare); +var + I, J: Integer; + P, T: TObject; begin - fList.Delete(index); + repeat + I := L; + J := R; + P := SortList^[(L + R) shr 1]; + repeat + while SCompare(SortList^[I], P) < 0 do + Inc(I); + while SCompare(SortList^[J], P) > 0 do + Dec(J); + if I <= J then + begin + T := SortList^[I]; + SortList^[I] := SortList^[J]; + SortList^[J] := T; + Inc(I); + Dec(J); + end; + until I > J; + if L < J then + QuickSort(SortList, L, J, SCompare); + L := I; + until I >= R; +end; + +procedure TBoldIntegerIndex.Sort(Compare: TIntegerIndexSortCompare); +begin + if (FObjectStaticArray <> nil) and (fCount > 0) then + QuickSort(FObjectStaticArray, 0, fCount - 1, Compare); end; procedure TBoldIntegerIndex.FillEmptyIndex(BoldIndex: TBoldIndex); var i: integer; begin - for i := 0 to Count - 1 do + for i := 0 to fCount - 1 do BoldIndex.Add(items[i]) end; procedure TBoldIntegerIndex.ItemChanged(Item: TObject); begin - // do nothing end; destructor TBoldIntegerIndex.Destroy; begin - FreeAndNil(fList); + Clear; + SetCapacity(0); inherited; end; @@ -704,48 +964,114 @@ function TBoldIntegerIndex.GetSupportsNilItems: Boolean; { TBoldHashIndexTraverser } +function TBoldHashIndexTraverser.FirstItemOfNextBucket: PItemEntry; +begin + result := nil; + while not Assigned(Result) and (fBucketIndex < (Length(fHashIndex.fBucketArray)-1)) do + begin + inc(fBucketIndex); + result := fHashIndex.fBucketArray[fBucketIndex]; + end; +end; + +procedure TBoldHashIndexTraverser.Clear; +begin + fCurrentItem := nil; +end; + constructor TBoldHashIndexTraverser.Create(HashIndex: TBoldHashIndex); begin inherited Create; fHashIndex := HashIndex; fBucketIndex := -1; - fNextItem := FirstItemOfNextBucket; - Next; end; destructor TBoldHashIndexTraverser.Destroy; begin + fHashIndex.RemoveTraverser(self); inherited; - fHashIndex.DecreaseTraverser; end; -function TBoldHashIndexTraverser.FirstItemOfNextBucket: PItemEntry; +function TBoldHashIndexTraverser.GetItem: TObject; begin - result := nil; - while not Assigned(Result) and (fBucketIndex < (fHashIndex.fBucketCount-1)) do + if Assigned(fCurrentItem) then begin - inc(fBucketIndex); - result := fHashIndex.PBucketForIndex(fBucketIndex)^; + result := fCurrentItem.Item; + Assert(Result is TObject); + end + else + result := nil; +end; + +function TBoldHashIndexTraverser.MoveNext: boolean; +begin + if Assigned(fCurrentItem) then + begin + if Assigned(fCurrentItem.Next) then + fCurrentItem := fCurrentItem.Next + else + fCurrentItem := FirstItemOfNextBucket; + end + else + begin + fCurrentItem := FirstItemOfNextBucket; end; + result := Assigned(fCurrentItem); end; -function TBoldHashIndexTraverser.GetEol: Boolean; +procedure TBoldHashIndexTraverser.ItemDestroyed(AItem: TObject); begin - result := not assigned(fCurrentItem); + if AutoMoveOnRemoveCurrent and Assigned(fCurrentItem) and (fCurrentItem.Item = AItem) then + begin + fCurrentItem := fCurrentItem.Next; + if not Assigned(fCurrentItem) then + fCurrentItem := FirstItemOfNextBucket; + end; end; -function TBoldHashIndexTraverser.GetItem: TObject; +{ TBoldHashIndexItemEntryRecHandler } + +constructor TBoldHashIndexItemEntryRecHandler.Create; begin - result := fCurrentItem.Item; + fBlocks := TObjectList.Create; + fBlocks.OwnsObjects := True; end; -procedure TBoldHashIndexTraverser.Next; +destructor TBoldHashIndexItemEntryRecHandler.Destroy; begin - fCurrentItem := fNextItem; - if assigned(fNextItem) and assigned(fNextItem.Next) then - fNExtItem := fNextItem.Next - else - fNextItem := FirstItemOfNextBucket; + // if fCount <> 0 then + // raise Exception.Create('TBoldHashIndexItemEntryRecHandler: Not all records freed'); + FreeAndNil(fBlocks); + inherited; +end; + +{ TBoldItemRecBloc } + +constructor TBoldItemRecBloc.Create; +var + I: Integer; +begin + for I :=low(fEntries) to high(fEntries)- 1 do + fEntries[i].Next := @fEntries[i+1]; + fEntries[high(fEntries)].Next := nil; end; +{ TBoldIndexTraverser } + +procedure TBoldIndexTraverser.AfterConstruction; +begin + inherited; + fAutoMoveOnRemoveCurrent := true; +end; + +procedure TBoldIndexTraverser.Clear; +begin +// nothing +end; + +initialization + G_HashIndexItemEntryRecHandler := TBoldHashIndexItemEntryRecHandler.Create; + +finalization + FreeAndNil(G_HashIndexItemEntryRecHandler); end. diff --git a/Source/Common/Support/BoldIndexCollection.pas b/Source/Common/Support/BoldIndexCollection.pas new file mode 100644 index 0000000..5778283 --- /dev/null +++ b/Source/Common/Support/BoldIndexCollection.pas @@ -0,0 +1,179 @@ +{ Global compiler directives } +{$include bold.inc} +unit BoldIndexCollection; + +interface + +uses + Classes; + +type + TBoldIndexCollection = class; + TBoldIndexCollectionClass = class of TBoldIndexCollection; + + TBoldIndexDefintion = class(TCollectionItem) + strict private + FTableName: String; + fColumns: String; + fUnique: Boolean; + fRemove: Boolean; + function GetAsString: string; + procedure SetAsString(const Value: string); + protected + function GetDisplayName: string; override; + procedure AssignTo(Dest: TPersistent); override; + public + property AsString: string read GetAsString write SetAsString; + function Equals(value: TBoldIndexDefintion): Boolean; reintroduce; + published + property TableName: String read FTableName write FTableName; + property Columns: String read fColumns write fColumns; + property Unique: Boolean read fUnique write fUnique; + property Remove: Boolean read fRemove write fRemove; + end; + + TBoldIndexCollection = class(TCollection) + private + fOwner: TComponent; + function GetDefinition(Index: integer): TBoldIndexDefintion; + procedure SaveToStringList(StrList: TStringList); + procedure LoadFromStringList(StrList: TStringList); + protected + function GetOwner: TPersistent; override; + public + constructor Create(Owner: TComponent); + property IndexDefinition[Index: integer]: TBoldIndexDefintion read GetDefinition; default; + procedure SaveToFile(const FileName: String); + procedure LoadFromFile(const FileName: String); + function AddIndexDefintion: TBoldIndexDefintion; + end; + + +implementation + +uses + SysUtils, + BoldDefs, + BoldNameExpander, + BoldTaggedValueSupport; + +{ TBoldTypeNameDictionary } + +function TBoldIndexCollection.AddIndexDefintion: TBoldIndexDefintion; +begin + result := Add as TBoldIndexDefintion; +end; + +constructor TBoldIndexCollection.Create(Owner: TComponent); +begin + inherited Create(TBoldIndexDefintion); + fOwner := Owner; +end; + +function TBoldIndexCollection.GetDefinition( + Index: integer): TBoldIndexDefintion; +begin + result := GetItem(index) as TBoldIndexDefintion; +end; + +function TBoldIndexCollection.GetOwner: TPersistent; +begin + result := fOwner; +end; + +procedure TBoldIndexCollection.LoadFromFile(const FileName: String); +var + StrList: TStringList; +begin + StrList := TStringList.Create; + try + StrList.LoadFromFile(FileName); + LoadFromStringList(StrList); + finally + StrList.Free; + end; +end; + +procedure TBoldIndexCollection.LoadFromStringList(StrList: TStringList); +var + i: integer; +begin + Clear; + for i := 0 to StrList.Count-1 do + if trim(StrList[i]) <> '' then + begin + Add; + IndexDefinition[Count-1].AsString := Trim(StrList[i]); + end; +end; + +procedure TBoldIndexCollection.SaveToFile(const FileName: String); +var + StrList: TStringLIst; +begin + StrList := TStringList.Create; + try + SaveToStringList(StrList); + StrList.SaveToFile(FileName); + finally + StrList.Free; + end; +end; + +procedure TBoldIndexCollection.SaveToStringList(StrList: TStringList); +var + i: integer; +begin + for i := 0 to Count-1 do + StrList.Add(IndexDefinition[i].AsString); +end; + +{ TBoldTypeNameMapping } + +function TBoldIndexDefintion.Equals(value: TBoldIndexDefintion): Boolean; +begin + result := (TableName = value.TableName) and (Columns = value.Columns) and + (Unique = value.Unique); + +end; + +function TBoldIndexDefintion.GetAsString: string; +begin + Result := Format('TableName=%s,Columns=%s', + [TableName, + Columns]); +end; + +function TBoldIndexDefintion.GetDisplayName: string; +begin + Result := Format('%s(%s)', [TableName, Columns]); + if Unique then + Result := Result + '[U]'; +end; + +procedure TBoldIndexDefintion.SetAsString(const Value: string); +begin + with TStringList.Create do + try + CommaText := value; + TableName := Values['TableName']; + Columns := Values['Columns']; + finally + Free; + end; +end; + +procedure TBoldIndexDefintion.AssignTo(Dest: TPersistent); +begin + if dest is TBoldIndexDefintion then + with dest as TBoldIndexDefintion do begin + TableName := self.TableName; + Columns := self.Columns; + Unique := self.Unique; + Remove := self.remove; + end + else + inherited; +end; + +end. diff --git a/Source/Common/Support/BoldIndexableList.pas b/Source/Common/Support/BoldIndexableList.pas index 5f1bc6b..af475a4 100644 --- a/Source/Common/Support/BoldIndexableList.pas +++ b/Source/Common/Support/BoldIndexableList.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldIndexableList; interface @@ -5,7 +8,6 @@ interface uses Classes, BoldBase, - BoldContainers, BoldIndex; type @@ -14,7 +16,7 @@ TBoldIndexableList = class; TBoldUnOrderedIndexableList = class; TBoldIndexableListTraverser = class; TBoldIndexableListTraverserClass = class of TBoldIndexableListTraverser; - + TBoldIndexableListOptions = (iloOwnsEntries, iloDestroying, iloKnowsSupportsNil, iloSupportsNil); TBoldIndexableListOptionsSet = set of TBoldIndexableListOptions; @@ -22,40 +24,47 @@ TBoldIndexableListTraverser = class(TBoldMemoryManagedObject) private fIndexTraverser: TBoldIndexTraverser; fCurrentIndex: integer; + function GetAutoMoveOnRemoveCurrent: boolean; + procedure SetAutoMoveOnRemoveCurrent(const Value: boolean); protected - function GetItem: TObject; - function GetEol: Boolean; + function GetItem: TObject; {$IFDEF BOLD_INLINE} inline; {$ENDIF} public constructor Create(IndexTraverser: TBoldIndexTraverser); destructor Destroy; override; - procedure Next; + function MoveNext: Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} property Item: TObject read GetItem; - property EndOfList: Boolean read GetEol; property CurrentIndex: integer read fCurrentIndex; + property Current: TObject read GetItem; + property AutoMoveOnRemoveCurrent: boolean read GetAutoMoveOnRemoveCurrent write SetAutoMoveOnRemoveCurrent; end; {---TBoldUnOrderedIndexableList---} TBoldUnOrderedIndexableList = class(TBoldNonRefCountedObject) private - fIndexes: TList; + fIndexes: array of TBoldIndex; fOptions: TBoldIndexableListOptionsSet; - function GetCount: Integer; - function GetIndex(Index: Integer): TBoldIndex; - function GetIndexCount: Integer; + fFirstNilSupportingIndex: Integer; + function GetCount: Integer; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetIndex(Index: Integer): TBoldIndex; {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure SetIndex(I: Integer; const Value: TBoldIndex); function GetAny: TObject; - function GetOwnsEntries: boolean; - procedure SetOwnsEntries(const Value: boolean); + function GetOwnsEntries: boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure SetOwnsEntries(const Value: boolean); {$IFDEF BOLD_INLINE} inline; {$ENDIF} function FirstNilSupportingIndex: TBoldIndex; function FirstAssignedIndex: TBoldIndex; - function GetKnowsSupportsNil: Boolean; - function GetSupportsNil: Boolean; - procedure SetKnowsSupportsNil(const Value: Boolean); - procedure SetSupportsNil(const Value: Boolean); - procedure CalculateSupportsNil; + function GetKnowsSupportsNil: Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetSupportsNil: Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure SetKnowsSupportsNil(const Value: Boolean); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure SetSupportsNil(const Value: Boolean); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure CalculateSupportsNil; {$IFDEF BOLD_INLINE} inline; {$ENDIF} function GetAssignedIndexCount: integer; + function GetIndexCount: integer; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetCapacity: integer; + procedure SetCapacity(const Value: integer); + function GetIsEmpty: boolean; protected + function GetDebugInfo: string; override; function AddIndex(BoldIndex: TBoldIndex): integer; procedure AddToAllIndexes(Item: TObject); procedure RemoveAndFreeIndex(var BoldIndex: TBoldIndex; DestroyObjects: Boolean); @@ -75,19 +84,23 @@ TBoldUnOrderedIndexableList = class(TBoldNonRefCountedObject) procedure ItemChanged(Item: TObject); procedure Remove(Item: TObject); function CreateTraverser: TBoldIndexableListTraverser; + function GetEnumerator: TBoldIndexableListTraverser; property Count: integer read GetCount; property Any: TObject read GetAny; property OwnsEntries: boolean read GetOwnsEntries write SetOwnsEntries; + property Capacity: integer read GetCapacity write SetCapacity; + property IsEmpty: boolean read GetIsEmpty; end; TBoldIndexableList = class(TBoldUnOrderedIndexableList) private fIndexIndex: TBoldIntegerIndex; - function GetItem(Index: integer): TObject; + function GetItem(Index: integer): TObject; {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure SetItem(Index: integer; value: TObject); procedure AddToAllNonOrderedIndexes(item: TObject); procedure RemoveFromAllNonOrderedIndexes(item: TObject); - function GetUnorderedIndexCount: integer; + function GetUnorderedIndexCount: integer; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure _DebugInfo(Index: Integer); protected property Items[I: Integer]: TObject read GetItem write SetItem; property UnorderedIndexCount: integer read GetUnorderedIndexCount; @@ -95,10 +108,12 @@ TBoldIndexableList = class(TBoldUnOrderedIndexableList) constructor Create; procedure Move(CurIndex, NewIndex: Integer); procedure RemoveByIndex(Index: Integer); - procedure Sort(Compare: TListSortCompare); + procedure Sort(Compare: TIntegerIndexSortCompare); procedure Exchange(Index1, Index2: integer); - function IndexOf(Item: TObject): integer; + function IndexOf(Item: TObject): integer; {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure Insert(Index: Integer; Item: TObject); + function Includes(Item: TObject): boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure RemoveList(AList: TBoldIndexableList); end; @@ -107,13 +122,9 @@ procedure SetIndexVariable(var Index: integer; GivenPosition: integer); implementation uses - BoldCommonConst, SysUtils, BoldDefs; -const - DEFAULTINDEXCAPACITY = 1; - procedure SetIndexVariable(var Index: integer; GivenPosition: integer); begin assert((index = -1) or (index = GivenPosition), 'Erroneous index construction, please debug!'); @@ -121,9 +132,113 @@ procedure SetIndexVariable(var Index: integer; GivenPosition: integer); end; { TBoldUnOrderedIndexableList } + +function TBoldUnOrderedIndexableList.GetIndex(Index: Integer): TBoldIndex; +begin + Result := FIndexes[Index] +end; + +procedure TBoldUnOrderedIndexableList.SetSupportsNil(const Value: Boolean); +begin + if value then + Include(fOptions, iloSupportsNil) + else + Exclude(fOptions, iloSupportsNil); +end; + +function TBoldUnOrderedIndexableList.GetKnowsSupportsNil: Boolean; +begin + result := iloKnowsSupportsNil in fOptions; +end; + +procedure TBoldUnOrderedIndexableList.SetKnowsSupportsNil( + const Value: Boolean); +begin + if value then + Include(fOptions, iloKnowsSupportsNil) + else + Exclude(fOptions, iloKnowsSupportsNil); +end; + +function TBoldUnOrderedIndexableList.GetIndexCount: integer; +begin + Result := Length(fIndexes); +end; + +function TBoldUnOrderedIndexableList.GetIsEmpty: boolean; +begin + result := Count = 0; +end; + +function TBoldUnOrderedIndexableList.FirstNilSupportingIndex: TBoldIndex; +var + i: integer; +begin + if fFirstNilSupportingIndex > -1 then begin + result := Indexes[fFirstNilSupportingIndex]; + end else begin + result := nil; + for i := 0 to IndexCount-1 do + if Assigned(Indexes[i]) and Indexes[i].SupportsNilItems then + begin + result := Indexes[i]; + fFirstNilSupportingIndex := i; + break; + end; + end; +end; + +procedure TBoldUnOrderedIndexableList.CalculateSupportsNil; +begin + SupportsNil := FirstNilSupportingIndex <> nil; + KnowsSupportsNil := true; +end; + +function TBoldUnOrderedIndexableList.GetSupportsNil: Boolean; +begin + if not knowsSupportsNil then + CalculateSupportsNil; + result := iloSupportsNil in fOptions; +end; + +procedure TBoldIndexableList._DebugInfo(Index: Integer); +var + Info: string; + I: Integer; +begin + Info := Format('GetItem(%d): Self.Classname:%s Count:%d fIndexIndex.Count:%d SupportsNil:%s IndexCount:%d'#13#10, [Index, Classname, Count, fIndexIndex.Count, BoolToStr(SupportsNil, True), IndexCount]); + for i := 0 to IndexCount-1 do + if Assigned(Indexes[i]) then + Info := Info+Format('Indexes[%d] Classname:%s Count:%d SupportsNilItems:%s '#13#10, [I, Indexes[i].ClassName, Indexes[i].Count, BoolToStr(Indexes[i].SupportsNilItems, True)]) + else + Info := Info+Format('Indexes[%d] = nil '#13#10, [I]); +// asm nop; end; //Breakpoint here! +end; + +function TBoldIndexableList.GetItem(Index: integer): TObject; +begin + if (index < 0) or (index>=fIndexIndex.FastCount) then + raise EBold.CreateFmt('%s.GetItem: Index %d out of bounds, count is %d', [classname, Index, fIndexIndex.FastCount]);//_DebugInfo(Index); + Result := fIndexIndex.items[index]; +end; + +function TBoldUnOrderedIndexableList.GetOwnsEntries: boolean; +begin + result := iloOwnsEntries in fOptions; +end; + +procedure TBoldUnOrderedIndexableList.SetOwnsEntries(const Value: boolean); +begin + if value then + Include(fOptions, iloOwnsEntries) + else + Exclude(fOptions, iloOwnsEntries); +end; + constructor TBoldUnOrderedIndexableList.Create; begin inherited; + fFirstNilSupportingIndex := -1; OwnsEntries := True; SupportsNil := false; KnowsSupportsNil := true; @@ -147,11 +262,28 @@ destructor TBoldUnOrderedIndexableList.Destroy; dec(IndicesToGo); end; end; - - FreeAndNil(fIndexes); inherited; end; +function TBoldUnOrderedIndexableList.GetCapacity: integer; +var + i: integer; +begin + result := MaxInt; + for i := 0 to IndexCount - 1 do + if Assigned(Indexes[i]) and (Indexes[i].Capacity < result) then + result := Indexes[i].Capacity; +end; + +procedure TBoldUnOrderedIndexableList.SetCapacity(const Value: integer); +var + i: integer; +begin + for i := 0 to IndexCount - 1 do + if Assigned(Indexes[i]) then + Indexes[i].Capacity := Value; +end; + function TBoldUnOrderedIndexableList.GetCount: Integer; begin if IndexCount > 0 then @@ -165,30 +297,18 @@ function TBoldUnOrderedIndexableList.GetCount: Integer; Result := 0; end; - -function TBoldUnOrderedIndexableList.GetIndex(Index: Integer): TBoldIndex; -begin - if Assigned(fIndexes) then - Result := TBoldIndex(FIndexes[Index]) - else - Result := nil; -end; - -function TBoldUnOrderedIndexableList.GetIndexCount: Integer; +function TBoldUnOrderedIndexableList.GetDebugInfo: string; begin - if Assigned(fIndexes) then - Result := FIndexes.Count - else - Result := 0; + result := Format('%s.count=%d', [ClassName, count]); end; function TBoldUnOrderedIndexableList.AddIndex(BoldIndex: TBoldIndex): integer; var SourceIndex: TBoldIndex; begin - if not Assigned(fIndexes) then - SetIndexCapacity(DEFAULTINDEXCAPACITY); - Result := FIndexes.Add(BoldIndex); + Result := IndexCount; + SetLength(fIndexes, Result+1); + fIndexes[Result] := BoldIndex; if IndexCount > 1 then begin SourceIndex := FirstNilSupportingIndex; @@ -204,9 +324,11 @@ function TBoldUnOrderedIndexableList.AddIndex(BoldIndex: TBoldIndex): integer; end; procedure TBoldUnOrderedIndexableList.RemoveAndFreeIndex(var BoldIndex: TBoldIndex; DestroyObjects: Boolean); +var + i: Integer; begin if not (ilodestroying in fOptions) and (AssignedIndexCount = 1) then - raise EBold.CreateFmt(sCannotRemoveLastIndex, [classname]); + raise EBold.CreateFmt('%s.RemoveAndfreeIndex: Can not remove the last index unless during destruction', [classname]); if Assigned(BoldIndex) then begin if BoldIndex.SupportsNilItems then @@ -214,23 +336,27 @@ procedure TBoldUnOrderedIndexableList.RemoveAndFreeIndex(var BoldIndex: TBoldInd if DestroyObjects then BoldIndex.Clear(DestroyObjects); - fIndexes[fIndexes.IndexOf(BoldIndex)] := nil; + for i := 0 to IndexCount - 1 do + if fIndexes[i] = BoldIndex then + begin + fIndexes[i] := nil; + if i <= fFirstNilSupportingIndex then + fFirstNilSupportingIndex := -1; + break; + end; FreeAndNil(BoldIndex); end; end; procedure TBoldUnOrderedIndexableList.SetIndexCapacity(NewCapacity: integer); begin - if not Assigned(fIndexes) then - fIndexes := TList.Create; - fIndexes.Capacity := NewCapacity; + // No longer used end; procedure TBoldUnOrderedIndexableList.AddToAllIndexes(Item: TObject); var i: integer; begin - // ordered indexes must get nil-pointers too. for i := 0 to IndexCount-1 do if Assigned(Indexes[i]) then Indexes[i].Add(Item); @@ -247,9 +373,15 @@ procedure TBoldUnOrderedIndexableList.RemoveFromAllIndexes(Item: TObject); end; procedure TBoldUnOrderedIndexableList.Add(Item: TObject); + + procedure InternalRaise; + begin + raise EBold.CreateFmt('%s.Add(nil): This list does not support nil-pointers', [ClassName]); + end; + begin if not assigned(item) and not SupportsNil then - raise EBold.CreateFmt(sNilPointersNotSupported, [ClassName]); + InternalRaise; AddToAllIndexes(Item); end; @@ -276,8 +408,9 @@ procedure TBoldUnOrderedIndexableList.Clear; i: Integer; IndicesToGo: integer; begin + if count = 0 then + exit; IndicesToGo := AssignedIndexCount; - // if we own the entries, remove them with the last index to be removed. for i := 0 to IndexCount-1 do if assigned(Indexes[i]) then begin @@ -288,20 +421,20 @@ procedure TBoldUnOrderedIndexableList.Clear; procedure TBoldUnOrderedIndexableList.SetIndex(I: Integer; const Value: TBoldIndex); begin - if assigned(fIndexes) then + if value.Count <> 0 then + raise EBold.CreateFmt('%s.SetIndex: Can not set an index that is not empty (%s)', [ClassName, value.ClassName]); + if Assigned(fIndexes[i]) and TBoldIndex(fIndexes[i]).SupportsNilItems then + KnowsSupportsNil := false; + fIndexes[i] := Value; + if Value.SupportsNilItems then begin - if value.Count <> 0 then - raise EBold.CreateFmt(sCannotSetNonEmptyIndex, [ClassName, value.ClassName]); - fIndexes[i] := Value; - if Value.SupportsNilItems then - begin - SupportsNil := true; - KnowsSupportsNil := true; - end; - if AssignedIndexCount > 1 then - FirstAssignedIndex.FillEmptyIndex(Value); -// AddAllToIndex(Value); + SupportsNil := true; + KnowsSupportsNil := true; end; + if i >= fFirstNilSupportingIndex then + fFirstNilSupportingIndex := -1; + if AssignedIndexCount > 1 then + FirstAssignedIndex.FillEmptyIndex(Value); end; function TBoldUnOrderedIndexableList.GetAny: TObject; @@ -310,33 +443,16 @@ function TBoldUnOrderedIndexableList.GetAny: TObject; result := FirstAssignedIndex.Any else result := nil - -end; - -function TBoldUnOrderedIndexableList.GetOwnsEntries: boolean; -begin - result := iloOwnsEntries in fOptions; -end; - -procedure TBoldUnOrderedIndexableList.SetOwnsEntries(const Value: boolean); -begin - if value then - Include(fOptions, iloOwnsEntries) - else - Exclude(fOptions, iloOwnsEntries); end; { TBoldUnOrderedIndexableList } -function TBoldIndexableList.GetItem(Index: integer): TObject; -begin - Result := fIndexIndex.items[index]; -end; - procedure TBoldIndexableList.RemoveByIndex(Index: Integer); var Item: Tobject; begin + if (index < 0) or (index>=fIndexIndex.FastCount) then + raise EBold.CreateFmt('%s.RemoveByIndex: Index %d out of bounds, count is %d', [classname, Index, fIndexIndex.FastCount]);//_DebugInfo(Index); Item := fIndexIndex.Items[Index]; RemoveFromAllNonOrderedIndexes(Item); fIndexIndex.RemoveByIndex(Index); @@ -353,6 +469,10 @@ procedure TBoldIndexableList.SetItem(Index: integer; value: TObject); var temp: TObject; begin + if (index < 0) or (index>=fIndexIndex.FastCount) then + raise EBold.CreateFmt('%s.SetItem: Index %d out of bounds, count is %d', [classname, Index, fIndexIndex.FastCount]);//_DebugInfo(Index); + if Value = fIndexIndex.items[index] then + exit; RemoveFromAllNonOrderedIndexes(fIndexIndex.items[index]); if OwnsEntries then @@ -369,6 +489,8 @@ procedure TBoldIndexableList.SetItem(Index: integer; value: TObject); procedure TBoldIndexableList.Insert(Index: Integer; Item: TObject); begin + if (index < 0) or (index>fIndexIndex.FastCount) then + raise EBold.CreateFmt('%s.Insert: Index %d out of bounds, count is %d', [classname, Index, fIndexIndex.FastCount]);//_DebugInfo(Index); fIndexIndex.Insert(Index, Item); AddToAllNonOrderedIndexes(item); end; @@ -378,12 +500,17 @@ function TBoldIndexableList.IndexOf(Item: TObject): integer; result := fIndexIndex.IndexOf(Item); end; +function TBoldIndexableList.Includes(Item: TObject): boolean; +begin + result := IndexOf(Item) <> -1; +end; + procedure TBoldIndexableList.Exchange(Index1, Index2: integer); begin fIndexIndex.Exchange(Index1, Index2); end; -procedure TBoldIndexableList.Sort(Compare: TListSortCompare); +procedure TBoldIndexableList.Sort(Compare: TIntegerIndexSortCompare); begin fIndexIndex.Sort(Compare); end; @@ -415,6 +542,18 @@ procedure TBoldIndexableList.RemoveFromAllNonOrderedIndexes(item: TObject); Indexes[i].Remove(item); end; +procedure TBoldIndexableList.RemoveList(AList: TBoldIndexableList); +var + i,j: integer; +begin + for I := 0 to AList.Count - 1 do + begin + j := IndexOf(AList.Items[i]); + if j <> -1 then + self.RemoveByIndex(j); + end; +end; + function TBoldIndexableList.GetUnorderedIndexCount: integer; begin result := IndexCount-1; @@ -433,58 +572,14 @@ function TBoldUnOrderedIndexableList.CreateTraverser: TBoldIndexableListTraverse end; end; - -function TBoldUnOrderedIndexableList.TraverserClass: TBoldIndexableListTraverserClass; +function TBoldUnOrderedIndexableList.GetEnumerator: TBoldIndexableListTraverser; begin - result := TBoldIndexableListTraverser; + result := CreateTraverser; end; -function TBoldUnOrderedIndexableList.FirstNilSupportingIndex: TBoldIndex; -var - i: integer; -begin - result := nil; - for i := 0 to IndexCount-1 do - if Assigned(Indexes[i]) and Indexes[i].SupportsNilItems then - begin - result := Indexes[i]; - break; - end; -end; - -function TBoldUnOrderedIndexableList.GetKnowsSupportsNil: Boolean; -begin - result := iloKnowsSupportsNil in fOptions; -end; - -function TBoldUnOrderedIndexableList.GetSupportsNil: Boolean; -begin - if not KnowsSupportsNil then - CalculateSupportsNil; - result := iloSupportsNil in fOptions; -end; - -procedure TBoldUnOrderedIndexableList.SetKnowsSupportsNil( - const Value: Boolean); -begin - if value then - Include(fOptions, iloKnowsSupportsNil) - else - Exclude(fOptions, iloKnowsSupportsNil); -end; - -procedure TBoldUnOrderedIndexableList.SetSupportsNil(const Value: Boolean); -begin - if value then - Include(fOptions, iloSupportsNil) - else - Exclude(fOptions, iloSupportsNil); -end; - -procedure TBoldUnOrderedIndexableList.CalculateSupportsNil; +function TBoldUnOrderedIndexableList.TraverserClass: TBoldIndexableListTraverserClass; begin - SupportsNil := FirstNilSupportingIndex <> nil; - KnowsSupportsNil := true; + result := TBoldIndexableListTraverser; end; function TBoldUnOrderedIndexableList.GetAssignedIndexCount: integer; @@ -525,10 +620,15 @@ destructor TBoldIndexableListTraverser.Destroy; FreeAndNil(fIndexTraverser); end; +function TBoldIndexableListTraverser.GetAutoMoveOnRemoveCurrent: boolean; +begin + result := fIndexTraverser.AutoMoveOnRemoveCurrent; +end; -function TBoldIndexableListTraverser.GetEol: Boolean; +procedure TBoldIndexableListTraverser.SetAutoMoveOnRemoveCurrent( + const Value: boolean); begin - result := fIndexTraverser.EndOfList; + fIndexTraverser.AutoMoveOnRemoveCurrent := Value; end; function TBoldIndexableListTraverser.GetItem: TObject; @@ -536,10 +636,11 @@ function TBoldIndexableListTraverser.GetItem: TObject; result := fIndexTraverser.Item; end; -procedure TBoldIndexableListTraverser.Next; +function TBoldIndexableListTraverser.MoveNext: Boolean; begin - fIndexTraverser.Next; - Inc(fCurrentIndex); + result := fIndexTraverser.MoveNext; end; +initialization + end. diff --git a/Source/Common/Support/BoldIsoDateTime.pas b/Source/Common/Support/BoldIsoDateTime.pas index 884b86a..e0dd644 100644 --- a/Source/Common/Support/BoldIsoDateTime.pas +++ b/Source/Common/Support/BoldIsoDateTime.pas @@ -1,22 +1,43 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldIsoDateTime; interface uses - BoldDefs; + BoldDefs, + Controls; // for TDate + +function ParseISODate(const s: string): TDateTime; +function ParseISODateTime(const s: string): TDateTime; +function ParseISOTime(const str: string): TDateTime; + +function AsISODateTime(d: TDateTime): string; +function AsISODate(d: TDate): string; +function AsISOTime(t: TTime): string; -function ParseISODate(s: string): TDateTime; -function ParseISODateTime(s: string): TDateTime; -function ParseISOTime(str: string): TDateTime; +function AsISODateTimeMS(d: TDateTime): string; +function AsISOTimeMS(t: TTime): string; + +const + cIsoDateFormat = 'yyyy-mm-dd'; + cIsoTimeFormat = 'hh:mm:ss'; + cIsoTimeFormatMS = 'hh:mm:ss:zzz'; + cIsoDateTimeSeparator = 'T'; + cIsoDateTimeFormat = cIsoDateFormat + '"' + cIsoDateTimeSeparator + '"' + cIsoTimeFormat; // '2018-12-31T11:50:00'; + cIsoDateTimeFormatMS = cIsoDateFormat + '"' + cIsoDateTimeSeparator + '"' + cIsoTimeFormatMS; // '2018-12-31T11:50:00:123'; implementation uses SysUtils, - BoldUtils, - BoldSupportConst; + BoldUtils; + +var + FormatSettings: TFormatSettings; -function MatchPattern(pattern, s: string): boolean; +function MatchPattern(const pattern, s: string): boolean; var i: integer; begin @@ -24,12 +45,12 @@ function MatchPattern(pattern, s: string): boolean; if result then for i := 1 to length(pattern) do case pattern[i] of - '#': result := result and (s[i] in ['0'..'9']); + '#': result := result and CharInSet(s[i], ['0'..'9']); else result := result and (s[i] = pattern[i]); end; end; -function ParseISODate(s: string): TDateTime; +function ParseISODate(const s: string): TDateTime; var y, m, d: integer; const @@ -37,44 +58,81 @@ function ParseISODate(s: string): TDateTime; 31, 31, 30, 31, 30, 31); begin if not MatchPattern('####-##-##', s) then - raise EBold.CreateFmt(sInvalidDateFormatFormat, [s]); + raise EBold.CreateFmt('ParseISODate: Invalid date format %s. Should be YYYY-MM-DD', [s]); y := StrToInt(copy(s, 1, 4)); m := StrToInt(copy(s, 6, 2)); if m > 12 then - raise EBold.CreateFmt(sInnvalidDateFormatLargeMonth, [s]); + raise EBold.CreateFmt('ParseISODate: Invalid date format %s. month > 12', [s]); if m < 1 then - raise EBold.CreateFmt(sInvalidDateFormatSmallMonth, [s]); + raise EBold.CreateFmt('ParseISODate: Invalid date format %s. month < 1', [s]); d := StrToInt(copy(s, 9, 2)); if d < 1 then - raise EBold.CreateFmt(sInvalidDateFormatSmallDay, [s]); + raise EBold.CreateFmt('ParseISODate: Invalid date format %s. date < 1', [s]); if d > dayspermonth[m] then - raise EBold.CreateFmt(sInvalidDateFormatBadDay, [s, daysPerMonth[m], m]); + raise EBold.CreateFmt('ParseISODate: Invalid date format %s. there is only %d days in month %d', [s, daysPerMonth[m], m]); result := EncodeDate(y, m, d); end; -function ParseISODateTime(s: string): TDateTime; +function ParseISODateTime(const s: string): TDateTime; begin - if not matchPattern('####-##-## ##:##', s) and not matchPattern('####-##-## ##:##:##', s) then - raise EBold.CreateFmt(sInvalidDateTimeFormat, [s]); - result := ParseIsoDate(copy(s, 1, 10)) + ParseIsoTime(copy(s, 12, 8)); + if not matchPattern('####-##-## ##:##', s) + and not matchPattern('####-##-## ##:##:##', s) + and not matchPattern('####-##-## ##:##:##:###', s) + and not matchPattern('####-##-##T##:##:##:###', s) then + raise EBold.CreateFmt('ParseISODateTime: Invalid datatime format %s. Should be YYYY-MM-DD HH:MM[:SS][:ZZZ]', [s]); + result := ParseIsoDate(copy(s, 1, 10)) + ParseIsoTime(copy(s, 12, MaxInt)); end; -function ParseISOTime(str: string): TDateTime; +function ParseISOTime(const str: string): TDateTime; var - h, m, s: integer; + h, m, s, z: integer; begin - if not MatchPattern('##:##:##', str) and not MatchPattern('##:##', str) then - raise EBold.CreateFmt(sInvalidTimeFormat, [str]); + if not MatchPattern('##:##:##:###', str) + and not MatchPattern('##:##:##.###', str) + and not MatchPattern('##:##:##', str) + and not MatchPattern('##:##', str) then + raise EBold.CreateFmt('ParseISOTime: Invalid time format %s. Should be HH:MM[:SS:ZZZ]', [str]); h := StrToInt(copy(str, 1, 2)); if h > 23 then - raise EBold.CreateFmt(sInvalidTimeFormatLargeHour, [str]); + raise EBold.CreateFmt('ParseISODate: Invalid date format %s. h > 23', [str]); m := StrToInt(copy(str, 4, 2)); if m > 59 then - raise EBold.CreateFmt(sInvalidTimeFormatLargeMinute, [str]); + raise EBold.CreateFmt('ParseISODate: Invalid date format %s. m > 59', [str]); s := StrToInt(copy(str, 7, 2)); if s > 59 then - raise EBold.CreateFmt(sInvalidTimeFormatLargeSecond, [str]); - result := EncodeTime(h, m, s, 0); + raise EBold.CreateFmt('ParseISODate: Invalid date format %s. s > 59', [str]); + z := StrToIntDef(copy(str, 10, 3),0); + result := EncodeTime(h, m, s, z); +end; + +function AsISODateTime(d: TDateTime): string; +begin + result := formatDateTime(cIsoDateTimeFormat, d, FormatSettings); end; +function AsISODate(d: TDate): string; +begin + result := formatDateTime(cIsoDateFormat, d, FormatSettings); +end; + +function AsISOTime(t: TTime): string; +begin + result := formatDateTime(cIsoTimeFormat, t, FormatSettings); +end; + +function AsISODateTimeMS(d: TDateTime): string; +begin + result := formatDateTime(cIsoDateTimeFormatMS, d, FormatSettings); +end; + +function AsISOTimeMS(t: TTime): string; +begin + result := formatDateTime(cIsoTimeFormatMS, t, FormatSettings); +end; + +initialization + FormatSettings := TFormatSettings.Create; + FormatSettings.DateSeparator := '-'; + FormatSettings.TimeSeparator := ':' + end. diff --git a/Source/Common/Support/BoldLoggableCriticalSection.pas b/Source/Common/Support/BoldLoggableCriticalSection.pas index 22034a4..f07153d 100644 --- a/Source/Common/Support/BoldLoggableCriticalSection.pas +++ b/Source/Common/Support/BoldLoggableCriticalSection.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldLoggableCriticalSection; interface @@ -6,11 +9,8 @@ interface SyncObjs, BoldThreadSafeLog; -type - { forward declarations } - TBoldLoggableCriticalSection = class; - { TBoldLoggableCriticalSection } +type TBoldLoggableCriticalSection = class(TCriticalSection) private fName: String; @@ -21,15 +21,15 @@ TBoldLoggableCriticalSection = class(TCriticalSection) end; implementation - uses - SysUtils; + SysUtils, + BoldRev; { TBoldLoggableCriticalSection } procedure TBoldLoggableCriticalSection.Acquire; begin - BoldLogThread('L='+fName); // do not localize + BoldLogThread('L='+fName); inherited; end; @@ -42,7 +42,8 @@ constructor TBoldLoggableCriticalSection.Create(name: string); procedure TBoldLoggableCriticalSection.Release; begin inherited; - BoldLogThread('U=' + fName); // do not localize + BoldLogThread('U=' + fName); end; +initialization end. diff --git a/Source/Common/Support/BoldMath.pas b/Source/Common/Support/BoldMath.pas index b689d7f..e2f3af8 100644 --- a/Source/Common/Support/BoldMath.pas +++ b/Source/Common/Support/BoldMath.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldMath; interface @@ -11,8 +14,7 @@ function MinIntValue(const Data: array of Integer): Integer; implementation uses - SysUtils, - BoldUtils; + BoldRev; function Floor(X: Extended): Integer; begin @@ -62,4 +64,6 @@ function MinIntValue(const Data: array of Integer): Integer; Result := Data[I]; end; +initialization + end. diff --git a/Source/Common/Support/BoldMemoryManager.pas b/Source/Common/Support/BoldMemoryManager.pas index 2ff6aee..52ffa3a 100644 --- a/Source/Common/Support/BoldMemoryManager.pas +++ b/Source/Common/Support/BoldMemoryManager.pas @@ -1,3 +1,7 @@ +///////////////////////////////////////////////////////// + +{ Global compiler directives } +{$include bold.inc} unit BoldMemoryManager; interface @@ -32,10 +36,13 @@ class function T.NewInstance: TObject; ---------------------------------------------------------------------*) -{.$DEFINE DEBUG} +{.$DEFINE DEBUG_BOLDMEMORYMANAGER} +// Define this conditional, if your application maybe uses only one thread. +// Normaly every application is multithreaded and the check is waste. +{.$DEFINE CHECK_ISMULTITHREAD} uses - {$IFDEF DEBUG} + {$IFDEF DEBUG_BOLDMEMORYMANAGER} // Dialogs, {$ENDIF} BoldDefs, @@ -43,13 +50,27 @@ class function T.NewInstance: TObject; Classes; const - BoldMemoryManagerPageSize = 256; + BoldMemoryManagerPageSize = 2048; BoldMemoryManagerLSBZero = 2; {//} BoldMemoryManagerLSBFactor = (1 shl BoldMemoryManagerLSBZero); BoldMemoryManagerMaxPage = 16; // memoryblocks with 4*MaxPage will be handled, must be power of 2 {//} BoldMemoryManagerMask = ((1 shl BoldMemoryManagerLSBZero)-1) or (not Cardinal((BoldMemoryManagerMaxPage shl BoldMemoryManagerLSBZero)-1)); // mask for quick test of allowed size +// Temporarly moved from BoldCommonConst + sMemoryManagerCalledInFinalization = 'Attempt to allocate with BoldMemoryManager during finalization'; + sMemoryManagerDestroyed = 'MemoryManager destroyed'; + sMemMgrSize = 'Size: %3d InUse: %10d(%4.0f%%) Free: %10d'; + sMemMgrAllocated = 'Allocated'; + sMemMgrInUse = 'InUse'; + sMemMgrOverHead = 'Overhead'; + sMemMgrDisabled = 'The Bold Memorymanager has been disabled. '; + sMemMgrDisabledReason = '(caused by compilerdirective BOLD_DISABLEMEMORYMANAGER)'; + sMemMgrTotalBigBlocks = 'Total Big blks'; + sMemMgrBigBlockCount = 'Big block count'; + sMemMgrNonBold = 'Non-Bold'; + sMemMgrNonBoldCount = 'Non-Bold Count'; + type { forward declarations } TBoldMemoryManager = class; @@ -71,13 +92,13 @@ TBoldMemoryManager = class fBigBlockCount: integer; fCriticalSection: TCriticalSection; {$IFNDEF BOLD_DISABLEMEMORYMANAGER} - procedure AllocateNewPage(Size, PageNum: integer); + procedure AllocateNewPage(Size: integer); procedure GarbageCollectPage(PageNum: integer; Page: Pointer; PageSize: integer); procedure LinkIn(var Chain: Pointer; Item: POinter); function LinkOut(var Chain: Pointer): Pointer; {$ENDIF} function GetAllocated: integer; - function GetMemoryInfo: String; + function GetMemoryInfo: string; function GetOverhead: integer; function GetInUse: integer; function GetAllocatedPages: integer; @@ -106,10 +127,9 @@ function BoldMemoryManager_: TBoldMemoryManager; implementation uses - SysUtils, - BoldCommonConst; + SysUtils, Types; -{$IFDEF DEBUG} +{$IFDEF DEBUG_BOLDMEMORYMANAGER} const LOGFILE: string = 'c:\temp\BoldMemoryManager.Log'; @@ -120,7 +140,7 @@ implementation procedure Log(const Str: String); begin - {$IFDEF DEBUG} + {$IFDEF DEBUG_BOLDMEMORYMANAGER} if not assigned(Strl) then begin strl := TStringList.Create; @@ -144,20 +164,18 @@ procedure Log(const Str: String); procedure DestroyIfEmpty; begin - if Assigned(G_BoldMemoryManager) and (G_BoldMemoryManager.InUse = 0) then - FreeAndNil(G_BoldMemoryManager); + if Assigned(G_BoldMemoryManager) and (G_BoldMemoryManager.InUse = 0) then + FreeAndNil(G_BoldMemoryManager); end; function BoldMemoryManager_: TBoldMemoryManager; begin - Result := G_BoldMemoryManager; - if not assigned(Result) then - begin + if G_BoldMemoryManager = nil then begin if Finalized then raise EBold.Create(sMemoryManagerCalledInFinalization); - Result := TBoldMemoryManager.Create; - G_BoldMemoryManager := Result; + G_BoldMemoryManager := TBoldMemoryManager.Create; end; + Result := G_BoldMemoryManager; end; @@ -176,7 +194,7 @@ function TBoldMemoryManager.LinkOut(var Chain: Pointer): Pointer; Chain := Pointer(result^); end; -procedure TBoldMemoryManager.AllocateNewPage(Size, PageNum: integer); +procedure TBoldMemoryManager.AllocateNewPage(Size: integer); var i: integer; Page: ^TPage; @@ -186,7 +204,7 @@ procedure TBoldMemoryManager.AllocateNewPage(Size, PageNum: integer); Pages.Add(Page); PageSizes.Add(Pointer(Size * BoldMemoryManagerPageSize)); SizeInWords := Size shr BoldMemoryManagerLSBZero; - {$IFDEF DEBUG} + {$IFDEF DEBUG_BOLDMEMORYMANAGER} FillChar(Page^, Size * BoldMemoryManagerPageSize, 0); {$ENDIF} for i := 0 to BoldMemoryManagerPageSize-2 do @@ -195,9 +213,9 @@ procedure TBoldMemoryManager.AllocateNewPage(Size, PageNum: integer); end; Page^[(BoldMemoryManagerPageSize-1) * sizeInWords] := nil; - FreePointers[PageNum] := Page; + FreePointers[Size] := Page; - Inc(TotalAllocated[Pagenum], BoldMemoryManagerPageSize); + Inc(TotalAllocated[Size], BoldMemoryManagerPageSize); end; procedure TBoldMemoryManager.GarbageCollectPage(PageNum: integer; Page: Pointer; PageSize: integer); @@ -244,12 +262,16 @@ function TBoldMemoryManager.GetOverhead: integer; var i: integer; begin + {$IFDEF CHECK_ISMULTITHREAD} if (IsMultiThread) then + {$ENDIF} fCriticalSection.Acquire; result := 0; for i := Low(TotalAllocated) to High(TotalAllocated) do result := result + (TotalAllocated[i] - CurrentInUse[i]) * i; + {$IFDEF CHECK_ISMULTITHREAD} if (IsMultiThread) then + {$ENDIF} fCriticalSection.Leave; end; @@ -257,12 +279,16 @@ function TBoldMemoryManager.GetInUse: integer; var i: integer; begin + {$IFDEF CHECK_ISMULTITHREAD} if (IsMultiThread) then + {$ENDIF} fCriticalSection.Acquire; result := 0; for i := Low(CurrentInUse) to High(CurrentInUse) do result := result + CurrentInUse[i] * i; + {$IFDEF CHECK_ISMULTITHREAD} if (IsMultiThread) then + {$ENDIF} fCriticalSection.Leave; end; @@ -277,7 +303,9 @@ function TBoldMemoryManager.AllocateMemory(Size: integer): Pointer; INC(fBigBlockCount); {$ELSE} // Note, ordering and code repetition intentional, to give best operaion pairing. + {$IFDEF CHECK_ISMULTITHREAD} if (IsMultiThread) then + {$ENDIF} fCriticalSection.Acquire; if ((Size and BoldMemoryManagerMask) = 0) then begin @@ -289,11 +317,11 @@ function TBoldMemoryManager.AllocateMemory(Size: integer): Pointer; if assigned(result) then begin Inc(CurrentInUse[Size]); - FreePointers[Size] := Pointer(result^); + FreePointers[Size] := Pointer(result^); end else begin - AllocateNewPage(Size, Size); + AllocateNewPage(Size); result := FreePointers[Size]; Inc(CurrentInUse[Size]); FreePointers[Size] := Pointer(result^); @@ -302,11 +330,15 @@ function TBoldMemoryManager.AllocateMemory(Size: integer): Pointer; end else begin + {$IFDEF DEBUG_BOLDMEMORYMANAGER} BytesInBigBlocks := BytesInBigBlocks + size; INC(fBigBlockCount); + {$ENDIF} getMem(result, Size); end; + {$IFDEF CHECK_ISMULTITHREAD} if (IsMultiThread) then + {$ENDIF} fCriticalSection.Leave; {$ENDIF} end; @@ -319,7 +351,9 @@ procedure TBoldMemoryManager.DeAllocateMemory(Ptr: Pointer; Size: integer); if fBigBlockCount = 0 then FreeAndNil(G_BoldMemoryManager); {$ELSE} + {$IFDEF CHECK_ISMULTITHREAD} if (IsMultiThread) then + {$ENDIF} fCriticalSection.Acquire; if ((Size and BoldMemoryManagerMask) = 0) then begin @@ -335,11 +369,15 @@ procedure TBoldMemoryManager.DeAllocateMemory(Ptr: Pointer; Size: integer); end else begin + {$IFDEF DEBUG_BOLDMEMORYMANAGER} BytesInBigBlocks := BytesInBigBlocks - size; DEC(fBigBlockCount); + {$ENDIF} Freemem(Ptr, size); end; + {$IFDEF CHECK_ISMULTITHREAD} if (IsMultiThread) then + {$ENDIF} fCriticalSection.Leave {$ENDIF} end; @@ -351,7 +389,9 @@ procedure TBoldMemoryManager.GarbageCollect; {$ENDIF} begin {$IFNDEF BOLD_DISABLEMEMORYMANAGER} + {$IFDEF CHECK_ISMULTITHREAD} if (IsMultiThread) then + {$ENDIF} fCriticalSection.Acquire; for PageNum := Low(TotalAllocated) to High(TotalAllocated) do begin @@ -366,7 +406,9 @@ procedure TBoldMemoryManager.GarbageCollect; end; end; end; + {$IFDEF CHECK_ISMULTITHREAD} if (IsMultiThread) then + {$ENDIF} fCriticalSection.Leave; {$ENDIF} end; @@ -382,7 +424,9 @@ constructor TBoldMemoryManager.Create; destructor TBoldMemoryManager.Destroy; begin + {$IFDEF CHECK_ISMULTITHREAD} if (IsMultiThread) then + {$ENDIF} fCriticalSection.Acquire; while pages.Count > 0 do begin @@ -391,45 +435,73 @@ destructor TBoldMemoryManager.Destroy; end; FreeAndNil(fPages); FreeAndNil(fPageSizes); + {$IFDEF CHECK_ISMULTITHREAD} if (IsMultiThread) then + {$ENDIF} fCriticalSection.Leave; FreeAndNil(fCriticalSection); Log(sMemoryManagerDestroyed); inherited; end; -function TBoldMemoryManager.GetMemoryInfo: String; +function TBoldMemoryManager.GetMemoryInfo: string; {$IFNDEF BOLD_DISABLEMEMORYMANAGER} var - PageNum: integer; + PageNum: Integer; + AllocMemSize, AllocMemCount: Integer; + {$IFDEF BOLD_DELPHI10_OR_LATER} + MemMgrState: TMemoryManagerState; + I: Integer; + {$ENDIF} {$ENDIF} begin - result := ''; + Result := ''; {$IFDEF BOLD_DISABLEMEMORYMANAGER} - result := sMemMgrDisabled + BOLDCRLF + + Result := sMemMgrDisabled + BOLDCRLF + sMemMgrDisabledReason; {$ELSE} + {$IFDEF CHECK_ISMULTITHREAD} if (IsMultiThread) then + {$ENDIF} fCriticalSection.Acquire; - for PageNum := Low(TotalAllocated) to High(TotalAllocated) do - if TotalAllocated[PageNum] <> 0 then - begin - result := result + format(sMemMgrSize, [PageNum, CurrentInUse[PageNum], - (CurrentInUse[PageNum]*100.0*PageNum)/InUse, - TotalAllocated[PageNum] - CurrentInUse[PageNum]]) + BOLDCRLF; + try + for PageNum := Low(TotalAllocated) to High(TotalAllocated) do begin + if TotalAllocated[PageNum] <> 0 then begin + Result := Result + Format(sMemMgrSize, [PageNum, CurrentInUse[PageNum], + (CurrentInUse[PageNum]*100.0*PageNum)/InUse, + TotalAllocated[PageNum] - CurrentInUse[PageNum]]) + BOLDCRLF; + end; end; - result := result + format('%-15s: %7dkb (%10d bytes)', [sMemMgrAllocated, allocated DIV 1024, Allocated]) + BOLDCRLF; // do not localize - result := result + format('%-15s: %7dkb (%10d bytes)', [sMemMgrInUse, InUse DIV 1024, InUse]) + BOLDCRLF; // do not localize - result := result + format('%-15s: %7dkb (%10d bytes)', [sMemMgrOverHead, overhead DIV 1024, overhead]) + BOLDCRLF; // do not localize - if BigBlockCount > 0 then - begin - result := result + format('%-15s: %7dkb (%10d bytes)', [sMemMgrTotalBigBlocks, bytesinbigblocks DIV 1024, bytesinbigblocks]) + BOLDCRLF; // do not localize - result := result + format('%-15s: %7d (%10d bytes)', [sMemMgrBigBlockCount, BigBlockCount, bytesinbigblocks DIV BigBlockCount]) + BOLDCRLF; // do not localize - result := result + format('%-15s: %7dkb (%10d bytes)', [sMemMgrNonBold, (AllocMemSize - allocated-bytesinbigblocks)DIV 1024, (AllocMemSize - allocated-bytesinbigblocks)]) + BOLDCRLF; // do not localize - result := result + format('%-15s: %7d (%10d bytes)', [sMemMgrNonBoldCount, AllocMemCount-BigBlockCount-AllocatedPages, (AllocMemSize - allocated - bytesinbigblocks) DIV (AllocMemCount-BigBlockCount-AllocatedPages)]) + BOLDCRLF; // do not localize + Result := Result + Format('%-15s: %7dkb (%10d bytes)', [sMemMgrAllocated, allocated DIV 1024, Allocated]) + BOLDCRLF; // do not localize + Result := Result + Format('%-15s: %7dkb (%10d bytes)', [sMemMgrInUse, InUse DIV 1024, InUse]) + BOLDCRLF; // do not localize + Result := Result + Format('%-15s: %7dkb (%10d bytes)', [sMemMgrOverHead, overhead DIV 1024, overhead]) + BOLDCRLF; // do not localize + if BigBlockCount > 0 then begin + {$IFDEF BOLD_DELPHI10_OR_LATER} + GetMemoryManagerState(MemMgrState); + AllocMemSize := MemMgrState.TotalAllocatedMediumBlockSize + + MemMgrState.TotalAllocatedLargeBlockSize; + AllocMemCount := MemMgrState.AllocatedMediumBlockCount + + MemMgrState.AllocatedLargeBlockCount; + for I := 0 to High(MemMgrState.SmallBlockTypeStates) do begin + Inc(AllocMemSize, MemMgrState.SmallBlockTypeStates[I].InternalBlockSize + + MemMgrState.SmallBlockTypeStates[I].UseableBlockSize); + Inc(AllocMemCount, MemMgrState.SmallBlockTypeStates[I].AllocatedBlockCount); + end; + {$ELSE} + AllocMemSize := System.AllocMemSize; + AllocMemCount := System.AllocMemCount; + {$ENDIF} + Result := Result + Format('%-15s: %7dkb (%10d bytes)', [sMemMgrTotalBigBlocks, bytesinbigblocks DIV 1024, bytesinbigblocks]) + BOLDCRLF; // do not localize + Result := Result + Format('%-15s: %7d (%10d bytes)', [sMemMgrBigBlockCount, BigBlockCount, bytesinbigblocks DIV BigBlockCount]) + BOLDCRLF; // do not localize + Result := Result + Format('%-15s: %7dkb (%10d bytes)', [sMemMgrNonBold, (AllocMemSize - allocated-bytesinbigblocks)DIV 1024, (AllocMemSize - allocated-bytesinbigblocks)]) + BOLDCRLF; // do not localize + Result := Result + Format('%-15s: %7d (%10d bytes)', [sMemMgrNonBoldCount, AllocMemCount-BigBlockCount-AllocatedPages, (AllocMemSize - allocated - bytesinbigblocks) DIV (AllocMemCount-BigBlockCount-AllocatedPages)]) + BOLDCRLF; // do not localize + end; + finally + {$IFDEF CHECK_ISMULTITHREAD} + if (IsMultiThread) then + {$ENDIF} + fCriticalSection.Leave; end; - if (IsMultiThread) then - fCriticalSection.Leave; {$ENDIF} end; @@ -440,10 +512,14 @@ function TBoldMemoryManager.GetAllocated: integer; function TBoldMemoryManager.GetAllocatedPages: integer; begin + {$IFDEF CHECK_ISMULTITHREAD} if (IsMultiThread) then + {$ENDIF} fCriticalSection.Acquire; Result :=Pages.count; + {$IFDEF CHECK_ISMULTITHREAD} if (IsMultiThread) then + {$ENDIF} fCriticalSection.Leave; end; @@ -458,7 +534,7 @@ function TBoldMemoryManager.ReallocateMemoryZeroFill(Ptr: Pointer; OldSize: inte if NewSize > OldSize then begin Move(Ptr^, Result^, OldSize); - FillChar((Pchar(Result)+Oldsize)^, NewSize-OldSize, 0); + FillChar((PAnsiChar(Result)+Oldsize)^, NewSize-OldSize, 0); end else // NewSize < Oldize Move(Ptr^ , Result^, NewSize); @@ -476,6 +552,7 @@ initialization finalization Finalized := True; DestroyIfEmpty; +{$IFDEF DEBUG_BOLDMEMORYMANAGER} + FreeAndNil(strl); +{$ENDIF} end. - - diff --git a/Source/Common/Support/BoldNamedValueList.pas b/Source/Common/Support/BoldNamedValueList.pas index 54b2487..52b6cfe 100644 --- a/Source/Common/Support/BoldNamedValueList.pas +++ b/Source/Common/Support/BoldNamedValueList.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldNamedValueList; interface @@ -6,7 +9,8 @@ interface Classes, BoldBase, BoldIndexableList, - BoldIndex; + BoldIndex, + BoldHashIndexes; type TBoldNamedValueListEntry = class(TBoldMemoryManagedObject) @@ -23,8 +27,9 @@ TBoldNamedValueListEntry = class(TBoldMemoryManagedObject) TBoldNamedValueList = class(TBoldIndexableList) private + class var IX_Name: integer; function GetItem(index: Integer): TBoldNamedValueListEntry; - function GetItemByName(const Name: string): TBoldNamedValueListEntry; + function GetItemByName(const Name: string): TBoldNamedValueListEntry; {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure SetCommaText(const CommaText: string); function GetCommaText: string; function GetValueByname(const Name: string): string; @@ -35,7 +40,7 @@ TBoldNamedValueList = class(TBoldIndexableList) constructor Create; procedure AddFromStrings(strings: TStrings); procedure AddToStrings(strings: TStrings); - procedure AddEntry(Name, Value: string; aObject: TObject = nil); + function AddEntry(const Name, Value: string; aObject: TObject = nil): TBoldNamedValueListEntry; procedure RemoveName(const Name: String); property Items[index: Integer]: TBoldNamedValueListEntry read GetItem; default; property ItemByName[const Name: string]: TBoldNamedValueListEntry read GetItemByName; @@ -49,14 +54,8 @@ TBoldNamedValueList = class(TBoldIndexableList) implementation uses - SysUtils, - BoldUtils, - BoldHashIndexes; - -var - IX_Name: integer = -1; + BoldRev; - {---TNameIndex---} type TNameIndex = class(TBoldCaseSensitiveStringHashIndex) protected @@ -70,10 +69,10 @@ function TNameIndex.ItemAsKeyString(Item: TObject): string; { TBoldStringDictionary } -procedure TBoldNamedValueList.AddEntry(Name, Value: string; - aObject: TObject); +function TBoldNamedValueList.AddEntry(const Name, Value: string; aObject: TObject): TBoldNamedValueListEntry; begin - Add(TBoldNamedValueListEntry.Create(Name, Value, aObject)); + result := TBoldNamedValueListEntry.Create(Name, Value, aObject); + Add(result); end; procedure TBoldNamedValueList.AddFromStrings(strings: TStrings); @@ -109,7 +108,7 @@ function TBoldNamedValueList.GetCommaText: string; try AddToStrings(StringList); Result := StringList.CommaText; - finally + finally Stringlist.Free; end; end; @@ -123,7 +122,7 @@ function TBoldNamedValueList.GetItem( function TBoldNamedValueList.GetItemByName( const Name: string): TBoldNamedValueListEntry; begin - Result := TBoldNamedValueListEntry(TNameIndex(Indexes[IX_Name]).FindByString(Name)); + Result := TBoldNamedValueListEntry(TBoldCaseSensitiveStringHashIndex(Indexes[IX_Name]).FindByString(Name)); end; @@ -205,4 +204,7 @@ procedure TBoldNamedValueList.SetValueByname(const Name, NewValue: string); AddEntry(Name, NewValue); end; +initialization + TBoldNamedValueList.IX_Name := -1; + end. diff --git a/Source/Common/Support/BoldNavigatorDefs.pas b/Source/Common/Support/BoldNavigatorDefs.pas index dab6319..7f63aaa 100644 --- a/Source/Common/Support/BoldNavigatorDefs.pas +++ b/Source/Common/Support/BoldNavigatorDefs.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldNavigatorDefs; interface @@ -28,7 +31,8 @@ TBoldNavigateBtnImageIndexOwner = class(TCustomPanel) property FocusedButton: TBoldNavigateBtn read fFocusedButton write fFocusedButton; end; - { TBoldNavigateBtnImageIndex } + + { TBoldNavigateBtnImageIndex } TBoldNavigateBtnImageIndex = class(TPersistent) private FnbNext: integer; @@ -49,8 +53,8 @@ TBoldNavigateBtnImageIndex = class(TPersistent) procedure SetnbMoveUp(const Value: integer); procedure SetnbMoveDown(const Value: integer); public - constructor Create(Owner: TBoldNavigateBtnImageIndexOwner); - procedure Assign(Source: TPersistent); override; + constructor create(Owner: TBoldNavigateBtnImageIndexOwner); + procedure assign(Source: TPersistent); override; published property nbFirst: integer read FnbFirst write SetnbFirst; property nbPrior: integer read FnbPrior write SetnbPrior; @@ -84,7 +88,7 @@ implementation uses SysUtils, - BoldUtils; + BoldRev; const InitRepeatPause = 400; { pause before repeat timer (ms)} @@ -226,4 +230,7 @@ procedure TBoldNavButton.Paint; end; end; + + +initialization end. diff --git a/Source/Common/Support/BoldPerformanceCounter.pas b/Source/Common/Support/BoldPerformanceCounter.pas index 07c0e7c..fb69dc6 100644 --- a/Source/Common/Support/BoldPerformanceCounter.pas +++ b/Source/Common/Support/BoldPerformanceCounter.pas @@ -1,13 +1,14 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldPerformanceCounter; interface -// ------------------------------------ -// this unit was originally by OpenInfo, Hasse&Egil -// ------------------------------------ - uses + {$IFDEF MSWINDOWS} Windows, + {$ENDIF} Classes, BoldDefs; @@ -18,38 +19,100 @@ TBoldPerformanceCounter = class; TLargeInteger = longint; {$ENDIF} TBoldPerformanceCounterState = (bpcsStopped, bpcsStarted); + TBoldPerformanceCounterClass = class of TBoldPerformanceCounter; + + TBoldPerformanceData = record + private + fAccumulatedTime: TLargeInteger; + fLastCallTime: Int64; + fStart: TLargeInteger; + fCalls: Int64; + fKernelTime, fUserTime: TFileTime; + fAccumulatedCPUTime: TDateTime; + fLastCallCpuTime: TDateTime; + function GetLastCallSeconds: double; + function GetLastCallAsString: string; + function GetAccumulatedTime: TDateTime; + function GetSeconds: double; + public + procedure Clear; + property LastCallSeconds: double read GetLastCallSeconds; + property LastCallAsString: string read GetLastCallAsString; +// property Calls: Int64 read fCalls; + property AccumulatedTime: TDateTime read GetAccumulatedTime; + property LastCallCpuTime: TDateTime read fLastCallCpuTime; + property AccumulatedCpuTime: TDateTime read fAccumulatedCPUTime; + property Seconds: Double read GetSeconds; + end; { TBoldPerformanceCounter } TBoldPerformanceCounter = class private + fOwnData: TBoldPerformanceData; + fChildrenData: TBoldPerformanceData; fNumberOfChildrenRunning: integer; - fChildren: TStringList; + fChildren: TList; fOwner: TBoldPerformanceCounter; fName: String; - fAccumulatedTime: TLargeInteger; - fStart: TLargeInteger; - fCalls: integer; + fTag: integer; // for user convenience + fActive: boolean; function GetChildren(index: integer): TBoldPerformanceCounter; - function GetChildByName(Name: String): TBoldPerformanceCounter; + function GetChildByName(const AName: String): TBoldPerformanceCounter; + function GetAsDetailedString: String; function GetAsString: String; function GetChildCount: integer; function GetSeconds: double; function GetPercentOfOwner: double; procedure StartFromChild; procedure StopFromChild; + function GetActive: boolean; + procedure SetActive(const Value: boolean); + function GetSecondsWithoutChildren: Double; + function GetLastCallSeconds: double; + function GetLastCallAsString: string; + function GetAccumulatedTime: TDateTime; + function GetNamePath: string; + function GetPercentOfOwnerAsString: String; + protected + function NumberOfParents: integer; + procedure InternalStart; + procedure InternalStop; + function FileTime2DateTime(FileTime: TFileTime): TDateTime; + function HasRuningChildren: boolean; public - constructor Create(Owner: TBoldPerformanceCounter; Name: String); + constructor Create(Owner: TBoldPerformanceCounter; const Name: String); virtual; destructor Destroy; override; - function Reset: boolean; - function Start: boolean; - function Stop: boolean; + procedure Reset; + procedure Start; + procedure Restart; + procedure Stop; virtual; + procedure Clear; function WriteToFile(FileName: string): Boolean; + property Name: string read fName; + property NamePath: string read GetNamePath; property ChildCount: integer read GetChildCount; property Children[index: integer]: TBoldPerformanceCounter read GetChildren; - property ChildByName[name: String]: TBoldPerformanceCounter read GetChildByName; + property ChildByName[const name: String]: TBoldPerformanceCounter read GetChildByName; property AsString: String read GetAsString; + property AsDetailedString: string read GetAsDetailedString; + property Seconds: Double read GetSeconds; + property SecondsWithoutChildren: Double read GetSecondsWithoutChildren; + property LastCallSeconds: double read GetLastCallSeconds; + property LastCallAsString: string read GetLastCallAsString; property PercentOfOwner: Double read GetPercentOfOwner; + property PercentOfOwnerAsString: String read GetPercentOfOwnerAsString; + property Active: boolean read GetActive write SetActive; + property Owner: TBoldPerformanceCounter read fOwner; + property Calls: Int64 read fOwnData.fCalls; + property AccumulatedTime: TDateTime read GetAccumulatedTime; + property LastCallCpuTime: TDateTime read fOwnData.fLastCallCpuTime; + property AccumulatedCpuTime: TDateTime read fOwnData.fAccumulatedCPUTime; + + property Tag: integer read fTag write fTag; + + property OwnData: TBoldPerformanceData read fOwnData; + property ChildrenData: TBoldPerformanceData read fChildrenData; end; function BoldMainPerformanceCounter: TBoldPerformanceCounter; @@ -58,21 +121,22 @@ implementation uses SysUtils, - BoldUtils, - BoldCommonConst; + DateUtils, + + BoldUtils; var G_MainPerformanceCounter: TBoldPerformanceCounter; + Frequency: TLargeInteger; function BoldMainPerformanceCounter: TBoldPerformanceCounter; begin if not assigned(G_MainPerformanceCounter) then - G_MainPerformanceCounter := TBoldPerformanceCounter.Create(nil, 'BoldMainPerformanceCounter'); // do not localize + G_MainPerformanceCounter := TBoldPerformanceCounter.Create(nil, 'BoldMainPerformanceCounter'); result := G_MainPerformanceCounter; end; {$IFDEF LINUX} -{ TODO : Find performancecoutner for LINUX. } function QueryPerformanceCounter(var PerformanceCounter: TLargeInteger): boolean; begin PerformanceCounter := 0; @@ -86,15 +150,43 @@ function QueryPerformanceFrequency(var Frequency: TLargeInteger): boolean; end; {$ENDIF} -constructor TBoldPerformanceCounter.Create(Owner: TBoldPerformanceCounter; Name: String); +function TBoldPerformanceCounter.FileTime2DateTime(FileTime: TFileTime): TDateTime; //Convert then FileTime to TDatetime format +var + ft1: TFileTime; + st: TSystemTime; +begin + if FileTime.dwLowDateTime + FileTime.dwHighDateTime = 0 then + Result := 0 + else + begin + FileTimeToLocalFileTime(FileTime, ft1); + FileTimeToSystemTime(ft1, st); + Result := SystemTimeToDateTime(st); + end; +end; + +procedure TBoldPerformanceCounter.Clear; +var + i: integer; begin + for i := ChildCount - 1 downto 0 do + begin + Children[i].free; + end; + fChildren.Clear; + Reset; +end; + +constructor TBoldPerformanceCounter.Create(Owner: TBoldPerformanceCounter; const Name: String); +begin + Assert(Name <> ''); inherited create; fNUmberOfChildrenRunning := 0; - fChildren := TStringList.Create; + fChildren := TList.Create; fOwner := Owner; - fName := UpperCase(Name); + fName := Name; if Assigned(Owner) then - Owner.fChildren.AddObject(Name,self); + Owner.fChildren.Add(self); end; destructor TBoldPerformanceCounter.Destroy; @@ -103,18 +195,8 @@ destructor TBoldPerformanceCounter.Destroy; BoldPerformanceCounter: TBoldPerformanceCounter; begin if Assigned(fOwner) then - begin - for i := 0 to fOwner.ChildCount - 1 do - begin - if fOwner.Children[i] = self then - begin - fOwner.fChildren.Delete(i); - break; - end; - end; - end; - - for i := ChildCount - 1 downto 0 do + fOwner.fChildren.Remove(self); + for i := ChildCount-1 downto 0 do begin BoldPerformanceCounter := Children[i]; BoldPerformanceCounter.fOwner := nil; @@ -131,74 +213,232 @@ function TBoldPerformanceCounter.GetChildCount: integer; function TBoldPerformanceCounter.GetChildren(index: integer): TBoldPerformanceCounter; begin - result := fChildren.Objects[index] as TBoldPerformanceCounter; + result := TBoldPerformanceCounter(fChildren[index]); +end; + +function TBoldPerformanceCounter.GetLastCallAsString: string; +begin + result := Trim(format('%8.3f', [LastCallSeconds])); +end; + +function TBoldPerformanceCounter.GetLastCallSeconds: double; +begin + result := (fOwnData.fLastCallTime / 10000000); end; -function TBoldPerformanceCounter.GetChildByName(Name: String): TBoldPerformanceCounter; +function TBoldPerformanceCounter.GetNamePath: string; +begin + if Assigned(Owner) and (Owner.NamePath <> '') then + result := Owner.NamePath + '.' + name + else + result := name; +end; + +function TBoldPerformanceCounter.GetChildByName(const AName: String): TBoldPerformanceCounter; var i: integer; begin - i := fChildren.IndexOf(UpperCase(Name)); - if i = -1 then - result := TBoldPerformanceCounter.Create(self,name) - else - result := Children[i]; +// if there is a need consider using hash instead + for I := 0 to fChildren.Count - 1 do + if CompareText(AName, TBoldPerformanceCounter(fChildren[i]).Name) = 0 then + begin + result := Children[i]; + exit; + end; + result := TBoldPerformanceCounterClass(classType).Create(self,AName) end; -function TBoldPerformanceCounter.Reset: boolean; +procedure TBoldPerformanceCounter.Reset; var i: integer; begin - fAccumulatedTime := 0; - fCalls := 0; + fOwnData.Clear; for i := 0 to ChildCount-1 do Children[i].Reset; - result := true; end; -function TBoldPerformanceCounter.Start: boolean; +procedure TBoldPerformanceCounter.Restart; begin - inc(fCalls); - if assigned(fOwner) then - fOwner.StartFromChild; - QueryPerformanceCounter(fStart); - result := true; + Reset; + Start; +end; + +procedure TBoldPerformanceCounter.SetActive(const Value: boolean); +begin + if fActive <> Value then + begin + if Value then + Start + else + Stop; + end; end; -function TBoldPerformanceCounter.Stop: boolean; +procedure TBoldPerformanceCounter.InternalStart; +var + CreationTime, ExitTime: TFileTime; +begin + if HasRuningChildren then + QueryPerformanceCounter(fChildrenData.FStart) + else + QueryPerformanceCounter(fOwnData.FStart); + fActive := true; + if HasRuningChildren then + GetProcessTimes(GetCurrentProcess, CreationTime, ExitTime, fChildrenData.fKernelTime, fChildrenData.fUserTime) + else + GetProcessTimes(GetCurrentProcess, CreationTime, ExitTime, fOwnData.fKernelTime, fOwnData.fUserTime); +end; + +procedure TBoldPerformanceCounter.InternalStop; var CurrentTime: TLargeInteger; + CreationTime, ExitTime, KernelTime, UserTime: TFileTime; begin QueryPerformanceCounter(CurrentTime); + if HasRuningChildren then + begin + fChildrenData.fLastCallTime := CurrentTime - fChildrenData.fStart; + fChildrenData.fAccumulatedTime := fChildrenData.fAccumulatedTime + fChildrenData.fLastCallTime; + end + else + begin + fOwnData.fLastCallTime := CurrentTime - fOwnData.fStart; + fOwnData.fAccumulatedTime := fOwnData.fAccumulatedTime + fOwnData.fLastCallTime; + end; + GetProcessTimes(GetCurrentProcess, CreationTime, ExitTime, KernelTime, UserTime); + if HasRuningChildren then + begin + fChildrenData.fLastCallCpuTime := FileTime2DateTime(KernelTime) + FileTime2DateTime(UserTime) - FileTime2DateTime(fChildrenData.fKernelTime) - FileTime2DateTime(fChildrenData.fUserTime); + fChildrenData.fAccumulatedCpuTime := fChildrenData.fAccumulatedCpuTime + fChildrenData.fLastCallCpuTime; + end + else + begin + fOwnData.fLastCallCpuTime := FileTime2DateTime(KernelTime) + FileTime2DateTime(UserTime) - FileTime2DateTime(fOwnData.fKernelTime) - FileTime2DateTime(fOwnData.fUserTime); + fOwnData.fAccumulatedCpuTime := fOwnData.fAccumulatedCpuTime + fOwnData.fLastCallCpuTime; + end; + fActive := false; +end; + +procedure TBoldPerformanceCounter.Start; +begin + if active then + exit; + if HasRuningChildren then + inc(fChildrenData.fCalls) + else + inc(fOwnData.fCalls); + if assigned(fOwner) then + fOwner.StartFromChild; + if HasRuningChildren then + QueryPerformanceCounter(fChildrenData.fStart) + else + QueryPerformanceCounter(fOwnData.fStart); + InternalStart; +end; + +procedure TBoldPerformanceCounter.Stop; +begin + if not active then + exit; // or do we want to raise ? + InternalStop; if assigned(fOwner) then fOwner.StopFromChild; - fAccumulatedTime := fAccumulatedTime + CurrentTime - fStart; - result := true; end; function TBoldPerformanceCounter.GetSeconds: double; +begin + result := DateUtils.SecondSpan(AccumulatedTime, 0); +end; + +function TBoldPerformanceCounter.GetSecondsWithoutChildren: Double; var - Frequency: TLargeInteger; + i: integer; begin - QueryPerformanceFrequency(Frequency); - result := fAccumulatedTime / Frequency; + result := Seconds; + for I := 0 to GetChildCount - 1 do + begin + result := result - Children[i].Seconds; + end; +end; + +function TBoldPerformanceCounter.HasRuningChildren: boolean; +begin + result := fNumberOfChildrenRunning > 0; +end; + +function TBoldPerformanceCounter.NumberOfParents: integer; +var + lCounter: TBoldPerformanceCounter; +begin + result := 0; + lCounter := fOwner; + while Assigned(lCounter) do + begin + lCounter := lCounter.fOwner; + inc(result); + end; end; function TBoldPerformanceCounter.GetPercentOfOwner: double; begin - if Assigned(fOwner) and (fOwner.Seconds <> 0)then - result := 100*Seconds/fOwner.Seconds + if Assigned(fOwner) and (fOwner.ChildrenData.AccumulatedTime <> 0)then + result := 100 * AccumulatedTime/fOwner.ChildrenData.AccumulatedTime else result := 100; end; +function TBoldPerformanceCounter.GetPercentOfOwnerAsString: String; +begin + result := format('%4.2f', [PercentOfOwner])+'%'; +end; + +function TBoldPerformanceCounter.GetAccumulatedTime: TDateTime; +var + CurrentTime: TLargeInteger; +begin + // for consistency this returns ownData like all other places + if Active {and HasRuningChildren} then + begin + QueryPerformanceCounter(CurrentTime); + result := (fOwnData.fAccumulatedTime + CurrentTime - fOwnData.fStart) / Frequency / SecsPerDay; + end + else + result := (fOwnData.fAccumulatedTime) / Frequency / SecsPerDay; + +// ElapsedMilliseconds / MSecsPerSec / SecsPerDay; +end; + +function TBoldPerformanceCounter.GetActive: boolean; +begin + result := fActive; +end; + +function TBoldPerformanceCounter.GetAsDetailedString: String; +var + i: integer; + lIndent: string; +begin + result := ''; + if Calls > 0 then + begin + lIndent := StringOfChar(' ', NumberOfParents); + + result := format('%-50s %8.9fs calls: %5d ', [lIndent+fName, Seconds, Calls]); + if Assigned(fOwner) then + result := format('%s %4.2f %% of %s', [result, PercentOfOwner, fOwner.fName]); + result := result + BOLDCRLF; + end; + for i := 0 to ChildCount - 1 do + result := result + Children[i].AsDetailedString + BOLDCRLF; +end; + function TBoldPerformanceCounter.GetAsString: String; var i: integer; begin - result := format(sCallCount, [fName, Seconds, fCalls]); + result := format('%-35s seconds: %8.4f calls: %5d ', [NamePath, Seconds, Calls]); if Assigned(fOwner) then - result := format(sPercentCount, [result, PercentOfOwner, fOwner.fName]); + result := format('%s %4.1f percent of %s', [result, PercentOfOwner, fOwner.NamePath]); result := result+BOLDCRLF; @@ -208,16 +448,18 @@ function TBoldPerformanceCounter.GetAsString: String; procedure TBoldPerformanceCounter.StartFromChild; begin - if fNumberOfChildrenRunning = 0 then - start; + if Active and not HasRuningChildren then + stop; // stop with own data, start with childdata inc(fNumberOfChildrenRunning); + if fNumberOfChildrenRunning = 1 then + start; end; procedure TBoldPerformanceCounter.StopFromChild; begin - dec(fNumberOfChildrenRunning); - if fNumberOfChildrenRunning = 0 then + if fNumberOfChildrenRunning = 1 then stop; + dec(fNumberOfChildrenRunning); end; function TBoldPerformanceCounter.WriteToFile(FileName: string): Boolean; @@ -234,7 +476,50 @@ function TBoldPerformanceCounter.WriteToFile(FileName: string): Boolean; end; end; -initialization // empty +{ TBoldPerformanceData } + +procedure TBoldPerformanceData.Clear; +begin + fAccumulatedTime := 0; + fLastCallTime := 0; + fStart := 0; + fCalls := 0; + fKernelTime.dwLowDateTime := 0; + fKernelTime.dwHighDateTime := 0; + fUserTime.dwLowDateTime := 0; + fUserTime.dwHighDateTime := 0; + fAccumulatedCPUTime := 0; + fLastCallCpuTime := 0; +end; + +function TBoldPerformanceData.GetAccumulatedTime: TDateTime; +begin +{ if Active and HasRuningChildren? then + begin + QueryPerformanceCounter(CurrentTime); + result := (fOwnData.fAccumulatedTime + CurrentTime - fOwnData.fStart) / Frequency / SecsPerDay; + end + else} + result := (fAccumulatedTime) / Frequency / SecsPerDay; +end; + +function TBoldPerformanceData.GetLastCallAsString: string; +begin + result := Trim(format('%8.3f seconds', [LastCallSeconds])); +end; + +function TBoldPerformanceData.GetLastCallSeconds: double; +begin + result := (fLastCallTime / 10000000); +end; + +function TBoldPerformanceData.GetSeconds: double; +begin + result := DateUtils.SecondSpan(AccumulatedTime, 0); +end; + +initialization + QueryPerformanceFrequency(Frequency); finalization freeAndNil(G_MainPerformanceCounter); diff --git a/Source/Common/Support/BoldPriorityQueue.pas b/Source/Common/Support/BoldPriorityQueue.pas index 024416f..819d6df 100644 --- a/Source/Common/Support/BoldPriorityQueue.pas +++ b/Source/Common/Support/BoldPriorityQueue.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldPriorityQueue; interface @@ -11,20 +14,18 @@ interface TBoldPriorityQueueItem = class; TBoldPriorityQueue = class; - { TBoldPriorityQueueItem } TBoldPriorityQueueItem = class(TBoldMemoryManagedObject) public function HasHigherPriorityThan(Item: TBoldPriorityQueueItem): Boolean; virtual; abstract; end; - { TBoldPriorityQueue } TBoldPriorityQueue = class(TBoldMemoryManagedObject) private fHeap: TList; fOnHeadChanged: TNotifyEvent; fLocker: TBoldLoggableCriticalSection; - procedure SiftUp(pos: Integer); // internal use only, not thread safe - procedure SiftDown(pos: Integer); // internal use only, not thread safe + procedure SiftUp(pos: Integer); + procedure SiftDown(pos: Integer); function RightChild(pos: Integer): Integer; function LeftChild(pos: Integer): Integer; function Parent(pos: Integer): Integer; @@ -49,7 +50,8 @@ TBoldPriorityQueue = class(TBoldMemoryManagedObject) implementation uses - SysUtils; + SysUtils, + BoldRev; { TBoldPriorityQueue } @@ -78,7 +80,7 @@ function TBoldPriorityQueue.ChopHead: TBoldPriorityQueueItem; constructor TBoldPriorityQueue.Create; begin fHeap := TList.Create; - fLocker := TBoldLoggableCriticalSection.Create('PriQ'); // do not localize + fLocker := TBoldLoggableCriticalSection.Create('PriQ'); end; destructor TBoldPriorityQueue.Destroy; @@ -115,7 +117,7 @@ procedure TBoldPriorityQueue.InternalRemoveHead; OldHead := Head; fHeap.Exchange(0, fHeap.Count-1); fHeap.Delete(fHeap.Count-1); - SiftDown(1); // heap positions 1-based, even though fHeap is 0-based + SiftDown(1); if (Head <> OldHead) and assigned(fOnHeadChanged) then OnHeadChanged(self); end; @@ -168,7 +170,7 @@ procedure TBoldPriorityQueue.SetItems(pos: Integer; fHeap[pos] := Value; finally fLocker.Release; - end; + end; end; procedure TBoldPriorityQueue.SiftDown(pos: Integer); @@ -220,5 +222,6 @@ procedure TBoldPriorityQueue.swap(pos1, pos2: Integer); end; end; +initialization end. diff --git a/Source/Common/Support/BoldRegistry.pas b/Source/Common/Support/BoldRegistry.pas index 3095837..f3a128c 100644 --- a/Source/Common/Support/BoldRegistry.pas +++ b/Source/Common/Support/BoldRegistry.pas @@ -1,9 +1,12 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldRegistry; interface uses - Windows, // HKEY_LOCAL_MACHINE + Windows, Registry; {** Usage (kala 990714) @@ -169,5 +172,6 @@ procedure TBoldRegistry.WriteString(const Name: String; Value: String); fRegistry.WriteString(Name, Value); end; +initialization end. diff --git a/Source/Common/Support/BoldRev.pas b/Source/Common/Support/BoldRev.pas index 951d71d..280abd6 100644 --- a/Source/Common/Support/BoldRev.pas +++ b/Source/Common/Support/BoldRev.pas @@ -1,11 +1,10 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldRev; interface -implementation - -(* - uses Classes; @@ -19,8 +18,6 @@ procedure BoldRegisterModuleVersion(const Version: string); implementation -{.$R *.res} - uses SysUtils; @@ -60,20 +57,22 @@ function BoldProductVersion: string; function BoldModuleVersions: TStringList; begin if not Assigned(G_VersionList) then + begin G_VersionList := TStringList.Create; + G_VersionList.Sorted := true; + G_VersionList.Duplicates := dupError; + end; Result := G_VersionList; end; procedure BoldRegisterModuleVersion(const Version: string); begin - with BoldModuleVersions do - if IndexOf(Version) = -1 then - BoldModuleVersions.Add(Version); + BoldModuleVersions.Add(Version); end; initialization finalization FreeAndNil(G_VersionList); -*) -end. \ No newline at end of file + +end. diff --git a/Source/Common/Support/BoldSharedStrings.pas b/Source/Common/Support/BoldSharedStrings.pas index 7c23be5..3ee84b3 100644 --- a/Source/Common/Support/BoldSharedStrings.pas +++ b/Source/Common/Support/BoldSharedStrings.pas @@ -1,16 +1,25 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldSharedStrings; interface +{$IFNDEF BOLD_DISABLESHAREDSTRINGS} uses +{$IFDEF UseCriticalSection} + SyncObjs, +{$ENDIF} BoldBase, BoldIndexableList; +{$ENDIF} type + {$IFNDEF BOLD_DISABLESHAREDSTRINGS} TBoldSharedStringHolder = class(TBoldMemoryManagedObject) private fValue: String; - function GetExternalRefCount: integer; + function GetExternalRefCount: integer; {$IFDEF BOLD_INLINE}inline;{$ENDIF} public constructor Create(const s: String); property ExternalRefCount: integer read GetExternalRefCount; @@ -19,51 +28,104 @@ TBoldSharedStringHolder = class(TBoldMemoryManagedObject) TBoldSharedStringCache = class(TBoldUnOrderedIndexableList) private - function GetHolderByValue(const s: String): TBoldSharedStringHolder; + class var IX_StringHolderValue: integer; + function GetHolderByValue(const s: String): TBoldSharedStringHolder; {$IFDEF BOLD_INLINE}inline;{$ENDIF} public constructor Create; property HolderByValue[const s: String]: TBoldSharedStringHolder read GetHolderByValue; end; + {$IFDEF BOLD_UNICODE} + TBoldSharedAnsiStringHolder = class(TBoldMemoryManagedObject) + private + fValue: AnsiString; + function GetExternalRefCount: integer; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + public + constructor Create(const s: AnsiString); + property ExternalRefCount: integer read GetExternalRefCount; + property Value: AnsiString read FValue; + end; + + TBoldSharedAnsiStringCache = class(TBoldUnOrderedIndexableList) + private + function GetHolderByValue(const s: AnsiString): TBoldSharedAnsiStringHolder; + public + constructor Create; + property HolderByValue[const s: AnsiString]: TBoldSharedAnsiStringHolder read GetHolderByValue; + end; + {$ENDIF} + {$ENDIF} + TBoldSharedStringManager = class private - fStringCache: TBoldSharedStringCache; + {$IFDEF UseCriticalSection} + fCriticalSection: TCriticalSection; + {$ENDIF} {$IFNDEF BOLD_DISABLESHAREDSTRINGS} + fAddsRemainingToGarbageCollect: integer; + fStringCache: TBoldSharedStringCache; + {$IFDEF BOLD_UNICODE} + fAnsiAddsRemainingToGarbageCollect: integer; + fAnsiStringCache: TBoldSharedAnsiStringCache; + {$ENDIF} fCachedHits: integer; + procedure DoGarbageCollect(KeepStringsWithOneReference: Boolean); overload; + {$IFDEF BOLD_UNICODE} + procedure DoAnsiGarbageCollect(KeepStringsWithOneReference: Boolean); overload; + {$ENDIF} {$ENDIF} - fAddsRemainingToGarbageCollect: integer; function GetSavedMemory: integer; function GetInfoString: String; public constructor Create; destructor Destroy; override; + procedure GarbageCollect; function GetSharedString(const s: String): String; - procedure GarbageCollect(KeepStringsWithOneReference: Boolean); + {$IFDEF BOLD_UNICODE} + function GetSharedAnsiString(const s: AnsiString): AnsiString; + {$ENDIF} property SavedMemory: integer read GetSavedMemory; property InfoString: String read GetInfoString; end; function BoldSharedStringManager: TBoldSharedStringManager; +{$IFNDEF BOLD_UNICODE} function StringRefCount(const s: String): integer; +{$ENDIF} implementation uses - SysUtils, + SysUtils + {$IFNDEF BOLD_DISABLESHAREDSTRINGS} + , BoldDefs, - BoldHashIndexes; + BoldIndex, + BoldHashIndexes + {$ENDIF}; var - IX_StringHolderValue: integer = -1; G_BoldSharedStringManager: TBoldSharedStringManager = nil; +{$IFNDEF BOLD_DISABLESHAREDSTRINGS} +const + MINIMUM_ADDS = 100; + type TBoldStringHolderValueIndex = class(TBoldCaseSensitiveStringHashIndex) protected function ItemAsKeyString(Item: TObject): string; override; end; + {$IFDEF BOLD_UNICODE} + TBoldAnsiStringHolderValueIndex = class(TBoldCaseSensitiveStringHashIndex) + protected + function ItemAsKeyString(Item: TObject): string; override; + end; + {$ENDIF} +{$ENDIF} + function BoldSharedStringManager: TBoldSharedStringManager; begin if not assigned(G_BoldSharedStringManager) then @@ -71,29 +133,119 @@ function BoldSharedStringManager: TBoldSharedStringManager; result := G_BoldSharedStringManager; end; +{$IFNDEF BOLD_UNICODE} function StringRefCount(const s: String): integer; begin result := Integer(Pointer(integer(Addr(s)^)-8)^); end; +{$ENDIF} + +{$IFNDEF BOLD_DISABLESHAREDSTRINGS} +{ TBoldSharedStringCache } + +constructor TBoldSharedStringCache.Create; +begin + inherited; + SetIndexVariable(IX_StringHolderValue, AddIndex(TBoldStringHolderValueIndex.Create)); +end; + +function TBoldSharedStringCache.GetHolderByValue( + const s: String): TBoldSharedStringHolder; +begin + Result := TBoldSharedStringHolder(TBoldCaseSensitiveStringHashIndex(Indexes[IX_StringHolderValue]).FindByString(s)); +end; + +{$IFDEF BOLD_UNICODE} +constructor TBoldSharedAnsiStringCache.Create; +begin + inherited; + SetIndexVariable(TBoldSharedStringCache.IX_StringHolderValue, AddIndex(TBoldAnsiStringHolderValueIndex.Create)); +end; + +function TBoldSharedAnsiStringCache.GetHolderByValue( + const s: AnsiString): TBoldSharedAnsiStringHolder; +begin + Result := TBoldSharedAnsiStringHolder(TBoldCaseSensitiveStringHashIndex(Indexes[TBoldSharedStringCache.IX_StringHolderValue]).FindByString(string(s))); +end; +{$ENDIF} + +{ TBoldStringHolderValueIndex } + +function TBoldStringHolderValueIndex.ItemAsKeyString(Item: TObject): string; +begin + Result := TBoldSharedStringHolder(item).Value; +end; + +{$IFDEF BOLD_UNICODE} +function TBoldAnsiStringHolderValueIndex.ItemAsKeyString(Item: TObject): string; +begin + Result := string(TBoldSharedAnsiStringHolder(item).Value); +end; +{$ENDIF} + +{ TBoldSharedStringHolder } + +constructor TBoldSharedStringHolder.Create(const s: String); +begin + inherited Create; + fValue := s; +end; + +function TBoldSharedStringHolder.GetExternalRefCount: integer; +begin + result := StringRefCount(fValue)-1; +end; + +{$IFDEF BOLD_UNICODE} +constructor TBoldSharedAnsiStringHolder.Create(const s: AnsiString); +begin + inherited Create; + fValue := s; +end; + +function TBoldSharedAnsiStringHolder.GetExternalRefCount: integer; +begin + result := StringRefCount(fValue)-1; +end; +{$ENDIF} +{$ENDIF} { TBoldSharedStringManager } constructor TBoldSharedStringManager.Create; begin inherited; + {$IFDEF UseCriticalSection} + fCriticalSection := TCriticalSection.Create; + {$ENDIF} + {$IFNDEF BOLD_DISABLESHAREDSTRINGS} fStringCache := TBoldSharedStringCache.Create; - fAddsRemainingToGarbageCollect := 100; + {$IFDEF BOLD_UNICODE} + fAnsiStringCache := TBoldSharedAnsiStringCache.Create; + {$ENDIF} + fAddsRemainingToGarbageCollect := MINIMUM_ADDS; + {$ENDIF} end; destructor TBoldSharedStringManager.Destroy; begin - inherited; + {$IFNDEF BOLD_DISABLESHAREDSTRINGS} FreeAndNil(fStringCache); + {$IFDEF BOLD_UNICODE} + FreeAndNil(fAnsiStringCache); + {$ENDIF} + {$ENDIF} + {$IFDEF UseCriticalSection} + FreeAndNil(fCriticalSection); + {$ENDIF} + inherited; end; -procedure TBoldSharedStringManager.GarbageCollect(KeepStringsWithOneReference: Boolean); +{$IFNDEF BOLD_DISABLESHAREDSTRINGS} +procedure TBoldSharedStringManager.DoGarbageCollect( + KeepStringsWithOneReference: Boolean); var - traverser: TBoldIndexableListTraverser; + Traverser: TBoldIndexableListTraverser; Holder: TBoldSharedStringHolder; MinimumReferencesToKeep: integer; begin @@ -101,109 +253,206 @@ procedure TBoldSharedStringManager.GarbageCollect(KeepStringsWithOneReference: B MinimumReferencesToKeep := 1 else MinimumReferencesToKeep := 2; + Traverser := fStringCache.CreateTraverser; - while not Traverser.EndOfList do + while Traverser.MoveNext do begin Holder := TBoldSharedStringHolder(Traverser.Item); if Holder.ExternalRefCount < MinimumReferencesToKeep then fStringCache.remove(Holder); - Traverser.Next; end; Traverser.Free; + fAddsRemainingToGarbageCollect := fStringCache.Count; + // Do not let fAddsRemainingToGarbageCollect get to small, + // because then GarbageCollect would be called very often and + // there is only a small chance, that Strings were added to the holder. + if fAddsRemainingToGarbageCollect < MINIMUM_ADDS then begin + fAddsRemainingToGarbageCollect := MINIMUM_ADDS; + end; +end; + +{$IFDEF BOLD_UNICODE} +procedure TBoldSharedStringManager.DoAnsiGarbageCollect( + KeepStringsWithOneReference: Boolean); +var + Traverser: TBoldIndexableListTraverser; + Holder: TBoldSharedAnsiStringHolder; + MinimumReferencesToKeep: integer; +begin + if KeepStringsWithOneReference then + MinimumReferencesToKeep := 1 + else + MinimumReferencesToKeep := 2; + + Traverser := fAnsiStringCache.CreateTraverser; + while Traverser.MoveNext do + begin + Holder := TBoldSharedAnsiStringHolder(Traverser.Item); + if Holder.ExternalRefCount < MinimumReferencesToKeep then + fAnsiStringCache.remove(Holder); + end; + Traverser.Free; + + fAnsiAddsRemainingToGarbageCollect := fAnsiStringCache.Count; + // Do not let fAnsiAddsRemainingToGarbageCollect get to small, + // because then GarbageCollect would be called very often and + // there is only a small chance, that Strings were added to the holder. + if fAnsiAddsRemainingToGarbageCollect < MINIMUM_ADDS then begin + fAnsiAddsRemainingToGarbageCollect := MINIMUM_ADDS; + end; +end; +{$ENDIF} +{$ENDIF} + +procedure TBoldSharedStringManager.GarbageCollect; +begin + {$IFNDEF BOLD_DISABLESHAREDSTRINGS} + {$IFDEF UseCriticalSection} + fCriticalSection.Enter; + try + {$ENDIF} + DoGarbageCollect(False); + {$IFDEF BOLD_UNICODE} + DoAnsiGarbageCollect(False); + {$ENDIF} + {$IFDEF UseCriticalSection} + finally + fCriticalSection.Leave; + end; + {$ENDIF} + {$ENDIF} end; function TBoldSharedStringManager.GetInfoString: String; +{$IFNDEF BOLD_DISABLESHAREDSTRINGS} +var + iSharedStrings: Integer; +{$ENDIF} begin - result := - format('Number of shared strings: %d', [FStringCache.Count])+BOLDCRLF+ {do not localize } - format('Saved memory %d', [SavedMemory]); {do not localize } +{$IFDEF BOLD_DISABLESHAREDSTRINGS} + Result := 'SharedStringManager disabled'; {do not localize } +{$ELSE} + {$IFDEF UseCriticalSection} + fCriticalSection.Enter; + try + {$ENDIF} + iSharedStrings := FStringCache.Count; + {$IFDEF BOLD_UNICODE} + Inc(iSharedStrings, fAnsiStringCache.Count); + {$ENDIF} + Result := + Format('Number of shared strings: %d', [iSharedStrings]) + BOLDCRLF + {do not localize } + Format('Saved memory %d', [SavedMemory]); {do not localize } +{$IFDEF UseCriticalSection} + finally + fCriticalSection.Leave; + end; +{$ENDIF} +{$ENDIF} end; function TBoldSharedStringManager.GetSavedMemory: integer; +{$IFNDEF BOLD_DISABLESHAREDSTRINGS} var - traverser: TBoldIndexableListTraverser; + Traverser: TBoldIndexableListTraverser; Holder: TBoldSharedStringHolder; + {$IFDEF BOLD_UNICODE} + AnsiHolder: TBoldSharedAnsiStringHolder; + {$ENDIF} +{$ENDIF} begin - result := 0; + Result := 0; +{$IFNDEF BOLD_DISABLESHAREDSTRINGS} Traverser := fStringCache.CreateTraverser; - while not Traverser.EndOfList do + while Traverser.MoveNext do begin Holder := TBoldSharedStringHolder(Traverser.Item); - result := result + (Holder.ExternalRefCount-1)*length(Holder.Value); - Traverser.Next; + Result := Result + (Holder.ExternalRefCount-1) * Length(Holder.Value) * SizeOf(Char); + end; + Traverser.Free; + {$IFDEF BOLD_UNICODE} + Traverser := fAnsiStringCache.CreateTraverser; + while Traverser.MoveNext do + begin + AnsiHolder := TBoldSharedAnsiStringHolder(Traverser.Item); + Result := Result + (AnsiHolder.ExternalRefCount-1) * Length(AnsiHolder.Value); end; Traverser.Free; + {$ENDIF} +{$ENDIF} end; function TBoldSharedStringManager.GetSharedString(const s: String): String; {$IFDEF BOLD_DISABLESHAREDSTRINGS} begin - result := s; -end; + Result := s; {$ELSE} var Holder: TBoldSharedStringHolder; begin - if s = '' then - result := s - else - begin + if s = '' then begin + Result := s; + end else begin + {$IFDEF UseCriticalSection} + fCriticalSection.Enter; + try + {$ENDIF} Holder := fStringCache.HolderByValue[s]; - if assigned(Holder) then - begin - result := Holder.Value; + if Assigned(Holder) then begin Inc(fCachedHits); - end - else - begin + end else begin Holder := TBoldSharedStringHolder.Create(s); fStringCache.Add(Holder); - result := s; end; + Result := Holder.Value; end; Dec(fAddsRemainingToGarbageCollect); if fAddsRemainingToGarbageCollect <= 0 then - GarbageCollect(true); -end; + DoGarbageCollect(true); +{$IFDEF UseCriticalSection} + finally + fCriticalSection.Leave; + end; +{$ENDIF} {$ENDIF} - -{ TBoldSharedStringCache } - -constructor TBoldSharedStringCache.Create; -begin - inherited; - SetIndexVariable(IX_StringHolderValue, AddIndex(TBoldStringHolderValueIndex.Create)); -end; - -function TBoldSharedStringCache.GetHolderByValue( - const s: String): TBoldSharedStringHolder; -begin - Result := TBoldSharedStringHolder(TBoldStringHolderValueIndex(Indexes[IX_StringHolderValue]).FindByString(s)); -end; - -{ TBoldStringHolderValueIndex } - -function TBoldStringHolderValueIndex.ItemASKeyString( - Item: TObject): string; -begin - result := TBoldSharedStringHolder(item).value; end; -{ TBoldSharedStringHolder } - -constructor TBoldSharedStringHolder.Create(const s: String); +{$IFDEF BOLD_UNICODE} +function TBoldSharedStringManager.GetSharedAnsiString(const s: AnsiString): + AnsiString; +{$IFDEF BOLD_DISABLESHAREDSTRINGS} begin - inherited Create; - fValue := s; -end; - -function TBoldSharedStringHolder.GetExternalRefCount: integer; + Result := s; +{$ELSE} +var + Holder: TBoldSharedAnsiStringHolder; begin - result := StringRefCount(fValue)-1; + if s = '' then begin + Result := s; + end else begin + Holder := fAnsiStringCache.HolderByValue[s]; + if Assigned(Holder) then begin + Inc(fCachedHits); + end else begin + Holder := TBoldSharedAnsiStringHolder.Create(s); + fAnsiStringCache.Add(Holder); + end; + Result := Holder.Value; + end; + Dec(fAnsiAddsRemainingToGarbageCollect); + if fAnsiAddsRemainingToGarbageCollect <= 0 then + DoAnsiGarbageCollect(true); +{$ENDIF} end; +{$ENDIF} initialization // empty +{$IFNDEF BOLD_DISABLESHAREDSTRINGS} + TBoldSharedStringCache.IX_StringHolderValue := -1; +{$ENDIF} + finalization FreeAndNil(G_BoldSharedStringManager); end. + diff --git a/Source/Common/Support/BoldSorter.pas b/Source/Common/Support/BoldSorter.pas index 48f49e5..3e2637e 100644 --- a/Source/Common/Support/BoldSorter.pas +++ b/Source/Common/Support/BoldSorter.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldSorter; interface @@ -11,6 +14,9 @@ procedure BoldSort(FirstIndex, LastIndex: Integer; Compare:TBoldSortCompare ; Ex implementation +uses + BoldRev; + procedure BoldSort(FirstIndex, LastIndex: Integer; Compare:TBoldSortCompare ; Exchange : TBoldSortExchange); var I, J, P: Integer; @@ -38,4 +44,7 @@ procedure BoldSort(FirstIndex, LastIndex: Integer; Compare:TBoldSortCompare ; Ex until I >= LastIndex; end; + + +initialization end. diff --git a/Source/Common/Support/BoldStringList.pas b/Source/Common/Support/BoldStringList.pas index 9c7473a..4fadd55 100644 --- a/Source/Common/Support/BoldStringList.pas +++ b/Source/Common/Support/BoldStringList.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldStringList; interface @@ -34,7 +37,8 @@ implementation uses BoldSharedStrings, - SysUtils; + SysUtils, + BoldRev; { TBoldStringList } @@ -87,7 +91,7 @@ function TBoldStringList.GetIndexOfName(const Name: String; var Index: integer): result := GetIndexOfPrefix(name + '=', Index); end; -function BoldAnsiLCompareShortest(Const s1, s2: string): integer; // Don't inline, will invoke UniqueString +function BoldAnsiLCompareShortest(Const s1, s2: string): integer; var Len, Len1: integer; @@ -178,4 +182,5 @@ procedure TBoldStringList.Sort; inherited; end; +initialization end. diff --git a/Source/Common/Support/BoldTemplateExpander.pas b/Source/Common/Support/BoldTemplateExpander.pas index 84b8053..abb1f7e 100644 --- a/Source/Common/Support/BoldTemplateExpander.pas +++ b/Source/Common/Support/BoldTemplateExpander.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldTemplateExpander; interface @@ -30,7 +33,7 @@ TBoldTemplatevariable = class(TBoldMemoryManagedObject) fValue: String; fFlags: TBoldvariableFlags; public - constructor Create(const name, value: string; Flags: TBoldVariableFlags); + constructor create(const name, value: string; Flags: TBoldVariableFlags); property Name: string read fName; property Value: String read fValue write fValue; property Flags: TBoldVariableFlags read fFlags; @@ -71,9 +74,9 @@ TBoldTemplateHolder = class(TComponent) procedure SetFileName(const Value: String); procedure TemplateChanged(sender: TObject); public - constructor Create(aOwner: Tcomponent); override; + constructor create(aOwner: Tcomponent); override; procedure ExpandTemplate; - destructor Destroy; override; + destructor destroy; override; property Variables: TBoldTemplateVariables read fvariables; property ExpandedTemplate: TStringList read GetExpandedTemplate; property LastExpansion: TStringList read fExpandedTemplate; @@ -91,22 +94,21 @@ TBoldTemplateList = class(TList) property items[index: integer]: TBoldTemplateHolder read GetItems; default; end; + function BoldExpandTemplate(const Source: string; Variables: TBoldtemplateVariables; MacroNamePad: String = ''): string; implementation uses SysUtils, - BoldUtils, - BoldCommonConst; - + BoldUtils; var IX_TemplateVariables: integer = -1; type TBoldTemplatevariableIndex = class(TBoldStringHashIndex) protected - function ItemAsKeyString(Item: TObject): string; override; + function ItemASKeyString(Item: TObject): string; override; end; { TBoldTemplateHolder } @@ -150,9 +152,9 @@ function TBoldTemplateVariables.Exists(const Name: string): Boolean; function TBoldTemplateVariables.ExpandString(const Source: string): string; begin - Change('DATETIME', DateTimeToStr(now)); // do not localize - Change('DATE', DateToStr(now)); // do not localize - Change('TIME', TimeToStr(now)); // do not localize + Change('DATETIME', DateTimeToStr(now)); + Change('DATE', DateToStr(now)); + Change('TIME', TimeToStr(now)); result := BoldExpandTemplate(Source, Self); end; @@ -214,7 +216,6 @@ function BoldExpandTemplate(const Source: string; Variables: TBoldTemplateVariab result := Variables.Values[MacroName]; while (Result = '') and (pos('.', MacroName) <> 0) do begin - // variable Might to belong to an outer loop scope i := length(MacroName); While MacroName[i] <> '.' do dec(i); Delete(MacroName, i, maxint); @@ -234,16 +235,16 @@ function BoldExpandTemplate(const Source: string; Variables: TBoldTemplateVariab if Me > 0 then begin Result := Result + Copy(TempSource, 1, Mb - 1); - if not (temp[1] in ['?', ',']) then // temp cant be empty since MAcroEnd is inside temp + if not CharInSet(temp[1], ['?', ',']) then // temp cant be empty since MAcroEnd is inside temp MacroName := Copy(Temp, 1, Me - 1) + MacroNamePad else - MacroName := Copy(Temp, 1, Me - 1); // namepad has to be added later to ?-macros - if (Length(MacroName) > 0) and (MacroName[1] in MacroModifiers) then + MacroName := Copy(Temp, 1, Me - 1); + if (Length(MacroName) > 0) and CharInSet(MacroName[1], MacroModifiers) then begin Modifier := MacroName[1]; MacroName := Copy(MacroName, 2, MaxInt); case Modifier of - ',': // Separation + ',': begin Value := copy(MacroName, pos(':', MacroName) + 1, MaxInt); macroName := copy(MacroName, 1, pos(':', MacroName) - 1); @@ -251,14 +252,14 @@ function BoldExpandTemplate(const Source: string; Variables: TBoldTemplateVariab result := result + Value end; - '+': // uppercase + '+': Result := Result + AnsiUppercase(GetVarvalue(MacroName)); - '-': // lowercase + '-': Result := Result + AnsiLowercase(GetVarvalue(MacroName)); - '<','>': // justification + '<','>': begin Number := ''; - while MacroName[1] in MacroNumbers do + while CharInSet(MacroName[1], MacroNumbers) do begin Number := Number + MacroName[1]; MacroName := Copy(MacroName, 2, MaxInt); @@ -268,9 +269,9 @@ function BoldExpandTemplate(const Source: string; Variables: TBoldTemplateVariab if (J > 0) and (J > Length(MacroValue)) then begin case Modifier of - '<': // left justify + '<': Pad := MacroValue + StringOfChar(' ', J - Length(MacroValue)); - '>': // right justify + '>': Pad := StringOfChar(' ', J - Length(MacroValue)) + MacroValue; end; end @@ -278,7 +279,7 @@ function BoldExpandTemplate(const Source: string; Variables: TBoldTemplateVariab Pad := MacroValue; Result := Result + Pad; end; - '?': begin // IfStatement $(?varname:true,false) + '?': begin ColonPos := pos(':', MacroName); CommaPos:= pos(',', MacroName); if GetVarvalue(copy(MacroName, 1, ColonPos - 1) + MacroNamePad) = '1' then @@ -291,13 +292,13 @@ function BoldExpandTemplate(const Source: string; Variables: TBoldTemplateVariab else begin EndLoopPos := 0; - if Pos('LOOP', MacroName) = 1 then // do not localize + if Pos('LOOP', MacroName) = 1 then begin MacroName := Copy(MacroName, 5, maxint); MatchMacroName := MacroName; if pos('.', MatchMacroName) <> 0 then Delete(MatchMacroName, pos('.', MatchMacroName), MaxInt); - MatchMacroname := UpperCase(MacroBegin + 'ENDLOOP' + MatchMacroName + MacroEnd); // do not localize + MatchMacroname := UpperCase(MacroBegin + 'ENDLOOP' + MatchMacroName + MacroEnd); EndLoopPos := pos(MatchMacroName, UpperCase(temp)); if EndLoopPos <> 0 then @@ -313,16 +314,16 @@ function BoldExpandTemplate(const Source: string; Variables: TBoldTemplateVariab Variables.SetVariable(Macroname, IntToStr(OldLoopValue)); end else - raise Exception.CreateFmt(sUnterminatedLoop, [MacroName]); + raise Exception.Create('Unterminated loop in template: ' + MacroName); end - else if Pos('CASE', macroName) = 1 then // do not localize + else if Pos('CASE', macroName) = 1 then begin MacroName := Copy(MacroName, 5, maxint); MatchMacroName := MacroName; if pos('.', MatchMacroName) <> 0 then Delete(MatchMacroName, pos('.', MatchMacroName), MaxInt); - MatchMacroname := UpperCase(MacroBegin + 'ENDCASE' + MatchMacroName + MacroEnd); // do not localize + MatchMacroname := UpperCase(MacroBegin + 'ENDCASE' + MatchMacroName + MacroEnd); EndLoopPos := pos(MatchMacroName, UpperCase(temp)); if EndLoopPos <> 0 then @@ -339,7 +340,7 @@ function BoldExpandTemplate(const Source: string; Variables: TBoldTemplateVariab CurrentCaseTag := UpperCase(BoldExpandTemplate(uppercase(trim(copy(CaseText[i], 1, barpos - 1))), variables, MacroNamePad)); if currentCaseTag <> CaseValue then begin - if CurrentCasetag = 'ELSE' then // do not localize + if CurrentCasetag = 'ELSE' then ElseValue := copy(CaseText[i], BarPos + 1, maxint) + BOLDCRLF + ElseValue; CaseText.Delete(i); end @@ -362,15 +363,15 @@ function BoldExpandTemplate(const Source: string; Variables: TBoldTemplateVariab result := result + BoldExpandTemplate(CaseText.Text, Variables, MacroNamePad); CaseText.Free; end else - Raise Exception.CreateFmt(sUnterminatedCase, [MacroName]); + Raise Exception.Create('Unterminated case in template: ' + MacroName); end - else if Pos('MACROSTART', MacroName) = 1 then // do not localize + else if Pos('MACROSTART', MacroName) = 1 then begin MacroName := trim(Copy(MacroName, 11, maxint)); MatchMacroName := MacroName; if pos('.', MatchMacroName) <> 0 then Delete(MatchMacroName, pos('.', MatchMacroName), MaxInt); - MatchMacroname := UpperCase(MacroBegin + 'MACROEND ' + MatchMacroName + MacroEnd); // do not localize + MatchMacroname := UpperCase(MacroBegin + 'MACROEND ' + MatchMacroName + MacroEnd); EndLoopPos := pos(MatchMacroName, UpperCase(temp)); if EndLoopPos <> 0 then @@ -380,17 +381,16 @@ function BoldExpandTemplate(const Source: string; Variables: TBoldTemplateVariab Variables.SetVariable(Macroname, MacroText); end else - raise Exception.CreateFmt(sUnterminatedMacro, [MacroName]); + raise Exception.Create('Unterminated Macro in template: ' + MacroName); end; - if pos('CRLF', upperCase(MacroName)) = 1 then // in loops the CRLF becomes CRLF.0 // do not localize + if pos('CRLF', upperCase(MacroName)) = 1 then result := result + BOLDCRLF else if endLoopPos = 0 then begin value := Variables.Values[MacroName]; while (value = '') and (pos('.', MacroName) <> 0) do begin - // variable seems to belong to an outer loop scope i := length(MacroName); While MacroName[i] <> '.' do dec(i); Delete(MacroName, i, maxint); @@ -425,7 +425,7 @@ constructor TBoldTemplateHolder.create(aOwner: Tcomponent); fExpandedTemplate := TStringList.Create; end; -destructor TBoldTemplateHolder.Destroy; +destructor TBoldTemplateHolder.destroy; begin FreeAndNil(fVariables); FreeAndNil(fTemplate); @@ -485,9 +485,9 @@ procedure TBoldTemplateHolder.SetFileName(const Value: String); procedure TBoldTemplateVariables.InitializeDateTimeMacros; begin - SetVariable('DATETIME', DateTimeToStr(now)); // do not localize - SetVariable('DATE', DateToStr(now)); // do not localize - SetVariable('TIME', TimeToStr(now)); // do not localize + SetVariable('DATETIME', DateTimeToStr(now)); + SetVariable('DATE', DateToStr(now)); + SetVariable('TIME', TimeToStr(now)); end; procedure TBoldTemplateHolder.TemplateChanged(sender: TObject); @@ -512,6 +512,8 @@ function TBoldTemplatevariableIndex.ItemASKeyString(Item: TObject): string; result := TBoldTemplatevariable(Item).Name; end; + + { TBoldTemplateList } function TBoldTemplateList.GetItems(index: integer): TBoldTemplateHolder; @@ -519,4 +521,7 @@ function TBoldTemplateList.GetItems(index: integer): TBoldTemplateHolder; result := TBoldTemplateHolder(inherited items[index]); end; + +initialization + end. diff --git a/Source/Common/Support/BoldUtils.pas b/Source/Common/Support/BoldUtils.pas index 84bf60d..5cb628d 100644 --- a/Source/Common/Support/BoldUtils.pas +++ b/Source/Common/Support/BoldUtils.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldUtils; interface @@ -7,7 +10,9 @@ interface SysUtils, Classes, TypInfo, - BoldDefs; + Windows, + BoldDefs, + WideStrings; type TBoldNotificationEvent = procedure(AComponent: TComponent; Operation: TOperation) of object; @@ -24,14 +29,14 @@ TBoldPassthroughNotifier = class(TComponent) function CharCount(c: char; const s: string): integer; function BoldNamesEqual(const name1, name2: string): Boolean; procedure BoldAppendToStrings(strings: TStrings; const aString: string; const ForceNewLine: Boolean); -function BoldSeparateStringList(strings: TStringList; const Separator, PreString, PostString: String): String; +function BoldSeparateStringList(strings: TStringList; const Separator, PreString, PostString: String; AIndex: integer = -1): String; function BoldSeparatedAppend(const S1, S2: string;const Separator: string = ','): string; function BoldTrim(const S: string): string; function BoldIsPrefix(const S, Prefix: string): Boolean; function BoldStrEqual(P1, P2: PChar; Len: integer): Boolean; -function BoldStrAnsiEqual(P1, P2: PChar; Len: integer): Boolean; -function BoldAnsiEqual(const S1, S2: string): Boolean; -function BoldStrStringEqual(const S1: string; P2: PChar; Len: integer): Boolean; +function BoldStrAnsiEqual(P1, P2: PChar; Len: integer): Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} +function BoldAnsiEqual(const S1, S2: string): Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} +function BoldStrStringEqual(const S1: string; P2: PChar; Len: integer): Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} function BoldCaseIndependentPos(const Substr, S: string): Integer; procedure EnumToStrings(aTypeInfo: pTypeInfo; Strings: TStrings); function CapitalisedToSpaced(Capitalised: String): String; @@ -48,7 +53,11 @@ function StrToDateFmt(const S: string; const DateFormat: string; const DateSepar function DateToStrFmt(const aDate: TDateTime; DateFormat: string; const DateSeparatorChar: char = '/'): String; function BoldParseFormattedDateList(const value: String; const formats: TStrings; var Date: TDateTime): Boolean; function BoldParseFormattedDate(const value: String; const formats: array of string; var Date: TDateTime): Boolean; - +{$IFDEF MSWINDOWS} +function FileTimeToDateTime(const FileTime: TFileTime): TDateTime; {$IFDEF BOLD_INLINE} inline; {$ENDIF} +{$ENDIF} +function UserTimeInTicks: Int64; +function TicksToDateTime(Ticks: Int64): TDateTime; {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure EnsureTrailing(var Str: String; ch: char); { Taken from FileCtrl to remove unit dependency } function DirectoryExists(const Name: string): Boolean; @@ -60,24 +69,91 @@ function GetModuleFileNameAsString(IncludePath: Boolean): string; {variant support} function BoldVariantToStrings(V: OleVariant; Strings: TStrings): Integer; -const - BoldProductNameShort = 'BfD'; - BoldProductVersion = '4.0'; +{$IFNDEF BOLD_DELPHI13_OR_LATER} +function CharInSet(C: AnsiChar; const CharSet: TSysCharSet): Boolean; overload; {$IFDEF BOLD_INLINE}inline;{$ENDIF} +function CharInSet(C: WideChar; const CharSet: TSysCharSet): Boolean; overload; {$IFDEF BOLD_INLINE}inline;{$ENDIF} +{$ENDIF} -var - BoldRunningAsDesignTimePackage: boolean = false; +var BoldRunningAsDesignTimePackage: boolean = false; implementation uses - BoldCommonConst, - Windows; + BoldRev + {$IFDEF RIL} + {$IFNDEF BOLD_UNICODE} + ,StringBuilder + {$ENDIF} + {$ENDIF} +; {$IFDEF LINUX} const MAX_COMPUTERNAME_LENGTH = 128; {$ENDIF} +{$IFDEF MSWINDOWS} + +type + TFileTimeAligner = record + case integer of + 0: (asFileTime: TFileTime); + 1: (asInt64: Int64); + end; +var + CurrentProcess: THANDLE = 0; + +function FileTimeToDateTime(const FileTime: TFileTime): TDateTime; +const + Nr100nsPerDay = 3600.0*24*10000000; +var + FileTimeAsInt64: Int64; +begin + Move(FileTime, FileTimeAsInt64, 8); + Result := FileTimeAsInt64/Nr100nsPerDay; + +end; +{$ENDIF} + +function UserTimeInTicks: Int64; +var + UserTime, CreationTime, ExitTime, KernelTime: TFileTimeAligner; +begin +{$IFDEF MSWINDOWS} + if CurrentProcess <> 0 then + CloseHandle(CurrentProcess); + CurrentProcess := OpenProcess(PROCESS_QUERY_INFORMATION, False, GetCurrentProcessId); + if GetProcessTimes(CurrentProcess, CreationTime.asFileTime, ExitTime.asFileTime, KernelTime.asFileTime, UserTime.asFileTime) then + Result := UserTime.asInt64 + else + Result := 0; +{$ELSE} + FIXME +{$ENDIF} +end; +function TicksToDateTime(Ticks: Int64): TDateTime; +const + Nr100nsPerDay = 3600.0*24.0*10000000.0; +begin +{$IFDEF MSWINDOWS} + Result := Ticks/Nr100nsPerDay; +{$ELSE} + FIXME +{$ENDIF} +end; + +{$IFNDEF BOLD_DELPHI13_OR_LATER} +function CharInSet(C: AnsiChar; const CharSet: TSysCharSet): Boolean; +begin + Result := C in CharSet; +end; + +function CharInSet(C: WideChar; const CharSet: TSysCharSet): Boolean; +begin + Result := C in CharSet; +end; +{$ENDIF} + { Taken from FileCtrl to remove unit dependency } function DirectoryExists(const Name: string): Boolean; var @@ -91,33 +167,37 @@ function ForceDirectories(Dir: string): Boolean; begin Result := True; if Length(Dir) = 0 then - raise Exception.Create(sCannotCreateDirectory); + raise Exception.Create('Cannot create directory'); Dir := ExcludeTrailingPathDelimiter(Dir); if (Length(Dir) < 3) or DirectoryExists(Dir) - or (ExtractFilePath(Dir) = Dir) then Exit; // avoid 'xyz:\' problem. + or (ExtractFilePath(Dir) = Dir) then Exit; Result := ForceDirectories(ExtractFilePath(Dir)) and CreateDir(Dir); end; function BoldIsPrefix(const S, Prefix: string): Boolean; +{ril - resusing length by variable } +var + PrefixLen: Integer; begin - Result := (Length(s) >= Length(Prefix)) and CompareMem(@s[1], @Prefix[1], Length(Prefix)); + PrefixLen := Length(Prefix); + Result := (Length(s) >= PrefixLen) and CompareMem(@s[1], @Prefix[1], PrefixLen * SizeOf(Char)); end; function BoldStrEqual(P1, P2: PChar; Len: integer): Boolean; begin - Result := CompareMem(P1, P2, Len); + Result := CompareMem(P1, P2, Len * SizeOf(Char)); end; function BoldStrAnsiEqual(P1, P2: PChar; Len: integer): Boolean; begin - Result := CompareMem(P1, P2, Len) or (AnsiStrLIComp(P1, P2, Len) = 0); + Result := CompareMem(P1, P2, Len * SizeOf(Char)) or (AnsiStrLIComp(P1, P2, Len) = 0); end; function BoldStrCaseIndpendentEqual(P1, P2: PChar; Len: integer): Boolean; var ch1, ch2: Char; begin - if not CompareMem(P1, P2, Len) then + if not CompareMem(P1, P2, Len * SizeOf(Char)) then while Len <> 0 do begin ch1 := P1^; @@ -158,7 +238,7 @@ function BoldStrStringEqual(const S1: string; P2: PChar; Len: integer): Boolean; if Len <> Length(S1) then Result := False else - Result := CompareMem(PChar(S1), P2, Len); + Result := CompareMem(PChar(S1), P2, Len * SizeOf(Char)); end; function BoldCaseIndependentPos(const Substr, S: string): Integer; @@ -172,7 +252,7 @@ function BoldCaseIndependentPos(const Substr, S: string): Integer; begin Result := Pos(Substr, S); if (Result = 0) or (Result > SubStrLen) then - Result := Pos(UpperCase(Substr), UpperCase(S)); + Result := Pos(AnsiUpperCase(Substr), AnsiUpperCase(S)); end; end; @@ -185,21 +265,20 @@ procedure EnsureTrailing(var Str: String; ch: char); function BooleanToString(BoolValue: Boolean): String; begin - if BoolValue then Result := 'True' else Result := 'False'; // do not localize + if BoolValue then Result := 'True' else Result := 'False'; end; function StringToBoolean(StrValue: String): Boolean; begin Result := False; - if (UpperCase(StrValue)= 'Y') or (UpperCase(StrValue) = 'T') or (UpperCase(StrValue) = 'TRUE') then // do not localize + if (UpperCase(StrValue)= 'Y') or (UpperCase(StrValue) = 'T') or (UpperCase(StrValue) = 'TRUE') then Result := True; end; function BoldRootRegistryKey: string; begin - // Returns something like this: Software\BoldSoft\BfD20D5Pro\2.0 - Result := Format('Software\BoldSoft\%s\%s', // do not localize - [BoldProductNameShort, BoldProductVersion]); + Result := Format('Software\BoldSoft\%s\%s', + [BoldProductNameShort,BoldProductVersion]); end; function GetModuleFileNameAsString(IncludePath: Boolean): string; @@ -212,7 +291,7 @@ function GetModuleFileNameAsString(IncludePath: Boolean): string; if IncludePath then Result := ModuleName else - Result := ExtractFileName(ModuleName); + Result := ExtractFileName(ModuleName); end; procedure EnumToStrings(aTypeInfo: pTypeInfo; Strings: TStrings); @@ -227,30 +306,119 @@ procedure EnumToStrings(aTypeInfo: pTypeInfo; Strings: TStrings); function BoldNamesEqual(const name1, name2: string): Boolean; begin - Result := (AnsiCompareText(name1, name2) = 0); + Result := (CompareText(name1, name2) = 0); end; -function BoldSeparateStringList(strings: TStringList; const Separator, PreString, PostString: String): String; +function BoldSeparateStringList(strings: TStringList; const Separator, PreString, PostString: String; AIndex: integer): String; +{$IFDEF RIL} +var + i, Cnt, Size: integer; + SB: TStringBuilder; +begin + Cnt := strings.Count; + case Cnt of + 0: Result := ''; + 1: Result := PreString + Strings[0] + PostString; + else + begin + Size := length(PreString) + length(PostString); + for I := 0 to Cnt - 1 do + Inc(Size, Length(Strings[I])); + Inc(Size, Length(Separator) * Cnt); + SB := TStringBuilder.Create(Size); + SB.Append(PreString); + for i := 0 to Cnt-2 do + begin + //result := result + Strings[i] + Separator; + SB.Append(Strings[i]); + if AIndex <> -1 then + SB.Append(IntToStr(AIndex)); + SB.Append(Separator); + end; + // result := result + Strings[Strings.Count - 1] + SB.Append(Strings[Cnt-1]); + if AIndex <> -1 then + SB.Append(IntToStr(AIndex)); + { no need to check Cnt again it IS > 0 so: } + // result := PreString + result +PostString; + SB.Append(PostString); + Result := SB.ToString; + FreeAndNil(SB); + end; + end; +{$ELSE} var i: integer; - begin result := ''; - if strings.Count > 0 then begin for i := 0 to strings.Count-2 do - result := result + Strings[i] + Separator; - result := result + Strings[Strings.Count - 1] + begin + result := result + Strings[i]; + if AIndex <> -1 then + result := result + IntToStr(AIndex); + result := result + Separator; + end; + result := result + Strings[Strings.Count - 1]; + if AIndex <> -1 then + result := result + IntToStr(AIndex); end else result := ''; - if strings.Count > 0 then result := PreString + result +PostString; +{$ENDIF} end; -procedure BoldAppendTostrings(Strings: TStrings; const aString: string; const ForceNewLine: Boolean); +procedure BoldAppendToStrings(Strings: TStrings; const aString: string; const ForceNewLine: Boolean); +{$IFDEF RIL} +var + StrCount, SplitterPos: Integer; + SB: TStringBuilder; + TempStr: string; +begin + + { replace all LFs and CRs in string with space chars. This is "Superfast" : } + if (Pos(BOLDLF, aString)>0) or (Pos(BOLDCR, aString)>0) then + begin + SB := TStringBuilder.Create(aString); + SB.Replace(BOLDCR, ' '); + SB.Replace(BOLDLF, ' '); + TempStr := SB.ToSTring; + FreeAndNil(SB); + end + else + TempStr := aString; + + Strings.BeginUpdate; + try + StrCount := Strings.Count-1; + if (StrCount = -1) or ForceNewLine then + begin + Strings.Add(TempStr); + Inc(StrCount); + end + else + Strings[StrCount] := Strings[StrCount] + TempStr; + + { break lines into max 80 chars per line } + while Length(Strings[StrCount]) > 80 do + begin + SplitterPos := 80; + + while (Pos(Strings[StrCount][SplitterPos],' ,=')=0) and (SplitterPos > 1) do + Dec(SplitterPos); + + Strings.Append(Copy(Strings[StrCount], SplitterPos + 1, 65536)); + Strings[StrCount] := Copy(Strings[StrCount], 1, SplitterPos); + + Inc(StrCount); + end; + finally + Strings.EndUpdate; + end; +{$ELSE} var StrCount: integer; i: integer; @@ -261,7 +429,7 @@ procedure BoldAppendTostrings(Strings: TStrings; const aString: string; const Fo try TempStr := aString; for i := 1 to length(TempStr) do - if TempStr[i] in [BOLDLF, BOLDCR] then + if CharInSet(TempStr[i], [BOLDLF, BOLDCR]) then TempStr[i] := ' '; StrCount := Pred(Strings.Count); if (StrCount = -1) or ForceNewLine then @@ -282,6 +450,7 @@ procedure BoldAppendTostrings(Strings: TStrings; const aString: string; const Fo finally Strings.EndUpdate; end; +{$ENDIF} end; function BoldSeparatedAppend(const S1, S2: string; const Separator: string = ','): string; @@ -337,7 +506,6 @@ function CapitalisedToSpaced(Capitalised: String): String; Start: Integer; begin Result := ''; - //if Pos('Neo',Capitalised)= 1 then Start := 4 else Start := 1; Start := 1; for I := Start to Length(Capitalised) do if (I>1) and (Capitalised[I] >= 'A') and (Capitalised[I] <= 'Z') @@ -371,7 +539,6 @@ function GetUpperLimitForMultiplicity(const Multiplicity: String): Integer; var p: Integer; begin - // unspecified multilicity is 0..1 if (Multiplicity = '') or (BoldTrim(Multiplicity) = '') then result := 1 @@ -411,7 +578,7 @@ function IsLocalMachine(const Machinename: WideString): Boolean; MachName:= BoldTrim(MachineName); Result := (MachName = '') or (AnsiCompareText(GetComputerNameStr, MachName) = 0); end; - +{$IFDEF MSWINDOWS} function GetComputerNameStr: string; var Size: DWORD; @@ -421,6 +588,14 @@ function GetComputerNameStr: string; GetComputerName(LocalMachine, Size); Result := LocalMachine; end; +{$ENDIF} + +{$IFDEF LINUX} +function GetComputerNameStr: string; +begin + Result := 'MyMachine'; +end; +{$ENDIF} function TimeStampComp(const Time1, Time2: TTimeStamp): Integer; var @@ -441,13 +616,13 @@ function StrToDateFmt(const S: string; const DateFormat: string; const DateSepar PreviousShortDateFormat: string; PreviousDateSeparator: char; begin - PreviousShortDateFormat := FormatSettings.ShortDateFormat; - FormatSettings.ShortDateFormat := DateFormat; - PreviousDateSeparator := FormatSettings.DateSeparator; - FormatSettings.DateSeparator := DateSeparatorChar; + PreviousShortDateFormat := {$IFDEF BOLD_DELPHI16_OR_LATER}FormatSettings.{$ENDIF}ShortDateFormat; + {$IFDEF BOLD_DELPHI16_OR_LATER}FormatSettings.{$ENDIF}ShortDateFormat := DateFormat; + PreviousDateSeparator := {$IFDEF BOLD_DELPHI16_OR_LATER}FormatSettings.{$ENDIF}DateSeparator; + {$IFDEF BOLD_DELPHI16_OR_LATER}FormatSettings.{$ENDIF}DateSeparator := DateSeparatorChar; Result := StrToDateTime(S); - FormatSettings.ShortDateFormat := PreviousShortDateFormat; - FormatSettings.DateSeparator := PreviousDateSeparator; + {$IFDEF BOLD_DELPHI16_OR_LATER}FormatSettings.{$ENDIF}ShortDateFormat := PreviousShortDateFormat; + {$IFDEF BOLD_DELPHI16_OR_LATER}FormatSettings.{$ENDIF}DateSeparator := PreviousDateSeparator; end; function DateToStrFmt(const aDate: TDateTime; DateFormat: string; const DateSeparatorChar: char = '/'): String; @@ -455,13 +630,13 @@ function DateToStrFmt(const aDate: TDateTime; DateFormat: string; const DateSepa PreviousShortDateFormat: string; PreviousDateSeparator: char; begin - PreviousShortDateFormat := FormatSettings.ShortDateFormat; - FormatSettings.ShortDateFormat := DateFormat; - PreviousDateSeparator := FormatSettings.DateSeparator; - FormatSettings.DateSeparator := DateSeparatorChar; + PreviousShortDateFormat := {$IFDEF BOLD_DELPHI16_OR_LATER}FormatSettings.{$ENDIF}ShortDateFormat; + {$IFDEF BOLD_DELPHI16_OR_LATER}FormatSettings.{$ENDIF}ShortDateFormat := DateFormat; + PreviousDateSeparator := {$IFDEF BOLD_DELPHI16_OR_LATER}FormatSettings.{$ENDIF}DateSeparator; + {$IFDEF BOLD_DELPHI16_OR_LATER}FormatSettings.{$ENDIF}DateSeparator := DateSeparatorChar; Result := DateToStr(aDate); - FormatSettings.ShortDateFormat := PreviousShortDateFormat; - FormatSettings.DateSeparator := PreviousDateSeparator; + {$IFDEF BOLD_DELPHI16_OR_LATER}FormatSettings.{$ENDIF}ShortDateFormat := PreviousShortDateFormat; + {$IFDEF BOLD_DELPHI16_OR_LATER}FormatSettings.{$ENDIF}DateSeparator := PreviousDateSeparator; end; function BoldVariantToStrings(V: OleVariant; Strings: TStrings): Integer; @@ -518,8 +693,11 @@ function BoldParseFormattedDateList(const Value: String; const formats: TStrings else if not (value[i] = format[i]) then exit; end; - if (format[i] in ['y', 'm', 'd']) and not (value[i] in ['0'..'9']) then + if CharInSet(format[i], ['y', 'm', 'd']) and + (not CharInSet(value[i], ['0'..'9'])) then + begin exit; + end; end; if length(y) = 0 then year := CurrentYear @@ -528,7 +706,7 @@ function BoldParseFormattedDateList(const Value: String; const formats: TStrings year := StrToInt(y); if length(y) = 2 then begin - if year < ((CurrentYear + FormatSettings.TwoDigitYearCenturyWindow) mod 100) then + if year < ((CurrentYear + {$IFDEF BOLD_DELPHI16_OR_LATER}FormatSettings.{$ENDIF}TwoDigitYearCenturyWindow) mod 100) then year := year + (CurrentYear div 100)*100 else year := year + ((CurrentYear div 100)+1)*100; diff --git a/Source/Common/Support/BoldXMLStreaming.pas b/Source/Common/Support/BoldXMLStreaming.pas index 6f9b380..3dad0d4 100644 --- a/Source/Common/Support/BoldXMLStreaming.pas +++ b/Source/Common/Support/BoldXMLStreaming.pas @@ -1,9 +1,13 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldXMLStreaming; interface uses - MSXML_TLB, + {$IFDEF OXML}OXmlPDOM{$ELSE}MSXML_TLB{$ENDIF}, + BoldDefs, BoldBase, BoldStreams, BoldIndexableList, @@ -41,23 +45,28 @@ TBoldXMLStreamStateManager = class(TBoldMemoryManagedObject) { TBoldXMLNode } TBoldXMLNode = class(TBoldMemoryManagedObject) private - fNode: IXMLDOMElement; + fNode: {$IFDEF OXML}PXMLNode{$ELSE}IXMLDOMElement{$ENDIF}; fManager: TBoldXMLStreamManager; fStateManager: TBoldXMLStreamStateManager; procedure EnsureType(const DynamicStreamName, StaticStreamName: string); function GetType(const StaticStreamName: string): string; + {$IFNDEF OXML} function GetDocument: IXMLDOMDocument; property Document: IXMLDOMDocument read GetDocument; + {$ENDIF} function GetAccessor: string; function GetIsNull: Boolean; public - constructor Create(Manager: TBoldXMLStreamManager; Node: IXMLDomElement; StreamStateManager: TBoldXMLStreamStateManager); + constructor Create(Manager: TBoldXMLStreamManager; Node: + {$IFDEF OXML}PXMLNode{$ELSE}IXMLDOMElement{$ENDIF}; StreamStateManager: + TBoldXMLStreamStateManager); function GetSubNode(const Accessor: string): TBoldXMLNode; function IsEmpty: Boolean; function NewSubNode(const Accessor: string): TBoldXMLNode; - function MakeNodeForElement(Element: IXMLDOMElement): TBoldXMLNode; + function MakeNodeForElement(Element: + {$IFDEF OXML}PXMLNode{$ELSE}IXMLDOMElement{$ENDIF}): TBoldXMLNode; function ReadBoolean: Boolean; - procedure ReadInterface(const StreamName: string; Item: IBoldStreamable); + procedure ReadInterface(const StreamName: string; const Item: IBoldStreamable); function ReadInteger: Integer; function ReadObject(const StreamName: string): TObject; function ReadString: string; @@ -65,19 +74,20 @@ TBoldXMLNode = class(TBoldMemoryManagedObject) function ReadCurrency: Currency; function ReadSubNodeBoolean(const Accessor: string): Boolean; function ReadSubNodeInteger(const Accessor: string): Integer; - function ReadSubNodeObject(const Accessor: string; const StreamName: string): TObject; - function ReadSubNodeString(const Accessor: string): String; //The caller of this function should take care of freeing the result object + function ReadSubNodeObject(const Accessor, StreamName: string): TObject; //The caller of this function should take care of freeing the result object + function ReadSubNodeString(const Accessor: string): String; function ReadSubNodeFloat(const Accessor: string): Double; procedure WriteBoolean(Value: Boolean); procedure WriteInteger(Value: Integer); - procedure WriteInterface(const StaticStreamName: string; Item: IBoldStreamable); + procedure WriteInterface(const StaticStreamName: string; const Item: IBoldStreamable); procedure WriteObject(const StaticStreamName: string; Obj: TBoldInterfacedObject); procedure WriteString(const Value: string); procedure WriteFloat(value: Double); procedure WriteCurrency(value: Currency); procedure WriteSubNodeBoolean(const Accessor: string; Value: Boolean); procedure WriteSubNodeInteger(const Accessor: string; Value: Integer); - procedure WriteSubNodeObject(const Accessor: string; const StaticStreamName: string; Obj: TBoldInterfacedObject); + procedure WriteSubNodeObject(const Accessor, StaticStreamName: string; Obj: + TBoldInterfacedObject); procedure WriteSubNodeString(const Accessor: string; const Value: String); procedure WriteSubNodeFloat(const Accessor: string; Value: Double); @@ -96,16 +106,17 @@ TBoldXMLNode = class(TBoldMemoryManagedObject) procedure WriteDateTime(Value: TDateTime); procedure WriteSubNodeDateTime(const Accessor: string; Value: TDateTime); - function ReadData: string; - function ReadSubNodeData(const Accessor: string): string; - procedure WriteData(Value: string); - procedure WriteSubNodeData(const Accessor: string; const Value: string); + function ReadData: TBoldAnsiString; + function ReadSubNodeData(const Accessor: string): TBoldAnsiString; + procedure WriteData(Value: TBoldAnsiString); + procedure WriteSubNodeData(const Accessor: string; const Value: TBoldAnsiString); procedure AddStateObject(const Name: string; StateObject: TObject); procedure RemoveStateObject(const Name: string); function GetStateObject(const Name: String): TObject; property Manager: TBoldXMLStreamManager read fManager; - property XMLDomElement: IXMLDOMElement read fNode; + property XMLDomElement: {$IFDEF OXML}PXMLNode{$ELSE}IXMLDOMElement{$ENDIF} + read fNode; property Accessor: string read GetAccessor; property IsNull: Boolean read GetIsNull; procedure SetToNull; @@ -132,10 +143,16 @@ TBoldXMLStreamManager = class(TBoldMemoryManagedObject) fRegistry: TBoldXMLStreamerRegistry; public constructor Create(Registry: TBoldXMLStreamerRegistry); - function GetRootNode(Document: TDomDocument; const Accessor: string): TBoldXMLNode; - function NewRootNode(Document: TDomDocument; const Accessor: string): TBoldXMLNode; - function GetSOAP(Document: TDomDocument): TBoldXMLNode; - function NewSOAP(Document: TDomDocument): TBoldXMLNode; + function GetRootNode(Document: + {$IFDEF OXML}TXMLDocument{$ELSE}TDomDocument{$ENDIF}; const Accessor: + string): TBoldXMLNode; + function NewRootNode(Document: + {$IFDEF OXML}TXMLDocument{$ELSE}TDomDocument{$ENDIF}; const Accessor: + string): TBoldXMLNode; + function GetSOAP(Document: + {$IFDEF OXML}TXMLDocument{$ELSE}TDomDocument{$ENDIF}): TBoldXMLNode; + function NewSOAP(Document: + {$IFDEF OXML}TXMLDocument{$ELSE}TDomDocument{$ENDIF}): TBoldXMLNode; property Registry: TBoldXMLStreamerRegistry read fRegistry; end; @@ -167,19 +184,18 @@ TBoldXMLObjectStreamer = class(TBoldXMLStreamer) { TBoldXMLInterfaceStreamer } TBoldXMLInterfaceStreamer = class(TBoldXMLStreamer) public - procedure WriteInterface(Item: IBoldStreamable; Node: TBoldXMLNode); virtual; - procedure ReadInterface(Item: IBoldStreamable; Node: TBoldXMLNode); virtual; + procedure WriteInterface(const Item: IBoldStreamable; Node: TBoldXMLNode); virtual; + procedure ReadInterface(const Item: IBoldStreamable; Node: TBoldXMLNode); virtual; end; implementation uses SysUtils, - BoldUtils, - BoldDefs, BoldHashIndexes, + {$IFDEF OXML}OXmlUtils,{$ENDIF} BoldBase64, - BoldCommonConst; + BoldUtils; const BoldNodeName_Year = 'Year'; @@ -207,20 +223,21 @@ TBoldXMLStreamerIndex = class(TBoldStringHashIndex) procedure PushFloatSettings; begin if FloatSettingsPushed then - raise EBold.Create(sCannotNestPushFloat); + raise EBold.Create('Nested calls to PushFloatSettings not allowed'); FloatSettingsPushed := true; - oldDecimalSeparator := FormatSettings.DecimalSeparator; - FormatSettings.DecimalSeparator := '.'; - oldThousandSeparator := FormatSettings.ThousandSeparator; - FormatSettings.ThousandSeparator := ','; + FloatSettingsPushed := true; + oldDecimalSeparator := {$IFDEF BOLD_DELPHI16_OR_LATER}FormatSettings.{$ENDIF}DecimalSeparator; + {$IFDEF BOLD_DELPHI16_OR_LATER}FormatSettings.{$ENDIF}DecimalSeparator := '.'; + oldThousandSeparator := {$IFDEF BOLD_DELPHI16_OR_LATER}FormatSettings.{$ENDIF}ThousandSeparator; + {$IFDEF BOLD_DELPHI16_OR_LATER}FormatSettings.{$ENDIF}ThousandSeparator := ','; end; procedure PopFloatSettings; begin if not FloatSettingsPushed then - raise EBold.Create(sPushNestMismatch); - FormatSettings.DecimalSeparator := oldDecimalSeparator; - FormatSettings.ThousandSeparator := oldThousandSeparator; + raise EBold.Create('Not allowed to call PopFloatSettins without previous call to PushFloatSettings'); + {$IFDEF BOLD_DELPHI16_OR_LATER}FormatSettings.{$ENDIF}DecimalSeparator := oldDecimalSeparator; + {$IFDEF BOLD_DELPHI16_OR_LATER}FormatSettings.{$ENDIF}ThousandSeparator := oldThousandSeparator; oldDecimalSeparator := '*'; oldThousandSeparator := '#'; FloatSettingsPushed := false; @@ -257,7 +274,7 @@ function TBoldXMLStreamerRegistry.GetStreamer(const Name: string): TBoldXMLStrea result := fParentRegistry.GetStreamer(Name); if not assigned(result) then - raise EBoldInternal.CreateFmt(sStreamerNotFound, [classname, name]); + raise EBoldInternal.CreateFmt('%s.GetStreamer: streamer for %s not found', [classname, name]); end; class function TBoldXMLStreamerRegistry.MainStreamerRegistry: TBoldXMLStreamerRegistry; @@ -280,7 +297,7 @@ procedure TBoldXMLObjectStreamer.ReadObject(Obj: TObject; Node: TBoldXMLNode); procedure TBoldXMLObjectStreamer.WriteObject(Obj: TBoldInterfacedObject; Node: TBoldXMLNode); begin -end; +end; { TBoldXMLNode } @@ -312,13 +329,24 @@ function TBoldXMLNode.ReadObject(const StreamName: string): TObject; end; function TBoldXMLNode.GetSubNode(const Accessor: string): TBoldXMLNode; +{$IFDEF OXML} +var + aNode: PXMLNode; +begin + Result := nil; + if FNode.ChildNodes.FindNode(Accessor, aNode) then begin + if aNode.NodeType = ntElement then begin + Result := TBoldXMLNode.Create(FManager, aNode, FStateManager); + end; + end; +end; +{$ELSE} var aList: IXMLDOMNodeList; aNode: IXMLDOMNode; anElement: IXMLDOMElement; begin - // this sucks. We shouldn't have to iterate our selves, but using - // GetElementsByTagName searches also lower levels than true child-nodes :-( + result := nil; aList := fNode.childNodes; aNode := aList.nextNode; @@ -336,56 +364,72 @@ function TBoldXMLNode.GetSubNode(const Accessor: string): TBoldXMLNode; aNode := aList.nextNode; end; end; +{$ENDIF} -constructor TBoldXMLNode.Create(Manager: TBoldXMLStreamManager; Node: IXMLDomElement; StreamStateManager: TBoldXMLStreamStateManager); +constructor TBoldXMLNode.Create(Manager: TBoldXMLStreamManager; Node: + {$IFDEF OXML}PXMLNode{$ELSE}IXMLDOMElement{$ENDIF}; StreamStateManager: + TBoldXMLStreamStateManager); begin fNode := Node; fManager := Manager; fStatemanager := StreamStateManager; end; +{$IFNDEF OXML} +function TBoldXMLNode.GetDocument: IXMLDOMDocument; +begin + result := fNode.ownerDocument; +end; +{$ENDIF} + function TBoldXMLNode.NewSubNode(const Accessor: string): TBoldXMLNode; var - aNode: IXMLDOMElement; + aNode: {$IFDEF OXML}PXMLNode{$ELSE}IXMLDOMElement{$ENDIF}; begin + {$IFDEF OXML} + aNode := fNode.AddChild(Accessor); + {$ELSE} aNode := Document.createElement(Accessor); fNode.appendChild(aNode); - result := TBoldXMLNode.Create(fManager, aNode, fStatemanager); + {$ENDIF} + result := TBoldXMLNode.Create(fManager, aNode, fStateManager); end; procedure TBoldXMLNode.WriteString(const Value: string); begin + {$IFDEF OXML} + fNode.AddText(Value); + {$ELSE} fNode.appendChild(Document.createTextNode(Value)); + {$ENDIF} end; function TBoldXMLNode.ReadString: string; var - aNode: IXMLDOMNode; + aNode: {$IFDEF OXML}PXMLNode{$ELSE}IXMLDOMNode{$ENDIF}; begin - aNode := fNode.childNodes.nextNode; - if assigned(aNode) and (aNode.nodeType = NODE_TEXT) then - result := aNode.Text - else + aNode := {$IFDEF OXML}fNode.ChildNodes.GetFirst + {$ELSE}fNode.childNodes.nextNode{$ENDIF}; + if assigned(aNode) and (aNode.nodeType = + {$IFDEF OXML}ntText{$ELSE}NODE_TEXT{$ENDIF}) then + begin + result := aNode.Text; + end else begin result := ''; + end; end; function TBoldXMLNode.ReadBoolean: Boolean; begin - result := (ReadString = '1'); //do not localize + result := ReadString = '1'; end; procedure TBoldXMLNode.WriteBoolean(Value: Boolean); begin if Value then - WriteString('1') //do not localize + WriteString('1') else - WriteString('0'); //do not localize -end; - -function TBoldXMLNode.GetDocument: IXMLDOMDocument; -begin - result := fNode.ownerDocument; -// result := fManager.fDocument; + WriteString('0'); end; function TBoldXMLNode.ReadInteger: Integer; @@ -398,7 +442,7 @@ procedure TBoldXMLNode.WriteInteger(Value: Integer); WriteString(IntToStr(Value)); end; -procedure TBoldXMLNode.WriteInterface(const StaticStreamName: string; Item: IBoldStreamable); +procedure TBoldXMLNode.WriteInterface(const StaticStreamName: string; const Item: IBoldStreamable); var DynamicStreamName: string; begin @@ -413,7 +457,7 @@ procedure TBoldXMLNode.EnsureType(const DynamicStreamName, StaticStreamName: str fNode.setAttribute(BoldSOAPTypeAttributeName, DynamicStreamName); end; -procedure TBoldXMLNode.ReadInterface(const StreamName: string; Item: IBoldStreamable); +procedure TBoldXMLNode.ReadInterface(const StreamName: string; const Item: IBoldStreamable); var aStreamer: TBoldXMLInterfaceStreamer; begin @@ -423,13 +467,14 @@ procedure TBoldXMLNode.ReadInterface(const StreamName: string; Item: IBoldStream function TBoldXMLNode.GetType(const StaticStreamName: string): string; var - anAttr: IXMLDOMAttribute; + anAttr: {$IFDEF OXML}PXMLNode{$ELSE}IXMLDOMAttribute{$ENDIF}; begin anAttr := fNode.getAttributeNode(BoldSOAPTypeAttributeName); - if assigned(anAttr) then - result := anAttr.Value - else + if assigned(anAttr) then begin + result := {$IFDEF OXML}anAttr.NodeValue{$ELSE}anAttr.Value{$ENDIF}; + end else begin result := StaticStreamName; + end; end; function TBoldXMLNode.GetAccessor: string; @@ -441,8 +486,6 @@ function TBoldXMLNode.IsEmpty: Boolean; begin result := not XMLDomElement.hasChildNodes; end; - -// The caller of this function should take care of freeing the returned object function TBoldXMLNode.ReadSubNodeObject(const Accessor, StreamName: string): TObject; var aSubNode: TBoldXMLNode; @@ -556,8 +599,11 @@ function TBoldXMLNode.ReadFloat: Double; procedure TBoldXMLNode.WriteFloat(value: Double); begin PushFloatSettings; - WriteString(FloatToStr(Value)); - PopFloatSettings; + try + WriteString(FloatToStr(Value)); + finally + PopFloatSettings; + end; end; function TBoldXMLNode.ReadSubNodeFloat(const Accessor: string): Double; @@ -609,7 +655,8 @@ procedure TBoldXMLNode.RemoveStateObject(const Name: string); end; end; -function TBoldXMLNode.MakeNodeForElement(Element: IXMLDOMElement): TBoldXMLNode; +function TBoldXMLNode.MakeNodeForElement(Element: + {$IFDEF OXML}PXMLNode{$ELSE}IXMLDOMElement{$ENDIF}): TBoldXMLNode; begin result := TBoldXMLNode.Create(Manager, Element, fStateManager); end; @@ -734,15 +781,15 @@ procedure TBoldXMLNode.WriteSubNodeDateTime(const Accessor: string; end; end; -procedure TBoldXMLNode.WriteData(Value: string); +procedure TBoldXMLNode.WriteData(Value: TBoldAnsiString); - function IncludesIllegalChar(Value: string): Boolean; + function IncludesIllegalChar(Value: TBoldAnsiString): Boolean; var i: Integer; begin result := true; for i := 1 to Length(Value) do - if not (Value[i] in [#9, BOLDLF, BOLDCR, #32..#255]) then + if not CharInSet(Value[i], [#9, BOLDLF, BOLDCR, #32..#255]) then exit; result := false; end; @@ -755,36 +802,38 @@ procedure TBoldXMLNode.WriteData(Value: string); begin Encoder := TBase64.Create; Encoder.EncodeData(Value, DataString); - XMLDomElement.setAttribute('dt', 'binary.base64'); // do not localize + XMLDomElement.setAttribute('dt', 'binary.base64'); Encoder.Free; end else - DataString := Value; + DataString := String(Value); WriteString(DataString); end; -function TBoldXMLNode.ReadData: string; +function TBoldXMLNode.ReadData: TBoldAnsiString; var - anAttr: IXMLDOMAttribute; + anAttr: {$IFDEF OXML}PXMLNode{$ELSE}IXMLDOMAttribute{$ENDIF}; DataString: string; Decoder: TBase64; begin DataString := ReadString; anAttr := fNode.getAttributeNode('dt'); // do not localize - if assigned(anAttr) and (anAttr.Value = 'binary.base64') then // do not localize + if assigned(anAttr) and ( + {$IFDEF OXML}anAttr.NodeValue{$ELSE}anAttr.Value{$ENDIF} = 'binary.base64') then // do not localize begin Decoder := TBase64.Create; - Decoder.DecodeData(DataString, result); + Decoder.DecodeData(DataString, Result); Decoder.Free; end else - result := DataString; + result := TBoldAnsiString(DataString); // without Base64 there are only AnsiChars end; function TBoldXMLNode.GetIsNull: Boolean; var - anAttr: IXMLDOMAttribute; + anAttr: {$IFDEF OXML}PXMLNode{$ELSE}IXMLDOMAttribute{$ENDIF}; begin anAttr := XMLDomElement.getAttributeNode(BoldSOAPNullAttributeName); - result := assigned(anAttr) and (anAttr.Value = '1'); + result := assigned(anAttr) and ( + {$IFDEF OXML}anAttr.NodeValue{$ELSE}anAttr.Value{$ENDIF} = '1'); end; procedure TBoldXMLNode.SetToNull; @@ -792,7 +841,7 @@ procedure TBoldXMLNode.SetToNull; XMLDomElement.setAttribute(BoldSOAPNullAttributeName, '1'); end; -function TBoldXMLNode.ReadSubNodeData(const Accessor: string): string; +function TBoldXMLNode.ReadSubNodeData(const Accessor: string): TBoldAnsiString; var aSubNode: TBoldXMLNode; begin @@ -804,7 +853,7 @@ function TBoldXMLNode.ReadSubNodeData(const Accessor: string): string; end; end; -procedure TBoldXMLNode.WriteSubNodeData(const Accessor, Value: string); +procedure TBoldXMLNode.WriteSubNodeData(const Accessor: string; const Value: TBoldAnsiString); var aSubNode: TBoldXMLNode; begin @@ -839,11 +888,11 @@ procedure TBoldXMLNode.WriteCurrency(value: Currency); { TBoldXMLInterfaceStreamer } -procedure TBoldXMLInterfaceStreamer.ReadInterface(Item: IBoldStreamable; Node: TBoldXMLNode); +procedure TBoldXMLInterfaceStreamer.ReadInterface(const Item: IBoldStreamable; Node: TBoldXMLNode); begin end; -procedure TBoldXMLInterfaceStreamer.WriteInterface(Item: IBoldStreamable; Node: TBoldXMLNode); +procedure TBoldXMLInterfaceStreamer.WriteInterface(const Item: IBoldStreamable; Node: TBoldXMLNode); begin end; @@ -854,20 +903,27 @@ constructor TBoldXMLStreamManager.Create(Registry: TBoldXMLStreamerRegistry); fRegistry := Registry; end; -function TBoldXMLStreamManager.GetRootNode(Document: TDomDocument; const Accessor: string): TBoldXMLNode; +function TBoldXMLStreamManager.GetRootNode(Document: + {$IFDEF OXML}TXMLDocument{$ELSE}TDomDocument{$ENDIF}; const Accessor: + string): TBoldXMLNode; +var + sTagName: string; begin if not assigned(Document) then - raise EBold.CreateFmt(sStreamerNotConnected, [classname, 'GetRootNode']); //do not localize + raise EBold.CreateFmt('%s.GetRootNode: Streamer is not connected to a Document', [classname]); if not assigned(Document.documentElement) then - raise EBold.CreateFmt(sDocumentHasNoRootNode, [classname]); - if (Accessor <> '') and (Document.documentElement.tagName <> Accessor) then - raise EBold.CreateFmt(sWrongTagName, - [classname, Document.documentElement.tagName, Accessor]); + raise EBold.CreateFmt('%s.GetRootNode: Document does not have root node', [classname]); + sTagName := {$IFDEF OXML}Document.documentElement.NodeName{$ELSE} + Document.documentElement.tagName{$ENDIF}; + if (Accessor <> '') and (sTagName <> Accessor) then + raise EBold.CreateFmt('%s.GetRootNode: Wrong tag name, is %s, should be %s', + [classname, sTagName, Accessor]); result := TBoldXMLNode.Create(self, Document.documentElement, nil); end; -function TBoldXMLStreamManager.GetSOAP(Document: TDomDocument): TBoldXMLNode; +function TBoldXMLStreamManager.GetSOAP(Document: + {$IFDEF OXML}TXMLDocument{$ELSE}TDomDocument{$ENDIF}): TBoldXMLNode; var aNode: TBoldXMLNode; begin @@ -876,27 +932,30 @@ function TBoldXMLStreamManager.GetSOAP(Document: TDomDocument): TBoldXMLNode; aNode.Free; end; -function TBoldXMLStreamManager.NewRootNode(Document: TDomDocument; const Accessor: string): TBoldXMLNode; +function TBoldXMLStreamManager.NewRootNode(Document: + {$IFDEF OXML}TXMLDocument{$ELSE}TDomDocument{$ENDIF}; const Accessor: + string): TBoldXMLNode; begin if not assigned(Document) then - raise EBold.CreateFmt(sStreamerNotConnected, [classname, 'NewRootNode']); // do not localize + raise EBold.CreateFmt('%s.NewRootNode: Streamer is not connected to a Document', [classname]); if assigned(Document.documentElement) then - raise EBold.CreateFmt(sDocumentHasRootNode, [classname]); + raise EBold.CreateFmt('%s.NewRootNode: Document already has root node', [classname]); Document.documentElement := Document.createElement(Accessor); result := TBoldXMLNode.Create(self, Document.documentElement, nil); - result.XMLDomElement.setAttribute('xmlns:xsi', 'http://www.w3.org/1999/XMLSchema-instance'); // do not localize - result.XMLDomElement.setAttribute('xml:space', 'preserve'); // do not localize + result.XMLDomElement.setAttribute('xmlns:xsi', 'http://www.w3.org/1999/XMLSchema-instance'); + result.XMLDomElement.setAttribute('xml:space', 'preserve'); end; -function TBoldXMLStreamManager.NewSOAP(Document: TDomDocument): TBoldXMLNode; +function TBoldXMLStreamManager.NewSOAP(Document: + {$IFDEF OXML}TXMLDocument{$ELSE}TDomDocument{$ENDIF}): TBoldXMLNode; var aNode: TBoldXMLNode; begin - aNode := NewRootNode(Document, 'SOAP-ENV:Envelope'); // do not localize - aNode.XMLDomElement.setAttribute('xmlns:SOAP-ENV', 'http://schemas.xmlsoap.org/soap/envelope/'); // do not localize - aNode.XMLDomElement.setAttribute('SOAP-ENV:encodingStyle', 'http://schemas.xmlsoap.org/soap/encoding/'); // do not localize - result := aNode.NewSubNode('SOAP-ENV:Body'); // do not localize + aNode := NewRootNode(Document, 'SOAP-ENV:Envelope'); + aNode.XMLDomElement.setAttribute('xmlns:SOAP-ENV', 'http://schemas.xmlsoap.org/soap/envelope/'); + aNode.XMLDomElement.setAttribute('SOAP-ENV:encodingStyle', 'http://schemas.xmlsoap.org/soap/encoding/'); + result := aNode.NewSubNode('SOAP-ENV:Body'); aNode.Free; end; @@ -914,10 +973,10 @@ constructor TBoldXMLStreamStateManager.create; fStateObjectList.Sorted := true; end; -destructor TBoldXMLStreamStateManager.Destroy; +destructor TBoldXMLStreamStateManager.destroy; begin freeAndNil(fStateObjectList); - inherited; + inherited; end; function TBoldXMLStreamStateManager.GetEmpty: Boolean; @@ -967,7 +1026,7 @@ function TBoldXMLStreamerIndex.ItemASKeyString(Item: TObject): string; result := TBoldXMLStreamer(Item).StreamName; end; -initialization // empty +initialization finalization FreeAndNil(G_MainRegistry); diff --git a/Source/Common/SupportWin/BoldThread.pas b/Source/Common/SupportWin/BoldThread.pas index 4f69f00..52fd239 100644 --- a/Source/Common/SupportWin/BoldThread.pas +++ b/Source/Common/SupportWin/BoldThread.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldThread; interface @@ -44,9 +47,9 @@ implementation uses SysUtils, Messages, - BoldPropagatorConstants, { TODO : Move TIMEOUT to BoldDefs } - BoldThreadSafeLog, - BoldCommonConst; + BoldPropagatorConstants, + BoldThreadSafeLog, + BoldRev; function WaitForObject (iHandle : THandle; iTimeOut : dword) : TWaitResult; begin @@ -83,12 +86,14 @@ procedure TBoldNotifiableThread.EnsureMessageQueue; var rMsg:TMsg; begin - PeekMessage(rMsg, 0, 0, 0, PM_NOREMOVE); // force thread message queue! + PeekMessage(rMsg, 0, 0, 0, PM_NOREMOVE); end; +{$Assertions On} + procedure TBoldNotifiableThread.Notify(const Msg: Cardinal); begin - PostThreadMessage(ThreadID, Msg, 0, 0); + Assert(PostThreadMessage(ThreadID, Msg, 0, 0), SysErrorMessage(GetLastError)); end; function TBoldNotifiableThread.WaitUntilReady(dwMilliseconds: Cardinal): Boolean; @@ -112,7 +117,7 @@ function TBoldNotifiableThread.Quit(Wait: Boolean): Boolean; begin Resume; WaitUntilReady(TIMEOUT); - SwitchToThread; //REVIEW ME + SwitchToThread; end; if not (Terminated) then begin @@ -121,7 +126,7 @@ function TBoldNotifiableThread.Quit(Wait: Boolean): Boolean; Result := WaitForQuit else Result := (WaitForObject(Handle, Timeout*2) = wrSignaled); - end; + end; end; procedure TBoldNotifiableThread.Execute; @@ -134,11 +139,10 @@ procedure TBoldNotifiableThread.Execute; while not Terminated do begin res := Integer(GetMessage(rMsg, 0, 0, 0)); - if res = -1 then //error + if res = -1 then Terminate - else if res = 0 then // terminated + else if res = 0 then Terminate - //handle message else ProcessMessage(rMsg); end; @@ -161,26 +165,23 @@ function TBoldNotifiableThread.WaitForQuit: Boolean; Result := false; try Assert(ThreadId <> GetCurrentThreadId, - 'Message queue thread cannot be terminated from within its own thread!!!' // do not localize + 'Message queue thread cannot be terminated from within its own thread!!!' ); wr := WaitForObject(Handle, timeout*5); - - //if thread is not properly terminated, then force terminate it Result := (wr = wrSignaled); if (wr <> wrSignaled) then begin TerminateThread (Handle, 1); - BoldLogError(sThreadWasForcedTerminated, [ClassName]); + BoldLogError('%s.WaitForQuit: thread was force terminated', [ClassName]); end; except on E:Exception do - BoldLogError(sErrorWaitForQuit, [ClassName, E.Message]); + BoldLogError('%s.WaitForQuit: %s', [ClassName, E.Message]); end; end; class procedure TBoldNotifiableThread.CreateQueueWindow( var ServerWindow: HWnd); begin - //impelement in subsclasses that use queue windows end; procedure TBoldNotifiableThread.InitServerWindow(bInit: boolean); @@ -204,4 +205,6 @@ destructor TBoldNotifiableThread.Destroy; inherited; end; +initialization + end. diff --git a/Source/Common/SupportWin/BoldWinINet.pas b/Source/Common/SupportWin/BoldWinINet.pas index 1caebff..1505ed2 100644 --- a/Source/Common/SupportWin/BoldWinINet.pas +++ b/Source/Common/SupportWin/BoldWinINet.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldWinINet; interface @@ -50,7 +53,7 @@ implementation SysUtils, BoldUtils; -{.$IFDEF BOLD_DELPHI} // marco +{$IFDEF BOLD_DELPHI} function BoldInternetOpen(Agent: String; AccessType: integer; Proxy: string; ProxyByPass: String; Flags: integer): pointer; begin result := InternetOpen(PChar(Agent), AccessType, PChar(Proxy), PChar(ProxyByPass), flags); @@ -111,85 +114,70 @@ function BoldInternetCrackUrl(Url: PChar; UrlLength, dwFlags: DWORD; var lpUrlCo begin result := InternetCrackURL(URL, UrlLength, dwFlags, lpUrlComponents); end; -{.$ENDIF} +{$ENDIF} {$IFDEF BOLD_BCB} - -function Unimplemented(const s: string); -begin - raise EBoldFeatureNotImplementedYet.CreateFmt('%s not yet implemented in Bold for C++', [s]); // do not localize -end; function BoldInternetOpen(Agent: String; AccessType: integer; Proxy: string; ProxyByPass: String; Flags: integer): pointer; begin - Unimplemented('BoldInternetOpen'); // do not localize -// result := InternetOpen(PChar(Agent), AccessType, PChar(Proxy), PChar(ProxyByPass), flags); + raise EBoldFeatureNotImplementedYet.Create('BoldInternetOpen now yet implemented in Bold for C++'); end; function BoldInternetOpenUrl(iNet: Pointer; URL: string; Headers: String; Flags, Context: cardinal): Pointer; begin - Unimplemented('BoldInternetOpenUrl'); // do not localize -// result := InternetOpenURL(iNet, pChar(Url), PChar(Headers), length(Headers), Flags, Context); + raise EBoldFeatureNotImplementedYet.Create('BoldInternetOpenUrl now yet implemented in Bold for C++'); end; function BoldInternetReadFile(hFile: Pointer; Buffer: Pointer; NumberOfBytesToRead: Cardinal; var NumberOfBytesRead: Cardinal): LongBool; begin - Unimplemented('BoldInternetReadFile'); // do not localize -// result := InternetReadFile(hFile, Buffer, NumberOfBytesToRead, NumberOfBytesRead); + raise EBoldFeatureNotImplementedYet.Create('BoldInternetReadFile now yet implemented in Bold for C++'); end; function BoldInternetCloseHandle(HINet: Pointer): LongBool; begin - Unimplemented('BoldInternetCloseHandle'); // do not localize -// result := InternetCloseHandle(hInet); + raise EBoldFeatureNotImplementedYet.Create('BoldInternetCloseHandle now yet implemented in Bold for C++'); end; function BoldHttpQueryInfo(hRequest: Pointer; InfoLevel: Cardinal; Buffer: Pointer; BufferLength: Cardinal; Reserved: Cardinal): LongBool; begin - Unimplemented('BoldHttpQueryInfo'); // do not localize -// result := HTTPQueryInfo(hRequest, InfoLevel, Buffer, BufferLength, Reserved); + raise EBoldFeatureNotImplementedYet.Create('BoldHttpQueryInfo now yet implemented in Bold for C++'); end; function BoldInternetQueryDataAvailable(hFile: Pointer; var NumberOfBytesAvailable: Cardinal; flags: Cardinal; Context: Cardinal): LongBool; begin - Unimplemented('BoldInternetQueryDataAvailable'); // do not localize -// result := InternetQueryDataAvailable(hFile, NumberOfBytesAvailable, flags, Context) + raise EBoldFeatureNotImplementedYet.Create('BoldInternetQueryDataAvailable now yet implemented in Bold for C++'); end; function BoldHttpOpenRequest(hConnect: Pointer; Verb, ObjectName, Version, Referrer: String; AcceptTypes: PCharArr; Flags, Context: Cardinal): Pointer; begin - Unimplemented('BoldHttpOpenRequest'); // do not localize -// result := httpOpenRequest(hConnect, PChar(Verb), PChar(ObjectName), PChar(Version), PChar(Referrer), Pointer(AcceptTypes), Flags, Context) + raise EBoldFeatureNotImplementedYet.Create('BoldHttpOpenRequest now yet implemented in Bold for C++'); end; function BoldHttpSendRequest(hRequest: Pointer; Headers: string; Optional: Pointer; OptionalLength: Cardinal): LongBool; begin - Unimplemented('BoldHttpSendRequest'); // do not localize -// HttpSendRequest(hRequest, PChar(Headers), length(Headers), Optional, OptionalLength); + raise EBoldFeatureNotImplementedYet.Create('BoldHttpSendRequest now yet implemented in Bold for C++'); end; function BoldInternetErrorDlg(hWnd: HWND; hRequest: HINTERNET; dwError, dwFlags: DWORD; var lppvData: Pointer): DWORD; begin - Unimplemented('BoldInternetErrorDlg'); // do not localize -// result := InternetErrorDlg(hWnd, hRequest, dwError, dwFlags, lppvData); + raise EBoldFeatureNotImplementedYet.Create('BoldInternetErrorDlg now yet implemented in Bold for C++'); end; function BoldInternetAttemptConnect(dwReserved: DWORD): DWORD; begin - Unimplemented('BoldInternetAttemptConnect'); // do not localize -// result := InternetAttemptConnect(dwReserved); + raise EBoldFeatureNotImplementedYet.Create('BoldInternetAttemptConnect now yet implemented in Bold for C++'); end; function BoldInternetConnect(hInet: HINTERNET; ServerName: string; nServerPort: INTERNET_PORT; Username: string; Password: string; dwService: DWORD; dwFlags: DWORD; dwContext: DWORD): HINTERNET; begin - Unimplemented('BoldInternetConnect'); // do not localize -// result := InternetConnect(hINet, PChar(ServerName), nServerPort, PChar(UserName), PChar(Password), dwService, dwFlags, dwContext); + raise EBoldFeatureNotImplementedYet.Create('BoldInternetConnect now yet implemented in Bold for C++'); end; function BoldInternetCrackUrl(Url: PChar; UrlLength, dwFlags: DWORD; var lpUrlComponents: TURLComponents): BOOL; begin - Unimplemented('BoldInternetCrackUrl'); // do not localize -// result := InternetCrackURL(URL, UrlLength, dwFlags, lpUrlComponents); + raise EBoldFeatureNotImplementedYet.Create('BoldInternetCrackUrl now yet implemented in Bold for C++'); end; {$ENDIF} +initialization + end. diff --git a/Source/Common/SupportWin/BoldWinUtils.pas b/Source/Common/SupportWin/BoldWinUtils.pas index 4b6df26..1695542 100644 --- a/Source/Common/SupportWin/BoldWinUtils.pas +++ b/Source/Common/SupportWin/BoldWinUtils.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldWinUtils; interface @@ -17,11 +20,13 @@ function GetTaskBarHeigth: Integer; var Parent, Child: HWND; ChildRect, ParentRect: TRect; begin - Parent := FindWindow('Progman', 'Program Manager'); // do not localize + Parent := FindWindow('Progman', 'Program Manager'); Child := FindWindowEx(Parent, 0, nil, nil); GetWindowRect(Parent, ParentRect); GetWindowRect(Child, ChildRect); Result := ParentRect.Bottom - ChildRect.Bottom; end; +initialization + end. diff --git a/Source/Common/TaggedValues/BoldDefaultTaggedValues.pas b/Source/Common/TaggedValues/BoldDefaultTaggedValues.pas index a18d9da..12fb56b 100644 --- a/Source/Common/TaggedValues/BoldDefaultTaggedValues.pas +++ b/Source/Common/TaggedValues/BoldDefaultTaggedValues.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldDefaultTaggedValues; interface @@ -7,11 +10,9 @@ interface BoldTaggedValueList; const - BOLDTVREV_MAJOR = '6'; // Increase when changing the default of Tagged values - BOLDTVREV_MINOR = '4'; // Increase when adding or removing Tagged values - BOLDTVREV = BOLDTVREV_MAJOR + '.' + BOLDTVREV_MINOR; - { TODO 1 : is changeability bold or stdvalue } - { TODO 1 : Should the common UML-TV:s be broken out? } + BOLDTVREV_MAJOR = '6'; + BOLDTVREV_MINOR = '4'; + BOLDTVREV = BOLDTVREV_MAJOR + '.' + BOLDTVREV_MINOR; {Genernal constants} @@ -21,74 +22,49 @@ interface TV_NAME_UPPERCASE: string = ''; TV_NAME_Length = 6; -const - DEFAULTVALUE = 'default'; - - // Tagged values of enum type - - // AttributeKind - TAG_ATTRIBUTEKIND: String = 'AttributeKind'; // used to be stereotype + TAG_ATTRIBUTEKIND: String = 'AttributeKind'; TV_ATTRIBUTEKIND_BOLD: String = 'Bold'; TV_ATTRIBUTEKIND_DELPHI: String = 'Delphi'; - - - // DeleteAction TAG_DELETEACTION: String = 'DeleteAction'; TV_DELETEACTION_DEFAULT: String = DEFAULTNAMELITERAL; TV_DELETEACTION_ALLOW: String = 'Allow'; TV_DELETEACTION_PROHIBIT: String = 'Prohibit'; TV_DELETEACTION_CASCADE: String = 'Cascade'; - - // DelphiPropertyRead/DelphiPropertyWrite TAG_DPREAD: String = 'DelphiPropertyRead'; TAG_DPWRITE: String = 'DelphiPropertyWrite'; - TV_DPNONE: String = 'None'; // FIXME, add underscore + TV_DPNONE: String = 'None'; TV_DPFIELD: String = 'Field'; TV_DPPRIVATEMETHOD: String = 'PrivateMethod'; TV_DPPROTECTEDVIRTUALMETHOD: String = 'ProtectedVirtualMethod'; - - // EvolutionState TAG_EVOLUTIONSTATE: String = 'EvolutionState'; TV_EVOLUTIONSTATE_NORMAL: String = 'Normal'; TV_EVOLUTIONSTATE_TOBEREMOVED: String = 'ToBeRemoved'; TV_EVOLUTIONSTATE_REMOVED: String = 'Removed'; - - // NatinalCharConversion TAG_NATIONALCHARCONVERSION: String = 'NationalCharConversion'; TV_NATIONALCHARCONVERSION_DEFAULT: String = DEFAULTNAMELITERAL; TV_NATIONALCHARCONVERSION_TRUE: String = 'True'; TV_NATIONALCHARCONVERSION_FALSE: String = 'False'; - - // OperationKind TAG_DELPHIOPERATIONKIND: String = 'OperationKind'; - TV_DELPHIOPERATIONKIND_NORMAL: String = 'Common'; // not 'Normal' for backwards compatibility reasons + TV_DELPHIOPERATIONKIND_NORMAL: String = 'Common'; TV_DELPHIOPERATIONKIND_VIRTUAL: String = 'Virtual'; TV_DELPHIOPERATIONKIND_OVERRIDE: String = 'Override'; TV_DELPHIOPERATIONKIND_DYNAMIC: String = 'Dynamic'; TV_DELPHIOPERATIONKIND_ABSTRACTVIRTUAL: String = 'Abstract'; - - // OptimisticLocking TAG_OPTIMISTICLOCKING: String = 'OptimisticLocking'; TV_OPTIMISTICLOCKING_DEFAULT: String = DEFAULTNAMELITERAL; TV_OPTIMISTICLOCKING_OFF: String = 'Off'; TV_OPTIMISTICLOCKING_MODIFIEDMEMBERS: String = 'ModifiedMembers'; TV_OPTIMISTICLOCKING_ALLMEMBERS: String = 'AllMembers'; TV_OPTIMISTICLOCKING_TIMESTAMP: String = 'TimeStamp'; - - // deprecated names for Optimistic Locking tagged values TV_OPTIMISTICLOCKING_MODIFIEDMEMBERS_OLDNAME: String = 'Member'; TV_OPTIMISTICLOCKING_ALLMEMBERS_OLDNAME: String = 'Class'; - - - // TableMapping TAG_TABLEMAPPING: String = 'TableMapping'; TV_TABLEMAPPING_OWN: String = 'Own'; TV_TABLEMAPPING_PARENT: String = 'Parent'; TV_TABLEMAPPING_CHILDREN: String = 'Children'; TV_TABLEMAPPING_IMPORTED: String = 'Imported'; - DEFAULTTABLEMAPPINGSTRING = 'Own'; //FIXME!! + DEFAULTTABLEMAPPINGSTRING = 'Own'; - // Storage TAG_STORAGE: String = 'Storage'; ENUM_TAG_CLASS_STORAGE: string = 'ClassStorageEnum'; ENUM_TAG_ATTRIBUTE_STORAGE: string = 'AttributeStorageEnum'; @@ -99,9 +75,7 @@ interface TV_STORAGE_EXTERNALKEY: String = 'ExternalKey'; - TV_PERSISTENT_OLD: String = 'Persistent'; - - // Tagged values of basic type + TV_PERSISTENT_OLD: String = 'Persistent'; TAG_ALLOWNULL: String = 'AllowNULL'; @@ -178,11 +152,9 @@ interface BOLDINTERALTVPREFIX = '_BoldInternal.'; TV_MODELERRORS = 'ModelErrors'; - - // Tags for boldification BOLDBOLDIFYPREFIX = '_Boldify.'; TAG_BOLDIFIED = 'boldified'; - TAG_AUTOCREATED = 'autoCreated'; // object + TAG_AUTOCREATED = 'autoCreated'; TAG_DEFAULTMULTIPLICITY = 'defaultMultiplicity'; TAG_NONAME = 'noName'; TAG_WASEMBEDED = 'wasEmbeded'; @@ -191,154 +163,143 @@ interface function BoldDefaultTaggedValueList: TBoldTaggedValuePerClassList; -function TVIsTrue(value: string): Boolean; -function TVIsFalse(value: string): Boolean; +function TVIsTrue(value: string): Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} +function TVIsFalse(value: string): Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} implementation uses - SysUtils, - BoldUtils; + SysUtils; var G_BoldDefaultTaggedValues: TBoldTaggedValuePerClassList = nil; procedure AddDefaultTaggedValues; begin -// Tagged values for Model - with G_BoldDefaultTaggedValues.ListForClassName['Model'] do // do not localize + with G_BoldDefaultTaggedValues.ListForClassName['Model'] do begin - Add('Boolean', TAG_GENERATEMULTIPLICITYCONSTRAINTS, TV_TRUE); // do not localize - Add('Text', TAG_INTERFACEUSES, ''); // do not localize - Add('Text', TAG_IMPLEMENTATIONUSES, ''); // do not localize - Add('Text', TAG_COPYRIGHTNOTICE, ''); // do not localize - Add('String', TAG_DEFAULTSUPERCLASS, ''); // do not localize - Add('String', TAG_DEFAULTLINKCLASSSUPERCLASS, ''); // do not localize - Add('String', TAG_UNITNAME, 'BusinessClasses'); // do not localize - Add('String', TAG_ROOTCLASS, ''); // do not localize - Add('String', TAG_PMAPPERNAME, DEFAULTNAMELITERAL); // do not localize - Add('Boolean', TAG_USEXFILES, TV_TRUE); // do not localize - Add('Boolean', TAG_USETIMESTAMP, TV_TRUE); // do not localize - Add('Boolean', TAG_USEGLOBALID, TV_TRUE); // do not localize - Add('Boolean', TAG_USEREADONLY, TV_TRUE); // do not localize - Add('Boolean', TAG_USEMODELVERSION, TV_FALSE); // do not localize - Add('Integer', TAG_MODELVERSION, '0'); // do not localize - Add('Boolean', TAG_USECLOCKLOG, TV_TRUE); // do not localize - Add('Boolean', TAG_UPDATEWHOLEOBJECTS, TV_FALSE); // do not localize - Add('OptimisticLockingSet', // do not localize + Add('Boolean', TAG_GENERATEMULTIPLICITYCONSTRAINTS, TV_TRUE); + Add('Text', TAG_INTERFACEUSES, ''); + Add('Text', TAG_IMPLEMENTATIONUSES, ''); + Add('Text', TAG_COPYRIGHTNOTICE, ''); + Add('String', TAG_DEFAULTSUPERCLASS, ''); + Add('String', TAG_DEFAULTLINKCLASSSUPERCLASS, ''); + Add('String', TAG_UNITNAME, 'BusinessClasses'); + Add('String', TAG_ROOTCLASS, ''); + Add('String', TAG_PMAPPERNAME, DEFAULTNAMELITERAL); + Add('Boolean', TAG_USEXFILES, TV_TRUE); + Add('Boolean', TAG_USETIMESTAMP, TV_TRUE); + Add('Boolean', TAG_USEGLOBALID, TV_TRUE); + Add('Boolean', TAG_USEREADONLY, TV_TRUE); + Add('Boolean', TAG_USEMODELVERSION, TV_FALSE); + Add('Integer', TAG_MODELVERSION, '0'); + Add('Boolean', TAG_USECLOCKLOG, TV_TRUE); + Add('Boolean', TAG_UPDATEWHOLEOBJECTS, TV_FALSE); + Add('OptimisticLockingSet', TAG_OPTIMISTICLOCKING, TV_OPTIMISTICLOCKING_OFF); - Add('NationalCharConversionEnum', // do not localize + Add('NationalCharConversionEnum', TAG_NATIONALCHARCONVERSION, TV_NATIONALCHARCONVERSION_DEFAULT); - Add('String', TAG_GUID, ''); // do not localize - Add('String', TAG_TYPELIBVERSION, '1.0'); // do not localize - Add('Text', TAG_REGIONDEFINITIONS, ''); // do not localize - Add('Boolean', TAG_GENERATEDEFAULTREGIONS, TV_FALSE); // do not localize + Add('String', TAG_GUID, ''); + Add('String', TAG_TYPELIBVERSION, '1.0'); + Add('Text', TAG_REGIONDEFINITIONS, ''); + Add('Boolean', TAG_GENERATEDEFAULTREGIONS, TV_FALSE); end; - -// Tagged values for Class - with G_BoldDefaultTaggedValues.ListForClassName['Class'] do // do not localize + with G_BoldDefaultTaggedValues.ListForClassName['Class'] do begin - Add('String', TAG_INCFILENAME, ''); // do not localize - Add('String', TAG_UNITNAME, ''); // do not localize - Add('Boolean', TAG_IMPORTED, TV_FALSE); // do not localize - Add('TableMappingSet', // do not localize + Add('String', TAG_INCFILENAME, ''); + Add('String', TAG_UNITNAME, ''); + Add('Boolean', TAG_IMPORTED, TV_FALSE); + Add('TableMappingSet', TAG_TABLEMAPPING, TV_TABLEMAPPING_OWN); - Add('String', TAG_DELPHINAME, 'T'); // do not localize - Add('String', TAG_CPPNAME, TV_NAME); // do not localize - Add('String', TAG_EXPRESSIONNAME, TV_NAME); // do not localize - Add('String', TAG_TABLENAME, TV_NAME); // do not localize - Add('EvolutionStateEnum', // do not localize + Add('String', TAG_DELPHINAME, 'T'); + Add('String', TAG_CPPNAME, TV_NAME); + Add('String', TAG_EXPRESSIONNAME, TV_NAME); + Add('String', TAG_TABLENAME, TV_NAME); + Add('EvolutionStateEnum', TAG_EVOLUTIONSTATE, TV_EVOLUTIONSTATE_NORMAL); - Add('String', TAG_PMAPPERNAME, DEFAULTNAMELITERAL); // do not localize - Add('String', TAG_DEFAULTSTRINGREPRESENTATION, ''); // do not localize - Add('Text', TAG_DERIVATIONEXPRESSIONS, ''); // do not localize - Add('Boolean', TAG_VERSIONED, TV_FALSE); // do not localize - Add('OptimisticLockingSet', // do not localize + Add('String', TAG_PMAPPERNAME, DEFAULTNAMELITERAL); + Add('String', TAG_DEFAULTSTRINGREPRESENTATION, ''); + Add('Text', TAG_DERIVATIONEXPRESSIONS, ''); + Add('Boolean', TAG_VERSIONED, TV_FALSE); + Add('OptimisticLockingSet', TAG_OPTIMISTICLOCKING, TV_OPTIMISTICLOCKING_DEFAULT); - Add('Text', TAG_FORMERNAMES, ''); // do not localize - Add('String', TAG_INTERFACENAME, 'I'); // do not localize - Add('String', TAG_GUID, ''); // do not localize - Add('Boolean', // do not localize + Add('Text', TAG_FORMERNAMES, ''); + Add('String', TAG_INTERFACENAME, 'I'); + Add('String', TAG_GUID, ''); + Add('Boolean', TAG_GENERATEDEFAULTREGION_CLASS, TV_TRUE); Add(ENUM_TAG_CLASS_STORAGE, TAG_STORAGE, TV_STORAGE_INTERNAL); end; - -// Tagged values for Association - with G_BoldDefaultTaggedValues.ListForClassName['Association'] do // do not localize + with G_BoldDefaultTaggedValues.ListForClassName['Association'] do begin - Add('String', TAG_LINKCLASSNAME, TV_NAME); // do not localize - Add('Text', TAG_FORMERNAMES, ''); // do not localize - Add('EvolutionStateEnum', // do not localize + Add('String', TAG_LINKCLASSNAME, TV_NAME); + Add('Text', TAG_FORMERNAMES, ''); + Add('EvolutionStateEnum', TAG_EVOLUTIONSTATE, TV_EVOLUTIONSTATE_NORMAL); Add(ENUM_TAG_ASSOCIATION_STORAGE, TAG_STORAGE, TV_STORAGE_INTERNAL); end; - -// Tagged values for Attribute - with G_BoldDefaultTaggedValues.ListForClassName['Attribute'] do // do not localize + with G_BoldDefaultTaggedValues.ListForClassName['Attribute'] do begin - Add('Integer', TAG_LENGTH, '255'); // do not localize - Add('Boolean', TAG_ALLOWNULL, TV_FALSE); // do not localize - Add('Boolean', TAG_DELAYEDFETCH, TV_FALSE); // do not localize - Add('String', TAG_COLUMNNAME, TV_NAME); // do not localize - Add('String', TAG_EXPRESSIONNAME, TV_NAME); // do not localize - Add('String', TAG_DELPHINAME, TV_NAME); // do not localize - Add('String', TAG_CPPNAME, TV_NAME); // do not localize - Add('String', TAG_PMAPPERNAME, DEFAULTNAMELITERAL); // do not localize - - Add('Text', TAG_DERIVATIONOCL, ''); // do not localize - Add('Boolean', TAG_VIRTUALDERIVE, TV_TRUE); // do not localize - Add('Boolean', TAG_REVERSEDERIVE, TV_FALSE); // do not localize - Add('AttributeKindSet', // do not localize + Add('Integer', TAG_LENGTH, '255'); + Add('Boolean', TAG_ALLOWNULL, TV_FALSE); + Add('Boolean', TAG_DELAYEDFETCH, TV_FALSE); + Add('String', TAG_COLUMNNAME, TV_NAME); + Add('String', TAG_EXPRESSIONNAME, TV_NAME); + Add('String', TAG_DELPHINAME, TV_NAME); + Add('String', TAG_CPPNAME, TV_NAME); + Add('String', TAG_PMAPPERNAME, DEFAULTNAMELITERAL); + + Add('Text', TAG_DERIVATIONOCL, ''); + Add('Boolean', TAG_VIRTUALDERIVE, TV_TRUE); + Add('Boolean', TAG_REVERSEDERIVE, TV_FALSE); + Add('AttributeKindSet', TAG_ATTRIBUTEKIND, TV_ATTRIBUTEKIND_BOLD); - Add('Boolean', TAG_DELPHIFIELD, TV_FALSE); // do not localize - Add('DelphiPropertySet', // do not localize + Add('Boolean', TAG_DELPHIFIELD, TV_FALSE); + Add('DelphiPropertySet', TAG_DPREAD, TV_DPNONE); - Add('DelphiPropertySet', // do not localize + Add('DelphiPropertySet', TAG_DPWRITE, TV_DPNONE); - Add('EvolutionStateEnum', // do not localize + Add('EvolutionStateEnum', TAG_EVOLUTIONSTATE, TV_EVOLUTIONSTATE_NORMAL); - Add('Text', TAG_FORMERNAMES, ''); // do not localize - Add('String', TAG_DEFAULTDBVALUE, ''); // do not localize + Add('Text', TAG_FORMERNAMES, ''); + Add('String', TAG_DEFAULTDBVALUE, ''); Add(ENUM_TAG_ATTRIBUTE_STORAGE, TAG_STORAGE, TV_STORAGE_INTERNAL); - end; -// Tagged values for AssociationEnd - with G_BoldDefaultTaggedValues.ListForClassName['AssociationEnd'] do // do not localize + end; + with G_BoldDefaultTaggedValues.ListForClassName['AssociationEnd'] do begin - Add('Boolean', TAG_ORDERED, TV_FALSE); // do not localize - Add('String', TAG_COLUMNNAME, TV_NAME); // do not localize - Add('String', TAG_EXPRESSIONNAME, TV_NAME); // do not localize - Add('String', TAG_DELPHINAME, TV_NAME); // do not localize - Add('String', TAG_CPPNAME, TV_NAME); // do not localize - Add('Boolean', TAG_EMBED, TV_TRUE); // do not localize - Add('Text', TAG_DERIVATIONOCL, ''); // do not localize - Add('Boolean', TAG_VIRTUALDERIVE, TV_TRUE); // do not localize - Add('DeleteActions', // do not localize + Add('Boolean', TAG_ORDERED, TV_FALSE); + Add('String', TAG_COLUMNNAME, TV_NAME); + Add('String', TAG_EXPRESSIONNAME, TV_NAME); + Add('String', TAG_DELPHINAME, TV_NAME); + Add('String', TAG_CPPNAME, TV_NAME); + Add('Boolean', TAG_EMBED, TV_TRUE); + Add('Text', TAG_DERIVATIONOCL, ''); + Add('Boolean', TAG_VIRTUALDERIVE, TV_TRUE); + Add('DeleteActions', TAG_DELETEACTION, TV_DELETEACTION_DEFAULT); - Add('Text', TAG_FORMERNAMES, ''); // do not localize - Add('DefaultRegionModeAssociationEnum', // do not localize + Add('Text', TAG_FORMERNAMES, ''); + Add('DefaultRegionModeAssociationEnum', TAG_DEFAULTREGIONMODE_ASSOCIATIONEND, TV_DEFAULTREGIONMODE_ASSOCIATIONEND_DEFAULT); end; - -// Tagged values for Operation - with G_BoldDefaultTaggedValues.ListForClassName['Operation'] do // do not localize + with G_BoldDefaultTaggedValues.ListForClassName['Operation'] do begin - Add('String', TAG_DELPHINAME, TV_NAME); // do not localize - Add('String', TAG_CPPNAME, TV_NAME); // do not localize - Add('String', TAG_EXPRESSIONNAME, TV_NAME); // do not localize - Add('BoldOperationKindSet', // do not localize + Add('String', TAG_DELPHINAME, TV_NAME); + Add('String', TAG_CPPNAME, TV_NAME); + Add('String', TAG_EXPRESSIONNAME, TV_NAME); + Add('BoldOperationKindSet', TAG_DELPHIOPERATIONKIND, TV_DELPHIOPERATIONKIND_NORMAL); - Add('Boolean', TAG_OVERRIDEINALLSUBCLASSES, TV_FALSE); // do not localize + Add('Boolean', TAG_OVERRIDEINALLSUBCLASSES, TV_FALSE); end; - with G_BoldDefaultTaggedValues.ListForClassName['Parameter'] do // do not localize + with G_BoldDefaultTaggedValues.ListForClassName['Parameter'] do begin - Add('Boolean', TAG_ISCONST, TV_FALSE); // do not localize + Add('Boolean', TAG_ISCONST, TV_FALSE); end; end; diff --git a/Source/Common/TaggedValues/BoldTaggedValueList.pas b/Source/Common/TaggedValues/BoldTaggedValueList.pas index c557614..4c199ec 100644 --- a/Source/Common/TaggedValues/BoldTaggedValueList.pas +++ b/Source/Common/TaggedValues/BoldTaggedValueList.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldTaggedValueList; interface @@ -70,7 +73,6 @@ implementation uses SysUtils, - BoldUtils, BoldSharedStrings; { TBoldTaggedValueDefinition } @@ -175,4 +177,6 @@ function TBoldTaggedValueDefinitionIndex.ItemAsKeyString(Item: TObject): string; result := TBoldTaggedValueDefinition(item).Tag; end; +initialization + end. diff --git a/Source/Common/TaggedValues/BoldTaggedValueSupport.pas b/Source/Common/TaggedValues/BoldTaggedValueSupport.pas index 5341a22..96ec46e 100644 --- a/Source/Common/TaggedValues/BoldTaggedValueSupport.pas +++ b/Source/Common/TaggedValues/BoldTaggedValueSupport.pas @@ -1,11 +1,13 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldTaggedValueSupport; interface uses - Classes, // TStrings + Classes, BoldDefaultTaggedValues, - BoldUMLTypes, BoldDefs; type @@ -27,8 +29,6 @@ TBoldTaggedValueSupport = class; { TBoldTaggedValueSupport } TBoldTaggedValueSupport = class - private - class procedure UnknownValue(const Invoker: string); public class procedure AddEvolutionStates(Strings: TStrings); class procedure AddNationalCharConversions(Strings: TStrings); @@ -65,8 +65,7 @@ implementation uses SysUtils, - BoldUtils, - BoldCommonConst; + BoldRev; class procedure TBoldTaggedValueSupport.AddTableMappings( Strings: TStrings); @@ -149,13 +148,14 @@ class procedure TBoldTaggedValueSupport.AddDefaultRegionModes( Strings.Add(DefaultRegionModeToString(i)); end; + class function TBoldTaggedValueSupport.AttributeKindToString(Value: TBoldAttributeKind): String; begin case Value of bastBold: Result := TV_ATTRIBUTEKIND_BOLD; bastDelphi: Result := TV_ATTRIBUTEKIND_DELPHI; else - UnknownValue('AttributeKindToString'); // do not localize + raise EBold.CreateFmt('%s.AttributeKindToString: Unknown TBoldAttributeKind', [ClassName]); end; end; @@ -167,7 +167,7 @@ class function TBoldTaggedValueSupport.DeleteActionToString(Value: TDeleteAction daProhibit: Result := TV_DELETEACTION_PROHIBIT; daCascade: Result := TV_DELETEACTION_CASCADE; else - UnknownValue('DeleteActionToString'); // do not localize + raise EBold.CreateFmt('%s.DeleteActionToString: Unknown TDeleteAction', [ClassName]); end; end; @@ -180,7 +180,7 @@ class function TBoldTaggedValueSupport.DelphiFunctionTypeToString(Value: TDelphi dfDynamic: Result := TV_DELPHIOPERATIONKIND_DYNAMIC; dfAbstractVirtual: Result := TV_DELPHIOPERATIONKIND_ABSTRACTVIRTUAL; else - UnknownValue('DelphiFunctionTypeToString'); // do not localize + raise EBold.CreateFmt('%s.DelphiFunctionTypeToString: Unknown TDelphiFunctionType', [ClassName]); end; end; @@ -192,7 +192,7 @@ class function TBoldTaggedValueSupport.DelphiPropertyAccessKindToString(Value: T pkPrivateMethod: Result := TV_DPPRIVATEMETHOD; pkProtectedVirtualMethod: Result := TV_DPPROTECTEDVIRTUALMETHOD; else - UnknownValue('DelphiPropertyAccessKindToString'); // do not localize + raise EBold.CreateFmt('%s.DelphiPropertyAccessKindToString: Unknown TDelphiPropertyAccessKind', [ClassName]); end; end; @@ -208,13 +208,12 @@ class function TBoldTaggedValueSupport.StringToAttributeKind(const Value: String class function TBoldTaggedValueSupport.StringToBoolean(const Value: String): Boolean; begin - Result := False; if SameText(Value, TV_TRUE) then Result := True else if SameText(Value, TV_FALSE) then Result := False else - UnknownValue('StringToBoolean'); // do not localize + raise EBold.CreateFmt('%s is not a valid string for a Boolean', [Value]); end; class function TBoldTaggedValueSupport.StringToDefaultRegionMode(const value: String): TBoldAssociationEndDefaultRegionMode; @@ -259,7 +258,7 @@ class function TBoldTaggedValueSupport.StringToDelphiFunctionType(const Value: S Result := dfDynamic else if Value = TV_DELPHIOPERATIONKIND_ABSTRACTVIRTUAL then Result := dfAbstractVirtual - else if Value = 'AbstractVirtual' then // legacy // do not localize + else if Value = 'AbstractVirtual' then Result := dfAbstractVirtual else result := dfNormal; @@ -349,7 +348,7 @@ class function TBoldTaggedValueSupport.TableMappingToString(Value: TTableMapping tmChildren: Result := TV_TABLEMAPPING_CHILDREN; tmImported: Result := TV_TABLEMAPPING_IMPORTED; else - UnknownValue('TableMappingToString'); // do not localize + raise EBold.CreateFmt('%s.TableMappingToString: Unknown TTableMapping', [ClassName]); end; end; @@ -363,7 +362,7 @@ class function TBoldTaggedValueSupport.OptimisticLockingModeToString( bolmAllMembers: Result := TV_OPTIMISTICLOCKING_ALLMEMBERS; bolmTimeStamp: Result := TV_OPTIMISTICLOCKING_TIMESTAMP; else - UnknownValue('OptimisticLockingModeToString'); // do not localize + raise EBold.CreateFmt('%s.OptimisticLockingModeToString: Unknown TBoldOptimisticLockingMode', [ClassName]); end; end; @@ -375,7 +374,7 @@ class function TBoldTaggedValueSupport.EvolutionStateToString( esToBeRemoved: Result := TV_EVOLUTIONSTATE_TOBEREMOVED; esRemoved: Result := TV_EVOLUTIONSTATE_REMOVED; else - UnknownValue('EvolutionStateToString'); // do not localize + raise EBold.CreateFmt('%s.EvolutionStateToString: Unknown TBoldEvolutionState', [ClassName]); end; end; @@ -400,28 +399,24 @@ class function TBoldTaggedValueSupport.NationalCharConversionToString( nccTrue: Result := TV_TRUE; nccFalse: Result := TV_FALSE; else - UnknownValue('NationalCharConversionToString'); // do not localize + raise EBold.CreateFmt('%s.NationalCharConversionoString: Unknown TBoldNationalCharConversion', [ClassName]); end; end; class function TBoldTaggedValueSupport.DefaultRegionModeToString( Value: TBoldAssociationEndDefaultRegionMode): String; begin - case Value of +case Value of aedrmDefault: Result := TV_DEFAULTREGIONMODE_ASSOCIATIONEND_DEFAULT; aedrmNone: Result := TV_DEFAULTREGIONMODE_ASSOCIATIONEND_NONE; aedrmExistence: Result := TV_DEFAULTREGIONMODE_ASSOCIATIONEND_EXISTENCE; aedrmIndependentCascade: Result := TV_DEFAULTREGIONMODE_ASSOCIATIONEND_INDEPENDENTCASCADE; aedrmCascade: Result := TV_DEFAULTREGIONMODE_ASSOCIATIONEND_CASCADE; else - UnknownValue('DefaultRegionModeToString'); // do not localize + raise EBold.CreateFmt('%s.DefaultRegionModeToString: Unknown TBoldAssociationEndDefaultRegionMode', [ClassName]); end; end; -class procedure TBoldTaggedValueSupport.UnknownValue( - const Invoker: string); -begin - raise EBold.CreateFmt(sUnknownValue, [ClassName, Invoker]); -end; +initialization end. diff --git a/Source/Common/TaggedValues/BoldUMLTaggedValues.pas b/Source/Common/TaggedValues/BoldUMLTaggedValues.pas index 53a1ed1..91cb343 100644 --- a/Source/Common/TaggedValues/BoldUMLTaggedValues.pas +++ b/Source/Common/TaggedValues/BoldUMLTaggedValues.pas @@ -1,11 +1,12 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldUMLTaggedValues; interface uses - BoldDefs, - BoldTaggedValueList, - BoldDefaultTaggedValues; + BoldTaggedValueList; const TAG_DOCUMENTATION: String ='documentation'; @@ -13,8 +14,9 @@ interface ENUM_TAG_PERSISTENCE: String = 'PersistenceEnum'; TAG_PERSISTENCE: String = 'persistence'; - TV_PERSISTENCE_PERSISTENT: String = 'persistent'; - TV_PERSISTENCE_TRANSIENT: String = 'transient'; + TV_PERSISTENCE_PERSISTENT: String = 'persistent'; + TV_PERSISTENCE_TRANSIENT: String = 'transient'; + function UMLTaggedValueList: TBoldTaggedValuePerClassList; @@ -22,30 +24,26 @@ implementation uses SysUtils, - BoldUtils; + BoldDefaultTaggedValues, + BoldRev; var G_UMLTaggedValues: TBoldTaggedValuePerClassList = nil; procedure AddDefaultTaggedValues; begin -// Tagged values for Class - with G_UMLTaggedValues.ListForClassName['Class'] do // do not localize + with G_UMLTaggedValues.ListForClassName['Class'] do begin Add(ENUM_TAG_PERSISTENCE, TAG_PERSISTENCE, TV_PERSISTENCE_PERSISTENT); end; - -// Tagged values for Association - with G_UMLTaggedValues.ListForClassName['Association'] do // do not localize - begin // do not localize - Add('Boolean', TAG_DERIVED, TV_FALSE); // do not localize + with G_UMLTaggedValues.ListForClassName['Association'] do + begin + Add('Boolean', TAG_DERIVED, TV_FALSE); Add(ENUM_TAG_PERSISTENCE, TAG_PERSISTENCE, TV_PERSISTENCE_PERSISTENT); end; - -// Tagged values for Attribute - with G_UMLTaggedValues.ListForClassName['Attribute'] do // do not localize + with G_UMLTaggedValues.ListForClassName['Attribute'] do begin - Add('Boolean', TAG_DERIVED, TV_FALSE); // do not localize + Add('Boolean', TAG_DERIVED, TV_FALSE); Add(ENUM_TAG_PERSISTENCE, TAG_PERSISTENCE, TV_PERSISTENCE_PERSISTENT); end; end; diff --git a/Source/Common/Template/BoldTemplate.pas b/Source/Common/Template/BoldTemplate.pas index 8d52dd0..df26bd9 100644 --- a/Source/Common/Template/BoldTemplate.pas +++ b/Source/Common/Template/BoldTemplate.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldTemplate; interface @@ -14,4 +17,10 @@ TBoldTemplate = class implementation +uses + SysUtils, + BoldUtils; + + +initialization end. diff --git a/Source/Common/UML/BoldUMLDelphiSupport.pas b/Source/Common/UML/BoldUMLDelphiSupport.pas index e122a6c..ec10897 100644 --- a/Source/Common/UML/BoldUMLDelphiSupport.pas +++ b/Source/Common/UML/BoldUMLDelphiSupport.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldUMLDelphiSupport; interface @@ -19,7 +22,8 @@ implementation uses SysUtils, - BoldUtils; + BoldUtils, + BoldRev; { TBoldUMLDelphiSupport } @@ -32,8 +36,8 @@ class function TBoldUMLDelphiSupport.ExtractType( if ColonPos > 0 then begin Result := BoldTrim(Copy(ParameterName, ColonPos+1, MaxInt)); - Delete(ParameterName, ColonPos, Maxint); - end; + Delete(ParameterName, ColonPos, Maxint); + end; end; class function TBoldUMLDelphiSupport.ExtractIsConst( @@ -41,10 +45,10 @@ class function TBoldUMLDelphiSupport.ExtractIsConst( var Index: integer; begin - Index := Pos('const ', LowerCase(ParameterName)); // do not localize + Index := Pos('const ', LowerCase(ParameterName)); Result := Index > 0; if Result then - Delete(ParameterName, Index, 6); // 6 = length('const '); + Delete(ParameterName, Index, 6); end; class function TBoldUMLDelphiSupport.ExtractKind( @@ -52,19 +56,19 @@ class function TBoldUMLDelphiSupport.ExtractKind( var Index: integer; begin - Index := Pos('var ', LowerCase(ParameterName)); // do not localize + Index := Pos('var ', LowerCase(ParameterName)); if Index > 0 then begin Result := pdInOut; - Delete(ParameterName, Index, 4); // 4 = length('var '); + Delete(ParameterName, Index, 4); end else begin - Index := Pos('out ', LowerCase(ParameterName)); // do not localize + Index := Pos('out ', LowerCase(ParameterName)); if Index > 0 then begin Result := pdOut; - Delete(ParameterName, Index, 4); // 4 = length('out '); + Delete(ParameterName, Index, 4); end else Result := pdIn; @@ -75,13 +79,14 @@ class function TBoldUMLDelphiSupport.ParameterModifier( Kind: TBoldParameterDirectionKind; IsConst: Boolean): string; begin if IsConst then - Result := 'const ' // do not localize + Result := 'const ' else if Kind = pdInOut then - Result := 'var ' // do not localize + Result := 'var ' else if Kind = pdOut then - Result := 'out ' // do not localize + Result := 'out ' else Result := ''; end; +initialization end. diff --git a/Source/Common/UML/BoldUMLTypes.pas b/Source/Common/UML/BoldUMLTypes.pas index 325cbd2..2a18038 100644 --- a/Source/Common/UML/BoldUMLTypes.pas +++ b/Source/Common/UML/BoldUMLTypes.pas @@ -1,19 +1,18 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldUMLTypes; interface uses - Classes, BoldBase, - BoldSharedStrings, BoldContainers; type { forward declarations } TBoldUMLRange = class; - TBoldUMLMultiplicity = class; - - { TODO : Normalize names to form TBoldUMLXX } + TBoldUMLMultiplicity = class; TBoldParameterDirectionKind = (pdIn, pdOut, pdInout, pdReturn); TAggregationKind = (akNone, akAggregate, akComposite); TVisibilityKind = (vkPrivate, vkProtected, vkPublic); @@ -61,7 +60,7 @@ implementation uses SysUtils, - BoldUtils; + BoldRev; { TBoldUMLRange } @@ -157,7 +156,7 @@ function TBoldUMLMultiplicity.FormatAsString( if length(Result) > 0 then Result := Result + ','; Result := result + Range[i].FormatAsString(UnlimitedString); - end; + end; end; function TBoldUMLMultiplicity.GetAsString: string; @@ -202,4 +201,5 @@ procedure TBoldUMLMultiplicity.SetAsString(const Value: string); end; end; +initialization end. diff --git a/Source/Common/UtilsGUI/BoldCursorGuard.pas b/Source/Common/UtilsGUI/BoldCursorGuard.pas index 9dd700e..98a49e7 100644 --- a/Source/Common/UtilsGUI/BoldCursorGuard.pas +++ b/Source/Common/UtilsGUI/BoldCursorGuard.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldCursorGuard; interface @@ -21,7 +24,8 @@ TBoldCursorGuard = class(TBoldRefCountedObject, IBoldCursorGuard) implementation uses - Forms; + Forms, + BoldRev; { TBoldGuardCursorChange } @@ -37,4 +41,6 @@ destructor TBoldCursorGuard.Destroy; inherited; end; +initialization + end. diff --git a/Source/ConcurrencyControl/COM/BoldLockManagerAdminHandleCom.pas b/Source/ConcurrencyControl/COM/BoldLockManagerAdminHandleCom.pas index 160c08e..d783be2 100644 --- a/Source/ConcurrencyControl/COM/BoldLockManagerAdminHandleCom.pas +++ b/Source/ConcurrencyControl/COM/BoldLockManagerAdminHandleCom.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldLockManagerAdminHandleCom; interface @@ -184,4 +187,6 @@ procedure TBoldLockManagerAdminHandleCom._Receive(Originator: TObject; end; end; +initialization + end. diff --git a/Source/ConcurrencyControl/COM/BoldLockManagerHandleCom.pas b/Source/ConcurrencyControl/COM/BoldLockManagerHandleCom.pas index 69e537c..44e03a4 100644 --- a/Source/ConcurrencyControl/COM/BoldLockManagerHandleCom.pas +++ b/Source/ConcurrencyControl/COM/BoldLockManagerHandleCom.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldLockManagerHandleCom; interface @@ -49,7 +52,8 @@ implementation BoldUtils, BoldLockingDefs, BoldComClient, - BoldDefs; + BoldDefs + ; { TBoldLockManagerHandleCom } @@ -171,4 +175,6 @@ procedure TBoldLockManagerHandleCom._Receive(Originator: TObject; end; end; +initialization + end. diff --git a/Source/ConcurrencyControl/Common/BoldAbstractLockManagerAdminHandle.pas b/Source/ConcurrencyControl/Common/BoldAbstractLockManagerAdminHandle.pas index bd26dfe..f4e446e 100644 --- a/Source/ConcurrencyControl/Common/BoldAbstractLockManagerAdminHandle.pas +++ b/Source/ConcurrencyControl/Common/BoldAbstractLockManagerAdminHandle.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldAbstractLockManagerAdminHandle; interface @@ -20,5 +23,10 @@ TBoldAbstractLockManagerAdminHandle = class(TBoldSubscribableComponent) implementation -end. +uses + BoldRev + ; +initialization + +end. diff --git a/Source/ConcurrencyControl/Common/BoldAbstractLockManagerHandle.pas b/Source/ConcurrencyControl/Common/BoldAbstractLockManagerHandle.pas index 0db68a2..348f7f9 100644 --- a/Source/ConcurrencyControl/Common/BoldAbstractLockManagerHandle.pas +++ b/Source/ConcurrencyControl/Common/BoldAbstractLockManagerHandle.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldAbstractLockManagerHandle; interface @@ -19,4 +22,9 @@ TBoldAbstractLockManagerHandle = class(TBoldSubscribableComponent) implementation +uses + BoldRev; + +initialization + end. diff --git a/Source/ConcurrencyControl/Common/BoldLockingDefs.pas b/Source/ConcurrencyControl/Common/BoldLockingDefs.pas index da84c46..efec360 100644 --- a/Source/ConcurrencyControl/Common/BoldLockingDefs.pas +++ b/Source/ConcurrencyControl/Common/BoldLockingDefs.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldLockingDefs; interface @@ -9,6 +12,9 @@ interface BOLD_DBLOCK_NAME = 'DBLock'; implementation +uses + BoldRev; -end. +initialization +end. diff --git a/Source/ConcurrencyControl/IDECOM/BoldConcurrencyControlReg.pas b/Source/ConcurrencyControl/IDECOM/BoldConcurrencyControlReg.pas index 0eacbf0..c12c6d4 100644 --- a/Source/ConcurrencyControl/IDECOM/BoldConcurrencyControlReg.pas +++ b/Source/ConcurrencyControl/IDECOM/BoldConcurrencyControlReg.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldConcurrencyControlReg; interface @@ -7,15 +10,11 @@ procedure Register; implementation uses - SysUtils, BoldLockManagerAdminHandleCom, BoldLockManagerHandleCom, BoldIDEConsts, Classes; -{$R *.res} - - procedure RegisterComponentsOnPalette; begin RegisterComponents(BOLDPAGENAME_OSS_CMS, [ @@ -24,7 +23,6 @@ procedure RegisterComponentsOnPalette; ]); end; - procedure Register; begin RegisterComponentsOnPalette; diff --git a/Source/Extensions/OLLE/Core/BoldOLLEController.pas b/Source/Extensions/OLLE/Core/BoldOLLEController.pas index c65d567..7ef784a 100644 --- a/Source/Extensions/OLLE/Core/BoldOLLEController.pas +++ b/Source/Extensions/OLLE/Core/BoldOLLEController.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldOLLEController; interface @@ -9,6 +12,7 @@ interface BoldSystem, BoldDBInterfaces, BoldSQLDatabaseConfig, + BoldIndexCollection, BoldAbstractPersistenceHandleDB; type @@ -16,11 +20,13 @@ TBoldPHandleMimic = class(TBoldAbstractPersistenceHandleDB) private fPHandle: TBoldAbstractPersistenceHandleDB; fSQLDatabaseConfig: TBoldSQLDatabaseConfig; + fCustomIndexes: TBoldIndexCollection; protected function GetDataBaseInterface: IBoldDatabase; override; function GetSQLDatabaseConfig: TBoldSQLDatabaseConfig; override; + function GetCustomIndexes: TBoldIndexCollection; override; public - destructor Destroy; override; + destructor destroy; override; end; TBoldOLLEController = class @@ -41,8 +47,8 @@ implementation uses SysUtils, - BoldUtils, - OLLEConsts; + BoldUtils; + { TBoldOLLEController } @@ -53,7 +59,7 @@ constructor TBoldOLLEController.Create(PersistenceHandle: TBoldAbstractPersisten fMimicPHandle.fPHandle := PersistenceHandle; fMimicPHandle.BoldModel := fOlleDM.BoldModel1; fMimicPHandle.SQLDatabaseConfig.AssignConfig(PersistenceHandle.SQLDatabaseConfig); - fMimicPHandle.SQLDataBaseConfig.SystemTablePrefix := 'OLLE'; // do not localize + fMimicPHandle.SQLDataBaseConfig.SystemTablePrefix := 'OLLE'; fOlleDM.BoldObjectInfoSystem.PersistenceHandle := fMimicPHandle; end; @@ -78,7 +84,7 @@ procedure TBoldOLLEController.SetPersistent(const Value: Boolean); if value <> Persistent then begin if fOlleDm.BoldObjectInfoSystem.Active then - raise Exception.CreateFmt(sCannotChangePersistenceWhenActive, [ClassName]); + raise Exception.Create( 'TBoldOLLEController: Can not change Persistent-property when the OLLE system is active' ); if Value then fOlleDM.BoldObjectInfoSystem.PersistenceHandle := fMimicPHandle else @@ -91,9 +97,17 @@ procedure TBoldOLLEController.SetPersistent(const Value: Boolean); destructor TBoldPHandleMimic.destroy; begin FreeAndNil(fSQLDatabaseConfig); + FreeAndNil(fCustomIndexes); inherited; end; +function TBoldPHandleMimic.GetCustomIndexes: TBoldIndexCollection; +begin + if not assigned(fCustomIndexes) then + fCustomIndexes := TBoldIndexCollection.Create(nil); + result := fCustomIndexes; +end; + function TBoldPHandleMimic.GetDataBaseInterface: IBoldDatabase; begin result := fPHandle.DataBaseInterface; @@ -106,4 +120,6 @@ function TBoldPHandleMimic.GetSQLDatabaseConfig: TBoldSQLDatabaseConfig; result := fSQLDatabaseConfig; end; +initialization + end. diff --git a/Source/Extensions/OLLE/Core/BoldOLLEDistributableObjectHandlers.pas b/Source/Extensions/OLLE/Core/BoldOLLEDistributableObjectHandlers.pas index 002187f..c4ca2b6 100644 --- a/Source/Extensions/OLLE/Core/BoldOLLEDistributableObjectHandlers.pas +++ b/Source/Extensions/OLLE/Core/BoldOLLEDistributableObjectHandlers.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldOLLEDistributableObjectHandlers; interface @@ -22,11 +25,13 @@ interface BoldDbInterfaces, BoldOLLEdmmain; + + const BOLD_OLL_IDATTRIBUTECOLUMN_NAME = 'LOCALID'; BOLD_OLL_PSIDATTRIBUTECOLUMN_NAME = 'GLOBALID'; BOLD_OLL_NAMEOFCLASSATTRIBUTECOLUMN_NAME = 'NAMEOFCLASS'; - + type TBoldPSId = string; TBoldDistributableObjectHandler = class; @@ -53,13 +58,11 @@ TBoldDistributableObjectHandler = class fBrokenLinkResolver: TBoldBrokenLinkResolver; fMyTransaction: Boolean; fTheMapping: TMapping; -// function GetDatabase: IBoldDatabase; function TheMapping: TMapping; function LookupInfoByLocalId(LocalId: TBoldDefaultId): TDistributableObjectInfo; procedure AddToMapping(anObj: TDistributableObjectInfo); procedure GetLocalIdsFor(InfoObjects: TDistributableObjectInfoList; IdList: TBoldObjectIdList); function GetForeignPSInfo(PSId: TBoldPSId): TForeignPSInfo; -// function NewLocalClassIdFor(ClassId: TBoldClassIdWithExpressionName): TBoldClassId; procedure ExtractAllIds(IdList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; OutIdList: TBoldObjectIdList); procedure Fetch(IdList: TBoldObjectIdList; ValueSpace: IBoldValueSpace); procedure GetInfoObjectsFor(IdList: TBoldObjectIdList; InfoObjectList: TDistributableObjectInfoList; RemainingIdList: TBoldObjectIdList); @@ -117,7 +120,6 @@ implementation uses SysUtils, BoldUtils, - OlleConsts, BoldDomainElement; procedure AddObjectToIdList(aDistributableInfo: TDistributableObjectInfo; anIdList: TBoldObjectIdList); @@ -155,10 +157,10 @@ procedure TBoldForeignObjectHandler.PutObjects( begin anObject := InfoObjects[i]; if not (anObject is TForeignObjectInfo) then - raise EBold.CreateFmt(sObjectNotForeign, [Classname]); + raise EBold.CreateFmt('%s.EnsureForeignInfo: Object is not a foreign object', [Classname]); aForeignObjectInfo := anObject as TForeignObjectInfo; if not (aForeignObjectInfo.Owner = Owner) then - raise EBold.CreateFmt(sWrongOwner, [Classname]); + raise EBold.CreateFmt('%s.EnsureForeignInfo: Wrong owner', [Classname]); anObjectId.AsInteger := aForeignObjectInfo.LocalId; aForeignObjectInfo.Put(ValueSpace, HoldList.IdInList[anObjectId], NewLocalTimeStamp); end; @@ -198,8 +200,6 @@ procedure TBoldForeignObjectHandler.Put(ValueSpace: IBoldValueSpace; IdList: TBo VerifyAssociations(ValueSpace, IdList2, HoldList2); Update(ValueSpace, IdList2, TranslationList2, NewLocalTimeStamp); - -// FVS.ApplyTranslationList(TranslationList2); Done by Update IdList2.ApplyTranslationList(TranslationList2); HoldList2.ApplyTranslationList(TranslationList2); @@ -238,7 +238,7 @@ procedure TBoldForeignObjectHandler.StartCheckIn(IdList, try OwnerForeignPSInfo := GetForeignPSInfo(Owner); if OwnerForeignPSInfo.IsCheckingIn then - raise EBold.CreateFmt(sObjectsAlreadyBeingCheckedIn, [Classname]); + raise EBold.CreateFmt('%s.StartCheckIn: Already checking in objects for this persistent storage', [Classname]); Fetch(Idlist, ValueSpace); StartCheckInObjects(ValueSpace, IdList, ReleaseList, OwnerForeignPSInfo); ReleaseObjects(ValueSpace, ReleaseList); @@ -347,7 +347,6 @@ procedure TBoldForeignObjectHandler.ModifiedObjectsFrom(Owner: TBoldPSId; aValueSpace: TBoldFreeStandingValueSpace; function DifferentTimeStamp: Boolean; - // This function exists to remove a weird bug that probably has to do with releasing interfaces. var anObjectContents: IBOldObjectContents; begin @@ -361,7 +360,7 @@ procedure TBoldForeignObjectHandler.ModifiedObjectsFrom(Owner: TBoldPSId; anObjectIdList := TBoldObjectIdList.Create; aValueSpace := TBoldFreeStandingValueSpace.Create; try - GetForeignPSInfo(Owner).EvaluateExpression('ownedObjectInfos.heldObjectInfo', anElement); // do not localize + GetForeignPSInfo(Owner).EvaluateExpression('ownedObjectInfos.heldObjectInfo', anElement); anObjectList := anElement.Value as TBoldObjectList; anObjectList.EnsureObjects; for i := 0 to anObjectList.Count-1 do @@ -390,6 +389,7 @@ procedure TBoldForeignObjectHandler.ObjectsFrom(Owner: TBoldPSId; AddObjectToIdList(anObjectList[i], Objects); end; + { TOwnObjectHandler } procedure TBoldOwnObjectHandler.AcknowledgeSynch(ForeignPS: TBoldPSId); @@ -424,8 +424,6 @@ procedure TBoldOwnObjectHandler.CheckIn(ValueSpace: IBoldValueSpace; IdList, VerifyAssociations(ValueSpace, IdList2, IdList2); Update(ValueSpace, IdList2, TranslationList2, NewTimeStamp); - -// FVS.ApplyTranslationList(TranslationList2); Done by Update IdList2.ApplyTranslationList(TranslationList2); ReleaseList2.ApplyTranslationList(TranslationList2); @@ -465,7 +463,7 @@ procedure TBoldOwnObjectHandler.CheckInObjects(ValueSpace: IBoldValueSpace; begin anObject := InfoObjects[i]; if not (anObject is TOwnObjectInfo) then - raise EBold.CreateFmt(sObjectNotOwned, [Classname, 'CheckInObjects']); // do not localize + raise EBold.CreateFmt('%s.CheckInObjects: Object is not an owned object', [Classname]); anOwnObjectInfo := anObject as TOwnObjectInfo; anObjectId.AsInteger := anOwnObjectInfo.LocalId; anOwnObjectInfo.CheckIn(ValueSpace, ReleaseList.IdInList[anObjectId], Holder); @@ -476,7 +474,7 @@ procedure TBoldOwnObjectHandler.CheckInObjects(ValueSpace: IBoldValueSpace; anOwnObjectInfo.LocalId := (NewInfoIds[i] as TBoldDefaultId).AsInteger; AddToMapping(anOwnObjectInfo); anOwnObjectInfo.CheckedOutObjectInfo := TCheckedOutObjectInfo.Create(OllSystem); - anOwnObjectInfo.CheckedOutObjectInfo.Holder := Holder; // Needed for those objects that aren't released + anOwnObjectInfo.CheckedOutObjectInfo.Holder := Holder; anOwnObjectInfo.CheckIn(ValueSpace, ReleaseList.IdInList[NewInfoIds[i]], Holder); end; finally @@ -552,7 +550,7 @@ procedure TBoldOwnObjectHandler.GetSynch(ForeignPS: TBoldPSId; try aForeignPS := GetForeignPSInfo(ForeignPS); if aForeignPS.IsSynching then - raise EBold.CreateFmt(sSynchInProgress, [classname]); + raise EBold.CreateFmt('%s.GetSynch: There is already an ongoing synch that must either be acknowledged or failed.', [classname]); ChangedObjects := TBoldObjectIdList.Create; HoldList := TBoldObjectIdList.Create; @@ -583,7 +581,6 @@ procedure TBoldOwnObjectHandler.GetSynch(ForeignPS: TBoldPSId; HoldList.Free; aCond.Free; InfoObjects.Free; - MissingIds.Free; end; OllSystem.UpdateDatabase; @@ -665,7 +662,7 @@ procedure TBoldOwnObjectHandler.UnCheckOutObjects(IdList: TBoldObjectIdList; for i := 0 to InfoObjects.Count - 1 do begin if not (InfoObjects[i] is TOwnObjectInfo) then - raise EBold.CreateFmt(sObjectNotOwned, [Classname, 'UnCheckOutObjects']); // do not localize + raise EBold.CreateFmt('%s.UnCheckOutObjects: Object is not an owned object', [Classname]); anOwnObjectInfo := InfoObjects[i] as TOwnObjectInfo; anOwnObjectInfo.UnCheckOut(Holder); end; @@ -693,7 +690,7 @@ function TBoldDistributableObjectHandler.GetForeignPSInfo( aCondition.WhereFragment := BOLD_OLL_PSIDATTRIBUTECOLUMN_NAME + ' = ''' + PSId + ''''; OllSystem.PersistenceController.PMFetchIDListWithCondition(PSInfoObjectIdList, OllSystem.AsIBoldvalueSpace[bdepPMIn], fmNormal, aCondition, 0); end else} - SearchByOcl('ForeignPSInfo.allInstances->select(globalId = ''' + PSId + ''')', PSInfoObjectIdList); // do not localize + SearchByOcl('ForeignPSInfo.allInstances->select(globalId = ''' + PSId + ''')', PSInfoObjectIdList); if PSInfoObjectIdList.Count = 0 then begin result := TForeignPSInfo.Create(OllSystem); @@ -809,8 +806,8 @@ procedure TBoldDistributableObjectHandler.GetInfoObjectsFor(IdList: TBoldObjectI aCondition := TBoldSQLCondition.Create; FoundIds := TBoldObjectIdList.Create; try - aCondition.TopSortedIndex := OllSystem.BoldSystemTypeInfo.ClassTypeInfoByModelName['DistributableObjectInfo'].TopSortedIndex; // do not localize - aCondition.WhereFragment := BOLD_OLL_IDATTRIBUTECOLUMN_NAME + ' IN (' + IdListToSQL(RemainingIds) + ')'; // do not localize + aCondition.TopSortedIndex := OllSystem.BoldSystemTypeInfo.ClassTypeInfoByModelName['DistributableObjectInfo'].TopSortedIndex; + aCondition.WhereFragment := BOLD_OLL_IDATTRIBUTECOLUMN_NAME + ' IN (' + IdListToSQL(RemainingIds) + ')'; OllSystem.GetAllWithCondition(FetchedInfoObjs, aCondition); FetchedInfoObjs.EnsureObjects; for i := 0 to FetchedInfoObjs.Count-1 do @@ -860,8 +857,7 @@ procedure TBoldDistributableObjectHandler.Update(ValueSpace: IBoldValueSpace; begin anObject := ValueSpace.ObjectContentsByObjectId[IdList[i]]; for j := 0 to anObject.MemberCount-1 do - if assigned(anObject.ValueByIndex[j]) then - anObject.ValueByIndex[j].BoldPersistenceState := bvpsModified; + anObject.ValueByIndex[j].BoldPersistenceState := bvpsModified; if IdList[i] is TBoldGlobalId then begin if anObject.BoldExistenceState = besDeleted then @@ -958,11 +954,9 @@ procedure TBoldDistributableObjectHandler.VerifyAssociations( VerifyObjectRoles(ValueSpace.ObjectContentsByObjectId[anIdRefPair.Id2]); end else if aMember.QueryInterface(IBoldObjectIdListRef, anIdListRef) = S_OK then begin -// VerifyAllInList(anIdListRef.IdList); end else if aMember.QueryInterface(IBoldObjectIdListRefPair, anIdListRefPair) = S_OK then begin -// VerifyAllInList(anIdListRefPair.anIdListRefPair.IdList1); -// VerifyAllInList(anIdListRefPair.anIdListRefPair.IdList2); + end; end; end; @@ -979,7 +973,6 @@ procedure TBoldDistributableObjectHandler.VerifyAssociations( aMember := ObjectContents.ValueByIndex[j]; if assigned(aMember) then begin - // FIXME: Doesn't work for non-embedded singlelinks, but that requires access to the model if ((aMember.QueryInterface(IBoldObjectIdRef, anIdRef) = S_OK) and (anIdRef.Id is TBoldGlobalId) and (not ValueSpace.HasContentsForId[anIdRef.Id])) or @@ -990,12 +983,11 @@ procedure TBoldDistributableObjectHandler.VerifyAssociations( begin if not BrokenLinkResolver.ResolveBrokenLink(ObjectContents, j, HoldList.IdInList[IdList[i]]) then begin - raise EBoldFeatureNotImplementedYet.CreateFmt(sCannotFailIndividualObjects, [classname]); -// CascadeToNeighbours; -// ValueSpace.deleteobject + raise EBoldFeatureNotImplementedYet.CreateFmt('%s.VerifyAssociations: Failing inidividual objects not implemented', [classname]); + end; end else - raise EBold.Create(sUnresolvedLink); + raise EBold.Create('Operation failed: Unresolved link'); end; end; end; @@ -1072,11 +1064,11 @@ function TBoldBrokenLinkResolver.ResolveBrokenLink( begin aMember := ObjectContents.ValueByIndex[MemberIndex]; if (aMember.QueryInterface(IBoldObjectIdRef, anIdRef) = S_OK) then - anIdRef.SetFromId(nil) + anIdRef.SetFromId(nil, false) else if (aMember.QueryInterface(IBoldObjectIdRefPair, anIdRefPair) = S_OK) then anIdRefPair.SetFromIds(nil, nil) else - raise EBoldInternal.CreateFmt(sMemberNotSingleLink, [Classname]); + raise EBoldInternal.CreateFmt('%.ResolveBrokenLink: Member is not a singlelink', [Classname]); end; begin @@ -1088,10 +1080,10 @@ function TBoldBrokenLinkResolver.ResolveBrokenLink( case ResolveAction of blraCut: Cut; - blraAbort: raise EBold.Create(sUnresolvedLink); + blraAbort: raise EBold.Create('Operation failed: Unresolved link'); blraFailObject: result := False; blraIgnore:; - blraMissing: raise EBoldFeatureNotImplementedYet.Create(sMissingObjectsNotImplemented); + blraMissing: raise EBoldFeatureNotImplementedYet.Create('Missing Objects not implemented'); end; end; @@ -1110,7 +1102,7 @@ procedure TBoldDistributableObjectHandler.GetLocalIdsFor( end; finally TempId.Free; - end; + end; end; procedure TBoldDistributableObjectHandler.NewOwnInfoObjectsFor( @@ -1161,7 +1153,7 @@ function TBoldDistributableObjectHandler.TheMapping: TMapping; begin if not assigned(fTheMapping) then begin - Mappings := fOllSystem.ClassByExpressionName['Mapping']; // do not localize + Mappings := fOllSystem.ClassByExpressionName['Mapping']; if Mappings.Count = 0 then fTheMapping := TMapping.Create(fOllSystem) else @@ -1179,4 +1171,5 @@ procedure TBoldDistributableObjectHandler.AddToMapping( TheMapping.M_ObjectInfo.Add(anObj); end; +initialization end. diff --git a/Source/Extensions/OLLE/Core/BoldOLLEHandles.pas b/Source/Extensions/OLLE/Core/BoldOLLEHandles.pas index 9d64f23..9ed00de 100644 --- a/Source/Extensions/OLLE/Core/BoldOLLEHandles.pas +++ b/Source/Extensions/OLLE/Core/BoldOLLEHandles.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldOLLEHandles; interface @@ -36,6 +39,8 @@ TBoldOLLEHandle = class(TBoldHandle) property ApplicationPersistenceHandle: TBoldAbstractPersistenceHandleDB read fAppPHandle write fAppPHandle; end; + + implementation uses @@ -99,4 +104,6 @@ procedure TBoldOLLEHandle.SetPersistent(const Value: Boolean); GetOLLEController.Persistent := Value; end; + +initialization end. diff --git a/Source/Extensions/OLLE/Core/BoldOLLEdmmain.pas b/Source/Extensions/OLLE/Core/BoldOLLEdmmain.pas index 524d003..647691d 100644 --- a/Source/Extensions/OLLE/Core/BoldOLLEdmmain.pas +++ b/Source/Extensions/OLLE/Core/BoldOLLEdmmain.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldOLLEDmmain; interface @@ -27,7 +30,6 @@ implementation uses SysUtils, - BoldRev, BoldUtils; {$R *.DFM} diff --git a/Source/Extensions/OLLE/Core/DistributableInfo.pas b/Source/Extensions/OLLE/Core/DistributableInfo.pas index a6330bd..3ccd0bf 100644 --- a/Source/Extensions/OLLE/Core/DistributableInfo.pas +++ b/Source/Extensions/OLLE/Core/DistributableInfo.pas @@ -1,27 +1,14 @@ -(*****************************************) -(* This file is autogenerated *) -(* Any manual changes will be LOST! *) -(*****************************************) -(* Generated 2002-04-04 15:49:35 *) -(*****************************************) -(* This file should be stored in the *) -(* same directory as the form/datamodule *) -(* with the corresponding model *) -(*****************************************) -(* Copyright notice: *) -(* *) -(*****************************************) +{ Global compiler directives } +{$include bold.inc} unit DistributableInfo; {$DEFINE DistributableInfo_unitheader} {$INCLUDE DistributableInfo_Interface.inc} uses - // implementation uses BoldDefaultId, - // implementation dependencies - // other + BoldGeneratedCodeDictionary; { Includefile for methodimplementations } @@ -759,46 +746,44 @@ procedure TOwnPSInfoList.SetBoldObject(index: Integer; NewObject: TOwnPSInfo); function GeneratedCodeCRC: String; begin - result := '287685748'; // do not localize + result := '287685748'; end; procedure InstallObjectListClasses(BoldObjectListClasses: TBoldGeneratedClassList); begin - BoldObjectListClasses.AddObjectEntry('BusinessClassesRoot', TBusinessClassesRootList); // do not localize - BoldObjectListClasses.AddObjectEntry('CheckedOutObjectInfo', TCheckedOutObjectInfoList); // do not localize - BoldObjectListClasses.AddObjectEntry('CheckingInObjectInfo', TCheckingInObjectInfoList); // do not localize - BoldObjectListClasses.AddObjectEntry('DistributableObjectInfo', TDistributableObjectInfoList); // do not localize - BoldObjectListClasses.AddObjectEntry('HeldObjectInfo', THeldObjectInfoList); // do not localize - BoldObjectListClasses.AddObjectEntry('Mapping', TMappingList); // do not localize - BoldObjectListClasses.AddObjectEntry('PSInfo', TPSInfoList); // do not localize - BoldObjectListClasses.AddObjectEntry('ForeignObjectInfo', TForeignObjectInfoList); // do not localize - BoldObjectListClasses.AddObjectEntry('OwnObjectInfo', TOwnObjectInfoList); // do not localize - BoldObjectListClasses.AddObjectEntry('ForeignPSInfo', TForeignPSInfoList); // do not localize - BoldObjectListClasses.AddObjectEntry('OwnPSInfo', TOwnPSInfoList); // do not localize + BoldObjectListClasses.AddObjectEntry('BusinessClassesRoot', TBusinessClassesRootList); + BoldObjectListClasses.AddObjectEntry('CheckedOutObjectInfo', TCheckedOutObjectInfoList); + BoldObjectListClasses.AddObjectEntry('CheckingInObjectInfo', TCheckingInObjectInfoList); + BoldObjectListClasses.AddObjectEntry('DistributableObjectInfo', TDistributableObjectInfoList); + BoldObjectListClasses.AddObjectEntry('HeldObjectInfo', THeldObjectInfoList); + BoldObjectListClasses.AddObjectEntry('Mapping', TMappingList); + BoldObjectListClasses.AddObjectEntry('PSInfo', TPSInfoList); + BoldObjectListClasses.AddObjectEntry('ForeignObjectInfo', TForeignObjectInfoList); + BoldObjectListClasses.AddObjectEntry('OwnObjectInfo', TOwnObjectInfoList); + BoldObjectListClasses.AddObjectEntry('ForeignPSInfo', TForeignPSInfoList); + BoldObjectListClasses.AddObjectEntry('OwnPSInfo', TOwnPSInfoList); end; procedure InstallBusinessClasses(BoldObjectClasses: TBoldGeneratedClassList); begin - BoldObjectClasses.AddObjectEntry('BusinessClassesRoot', TBusinessClassesRoot); // do not localize - BoldObjectClasses.AddObjectEntry('CheckedOutObjectInfo', TCheckedOutObjectInfo); // do not localize - BoldObjectClasses.AddObjectEntry('CheckingInObjectInfo', TCheckingInObjectInfo); // do not localize - BoldObjectClasses.AddObjectEntry('DistributableObjectInfo', TDistributableObjectInfo); // do not localize - BoldObjectClasses.AddObjectEntry('HeldObjectInfo', THeldObjectInfo); // do not localize - BoldObjectClasses.AddObjectEntry('Mapping', TMapping); // do not localize - BoldObjectClasses.AddObjectEntry('PSInfo', TPSInfo); // do not localize - BoldObjectClasses.AddObjectEntry('ForeignObjectInfo', TForeignObjectInfo); // do not localize - BoldObjectClasses.AddObjectEntry('OwnObjectInfo', TOwnObjectInfo); // do not localize - BoldObjectClasses.AddObjectEntry('ForeignPSInfo', TForeignPSInfo); // do not localize - BoldObjectClasses.AddObjectEntry('OwnPSInfo', TOwnPSInfo); // do not localize + BoldObjectClasses.AddObjectEntry('BusinessClassesRoot', TBusinessClassesRoot); + BoldObjectClasses.AddObjectEntry('CheckedOutObjectInfo', TCheckedOutObjectInfo); + BoldObjectClasses.AddObjectEntry('CheckingInObjectInfo', TCheckingInObjectInfo); + BoldObjectClasses.AddObjectEntry('DistributableObjectInfo', TDistributableObjectInfo); + BoldObjectClasses.AddObjectEntry('HeldObjectInfo', THeldObjectInfo); + BoldObjectClasses.AddObjectEntry('Mapping', TMapping); + BoldObjectClasses.AddObjectEntry('PSInfo', TPSInfo); + BoldObjectClasses.AddObjectEntry('ForeignObjectInfo', TForeignObjectInfo); + BoldObjectClasses.AddObjectEntry('OwnObjectInfo', TOwnObjectInfo); + BoldObjectClasses.AddObjectEntry('ForeignPSInfo', TForeignPSInfo); + BoldObjectClasses.AddObjectEntry('OwnPSInfo', TOwnPSInfo); end; var CodeDescriptor: TBoldGeneratedCodeDescriptor; initialization - CodeDescriptor := GeneratedCodes.AddGeneratedCodeDescriptorWithFunc('DistributableInfo', InstallBusinessClasses, InstallObjectListClasses, GeneratedCodeCRC); // do not localize + CodeDescriptor := GeneratedCodes.AddGeneratedCodeDescriptorWithFunc('DistributableInfo', InstallBusinessClasses, InstallObjectListClasses, GeneratedCodeCRC); finalization GeneratedCodes.Remove(CodeDescriptor); end. - - diff --git a/Source/Extensions/OLLE/Core/OlleConsts.pas b/Source/Extensions/OLLE/Core/OlleConsts.pas index dde68fe..6ef2761 100644 --- a/Source/Extensions/OLLE/Core/OlleConsts.pas +++ b/Source/Extensions/OLLE/Core/OlleConsts.pas @@ -23,4 +23,4 @@ interface implementation -end. \ No newline at end of file +end. diff --git a/Source/Extensions/OLLE/IDE/BoldOLLEHandlesComponentEditor.pas b/Source/Extensions/OLLE/IDE/BoldOLLEHandlesComponentEditor.pas index 95b3513..cc1e162 100644 --- a/Source/Extensions/OLLE/IDE/BoldOLLEHandlesComponentEditor.pas +++ b/Source/Extensions/OLLE/IDE/BoldOLLEHandlesComponentEditor.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldOLLEHandlesComponentEditor; interface @@ -19,8 +22,7 @@ implementation uses SysUtils, - BoldUtils, - OLLEConsts; + BoldUtils; { TBoldOLLEHandleComponentEditor } @@ -36,9 +38,9 @@ procedure TBoldOLLEHandleComponentEditor.ExecuteVerb(index: Integer); function TBoldOLLEHandleComponentEditor.GetVerb(index: Integer): string; begin case index of - 0: result := sGenerateOLLEDB; + 0: result := 'Generate OLLE database'; else - result := sNonexistingAction; + result := 'Nonexisting action'; end; end; @@ -47,5 +49,5 @@ function TBoldOLLEHandleComponentEditor.GetVerbCount: Integer; result := 1; end; +initialization end. - diff --git a/Source/Extensions/OLLE/IDE/BoldOLLEHandlesReg.pas b/Source/Extensions/OLLE/IDE/BoldOLLEHandlesReg.pas index dfd3acb..409dd8e 100644 --- a/Source/Extensions/OLLE/IDE/BoldOLLEHandlesReg.pas +++ b/Source/Extensions/OLLE/IDE/BoldOLLEHandlesReg.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldOLLEHandlesReg; interface @@ -6,8 +9,6 @@ procedure Register; implementation -{$R BoldOLLEHandles.res} - uses SysUtils, BoldUtils, @@ -31,7 +32,6 @@ procedure RegisterComponentEditors; procedure Register; begin - RemovePackageFromDisabledPackagesRegistry(Format('BoldOLLE%s', [LIBSUFFIX])); // do not localize RegisterComponentsOnPalette; RegisterComponentEditors; end; diff --git a/Source/FreestandingValueSpace/Core/BoldFreeStandingValueFactories.pas b/Source/FreestandingValueSpace/Core/BoldFreeStandingValueFactories.pas index 814854b..738c54d 100644 --- a/Source/FreestandingValueSpace/Core/BoldFreeStandingValueFactories.pas +++ b/Source/FreestandingValueSpace/Core/BoldFreeStandingValueFactories.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldFreeStandingValueFactories; interface @@ -29,7 +32,6 @@ implementation uses SysUtils, - FreeStandingValuesConst, BoldDefs, BoldDefaultStreamNames; {--- TBoldFreeStandingObjectContentsFactory ---} @@ -40,7 +42,7 @@ constructor TBoldFreeStandingElementFactory.create; fClasses := TBoldNamedValueList.Create; end; -destructor TBoldFreeStandingElementFactory.Destroy; +destructor TBoldFreeStandingElementFactory.destroy; begin FreeAndNil(fClasses); inherited; @@ -48,7 +50,7 @@ destructor TBoldFreeStandingElementFactory.Destroy; procedure TBoldFreeStandingElementFactory.RegisterFreeStandingClass(const ContentName: String; FreeStandingClass: TBoldFreeStandingElementClass); begin - fClasses.AddEntry(ContentName, '', TObject(FreeStandingClass)); + fClasses.AddEntry(ContentName, '', TObject(FreeStandingClass)); end; function TBoldFreeStandingElementFactory.CreateInstance(const ContentName: string): TBoldInterfacedObject; @@ -58,8 +60,8 @@ function TBoldFreeStandingElementFactory.CreateInstance(const ContentName: strin ElementClass := TBoldFreeStandingElementClass(fClasses.ObjectByName[ContentName]); if Assigned(ElementClass) then result := ElementClass.Create - else - raise EBold.createFmt(sNoClassregisteredForName, [classname, ContentName]); + else + raise EBold.createFmt('%s.CreateInstance: No freestanding class registered for name %s', [classname, ContentName]); end; initialization @@ -87,4 +89,3 @@ finalization FreeAndNil(FreeStandingValueFactory); end. - diff --git a/Source/FreestandingValueSpace/Core/BoldFreeStandingValues.pas b/Source/FreestandingValueSpace/Core/BoldFreeStandingValues.pas index 4b45072..7ef3b87 100644 --- a/Source/FreestandingValueSpace/Core/BoldFreeStandingValues.pas +++ b/Source/FreestandingValueSpace/Core/BoldFreeStandingValues.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldFreeStandingValues; interface @@ -48,49 +51,56 @@ TBFSObjectIdListRefPair = class; end; TBoldFreeStandingElementClass = class of TBoldFreeStandingElement; + TBoldFreeStandingObjectContentsClass = class of TBoldFreeStandingObjectContents; { TBoldFreeStandingElement } TBoldFreeStandingElement = class(TBoldNonRefCountedObject) public + class function ContentType: TBoldValueContentType; virtual; abstract; + function GetContentType: TBoldValueContentType; constructor Create; virtual; end; { TBoldFreeStandingValueSpace } TBoldFreeStandingValueSpace = class(TBoldFreeStandingElement, IBoldValueSpace) - private - fIdLIst: TBoldObjectIdlist; + strict private + fIdList: TBoldObjectIdlist; fObjectContentsList: TBoldFSObjectContentList; fTranslationList: TBoldIdTranslationList; - function GetIdList: TBoldObjectIdList; - function GetObjectContentsByObjectId(ObjectId: TBoldObjectId): IBoldObjectContents; + private + function GetIdList: TBoldObjectIdList; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetObjectContentsByObjectId(ObjectId: TBoldObjectId): IBoldObjectContents; {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure ApplyTranslationList(IdTranslationList: TBoldIdTranslationList); - procedure EnsureObjectId(ObjectId: TBoldObjectId); + procedure EnsureObjectId(ObjectId: TBoldObjectId); {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure ExactifyIDs(TranslationList: TBoldIdTranslationList); protected property IdList: TBoldObjectIdList read GetIdList; public constructor Create; override; destructor Destroy; override; + class function ContentType: TBoldValueContentType; override; procedure RemoveDeletedObjects; procedure MarkAllObjectsAndMembersCurrent; - function GetFSObjectContentsByObjectId(ObjectId: TBoldObjectId): TBoldFreeStandingObjectContents; - procedure RemoveFSObjectContentsByObjectId(ObjectId: TBoldObjectId); - procedure ApplyValueSpace(ValueSpace: IBoldValueSpace; IgnorePersistenceState: Boolean); + function GetFSObjectContentsByObjectId(ObjectId: TBoldObjectId): TBoldFreeStandingObjectContents; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure RemoveFSObjectContentsByObjectId(ObjectId: TBoldObjectId); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure RemoveFSObjectContents(ObjectContents: TBoldFreeStandingObjectContents); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure ApplyValueSpace(const ValueSpace: IBoldValueSpace; IgnorePersistenceState: Boolean); procedure AllObjectIds(resultList: TBoldObjectIdList; OnlyLoaded: Boolean); - procedure UpdateOwnValuesFrom(ValueSpace: IBoldValueSpace); + procedure ClearWhenObjectContentsEmpty; + procedure UpdateOwnValuesFrom(const ValueSpace: IBoldValueSpace); procedure RemoveAllObjectContents; - function GetHasContentsForId(ObjectId: TBoldObjectId): boolean; - procedure EnsureObjectContents(ObjectId: TBoldObjectId); - function GetEnsuredObjectContentsByObjectId(ObjectId: TBoldObjectId): IBoldObjectContents; - function GetEnsuredFSObjectContentsByObjectId(ObjectId: TBoldObjectId): TBoldFreeStandingObjectContents; + function GetHasContentsForId(ObjectId: TBoldObjectId): boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure EnsureObjectContents(ObjectId: TBoldObjectId); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetEnsuredObjectContentsByObjectIdAndCheckIfCreated(ObjectId: TBoldObjectId; out aBoldObjectContents: IBoldObjectContents): boolean; + function GetEnsuredObjectContentsByObjectId(ObjectId: TBoldObjectId): IBoldObjectContents; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetEnsuredFSObjectContentsByObjectId(ObjectId: TBoldObjectId): TBoldFreeStandingObjectContents; overload; + function GetEnsuredFSObjectContentsByObjectId(ObjectId: TBoldObjectId; out aCreated: boolean): TBoldFreeStandingObjectContents; overload; function GetValueForIdAndMemberIndex(Id: TBoldObjectId; MemberIndex: integer): IBoldValue; + function IdCount: integer; + function IsEmpty: boolean; + procedure Clear; end; - PMemberList = ^TMemberList; - TMemberList = array[0..MaxListSize - 1] of TBoldFreeStandingValue; - - - { TBoldFreeStandingObjectContents } TBoldFreeStandingObjectContents = class(TBoldFreeStandingElement, IBoldObjectContents, IBoldStreamable) private @@ -98,42 +108,47 @@ TBoldFreeStandingObjectContents = class(TBoldFreeStandingElement, IBoldObjectC fBoldPersistenceState: TBoldValuePersistenceState; fGlobalId: string; fIsReadOnly: Boolean; - fMemberList: PMemberList; - fMemberCount: integer; fObjectId: TBoldObjectId; fTimeStamp: TBoldTimeStampType; - function GetObjectId: TBoldObjectId; - function GetStreamName: string; + function GetObjectId: TBoldObjectId; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetStreamName: string; {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure ApplyTranslationList(TranslationList: TBoldIdTranslationList); - function GetBoldExistenceState: TBoldExistenceState; - function GetBoldMemberCount: Integer; - function GetBoldPersistenceState: TBoldValuePersistenceState; - function GetGlobalId: string; - function GetIsModified: Boolean; - function GetIsReadOnly: Boolean; - function GetValueByIndex(I: Integer): IBoldValue; - function GetFSValueByIndex(i: integer): TBoldFreeStandingValue; - function GetValueByMemberId(MemberId: TBoldMemberID):IBoldValue; - function GetTimeStamp: TBoldTimeStampType; - procedure SetBoldExistenceState(Value: TBoldExistenceState); - procedure SetBoldPersistenceState(Value: TBoldValuePersistenceState); - procedure SetGlobalId(const NewValue: string); - procedure SetIsReadOnly(NewValue: Boolean); - procedure SetTimeStamp(NewValue: TBoldTimeStampType); + function GetBoldExistenceState: TBoldExistenceState; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetBoldMemberCount: Integer; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetBoldPersistenceState: TBoldValuePersistenceState; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetGlobalId: string; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetIsModified: Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetIsReadOnly: Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetValueByIndex(I: Integer): IBoldValue; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetFSValueByIndex(i: integer): TBoldFreeStandingValue; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetValueByMemberId(MemberId: TBoldMemberID):IBoldValue; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetTimeStamp: TBoldTimeStampType; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure SetBoldExistenceState(Value: TBoldExistenceState); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure SetBoldPersistenceState(Value: TBoldValuePersistenceState); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure SetGlobalId(const NewValue: string); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure SetIsReadOnly(NewValue: Boolean); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure SetTimeStamp(NewValue: TBoldTimeStampType); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + protected + fMemberList: array of TBoldFreeStandingValue; + procedure EnsureMemberListLength(index: integer); // {$IFDEF BOLD_INLINE} inline; {$ENDIF} public constructor Create; override; destructor Destroy; override; + class function ContentType: TBoldValueContentType; override; procedure MarkAllMembersCurrent; - procedure RemoveMemberByIndex(Index: integer); + procedure RemoveMemberByIndex(Index: integer); {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure EnsureMember(MemberId: TBoldMemberId; const StreamName: string); - procedure EnsureMemberByIndex(Index: integer; const StreamName: string); - procedure ApplyObjectContents(ObjectContents: IBoldObjectContents; const ApplyValues: Boolean; const IgnorePersistenceState: Boolean); - procedure UpdateObjectContentsFrom(ObjectContents: IBoldObjectContents); + function EnsureMemberAndGetValueByIndex(Index: integer; const StreamName: string): IBoldValue; + procedure ApplyObjectContents(const ObjectContents: IBoldObjectContents; ApplyValues: Boolean; IgnorePersistenceState: Boolean); + procedure UpdateObjectContentsFrom(const ObjectContents: IBoldObjectContents); + function IsEmpty: boolean; property ValueByIndex[I: integer]: IBoldValue read GetValueByIndex; property FSValueByIndex[I: integer]: TBoldFreeStandingValue read GetFSValueByIndex; property BoldExistenceState: TBoldExistenceState read GetBoldExistenceState write SetBoldExistenceState; property BoldPersistenceState: TBoldValuePersistenceState read GetBoldPersistenceState write SetBoldPersistenceState; - property MemberCount: integer read fMemberCount; + property TimeStamp: TBoldTimeStampType read GetTimeStamp write SetTimeStamp; + property MemberCount: integer read GetBoldMemberCount; + property ObjectId: TBoldObjectId read GetObjectId; end; { TBoldFreeStandingValue } @@ -141,39 +156,49 @@ TBoldFreeStandingValue = class(TBoldFreeStandingElement, IBoldValue, IBoldStre private fBoldPersistenceState: TBoldValuePersistenceState; protected - function GetContentName: String; - function GetBoldPersistenceState: TBoldValuePersistenceState; - procedure SetBoldPersistenceState(Value: TBoldValuePersistenceState); + function GetContentName: String; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetBoldPersistenceState: TBoldValuePersistenceState; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure SetBoldPersistenceState(Value: TBoldValuePersistenceState); {$IFDEF BOLD_INLINE} inline; {$ENDIF} function GetStreamName: string; virtual; abstract; procedure ApplyTranslationList(TranslationList: TBoldIdTranslationList); virtual; - procedure AssignContentValue(Source: IBoldValue); virtual; + procedure AssignContentValue(const Source: IBoldValue); virtual; public constructor Create; override; - procedure AssignContent(Source: IBoldValue); + procedure AssignContent(const Source: IBoldValue); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function IsEqualToValue(const Value: IBoldValue): Boolean; virtual; property ContentName: string read GetContentName; property BoldPersistenceState: TBoldValuePersistenceState read fBoldPersistenceState write fBoldPersistenceState; end; { TBoldFreeStandingNullableValue } - TBoldFreeStandingNullableValue = class(TBoldFreeStandingValue, IBoldNullableValue) + TBoldFreeStandingNullableValue = class(TBoldFreeStandingValue, IBoldNullableValue, IBoldVariantReadable, IBoldStringRepresentable) private fIsNull: Boolean; + function GetAsVariant: Variant; {$IFDEF BOLD_INLINE} inline; {$ENDIF} protected - procedure SetToNonNull; - function GetContentIsNull: Boolean; - procedure SetContentToNull; + procedure SetToNonNull; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetContentIsNull: Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure SetContentToNull; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetValueAsVariant: Variant; virtual; abstract; + function GetStringRepresentation(representation:integer): String; virtual; + function GetContentAsString: String; virtual; + public + function IsEqualToValue(const Value: IBoldValue): Boolean; override; end; { TBFSInteger } TBFSInteger = class(TBoldFreeStandingNullableValue, IBoldIntegerContent) private fDataValue: Integer; - function GetContentAsInteger: Integer; - procedure SetContentAsInteger(NewValue: Integer); + function GetContentAsInteger: Integer; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure SetContentAsInteger(NewValue: Integer); {$IFDEF BOLD_INLINE} inline; {$ENDIF} protected function GetStreamName: string; override; - procedure AssignContentValue(Source: IBoldValue); override; + procedure AssignContentValue(const Source: IBoldValue); override; + function GetValueAsVariant: Variant; override; public + class function ContentType: TBoldValueContentType; override; + function IsEqualToValue(const Value: IBoldValue): Boolean; override; property AsInteger: Integer read GetContentAsInteger write SetContentAsInteger; end; @@ -181,12 +206,15 @@ TBFSInteger = class(TBoldFreeStandingNullableValue, IBoldIntegerContent) TBFSString = class(TBoldFreeStandingNullableValue, IBoldStringContent) private fDataValue: String; - function GetContentAsString: String; - procedure SetContentAsString(const NewValue: String); + function GetContentAsString: String; override; + procedure SetContentAsString(const NewValue: String); {$IFDEF BOLD_INLINE} inline; {$ENDIF} protected function GetStreamName: string; override; - procedure AssignContentValue(Source: IBoldValue); override; + procedure AssignContentValue(const Source: IBoldValue); override; + function GetValueAsVariant: Variant; override; public + class function ContentType: TBoldValueContentType; override; + function IsEqualToValue(const Value: IBoldValue): Boolean; override; property AsString: String read GetContentAsString write SetContentAsString; end; @@ -194,12 +222,15 @@ TBFSString = class(TBoldFreeStandingNullableValue, IBoldStringContent) TBFSCurrency = class(TBoldFreeStandingNullableValue, IBoldCurrencyContent) private fDataValue: Currency; - function GetContentAsCurrency: Currency; - procedure SetContentAsCurrency(NewValue: Currency); + function GetContentAsCurrency: Currency; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure SetContentAsCurrency(NewValue: Currency); {$IFDEF BOLD_INLINE} inline; {$ENDIF} protected function GetStreamName: String; override; - procedure AssignContentValue(Source: IBoldValue); override; + procedure AssignContentValue(const Source: IBoldValue); override; + function GetValueAsVariant: Variant; override; public + class function ContentType: TBoldValueContentType; override; + function IsEqualToValue(const Value: IBoldValue): Boolean; override; property AsCurrency: Currency read GetContentAsCurrency write SetContentAsCurrency; end; @@ -207,12 +238,15 @@ TBFSCurrency = class(TBoldFreeStandingNullableValue, IBoldCurrencyContent) TBFSFloat = class(TBoldFreeStandingNullableValue, IBoldFloatContent) private fDataValue: Double; - function GetContentAsFloat: Double; - procedure SetContentAsFloat(NewValue: Double); + function GetContentAsFloat: Double; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure SetContentAsFloat(NewValue: Double); {$IFDEF BOLD_INLINE} inline; {$ENDIF} protected function GetStreamName: String; override; - procedure AssignContentValue(Source: IBoldValue); override; + procedure AssignContentValue(const Source: IBoldValue); override; + function GetValueAsVariant: Variant; override; public + class function ContentType: TBoldValueContentType; override; + function IsEqualToValue(const Value: IBoldValue): Boolean; override; property AsFloat: Double read GetContentAsFloat write SetContentAsFloat; end; @@ -220,12 +254,15 @@ TBFSFloat = class(TBoldFreeStandingNullableValue, IBoldFloatContent) TBFSBoolean = class(TBoldFreeStandingNullableValue, IBoldBooleanContent) private fDataValue: Boolean; - function GetContentAsBoolean: Boolean; - procedure SetContentAsBoolean(NewValue: Boolean); + function GetContentAsBoolean: Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure SetContentAsBoolean(NewValue: Boolean); {$IFDEF BOLD_INLINE} inline; {$ENDIF} protected function GetStreamName: String; override; - procedure AssignContentValue(Source: IBoldValue); override; + procedure AssignContentValue(const Source: IBoldValue); override; + function GetValueAsVariant: Variant; override; public + class function ContentType: TBoldValueContentType; override; + function IsEqualToValue(const Value: IBoldValue): Boolean; override; property AsBoolean: Boolean read GetContentAsBoolean write SetContentAsBoolean; end; @@ -234,20 +271,23 @@ TBFSDateTimeAbstract = class(TBoldFreeStandingNullableValue) private fDataValue: TDateTime; protected - function GetContentAsDateTime: TDateTime; - procedure SetContentAsDateTime(NewValue: TDateTime); - function GetContentAsTime: TDateTime; - procedure SetContentAsTime(NewValue: TDateTime); - function GetContentAsDate: TDateTime; - procedure SetContentAsDate(NewValue: TDateTime); + function GetContentAsDateTime: TDateTime; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure SetContentAsDateTime(NewValue: TDateTime); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetContentAsTime: TDateTime; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure SetContentAsTime(NewValue: TDateTime); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetContentAsDate: TDateTime; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure SetContentAsDate(NewValue: TDateTime); {$IFDEF BOLD_INLINE} inline; {$ENDIF} end; { TBFSDateTime } TBFSDateTime = class(TBFSDateTimeAbstract, IBoldDateTimeContent) protected function GetStreamName: String; override; - procedure AssignContentValue(Source: IBoldValue); override; + procedure AssignContentValue(const Source: IBoldValue); override; + function GetValueAsVariant: Variant; override; public + class function ContentType: TBoldValueContentType; override; + function IsEqualToValue(const Value: IBoldValue): Boolean; override; property AsDateTime: TDateTime read GetContentAsDateTime write SetContentAsDateTime; end; @@ -255,8 +295,11 @@ TBFSDateTime = class(TBFSDateTimeAbstract, IBoldDateTimeContent) TBFSDate = class(TBFSDateTimeAbstract, IBoldDateContent) protected function GetStreamName: String; override; - procedure AssignContentValue(Source: IBoldValue); override; + procedure AssignContentValue(const Source: IBoldValue); override; + function GetValueAsVariant: Variant; override; public + class function ContentType: TBoldValueContentType; override; + function IsEqualToValue(const Value: IBoldValue): Boolean; override; property AsDate: TDateTime read GetContentAsDate write SetContentAsDate; end; @@ -264,39 +307,48 @@ TBFSDate = class(TBFSDateTimeAbstract, IBoldDateContent) TBFSTime = class(TBFSDateTimeAbstract, IBoldTimeContent) protected function GetStreamName: String; override; - procedure AssignContentValue(Source: IBoldValue); override; + procedure AssignContentValue(const Source: IBoldValue); override; + function GetValueAsVariant: Variant; override; public + class function ContentType: TBoldValueContentType; override; + function IsEqualToValue(const Value: IBoldValue): Boolean; override; property AsTime: TDateTime read GetContentAsTime write SetContentAsTime; end; { TBFSBlobAbstract } TBFSBlobAbstract = class(TBoldFreeStandingNullableValue) private - fDataValue: String; - function GetContentAsBlob: String; - procedure SetContentAsBlob(const NewValue: String); + fDataValue: AnsiString; + function GetContentAsBlob: TBoldAnsiString; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure SetContentAsBlob(const NewValue: TBoldAnsiString); {$IFDEF BOLD_INLINE} inline; {$ENDIF} protected function GetStreamName: String; override; + function GetValueAsVariant: Variant; override; public - property AsBlob: String read GetContentAsBlob write SetContentAsBlob; + property AsBlob: TBoldAnsiString read GetContentAsBlob write SetContentAsBlob; end; { TBFSBlob } TBFSBlob = class(TBFSBlobAbstract, IBoldBlobContent) protected - procedure AssignContentValue(Source: IBoldValue); override; + procedure AssignContentValue(const Source: IBoldValue); override; + public + class function ContentType: TBoldValueContentType; override; + function IsEqualToValue(const Value: IBoldValue): Boolean; override; end; { TBFSTypedBlob } TBFSTypedBlob = class(TBFSBlobAbstract, IBoldTypedBlob, IBoldBlobContent) private fContent: String; - function GetContentTypeContent: String; - procedure SetContentTypeContent(const NewValue: String); + function GetContentTypeContent: String; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure SetContentTypeContent(const NewValue: String); {$IFDEF BOLD_INLINE} inline; {$ENDIF} protected - function GetStreamName: String; override; - procedure AssignContentValue(Source: IBoldValue); override; + function GetStreamName: String; override; + procedure AssignContentValue(const Source: IBoldValue); override; public + class function ContentType: TBoldValueContentType; override; + function IsEqualToValue(const Value: IBoldValue): Boolean; override; property ContentTypeContent: String read GetContentTypeContent write SetContentTypeContent; end; @@ -306,8 +358,8 @@ TBFSTypedBlob = class(TBFSBlobAbstract, IBoldTypedBlob, IBoldBlobContent) TBFSObjectIDRefAbstract = class(TBoldFreeStandingValue) private fOrderNo: Integer; - function GetOrderNo: integer; - procedure SetOrderNo(NewOrder: Integer); + function GetOrderNo: integer; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure SetOrderNo(NewOrder: Integer); {$IFDEF BOLD_INLINE} inline; {$ENDIF} public property OrderNo: integer read GetOrderNo write SetOrderNo; end; @@ -316,14 +368,16 @@ TBFSObjectIDRefAbstract = class(TBoldFreeStandingValue) TBFSObjectIDRef = class(TBFSObjectIDRefAbstract, IBoldObjectIdRef) private fObjectId: TBoldObjectId; - function GetId: TBoldObjectID; + function GetId: TBoldObjectID; {$IFDEF BOLD_INLINE} inline; {$ENDIF} protected - procedure AssignContentValue(Source: IBoldValue); override; + procedure AssignContentValue(const Source: IBoldValue); override; function GetStreamName: String; override; procedure ApplyTranslationList(TranslationList: TBoldIdTranslationList); override; public destructor Destroy; override; - procedure SetFromId(Id: TBoldObjectId); + class function ContentType: TBoldValueContentType; override; + function IsEqualToValue(const Value: IBoldValue): Boolean; override; + procedure SetFromId(Id: TBoldObjectId; Adopt: Boolean); property Id: TBoldObjectId read GetId; end; @@ -331,15 +385,16 @@ TBFSObjectIDRef = class(TBFSObjectIDRefAbstract, IBoldObjectIdRef) TBFSObjectIDRefPair = class(TBFSObjectIDRefAbstract, IBoldObjectIdRefPair) private fObjectIds: TBoldObjectIdList; - procedure EnsureIdList; - function GetId1: TBoldObjectID; - function GetId2: TBoldObjectID; + procedure EnsureIdList; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetId1: TBoldObjectID; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetId2: TBoldObjectID; {$IFDEF BOLD_INLINE} inline; {$ENDIF} protected - procedure AssignContentValue(Source: IBoldValue); override; + procedure AssignContentValue(const Source: IBoldValue); override; function GetStreamName: String; override; procedure ApplyTranslationList(TranslationList: TBoldIdTranslationList); override; public destructor Destroy; override; + class function ContentType: TBoldValueContentType; override; procedure SetFromIds(Id1, Id2: TBoldObjectId); property Id1: TBoldObjectId read GetId1; property Id2: TBoldObjectId read GetId2; @@ -352,15 +407,17 @@ TBFSObjectIdListref = class(TBoldFreeStandingValue, IBoldObjectIdListRef, IBol function GetIdList(Index: Integer): TBoldObjectID; procedure RemoveId(Id: TBoldObjectId); procedure AddId(Id: TBoldObjectId); - procedure EnsureList; + procedure EnsureList; {$IFDEF BOLD_INLINE} inline; {$ENDIF} protected - procedure AssignContentValue(Source: IBoldValue); override; + procedure AssignContentValue(const Source: IBoldValue); override; function GetStreamName: String; override; procedure ApplyTranslationList(TranslationList: TBoldIdTranslationList); override; - function GetCount: integer; + function GetCount: integer; {$IFDEF BOLD_INLINE} inline; {$ENDIF} public destructor Destroy; override; + class function ContentType: TBoldValueContentType; override; procedure SetFromIdList(IdList: TBoldObjectIdList); + procedure SetList(IdList: TBoldObjectIdList); property IdList[Index: integer]: TBoldObjectID read GetIdList; property Count: integer read GetCount; end; @@ -369,18 +426,19 @@ TBFSObjectIdListref = class(TBoldFreeStandingValue, IBoldObjectIdListRef, IBol TBFSObjectIdListrefPair = class(TBoldFreeStandingValue, IBoldObjectIdListRefPair, IBoldFreeStandingIdListPair) private fIdLIst1, fIdList2: TBoldObjectidLIst; - function GetIdList1(Index: Integer): TBoldObjectID; - function GetIdList2(Index: Integer): TBoldObjectID; - procedure EnsureLists; + function GetIdList1(Index: Integer): TBoldObjectID; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetIdList2(Index: Integer): TBoldObjectID; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure EnsureLists; {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure AddIds(Id1, Id2: TBoldObjectId); procedure RemoveId(Id: TBoldObjectId); protected - procedure AssignContentValue(Source: IBoldValue); override; + procedure AssignContentValue(const Source: IBoldValue); override; function GetStreamName: String; override; procedure ApplyTranslationList(TranslationList: TBoldIdTranslationList); override; - function GetCount: integer; + function GetCount: integer; {$IFDEF BOLD_INLINE} inline; {$ENDIF} public destructor Destroy; override; + class function ContentType: TBoldValueContentType; override; procedure SetFromIdLists(IdList1, IdList2: TBoldObjectIdList); property IdList1[Index: integer]: TBoldObjectID read GetIdList1; property IdList2[Index: integer]: TBoldObjectID read GetIdList2; @@ -388,30 +446,32 @@ TBFSObjectIdListrefPair = class(TBoldFreeStandingValue, IBoldObjectIdListRefPa end; { TBoldFSObjectContentList } - - // this list should be an unordered indexable list for performace reasons, but FSValueSpace.ApplyTranslationList is a bit tricky to rewrite... TBoldFSObjectContentList = class(TBoldIndexableList) private - function GetItems(index: integer): TBoldFreeStandingObjectContents; + class var IX_FSObjectContent: integer; + function GetItems(index: integer): TBoldFreeStandingObjectContents; {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure SetItems(index: integer; const Value: TBoldFreeStandingObjectContents); public constructor Create; - function FindObjectContentById(Id: TBoldObjectId): TBoldFreeStandingObjectContents; + function FindObjectContentById(Id: TBoldObjectId): TBoldFreeStandingObjectContents; {$IFDEF BOLD_INLINE} inline; {$ENDIF} property Items[index: integer]: TBoldFreeStandingObjectContents read GetItems write SetItems; default; end; + +var + BoldFreeStandingObjectContentsClass: TBoldFreeStandingObjectContentsClass = TBoldFreeStandingObjectContents; + implementation uses SysUtils, - FreeStandingValuesConst, BoldUtils, BoldIndex, BoldHashIndexes, BoldFreeStandingValueFactories, BoldDefaultStreamNames, - BoldMemoryManager, - BoldGuard; + BoldGuard, + Variants; type {---TBoldObjectIdHashIndex---} @@ -421,29 +481,30 @@ TBoldFSObjectContentHashIndex = class(TBoldHashIndex) function HashItem(Item: TObject): Cardinal; override; function Match(const Key; Item:TObject):Boolean; override; function Hash(const Key): Cardinal; override; - function FindById(boldObjectId:TboldObjectId): TObject; + function FindById(BoldObjectId: TBoldObjectId): TObject; {$IFDEF BOLD_INLINE} inline; {$ENDIF} end; -var - IX_FSObjectContent: integer = -1; - {---TBoldFreeStandingElement---} constructor TBoldFreeStandingElement.Create; begin - // this is empty, but allows other freestanding values to initialize values - // in their overridden constructors + inherited; end; +function TBoldFreeStandingElement.GetContentType: TBoldValueContentType; +begin + result := ContentType; +end; + {---TBoldFreeStandingvalueSpace---} constructor TBoldFreeStandingvalueSpace.Create; begin inherited; fObjectContentsList := TBoldFSObjectContentList.create; - fIdLIst := tBoldObjectIdList.Create; + fIdLIst := TBoldObjectIdList.Create; end; destructor TBoldFreeStandingvalueSpace.Destroy; @@ -467,25 +528,30 @@ function TBoldFreeStandingvalueSpace.GetIdList: TBoldObjectIdList; result := fIdList; end; +function TBoldFSObjectContentList.FindObjectContentById(Id: TBoldObjectId): TBoldFreeStandingObjectContents; +begin + Result := TBoldFreeStandingObjectContents(TBoldHashIndex(indexes[IX_FSObjectContent]).Find(ID)); +end; + function TBoldFreeStandingvalueSpace.GetFSObjectContentsByObjectId(ObjectId: TBoldObjectId): TBoldFreeStandingObjectContents; begin result := fObjectContentsList.FindObjectContentById(ObjectId); end; +procedure TBoldFreeStandingValueSpace.RemoveFSObjectContents( + ObjectContents: TBoldFreeStandingObjectContents); +begin + fObjectContentsList.Remove(ObjectContents); +end; + procedure TBoldFreeStandingvalueSpace.RemoveFSObjectContentsByObjectId(ObjectId: TBoldObjectId); begin fObjectContentsList.Remove(GetFSObjectContentsByObjectId(ObjectId)); end; function TBoldFreeStandingvalueSpace.GetObjectContentsByObjectId(ObjectId: TBoldObjectId): IBoldObjectContents; -var - temp: TBoldFreeStandingObjectContents; begin - temp := GetFSObjectContentsByObjectId(ObjectId); - if assigned(temp) then - result := temp - else - result := nil; + result := GetFSObjectContentsByObjectId(ObjectId); end; function TBoldFreeStandingvalueSpace.GetEnsuredObjectContentsByObjectId(ObjectId: TBoldObjectId): IBoldObjectContents; @@ -493,6 +559,13 @@ function TBoldFreeStandingvalueSpace.GetEnsuredObjectContentsByObjectId(ObjectId Result := GetEnsuredFSObjectContentsByObjectId(ObjectId); end; +function TBoldFreeStandingValueSpace.GetEnsuredObjectContentsByObjectIdAndCheckIfCreated( + ObjectId: TBoldObjectId; + out aBoldObjectContents: IBoldObjectContents): boolean; +begin + aBoldObjectContents := GetEnsuredFSObjectContentsByObjectId(ObjectId, result); +end; + function TBoldFreeStandingvalueSpace.GetHasContentsForId(ObjectId: TBoldObjectId): boolean; begin result := assigned(GetObjectContentsByObjectId(Objectid)); @@ -534,12 +607,13 @@ procedure TBoldFreeStandingvalueSpace.ApplytranslationList(IdTranslationList: TB if not assigned(fTranslationList) then fTranslationList := TBoldIDTranslationList.Create; For i := 0 to IdTranslationList.Count - 1 do + if IdTranslationList.OldIds[i] <> nil then fTranslationList.AddTranslation(IdTranslationList.OldIds[i], IdTranslationList.NewIds[i]); for i := 0 to fObjectContentsList.Count - 1 do DoOneObject(i, TBoldFreeStandingObjectContents(fObjectContentsList[i])); end; -procedure TBoldFreeStandingvalueSpace.ApplyValueSpace(ValueSpace: IBoldValueSpace; IgnorePersistenceState: Boolean); +procedure TBoldFreeStandingvalueSpace.ApplyValueSpace(const ValueSpace: IBoldValueSpace; IgnorePersistenceState: Boolean); var i: Integer; anIdList: TBoldObjectIdList; @@ -580,12 +654,8 @@ destructor TBoldFreeStandingObjectContents.Destroy; var i: integer; begin - if Assigned(fMemberList) then - begin - for i := 0 to fMemberCount - 1 do - fMemberList^[i].Free; - BoldMemoryManager_.DeAllocateMemory(fMemberList, fMemberCount*sizeof(Pointer)); - end; + for i := 0 to Length(fMemberList) - 1 do + FreeAndNil(fMemberList[i]); inherited; end; @@ -595,6 +665,19 @@ function TBoldFreeStandingObjectContents.GetValueByMemberId(MemberId: TBoldMembe result := GetValueByIndex(MemberId.MemberIndex); end; +function TBoldFreeStandingObjectContents.IsEmpty: boolean; +var + i: integer; +begin + result := true; + for i := Length(fMemberList) - 1 downto 0 do + if Assigned(fMemberList[i]) then + begin + result := false; + exit; + end; +end; + function TBoldFreeStandingObjectContents.GetStreamName: string; begin result := BOLDOBJECTCONTENTSNAME; @@ -602,13 +685,13 @@ function TBoldFreeStandingObjectContents.GetStreamName: string; procedure TBoldFreeStandingObjectContents.EnsureMember(MemberId: TBoldMemberId; const StreamName: string); begin - EnsurememberByIndex( MemberId.MemberIndex, StreamName ); + EnsureMemberAndGetValueByIndex( MemberId.MemberIndex, StreamName ); end; function TBoldFreeStandingObjectContents.GetValueByIndex(I: Integer): IBoldValue; begin - if i < MemberCount then - result := fMemberList^[i] + if i < Length(fMemberList) then + result := fMemberList[i] else result := nil; end; @@ -616,12 +699,11 @@ function TBoldFreeStandingObjectContents.GetValueByIndex(I: Integer): IBoldValue function TBoldFreeStandingObjectContents.GetFSValueByIndex(i: integer): TBoldFreeStandingValue; begin if i < MemberCount then - result := fMemberList^[i] + result := fMemberList[i] else result := nil; end; - function TBoldFreeStandingObjectContents.GetIsModified: Boolean; begin result := True; @@ -636,7 +718,6 @@ function TBoldFreeStandingValue.GetBoldPersistenceState: TBoldValuePersistenceSt procedure TBoldFreeStandingValue.ApplyTranslationList(TranslationList: TBoldIdTranslationList); begin - // do nothing end; {---TBoldFreeStandingNullableValue---} @@ -646,16 +727,48 @@ procedure TBoldFreeStandingNullableValue.SetContentToNull; fIsNull := true; end; +function TBoldFreeStandingNullableValue.GetContentAsString: String; +begin + result := GetStringRepresentation(brDefault); +end; + function TBoldFreeStandingNullableValue.GetContentIsNull: Boolean; begin result := fIsNull; end; +function TBoldFreeStandingNullableValue.IsEqualToValue(const Value: IBoldValue): + Boolean; +var + aNullableValue: IBoldNullableValue; +begin + Result := Assigned(Value) and + (Value.QueryInterface(IBoldNullableValue, aNullableValue) = S_OK) and + (fIsNull = aNullableValue.IsNull); +end; + +function TBoldFreeStandingNullableValue.GetStringRepresentation( + representation: integer): String; +begin + if GetContentIsNull then + result := '' + else + result := VarToStr(GetValueAsVariant); +end; + procedure TBoldFreeStandingNullableValue.SetToNonNull; begin fIsNull := false; end; +function TBoldFreeStandingNullableValue.GetAsVariant; +begin + if GetContentIsNull then + result := Null + else + result := GetValueAsVariant; +end; + {---TBFSInteger---} function TBFSInteger.GetStreamName: string; @@ -663,11 +776,21 @@ function TBFSInteger.GetStreamName: string; result := BoldContentName_Integer; end; +function TBFSInteger.GetValueAsVariant: Variant; +begin + result := AsInteger; +end; + function TBFSInteger.GetContentAsInteger: Integer; begin result := fDataValue; end; +class function TBFSInteger.ContentType: TBoldValueContentType; +begin + result := bctInteger; +end; + procedure TBFSInteger.SetContentAsInteger(NewValue: Integer); begin fDataValue := NewValue; @@ -681,14 +804,24 @@ function TBFSString.GetStreamName: string; result := BoldContentName_String; end; +function TBFSString.GetValueAsVariant: Variant; +begin + result := AsString; +end; + function TBFSString.GetContentAsString: String; begin result := fDataValue; end; +class function TBFSString.ContentType: TBoldValueContentType; +begin + result := bctString; +end; + procedure TBFSString.SetContentAsString(const NewValue: String); begin - fDataValue := NewValue; + fDataValue := NewValue; // Use BoldSharedStringManager ? SetToNonNull; end; @@ -699,11 +832,21 @@ function TBFSCurrency.GetStreamName: String; result := BoldContentName_Currency; end; +function TBFSCurrency.GetValueAsVariant: Variant; +begin + result := AsCurrency; +end; + function TBFSCurrency.GetContentAsCurrency: Currency; begin result := fDataValue; end; +class function TBFSCurrency.ContentType: TBoldValueContentType; +begin + result := bctCurrency; +end; + procedure TBFSCurrency.SetContentAsCurrency(NewValue: Currency); begin fDataValue := NewValue; @@ -717,11 +860,21 @@ function TBFSFloat.GetStreamName: String; result := BoldContentName_Float; end; +function TBFSFloat.GetValueAsVariant: Variant; +begin + result := AsFloat; +end; + function TBFSFloat.GetContentAsFloat: double; begin result := fDataValue; end; +class function TBFSFloat.ContentType: TBoldValueContentType; +begin + result := bctFloat; +end; + procedure TBFSFloat.SetContentAsFloat(NewValue: Double); begin fDataValue := NewValue; @@ -735,11 +888,21 @@ function TBFSBoolean.GetStreamName: String; Result := BoldContentName_Boolean; end; +function TBFSBoolean.GetValueAsVariant: Variant; +begin + result := AsBoolean; +end; + function TBFSBoolean.GetContentAsBoolean: Boolean; begin Result := fDataValue; end; +class function TBFSBoolean.ContentType: TBoldValueContentType; +begin + result := bctBoolean; +end; + procedure TBFSBoolean.SetContentAsBoolean(NewValue: Boolean); begin fDataValue := NewValue; @@ -788,12 +951,17 @@ function TBFSBlobAbstract.GetStreamName: String; Result := BoldContentName_Blob; end; -function TBFSBlobAbstract.GetContentAsBlob: String; +function TBFSBlobAbstract.GetValueAsVariant: Variant; +begin + result := AsBlob; +end; + +function TBFSBlobAbstract.GetContentAsBlob: TBoldAnsiString; begin Result := fDataValue; end; -procedure TBFSBlobAbstract.SetContentAsBlob(const NewValue: String); +procedure TBFSBlobAbstract.SetContentAsBlob(const NewValue: TBoldAnsiString); begin fDataValue := NewValue; SetToNonNull; @@ -806,6 +974,11 @@ function TBFSTypedBlob.GetStreamName: String; Result := BoldContentName_TypedBlob; end; +class function TBFSTypedBlob.ContentType: TBoldValueContentType; +begin + result := bctTypedBlob; +end; + function TBFSTypedBlob.GetContentTypeContent: String; begin Result := fContent; @@ -836,18 +1009,36 @@ function TBFSObjectIdRef.GetStreamName: String; Result := BoldContentName_ObjectIdRef; end; -procedure TBFSObjectIdRef.SetFromId(Id: TBoldObjectId); +procedure TBFSObjectIdRef.SetFromId(Id: TBoldObjectId; Adopt: Boolean); +var + Assign: Boolean; begin + Assign := false; if assigned(Id) then begin if (not Assigned(fObjectId)) or (not Id.IsEqual[fObjectId]) then begin FreeAndNil(fObjectId); - fObjectId := Id.Clone; + Assign := True; end - end + end else FreeAndNil(fObjectId); + if Adopt then + begin + if Assign then + fObjectId := Id + else + FreeAndNil(Id); + end + else + if Assign then + fObjectId := Id.Clone; +end; + +class function TBFSObjectIDRef.ContentType: TBoldValueContentType; +begin + result := bctObjectIdRef; end; function TBFSObjectIdRef.GetId: TBoldObjectID; @@ -875,6 +1066,11 @@ procedure TBFSObjectIdRefPair.SetFromIds(Id1, Id2: TBoldObjectId); end; end; +class function TBFSObjectIDRefPair.ContentType: TBoldValueContentType; +begin + result := bctObjectIdRefPair; +end; + function TBFSObjectIdRefPair.GetId1: TBoldObjectID; begin EnsureIdList; @@ -905,6 +1101,16 @@ procedure TBFSObjectIdListref.SetFromIdList(IdList: TBoldObjectIdList); fIdList := IdList.Clone; end; +procedure TBFSObjectIdListref.SetList(IdList: TBoldObjectIdList); +var + i: integer; +begin + IdList.Clear; + IdList.Capacity := fIdList.Count; + for i := 0 to fIdList.Count - 1 do + IdList.Add(fIdList[i]); +end; + function TBFSObjectIdListref.GetIdList(Index: Integer): TBoldObjectID; begin result := fIdList[Index]; @@ -969,11 +1175,12 @@ procedure TBoldFreeStandingObjectContents.ApplyTranslationList( var i: Integer; begin - for i := 0 to MemberCount - 1 do - if Assigned(fMemberList^[i]) then - fMemberList^[i].ApplyTranslationList(TranslationList); + for i := 0 to Length(fMemberList)- 1 do + if Assigned(fMemberList[i]) then + fMemberList[i].ApplyTranslationList(TranslationList); end; + procedure TBFSObjectIdListref.ApplyTranslationList( TranslationList: TBoldIdTranslationList); begin @@ -986,7 +1193,6 @@ procedure TBFSObjectIdListrefPair.ApplyTranslationList( begin if assigned(fIdlist1) then begin - // the two lists are either assigned or not assigned, there can never be one assigned and one not assigned fIdLIst1.ApplyTranslationList(TranslationList); fIdList2.ApplyTranslationList(TranslationList); end; @@ -1036,9 +1242,13 @@ procedure TBFSObjectIDRefPair.EnsureIdList; procedure TBoldFreeStandingValueSpace.AllObjectIds( resultList: TBoldObjectIdList; OnlyLoaded: Boolean); var - i: integer; + i,j: integer; begin - for i := 0 to fIdList.Count - 1 do + j := fIdList.Count; + if j = 0 then + exit; + resultList.Capacity := j; + for i := 0 to j - 1 do if OnlyLoaded then begin if Assigned(GetObjectContentsByObjectId(fIdList[i])) then @@ -1066,6 +1276,11 @@ procedure TBoldFreeStandingValueSpace.RemoveDeletedObjects; end; end; +class function TBFSObjectIdListref.ContentType: TBoldValueContentType; +begin + result := bctObjectIdListRef; +end; + function TBFSObjectIdListref.GetCount: integer; begin if assigned(fIdList) then @@ -1074,6 +1289,11 @@ function TBFSObjectIdListref.GetCount: integer; result := 0; end; +class function TBFSObjectIdListrefPair.ContentType: TBoldValueContentType; +begin + result := bctObjectIdListRefPair; +end; + function TBFSObjectIdListrefPair.GetCount: integer; begin if assigned(fIdList1) then @@ -1098,6 +1318,11 @@ function TBoldFreeStandingObjectContents.GetBoldPersistenceState: TBoldValuePers result := fBoldPersistenceState; end; +class function TBoldFreeStandingObjectContents.ContentType: TBoldValueContentType; +begin + result := bctObject; +end; + procedure TBoldFreeStandingObjectContents.SetBoldExistenceState( Value: TBoldExistenceState); begin @@ -1110,13 +1335,13 @@ procedure TBoldFreeStandingObjectContents.SetBoldPersistenceState( fBoldPersistenceState := Value; end; -procedure TBoldFreeStandingValue.AssignContent(Source: IBoldValue); +procedure TBoldFreeStandingValue.AssignContent(const Source: IBoldValue); begin AssignContentValue(Source); BoldPersistenceState := Source.BoldPersistenceState; end; -procedure TBFSInteger.AssignContentValue(Source: IBoldValue); +procedure TBFSInteger.AssignContentValue(const Source: IBoldValue); var s: IBoldIntegerContent; begin @@ -1126,10 +1351,19 @@ procedure TBFSInteger.AssignContentValue(Source: IBoldValue); else SetContentAsInteger(s.AsInteger) else - raise EBold.CreateFmt(sUnknownTypeOfSource, [classname]); + raise EBold.CreateFmt('%s.AssignContentValue: unknown type of source', [classname]); +end; + +function TBFSInteger.IsEqualToValue(const Value: IBoldValue): Boolean; +var + aIntegerValue: IBoldIntegerContent; +begin + Result := inherited IsEqualToValue(Value) and + (Value.QueryInterface(IBoldIntegerContent, aIntegerValue) = S_OK) and + (AsInteger = aIntegerValue.asInteger); end; -procedure TBFSString.AssignContentValue(Source: IBoldValue); +procedure TBFSString.AssignContentValue(const Source: IBoldValue); var s: IBoldStringContent; begin @@ -1139,10 +1373,19 @@ procedure TBFSString.AssignContentValue(Source: IBoldValue); else SetContentAsString(s.AsString) else - raise EBold.CreateFmt(sUnknownTypeOfSource, [classname]); + raise EBold.CreateFmt('%s.AssignContentValue: unknown type of source', [classname]); +end; + +function TBFSString.IsEqualToValue(const Value: IBoldValue): Boolean; +var + aStringValue: IBoldStringContent; +begin + Result := inherited IsEqualToValue(Value) and + (Value.QueryInterface(IBoldStringContent, aStringValue) = S_OK) and + (AsString = aStringValue.asString); end; -procedure TBFSCurrency.AssignContentValue(Source: IBoldValue); +procedure TBFSCurrency.AssignContentValue(const Source: IBoldValue); var s: IBoldCurrencyContent; begin @@ -1152,10 +1395,19 @@ procedure TBFSCurrency.AssignContentValue(Source: IBoldValue); else SetContentAsCurrency(s.AsCurrency) else - raise EBold.CreateFmt(sUnknownTypeOfSource, [classname]); + raise EBold.CreateFmt('%s.AssignContentValue: unknown type of source', [classname]); end; -procedure TBFSFloat.AssignContentValue(Source: IBoldValue); +function TBFSCurrency.IsEqualToValue(const Value: IBoldValue): Boolean; +var + aCurrencyValue: IBoldCurrencyContent; +begin + Result := inherited IsEqualToValue(Value) and + (Value.QueryInterface(IBoldCurrencyContent, aCurrencyValue) = S_OK) and + (AsCurrency = aCurrencyValue.asCurrency); +end; + +procedure TBFSFloat.AssignContentValue(const Source: IBoldValue); var s: IBoldFloatContent; begin @@ -1165,10 +1417,19 @@ procedure TBFSFloat.AssignContentValue(Source: IBoldValue); else SetContentAsFloat(s.AsFloat) else - raise EBold.CreateFmt(sUnknownTypeOfSource, [classname]); + raise EBold.CreateFmt('%s.AssignContentValue: unknown type of source', [classname]); +end; + +function TBFSFloat.IsEqualToValue(const Value: IBoldValue): Boolean; +var + aFloatValue: IBoldFloatContent; +begin + Result := inherited IsEqualToValue(Value) and + (Value.QueryInterface(IBoldFloatContent, aFloatValue) = S_OK) and + (AsFloat = aFloatValue.asFloat); end; -procedure TBFSBoolean.AssignContentValue(Source: IBoldValue); +procedure TBFSBoolean.AssignContentValue(const Source: IBoldValue); var s: IBoldBooleanContent; begin @@ -1178,12 +1439,21 @@ procedure TBFSBoolean.AssignContentValue(Source: IBoldValue); else SetContentAsBoolean(s.AsBoolean) else - raise EBold.CreateFmt(sUnknownTypeOfSource, [classname]); + raise EBold.CreateFmt('%s.AssignContentValue: unknown type of source', [classname]); +end; + +function TBFSBoolean.IsEqualToValue(const Value: IBoldValue): Boolean; +var + aBooleanValue: IBoldBooleanContent; +begin + Result := inherited IsEqualToValue(Value) and + (Value.QueryInterface(IBoldBooleanContent, aBooleanValue) = S_OK) and + (AsBoolean = aBooleanValue.asBoolean); end; { TBFSDateTime } -procedure TBFSDateTime.AssignContentValue(Source: IBoldValue); +procedure TBFSDateTime.AssignContentValue(const Source: IBoldValue); var s: IBoldDateTimeContent; begin @@ -1193,7 +1463,17 @@ procedure TBFSDateTime.AssignContentValue(Source: IBoldValue); else SetContentAsDateTime(s.AsDateTime) else - raise EBold.CreateFmt(sUnknownTypeOfSource, [classname]); + raise EBold.CreateFmt('%s.AssignContentValue: unknown type of source', [classname]); +end; + +function TBFSDateTime.GetValueAsVariant: Variant; +begin + result := AsDateTime; +end; + +class function TBFSDateTime.ContentType: TBoldValueContentType; +begin + result := bctDateTime; end; function TBFSDateTime.GetStreamName: String; @@ -1201,9 +1481,18 @@ function TBFSDateTime.GetStreamName: String; result := BoldContentName_DateTime; end; +function TBFSDateTime.IsEqualToValue(const Value: IBoldValue): Boolean; +var + aDateTimeValue: IBoldDateTimeContent; +begin + Result := inherited IsEqualToValue(Value) and + (Value.QueryInterface(IBoldDateTimeContent, aDateTimeValue) = S_OK) and + (AsDateTime = aDateTimeValue.asDateTime); +end; + { TBFSDate } -procedure TBFSDate.AssignContentValue(Source: IBoldValue); +procedure TBFSDate.AssignContentValue(const Source: IBoldValue); var s: IBoldDateContent; begin @@ -1213,7 +1502,17 @@ procedure TBFSDate.AssignContentValue(Source: IBoldValue); else SetContentAsDate(s.AsDate) else - raise EBold.CreateFmt(sUnknownTypeOfSource, [classname]); + raise EBold.CreateFmt('%s.AssignContentValue: unknown type of source', [classname]); +end; + +function TBFSDate.GetValueAsVariant: Variant; +begin + result := AsDate; +end; + +class function TBFSDate.ContentType: TBoldValueContentType; +begin + result := bctDate; end; function TBFSDate.GetStreamName: String; @@ -1221,9 +1520,18 @@ function TBFSDate.GetStreamName: String; result := BoldContentName_Date; end; +function TBFSDate.IsEqualToValue(const Value: IBoldValue): Boolean; +var + aDateValue: IBoldDateContent; +begin + Result := inherited IsEqualToValue(Value) and + (Value.QueryInterface(IBoldDateContent, aDateValue) = S_OK) and + (AsDate = aDateValue.asDate); +end; + { TBFSTime } -procedure TBFSTime.AssignContentValue(Source: IBoldValue); +procedure TBFSTime.AssignContentValue(const Source: IBoldValue); var s: IBoldTimeContent; begin @@ -1233,7 +1541,17 @@ procedure TBFSTime.AssignContentValue(Source: IBoldValue); else SetContentAsTime(s.AsTime) else - raise EBold.CreateFmt(sUnknownTypeOfSource, [classname]); + raise EBold.CreateFmt('%s.AssignContentValue: unknown type of source', [classname]); +end; + +function TBFSTime.GetValueAsVariant: Variant; +begin + result := AsTime; +end; + +class function TBFSTime.ContentType: TBoldValueContentType; +begin + result := bctTime; end; function TBFSTime.GetStreamName: String; @@ -1241,9 +1559,18 @@ function TBFSTime.GetStreamName: String; result := BoldContentName_Time; end; +function TBFSTime.IsEqualToValue(const Value: IBoldValue): Boolean; +var + aTimeValue: IBoldTimeContent; +begin + Result := inherited IsEqualToValue(Value) and + (Value.QueryInterface(IBoldTimeContent, aTimeValue) = S_OK) and + (AsTime = aTimeValue.asTime); +end; + { TBFSBlob } -procedure TBFSBlob.AssignContentValue(Source: IBoldValue); +procedure TBFSBlob.AssignContentValue(const Source: IBoldValue); var s: IBoldBlobContent; begin @@ -1253,10 +1580,24 @@ procedure TBFSBlob.AssignContentValue(Source: IBoldValue); else SetContentAsBlob(s.AsBlob) else - raise EBold.CreateFmt(sUnknownTypeOfSource, [classname]); + raise EBold.CreateFmt('%s.AssignContentValue: unknown type of source', [classname]); +end; + +class function TBFSBlob.ContentType: TBoldValueContentType; +begin + result := bctBlob; +end; + +function TBFSBlob.IsEqualToValue(const Value: IBoldValue): Boolean; +var + aBlobValue: IBoldBlobContent; +begin + Result := inherited IsEqualToValue(Value) and + (Value.QueryInterface(IBoldBlobContent, aBlobValue) = S_OK) and + (AsBlob = aBlobValue.asBlob); end; -procedure TBFSTypedBlob.AssignContentValue(Source: IBoldValue); +procedure TBFSTypedBlob.AssignContentValue(const Source: IBoldValue); var s: IBoldBlobContent; t: IBoldTypedBlob; @@ -1271,23 +1612,44 @@ procedure TBFSTypedBlob.AssignContentValue(Source: IBoldValue); SetContentTypeContent(t.ContentTypeContent); end else - raise EBold.CreateFmt(sUnknownTypeOfSource, [classname]); + raise EBold.CreateFmt('%s.AssignContentValue: unknown type of source', [classname]); end; -procedure TBFSObjectIDRef.AssignContentValue(Source: IBoldValue); +function TBFSTypedBlob.IsEqualToValue(const Value: IBoldValue): Boolean; +var + aBlobValue: IBoldBlobContent; + aTypedBlob: IBoldTypedBlob; +begin + Result := inherited IsEqualToValue(Value) and + (Value.QueryInterface(IBoldBlobContent, aBlobValue) = S_OK) and + (Value.QueryInterface(IBoldTypedBlob, aTypedBlob) = S_OK) and + (AsBlob = aBlobValue.asBlob) and + (ContentTypeContent = aTypedBlob.ContentTypeContent); +end; + +procedure TBFSObjectIDRef.AssignContentValue(const Source: IBoldValue); var s: IBoldObjectIdRef; begin if source.QueryInterface(IBoldObjectIDRef, S) = S_OK then begin - SetFromId(s.Id); + SetFromId(s.Id, false); OrderNo := s.OrderNo; end else - raise EBold.CreateFmt(sUnknownTypeOfSource, [classname]); + raise EBold.CreateFmt('%s.AssignContentValue: unknown type of source', [classname]); end; -procedure TBFSObjectIDRefPair.AssignContentValue(Source: IBoldValue); +function TBFSObjectIDRef.IsEqualToValue(const Value: IBoldValue): Boolean; +var + aObjectIDRef: IBoldObjectIdRef; +begin + Result := Assigned(Value) and + (Value.QueryInterface(IBoldObjectIdRef, aObjectIDRef) = S_OK) and + ((Assigned(ID) and Assigned(aObjectIDRef.Id) and Id.IsEqual[aObjectIDRef.Id]) or + ((ID = nil) and (aObjectIDRef.Id = nil))); +end; +procedure TBFSObjectIDRefPair.AssignContentValue(const Source: IBoldValue); var s: IBoldObjectIdRefPair; begin @@ -1297,10 +1659,26 @@ procedure TBFSObjectIDRefPair.AssignContentValue(Source: IBoldValue); OrderNo := s.OrderNo; end else - raise EBold.CreateFmt(sUnknownTypeOfSource, [classname]); + raise EBold.CreateFmt('%s.AssignContentValue: unknown type of source', [classname]); end; -procedure TBFSObjectIdListref.AssignContentValue(Source: IBoldValue); +procedure TBFSObjectIdListref.EnsureList; +begin + if not assigned(fIdList) then + fIdList := TBoldObjectIdList.Create + else + Assert(fIdList is TBoldObjectIdList); +end; + +procedure TBFSObjectIdListrefPair.EnsureLists; +begin + if not assigned(fIdList1) then + fIdList1 := TBoldObjectIdList.Create; + if not assigned(fIdList2) then + fIdList2 := TBoldObjectIdList.Create; +end; + +procedure TBFSObjectIdListref.AssignContentValue(const Source: IBoldValue); var s: IBoldObjectIdListRef; i: Integer; @@ -1308,15 +1686,13 @@ procedure TBFSObjectIdListref.AssignContentValue(Source: IBoldValue); if source.QueryInterface(IBoldObjectIDListRef, S) = S_OK then begin EnsureList; - fIdList.Clear; - for i := 0 to s.Count - 1 do - fIdList.Add(s.IdList[i]); + s.SetList(fIdList); end else - raise EBold.CreateFmt(sUnknownTypeOfSource, [classname]); + raise EBold.CreateFmt('%s.AssignContentValue: unknown type of source', [classname]); end; -procedure TBFSObjectIdListrefPair.AssignContentValue(Source: IBoldValue); +procedure TBFSObjectIdListrefPair.AssignContentValue(const Source: IBoldValue); var s: IBoldObjectIdListRefPair; i: Integer; @@ -1326,6 +1702,8 @@ procedure TBFSObjectIdListrefPair.AssignContentValue(Source: IBoldValue); EnsureLists; fIdList1.Clear; fIdList2.Clear; + fIdList1.Capacity := s.Count; + fIdList2.Capacity := s.Count; for i := 0 to s.Count - 1 do begin fIdList1.Add(s.IdList1[i]); @@ -1333,7 +1711,7 @@ procedure TBFSObjectIdListrefPair.AssignContentValue(Source: IBoldValue); end; end else - raise EBold.CreateFmt(sUnknownTypeOfSource, [classname]); + raise EBold.CreateFmt('%s.AssignContentValue: unknown type of source', [classname]); end; destructor TBFSObjectIdListrefPair.Destroy; @@ -1353,37 +1731,11 @@ procedure TBoldFreeStandingObjectContents.RemoveMemberByIndex(Index: integer); begin if MemberCount > Index then begin - fMemberList^[Index].Free; - fMemberList^[Index] := nil; + fMemberList[Index].Free; + fMemberList[Index] := nil; end; end; -{ TBoldFSObjectContentList } - -constructor TBoldFSObjectContentList.Create; -begin - inherited Create; - SetIndexCapacity(1); - OwnsEntries := true; - SetIndexVariable(IX_FSObjectContent, AddIndex(TBoldFSObjectContentHashIndex.Create)); -end; - -function TBoldFSObjectContentList.FindObjectContentById(Id: TBoldObjectId): TBoldFreeStandingObjectContents; -begin - Result := TBoldFreeStandingObjectContents(TBoldFSObjectContentHashIndex(indexes[IX_FSObjectContent]).FindByID(ID)); -end; - -function TBoldFSObjectContentList.GetItems(index: integer): TBoldFreeStandingObjectContents; -begin - result := TBoldFreeStandingObjectContents(inherited items[index]); -end; - -procedure TBoldFSObjectContentList.SetItems(index: integer; - const Value: TBoldFreeStandingObjectContents); -begin - inherited items[index] := Value; -end; - { TBoldFSObjectContentHashIndex } function TBoldFSObjectContentHashIndex.FindById(BoldObjectId: TBoldObjectId): TObject; @@ -1412,6 +1764,28 @@ function TBoldFSObjectContentHashIndex.Match(const Key; Item: TObject): Boolean; Result := TBoldObjectId(Key).IsEqual[ItemAsBoldObjectId(Item)]; end; +{ TBoldFSObjectContentList } + +constructor TBoldFSObjectContentList.Create; +begin + inherited Create; + SetIndexCapacity(1); + OwnsEntries := true; + IX_FSObjectContent := -1; + SetIndexVariable(IX_FSObjectContent, AddIndex(TBoldFSObjectContentHashIndex.Create)); +end; + +function TBoldFSObjectContentList.GetItems(index: integer): TBoldFreeStandingObjectContents; +begin + result := TBoldFreeStandingObjectContents(inherited items[index]); +end; + +procedure TBoldFSObjectContentList.SetItems(index: integer; + const Value: TBoldFreeStandingObjectContents); +begin + inherited items[index] := Value; +end; + function TBoldFreeStandingValue.GetContentName: String; begin result := GetStreamName; @@ -1423,9 +1797,14 @@ constructor TBoldFreeStandingValue.create; BoldPersistenceState := bvpsInvalid; end; -procedure TBoldFreeStandingValue.AssignContentValue(Source: IBoldValue); +procedure TBoldFreeStandingValue.AssignContentValue(const Source: IBoldValue); begin - raise EBold.CreateFmt(sAbstractError, [classname]); + raise EBold.CreateFmt('%s.AssignContentValue: Abstract error', [classname]); +end; + +function TBoldFreeStandingValue.IsEqualToValue(const Value: IBoldValue): Boolean; +begin + raise EBold.CreateFmt('%s.IsEqualToValue: Abstract error', [classname]); end; function TBoldFreeStandingObjectContents.GetObjectId: TBoldObjectId; @@ -1434,36 +1813,30 @@ function TBoldFreeStandingObjectContents.GetObjectId: TBoldObjectId; end; procedure TBoldFreeStandingObjectContents.ApplyObjectContents( - ObjectContents: IBoldObjectContents; const ApplyValues: Boolean; const IgnorePersistenceState: Boolean); + const ObjectContents: IBoldObjectContents; ApplyValues: Boolean; IgnorePersistenceState: Boolean); var i: Integer; aValue: IBoldValue; - MemberId: TBoldMemberId; begin SetBoldExistenceState(ObjectContents.BoldExistenceState); SetBoldPersistenceState(ObjectContents.BoldPersistenceState); if ApplyValues then - for i := 0 to ObjectContents.MemberCount - 1 do + for i := ObjectContents.MemberCount - 1 downto 0 do begin aValue := ObjectContents.valueByIndex[i]; if assigned(aValue) then begin - MemberId := TBoldMemberId.Create(i); - try - EnsureMember(MemberId, aValue.ContentName); - if IgnorePersistenceState then - fMemberList^[i].AssignContentValue(aValue) - else - fMemberList^[i].AssignContent(aValue); - finally - FreeAndNil(MemberId); - end; + EnsureMemberAndGetValueByIndex(i, aValue.ContentName); + if IgnorePersistenceState then + fMemberList[i].AssignContentValue(aValue) + else + fMemberList[i].AssignContent(aValue); end; end; end; procedure TBoldFreeStandingValueSpace.UpdateOwnValuesFrom( - ValueSpace: IBoldValueSpace); + const ValueSpace: IBoldValueSpace); var i: Integer; anIdList: TBoldObjectIdList; @@ -1488,27 +1861,32 @@ procedure TBoldFreeStandingValueSpace.UpdateOwnValuesFrom( end; procedure TBoldFreeStandingObjectContents.UpdateObjectContentsFrom( - ObjectContents: IBoldObjectContents); + const ObjectContents: IBoldObjectContents); var i: Integer; OwnValue, aValue: IBoldValue; begin SetBoldExistenceState(ObjectContents.BoldExistenceState); SetBoldPersistenceState(ObjectContents.BoldPersistenceState); - for i := 0 to MemberCount - 1 do + for i := MemberCount - 1 downto 0 do begin OwnValue := GetValueByIndex(i); - aValue := ObjectContents.ValueByIndex[i]; - if assigned(OwnValue) and assigned(aValue) then - OwnValue.AssignContent(aValue); + if Assigned(OwnValue) then begin + aValue := ObjectContents.ValueByIndex[i]; + if Assigned(aValue) then begin + OwnValue.AssignContent(aValue); + end; + end; end; end; procedure TBoldFreeStandingValueSpace.RemoveAllObjectContents; -var +{var i: integer; - ObjectIds: TBoldObjectIdlist; + ObjectIds: TBoldObjectIdlist;} begin + fObjectContentsList.Clear; +{ ObjectIds := TBoldObjectIdList.Create; try AllObjectIds(ObjectIds, True); @@ -1517,6 +1895,7 @@ procedure TBoldFreeStandingValueSpace.RemoveAllObjectContents; finally FreeAndNil(Objectids); end; +} end; procedure TBoldFreeStandingValueSpace.MarkAllObjectsAndMembersCurrent; @@ -1537,31 +1916,44 @@ procedure TBoldFreeStandingObjectContents.MarkAllMembersCurrent; M: integer; begin for M := 0 to MemberCount - 1 do - if Assigned(fMemberList^[M]) then - GetValueByIndex(M).BoldPersistenceState := bvpsCurrent; + if Assigned(fMemberList[M]) then + fMemberList[M].BoldPersistenceState := bvpsCurrent; end; +procedure TBoldFreeStandingObjectContents.EnsureMemberListLength( + index: integer); +begin + if (Index >= Length(fMemberList)) then + SetLength(fMemberList, Index+1); +end; +procedure TBoldFreeStandingValueSpace.Clear; +begin + fIdLIst.Clear; + fObjectContentsList.Clear; + FreeAndNil(fTranslationList); +end; -procedure TBoldFreeStandingObjectContents.EnsureMemberByIndex( - Index: integer; const StreamName: string); +procedure TBoldFreeStandingValueSpace.ClearWhenObjectContentsEmpty; begin - if not Assigned(fMemberlist) then - begin - fMemberlist := BoldMemoryManager_.AllocateMemoryZeroFill((Index+1)*sizeof(Pointer)); - fMemberCount := Index+1; - end; - if (Index >= MemberCount) then - begin - fMemberlist := BoldMemoryManager_.ReallocateMemoryZeroFill(fMemberlist, MemberCount*sizeof(Pointer), - (Index+1)*sizeof(Pointer)); - fMemberCount := Index+1; + if fObjectContentsList.Count = 0 then begin + if Assigned(fIdLIst) then begin + fIdLIst.Clear; + end; + if Assigned(fTranslationList) then begin + FreeAndNil(fTranslationList); + end; end; - - if not assigned(fMemberlist^[Index]) then - fMemberlist^[Index] := TBoldFreeStandingValue(FreeStandingValueFactory.CreateInstance(StreamName)); end; +function TBoldFreeStandingObjectContents.EnsureMemberAndGetValueByIndex( + Index: integer; const StreamName: string): IBoldValue; +begin + EnsureMemberListLength(Index); + if not assigned(fMemberlist[Index]) then + fMemberlist[Index] := TBoldFreeStandingValue(FreeStandingValueFactory.CreateInstance(StreamName)); + Result := fMemberlist[Index]; +end; function TBoldFreeStandingValueSpace.GetValueForIdAndMemberIndex( Id: TBoldObjectId; MemberIndex: integer): IBoldValue; @@ -1571,33 +1963,66 @@ function TBoldFreeStandingValueSpace.GetValueForIdAndMemberIndex( ObjectContents := GetFSObjectContentsByObjectId(Id); if Assigned(ObjectContents) then Result := ObjectContents.ValueByIndex[MemberIndex] + else + result := nil; +end; + +class function TBoldFreeStandingValueSpace.ContentType: TBoldValueContentType; +begin + result := bctValueSpace; end; function TBoldFreeStandingValueSpace.GetEnsuredFSObjectContentsByObjectId( - ObjectId: TBoldObjectId): TBoldFreeStandingObjectContents; + ObjectId: TBoldObjectId; + out aCreated: boolean): TBoldFreeStandingObjectContents; var LocalId: TBoldObjectId; begin Result := GetFSObjectContentsByObjectId(ObjectId); - if not Assigned(Result) then + aCreated := not Assigned(Result); + if aCreated then begin LocalId := IdLIst.IdById[ObjectId]; if not assigned(LocalId) then begin - IdList.Add(ObjectId); - LocalId :=IdLIst.IdById[ObjectId]; + LocalId := IdList.AddAndGetID(ObjectId); end; - Result := TBoldFreeStandingObjectContents.Create; + Result := BoldFreeStandingObjectContentsClass.Create; Result.fObjectId := LocalId; fObjectContentsList.Add(Result); end; end; -function TBoldFreeStandingObjectContents.GetBoldMemberCount: Integer; +function TBoldFreeStandingValueSpace.GetEnsuredFSObjectContentsByObjectId( + ObjectId: TBoldObjectId): TBoldFreeStandingObjectContents; +var + lCreated: boolean; begin - Result := fMemberCount; + result := GetEnsuredFSObjectContentsByObjectId(ObjectId, lCreated); end; +function TBoldFreeStandingValueSpace.IdCount: integer; +begin + result := fIdLIst.Count; +end; + +function TBoldFreeStandingValueSpace.IsEmpty: boolean; +var + i: integer; +begin + for i := 0 to fIdList.Count - 1 do + if Assigned(GetObjectContentsByObjectId(fIdList[i])) then + begin + result := false; + exit; + end; + result := true; +end; + +function TBoldFreeStandingObjectContents.GetBoldMemberCount: Integer; +begin + Result := Length(fMemberList); +end; procedure TBFSObjectIdListrefPair.RemoveId(Id: TBoldObjectId); var @@ -1615,13 +2040,14 @@ procedure TBFSObjectIdListref.RemoveId(Id: TBoldObjectId); var p: integer; begin - p := fIdList.IndexByID[id]; + p := fIdList.IndexByID[Id]; if p <> -1 then fIdLIst.RemoveByIndex(p); end; procedure TBFSObjectIdListrefPair.AddIds(Id1, Id2: TBoldObjectId); begin + EnsureLists; fIdList1.Add(Id1); fIdLIst2.Add(Id2); end; @@ -1632,18 +2058,6 @@ procedure TBFSObjectIdListref.AddId(Id: TBoldObjectId); fIdList.Add(Id); end; -procedure TBFSObjectIdListref.EnsureList; -begin - if not assigned(fIdList) then - fIdList := TBoldObjectIdList.Create; -end; - -procedure TBFSObjectIdListrefPair.EnsureLists; -begin - if not assigned(fIdList1) then - fIdList1 := TBoldObjectIdList.Create; - if not assigned(fIdList2) then - fIdList2 := TBoldObjectIdList.Create; -end; - +initialization end. + diff --git a/Source/FreestandingValueSpace/Core/FreeStandingValuesConst.pas b/Source/FreestandingValueSpace/Core/FreeStandingValuesConst.pas index 92e3e1b..5dc0937 100644 --- a/Source/FreestandingValueSpace/Core/FreeStandingValuesConst.pas +++ b/Source/FreestandingValueSpace/Core/FreeStandingValuesConst.pas @@ -10,4 +10,4 @@ interface implementation -end. \ No newline at end of file +end. diff --git a/Source/Handles/Actions/BoldActionDefs.pas b/Source/Handles/Actions/BoldActionDefs.pas index 2f4dc7d..8de10fc 100644 --- a/Source/Handles/Actions/BoldActionDefs.pas +++ b/Source/Handles/Actions/BoldActionDefs.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldActionDefs; interface @@ -12,4 +15,3 @@ interface implementation end. - diff --git a/Source/Handles/Actions/BoldActions.pas b/Source/Handles/Actions/BoldActions.pas index dcfbb67..70dbd1e 100644 --- a/Source/Handles/Actions/BoldActions.pas +++ b/Source/Handles/Actions/BoldActions.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldActions; interface @@ -81,7 +84,6 @@ implementation uses SysUtils, - HandlesConst, BoldDefs, Controls, Dialogs, @@ -104,7 +106,7 @@ procedure TBoldUpdateDBAction.CheckAllowEnable(var EnableAction: boolean); constructor TBoldUpdateDBAction.Create(AOwner: TComponent); begin inherited; - Caption := sUpdateDB; + Caption := 'Update DB'; end; procedure TBoldUpdateDBAction.ExecuteTarget(Target: TObject); @@ -120,9 +122,9 @@ constructor TBoldActivateSystemAction.Create(AOwner: TComponent); begin inherited; fHandleIdentitySubscriber := TBoldPassthroughSubscriber.Create(_Receive); - fOpenCaption := sOpenSystem; - fCloseCaption := sCloseSystem; - fSaveQuestion := sThereAreDirtyObjects; + fOpenCaption := 'Open system'; + fCloseCaption := 'Close system'; + fSaveQuestion := 'There are dirty objects. Save them before closing system?'; UpdateCaption; end; @@ -151,7 +153,7 @@ procedure TBoldActivateSystemAction.ExecuteTarget(Target: TObject); saYes: BoldSystemHandle.UpdateDatabase; saNo: BoldSystemHandle.System.Discard; saFail: if BoldSystemHandle.System.DirtyObjects.Count > 0 then - raise EBold.Create(sClosingWithDirtyObjects); + raise EBold.Create('Closing system with dirty objects!!'); end; if Update then BoldSystemHandle.Active := not BoldSystemHandle.Active; @@ -256,8 +258,6 @@ procedure TBoldFailureDetectionAction.UpdateTarget(Target: TObject); else Caption := ''; - // The statusbar seems to have a bug, it does not correctly update its caption... - // even this does not make it work fully... Bug in VCL if Target is TStatusBar then (Target as TStatusBar).SimpleText := Caption; @@ -276,4 +276,6 @@ procedure TBoldSystemHandleAction.SetBoldSystemHandle( BoldElementHandle := Value; end; +initialization + end. diff --git a/Source/Handles/Actions/BoldHandleAction.pas b/Source/Handles/Actions/BoldHandleAction.pas index 9a74586..40bd5ed 100644 --- a/Source/Handles/Actions/BoldHandleAction.pas +++ b/Source/Handles/Actions/BoldHandleAction.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldHandleAction; interface @@ -35,7 +38,8 @@ implementation uses SysUtils, - BoldUtils; + BoldUtils, + BoldRev; const breFreeHandle = 44; @@ -98,5 +102,6 @@ procedure TBoldHandleAction.CheckAllowEnable(var EnableAction: boolean); EnableAction := Assigned(BoldElementHandle); end; -end. +initialization +end. diff --git a/Source/Handles/Actions/BoldListActions.pas b/Source/Handles/Actions/BoldListActions.pas index 9715b55..3322a7a 100644 --- a/Source/Handles/Actions/BoldListActions.pas +++ b/Source/Handles/Actions/BoldListActions.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldListActions; interface @@ -5,12 +8,12 @@ interface uses Classes, Controls, - BoldDefs, // Defines EBold (Move it to BoldExceptions?) + BoldDefs, BoldSubscription, BoldSystem, BoldAbstractListHandle, BoldHandleAction, - BoldNavigatorDefs; // Defines TBoldDeleteMode (should move to BoldDefs) + BoldNavigatorDefs; type TBoldListHandleAction = class; @@ -23,7 +26,6 @@ TBoldListHandleAddNewAction = class; TBoldListHandleMoveUpAction = class; TBoldListHandleMoveDownAction = class; - { TBoldListHandleAction } TBoldListHandleAction = class(TBoldHandleAction) private function GetBoldHandle: TBoldAbstractListHandle; @@ -34,7 +36,6 @@ TBoldListHandleAction = class(TBoldHandleAction) property BoldHandle: TBoldAbstractListHandle read GetBoldHandle write SetBoldHandle; end; - { TBoldListHandleNextAction } TBoldListHandleNextAction = class(TBoldListHandleAction) protected procedure CheckAllowEnable(var EnableAction: boolean); override; @@ -43,7 +44,6 @@ TBoldListHandleNextAction = class(TBoldListHandleAction) procedure ExecuteTarget(Target: TObject); override; end; - { TBoldListHandlePrevAction } TBoldListHandlePrevAction = class(TBoldListHandleAction) protected procedure CheckAllowEnable(var EnableAction: boolean); override; @@ -52,7 +52,6 @@ TBoldListHandlePrevAction = class(TBoldListHandleAction) procedure ExecuteTarget(Target: TObject); override; end; - { TBoldListHandleFirstAction } TBoldListHandleFirstAction = class(TBoldListHandleAction) protected procedure CheckAllowEnable(var EnableAction: boolean); override; @@ -111,7 +110,7 @@ implementation uses SysUtils, BoldUtils, - HandlesConst; + BoldRev; { TBoldListHandleAction } @@ -148,7 +147,7 @@ procedure TBoldListHandleNextAction.CheckAllowEnable( constructor TBoldListHandleNextAction.Create(AOwner: TComponent); begin inherited; - Caption := sNext; + Caption := 'Next'; end; procedure TBoldListHandleNextAction.ExecuteTarget(Target: TObject); @@ -170,7 +169,7 @@ procedure TBoldListHandlePrevAction.CheckAllowEnable( constructor TBoldListHandlePrevAction.Create(AOwner: TComponent); begin inherited; - Caption := sPrev; + Caption := 'Prev'; end; procedure TBoldListHandlePrevAction.ExecuteTarget(Target: TObject); @@ -192,7 +191,7 @@ procedure TBoldListHandleFirstAction.CheckAllowEnable( constructor TBoldListHandleFirstAction.Create(AOwner: TComponent); begin inherited; - Caption := sFirst; + Caption := 'First'; end; procedure TBoldListHandleFirstAction.ExecuteTarget(Target: TObject); @@ -214,7 +213,7 @@ procedure TBoldListHandleLastAction.CheckAllowEnable( constructor TBoldListHandleLastAction.Create(AOwner: TComponent); begin inherited; - Caption := sLast; + Caption := 'Last'; end; procedure TBoldListHandleLastAction.ExecuteTarget(Target: TObject); @@ -236,7 +235,7 @@ function TBoldListHandleDeleteAction.AllowDelete( dmUnlinkAllAndDelete: Result := True; else - raise EBold.CreateFmt(sUnknownDeleteMode, [ClassName]); + raise EBold.CreateFmt('%s.AllowDelete: Unknown deletemode', [ClassName]); end; end; @@ -257,7 +256,7 @@ procedure TBoldListHandleDeleteAction.CheckAllowEnable( constructor TBoldListHandleDeleteAction.Create(AOwner: TComponent); begin inherited; - Caption := sDelete; + Caption := 'Delete'; end; procedure TBoldListHandleDeleteAction.ExecuteTarget(Target: TObject); @@ -290,7 +289,7 @@ procedure TBoldListHandleAddNewAction.CheckAllowEnable( constructor TBoldListHandleAddNewAction.Create(AOwner: TComponent); begin inherited; - Caption := sAddNew; + Caption := 'Add New'; end; procedure TBoldListHandleAddNewAction.ExecuteTarget(Target: TObject); @@ -315,7 +314,7 @@ procedure TBoldListHandleMoveUpAction.CheckAllowEnable( constructor TBoldListHandleMoveUpAction.Create(AOwner: TComponent); begin inherited; - Caption := sMoveUp; + Caption := 'Move up'; end; procedure TBoldListHandleMoveUpAction.ExecuteTarget(Target: TObject); @@ -337,7 +336,7 @@ procedure TBoldListHandleMoveDownAction.CheckAllowEnable( constructor TBoldListHandleMoveDownAction.Create(AOwner: TComponent); begin inherited; - Caption := sMoveDown; + Caption := 'Move down'; end; procedure TBoldListHandleMoveDownAction.ExecuteTarget(Target: TObject); @@ -346,4 +345,6 @@ procedure TBoldListHandleMoveDownAction.ExecuteTarget(Target: TObject); BoldHandle.List.Move(BoldHandle.CurrentIndex, BoldHandle.CurrentIndex+1); end; +initialization + end. diff --git a/Source/Handles/Actions/BoldUndoActions.pas b/Source/Handles/Actions/BoldUndoActions.pas index 6acd626..78a1edb 100644 --- a/Source/Handles/Actions/BoldUndoActions.pas +++ b/Source/Handles/Actions/BoldUndoActions.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldUndoActions; interface @@ -35,14 +38,15 @@ TBoldRedoAction = class(TBoldSystemHandleAction) procedure ExecuteTarget(Target: TObject); override; end; + implementation uses - HandlesConst, BoldSystem, ActnList, BoldUndoInterfaces; + { TBoldSetCheckPointAction } procedure TBoldSetCheckPointAction.CheckAllowEnable( @@ -56,7 +60,7 @@ procedure TBoldSetCheckPointAction.CheckAllowEnable( constructor TBoldSetCheckPointAction.Create(AOwner: TComponent); begin inherited; - Caption := sSetCheckPoint; + Caption := 'Set check point'; end; procedure TBoldSetCheckPointAction.ExecuteTarget(Target: TObject); @@ -80,7 +84,7 @@ procedure TBoldUndoAction.CheckAllowEnable(var EnableAction: boolean); constructor TBoldUndoAction.Create(AOwner: TComponent); begin inherited; - Caption := sUndo; + Caption := 'Undo'; end; procedure TBoldUndoAction.ExecuteTarget(Target: TObject); @@ -102,7 +106,7 @@ procedure TBoldRedoAction.CheckAllowEnable(var EnableAction: boolean); constructor TBoldRedoAction.Create(AOwner: TComponent); begin inherited; - Caption := sRedo; + Caption := 'Redo'; end; procedure TBoldRedoAction.ExecuteTarget(Target: TObject); @@ -111,4 +115,6 @@ procedure TBoldRedoAction.ExecuteTarget(Target: TObject); BoldSystemHandle.System.UndoHandlerInterface.RedoLatest; end; +initialization + end. diff --git a/Source/Handles/COM/BoldComClientElementHandles.pas b/Source/Handles/COM/BoldComClientElementHandles.pas index 484d840..9e3949c 100644 --- a/Source/Handles/COM/BoldComClientElementHandles.pas +++ b/Source/Handles/COM/BoldComClientElementHandles.pas @@ -1,7 +1,15 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldComClientElementHandles; interface implementation +uses + BoldRev; + +initialization + end. diff --git a/Source/Handles/COM/BoldComServerElementHandleFactory.pas b/Source/Handles/COM/BoldComServerElementHandleFactory.pas index d445d75..284920d 100644 --- a/Source/Handles/COM/BoldComServerElementHandleFactory.pas +++ b/Source/Handles/COM/BoldComServerElementHandleFactory.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldComServerElementHandleFactory; interface @@ -30,7 +33,6 @@ implementation uses SysUtils, BoldComAdapter, - // Handles BoldCursorHandle, BoldDerivedHandle, BoldExpressionHandle, @@ -99,7 +101,6 @@ function TBoldComServerElementHandleFactory.GetObject(const ClassId: TGUID; procedure TBoldComServerElementHandleFactory.GetObjectInfo( const ClassId: TGUID; ObjectNames, ClassNames: TStrings); begin - // Using Class.ClassName to get compiler errors if classes change names ClassNames.Add(TBoldCursorHandle.ClassName); ClassNames.Add(TBoldDerivedHandle.ClassName); ClassNames.Add(TBoldExpressionHandle.ClassName); @@ -113,6 +114,6 @@ initialization G_ServerElementHandleFactory := TBoldComServerElementHandleFactory.Create; finalization - FreeAndNil(G_ServerElementHandleFactory); + FreeAndNil(G_ServerElementHandleFactory); end. diff --git a/Source/Handles/COM/BoldComServerElementHandles.pas b/Source/Handles/COM/BoldComServerElementHandles.pas index eebe6a3..f822e1d 100644 --- a/Source/Handles/COM/BoldComServerElementHandles.pas +++ b/Source/Handles/COM/BoldComServerElementHandles.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldComServerElementHandles; interface @@ -33,8 +36,7 @@ implementation uses BoldComAdapter, - // These two are not used here, this is just to make - // sure they get linked into the executable + BoldComObjectSpaceAdapters, BoldComServerElementHandleFactory; @@ -88,4 +90,6 @@ procedure TBoldComServerElementHandle.SetExportMode(Value: TBoldComServerElement end; end; +initialization + end. diff --git a/Source/Handles/Core/BoldAbstractListHandle.pas b/Source/Handles/Core/BoldAbstractListHandle.pas index 47f2c9b..97b535c 100644 --- a/Source/Handles/Core/BoldAbstractListHandle.pas +++ b/Source/Handles/Core/BoldAbstractListHandle.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldAbstractListHandle; interface @@ -24,6 +27,8 @@ TBoldAbstractListHandle = class(TBoldRootedHandle) function GetStaticListType: TBoldListTypeInfo; function GetObjectList: TBoldObjectList; function GetMutableObjectList: TBoldObjectList; + procedure SetCurrentBoldObject(const Value: TBoldObject); + procedure SetCurrentElement(const Value: TBoldElement); protected function GetCurrentElement: TBoldElement; virtual; abstract; function GetCurrentIndex: Integer; virtual; abstract; @@ -37,8 +42,8 @@ TBoldAbstractListHandle = class(TBoldRootedHandle) procedure Prior; procedure RemoveCurrentElement; property Count: Integer read GetCount; - property CurrentBoldObject: TBoldObject read GetCurrentBoldObject; - property CurrentElement: TBoldElement read GetCurrentElement; + property CurrentBoldObject: TBoldObject read GetCurrentBoldObject write SetCurrentBoldObject; + property CurrentElement: TBoldElement read GetCurrentElement write SetCurrentElement; property CurrentIndex: Integer read GetCurrentIndex write SetCurrentIndex; property List: TBoldList read GetList; property ObjectList: TBoldObjectList read GetObjectList; @@ -55,15 +60,17 @@ implementation uses SysUtils, - HandlesConst, BoldDefs; { TBoldAbstractListHandle } function TBoldAbstractListHandle.GetCount: Integer; +var + BoldList: TBoldList; begin - if Assigned(List) then - Result := List.Count + BoldList := List; + if Assigned(BoldList) then + Result := BoldList.Count else Result := 0; end; @@ -73,7 +80,7 @@ procedure TBoldAbstractListHandle.Prior; if GetHasPrior then CurrentIndex := CurrentIndex - 1 else - raise EBold.CreateFmt(sNoPreviousElement, [ClassName]); + raise EBold.CreateFmt('%s: No previous element', [ClassName]); end; procedure TBoldAbstractListHandle.Next; @@ -81,7 +88,7 @@ procedure TBoldAbstractListHandle.Next; if GetHasNext then CurrentIndex := CurrentIndex + 1 else - raise EBold.CreateFmt(sNoNextElement, [ClassName]); + raise EBold.CreateFmt('%s: No next element', [ClassName]); end; procedure TBoldAbstractListHandle.First; @@ -96,34 +103,57 @@ procedure TBoldAbstractListHandle.Last; end; procedure TBoldAbstractListHandle.RemoveCurrentElement; +var + BoldList: TBoldList; begin - if CurrentIndex = -1 then - raise EBold.CreateFmt(sNoCurrentElement, [ClassName]) - else - begin - if list.mutable then - List.RemoveByIndex(CurrentIndex) - else if assigned(MutableLIst) then - mutableList.remove(CurrentElement) - else - raise EBold.CreateFmt(sCannotRemoveCurrentFromImmutable, [classname, name]); - end; + if CurrentIndex = -1 then begin + raise EBold.CreateFmt('%s.RemoveCurrentElement: No current element', [ClassName]) + end else begin + BoldList := List; + if Assigned(BoldList) and BoldList.Mutable then begin + BoldList.RemoveByIndex(CurrentIndex); + end else begin + BoldList := MutableList; + if Assigned(BoldList) then begin + BoldList.Remove(CurrentElement); + end else begin + raise EBold.CreateFmt('%s: Can not remove current Element from an immutable list (in %s)', [classname, name]); + end; + end;; + end; +end; + +procedure TBoldAbstractListHandle.SetCurrentBoldObject( + const Value: TBoldObject); +begin + SetCurrentElement(Value); +end; + +procedure TBoldAbstractListHandle.SetCurrentElement(const Value: TBoldElement); +begin + CurrentIndex := List.IndexOf(Value); end; function TBoldAbstractListHandle.GetCurrentBoldObject: TBoldObject; +var + aCurrentElement: TBoldElement; begin - if CurrentElement is TBoldObject then - Result := TBoldObject(CurrentElement) - else if not Assigned(CurrentElement) then + aCurrentElement := CurrentElement; + if aCurrentElement is TBoldObject then + Result := TBoldObject(aCurrentElement) + else if aCurrentElement = nil then Result := nil else - raise EBold.CreateFmt(sCurrentElementNotBoldObject, [ClassName]); + raise EBold.CreateFmt('%s.CurrentBoldObject: Current element is not a TBoldObject', [ClassName]); end; function TBoldAbstractListHandle.GetListElementType: TBoldElementTypeInfo; +var + BoldList: TBoldList; begin - if Assigned(List) then - Result := TBoldListTypeInfo(List.BoldType).ListElementTypeInfo + BoldList := List; + if Assigned(BoldList) then + Result := TBoldListTypeInfo(BoldList.BoldType).ListElementTypeInfo else Result := StaticBoldType; end; @@ -139,9 +169,12 @@ function TBoldAbstractListHandle.GetHasPrior: Boolean; end; function TBoldAbstractListHandle.GetListType: TBoldListTypeInfo; +var + BoldList: TBoldList; begin - if Assigned(List) then - Result := TBoldListTypeInfo(List.BoldType) + BoldList := List; + if Assigned(BoldList) then + Result := TBoldListTypeInfo(BoldList.BoldType) else result := StaticListType; end; @@ -166,19 +199,27 @@ function TBoldAbstractListHandle.GetMutableList: TBoldList; end; function TBoldAbstractListHandle.GetObjectList: TBoldObjectList; +var + BoldList: TBoldList; begin - if list is TBoldObjectList then - result := list as TBoldObjectList + BoldList := List; + if BoldList is TBoldObjectList then + result := TBoldObjectList(BoldList) else result := nil; end; function TBoldAbstractListHandle.GetMutableObjectList: TBoldObjectList; +var + BoldList: TBoldList; begin - if MutableList is TBoldObjectList then - result := MutableList as TBoldObjectList + BoldList := MutableList; + if BoldList is TBoldObjectList then + result := TBoldObjectList(BoldList) else result := nil; end; +initialization + end. diff --git a/Source/Handles/Core/BoldCursorHandle.pas b/Source/Handles/Core/BoldCursorHandle.pas index 7408197..4c3754b 100644 --- a/Source/Handles/Core/BoldCursorHandle.pas +++ b/Source/Handles/Core/BoldCursorHandle.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldCursorHandle; interface @@ -17,11 +20,10 @@ TBoldCursorHandle = class; TBoldCursorHandle = class(TBoldAbstractListHandle) private fAutoFirst: Boolean; - fListElement: TBoldIndirectElement; + fListElement: TBoldIndirectElement; fCurrentIndex: Integer; fListSubscriber: TBoldPassThroughSubscriber; procedure SetAutoFirst(Value: Boolean); -// function GetListSubscriber: TBoldPassThroughSubscriber; procedure _ReceiveFromList(Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent); protected procedure DeriveAndSubscribe(DerivedObject: TObject; Subscriber: TBoldSubscriber); override; @@ -30,7 +32,7 @@ TBoldCursorHandle = class(TBoldAbstractListHandle) function GetList: TBoldList; override; procedure SetCurrentIndex(NewIndex: Integer); override; function GetStaticBoldType: TBoldElementTypeInfo; override; -// property ListSubscriber: TBoldPassThroughSubscriber read GetListSubscriber; + property ListElement: TBoldIndirectElement read fListElement; public constructor Create(Owner: TComponent); override; destructor Destroy; override; @@ -42,7 +44,6 @@ implementation uses SysUtils, - HandlesConst, BoldDefs, BoldSystemRT; @@ -51,7 +52,7 @@ implementation constructor TBoldCursorhandle.Create(Owner: TComponent); begin inherited; - fListElement := TBOldIndirectElement.Create; + fListElement := TBoldIndirectElement.Create; fListSubscriber := TBoldPassThroughSubscriber.Create(_ReceiveFromList); fCurrentIndex := -1; AutoFirst := True; @@ -66,6 +67,8 @@ procedure TBoldCursorhandle.DeriveAndSubscribe(DerivedObject: TObject; TheList: TBoldList; NewValue: TBoldElement; begin + if csDestroying in ComponentState then + raise EBold.CreateFmt('%s.DeriveAndSubscribe: %s Handle is in csDestroying state, can not DeriveAndSubscribe.', [classname, name]); fListSubscriber.CancelAllSubscriptions; if EffectiveRootValue = nil then @@ -80,7 +83,7 @@ procedure TBoldCursorhandle.DeriveAndSubscribe(DerivedObject: TObject; if Assigned(TheList) then begin ListCount := TheList.Count; - IndexOfOldCurrent := TheList.IndexOf(ResultElement.Value) // Don't ensure current! + IndexOfOldCurrent := TheList.IndexOf(ResultElement.Value) end else begin @@ -190,8 +193,8 @@ procedure TBoldCursorhandle.SetCurrentIndex(NewIndex: Integer); var NewValue: TBoldElement; begin - if (NewIndex < -1) or (NewIndex >= Count) then // -1 accepted as "no current element" - raise EBold.CreateFmt(sIndexOutOfBounds, [ClassName, Count-1, NewIndex]); + if (NewIndex < -1) or (NewIndex >= Count) then + raise EBold.CreateFmt('%s.SetCurrentIndex: Index out of bounds. Valid range from -1 to %d. Attempted to set %d', [ClassName, Count-1, NewIndex]); if (NewIndex = -1) then NewValue := nil else @@ -202,8 +205,10 @@ procedure TBoldCursorhandle.SetCurrentIndex(NewIndex: Integer); fCurrentIndex := NewIndex; ResultElement.SetReferenceValue(NewValue); SubscribeToValue; - ValueIdentityChanged; // changing index is an identitychange + ValueIdentityChanged; end; end; +initialization + end. diff --git a/Source/Handles/Core/BoldDerivedHandle.pas b/Source/Handles/Core/BoldDerivedHandle.pas index d151425..3ce3bae 100644 --- a/Source/Handles/Core/BoldDerivedHandle.pas +++ b/Source/Handles/Core/BoldDerivedHandle.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldDerivedHandle; interface @@ -23,6 +26,7 @@ TBoldDerivedHandle = class(TBoldRootedHandle) procedure SetOnDeriveAndSubscribe(Value: TBoldHandleDeriveAndSubscribe); procedure SetValueTypeName(Value: string); protected + procedure DoAssign(Source: TPersistent); override; procedure DeriveAndSubscribe(DerivedObject: TObject; Subscriber: TBoldSubscriber); override; function GetStaticBoldType: TBoldElementTypeInfo; override; published @@ -34,16 +38,27 @@ implementation uses SysUtils, - HandlesConst, BoldSystemRT, BoldDefs; + { TBoldDerviedHandle } -procedure TBoldDerivedHandle.DeriveAndSubscribe(DerivedObject: TObject; - Subscriber: TBoldSubscriber); +procedure TBoldDerivedHandle.DoAssign(Source: TPersistent); +begin + inherited; + if Source is TBoldDerivedHandle then with TBoldDerivedHandle(Source) do + begin + self.ValueTypeName := ValueTypeName; + self.OnDeriveAndSubscribe := OnDeriveAndSubscribe; + end; +end; + +procedure TBoldDerivedHandle.DeriveAndSubscribe(DerivedObject: TObject;Subscriber: TBoldSubscriber); begin - Assert (DerivedObject is TBoldIndirectElement); + if csDestroying in ComponentState then + raise EBold.CreateFmt('%s.DeriveAndSubscribe: %s Handle is in csDestroying state, can not DeriveAndSubscribe.', [classname, name]); + Assert(DerivedObject is TBoldIndirectElement); if Assigned(fOnDeriveAndSubscribe) then fOnDeriveAndSubscribe(Self, EffectiveRootValue, TBoldIndirectElement(DerivedObject), Subscriber); end; @@ -63,7 +78,7 @@ function TBoldDerivedHandle.GetStaticBoldType: TBoldElementTypeInfo; begin result := SystemTypeInfo.ElementTypeInfoByExpressionName[ValueTypeName]; if assigned(result) and not (result.BoldValueType in [bvtAttr, bvtList]) then - raise EBold.CreateFmt(sIllegalTypeSelected, [ClassName, ValueTypeName]); + raise EBold.CreateFmt('%s.GetStaticBoldType: Only lists and attributes are allowed as types (expr: %s)', [ClassName, ValueTypeName]); end else result := nil; diff --git a/Source/Handles/Core/BoldExpressionHandle.pas b/Source/Handles/Core/BoldExpressionHandle.pas index 1a85ff3..292b7f7 100644 --- a/Source/Handles/Core/BoldExpressionHandle.pas +++ b/Source/Handles/Core/BoldExpressionHandle.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldExpressionHandle; interface @@ -14,6 +17,8 @@ interface { forward declaration of classes } TBoldExpressionHandle = class; + TBoldExpressionHandleClass = class of TBoldExpressionHandle; + {---TBoldExpressionHandle---} TBoldExpressionHandle = class(TBoldRootedHandle, IBoldOCLComponent) function IBoldOCLComponent.GetContextType = GetStaticRootType; @@ -22,33 +27,42 @@ TBoldExpressionHandle = class(TBoldRootedHandle, IBoldOCLComponent) FVariables: TBoldOclVariables; fVariablesSubscriber: TBoldPassThroughSubscriber; fEvaluateInPS: Boolean; + fUsePrefetch: Boolean; procedure _VariablesReceive(Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent); - procedure SetExpression(Value: string); - function GetExpression: String; + procedure SetExpression(const Value: TBoldExpression); + function GetExpression: TBoldExpression; procedure SetVariables(const Value: TBoldOclVariables); - function GetVariableList: TBoldExternalVariableList; procedure SetEvaluateInPS(const Value: Boolean); protected function GetStaticBoldType: TBoldElementTypeInfo; override; procedure DeriveAndSubscribe(DerivedObject: TObject; Subscriber: TBoldSubscriber); override; + procedure DoAssign(Source: TPersistent); override; + procedure DoExpressionChanged; virtual; + function GetVariables: TBoldOclVariables; virtual; + function GetVariableList: TBoldExternalVariableList; virtual; + property VariableList: TBoldExternalVariableList read GetVariableList; public constructor Create(owner: TComponent); override; destructor Destroy; override; function RefersToComponent(Component: TBoldSubscribableComponent): Boolean; override; published - property Expression: TBoldExpression read fExpression write SetExpression; - property Variables: TBoldOclVariables read FVariables write SetVariables; + property Expression: TBoldExpression read GetExpression write SetExpression; + property Variables: TBoldOclVariables read GetVariables write SetVariables; property EvaluateInPS: Boolean read fEvaluateInPS write SetEvaluateInPS default false; {$IFNDEF T2H} property Subscribe; {$ENDIF} + property UsePrefetch: Boolean read fUsePrefetch write fUsePrefetch default true; end; implementation uses SysUtils, - HandlesConst; + {$IFDEF SpanFetch} + AttracsSpanFetchManager, + {$ENDIF} + BoldRev; const breVariablesDestroyed = 200; @@ -56,50 +70,64 @@ implementation {---TBoldExpressionHandle---} function TBoldExpressionHandle.GetStaticBoldType: TBoldElementTypeInfo; +var + vStaticRootType: TBoldElementTypeInfo; begin - if Assigned(StaticRootType) then - begin - if assigned(Variables) then - Result := StaticRootType.Evaluator.ExpressionType(Expression, StaticRootType, False, Variables.VariableList) - else - Result := StaticRootType.Evaluator.ExpressionType(Expression, StaticRootType, False); - end + vStaticRootType := StaticRootType; + if Assigned(vStaticRootType) then + Result := vStaticRootType.Evaluator.ExpressionType(Expression, vStaticRootType, True, VariableList) else Result := nil; end; -procedure TBoldExpressionHandle.SetExpression(Value: string); +procedure TBoldExpressionHandle.SetExpression(const Value: TBoldExpression); begin if Value <> fExpression then begin fExpression := Value; MarkSubscriptionOutOfdate; + DoExpressionChanged; end; end; procedure TBoldExpressionHandle.DeriveAndSubscribe(DerivedObject: TObject; Subscriber: TBoldSubscriber); + + function GetFullName(AComponent: TComponent): string; + begin + result := AComponent.GetNamePath; + if result = '' then + result := '('+AComponent.ClassName+')'; + if (AComponent is TComponent) and Assigned(TComponent(AComponent).Owner) then + result := GetFullName(TComponent(AComponent).Owner) + '.' + result; + end; + var RootValue: TBoldElement; vars: TBoldExternalVariableList; begin + if csDestroying in ComponentState then + raise EBold.CreateFmt('%s.DeriveAndSubscribe: %s Handle is in csDestroying state, can not DeriveAndSubscribe.', [classname, name]); RootValue := EffectiveRootValue; if Assigned(RootValue) then begin if assigned(Variables) then - begin - Vars := variables.VariableList; - variables.SubscribeToHandles(Subscriber); - end - else - vars := nil; + variables.SubscribeToHandles(Subscriber, Expression); + Vars := VariableList; try - RootValue.EvaluateAndSubscribeToExpression(Expression, Subscriber, ResultElement, False, EvaluateInPS, vars) + begin +{$IFDEF SpanFetch} + if UsePrefetch and not EvaluateInps then + FetchOclSpan(RootValue, Expression, vars); +{$ENDIF} + if Assigned(RootValue.BoldType) then // ValueSetValue has no BoldType + RootValue.EvaluateAndSubscribeToExpression(Expression, Subscriber, ResultElement, False, EvaluateInPS, vars) + end; except on e: Exception do begin - e.message := format(sDeriveAndSubscribeFailed, - [ClassName, Name, e.Message]); + e.message := format('%s.DeriveAndSubscribe (%s): Failed with message: %s', + [ClassName, GetFullName(self), e.Message]); raise end; end; @@ -118,7 +146,7 @@ procedure TBoldExpressionHandle.SetVariables(const Value: TBoldOclVariables); if Value <> Variables then begin if assigned(value) and value.LinksToHandle(self) then - raise EBold.CreateFmt(sCircularReference, [classname, name, value.name]); + raise EBold.CreateFmt('%s.SetVariables: %s can not be linked to %s. Circular reference', [classname, name, value.name]); FVariables := Value; StaticBoldTypeChanged; fVariablesSubscriber.CancelAllSubscriptions; @@ -143,10 +171,26 @@ procedure TBoldExpressionHandle._VariablesReceive(Originator: TObject; FVariables := nil; end; -constructor TBoldExpressionHandle.create(owner: TComponent); +procedure TBoldExpressionHandle.DoAssign(Source: TPersistent); +begin + inherited; + if Source is TBoldExpressionHandle then with TBoldExpressionHandle(Source) do + begin + self.Expression := Expression; + self.Variables := Variables; + self.EvaluateInPS := EvaluateInPS; + end; +end; + +procedure TBoldExpressionHandle.DoExpressionChanged; +begin +end; + +constructor TBoldExpressionHandle.Create(owner: TComponent); begin inherited; fVariablesSubscriber := TBoldPassthroughSubscriber.create(_VariablesReceive); + fUsePrefetch := true; end; destructor TBoldExpressionHandle.Destroy; @@ -163,6 +207,11 @@ function TBoldExpressionHandle.GetVariableList: TBoldExternalVariableList; result := nil; end; +function TBoldExpressionHandle.GetVariables: TBoldOclVariables; +begin + result := fVariables; +end; + function TBoldExpressionHandle.RefersToComponent(Component: TBoldSubscribableComponent): Boolean; begin result := inherited RefersToComponent(Component); @@ -170,4 +219,6 @@ function TBoldExpressionHandle.RefersToComponent(Component: TBoldSubscribableCom result := Component = variables; end; +initialization end. + diff --git a/Source/Handles/Core/BoldFilteredHandle.pas b/Source/Handles/Core/BoldFilteredHandle.pas index 9ba12df..1e27bb5 100644 --- a/Source/Handles/Core/BoldFilteredHandle.pas +++ b/Source/Handles/Core/BoldFilteredHandle.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldFilteredHandle; interface @@ -27,8 +30,8 @@ TBoldFilter = class(TBoldSubscribableComponentViaBoldElem) procedure SetPreFetchRoles(const Value: TStrings); function StorePreFetchRoles: Boolean; public - constructor Create(owner: TComponent); override; - destructor Destroy; override; + constructor create(owner: TComponent); override; + destructor destroy; override; procedure Subscribe(boldElement: TBoldElement; Subscriber: TBoldSubscriber); virtual; function Filter(Element: TBoldElement): Boolean; virtual; procedure FilterList(List: TBoldList); @@ -54,8 +57,10 @@ implementation uses SysUtils, + BoldDefs, BoldSystemRT; + {---TBoldFilter---} constructor TBoldFilter.create(owner: TComponent); @@ -64,10 +69,10 @@ constructor TBoldFilter.create(owner: TComponent); fPreFetchRoles := TStringList.Create; end; -destructor TBoldFilter.Destroy; +destructor TBoldFilter.destroy; begin FreeAndNil(fPreFetchRoles); - inherited; + inherited; end; function TBoldFilter.Filter(Element: TBoldElement): Boolean; @@ -100,7 +105,7 @@ procedure TBoldFilter.SetPreFetchRoles(const Value: TStrings); function TBoldFilter.StorePreFetchRoles: Boolean; begin - result := PreFetchRoles.Count <> 0; + result := PreFetchRoles.Count <> 0; end; procedure TBoldFilter.Subscribe(boldElement: TBoldElement; Subscriber: TBoldSubscriber); @@ -121,7 +126,10 @@ procedure TBoldFilteredHandle.DeriveAndSubscribe(DerivedObject: TObject; ListTypeInfo: TBoldListTypeInfo; ClassTypeInfo: TBoldClassTypeInfo; MemberRTInfo: TBoldMemberRTInfo; + begin + if csDestroying in ComponentState then + raise EBold.CreateFmt('%s.DeriveAndSubscribe: %s Handle is in csDestroying state, can not DeriveAndSubscribe.', [classname, name]); if EffectiveRootValue = nil then ResultElement.SetOwnedValue(nil) else if not Assigned(BoldFilter) then @@ -186,4 +194,6 @@ procedure TBoldFilteredHandle.SetBoldFilter(NewValue: TBoldFilter); end; end; +initialization + end. diff --git a/Source/Handles/Core/BoldHandles.pas b/Source/Handles/Core/BoldHandles.pas index b1fb5cb..98cbcbb 100644 --- a/Source/Handles/Core/BoldHandles.pas +++ b/Source/Handles/Core/BoldHandles.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldHandles; interface @@ -9,7 +12,8 @@ interface BoldSubscription, BoldElements, BoldSystem, - BoldSystemRT; + BoldSystemRT, + BoldComponentValidator; // maybe move IBoldValidateableComponent here instead ? type { forward declaration of classes } @@ -18,26 +22,38 @@ TBoldElementHandle = class; TBoldSystemTypeInfoHandle = class; TBoldNonSystemHandle = class; + TBoldElementHandleClass = class of TBoldElementHandle; + TBoldNonSystemHandleClass = class of TBoldNonSystemHandle; + {---TBoldElementHandle---} - TBoldElementHandle = class(TBoldSubscribableComponent) + TBoldElementHandle = class(TBoldSubscribableComponent, IBoldValidateableComponent) private fStrictType: Boolean; function GetDynamicBoldType: TBoldElementTypeInfo; function GetBoldType: TBoldElementTypeInfo; + function GetValueAsString: String; + function GetValueAsVariant: variant; protected function GetValue: TBoldElement; virtual; abstract; function GetStaticSystemTypeInfo: TBoldSystemTypeInfo; virtual; abstract; function GetStaticBoldType: TBoldElementTypeInfo; virtual; abstract; procedure StaticBoldTypeChanged; virtual; + function GetCanSetValue: boolean; virtual; + procedure SetValue(NewValue: TBoldElement); virtual; public destructor Destroy; override; function RefersToComponent(Component: TBoldSubscribableComponent): Boolean; virtual; + { IBoldValidateableComponent} + function ValidateComponent(ComponentValidator: TBoldComponentValidator; NamePrefix: String): Boolean; virtual; property StaticSystemTypeInfo: TBoldSystemTypeInfo read GetStaticSystemTypeInfo; property BoldType: TBoldElementTypeInfo read GetBoldType; property DynamicBoldType: TBoldElementTypeInfo read GetDynamicBoldType; property StaticBoldType: TBoldElementTypeInfo read GetStaticBoldType; property Value: TBoldElement read GetValue; property StrictType: Boolean read fStrictType write fStrictType; + property AsString: String read GetValueAsString; + property AsVariant: Variant read GetValueAsVariant; + property CanSetValue: boolean read GetCanSetValue; end; { TBoldSystemTypeInfoHandle } @@ -54,6 +70,7 @@ TBoldSystemTypeInfoHandle = class(TBoldElementHandle) procedure SetBoldModel(Value: TBoldAbstractModel); procedure ModelChanged; function GetRegionDefinitions: TBoldRegionDefinitions; + function GetIsSystemTypeInfoAvailable: boolean; protected function GetStaticBoldType: TBoldElementTypeInfo; override; function GetStaticSystemTypeInfo: TBoldSystemTypeInfo; override; @@ -64,6 +81,7 @@ TBoldSystemTypeInfoHandle = class(TBoldElementHandle) procedure InstallOclDefinitionLookUp(const Value: TBoldLookUpOclDefinition); function RefersToComponent(Component: TBoldSubscribableComponent): Boolean; override; property RegionDefinitions: TBoldRegionDefinitions read GetRegionDefinitions; + property IsSystemTypeInfoAvailable: boolean read GetIsSystemTypeInfoAvailable; published property BoldModel: TBoldAbstractModel read fBoldModel write SetBoldModel; property UseGeneratedCode: Boolean read fUseGeneratedCode write fUseGeneratedCode default True; @@ -78,8 +96,7 @@ TBoldAbstractSystemHandle = class(TBoldElementHandle) fSystemTypeInfoHandle: TBoldSystemTypeInfoHandle; procedure SetSystemTypeInfoHandle(Value: TBoldSystemTypeInfoHandle); procedure _Recieve(Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent); - procedure setIsDefault(Value: Boolean); - function GetIsDefault: Boolean; + procedure SetIsDefault(Value: Boolean); protected function GetActive: Boolean; virtual; abstract; procedure SetActive(Value: Boolean); virtual; abstract; @@ -96,8 +113,9 @@ TBoldAbstractSystemHandle = class(TBoldElementHandle) property SystemTypeInfoHandle: TBoldSystemTypeInfoHandle read fSystemTypeInfoHandle write SetSystemTypeInfoHandle; class function DefaultBoldSystemTypeInfo: TBoldSystemTypeInfo; class function DefaultBoldSystemHandle: TBoldAbstractSystemHandle; + class function FindSystemHandleForSystem(ABoldSystem: TBoldSystem): TBoldAbstractSystemHandle; published - property IsDefault: Boolean read GetIsDefault write setIsDefault nodefault; {Always save} + property IsDefault: Boolean read fIsDefault write SetIsDefault nodefault; {Always save} end; { TBoldNonSystemHandle } @@ -106,23 +124,31 @@ TBoldNonSystemHandle = class(TBoldElementHandle) fStaticSystemHandle: TBoldAbstractSystemHandle; fStaticSystemHandleSubscriber: TBoldPassthroughSubscriber; procedure _Receive(Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent); + function GetBoldSystem: TBoldSystem; protected + function GetStaticSystemHandle: TBoldAbstractSystemHandle; virtual; procedure SetStaticSystemHandle(Value: TBoldAbstractSystemHandle); virtual; function GetStaticSystemTypeInfo: TBoldSystemTypeInfo; override; + procedure DoAssign(Source: TPersistent); virtual; + function IsStaticSystemHandleStored: boolean; virtual; public constructor Create(Owner: TComponent); override; + procedure AfterConstruction; override; destructor Destroy; override; + procedure Assign(Source: TPersistent); override; + property BoldSystem: TBoldSystem read GetBoldSystem; published - property StaticSystemHandle: TBoldAbstractSystemHandle read fStaticSystemHandle write SetStaticSystemHandle; + property StaticSystemHandle: TBoldAbstractSystemHandle read GetStaticSystemHandle write SetStaticSystemHandle stored IsStaticSystemHandleStored; end; implementation uses SysUtils, - HandlesConst, BoldDefs, - BoldregionDefinitionParser; + BoldregionDefinitionParser, + BoldContainers, + Variants; const breModelDestroyed = 42; @@ -132,6 +158,7 @@ implementation var G_DefaultBoldSystemHandle: TBoldAbstractSystemHandle = nil; + G_BoldSystemHandleList: TBoldObjectArray; {---TBoldElementHandle---} @@ -144,10 +171,15 @@ destructor TBoldElementHandle.Destroy; function TBoldElementHandle.GetBoldType: TBoldElementTypeInfo; begin Result := DynamicBoldType; - if not Assigned(DynamicBoldType) then + if not Assigned(Result) then Result := StaticBoldType; end; +function TBoldElementHandle.GetCanSetValue: boolean; +begin + result := false; +end; + function TBoldElementHandle.GetDynamicBoldType: TBoldElementTypeInfo; begin if Assigned(Value) then @@ -156,23 +188,53 @@ function TBoldElementHandle.GetDynamicBoldType: TBoldElementTypeInfo; Result := nil; end; +function TBoldElementHandle.GetValueAsString: String; +begin + if Assigned(Value) then + result := Value.AsString + else + result := ''; +end; + +function TBoldElementHandle.GetValueAsVariant: variant; +begin + if Assigned(Value) then + result := Value.AsVariant + else + result := null; +end; + function TBoldElementHandle.RefersToComponent(Component: TBoldSubscribableComponent): Boolean; begin result := false; end; +procedure TBoldElementHandle.SetValue(NewValue: TBoldElement); +begin + raise EBold.CreateFmt('%s: SetValue Not supported', [ClassName]); +end; + procedure TBoldElementHandle.StaticBoldTypeChanged; begin SendEvent(self, beValueIdentityChanged); end; +function TBoldElementHandle.ValidateComponent( + ComponentValidator: TBoldComponentValidator; NamePrefix: String): Boolean; +var + vBoldOCLComponent: IBoldOCLComponent; +begin + result := Assigned(BoldType); + if result and Supports(self, IBoldOCLComponent, vBoldOCLComponent) then + result := ComponentValidator.ValidateOCLComponent(vBoldOCLComponent, NamePrefix+Name); +end; + { TBoldNonSystemHandle } procedure TBoldNonSystemHandle._Receive(Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent); begin - Assert(Originator=StaticSystemHandle); - Assert(RequestedEvent in [breFreeHandle, breValueIdentityChanged]); + Assert(RequestedEvent in [breFreeHandle, breValueIdentityChanged], IntToStr(OriginalEvent) + ',' + IntToStr(RequestedEvent)); case RequestedEvent of breFreeHandle: StaticSystemHandle := nil; breValueIdentityChanged: StaticBoldTypeChanged; @@ -185,23 +247,78 @@ procedure TBoldNonSystemHandle.SetStaticSystemHandle(Value: TBoldAbstractSystemH begin fStaticSystemHandleSubscriber.CancelAllSubscriptions; fStaticSystemHandle := Value; - if Assigned(StaticSystemHandle) then + if Assigned(fStaticSystemHandle) then begin - StaticSystemHandle.AddSmallSubscription(fStaticSystemHandleSubscriber, [beDestroying], breFreeHandle); - StaticSystemHandle.AddSmallSubscription(fStaticSystemHandleSubscriber, [beValueIDentityChanged], breValueIdentityChanged); + fStaticSystemHandle.AddSmallSubscription(fStaticSystemHandleSubscriber, [beDestroying], breFreeHandle); + fStaticSystemHandle.AddSmallSubscription(fStaticSystemHandleSubscriber, [beValueIDentityChanged], breValueIdentityChanged); end; StaticBoldTypeChanged; end; end; +function TBoldNonSystemHandle.GetBoldSystem: TBoldSystem; +begin + if Assigned(fStaticSystemHandle) then + result := fStaticSystemHandle.System + else + result := nil; +end; + +function TBoldNonSystemHandle.GetStaticSystemHandle: TBoldAbstractSystemHandle; +begin + if Assigned(fStaticSystemHandle) then + result := fStaticSystemHandle + else + begin + result := nil; +{ if BoldSystemCount = 1 then + begin + result := TBoldAbstractSystemHandle.DefaultBoldSystemHandle; + if Assigned(result) and (fStaticSystemHandleSubscriber.SubscriptionCount = 0) then + begin + result.AddSmallSubscription(fStaticSystemHandleSubscriber, [beDestroying], breFreeHandle); + result.AddSmallSubscription(fStaticSystemHandleSubscriber, [beValueIDentityChanged], breValueIdentityChanged); + end; + end; +} + end; +end; + function TBoldNonSystemHandle.GetStaticSystemTypeInfo: TBoldSystemTypeInfo; begin if Assigned(StaticSystemHandle) then Result := StaticSystemHandle.StaticSystemTypeInfo - else if TBoldAbstractSystemHandle.DefaultBoldSystemHandle <> nil then + else Result := TBoldAbstractSystemHandle.DefaultBoldSystemTypeInfo +end; + +function TBoldNonSystemHandle.IsStaticSystemHandleStored: boolean; +begin + result := Assigned(fStaticSystemHandle); +end; + +procedure TBoldNonSystemHandle.AfterConstruction; +begin + inherited; + if Assigned(G_DefaultBoldSystemHandle) and not (csLoading in ComponentState) and (csDesigning in ComponentState) then + {connect to default system at design time} + StaticSystemHandle := G_DefaultBoldSystemHandle; +end; + +procedure TBoldNonSystemHandle.Assign(Source: TPersistent); +begin + if Source is TBoldNonSystemHandle then + DoAssign(Source) else - Result := nil; + inherited Assign(Source); +end; + +procedure TBoldNonSystemHandle.DoAssign(Source: TPersistent); +begin + if (Source is TBoldNonSystemHandle) then + begin + StaticSystemHandle := TBoldNonSystemHandle(Source).StaticSystemHandle; + end end; constructor TBoldNonSystemHandle.Create(Owner: TComponent); @@ -225,6 +342,7 @@ constructor TBoldAbstractSystemHandle.create(owner: TComponent); fSystemTypeInfoHandleSubscriber := TBoldPassThroughSubscriber.Create(_Recieve); if not Assigned(G_DefaultBoldSystemHandle) and (csdesigning in ComponentState) then {only make first default at design time} IsDefault := True; + G_BoldSystemHandleList.Add(self); end; class function TBoldAbstractSystemHandle.DefaultBoldSystemHandle: TBoldAbstractSystemHandle; @@ -243,6 +361,7 @@ class function TBoldAbstractSystemHandle.DefaultBoldSystemTypeInfo: TBoldSystemT destructor TBoldAbstractSystemHandle.Destroy; begin FreePublisher; + G_BoldSystemHandleList.Remove(self); if G_DefaultBoldSystemHandle = self then G_DefaultBoldSystemHandle := nil; IsDefault := False; @@ -250,9 +369,17 @@ destructor TBoldAbstractSystemHandle.Destroy; inherited; end; -function TBoldAbstractSystemHandle.GetIsDefault: Boolean; +class function TBoldAbstractSystemHandle.FindSystemHandleForSystem(ABoldSystem: TBoldSystem): TBoldAbstractSystemHandle; +var + i: integer; begin - result := fIsDefault; + for I := 0 to G_BoldSystemHandleList.Count - 1 do + begin + result := TBoldAbstractSystemHandle(G_BoldSystemHandleList[i]); + if ABoldSystem = result.System then + exit; + end; + result := nil; end; function TBoldAbstractSystemHandle.GetStaticBoldType: TBoldElementTypeInfo; @@ -275,17 +402,18 @@ function TBoldAbstractSystemHandle.RefersToComponent(Component: TBoldSubscribabl result := Component = SystemTypeInfoHandle; end; -procedure TBoldAbstractSystemHandle.setIsDefault(Value: Boolean); +procedure TBoldAbstractSystemHandle.SetIsDefault(Value: Boolean); begin if (Value <> IsDefault) then begin fIsDefault := Value; if Value then G_DefaultBoldSystemHandle := Self - else if Isdefault then + else + if G_DefaultBoldSystemHandle = Self then G_DefaultBoldSystemHandle := nil; if Active then - System.IsDefault := Value; + System.IsDefault := G_DefaultBoldSystemHandle = Self; end; end; @@ -294,7 +422,7 @@ procedure TBoldAbstractSystemHandle.SetSystemTypeInfoHandle(Value: TBoldSystemTy if Value <> fSystemTypeInfoHandle then begin if Active then - raise EBold.CreateFmt(sNotAllowedOnActiveHandle, [Name]); + raise EBold.CreateFmt('%s: Not allowed to change the systemTypeInfoHandle on an active system', [Name]); fSystemTypeInfoHandleSubscriber.CancelAllSubscriptions; if Assigned(Value) then begin @@ -336,7 +464,7 @@ procedure TBoldSystemTypeInfoHandle._Recieve(Originator: TObject; function TBoldSystemTypeInfoHandle.GetStaticBoldType: TBoldElementTypeInfo; begin - result := GetStaticSystemTypeInfo; + result := GetStaticSystemTypeInfo; end; function TBoldSystemTypeInfoHandle.GetStaticSystemTypeInfo: TBoldSystemTypeInfo; @@ -358,10 +486,16 @@ function TBoldSystemTypeInfoHandle.GetStaticSystemTypeInfo: TBoldSystemTypeInfo; end; procedure TBoldSystemTypeInfoHandle.ModelChanged; +var + WasActive: boolean; begin + WasActive := Assigned(fSystemTypeInfo); + if WasActive then + SendEvent(self, beValueIdentityChanged); FreeAndNil(fSystemTypeInfo); FreeAndNil(fRegionDefinitions); - SendEvent(self, beValueIdentityChanged); // type change regarded as idenitychange + if not WasActive then + SendEvent(self, beValueIdentityChanged); end; procedure TBoldSystemTypeInfoHandle.SetBoldModel(Value: TBoldAbstractModel); @@ -387,7 +521,7 @@ constructor TBoldSystemTypeInfoHandle.Create(owner: TComponent); fModelSubscriber := TBoldPassThroughSubscriber.Create(_Recieve); end; -destructor TBoldSystemTypeInfoHandle.Destroy; +destructor TBoldSystemTypeInfoHandle.destroy; begin FreePublisher; FreeAndNil(fModelSubscriber); @@ -415,6 +549,11 @@ function TBoldSystemTypeInfoHandle.RefersToComponent(Component: TBoldSubscribabl result := Component = BoldModel; end; +function TBoldSystemTypeInfoHandle.GetIsSystemTypeInfoAvailable: boolean; +begin + result := Assigned(fSystemTypeInfo); +end; + function TBoldSystemTypeInfoHandle.GetRegionDefinitions: TBoldRegionDefinitions; var Parser: TBoldRegionParser; @@ -437,4 +576,10 @@ function TBoldSystemTypeInfoHandle.GetRegionDefinitions: TBoldRegionDefinitions; result := fRegionDefinitions; end; +initialization + G_BoldSystemHandleList := TBoldObjectArray.Create(10, []); + +finalization + FreeAndNil(G_BoldSystemHandleList); + end. diff --git a/Source/Handles/Core/BoldListHandle.pas b/Source/Handles/Core/BoldListHandle.pas index 703b694..58b66ab 100644 --- a/Source/Handles/Core/BoldListHandle.pas +++ b/Source/Handles/Core/BoldListHandle.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldListHandle; interface @@ -17,7 +20,7 @@ interface type {---Forward declarations---} - TBoldListHandle = class; + TBoldListHandle = class; {---TBoldListHandle---} TBoldListHandle = class(TBoldCursorHandle, IBoldOCLComponent) @@ -25,21 +28,23 @@ TBoldListHandle = class(TBoldCursorHandle, IBoldOCLComponent) fExpressionHandle: TBoldExpressionHandle; fFilterHandle: TBoldFilteredHandle; fSorterHandle: TBoldSortedHandle; + FInternalRootHandle: TBoldSortedHandle; fMutableListExpression: TBoldExpression; + fUsePrefetch: boolean; function GetContextType: TBoldElementTypeInfo; function GetComparer: TBoldComparer; function GetExpression: TBoldExpression; function GetFilter: TBoldFilter; procedure SetComparer(Value: TBoldComparer); - procedure SetExpression(Value: string); + procedure SetExpression(const Value: TBoldExpression); procedure SetFilter(Value: TBoldFilter); - function GetVariableList: TBoldExternalVariableList; - function GetVariables: TBoldOclVariables; procedure SetVariables(Value: TBoldOclVariables); function GetEvaluateInPS: Boolean; procedure SetEvaluateInPS(const Value: Boolean); procedure SetMutableListExpression(const Value: TBoldExpression); procedure FixupRoots; + function GetUsePrefetch: Boolean; + procedure SetUsePrefetch(const Value: Boolean); protected procedure Notification(AComponent: TComponent; Operation: TOperation); override; procedure SetSubscribe(Value: Boolean); override; @@ -47,12 +52,18 @@ TBoldListHandle = class(TBoldCursorHandle, IBoldOCLComponent) procedure Loaded; override; function GetRootHandle: TBoldElementHandle; override; procedure SetRootHandle(const Value: TBoldElementHandle); override; + procedure SetRootTypeName(Value: string); override; function GetMutableList: TBoldList; override; + procedure DoAssign(Source: TPersistent); override; + function GetVariables: TBoldOclVariables; virtual; + function GetVariableList: TBoldExternalVariableList; virtual; + function GetExpressionHandleClass: TBoldExpressionHandleClass; virtual; public constructor Create(Owner: TComponent); override; destructor Destroy; override; procedure MarkOutOfDate; override; function RefersToComponent(Component: TBoldSubscribableComponent): Boolean; override; + property VariableList: TBoldExternalVariableList read GetVariableList; published property BoldComparer: TBoldComparer read GetComparer write SetComparer; property BoldFilter: TBoldFilter read GetFilter write SetFilter; @@ -60,21 +71,26 @@ TBoldListHandle = class(TBoldCursorHandle, IBoldOCLComponent) property Variables: TBoldOclVariables read GetVariables write SetVariables; property EvaluateInPS: Boolean read GetEvaluateInPS write SetEvaluateInPS default false; property MutableListExpression: TBoldExpression read fMutableListExpression write SetMutableListExpression; + property UsePrefetch: Boolean read GetUsePrefetch write SetUsePrefetch default true; end; implementation uses SysUtils, - HandlesConst, BoldRootedHandles; +type + THackSortedHandle = class(TBoldSortedHandle); + {---TBoldListHandle---} constructor TBoldListHandle.Create(Owner: TComponent); begin inherited; - fExpressionHandle := TBoldExpressionHandle.Create(nil); + fExpressionHandle := GetExpressionHandleClass.Create(self); + FInternalRootHandle := TBoldSortedHandle.Create(nil); FixupRoots; + UsePrefetch := true; end; destructor TBoldListHandle.Destroy; @@ -83,9 +99,24 @@ destructor TBoldListHandle.Destroy; FreeAndNil(fSorterHandle); FreeAndNil(fFilterHandle); FreeAndNil(fExpressionHandle); + FreeAndNil(FInternalRootHandle); inherited; end; +procedure TBoldListHandle.DoAssign(Source: TPersistent); +begin + inherited; + if Source is TBoldListHandle then with TBoldListHandle(Source) do + begin + self.BoldComparer := BoldComparer; + self.BoldFilter := BoldFilter; + self.Expression := Expression; + self.Variables := Variables; + self.EvaluateInPS := EvaluateInPS; + self.MutableListExpression := MutableListExpression; + end; +end; + procedure TBoldListHandle.Notification(AComponent: TComponent; Operation: TOperation); begin inherited Notification(AComponent, Operation); @@ -102,6 +133,7 @@ procedure TBoldListHandle.SetSubscribe(Value: Boolean); fFilterHandle.Subscribe := Value; if Assigned(fSorterHandle) then fSorterHandle.Subscribe := Value; + FInternalRootHandle.Subscribe := Value; inherited; end; @@ -112,6 +144,7 @@ procedure TBoldListHandle.MarkOutOfDate; fFilterHandle.MarkOutOfDate; if Assigned(fSorterHandle) then fSorterHandle.MarkOutOfDate; + FInternalRootHandle.MarkOutOfDate; inherited; end; @@ -120,25 +153,29 @@ procedure TBoldListHandle.FixupRoots; NextHandle: TBoldElementHandle; begin NextHandle := fExpressionHandle; - fExpressionHandle.Name := Name + '_expr'; // do not localize + fExpressionHandle.Name := Name + '_expr'; if Assigned(fFilterHandle) then begin fFilterHandle.RootHandle := NextHandle; - fFilterHandle.Name := Name + '_filt'; // do not localize + fFilterHandle.Name := Name + '_filt'; NextHandle := fFilterHandle; end; if Assigned(fSorterHandle) then begin FSorterHandle.RootHandle := NextHandle; - fSorterHandle.Name := Name + '_sort'; // do not localize + fSorterHandle.Name := Name + '_sort'; NextHandle := FSorterHandle; end; + FInternalRootHandle.RootHandle := NextHandle; + FInternalRootHandle.Name := Name + '_root'; // do not localize + NextHandle := FInternalRootHandle; + InternalRootHandle := NextHandle; end; -procedure TBoldListHandle.SetExpression(Value: string); +procedure TBoldListHandle.SetExpression(const Value: TBoldExpression); begin if value <> fExpressionHandle.Expression then begin @@ -152,6 +189,11 @@ function TBoldListHandle.GetExpression: TBoldExpression; Result := fExpressionHandle.Expression; end; +function TBoldListHandle.GetExpressionHandleClass: TBoldExpressionHandleClass; +begin + result := TBoldExpressionHandle; +end; + procedure TBoldListHandle.SetFilter(Value: TBoldFilter); begin if Value = BoldFilter then @@ -160,6 +202,11 @@ procedure TBoldListHandle.SetFilter(Value: TBoldFilter); begin if Assigned(fFilterHandle) then begin + if Assigned(FSorterHandle) then begin + FSorterHandle.RootHandle := FExpressionHandle; + end else begin + FInternalRootHandle.RootHandle := FExpressionHandle; + end; FreeAndNil(fFilterHandle); end end @@ -183,12 +230,21 @@ function TBoldListHandle.GetFilter: TBoldFilter; procedure TBoldListHandle.SetComparer(Value: TBoldComparer); begin - if Value = BoldComparer then + if Value = BoldComparer then begin + if Assigned(FSorterHandle) then begin + THackSortedHandle(FSorterHandle).MarkSubscriptionOutOfdate; + end; Exit; + end; if Value = nil then begin if Assigned(FSorterHandle) then begin + if Assigned(FFilterHandle) then begin + FInternalRootHandle.RootHandle := FFilterHandle; + end else begin + FInternalRootHandle.RootHandle := FExpressionHandle; + end; FreeAndNil(fSorterHandle); end end @@ -222,11 +278,30 @@ function TBoldListHandle.GetRootHandle: TBoldElementHandle; Result := fExpressionHandle.RootHandle; end; +procedure TBoldListHandle.SetUsePrefetch(const Value: Boolean); +begin + fUsePrefetch := Value; + fExpressionHandle.UsePrefetch := Value; +end; + +function TBoldListHandle.GetUsePrefetch: Boolean; +begin + result := fUsePrefetch; +end; + procedure TBoldListHandle.SetRootHandle(const Value: TBoldElementHandle); begin fExpressionHandle.RootHandle := Value; end; +procedure TBoldListHandle.SetRootTypeName(Value: string); +begin + inherited; + fExpressionHandle.RootTypeName := Value; + fInternalROotHandle.RootTypeName := Value; + StaticBoldTypeChanged; +end; + procedure TBoldListHandle.SetStaticSystemHandle( Value: TBoldAbstractSystemHandle); begin @@ -253,7 +328,7 @@ function TBoldListHandle.GetVariables: TBoldOclVariables; procedure TBoldListHandle.SetVariables(Value: TBoldOclVariables); begin if assigned(value) and value.LinksToHandle(self) then - raise EBold.CreateFmt(sCircularReference, [classname, name, value.name]); + raise EBold.CreateFmt('%s.SetVariables: %s can not be linked to %s. Circular reference', [classname, name, value.name]); fExpressionHandle.Variables := Value; end; @@ -332,4 +407,5 @@ function TBoldListHandle.RefersToComponent(Component: TBoldSubscribableComponent result := Component = variables; end; +initialization end. diff --git a/Source/Handles/Core/BoldOclRepository.pas b/Source/Handles/Core/BoldOclRepository.pas index 0c04a65..81c2952 100644 --- a/Source/Handles/Core/BoldOclRepository.pas +++ b/Source/Handles/Core/BoldOclRepository.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldOclRepository; interface @@ -8,26 +11,30 @@ interface BoldSystemRT, BoldSystemHandle, BoldSubscription, - BoldComponentvalidator; + BoldHandles, + BoldComponentvalidator, + BoldDefs; type TBoldOclDefinitions = class; TBoldOclDefinition = class; TBoldOclRepository = class; - TBoldOclRepository = class(TBoldSubscribableComponent, IBoldValidateableComponent) + TBoldOclRepository = class(TBoldNonSystemHandle, IBoldValidateableComponent) private FOclDefinitions: TBoldOclDefinitions; - FSystemHandle: TBoldSystemHandle; procedure SetOclDefinitions(const Value: TBoldOclDefinitions); - procedure SetSystemHandle(const Value: TBoldSystemHandle); - function ValidateComponent(ComponentValidator: TBoldComponentValidator; NamePrefix: String): Boolean; +// procedure SetStaticSystemHandle(Value: TBoldSystemHandle); + protected +// procedure Notification(AComponent: TComponent; Operation: TOperation); override; + procedure SetStaticSystemHandle(Value: TBoldAbstractSystemHandle); override; + function ValidateComponent(ComponentValidator: TBoldComponentValidator; NamePrefix: String): Boolean; override; public constructor Create(owner: TComponent); override; + destructor Destroy; override; function LookUpOclDefinition(Name: string): string; published property OclDefinitions: TBoldOclDefinitions read FOclDefinitions write SetOclDefinitions; - property SystemHandle: TBoldSystemHandle read FSystemHandle write SetSystemHandle; end; TBoldOclDefinitions = class(TCollection) @@ -39,7 +46,7 @@ TBoldOclDefinitions = class(TCollection) property OwningRepository: TBoldOclRepository read fOwningRepository; function NameIsUnique(Name: String): Boolean; public - constructor Create(OwningRepository: TBoldOclRepository); + constructor create(OwningRepository: TBoldOclRepository); function GetUniqueName: String; function LookUpOclDefinition(Name: string): string; property Items[Index: integer]: TBoldOclDefinition read GetItems; default; @@ -50,8 +57,8 @@ TBoldOclDefinition = class(TCollectionItem, IBoldOclComponent) fName: String; fExpression: String; fContext: String; - procedure SetExpression(Expression: String); - function GetExpression: String; + procedure SetExpression(const Value: TBoldExpression); + function GetExpression: TBoldExpression; function GetVariableList: TBoldExternalVariableList; function GetDefinitions: TBoldOclDefinitions; function QueryInterface(const IId: TGUID; out Obj): HResult; virtual; stdcall; @@ -63,7 +70,7 @@ TBoldOclDefinition = class(TCollectionItem, IBoldOclComponent) function GetDisplayName: string; override; public constructor Create(Collection: TCollection); override; - destructor Destroy; override; + destructor destroy; override; function GetContextType: TBoldElementTypeInfo; property Definitions: TBoldOclDefinitions read GetDefinitions; property SystemTypeInfo: TBoldSystemTypeInfo read GetSystemTypeInfo; @@ -73,23 +80,27 @@ TBoldOclDefinition = class(TCollectionItem, IBoldOclComponent) property Context: String read FContext write fContext; end; + implementation uses SysUtils, - BoldDefs, - BoldHandles, - BoldLogHandler, - HandlesConst; + BoldLogHandler; { TBoldOclRepository } -constructor TBoldOclRepository.create(owner: TComponent); +constructor TBoldOclRepository.Create(owner: TComponent); begin inherited; FOclDefinitions := TBoldOclDefinitions.Create(self); end; +destructor TBoldOclRepository.Destroy; +begin + FreeAndNil(FOclDefinitions); + inherited; +end; + function TBoldOclRepository.LookUpOclDefinition(Name: string): string; begin result := OclDefinitions.LookUpOclDefinition(Name); @@ -101,14 +112,21 @@ procedure TBoldOclRepository.SetOclDefinitions( FOclDefinitions := Value; end; -procedure TBoldOclRepository.SetSystemHandle(const Value: TBoldSystemHandle); +procedure TBoldOclRepository.SetStaticSystemHandle(Value: TBoldAbstractSystemHandle); begin - if assigned(SystemHandle) then - SystemHandle.InstallOclDefinitionLookUp(nil); - - FSystemHandle := Value; - if assigned(SystemHandle) then - SystemHandle.InstallOclDefinitionLookUp(LookUpOclDefinition); + if StaticSystemHandle = Value then + exit; + if assigned(StaticSystemHandle) then + begin + (StaticSystemHandle as TBoldSystemHandle).InstallOclDefinitionLookUp(nil); + StaticSystemHandle.RemoveFreeNotification(self); + end; + if assigned(Value) then + begin + (Value as TBoldSystemHandle).InstallOclDefinitionLookUp(LookUpOclDefinition); + Value.FreeNotification(Self); + end; + inherited SetStaticSystemHandle(Value); end; function TBoldOclRepository.ValidateComponent( @@ -118,20 +136,19 @@ function TBoldOclRepository.ValidateComponent( i: integer; Context: TBoldElementTypeInfo; begin - result := true; - if not assigned(SystemHandle) then - BoldLog.LogFmt(sRepositoryHasNoSystemHandle, [NamePrefix, Name]) - else if not assigned(SystemHandle.StaticSystemTypeInfo) then - BoldLog.LogFmt(sSystemHandleHasNoTypeInfo, [NamePrefix, Name]) + result := inherited ValidateComponent(ComponentValidator, NamePrefix); + if not assigned(StaticSystemHandle) then + BoldLog.LogFmt('*** OclRepository %s%s has no StaticSystemHandle', [NamePrefix, Name]) + else if not assigned(StaticSystemHandle.StaticSystemTypeInfo) then + BoldLog.LogFmt('*** StaticSystemHandle of OclRepository %s%s has no TypeInfo', [NamePrefix, Name]) else begin - for i := 0 to OclDefinitions.count - 1 do - begin - Context := SystemHandle.StaticSystemTypeInfo.ElementTypeInfoByExpressionName[OclDefinitions[i].Context]; + for i := 0 to OclDefinitions.count-1 do begin + Context := StaticSystemHandle.StaticSystemTypeInfo.ElementTypeInfoByExpressionName[OclDefinitions[i].Context]; result := ComponentValidator.ValidateExpressionInContext( OclDefinitions[i].Expression, Context, - NamePrefix + Name + '.' + OclDefinitions[i].Name) and result; + NamePrefix+Name+ '.'+OclDefinitions[i].Name) and result; end; end; end; @@ -144,9 +161,10 @@ constructor TBoldOclDefinition.Create(Collection: TCollection); Name := (Collection as TBoldOclDefinitions).GetUniqueName; end; -destructor TBoldOclDefinition.Destroy; +destructor TBoldOclDefinition.destroy; begin inherited; + end; function TBoldOclDefinition.GetContextType: TBoldElementTypeInfo; @@ -164,19 +182,19 @@ function TBoldOclDefinition.GetDefinitions: TBoldOclDefinitions; function TBoldOclDefinition.GetDisplayName: string; begin - result:= '%' + name + ': ' + Expression; + result:= '%' + name + ': '+Expression; end; -function TBoldOclDefinition.GetExpression: String; +function TBoldOclDefinition.GetExpression: TBoldExpression; begin result := fExpression; end; function TBoldOclDefinition.GetSystemTypeInfo: TBoldSystemTypeInfo; begin - if assigned(Definitions.OwningRepository.SystemHandle) then - result := Definitions.OwningRepository.SystemHandle.StaticSystemTypeInfo + if assigned(Definitions.OwningRepository.StaticSystemHandle) then + result := Definitions.OwningRepository.StaticSystemHandle.StaticSystemTypeInfo else result := nil; end; @@ -195,9 +213,9 @@ function TBoldOclDefinition.QueryInterface(const IId: TGUID; Result := E_NOINTERFACE; end; -procedure TBoldOclDefinition.SetExpression(Expression: String); +procedure TBoldOclDefinition.SetExpression(const Value: TBoldExpression); begin - fExpression := Expression; + fExpression := Value; end; procedure TBoldOclDefinition.SetName(const Value: String); @@ -207,7 +225,7 @@ procedure TBoldOclDefinition.SetName(const Value: String); if TBoldOclDefinitions(Collection).NameIsUnique(Value) then FName := Value else - raise EBold.CreateFmt(sNameNotUnique, [Value]); + raise EBold.CreateFmt('Invalid Name: %s Not Unique', [Value]); end; end; @@ -245,7 +263,7 @@ function TBoldOclDefinitions.GetUniqueName: String; begin i := 1; repeat - result := 'Ocl' + IntToStr(i); // do not translate + result := 'Ocl'+IntToStr(i); Inc(i); until NameIsUnique(result); end; @@ -255,7 +273,7 @@ function TBoldOclDefinitions.LookUpOclDefinition(Name: string): string; i: integer; begin result := ''; - for i := 0 to Count - 1 do + for i := 0 to Count -1 do if Items[i].Name = Name then begin result := items[i].Expression; @@ -269,12 +287,12 @@ function TBoldOclDefinitions.NameIsUnique(Name: String): Boolean; begin result := true; for i := 0 to Count-1 do - if AnsiCompareStr(Name, Items[i].Name) = 0 then + if CompareStr(Name, Items[i].Name) = 0 then begin result := false; exit; end; end; +initialization end. - diff --git a/Source/Handles/Core/BoldOclVariables.pas b/Source/Handles/Core/BoldOclVariables.pas index ff56baf..6159621 100644 --- a/Source/Handles/Core/BoldOclVariables.pas +++ b/Source/Handles/Core/BoldOclVariables.pas @@ -1,9 +1,16 @@ + +{ Global compiler directives } +{$include bold.inc} + unit BoldOclVariables; interface uses Classes, +{$IFNDEF BOLD_DELPHI16_OR_LATER} + Controls, // TDate = type TDateTime; +{$ENDIF} BoldSubscription, BoldHandles, BoldElements; @@ -20,11 +27,13 @@ TBoldHandleBasedExternalVariable = class(TBoldExternalVariable) private fHandle: TBoldElementHandle; fUseListElement: Boolean; - fhandleSubscriber: TBoldPassThroughSubscriber; + fHandleSubscriber: TBoldPassThroughSubscriber; procedure _ReceiveHandleEvent(Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent); + procedure SetHandle(const Value: TBoldElementHandle); protected function GetValue: TBoldElement; override; function GetValueType: TBoldElementTypeInfo; override; + property Handle: TBoldElementHandle read fHandle write SetHandle; public constructor Create(Name: String; Handle: TBoldElementHandle; UseListElement: Boolean); destructor Destroy; override; @@ -35,33 +44,59 @@ TBoldOclVariables = class(TBoldSubscribableComponent) private fVariableTupleList: TBoldVariableTupleList; fVariableList: TBoldExternalVariableList; + fGlobalSystemHandle: TBoldAbstractSystemhandle; + fSubscriber: TBoldPassthroughSubscriber; procedure SetVariableTupleList(const Value: TBoldVariableTupleList); procedure VariablesChanged; function GetVariableList: TBoldExternalVariableList; + procedure SetGlobalSystemHandle(aSystemHandle: TBoldAbstractSystemhandle); + procedure _Receive(Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent); + procedure PlaceSubscriptions; + procedure SubscribeToHandle(AHandle: TBoldElementHandle); + function GetGlobalSystemHandle: TBoldAbstractSystemhandle; + function GetVariableFromHandle(AHandle: TBoldElementHandle): TBoldExternalVariable; + protected + procedure Loaded; override; + procedure RegisterVariables; public constructor Create(Owner: TComponent); override; destructor Destroy; override; - procedure SubscribeToHandles(Subscriber: TBoldSubscriber); + procedure SubscribeToHandles(Subscriber: TBoldSubscriber); overload; + procedure SubscribeToHandles(Subscriber: TBoldSubscriber; Expression: string); overload; + function AddVariable(aVariableName: string; aBoldHandle: TBoldElementHandle; aUseListElement: boolean = false): TBoldVariableTuple; + procedure AddVariables(aBoldOclVariables: TBoldOclVariables); + function FindVariableByName(const aVariableName: string): TBoldExternalVariable; + function GetVariableValue(const aVariableName: string): TBoldElement; function LinksToHandle(Handle: TBoldElementHandle): Boolean; property VariableList: TBoldExternalVariableList read GetVariableList; published + property GlobalSystemHandle: TBoldAbstractSystemhandle read GetGlobalSystemHandle write SetGlobalSystemHandle; property Variables: TBoldVariableTupleList read fVariableTupleList write SetVariableTupleList; end; + TBoldVariableTupleListEnumerator = class(TCollectionEnumerator) + public + function GetCurrent: TBoldVariableTuple; + property Current: TBoldVariableTuple read GetCurrent; + end; + { TBoldVariableTupleList } TBoldVariableTupleList = class(TCollection) private fOwningDefinition: TBoldOclVariables; function GetItems(Index: integer): TBoldVariableTuple; + function GetVariableByName(const aName: string): TBoldVariableTuple; protected function GetOwner: TPersistent; override; property OwningDefinition: TBoldOclVariables read fOwningDefinition; public constructor Create(aOwningDefinition: TBoldOclVariables); + function GetEnumerator: TBoldVariableTupleListEnumerator; function NameIsUnique(Name: String): Boolean; function NameIsValid(Name: String): Boolean; function GetUniqueName: String; property Items[Index: integer]: TBoldVariableTuple read GetItems; default; + property VariableByName[const aName: string]: TBoldVariableTuple read GetVariableByName; end; { TBoldVariableTuple } @@ -82,7 +117,7 @@ TBoldVariableTuple = class(TCollectionItem) function GetDisplayName: string; override; public constructor Create(Collection: TCollection); override; - destructor Destroy; override; + destructor destroy; override; procedure Assign(Source: TPersistent); override; function LinksToHandle(Handle: TBoldElementHandle): Boolean; property TupleList: TBoldVariableTupleList read GetTupleList; @@ -90,7 +125,27 @@ TBoldVariableTuple = class(TCollectionItem) published property BoldHandle: TBoldElementHandle read FBoldHandle write SetBoldHandle; property VariableName: String read FVariableName write SetVariableName; - property UseListElement: Boolean read fUseListElement write SetUseListElement; + property UseListElement: Boolean read fUseListElement write SetUseListElement default false; + end; + + + TBoldOclVariable = class(TBoldExternalVariable) + private + fBoldIndirectElement: TBoldIndirectElement; + fBoldElementTypeInfo: TBoldElementTypeInfo; + function GetBoldIndirectElement: TBoldIndirectElement; + protected + function GetValue: TBoldElement; override; + function GetValueType: TBoldElementTypeInfo; override; + public + constructor Create(const aName: string; aValue: TBoldElement{; aOwnsValue: boolean = false}); overload; + constructor CreateWithTypeInfo(const aName: string; AValue: TBoldElement; aBoldElementTypeInfo: TBoldElementTypeInfo); + constructor CreateFromIndirectElement(const aName: string; aBoldIndirectElement: TBoldIndirectElement); + constructor CreateStringVariable(const aName: string; const aValue: string); + constructor CreateDateVariable(const aName: string; const aValue: TDate); + constructor CreateDateTimeVariable(const aName: string; const aValue: TDateTime); + destructor Destroy; override; + property BoldIndirectElement: TBoldIndirectElement read GetBoldIndirectElement; end; implementation @@ -98,27 +153,99 @@ implementation uses SysUtils, BoldDefs, + BoldSystem, BoldRootedHandles, - HandlesConst, - BoldAbstractListHandle; + BoldAbstractListHandle, + BoldAttributes, + BoldUtils; { TBoldOclVariables } +function TBoldOclVariables.AddVariable(aVariableName: string; + aBoldHandle: TBoldElementHandle; aUseListElement: boolean): TBoldVariableTuple; +begin + result := Variables.VariableByName[aVariableName]; + if not Assigned(result) then + begin + result := Variables.Add as TBoldVariableTuple; + result.VariableName := aVariableName; + end; + result.BoldHandle := aBoldHandle; + result.UseListElement := aUseListElement; +end; + +procedure TBoldOclVariables.AddVariables(aBoldOclVariables: TBoldOclVariables); +var + i: integer; + lBoldVariableTuple: TBoldVariableTuple; +begin + for I := 0 to aBoldOclVariables.Variables.Count - 1 do + begin + lBoldVariableTuple := Variables.VariableByName[aBoldOclVariables.Variables[i].VariableName]; + if Assigned(lBoldVariableTuple) then + lBoldVariableTuple.Assign(aBoldOclVariables.Variables[i]) + else + Variables.Add.Assign(aBoldOclVariables.Variables[i]); + end; +end; + constructor TBoldOclVariables.create(Owner: TComponent); begin inherited; fVariableList := nil; fVariableTupleList := TBoldVariableTupleList.Create(self); + fSubscriber := TBoldPassthroughSubscriber.Create(_Receive); + PlaceSubscriptions; end; -destructor TBoldOclVariables.Destroy; +destructor TBoldOclVariables.destroy; begin FreePublisher; FreeAndNil(fVariableList); FreeAndNil(fVariableTupleList); + FreeAndNil(fSubscriber); inherited; end; +function TBoldOclVariables.FindVariableByName( + const aVariableName: string): TBoldExternalVariable; +var + i: integer; +begin + for I := 0 to VariableList.Count - 1 do + begin + if CompareText(VariableList.Variables[i].Name, aVariableName) = 0 then + begin + result := VariableList.Variables[i]; + exit; + end; + end; + result := nil; +end; + +function TBoldOclVariables.GetGlobalSystemHandle: TBoldAbstractSystemhandle; +begin + result := fGlobalSystemHandle +end; + +function TBoldOclVariables.GetVariableFromHandle( + AHandle: TBoldElementHandle): TBoldExternalVariable; +var + i: integer; + vTuple: TBoldVariableTuple; +begin + for i := 0 to Variables.count - 1 do + begin + vTuple := Variables[i]; + if vTuple.BoldHandle = AHandle then + begin + result := VariableList[i]; + exit; + end; + end; + result := nil; +end; + function TBoldOclVariables.GetVariableList: TBoldExternalVariableList; var i: integer; @@ -145,6 +272,18 @@ function TBoldOclVariables.GetVariableList: TBoldExternalVariableList; result := fVariableList; end; +function TBoldOclVariables.GetVariableValue( + const aVariableName: string): TBoldElement; +var + lVariable: TBoldExternalVariable; +begin + lVariable := FindVariableByName(aVariableName); + if Assigned(lVariable) then + result := lVariable.Value + else + result := nil; +end; + function TBoldOclVariables.LinksToHandle(Handle: TBoldElementHandle): Boolean; var i: integer; @@ -154,6 +293,73 @@ function TBoldOclVariables.LinksToHandle(Handle: TBoldElementHandle): Boolean; result := result or Variables[i].linksToHandle(Handle); end; +procedure TBoldOclVariables.Loaded; +begin + inherited Loaded; + PlaceSubscriptions; +end; + +procedure TBoldOclVariables.PlaceSubscriptions; +begin + fSubscriber.CancelAllSubscriptions; + RegisterVariables; + SubscribeToHandles(fSubscriber); +end; + +procedure TBoldOclVariables.RegisterVariables; +var + vEvaluator: TBoldEvaluator; + vVariable: TBoldExternalVariable; + vTuple: TBoldVariableTuple; + vTypeInfo: TBoldElementTypeInfo; +begin + if (VariableList.Count > 0) and Assigned(GlobalSystemHandle) and Assigned(GlobalSystemHandle.SystemTypeInfoHandle) and GlobalSystemHandle.SystemTypeInfoHandle.IsSystemTypeInfoAvailable then + begin + if not (csDesigning in ComponentState) then + begin + if GlobalSystemHandle.Active then + begin + vEvaluator := GlobalSystemHandle.System.Evaluator; + if Assigned(vEvaluator) then + for vVariable in VariableList do + begin + Assert(not Assigned(vVariable.Evaluator) or (vVariable.Evaluator = vEvaluator)); + vEvaluator.DefineVariable(vVariable.Name, vVariable); + end; + end + else + begin + for vVariable in VariableList do + begin + if Assigned(vVariable.Evaluator) then + vVariable.Evaluator := nil; + end; + end; + end; + // register into type/meta evaluator + vEvaluator := GlobalSystemHandle.BoldType.Evaluator; + for vTuple in Variables do + if Assigned(vTuple.BoldHandle) then + begin + if vTuple.EffectiveUseListElement then + vTypeInfo := TBoldAbstractListHandle(vTuple.BoldHandle).StaticListType + else + vTypeInfo := vTuple.BoldHandle.StaticBoldType; + vEvaluator.DefineVariable(vTuple.VariableName, nil, vTypeInfo, false, false); + end; + end; +end; + +procedure TBoldOclVariables.SetGlobalSystemHandle( + aSystemHandle: TBoldAbstractSystemhandle); +begin + if aSystemHandle <> fGlobalSystemHandle then + begin + fGlobalSystemHandle := aSystemHandle; + PlaceSubscriptions; + end; +end; + procedure TBoldOclVariables.SetVariableTupleList( const Value: TBoldVariableTupleList); begin @@ -163,12 +369,57 @@ procedure TBoldOclVariables.SetVariableTupleList( procedure TBoldOclVariables.SubscribeToHandles( Subscriber: TBoldSubscriber); var - i: integer; + vTuple: TBoldVariableTuple; begin - if assigned(Subscriber) then - for i := 0 to Variables.Count-1 do - if assigned(Variables[i].boldHandle) then - Variables[i].BoldHandle.AddSubscription(Subscriber, beValueIdentityChanged, breResubscribe); + if self.fSubscriber <> Subscriber then + self.AddSubscription(Subscriber, beDestroying, breReSubscribe); + if Assigned(GlobalSystemHandle) then + begin + GlobalSystemHandle.AddSmallSubscription(Subscriber, [beValueIdentityChanged, beDestroying], beValueIdentityChanged); + if GlobalSystemHandle.Active then + GlobalSystemHandle.System.AddSmallSubscription(Subscriber, [beDestroying], beDestroying); + end; + for vTuple in Variables do + if assigned(vTuple.boldHandle) then + vTuple.BoldHandle.AddSubscription(Subscriber, beValueIdentityChanged, breResubscribe); +end; + +procedure TBoldOclVariables.SubscribeToHandle(AHandle: TBoldElementHandle); +var + vVariable: TBoldExternalVariable; +begin + if (not (csDestroying in ComponentState) and ((Owner = nil) or not (csDestroying in TComponent(Owner).ComponentState))) + and (VariableList.Count > 0) and Assigned(GlobalSystemHandle) and GlobalSystemHandle.Active then // Assigned(GlobalSystemHandle.SystemTypeInfoHandle) and GlobalSystemHandle.SystemTypeInfoHandle.IsSystemTypeInfoAvailable then + begin + GlobalSystemHandle.System.AddSmallSubscription(fSubscriber, [beDestroying], beDestroying); + vVariable := GetVariableFromHandle(AHandle); + if Assigned(vVariable) then + begin + AHandle.AddSubscription(fSubscriber, beDestroying, breReSubscribe); + AHandle.AddSubscription(fSubscriber, beValueIdentityChanged, breResubscribe); + GlobalSystemHandle.System.Evaluator.DefineVariable(vVariable.Name, vVariable); + end; + end; +end; + +procedure TBoldOclVariables.SubscribeToHandles(Subscriber: TBoldSubscriber; + Expression: string); +var + vVariable: TBoldVariableTuple; +begin + if self.fSubscriber <> Subscriber then + self.AddSubscription(Subscriber, beDestroying, breReSubscribe); + if Assigned(GlobalSystemHandle) then + begin + GlobalSystemHandle.AddSmallSubscription(Subscriber, [beValueIdentityChanged, beDestroying], beValueIdentityChanged); + if GlobalSystemHandle.Active then + GlobalSystemHandle.System.AddSmallSubscription(Subscriber, [beDestroying], beDestroying); + end; + if Assigned(Subscriber) then + for vVariable in Variables do + if Assigned(vVariable.BoldHandle) then + if BoldCaseIndependentPos(vVariable.VariableName, Expression) > 0 then + vVariable.BoldHandle.AddSubscription(Subscriber, beValueIdentityChanged, breResubscribe); end; procedure TBoldOclVariables.VariablesChanged; @@ -177,6 +428,44 @@ procedure TBoldOclVariables.VariablesChanged; SendEvent(Self, beValueChanged); end; +procedure TBoldOclVariables._Receive(Originator: TObject; + OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent); +var + vVariable: TBoldExternalVariable; + i: integer; +begin + if (Originator = fGlobalSystemHandle) then + begin + case OriginalEvent of + beDestroying: + begin + GlobalSystemHandle := nil; + fSubscriber.CancelAllSubscriptions; + end; + beValueIdentityChanged: + begin + RegisterVariables; + end; + end; + end + else + if (Originator is TBoldSystem)then + begin + if OriginalEvent = beDestroying then + begin + FreeAndNil(fVariableList); + SendEvent(Self, beValueChanged); + end + else + RegisterVariables; + end + else + if Originator is TBoldElementHandle then + begin + SubscribeToHandle(TBoldElementHandle(Originator)); + end; +end; + { TBoldVariableTupleList } constructor TBoldVariableTupleList.create(aOwningDefinition: TBoldOclVariables); @@ -185,6 +474,11 @@ constructor TBoldVariableTupleList.create(aOwningDefinition: TBoldOclVariables); fOwningDefinition := aOwningDefinition; end; +function TBoldVariableTupleList.GetEnumerator: TBoldVariableTupleListEnumerator; +begin + result := TBoldVariableTupleListEnumerator.Create(self); +end; + function TBoldVariableTupleList.GetItems( Index: integer): TBoldVariableTuple; begin @@ -202,18 +496,32 @@ function TBoldVariableTupleList.GetUniqueName: String; begin i := 1; repeat - result := 'Variable' + IntToStr(i); // do not localize + result := 'Variable'+IntToStr(i); Inc(i); until NameIsUnique(result); end; +function TBoldVariableTupleList.GetVariableByName( + const aName: string): TBoldVariableTuple; +var + i: integer; +begin + for I := 0 to Count - 1 do + if Items[i].VariableName = aName then + begin + result := Items[i]; + exit; + end; + result := nil; +end; + function TBoldVariableTupleList.NameIsUnique(Name: String): Boolean; var i: integer; begin result := true; for i := 0 to Count-1 do - if AnsiCompareStr(Name, Items[i].VariableName) = 0 then + if CompareText(Name, Items[i].VariableName) = 0 then begin result := false; exit; @@ -226,7 +534,7 @@ function TBoldVariableTupleList.NameIsValid(Name: String): Boolean; begin result := true; for i := 1 to length(name) do - if not (name[i] in ['A'..'Z', 'a'..'z', '_', '0'..'9']) then + if not CharInSet(name[i], ['A'..'Z', 'a'..'z', '_', '0'..'9']) then begin result := false; exit; @@ -263,7 +571,7 @@ constructor TBoldVariableTuple.Create(Collection: TCollection); fBoldHandleSubscriber := TBoldPassthroughSubscriber.Create(_ReceiveHandleEvent); end; -destructor TBoldVariableTuple.Destroy; +destructor TBoldVariableTuple.destroy; begin FreeAndNil(fBoldHandleSubscriber); inherited; @@ -275,9 +583,9 @@ function TBoldVariableTuple.GetDisplayName: string; if assigned(BoldHandle) then Result := result + ': ' + BoldHandle.Name else - result := result + ': Not Connected'; // do not localize + result := result + ': Not Connected'; if EffectiveUseListElement then - result := result + ' (list)'; // do not localize + result := result + ' (list)'; end; function TBoldVariableTuple.GetEffectiveUseListElement: Boolean; @@ -302,7 +610,7 @@ procedure TBoldVariableTuple.SetBoldHandle(const Value: TBoldElementHandle); if value <> fBoldHandle then begin if assigned(value) and Value.RefersToComponent(TupleList.OwningDefinition) then - raise EBold.CreateFmt(sCircularReference, [classname, TupleList.OwningDefinition.name, value.name]); + raise EBold.CreateFmt('%s.SetBoldHandle: %s can not be linked to %s. Circular reference', [classname, TupleList.OwningDefinition.name, value.name]); FBoldHandle := Value; fBoldHandleSubscriber.CancelAllSubscriptions; if assigned(value) then @@ -321,14 +629,17 @@ procedure TBoldVariableTuple.SetUseListElement(const Value: Boolean); end; procedure TBoldVariableTuple.SetVariableName(const Value: String); +var + vNewName: string; begin - if FVariableName <> Value then + if CompareText(FVariableName, Value) <> 0 then begin - if not (Collection as TBoldVariableTupleList).NameIsUnique(Value) then - raise EBold.CreateFmt(sNameNotUnique, [Value]); - if not (Collection as TBoldVariableTupleList).NameIsValid(Value) then - raise EBold.Create(sIllegalCharsInName); - FVariableName := Value; + vNewName := LowerCase(Copy(Value,1,1)) + Copy(Value,2,MaxInt); + if not (Collection as TBoldVariableTupleList).NameIsUnique(vNewName) then + raise EBold.CreateFmt('Can''t rename variable to "%s", name already exists', [vNewName]); + if not (Collection as TBoldVariableTupleList).NameIsValid(vNewName) then + raise EBold.Create('Invalid variable name, only alphanum characters and underscore valid'); + FVariableName := vNewName; Changed; end; end; @@ -364,7 +675,7 @@ constructor TBoldHandleBasedExternalVariable.Create(Name: String; destructor TBoldHandleBasedExternalVariable.Destroy; begin FreeAndNil(fHandleSubscriber); - inherited; + inherited; end; function TBoldHandleBasedExternalVariable.GetValue: TBoldElement; @@ -393,4 +704,112 @@ function TBoldHandleBasedExternalVariable.GetValueType: TBoldElementTypeInfo; result := nil; end; +procedure TBoldHandleBasedExternalVariable.SetHandle( + const Value: TBoldElementHandle); +begin + if fHandle = Value then + exit; + fHandleSubscriber.CancelAllSubscriptions; + fHandle := Value; + if assigned(fHandle) then + fHandle.AddSmallSubscription(fHandleSubscriber, [beDestroying], beDestroying); +end; + +{ TBoldOclVariable } + +constructor TBoldOclVariable.Create(const aName: string; + aValue: TBoldElement{; aOwnsValue: boolean = false}); +begin + inherited Create(aName); +{ if aOwnsValue then + BoldIndirectElement.SetOwnedValue(aValue) + else +} + BoldIndirectElement.SetReferenceValue(aValue); +end; + +constructor TBoldOclVariable.CreateFromIndirectElement(const aName: string; + aBoldIndirectElement: TBoldIndirectElement); +begin + inherited Create(aName); + aBoldIndirectElement.TransferValue(BoldIndirectElement); +end; + +constructor TBoldOclVariable.CreateWithTypeInfo(const aName: string; AValue: TBoldElement; + aBoldElementTypeInfo: TBoldElementTypeInfo); +begin + inherited Create(aName); + BoldIndirectElement.SetOwnedValue(AValue); + fBoldElementTypeInfo := aBoldElementTypeInfo; +end; + +constructor TBoldOclVariable.CreateStringVariable(const aName, aValue: string); +var + vString: TBAString; +begin + inherited Create(aName); + vString := TBAString.Create; + vString.AsString := aValue; + BoldIndirectElement.SetOwnedValue(vString); +end; + +constructor TBoldOclVariable.CreateDateTimeVariable(const aName: string; + const aValue: TDateTime); +var + vDateTime: TBADateTime; +begin + inherited Create(aName); + vDateTime := TBADateTime.Create; + vDateTime.AsDateTime := aValue; + BoldIndirectElement.SetOwnedValue(vDateTime); +end; + +constructor TBoldOclVariable.CreateDateVariable(const aName: string; + const aValue: TDate); +var + vDate: TBADate; +begin + inherited Create(aName); + vDate := TBADate.Create; + vDate.AsDate := aValue; + BoldIndirectElement.SetOwnedValue(vDate); +end; + +destructor TBoldOclVariable.Destroy; +begin + FreeAndNil(fBoldIndirectElement); + inherited; +end; + +function TBoldOclVariable.GetBoldIndirectElement: TBoldIndirectElement; +begin + if not Assigned(fBoldIndirectElement) then + begin + fBoldIndirectElement := TBoldIndirectElement.Create; + end; + result := fBoldIndirectElement; +end; + +function TBoldOclVariable.GetValue: TBoldElement; +begin + result:= BoldIndirectElement.Value; +end; + +function TBoldOclVariable.GetValueType: TBoldElementTypeInfo; +begin + if GetValue <> nil then + result:= GetValue.BoldType + else + result := fBoldElementTypeInfo; +end; + +{ TBoldVariableTupleListEnumerator } + +function TBoldVariableTupleListEnumerator.GetCurrent: TBoldVariableTuple; +begin + result := inherited GetCurrent as TBoldVariableTuple; +end; + +initialization + end. diff --git a/Source/Handles/Core/BoldPlaceableSubscriber.pas b/Source/Handles/Core/BoldPlaceableSubscriber.pas index ef1eebe..a3b1811 100644 --- a/Source/Handles/Core/BoldPlaceableSubscriber.pas +++ b/Source/Handles/Core/BoldPlaceableSubscriber.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldPlaceableSubscriber; interface @@ -24,7 +27,7 @@ TBoldPlaceableSubscriber = class(TBoldSubscribableComponentViaBoldElem) FOnReceive: TBoldPlaceableSubcriberReceive; FOnSubscribeToElement: TBoldSubscribeToElementEvent; FHandleSubscriber: TBoldPassthroughSubscriber; - FValueSubscriber: TBoldPassthroughSubscriber; + FValueSubscriber: TBoldExtendedPassthroughSubscriber; FDelayEventsUntilPostNotify: Boolean; procedure SetBoldHandle(Value: TBoldElementHandle); procedure HandleSubscriberReceive(Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent); @@ -43,18 +46,21 @@ TBoldPlaceableSubscriber = class(TBoldSubscribableComponentViaBoldElem) property BoldHandle: TBoldElementHandle read FBoldHandle write SetBoldHandle; property OnReceive: TBoldPlaceableSubcriberReceive read FOnReceive write fOnReceive; property OnSubscribeToElement: TBoldSubscribeToElementEvent read FOnSubscribeToElement write FOnSubscribeToElement; - property DelayEventsUntilPostNotify: Boolean read FDelayEventsUntilPostNotify write SetDelayEventsUntilPostNotify; + property DelayEventsUntilPostNotify: Boolean read FDelayEventsUntilPostNotify write SetDelayEventsUntilPostNotify default false; end; implementation +uses + BoldRev; + {---TBoldPlaceableSubscriber---} constructor TBoldPlaceableSubscriber.Create(Owner: TComponent); begin inherited; FHandleSubscriber := TBoldPassthroughSubscriber.Create(HandleSubscriberReceive); - FValueSubscriber := TBoldPassthroughSubscriber.CreateWithExtendedReceive(ValueSubscriberReceive); + FValueSubscriber := TBoldExtendedPassthroughSubscriber.CreateWithExtendedReceive(ValueSubscriberReceive); end; destructor TBoldPlaceableSubscriber.Destroy; @@ -80,7 +86,7 @@ procedure TBoldPlaceableSubscriber.SetBoldHandle(Value: TBoldElementHandle); if Assigned(Value) then begin Value.FreeNotification(Self); - BoldHandle.AddSmallSubscription(fHandleSubscriber, [beDestroying, beValueIdentityChanged], breReEvaluate); // CHECKME + BoldHandle.AddSmallSubscription(fHandleSubscriber, [beDestroying, beValueIdentityChanged], breReEvaluate); end; HandleValueChanged; end; @@ -88,6 +94,8 @@ procedure TBoldPlaceableSubscriber.SetBoldHandle(Value: TBoldElementHandle); procedure TBoldPlaceableSubscriber.HandleSubscriberReceive(Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent); begin + if (csDestroying in ComponentState) or (Assigned(BoldHandle) and (csDestroying in BoldHandle.ComponentState)) then + exit; Receive(Originator, OriginalEvent, RequestedEvent, []); HandleValueChanged; end; @@ -114,7 +122,9 @@ procedure TBoldPlaceableSubscriber.HandleValueChanged; procedure TBoldPlaceableSubscriber.SubscribeToElement(Element: TBoldElement; Subscriber: TBoldSubscriber); begin if Assigned(FOnSubscribeToElement) then - FOnSubscribeToElement(Element, Subscriber); + FOnSubscribeToElement(Element, Subscriber) + else if Assigned(Element) then + Element.DefaultSubscribe(Subscriber); end; procedure TBoldPlaceableSubscriber.Receive(Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent; const Args: array of const); @@ -126,7 +136,7 @@ procedure TBoldPlaceableSubscriber.Receive(Originator: TObject; OriginalEvent: T procedure TBoldPlaceableSubscriber.ActOnHandleValueChanged(Sender: TObject); begin fValueSubscriber.CancelAllSubscriptions; - if assigned(BoldHandle) and assigned(BoldHandle.Value) then + if not (csDestroying in ComponentState) and assigned(BoldHandle) and not (csDestroying in BoldHandle.ComponentState) and assigned(BoldHandle.Value) then SubscribeToElement(BoldHandle.Value, fValueSubscriber); end; @@ -135,4 +145,6 @@ procedure TBoldPlaceableSubscriber.SetDelayEventsUntilPostNotify(const Value: Bo FDelayEventsUntilPostNotify := Value; end; +initialization + end. diff --git a/Source/Handles/Core/BoldRawSQLHandle.pas b/Source/Handles/Core/BoldRawSQLHandle.pas new file mode 100644 index 0000000..bfbe2e6 --- /dev/null +++ b/Source/Handles/Core/BoldRawSQLHandle.pas @@ -0,0 +1,176 @@ + +///////////////////////////////////////////////////////// +// // +// Bold for Delphi // +// Copyright (c) 2002 BoldSoft AB, Sweden // +// // +///////////////////////////////////////////////////////// + +{ Global compiler directives } +{$include bold.inc} +unit BoldRawSQLHandle; + +interface + +uses + Classes, + Db, + BoldElements, + BoldHandles, + BoldSystem; + +type + { forward declarations } + TBoldRawSQLHandle = class; + + { TBoldRawSQLHandle } + TBoldRawSQLHandle = class(TBoldNonSystemHandle) + private + fBoldObjectClass: TBoldObjectClass; + fSQL: string; + fClassExpressionName: string; + fObjectList: TBoldObjectlist; + fListMode: TBoldListDupMode; + fClearBeforeExecute: Boolean; + fParams: TParams; + fMaxAnswers: integer; + fOffset: integer; + procedure SetClassExpressionName(const Value: string); + procedure SetListMode(const Value: TBoldListDupMode); + procedure SetParams(const Value: TParams); + protected + { Protected declarations } + function GetStaticBoldType: TBoldElementTypeInfo; override; + function GetValue: TBoldElement; override; + procedure EnsureList(RaiseException: Boolean); + public + { Public declarations } + constructor Create(Owner: TComponent); override; + destructor Destroy; override; + procedure ExecuteSQL; + procedure ClearList; + published + { Published declarations } + property SQL: string read fSQL write fSQL; + property ListMode: TBoldListDupMode read FListMode write SetListMode default bldmMerge; + property ClassExpressionName: string read fClassExpressionName write SetClassExpressionName; + property ClearBeforeExecute: Boolean read fClearBeforeExecute write fClearBeforeExecute default true; + property MaxAnswers: integer read fMaxAnswers write fMaxAnswers default -1; + property Offset: integer read fOffset write fOffset default -1; + property Params: TParams read fParams write SetParams; + end; + +implementation + +uses + SysUtils, + BoldDefs, + BoldSubscription, + BoldSystemRT; + +constructor TBoldRawSQLHandle.Create(Owner: TComponent); +begin + inherited; + fClearBeforeExecute := true; + fListMode := bldmMerge; + fParams := TParams.Create(self); + fMaxAnswers := -1; + fOffset := -1; +end; + +destructor TBoldRawSQLHandle.Destroy; +begin + FreePublisher; + FreeAndNil(fObjectList); + FreeAndNil(fParams); + inherited; +end; + +function TBoldRawSQLHandle.GetStaticBoldType: TBoldElementTypeInfo; +begin + if assigned(StaticSystemTypeInfo) then + Result := StaticSystemTypeInfo.ClassTypeInfoByExpressionName[fClassExpressionName] + else + result := nil; +end; + +procedure TBoldRawSQLHandle.ExecuteSQL; +begin + if not assigned(StaticSystemHandle) then + raise EBold.CreateFmt('%s.ExecuteSQL: %s has no SystemHandle', [classname, name]); + if not StaticSystemHandle.Active then + raise EBold.CreateFmt('%s.ExecuteSQL: Systemhandle is not active', [classname]); + + if ClearBeforeExecute then + ClearList; + EnsureList(true); + StaticSystemHandle.System.GetAllInClassWithRawSQL(fObjectList, fBoldObjectClass, SQL, Params, MaxAnswers, Offset); +end; + +procedure TBoldRawSQLHandle.ClearList; +begin + if assigned(fObjectList) then + fObjectlist.Clear; +end; + +function TBoldRawSQLHandle.GetValue: TBoldElement; +begin + EnsureList(false); + result := fObjectList; +end; + +procedure TBoldRawSQLHandle.SetClassExpressionName(const Value: string); +begin + if fClassExpressionName <> Value then + begin + fClassExpressionName := Value; + FreeAndNil(fObjectList); + SendEvent(Self, beValueIdentityChanged); + end; +end; + +procedure TBoldRawSQLHandle.EnsureList(RaiseException: Boolean); +var + ElementTypeInfo: TBoldElementTypeInfo; + ClassTypeInfo: TBoldClassTypeInfo; + ListTypeInfo: TBoldListTypeInfo; +begin + if not assigned(fObjectList) then + begin + + if not assigned(StaticSystemHandle) and RaiseException then + raise EBold.CreateFmt('%s.EnsureList: %s not connected to a SystemHandle', [ClassName, name]); + + ElementTypeInfo := StaticBoldType; + + if ElementTypeInfo is TBoldClassTypeInfo then + begin + ClassTypeInfo := ElementTypeInfo as TBoldClassTypeInfo; + fBoldObjectClass := TBoldObjectClass(ClassTypeInfo.ObjectClass); + ListTypeInfo := StaticSystemTypeInfo.ListTypeInfoByElement[ClassTypeInfo]; + fObjectList := TBoldMemberFactory.CreateMemberFromBoldType(ListTypeInfo) as TBoldObjectList; + fObjectList.DuplicateMode := ListMode; + end + else + if raiseException then + raise EBold.CreateFmt('%s.EnsureList: Unable to create list (%s), cant find valid type', [ClassName, Name]); + end; +end; + +procedure TBoldRawSQLHandle.SetListMode(const Value: TBoldListDupMode); +begin + if FListMode <> value then + begin + FListMode := Value; + if assigned(fObjectList) then + fObjectList.DuplicateMode := value; + end; +end; + +procedure TBoldRawSQLHandle.SetParams(const Value: TParams); +begin + Params.Assign(Value); +end; + +initialization +end. diff --git a/Source/Handles/Core/BoldReferenceHandle.pas b/Source/Handles/Core/BoldReferenceHandle.pas index eda6eef..fe47eec 100644 --- a/Source/Handles/Core/BoldReferenceHandle.pas +++ b/Source/Handles/Core/BoldReferenceHandle.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldReferenceHandle; interface @@ -20,12 +23,15 @@ TBoldReferenceHandle = class(TBoldNonSystemHandle) fValueSubscriber: TBoldPassthroughSubscriber; FOnValueDestroyed: TNotifyEvent; FOnObjectDeleted: TNotifyEvent; - procedure SetValue(NewValue: TBoldElement); procedure SetStaticValueTypeName(Value: string); procedure _Receive(Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent); protected function GetValue: TBoldElement; override; function GetStaticBoldType: TBoldElementTypeInfo; override; + function GetStaticSystemHandle: TBoldAbstractSystemHandle; override; + procedure SetValue(NewValue: TBoldElement); override; + function GetCanSetValue: boolean; override; + procedure DoAssign(Source: TPersistent); override; public constructor Create(Owner: TComponent); override; destructor Destroy; override; @@ -40,7 +46,9 @@ implementation uses SysUtils, - BoldSystemRT; + BoldSystemRT, + BoldSystem, + BoldRev; const breValueDestroyed = 42; @@ -61,6 +69,23 @@ destructor TBoldReferenceHandle.Destroy; inherited; end; +procedure TBoldReferenceHandle.DoAssign(Source: TPersistent); +begin + inherited; + if Source is TBoldReferenceHandle then with TBoldReferenceHandle(Source) do + begin + self.StaticValueTypeName := StaticValueTypeName; + // do we want to assign these events ? + self.OnObjectDeleted := OnObjectDeleted; + self.OnValueDestroyed := OnValueDestroyed; + end; +end; + +function TBoldReferenceHandle.GetCanSetValue: boolean; +begin + result := true; +end; + function TBoldReferenceHandle.GetStaticBoldType: TBoldElementTypeInfo; begin if Assigned(StaticSystemTypeInfo) then @@ -69,6 +94,25 @@ function TBoldReferenceHandle.GetStaticBoldType: TBoldElementTypeInfo; Result := nil; end; +function TBoldReferenceHandle.GetStaticSystemHandle: TBoldAbstractSystemHandle; +var + System: TBoldSystem; +begin + result := inherited GetStaticSystemHandle; + if Assigned(result) or not Assigned(fValue) then + exit; + System := nil; + if fValue is TBoldSystem then + System := TBoldSystem(fValue) + else + if fValue is TBoldObject then + System := TBoldObject(fValue).BoldSystem + else + if fValue is TBoldMember then + System := TBoldMember(fValue).BoldSystem; + result := TBoldAbstractSystemHandle.FindSystemHandleForSystem(System); +end; + function TBoldReferenceHandle.GetValue: TBoldElement; begin result := fValue; @@ -89,10 +133,11 @@ procedure TBoldReferenceHandle.SetValue(NewValue: TBoldElement); begin fValue := NewValue; fValueSubscriber.CancelAllSubscriptions; - if Assigned(fValue) then + if Assigned(fValue) and (not (fValue is TBoldSystem)) then begin fValue.AddSmallSubscription(fValueSubscriber, [beDestroying], breValueDestroyed); - fValue.AddSmallSubscription(fValueSubscriber, [beObjectDeleted], breObjectDeleted); + if (fValue is TBoldObject) then + fValue.AddSmallSubscription(fValueSubscriber, [beObjectDeleted], breObjectDeleted) end; SendEvent(Self, beValueIdentityChanged); end; @@ -117,4 +162,6 @@ procedure TBoldReferenceHandle._Receive(Originator: TObject; end; end; +initialization + end. diff --git a/Source/Handles/Core/BoldRootedHandles.pas b/Source/Handles/Core/BoldRootedHandles.pas index c93c11c..8296b59 100644 --- a/Source/Handles/Core/BoldRootedHandles.pas +++ b/Source/Handles/Core/BoldRootedHandles.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldRootedHandles; interface @@ -23,11 +26,12 @@ TBoldRootedHandle = class(TBoldNonSystemHandle) fInternalRootHandleSubscriber: TBoldPassthroughSubscriber; fValueSubscriber: TBoldPassthroughSubscriber; fDeriver: TBoldDeriver; + FOnBeginValueIdentityChanged: TNotifyEvent; + FOnEndValueIdentityChanged: TNotifyEvent; fResultElement: TBoldIndirectElement; fRootTypeName: String; - procedure SetRootTypeName(Value: string); - procedure ReadDesignTimeContext(Reader: TReader); // compatibility - procedure ReadDesignTimeHandle(Reader: TReader); // compatibility + procedure ReadDesignTimeContext(Reader: TReader); + procedure ReadDesignTimeHandle(Reader: TReader); procedure _ReceiveFromRoot(Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent); procedure _ReceiveFromValue(Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent); procedure SetInternalRootHandle(Value: TBoldElementHandle); @@ -35,11 +39,16 @@ TBoldRootedHandle = class(TBoldNonSystemHandle) procedure _NotifyOutOfDate; function GetSubscribe: Boolean; function GetIsDeriving: Boolean; + function IsRootTypeNameStored: Boolean; + function GetRootTypeName: string; + function GetIsCurrent: boolean; protected procedure SubscribeToValue; procedure EffectiveRootValueChanged; virtual; function EffectiveRootValue: TBoldElement; + function GetStaticSystemHandle: TBoldAbstractSystemHandle; override; function GetStaticSystemTypeInfo: TBoldSystemTypeInfo; override; + procedure SetRootTypeName(Value: string); virtual; procedure Loaded; override; procedure SetEnabled(Value: Boolean); virtual; procedure SetSubscribe(Value: Boolean); virtual; @@ -52,7 +61,9 @@ TBoldRootedHandle = class(TBoldNonSystemHandle) function GetStaticRootType: TBoldElementTypeInfo; procedure ValueIdentityChanged; function GetRootHandle: TBoldElementHandle; virtual; + procedure InternalValueIdentityChanged; virtual; procedure SetRootHandle(const Value: TBoldElementHandle); virtual; + procedure DoAssign(Source: TPersistent); override; property InternalRootHandle: TBoldElementHandle read fInternalRootHandle write SetInternalRootHandle; property IsDeriving: Boolean read GetIsDeriving; public @@ -63,18 +74,24 @@ TBoldRootedHandle = class(TBoldNonSystemHandle) function IsRootLinkedTo(Handle: TBoldElementHandle): Boolean; function RefersToComponent(Component: TBoldSubscribableComponent): Boolean; override; property StaticRootType: TBoldElementTypeInfo read GetStaticRootType; + function IsStaticSystemHandleStored: boolean; override; + property IsCurrent: boolean read GetIsCurrent; published property RootHandle: TBoldElementHandle read GetRootHandle write SetRootHandle; property Enabled: Boolean read FEnabled write SetEnabled default True; - property RootTypeName: string read fRootTypeName write SetRootTypeName; + property RootTypeName: string read GetRootTypeName write SetRootTypeName stored IsRootTypeNameStored; + property OnBeginValueIdentityChanged: TNotifyEvent read + FOnBeginValueIdentityChanged write FOnBeginValueIdentityChanged; + property OnEndValueIdentityChanged: TNotifyEvent read + FOnEndValueIdentityChanged write FOnEndValueIdentityChanged; end; implementation uses + SysUtils, BoldDefs, - HandlesConst, BoldEnvironment; const @@ -82,6 +99,7 @@ implementation breValueIdentityChanged = 43; {---TBoldRootedHandle---} + constructor TBoldRootedHandle.Create(Owner: TComponent); begin inherited; @@ -96,6 +114,17 @@ constructor TBoldRootedHandle.Create(Owner: TComponent); fDeriver.OnDeriveAndSubscribe := DeriveAndSubscribe; end; +procedure TBoldRootedHandle.DoAssign(Source: TPersistent); +begin + inherited; + if Source is TBoldRootedHandle then with TBoldRootedHandle(Source) do + begin + self.RootHandle := RootHandle; + self.RootTypeName := RootTypeName; + self.Enabled := Enabled; + end; +end; + procedure TBoldRootedHandle.Loaded; begin inherited Loaded; @@ -110,6 +139,20 @@ procedure TBoldRootedHandle.Loaded; end; end; +function TBoldRootedHandle.GetStaticSystemHandle: TBoldAbstractSystemHandle; +begin + if (RootHandle is TBoldNonSystemHandle) then + Result := TBoldNonSystemHandle(RootHandle).StaticSystemHandle + else + if (RootHandle is TBoldAbstractSystemHandle) then + Result := RootHandle as TBoldAbstractSystemHandle + else + if Assigned(RootHandle) then + Result := nil + else + Result := inherited GetStaticSystemHandle; +end; + function TBoldRootedHandle.GetStaticSystemTypeInfo: TBoldSystemTypeInfo; begin if Assigned(InternalRootHandle) then @@ -120,9 +163,8 @@ function TBoldRootedHandle.GetStaticSystemTypeInfo: TBoldSystemTypeInfo; procedure TBoldRootedHandle.EffectiveRootValueChanged; begin - Assert (Assigned(fDeriver)); + Assert(Assigned(fDeriver)); MarkSubscriptionOutOfdate; - // ValueIdentityChanged; // fix for unknown bug.. JaNo will look at this. end; procedure TBoldRootedHandle.SetInternalRootHandle(Value: TBoldElementHandle); @@ -131,7 +173,7 @@ procedure TBoldRootedHandle.SetInternalRootHandle(Value: TBoldElementHandle); begin if (Value = self) or ((Value is TBoldRootedHandle) and TBoldRootedHandle(Value).IsRootLinkedTo(Self)) then - raise EBold.CreateFmt(sInternalRootHandle_CircRef, [ClassName]); + raise EBold.CreateFmt('%s.SetInternalRootHandle: Circular reference', [ClassName]); fInternalRootHandleSubscriber.CancelAllSubscriptions; fInternalRootHandle := Value; if Assigned(InternalRootHandle) then @@ -150,7 +192,7 @@ procedure TBoldRootedHandle.SetEnabled(Value: Boolean); else if Value <> FEnabled then begin FEnabled := Value; - SendEvent(self, beValueIdentityChanged); // can't call ValueIdentityChanged. We should send even when changing to not enabled + SendEvent(self, beValueIdentityChanged); if not Enabled then MarkSubscriptionOutOfDate; end; @@ -177,7 +219,7 @@ function TBoldRootedHandle.EffectiveRootValue: TBoldElement; if Assigned(InternalRootHandle) then Result := InternalRootHandle.Value else - Result:= nil; + Result := nil; end; procedure TBoldRootedHandle._ReceiveFromRoot(Originator: TObject; @@ -232,20 +274,25 @@ function TBoldRootedHandle.GetSubscribe: Boolean; function TBoldRootedHandle.GetStaticRootType: TBoldElementTypeInfo; begin + Result := nil; if assigned(InternalRootHandle) then result := InternalRootHandle.StaticBoldType - else if Assigned(StaticSystemTypeInfo) then - Result := StaticSystemTypeInfo.ElementTypeInfoByExpressionName[RootTypeName] else - Result := nil; + if Assigned(StaticSystemTypeInfo) then + begin + if (RootTypeName <> '') then + Result := StaticSystemTypeInfo.ElementTypeInfoByExpressionName[RootTypeName] + else + Result := TBoldAbstractSystemHandle.DefaultBoldSystemTypeInfo; + end; end; procedure TBoldRootedHandle.DefineProperties(Filer: TFiler); begin inherited; - Filer.DefineProperty('TrackBold', ReadTrackBold, nil, False); // do not localize - Filer.DefineProperty('DesignTimeContext', ReadDesignTimeContext, nil, False); // do not localize - Filer.DefineProperty('DesignTimeHandle', ReadDesignTimeHandle, nil, False); // do not localize + Filer.DefineProperty('TrackBold', ReadTrackBold, nil, False); + Filer.DefineProperty('DesignTimeContext', ReadDesignTimeContext, nil, False); + Filer.DefineProperty('DesignTimeHandle', ReadDesignTimeHandle, nil, False); end; procedure TBoldRootedHandle.ReadDesignTimeContext(Reader: TReader); @@ -279,6 +326,16 @@ function TBoldRootedHandle.IsRootLinkedTo(Handle: TBoldElementHandle): Boolean; Result := false; end; +function TBoldRootedHandle.IsRootTypeNameStored: Boolean; +begin + result := (fRootTypeName <> ''); +end; + +function TBoldRootedHandle.IsStaticSystemHandleStored: boolean; +begin + result := inherited IsStaticSystemHandleStored and not (RootHandle is TBoldAbstractSystemHandle) and not (RootHandle is TBoldNonSystemHandle); +end; + procedure TBoldRootedHandle.SetRootTypeName(Value: string); begin if Value <> RootTypeName then @@ -313,7 +370,7 @@ procedure TBoldRootedHandle.MarkOutOfDate; procedure TBoldRootedHandle.ValueIdentityChanged; begin if Enabled then - SendEvent(self, beValueIdentityChanged); + InternalValueIdentityChanged; end; function TBoldRootedHandle.GetRootHandle: TBoldElementHandle; @@ -321,16 +378,51 @@ function TBoldRootedHandle.GetRootHandle: TBoldElementHandle; result := InternalRootHandle; end; +function TBoldRootedHandle.GetRootTypeName: string; +begin + result := fRootTypeName; + if (result = '') then + begin + if Assigned(RootHandle) then + begin + if Assigned(RootHandle.BoldType) then + result := RootHandle.BoldType.AsString + end + else + if Assigned(StaticSystemTypeInfo) then + result := StaticSystemTypeInfo.AsString + end; +end; + procedure TBoldRootedHandle.SetRootHandle(const Value: TBoldElementHandle); begin InternalRootHandle := value; end; +function TBoldRootedHandle.GetIsCurrent: boolean; +begin + Result := fDeriver.IsCurrent; +end; + function TBoldRootedHandle.GetIsDeriving: Boolean; begin Result := fDeriver.IsDeriving; end; +procedure TBoldRootedHandle.InternalValueIdentityChanged; +begin + if Assigned(FOnBeginValueIdentityChanged) then begin + FOnBeginValueIdentityChanged(Self); + end; + try + SendEvent(self, beValueIdentityChanged); + finally + if Assigned(FOnEndValueIdentityChanged) then begin + FOnEndValueIdentityChanged(Self); + end; + end; +end; + function TBoldRootedHandle.RefersToComponent(Component: TBoldSubscribableComponent): Boolean; begin result := inherited RefersToComponent(Component); @@ -338,4 +430,6 @@ function TBoldRootedHandle.RefersToComponent(Component: TBoldSubscribableCompone result := IsRootLinkedTo(Component as TBoldElementHandle); end; +initialization + end. diff --git a/Source/Handles/Core/BoldSQLHandle.pas b/Source/Handles/Core/BoldSQLHandle.pas index fdfef1b..bedb0f1 100644 --- a/Source/Handles/Core/BoldSQLHandle.pas +++ b/Source/Handles/Core/BoldSQLHandle.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldSQLHandle; interface @@ -35,6 +38,7 @@ TBoldSQLHandle = class(TBoldNonSystemHandle) function GetStaticBoldType: TBoldElementTypeInfo; override; function GetValue: TBoldElement; override; procedure EnsureList(RaiseException: Boolean); + procedure DoAssign(Source: TPersistent); override; public { Public declarations } constructor Create(Owner: TComponent); override; @@ -59,7 +63,6 @@ implementation uses SysUtils, BoldDefs, - HandlesConst, BoldSubscription, BoldSystemRT; @@ -93,9 +96,9 @@ function TBoldSQLHandle.GetStaticBoldType: TBoldElementTypeInfo; procedure TBoldSQLHandle.ExecuteSQL; begin if not assigned(StaticSystemHandle) then - raise EBold.CreateFmt(sNoSystemHandle, [classname, 'ExecuteSQL', name]); // do not localize + raise EBold.CreateFmt('%s.ExecuteSQL: %s has no SystemHandle', [classname, name]); if not StaticSystemHandle.Active then - raise EBold.CreateFmt(sSystemHandleNotActive, [classname]); + raise EBold.CreateFmt('%s.ExecuteSQL: Systemhandle is not active', [classname]); if ClearBeforeExecute then ClearList; @@ -103,6 +106,23 @@ procedure TBoldSQLHandle.ExecuteSQL; StaticSystemHandle.System.GetAllInClassWithSQL(fObjectList, fBoldObjectClass, SQLWhereClause, SQLOrderByClause, Params, JoinInheritedTables, MaxAnswers, Offset); end; +procedure TBoldSQLHandle.DoAssign(Source: TPersistent); +begin + inherited; + if Source is TBoldSQLHandle then with TBoldSQLHandle(Source) do + begin + self.SQLWhereClause := SQLWhereClause; + self.SQLOrderByClause := SQLOrderByClause; + self.ListMode := ListMode; + self.ClassExpressionName := ClassExpressionName; + self.ClearBeforeExecute := ClearBeforeExecute; + self.MaxAnswers := MaxAnswers; + self.Offset := Offset; + self.Params.Assign(Params); + self.JoinInheritedTables := JoinInheritedTables; + end; +end; + procedure TBoldSQLHandle.ClearList; begin if assigned(fObjectList) then @@ -135,7 +155,7 @@ procedure TBoldSQLHandle.EnsureList(RaiseException: Boolean); begin if not assigned(StaticSystemHandle) and RaiseException then - raise EBold.CreateFmt(sNoSystemHandle, [ClassName, 'EnsureList', name]); // do not localize + raise EBold.CreateFmt('%s.EnsureList: %s not connected to a SystemHandle', [ClassName, name]); ElementTypeInfo := StaticBoldType; @@ -149,7 +169,7 @@ procedure TBoldSQLHandle.EnsureList(RaiseException: Boolean); end else if raiseException then - raise EBold.CreateFmt(sCannotCreateListDueToInvalidType, [ClassName, Name]); + raise EBold.CreateFmt('%s.EnsureList: Unable to create list (%s), cant find valid type', [ClassName, Name]); end; end; @@ -168,4 +188,5 @@ procedure TBoldSQLHandle.SetParams(const Value: TParams); Params.Assign(Value); end; +initialization end. diff --git a/Source/Handles/Core/BoldSortedHandle.pas b/Source/Handles/Core/BoldSortedHandle.pas index 26fea4e..bd46bf7 100644 --- a/Source/Handles/Core/BoldSortedHandle.pas +++ b/Source/Handles/Core/BoldSortedHandle.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldSortedHandle; interface @@ -19,15 +22,19 @@ TBoldComparer = class(TBoldSubscribableComponentViaBoldElem) FOnCompare: TBoldElementCompare; FOnSubscribe: TBoldElementSubscribe; fOnPrepareSort: TBoldPrepareListOperation; + FOnFinishSort: TBoldPrepareListOperation; public procedure Subscribe(boldElement: TBoldElement; Subscriber: TBoldSubscriber); virtual; function Compare(Item1, Item2: TBoldElement): Integer; virtual; procedure SortList(List: TBoldList); procedure PrepareSort(List: TBoldList); + procedure FinishSort(List: TBoldList); published property OnSubscribe: TBoldElementSubscribe read FOnSubscribe write FOnSubscribe; property OnCompare: TBoldElementCompare read FOnCompare write FOnCompare; property OnPrepareSort: TBoldPrepareListOperation read fOnPrepareSort write fOnPrepareSort; + property OnFinishSort: TBoldPrepareListOperation read FOnFinishSort write + FOnFinishSort; end; { TBoldSortedHandle } @@ -45,7 +52,12 @@ TBoldSortedHandle = class(TBoldRootedHandle) implementation uses - BoldSystemRT; + SysUtils, + Classes, + BoldDefs, + BoldSystemRT, + BoldElementList; + {---TBoldComparer---} procedure TBoldComparer.Subscribe(boldElement: TBoldElement; Subscriber: TBoldSubscriber); @@ -72,6 +84,8 @@ procedure TBoldSortedHandle.DeriveAndSubscribe(DerivedObject: TObject; SourceList: TBoldList; NewList: TBoldList; begin + if csDestroying in ComponentState then + raise EBold.CreateFmt('%s.DeriveAndSubscribe: %s Handle is in csDestroying state, can not DeriveAndSubscribe.', [classname, name]); if EffectiveRootValue = nil then ResultElement.SetOwnedValue(nil) else if not Assigned(BoldComparer) then @@ -82,22 +96,30 @@ procedure TBoldSortedHandle.DeriveAndSubscribe(DerivedObject: TObject; try EffectiveRootValue.GetAsList(ValueAsListHolder); SourceList := TBoldList(ValueAsListHolder.Value); - NewList := TBoldMemberFactory.CreateMemberFromBoldType(SourceList.BoldType) as TBoldList; + if (SourceList.BoldType is TBoldListTypeInfo) and not Assigned(TBoldListTypeInfo(SourceList.BoldType).ListElementTypeInfo) then + NewList := TBoldElementList.CreateWithTypeInfo(SourceList.BoldType) + else + NewList := TBoldMemberFactory.CreateMemberFromBoldType(SourceList.BoldType) as TBoldList; NewList.DuplicateMode := bldmAllow; + if Assigned(Subscriber) then SourceList.DefaultSubscribe(Subscriber, breResubscribe); SourceList.EnsureRange(0, SourceList.Count - 1); BoldComparer.PrepareSort(SourceList); - for i := 0 to SourceList.Count - 1 do - begin - NewList.Add(SourceList[i]); - if Assigned(Subscriber) then - BoldComparer.Subscribe(SourceList[I], Subscriber); + try + for i := 0 to SourceList.Count - 1 do + begin + NewList.Add(SourceList[i]); + if Assigned(Subscriber) then + BoldComparer.Subscribe(SourceList[I], Subscriber); + end; + NewList.Sort(BoldComparer.Compare); + NewList.MakeImmutable; + ResultElement.SetOwnedValue(NewList); + finally + BoldComparer.FinishSort(NewList); end; - NewList.Sort(BoldComparer.Compare); - NewList.MakeImmutable; - ResultElement.SetOwnedValue(NewList); finally ValueAsListHolder.Free; end; @@ -139,4 +161,12 @@ procedure TBoldComparer.PrepareSort(List: TBoldList); OnPrepareSort(list); end; +procedure TBoldComparer.FinishSort(List: TBoldList); +begin + if assigned(OnFinishSort) then + OnFinishSort(list); +end; + +initialization + end. diff --git a/Source/Handles/Core/BoldSystemHandle.pas b/Source/Handles/Core/BoldSystemHandle.pas index 13ac7cc..9f37c8e 100644 --- a/Source/Handles/Core/BoldSystemHandle.pas +++ b/Source/Handles/Core/BoldSystemHandle.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldSystemHandle; interface @@ -9,7 +12,8 @@ interface BoldPersistenceHandle, BoldSubscription, BoldHandles, - BoldLockRegions; + BoldLockRegions, + BoldAbstractPersistenceHandleDB; type { Forward declaration of classes } @@ -38,6 +42,7 @@ TBoldSystemHandle = class(TBoldAbstractSystemHandle) procedure ReadTrackBold(Reader: TReader); procedure SetOnOptimisticLockingFailed(const Value: TBoldOptimisticLockingFailedEvent); procedure SetOnPreUpdate(Value: TNotifyEvent); + function GetPersistenceHandleDB: TBoldAbstractPersistenceHandleDB; protected function GetValue: TBoldElement; override; procedure Loaded; override; @@ -54,6 +59,7 @@ TBoldSystemHandle = class(TBoldAbstractSystemHandle) function RefersToComponent(Component: TBoldSubscribableComponent): Boolean; override; property Persistent: Boolean read GetPersistent; property RegionFactory: TBoldRegionFactory read fRegionFactory; + property PersistenceHandleDB: TBoldAbstractPersistenceHandleDB read GetPersistenceHandleDB; published property AutoActivate: Boolean read GetAutoActivate write SetAutoActivate default False; {$IFNDEF T2H} @@ -73,7 +79,7 @@ implementation BoldRegionDefinitions, BoldEnvironment, BoldPersistenceController, - HandlesConst; + BoldPersistenceHandlePassthrough; const brePersistenceHandleDestroying = 100; @@ -111,7 +117,7 @@ procedure TBoldSystemHandle.UpdateDatabase; if Assigned(System) then System.UpdateDatabase else - raise EBold.CreateFmt(sCannotUpdateDatebaseWithoutSystem, [ClassName, Name]); + raise EBold.CreateFmt('%s.UpdateDatabase (%s) cannot be invoked without a system', [ClassName, Name]); end; function TBoldSystemHandle.GetSystem: TBoldSystem; @@ -124,7 +130,6 @@ procedure TBoldSystemHandle.SetAutoActivate(Value: Boolean); if Value <> fAutoActivate then begin fAutoActivate := Value; - // During read AutoActivate means Activate! if (csReading in ComponentState) and not (csDesigning in ComponentState) then Active := AutoActivate; @@ -139,8 +144,8 @@ function TBoldSystemHandle.GetAutoActivate: Boolean; procedure TBoldSystemHandle.SetActive(Value: Boolean); var PController: TBoldPersistenceController; + vBoldSystem: TBoldSystem; begin - // During read Activation is deferred to Loaded if csReading in ComponentState then FStreamedActive := Value else @@ -148,15 +153,17 @@ procedure TBoldSystemHandle.SetActive(Value: Boolean); begin if Value then begin + if (csDesigning in ComponentState) then + exit; if not assigned(SystemTypeInfoHandle) then - raise EBold.CreateFmt(sUnableToActivateSystemWithoutTypeInfoHandle, [name]); + raise EBold.CreateFmt('Unable to activate a system without a SystemTypeInfoHandle (%s)', [name]); if not assigned(StaticSystemTypeInfo) then - raise EBold.Create(sUnableToFindTypeInfoHandle); + raise EBold.Create('Unable to find a SystemTypeInfo. Possible misstakes: Forgot to connect the SystemTypeInfoHandle to a Model, CreationOrder of the forms/dataModules'); if not StaticSystemTypeInfo.SystemIsRunnable then - raise EBold.CreateFmt(sUnableToActivateSystem, [BOLDCRLF, - StaticSystemTypeInfo.InitializationLog.Text]); + raise EBold.Create('Unable to activate system. Initialization errors in StaticSystemTypeInfo:' + BOLDCRLF + + StaticSystemTypeInfo.InitializationLog.Text); if Persistent then begin @@ -169,22 +176,21 @@ procedure TBoldSystemHandle.SetActive(Value: Boolean); if assigned(SystemTypeInfoHandle.RegionDefinitions) and not assigned(fRegionFactory) then begin SystemTypeInfoHandle.RegionDefinitions.AddSmallSubscription(fRegionDefinitionSubscriber, [beDestroying], breRegionDefinitionsDestroying); - SystemTypeInfoHandle.RegionDefinitions.AddSmallSubscription(fRegionDefinitionSubscriber, [beRegionDefinitionClearing], breRegionDefinitionClearing); + SystemTypeInfoHandle.RegionDefinitions.AddSubscription(fRegionDefinitionSubscriber, beRegionDefinitionClearing, breRegionDefinitionClearing); fRegionFactory := TBoldRegionFactory.Create(SystemTypeInfoHandle.RegionDefinitions); end; - try // will fail if no license + try fBoldSystem := TBoldSystem.CreatewithTypeInfo(nil, StaticSystemTypeInfo, PController, fRegionFactory); - except // If license control failed - fBoldSystem := nil; // Make sure we're not active + except + fBoldSystem := nil; FreeAndNil(fRegionFactory); if Persistent then PersistenceHandle.Active := False; raise; - //FIXME: Other cleanup required? end; - if Active then // I.e. there was a license + if Active then begin fBoldSystem.Evaluator.SetLookupOclDefinition(fOnLookupOclDefinition); fBoldSystem.IsDefault := IsDefault; @@ -194,10 +200,12 @@ procedure TBoldSystemHandle.SetActive(Value: Boolean); end else begin + fBoldSystem.EnsureCanDestroy; + vBoldSystem := fBoldSystem; + fBoldSystem := nil; if Persistent then PersistenceHandle.Active := false; - fBoldSystem.EnsureCanDestroy; //Will raise exception of destructor is constrained - FreeAndNil(fBoldSystem); + FreeAndNil(vBoldSystem); FreeAndNil(fRegionFactory); end; SendEvent(Self, beValueIdentityChanged); @@ -215,13 +223,30 @@ procedure TBoldSystemHandle.SetPersistenceHandle(NewHandle: TBoldPersistenceHand begin fPersistenceHandleSubscriber.CancelAllSubscriptions; if Active then - PanicShutDownSystem(sPersistenceHandleChangedOnRunningSystem); + PanicShutDownSystem('PersistenceHandle was changed on a running system.'); fPersistenceHandle := NewHandle; if assigned(fPersistenceHandle) then fPersistenceHandle.AddSmallSubscription(fPersistenceHandleSubscriber, [beDestroying], brePersistenceHandleDestroying); end; end; +function TBoldSystemHandle.GetPersistenceHandleDB: TBoldAbstractPersistenceHandleDB; +var + Handle: TBoldPersistenceHandle; +begin + result := nil; + Handle := PersistenceHandle; + repeat + if Handle is TBoldAbstractPersistenceHandleDB then + result := TBoldAbstractPersistenceHandleDB(Handle) + else + if Handle is TBoldPersistenceHandlePassthrough then + Handle := TBoldPersistenceHandlePassthrough(Handle).NextPersistenceHandle + else + exit; + until Assigned(result) or not Assigned(Handle); +end; + function TBoldSystemHandle.GetPersistent: Boolean; begin result := assigned(PersistenceHandle); @@ -231,14 +256,15 @@ procedure TBoldSystemHandle.ModelChanged; var WasActive: Boolean; begin - if Active then - PanicShutDownSystem(sModelChangedOnRunningSystem); WasActive := Active; + if Active then + PanicShutDownSystem('The model changed in a running system'); Active := False; - if WasActive then +{ if WasActive then Active := True else - SendEvent(self, beValueIdentityChanged); // type change regarded as idenitychange +} + SendEvent(self, beValueIdentityChanged); end; function TBoldSystemHandle.GetValue: TBoldElement; @@ -249,12 +275,12 @@ function TBoldSystemHandle.GetValue: TBoldElement; procedure TBoldSystemHandle.DefineProperties(Filer: TFiler); begin inherited; - Filer.DefineProperty('TrackBold', ReadTrackBold, nil, False); // do not localize + Filer.DefineProperty('TrackBold', ReadTrackBold, nil, False); end; procedure TBoldSystemHandle.ReadTrackBold(Reader: TReader); begin - Reader.ReadBoolean; // Just throw it away + Reader.ReadBoolean; end; procedure TBoldSystemHandle._ReceivePersistenceHandle(Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent); @@ -271,13 +297,13 @@ procedure TBoldSystemHandle._ReceiveRegionDefinitions(Originator: TObject; Origi beRegionDefinitionClearing: begin if Active then - PanicShutDownSystem(sRegionDefinitionsRemovedFromRunningSystem); + PanicShutDownSystem('RegionDefinitions were removed from a running system.'); FreeAndNil(fRegionFactory); end; end; end; -constructor TBoldSystemHandle.create(owner: TComponent); +constructor TBoldSystemHandle.Create(owner: TComponent); begin inherited; fPersistenceHandleSubscriber := TBoldPassthroughSubscriber.Create(_ReceivePersistenceHandle); @@ -288,7 +314,6 @@ procedure TBoldSystemHandle.PanicShutDownSystem(Message: String); var DirtyCount: integer; begin - // if we are destroying, then we can just ignore this problem, if csDestroying in ComponentState then exit; try @@ -296,13 +321,13 @@ procedure TBoldSystemHandle.PanicShutDownSystem(Message: String); System.Discard; Active := False; if DirtyCount >0 then - raise EBold.CreateFmt(sPanicShutDown, [Message, BOLDCRLF, system.DirtyObjects.Count]); + raise EBold.CreateFmt(Message + BOLDCRLF + 'System Panic shut down. %d objects discarded', [system.DirtyObjects.Count]); except on e: Exception do if BoldEffectiveEnvironment.RunningInIDE then BoldEffectiveEnvironment.HandleDesigntimeException(Self) else - raise; + raise; end; end; @@ -311,7 +336,7 @@ procedure TBoldSystemHandle.InstallOclDefinitionLookUp(const Value: TBoldLookUpO fOnLookupOclDefinition := Value; if assigned(SystemTypeInfoHandle) then SystemTypeInfoHandle.InstallOclDefinitionLookUp(Value); - + if Active then System.Evaluator.SetLookupOclDefinition(value); end; @@ -338,8 +363,6 @@ procedure TBoldSystemHandle.SetOnPreUpdate(Value: TNotifyEvent); fBoldSystem.OnPreUpdate := Value; end; -end. - - - +initialization +end. diff --git a/Source/Handles/Core/BoldVariableDefinition.pas b/Source/Handles/Core/BoldVariableDefinition.pas index 6622b1d..6ba2b15 100644 --- a/Source/Handles/Core/BoldVariableDefinition.pas +++ b/Source/Handles/Core/BoldVariableDefinition.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldVariableDefinition; interface @@ -17,4 +20,9 @@ TBoldVariableDefinition = class(TBoldOclVariables) implementation +uses + BoldRev; + +initialization + end. diff --git a/Source/Handles/Core/BoldVariableHandle.pas b/Source/Handles/Core/BoldVariableHandle.pas index 2bdf101..8be00a0 100644 --- a/Source/Handles/Core/BoldVariableHandle.pas +++ b/Source/Handles/Core/BoldVariableHandle.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldVariableHandle; interface @@ -23,6 +26,7 @@ TBoldVariableHandle = class(TBoldNonSystemHandle) function GetValue: TBoldElement; override; function GetStaticBoldType: TBoldElementTypeInfo; override; procedure StaticBoldTypeChanged; override; + procedure DoAssign(Source: TPersistent); override; public constructor Create(owner: TComponent); override; destructor Destroy; override; @@ -39,18 +43,25 @@ implementation BoldSubscription, BoldDefs, BoldSystemRT, - HandlesConst; + BoldRev; { TBoldVariableHandle } constructor TBoldVariableHandle.Create(owner: TComponent); -var - s: TStringList; begin inherited; - s := TStringList.Create; - s.OnChange := InitialvaluesChanged; - fInitialValues := s; + fInitialValues := TStringList.Create; + fInitialValues.OnChange := InitialvaluesChanged; +end; + +procedure TBoldVariableHandle.DoAssign(Source: TPersistent); +begin + inherited; + if Source is TBoldVariableHandle then with TBoldVariableHandle(Source) do + begin + self.ValueTypeName := ValueTypeName; + self.InitialValues.Assign(InitialValues); + end; end; procedure TBoldVariableHandle.CreateVariableElement; @@ -73,7 +84,7 @@ procedure TBoldVariableHandle.CreateVariableElement; end; end; -destructor TBoldVariableHandle.Destroy; +destructor TBoldVariableHandle.destroy; begin FreePublisher; FreeAndNil(fInitialValues); @@ -83,11 +94,11 @@ destructor TBoldVariableHandle.Destroy; function TBoldVariableHandle.GetStaticBoldType: TBoldElementTypeInfo; begin - if assigned(StaticSystemHandle) then + if assigned(StaticSystemTypeInfo) then begin - result := StaticSystemHandle.StaticSystemTypeInfo.ElementTypeInfoByExpressionName[ValueTypeName]; + Result := StaticSystemTypeInfo.ElementTypeInfoByExpressionName[ValueTypeName]; if assigned(result) and not (result.BoldValueType in [bvtAttr, bvtList]) then - raise EBold.CreateFmt(sOnlyListsAndAttributeTypesAllowed, [ClassName, ValueTypeName]); + raise EBold.CreateFmt('%s.GetStaticBoldType: Only lists and attributes are allowed as types (expr: %s)', [ClassName, ValueTypeName]); end else result := nil; @@ -97,10 +108,10 @@ function TBoldVariableHandle.GetValue: TBoldElement; begin if not (csDesigning in ComponentState) and not (csLoading in ComponentState) then begin - if not assigned(StaticSystemHandle) then - raise EBold.CreateFmt(sNoSystemHandle, [classname, 'GetValue', name]); // do not localize +// if not assigned(StaticSystemHandle) then +// raise EBold.CreateFmt('%s.Getvalue: %s is not connected to a systemhandle', [classname, name]); if not assigned(StaticBoldType) then - raise EBold.CreateFmt(sValueTypeNameInvalid, [classname, name, ValueTypeName]); + raise EBold.CreateFmt('%s.Getvalue: The ValueTypeName of %s does not seem to be valid (%s)', [classname, name, ValueTypeName]); end; if {not (csDesigning in ComponentState) and} @@ -148,4 +159,5 @@ function TBoldVariableHandle.GetObjectList: TBoldObjectList; result := nil; end; +initialization end. diff --git a/Source/Handles/Core/HandlesConst.pas b/Source/Handles/Core/HandlesConst.pas index 2a42101..5ae35d8 100644 --- a/Source/Handles/Core/HandlesConst.pas +++ b/Source/Handles/Core/HandlesConst.pas @@ -93,4 +93,4 @@ interface implementation -end. \ No newline at end of file +end. diff --git a/Source/Handles/IDE/BoldHandlePropEditor.pas b/Source/Handles/IDE/BoldHandlePropEditor.pas index d6e00c8..d1612e5 100644 --- a/Source/Handles/IDE/BoldHandlePropEditor.pas +++ b/Source/Handles/IDE/BoldHandlePropEditor.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldHandlePropEditor; interface @@ -41,7 +44,7 @@ TBoldRootedHandleRootHandlePropertyEditor = class(TBoldComponentPropertyIndica procedure MyGetProc(const s: string); protected function AllMayBeSetTo(NewValue: TPersistent): boolean; - function ComponentMayBeSetTo(Component: TPersistent; NewValue: TPersistent):boolean; + function ComponentMayBeSetTo(Component: TPersistent; NewValue: TPersistent):boolean; virtual; property OrgGetProc: TGetStrProc read fOrgProc write fOrgProc; public procedure GetValues(Proc: TGetStrProc); override; @@ -64,9 +67,8 @@ implementation uses SysUtils, - BoldUtils, - HandlesConst; - + BoldUtils; + { TBoldHandlePropertyEditor } procedure TBoldRootedHandleRootHandlePropertyEditor.GetValues(Proc: TGetStrProc); begin @@ -92,14 +94,13 @@ function TBoldRootedHandleRootHandlePropertyEditor.AllMayBeSetTo(NewValue: TPers function TBoldRootedHandleRootHandlePropertyEditor.ComponentMayBeSetTo( Component: TPersistent; NewValue: TPersistent): boolean; begin - Assert(Component is TBoldRootedHandle); - if (NewValue = Component) or // Prevent link to self - ((NewValue is TBoldRootedHandle) and - TBoldRootedHandle(NewValue).IsRootLinkedTo(Component as TBoldRootedhandle)) then // Prevent circular links + if (NewValue = Component) or + ((NewValue is TBoldRootedHandle) and (Component is TBoldRootedHandle) and + TBoldRootedHandle(NewValue).IsRootLinkedTo(Component as TBoldRootedhandle)) then Result := False else Result := True; -end; +end; { TBoldOclExpressionForOclDefinition } @@ -109,7 +110,7 @@ function TBoldOclExpressionForOclDefinition.GetContextType( if component is TBoldOclDefinition then result := (Component as TBoldOclDefinition).GetContextType else - raise Exception.CreateFmt(sComnponentNotOCLDefinition, [ClassName]); + raise Exception.CreateFmt('%s.GetContextType: Component is not a TBoldOclDefinition', [ClassName]); end; { TBoldTypeNameSelectorForOclDefinition } @@ -125,25 +126,24 @@ function TBoldTypeNameSelectorForOclDefinition.GetContextType( if component is TBoldOclDefinition then result := (Component as TBoldOclDefinition).SystemTypeInfo else - raise Exception.CreateFmt(sComnponentNotOCLDefinition, [ClassName]); + raise Exception.CreateFmt('%s.GetContextType: Component is not a TBoldOclDefinition', [ClassName]); end; { TBoldOclVariablesEditor } function TBoldOclVariablesEditor.GetDefaultMethodName: string; -const - MethodName = 'Variables'; begin - Result := MethodName; + Result := 'Variables'; end; { TBoldOCLRepositoryEditor } function TBoldOCLRepositoryEditor.GetDefaultMethodName: string; -const - MethodName = 'OCLDefinitions'; begin - Result := MethodName; + Result := 'OCLDefinitions'; end; + +initialization + end. diff --git a/Source/Handles/IDE/BoldHandleReg.pas b/Source/Handles/IDE/BoldHandleReg.pas index 85a7f5b..553e677 100644 --- a/Source/Handles/IDE/BoldHandleReg.pas +++ b/Source/Handles/IDE/BoldHandleReg.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldHandleReg; interface @@ -33,6 +36,7 @@ implementation BoldVariableHandle, BoldSystemHandle, BoldSQLHandle, + BoldRawSQLHandle, BoldFilteredHandle, BoldSortedHandle, BoldReferenceHandle, @@ -79,6 +83,7 @@ procedure RegisterComponentsOnPalette; TBoldVariableHandle, TBoldListHandle, TBoldSQLHandle, + TBoldRawSQLHandle, TBoldCursorHandle, TBoldReferenceHandle, TBoldOclVariables, @@ -122,7 +127,9 @@ procedure RegisterEditors; RegisterPropertyEditor(TypeInfo(string), TBoldRootedHandle, 'RootTypeName', TBoldTypeNameSelectorPropertyForAllTypes); // do not localize RegisterPropertyEditor(TypeInfo(string), TBoldVariableHandle, 'ValueTypeName', TBoldTypeNameSelectorPropertyForVariableHandle); // do not localize RegisterPropertyEditor(TypeInfo(string), TBoldDerivedHandle, 'ValueTypeName', TBoldTypeNameSelectorPropertyForAllTypes); // do not localize + RegisterPropertyEditor(TypeInfo(string), TBoldDerivedHandle, 'ValueTypeName', TBoldTypeNameSelectorPropertyForVariableHandle); // do not localize RegisterPropertyEditor(TypeInfo(string), TBoldSQLHandle, 'ClassExpressionName', TBoldTypeNameSelectorForSQLHandle); // do not localize + RegisterPropertyEditor(TypeInfo(string), TBoldRawSQLHandle, 'ClassExpressionName', TBoldTypeNameSelectorForSQLHandle); // do not localize // Propeditor för listhandle.expression // Propeditor för Exprhandle.expression @@ -137,6 +144,7 @@ procedure RegisterEditors; RegisterComponentEditor(TBoldDerivedHandle, TBoldModelAwareComponentEditor); RegisterComponentEditor(TBoldVariableHandle, TBoldModelAwareComponentEditor); RegisterComponentEditor(TBoldSQLHandle, TBoldModelAwareComponentEditor); + RegisterComponentEditor(TBoldRawSQLHandle, TBoldModelAwareComponentEditor); RegisterComponentEditor(TBoldCursorHandle, TBoldModelAwareComponentEditor); RegisterComponentEditor(TBoldReferenceHandle, TBoldModelAwareComponentEditor); end; @@ -151,3 +159,4 @@ procedure Register; end. + diff --git a/Source/Handles/IDE/BoldLockingReg.pas b/Source/Handles/IDE/BoldLockingReg.pas index 810254e..85483a0 100644 --- a/Source/Handles/IDE/BoldLockingReg.pas +++ b/Source/Handles/IDE/BoldLockingReg.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldLockingReg; interface @@ -14,7 +17,6 @@ implementation BoldIDEConsts, BoldLockingHandles; -{.$R *.res} procedure RegisterComponentsOnPalette; begin @@ -27,3 +29,4 @@ procedure Register; end; end. + diff --git a/Source/Handles/IDE/BoldManipulatorReg.pas b/Source/Handles/IDE/BoldManipulatorReg.pas index b9da93e..fd7de7a 100644 --- a/Source/Handles/IDE/BoldManipulatorReg.pas +++ b/Source/Handles/IDE/BoldManipulatorReg.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldManipulatorReg; interface @@ -25,3 +28,4 @@ procedure Register; end; end. + diff --git a/Source/Handles/IDE/BoldXMLReg.pas b/Source/Handles/IDE/BoldXMLReg.pas index 25ac31b..e72b81f 100644 --- a/Source/Handles/IDE/BoldXMLReg.pas +++ b/Source/Handles/IDE/BoldXMLReg.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldXMLReg; interface @@ -9,12 +12,12 @@ procedure Register; implementation uses + BoldGuard, BoldXMLProducers; procedure Register; begin - RegisterComponents('Bold XML', [TBoldXMLProducer]); // do not localize + RegisterComponents('Bold XML', [TBoldXMLProducer]); end; end. - diff --git a/Source/Handles/IDECOM/BoldComElementHandleReg.pas b/Source/Handles/IDECOM/BoldComElementHandleReg.pas index 7022aca..2eb7ed0 100644 --- a/Source/Handles/IDECOM/BoldComElementHandleReg.pas +++ b/Source/Handles/IDECOM/BoldComElementHandleReg.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldComElementHandleReg; interface @@ -6,15 +9,13 @@ procedure Register; implementation -{$R BoldComElementHandleReg.Res} - uses Classes, BoldComServerElementHandles; procedure Register; begin - RegisterComponents('Bold COM', [TBoldComServerElementHandle]); // do not localize + RegisterComponents('Bold COM',[TBoldComServerElementHandle]); end; end. diff --git a/Source/Handles/Manipulators/BoldManipulators.pas b/Source/Handles/Manipulators/BoldManipulators.pas index 9d93d49..26f6cd9 100644 --- a/Source/Handles/Manipulators/BoldManipulators.pas +++ b/Source/Handles/Manipulators/BoldManipulators.pas @@ -1,9 +1,11 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldManipulators; interface uses - BoldSystem, BoldDefs, BoldElements, BoldHandles, @@ -28,18 +30,14 @@ TBoldManipulator = class(TBoldSubscribableComponentViaBoldElem) fOnEncrypt: TBoldStringStringFunction; fOnDecrypt: TBoldStringStringFunction; FMappers: TBoldManipulatorMapperCollection; - fBoldSystem: TBoldSystem; - function RawIdStringForElement(Element: TBoldElement): string; // unencrypted - function ElementForRawIdString(IdString: string): TBoldElement; // unencrypted + function RawIdStringForElement(Element: TBoldElement): string; + function ElementForRawIdString(IdString: string): TBoldElement; function AddMapping(const RawIdString: string; const Mapping: string): string; function GetMapping(const IdString: string): string; function StripMapping(const IdString: string): string; procedure SetMappers(const Value: TBoldManipulatorMapperCollection); procedure SetBoldSystemHandle(const Value: TBoldAbstractSystemhandle); - function GetAttachedSystem: TBoldSystem; - procedure SetBoldSystem(const Value: TBoldSystem); protected - property AttachedSystem: TBoldSystem read GetAttachedSystem; procedure Notification(AComponent: TComponent; Operation: TOperation); override; public constructor Create(AOwner: TComponent); override; @@ -51,10 +49,9 @@ TBoldManipulator = class(TBoldSubscribableComponentViaBoldElem) function IdStringForElement(Element: TBoldElement; const Mapping: string = ''): string; procedure DeleteObject(IdString: string); function CreateObject(Classname: string): string; - procedure SetFromList(IdValuePairs: TStrings); + procedure SetFromList(IdValuePairs: TStrings); published property IdStringRepresentation:TBoldIdStringRepresentation read fIdStringRepresentation write fIdStringRepresentation; - property BoldSystem: TBoldSystem read fBoldSystem write SetBoldSystem; property BoldSystemHandle: TBoldAbstractSystemhandle read fBoldSystemHandle write SetBoldSystemHandle; property OnEncrypt: TBoldStringStringFunction read fOnEncrypt write fOnEncrypt; property OnDecrypt: TBoldStringStringFunction read fOnDecrypt write fOnDecrypt; @@ -95,21 +92,19 @@ TBoldManipulatorMapperCollection = class(TCollection) implementation -{.$R *.res} - uses SysUtils, BoldUtils, BoldId, BoldDefaultId, - HandlesConst; + BoldSystem; { TBoldManipulator } function TBoldManipulator.AddMapping(const RawIdString, Mapping: string): string; begin if Mapping <> '' then - Result := Format('%s[%s]', [RawIdString, Mapping]) // do not localize + Result := Format('%s[%s]', [RawIdString, Mapping]) else Result := RawIdString; end; @@ -129,6 +124,11 @@ function TBoldManipulator.ElementForRawIdString(IdString: string): TBoldElement; ColonPos: integer; ObjectId: TBoldObjectID; begin + if Trim(IdString) = '' then + begin + Result := nil; + exit; + end; if IdStringRepresentation = isrVerbose then IdString := Copy(IdString, Pos('.', IdString) + 1, MAXINT); ColonPos := Pos(':', IdString); @@ -145,7 +145,7 @@ function TBoldManipulator.ElementForRawIdString(IdString: string): TBoldElement; ObjectID := TBoldDefaultId.CreateWithClassID(0, false); (ObjectID as TBoldDefaultId).AsInteger := StrToInt(ObjectIdStr); end; - BoldObject := AttachedSystem.EnsuredLocatorByID[ObjectID].EnsuredBoldObject; // FIXME error handling if object has been deleted + BoldObject := BoldSystemHandle.System.EnsuredLocatorByID[ObjectID].EnsuredBoldObject; if ColonPos = 0 then result := BoldObject else if IdStringRepresentation = isrVerbose then @@ -181,7 +181,7 @@ function TBoldManipulator.GetValueAndId(Element: TBoldElement; else begin IdString := AddMapping(IdString, Mapping); - Result := Mappers.ItemByname[Mapping].GetAsString(Element); // FIXME error handling + Result := Mappers.ItemByname[Mapping].GetAsString(Element); end; if Assigned(fOnEncrypt) and (IdString <> '') then IdString := OnEncrypt(IdString); @@ -189,7 +189,6 @@ function TBoldManipulator.GetValueAndId(Element: TBoldElement; function TBoldManipulator.RawIdStringForElement(Element: TBoldElement): string; begin - Result := ''; if Element is TBoldObject then begin if IdStringRepresentation = isrVerbose then @@ -236,7 +235,7 @@ procedure TBoldManipulator.SetValue(IdString: string; const NewValue: string); NewId := OnDecrypt(NewId); NewElement := ElementForRawIdString(StripMapping(NewId)); if (NewElement is TBoldObject) then - r.BoldObject := TBoldObject(NewElement); // FIXME error handling + r.BoldObject := TBoldObject(NewElement); end; var @@ -256,13 +255,13 @@ procedure TBoldManipulator.SetValue(IdString: string; const NewValue: string); else if (Element is TBoldObjectReference) then SetObjectReference(TBoldObjectReference(Element), NewValue) else if (Element is TBoldObjectList) then - raise EBold.Create(sCannotSetMultiLinkFromValue) + raise EBold.Create('Can''t set Multilink from value') else if (Element is TBoldObject) then - raise EBold.Create(sCannotSetObjectFromValue); + raise EBold.Create('Can''t set Object from value'); end; end else - Mappers.ItemByname[Mapping].SetFromString(Element, NewValue); // FIXME error handling + Mappers.ItemByname[Mapping].SetFromString(Element, NewValue); end; function TBoldManipulator.StripMapping(const IdString: string): string; @@ -297,10 +296,10 @@ destructor TBoldManipulator.Destroy; function TBoldManipulator.CreateObject(Classname: string): string; begin - if Assigned(AttachedSystem) then - Result := IdStringForElement(AttachedSystem.CreateNewObjectByExpressionName(ClassName)) + if Assigned(BoldSystemhandle) then + Result := IdStringForElement(BoldSystemHandle.System.CreateNewObjectByExpressionName(ClassName)) else - raise EBold.CreateFmt(sNoSystemHandle, [classname, 'CreateObject', Name]); // do not localize + raise EBold.CreateFmt('%s.CreateObject: The manipulator is not connected to a systemhandle', [classname]); end; procedure TBoldManipulator.DeleteObject(IdString: string); @@ -337,21 +336,7 @@ function TBoldManipulator.DefaultTagForElement(Element: TBoldElement): string; else if Assigned(Element.BoldType) then Result := Element.BoldType.ExpressionName else - raise EBold.CreateFmt(sElementLacksTypeInfo, [ClassName]); -end; - -function TBoldManipulator.GetAttachedSystem: TBoldSystem; -begin - if BoldSystemHandle <> nil then - Result := BoldSystemHandle.System - else - Result := fBoldSystem; -end; - -procedure TBoldManipulator.SetBoldSystem(const Value: TBoldSystem); -begin - fBoldSystem := Value; - { TODO : Get OnDestroy notification for system} + raise EBold.CreateFmt('%s.DefaultTagForElement: Element lacks type information', [ClassName]); end; { TBoldManipulatorMapper } @@ -393,7 +378,7 @@ function TBoldManipulatorMapperCollection.GetItemByname( result := Items[i]; Exit; end; - raise EBold.CreateFmt(sUnknownMapping, [Name]); + raise EBold.CreateFmt('Unknown mapping: %s', [Name]); end; function TBoldManipulatorMapperCollection.GetItems(Index: integer): TBoldManipulatorMapper; @@ -406,4 +391,5 @@ function TBoldManipulatorMapperCollection.GetOwner: TPersistent; result := fOwner; end; +initialization end. diff --git a/Source/Handles/PessimisticLocking/BoldLockingHandles.pas b/Source/Handles/PessimisticLocking/BoldLockingHandles.pas index 23dc808..913ebce 100644 --- a/Source/Handles/PessimisticLocking/BoldLockingHandles.pas +++ b/Source/Handles/PessimisticLocking/BoldLockingHandles.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldLockingHandles; interface @@ -6,20 +9,24 @@ interface Classes, BoldDefs, BoldSubscription, + {$IFNDEF BOLD_NO_QUERIES} BoldLockHandler, + {$ENDIF} BoldLockHolder, BoldListenerHandle, BoldAbstractLockManagerHandle, BoldHandles; type - { TBoldLockingHandle } + TBoldLockingHandle = class(TBoldSubscribableComponent) private fActive: Boolean; fSubscriber: TBoldPassthroughSubscriber; FSystemHandle: TBoldAbstractSystemHandle; + {$IFNDEF BOLD_NO_QUERIES} fLockHandler: TBoldPessimisticLockHandler; + {$ENDIF} fLockHolder: TBoldLockHolder; FListener: TBoldListenerHandle; FLockManager: TBoldAbstractLockManagerHandle; @@ -37,7 +44,9 @@ TBoldLockingHandle = class(TBoldSubscribableComponent) public constructor Create(AOwner: TComponent); override; destructor Destroy; override; + {$IFNDEF BOLD_NO_QUERIES} property LockHandler: TBoldPessimisticLockHandler read fLockHandler; + {$ENDIF} property LockHolder: TBoldLockHolder read GetLockHolder; property Active: Boolean read fActive; published @@ -52,7 +61,6 @@ TBoldLockingHandle = class(TBoldSubscribableComponent) implementation uses - HandlesConst, BoldUtils, SysUtils; @@ -65,16 +73,18 @@ procedure TBoldLockingHandle.Activate; if not assigned(SystemHandle.System) then raise EBoldInternal.CreateFmt('%s.Activate: Cannot activate Locking. The system is not active.', [classname]); if not assigned(Listener) then - raise EBold.CreateFmt(sCannotActivateWithoutListener, [classname]); + raise EBold.CreateFmt('%s.Activate: Cannot activate Locking without a listener. Set the Listener property of the %0:s', [classname]); if not assigned(LockManager) then - raise EBold.CreateFmt(sCannotActivateWithoutLockManager, [classname]); + raise EBold.CreateFmt('%s.Activate: Cannot activate Locking without a LockManager. Set the LockManager property of the %0:s', [classname]); if not Active then begin + {$IFNDEF BOLD_NO_QUERIES} fLockHandler := TBoldPessimisticLockHandler.CreateWithLockHolder(FSystemHandle.System, LockHolder); fLockHandler.OnActivityStart := OnActivityStart; fLockHandler.OnActivityEnd := OnActivityEnd; fLockHandler.OnProgress := OnProgress; + {$ENDIF} fActive := True; end; end; @@ -102,7 +112,9 @@ procedure TBoldLockingHandle.Deactivate; if Active then begin FreeAndNil(fLockHolder); + {$IFNDEF BOLD_NO_QUERIES} FreeAndNil(fLockHandler); + {$ENDIF} fActive := false; end; end; @@ -191,4 +203,6 @@ procedure TBoldLockingHandle._Receive(Originator: TObject; end; end; +initialization + end. diff --git a/Source/Handles/UnLoader/BoldUnloaderHandle.pas b/Source/Handles/UnLoader/BoldUnloaderHandle.pas index 7600dd3..fe8ec76 100644 --- a/Source/Handles/UnLoader/BoldUnloaderHandle.pas +++ b/Source/Handles/UnLoader/BoldUnloaderHandle.pas @@ -1,3 +1,6 @@ +///////////////////////////////////////////////////////// + + unit BoldUnloaderHandle; interface @@ -12,6 +15,11 @@ interface Classes, ExtCtrls; +const + cTickInterval = 60 * 1000; // 1 minute + cScanPerTick = 50; // milliseconds, max time to spend scaning + cMinAgeForUnload = 5; // unit is the TickInterval so (cTickInterval * cMinAgeForUnload) = 5 minutes + type { Forward declaration of classes } TBoldUnloaderHandle = class; @@ -32,6 +40,12 @@ TBoldUnloaderHandle = class(TComponent) procedure SetUnloadDelayedFetch(const Value: boolean); procedure SetMinAgeForUnload(const Value: integer); procedure SetScanPerTick(const Value: integer); + function GetOnMayStart: TBoldMayUnloadStartEvent; + procedure SetOnMayStart(const Value: TBoldMayUnloadStartEvent); + function GetOnReportUnload: TBoldReportUnloadEvent; + procedure SetOnReportUnload(const Value: TBoldReportUnloadEvent); + function GetUnloadFromCurrentClassList: boolean; + procedure SetUnloadFromCurrentClassList(const Value: boolean); property Unloader: TBoldUnloader read fUnloader; procedure SetBoldSystemHandle(const Value: TBoldSystemHandle); procedure Tick(Sender: Tobject); @@ -42,18 +56,22 @@ TBoldUnloaderHandle = class(TComponent) function GetOnMayUnload: TBoldUnloadObjectEvent; procedure SetOnMayInvalidate(const Value: TBoldInvalidateMemberEvent); procedure SetOnMayUnload(const Value: TBoldUnloadObjectEvent); + procedure PlaceSubscriptions; public constructor Create(AOwner: TComponent); override; destructor Destroy; override; published - property TickIntervall: integer read GetTickInterval write SetTickInterval default 1000; + property TickInterval: integer read GetTickInterval write SetTickInterval default cTickInterval; property BoldSystemHandle: TBoldSystemHandle read fBoldSystemHandle write SetBoldSystemHandle; - property ScanPerTick: integer read GetScanPerTick write SetScanPerTick default 1000; - property MinAgeForUnload: integer read GetMinAgeForUnload write SetMinAgeForUnload default 300000; - property UnloadDelayedFetch: boolean read GetUnloadDelayedFetch write SetUnloadDelayedFetch; + property ScanPerTick: integer read GetScanPerTick write SetScanPerTick default cScanPerTick; + property MinAgeForUnload: integer read GetMinAgeForUnload write SetMinAgeForUnload default cMinAgeForUnload; + property UnloadDelayedFetch: boolean read GetUnloadDelayedFetch write SetUnloadDelayedFetch default false; + property UnloadFromCurrentClassList: boolean read GetUnloadFromCurrentClassList write SetUnloadFromCurrentClassList default false; property Active: boolean read fActive write SetActive default true; property OnMayInvalidate: TBoldInvalidateMemberEvent read GetOnMayInvalidate write SetOnMayInvalidate; property OnMayUnload: TBoldUnloadObjectEvent read GetOnMayUnload write SetOnMayUnload; + property OnMayStart: TBoldMayUnloadStartEvent read GetOnMayStart write SetOnMayStart; + property OnReportUnload: TBoldReportUnloadEvent read GetOnReportUnload write SetOnReportUnload; end; @@ -75,15 +93,16 @@ constructor TBoldUnloaderHandle.Create(AOwner: TComponent); fSubscriber := TBoldPassthroughSubscriber.Create(ReceiveFromSystemHandle); fTimer := TTimer.Create(Self); fTimer.Enabled := True; - TickIntervall := 1000; - ScanPertick := 1000; - MinAgeForUnload := 300000; + TickInterval := cTickInterval; + ScanPertick := cScanPertick; + MinAgeForUnload := cMinAgeForUnload; fTimer.OnTimer := Tick; Active := True; end; destructor TBoldUnloaderHandle.Destroy; begin + BoldSystemHandle := nil; FreeAndNil(fSubscriber); FreeAndNil(fUnLoader); FreeAndNil(fTimer); @@ -95,6 +114,11 @@ function TBoldUnloaderHandle.GetUnloadDelayedFetch: boolean; Result := Unloader.UnloadDelayedFetch; end; +function TBoldUnloaderHandle.GetUnloadFromCurrentClassList: boolean; +begin + result := Unloader.UnloadFromCurrentClassList; +end; + function TBoldUnloaderHandle.GetMinAgeForUnload: integer; begin Result := Unloader.MinAgeForUnload; @@ -110,16 +134,28 @@ function TBoldUnloaderHandle.GetTickInterval: integer; Result := fTimer.Interval; end; +procedure TBoldUnloaderHandle.PlaceSubscriptions; +begin + fSubscriber.CancelAllSubscriptions; + if assigned(fBoldSystemHandle) then + begin + fBoldSystemHandle.AddSmallSubscription(fSubscriber, [beDestroying], breHandleDestroyed); + fBoldSystemHandle.AddSmallSubscription(fSubscriber, [beValueIdentityChanged], breSystemChanged); + if assigned(fBoldSystemHandle.System) then + fBoldSystemHandle.System.AddSmallSubscription(fSubscriber, [beDestroying], beDestroying); + end; +end; + procedure TBoldUnloaderHandle.PropagateToUnloder; begin + PlaceSubscriptions; if Active then begin if Assigned(BoldSystemHandle) then fUnloader.BoldSystem := BoldSystemHandle.System else fUnloader.BoldSystem := nil; - if Assigned(fUnloader.BoldSystem) then - fUnloader.Active := True; + fUnloader.Active := Assigned(fUnloader.BoldSystem); end else fUnLoader.Active := False; @@ -146,15 +182,9 @@ procedure TBoldUnloaderHandle.SetActive(const Value: boolean); procedure TBoldUnloaderHandle.SetBoldSystemHandle( const Value: TBoldSystemHandle); begin - if Value <> BoldSystemHandle then + if Value <> fBoldSystemHandle then begin - fSubscriber.CancelAllSubscriptions; fBoldSystemHandle := Value; - if assigned(Value) then - begin - fBoldSystemHandle.AddSmallSubscription(fSubscriber, [beDestroying], breHandleDestroyed); - fBoldSystemHandle.AddSmallSubscription(fSubscriber, [beValueIdentityChanged], breSystemChanged); - end; PropagateToUnloder; end; end; @@ -165,6 +195,12 @@ procedure TBoldUnloaderHandle.SetUnloadDelayedFetch( Unloader.UnloadDelayedFetch := Value; end; +procedure TBoldUnloaderHandle.SetUnloadFromCurrentClassList( + const Value: boolean); +begin + Unloader.UnloadFromCurrentClassList := Value; +end; + procedure TBoldUnloaderHandle.SetMinAgeForUnload( const Value: integer); begin @@ -191,25 +227,43 @@ function TBoldUnloaderHandle.GetOnMayInvalidate: TBoldInvalidateMemberEvent; Result := Unloader.OnMayInvalidate; end; +function TBoldUnloaderHandle.GetOnMayStart: TBoldMayUnloadStartEvent; +begin + Result := Unloader.OnMayStart; +end; + function TBoldUnloaderHandle.GetOnMayUnload: TBoldUnloadObjectEvent; begin Result := Unloader.OnMayUnload; end; +function TBoldUnloaderHandle.GetOnReportUnload: TBoldReportUnloadEvent; +begin + result := Unloader.OnReportUnload; +end; + procedure TBoldUnloaderHandle.SetOnMayInvalidate( const Value: TBoldInvalidateMemberEvent); begin Unloader.OnMayInvalidate := Value; end; +procedure TBoldUnloaderHandle.SetOnMayStart(const Value: TBoldMayUnloadStartEvent); +begin + Unloader.OnMayStart := Value; +end; + procedure TBoldUnloaderHandle.SetOnMayUnload( const Value: TBoldUnloadObjectEvent); begin Unloader.OnMayUnload := Value; end; -end. - - +procedure TBoldUnloaderHandle.SetOnReportUnload( + const Value: TBoldReportUnloadEvent); +begin + Unloader.OnReportUnload := Value; +end; +end. diff --git a/Source/Handles/XML/BoldXMLProducers.pas b/Source/Handles/XML/BoldXMLProducers.pas index 24f40e6..5b86e49 100644 --- a/Source/Handles/XML/BoldXMLProducers.pas +++ b/Source/Handles/XML/BoldXMLProducers.pas @@ -1,7 +1,9 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldXMLProducers; interface - uses MSXML_TLB, BoldStringList, @@ -10,7 +12,8 @@ interface BoldElements, BoldSystem, BoldSubscription, - Classes; + Classes + ; type TBoldXMLProducerOption = (xpoIncludeIdString, xpoIncludeValue); @@ -34,7 +37,7 @@ TBoldAbstractXMLProducer = class(TBoldSubscribableComponent) protected procedure Produce(const paramList: TBoldStringList; const DomDoc: IXMLDomDocument); virtual; abstract; procedure Notification(AComponent: TComponent; Operation: TOperation); override; - function getDocument(const paramList: TBoldStringList): IXMLDomDocument; + function getDocument(const paramList: TBoldStringList): IXMLDomDocument; property BoldManipulator: TBoldManipulator read FBoldManipulator write SetBoldManipulator; property XMLElementBoldIDName: string read FXMLElementBoldIDName write FXMLElementBoldIDName; public @@ -62,12 +65,11 @@ TBoldXMLProducer = class(TBoldAbstractXMLProducer) implementation -{.$R *.res} - uses SysUtils, BoldUtils, - HandlesConst; + HandlesConst + ; { TBoldXMLProducer } @@ -202,4 +204,5 @@ function TBoldAbstractXMLProducer.AddDomElement( Result.setAttribute(WideString(XMLAttributes.Names[i]), WideString(XMLAttributes.Strings[i])); end; + end. diff --git a/Source/MoldModel/Bld/BoldBld.pas b/Source/MoldModel/Bld/BoldBld.pas index 3414bb3..afd50fc 100644 --- a/Source/MoldModel/Bld/BoldBld.pas +++ b/Source/MoldModel/Bld/BoldBld.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldBld; interface @@ -16,12 +19,13 @@ TMoldBLDRW = class; {---Exceptions---} EBoldBLDParseError = class(EBold); + {---TMoldBLDRW---} TMoldBLDRW = class - class function ModelFromFile(const filename: string): TMoldModel; // returns dynamically allocated model, with parts. + class function ModelFromFile(const filename: string): TMoldModel; class procedure ModelToFile(Model: TMoldModel; const filename: string); class procedure ModelToStrings(Model: TMoldModel; s: TSTrings); - class function StringsToModel(s: TStrings): TMoldModel; // returns dynamically allocated model, with parts. + class function StringsToModel(s: TStrings): TMoldModel; end; @@ -36,8 +40,7 @@ implementation BoldTaggedValueSupport, BoldDefaultTaggedValues, BoldUMLTaggedValues, - BoldUMLTypes, - BoldMoldConsts; + BoldUMLTypes; const LINKEXTENSION: string = '.bld'; @@ -56,6 +59,8 @@ TPClass = class; TElementClass = class of TElement; + + TElementClassRecord = record ElementClass: TElementClass; MoldElementClass: TMoldElementClass; @@ -101,13 +106,13 @@ TReader = class(TBoldMemoryManagedObject) Position: Integer; CurrentToken: TToken; CurrentCharacter: Char; - procedure GetToken; // Get a token - procedure Skip; // skip to next non-whitespace character - procedure GetCharacter; // Get next character - procedure GetCharacterNotEof; // Get next character, don't allow EOF - function NextCharacter: Char; // Get next non-whitespace character, and return in - procedure EatStartBlock(const keyw: string); // Eat start block - function TryKeyword(const keyw: string): Boolean; // eat keyword if matching + procedure GetToken; + procedure Skip; + procedure GetCharacter; + procedure GetCharacterNotEof; + function NextCharacter: Char; + procedure EatStartBlock(const keyw: string); + function TryKeyword(const keyw: string): Boolean; function GetKeyword: string; procedure Eat(t: BLDTokenKind); procedure EatKeyword(const keyw: string); @@ -142,7 +147,7 @@ TModel = class(TElement) {---TElementList---} TElementList = class(TBoldMemoryManagedObject) class procedure Write(list: TMoldElementList; w: TWriter); - class procedure Read(parent: TMoldElement; r: TReader); // classes link themselves into the right list + class procedure Read(parent: TMoldElement; r: TReader); end; {---TPClass---} @@ -193,7 +198,7 @@ class procedure TMoldBLDRW.ModelToStrings(model: TMoldModel; s: TStrings); Exit; theWriter := TWriter.Create(s); try - theWriter.Put(Format('VERSION %d', [CURRENTVERSION])); // do not localize + theWriter.Put(Format('VERSION %d', [CURRENTVERSION])); Tmodel.Write(model, theWriter); finally theWriter.Free; @@ -213,13 +218,13 @@ class procedure TMoldBLDRW.ModelToFile(Model: TMoldModel; const Filename: string end; end; -class function TMoldBLDRW.StringsToModel(s:TStrings): TMoldModel; // returns dynamically allocated model, with parts. +class function TMoldBLDRW.StringsToModel(s:TStrings): TMoldModel; var reader: TReader; begin Result := nil; if s.Count = 0 then - Result := TMoldModel.Create(nil, 'New_Model') // do not localize + Result := TMoldModel.Create(nil, 'New_Model') else begin reader := TReader.Create(s); @@ -228,8 +233,7 @@ class function TMoldBLDRW.StringsToModel(s:TStrings): TMoldModel; // returns dyn reader.CurrentToken := TToken.Create; reader.GetCharacter; reader.GetToken; - // Get version information (if any) - if reader.TryKeyword('VERSION') then // do not localize + if reader.TryKeyword('VERSION') then reader.FFormatVersion := reader.GetInteger else reader.FFormatVersion := 1; @@ -240,12 +244,10 @@ class function TMoldBLDRW.StringsToModel(s:TStrings): TMoldModel; // returns dyn } Result := TElement.CreateAndRead(nil, reader) as TMoldModel; -// if reader.fFormatVersion < 11 then -// Result.RootClass.ClassID := Result.FreeClassID; except on e: EBoldBLDParseError do - raise EBoldBLDParseError.CreateFmt(sErrorOnPos, [e.Message, reader.LineNumber, reader.Position]); + raise EBoldBLDParseError.CreateFmt('%s Line: %d Position: %d', [e.Message, reader.LineNumber, reader.Position]); end; finally Reader.Free; @@ -319,7 +321,6 @@ procedure TWriter.PutQuotedString(const s: string); else if s[i] = BOLDLF then begin Put('\' + 'l'); - // DontIndent; end else Put(s[i]); @@ -336,9 +337,9 @@ procedure TWriter.PutBoolean(b: Boolean); begin doIndent; if b then - Put('TRUE') // do not localize + Put('TRUE') else - Put('FALSE'); // do not localize + Put('FALSE'); end; Procedure TWriter.PutClassReference(aClass: TMoldClass); @@ -346,7 +347,7 @@ procedure TWriter.PutBoolean(b: Boolean); if Assigned(aClass) then PutQuotedString(aClass.Name) else - PutQuotedString(''); // do not localize + PutQUotedString(''); end; {---TReader---} @@ -366,7 +367,7 @@ destructor TReader.Destroy; procedure TReader.Skip; begin - while (not EOS) and (CurrentCharacter in [SPACE, TAB]) do + while (not EOS) and CharInSet(CurrentCharacter, [SPACE, TAB]) do GetCharacter; end; @@ -383,12 +384,12 @@ procedure TReader.GetCharacter; Inc(fLineNumber); end; Position := 1; - CurrentCharacter := ' '; // Space for newline + CurrentCharacter := ' '; end; - + begin if EOS then - CurrentCharacter := ' ' // Space for newline + CurrentCharacter := ' ' else if (Position > fLineLength) then NextLine @@ -397,13 +398,12 @@ procedure TReader.GetCharacter; CurrentCharacter := Line[Position]; INC(Position); end; - // write(output, currentcharacter); // DEBUG only (or you'll get an IO error 103) end; procedure TReader.GetCharacterNotEof; begin if EOS then - raise EBoldBLDParseError.Create(sUnexpectedEOF) + raise EBoldBLDParseError.Create('BLD Reader: Unexpected EOF') else GetCharacter; end; @@ -414,9 +414,10 @@ function TReader.NextCharacter: Char; Result := CurrentCharacter; end; + var TokenBuffer: string = ' '; - TokenBufferLength: integer = 6; // TokenBuffer MUST consist of this many spaces to start with + TokenBufferLength: integer = 6; procedure TReader.GetToken; var @@ -446,7 +447,7 @@ procedure TReader.GetToken; begin Kind := INTVALUE; IntegerValue := ord(CurrentCharacter) - ord('0'); - while Nextcharacter in ['0'..'9'] do + while CharInSet(Nextcharacter, ['0'..'9']) do IntegerValue := IntegerValue * 10 + ord(CurrentCharacter) - ord('0') end; @@ -457,7 +458,7 @@ procedure TReader.GetToken; StartIndex := Position; FoundLength := 1; TokenBuffer[FoundLength] := CurrentCharacter; - while NextCharacter in ['A'..'Z','a'..'z'] do + while CharInSet(NextCharacter, ['A'..'Z','a'..'z']) do Inc(FoundLength); StringValue := Copy(LineWithToken, StartIndex-1, FoundLength); end; @@ -491,7 +492,7 @@ procedure TReader.GetToken; StringValue := Copy(TokenBuffer, 1, i); end; else - raise EBoldBLDParseError.CreateFmt(sBadCharacter, [IntToStr(ord(CurrentCharacter))]) + raise EBoldBLDParseError.CreateFmt('BLD Reader: Bad character %s', [IntToStr(ord(CurrentCharacter))]) end; end; @@ -500,13 +501,13 @@ procedure TReader.Eat(t: BLDTokenKind); if CurrentToken.Kind = t then GetToken else - raise EBoldBLDParseError.Create(sSyntaxError); + raise EBoldBLDParseError.Create('BLD Reader: Syntax error'); end; procedure TReader.EatKeyword(const keyw: string); begin if not TryKeyword(keyw) then - raise EBoldBLDParseError.CreateFmt(sAKeywordExpected, [keyw]); + raise EBoldBLDParseError.CreateFmt('BLD Reader: ''%s'' expected', [keyw]); end; procedure TReader.EatStartBlock(const keyw: string); @@ -532,7 +533,7 @@ function TReader.GetQuotedString: string; if CurrentToken.Kind = QSTRING then GetToken else - raise EBoldBLDParseError.Create(sQuotedStringExpected); + raise EBoldBLDParseError.Create('BLD Reader: Quoted string expected'); end; function TReader.GetKeyword: string; @@ -541,7 +542,7 @@ function TReader.GetKeyword: string; if CurrentToken.Kind = KEYWORD then GetToken else - raise EBoldBLDParseError.Create(sKeyWordTokenExpected); + raise EBoldBLDParseError.Create('BLD Reader: KEYWORD expected'); end; function TReader.GetInteger: integer; @@ -550,17 +551,17 @@ function TReader.GetInteger: integer; if CurrentToken.Kind = INTVALUE then GetToken else - raise EBoldBLDParseError.Create(sIntegerExpected); + raise EBoldBLDParseError.Create('BLD Reader: Integer expected'); end; function TReader.GetBoolean: Boolean; begin Result := False; - if (CurrentToken.Kind = KEYWORD) and (CurrentToken.StringValue = 'TRUE') then // do not localize + if (CurrentToken.Kind = KEYWORD) and (CurrentToken.StringValue = 'TRUE') then Result := True else - if (CurrentToken.Kind <> KEYWORD) or (CurrentToken.StringValue <> 'FALSE') then // do not localize - raise EBoldBLDParseError.Create(sBooleanExpected); + if (CurrentToken.Kind <> KEYWORD) or (CurrentToken.StringValue <> 'FALSE') then + raise EBoldBLDParseError.Create('BLD Reader: Boolean expected'); GetToken; end; @@ -569,7 +570,7 @@ function TReader.GetClassReference: TMoldClass; name: string; begin name := GetQuotedString; - if name = '' then // do not localize + if name = '' then Result := nil else Result := CurrentModel.GetClassByName(name); @@ -581,7 +582,7 @@ class procedure TModel.Write(element: TMoldElement; w: TWriter); model: TMoldModel; begin model := element as TMoldModel; - w.PutStartBlock('Model'); // do not localize + w.PutStartBlock('Model'); w.PutQuotedString(Model.Name); { version 11 } w.PutQuotedString(Model.RootClass.Name); @@ -591,10 +592,10 @@ class procedure TModel.Write(element: TMoldElement; w: TWriter); { version 17 } w.PutQuotedString(Model.NonDefaultTaggedValuesCommaText); - w.PutStartBlock('Classes'); // do not localize + w.PutStartBlock('Classes'); TElementList.Write(Model.Classes, w); w.PutEndBlock; - w.PutStartBlock('Associations'); // do not localize + w.PutStartBlock('Associations'); TElementList.Write(Model.Associations, w); w.PutEndBlock; w.PutEndBlock; @@ -615,11 +616,12 @@ class procedure TModel.Write(element: TMoldElement; w: TWriter); if r.FormatVersion >= 11 then model.RootClass.Name := r.GetQuotedString; + if r.FormatVersion >= 12 then if r.formatVersion < 19 then Model.BoldTVByName[TAG_PMAPPERNAME] := r.GetQuotedString; if r.FormatVersion >= 13 then - if r.formatVersion < 19 then r.GetQuotedString; // legacy, was Model.DatabaseName + if r.formatVersion < 19 then r.GetQuotedString; if r.FormatVersion >= 15 then begin @@ -641,12 +643,12 @@ class procedure TModel.Write(element: TMoldElement; w: TWriter); end; {get classes} - r.EatStartBlock('Classes'); // do not localize + r.EatStartBlock('Classes'); r.CurrentModel := model; TElementList.Read(model, r); r.Eat(RPAR); - r.EatStartBlock('Associations'); // do not localize + r.EatStartBlock('Associations'); TElementList.Read(model, r); r.Eat(RPAR); r.Eat(RPAR); @@ -662,7 +664,6 @@ class procedure TElement.Write(element: TMoldElement; w: TWriter); class procedure TElement.Read(element: TMoldElement; r: TReader); begin - // Do nothing end; class function TElement.CreateAndRead(parent: TMoldElement; r: TReader): TMoldElement; @@ -700,7 +701,7 @@ class procedure TPClass.Write(element: TMoldElement; w: TWriter); begin with element as TMoldClass do begin - w.PutStartBlock('Class'); // do not localize + w.PutStartBlock('Class'); inherited write(element, w); w.PutClassReference(SuperClass); @@ -713,10 +714,10 @@ class procedure TPClass.Write(element: TMoldElement; w: TWriter); { version 17 } w.PutQuotedString(NonDefaultTaggedValuesCommaText); - w.PutStartBlock('Attributes'); // do not localize + w.PutStartBlock('Attributes'); TElementList.Write(Attributes, w); w.PutEndBlock; - w.PutStartBlock('Methods'); // do not localize + w.PutStartBlock('Methods'); TElementList.Write(Methods, w); w.PutEndBlock; w.PutEndBlock; @@ -727,12 +728,10 @@ class procedure TPClass.Read(element: TMoldElement; r: TReader); begin with element as TMoldClass do begin - // note special handling for classes inherited read(element, r); if r.formatVersion < 19 then BoldTVByName[TAG_TABLENAME] := r.GetQuotedString; if r.formatVersion < 19 then BoldTVByName[TAG_TABLEMAPPING] := TBoldTaggedValueSupport.TableMappingToString(TTableMapping(r.GetInteger)); - if r.formatVersion < 19 then r.GetInteger; // used to be classid, read for backward comaptibility + if r.formatVersion < 19 then r.GetInteger; SuperClass := r.GetClassReference; - // for older versions superclass may be nil but should be RootClass if (not Assigned(SuperClass)) and (Element <> Model.RootClass) then SuperClass := Model.RootClass; @@ -766,13 +765,13 @@ class procedure TPClass.Read(element: TMoldElement; r: TReader); if r.FormatVersion >= 17 then begin NonDefaultTaggedValuesCommaText := r.GetQuotedString; - end; + end; - r.EatStartBlock('Attributes'); // do not localize + r.EatStartBlock('Attributes'); TElementList.Read(element, r); r.Eat(RPAR); - r.EatStartBlock('Methods'); // do not localize + r.EatStartBlock('Methods'); TElementList.Read(element, r); r.Eat(RPAR); r.Eat(RPAR); @@ -784,7 +783,7 @@ class procedure TAttribute.Write(element: TMoldElement; w: TWriter); begin with Element as TMoldAttribute do begin - w.PutStartBlock('Attribute'); // do not localize + w.PutStartBlock('Attribute'); inherited write(element, w); w.PutQuotedString(BoldType); { version 3 } @@ -841,7 +840,7 @@ class procedure TAttribute.Read(element: TMoldElement; r: TReader); Stereotype := r.GetQuotedString; Constraints.CommaText := r.GetQuotedString; Visibility := TVisibilityKind(r.GetInteger); - if r.formatVersion < 19 then {DelphiField := }r.GetQuotedString; // removed in version 18 + if r.formatVersion < 19 then {DelphiField := }r.GetQuotedString; if r.formatVersion < 19 then BoldTVByName[TAG_DPREAD] := TBoldTaggedValueSupport.DelphiPropertyAccessKindToString(TDelphiPropertyAccessKind(r.GetInteger)); if r.formatVersion < 19 then BoldTVByName[TAG_DPWRITE] := TBoldTaggedValueSupport.DelphiPropertyAccessKindToString(TDelphiPropertyAccessKind(r.GetInteger)); if r.formatVersion < 19 then {DerivationOCL := }r.GetQuotedString; @@ -861,7 +860,6 @@ class procedure TAttribute.Read(element: TMoldElement; r: TReader); end else begin - // FIXME: Jan, ta ställning till vad de andra ska bli /fredrik 96-11-04 BoldTVByName[TAG_DELPHINAME] := ColumnName; end; r.Eat(RPAR); @@ -873,7 +871,7 @@ class procedure TMethod.Write(element: TMoldElement; w: TWriter); begin with element as TMoldMethod do begin - w.PutStartBlock('Method'); // do not localize + w.PutStartBlock('Method'); inherited write(element, w); w.PutQuotedString(Signature); w.PutBoolean(IsClassMethod); @@ -906,6 +904,7 @@ class procedure TMethod.Read(element: TMoldElement; r: TReader); if r.formatVersion < 19 then BoldTVByName[TAG_DELPHINAME] := r.GetQuotedString; end; + if r.FormatVersion >= 16 then begin Stereotype := r.GetQuotedString; @@ -931,7 +930,7 @@ class procedure TRole.Write(element: TMoldElement; w: TWriter); begin with element as TMoldRole do begin - w.PutStartBlock('Role'); // do not localize + w.PutStartBlock('Role'); inherited write(element, w); w.PutBoolean(Navigable); { version 2 } @@ -947,7 +946,7 @@ class procedure TRole.Write(element: TMoldElement; w: TWriter); { version 17 } w.PutQuotedString(NonDefaultTaggedValuesCommaText); { version 13} - w.PutStartBlock('Qualifiers'); // do not localize + w.PutStartBlock('Qualifiers'); TElementList.Write(Qualifiers, w); w.PutEndBlock; w.PutEndBlock; @@ -979,7 +978,7 @@ class procedure TRole.Read(element: TMoldElement;r: TReader); BoldTVByName[TAG_DELPHINAME] := ColumnName; if r.FormatVersion >= 4 then - if r.formatVersion < 19 then r.GetBoolean; // legacy, was Mandatory + if r.formatVersion < 19 then r.GetBoolean; if r.formatVersion < 19 then BoldTVByName[TAG_EMBED] := BooleanToString((r.FormatVersion < 9) or { Embed introduced in v9, default True } r.GetBoolean); @@ -1006,7 +1005,7 @@ class procedure TRole.Read(element: TMoldElement;r: TReader); if r.FormatVersion >= 14 then begin - r.EatStartBlock('Qualifiers'); // do not localize + r.EatStartBlock('Qualifiers'); TElementList.Read(element, r); r.Eat(RPAR); end; @@ -1020,7 +1019,7 @@ class procedure TQualifier.Write(element: TMoldElement; w: TWriter); begin with Element as TMoldQualifier do begin - w.PutStartBlock('Qualifier'); // do not localize + w.PutStartBlock('Qualifier'); inherited write(element, w); w.PutQuotedString(BoldType); { version 19 } @@ -1049,7 +1048,7 @@ class procedure TAssociation.Write(element: TMoldElement;w: TWriter); begin with element as TMoldAssociation do begin - w.PutStartBlock('Association'); // do not localize + w.PutStartBlock('Association'); inherited write(element, w); w.PutClassReference(LinkClass); { version 16 } @@ -1060,7 +1059,7 @@ class procedure TAssociation.Write(element: TMoldElement;w: TWriter); { version 19 } w.PutBoolean(Derived); - w.PutStartBlock('Roles'); // do not localize + w.PutStartBlock('Roles'); TElementList.Write(Roles, w); w.PutEndBlock; w.PutEndBlock; @@ -1081,18 +1080,16 @@ class procedure TAssociation.Read(element: TMoldElement;r: TReader); Stereotype := r.GetQuotedString; Constraints.CommaText := r.GetQuotedString; end; - // support for older versions that did not store "Persistent" for associations StdTVByName[TAG_PERSISTENCE] := TV_PERSISTENCE_PERSISTENT; if r.FormatVersion >= 17 then begin NonDefaultTaggedValuesCommaText := r.GetQuotedString; end; - // Get aRole list if r.FormatVersion >= 19 then Derived := r.GetBoolean; - r.EatStartBlock('Roles'); // do not localize + r.EatStartBlock('Roles'); TElementList.Read(element, r); r.Eat(RPAR); r.Eat(RPAR); @@ -1104,13 +1101,13 @@ class procedure TAssociation.Read(element: TMoldElement;r: TReader); var TypeTable: array [typetableIndex] of TElementClassRecord = ( - (elementClass: TModel; moldElementClass: TMoldModel; name: 'Model'), // do not localize - (elementClass: TPClass; moldElementClass: TMoldClass; name: 'Class'), // do not localize - (elementClass: TAttribute; moldElementClass: TMoldAttribute; name: 'Attribute'), // do not localize - (elementClass: TMethod; moldElementClass: TMoldMethod; name: 'Method'), // do not localize - (elementClass: TAssociation; moldElementClass: TMoldAssociation; name: 'Association'), // do not localize - (elementClass: TRole; moldElementClass: TMoldRole; name: 'Role'), // do not localize - (elementClass: TQualifier; moldElementClass: TMoldQualifier; name: 'Qualifier') // do not localize + (elementClass: TModel; moldElementClass: TMoldModel; name: 'Model'), + (elementClass: TPClass; moldElementClass: TMoldClass; name: 'Class'), + (elementClass: TAttribute; moldElementClass: TMoldAttribute; name: 'Attribute'), + (elementClass: TMethod; moldElementClass: TMoldMethod; name: 'Method'), + (elementClass: TAssociation; moldElementClass: TMoldAssociation; name: 'Association'), + (elementClass: TRole; moldElementClass: TMoldRole; name: 'Role'), + (elementClass: TQualifier; moldElementClass: TMoldQualifier; name: 'Qualifier') ); function TypeTableByMoldElement(moldElement: TMoldElement): TElementClassRecord; @@ -1123,7 +1120,7 @@ function TypeTableByMoldElement(moldElement: TMoldElement): TElementClassRecord; Result := typetable[i]; Exit; end; - raise EBoldInternal.Create('TypeTableByMoldElement: moldElementClass not found in typetable'); // do not localize + raise EBoldInternal.Create('TypeTableByMoldElement: moldElementClass not found in typetable'); end; function TypeTableByName(name: string): TElementClassRecord; @@ -1136,7 +1133,7 @@ function TypeTableByName(name: string): TElementClassRecord; Result := typetable[i]; Exit; end; - raise EBoldInternal.CreateFmt('TypeTableByName: %s not found in typetable', [name]); // do not localize + raise EBoldInternal.CreateFmt('TypeTableByName: %s not found in typetable', [name]); end; function BooleanToMultiplicityString(Value: Boolean): String; @@ -1147,4 +1144,6 @@ function BooleanToMultiplicityString(Value: Boolean): String; Result := '1'; end; +initialization + end. diff --git a/Source/MoldModel/CodeGenerator/BoldGen.pas b/Source/MoldModel/CodeGenerator/BoldGen.pas index a595108..708a53d 100644 --- a/Source/MoldModel/CodeGenerator/BoldGen.pas +++ b/Source/MoldModel/CodeGenerator/BoldGen.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldGen; interface @@ -8,14 +11,14 @@ interface BoldTypeNameDictionary, BoldFileHandler, BoldTemplateExpander, - BoldDefs, - BoldMoldConsts; + BoldDefs; const INDENTSIZE = 2; DEBUGGERWORKAROUNDINTERVAL = 50; AddVisitorSupport = true; + type TBoldGenerator = class; TBoldGeneratorClass = class of TBoldGenerator; @@ -45,6 +48,7 @@ TBoldGenerator = class fGenerateMIDLCode: boolean; fGenerateIDLVariables: Boolean; procedure EnsureMethod(Strings: TStrings); + procedure InitializeTemplateForComponent(Template: TBoldTemplateHolder; Model: TMoldModel; Component: TMoldComponent; InitializeClasses: Boolean); virtual; function MethodToDelphiHeader(OwningClass: TMoldClass; Method: TMoldMethod; TagValue: Integer; AddSignature: Boolean; AutoOverride: Boolean): String; function MethodToCOMHeader(OwningClass: TMoldClass; Method: TMoldMethod; InterfaceCode: Boolean; ParametersToCoerce, ParametersToInterfaceCoerce: TStringList): String; function MethodToIDLHeader(OwningClass: TMoldClass; Method: TMoldMethod): String; @@ -63,7 +67,6 @@ TBoldGenerator = class property MethodIndex: TStringList read fMethodIndex; function FindInCurrentFile(s: String): Boolean; procedure InitializeMethodIndex; - procedure InitializeTemplateForComponent(Template: TBoldTemplateHolder; Model: TMoldModel; Component: TMoldComponent; InitializeClasses: Boolean); virtual; property CurrentClass: TMoldClass read fCurrentClass write fCurrentClass; property GenerateIDLVariables: Boolean read fGenerateIDLVariables write fGenerateIDLVariables; public @@ -168,7 +171,7 @@ procedure TBoldGenerator.ExpandTemplatelist(TemplateList: TBoldTemplateList); BoldLog.ProgressMax := MoldModel.Classes.Count * 3; - BoldLog.LogFmt(sLogGeneratingInPath, [BaseFilePath]); + BoldLog.LogFmt('Generating in path: %s', [BaseFilePath]); for ComponentIx := 0 to MoldModel.Components.Count - 1 do begin for TemplateIx := 0 to TemplateList.Count - 1 do @@ -178,30 +181,30 @@ procedure TBoldGenerator.ExpandTemplatelist(TemplateList: TBoldTemplateList); with TemplateList[TemplateIx] do begin - Variables.SetVariable('COMPONENTNAME', MoldModel.Components[ComponentIx].Name); // do not localize - BoldLog.LogFmt(sLogGeneratingFile, [ExpandedFileName]); + Variables.SetVariable('COMPONENTNAME', MoldModel.Components[ComponentIx].Name); + BoldLog.LogFmt('Generating file: %s', [ExpandedFileName]); SetCurrentFileHandler(BaseFilePath, ExpandedFileName, ModuleTypeForFile(ExpandedFileName), true, false); BoldFilehandler.Clear; - BoldLog.LogHeader := sLogInitializingVars; + BoldLog.LogHeader := 'Initializing variables'; InitializeTemplateForComponent(TemplateList[TemplateIx], MoldModel, MoldModel.Components[ComponentIx], true); if BoldLog.ProcessInterruption then exit; - - BoldLog.LogHeader := sLogExpandingTemplate; + + BoldLog.LogHeader := 'Expanding template'; BoldFilehandler.AddStrings(ExpandedTemplate); end; end; end; - if MoldModel.MainComponent.Name = BoldDefaultTaggedValueList.DefaultForClassAndTag['Model', TAG_UNITNAME] then // do not localize + if MoldModel.MainComponent.Name = BoldDefaultTaggedValueList.DefaultForClassAndTag['Model', TAG_UNITNAME] then begin BoldLog.Separator; - BoldLog.Log(sLogConsiderNameChange1, ltWarning); - BoldLog.Log(sLogConsiderNameChange2, ltWarning); + BoldLog.Log('You should consider naming your model and base unit', ltWarning); + BoldLog.Log('to avoid filename conflicts with other projects', ltWarning); BoldLog.Separator; end; end; @@ -231,12 +234,12 @@ procedure TBoldGenerator.InitializeTemplateForComponent(Template: TBoldTemplateH procedure internalInitialize; begin - AddVariable('MEMBERHASNATIVE' + PostFix, '1'); // do not localize + AddVariable('MEMBERHASNATIVE' + PostFix, '1'); if not MoldAttribute.Derived or MoldAttribute.ReverseDerived then - AddVariable('MEMBERISSETABLE' + PostFix, '1') // do not localize + AddVariable('MEMBERISSETABLE' + PostFix, '1') else - AddVariable('MEMBERISSETABLE' + PostFix, '0'); // do not localize - end; + AddVariable('MEMBERISSETABLE' + PostFix, '0'); + end; begin Mapping := TypeNameDictionary.MappingForModelName[MoldAttribute.BoldType]; @@ -244,11 +247,11 @@ procedure TBoldGenerator.InitializeTemplateForComponent(Template: TBoldTemplateH begin if UnmappedTypes.IndexOf(MoldAttribute.BoldType) = -1 then begin - BoldLog.LogFmt(sLogNoDelphiMappingForType, [MoldAttribute.BoldType], ltWarning); + BoldLog.LogFmt('No Delphimapping for type %s', [MoldAttribute.BoldType], ltWarning); UnmappedTypes.Add(MoldAttribute.BoldType); end; - Typename := 'TBoldAttribute'; // do not localize - ValueInterfacename := 'IBoldNullableValue'; // do not localize + Typename := 'TBoldAttribute'; + ValueInterfacename := 'IBoldNullableValue'; end else begin TypeName := Mapping.ExpandedDelphiName; @@ -259,16 +262,16 @@ procedure TBoldGenerator.InitializeTemplateForComponent(Template: TBoldTemplateH (Mapping.IDLType <> '') then begin internalInitialize; - AddVariable('MEMBERNATIVECOMTYPE' + PostFix, Mapping.ExpandedCOMType); // do not localize - AddVariable('MEMBERNATIVEIDLTYPE' + PostFix, Mapping.IDLType); // do not localize - AddVariable('DISPID' + PostFix, IntToHex(MoldAttribute.DispId, 8)); // do not localize + AddVariable('MEMBERNATIVECOMTYPE' + PostFix, Mapping.ExpandedCOMType); + AddVariable('MEMBERNATIVEIDLTYPE' + PostFix, Mapping.IDLType); + AddVariable('DISPID' + PostFix, IntToHex(MoldAttribute.DispId, 8)); if CompareText(Mapping.ExpandedCOMType, BoldWideStringTypeName) = 0 then - AddVariable('SETMEMBERASCONST' + PostFix, 'const '); // do not localize + AddVariable('SETMEMBERASCONST' + PostFix, 'const '); end else if typesWithoutNative.IndexOf(MoldAttribute.BoldType) = -1 then begin - BoldLog.LogFmt(sLogNoCOMMappingForType, [MoldAttribute.BoldType, MoldAttribute.MoldClass.Name, MoldAttribute.Name], ltWarning); + BoldLog.LogFmt('No COM/IDL mapping for type %s, No attribute generated for %s.%s', [MoldAttribute.BoldType, MoldAttribute.MoldClass.Name, MoldAttribute.Name], ltWarning); typesWithoutNative.Add(MoldAttribute.BoldType); end; end @@ -278,40 +281,39 @@ procedure TBoldGenerator.InitializeTemplateForComponent(Template: TBoldTemplateH (Mapping.ExpandedNativeType <> '') then begin internalInitialize; - AddVariable('MEMBERNATIVEACCESSOR' + PostFix, Mapping.ExpandedAccessor); // do not localize - AddVariable('MEMBERNATIVETYPE' + PostFix, Mapping.ExpandedNativeType); // do not localize + AddVariable('MEMBERNATIVEACCESSOR' + PostFix, Mapping.ExpandedAccessor); + AddVariable('MEMBERNATIVETYPE' + PostFix, Mapping.ExpandedNativeType); end else begin - if typesWithoutNative.IndexOf(MoldAttribute.BoldType) = -1 then + if GenerateIDLVariables and (typesWithoutNative.IndexOf(MoldAttribute.BoldType) = -1) then begin - BoldLog.LogFmt(sLogNoNativeMappingForType, [MoldAttribute.BoldType, MoldAttribute.Name, MoldAttribute.MoldClass.Name], ltWarning); + BoldLog.LogFmt('No native mapping for type %s used in attribute %s.%s, only Bold attribute generated', [MoldAttribute.BoldType, MoldAttribute.Name, MoldAttribute.MoldClass.Name], ltWarning); typesWithoutNative.Add(MoldAttribute.BoldType); end; end; - if MoldAttribute.EffectivePersistent then + if MoldAttribute.EffectivePersistent and + (Mapping.ValueInterfaceAccessor <> '') and + (Mapping.ValueInterfaceNativeType <> '') then begin - if (Mapping.ValueInterfaceAccessor <> '') and - (Mapping.ValueInterfaceNativeType <> '') then + AddVariable('MEMBERHASVALUEINTERFACENATIVE' + PostFix, '1'); + AddVariable('MEMBERVALUEINTERFACENATIVEACCESSOR' + PostFix, Mapping.ValueInterfaceAccessor); + AddVariable('MEMBERVALUEINTERFACENATIVETYPE' + PostFix, Mapping.ValueInterfaceNativeType); + end + else begin + if GenerateIDLVariables and (typesWithoutNative.IndexOf(MoldAttribute.BoldType) = -1) then begin - AddVariable('MEMBERHASVALUEINTERFACENATIVE' + PostFix, '1'); // do not localize - AddVariable('MEMBERVALUEINTERFACENATIVEACCESSOR' + PostFix, Mapping.ValueInterfaceAccessor); // do not localize - AddVariable('MEMBERVALUEINTERFACENATIVETYPE' + PostFix, Mapping.ValueInterfaceNativeType); // do not localize - end - else begin - if typesWithoutNative.IndexOf(MoldAttribute.BoldType) = -1 then - begin - BoldLog.LogFmt(sNoValueTypeMappingForType, [MoldAttribute.BoldType, MoldAttribute.Name, MoldAttribute.MoldClass.Name], ltWarning); - typesWithoutNative.Add(MoldAttribute.BoldType); - end; + BoldLog.LogFmt('No native mapping for type %s used in attribute %s.%s, only Bold attribute generated', [MoldAttribute.BoldType, MoldAttribute.Name, MoldAttribute.MoldClass.Name], ltWarning); + typesWithoutNative.Add(MoldAttribute.BoldType); end; end; + end; end; - AddVariable('MEMBERTYPE' + PostFix, TypeName); // do not localize - addVariable('MEMBERVALUEINTERFACE'+PostFix, ValueInterfaceName); // do not localize - AddVariable('MEMBERKIND' + PostFix, 'Attribute'); // do not localize - AddVariable('MEMBERVISIBILITY' + PostFix, VisibilityTOString[MoldAttribute.Visibility]); // do not localize + AddVariable('MEMBERTYPE' + PostFix, TypeName); + addVariable('MEMBERVALUEINTERFACE'+PostFix, ValueInterfaceName); + AddVariable('MEMBERKIND' + PostFix, 'Attribute'); + AddVariable('MEMBERVISIBILITY' + PostFix, VisibilityTOString[MoldAttribute.Visibility]); end; procedure InitializeNativeAttribute(MoldAttribute: TMoldAttribute; const PostFix: String); @@ -322,13 +324,13 @@ procedure TBoldGenerator.InitializeTemplateForComponent(Template: TBoldTemplateH ('None', 'Field', 'PrivateMethod', 'ProtectedVirtualMethod'); begin TypeName := GetNativeDelphiTypeForModelNameNoDefaults(MoldAttribute); - AddVariable('DelphiAttributeType' + PostFix, TypeName); // do not localize - AddVariable('DelphiAttributeKind' + PostFix, 'Attribute'); // do not localize - AddVariable('DelphiAttributeHasField' + PostFix, BoldBooleanToTemplateVar[MoldAttribute.HasDelphiField]); // do not localize + AddVariable('DelphiAttributeType' + PostFix, TypeName); + AddVariable('DelphiAttributeKind' + PostFix, 'Attribute'); + AddVariable('DelphiAttributeHasField' + PostFix, BoldBooleanToTemplateVar[MoldAttribute.HasDelphiField]); - AddVariable('DelphiAttributeVisibility' + PostFix, VisibilityToString[MoldAttribute.Visibility]); // do not localize - AddVariable('DelphiAttributePropertyRead' + PostFix, PropertyAccessKindToStr[MoldAttribute.DelphiPropertyRead]); // do not localize - AddVariable('DelphiAttributePropertyWrite' + PostFix, PropertyAccessKindToStr[MoldAttribute.DelphiPropertyWrite]); // do not localize + AddVariable('DelphiAttributeVisibility' + PostFix, VisibilityToString[MoldAttribute.Visibility]); + AddVariable('DelphiAttributePropertyRead' + PostFix, PropertyAccessKindToStr[MoldAttribute.DelphiPropertyRead]); + AddVariable('DelphiAttributePropertyWrite' + PostFix, PropertyAccessKindToStr[MoldAttribute.DelphiPropertyWrite]); end; procedure InitializeQualifier(MoldRole: TMoldRole; const PostFix: String); @@ -353,9 +355,9 @@ procedure TBoldGenerator.InitializeTemplateForComponent(Template: TBoldTemplateH Mapping := TypeNameDictionary.MappingForModelName[AttrOfOtherEnd.BoldType]; if assigned(Mapping) then begin - AddVariable('QUALIFIERNAME' + PostFix + '.' + IntToStr(i), AttrOfOtherEnd.ExpandedDelphiName); // do not localize - AddVariable('QUALIFIERBOLDTYPE' + PostFix + '.' + IntToStr(i), Mapping.ExpandedDelphiName); // do not localize - AddVariable('QUALIFIERACCESSOR' + PostFix + '.' + IntToStr(i), Mapping.ExpandedAccessor); // do not localize + AddVariable('QUALIFIERNAME' + PostFix + '.' + IntToStr(i), AttrOfOtherEnd.ExpandedDelphiName); + AddVariable('QUALIFIERBOLDTYPE' + PostFix + '.' + IntToStr(i), Mapping.ExpandedDelphiName); + AddVariable('QUALIFIERACCESSOR' + PostFix + '.' + IntToStr(i), Mapping.ExpandedAccessor); BoldGeneratorTemplatesManager.AddQualifierPropertyParam(QualifierPropertyParams, AttrOfOtherEnd.ExpandedDelphiName, Mapping.ExpandedNativeType); BoldGeneratorTemplatesManager.AddQualifierFunctionParam(QualifierFunctionParams, AttrOfOtherEnd.ExpandedDelphiName, Mapping.ExpandedNativeType); end @@ -365,10 +367,10 @@ procedure TBoldGenerator.InitializeTemplateForComponent(Template: TBoldTemplateH else AllOK := false; end; - AddVariable('QUALIFIERPROPERTYPARAMS' + PostFix, QualifierPropertyParams); // do not localize - AddVariable('QUALIFIERFUNCTIONPARAMS' + PostFix, QualifierFunctionParams); // do not localize - AddVariable('ROLEQUALIFIED' + PostFix, BoldBooleanToTemplateVar[AllOK and (MoldRole.Qualifiers.Count > 0)]); // do not localize - AddVariable('QUALIFIERCOUNT' + PostFix, IntToStr(MoldRole.Qualifiers.Count)); // do not localize + AddVariable('QUALIFIERPROPERTYPARAMS' + PostFix, QualifierPropertyParams); + AddVariable('QUALIFIERFUNCTIONPARAMS' + PostFix, QualifierFunctionParams); + AddVariable('ROLEQUALIFIED' + PostFix, BoldBooleanToTemplateVar[AllOK and (MoldRole.Qualifiers.Count > 0)]); + AddVariable('QUALIFIERCOUNT' + PostFix, IntToStr(MoldRole.Qualifiers.Count)); end; procedure InitializeRole(MoldRole: TMoldRole; const PostFix: String); @@ -379,50 +381,48 @@ procedure TBoldGenerator.InitializeTemplateForComponent(Template: TBoldTemplateH OtherEnd := MoldRole.MoldClass.LowestVisibleAncestor(MoldRole.OtherEnd.MoldClass); if (not MoldRole.Multi or UseTypedLists) and assigned(OtherEnd) then begin - AddVariable('MEMBERTYPE' + PostFix, OtherEnd.ExpandedDelphiName); // do not localize - AddVariable('MEMBERPERSISTENCEINTERFACE'+PostFix, MakePersistenceInterfaceName(OtherEnd)); // do not localize + AddVariable('MEMBERTYPE' + PostFix, OtherEnd.ExpandedDelphiName); + AddVariable('MEMBERPERSISTENCEINTERFACE'+PostFix, MakePersistenceInterfaceName(OtherEnd)); if GenerateIDLVariables then begin if GenerateMIDLCode then - AddVariable('MEMBERCOMTYPE' + PostFix, OtherEnd.ExpandedInterfaceName) // do not localize + AddVariable('MEMBERCOMTYPE' + PostFix, OtherEnd.ExpandedInterfaceName) else begin IDLTypeOfOtherEnd := MoldRole.MoldClass.LowestCommonSuperClass(OtherEnd); - - // stupid DelphiIDL-parser will not allow a list to know its own list-class since it is declared below itself if MoldRole.Multi and (MoldRole.MoldClass = IDLTypeOfOtherEnd) then IDLTypeOfOtherEnd := MoldRole.MoldClass.SuperClass; if assigned(IDLTypeOfOtherEnd) then - AddVariable('MEMBERCOMTYPE' + PostFix, IDLTypeOfOtherEnd.ExpandedInterfaceName) // do not localize + AddVariable('MEMBERCOMTYPE' + PostFix, IDLTypeOfOtherEnd.ExpandedInterfaceName) else - AddVariable('MEMBERCOMTYPE' + PostFix, 'IBoldObjectList') // do not localize + AddVariable('MEMBERCOMTYPE' + PostFix, 'IBoldObjectList') end; - AddVariable('MEMBERREALCOMTYPE' + PostFix, OtherEnd.ExpandedInterfaceName); // do not localize + AddVariable('MEMBERREALCOMTYPE' + PostFix, OtherEnd.ExpandedInterfaceName); end; end else begin - AddVariable('MEMBERTYPE' + PostFix, 'TBoldObject'); // do not localize + AddVariable('MEMBERTYPE' + PostFix, 'TBoldObject'); if GenerateIDLVariables then begin - AddVariable('MEMBERCOMTYPE' + PostFix, 'IBoldObject'); // do not localize - AddVariable('MEMBERREALCOMTYPE' + PostFix, 'IBoldObject'); // do not localize + AddVariable('MEMBERCOMTYPE' + PostFix, 'IBoldObject'); + AddVariable('MEMBERREALCOMTYPE' + PostFix, 'IBoldObject'); end; end; - AddVariable('DISPID' + PostFix, IntToHex(MoldRole.Dispid, 8)); // do not localize + AddVariable('DISPID' + PostFix, IntToHex(MoldRole.Dispid, 8)); if MoldRole.Multi then - AddVariable('MEMBERKIND' + PostFix, 'MultiRole') // do not localize + AddVariable('MEMBERKIND' + PostFix, 'MultiRole') else - AddVariable('MEMBERKIND' + PostFix, 'SingleRole'); // do not localize + AddVariable('MEMBERKIND' + PostFix, 'SingleRole'); - AddVariable('ISTRUEROLE' + PostFix, BoldBooleanToTemplateVar[MoldRole.RoleType = rtRole]); // do not localize - AddVariable('MEMBERVISIBILITY' + PostFix, VisibilityTOString[MoldRole.Visibility]); // do not localize - AddVariable('ROLENAVIGABLE' + PostFix, BoldBooleanToTemplateVar[MoldRole.Navigable]); // do not localize + AddVariable('ISTRUEROLE' + PostFix, BoldBooleanToTemplateVar[MoldRole.RoleType = rtRole]); + AddVariable('MEMBERVISIBILITY' + PostFix, VisibilityTOString[MoldRole.Visibility]); + AddVariable('ROLENAVIGABLE' + PostFix, BoldBooleanToTemplateVar[MoldRole.Navigable]); InitializeQualifier(MoldRole, PostFix); end; @@ -437,32 +437,31 @@ procedure TBoldGenerator.InitializeTemplateForComponent(Template: TBoldTemplateH if assigned(MoldClass) then case kind of - 0: result := 'object'; // do not localize + 0: result := 'object'; 1: result := ParameterDelphiType; 2: result := ''; end - else if SameText(ParameterType, 'STRING') then // do not localize + else if SameText(ParameterType, 'STRING') then case kind of - 0: result := 'attribute'; // do not localize - 1: result := 'TBAString'; // do not localize - 2: result := '.AsString'; // do not localize + 0: result := 'attribute'; + 1: result := 'TBAString'; + 2: result := '.AsString'; end - else if SameText(ParameterType, 'INTEGER') then // do not localize + else if SameText(ParameterType, 'INTEGER') then case kind of - 0: result := 'attribute'; // do not localize - 1: result := 'TBAInteger'; // do not localize - 2: result := '.AsInteger'; // do not localize + 0: result := 'attribute'; + 1: result := 'TBAInteger'; + 2: result := '.AsInteger'; end - else if SameText(ParameterType, 'DOUBLE') then // do not localize + else if SameText(ParameterType, 'DOUBLE') then case kind of - 0: result := 'attribute'; // do not localize - 1: result := 'TBAFloat'; // do not localize - 2: result := '.AsFloat'; // do not localize + 0: result := 'attribute'; + 1: result := 'TBAFloat'; + 2: result := '.AsFloat'; end else - Template.Variables.SetVariable('CASEMETHODISOCLCOMPATIBLE', '0'); // do not localize + Template.Variables.SetVariable('CASEMETHODISOCLCOMPATIBLE', '0'); end; - procedure InitializeDispIdMethod(MoldMethod: TMoldMethod; const postfix: String; DispIdOffset: integer); var i: integer; @@ -478,21 +477,19 @@ procedure TBoldGenerator.InitializeTemplateForComponent(Template: TBoldTemplateH ParametersToCoerce := TStringList.Create; ParametersToInterfaceCoerce := TStringList.create; try - AddVariable('COMMETHODHEADERINTERFACE' + PostFix, MethodToCOMHeader(MoldMethod.MoldClass, MoldMethod, true, ParametersToCoerce, ParametersToInterfaceCoerce)); // do not localize + AddVariable('COMMETHODHEADERINTERFACE' + PostFix, MethodToCOMHeader(MoldMethod.MoldClass, MoldMethod, true, ParametersToCoerce, ParametersToInterfaceCoerce)); if (ParametersToInterfaceCoerce.Count + ParametersTocoerce.Count) <> 0 then begin - // Com-adapter declares strings as WideString, but delphiclass as string... we must convert them if they are var-declared - VarDeclString := 'var' + BOLDCRLF; // do not localize + VarDeclString := 'var' + BOLDCRLF; ConvertString := ''; ConvertBackString := ''; for i := 0 to ParametersToCoerce.Count - 1 do begin - VarDeclString := VarDeclString + ' ' + ParametersToCoerce.Names[i] + '_temp: '+ ParametersToCoerce.values[ParametersToCoerce.Names[i]] + ';' + BOLDCRLF; // do not localize - ConvertString := ConvertString + ' ' + ParametersToCoerce.Names[i] + '_temp := ' + ParametersToCoerce.Names[i] + ';' + BOLDCRLF; // do not localize - ConvertBackString := ConvertBackString + ' ' + ParametersToCoerce.names[i] +' := ' + ParametersToCoerce.Names[i] + '_temp;' + BOLDCRLF; // do not localize + VarDeclString := VarDeclString + ' ' + ParametersToCoerce.Names[i] + '_temp: '+ ParametersToCoerce.values[ParametersToCoerce.Names[i]] + ';' + BOLDCRLF; + ConvertString := ConvertString + ' ' + ParametersToCoerce.Names[i] + '_temp := ' + ParametersToCoerce.Names[i] + ';' + BOLDCRLF; + ConvertBackString := ConvertBackString + ' ' + ParametersToCoerce.names[i] +' := ' + ParametersToCoerce.Names[i] + '_temp;' + BOLDCRLF; end; - for i := 0 to ParametersToInterfaceCoerce.Count - 1 do begin ParamName := ParametersToInterfaceCoerce.Names[i]; @@ -501,21 +498,21 @@ procedure TBoldGenerator.InitializeTemplateForComponent(Template: TBoldTemplateH ParamType := Copy(ParamType, 1, pos('=', ParamType) - 1); varDeclString := VarDeclString + - format(' %s_temp: %s;' + BOLDCRLF, [ParamName, ParamType]); // do not localize + format(' %s_temp: %s;' + BOLDCRLF, [ParamName, ParamType]); ConvertString := ConvertString + - format(' %s_temp := BoldComInterfaceToObject(%s) as %s;' + BOLDCRLF, [ParamName, ParamName, ParamType]); // do not localize + format(' %s_temp := BoldComInterfaceToObject(%s) as %s;' + BOLDCRLF, [ParamName, ParamName, ParamType]); ConvertBackString := ConvertBackString + - format(' BoldComCreateAdapter(%s_temp, False, %s, %s);' + BOLDCRLF, [ParamName, ParamInterfaceType, ParamName]); // do not localize + format(' BoldComCreateAdapter(%s_temp, False, %s, %s);' + BOLDCRLF, [ParamName, ParamInterfaceType, ParamName]); end; - AddVariable('COMMETHOD_TEMPVARS' + PostFix, VarDeclString); // do not localize - AddVariable('COMMETHOD_TEMPVARSCONVERT' + PostFix, ConvertString); // do not localize - AddVariable('COMMETHOD_TEMPVARSCONVERTBACK' + PostFix, ConvertBackString); // do not localize + AddVariable('COMMETHOD_TEMPVARS' + PostFix, VarDeclString); + AddVariable('COMMETHOD_TEMPVARSCONVERT' + PostFix, ConvertString); + AddVariable('COMMETHOD_TEMPVARSCONVERTBACK' + PostFix, ConvertBackString); end; - AddVariable('COMMETHODHEADERIMPLEMENTATION' + PostFix, MethodToCOMHeader(MoldMethod.MoldClass, MoldMethod, false, nil, nil)); // do not localize - AddVariable('METHODWRAPPERCALL' + PostFix, MethodToComCall(MoldMethod.MoldClass, MoldMethod, parametersToCoerce, ParametersToInterfaceCoerce)); // do not localize - AddVariable('IDLMETHODHEADER' + PostFix, MethodToIDLHeader(MoldMethod.MoldClass, MoldMethod)); // do not localize - AddVariable('METHODDISPID' + PostFix, IntToHex(DispIdOffset, 8)); // do not localize + AddVariable('COMMETHODHEADERIMPLEMENTATION' + PostFix, MethodToCOMHeader(MoldMethod.MoldClass, MoldMethod, false, nil, nil)); + AddVariable('METHODWRAPPERCALL' + PostFix, MethodToComCall(MoldMethod.MoldClass, MoldMethod, parametersToCoerce, ParametersToInterfaceCoerce)); + AddVariable('IDLMETHODHEADER' + PostFix, MethodToIDLHeader(MoldMethod.MoldClass, MoldMethod)); + AddVariable('METHODDISPID' + PostFix, IntToHex(DispIdOffset, 8)); finally ParametersToCoerce.Free; end; @@ -526,45 +523,43 @@ procedure TBoldGenerator.InitializeTemplateForComponent(Template: TBoldTemplateH i: integer; MethodType: String; begin - AddVariable('INTERFACEMETHODHEADER' + PostFix, MethodToDelphiHeader(MoldMethod.MoldClass, MoldMethod, Publictag, true, AutoOverride)); // do not localize - AddVariable('METHODNAME' + PostFix, MoldMethod.ExpandedDelphiName); // do not localize - AddVariable('METHODVISIBILITY' + PostFix, visibilityToString[MoldMethod.Visibility]); // do not localize + AddVariable('INTERFACEMETHODHEADER' + PostFix, MethodToDelphiHeader(MoldMethod.MoldClass, MoldMethod, Publictag, true, AutoOverride)); + AddVariable('METHODNAME' + PostFix, MoldMethod.ExpandedDelphiName); + AddVariable('METHODVISIBILITY' + PostFix, visibilityToString[MoldMethod.Visibility]); if MoldMethod.IsClassMethod then - MethodType := 'class ' // do not localize + MethodType := 'class ' else MethodType := ''; if MoldMethod.HasReturnValue then - MethodType := methodType + 'function' // do not localize + MethodType := methodType + 'function' else - MethodType := methodType + 'procedure'; // do not localize + MethodType := methodType + 'procedure'; - AddVariable('METHODKIND' + PostFix, MethodType); // do not localize + AddVariable('METHODKIND' + PostFix, MethodType); - AddVariable('METHODISOCLCOMPATIBLE' + PostFix, '1'); // do not localize + AddVariable('METHODISOCLCOMPATIBLE' + PostFix, '1'); if MoldMethod.HasReturnValue then begin - AddVariable('METHODRESULTBOLDTYPE' + PostFix, ParameterInfo(MoldMethod, MoldMethod.ReturnType, MoldMethod.DelphiReturnType, 1)); // do not localize - AddVariable('METHODRESULTACCESSOR' + PostFix, ParameterInfo(MoldMethod, MoldMethod.ReturnType, MoldMethod.DelphiReturnType, 2)); // do not localize - end - else - begin - AddVariable('METHODRESULTBOLDTYPE' + PostFix, 'TBAInteger'); // do not localize - AddVariable('METHODRESULTACCESSOR' + PostFix, '.AsInteger'); // do not localize + AddVariable('METHODRESULTBOLDTYPE' + PostFix, ParameterInfo(MoldMethod, MoldMethod.ReturnType, MoldMethod.DelphiReturnType, 1)); + AddVariable('METHODRESULTACCESSOR' + PostFix, ParameterInfo(MoldMethod, MoldMethod.ReturnType, MoldMethod.DelphiReturnType, 2)); + end else begin + AddVariable('METHODRESULTBOLDTYPE' + PostFix, 'TBAInteger'); + AddVariable('METHODRESULTACCESSOR' + PostFix, '.AsInteger'); end; for i := 0 to MoldMethod.Parameters.count - 1 do begin with TMoldParameter(MoldMethod.Parameters[i]) do begin - AddVariable('METHODPARAMETERKIND' + PostFix + '.' + IntToStr(i), ParameterInfo(MoldMethod, ParameterType, DelphiParameterType, 0)); // do not localize - AddVariable('METHODPARAMETERBOLDTYPE' + PostFix + '.' + IntToStr(i), ParameterInfo(MoldMethod, ParameterType, DelphiParameterType, 1)); // do not localize - AddVariable('METHODPARAMETERACCESSOR' + PostFix + '.' + IntToStr(i), ParameterInfo(MoldMethod, ParameterType, DelphiParameterType, 2)); // do not localize + AddVariable('METHODPARAMETERKIND' + PostFix + '.' + IntToStr(i), ParameterInfo(MoldMethod, ParameterType, DelphiParameterType, 0)); + AddVariable('METHODPARAMETERBOLDTYPE' + PostFix + '.' + IntToStr(i), ParameterInfo(MoldMethod, ParameterType, DelphiParameterType, 1)); + AddVariable('METHODPARAMETERACCESSOR' + PostFix + '.' + IntToStr(i), ParameterInfo(MoldMethod, ParameterType, DelphiParameterType, 2)); end; end; - AddVariable('METHODPARAMETERCOUNT' + PostFix, IntToStr(MoldMethod.Parameters.count)); // do not localize + AddVariable('METHODPARAMETERCOUNT' + PostFix, IntToStr(MoldMethod.Parameters.count)); end; procedure InitializeClass(MoldClass: TMoldClass; const PostFix: String); @@ -573,55 +568,59 @@ procedure TBoldGenerator.InitializeTemplateForComponent(Template: TBoldTemplateH Attribute: TMoldAttribute; Member: TMoldMember; MemberPostFix: String; + MethodCount : Integer; begin - AddVariable('CLASSNAME' + PostFix, MoldClass.ExpandedDelphiName); // do not localize + AddVariable('CLASSNAME' + PostFix, MoldClass.ExpandedDelphiName); if MoldClass.GUID <> '' then - AddVariable('CLASSGUID' + PostFix, MoldClass.GUID) // do not localize + AddVariable('CLASSGUID' + PostFix, MoldClass.GUID) else - AddVariable('CLASSGUID' + PostFix, BoldCreateGUIDAsString(true)); // do not localize + AddVariable('CLASSGUID' + PostFix, BoldCreateGUIDAsString(true)); if MoldClass.ListGUID <> '' then - AddVariable('LISTGUID' + PostFix, MoldClass.ListGUID) // do not localize + AddVariable('LISTGUID' + PostFix, MoldClass.ListGUID) else - AddVariable('LISTGUID' + PostFix, BoldCreateGUIDAsString(true)); // do not localize + AddVariable('LISTGUID' + PostFix, BoldCreateGUIDAsString(true)); - AddVariable('INTERFACENAME' + PostFix, MoldClass.ExpandedInterfaceName); // do not localize - AddVariable('PERSISTENCEINTERFACENAME' + PostFix, MakePersistenceInterfaceName(MoldClass)); // do not localize - AddVariable('PERSISTENCEINTERFACEGUID' + PostFix, BoldCreateGUIDWithBracketsAsString); // do not localize + AddVariable('INTERFACENAME' + PostFix, MoldClass.ExpandedInterfaceName); + AddVariable('PERSISTENCEINTERFACENAME' + PostFix, MakePersistenceInterfaceName(MoldClass)); + AddVariable('PERSISTENCEINTERFACEGUID' + PostFix, BoldCreateGUIDWithBracketsAsString); - AddVariable('ISVERSIONED' + PostFix, BoldBooleanToTemplateVar[MoldClass.Versioned]); // do not localize + AddVariable('ISVERSIONED' + PostFix, BoldBooleanToTemplateVar[MoldClass.Versioned]); - AddVariable('ISLINKCLASS' + PostFix, BoldBooleanToTemplateVar[Assigned(MoldClass.Association)]); // do not localize - AddVariable('CLASSEXPRESSIONNAME' + PostFix, MoldClass.ExpandedExpressionName); // do not localize + AddVariable('ISLINKCLASS' + PostFix, BoldBooleanToTemplateVar[Assigned(MoldClass.Association)]); + AddVariable('CLASSEXPRESSIONNAME' + PostFix, MoldClass.ExpandedExpressionName); if Assigned(MoldClass.SuperClass) then begin - AddVariable('SUPERCLASSNAME' + PostFix, MoldClass.SuperClass.ExpandedDelphiName); // do not localize - AddVariable('SUPERPERSISTENCEINTERFACENAME' + PostFix, MakePersistenceInterfaceName(MoldClass.SuperClass)); // do not localize + AddVariable('SUPERCLASSNAME' + PostFix, MoldClass.SuperClass.ExpandedDelphiName); + AddVariable('SUPERPERSISTENCEINTERFACENAME' + PostFix, MakePersistenceInterfaceName(MoldClass.SuperClass)); end else begin - AddVariable('SUPERCLASSNAME' + PostFix, 'TBoldObject'); // do not localize - AddVariable('SUPERCLASSNAMESPACEPREFIX' + PostFix, 'Boldsystem::'); // do not localize - AddVariable('CONSTRUCTORPARAMETER' + PostFix, ', true'); // do not localize - AddVariable('SUPERPERSISTENCEINTERFACENAME' + PostFix, 'IPersistentBoldObject'); // do not localize + AddVariable('SUPERCLASSNAME' + PostFix, 'TBoldObject'); + AddVariable('SUPERCLASSNAMESPACEPREFIX' + PostFix, 'Boldsystem::'); + AddVariable('CONSTRUCTORPARAMETER' + PostFix, ', true'); + AddVariable('SUPERPERSISTENCEINTERFACENAME' + PostFix, 'IPersistentBoldObject'); end; if GenerateIDLVariables then begin if assigned(MoldClass.SuperClass) then - AddVariable('SUPERINTERFACE' + PostFix, MoldClass.SuperClass.ExpandedInterfaceName) // do not localize + AddVariable('SUPERINTERFACE' + PostFix, MoldClass.SuperClass.ExpandedInterfaceName) else - AddVariable('SUPERINTERFACE' + PostFix, 'IBoldObject'); // do not localize + AddVariable('SUPERINTERFACE' + PostFix, 'IBoldObject'); if Assigned(MoldClass.SuperClass) then - AddVariable('SUPERADAPTERNAME' + PostFix, MoldClass.SuperClass.ExpandedDelphiName) // do not localize + AddVariable('SUPERADAPTERNAME' + PostFix, MoldClass.SuperClass.ExpandedDelphiName) else - AddVariable('SUPERADAPTERNAME' + PostFix, 'TBoldComObject'); // do not localize + AddVariable('SUPERADAPTERNAME' + PostFix, 'TBoldComObject'); end; if MoldClass.IntroducesManuallyDerivedMembers then - AddVariable('CLASSINTRODUCESMANUALLYDERIVEDMEMBERS' + PostFix, 'true'); // do not localize + AddVariable('CLASSINTRODUCESMANUALLYDERIVEDMEMBERS' + PostFix, 'true'); + + if MoldClass.IntroducesManuallyReverseDerivedMembers then + AddVariable('CLASSINTRODUCESMANUALLYREVERSEDERIVEDMEMBERS' + PostFix, 'true'); membercounter := 0; @@ -629,10 +628,10 @@ procedure TBoldGenerator.InitializeTemplateForComponent(Template: TBoldTemplateH begin Member := MoldClass.AllBoldMembers[i]; MemberpostFix := PostFix + '.' + IntTostr(i - MoldClass.FirstOwnBoldMemberIndex); - AddVariable('MEMBERNAME' + MemberPostFix, Member.ExpandedDelphiName); // do not localize - AddVariable('MEMBERINDEX' + MemberPostFix, IntToStr(i)); // do not localize + AddVariable('MEMBERNAME' + MemberPostFix, Member.ExpandedDelphiName); + AddVariable('MEMBERINDEX' + MemberPostFix, IntToStr(i)); - AddVariable('MEMBERPERSISTENT' + MemberPostFix, BoldBooleanToTemplateVar[Member.EffectivePersistent]); // do not localize + AddVariable('MEMBERPERSISTENT' + MemberPostFix, BoldBooleanToTemplateVar[Member.EffectivePersistent]); if Member is TMoldAttribute then InitializeAttribute(Member as TMoldAttribute, MemberPostFix) @@ -641,9 +640,28 @@ procedure TBoldGenerator.InitializeTemplateForComponent(Template: TBoldTemplateH Inc(MemberCounter); end; - AddVariable('MEMBERCOUNT' + Postfix, IntToStr(MemberCounter)); // do not localize + AddVariable('MEMBERCOUNT' + Postfix, IntToStr(MemberCounter)); + membercounter := 0; + + for i := 0 to MoldClass.AllBoldMembers.Count - 1 do + begin + Member := MoldClass.AllBoldMembers[i]; + MemberpostFix := '-ALL' + PostFix + '.' + IntTostr(i); + AddVariable('MEMBERNAME' + MemberPostFix, Member.ExpandedDelphiName); + AddVariable('MEMBERINDEX' + MemberPostFix, IntToStr(i)); + + AddVariable('MEMBERPERSISTENT' + MemberPostFix, BoldBooleanToTemplateVar[Member.EffectivePersistent]); + + if Member is TMoldAttribute then + InitializeAttribute(Member as TMoldAttribute, MemberPostFix) + else if Member is TMoldRole then + InitializeRole(Member as TMoldRole, MemberPostFix); + Inc(MemberCounter); + end; + AddVariable('MEMBERCOUNT-ALL' + Postfix , IntToStr(MemberCounter)); membercounter := 0; + for i := MoldClass.FirstOwnNativeAttributeIndex to MoldClass.AllNativeAttributes.Count - 1 do begin Attribute := MoldClass.AllNativeAttributes[i]; @@ -651,12 +669,12 @@ procedure TBoldGenerator.InitializeTemplateForComponent(Template: TBoldTemplateH if (Attribute.DelphiPropertyRead <> pkNone) or (Attribute.DelphiPropertyWrite <> pkNone) then begin MemberpostFix := PostFix + '.' + IntTostr(i - MoldClass.FirstOwnNativeAttributeIndex); - AddVariable('DelphiAttributeName' + MemberPostFix, Attribute.ExpandedDelphiName); // do not localize + AddVariable('DelphiAttributeName' + MemberPostFix, Attribute.ExpandedDelphiName); InitializeNativeAttribute(Attribute, MemberPostFix); Inc(MemberCounter); end; end; - AddVariable('DelphiAttributeCount' + Postfix, IntToStr(MemberCounter)); // do not localize + AddVariable('DelphiAttributeCount' + Postfix, IntToStr(MemberCounter)); for i := 0 to MoldClass.Methods.Count - 1 do InitializeMethod(MoldClass.Methods[i], PostFix + '.' + IntToStr(i), false); @@ -664,7 +682,7 @@ procedure TBoldGenerator.InitializeTemplateForComponent(Template: TBoldTemplateH for i := 0 to MoldClass.AllAutoOverrideMethods.Count - 1 do InitializeMethod(MoldClass.AllAutoOverrideMethods[i], PostFix + '.' + IntToStr(MoldClass.Methods.Count + i), true); - AddVariable('METHODCOUNT' + PostFix, IntToStr(MoldClass.Methods.Count + MoldClass.AllAutoOverrideMethods.Count)); // do not localize + AddVariable('METHODCOUNT' + PostFix, IntToStr(MoldClass.Methods.Count + MoldClass.AllAutoOverrideMethods.Count)); if GenerateIDLVariables then begin @@ -675,25 +693,27 @@ procedure TBoldGenerator.InitializeTemplateForComponent(Template: TBoldTemplateH InitializeDispIDMethod(MoldClass.Methods[i], PostFix + '.' + IntToStr(MemberCounter), MoldClass.Methods[i].DispId); Inc(MemberCounter); end; - AddVariable('DISPIDMETHODCOUNT' + PostFix, IntToStr(MemberCounter)); // do not localize + AddVariable('DISPIDMETHODCOUNT' + PostFix, IntToStr(MemberCounter)); end; Derivedcounter := 0; for i := 0 to MoldClass.AllBoldMembers.Count - 1 do begin - if MoldClass.AllBoldMembers[i].ManuallyDerived and + if (MoldClass.AllBoldMembers[i].Derived and((MoldClass.AllBoldMembers[i].Derivationocl = '') or MoldClass.AllBoldMembers[i].ReverseDerived)) and ((MoldClass.AllBoldMembers[i].MoldClass = MoldClass) or (TVIsTrue(MoldClass.AllBoldMembers[i].BoldTVByName[TAG_VIRTUALDERIVE]))) then begin - AddVariable('DERIVEDMEMBERINTRODUCEDHERE' + Postfix + '.' + IntToStr(DerivedCounter), BoldBooleanToTemplateVar[MoldClass.AllBoldMembers[i].MoldClass = MoldClass]); // do not localize - AddVariable('DERIVEDMEMBERREVERSEDERIVED' + Postfix + '.' + IntToStr(DerivedCounter), BoldBooleanToTemplateVar[MoldClass.AllBoldMembers[i].ReverseDerived]); // do not localize + AddVariable('DERIVEDMEMBERINTRODUCEDHERE' + Postfix + '.' + IntToStr(DerivedCounter), BoldBooleanToTemplateVar[MoldClass.AllBoldMembers[i].MoldClass = MoldClass]); + AddVariable('DERIVEDMEMBERREVERSEDERIVED' + Postfix + '.' + IntToStr(DerivedCounter), BoldBooleanToTemplateVar[MoldClass.AllBoldMembers[i].ReverseDerived]); + AddVariable('DERIVEDMEMBERFORWARDCODEDERVIED' + Postfix + '.' + IntToStr(DerivedCounter), BoldBooleanToTemplateVar[MoldClass.AllBoldMembers[i].ManuallyDerived]); - AddVariable('DERIVEDMEMBERNAME' + Postfix + '.' + IntToStr(DerivedCounter), MoldClass.AllBoldMembers[i].ExpandedDelphiName); // do not localize + AddVariable('DERIVEDMEMBERNAME' + Postfix + '.' + IntToStr(DerivedCounter), MoldClass.AllBoldMembers[i].ExpandedDelphiName); + AddVariable('DERIVEDMEMBERINDEX' + Postfix + '.' + IntToStr(DerivedCounter), IntToStr(i)); Inc(DerivedCounter); end; end; - AddVariable('DERIVEDMEMBERCOUNT' + Postfix, IntToStr(DerivedCounter)); // do not localize + AddVariable('DERIVEDMEMBERCOUNT' + Postfix, IntToStr(DerivedCounter)); end; procedure BuildListOfAllUsedUnits(StringList: TStringList); @@ -711,10 +731,10 @@ procedure TBoldGenerator.InitializeTemplateForComponent(Template: TBoldTemplateH begin Mapping := TypenameDictionary.MappingForModelName[Model.Classes[c].Attributes[a].BoldType]; if Assigned(Mapping) then - if (Mapping.UnitNameText = '') then - StringList.Add('BoldAttributes') // do not localize + if (Mapping.UnitName = '') then + StringList.Add('BoldAttributes') else - StringList.Add(Mapping.UnitNameText); + StringList.Add(Mapping.UnitName); end; end; end; @@ -722,39 +742,39 @@ procedure TBoldGenerator.InitializeTemplateForComponent(Template: TBoldTemplateH begin Template.Variables.Clear; if GenerateMIDLCode then - AddVariable('FORWARDDECLAREINTERFACES', '1'); // do not localize - AddVariable('USETYPEDLISTS', BoldBooleanToTemplateVar[useTypedLIsts]); // do not localize - AddVariable('UNITNAME', Component.Name); // do not localize + AddVariable('FORWARDDECLAREINTERFACES', '1'); + AddVariable('USETYPEDLISTS', BoldBooleanToTemplateVar[useTypedLIsts]); + AddVariable('UNITNAME', Component.Name); if MoldModel.GUID <> '' then - AddVariable('UNITGUID', MoldModel.GUID) // do not localize + AddVariable('UNITGUID', MoldModel.GUID) else - AddVariable('UNITGUID', BoldCreateGUIDAsString(true)); // do not localize + AddVariable('UNITGUID', BoldCreateGUIDAsString(true)); - AddVariable('CRC', MoldModel.CRC); // do not localize + AddVariable('CRC', MoldModel.CRC); - AddVariable('COPYRIGHTNOTICE', Model.BoldTVByName['CopyrightNotice']); // do not localize + AddVariable('COPYRIGHTNOTICE', Model.BoldTVByName['CopyrightNotice']); Dependencies := TStringList.Create; Component.GetInterfaceDependencies(Dependencies); for i := 0 to Dependencies.Count - 1 do begin - AddVariable('INTERFACEADAPTERDEPENDENCY.' + IntToStr(i), Dependencies[i] + 'Adapters'); // do not localize - AddVariable('INTERFACEDEPENDENCY.' + IntToStr(i), Dependencies[i]); // do not localize + AddVariable('INTERFACEADAPTERDEPENDENCY.' + IntToStr(i), Dependencies[i] + 'Adapters'); + AddVariable('INTERFACEDEPENDENCY.' + IntToStr(i), Dependencies[i]); end; - AddVariable('INTERFACEDEPENDENCIESCOUNT', IntToStr(Dependencies.Count)); // do not localize + AddVariable('INTERFACEDEPENDENCIESCOUNT', IntToStr(Dependencies.Count)); Component.GetImplementationDependencies(Dependencies); for i := 0 to Dependencies.Count - 1 do begin - AddVariable('IMPLEMENTATIONADAPTERDEPENDENCY.' + IntToStr(i), Dependencies[i] + 'Adapters'); // do not localize - AddVariable('IMPLEMENTATIONDEPENDENCY.' + IntToStr(i), Dependencies[i]); // do not localize + AddVariable('IMPLEMENTATIONADAPTERDEPENDENCY.' + IntToStr(i), Dependencies[i] + 'Adapters'); + AddVariable('IMPLEMENTATIONDEPENDENCY.' + IntToStr(i), Dependencies[i]); end; - AddVariable('IMPLEMENTATIONDEPENDENCIESCOUNT', IntToStr(Dependencies.Count)); // do not localize + AddVariable('IMPLEMENTATIONDEPENDENCIESCOUNT', IntToStr(Dependencies.Count)); BuildListOfAllUsedUnits(Dependencies); for i := 0 to Dependencies.Count-1 do - AddVariable('ATTRIBUTECLASSDEPENDENCY.'+IntToStr(i), Dependencies[i]); // do not localize - AddVariable('ATTRIBUTECLASSDEPENDENCIESCOUNT', IntToStr(Dependencies.Count)); // do not localize + AddVariable('ATTRIBUTECLASSDEPENDENCY.'+IntToStr(i), Dependencies[i]); + AddVariable('ATTRIBUTECLASSDEPENDENCIESCOUNT', IntToStr(Dependencies.Count)); Dependencies.Free; @@ -765,17 +785,17 @@ procedure TBoldGenerator.InitializeTemplateForComponent(Template: TBoldTemplateH temp := temp + Model.Components[i].Name end; - AddVariable('ALLCOMPONENTS', temp); // do not localize + AddVariable('ALLCOMPONENTS', temp); ClassCount := 0; - AddVariable('MODELNAME', MoldModel.ExpandedExpressionName); // do not localize + AddVariable('MODELNAME', MoldModel.ExpandedExpressionName); if MoldModel.Interfaceuses <> '' then - AddVarList(Template, 'INTERFACEUSES', MoldModel.InterfaceUses + ','); // do not localize + AddVarList(Template, 'INTERFACEUSES', MoldModel.InterfaceUses + ','); if MoldModel.ImplementationUses <> '' then - AddVarList(Template, 'IMPLEMENTATIONUSES', MoldModel.ImplementationUses + ','); // do not localize + AddVarList(Template, 'IMPLEMENTATIONUSES', MoldModel.ImplementationUses + ','); IncludeFiles := TStringList.Create; @@ -793,7 +813,7 @@ procedure TBoldGenerator.InitializeTemplateForComponent(Template: TBoldTemplateH end; if (ClassCount + 1) mod DEBUGGERWORKAROUNDINTERVAL = 0 then - AddVariable('DEBUGGERWORKAROUND.' + IntTostr(ClassCount), '1'); // do not localize + AddVariable('DEBUGGERWORKAROUND.' + IntTostr(ClassCount), '1'); InitializeClass(MoldModel.Classes[i], '.' + IntTostr(ClassCount)); inc(ClassCount); @@ -805,19 +825,17 @@ procedure TBoldGenerator.InitializeTemplateForComponent(Template: TBoldTemplateH end; end; - AddVariable('CLASSCOUNT', IntToStr(ClassCount)); // do not localize + AddVariable('CLASSCOUNT', IntToStr(ClassCount)); for i := 0 to IncludeFiles.Count - 1 do - AddVariable('INCLUDEFILE.' + IntToStr(i), IncludeFiles[i]); // do not localize - AddVariable('INCLUDEFILECOUNT', IntToStr(includeFiles.Count)); // do not localize + AddVariable('INCLUDEFILE.' + IntToStr(i), IncludeFiles[i]); + AddVariable('INCLUDEFILECOUNT', IntToStr(includeFiles.Count)); if GenerateBold1CompatibleCode then - AddVariable('DELPHIATTRIBUTEPOSTFIX', '_') // do not localize + AddVariable('DELPHIATTRIBUTEPOSTFIX', '_') else - AddVariable('BOLDATTRIBUTEPOSTFIX', 'Attribute'); // do not localize + AddVariable('BOLDATTRIBUTEPOSTFIX', 'Attribute'); IncludeFiles.Free; - -// Template.Variables.finalize; end; procedure TBoldGenerator.SetCurrentFileHandler(const path, Filename: string; ModuleType: TBoldModuleType; Show: boolean; IsIncFile: Boolean); @@ -856,8 +874,8 @@ procedure InitializeMethod(MoldClass: TMoldClass; MoldMethod: TMoldMethod; Varia begin inheritedCall := BoldGeneratorTemplatesManager.GenerateInheritedCall(MoldClass, MoldMethod); - Variables.SetVariable('INHERITEDCALL', InheritedCall); // do not localize - Variables.SetVariable('CLASSNAME', MoldClass.ExpandedDelphiName); // do not localize + Variables.SetVariable('INHERITEDCALL', InheritedCall); + Variables.SetVariable('CLASSNAME', MoldClass.ExpandedDelphiName); AddSuperClassName(Variables, MoldClass); end; @@ -880,14 +898,12 @@ procedure InitializeMethod(MoldClass: TMoldClass; MoldMethod: TMoldMethod; Varia LastIncFileName := CurrentIncFileName; CurrentIncFileName := CurrentClass.EffectiveIncFileName(BoldGeneratorTemplatesManager.DefaultIncFileExtension); - if AnsiCompareText(LastIncFileName, CurrentIncFileName) <> 0 then + if CompareText(LastIncFileName, CurrentIncFileName) <> 0 then begin SetCurrentFileHandler(BaseFilePath, CurrentIncFileName, mtIncFile, true, true); initializeMethodIndex; end; - BoldLog.LogFmt(sProcessingClassXFileY, [CurrentClass.Name, CurrentIncFileName]); - - // userdefined methods + BoldLog.LogFmt('Processing class %s, file %s', [CurrentClass.Name, CurrentIncFileName]); for i := 0 to CurrentClass.Methods.Count - 1 do if CurrentClass.Methods[i].FuncType <> dfAbstractVirtual then @@ -895,26 +911,22 @@ procedure InitializeMethod(MoldClass: TMoldClass; MoldMethod: TMoldMethod; Varia with BoldGeneratorTemplatesManager.MethodTemplate do begin InitializeMethod(CurrentClass, CurrentClass.Methods[i], Variables); - Variables.Setvariable('METHODHEADER', MethodToDelphiHeader(CurrentClass, CurrentClass.Methods[i], ImplementationTag, true, false)); // do not localize - Variables.SetVariable('CALLINHERITED', BoldBooleanToTemplateVar[CurrentClass.Methods[i].CanCallInherited]); // do not localize + Variables.Setvariable('METHODHEADER', MethodToDelphiHeader(CurrentClass, CurrentClass.Methods[i], ImplementationTag, true, false)); + Variables.SetVariable('CALLINHERITED', BoldBooleanToTemplateVar[CurrentClass.Methods[i].CanCallInherited]); EnsureMethod(ExpandedTemplate); end; end; - - // autooverride methods for i := 0 to CurrentClass.AllAutoOverrideMethods.Count - 1 do with BoldGeneratorTemplatesManager.MethodTemplate do begin MoldMethod := CurrentClass.AllAutoOverrideMethods[i]; InitializeMethod(CurrentClass, MoldMethod, Variables); - Variables.Setvariable('METHODHEADER', MethodToDelphiHeader(CurrentClass, CurrentClass.AllAutoOverrideMethods[i], ImplementationTag, true, true)); // do not localize + Variables.Setvariable('METHODHEADER', MethodToDelphiHeader(CurrentClass, CurrentClass.AllAutoOverrideMethods[i], ImplementationTag, true, true)); SuperMethodIsAbstract := (MoldMethod.funcType = dfAbstractVirtual) and (CurrentClass.SuperClass = MoldMethod.Moldclass); - Variables.SetVariable('CALLINHERITED', BoldBooleanToTemplateVar[not SuperMethodIsAbstract]); // do not localize + Variables.SetVariable('CALLINHERITED', BoldBooleanToTemplateVar[not SuperMethodIsAbstract]); EnsureMethod(ExpandedTemplate); end; - // native attributes get-method - for i := CurrentClass.FirstOwnNativeAttributeIndex to CurrentClass.AllNativeAttributes.Count - 1 do begin Attr := CurrentClass.AllNativeAttributes[i]; @@ -923,17 +935,15 @@ procedure InitializeMethod(MoldClass: TMoldClass; MoldMethod: TMoldMethod; Varia TypeName := GetNativeDelphiTypeForModelNameNoDefaults(Attr); with BoldGeneratorTemplatesManager.MethodTemplate do begin - Variables.SetVariable('CLASSNAME', CurrentClass.ExpandedDelphiName); // do not localize - Variables.Setvariable('METHODHEADER', BoldGeneratorTemplatesManager.readMethodSignature( // do not localize + Variables.SetVariable('CLASSNAME', CurrentClass.ExpandedDelphiName); + Variables.Setvariable('METHODHEADER', BoldGeneratorTemplatesManager.readMethodSignature( CurrentClass.ExpandedDelphiName, Attr.ExpandedDelphiName, TypeName)); - Variables.SetVariable('CALLINHERITED', BoldBooleanToTemplateVar[False]); // do not localize + Variables.SetVariable('CALLINHERITED', BoldBooleanToTemplateVar[False]); EnsureMethod(ExpandedTemplate); end; end; end; - // native attributes set-method - for i := CurrentClass.FirstOwnNativeAttributeIndex to CurrentClass.AllNativeAttributes.Count - 1 do begin Attr := CurrentClass.AllNativeAttributes[i]; @@ -942,57 +952,56 @@ procedure InitializeMethod(MoldClass: TMoldClass; MoldMethod: TMoldMethod; Varia TypeName := GetNativeDelphiTypeForModelNameNoDefaults(Attr); with BoldGeneratorTemplatesManager.MethodTemplate do begin - Variables.SetVariable('CLASSNAME', CurrentClass.ExpandedDelphiName); // do not localize - Variables.Setvariable('METHODHEADER', BoldGeneratorTemplatesManager.WriteMethodSignature( // do not localize + Variables.SetVariable('CLASSNAME', CurrentClass.ExpandedDelphiName); + Variables.Setvariable('METHODHEADER', BoldGeneratorTemplatesManager.WriteMethodSignature( CurrentClass.ExpandedDelphiName, Attr.ExpandedDelphiName, TypeName)); - Variables.SetVariable('CALLINHERITED', BoldBooleanToTemplateVar[false]); // do not localize + Variables.SetVariable('CALLINHERITED', BoldBooleanToTemplateVar[false]); EnsureMethod(ExpandedTemplate); end; end; end; - // derived Members (always procedures) - for i := 0 to CurrentClass.AllBoldMembers.Count - 1 do - if CurrentClass.AllBoldMembers[i].ManuallyDerived and ( - (i >= CurrentClass.FirstOwnBoldMemberIndex) or - (TVIsTrue(CurrentClass.AllBoldMembers[i].BoldTVByName[TAG_VIRTUALDERIVE]))) then + if (CurrentClass.AllBoldMembers[i].Derived and((CurrentClass.AllBoldMembers[i].DerivationOcl = '') or CurrentClass.AllBoldMembers[i].ReverseDerived)) and + ( + (i >= CurrentClass.FirstOwnBoldMemberIndex) or + (TVIsTrue(CurrentClass.AllBoldMembers[i].BoldTVByName[TAG_VIRTUALDERIVE])) + ) then begin - - with BoldGeneratorTemplatesManager.DerivedMethodTemplate do - begin - if (CurrentClass.AllBoldMembers[i] is TMoldAttribute) then - Mapping := TypeNameDictionary.MappingForModelName[(CurrentClass.AllBoldMembers[i] as TMoldAttribute).BoldType] - else - Mapping := nil; - if assigned(Mapping) and - (Mapping.ExpandedAccessor <> '') and - (Mapping.ExpandedNativeType <> '') then + if CurrentClass.AllBoldMembers[i].ManuallyDerived then + with BoldGeneratorTemplatesManager.DerivedMethodTemplate do begin - Variables.SetVariable('MEMBERHASNATIVE', '1'); // do not localize - Variables.SetVariable('MEMBERNATIVEACCESSOR', Mapping.ExpandedAccessor); // do not localize - Variables.SetVariable('MEMBERNATIVETYPE', Mapping.ExpandedNativeType); // do not localize - end - else - Variables.SetVariable('MEMBERHASNATIVE', '0'); // do not localize - - Variables.SetVariable('CLASSNAME', CurrentClass.ExpandedDelphiName); // do not localize - Variables.SetVariable('INHERITEDCALL', 'inherited'); // do not localize - Variables.SetVariable('INTRODUCEDHERE', BoldBooleanToTemplateVar [i >= CurrentClass.FirstOwnBoldMemberIndex]); // do not localize - Variables.SetVariable('MEMBERNAME', CurrentClass.AllBoldMembers[i].ExpandedDelphiName); // do not localize - AddSuperClassName(variables, CurrentClass); - EnsureMethod(ExpandedTemplate); - end; - if CurrentClass.AllBoldMembers[i].ReverseDerived then - with BoldGeneratorTemplatesManager.ReverseDeriveMethodTemplate do - begin - Variables.SetVariable('CLASSNAME', CurrentClass.ExpandedDelphiName); // do not localize - Variables.SetVariable('INHERITEDCALL', 'inherited'); // do not localize - Variables.SetVariable('INTRODUCEDHERE', BoldBooleanToTemplateVar[i >= CurrentClass.FirstOwnBoldMemberIndex]); // do not localize - Variables.SetVariable('MEMBERNAME', CurrentClass.AllBoldMembers[i].ExpandedDelphiName); // do not localize + if (CurrentClass.AllBoldMembers[i] is TMoldAttribute) then + Mapping := TypeNameDictionary.MappingForModelName[(CurrentClass.AllBoldMembers[i] as TMoldAttribute).BoldType] + else + Mapping := nil; + if assigned(Mapping) and + (Mapping.ExpandedAccessor <> '') and + (Mapping.ExpandedNativeType <> '') then + begin + Variables.SetVariable('MEMBERHASNATIVE', '1'); + Variables.SetVariable('MEMBERNATIVEACCESSOR', Mapping.ExpandedAccessor); + Variables.SetVariable('MEMBERNATIVETYPE', Mapping.ExpandedNativeType); + end else + Variables.SetVariable('MEMBERHASNATIVE', '0'); + + Variables.SetVariable('CLASSNAME', CurrentClass.ExpandedDelphiName); + Variables.SetVariable('INHERITEDCALL', 'inherited'); + Variables.SetVariable('INTRODUCEDHERE', BoldBooleanToTemplateVar [i >= CurrentClass.FirstOwnBoldMemberIndex]); + Variables.SetVariable('MEMBERNAME', CurrentClass.AllBoldMembers[i].ExpandedDelphiName); AddSuperClassName(variables, CurrentClass); EnsureMethod(ExpandedTemplate); end; + if CurrentClass.AllBoldMembers[i].Derived and CurrentClass.AllBoldMembers[i].ReverseDerived then + with BoldGeneratorTemplatesManager.ReverseDeriveMethodTemplate do + begin + Variables.SetVariable('CLASSNAME', CurrentClass.ExpandedDelphiName); + Variables.SetVariable('INHERITEDCALL', 'inherited'); + Variables.SetVariable('INTRODUCEDHERE', BoldBooleanToTemplateVar[i >= CurrentClass.FirstOwnBoldMemberIndex]); + Variables.SetVariable('MEMBERNAME', CurrentClass.AllBoldMembers[i].ExpandedDelphiName); + AddSuperClassName(variables, CurrentClass); + EnsureMethod(ExpandedTemplate); + end; end; end; BoldLog.progressStep; @@ -1002,7 +1011,6 @@ procedure InitializeMethod(MoldClass: TMoldClass; MoldMethod: TMoldMethod; Varia end; end; - function TBoldGenerator.MethodToCOMHeader(OwningClass: TMoldClass; Method: TMoldMethod; InterfaceCode: Boolean; ParametersToCoerce, ParametersToInterfaceCoerce: TStringList): String; begin result := BoldGeneratorTemplatesManager.MethodToCOMHeader(OwningClass, Method, InterfaceCode, ParametersToCoerce, ParametersToInterfaceCoerce, MoldModel, GenerateMIDLCode); @@ -1024,10 +1032,10 @@ function TBoldGenerator.MethodToIDLHeader(OwningClass: TMoldClass; Method: TMold params := params + ', '; Param := TMoldParameter(Method.Parameters[i]); case param.ParameterKind of - pdIn: P := '[in]'; // do not localize - pdOut: P := '[out]'; // do not localize - pdInout: P := '[in, out]'; // do not localize - pdReturn: P := '[out, retval]'; // do not localize + pdIn: P := '[in]'; + pdOut: P := '[out]'; + pdInout: P := '[in, out]'; + pdReturn: P := '[out, retval]'; end; paramType := TBoldMetaSupport.ParameterTypeToIDLType(Param.ParameterType, MoldModel, IsPtr); if not GenerateMIDLCode then @@ -1051,15 +1059,15 @@ function TBoldGenerator.MethodToIDLHeader(OwningClass: TMoldClass; Method: TMold if not GenerateMIDLCode then P := EnsureSafeIDLType(P, Method.MoldClass); - p := p + '*'; // retval + p := p + '*'; if IsPtr then p := p + '*'; - Params := Params + '[out, retval] ' + p + ' ReturnParam'; // do not localize + Params := Params + '[out, retval] ' + p + ' ReturnParam'; end; if params = '' then - params := 'void'; // do not localize + params := 'void'; result := Method.ExpandedDelphiName + '(' + Params + ')'; end; @@ -1086,7 +1094,6 @@ function TBoldGenerator.FindInCurrentFile(s: String): Boolean; begin result := false; s := Uppercase(s); - // This code only searches for the name, not the signature. for i := 0 to MethodIndex.count - 1 do begin @@ -1096,6 +1103,7 @@ function TBoldGenerator.FindInCurrentFile(s: String): Boolean; exit; end; end; + end; procedure TBoldGenerator.InitializeMethodIndex; @@ -1186,10 +1194,10 @@ procedure TBoldCodeGenInitializer.MoveClassTreeToComponent( begin TargetComponent := nil; if not assigned(SuperClass) then - raise Exception.Create(sMoveToComponent_NoSuperClass); + raise Exception.Create('MoveClassTreeToComponent: No SuperClass'); if not assigned(MoldModel) then - raise Exception.Create(sMoveToComponent_NoMoldModel); + raise Exception.Create('MoveClassTreeToComponent: No MoldModel'); for i := 0 to MoldModel.Classes.count - 1 do begin @@ -1210,7 +1218,7 @@ procedure TBoldCodeGenInitializer.EnsureDependency(const SubComponentName, SubComponent: TMoldComponent; SuperComponent: TMoldComponent; begin - if AnsiCompareText(SubComponentName, SuperComponentName) = 0 then + if CompareText(SubComponentName, SuperComponentName) = 0 then exit; SubComponent := FindComponent(SubComponentName); SuperComponent := FindComponent(SuperComponentname); @@ -1242,9 +1250,9 @@ function TBoldCodeGenInitializer.ValidateFileNames: Boolean; for j := 0 to MoldModel.Components.count - 1 do begin if (MoldModel.Classes[i].Component <> MoldModel.Components[j]) and - (ansiCompareText(MoldModel.Classes[i].EffectiveIncFileName(BoldGeneratorTemplatesManager.DefaultIncFileExtension), MoldModel.Components[j].Name + '.'+BoldGeneratorTemplatesManager.DefaultIncFileExtension) = 0) then + (CompareText(MoldModel.Classes[i].EffectiveIncFileName(BoldGeneratorTemplatesManager.DefaultIncFileExtension), MoldModel.Components[j].Name + '.'+BoldGeneratorTemplatesManager.DefaultIncFileExtension) = 0) then begin - BoldLog.LogFmt(sCollidingFileName, [MoldModel.Classes[i].Name, MoldModel.Components[j].Name]); + BoldLog.LogFmt('WARNING! class %s has a file name that collides with another component (%s)!', [MoldModel.Classes[i].Name, MoldModel.Components[j].Name]); result := false; end; end; @@ -1310,7 +1318,7 @@ procedure TBoldGenerator.GenerateComInterfaces; BoldLog.ProgressMax := MoldModel.Classes.Count * 2; - BoldLog.LogFmt(sLogGeneratingInPath, [BaseFilePath]); + BoldLog.LogFmt('Generating in path: %s', [BaseFilePath]); for ComponentIx := 0 to MoldModel.Components.Count - 1 do begin for j := 0 to BoldGeneratorTemplatesManager.ComFileTemplates.Count - 1 do @@ -1320,17 +1328,17 @@ procedure TBoldGenerator.GenerateComInterfaces; with BoldGeneratorTemplatesManager.COMFileTemplates[j] do begin - Variables.SetVariable('COMPONENTNAME', MoldModel.Components[ComponentIx].Name); // do not localize - BoldLog.LogFmt(sLogGeneratingFile, [ExpandedFileName]); + Variables.SetVariable('COMPONENTNAME', MoldModel.Components[ComponentIx].Name); + BoldLog.LogFmt('Generating file %s', [ExpandedFileName]); SetCurrentFileHandler(BaseFilePath, ExpandedFileName, ModuleTypeForFile(ExpandedFileName), true, false); BoldFilehandler.Clear; - BoldLog.LogHeader := sLogInitializingVars; + BoldLog.LogHeader := 'Initializing variables'; InitializeTemplateForComponent(BoldGeneratorTemplatesManager.COMFileTemplates[j], MoldModel, MoldModel.Components[ComponentIx], true); if BoldLog.ProcessInterruption then exit; - BoldLog.LogHeader := sLogExpandingTemplate; + BoldLog.LogHeader := 'Expanding template'; BoldFilehandler.AddStrings(ExpandedTemplate); end; end; @@ -1347,8 +1355,8 @@ procedure TBoldGenerator.AddVarList(Template: TBoldTemplateHolder; VariableBaseN while sList[sList.Count-1] = '' do sList.Delete(SList.Count-1); for i := 0 to sList.Count-1 do - Template.Variables.ForceAdd(Variablebasename + '.' + IntToStr(i), SList[i], []); - Template.Variables.ForceAdd(Variablebasename + 'COUNT', IntToStr(sList.Count), []); // do not localize + Template.Variables.ForceAdd(Variablebasename+'.'+IntToStr(i), SList[i], []); + Template.Variables.ForceAdd(Variablebasename+'COUNT', IntToStr(sList.Count), []); sList.Free; end; @@ -1356,9 +1364,9 @@ procedure TBoldGenerator.AddSuperClassName(variables: TBoldTemplateVariables; MoldClass: tMoldClass); begin if assigned(MoldClass.SuperClass) then - variables.SetVariable('SUPERCLASSNAME', MoldClass.SuperClass.ExpandedDelphiName) // do not localize + variables.SetVariable('SUPERCLASSNAME', MoldClass.SuperClass.ExpandedDelphiName) else - variables.SetVariable('SUPERCLASSNAME', 'TBoldObject') // do not localize + variables.SetVariable('SUPERCLASSNAME', 'TBoldObject') end; procedure TBoldCodeGenInitializer.MoveImplicitLinkClassesToAssociationEndComponent; @@ -1381,14 +1389,12 @@ procedure TBoldCodeGenInitializer.MoveImplicitLinkClassesToAssociationEndCompone if assigned(MoldModel.Classes[i].Association) then begin LinkClass := MoldModel.Classes[i]; - // Only do this for implicit link-classes... if LinkClass.TVByName[BOLDBOLDIFYPREFIX+TAG_AUTOCREATED] = TV_TRUE then begin Component1 := GetAssociationEndComponent(LinkClass.Association, 0); Component2 := GetAssociationEndComponent(LinkClass.Association, 1); - // if the two ends belong to the same component, and it differs - // from the link class, reassign the link class. if there is - // already a dependency between the new and the old component + + if assigned(Component1) and (Component1 <> LinkClass.Component) and (Component1 = Component2) and Component1.DependentOf(LinkClass.Component) then @@ -1408,11 +1414,9 @@ procedure TBoldCodeGenInitializer.MoveImplicitLinkClassesToSuperClassComponent; if assigned(MoldModel.Classes[i].Association) then begin LinkClass := MoldModel.Classes[i]; - // check if the link class is an implicit class in the default component if (LinkClass.Component = MoldModel.MainComponent) and (LinkClass.TVByName[BOLDBOLDIFYPREFIX+TAG_AUTOCREATED] = TV_TRUE) then begin - // if the linkclass inherits from a class in another component, then move it there. if (LinkClass.SuperClass.Component <> MoldModel.MainComponent) then LinkClass.Component := LinkClass.SuperClass.Component; end; @@ -1422,7 +1426,7 @@ procedure TBoldCodeGenInitializer.MoveImplicitLinkClassesToSuperClassComponent; function TBoldGenerator.MakePersistenceInterfaceName(MoldClass: TMoldClass): string; begin - result := BoldExpandName('IPersistent', MoldClass.Name, xtDelphi, -1, nccDefault) // do not localize + result := BoldExpandName('IPersistent', MoldClass.Name, xtDelphi, -1, nccDefault) end; procedure TBoldGenerator.GenerateBusinessObjectCode; @@ -1442,25 +1446,22 @@ procedure TBoldGenerator.GeneratePersistenceInterfaces; TemplateList.free; end else - raise EBold.create(sNoTemplateForPersistenceInterfaces); + raise EBold.create('No template defined for PersistenceInterfaces'); end; function TBoldGenerator.ModuleTypeForFile(const FileName: string): TBoldModuleType; -const - PASExtension = '.PAS'; - INCExtension = '.INC'; var Extension: string; begin Extension := UpperCase(ExtractFileExt(FileName)); - if Extension = PASExtension then + if Extension = '.PAS' then Result := mtUnit - else if Extension = INCExtension then + else if Extension = '.INC' then Result := mtIncFile else Result := mtText; end; -end. - +initialization +end. diff --git a/Source/MoldModel/CodeGenerator/BoldGeneratorTemplates.pas b/Source/MoldModel/CodeGenerator/BoldGeneratorTemplates.pas index 5e063b1..9b3a929 100644 --- a/Source/MoldModel/CodeGenerator/BoldGeneratorTemplates.pas +++ b/Source/MoldModel/CodeGenerator/BoldGeneratorTemplates.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldGeneratorTemplates; interface @@ -5,7 +8,7 @@ interface uses Classes, BoldMeta, - BoldTemplateExpander; + BoldTemplateExpander; const publicTag = 0; @@ -31,10 +34,11 @@ TBoldGeneratorTemplateManager = class procedure InitializeTemplateList(TemplateList: TBoldTemplateList); virtual; procedure InitializeCOMTemplateList(TemplateList: TBoldTemplateList); virtual; function GetDefaultIncFileExtension: string; virtual; abstract; - function GetPersistenceInterfaceTemplate: TBoldTemplateHolder; virtual; + function GetPersistenceInterfaceTemplate: TBoldTemplateHolder; virtual; function GetTemplateList: TBoldTemplateList; function GetCOMTemplateList: TBoldTemplateList; public + destructor Destroy; override; function MethodToCOMHeader(OwningClass: TMoldClass; Method: TMoldMethod; InterfaceCode: Boolean; ParametersToCoerce: TStringList; ParametersToInterfaceCoerce: TStringList; MoldModel: TMoldModel; GenerateMIDLCode: Boolean): String; virtual; abstract; function MethodToCOMCall(OwningClass: TMoldClass; Method: TMoldMethod; ParametersToCoerce, ParametersToInterfaceCoerce: TStringList; MoldModel: TMoldModel): String; virtual; abstract; function ReadMethodSignature(ClassName, AttributeName, AttributeType: string): string; virtual; abstract; @@ -66,7 +70,8 @@ implementation uses SysUtils, - BoldDefs; + BoldDefs, + BoldRev; var G_BoldGeneratorTemplateManager: TBoldGeneratorTemplateManager; @@ -85,6 +90,13 @@ function BoldGeneratorTemplatesManager: TBoldGeneratorTemplateManager; { TBoldGeneratorTemplateManager } +destructor TBoldGeneratorTemplateManager.Destroy; +begin + FreeAndNil(fTemplateList); + FreeAndNil(fComTemplateList); + inherited; +end; + function TBoldGeneratorTemplateManager.GetCOMTemplateList: TBoldTemplateList; begin if not assigned(fCOMTemplateList) then @@ -120,4 +132,10 @@ procedure TBoldGeneratorTemplateManager.InitializeTemplateList(TemplateList: TBo begin end; +initialization + +finalization + FreeAndNil(G_BoldGeneratorTemplateManager); + + end. diff --git a/Source/MoldModel/CodeGenerator/BoldGeneratorTemplatesCPP.pas b/Source/MoldModel/CodeGenerator/BoldGeneratorTemplatesCPP.pas index f07e78d..74107b5 100644 --- a/Source/MoldModel/CodeGenerator/BoldGeneratorTemplatesCPP.pas +++ b/Source/MoldModel/CodeGenerator/BoldGeneratorTemplatesCPP.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldGeneratorTemplatesCPP; interface @@ -6,7 +9,8 @@ interface Classes, BoldMeta, BoldGeneratorTemplates, - BoldTemplateExpander; + BoldTemplateExpander + ; type { TBoldGeneratorTemplateCPPDM } @@ -26,6 +30,7 @@ TBoldGeneratorTemplateCPPDM = class(TDataModule) { Public declarations } end; + { TBoldCPPTemplateManager } TBoldCPPTemplateManager = class(TBoldGeneratorTemplateManager) private @@ -43,7 +48,7 @@ TBoldCPPTemplateManager = class(TBoldGeneratorTemplateManager) function GetDefaultIncFileExtension: string; override; property DataModule: TBoldGeneratorTemplateCPPDM read GetDataModule; public - destructor Destroy; override; + destructor destroy; override; function MethodToCOMHeader(OwningClass: TMoldClass; Method: TMoldMethod; InterfaceCode: Boolean; ParametersToCoerce: TStringList; ParametersToInterfaceCoerce: TStringList; MoldModel: TMoldModel; GenerateMIDLCode: Boolean): String; override; function MethodToCOMCall(OwningClass: TMoldClass; Method: TMoldMethod; ParametersToCoerce, ParametersToInterfaceCoerce: TStringList; MoldModel: TMoldModel): String; override; function ReadMethodSignature(ClassName, AttributeName, AttributeType: string): string; override; @@ -62,7 +67,6 @@ implementation uses SysUtils, - BoldRev, BoldUMLTypes, BoldTaggedValueSupport, BoldMetaSupport; @@ -71,7 +75,7 @@ implementation { TBoldCPPTemplateManager } -destructor TBoldCPPTemplateManager.Destroy; +destructor TBoldCPPTemplateManager.destroy; begin FreeAndNil(fDataModule); inherited; @@ -166,15 +170,12 @@ function TBoldCPPTemplateManager.MethodToCOMHeader(OwningClass: TMoldClass; Meth s := s + ParamType + ' '; end else - s := s + 'void '; // do not localize + s := s + 'void '; + s := s + '__safecall '; -// if InterfaceCode then - s := s + '__safecall '; // do not localize -// else -// s := s + '__fastcall '; // do not localize if not InterfaceCode then - s := s + OwningClass.ExpandedDelphiName + 'Adapter::'; // do not localize + s := s + OwningClass.ExpandedDelphiName + 'Adapter::'; s := s + Method.ExpandedDelphiName; @@ -195,7 +196,6 @@ function TBoldCPPTemplateManager.MethodToCOMHeader(OwningClass: TMoldClass; Meth if param.ParameterKind in [pdOut, pdInout] then begin - // ISJE params := params + 'var '; if assigned(ParametersToCoerce) and ((ParamType = BoldWideStringTypeName) or (ParamType = BoldWordBoolTypeName)) then @@ -211,7 +211,7 @@ function TBoldCPPTemplateManager.MethodToCOMHeader(OwningClass: TMoldClass; Meth end else if IsConst then - Params := Params + 'const '; // do not localize + Params := Params + 'const '; Params := Params + ParamType + ' ' + Param.ParameterName; end; @@ -238,7 +238,7 @@ function TBoldCPPTemplateManager.MethodToCOMCall(OwningClass: TMoldClass; Method end; begin - s := 'As' + OwningClass.ExpandedExpressionName + '->' + Method.ExpandedDelphiName; // do not localize + s := 'As' + OwningClass.ExpandedExpressionName + '->' + Method.ExpandedDelphiName; params := ''; for i := 0 to Method.Parameters.Count - 1 do @@ -247,11 +247,11 @@ function TBoldCPPTemplateManager.MethodToCOMCall(OwningClass: TMoldClass; Method params := params + ', '; Param := tMoldParameter(Method.Parameters[i]); if ParametersToInterfaceCoerce.IndexOfName(Param.ParameterName) <> -1 then - params := params + param.ParameterName + '_temp' // do not localize + params := params + param.ParameterName + '_temp' else if ParameterNeedsMarshalling(Param.ParameterType, InterfaceName) then - Params := Params + '((' + Param.DelphiParameterType + '*)' + '(BoldComInterfaceToObject(' + Param.ParameterName + ')))' // do not localize + Params := Params + '((' + Param.DelphiParameterType + '*)' + '(BoldComInterfaceToObject(' + Param.ParameterName + ')))' else if parametersToCoerce.IndexOfName(param.ParameterName) <> -1 then - params := params + param.ParameterName + '_temp' // do not localize + params := params + param.ParameterName + '_temp' else Params := params + Param.ParameterName; end; @@ -261,13 +261,15 @@ function TBoldCPPTemplateManager.MethodToCOMCall(OwningClass: TMoldClass; Method if Method.HasReturnValue then begin if ParameterNeedsMarshalling(Trim(method.ReturnType), InterfaceName) then - s := 'BoldComCreateAdapter(' + s + ', False, ' + '__uuidof(' + Interfacename + '), Result)' // do not localize + s := 'BoldComCreateAdapter(' + s + ', False, ' + '__uuidof(' + Interfacename + '), Result)' else - s := 'result := ' + s; // do not localize + s := 'result := ' + s; end; result := s + ';'; + end; + function TBoldCPPTemplateManager.MethodToCodeHeader( OwningClass: TMoldClass; Method: TMoldMethod; TagValue: Integer; AddSignature, AutoOverride: Boolean): String; @@ -278,22 +280,22 @@ function TBoldCPPTemplateManager.MethodToCodeHeader( s := ''; if (TagValue in [publicTag..PrivateTag]) and Method.IsClassMethod then - s := s + 'static '; // do not localize + s := s + 'static '; if (TagValue in [publicTag..PrivateTag]) and (Autooverride or (Method.FuncType in [dfvirtual]) or method.OverrideInAllSubclasses) then begin - s := s + 'virtual '; // do not localize + s := s + 'virtual '; end; if Method.HasReturnValue then s := s + Method.DelphiReturnType+' ' else - s := s + 'void '; // do not localize + s := s + 'void '; - s := s + '__fastcall '; // do not localize + s := s + '__fastcall '; if TagValue = ImplementationTag then s := s + OwningClass.ExpandedDelphiName + '::'; @@ -305,11 +307,11 @@ function TBoldCPPTemplateManager.MethodToCodeHeader( if Signature <> '' then s := s + '(' + Signature + ')' else - s := s + '(void)'; // do not localize + s := s + '(void)'; end; if Method.FuncType = dfAbstractVirtual then - s := s + ' = 0'; // do not localize + s := s + ' = 0'; result := s; end; @@ -335,22 +337,23 @@ function TBoldCPPTemplateManager.GetCPPSignature(MoldMethod: TMoldMethod): Strin result := result + ', '; { if Parameter.IsConst then - Result := Result + 'const ' // do not localize + Result := Result + 'const ' else if Parameter.ParameterKind = pdInOut then - Result := Result + 'var ' // do not localize + Result := Result + 'var ' else if Parameter.ParameterKind = pdOut then - Result := Result + 'out '; // do not localize + Result := Result + 'out '; } - result := result + format('%s %s', [ // do not localize + result := result + format('%s %s', [ AdaptCPPParameterType(Parameter.DelphiParameterType), Parameter.ParameterName]); end; + end; function TBoldCPPTemplateManager.GetDefaultIncFileExtension: string; begin - result := '_impl.cpp'; // do not localize + result := '_impl.cpp'; end; function TBoldCPPTemplateManager.StringContainsMethodHeader(s: String): Boolean; @@ -372,6 +375,7 @@ procedure TBoldCPPTemplateManager.AddQualifierFunctionParam(var Params: String; Params := Params + ParamType + ' ' + ParamName; end; + function TBoldCPPTemplateManager.GetSearchStringfromMethodHeader(header: String; SearchParameterList: Boolean): String; begin result := header; @@ -384,23 +388,24 @@ function TBoldCPPTemplateManager.GenerateInheritedCall( begin result := ''; if MoldMethod.HasReturnValue then - result := 'return '; // do not localize + result := 'return '; if assigned(MoldClass.SuperClass) then result := result + MoldClass.SuperClass.ExpandedDelphiName else - result := result + 'TBoldObject'; // do not localize + result := result + 'TBoldObject'; + + result := result + format('::%s(%s)', [Moldmethod.Name, MoldMethod.CallSignature]); - result := result + format('::%s(%s)', [Moldmethod.Name, MoldMethod.CallSignature]); // do not localize end; function TBoldCPPTemplateManager.ReadMethodSignature(ClassName, AttributeName, AttributeType: string): string; begin - result := format('%s __fastcall %s::Get%s()', [AttributeType, ClassName, AttributeName]); // do not localize + result := format('%s __fastcall %s::Get%s()', [AttributeType, ClassName, AttributeName]); end; function TBoldCPPTemplateManager.WriteMethodSignature(ClassName, AttributeName, AttributeType: string): string; begin - result := format('void __fastcall %s::Set%s(%s NewValue)', [ClassName, AttributeName, AttributeType]); // do not localize + result := format('void __fastcall %s::Set%s(%s NewValue)', [ClassName, AttributeName, AttributeType]); end; initialization diff --git a/Source/MoldModel/CodeGenerator/BoldGeneratorTemplatesDelphi.pas b/Source/MoldModel/CodeGenerator/BoldGeneratorTemplatesDelphi.pas index 30db28e..baee879 100644 --- a/Source/MoldModel/CodeGenerator/BoldGeneratorTemplatesDelphi.pas +++ b/Source/MoldModel/CodeGenerator/BoldGeneratorTemplatesDelphi.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldGeneratorTemplatesDelphi; interface @@ -6,7 +9,8 @@ interface Classes, BoldMeta, BoldGeneratorTemplates, - BoldTemplateExpander; + BoldTemplateExpander + ; type @@ -50,7 +54,7 @@ TBoldDelphiTemplateManager = class(TBoldGeneratorTemplateManager) function GetDefaultIncFileExtension: string; override; property DataModule: TBoldGeneratorTemplatesDelphiDM read GetDataModule; public - destructor Destroy; override; + destructor destroy; override; function MethodToCOMHeader(OwningClass: TMoldClass; Method: TMoldMethod; InterfaceCode: Boolean; ParametersToCoerce: TStringList; ParametersToInterfaceCoerce: TStringList; MoldModel: TMoldModel; GenerateMIDLCode: Boolean): String; override; function MethodToCOMCall(OwningClass: TMoldClass; Method: TMoldMethod; ParametersToCoerce, ParametersToInterfaceCoerce: TStringList; MoldModel: TMoldModel): String; override; function ReadMethodSignature(ClassName, AttributeName, AttributeType: string): string; override; @@ -73,20 +77,21 @@ TBoldDelphiTemplateManagerNameBound = class(TBoldDelphiTemplateManager) class procedure InstallTemplates; end; + implementation uses SysUtils, - BoldRev, BoldUMLTypes, BoldTaggedValueSupport, BoldMetaSupport; {$R *.dfm} + { TBoldDelphiTemplateManager } -destructor TBoldDelphiTemplateManager.Destroy; +destructor TBoldDelphiTemplateManager.destroy; begin FreeAndNil(fDataModule); inherited; @@ -165,11 +170,11 @@ function TBoldDelphiTemplateManager.MethodToCOMHeader(OwningClass: TMoldClass; M begin s := ''; if Method.HasReturnValue then - s := s + 'function ' // do not localize + s := s + 'function ' else - s := s + 'procedure '; // do not localize + s := s + 'procedure '; if not InterfaceCode then - s := s + OwningClass.ExpandedDelphiName + 'Adapter.'; // do not localize + s := s + OwningClass.ExpandedDelphiName + 'Adapter.'; s := s + Method.ExpandedDelphiName; @@ -188,8 +193,8 @@ function TBoldDelphiTemplateManager.MethodToCOMHeader(OwningClass: TMoldClass; M if param.ParameterKind in [pdOut, pdInout] then begin case param.ParameterKind of - pdOut: params := params + 'out '; // do not localize - pdInOut: params := params + 'var '; // do not localize + pdOut: params := params + 'out '; + pdInOut: params := params + 'var '; end; if assigned(ParametersToCoerce) and ((ParamType = BoldWideStringTypeName) or @@ -206,7 +211,7 @@ function TBoldDelphiTemplateManager.MethodToCOMHeader(OwningClass: TMoldClass; M end else if IsConst then - Params := Params + 'const '; // do not localize + Params := Params + 'const '; Params := Params + Param.ParameterName + ': ' + ParamType; end; if Params <> '' then @@ -223,7 +228,7 @@ function TBoldDelphiTemplateManager.MethodToCOMHeader(OwningClass: TMoldClass; M s := s + ';'; if InterfaceCode then - s := s + ' safecall;'; // do not localize + s := s + ' safecall;'; result := s; end; @@ -243,7 +248,7 @@ function TBoldDelphiTemplateManager.MethodToCOMCall(OwningClass: TMoldClass; Met end; begin - s := 'As' + OwningClass.ExpandedExpressionName + '.' + Method.ExpandedDelphiName; // do not localize + s := 'As' + OwningClass.ExpandedExpressionName + '.' + Method.ExpandedDelphiName; params := ''; for i := 0 to Method.Parameters.Count - 1 do @@ -252,11 +257,11 @@ function TBoldDelphiTemplateManager.MethodToCOMCall(OwningClass: TMoldClass; Met params := params + ', '; Param := tMoldParameter(Method.Parameters[i]); if ParametersToInterfaceCoerce.IndexOfName(Param.ParameterName) <> -1 then - params := params + param.ParameterName + '_temp' // do not localize + params := params + param.ParameterName + '_temp' else if ParameterNeedsMarshalling(Param.ParameterType, InterfaceName) then - Params := Params + 'BoldComInterfaceToObject(' + Param.ParameterName + ') as ' + Param.DelphiParameterType // do not localize + Params := Params + 'BoldComInterfaceToObject(' + Param.ParameterName + ') as ' + Param.DelphiParameterType else if parametersToCoerce.IndexOfName(param.ParameterName) <> -1 then - params := params + param.ParameterName + '_temp' // do not localize + params := params + param.ParameterName + '_temp' else Params := params + Param.ParameterName; end; @@ -267,9 +272,9 @@ function TBoldDelphiTemplateManager.MethodToCOMCall(OwningClass: TMoldClass; Met if Method.HasReturnValue then begin if ParameterNeedsMarshalling(Trim(method.ReturnType), InterfaceName) then - s :='BoldComCreateAdapter(' + s + ', False, ' + Interfacename + ', Result)' // do not localize + s :='BoldComCreateAdapter(' + s + ', False, ' + Interfacename + ', Result)' else - s := 'result := ' + s; // do not localize + s := 'result := ' + s; end; result := s + ';'; end; @@ -286,14 +291,14 @@ function TBoldDelphiTemplateManager.MethodToCodeHeader( begin s := ''; if Method.IsClassMethod then - s := s + 'class '; // do not localize + s := s + 'class '; - if AnsiCompareText(Method.Name, 'Destroy') = 0 then // do not localize - s := s + 'destructor ' // do not localize + if AnsiCompareText(Method.Name, 'Destroy') = 0 then + s := s + 'destructor ' else if Method.HasReturnValue then - s := s + 'function ' // do not localize + s := s + 'function ' else - s := s + 'procedure '; // do not localize + s := s + 'procedure '; if TagValue = ImplementationTag then s := s + OwningClass.ExpandedDelphiName + '.'; @@ -347,20 +352,20 @@ function TBoldDelphiTemplateManager.GetDelphiSignature( result := result + '; '; if Parameter.IsConst then - Result := Result + 'const ' // do not localize + Result := Result + 'const ' else if Parameter.ParameterKind = pdInOut then - Result := Result + 'var ' // do not localize + Result := Result + 'var ' else if Parameter.ParameterKind = pdOut then - Result := Result + 'out '; // do not localize + Result := Result + 'out '; - result := result + format('%s: %s', [Parameter.ParameterName, // do not localize + result := result + format('%s: %s', [Parameter.ParameterName, Parameter.DelphiParameterType]); end; end; function TBoldDelphiTemplateManager.GetDefaultIncFileExtension: string; begin - result := '.inc'; // do not localize + result := '.inc'; end; function TBoldDelphiTemplateManager.StringContainsMethodHeader(s: String): Boolean; @@ -368,16 +373,16 @@ function TBoldDelphiTemplateManager.StringContainsMethodHeader(s: String): Boole temp: String; begin temp := UpperCase(s); - result := (pos('PROCEDURE', temp) <> 0) or // do not localize - (pos('FUNCTION', temp) <> 0) or // do not localize - (pos('DESTRUCTOR', temp) <> 0); // do not localize + result := (pos('PROCEDURE', temp) <> 0) or + (pos('FUNCTION', temp) <> 0) or + (pos('DESTRUCTOR', temp) <> 0); end; procedure TBoldDelphiTemplateManager.AddQualifierParam(var Params: String; ParamName, ParamType: String); begin if Params <> '' then Params := Params + '; '; - Params := Params + ParamName+': '+ParamType; // do not localize + Params := Params + ParamName+': '+ParamType; end; procedure TBoldDelphiTemplateManager.AddQualifierFunctionParam(var Params: String; ParamName, ParamType: String); @@ -404,19 +409,20 @@ function TBoldDelphiTemplateManager.GetSearchStringfromMethodHeader(header: Stri function TBoldDelphiTemplateManager.GenerateInheritedCall(MoldClass: TMoldClass; MoldMethod: TMoldMethod): String; begin if not MoldMethod.HasReturnValue then - result := 'inherited' // do not localize + result := 'inherited' else - result := format('result := inherited %s(%s)', [Moldmethod.Name, MoldMethod.CallSignature]); // do not localize + result := format('result := inherited %s(%s)', [Moldmethod.Name, MoldMethod.CallSignature]); end; + function TBoldDelphiTemplateManager.ReadMethodSignature(ClassName, AttributeName, AttributeType: string): string; begin - result := format('function %s.Get%s: %s;', [ClassName, AttributeName, AttributeType]); // do not localize + result := format('function %s.Get%s: %s;', [ClassName, AttributeName, AttributeType]); end; function TBoldDelphiTemplateManager.WriteMethodSignature(ClassName, AttributeName, AttributeType: string): string; begin - result := format('procedure %s.Set%s(NewValue: %s);', [ClassName, AttributeName, AttributeType]); // do not localize + result := format('procedure %s.Set%s(NewValue: %s);', [ClassName, AttributeName, AttributeType]); end; function TBoldDelphiTemplateManager.GetPersistenceInterfaceTemplate: TBoldTemplateHolder; @@ -433,8 +439,8 @@ procedure TBoldDelphiTemplateManagerNameBound.InitializeTemplateList(TemplateLis if TemplateList.Count = 0 then begin template := DataModule.UnitTemplate.Template.Text; - Template := StringReplace(template, 'BoldMembers[$(MEMBERINDEX)]', 'BoldMemberByExpressionName[''$(MEMBERNAME)'']', [rfReplaceAll]); // do not localize - Template := StringReplace(template, '$(MEMBERINDEX)', '-1', [rfReplaceAll]); // do not localize + Template := StringReplace(template, 'BoldMembers[$(MEMBERINDEX)]', 'BoldMemberByExpressionName[''$(MEMBERNAME)'']', [rfReplaceAll]); + Template := StringReplace(template, '$(MEMBERINDEX)', '-1', [rfReplaceAll]); DataModule.UnitTemplate.Template.Text := Template; end; inherited; @@ -449,4 +455,4 @@ initialization {$IFDEF BOLD_DELPHI} TBoldDelphiTemplateManager.InstallTemplates; {$ENDIF} -end. \ No newline at end of file +end. diff --git a/Source/MoldModel/Core/BoldMeta.pas b/Source/MoldModel/Core/BoldMeta.pas index 7543e72..669a429 100644 --- a/Source/MoldModel/Core/BoldMeta.pas +++ b/Source/MoldModel/Core/BoldMeta.pas @@ -1,15 +1,15 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldMeta; interface uses Classes, - BoldUtils, BoldDefs, BoldBase, BoldContainers, - BoldNameExpander, - BoldSharedStrings, BoldNamedValueList, BoldUMLTypes, BoldTypeNameDictionary, @@ -59,20 +59,20 @@ TMoldElement = class(TBoldMemoryManagedObject) fBoldTaggedValues: TBoldNamedValueList; fDispId: integer; FDefaultBoldTVList: TBoldTaggedValueList; - function GetExpandedDelphiName: string; + function GetExpandedDelphiName: string; {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure SetBoldTVByName(const Tag, value: string); function GetBoldTVByName(const Tag: string): string; - function GetStdTVByName(const Tag: string): string; - function GetDelphiName: string; - function GetExpressionName: string; - function GetPMapperName: string; - procedure SetStdTVByName(const Tag, Value: string); - function GetDispId: integer; + function GetStdTVByName(const Tag: string): string; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetDelphiName: string; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetExpressionName: string; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetPMapperName: string; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure SetStdTVByName(const Tag, Value: string); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetDispId: integer; {$IFDEF BOLD_INLINE} inline; {$ENDIF} function GetDefaultBoldTVList: TBoldTaggedValueList; function GetTVByName(const Tag: string): string; procedure SetTVByName(const Tag, Value: string); - function GetTaggedValues: TBoldNamedValueList; - function GetBoldTaggedValues: TBoldNamedValueList; + function GetTaggedValues: TBoldNamedValueList; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetBoldTaggedValues: TBoldNamedValueList; {$IFDEF BOLD_INLINE} inline; {$ENDIF} function GetNonDefaultTaggedValuesCommaText: string; procedure SetNonDefaultTaggedValuesCommaText(const Value: string); protected @@ -80,8 +80,8 @@ TMoldElement = class(TBoldMemoryManagedObject) function GetModel: TMoldModel; virtual; abstract; procedure SetName(const S: string); virtual; function GetExpandedExpressionName: string; virtual; - function GetEvolutionState: TBoldEvolutionState; - function GetFormerNames: string; + function GetEvolutionState: TBoldEvolutionState; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetFormerNames: string; {$IFDEF BOLD_INLINE} inline; {$ENDIF} function GetUMLClassName: string; virtual; abstract; property UMLClassName: string read GetUMLClassName; property DefaultBoldTVList: TBoldTaggedValueList read GetDefaultBoldTVList; @@ -125,23 +125,23 @@ TMoldModel = class(TMoldElement) fIsDestroying: Boolean; function CalculateCRC: Cardinal; procedure SetRootClass(NewRootClass: TMoldClass); - function GetUnitName: string; - function GetComponents: TMoldComponentList; - function GetMainComponent: TMoldComponent; - function GetInterfaceUses: string; - function GetUseGlobalId: Boolean; - function GetUseReadOnly: Boolean; - function GetUseModelVersion: Boolean; - function GetModelVersion: Integer; - function GetUseTimestamp: Boolean; - function GetUseXFiles: Boolean; - function GetUseClockLog: Boolean; - function GetImplementationUses: string; - function GetGUID: string; - function GetTypeLibVersion: String; - function GetOptimisticLocking: TBoldOptimisticLockingMode; - function GetUpdateWholeObjects: Boolean; - function GetExpandedUnitName: string; + function GetBoldUnitName: string; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetComponents: TMoldComponentList; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetMainComponent: TMoldComponent; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetInterfaceUses: string; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetUseGlobalId: Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetUseReadOnly: Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetUseModelVersion: Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetModelVersion: Integer; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetUseTimestamp: Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetUseXFiles: Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetUseClockLog: Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetImplementationUses: string; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetGUID: string; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetTypeLibVersion: String; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetOptimisticLocking: TBoldOptimisticLockingMode; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetUpdateWholeObjects: Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetExpandedUnitName: string; {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure RemoveAssoc(MoldAssoc: TMoldAssociation; ClassList: TMoldClassList; AssocList: TMoldAssociationList); procedure RemoveClass(MoldClass: TMoldClass; ClassList: TMoldClassList; AssocList: TMoldAssociationList); function GetNationalCharConversion: TBoldNationalCharConversion; @@ -157,7 +157,7 @@ TMoldModel = class(TMoldElement) public constructor Create(Parent: TMoldElement; const Name: string); override; destructor Destroy; override; - function GetClassByName(const name: string): TMoldClass; // Find if exists, otherwise create + function GetClassByName(const name: string): TMoldClass; function FindRoleByClassNameAndName(const boldclassName, roleName: string): TMoldRole; procedure EnsureLinkRoles; procedure EnsureTopSorted; @@ -181,7 +181,7 @@ TMoldModel = class(TMoldElement) function FindComponent(const ComponentName: string): TMoldComponent; function RenameComponent(const OldComponentName, NewComponentName: string): TMoldComponent; function EnsureComponent(const ComponentName: string): TMoldComponent; - property UnitName: string read GetUnitName; + property BoldUnitName: string read GetBoldUnitName; property ExpandedUnitName: string read GetExpandedUnitName; property GUID: string read GetGUID; property TypeLibVersion: String read GetTypeLibVersion; @@ -199,8 +199,9 @@ TMoldModel = class(TMoldElement) {---TMoldElementList---} TMoldElementList = class(TBoldIndexableList) private + class var IX_Name: integer; function GetItem(index: Integer): TMoldElement; - function GetItemByName(const name: string): TMoldElement; + function GetItemByName(const name: string): TMoldElement; {$IFDEF BOLD_INLINE} inline; {$ENDIF} public constructor Create; procedure RemoveEntryReference(Item: TMoldElement); @@ -213,10 +214,12 @@ TMoldElementList = class(TBoldIndexableList) {---TMoldClassList---} TMoldClassList = class(TMoldElementList) private - function GetItem(index: Integer): TMoldClass; - function GetItemByName(const name: string): TMoldClass; - function GetItemByExpressionName(const ExpressionName: String): TMoldClass; - function GetItemByDelphiName(const DelphiName: String): TMoldClass; + class var IX_ExpressionName: integer; + class var IX_DelphiName: integer; + function GetItem(index: Integer): TMoldClass; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetItemByName(const name: string): TMoldClass; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetItemByExpressionName(const ExpressionName: String): TMoldClass; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetItemByDelphiName(const DelphiName: String): TMoldClass; {$IFDEF BOLD_INLINE} inline; {$ENDIF} public constructor Create; property Items[index: Integer]: TMoldClass read GetItem; default; @@ -228,8 +231,8 @@ TMoldClassList = class(TMoldElementList) { TMoldMemberList } TMoldMemberList = class(TMoldElementList) private - function GetItem(index: Integer): TMoldMember; - function GetItemByName(const name: string): TMoldMember; + function GetItem(index: Integer): TMoldMember; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetItemByName(const name: string): TMoldMember; {$IFDEF BOLD_INLINE} inline; {$ENDIF} public property Items[index: Integer]: TMoldMember read GetItem; default; property ItemsByName[const name: string]: TMoldMember read GetItemByName; @@ -238,8 +241,8 @@ TMoldMemberList = class(TMoldElementList) {---TMoldRoleList---} TMoldRoleList = class(TMoldMemberList) private - function GetItem(index: Integer): TMoldRole; - function GetItemByName(const name: string): TMoldRole; + function GetItem(index: Integer): TMoldRole; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetItemByName(const name: string): TMoldRole; {$IFDEF BOLD_INLINE} inline; {$ENDIF} public property Items[index: Integer]: TMoldRole read GetItem; default; property ItemsByName[const name: string]: TMoldRole read GetItemByName; @@ -248,8 +251,8 @@ TMoldRoleList = class(TMoldMemberList) {---TMoldMethodList---} TMoldMethodList = class(TMoldElementList) private - function GetItem(index: Integer): TMoldMethod; - function GetItemByName(const name: string): TMoldMethod; + function GetItem(index: Integer): TMoldMethod; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetItemByName(const name: string): TMoldMethod; {$IFDEF BOLD_INLINE} inline; {$ENDIF} public property Items[index: Integer]: TMoldMethod read GetItem; default; property ItemsByName[const name: string]: TMoldMethod read GetItemByName; @@ -258,8 +261,8 @@ TMoldMethodList = class(TMoldElementList) {---TMoldAssociationList---} TMoldAssociationList = class(TMoldElementList) private - function GetItem(index: Integer): TMoldAssociation; - function GetItemByName(const name: string): TMoldAssociation; + function GetItem(index: Integer): TMoldAssociation; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetItemByName(const name: string): TMoldAssociation; {$IFDEF BOLD_INLINE} inline; {$ENDIF} public property Items[index: Integer]: TMoldAssociation read GetItem; default; property ItemsByName[const name: string]: TMoldAssociation read GetItemByName; @@ -268,8 +271,8 @@ TMoldAssociationList = class(TMoldElementList) {---TMoldAttributeList---} TMoldAttributeList = class(TMoldMemberList) private - function GetItem(index: Integer): TMoldAttribute; - function GetItemByName(const name: string): TMoldAttribute; + function GetItem(index: Integer): TMoldAttribute; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetItemByName(const name: string): TMoldAttribute; {$IFDEF BOLD_INLINE} inline; {$ENDIF} public property Items[index: Integer]: TMoldAttribute read GetItem; default; property ItemsByName[const name: string]: TMoldAttribute read GetItemByName; @@ -278,8 +281,8 @@ TMoldAttributeList = class(TMoldMemberList) {---TMoldQualifierList---} TMoldQualifierList = class(TMoldElementList) private - function GetItem(index: Integer): TMoldQualifier; - function GetItemByName(const name: string): TMoldQualifier; + function GetItem(index: Integer): TMoldQualifier; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetItemByName(const name: string): TMoldQualifier; {$IFDEF BOLD_INLINE} inline; {$ENDIF} public property Items[index: Integer]: TMoldQualifier read GetItem; default; property ItemsByName[const name: string]: TMoldQualifier read GetItemByName; @@ -304,50 +307,50 @@ TMoldClass = class(TMoldElement) fPersistent: Boolean; fLastDispId: integer; fAllPossibleNames: TStringList; + fTopSortedIndex: integer; procedure SetSuperClass(super: TMoldClass); - function GetIncFileName: string; -// function GetExpandedTableName(const TablePrefix: String):string; - function GetIsRootClass: Boolean; + function GetIncFileName: string; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetIsRootClass: Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure InitializeClass(Parent: TMoldModel); - function GetTopSortedIndex:Integer; - procedure SetComponent(const Value: TMoldComponent); + procedure SetComponent(const Value: TMoldComponent); {$IFDEF BOLD_INLINE} inline; {$ENDIF} function GetAllNativeAttributes: TMoldAttributeList; function GetAllBoldMembers: TMoldMemberList; function GetIntroducesManuallyDerivedMembers: Boolean; - function GetFirstOwnBoldMemberIndex: integer; - function GetFirstOwnNativeAttributeIndex: integer; + function GetFirstOwnBoldMemberIndex: integer; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetFirstOwnNativeAttributeIndex: integer; {$IFDEF BOLD_INLINE} inline; {$ENDIF} function GetHasManuallyDerivedMembers: Boolean; function GetAllAutoOverrideMethods: TMoldMethodList; - function GetComponent: TMoldComponent; - function GetTablemapping: TTableMapping; - function GetUnitName: string; - function GetImported: Boolean; - function GetTableName: string; - procedure SetUnitName(const Value: string); - procedure SetIncFileName(const Value: string); - function GetDefaultStringRepresentation: String; - function GetEffectiveDefaultStringRepresentation: String; + function GetComponent: TMoldComponent; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetTableMapping: TTableMapping; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetBoldUnitName: string; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetImported: Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetTableName: string; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure SetBoldUnitName(const Value: string); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure SetIncFileName(const Value: string); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetDefaultStringRepresentation: String; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetEffectiveDefaultStringRepresentation: String; {$IFDEF BOLD_INLINE} inline; {$ENDIF} function GetHasCodeStubs: Boolean; function GetVersioned: Boolean; - function GetGuid: String; - function GetListGuid: String; - function GetOptimisticLocking: TBoldOptimisticLockingMode; - function GetExpandedUnitName: string; + function GetGuid: String; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetListGuid: String; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetOptimisticLocking: TBoldOptimisticLockingMode; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetExpandedUnitName: string; {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure TrimRemoved; - function GetEffectiveEvolutionState: TBoldEvolutionState; - function GetFirstDispId: integer; - function GetLastDispId: integer; + function GetEffectiveEvolutionState: TBoldEvolutionState; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetFirstDispId: integer; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetLastDispId: integer; {$IFDEF BOLD_INLINE} inline; {$ENDIF} function GetAllPossibleNames: TStringList; function GetHasDelphiAttributesWithAccessorFunctions: Boolean; function CalculateCRC: Cardinal; function GetEffectiveOptimisticLocking: TBoldOptimisticLockingMode; - function GetGenerateDefaultRegion: Boolean; - function GetStorage: TBoldStorage; + function GetGenerateDefaultRegion: Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetStorage: TBoldStorage; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetIntroducesManuallyReverseDerivedMembers: Boolean; protected procedure AssignMemberDispIds; function GetModel: TMoldModel; override; function GetExpandedExpressionName: string; override; - function GetExpandedInterfaceName: string; + function GetExpandedInterfaceName: string; {$IFDEF BOLD_INLINE} inline; {$ENDIF} function GetEffectivePersistent: Boolean; function GetHasNotNullMembers: Boolean; function GetUMLClassName: string; override; @@ -356,7 +359,6 @@ TMoldClass = class(TMoldElement) destructor Destroy; override; function ChildTo(MoldClass: TMoldClass): Boolean; procedure NameChanged; override; -// procedure MainTables(Strings: TStrings; const AllowChild, AllowParent: Boolean; TablePrefix: String); function FindStoringClass(DefiningClass: TMoldClass; AbovedefiningClass: Boolean; Member: TMoldMember): TMoldClass; function LowestCommonSuperClass(otherClass: TMoldClass): TMoldClass; function LowestVisibleAncestor(MoldClass:TMoldClass): TMoldClass; @@ -369,15 +371,14 @@ TMoldClass = class(TMoldElement) property Attributes: TMoldAttributeList read FAttributes; property Methods: TMoldMethodList read FMethods; property Roles: TMoldRoleList read FRoles; - property Association: TMoldAssociation read FAssociation write fAssociation; // For relationship classes only + property Association: TMoldAssociation read FAssociation write fAssociation; property IsAbstract: Boolean read FIsAbstract write fIsAbstract; property Imported: Boolean read GetImported; -// property ExpandedTableName[const TablePrefix: String]: string read GetExpandedTableName; - property UnitName: string read GetUnitName write SetUnitName; + property BoldUnitName: string read GetBoldUnitName write SetBoldUnitName; property ExpandedUnitName: string read GetExpandedUnitName; property IncFileName: string read GetIncFileName write SetIncFileName; property HasNotNullMembers: Boolean read GetHasNotNullMembers; - property TopSortedIndex:integer read GetTopSortedIndex; + property TopSortedIndex:integer read fTopSortedIndex; property Component:TMoldComponent read GetComponent write SetComponent; property AllBoldMembers: TMoldMemberList read GetAllBoldMembers; property AllNativeAttributes: TMoldAttributeList read GetAllNativeAttributes; @@ -385,6 +386,7 @@ TMoldClass = class(TMoldElement) property FirstOwnBoldMemberIndex:integer read GetFirstOwnBoldMemberIndex; property FirstOwnNativeAttributeIndex:integer read GetFirstOwnNativeAttributeIndex; property IntroducesManuallyDerivedMembers: Boolean read GetIntroducesManuallyDerivedMembers; + property IntroducesManuallyReverseDerivedMembers: Boolean read GetIntroducesManuallyReverseDerivedMembers; property HasManuallyDerivedMembers: Boolean read GetHasManuallyDerivedMembers; property HasDelphiAttributesWithAccessorFunctions: Boolean read GetHasDelphiAttributesWithAccessorFunctions; property EffectivePersistent: Boolean read GetEffectivePersistent; @@ -413,13 +415,14 @@ TMoldMember = class(TMoldElement) private FMoldClass: TMoldClass; fVisibility: TVisibilityKind; -// function GetExpandedColumnName: string; + fIndex: integer; function GetDerived: Boolean; virtual; abstract; function GetReverseDerived: Boolean; virtual; abstract; - function GetDerivationOCL: String; + function GetDerivationOCL: String; {$IFDEF BOLD_INLINE} inline; {$ENDIF} function GetMemberExists: boolean; virtual; - function GetColumnName: string; + function GetColumnName: string; {$IFDEF BOLD_INLINE} inline; {$ENDIF} function GetTypeStreamName: string; virtual; abstract; + function GetIndex: integer; protected function GetEffectiveDelayedFetch: Boolean; virtual; function GetModel: TMoldModel; override; @@ -429,11 +432,13 @@ TMoldMember = class(TMoldElement) function GetMoldClass: TMoldClass; function GetManuallyDerived: Boolean; function GetStorage: TBoldStorage; virtual; abstract; + function GetIsAttribute: boolean; virtual; abstract; + function GetIsRole: boolean; virtual; abstract; public + constructor Create(Parent: TMoldElement; const Name: string); override; property MoldClass: TMoldClass read GetMoldClass; property ColumnName: string read GetColumnName; property EffectiveDelayedFetch: Boolean read GetEffectiveDelayedFetch; -// property ExpandedColumnName: string read GetExpandedColumnName; property Visibility: TVisibilityKind read fVisibility write fVisibility; property Derived: Boolean read GetDerived; property ManuallyDerived: Boolean read GetManuallyDerived; @@ -444,6 +449,9 @@ TMoldMember = class(TMoldElement) property TypeStreamName: string read GetTypeStreamName; property FormerNames: String read GetFormerNames; property Storage: TBoldStorage read GetStorage; + property IsAttribute: boolean read GetIsAttribute; + property IsRole: boolean read GetIsRole; + property Index: integer read GetIndex; end; {---TMoldAttribute---} @@ -455,21 +463,23 @@ TMoldAttribute = class(TMoldMember) function CalculateCRC: Cardinal; function GetDerived: Boolean; override; function GetReverseDerived: Boolean; override; - function GetAllowNull: Boolean; - function GetAttributeKind: TBoldAttributeKind; - function GetDelphiPropertyRead: TDelphiPropertyAccessKind; - function GetDelphiPropertyWrite: TDelphiPropertyAccessKind; - function GetHasDelphiField: Boolean; - function GetLength: Integer; - function GetPersistent: Boolean; + function GetAllowNull: Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetAttributeKind: TBoldAttributeKind; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetDelphiPropertyRead: TDelphiPropertyAccessKind; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetDelphiPropertyWrite: TDelphiPropertyAccessKind; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetHasDelphiField: Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetLength: Integer; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetPersistent: Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} function GetTypeStreamName: string; override; - function GetDefaultDBValue: string; + function GetDefaultDBValue: string; {$IFDEF BOLD_INLINE} inline; {$ENDIF} protected function GetEffectivePersistent: Boolean; override; function GetEffectiveDelayedFetch: Boolean; override; function GetHasDispId: boolean; override; function GetUMLClassName: string; override; function GetStorage: TBoldStorage; override; + function GetIsAttribute: boolean; override; + function GetIsRole: boolean; override; public constructor Create(Parent: TMoldElement; const Name: string); override; destructor Destroy; override; @@ -497,14 +507,14 @@ TMoldMethod = class(TMoldElement) FReturnType: string; fParameters: TBoldObjectArray; fVisibility: TVisibilityKind; - procedure setSignature(Value: string); + procedure SetSignature(Value: string); function GetSignature: String; - function GetParameters: TBoldObjectArray; + function GetParameters: TBoldObjectArray; {$IFDEF BOLD_INLINE} inline; {$ENDIF} function GetCallSignature: string; - function GetFuncType: TDelphiFunctionType; - function GetOverrideInAllSubclasses: Boolean; + function GetFuncType: TDelphiFunctionType; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetOverrideInAllSubclasses: Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} function GetDelphiReturnType: String; - function GetHasReturnValue: Boolean; + function GetHasReturnValue: Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} function GetCanCallInherited: Boolean; protected function GetModel: TMoldModel; override; @@ -538,7 +548,7 @@ TMoldParameter= class(TBoldMemoryManagedObject) fOwningMethod: TMoldMethod; function GetDelphiParameterType: String; public - constructor create(OwningMethod: TMoldMethod); + constructor Create(OwningMethod: TMoldMethod); property ParameterName: String read FParameterName write fParameterName; property ParameterType: String read FParameterType write fParameterType; property ParameterKind: TBoldParameterDirectionKind read FParameterKind write fParameterKind; @@ -560,33 +570,35 @@ TMoldRole = class(TMoldMember) fMultiplicity: String; function CalculateCRC: Cardinal; function GetOtherEnd: TMoldRole; - procedure setAssociation(Association: TMoldAssociation); - function GetHasLinkRole: Boolean; + procedure SetAssociation(Association: TMoldAssociation); + function GetHasLinkRole: Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} function GetLinkRole: TMoldRole; procedure EnsureLinkRole; - function GetMainRole: TMoldRole; + function GetMainRole: TMoldRole; {$IFDEF BOLD_INLINE} inline; {$ENDIF} function GetMulti: Boolean; function GetDerived: Boolean; override; function GetReverseDerived: Boolean; override; - function GetMandatory: Boolean; - function GetEmbed: Boolean; - function GetEffectiveEmbed: Boolean; - function GetEffectiveOrdered: Boolean; + function GetMandatory: Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetEmbed: Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetEffectiveEmbed: Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetEffectiveOrdered: Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} function GetTypeStreamName: string; override; - function GetQualifiedMulti: Boolean; - function GetDefaultRegionMode: TBoldAssociationEndDefaultRegionMode; + function GetQualifiedMulti: Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetDefaultRegionMode: TBoldAssociationEndDefaultRegionMode; {$IFDEF BOLD_INLINE} inline; {$ENDIF} function GetEffectiveDefaultRegionMode: TBoldAssociationEndDefaultRegionMode; protected function GetEffectiveDelayedFetch: Boolean; override; function GetModel: TMoldModel; override; - procedure SetMoldClass(NewMoldClass: TMoldClass); override; + procedure setMoldClass(NewMoldClass: TMoldClass); override; function GetEffectivePersistent: Boolean; override; - function GetDeleteAction: TDeleteAction; - function GetEffectiveDeleteAction: TDeleteAction; + function GetDeleteAction: TDeleteAction; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetEffectiveDeleteAction: TDeleteAction; {$IFDEF BOLD_INLINE} inline; {$ENDIF} function GetMemberExists: boolean; override; function GetHasDispId: boolean; override; function GetUMLClassName: string; override; function GetStorage: TBoldStorage; override; + function GetIsAttribute: boolean; override; + function GetIsRole: boolean; override; public constructor Create(Parent: TMoldElement; const Name: string); override; destructor Destroy; override; @@ -594,13 +606,13 @@ TMoldRole = class(TMoldMember) property Association: TMoldAssociation read FAssociation write setAssociation; property Multi: Boolean read GetMulti; property Navigable: Boolean read FNavigable write fNavigable; - property OtherEnd: TMoldRole read GetOtherEnd; // Only binary association so far + property OtherEnd: TMoldRole read GetOtherEnd; property Ordered: Boolean read FOrdered write fOrdered; property EffectiveOrdered: Boolean read GetEffectiveOrdered; property Mandatory: Boolean read GetMandatory; property Embed: Boolean read GetEmbed; property EffectiveEmbedded: Boolean read GetEffectiveEmbed; - property MoldClass: TMoldClass read GetMoldClass write SetMoldClass; + property MoldClass: TMoldClass read GetMoldClass write setMoldClass; property Qualifiers: TMoldQualifierList read FQualifiers; property QualifiedMulti: Boolean read GetQualifiedMulti; property HasLinkRole: Boolean read GetHasLinkRole; @@ -624,12 +636,12 @@ TMoldAssociation = class(TMoldElement) FRoles: TMoldRoleList; fLinkRoles: TMoldRolelist; fInnerLinkRoles: TMoldRoleList; - FLinkClass: TMoldClass; // For n-n relations only + FLinkClass: TMoldClass; fAllPossibleNames: TStringList; procedure SetLinkClass(Value: TMoldClass); - function GetPersistent: Boolean; + function GetPersistent: Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} function GetAllPossibleNames: TStringList; - function GetStorage: TBoldStorage; + function GetStorage: TBoldStorage; {$IFDEF BOLD_INLINE} inline; {$ENDIF} protected function GetModel: TMoldModel; override; function GetEffectivePersistent: Boolean; @@ -683,7 +695,7 @@ TMoldComponent = class(TBoldMemoryManagedObject) { TMoldComponentList } TMoldComponentList = Class(TList) private - function GetItem(index: Integer): TMoldComponent; + function GetItem(index: Integer): TMoldComponent; {$IFDEF BOLD_INLINE} inline; {$ENDIF} function GetItemByName(const name: string): TMoldComponent; public property Items[index: Integer]: TMoldComponent read GetItem; default; @@ -695,17 +707,15 @@ implementation uses SysUtils, BoldDefaultStreamNames, + BoldDefaultTaggedValues, BoldGuard, BoldHashIndexes, BoldMetaSupport, - BoldDefaultTaggedValues, + BoldMoldConsts, + BoldNameExpander, + BoldSharedStrings, BoldUMLTaggedValues, - BoldMoldConsts; - -var - IX_Name: integer = -1; - IX_ExpressionName: integer = -1; - IX_DelphiName: integer = -1; + BoldUtils; type {---TNameIndex---} @@ -800,16 +810,16 @@ constructor TMoldModel.Create(Parent: TMoldElement; const Name: string); FAssociations := TMoldAssociationList.Create; fDispIdAssigningState := dasNotStarted; - BoldTVByName[TAG_DELPHINAME] := TV_NAME; // FIXME + BoldTVByName[TAG_DELPHINAME] := TV_NAME; + + FRootClass := TMoldClass.Create(self, Format('%sRoot',[name])); - FRootClass := TMoldClass.Create(self, Format('%sRoot',[name])); // do not localize end; destructor TMoldModel.Destroy; var i: integer; begin - // note, associations first fIsDestroying := true; FreeAndNil(fAssociations); FreeAndNil(fClasses); @@ -825,6 +835,11 @@ function TMoldModel.GetModel: TMoldModel; Result := self; end; +function TMoldClassList.GetItemByName(const name: string): TMoldClass; +begin + Result := TMoldClass(TBoldCaseSensitiveStringHashIndex(Indexes[IX_Name]).FindByString(name)); +end; + function TMoldModel.FindRoleByClassNameAndName(const boldclassName, roleName: string): TMoldRole; var MoldClass: TMoldClass; @@ -842,35 +857,14 @@ function TMoldModel.GetClassByName(const name: string): TMoldClass; Result := TMoldClass.Create(self, name); end; -function ClassesComparer(Item1, Item2: Pointer): Integer; +function ClassesComparer(Item1, Item2: TObject): Integer; begin - if (TObject(Item1) is TMoldClass) and (TObject(Item1) is TMoldClass) then - result := AnsiCompareStr(TMoldClass(Item1).name, TMoldClass(Item2).Name) + if (Item1 is TMoldClass) and (Item1 is TMoldClass) then + result := CompareStr(TMoldClass(Item1).name, TMoldClass(Item2).Name) else raise EBoldInternal.Create('ooops, class was not a class in TMoldModel.EnsureTopSorted'); end; -procedure TMoldModel.EnsureTopSorted; -var - ClassIx, SubClassIx: Integer; -begin - if Topsorted then - Exit; - Classes.OwnsEntries := false; - Classes.Clear; - Classes.OwnsEntries := true; - Classes.Add(RootClass); - ClassIx := 0; - while ClassIx < Classes.Count do - begin - Classes[ClassIx].SubClasses.Sort(ClassesComparer); - for SubClassIx := 0 to Classes[ClassIx].SubClasses.Count-1 do - Classes.Add(Classes[ClassIx].SubClasses[SubClassIx]); - inc(ClassIx); - end; - fTopSorted := True; -end; - procedure TMoldModel.SetRootClass(NewRootClass: TMoldClass); begin if Assigned(NewRootClass) then @@ -883,9 +877,30 @@ function TMoldClass.GetIntroducesManuallyDerivedMembers: Boolean; begin result := false; for i := 0 to Attributes.Count-1 do - result := result or (Attributes[i].Derived and (Attributes[i].DerivationOCL = '')); + result := result or + (Attributes[i].Derived and (Attributes[i].DerivationOCL = '')); for i := 0 to Roles.Count-1 do - result := result or (Roles[i].Derived and (Roles[i].DerivationOCL = '')); + result := result or (Roles[i].Derived and (Roles[i].DerivationOCL = '') and {Roles[i].Embed and} Roles[i].Navigable); +end; + +function TMoldClass.GetIntroducesManuallyReverseDerivedMembers: Boolean; +var + i: integer; +begin + result := false; + for i := 0 to Attributes.Count-1 do + result := result or + (Attributes[i].Derived and Attributes[i].ReverseDerived); +end; + +function TMoldAssociationList.GetItem(index: Integer): TMoldAssociation; +begin + Result := TMoldAssociation(inherited Items[index]); +end; + +function TMoldRoleList.GetItem(index: Integer): TMoldRole; +begin + Result := TMoldRole(inherited Items[index]); end; procedure TMoldModel.EnsureLinkRoles; @@ -904,11 +919,6 @@ procedure TMoldModel.EnsureLinkRoles; { TMoldClass } -function TMoldClass.GetTopSortedIndex:Integer; -begin - result := FModel.classes.IndexOf(self); -end; - constructor TMoldClass.Create(Parent: TMoldElement; const Name: string); begin inherited Create(Parent, Name); @@ -916,6 +926,7 @@ constructor TMoldClass.Create(Parent: TMoldElement; const Name: string); InitializeClass(TMoldModel(Parent)); end; + procedure TMoldClass.InitializeClass(Parent: TMoldModel); begin FModel := Parent; @@ -936,15 +947,13 @@ destructor TMoldClass.Destroy; i: Integer; TempSuperClass: TMoldClass; begin - // it should be safe to do the subclass unlinking during model destruction - // but at least Aholas model from 2001-06-01 gives an AV at one point during the resizing of - // the subclasseslist. Not performing this operation during model destruction - // is an optimization, but it is very annoying that it crashes on the above model. + + + if not Model.fIsdestroying then begin TempSuperClass := SuperClass; SuperClass := nil; - // set all children to inherit from parent instead, as this will unlink, do it backwards if Assigned(SubClasses) then for i := SubClasses.Count - 1 downto 0 do fSubClasses[i].SuperClass := TempSuperClass; @@ -965,6 +974,7 @@ destructor TMoldClass.Destroy; freeAndNil(fAllBoldMembers); freeAndNil(fAllNativeAttributes); FreeAndNil(fAllPossibleNames); + FreeAndNil(fAllAutoOverrideMethods); if Assigned(Model) and assigned(Model.Classes) then Model.Classes.RemoveEntryReference(self); @@ -976,6 +986,7 @@ function TMoldClass.GetModel: TMoldModel; Result := FModel; end; + procedure TMoldClass.NameChanged; begin if Assigned(Model) and assigned(Model.Classes) then @@ -1020,6 +1031,11 @@ function TMoldClass.GetIsRootClass: Boolean; Result := Model.RootClass = self; end; +function TMoldClassList.GetItem(index: Integer): TMoldClass; +begin + Result := TMoldClass(inherited Items[index]); +end; + function TMoldClass.GetEffectivePersistent: Boolean; var AllSubClassesTransient: Boolean; @@ -1038,7 +1054,7 @@ function TMoldClass.GetEffectivePersistent: Boolean; function TMoldClass.GetExpandedExpressionName: string; begin Result := inherited GetExpandedExpressionName; - if (length(result) > 0) and (Result[1] in ['a'..'z']) then + if (length(result) > 0) and CharInSet(Result[1], ['a'..'z']) then begin Result[1] := UpCase(Result[1]); result := BoldSharedStringManager.GetSharedString(Result); @@ -1069,12 +1085,11 @@ procedure TMoldClass.MainTables(Strings: TStrings; const AllowChild, AllowParent function TMoldClass.FindStoringClass(DefiningClass: TMoldClass; AbovedefiningClass: Boolean; Member:TMoldMember): TMoldClass; begin - // Since the defining class of the links of associationclasses is actually the other end, - // we have to return back to the link-class, unless it is a common member, and not a relation) + if Assigned(Association) and (member is TMoldRole) and (TMoldRole(Member).association = Association) then - DefiningClass := self; //CHECKME: Was Model.RootClass + DefiningClass := self; result := nil; if AbovedefiningClass then @@ -1118,14 +1133,20 @@ function TMoldClass.LowestVisibleAncestor(MoldClass: TMoldClass): TMoldClass; result := nil; end; +function TMoldAttributeList.GetItem(index: Integer): TMoldAttribute; +begin + Result := TMoldAttribute(inherited Items[index]); +end; + function TMoldClass.GetAllBoldMembers: TMoldMemberList; var i: integer; -procedure TryAdd(Member: TMoldMember); -begin - if Member.MemberExists then - fAllBoldMembers.Add(Member); -end; + + procedure TryAdd(Member: TMoldMember); + begin + if Member.MemberExists then + fAllBoldMembers.Add(Member); + end; begin if not assigned(fAllBoldMembers) then begin @@ -1134,8 +1155,11 @@ procedure TryAdd(Member: TMoldMember); fAllBoldMembers.OwnsEntries := false; if Assigned(SuperClass) then + begin + AllBoldMembers.Capacity := SuperClass.AllBoldMembers.count + Attributes.Count + (Roles.Count*2); for i := 0 to SuperClass.AllBoldMembers.count-1 do AllBoldMembers.Add(SuperClass.AllBoldMembers[i]); + end; fFirstOwnBoldMemberIndex := fAllBoldMembers.Count; @@ -1202,7 +1226,7 @@ constructor TMoldElementList.Create; function TMoldElementList.GetItemByName(const name: string): TMoldElement; begin - Result := TMoldElement(TNameIndex(Indexes[IX_Name]).FindByString(name)); + Result := TMoldElement(TBoldCaseSensitiveStringHashIndex(Indexes[IX_Name]).FindByString(name)); end; function TMoldElementList.GetItem(index: Integer): TMoldElement; @@ -1222,7 +1246,7 @@ function TMoldElementList.MakeUniqueName(const prefix: string): string; i := 0; repeat inc(i); - Result := Format('%s%d', [prefix, i]); // do not localize + Result := Format('%s%d', [prefix, i]); until ItemsByName[Result] = nil; end; @@ -1244,35 +1268,21 @@ constructor TMoldClassList.Create; SetIndexVariable(IX_DelphiName, AddIndex(TDelphiNameIndex.Create)); end; -function TMoldClassList.GetItem(index: Integer): TMoldClass; -begin - Result := TMoldClass(inherited Items[index]); -end; - function TMoldClassList.GetItemByDelphiName(const DelphiName: String): TMoldClass; begin - Result := TMoldClass(TNameIndex(Indexes[IX_DelphiName]).FindByString(DelphiName)); + Result := TMoldClass(TBoldCaseSensitiveStringHashIndex(Indexes[IX_DelphiName]).FindByString(DelphiName)); end; function TMoldClassList.GetItemByExpressionName(const ExpressionName: String): TMoldClass; begin - Result := TMoldClass(TNameIndex(Indexes[IX_ExpressionName]).FindByString(Expressionname)); -end; - -function TMoldClassList.GetItemByName(const name: string): TMoldClass; -begin - Result := TMoldClass(TNameIndex(Indexes[IX_Name]).FindByString(name)); + Result := TMoldClass(TBoldCaseSensitiveStringHashIndex(Indexes[IX_ExpressionName]).FindByString(Expressionname)); end; {---TMoldRoleList---} -function TMoldRoleList.GetItem(index: Integer): TMoldRole; -begin - Result := TMoldRole(inherited Items[index]); -end; function TMoldRoleList.GetItemByName(const name: string): TMoldRole; begin - Result := TMoldRole(TNameIndex(Indexes[IX_Name]).FindByString(name)); + Result := TMoldRole(TBoldCaseSensitiveStringHashIndex(Indexes[IX_Name]).FindByString(name)); end; {---TMoldMethodList---} @@ -1283,29 +1293,21 @@ function TMoldMethodList.GetItem(index: Integer): TMoldMethod; function TMoldMethodList.GetItemByName(const name: string): TMoldMethod; begin - Result := TMoldMethod(TNameIndex(Indexes[IX_Name]).FindByString(name)); + Result := TMoldMethod(TBoldCaseSensitiveStringHashIndex(Indexes[IX_Name]).FindByString(name)); end; {---TMoldAssociationList---} -function TMoldAssociationList.GetItem(index: Integer): TMoldAssociation; -begin - Result := TMoldAssociation(inherited Items[index]); -end; function TMoldAssociationList.GetItemByName(const name: string): TMoldAssociation; begin - Result := TMoldAssociation(TNameIndex(Indexes[IX_Name]).FindByString(name)); + Result := TMoldAssociation(TBoldCaseSensitiveStringHashIndex(Indexes[IX_Name]).FindByString(name)); end; {---TMoldAttributeList---} -function TMoldAttributeList.GetItem(index: Integer): TMoldAttribute; -begin - Result := TMoldAttribute(inherited Items[index]); -end; function TMoldAttributeList.GetItemByName(const name: string): TMoldAttribute; begin - Result := TMoldAttribute(TNameIndex(Indexes[IX_Name]).FindByString(name)); + Result := TMoldAttribute(TBoldCaseSensitiveStringHashIndex(Indexes[IX_Name]).FindByString(name)); end; {---TMoldQualifierList---} @@ -1316,7 +1318,7 @@ function TMoldQualifierList.GetItem(index: Integer): TMoldQualifier; function TMoldQualifierList.GetItemByName(const name: string): TMoldQualifier; begin - Result := TMoldQualifier(TNameIndex(Indexes[IX_Name]).FindByString(name)); + Result := TMoldQualifier(TBoldCaseSensitiveStringHashIndex(Indexes[IX_Name]).FindByString(name)); end; {---TMoldMember---} @@ -1329,13 +1331,20 @@ function TMoldMember.GetModel: TMoldModel; function TMoldMember.GetExpandedExpressionName: string; begin Result := inherited GetExpandedExpressionName; - if (length(result) > 0) and (Result[1] in ['A'..'Z']) then + if (length(result) > 0) and CharInSet(Result[1], ['A'..'Z']) then begin - Result[1] := chr(ord(Result[1]) + 32); // Make into lowercase + Result[1] := chr(ord(Result[1]) + 32); result := BoldSharedStringManager.GetSharedString(Result); end; end; +function TMoldMember.GetIndex: integer; +begin + if (fIndex = -1) and Assigned(FMoldClass) then + fIndex := FMoldClass.AllBoldMembers.IndexOf(self); + result := fIndex; +end; + procedure TMoldMember.SetMoldClass(NewMoldClass: TMoldClass); begin fMoldClass := NewMoldClass; @@ -1352,7 +1361,7 @@ constructor TMoldAttribute.Create(Parent: TMoldElement; const Name: string); inherited Create(Parent, Name); Assert(Parent is TMoldClass); SetMoldClass(TMoldClass(Parent)); - BoldType := 'String'; // do not localize + BoldType := 'String'; MoldClass.Attributes.Add(self); end; @@ -1403,10 +1412,6 @@ procedure TMoldMethod.NameChanged; end; procedure TMoldMethod.setSignature(Value: string); -const - ConstParam = 'CONST '; - VarParam = 'VAR '; - OutParam = 'OUT '; var i:integer; ParamType, @@ -1430,20 +1435,20 @@ procedure TMoldMethod.setSignature(Value: string); next := copy(value, 1, pos(';', value) - 1); value := copy(value, pos(';', value) + 1, maxint); - if Pos(ConstParam, UpperCase(Next)) > 0 then + if Pos(UpperCase('const '), UpperCase(Next)) > 0 then begin IsConst := True; - Delete(Next, Pos(ConstParam, UpperCase(Next)), Length(ConstParam)); + Delete(Next, Pos(UpperCase('const '), UpperCase(Next)), Length('const ')); end - else if Pos(VarParam, UpperCase(Next)) > 0 then + else if Pos(UpperCase('var '), UpperCase(Next)) > 0 then begin IsVar := True; - Delete(Next, Pos(VarParam, UpperCase(Next)), Length(VarParam)); + Delete(Next, Pos(UpperCase('var '), UpperCase(Next)), Length('var ')); end - else if Pos(OutParam, UpperCase(Next)) > 0 then + else if Pos(UpperCase('out '), UpperCase(Next)) > 0 then begin IsOut := True; - Delete(Next, Pos(OutParam, UpperCase(Next)), Length(OutParam)); + Delete(Next, Pos(UpperCase('out '), UpperCase(Next)), Length('out ')); end; if pos(':', next) <> 0 then @@ -1489,13 +1494,13 @@ function TMoldMethod.GetSignature: String; Assert(Parameters[i] is TMoldParameter); Param := TMoldParameter(Parameters[i]); if Param.IsConst then - Result := Result + 'const ' // do not localize + Result := Result + 'const ' else if Param.ParameterKind = pdInOut then - Result := Result + 'var ' // do not localize + Result := Result + 'var ' else if Param.ParameterKind = pdOut then - Result := Result + 'out '; // do not localize + Result := Result + 'out '; - result := result + format('%s: %s', [ // do not localize + result := result + format('%s: %s', [ TMoldParameter(parameters[i]).ParameterName, TMoldParameter(parameters[i]).ParameterType]); end; @@ -1503,7 +1508,7 @@ function TMoldMethod.GetSignature: String; function TMoldMethod.GetUMLClassName: string; begin - result := 'Operation'; // do not localize + result := 'Operation'; end; {---TMoldRole---} @@ -1514,7 +1519,7 @@ constructor TMoldRole.Create(Parent: TMoldElement; const Name: string); begin Association := TMoldAssociation(Parent); end; - Multiplicity := '0..1'; // do not localize + Multiplicity := '0..1'; Navigable := True; fRoleType := rtRole; FQualifiers := TMoldQualifierList.Create; @@ -1548,7 +1553,7 @@ function TMoldRole.GetEffectivePersistent: Boolean; Result := association.effectivePersistent and (not Derived) and (RoleType <> rtLinkRole); end; -procedure TMoldRole.setAssociation(Association: TMoldAssociation); +procedure TMoldRole.SetAssociation(Association: TMoldAssociation); var oldAssociation: TMoldAssociation; begin @@ -1612,6 +1617,16 @@ function TMoldRole.GetHasLinkRole: Boolean; result := (RoleType = rtRole) and Assigned(Association.LinkClass); end; +function TMoldRole.GetIsAttribute: boolean; +begin + result := false; +end; + +function TMoldRole.GetIsRole: boolean; +begin + result := true; +end; + function TMoldRole.GetLinkRole: TMoldRole; begin MoldClass.Model.EnsureLinkRoles; @@ -1629,7 +1644,6 @@ procedure TMoldRole.EnsureLinkRole; begin if HasLinkRole and not assigned(fRelatedRole) then begin - // make sure the additional roles comes in a known order if Association.Roles.IndexOf(self) = 1 then OtherEnd.EnsureLinkRole; if MoldClass.ChildTo(OtherEnd.MoldClass) or otherEnd.MoldClass.ChildTo(MoldClass) then @@ -1643,14 +1657,14 @@ procedure TMoldRole.EnsureLinkRole; fRelatedRole.fRoleType := rtLinkRole; fRelatedRole.MoldClass := MoldClass; fRelatedRole.FOrdered := Ordered; - fRelatedRole.Association := Association; //adds to association.LInkRole + fRelatedRole.Association := Association; fRelatedRole.FNavigable := Navigable; fRelatedRole.BoldTVByName[TAG_EMBED] := TV_FALSE; fRelatedRole.fVisibility := Visibility; InnerLinkRole := TMoldRole.Create(self, OtherEnd.Name); InnerLinkRole.fRoleType := rtInnerLinkRole; InnerLinkRole.MoldClass := Association.LinkClass; - InnerLinkRole.Association := Association; //adds to association.InnerLInkRole + InnerLinkRole.Association := Association; InnerLinkRole.Multiplicity := '1'; InnerLinkRole.Ordered := false; InnerLinkRole.BoldTVByName[TAG_EMBED] := TV_TRUE; @@ -1672,7 +1686,7 @@ function TMoldRole.GetMainRole: TMoldRole; function TMoldRole.GetUMLClassName: string; begin - result := 'AssociationEnd'; // do not localize + result := 'AssociationEnd'; end; {---TMoldAssociation---} @@ -1713,12 +1727,9 @@ function TMoldAssociation.GetModel: TMoldModel; function TMoldAssociation.GetEffectivePersistent: Boolean; begin - // associations are made implicitly transient if either class is transient during Boldify - // but the classes could still be "effective transient" Result := Persistent and not derived and - // the middle test below that the associationend is not the same as the - // link-class is just to avoid a recursion between class.effectivepersistent - // and association.effectivePersistent. Should they be the same, the model is invalid anyway... + + assigned(Roles[0].MoldClass) and (Roles[0].MoldClass <> LinkClass) and Roles[0].MoldClass.EffectivePersistent and assigned(Roles[1].MoldClass) and (Roles[1].MoldClass <> LinkClass) and Roles[1].MoldClass.EffectivePersistent; end; @@ -1734,7 +1745,7 @@ procedure TMoldAssociation.SetLinkClass(Value: TMoldClass); begin if Assigned(Value.Association) and (Value.Association <> self) then - raise EBold.CreateFmt(sClassIsRelation, [value.Name]); + raise EBold.Create(sClassIsRelation); FLinkClass := Value; LinkClass.Association := self; end; @@ -1742,7 +1753,7 @@ procedure TMoldAssociation.SetLinkClass(Value: TMoldClass); function TMoldAssociation.GetUMLClassName: string; begin - result := 'Association'; // do not localize + result := 'Association'; end; {---TMoldQualifier---} @@ -1768,7 +1779,7 @@ function TMoldQualifier.GetModel: TMoldModel; function TMoldQualifier.GetUMLClassName: string; begin - result := 'Attribute'; // do not localize + result := 'Attribute'; end; function TMoldClass.GetHasManuallyDerivedMembers: Boolean; @@ -1778,7 +1789,7 @@ function TMoldClass.GetHasManuallyDerivedMembers: Boolean; result := false; for i := 0 to AllBoldMembers.Count-1 do if AllBoldMembers[i].Derived and - (AllBoldMembers[i].DerivationOCL = '') then + ((AllBoldMembers[i].DerivationOCL = '') or AllBoldMembers[i].ReverseDerived) then begin result := true; exit; @@ -1826,17 +1837,17 @@ function TMoldClass.GetComponent: TMoldComponent; procedure TMoldClass.SetComponent(const Value: TMoldComponent); begin if assigned(Value) then - UnitName := Value.Name + BoldUnitName := Value.Name else - UnitName := ''; + BoldUnitName := ''; end; -function TMoldClass.GetTablemapping: TTableMapping; +function TMoldClass.GetTableMapping: TTableMapping; begin result := TBoldTaggedValueSupport.StringToTableMapping(BoldTVByName[TAG_TABLEMAPPING]); end; -function TMoldClass.GetUnitName: string; +function TMoldClass.GetBoldUnitName: string; begin result := BoldTVByName[TAG_UNITNAME]; end; @@ -1851,7 +1862,7 @@ function TMoldClass.GetTableName: string; result := BoldTVByName[TAG_TABLENAME]; end; -procedure TMoldClass.SetUnitName(const Value: string); +procedure TMoldClass.SetBoldUnitName(const Value: string); begin BoldTVByName[TAG_UNITNAME] := Value; end; @@ -1948,7 +1959,7 @@ function TMoldClass.GetOptimisticLocking: TBoldOptimisticLockingMode; function TMoldClass.GetExpandedUnitName: string; begin - result := BoldExpandName(UnitName, Name, xtDelphi, -1, Model.NationalCharConversion); + result := BoldExpandName(BoldUnitName, Name, xtDelphi, -1, Model.NationalCharConversion); end; procedure TMoldClass.TrimRemoved; @@ -2041,7 +2052,7 @@ function TMoldClass.GetHasDelphiAttributesWithAccessorFunctions: Boolean; function TMoldClass.GetUMLClassName: string; begin - result := 'Class'; // do not localize + result := 'Class'; end; function TMoldClass.CalculateCRC: Cardinal; @@ -2081,8 +2092,7 @@ function TMoldClass.GetStorage: TBoldStorage; function TMoldComponentList.GetItem(index: Integer): TMoldComponent; begin - Result := TMoldComponent(inherited Items[index]); -// Result := TMoldComponent(inherited Items[index]); + Result := TMoldComponent(inherited Items[index]); end; function TMoldComponentList.GetItemByName(const name: string): TMoldComponent; @@ -2096,7 +2106,6 @@ function TMoldComponentList.GetItemByName(const name: string): TMoldComponent; result := Items[i]; break; end; -// Result := TMoldComponent(TNameIndex(Indexes[IX_Name]).FindByString(name)); end; { TMoldComponent } @@ -2136,7 +2145,6 @@ constructor TMoldComponent.create(MoldModel: TMoldModel); begin inherited create; fDependencies := TMoldComponentlist.Create; -// fDependencies.OwnsEntries := false; fMoldModel := MoldModel; end; @@ -2150,7 +2158,7 @@ function TMoldComponent.dependentOf(Component: TMoldComponent): Boolean; dependencyList.Free; end; -destructor TMoldComponent.Destroy; +destructor TMoldComponent.destroy; begin FreeAndNil(fDependencies); inherited; @@ -2163,8 +2171,7 @@ function TMoldRole.GetMulti: Boolean; rtLinkRole: Result := (GetUpperLimitForMultiplicity(Multiplicity) > 1) or (fRelatedRole.Qualifiers.Count > 0); rtInnerLinkRole: Result := false; else - // there are only three rolekinds, this mainly to fool compiler hints; - raise EBold.CreateFmt(sUnknownRoleType, [ClassName, MoldClass.Name, Name]); + raise EBold.CreateFmt('%s.GetMulti: Unknown roletype for %s.%s', [ClassName, MoldClass.Name, Name]); end; end; @@ -2237,7 +2244,7 @@ function TMoldModel.RenameComponent(const OldComponentName, result.Name := NewComponentName; end; -function TMoldModel.GetUnitName: string; +function TMoldModel.GetBoldUnitName: string; begin result := BoldTVByName[TAG_UNITNAME]; end; @@ -2250,7 +2257,6 @@ procedure TMoldElement.SetBoldTVByName(const Tag, value: string); TrimmedValue := BoldTrim(Value); Definition := DefaultBoldTVList.DefinitionForTag[Tag]; if Assigned(Definition) and (Definition.DefaultValue = TrimmedValue) then - // do Nothing else BoldTaggedValues.ValueByName[Tag] := TrimmedValue; end; @@ -2301,7 +2307,7 @@ function TMoldRole.GetReverseDerived: Boolean; function TMoldMember.GetDerivationOCL: String; begin - result := BoldTVByName['DerivationOCL']; // do not localize + result := BoldTVByName['DerivationOCL']; end; function TMoldMember.GetMemberExists: boolean; @@ -2345,18 +2351,17 @@ function TMoldMethod.GetCallSignature: string; function TMoldModel.GetMainComponent: TMoldComponent; var - UnitName: String; + BoldUnitName: String; begin - UnitName := ExpandedUnitName; - if UnitName = '' then - UnitName := ExpandedDelphiName; + BoldUnitName := ExpandedUnitName; + if BoldUnitName = '' then + BoldUnitName := ExpandedDelphiName; - Result := EnsureComponent(unitName); + Result := EnsureComponent(BoldUnitName); end; procedure TMoldElement.NameChanged; begin - // do nothing end; function TMoldElement.GetDelphiName: string; @@ -2369,6 +2374,12 @@ function TMoldModel.GetInterfaceUses: string; result := BoldTVByName[TAG_INTERFACEUSES]; end; +constructor TMoldMember.Create(Parent: TMoldElement; const Name: string); +begin + inherited Create(Parent, Name); + fIndex := -1; +end; + function TMoldMember.GetColumnName: string; begin result := BoldTVByName[TAG_COLUMNNAME]; @@ -2392,7 +2403,6 @@ function TMoldRole.GetMandatory: Boolean; function TMoldElement.GetExpressionName: string; begin result := BoldTVByName[TAG_EXPRESSIONNAME]; - // associations does not have a Tagged value ExpressionName, but they still have an ExpressionName in Mold. if result = '' then result := TV_NAME; end; @@ -2456,7 +2466,7 @@ function TMoldAttribute.GetPersistent: Boolean; function TMoldAttribute.GetUMLClassName: string; begin - result := 'Attribute'; // do not localize + result := 'Attribute'; end; function TMoldAssociation.GetPersistent: Boolean; @@ -2495,6 +2505,7 @@ function TMoldModel.GetUseXFiles: Boolean; result := TVIsTrue(BoldTVByName[TAG_USEXFILES]); end; + function TMoldModel.GetImplementationUses: string; begin result := BoldTVByName[TAG_IMPLEMENTATIONUSES]; @@ -2539,13 +2550,9 @@ function TMoldMethod.GetHasDispId: Boolean; begin result := (FuncType in [dfNormal, dfVirtual, dfDynamic, dfAbstractVirtual]) and (Visibility = vkPublic); - - // each parameter must be a valid COM/IDL type - if Assigned(fParameters) then // Due to lazy create + if Assigned(fParameters) then for i := 0 to fParameters.Count -1 do result := result and (TBoldMetaSupport.ParameterTypeToIDLType(TMoldParameter(fParameters[i]).ParameterType, MoldClass.Model, dummy) <> ''); - - // returntype must be valid result := result and ((returnType = '') or (TBoldMetaSupport.ParameterTypeToIDLType(returnType, MoldClass.Model, dummy) <> '')); end; @@ -2600,7 +2607,7 @@ function TMoldRole.GetTypeStreamName: string; function TMoldModel.GetExpandedUnitName: string; begin - result := BoldExpandName(UnitName, Name, xtDelphi, -1, Model.NationalCharConversion); + result := BoldExpandName(BoldUnitName, Name, xtDelphi, -1, Model.NationalCharConversion); end; procedure TMoldElement.SetStdTVByName(const Tag, Value: string); @@ -2673,7 +2680,7 @@ procedure TMoldModel.TrimRemoved; i: integer; begin if fLinkRolesEnsured then - raise EBold.Create(sCannotTrimAfterLinkRolesEnsured); + raise EBold.Create('Can not trim removed elements after the linkroles have been ensured...'); ClassList := TMoldClassList.Create; AssocList := TMoldAssociationList.Create; @@ -2687,7 +2694,6 @@ for i := classes.count-1 downto 0 do if Associations[i].EvolutionState = esRemoved then RemoveAssoc(Associations[i], ClassList, AssocList); finally - // this will free all elements in the lists... FreeAndNil(ClassList); freeAndNil(AssocList); end; @@ -2698,7 +2704,7 @@ for i := classes.count-1 downto 0 do function TMoldModel.GetUMLClassName: string; begin - result := 'Model'; // do not localize + result := 'Model'; end; function TMoldRole.GetEffectiveDelayedFetch: Boolean; @@ -2725,6 +2731,28 @@ function TMoldElement.GetHasDispId: boolean; Result := false; end; +procedure TMoldModel.EnsureTopSorted; +var + ClassIx, SubClassIx: Integer; +begin + if Topsorted then + Exit; + Classes.OwnsEntries := false; + Classes.Clear; + Classes.OwnsEntries := true; + Classes.Add(RootClass); + ClassIx := 0; + while ClassIx < Classes.Count do + begin + Classes[ClassIx].SubClasses.Sort(ClassesComparer); + for SubClassIx := 0 to Classes[ClassIx].SubClasses.Count-1 do + Classes.Add(Classes[ClassIx].SubClasses[SubClassIx]); + Classes[ClassIx].fTopSortedIndex := ClassIx; + inc(ClassIx); + end; + fTopSorted := True; +end; + procedure TMoldModel.AssignDispIds; var i: integer; @@ -2739,7 +2767,7 @@ procedure TMoldModel.AssignDispIds; function TMoldElement.GetDispId: integer; begin if not HasDispId then - raise EBold.Create(sMemberHasNoDispID); + raise EBold.Create('member has no Dispid'); if not Model.DispIdsAssigned then Model.AssignDispIds; Result := fDispId; @@ -2759,6 +2787,16 @@ function TMoldAttribute.GetHasDispId: boolean; end; end; +function TMoldAttribute.GetIsAttribute: boolean; +begin + result := true; +end; + +function TMoldAttribute.GetIsRole: boolean; +begin + result := false; +end; + function TMoldRole.GetHasDispId: boolean; begin Result := False; @@ -2818,7 +2856,6 @@ function TMoldAssociation.GetAllPossibleNames: TStringList; try for Rn1Ix := 0 to Rolenames1.Count-1 do for Rn2Ix := 0 to RoleNames2.Count-1 do - // skip the combination of the two current names (they are last in each list)... if not ((Rn1Ix = Rolenames1.Count-1) and (Rn2Ix = Rolenames2.Count-1)) then begin fAllPossibleNames.Add(RoleNames1[Rn1Ix]+Rolenames2[Rn2Ix]); @@ -2840,7 +2877,7 @@ function TMoldAssociation.GetStorage: TBoldStorage; { TMoldParameter } -constructor TMoldParameter.create(OwningMethod: TMoldMethod); +constructor TMoldParameter.Create(OwningMethod: TMoldMethod); begin inherited Create; fOwningMethod := OwningMethod; @@ -2907,13 +2944,13 @@ function TMoldRole.CalculateCRC: Cardinal; function TMoldModel.CRC: string; begin EnsureCRC; - result := BoldTVByName['CRC']; // do not localize + result := BoldTVByName['CRC']; end; procedure TMoldModel.EnsureCRC; begin - if BoldTVByName['CRC'] = '' then // do not localize - BoldTVByName['CRC'] := intToStr(CalculateCRC); // do not localize + if BoldTVByName['CRC'] = '' then + BoldTVByName['CRC'] := intToStr(CalculateCRC); end; function TMoldModel.GetDefaultDeleteAction(AggregationKind: TAggregationKind): TDeleteAction; @@ -2975,7 +3012,7 @@ function TMoldMethod.GetCanCallInherited: Boolean; end; function TMoldElement.GetDefaultBoldTVList: TBoldTaggedValueList; - procedure DoGet; // own procedure avoids string handling overhead + procedure DoGet; begin fDefaultBoldTVList := BoldDefaultTaggedValueList.ListForClassName[UMLClassName]; end; @@ -3054,13 +3091,16 @@ procedure TMoldElement.SetNonDefaultTaggedValuesCommaText( G := TBoldGuard.Create(StringList); StringList := TStringList.Create; Stringlist.CommaText := Value; + if StringList.Count = 0 then + exit; + TaggedValues.Capacity := StringList.Count; for i := 0 to StringList.Count-1 do begin Line := StringList[i]; EqualPos := Pos('=', Line); Assert(EqualPos <> 0); Name := Copy(Line, 1, EqualPos-1); - if Name = 'Persistence' then // do not localize + if Name = 'Persistence' then Name := TAG_PERSISTENCE; TVByName[Name] := Copy(Line, EqualPos + 1, MaxInt); end; @@ -3103,4 +3143,9 @@ function TMoldRole.GetStorage: TBoldStorage; result := Association.Storage; end; +initialization + TMoldElementList.IX_Name := -1; + TMoldClassList.IX_ExpressionName := -1; + TMoldClassList.IX_DelphiName := -1; + end. diff --git a/Source/MoldModel/Core/BoldMetaSupport.pas b/Source/MoldModel/Core/BoldMetaSupport.pas index cc758da..8a4c8ee 100644 --- a/Source/MoldModel/Core/BoldMetaSupport.pas +++ b/Source/MoldModel/Core/BoldMetaSupport.pas @@ -1,11 +1,12 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldMetaSupport; interface uses - BoldMeta, - BoldDefaultTaggedValues, - BoldDefs; + BoldMeta; type { forward declarations } @@ -52,11 +53,12 @@ TBoldNamePairRecord = record BoldWideStringTypeName = 'WideString'; BoldWordBoolTypeName = 'WordBool'; + implementation uses SysUtils, - BoldUtils; + BoldRev; type TBoldCOMIDLTypeNameMapping = record @@ -67,19 +69,19 @@ TBoldCOMIDLTypeNameMapping = record const BoldCOMIDLTypeNameMapping: array[0..21] of TBoldCOMIDLTypeNameMapping = ( - (DelphiName: 'String'; IDLName: 'BSTR'; ComName: BoldWideStringTypeName), //Type Conversion, Automation safe - (DelphiName: 'Integer'; IDLName: 'long'; ComName: 'Integer'), //Automation safe - (DelphiName: 'Boolean'; IDLName: 'VARIANT_BOOL'; ComName: BoldWordBoolTypeName), //Type Conversion, Automation safe - (DelphiName: 'Currency'; IDLName: 'CURRENCY'; ComName: 'Currency'), //Automation safe - (DelphiName: 'Double'; IDLName: 'double'; ComName: 'Double'), //Automation safe - (DelphiName: 'TDateTime'; IDLName: 'DATE'; ComName: 'TDateTime'), //Automation safe - (DelphiName: 'Longint'; IDLName: 'long'; ComName: 'Longint'), //Automation safe - (DelphiName: 'Smallint'; IDLName: 'short'; ComName: 'Smallint'), //Automation safe - (DelphiName: 'Single'; IDLName: 'float'; ComName: 'Single'), //Automation safe - (DelphiName: 'WideString'; IDLName: 'BSTR'; ComName: 'WideString'), //Automation safe - (DelphiName: 'WordBool'; IDLName: 'VARIANT_BOOL'; ComName: 'WordBool'), //Automation safe - (DelphiName: 'OleVariant'; IDLName: 'VARIANT'; ComName: 'OleVariant'), //Automation safe - (DelphiName: 'Variant'; IDLName: 'VARIANT'; ComName: 'OleVariant'), //Type Conversion, Automation safe + (DelphiName: 'String'; IDLName: 'BSTR'; ComName: BoldWideStringTypeName), + (DelphiName: 'Integer'; IDLName: 'long'; ComName: 'Integer'), + (DelphiName: 'Boolean'; IDLName: 'VARIANT_BOOL'; ComName: BoldWordBoolTypeName), + (DelphiName: 'Currency'; IDLName: 'CURRENCY'; ComName: 'Currency'), + (DelphiName: 'Double'; IDLName: 'double'; ComName: 'Double'), + (DelphiName: 'TDateTime'; IDLName: 'DATE'; ComName: 'TDateTime'), + (DelphiName: 'Longint'; IDLName: 'long'; ComName: 'Longint'), + (DelphiName: 'Smallint'; IDLName: 'short'; ComName: 'Smallint'), + (DelphiName: 'Single'; IDLName: 'float'; ComName: 'Single'), + (DelphiName: 'WideString'; IDLName: 'BSTR'; ComName: 'WideString'), + (DelphiName: 'WordBool'; IDLName: 'VARIANT_BOOL'; ComName: 'WordBool'), + (DelphiName: 'OleVariant'; IDLName: 'VARIANT'; ComName: 'OleVariant'), + (DelphiName: 'Variant'; IDLName: 'VARIANT'; ComName: 'OleVariant'), (DelphiName: 'Shortint'; IDLName: 'byte'; ComName: 'Shortint'), (DelphiName: 'Int64'; IDLName: '__int64'; ComName: 'Int64'), (DelphiName: 'Byte'; IDLName: 'unsigned char'; ComName: 'Byte'), @@ -139,8 +141,9 @@ class function TBoldMetaSupport.ParameterTypeToInterfaceType( result := ''; MoldClass := MoldModel.Classes.ItemsByName[ParameterType]; if assigned(MoldClass) then - result := MoldClass.ExpandedInterfaceName - else + result := MoldClass.ExpandedInterfaceName; + + if not Assigned(MoldClass) then begin MoldClass := MoldModel.Classes.ItemsByDelphiName[ParameterType]; if assigned(MoldClass) then @@ -158,17 +161,29 @@ class function TBoldMetaSupport.ParameterTypeToInterfaceType( end; end; - if SameText(ParameterType, 'IDispatch') then // do not localize + if (result ='') and (ParameterType <> 'TList') and (Pos('List',ParameterType) = Length(ParameterType)-3) then begin - result := 'IDispatch'; // do not localize + MoldClass := MoldModel.Classes.ItemsByDelphiName[Copy(ParameterType,1, Length(ParameterType) - 4)]; + if not Assigned(MoldClass) then + MoldClass := MoldModel.Classes.ItemsByName[Copy(ParameterType,1, Length(ParameterType) - 4)]; + + if assigned(MoldClass) then + result := MoldClass.ExpandedInterfaceName + 'List'; + end; + + if SameText(ParameterType, 'IDispatch') then + begin + result := 'IDispatch'; exit; end; - if SameText(ParameterType, 'IUnknown') then // do not localize + if SameText(ParameterType, 'IUnknown') then begin - result := 'IUnknown'; // do not localize + result := 'IUnknown'; exit; end; end; +initialization + end. diff --git a/Source/MoldModel/Core/BoldMoldConsts.pas b/Source/MoldModel/Core/BoldMoldConsts.pas index 7106995..66f44c7 100644 --- a/Source/MoldModel/Core/BoldMoldConsts.pas +++ b/Source/MoldModel/Core/BoldMoldConsts.pas @@ -1,53 +1,20 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldMoldConsts; interface resourcestring + sRecursiveAssignment = 'Attempt to make recursive assignment'; - sClassIsRelation = 'Class "%s" is already relation class for another association'; - -//BoldBld - sErrorOnPos = '%s Line: %d Position: %d'; - sUnexpectedEOF = 'BLD Reader: Unexpected EOF'; - sBadCharacter = 'BLD Reader: Bad character %s'; - sSyntaxError = 'BLD Reader: Syntax error'; - sAKeywordExpected = 'BLD Reader: ''%s'' expected'; - sQuotedStringExpected = 'BLD Reader: Quoted string expected'; - sKeyWordTokenExpected = 'BLD Reader: KEYWORD expected'; - sIntegerExpected = 'BLD Reader: Integer expected'; - sBooleanExpected = 'BLD Reader: Boolean expected'; - -//BoldGen - sLogGeneratingInPath = 'Generating in path: %s'; - sLogGeneratingFile = 'Generating file: %s'; - sLogInitializingVars = 'Initializing variables'; - sLogExpandingTemplate = 'Expanding template'; - sLogConsiderNameChange1 = 'You should consider naming your model and base unit'; - sLogConsiderNameChange2 = 'to avoid filename conflicts with other projects'; - sLogNoDelphiMappingForType = 'No Delphimapping for type %s'; - sLogNoCOMMappingForType = 'No COM/IDL mapping for type %s, No attribute generated for %s.%s'; - sLogNoNativeMappingForType = 'No native mapping for type %s used in attribute %s.%s, only Bold attribute generated'; - sNoValueTypeMappingForType = 'No Valueinterface mapping for type %s used in persistent attribute %s.%s'; - sProcessingClassXFileY = 'Processing class %s, file %s'; - sMoveToComponent_NoSuperClass = 'MoveClassTreeToComponent: No SuperClass'; - sMoveToComponent_NoMoldModel = 'MoveClassTreeToComponent: No MoldModel'; - sCollidingFileName = 'WARNING! class %s has a file name that collides with another component (%s)!'; - sNoTemplateForPersistenceInterfaces = 'No template defined for PersistenceInterfaces'; - -//BoldMeta - sUnknownRoleType = '%s.GetMulti: Unknown roletype for %s.%s'; - sCannotTrimAfterLinkRolesEnsured = 'Can not trim removed elements after the linkroles have been ensured...'; - sMemberHasNoDispID = 'Member has no Dispid'; - -//BoldTypeNameHandleReg - sEditTypeNames = 'Edit type names'; + sClassIsRelation = 'Class is already relation class for another association'; + +implementation -//BoldNameExpander - sNameHasInvalidChars = 'Name has invalid characters'; - sNameTooLong = 'Name is too long'; - sNameCannotBeEmpty = 'Name can not be empty'; - sInvalidFirstChar = 'Name must begin with an alpha-character or underscore'; +uses + BoldRev; -implementation +initialization end. diff --git a/Source/MoldModel/Core/BoldNameExpander.pas b/Source/MoldModel/Core/BoldNameExpander.pas index c0ed839..b26c069 100644 --- a/Source/MoldModel/Core/BoldNameExpander.pas +++ b/Source/MoldModel/Core/BoldNameExpander.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldNameExpander; interface @@ -6,11 +9,6 @@ interface BoldDefs, BoldTaggedValueSupport; -// Ideas for the future: -// German double-S to ss -// Handle danish ae, oe -// Drawbacks: Performance! - type { forward declarations } TBoldAbstractNameExpander = class; @@ -24,7 +22,7 @@ TBoldDelphiNameExpanderClass = class of TBoldDelphiNameExpander; TBoldExpressionNameExpanderClass = class of TBoldExpressionNameExpander; TExpansionType = (xtDelphi, xtSQL, xtExpression); - TBoldCharacterSet = set of char; + TBoldCharacterSet = set of {$IFDEF BOLD_UNICODE}AnsiChar{$ELSE}Char{$ENDIF}; { TBoldAbstractNameExpander } TBoldAbstractNameExpander = class @@ -47,7 +45,6 @@ TBoldSQLNameExpander = class(TBoldAbstractNameExpander) protected function GetValidCharacters: TBoldCharacterSet; override; public -// function TruncateName(const Name: String; MaxIdentifierLength: integer): string; override; function ExpandName(const Name, ReplacementName: string): string; override; end; @@ -78,8 +75,8 @@ TBoldExpressionNameExpander = class(TBoldAbstractNameExpander) BoldSQLNameExpanderNameLimit: integer = 255; BoldSQLNameExpanderUpperCaseNames: boolean = false; -function BoldExpandName(Name, ReplacementName: string; ExpansionType: TExpansionType; MaxIdentifierLength: integer; NationalCharConversion: TBoldNationalCharConversion): string; -function BoldExpandPrefix(value: String; const ReplacementName, Prefix: String; MaxIdentifierLength: integer; NationalCharConversion: TBoldNationalCharConversion): String; +function BoldExpandName(const Name, ReplacementName: string; ExpansionType: TExpansionType; MaxIdentifierLength: integer; NationalCharConversion: TBoldNationalCharConversion): string; +function BoldExpandPrefix(const value: String; const ReplacementName, Prefix: String; MaxIdentifierLength: integer; NationalCharConversion: TBoldNationalCharConversion): String; implementation @@ -87,15 +84,14 @@ implementation SysUtils, BoldUtils, BoldSharedStrings, - BoldDefaultTaggedValues, - BoldMoldConsts; + BoldDefaultTaggedValues; var BoldSQLNameExpander: TBoldSQLNameExpander = nil; BoldDelphiNameExpander: TBoldDelphiNameExpander = nil; BoldExpressionNameExpander: TBoldExpressionNameExpander = nil; -function BoldExpandName(Name, ReplacementName: string; +function BoldExpandName(const Name, ReplacementName: string; ExpansionType: TExpansionType; MaxIdentifierLength: integer; NationalCharConversion: TBoldNationalCharConversion): string; @@ -110,10 +106,10 @@ function BoldExpandName(Name, ReplacementName: string; BoldSQLNameExpander.Free; BoldSQLNameExpander := BoldSQLNameExpanderClass.Create; end; - + if MaxIdentifierLength = -1 then MaxIdentifierLength := BoldSQLNameExpanderNameLimit; - + CurrentNameExpander := BoldSQLNameExpander; end; xtDelphi: begin @@ -146,7 +142,7 @@ function BoldExpandName(Name, ReplacementName: string; result := BoldSharedStringManager.GetSharedString(Result); end; -function BoldExpandPrefix(value: String; +function BoldExpandPrefix(const value: String; const ReplacementName, Prefix: String; MaxIdentifierLength: integer; NationalCharConversion: TBoldNationalCharConversion): String; @@ -184,7 +180,7 @@ function TBoldAbstractNameExpander.ExpandName(const Name, ReplacementName: strin DoExpand(Copy(S, I + TV_NAME_Length, MaxInt)) else Result := S; - end; + end; end; begin Result := DoExpand(Name); @@ -278,7 +274,7 @@ function TBoldAbstractNameExpander.MapCharacters(const Name: String; validChars := ValidCharacters; if validChars <> [] then for i := 1 to Length(result) do - if not (result[i] in ValidChars) then + if not CharInSet(result[i], ValidChars) then result[i] := MapCharacter[result[i], NationalCharConversion]; end; @@ -320,18 +316,18 @@ function TBoldAbstractNameExpander.ValidateName(Name: String; if name <> MapCharacters(Name, NationalCharConversion) then begin result := false; - reason := sNameHasInvalidChars; + reason := 'Name has invalid characters'; end; if name <> truncateName(Name, MaxIdentifierLength) then begin result := false; - reason := sNameTooLong; + reason := 'Name is too long'; end; if result then begin if not LanguageIsCaseSensitive then name := UpperCase(Name); - end; + end; end; { TBoldSQLNameExpander } @@ -386,7 +382,7 @@ function TBoldDelphiNameExpander.MapCharacters(const Name: String; NationalCharConversion: TBoldNationalCharConversion): string; begin result := inherited MapCharacters(Name, NationalCharConversion); - if (length(result) > 0) and not (result[1] in ['a'..'z', 'A'..'Z', '_']) then + if (length(result) > 0) and not CharInSet(result[1], ['a'..'z', 'A'..'Z', '_']) then result[1] := MapCharacter[result[1], NationalCharConversion]; end; @@ -399,12 +395,12 @@ function TBoldDelphiNameExpander.ValidateName(Name: String; if result and (length(name) = 0) then begin result := false; - reason := sNameCannotBeEmpty; + reason := 'Name can not be empty'; end; - if result and not (name[1] in ['a'..'z', 'A'..'Z', '_']) then + if result and not CharInSet(name[1], ['a'..'z', 'A'..'Z', '_']) then begin result := false; - reason := sInvalidFirstChar; + reason := 'Name must begin with an alpha-character or underscore'; end; end; @@ -419,7 +415,7 @@ function TBoldExpressionNameExpander.MapCharacters(const Name: String; NationalCharConversion: TBoldNationalCharConversion): string; begin result := inherited MapCharacters(Name, NationalCharConversion); - if (length(result) > 0) and not (result[1] in ['a'..'z', 'A'..'Z', '_']) then + if (length(result) > 0) and not CharInSet(result[1], ['a'..'z', 'A'..'Z', '_']) then result[1] := MapCharacter[result[1], NationalCharConversion]; end; @@ -432,13 +428,13 @@ function TBoldExpressionNameExpander.ValidateName(Name: String; if result and (length(name) = 0) then begin result := false; - reason := sNameCannotBeEmpty; + reason := 'Name can not be empty'; end; - if result and not (name[1] in ['a'..'z', 'A'..'Z', '_']) then + if result and not CharInSet(name[1], ['a'..'z', 'A'..'Z', '_']) then begin result := false; - reason := sInvalidFirstChar; + reason := 'Name must begin with an alpha-character or underscore'; end; end; diff --git a/Source/MoldModel/Handles/BoldAbstractModel.pas b/Source/MoldModel/Handles/BoldAbstractModel.pas index 542698f..667e8bc 100644 --- a/Source/MoldModel/Handles/BoldAbstractModel.pas +++ b/Source/MoldModel/Handles/BoldAbstractModel.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldAbstractModel; interface @@ -13,7 +16,6 @@ interface beModelChanged = 25; type - // Forward declarations of all classes TBoldAbstractModel = class; { TBoldAbstractModel } @@ -36,10 +38,10 @@ TBoldAbstractModel = class(TBoldSubscribableComponent) procedure DefineProperties(Filer: TFiler); override; procedure Notification(AComponent: TComponent; Operation: TOperation); override; procedure EnsureMoldModelCurrent; virtual; - procedure SetFromModel(model: TMoldModel); public constructor Create(AOwner: TComponent); override; destructor Destroy; override; + procedure SetFromModel(model: TMoldModel); //PATCH CFloury made public procedure UpdateDesigner; procedure WriteToBeRemovedInfoToFile(FileName: String); property MoldModel: TMoldModel read GetMoldModel; @@ -64,7 +66,6 @@ implementation constructor TBoldAbstractModel.Create(AOwner: TComponent); begin inherited Create(AOwner); - fComponentStyle := fComponentStyle - [csInheritable]; SetFromModel(nil); end; @@ -96,7 +97,6 @@ procedure TBoldAbstractModel.DefineProperties(Filer: TFiler); begin ModelAsStrings := TStringList.Create; AncestorModelAsStrings := TStringList.Create; - // takes care of not writing the model on an inherited form if it has not been changed TMoldBLDRW.ModelToStrings(RawMoldModel, ModelAsStrings); TMoldBLDRW.ModelToStrings((Filer.Ancestor as TBoldAbstractModel).RawMoldModel,AncestorModelAsStrings); Result := not ModelAsStrings.Equals(AncestorModelAsStrings); @@ -105,7 +105,7 @@ procedure TBoldAbstractModel.DefineProperties(Filer: TFiler); begin inherited DefineProperties(Filer); - Filer.DefineProperty('Model', ReadModel, WriteModel, DoWriteModel); // do not localize + Filer.DefineProperty('Model', ReadModel, WriteModel, DoWriteModel); end; procedure TBoldAbstractModel.ReadModel(Reader: TReader); @@ -285,9 +285,12 @@ procedure TBoldAbstractModel.WriteToBeRemovedInfoToFile(FileName: String); end; end; + procedure TBoldAbstractModel.EnsureMoldModelCurrent; begin end; +initialization + end. diff --git a/Source/MoldModel/Handles/BoldTypeNameHandle.pas b/Source/MoldModel/Handles/BoldTypeNameHandle.pas index f61270e..f212c3e 100644 --- a/Source/MoldModel/Handles/BoldTypeNameHandle.pas +++ b/Source/MoldModel/Handles/BoldTypeNameHandle.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldTypeNameHandle; interface @@ -25,7 +28,8 @@ TBoldTypeNameHandle = class(TComponent) implementation uses - SysUtils; + SysUtils, + BoldRev; { TBoldTypeNameHandle } @@ -47,4 +51,6 @@ procedure TBoldTypeNameHandle.SetDictionary(const Value: TBoldTypeNameDictionary FDictionary.Assign(Value); end; +initialization + end. diff --git a/Source/MoldModel/IDE/BoldModelReg.pas b/Source/MoldModel/IDE/BoldModelReg.pas index 62d29b1..41ba779 100644 --- a/Source/MoldModel/IDE/BoldModelReg.pas +++ b/Source/MoldModel/IDE/BoldModelReg.pas @@ -1,25 +1,29 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldModelReg; interface +uses + DesignIntf, + Classes; + procedure Register; implementation uses SysUtils, - DesignIntf, - Classes, BoldUtils, + BoldGuard, BoldTypeNameHandle, BoldAbstractModel, BoldIDEConsts; -{.$R BoldModelReg.res} - procedure Register; begin RegisterComponents(BOLDPAGENAME_MISC, [TBoldTypeNameHandle]); end; -end. +end. diff --git a/Source/MoldModel/IDE/BoldTypeNameHandleReg.pas b/Source/MoldModel/IDE/BoldTypeNameHandleReg.pas index a5c1e06..79d7c82 100644 --- a/Source/MoldModel/IDE/BoldTypeNameHandleReg.pas +++ b/Source/MoldModel/IDE/BoldTypeNameHandleReg.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldTypeNameHandleReg; interface @@ -37,13 +40,15 @@ implementation Controls, BoldTypeNameDictionary, BoldTypeNameHandle, - BoldTypeNameEditor, - BoldMoldConsts; + + BoldTypeNameEditor, + BoldGuard, + BoldRev; procedure Register; begin RegisterComponentEditor(TBoldTypeNameHandle, TBoldTypeNameEditor); - RegisterPropertyEditor(TypeInfo(TBoldTypeNameDictionary), TBoldTypeNameHandle, 'Dictionary', TBoldTypeNamePropEditor); // do not localize + RegisterPropertyEditor(TypeInfo(TBoldTypeNameDictionary), TBoldTypeNameHandle, 'Dictionary', TBoldTypeNamePropEditor); end; { TTBoldModelEditor } @@ -55,23 +60,21 @@ procedure TBoldTypeNameEditor.ExecuteVerb(index: Integer); with Component as TBoldTypeNameHandle do begin EditorForm := TBoldTypeNameEditorForm.Create(nil); - try - EditorForm.LoadFromDictionary(Dictionary); - - if EditorForm.ShowModal = mrOK then - begin - EditorForm.SaveToDictionary(Dictionary); - Designer.Modified; - end; - finally - EditorForm.Free; + EditorForm.LoadFromDictionary(Dictionary); + + if EditorForm.ShowModal = mrOK then + begin + EditorForm.SaveToDictionary(Dictionary); + Designer.Modified; end; + + EditorForm.Free; end; end; function TBoldTypeNameEditor.GetVerb(index: Integer): string; begin - result := sEditTypeNames; + result := 'Edit type names'; end; function TBoldTypeNameEditor.GetVerbCount: Integer; @@ -107,7 +110,7 @@ function TBoldTypeNamePropEditor.GetAttributes: TPropertyAttributes; function TBoldTypeNamePropEditor.GetValue: String; begin - result := 'TBoldTypeNameDictionary'; // do not localize + result := 'TBoldTypeNameDictionary'; end; end. diff --git a/Source/MoldModel/TypeNameDictionary/BoldTypeNameDictionary.pas b/Source/MoldModel/TypeNameDictionary/BoldTypeNameDictionary.pas index b8fb488..2184c9d 100644 --- a/Source/MoldModel/TypeNameDictionary/BoldTypeNameDictionary.pas +++ b/Source/MoldModel/TypeNameDictionary/BoldTypeNameDictionary.pas @@ -1,10 +1,12 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldTypeNameDictionary; interface uses - Classes, - BoldDefs; + Classes; type TBoldTypeNameDictionary = class; @@ -19,7 +21,7 @@ TBoldTypeNameMapping = class(TCollectionItem) FNativeType: String; FMapperName: String; fContentsName: String; - fUnitName: String; + fBoldUnitName: String; fComType: String; fIDLType: String; fValueInterface: String; @@ -53,13 +55,13 @@ TBoldTypeNameMapping = class(TCollectionItem) property MapperName: String read FMapperName write fMapperName; property Accessor: String read FAccessor write fAccessor; property NativeType: String read FNativeType write fNativeType; - property UnitNameText: String read fUnitName write fUnitName; + property BoldUnitName: String read fBoldUnitName write fBoldUnitName; + property UnitName: String read fBoldUnitName write fBoldUnitName stored false; property ComType: String read fComType write fComType; property IDLType: String read fIDLType write fIDLType; property ValueInterface: String read fValueInterface write fValueInterface; property ValueInterfaceAccessor: String read fValueInterfaceAccessor write fValueInterfaceAccessor; property ValueInterfaceNativeType: String read fValueInterfaceNativeType write fValueInterfaceNativeType; - end; TBoldTypeNameDictionary = class(TCollection) @@ -90,16 +92,18 @@ implementation uses SysUtils, - BoldUtils, + BoldDefs, BoldNameExpander, BoldTaggedValueSupport; const - DefaultMappings: array[0..29, 0..12] of String = ( -// ModelName ExpressionName DelphiName Contentname PMapper Accessor NativeType Unit ComType IDL ValueInterface - (DEFAULTNAMELITERAL,'String', 'TBA', '', 'TBoldPM', 'As', '', 'BoldAttributes', 'WideString', 'BSTR', 'IBoldStringContent', 'AsString', 'String'), + DefaultMappings: array[0..32, 0..12] of String = ( + (DEFAULTNAMELITERAL,'String', 'TBA', '', 'TBoldPM', 'As', '', 'BoldAttributes', 'WideString', 'BSTR', 'IBoldStringContent', 'AsString', 'String'), ('String', 'String', 'TBA', '', 'TBoldPM', 'As', '', 'BoldAttributes', 'WideString', 'BSTR', 'IBoldStringContent', 'AsString', 'String'), ('AnsiString', 'String', 'TBA', '', 'TBoldPM', 'As', '', 'BoldAttributes', 'WideString', 'BSTR', 'IBoldStringContent', 'AsString', 'String'), + ('UnicodeString', 'UnicodeString','TBA', 'String', 'TBoldPM', 'AsString', 'String', 'BoldAttributes', 'WideString', 'BSTR', 'IBoldUnicodeStringContent', 'AsUnicodeString', 'String'), + ('Text', 'Text', 'TBA', 'String', 'TBoldPM', 'AsString', 'String', 'BoldAttributes', 'WideString', 'BSTR', 'IBoldAnsiStringContent', 'AsAnsiString', 'AnsiString'), + ('UnicodeText', 'UnicodeText', 'TBA', 'String', 'TBoldPM', 'AsString', 'String', 'BoldAttributes', 'WideString', 'BSTR', 'IBoldUnicodeStringContent', 'AsUnicodeString', 'String'), ('', 'Numeric', 'TBA', '', '', '', '', 'BoldAttributes', '', '', '', '', ''), ('Integer', 'Integer', 'TBA', '', 'TBoldPM', 'As', '', 'BoldAttributes', 'Integer', 'LONG', 'IBoldIntegerContent', 'AsInteger', 'integer'), ('Int', 'Integer', 'TBA', '', 'TBoldPM', 'As', '', 'BoldAttributes', 'Integer', 'LONG', 'IBoldIntegerContent', 'AsInteger', 'integer'), @@ -145,7 +149,7 @@ procedure TBoldTypeNameDictionary.AddDefaultMappings; MapperName := DefaultMappings[i, 4]; Accessor := DefaultMappings[i, 5]; NativeType := DefaultMappings[i, 6]; - UnitNameText := DefaultMappings[i, 7]; + BoldUnitName := DefaultMappings[i, 7]; ComType := DefaultMappings[i, 8]; IDLType := DefaultMappings[i, 9]; ValueInterface := DefaultMappings[i, 10]; @@ -243,7 +247,7 @@ procedure TBoldTypeNameDictionary.SaveToStringList(StrList: TStringList); function TBoldTypeNameMapping.GetAsString: string; begin - Result := Format('ModelName=%s,ExpressionName=%s,DelphiName=%s,ContentsName=%s,MapperName=%s,AccessorName=%s,NativeType=%s,UnitName=%s,ComType=%s,IDLType=%s,ValueInterface=%s,ValueInterfaceAccessor=%s,ValueInterfaceNativeType=%s', // do not localize + Result := Format('ModelName=%s,ExpressionName=%s,DelphiName=%s,ContentsName=%s,MapperName=%s,AccessorName=%s,NativeType=%s,UnitName=%s,ComType=%s,IDLType=%s,ValueInterface=%s,ValueInterfaceAccessor=%s,ValueInterfaceNativeType=%s', [ModelName, ExpressionName, DelphiName, @@ -251,7 +255,7 @@ function TBoldTypeNameMapping.GetAsString: string; MapperName, Accessor, NativeType, - UnitNameText, + BoldUnitName, ComType, IDLType, ValueInterface, @@ -285,26 +289,30 @@ function TBoldTypeNameMapping.GetExpandedContentsName: String; end; procedure TBoldTypeNameMapping.SetAsString(const Value: string); +var + vTmpList: TStringList; begin - with TStringList.Create do + vTmpList := TStringList.Create; try - CommaText := value; - ModelName := Values['ModelName']; // do not localize - ExpressionName := Values['ExpressionName']; // do not localize - DelphiName := Values['DelphiName']; // do not localize - if Values['StreamName'] <> '' then // do not localize - ContentsName := Values['StreamName'] // do not localize + vTmpList.CommaText := value; + ModelName := vTmpList.Values['ModelName']; + ExpressionName := vTmpList.Values['ExpressionName']; + DelphiName := vTmpList.Values['DelphiName']; + + if vTmpList.Values['StreamName'] <> '' then + ContentsName := vTmpList.Values['StreamName'] else - ContentsName := Values['ContentsName']; // do not localize - MapperName := Values['MapperName']; // do not localize - Accessor := Values['AccessorName']; // do not localize - NativeType := Values['NativeType']; // do not localize - UnitNameText := Values['UnitName']; // do not localize - ComType := Values['ComType']; // do not localize - IDLType := Values['IDLType']; // do not localize - ValueInterface := Values['ValueInterface']; // do not localize - ValueInterfaceAccessor := Values['ValueInterfaceAccessor']; // do not localize - ValueInterfaceNativeType := Values['ValueInterfaceNativeType']; // do not localize + ContentsName := vTmpList.Values['ContentsName']; + + MapperName := vTmpList.Values['MapperName']; + Accessor := vTmpList.Values['AccessorName']; + NativeType := vTmpList.Values['NativeType']; + BoldUnitName := vTmpList.Values['UnitName']; + ComType := vTmpList.Values['ComType']; + IDLType := vTmpList.Values['IDLType']; + ValueInterface := vTmpList.Values['ValueInterface']; + ValueInterfaceAccessor := vTmpList.Values['ValueInterfaceAccessor']; + ValueInterfaceNativeType := vTmpList.Values['ValueInterfaceNativeType']; finally Free; end; @@ -313,7 +321,7 @@ procedure TBoldTypeNameMapping.SetAsString(const Value: string); procedure TBoldTypeNameMapping.DefineProperties(Filer: TFiler); begin inherited; - Filer.DefineProperty('StreamName', ReadStreamName, nil, False); // do not localize + Filer.DefineProperty('StreamName', ReadStreamName, nil, False); end; procedure TBoldTypeNameMapping.ReadStreamName(Reader: TReader); @@ -324,8 +332,7 @@ procedure TBoldTypeNameMapping.ReadStreamName(Reader: TReader); procedure TBoldTypeNameMapping.AssignTo(Dest: TPersistent); begin if dest is TBoldTypeNameMapping then - with dest as TBoldTypeNameMapping do - begin + with dest as TBoldTypeNameMapping do begin ModelName := self.ModelName; ExpressionName := self.ExpressionName; DelphiName := self.DelphiName; @@ -333,7 +340,7 @@ procedure TBoldTypeNameMapping.AssignTo(Dest: TPersistent); MapperName := self.MapperName; Accessor := self.Accessor; NativeType := self.NativeType; - UnitNameText := self.UnitNameText; + BoldUnitName := self.BoldUnitName; ComType := self.ComType; IDLType := self.IDLType; ValueInterface := self.ValueInterface; @@ -344,9 +351,12 @@ procedure TBoldTypeNameMapping.AssignTo(Dest: TPersistent); inherited; end; + function TBoldTypeNameMapping.GetExpandedComType: String; begin result := BoldExpandName(ComType, ExpressionName, xtExpression, -1, nccDefault); end; + +initialization end. diff --git a/Source/MoldModel/UtilsGUI/BoldTypeNameEditor.pas b/Source/MoldModel/UtilsGUI/BoldTypeNameEditor.pas index 4f90152..181f547 100644 --- a/Source/MoldModel/UtilsGUI/BoldTypeNameEditor.pas +++ b/Source/MoldModel/UtilsGUI/BoldTypeNameEditor.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldTypeNameEditor; interface @@ -57,25 +60,26 @@ implementation uses SysUtils, - BoldUtils; + BoldUtils, + BoldRev; {$R *.dfm} procedure TBoldTypeNameEditorForm.FormCreate(Sender: TObject); begin - StringGrid1.Cells[0, 0] := 'ModelName'; // do not localize - StringGrid1.Cells[1, 0] := 'ExpressionName'; // do not localize - StringGrid1.Cells[2, 0] := 'DelphiName'; // do not localize - StringGrid1.Cells[3, 0] := 'ContentName'; // do not localize - StringGrid1.Cells[4, 0] := 'PMapper'; // do not localize - StringGrid1.Cells[5, 0] := 'Accessor'; // do not localize - StringGrid1.Cells[6, 0] := 'NativeType'; // do not localize - StringGrid1.Cells[7, 0] := 'UnitName'; // do not localize - StringGrid1.Cells[8, 0] := 'ComType'; // do not localize - StringGrid1.Cells[9, 0] := 'IDLType'; // do not localize - StringGrid1.Cells[10, 0] := 'ValueInterface'; // do not localize - StringGrid1.Cells[11, 0] := 'VI-accessor'; // do not localize - StringGrid1.Cells[12, 0] := 'VI-NativeType'; // do not localize + StringGrid1.Cells[0, 0] := 'ModelName'; + StringGrid1.Cells[1, 0] := 'ExpressionName'; + StringGrid1.Cells[2, 0] := 'DelphiName'; + StringGrid1.Cells[3, 0] := 'ContentName'; + StringGrid1.Cells[4, 0] := 'PMapper'; + StringGrid1.Cells[5, 0] := 'Accessor'; + StringGrid1.Cells[6, 0] := 'NativeType'; + StringGrid1.Cells[7, 0] := 'UnitName'; + StringGrid1.Cells[8, 0] := 'ComType'; + StringGrid1.Cells[9, 0] := 'IDLType'; + StringGrid1.Cells[10, 0] := 'ValueInterface'; + StringGrid1.Cells[11, 0] := 'VI-accessor'; + StringGrid1.Cells[12, 0] := 'VI-NativeType'; end; procedure TBoldTypeNameEditorForm.btnAddClick(Sender: TObject); @@ -83,12 +87,12 @@ procedure TBoldTypeNameEditorForm.btnAddClick(Sender: TObject); StringGrid1.RowCount := StringGrid1.RowCount + 1; StringGrid1.Row := StringGrid1.RowCount - 1; StringGrid1.Col := 0; - Stringgrid1.Cells[2, StringGrid1.RowCount - 1] := 'TXX'; // do not localize - Stringgrid1.Cells[3, StringGrid1.RowCount - 1] := ''; // do not localize - Stringgrid1.Cells[4, StringGrid1.RowCount - 1] := 'TBoldPM'; // do not localize - Stringgrid1.Cells[5, StringGrid1.RowCount - 1] := 'as'; // do not localize - Stringgrid1.Cells[6, StringGrid1.RowCount - 1] := 'T'; // do not localize - Stringgrid1.Cells[10, StringGrid1.RowCount - 1] := 'IBoldContent'; // do not localize + Stringgrid1.Cells[2, StringGrid1.RowCount - 1] := 'TXX'; + Stringgrid1.Cells[3, StringGrid1.RowCount - 1] := ''; + Stringgrid1.Cells[4, StringGrid1.RowCount - 1] := 'TBoldPM'; + Stringgrid1.Cells[5, StringGrid1.RowCount - 1] := 'as'; + Stringgrid1.Cells[6, StringGrid1.RowCount - 1] := 'T'; + Stringgrid1.Cells[10, StringGrid1.RowCount - 1] := 'IBoldContent'; StringGrid1.SetFocus; end; @@ -105,6 +109,7 @@ procedure TBoldTypeNameEditorForm.btnDeleteClick(Sender: TObject); end; end; + procedure TBoldTypeNameEditorForm.btnDownClick(Sender: TObject); begin MoveRow(1); @@ -174,7 +179,7 @@ procedure TBoldTypeNameEditorForm.LoadFromDictionary(Dictionary: TBoldTypeNameDi StringGrid1.Cells[4, i + 1] := Dictionary.Mapping[i].MapperName; StringGrid1.Cells[5, i + 1] := Dictionary.Mapping[i].Accessor; StringGrid1.Cells[6, i + 1] := Dictionary.Mapping[i].NativeType; - StringGrid1.Cells[7, i + 1] := Dictionary.Mapping[i].UnitNameText; + StringGrid1.Cells[7, i + 1] := Dictionary.Mapping[i].UnitName; StringGrid1.Cells[8, i + 1] := Dictionary.Mapping[i].ComType; StringGrid1.Cells[9, i + 1] := Dictionary.Mapping[i].IdlType; StringGrid1.Cells[10, i + 1] := Dictionary.Mapping[i].ValueInterface; @@ -199,7 +204,7 @@ procedure TBoldTypeNameEditorForm.SaveToDictionary(Dictionary: TBoldTypeNameDict MapperName := StringGrid1.Cells[4, i]; Accessor := StringGrid1.Cells[5, i]; NativeType := StringGrid1.Cells[6, i]; - UnitNameText := StringGrid1.Cells[7, i]; + UnitName := StringGrid1.Cells[7, i]; ComType := StringGrid1.Cells[8, i]; IDLType := StringGrid1.Cells[9, i]; ValueInterface := StringGrid1.Cells[10, i]; @@ -242,7 +247,6 @@ procedure TBoldTypeNameEditorForm.MergeDefaultsmappings1Click(Sender: TObject); Mapping := CurrentMappings.ExactMappingForModelName[DefaultMappings.Mapping[i].modelName] else begin - // our abstract types does not have model names. Fortuantely, for j := 0 to CurrentMappings.Count - 1 do if CompareText(DefaultMappings.Mapping[i].ExpressionName, CurrentMappings.Mapping[j].ExpressionName) = 0 then begin @@ -262,4 +266,6 @@ procedure TBoldTypeNameEditorForm.MergeDefaultsmappings1Click(Sender: TObject); end; end; +initialization + end. diff --git a/Source/ObjectSpace/BORepresentation/BoldAttributes.pas b/Source/ObjectSpace/BORepresentation/BoldAttributes.pas index a664147..9942dc0 100644 --- a/Source/ObjectSpace/BORepresentation/BoldAttributes.pas +++ b/Source/ObjectSpace/BORepresentation/BoldAttributes.pas @@ -1,9 +1,13 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldAttributes; interface uses Classes, + SysUtils, BoldSystem, BoldSystemRT, BoldDefs, @@ -11,14 +15,16 @@ interface BoldSubscription, BoldElements, BoldDomainElement, - BoldValueInterfaces; + BoldValueInterfaces, + BoldFreeStandingValues; + {$IFNDEF BOLD_NO_QUERIES} const {Query events} bqBaseAttributes = bqMaxSystem + 1; bqMaySetContentType = bqBaseAttributes + 0; bqMaxAttributes = bqBaseAttributes + 0; - + {$ENDIF} type {Declare New Exceptions Types} @@ -42,54 +48,163 @@ TBAValueSetValue = class; TBAValueSetValueList = class; TBAValueSet = class; + TBAValueSetClass = class of TBAValueSet; + {---TBAString---} + { Base class for all string attributes. Before Unicode (Delphi 2009) this class + constains an AnsiString, after Unicode (Delphi 2009 and up) a UnicodeString. + + The descendants TBAAnsiString and TBAUnicodeString only contains implementation + and an additional data field, if it is a different string kind compared to + this class in the respective Delphi version. + This ensures that TBAString can be used as a base class for all string attributes + which helps in type checks and comparation and on the other hand it can be + instanciated and then uses the default string type of the Delphi version. } TBAString = class(TBoldAttribute) + strict private + FValue: string; private - fValue: string; - procedure SetDataValue(NewValue: string); - procedure SetContent(NewValue: string); + class var AttributeTypeInfo: TBoldElementTypeInfo; + procedure SetDataValue(const NewValue: string); + procedure SetContent(const NewValue: string); protected - procedure AssignContentValue(Source: IBoldValue); override; + function GetAttributeTypeInfoForType: TBoldElementTypeInfo; override; + procedure AssignContentValue(const Source: IBoldValue); override; procedure FreeContent; override; + function GetAsAnsiString: TBoldAnsiString; virtual; + function GetAsUnicodeString: TBoldUnicodeString; virtual; function GetStringRepresentation(Representation: TBoldRepresentation): string; override; - procedure SetStringRepresentation(Representation: TBoldRepresentation; Value: string); override; + procedure SetStringRepresentation(Representation: TBoldRepresentation; const Value: string); override; + function GetValue: string; virtual; function MaySetValue(NewValue: String; Subscriber: TBoldSubscriber): Boolean; virtual; - function ProxyClass: TBoldMember_ProxyClass; override; + function GetProxy(Mode: TBoldDomainElementProxyMode): TBoldMember_Proxy; override; + procedure SetAsAnsiString(const Value: TBoldAnsiString); virtual; + procedure SetAsUnicodeString(const Value: TBoldUnicodeString); virtual; + procedure SetValue(const Value: string); virtual; + function GetFreeStandingClass: TBoldFreeStandingElementClass; override; + property Value: string read GetValue write SetValue; public + constructor CreateWithValue(const Value: string); procedure Assign(Source: TBoldElement); override; - procedure AssignValue(Source: IBoldValue); override; + procedure AssignValue(const Source: IBoldValue); override; function CompareToAs(CompType: TBoldCompareType; BoldElement: TBoldElement): Integer; override; - function ValidateString(Value: string; Representation: TBoldRepresentation): Boolean; override; + function ValidateString(const Value: string; Representation: TBoldRepresentation): Boolean; override; function CanSetValue(NewValue: string; Subscriber: TBoldSubscriber): Boolean; function ProxyInterface(const IId: TGUID; Mode: TBoldDomainElementProxyMode; out Obj): Boolean; override; procedure SetEmptyValue; override; + function IsNullOrEmpty: Boolean; + function IsEqualToValue(const Value: IBoldValue): Boolean; override; + property AsAnsiString: TBoldAnsiString read GetAsAnsiString write + SetAsAnsiString; + property AsUnicodeString: TBoldUnicodeString read GetAsUnicodeString write + SetAsUnicodeString; end; {$IFNDEF T2H} TBAString_Proxy = class(TBoldAttribute_Proxy, IBoldStringContent) private + class var fLastUsed: array[TBoldDomainElementProxyMode] of TBoldMember_Proxy; + class var fLastUsedAsInterface: array[TBoldDomainElementProxyMode] of IBoldValue; + function GetContentAsAnsiString: TBoldAnsiString; + function GetContentAsUnicodeString: TBoldUnicodeString; function GetProxedString: TBAString; procedure SetContentAsString(const NewValue: String); - function GetContentAsString: String; + function GetContentAsString: String; override; + procedure SetContentAsAnsiString(const NewValue: TBoldAnsiString); + procedure SetContentAsUnicodeString(const NewValue: TBoldUnicodeString); protected - property ProxedString: TBAString read GetProxedString ; + property ProxedString: TBAString read GetProxedString; + class function MakeProxy(ProxedMember: TBoldMember; Mode: TBoldDomainElementProxyMode): TBoldMember_Proxy; override; end; {$ENDIF} + {---TBAAnsiString---} + TBAAnsiString = class(TBAString) + private + function ProxyClass: TBoldMember_ProxyClass; + {$IFDEF BOLD_UNICODE} + private + fValue: TBoldAnsiString; + procedure SetContent(NewValue: TBoldAnsiString); + procedure SetDataValue(NewValue: TBoldAnsiString); + {$ENDIF} + protected + {$IFDEF BOLD_UNICODE} + procedure FreeContent; override; + function GetValue: string; override; + procedure SetValue(const Value: string); override; + function GetAsAnsiString: TBoldAnsiString; override; + procedure SetAsAnsiString(const Value: TBoldAnsiString); override; + {$ENDIF} + function GetProxy(Mode: TBoldDomainElementProxyMode): TBoldMember_Proxy; override; + public + function ProxyInterface(const IId: TGUID; Mode: TBoldDomainElementProxyMode; + out Obj): Boolean; override; + {$IFDEF BOLD_UNICODE} + function ValidateCharacter(C: Char; Representation: TBoldRepresentation): + Boolean; override; + function ValidateString(const Value: string; Representation: TBoldRepresentation): + Boolean; override; + {$ENDIF} + end; + + {---TBAUnicodeString---} + TBAUnicodeString = class(TBAString) + private + {$IFNDEF BOLD_UNICODE} + fValue: TBoldUnicodeString; + procedure SetContent(NewValue: TBoldUnicodeString); + procedure SetDataValue(NewValue: TBoldUnicodeString); + {$ENDIF} + function ProxyClass: TBoldMember_ProxyClass; + protected + {$IFNDEF BOLD_UNICODE} + procedure FreeContent; override; + function GetAsUnicodeString: TBoldUnicodeString; override; + function GetValue: string; override; + procedure SetAsUnicodeString(const Value: TBoldUnicodeString); override; + procedure SetValue(const Value: string); override; + {$ENDIF} + function GetProxy(Mode: TBoldDomainElementProxyMode): TBoldMember_Proxy; override; + public + function ProxyInterface(const IId: TGUID; Mode: TBoldDomainElementProxyMode; + out Obj): Boolean; override; + end; + + {---TBAText---} + TBAText = class(TBAAnsiString) + protected + public + function ValidateString(const Value: string; Representation: TBoldRepresentation): + Boolean; override; + end; + + {---TBAUnicodeText---} + TBAUnicodeText = class(TBAUnicodeString) + public + function ValidateString(const Value: string; Representation: TBoldRepresentation): + Boolean; override; + end; {---TBATrimmedString---} TBATrimmedString = class(TBAString) protected - procedure SetStringRepresentation(Representation: TBoldRepresentation; Value: string); override; + procedure SetStringRepresentation(Representation: TBoldRepresentation; const Value: string); override; end; {---TBANumeric---} TBANumeric = class(TBoldAttribute) + private + class var AttributeTypeInfo: TBoldElementTypeInfo; protected function GetAsFloat: Double; virtual; abstract; procedure SetAsInteger(Value: integer); virtual; abstract; + function GetAttributeTypeInfoForType: TBoldElementTypeInfo; override; public procedure SetEmptyValue; override; + function IsVariantTypeCompatible(const Value: Variant): Boolean; override; + function IsNullOrZero: boolean; virtual; + function CompareToAs(CompType: TBoldCompareType; BoldElement: TBoldElement): Integer; override; property AsFloat: Double read GetAsFloat; property AsInteger: Integer write SetAsInteger; end; @@ -101,26 +216,32 @@ TBAInteger = class(TBANumeric) procedure SetDataValue(NewValue: Integer); procedure SetContent(NewValue: Integer); protected - procedure AssignContentValue(Source: IBoldValue); override; + procedure FreeContent; override; + procedure AssignContentValue(const Source: IBoldValue); override; function CheckRangeWithBounds(Value, Min, Max: integer): boolean; function GetAsInteger: integer; virtual; function GetAsFloat: Double; override; function GetStringRepresentation(Representation: TBoldRepresentation): string; override; procedure SetAsInteger(Value: integer); override; - procedure SetStringRepresentation(Representation: TBoldRepresentation; Value: string); override; + procedure SetStringRepresentation(Representation: TBoldRepresentation; const Value: string); override; function MaySetValue(NewValue: integer; Subscriber: TBoldSubscriber): Boolean; virtual; - function ProxyClass: TBoldMember_ProxyClass; override; + function GetProxy(Mode: TBoldDomainElementProxyMode): TBoldMember_Proxy; override; + function GetFreeStandingClass: TBoldFreeStandingElementClass; override; public + constructor CreateWithValue(Value: integer); procedure Assign(Source: TBoldElement); override; - procedure AssignValue(Source: IBoldValue); override; + procedure AssignValue(const Source: IBoldValue); override; function CanSetValue(Value: integer; Subscriber: TBoldSubscriber): Boolean; function CheckRange(Value: integer): Boolean; virtual; function CompareToAs(CompType: TBoldCompareType; BoldElement: TBoldElement): Integer; override; function ProxyInterface(const IId: TGUID; Mode: TBoldDomainElementProxyMode; out Obj): Boolean; override; + procedure SetEmptyValue; override; procedure SetAsVariant(const Value: Variant); override; function GetAsVariant: Variant; override; - function ValidateString(Value: string; Representation: TBoldRepresentation): Boolean; override; + function ValidateString(const Value: string; Representation: TBoldRepresentation): Boolean; override; function ValidateCharacter(C: Char; Representation: TBoldRepresentation): Boolean; override; + function IsVariantTypeCompatible(const Value: Variant): Boolean; override; + function IsEqualToValue(const Value: IBoldValue): Boolean; override; property AsInteger: integer read GetAsInteger write SetAsInteger; end; @@ -171,22 +292,28 @@ TBAFloat = class(TBANumeric) procedure SetContent(NewValue: Double); procedure SetDataValue(NewValue: Double); protected - procedure AssignContentValue(Source: IBoldValue); override; + procedure FreeContent; override; + procedure AssignContentValue(const Source: IBoldValue); override; function GetAsFloat: Double; override; function GetStringRepresentation(Representation: TBoldRepresentation): string; override; procedure SetAsFloat(Value: Double); virtual; procedure SetAsInteger(Value: integer); override; - procedure SetStringRepresentation(Representation: TBoldRepresentation; Value: string); override; + procedure SetStringRepresentation(Representation: TBoldRepresentation; const Value: string); override; function MaySetValue(NewValue: Double; Subscriber: TBoldSubscriber): Boolean; virtual; - function ProxyClass: TBoldMember_ProxyClass; override; + function GetProxy(Mode: TBoldDomainElementProxyMode): TBoldMember_Proxy; override; + function GetFreeStandingClass: TBoldFreeStandingElementClass; override; public + constructor CreateWithValue(Value: double); procedure SetAsVariant(const Value: Variant); override; function GetAsVariant: Variant; override; - function ValidateString(Value: string; Representation: TBoldRepresentation): Boolean; override; + function ValidateString(const Value: string; Representation: TBoldRepresentation): Boolean; override; function ValidateCharacter(C: Char; Representation: TBoldRepresentation): Boolean; override; + function IsVariantTypeCompatible(const Value: Variant): Boolean; override; + procedure SetEmptyValue; override; procedure Assign(Source: TBoldElement); override; - procedure AssignValue(Source: IBoldValue); override; + procedure AssignValue(const Source: IBoldValue); override; function CompareToAs(CompType: TBoldCompareType; BoldElement: TBoldElement): Integer; override; + function IsEqualToValue(const Value: IBoldValue): Boolean; override; property AsInteger: Integer write SetAsInteger; property AsFloat: Double read GetAsFloat write SetAsFloat; function CanSetValue(NewValue: Double; Subscriber: TBoldSubscriber): Boolean; @@ -200,24 +327,30 @@ TBACurrency = class(TBANumeric) procedure SetContent(NewValue: Currency); procedure SetDataValue(NewValue: Currency); protected - procedure AssignContentValue(Source: IBoldValue); override; + procedure FreeContent; override; + procedure AssignContentValue(const Source: IBoldValue); override; function GetAsCurrency: Currency; function GetAsFloat: Double; override; function GetStringRepresentation(Representation: TBoldRepresentation): string; override; procedure SetAsCurrency(Value: Currency); procedure SetAsFloat(Value: Double); virtual; procedure SetAsInteger(Value: integer); override; - procedure SetStringRepresentation(Representation: TBoldRepresentation; Value: string); override; + procedure SetStringRepresentation(Representation: TBoldRepresentation; const Value: string); override; function MaySetValue(NewValue: Currency; Subscriber: TBoldSubscriber): Boolean; virtual; - function ProxyClass: TBoldMember_ProxyClass; override; + function GetProxy(Mode: TBoldDomainElementProxyMode): TBoldMember_Proxy; override; + function GetFreeStandingClass: TBoldFreeStandingElementClass; override; public + constructor CreateWithValue(Value: currency); procedure SetAsVariant(const Value: Variant); override; function GetAsVariant: Variant; override; - function ValidateString(Value: string; Representation: TBoldRepresentation): Boolean; override; + function ValidateString(const Value: string; Representation: TBoldRepresentation): Boolean; override; function ValidateCharacter(C: Char; Representation: TBoldRepresentation): Boolean; override; + function IsVariantTypeCompatible(const Value: Variant): Boolean; override; + procedure SetEmptyValue; override; procedure Assign(Source: TBoldElement); override; - procedure AssignValue(Source: IBoldValue); override; + procedure AssignValue(const Source: IBoldValue); override; function CompareToAs(CompType: TBoldCompareType; BoldElement: TBoldElement): Integer; override; + function IsEqualToValue(const Value: IBoldValue): Boolean; override; property AsCurrency: Currency read GetAsCurrency write SetAsCurrency; property AsFloat: Double read GetAsFloat write SetAsFloat; property AsInteger: Integer write SetAsInteger; @@ -225,63 +358,75 @@ TBACurrency = class(TBANumeric) function ProxyInterface(const IId: TGUID; Mode: TBoldDomainElementProxyMode; out Obj): Boolean; override; end; - {-- TBoldBlobStream --} - - TBoldBlobStreamMode = (bmRead, bmWrite, bmReadWrite); - { TBoldBlobStream } TBoldBlobStream = class(TStream) private + fData: TBytes; fBlobAttr: TBABlob; - fMode: TBoldBlobStreamMode; - fPosition: Integer; - function GetBlobSize: Integer; - procedure StartModifyOfBlob(Operation: String); - procedure EndModifyOfBlob; - procedure FailModifyOfBlob; - procedure InternalSetSize(NewSize: Integer; BlobEvents: Boolean); + fPosition: Int64; + function GetBlobSize: Int64; + procedure InternalSetSize(NewSize: Int64; BlobEvents: Boolean); public - constructor Create(BlobAttr: TBABlob; Mode: TBoldBlobStreamMode); - function Read(var Buffer; Count: integer): integer; override; - function Write(const Buffer; Count: integer): integer; override; - function Seek(Offset: integer; Origin: Word): integer; override; + constructor Create(BlobAttr: TBABlob); + function Read(var Buffer; Count: Longint): Longint; override; + function Write(const Buffer; Count: Longint): Longint; override; + function Seek(Offset: Longint; Origin: Word): Longint; override; procedure Clear; procedure Truncate; procedure LoadFromStream(Stream: TStream); - procedure LoadFromFile(const FileName: string); + procedure LoadFromFile(const aFileName: string; aMode: Word = fmShareDenyNone); procedure SaveToStream(Stream: TStream); procedure SaveToFile(const FileName: string); - procedure SetSize(NewSize: integer); override; + procedure SetSize(NewSize: Longint); override; deprecated; + procedure SetSize(const NewSize: Int64); override; + function IsDataSame(AData: Pointer; ASize: Int64): boolean; end; {---TBABlob---} TBABlob = class(TBoldAttribute) private - FValue: string; - procedure SetContent(NewValue: string); - procedure SetDataValue(NewValue: string); + fStream: TBoldBlobStream; + fSupressEventCount: integer; + procedure SetContent(NewValue: TBoldAnsiString); + procedure SetDataValue(NewValue: TBoldAnsiString); + function GetBlobSize: Int64; + function GetAsStream: TBoldBlobStream; protected - procedure AssignContentValue(Source: IBoldValue); override; + procedure AssignContentValue(const Source: IBoldValue); override; procedure FreeContent; override; + procedure SetAsVariant(const Value: Variant); override; function GetStringRepresentation(Representation: TBoldRepresentation): string; override; - procedure SetStringRepresentation(Representation: TBoldRepresentation; Value: string); override; - function GetAsBlob: String; - procedure SetAsBlob(NewValue: String); - function MaySetValue(NewValue: String; Subscriber: TBoldSubscriber): Boolean; virtual; - function ProxyClass: TBoldMember_ProxyClass; override; + procedure SetStringRepresentation(Representation: TBoldRepresentation; const Value: string); override; + function GetAsBlob: TBoldAnsiString; + procedure SetAsBlob(NewValue: TBoldAnsiString); + function MaySetValue(NewValue: TBoldAnsiString; Subscriber: TBoldSubscriber): Boolean; virtual; + function GetProxy(Mode: TBoldDomainElementProxyMode): TBoldMember_Proxy; override; + function GetFreeStandingClass: TBoldFreeStandingElementClass; override; + function SupressEvents: Boolean; + procedure BeginSupressEvents; + procedure EndSupressEvents; + procedure StartModifyOfBlob(const Operation: String); + procedure EndModifyOfBlob; + procedure FailModifyOfBlob; public - procedure SetAsVariant(const Value: Variant); override; - function GetAsVariant: Variant; override; - function CreateBlobStream(Mode: TBoldBlobStreamMode): TBoldBlobStream; + destructor Destroy; override; + procedure Initialize; override; procedure SetToNull; override; procedure Assign(Source: TBoldElement); override; - procedure AssignValue(Source: IBoldValue); override; + procedure AssignValue(const Source: IBoldValue); override; property ContentType: string index brShort read GetStringRepresentation write SetStringRepresentation; - function CanSetValue(NewValue: string; Subscriber: TBoldSubscriber): Boolean; + function CanSetValue(NewValue: TBoldAnsiString; Subscriber: TBoldSubscriber): Boolean; function CompareToAs(CompareType: TBoldCompareType; BoldElement: TBoldElement): Integer; override; + function IsEqualToValue(const Value: IBoldValue): Boolean; override; function IsEqualAs(CompareType: TBoldCompareType; BoldElement: TBoldElement): Boolean; override; function ProxyInterface(const IId: TGUID; Mode: TBoldDomainElementProxyMode; out Obj): Boolean; override; procedure SetEmptyValue; override; + property BlobSize: Int64 read GetBlobSize; + procedure LoadFromStream(Stream: TStream); + procedure LoadFromFile(const aFileName: string; aMode: Word = fmShareDenyNone); + procedure SaveToStream(Stream: TStream); + procedure SaveToFile(const FileName: string); + property AsStream: TBoldBlobStream read GetAsStream; end; {-- TBATypedBlob --} @@ -292,14 +437,16 @@ TBATypedBlob = class(TBABlob) procedure SetContentTypeContent(NewValue: String); protected function GetStringRepresentation(Representation: TBoldRepresentation): string; override; - procedure SetStringRepresentation(Representation: TBoldRepresentation; Value: string); override; + procedure SetStringRepresentation(Representation: TBoldRepresentation; const Value: string); override; function GetContentTypeContent: String; - function ProxyClass: TBoldMember_ProxyClass; override; + function GetProxy(Mode: TBoldDomainElementProxyMode): TBoldMember_Proxy; override; + function GetFreeStandingClass: TBoldFreeStandingElementClass; override; public - procedure AssignValue(Source: IBoldValue); override; + procedure AssignValue(const Source: IBoldValue); override; procedure SetToNull; override; function CanSetContentType(Value: string; Subscriber: TBoldSubscriber): Boolean; function CompareToAs(CompareType: TBoldCompareType; BoldElement: TBoldElement): Integer; override; + function IsEqualToValue(const Value: IBoldValue): Boolean; override; function IsEqualAs(CompareType: TBoldCompareType; BoldElement: TBoldElement): Boolean; override; function ProxyInterface(const IId: TGUID; Mode: TBoldDomainElementProxyMode; out Obj): Boolean; override; end; @@ -308,22 +455,23 @@ TBATypedBlob = class(TBABlob) TBABlobImageJPEG = class(TBABlob) protected function GetStringRepresentation(Representation: TBoldRepresentation): string; override; - procedure SetStringRepresentation(Representation: TBoldRepresentation; Value: string); override; + procedure SetStringRepresentation(Representation: TBoldRepresentation; const Value: string); override; end; {-- TBABlobImageBMP --} TBABlobImageBMP = class(TBABlob) protected function GetStringRepresentation(Representation: TBoldRepresentation): string; override; - procedure SetStringRepresentation(Representation: TBoldRepresentation; Value: string); override; + procedure SetStringRepresentation(Representation: TBoldRepresentation; const Value: string); override; end; {---TBAMoment---} - TBAMoment = class(TBoldAttribute) + TBAMoment = class(TBANumeric) private FValue: TDateTime; + class var AttributeTypeInfo: TBoldElementTypeInfo; procedure SetDataValue(NewValue: TDateTime); - procedure SetContent(NewValue: TDateTime); + procedure SetDateTimeContent(NewValue: TDateTime); function GetDays: Word; function GetHours: Word; function GetMinutes: Word; @@ -331,6 +479,9 @@ TBAMoment = class(TBoldAttribute) function GetSeconds: Word; function GetYears: Word; protected + procedure FreeContent; override; + function GetAsFloat: Double; override; + procedure SetAsInteger(Value: integer); override; function GetAsDate: TDateTime; function GetAsDateTime: TDateTime; function GetAsTime: TDateTime; @@ -338,7 +489,7 @@ TBAMoment = class(TBoldAttribute) procedure SetAsDateTime(Value: TDateTime); procedure SetAsTime(Value: TDateTime); function MaySetValue(NewValue: TDateTime; Subscriber: TBoldSubscriber): Boolean; virtual; - property AsDateTime: TDateTime read GetAsDateTime write SetAsDateTime; + function GetAttributeTypeInfoForType: TBoldElementTypeInfo; override; property AsDate: TDateTime read GetAsDate write SetAsDate; property AsTime: TDateTime read GetAsTime write SetAsTime; property Seconds: Word read GetSeconds; @@ -353,18 +504,24 @@ TBAMoment = class(TBoldAttribute) procedure Assign(Source: TBoldElement); override; function CanSetValue(NewValue: TDateTime; Subscriber: TBoldSubscriber): Boolean; function CompareToAs(CompType: TBoldCompareType; BoldElement: TBoldElement): Integer; override; + function IsEqualToValue(const Value: IBoldValue): Boolean; override; + function IsVariantTypeCompatible(const Value: Variant): Boolean; override; procedure SetEmptyValue; override; + property AsDateTime: TDateTime read GetAsDateTime write SetAsDateTime; + function IsNullOrZero: boolean; override; end; {---TBADateTime---} TBADateTime = class(TBAMoment) protected - procedure AssignContentValue(Source: IBoldValue); override; + procedure AssignContentValue(const Source: IBoldValue); override; function GetStringRepresentation(Representation: TBoldRepresentation): string; override; - procedure SetStringRepresentation(Representation: TBoldRepresentation; Value: string); override; - function ProxyClass: TBoldMember_ProxyClass; override; + procedure SetStringRepresentation(Representation: TBoldRepresentation; const Value: string); override; + function GetProxy(Mode: TBoldDomainElementProxyMode): TBoldMember_Proxy; override; + function GetFreeStandingClass: TBoldFreeStandingElementClass; override; public - procedure AssignValue(Source: IBoldValue); override; + constructor CreateWithValue(Value: TDateTime); + procedure AssignValue(const Source: IBoldValue); override; property AsDateTime; property AsDate; property AsTime; @@ -374,7 +531,7 @@ TBADateTime = class(TBAMoment) property Days; property Months; property Years; - function ValidateString(Value: string; Representation: TBoldRepresentation): Boolean; override; + function ValidateString(const Value: string; Representation: TBoldRepresentation): Boolean; override; function ValidateCharacter(C: Char; Representation: TBoldRepresentation): Boolean; override; function ProxyInterface(const IId: TGUID; Mode: TBoldDomainElementProxyMode; out Obj): Boolean; override; end; @@ -382,13 +539,15 @@ TBADateTime = class(TBAMoment) {---TBADate---} TBADate = class(TBAMoment) protected - procedure AssignContentValue(Source: IBoldValue); override; - procedure SetStringRepresentation(Representation: TBoldRepresentation; Value: string); override; + procedure AssignContentValue(const Source: IBoldValue); override; + procedure SetStringRepresentation(Representation: TBoldRepresentation; const Value: string); override; function GetStringRepresentation(Representation: TBoldRepresentation): string; override; - function ProxyClass: TBoldMember_ProxyClass; override; + function GetProxy(Mode: TBoldDomainElementProxyMode): TBoldMember_Proxy; override; + function GetFreeStandingClass: TBoldFreeStandingElementClass; override; public - procedure AssignValue(Source: IBoldValue); override; - function ValidateString(Value: string; Representation: TBoldRepresentation): Boolean; override; + constructor CreateWithValue(Value: TDateTime); + procedure AssignValue(const Source: IBoldValue); override; + function ValidateString(const Value: string; Representation: TBoldRepresentation): Boolean; override; function ValidateCharacter(C: Char; Representation: TBoldRepresentation): Boolean; override; function ProxyInterface(const IId: TGUID; Mode: TBoldDomainElementProxyMode; out Obj): Boolean; override; property AsDate; @@ -402,13 +561,15 @@ TBATime = class(TBAMoment) private function GetAsSeconds: cardinal; protected - procedure AssignContentValue(Source: IBoldValue); override; - procedure SetStringRepresentation(Representation: TBoldRepresentation; Value: string); override; + procedure AssignContentValue(const Source: IBoldValue); override; + procedure SetStringRepresentation(Representation: TBoldRepresentation; const Value: string); override; function GetStringRepresentation(Representation: TBoldRepresentation): string; override; - function ProxyClass: TBoldMember_ProxyClass; override; + function GetProxy(Mode: TBoldDomainElementProxyMode): TBoldMember_Proxy; override; + function GetFreeStandingClass: TBoldFreeStandingElementClass; override; public - procedure AssignValue(Source: IBoldValue); override; - function ValidateString(Value: string; Representation: TBoldRepresentation): Boolean; override; + constructor CreateWithValue(Value: TDateTime); + procedure AssignValue(const Source: IBoldValue); override; + function ValidateString(const Value: string; Representation: TBoldRepresentation): Boolean; override; function ValidateCharacter(C: Char; Representation: TBoldRepresentation): Boolean; override; function ProxyInterface(const IId: TGUID; Mode: TBoldDomainElementProxyMode; out Obj): Boolean; override; property AsTime; @@ -425,7 +586,7 @@ TBAValueSetValue = class(TBoldElement) FStringRepresentations: TStringList; protected function GetStringRepresentation(Representation: TBoldRepresentation): string; override; - procedure SetStringRepresentation(Representation: TBoldRepresentation; Value: string); override; + procedure SetStringRepresentation(Representation: TBoldRepresentation; const Value: string); override; function GetAsInteger: Integer; procedure SetAsInteger(Value: Integer); procedure AddString(Value: string); @@ -436,6 +597,7 @@ TBAValueSetValue = class(TBoldElement) destructor Destroy; override; procedure DefaultSubscribe(Subscriber: TBoldSubscriber; RequestedEvent: TBoldEvent = breReEvaluate); override; procedure GetAsList(ResultList: TBoldIndirectElement); override; + function CompareToAs(CompareType: TBoldCompareType; BoldElement: TBoldElement): Integer; override; property AsInteger: Integer read GetAsInteger write SetAsInteger; property StringRepresentationCount: Integer read GetStringRepresentationCount; end; @@ -466,6 +628,7 @@ TBAValueSetValueList = class(TBoldMemoryManagedObject) TBAValueSet = class(TBoldAttribute) private FValue: TBAValueSetValue; + class var AttributeTypeInfo: TBoldElementTypeInfo; procedure CheckIllegalValue; function GetAsInteger: Integer; procedure SetAsInteger(Value: Integer); @@ -473,45 +636,52 @@ TBAValueSet = class(TBoldAttribute) procedure SetContentAsInteger(NewValue: Integer); procedure SetDataValue(NewValue: TBAValueSetValue); protected + procedure FreeContent; override; function GetContentAsInteger: Integer; virtual; - procedure AssignContentValue(Source: IBoldValue); override; - procedure InitializeMember(OwningElement: TBoldDomainElement; ElementTypeInfo: TBoldElementTypeInfo); override; - function GetValues: TBAValueSetValueList; virtual; abstract; + procedure AssignContentValue(const Source: IBoldValue); override; + procedure Initialize; override; function GetStringRepresentation(Representation: TBoldRepresentation): string; override; - procedure SetStringRepresentation(Representation: TBoldRepresentation; Value: string); override; + procedure SetStringRepresentation(Representation: TBoldRepresentation; const Value: string); override; function MaySetValue(NewValue: TBAValueSetValue; Subscriber: TBoldSubscriber): Boolean; virtual; property ContentAsInteger: Integer read GetContentAsInteger write SetContentAsInteger; - function ProxyClass: TBoldMember_ProxyClass; override; + function GetProxy(Mode: TBoldDomainElementProxyMode): TBoldMember_Proxy; override; + function GetAttributeTypeInfoForType: TBoldElementTypeInfo; override; + function GetFreeStandingClass: TBoldFreeStandingElementClass; override; public + class function GetValues: TBAValueSetValueList; virtual; procedure SetAsVariant(const Value: Variant); override; function GetAsVariant: Variant; override; - function ValidateString(Value: string; Representation: TBoldRepresentation): Boolean; override; + function ValidateString(const Value: string; Representation: TBoldRepresentation): Boolean; override; function ValidateCharacter(C: Char; Representation: TBoldRepresentation): Boolean; override; procedure Assign(Source: TBoldElement); override; function CompareToEnumLiteral(const str: String): Boolean; virtual; - procedure AssignValue(Source: IBoldValue); override; + procedure AssignValue(const Source: IBoldValue); override; function CompareToAs(CompType: TBoldCompareType; BoldElement: TBoldElement): Integer; override; - property Values: TBAValueSetValueList read GetValues; property AsInteger: Integer read GetAsInteger write SetAsInteger; + property Values: TBAValueSetValueList read GetValues; function CanSetValue(NewValue: TBAValueSetValue; Subscriber: TBoldSubscriber): Boolean; function ProxyInterface(const IId: TGUID; Mode: TBoldDomainElementProxyMode; out Obj): Boolean; override; procedure SetEmptyValue; override; end; - - {---TBABoolean---} TBABoolean = class(TBAValueSet) + private + class var _BooleanValues: TBAValueSetValueList; protected - procedure AssignContentValue(Source: IBoldValue); override; + procedure AssignContentValue(const Source: IBoldValue); override; function GetAsBoolean: Boolean; procedure SetAsBoolean(Value: Boolean); - function GetValues: TBAValueSetValueList; override; - function ProxyClass: TBoldMember_ProxyClass; override; + function GetProxy(Mode: TBoldDomainElementProxyMode): TBoldMember_Proxy; override; + function GetFreeStandingClass: TBoldFreeStandingElementClass; override; public + constructor CreateWithValue(Value: Boolean); + class function GetValues: TBAValueSetValueList; override; procedure SetAsVariant(const Value: Variant); override; function GetAsVariant: Variant; override; function ProxyInterface(const IId: TGUID; Mode: TBoldDomainElementProxyMode; out Obj): Boolean; override; + function IsVariantTypeCompatible(const Value: Variant): Boolean; override; + function IsEqualToValue(const Value: IBoldValue): Boolean; override; property AsBoolean: Boolean read GetAsBoolean write SetAsBoolean; end; @@ -525,21 +695,24 @@ TBAConstraint = class(TBABoolean) protected function GetContentAsInteger: Integer; override; function GetStringRepresentation(Representation: TBoldRepresentation): string; override; - procedure InitializeMember(OwningElement: TBoldDomainElement; ElementTypeInfo: TBoldElementTypeInfo); override; + procedure Initialize; override; public destructor Destroy; override; procedure Assign(Source: TBoldElement); override; procedure DefaultSubscribe(Subscriber: TBoldSubscriber; RequestedEvent: TBoldEvent = breReEvaluate); override; procedure SubscribeToStringRepresentation(Representation: TBoldRepresentation; Subscriber: TBoldSubscriber; RequestedEvent: TBoldEvent = breReEvaluate); override; - procedure Initialize(Constraint: TBoldConstraintRTInfo; OwningElement: TBoldElement); + procedure InitializeConstraint(Constraint: TBoldConstraintRTInfo; OwningElement: TBoldElement); property Constraint: TBoldConstraintRTInfo read fConstraint; property OwningElement: TBoldElement read fOwningElement; end; +function VarRecToBoldAttribute(const Value: TVarRec): TBoldAttribute; +function VarArrayToBoldMemberList(const Values: array of const): TBoldMemberList; + implementation uses - SysUtils, + {$IFDEF BOLD_UNICODE}AnsiStrings,{$ENDIF} BoldNameExpander, BoldTaggedValueSupport, Variants, @@ -547,17 +720,43 @@ implementation BoldCoreConsts, BoldMemberTypeDictionary; +type + TBAAnsiString_Proxy = class(TBAString_Proxy, IBoldAnsiStringContent) + end; + + + TBoldSystemSubscriber = class(TBoldPassthroughSubscriber) + protected + procedure Receive(Originator: TObject; OriginalEvent: TBoldEvent; + RequestedEvent: TBoldRequestedEvent); override; + end; + var - _BooleanValues: TBAValueSetValueList; + _SystemSubscriber: TBoldSystemSubscriber; -const - DEFAULTNOW = ''; - Meth_GetStringRepresentation = 'GetStringRepresentation'; - Meth_SetStringRepresentation = 'SetStringRepresentation'; - Meth_AssignContentValue = 'AssignContentValue'; - Meth_AssignValue = 'AssignValue'; +procedure SubscribeToSystem; +begin + if not Assigned(_SystemSubscriber) then + _SystemSubscriber := TBoldSystemSubscriber.Create(nil); + TBoldSystem.DefaultSystem.AddSmallSubscription(_SystemSubscriber, [beDestroying], beDestroying); +end; + +{ TBoldSystemSubscriber } + +procedure TBoldSystemSubscriber.Receive(Originator: TObject; + OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent); +begin + TBAString.AttributeTypeInfo := nil; + TBANumeric.AttributeTypeInfo := nil; + TBAMoment.AttributeTypeInfo := nil; + TBAValueSet.AttributeTypeInfo := nil; + FreeAndNil(_SystemSubscriber); +end; type + TBAUnicodeString_Proxy = class(TBAString_Proxy, IBoldUnicodeStringContent) + end; + TBAInteger_Proxy = class(TBoldAttribute_Proxy, IBoldIntegerContent) private function GetProxedInteger: TBAInteger; @@ -571,17 +770,20 @@ TBAFloat_Proxy = class(TBoldAttribute_Proxy, IBoldFloatContent) private function GetProxedFloat: TBAFloat; function GetContentAsFloat: Double; - procedure SetContentAsFloat(NewValue: Double); + procedure SetContentAsFloat(NewValue: Double); protected property ProxedFloat: TBAFloat read GetProxedFloat; end; - TBABlob_Proxy = class(TBoldAttribute_Proxy, IBoldBlobContent) + TBABlob_Proxy = class(TBoldAttribute_Proxy, IBoldBlobContent, IBoldBlobStreamContent) private function GetProxedBlob: TBABlob; - function GetContentAsBlob: String; - procedure SetContentAsBlob(const NewValue: String); - protected + function GetContentAsBlob: TBoldAnsiString; + procedure SetContentAsBlob(const NewValue: TBoldAnsiString); + function GetBlobAsStream: TStream; + procedure BeginSupressEvents; + procedure EndSupressEvents; + function SupressEvents: boolean; property ProxedBlob: TBABlob read GetProxedBlob; end; @@ -631,7 +833,7 @@ TBAValueSet_Proxy = class(TBoldAttribute_Proxy, IBoldIntegerContent, IBoldStri function GetContentAsInteger: Integer; procedure SetContentAsInteger(NewValue: Integer); procedure SetContentAsString(const NewValue: String); - function GetContentAsString: String; + function GetContentAsString: String; override; protected property ProxedValueSet: TBAValueSet read GetProxedValueSet; end; @@ -642,17 +844,46 @@ TBABoolean_Proxy = class(TBAValueSet_Proxy, IBoldBooleanContent) procedure SetContentAsBoolean(NewValue: Boolean); end; +function VarRecToBoldAttribute(Const Value: TVarRec): TBoldAttribute; +begin + case Value.VType of + vtInteger: Result := TBAInteger.CreateWithValue(value.VInteger); + vtInt64: Result := TBAInteger.CreateWithValue(value.VInt64^); + vtBoolean: Result := TBABoolean.CreateWithValue(value.VBoolean); + vtExtended: Result := TBAFloat.CreateWithValue(value.VExtended^); + vtString: Result := TBAString.CreateWithValue(value.VString^); + vtAnsiString: Result := TBAString.CreateWithValue(String(value.VAnsiString)); +{$IFDEF BOLD_UNICODE} + vtUnicodeString: Result := TBAString.CreateWithValue(String(value.vUnicodeString)); +{$ENDIF} + vtCurrency: Result := TBACurrency.CreateWithValue(value.VCurrency^); + vtWideString: Result := TBAString.CreateWithValue(PWideString(value.VWideString)^); + else + raise EBold.Create('Unsupported Variant type: ' + IntToStr(Value.Vtype)); + end; +end; + +function VarArrayToBoldMemberList(const Values: array of const): TBoldMemberList; +var + i: integer; +begin + result := TBoldMemberList.Create; + result.CloneMembers := false; + for I := 0 to length(Values) - 1 do + result.Add(VarRecToBoldAttribute(Values[i])); +end; + { TBAString } -procedure TBAString.SetDataValue(NewValue: string); +procedure TBAString.SetDataValue(const NewValue: string); begin BoldClearLastFailure; if not CanSetValue(NewValue, nil) then - BoldRaiseLastFailure(self, 'SetDataValue', ''); // do not localize + BoldRaiseLastFailure(self, 'SetDataValue', ''); if IsNull or (FValue <> NewValue) then begin if not StartModify then - BoldRaiseLastFailure(self, 'SetDataValue', ''); // do not localize + BoldRaiseLastFailure(self, 'SetDataValue', ''); try SetContent(NewValue); EndModify; @@ -663,12 +894,11 @@ procedure TBAString.SetDataValue(NewValue: string); end; end; -procedure TBAString.SetStringRepresentation(Representation: TBoldRepresentation; Value: string); +procedure TBAString.SetStringRepresentation(Representation: TBoldRepresentation; const Value: string); begin if not ValidateString(Value, Representation) then - BoldRaiseLastFailure(self, Meth_SetStringRepresentation, sStringValidationFailed); + BoldRaiseLastFailure(self, 'SetStringRepresentation', 'String validation failed'); - EnsureValidString(Value, Representation); if Representation = brDefault then SetDataValue(Value) else @@ -679,7 +909,7 @@ function TBAString.GetStringRepresentation(Representation: TBoldRepresentation): begin BoldClearLastFailure; if not CanRead(nil) then - BoldRaiseLastFailure(self, Meth_GetStringRepresentation, ''); + BoldRaiseLastFailure(self, 'GetStringRepresentation', ''); if Representation <> brDefault then inherited GetStringRepresentation(Representation); @@ -689,14 +919,14 @@ function TBAString.GetStringRepresentation(Representation: TBoldRepresentation): Result := FValue; end; -function TBAString.ValidateString(Value: string; Representation: TBoldRepresentation): Boolean; +function TBAString.ValidateString(const Value: string; Representation: TBoldRepresentation): Boolean; begin if Assigned(BoldAttributeRtInfo) then begin Result := (BoldAttributeRtInfo.Length = -1) or (Length(Value) <= BoldAttributeRtInfo.Length); if not result then - SetBoldLastFailureReason(TBoldFailureReason.Create(sStringTooLong, self)); + SetBoldLastFailureReason(TBoldFailureReason.CreateFmt('String too long. Max allowed: %d, actual: %d.', [BoldAttributeRtInfo.Length, Length(Value)] , self)); end else Result := True; @@ -722,29 +952,27 @@ function TBAString.CompareToAs(CompType: TBoldCompareType; BoldElement: TBoldEle if EitherIsNull(Self, TBAString(BoldElement)) then Result := NullSmallest(BoldElement) else - case CompType of - ctDefault: - Result := AnsiCompareText(AsString, TBAString(BoldElement).AsString); - ctAsString: - Result := CompareStr(AsString, TBAString(BoldElement).AsString); - ctAsText: - Result := CompareText(AsString, TBAString(BoldElement).AsString); - ctAsAnsiString: - Result := AnsiCompareStr(AsString, TBAString(BoldElement).AsString); - ctAsAnsiText: - Result := AnsiCompareText(AsString, TBAString(BoldElement).AsString); - else - Result := inherited CompareToAs(CompType, BoldElement); - end + Result := StringCompare(CompType, AsString, BoldElement.AsString); end else - Result := inherited CompareToAs(CompType, BoldElement); + if Assigned(BoldElement) then + Result := StringCompare(CompType, AsString, BoldElement.AsString) + else + result := -1; +end; + +constructor TBAString.CreateWithValue(const Value: string); +begin + inherited Create; + asString := value; end; function TBAString.CanSetValue(NewValue: string; Subscriber: TBoldSubscriber): Boolean; begin - result := MaySetValue(NewValue, Subscriber) and - SendQuery(bqMaySetValue, [NewValue], Subscriber) + result := MaySetValue(NewValue, Subscriber); +{$IFNDEF BOLD_NO_QUERIES} + result := result and SendQuery(bqMaySetValue, [NewValue], Subscriber) +{$ENDIF} end; function TBAString.MaySetValue(NewValue: String; @@ -754,31 +982,50 @@ function TBAString.MaySetValue(NewValue: String; end; -procedure TBAString.AssignValue(Source: IBoldValue); +procedure TBAString.AssignValue(const Source: IBoldValue); var s: IBoldStringContent; begin if source.QueryInterface(IBoldStringContent, S) = S_OK then SetDataValue(s.AsString) else - raise EBold.CreateFmt(sUnknownTypeOfSource, [classname, Meth_AssignValue]); + raise EBold.CreateFmt('%s.AssignValue: unknown type of source', [classname]); end; -procedure TBAString.SetContent(NewValue: string); +procedure TBAString.SetContent(const NewValue: string); +var + bContentIsNull: Boolean; + sOldValue: string; begin + bContentIsNull := ContentIsNull; if (BoldPersistenceState = bvpsInvalid) or - ContentIsNull or (FValue <> NewValue) then + bContentIsNull or (fValue <> NewValue) then begin PreChange; - FValue := NewValue; + sOldValue := fValue; + fValue := NewValue; SetToNonNull; - Changed(beValueChanged, [NewValue]); + if bContentIsNull then begin + Changed(beValueChanged, [NewValue]); + end else begin + Changed(beValueChanged, [NewValue, sOldValue]); + end; end; end; function TBAString_Proxy.GetContentAsString: string; begin - result := ProxedString.FValue; + result := ProxedString.Value; +end; + +function TBAString_Proxy.GetContentAsAnsiString: TBoldAnsiString; +begin + result := ProxedString.AsAnsiString; +end; + +function TBAString_Proxy.GetContentAsUnicodeString: TBoldUnicodeString; +begin + result := ProxedString.AsUnicodeString; end; procedure TBAString_Proxy.SetContentAsString(const NewValue: string); @@ -786,9 +1033,30 @@ procedure TBAString_Proxy.SetContentAsString(const NewValue: string); ProxedString.SetContent(NewValue); end; -procedure TBAString.AssignContentValue(Source: IBoldValue); +procedure TBAString_Proxy.SetContentAsAnsiString(const NewValue: + TBoldAnsiString); +begin + if ProxedString is TBAAnsiString then begin + TBAAnsiString(ProxedString).SetContent(NewValue); + end else begin + ProxedString.SetContent(string(NewValue)); + end; +end; + +procedure TBAString_Proxy.SetContentAsUnicodeString(const NewValue: + TBoldUnicodeString); +begin + if ProxedString is TBAUnicodeString then begin + TBAUnicodeString(ProxedString).SetContent(NewValue); + end else begin + ProxedString.SetContent(string(NewValue)); + end; +end; + +procedure TBAString.AssignContentValue(const Source: IBoldValue); var s: IBoldStringContent; + sr: IBoldStringRepresentable; begin if not assigned(source) and CanSetToNull(nil) then SetContentToNull @@ -801,46 +1069,410 @@ procedure TBAString.AssignContentValue(Source: IBoldValue); else SetContent(s.AsString) end + else if source.QueryInterface(IBoldStringRepresentable, sr) = S_OK then + begin + if sr.IsNull then + SetContentToNull + else + SetContent(sr.AsString) + end else - raise EBold.CreateFmt(sUnknownTypeOfSource, [classname, Meth_AssignContentValue]); + raise EBold.CreateFmt('%s.AssignContentValue: unknown type of source', [classname]); end; -function TBAString.ProxyClass: TBoldMember_ProxyClass; +function TBAString.GetProxy(Mode: TBoldDomainElementProxyMode): TBoldMember_Proxy; begin - result := TBAString_Proxy; + result := TBAString_Proxy.MakeProxy(self, mode); end; function TBAString.ProxyInterface(const IId: TGUID; Mode: TBoldDomainElementProxyMode; out Obj): Boolean; begin - if IsEqualGuid(IID, IBoldStringContent) then + if IsEqualGuid(IID, IBoldStringContent) then begin Result := RetrieveProxyInterface(IID, Mode, obj, 'IBoldStringContent') // do not localize + end else if IsEqualGUID(IID, IBoldAnsiStringContent) then begin + Result := RetrieveProxyInterface(IID, Mode, obj, 'IBoldAnsiStringContent') // do not localize + end else if IsEqualGUID(IID, IBoldUnicodeStringContent) then begin + Result := RetrieveProxyInterface(IID, Mode, obj, 'IBoldUnicodeStringContent') // do not localize + end else begin + Result := inherited ProxyInterface(IID, Mode, Obj); + end; +end; + +procedure TBAString.FreeContent; +begin + inherited; + FValue := ''; +end; + +function TBAString.GetAsAnsiString: TBoldAnsiString; +begin + Result := TBoldAnsiString(AsString); +end; + +function TBAString.GetAsUnicodeString: TBoldUnicodeString; +begin + Result := TBoldUnicodeString(AsString); +end; + +function TBAString.GetValue: string; +begin + Result := FValue; +end; + +function TBAString.IsEqualToValue(const Value: IBoldValue): Boolean; +var + vString: IBoldStringContent; +begin + Assert(Assigned(Value), ClassName + '.IsEqualToValue: Value can not be nil.'); + if Value.QueryInterface(IBoldStringContent, vString) = S_OK then + begin + if IsNull and vString.IsNull then + result := true + else + if IsNull or vString.IsNull then + result := false + else + result := StringCompare(ctCaseSensitive, Self.AsString, vString.asString) = 0 + end else - result := inherited ProxyInterface(IID, Mode, Obj); + result := inherited IsEqualToValue(Value); +end; + +function TBAString.IsNullOrEmpty: Boolean; +begin + Result := IsNull or (Value = ''); +end; + +procedure TBAString.SetAsAnsiString(const Value: TBoldAnsiString); +begin + AsString := string(Value); +end; + +procedure TBAString.SetAsUnicodeString(const Value: TBoldUnicodeString); +begin + AsString := string(Value); +end; + +procedure TBAString.SetEmptyValue; +begin + if FValue <> '' then + asString := ''; +end; + +procedure TBAString.SetValue(const Value: string); +begin + FValue := Value; +end; + +function TBAString.GetAttributeTypeInfoForType: TBoldElementTypeInfo; +begin + if not Assigned(AttributeTypeInfo) then + begin + AttributeTypeInfo := inherited GetAttributeTypeInfoForType; + SubscribeToSystem; + end; + result := AttributeTypeInfo; +end; + +function TBAString.GetFreeStandingClass: TBoldFreeStandingElementClass; +begin + result := TBFSString; +end; + +{ TBAAnsiString } + +{$IFDEF BOLD_UNICODE} +procedure TBAAnsiString.FreeContent; +begin + inherited; + fValue := ''; +end; + +function TBAAnsiString.GetAsAnsiString: TBoldAnsiString; +begin + BoldClearLastFailure; + if not CanRead(nil) then + BoldRaiseLastFailure(self, 'GetAsAnsiString', ''); // do not localize + + if IsNull then {IsNull ensures current} + Result := '' + else + Result := fValue; +end; + +function TBAAnsiString.GetValue: string; +begin + Result := String(fValue); +end; + +procedure TBAAnsiString.SetAsAnsiString(const Value: TBoldAnsiString); +begin + SetDataValue(Value); +end; + +procedure TBAAnsiString.SetContent(NewValue: TBoldAnsiString); +var + bContentIsNull: Boolean; + sOldValue: TBoldAnsiString; +begin + bContentIsNull := ContentIsNull; + if (BoldPersistenceState = bvpsInvalid) or + bContentIsNull or (fValue <> NewValue) then + begin + PreChange; + sOldValue := fValue; + fValue := NewValue; + SetToNonNull; + if bContentIsNull then begin + Changed(beValueChanged, [NewValue]); + end else begin + Changed(beValueChanged, [NewValue, sOldValue]); + end; + end; +end; + +procedure TBAAnsiString.SetDataValue(NewValue: TBoldAnsiString); +begin + BoldClearLastFailure; + if not CanSetValue(string(NewValue), nil) then + BoldRaiseLastFailure(self, 'SetDataValue', ''); // do not localize + + if IsNull or (fValue <> NewValue) then + begin + if not StartModify then + BoldRaiseLastFailure(self, 'SetDataValue', ''); // do not localize + try + SetContent(NewValue); + EndModify; + except + FailModify; + raise; + end; + end; +end; + +procedure TBAAnsiString.SetValue(const Value: string); +begin + fValue := TBoldAnsiString(Value); +end; + +function TBAAnsiString.ValidateCharacter(C: Char; Representation: + TBoldRepresentation): Boolean; +begin + Result := inherited ValidateCharacter(C, Representation); + Result := Result and (Ord(C) < 256); +end; + +function TBAAnsiString.ValidateString(const Value: string; Representation: + TBoldRepresentation): Boolean; +begin + Result := inherited ValidateString(Value, Representation); + if Result and (String(AnsiString(Value)) <> Value) then begin + Result := False; + SetBoldLastFailureReason(TBoldFailureReason.Create(sStringIsNotAnsiString, Self)); + end; +end; +{$ENDIF} + +function TBAAnsiString.GetProxy( + Mode: TBoldDomainElementProxyMode): TBoldMember_Proxy; +begin + result := TBAAnsiString_Proxy.MakeProxy(self, mode); +end; + +function TBAAnsiString.ProxyClass: TBoldMember_ProxyClass; +begin + result := TBAAnsiString_Proxy; +end; + +function TBAAnsiString.ProxyInterface(const IId: TGUID; Mode: + TBoldDomainElementProxyMode; out Obj): Boolean; +begin + if IsEqualGUID(IID, IBoldAnsiStringContent) then + Result := RetrieveProxyInterface(IID, Mode, obj, 'IBoldAnsiStringContent') // do not localize + else + Result := inherited ProxyInterface(IID, Mode, Obj); +end; + +{ TBAUnicodeString } + +function TBAUnicodeString.GetProxy( + Mode: TBoldDomainElementProxyMode): TBoldMember_Proxy; +begin + result := TBAUnicodeString_Proxy.MakeProxy(self, mode); +end; + +{$IFNDEF BOLD_UNICODE} +procedure TBAUnicodeString.FreeContent; +begin + inherited; + FValue := ''; +end; + +function TBAUnicodeString.GetAsUnicodeString: TBoldUnicodeString; +begin + BoldClearLastFailure; + if not CanRead(nil) then + BoldRaiseLastFailure(self, 'GetAsUnicodeString', ''); // do not localize + + if IsNull then {IsNull ensures current} + Result := '' + else + Result := fValue; +end; + +function TBAUnicodeString.GetValue: string; +begin + Result := String(FValue); +end; + +procedure TBAUnicodeString.SetAsUnicodeString(const Value: TBoldUnicodeString); +begin + SetDataValue(Value); +end; + +procedure TBAUnicodeString.SetContent(NewValue: TBoldUnicodeString); +var + bContentIsNull: Boolean; + sOldValue: TBoldUnicodeString; +begin + bContentIsNull := ContentIsNull; + if (BoldPersistenceState = bvpsInvalid) or + bContentIsNull or (fValue <> NewValue) then + begin + PreChange; + sOldValue := fValue; + fValue := NewValue; + SetToNonNull; + if bContentIsNull then begin + Changed(beValueChanged, [NewValue]); + end else begin + Changed(beValueChanged, [NewValue, sOldValue]); + end; + end; +end; + +procedure TBAUnicodeString.SetDataValue(NewValue: TBoldUnicodeString); +begin + BoldClearLastFailure; + if not CanSetValue(string(NewValue), nil) then + BoldRaiseLastFailure(self, 'SetDataValue', ''); // do not localize + + if IsNull or (fValue <> NewValue) then + begin + if not StartModify then + BoldRaiseLastFailure(self, 'SetDataValue', ''); // do not localize + try + SetContent(NewValue); + EndModify; + except + FailModify; + raise; + end; + end; +end; + +procedure TBAUnicodeString.SetValue(const Value: string); +begin + FValue := TBoldUnicodeString(Value); +end; +{$ENDIF} + +function TBAUnicodeString.ProxyClass: TBoldMember_ProxyClass; +begin + result := TBAUnicodeString_Proxy; +end; + +function TBAUnicodeString.ProxyInterface(const IId: TGUID; Mode: + TBoldDomainElementProxyMode; out Obj): Boolean; +begin + if IsEqualGUID(IID, IBoldUnicodeStringContent) then + Result := RetrieveProxyInterface(IID, Mode, obj, 'IBoldUnicodeStringContent') // do not localize + else + Result := inherited ProxyInterface(IID, Mode, Obj); +end; + +{ TBAText } + +function TBAText.ValidateString(const Value: string; Representation: + TBoldRepresentation): Boolean; +begin + // no inherited (inherited checks length) + Result := True; + // but we need AnsiString-Check + {$IFDEF BOLD_UNICODE} + if (String(AnsiString(Value)) <> Value) then begin + Result := False; + SetBoldLastFailureReason(TBoldFailureReason.Create(sStringIsNotAnsiString, Self)); + end; + {$ENDIF} +end; + +{ TBAUnicodeText } + +function TBAUnicodeText.ValidateString(const Value: string; Representation: + TBoldRepresentation): Boolean; +begin + // no inherited (inherited checks length) + Result := True; +end; + +{ TBATrimmedString } + +procedure TBATrimmedString.SetStringRepresentation(Representation: TBoldRepresentation; const Value: string); +begin + inherited SetStringRepresentation(Representation, trim(Value)); +end; + +{ TBANumeric } + +function TBANumeric.CompareToAs(CompType: TBoldCompareType; + BoldElement: TBoldElement): Integer; +begin + if BoldElement is TBANumeric then + begin + if EitherIsNull(Self, TBoldAttribute(BoldElement)) then + Result := NullSmallest(BoldElement) + else + case CompType of + ctDefault: + if AsFloat = TBANumeric(BoldElement).AsFloat then + Result := 0 + else if AsFloat > TBANumeric(BoldElement).AsFloat then + Result := 1 + else + Result := -1; + else + Result := inherited CompareToAs(CompType, BoldElement); + end; + end else + Result := inherited CompareToAs(CompType, BoldElement); end; -procedure TBAString.FreeContent; +function TBANumeric.GetAttributeTypeInfoForType: TBoldElementTypeInfo; begin - inherited; - FValue := ''; + if not Assigned(AttributeTypeInfo) then + begin + AttributeTypeInfo := inherited GetAttributeTypeInfoForType; + SubscribeToSystem; + end; + result := AttributeTypeInfo; end; -procedure TBAString.SetEmptyValue; +function TBANumeric.IsNullOrZero: boolean; begin - asString := ''; + result := isNull or (AsFloat = 0); end; -{ TBATrimmedString } - -procedure TBATrimmedString.SetStringRepresentation(Representation: TBoldRepresentation; Value: string); +function TBANumeric.IsVariantTypeCompatible(const Value: Variant): Boolean; begin - inherited SetStringRepresentation(Representation, trim(Value)); + result := VarType(Value) in [varSmallInt, varInteger, varShortInt, varByte, varWord, varLongWord, varInt64]; end; -{ TBANumeric } - procedure TBANumeric.SetEmptyValue; begin - AsInteger := 0; + if AsFloat <> 0 then + AsInteger := 0; end; { TBAInteger } @@ -849,14 +1481,14 @@ procedure TBAInteger.SetDataValue(NewValue: Integer); begin BoldClearLastFailure; if not CanSetValue(NewValue, nil) then - BoldRaiseLastFailure(self, 'SetDataValue', ''); // do not localize + BoldRaiseLastFailure(self, 'SetDataValue', ''); if not CheckRange(NewValue) then - raise EBoldInternal.CreateFmt('%s: %s', [DisplayName, GetBoldLastFailureReason.Reason]); // do not localize + raise EBoldInternal.CreateFmt('%s: %s', [DisplayName, GetBoldLastFailureReason.Reason]); if IsNull or (FValue <> NewValue) then begin if not StartModify then - BoldRaiseLastFailure(self, 'SetDataValue', ''); // do not localize + BoldRaiseLastFailure(self, 'SetDataValue', ''); try SetContent(NewValue); EndModify; @@ -867,15 +1499,21 @@ procedure TBAInteger.SetDataValue(NewValue: Integer); end; end; +procedure TBAInteger.SetEmptyValue; +begin + if fValue <> 0 then + inherited; +end; + function TBAInteger.CheckRange(Value: integer): Boolean; begin result := CheckRangeWithBounds(Value, Low(integer), High(integer)); end; -procedure TBAInteger.SetStringRepresentation(Representation: TBoldRepresentation; Value: string); +procedure TBAInteger.SetStringRepresentation(Representation: TBoldRepresentation; const Value: string); begin if not ValidateString(Value, Representation) then - BoldRaiseLastFailure(self, Meth_SetStringRepresentation, sStringValidationFailed); + BoldRaiseLastFailure(self, 'SetStringRepresentation', 'String validation failed'); if Representation = brDefault then if Value = '' then SetToNull @@ -889,20 +1527,44 @@ function TBAInteger.GetStringRepresentation(Representation: TBoldRepresentation) begin BoldClearLastFailure; if not CanRead(nil) then - BoldRaiseLastFailure(self, Meth_GetStringRepresentation, ''); + BoldRaiseLastFailure(self, 'GetStringRepresentation', ''); if Representation <> brDefault then inherited GetStringRepresentation(Representation); if IsNull then {IsNull ensures current} Result := '' else - Str(GetAsInteger, Result); + Result := IntToStr(GetAsInteger); +end; + +function TBAInteger.IsEqualToValue(const Value: IBoldValue): Boolean; +var + vInteger: IBoldIntegerContent; +begin + Assert(Assigned(Value), ClassName + '.IsEqualToValue: Value can not be nil.'); + if Value.QueryInterface(IBoldIntegerContent, vInteger) = S_OK then + begin + if IsNull and vInteger.IsNull then + result := true + else + if IsNull or vInteger.IsNull then + result := false + else + result := Self.asInteger = vInteger.asInteger + end + else + result := inherited IsEqualToValue(Value); +end; + +function TBAInteger.IsVariantTypeCompatible(const Value: Variant): Boolean; +begin + result := inherited IsVariantTypeCompatible(Value) and CheckRange(Value); end; function TBAInteger.GetAsInteger: integer; begin BoldClearLastFailure; if not canRead(nil) then - BoldRaiseLastFailure(self, 'GetAsInteger', ''); // do not localize + BoldRaiseLastFailure(self, 'GetAsInteger', ''); EnsureNotNull; {ensures current} Result := FValue; end; @@ -911,7 +1573,7 @@ function TBAInteger.GetAsFloat: Double; begin BoldClearLastFailure; if not CanRead(nil) then - BoldRaiseLastFailure(self, 'GetAsFloat', ''); // do not localize + BoldRaiseLastFailure(self, 'GetAsFloat', ''); EnsureNotNull; {ensures current} Result := FValue; end; @@ -923,10 +1585,10 @@ procedure TBAInteger.SetAsInteger(Value: integer); function TBAInteger.ValidateCharacter(C: Char; Representation: TBoldRepresentation): Boolean; begin - Result := C in ['0'..'9', '-', '+']; + Result := CharInSet(C, ['0'..'9', '-', '+']); end; -function TBAInteger.ValidateString(Value: string; Representation: TBoldRepresentation): Boolean; +function TBAInteger.ValidateString(const Value: string; Representation: TBoldRepresentation): Boolean; begin if value = '' then result := CanSetToNull(nil) @@ -965,30 +1627,29 @@ function TBAInteger.CompareToAs(CompType: TBoldCompareType; BoldElement: TBoldEl else Result := inherited CompareToAs(CompType, BoldElement); end; - end else if BoldElement is TBANumeric then - begin - if EitherIsNull(Self, TBoldAttribute(BoldElement)) then - Result := NullSmallest(BoldElement) - else - case CompType of - ctDefault: - if AsInteger = TBANumeric(BoldElement).AsFloat then - Result := 0 - else if AsInteger > TBANumeric(BoldElement).AsFloat then - Result := 1 - else - Result := -1; - else - Result := inherited CompareToAs(CompType, BoldElement); - end; - end else + end + else Result := inherited CompareToAs(CompType, BoldElement); end; +constructor TBAInteger.CreateWithValue(Value: integer); +begin + inherited Create; + asInteger := value; +end; + +procedure TBAInteger.FreeContent; +begin + inherited; + fValue := 0; +end; + function TBAInteger.CanSetValue(Value: Integer; Subscriber: TBoldSubscriber): Boolean; begin - result := MaySetValue(Value, Subscriber) and - SendQuery(bqMaySetValue, [Value], Subscriber); + result := MaySetValue(Value, Subscriber); +{$IFNDEF BOLD_NO_QUERIES} + result := result and SendQuery(bqMaySetValue, [Value], Subscriber) +{$ENDIF} end; function TBAInteger.MaySetValue(NewValue: integer; @@ -1005,12 +1666,12 @@ function TBAInteger.CheckRangeWithBounds(Value, Min, result := false; SetBoldLastFailureReason( TBoldFailureReason.createFmt( - sRangeError, - [ClassName, Min, MAX, Value], self)); + 'Value outside range, range is %d to %d. Attempted to set %d', + [Min, MAX, Value], self)); end else result := true; -end; +end; {---TBAByte---} function TBAByte.CheckRange(Value: integer): Boolean; @@ -1034,6 +1695,7 @@ function TBAShortInt.CheckRange(Value: integer): Boolean; result := CheckRangeWithBounds(Value, Low(ShortInt), High(ShortInt)); end; + function TBAShortInt.GetAsShortInt: ShortInt; begin result := AsInteger; @@ -1076,25 +1738,34 @@ procedure TBAWord.SetAsWord(const Value: Word); SetDataValue(Value); end; -procedure TBAInteger.AssignValue(Source: IBoldValue); +procedure TBAInteger.AssignValue(const Source: IBoldValue); var s: IBoldIntegerContent; begin if source.QueryInterface(IBoldIntegerContent, S) = S_OK then SetDataValue(s.AsInteger) else - raise EBold.CreateFmt(sUnknownTypeOfSource, [classname, Meth_AssignValue]); + raise EBold.CreateFmt('%s.AssignValue: unknown type of source', [classname]); end; procedure TBAInteger.SetContent(NewValue: Integer); +var + bContentIsNull: Boolean; + sOldValue: Integer; begin + bContentIsNull := ContentIsNull; if (BoldPersistenceState = bvpsInvalid) or ContentIsNull or (FValue <> NewValue) then begin PreChange; + sOldValue := fValue; FValue := NewValue; SetToNonNull; - Changed(beValueChanged, [NewValue]); + if bContentIsNull then begin + Changed(beValueChanged, [NewValue]); + end else begin + Changed(beValueChanged, [NewValue, sOldValue]); + end; end; end; @@ -1108,7 +1779,7 @@ function TBAInteger_Proxy.GetContentAsInteger: Integer; result := ProxedInteger.fValue; end; -procedure TBAInteger.AssignContentValue(Source: IBoldValue); +procedure TBAInteger.AssignContentValue(const Source: IBoldValue); var s: IBoldIntegerContent; begin @@ -1124,20 +1795,20 @@ procedure TBAInteger.AssignContentValue(Source: IBoldValue); SetContent(s.AsInteger) end else - raise EBold.CreateFmt(sUnknownTypeOfSource, [classname, Meth_AssignContentValue]); + raise EBold.CreateFmt('%s.AssignContentValue: unknown type of source', [classname]); end; function TBAInteger.ProxyInterface(const IId: TGUID; Mode: TBoldDomainElementProxyMode; out Obj): Boolean; begin if IsEqualGuid(IID, IBoldIntegerContent) then - Result := RetrieveProxyInterface(IID, Mode, obj, 'IBoldIntegerContent') // do not localize + Result := RetrieveProxyInterface(IID, Mode, obj, 'IBoldIntegerContent') else result := inherited ProxyInterface(IID, Mode, Obj); end; -function TBAInteger.ProxyClass: TBoldMember_ProxyClass; +function TBAInteger.GetProxy(Mode: TBoldDomainElementProxyMode): TBoldMember_Proxy; begin - result := TBAInteger_Proxy; + result := TBAInteger_Proxy.MakeProxy(self, mode); end; { TBAFloat } @@ -1146,12 +1817,12 @@ procedure TBAFloat.SetDataValue(NewValue: Double); begin BoldClearLastFailure; if not CanSetValue(NewValue, nil) then - BoldRaiseLastFailure(self, 'SetDataValue', ''); // do not localize + BoldRaiseLastFailure(self, 'SetDataValue', ''); if IsNull or (FValue <> NewValue) then begin if not StartModify then - BoldRaiseLastFailure(self, 'SetDataValue', ''); // do not localize + BoldRaiseLastFailure(self, 'SetDataValue', ''); try SetContent(NewValue); @@ -1163,10 +1834,16 @@ procedure TBAFloat.SetDataValue(NewValue: Double); end; end; -procedure TBAFloat.SetStringRepresentation(Representation: TBoldRepresentation; Value: string); +procedure TBAFloat.SetEmptyValue; +begin + if FValue <> 0 then + inherited; +end; + +procedure TBAFloat.SetStringRepresentation(Representation: TBoldRepresentation; const Value: string); begin if not ValidateString(Value, Representation) then - BoldRaiseLastFailure(self, Meth_SetStringRepresentation, sStringValidationFailed); + BoldRaiseLastFailure(self, 'SetStringRepresentation', 'String validation failed'); if Representation = brDefault then if Value = '' then SetToNull @@ -1180,7 +1857,7 @@ function TBAFloat.GetStringRepresentation(Representation: TBoldRepresentation): begin BoldClearLastFailure; if not CanRead(nil) then - BoldRaiseLastFailure(self, Meth_GetStringRepresentation, ''); + BoldRaiseLastFailure(self, 'GetStringRepresentation', ''); if Representation <> brDefault then inherited GetStringRepresentation(Representation); if IsNull then {IsNull ensures current} @@ -1189,11 +1866,35 @@ function TBAFloat.GetStringRepresentation(Representation: TBoldRepresentation): Result := FloatToStr(GetAsFloat); end; +function TBAFloat.IsEqualToValue(const Value: IBoldValue): Boolean; +var + vFloat: IBoldFloatContent; +begin + Assert(Assigned(Value), ClassName + '.IsEqualToValue: Value can not be nil.'); + if Value.QueryInterface(IBoldFloatContent, vFloat) = S_OK then + begin + if IsNull and vFloat.IsNull then + result := true + else + if IsNull or vFloat.IsNull then + result := false + else + result := Self.asFloat = vFloat.asFloat + end + else + result := inherited IsEqualToValue(Value); +end; + +function TBAFloat.IsVariantTypeCompatible(const Value: Variant): Boolean; +begin + result := (VarType(Value) in [varSmallInt, varInteger, varShortInt, varByte, varWord, varLongWord, varInt64, varSingle, varDouble, varCurrency]) +end; + function TBAFloat.GetAsFloat: Double; begin BoldClearLastFailure; if not CanRead(nil) then - BoldRaiseLastFailure(self, 'GetAsFloat', ''); // do not localize + BoldRaiseLastFailure(self, 'GetAsFloat', ''); EnsureNotNull; {ensures current} Result := FValue; end; @@ -1210,10 +1911,10 @@ procedure TBAFloat.SetAsInteger(Value: Integer); function TBAFloat.ValidateCharacter(C: Char; Representation: TBoldRepresentation): Boolean; begin - Result := C in ['0'..'9', '-', '+', 'e', 'E', FormatSettings.DecimalSeparator]; + Result := CharInSet(C, ['0'..'9', '-', '+', 'e', 'E', {$IFDEF BOLD_DELPHI16_OR_LATER}FormatSettings.{$ENDIF}DecimalSeparator]); end; -function TBAFloat.ValidateString(Value: string; Representation: TBoldRepresentation): Boolean; +function TBAFloat.ValidateString(const Value: string; Representation: TBoldRepresentation): Boolean; var temp: Extended; begin @@ -1223,7 +1924,7 @@ function TBAFloat.ValidateString(Value: string; Representation: TBoldRepresentat begin result := TextToFloat(PChar(Value), temp, fvExtended); if not result then - FormatFailure(value, 'float'); // do not localize + FormatFailure(value, 'float'); end; end; @@ -1269,10 +1970,24 @@ function TBAFloat.CompareToAs(CompType: TBoldCompareType; BoldElement: TBoldElem Result := inherited CompareToAs(CompType, BoldElement); end; +constructor TBAFloat.CreateWithValue(Value: double); +begin + inherited Create; + asFloat := Value; +end; + +procedure TBAFloat.FreeContent; +begin + inherited; + fValue := 0; +end; + function TBAFloat.CanSetValue(NewValue: Double; Subscriber: TBoldSubscriber): Boolean; begin - result := MaySetValue(NewValue, Subscriber) and - SendQuery(bqMaySetValue, [NewValue], Subscriber); + result := MaySetValue(NewValue, Subscriber); +{$IFNDEF BOLD_NO_QUERIES} + result := result and SendQuery(bqMaySetValue, [NewValue], Subscriber) +{$ENDIF} end; function TBAFloat.MaySetValue(NewValue: Double; @@ -1281,24 +1996,34 @@ function TBAFloat.MaySetValue(NewValue: Double; result := True; end; -procedure TBAFloat.AssignValue(Source: IBoldValue); +procedure TBAFloat.AssignValue(const Source: IBoldValue); var s: IBoldFloatContent; begin if source.QueryInterface(IBoldFloatContent, S) = S_OK then SetDataValue(s.AsFloat) else - raise EBold.CreateFmt(sUnknownTypeOfSource, [classname, Meth_AssignValue]); + raise EBold.CreateFmt('%s.AssignValue: unknown type of source', [classname]); end; procedure TBAFloat.SetContent(NewValue: Double); +var + bContentIsNull: Boolean; + sOldValue: Double; begin - if ContentIsNull or (FValue <> NewValue) then + bContentIsNull := ContentIsNull; + if (BoldPersistenceState = bvpsInvalid) or + ContentIsNull or (FValue <> NewValue) then begin PreChange; + sOldValue := fValue; FValue := NewValue; SetToNonNull; - Changed(beValueChanged, [NewValue]); + if bContentIsNull then begin + Changed(beValueChanged, [NewValue]); + end else begin + Changed(beValueChanged, [NewValue, sOldValue]); + end; end; end; @@ -1312,7 +2037,7 @@ procedure TBAFloat_Proxy.SetContentAsFloat(NewValue: Double); ProxedFloat.SetContent(NewValue); end; -procedure TBAFloat.AssignContentValue(Source: IBoldValue); +procedure TBAFloat.AssignContentValue(const Source: IBoldValue); var FloatContent: IBoldFloatContent; CurrencyContent: IBoldCurrencyContent; @@ -1344,20 +2069,20 @@ procedure TBAFloat.AssignContentValue(Source: IBoldValue); SetContent(IntegerContent.asInteger) end else - raise EBold.CreateFmt(sUnknownTypeOfSource, [classname, Meth_AssignContentValue]); + raise EBold.CreateFmt('%s.AssignValue: unknown type of source', [classname]); end; function TBAFloat.ProxyInterface(const IId: TGUID; Mode: TBoldDomainElementProxyMode; out Obj): Boolean; begin if IsEqualGuid(IID, IBoldFloatContent) then - Result := RetrieveProxyInterface(IBoldFloatContent, Mode, obj, 'IBoldFloatContent') // do not localize + Result := RetrieveProxyInterface(IBoldFloatContent, Mode, obj, 'IBoldFloatContent') else result := inherited ProxyInterface(IID, Mode, Obj); end; -function TBAFloat.ProxyClass: TBoldMember_ProxyClass; +function TBAFloat.GetProxy(Mode: TBoldDomainElementProxyMode): TBoldMember_Proxy; begin - result := TBAFloat_Proxy; + result := TBAFloat_Proxy.MakeProxy(self, mode); end; { TBACurrency } @@ -1366,12 +2091,12 @@ procedure TBACurrency.SetDataValue(NewValue: Currency); begin BoldClearLastFailure; if not CanSetValue(NewValue, nil) then - BoldRaiseLastFailure(self, 'SetDataValue', ''); // do not localize + BoldRaiseLastFailure(self, 'SetDataValue', ''); if IsNull or (FValue <> NewValue) then begin if not StartModify then - BoldRaiseLastFailure(self, 'SetDataValue', ''); // do not localize + BoldRaiseLastFailure(self, 'SetDataValue', ''); try SetContent(NewValue); EndModify; @@ -1382,19 +2107,26 @@ procedure TBACurrency.SetDataValue(NewValue: Currency); end; end; -procedure TBACurrency.SetStringRepresentation(Representation: TBoldRepresentation; Value: string); +procedure TBACurrency.SetEmptyValue; +begin + if fValue <> 0 then + inherited; +end; + +procedure TBACurrency.SetStringRepresentation(Representation: TBoldRepresentation; const Value: string); begin if not ValidateString(Value, Representation) then - BoldRaiseLastFailure(self, Meth_SetStringRepresentation, sStringValidationFailed); + BoldRaiseLastFailure(self, 'SetStringRepresentation', 'String validation failed'); if Representation = brDefault then begin if Value = '' then SetToNull else begin - if Value[Length(Value)] = FormatSettings.DecimalSeparator then - Value := Concat(Value, '0'); - SetDataValue(StrToCurr(Value)); + if Value[Length(Value)] = {$IFDEF BOLD_DELPHI16_OR_LATER}FormatSettings.{$ENDIF}DecimalSeparator then + SetDataValue(StrToCurr(Concat(Value, '0'))) + else + SetDataValue(StrToCurr(Value)); end; end else inherited SetStringRepresentation(Representation, Value); @@ -1404,7 +2136,7 @@ function TBACurrency.GetStringRepresentation(Representation: TBoldRepresentation begin BoldClearLastFailure; if not CanRead(nil) then - BoldRaiseLastFailure(self, Meth_GetStringRepresentation, ''); + BoldRaiseLastFailure(self, 'GetStringRepresentation', ''); if Representation <> brDefault then inherited GetStringRepresentation(Representation); if IsNull then {IsNull ensures current} @@ -1413,6 +2145,30 @@ function TBACurrency.GetStringRepresentation(Representation: TBoldRepresentation Result := CurrToStr(GetAsCurrency); end; +function TBACurrency.IsEqualToValue(const Value: IBoldValue): Boolean; +var + vCurrency: IBoldCurrencyContent; +begin + Assert(Assigned(Value), ClassName + '.IsEqualToValue: Value can not be nil.'); + if Value.QueryInterface(IBoldCurrencyContent, vCurrency) = S_OK then + begin + if IsNull and vCurrency.IsNull then + result := true + else + if IsNull or vCurrency.IsNull then + result := false + else + result := Self.asCurrency = vCurrency.asCurrency + end + else + result := inherited IsEqualToValue(Value); +end; + +function TBACurrency.IsVariantTypeCompatible(const Value: Variant): Boolean; +begin + result := (VarType(Value) in [varSmallInt, varInteger, varShortInt, varByte, varWord, varLongWord, varInt64, varSingle, varDouble, varCurrency]) +end; + procedure TBACurrency.SetAsCurrency(Value: Currency); begin SetDataValue(Value); @@ -1422,7 +2178,7 @@ function TBACurrency.GetAsCurrency: Currency; begin BoldClearLastFailure; if not CanRead(nil) then - BoldRaiseLastFailure(self, 'GetAsCurrency', ''); // do not localize + BoldRaiseLastFailure(self, 'GetAsCurrency', ''); EnsureNotNull; {ensures current} Result := FValue; end; @@ -1431,7 +2187,7 @@ function TBACurrency.GetAsFloat: Double; begin BoldClearLastFailure; if not CanRead(nil) then - BoldRaiseLastFailure(self, 'GetAsFloat', ''); // do not localize + BoldRaiseLastFailure(self, 'GetAsFloat', ''); EnsureNotNull; {ensures current} Result := FValue; end; @@ -1446,7 +2202,7 @@ procedure TBACurrency.SetAsInteger(Value: integer); SetAsFloat(Value); end; -function TBACurrency.ValidateString(Value: string; Representation: TBoldRepresentation): Boolean; +function TBACurrency.ValidateString(const Value: string; Representation: TBoldRepresentation): Boolean; var Temp: Currency; begin @@ -1456,13 +2212,13 @@ function TBACurrency.ValidateString(Value: string; Representation: TBoldRepresen begin result := TextToFloat(PChar(Value), temp, fvCurrency); if not result then - FormatFailure(value, 'currency'); // do not localize + FormatFailure(value, 'currency'); end; end; function TBACurrency.ValidateCharacter(C: Char; Representation: TBoldRepresentation): Boolean; begin - Result := C in ['0'..'9', '-', '+', 'e', 'E', FormatSettings.DecimalSeparator]; + Result := CharInSet(C, ['0'..'9', '-', '+', 'e', 'E', {$IFDEF BOLD_DELPHI16_OR_LATER}FormatSettings.{$ENDIF}DecimalSeparator]); end; procedure TBACurrency.Assign(Source: TBoldElement); @@ -1511,10 +2267,24 @@ function TBACurrency.CompareToAs(CompType: TBoldCompareType; BoldElement: TBoldE Result := inherited CompareToAs(CompType, BoldElement); end; +constructor TBACurrency.CreateWithValue(Value: currency); +begin + inherited Create; + asCurrency := Value; +end; + +procedure TBACurrency.FreeContent; +begin + inherited; + fValue := 0; +end; + function TBACurrency.CanSetValue(NewValue: Currency; Subscriber: TBoldSubscriber): Boolean; begin - Result := MaySetValue(NewValue, Subscriber) and - SendQuery(bqMaySetValue, [NewValue], Subscriber); + result := MaySetValue(NewValue, Subscriber); +{$IFNDEF BOLD_NO_QUERIES} + result := result and SendQuery(bqMaySetValue, [NewValue], Subscriber) +{$ENDIF} end; function TBACurrency.MaySetValue(NewValue: Currency; @@ -1523,24 +2293,34 @@ function TBACurrency.MaySetValue(NewValue: Currency; Result := True; end; -procedure TBACurrency.AssignValue(Source: IBoldValue); +procedure TBACurrency.AssignValue(const Source: IBoldValue); var s: IBoldCurrencyContent; begin if source.QueryInterface(IBoldCurrencyContent, S) = S_OK then SetDataValue(s.AsCurrency) else - raise EBold.CreateFmt(sUnknownTypeOfSource, [classname, Meth_AssignValue]); + raise EBold.CreateFmt('%s.AssignValue: unknown type of source', [classname]); end; procedure TBACurrency.SetContent(NewValue: Currency); +var + bContentIsNull: Boolean; + sOldValue: Currency; begin - if ContentIsNull or (FValue <> NewValue) then + bContentIsNull := ContentIsNull; + if (BoldPersistenceState = bvpsInvalid) or + ContentIsNull or (FValue <> NewValue) then begin PreChange; + sOldValue := fValue; FValue := NewValue; SetToNonNull; - Changed(beValueChanged, [NewValue]); + if bContentIsNull then begin + Changed(beValueChanged, [NewValue]); + end else begin + Changed(beValueChanged, [NewValue, sOldValue]); + end; end; end; @@ -1554,7 +2334,7 @@ function TBACurrency_Proxy.GetContentAsCurrency: Currency; result := ProxedCurrency.fValue; end; -procedure TBACurrency.AssignContentValue(Source: IBoldValue); +procedure TBACurrency.AssignContentValue(const Source: IBoldValue); var s: IBoldCurrencyContent; FloatContent: IBoldFloatContent; @@ -1585,55 +2365,48 @@ procedure TBACurrency.AssignContentValue(Source: IBoldValue); else SetContent(IntegerContent.AsInteger) end else - raise EBold.CreateFmt(sUnknownTypeOfSource, [classname, Meth_AssignContentValue]); + raise EBold.CreateFmt('%s.AssignContentValue: unknown type of source', [classname]); end; function TBACurrency.ProxyInterface(const IId: TGUID; Mode: TBoldDomainElementProxyMode; out Obj): Boolean; begin if IsEqualGuid(IID, IBoldCurrencyContent) then - Result := RetrieveProxyInterface(IID, Mode, obj, 'IBoldCurrencyContent') // do not localize + Result := RetrieveProxyInterface(IID, Mode, obj, 'IBoldCurrencyContent') else result := inherited ProxyInterface(IID, Mode, Obj); end; -function TBACurrency.ProxyClass: TBoldMember_ProxyClass; +function TBACurrency.GetProxy(Mode: TBoldDomainElementProxyMode): TBoldMember_Proxy; begin - result := TBACurrency_Proxy; + result := TBACurrency_Proxy.MakeProxy(self, mode); end; { TBoldBlobStream } -constructor TBoldBlobStream.Create(BlobAttr: TBABlob; Mode: TBoldBlobStreamMode); +constructor TBoldBlobStream.Create(BlobAttr: TBABlob); begin inherited Create; fBlobAttr := BlobAttr; - fMode := Mode; - if (Mode in [bmReadWrite, bmWrite]) and not BlobAttr.Mutable then - BlobAttr.MutableError('Binary Large Object'); //FIXME Better representation of BLOBs!!! // do not localize - if Mode in [bmRead, bmReadWrite] then - fBlobAttr.EnsureNotNull; - if (Mode = bmWrite) then - Truncate; end; -function TBoldBlobStream.GetBlobSize: Integer; +function TBoldBlobStream.GetBlobSize: Int64; begin - Result := Length(fBlobAttr.fValue); + Result := Length(fData); end; -function TBoldBlobStream.Read(var Buffer; Count: integer): integer; +function TBoldBlobStream.Read(var Buffer; Count: Longint): Longint; begin if Count > Size - fPosition then Result := Size - fPosition else Result := Count; if Result > 0 then begin - Move(PChar(fBlobAttr.fValue)[fPosition], Buffer, Result); + Move(PAnsiChar(fBlobAttr.AsStream.fData)[fPosition], Buffer, Result); Inc(FPosition, Result); end; end; -function TBoldBlobStream.Write(const Buffer; Count: integer): integer; +function TBoldBlobStream.Write(const Buffer; Count: Longint): Longint; var EndPos: integer; begin @@ -1644,23 +2417,27 @@ function TBoldBlobStream.Write(const Buffer; Count: integer): integer; if EndPos > 0 then begin try - StartModifyOfBlob('Write'); // do not localize + if not fBlobAttr.SupressEvents then + fBlobAttr.StartModifyOfBlob('Write'); if EndPos > Size then begin - SetLength(fBlobAttr.fValue, EndPos); + SetLength(fData, EndPos); end; - System.Move(Buffer, PChar(fBlobAttr.fValue)[fPosition], Count); + System.Move(Buffer, PAnsiChar(fBlobAttr.AsStream.fData)[fPosition], Count); fPosition := EndPos; Result := Count; - EndModifyOfBlob; + if not fBlobAttr.SupressEvents then + fBlobAttr.EndModifyOfBlob; except - FailModifyOfBlob; + if not fBlobAttr.SupressEvents then + fBlobAttr.FailModifyOfBlob; + raise; end; end; end; end; -function TBoldBlobStream.Seek(Offset: integer; Origin: Word): integer; +function TBoldBlobStream.Seek(Offset: Longint; Origin: Word): Longint; begin case Origin of 0: FPosition := Offset; @@ -1670,6 +2447,11 @@ function TBoldBlobStream.Seek(Offset: integer; Origin: Word): integer; Result := FPosition; end; +procedure TBoldBlobStream.SetSize(NewSize: Longint); +begin + SetSize(Int64(NewSize)); +end; + procedure TBoldBlobStream.Clear; begin SetSize(0); @@ -1684,26 +2466,26 @@ procedure TBoldBlobStream.LoadFromStream(Stream: TStream); var Count: Integer; begin - Stream.Position := 0; - Count := Stream.Size; - InternalSetSize(Count, Count = 0); // dont send any events if we are going to set the stream-value below - if Count <> 0 then - begin - try - StartModifyOfBlob('LoadFromStream'); // do not localize - Stream.ReadBuffer(PChar(fBlobAttr.fValue)[0], Count); - EndModifyOfBlob; - except - FailModifyOfBlob; + try + fBlobAttr.StartModifyOfBlob('LoadFromStream'); + Count := Stream.Size; + InternalSetSize(Count, Count = 0); + if Count <> 0 then + begin + Stream.ReadBuffer(fBlobAttr.AsStream.fData, Count); end; + fBlobAttr.EndModifyOfBlob; + except + fBlobAttr.FailModifyOfBlob; + raise; end; end; -procedure TBoldBlobStream.LoadFromFile(const FileName: string); +procedure TBoldBlobStream.LoadFromFile(const aFileName: string; aMode: Word = fmShareDenyNone); var Stream: TStream; begin - Stream := TFileStream.Create(FileName, fmOpenRead); + Stream := TFileStream.Create(aFileName, aMode); try LoadFromStream(Stream); finally @@ -1713,8 +2495,9 @@ procedure TBoldBlobStream.LoadFromFile(const FileName: string); procedure TBoldBlobStream.SaveToStream(Stream: TStream); begin + fBlobAttr.EnsureContentsCurrent; if Size <> 0 then - Stream.WriteBuffer(PChar(fBlobAttr.fValue)[0], Size); + Stream.WriteBuffer(fBlobAttr.AsStream.fData, Size); end; procedure TBoldBlobStream.SaveToFile(const FileName: string); @@ -1729,67 +2512,61 @@ procedure TBoldBlobStream.SaveToFile(const FileName: string); end; end; -procedure TBoldBlobStream.SetSize(NewSize: integer); -begin - InternalSetSize(NewSize, true); -end; - -procedure TBoldBlobStream.EndModifyOfBlob; -begin - // we can not call SetToNull since that will cause recursive Modification. that must be done by InternalSetSize - if (Size<>0) then - fBlobAttr.SetToNonNull; - fBlobAttr.Changed(beValueChanged, [fBlobAttr.FValue]); - fBlobAttr.EndModify; -end; - -procedure TBoldBlobStream.FailModifyOfBlob; -begin - fBlobAttr.FailModify; -end; - -procedure TBoldBlobStream.StartModifyOfBlob(Operation: String); +procedure TBoldBlobStream.SetSize(const NewSize: Int64); begin - if not fBlobAttr.StartModify then - BoldRaiseLastFailure(fBlobAttr, 'BlobStream: ' + Operation, ''); // do not localize - fBlobAttr.PreChange; + if NewSize <> GetBlobSize then + InternalSetSize(NewSize, not fBlobAttr.SupressEvents); end; -procedure TBoldBlobStream.InternalSetSize(NewSize: Integer; BlobEvents: Boolean); +procedure TBoldBlobStream.InternalSetSize(NewSize: Int64; BlobEvents: Boolean); var - OldPosition: Integer; + OldPosition: Int64; begin + if NewSize = Size then + exit; OldPosition := fPosition; if (NewSize = 0) and (not assigned(fBlobAttr.BoldAttributeRTInfo) or fBlobAttr.BoldAttributeRTInfo.AllowNull) then - fBlobAttr.SetToNull + begin + SetLength(fData, 0); + if not fBlobAttr.SupressEvents then + fBlobAttr.SetToNull; + end else try if BlobEvents then - StartModifyOfBlob('SetSize'); // do not localize - SetLength(fBlobAttr.fValue, NewSize); + fBlobAttr.StartModifyOfBlob('SetSize'); + SetLength(fData, NewSize); if BlobEvents then - EndModifyOfBlob; + fBlobAttr.EndModifyOfBlob; except if BlobEvents then - FailModifyOfBlob; + fBlobAttr.FailModifyOfBlob; + raise end; if OldPosition > NewSize then Seek(0, soFromEnd); +end; +function TBoldBlobStream.IsDataSame(AData: Pointer; ASize: Int64): boolean; +begin + result := false; + if ASize = Length(fData) then + result := CompareMem(AData, fData, ASize); end; { TBABlob } -procedure TBABlob.SetDataValue(NewValue: string); + +procedure TBABlob.SetDataValue(NewValue: TBoldAnsiString); begin BoldClearLastFailure; if not CanSetValue(NewValue, nil) then - BoldRaiseLastFailure(self, 'SetDataValue', ''); // do not localize + BoldRaiseLastFailure(self, 'SetDataValue', ''); - if IsNull or (FValue <> NewValue) then + if IsNull or not AsStream.IsDataSame(PAnsiChar(NewValue), Length(NewValue)) then begin if not StartModify then - BoldRaiseLastFailure(self, 'SetDataValue', ''); // do not localize + BoldRaiseLastFailure(self, 'SetDataValue', ''); try SetContent(NewValue); EndModify; @@ -1800,29 +2577,47 @@ procedure TBABlob.SetDataValue(NewValue: string); end; end; -procedure TBABlob.SetStringRepresentation(Representation: TBoldRepresentation; Value: string); +procedure TBABlob.SetStringRepresentation(Representation: TBoldRepresentation; const Value: string); begin if not ValidateString(Value, Representation) then - BoldRaiseLastFailure(self, Meth_SetStringRepresentation, sStringValidationFailed); + BoldRaiseLastFailure(self, 'SetStringRepresentation', 'String validation failed'); case Representation of - brDefault: SetDataValue(Value); + brDefault: SetDataValue(TBoldAnsiString(Value)); brShort: {Content type is lost when assigned to a Blob}; else inherited SetStringRepresentation(Representation, Value); end; end; +function TBABlob.SupressEvents: Boolean; +begin + result := fSupressEventCount > 0; +end; + +procedure TBABlob.BeginSupressEvents; +begin + Inc(fSupressEventCount); + StartModifyOfBlob('Write'); +end; + +procedure TBABlob.EndSupressEvents; +begin + EndModifyOfBlob; + Dec(fSupressEventCount); + Assert(fSupressEventCount >= 0); +end; + function TBABlob.GetStringRepresentation(Representation: TBoldRepresentation): string; begin BoldClearLastFailure; if not CanRead(nil) then - BoldRaiseLastFailure(self, Meth_GetStringRepresentation, ''); + BoldRaiseLastFailure(self, 'GetStringRepresentation', ''); case Representation of brDefault: begin if IsNull then {IsNull ensures current} Result := '' else - Result := FValue; + Result := TEncoding.Default.GetString(AsStream.fData); end; brShort: begin Result := ''; @@ -1832,21 +2627,84 @@ function TBABlob.GetStringRepresentation(Representation: TBoldRepresentation): s end; end; -function TBABlob.GetAsBlob: String; +function TBABlob.GetAsBlob: TBoldAnsiString; +begin + result := TBoldAnsiString(TEncoding.Default.GetString(AsStream.fData)); +end; + +function TBABlob.GetAsStream: TBoldBlobStream; +begin + if not SupressEvents then + EnsureContentsCurrent; + if not Assigned(fStream) then + fStream := TBoldBlobStream.Create(self); + result := fStream; +end; + +function TBABlob.GetBlobSize: Int64; +begin + result := AsStream.GetBlobSize; +end; + +function TBABlob.GetFreeStandingClass: TBoldFreeStandingElementClass; +begin + result := TBFSBlob; +end; + +procedure TBABlob.SetAsBlob(NewValue: TBoldAnsiString); begin - result := GetStringRepresentation(brDefault); + SetStringRepresentation(brDefault, String(NewValue)); end; -procedure TBABlob.SetAsBlob(NewValue: String); +procedure TBABlob.SetAsVariant(const Value: Variant); +var + p: Pointer; begin - SetStringRepresentation(brDefault, NewValue); + if VarIsArray(Value) then + begin + if VarType(Value) <> VarArray + VarByte then + raise EBold.CreateFmt('%s.SetAsVariant: Unsupported type of variant array, type: %d.', [classname, VarType(Value)]); + AsStream.Clear; + p := VarArrayLock(Value); + try + AsStream.Write(p ^, VarArrayHighBound(Value, 1)); + finally + VarArrayUnlock(Value); + end; + end + else + inherited SetAsVariant(Value); end; procedure TBABlob.SetToNull; begin inherited; - // save memory by "disposing" of blob data - FValue := ''; + AsStream.Clear; +end; + +procedure TBABlob.StartModifyOfBlob(const Operation: String); +begin + if not SupressEvents and not StartModify then + BoldRaiseLastFailure(self, 'BlobStream: '+Operation, ''); + PreChange; +end; + +procedure TBABlob.EndModifyOfBlob; +begin + if (GetBlobSize<>0) then + SetToNonNull; + // Old value is not passed in as parameter when Blob is set via Stream + // TODO: If Old value is needed store it in StartModifyOfBlob + Changed(beValueChanged, [fStream.fData]); + if not SupressEvents then + EndModify; +end; + +procedure TBABlob.FailModifyOfBlob; +begin + if SupressEvents then + exit; + FailModify; end; procedure TBABlob.Assign(Source: TBoldElement); @@ -1857,7 +2715,8 @@ procedure TBABlob.Assign(Source: TBoldElement); SetToNull else begin - AsString := TBABlob(Source).AsString; + TBABlob(Source).AsStream.Position:=0; + LoadFromStream(TBABlob(Source).AsStream); ContentType := TBABlob(Source).ContentType; end; Exit; @@ -1866,55 +2725,85 @@ procedure TBABlob.Assign(Source: TBoldElement); inherited; end; -function TBABlob.CreateBlobStream(Mode: TBoldBlobStreamMode): TBoldBlobStream; -begin - Result := TBoldBlobStream.Create(Self, Mode); -end; - -function TBABlob.CanSetValue(NewValue: string; Subscriber: TBoldSubscriber): Boolean; +function TBABlob.CanSetValue(NewValue: TBoldAnsiString; Subscriber: TBoldSubscriber): Boolean; begin - Result := MaySetValue(NewValue, Subscriber) and - SendQuery(bqMaySetValue, [NewValue], Subscriber); + result := MaySetValue(NewValue, Subscriber); +{$IFNDEF BOLD_NO_QUERIES} + result := result and SendQuery(bqMaySetValue, [NewValue], Subscriber) +{$ENDIF} end; -function TBABlob.MaySetValue(NewValue: String; +function TBABlob.MaySetValue(NewValue: TBoldAnsiString; Subscriber: TBoldSubscriber): Boolean; begin Result := True; end; -procedure TBABlob.AssignValue(Source: IBoldValue); +procedure TBABlob.AssignValue(const Source: IBoldValue); var s: IBoldBlobContent; begin if source.QueryInterface(IBoldBlobContent, S) = S_OK then SetDataValue(s.AsBlob) else - raise EBold.CreateFmt(sUnknownTypeOfSource, [classname, Meth_AssignValue]); + raise EBold.CreateFmt('%s.AssignValue: unknown type of source', [classname]); end; -procedure TBABlob.SetContent(NewValue: string); +procedure TBABlob.SetContent(NewValue: TBoldAnsiString); +var + bContentIsNull: Boolean; + aOldValue: TBytes; begin - if ContentIsNull or (FValue <> NewValue) then + bContentIsNull := ContentIsNull; + if bContentIsNull or not AsStream.IsDataSame(PAnsiChar(NewValue), Length(NewValue)) then begin PreChange; - FValue := NewValue; + aOldValue := Copy(AsStream.fData, 0, BlobSize); + if NewValue = '' then + begin + AsStream.Clear; + AsStream.Seek(0, soFromBeginning); + end + else + begin + AsStream.fData := BytesOf(NewValue); + AsStream.Seek(0, soFromEnd); + end; SetToNonNull; - Changed(beValueChanged, [NewValue]); + if bContentIsNull then begin + Changed(beValueChanged, [AsStream.fData]); + end else begin + Changed(beValueChanged, [AsStream.fData, aOldValue]); + end; end; end; -function TBABlob_Proxy.GetContentAsBlob: string; +procedure TBABlob_Proxy.BeginSupressEvents; +begin + ProxedBlob.BeginSupressEvents; +end; + +procedure TBABlob_Proxy.EndSupressEvents; +begin + ProxedBlob.EndSupressEvents; +end; + +function TBABlob_Proxy.GetBlobAsStream: TStream; +begin + result := ProxedBlob.AsStream; +end; + +function TBABlob_Proxy.GetContentAsBlob: TBoldAnsiString; begin - result := ProxedBlob.fValue; + SetString(result, PAnsiChar(ProxedBlob.AsStream.fData), ProxedBlob.BlobSize); end; -procedure TBABlob_Proxy.SetContentAsBlob(const NewValue: string); +procedure TBABlob_Proxy.SetContentAsBlob(const NewValue: TBoldAnsiString); begin ProxedBlob.SetContent(NewValue); end; -procedure TBABlob.AssignContentValue(Source: IBoldValue); +procedure TBABlob.AssignContentValue(const Source: IBoldValue); var s: IBoldBlobContent; begin @@ -1930,7 +2819,7 @@ procedure TBABlob.AssignContentValue(Source: IBoldValue); SetContent(s.AsBlob) end else - raise EBold.CreateFmt(sUnknownTypeOfSource, [classname, Meth_AssignContentValue]); + raise EBold.CreateFmt('%s.AssignContentValue: unknown type of source', [classname]); end; function TBABlob.CompareToAs(CompareType: TBoldCompareType; @@ -1945,25 +2834,32 @@ function TBABlob.CompareToAs(CompareType: TBoldCompareType; Result := NullSmallest(CompareBlob) else begin - case CompareType of - ctDefault, ctAsString: - // will this really compare binary values with #0 inside? /joho - Result := CompareStr(fValue, CompareBlob.fValue); - ctAsText: - Result := CompareText(fValue, CompareBlob.fValue); - ctAsAnsiString: - Result := AnsiCompareStr(fValue, CompareBlob.fValue); - ctAsAnsiText: - Result := AnsiCompareText(fValue, CompareBlob.fValue); + if CompareBlob.BlobSize > MaxInt then + begin // memory compare, 2 results + if AsStream.IsDataSame(CompareBlob.AsStream.fData, CompareBlob.BlobSize) then + result := 0 else - result := inherited CompareToAs(CompareType, BoldElement); - end; + result := -1; + end + else // string compare, 3 results + Result := StringCompare(CompareType, AsString, CompareBlob.AsString); end; end else Result := inherited CompareToAs(CompareType, BoldElement); end; +destructor TBABlob.Destroy; +begin + FreeAndNil(fStream); + inherited; +end; + +procedure TBABlob.Initialize; +begin + inherited; +end; + function TBABlob.IsEqualAs(CompareType: TBoldCompareType; BoldElement: TBoldElement): Boolean; var @@ -1975,34 +2871,77 @@ function TBABlob.IsEqualAs(CompareType: TBoldCompareType; if EitherIsNull(self, CompareBlob) then result := CompareBlob.IsNull and IsNull else - result := CompareBlob.fValue = fValue; // will this really compare binary values with #0 inside? /joho + result := CompareBlob.AsStream.fData = AsStream.fData; end else Result := inherited IsEqualAs(CompareType, BoldElement); end; +function TBABlob.IsEqualToValue(const Value: IBoldValue): Boolean; +var + vBlob: IBoldBlobContent; +begin + Assert(Assigned(Value), ClassName + '.IsEqualToValue: Value can not be nil.'); + if Value.QueryInterface(IBoldBlobContent, vBlob) = S_OK then + begin + if IsNull and vBlob.IsNull then + result := true + else + if IsNull or vBlob.IsNull then + result := false + else + result := Self.GetAsBlob = vBlob.asBlob + end + else + result := inherited IsEqualToValue(Value); +end; + function TBABlob.ProxyInterface(const IId: TGUID; Mode: TBoldDomainElementProxyMode; out Obj): Boolean; begin if IsEqualGuid(IID, IBoldBlobContent) then - Result := RetrieveProxyInterface(IID, Mode, obj, 'IBoldBlobContent') // do not localize + Result := RetrieveProxyInterface(IID, Mode, obj, 'IBoldBlobContent') else result := inherited ProxyInterface(IID, Mode, Obj); end; -function TBABlob.ProxyClass: TBoldMember_ProxyClass; +function TBABlob.GetProxy(Mode: TBoldDomainElementProxyMode): TBoldMember_Proxy; +begin + result := TBABlob_Proxy.MakeProxy(self, mode); +end; + +procedure TBABlob.FreeContent; +begin + inherited; + if assigned(fStream) then + fStream.Clear; +end; + +procedure TBABlob.SetEmptyValue; +begin + if Assigned(BoldAttributeRTInfo) and not BoldAttributeRTInfo.AllowNull then + asString := '' + else + SetContentToNull; +end; + +procedure TBABlob.LoadFromFile(const aFileName: string; aMode: Word); +begin + AsStream.LoadFromFile(aFilename, aMode); +end; + +procedure TBABlob.LoadFromStream(Stream: TStream); begin - result := TBABlob_Proxy; + AsStream.LoadFromStream(Stream); end; -procedure TBABlob.FreeContent; +procedure TBABlob.SaveToFile(const FileName: string); begin - inherited; - FValue := ''; + AsStream.SaveToFile(FileName); end; -procedure TBABlob.SetEmptyValue; +procedure TBABlob.SaveToStream(Stream: TStream); begin - asString := ''; + AsStream.SaveToStream(Stream); end; { TBATypedBlob } @@ -2010,12 +2949,12 @@ procedure TBATypedBlob.SetContentType2(Value: string); begin BoldClearLastFailure; if not CanSetContentType(Value, nil) then - BoldRaiseLastFailure(self, 'SetContentType', ''); // do not localize + BoldRaiseLastFailure(self, 'SetContentType', ''); if ContentIsNull or (FContentType <> Value) then begin if not StartModify then - BoldRaiseLastFailure(self, 'SetContentType', ''); // do not localize + BoldRaiseLastFailure(self, 'SetContentType', ''); try SetContentTypeContent(Value); EndModify; @@ -2030,16 +2969,21 @@ function TBATypedBlob.GetContentTypeContent: String; begin BoldClearLastFailure; if not CanRead(nil) then - BoldRaiseLastFailure(self, 'GetContentType', ''); // do not localize + BoldRaiseLastFailure(self, 'GetContentType', ''); result := ContentType; end; +function TBATypedBlob.GetFreeStandingClass: TBoldFreeStandingElementClass; +begin + result := TBFSTypedBlob; +end; + function TBATypedBlob.GetStringRepresentation(Representation: TBoldRepresentation): string; begin case Representation of brShort: begin if not CanRead(nil) then - BoldRaiseLastFailure(self, Meth_GetStringRepresentation, ''); + BoldRaiseLastFailure(self, 'GetStringRepresentation', ''); Result := FContentType; end; else @@ -2047,12 +2991,12 @@ function TBATypedBlob.GetStringRepresentation(Representation: TBoldRepresentatio end; end; -procedure TBATypedBlob.SetStringRepresentation(Representation: TBoldRepresentation; Value: string); +procedure TBATypedBlob.SetStringRepresentation(Representation: TBoldRepresentation; const Value: string); begin case Representation of brShort: begin if not ValidateString(Value, Representation) then - BoldRaiseLastFailure(self, Meth_SetStringRepresentation, sStringValidationFailed); + BoldRaiseLastFailure(self, 'SetStringRepresentation', 'String validation failed'); SetContentType2(Value); end; else @@ -2068,10 +3012,14 @@ procedure TBATypedBlob.SetToNull; function TBATypedBlob.CanSetContentType(Value: string; Subscriber: TBoldSubscriber): Boolean; begin +{$IFDEF BOLD_NO_QUERIES} + result := True; +{$ELSE} Result := SendQuery(bqMaySetContentType, [Value], Subscriber); +{$ENDIF} end; -procedure TBATypedBlob.AssignValue(Source: IBoldValue); +procedure TBATypedBlob.AssignValue(const Source: IBoldValue); var s: IBoldTypedBlob; s2: IBoldBlobContent; @@ -2084,7 +3032,7 @@ procedure TBATypedBlob.AssignValue(Source: IBoldValue); SetDataValue(s2.AsBlob); end else - raise EBold.CreateFmt(sUnknownTypeOfSource, [classname, Meth_AssignValue]); + raise EBold.CreateFmt('%s.AssignValue: unknown type of source', [classname]); end; function TBATypedBlob.CompareToAs(CompareType: TBoldCompareType; @@ -2110,15 +3058,27 @@ function TBATypedBlob.IsEqualAs(CompareType: TBoldCompareType; end else result := inherited IsEqualAs(CompareType, BoldElement); + +end; + +function TBATypedBlob.IsEqualToValue(const Value: IBoldValue): Boolean; +var + vTypedBlob: IBoldTypedBlob; +begin + Assert(Assigned(Value), ClassName + '.IsEqualToValue: Value can not be nil.'); + if Value.QueryInterface(IBoldTypedBlob, vTypedBlob) = S_OK then + result := (Self.ContentType = vTypedBlob.ContentTypeContent) and inherited IsEqualToValue(Value) + else + result := inherited IsEqualToValue(Value); end; {-- TBABlobImageJPEG --} -procedure TBABlobImageJPEG.SetStringRepresentation(Representation: TBoldRepresentation; Value: string); +procedure TBABlobImageJPEG.SetStringRepresentation(Representation: TBoldRepresentation; const Value: string); begin case Representation of brShort: begin - if (Value <> '') and (Value <> ContentType) then - raise EBold.CreateFmt(sCannotAssignXtoY, [ClassName, Value, ContentType]); + if (Value<>'') and (Value<>ContentType) then + raise EBold.CreateFmt('%s.SetStringRepresentation: Can not assign a ''%s'' to a ''%s''', [ClassName, Value, ContentType]); end; else inherited SetStringRepresentation(Representation, Value); @@ -2129,7 +3089,7 @@ function TBABlobImageJPEG.GetStringRepresentation(Representation: TBoldRepresent begin case Representation of brShort: begin - Result := 'image/jpeg'; // do not localize + Result := 'image/jpeg'; end; else inherited GetStringRepresentation(Representation); @@ -2137,12 +3097,12 @@ function TBABlobImageJPEG.GetStringRepresentation(Representation: TBoldRepresent end; {-- TBABlobImageBMP --} -procedure TBABlobImageBMP.SetStringRepresentation(Representation: TBoldRepresentation; Value: string); +procedure TBABlobImageBMP.SetStringRepresentation(Representation: TBoldRepresentation; const Value: string); begin case Representation of brShort: begin if (Value <> '') and (Value <> ContentType) then - raise EBold.CreateFmt(sCannotAssignXtoY, [ClassName, Value, ContentType]); + raise EBold.CreateFmt('%s.SetStringRepresentation: Can not assign a ''%s'' to a ''%s''', [ClassName, Value, ContentType]); end; else inherited SetStringRepresentation(Representation, Value); @@ -2153,7 +3113,7 @@ function TBABlobImageBMP.GetStringRepresentation(Representation: TBoldRepresenta begin case Representation of brShort: begin - Result := 'image/bitmap'; // do not localize + Result := 'image/bitmap'; end; else inherited GetStringRepresentation(Representation); @@ -2163,14 +3123,14 @@ function TBABlobImageBMP.GetStringRepresentation(Representation: TBoldRepresenta function TBATypedBlob.ProxyInterface(const IId: TGUID; Mode: TBoldDomainElementProxyMode; out Obj): Boolean; begin if IsEqualGuid(IID, IBoldTypedBlob) then - Result := RetrieveProxyInterface(IID, Mode, obj, 'IBoldTypedBlob') // do not localize + Result := RetrieveProxyInterface(IID, Mode, obj, 'IBoldTypedBlob') else result := inherited ProxyInterface(IID, Mode, Obj); end; -function TBATypedBlob.ProxyClass: TBoldMember_ProxyClass; +function TBATypedBlob.GetProxy(Mode: TBoldDomainElementProxyMode): TBoldMember_Proxy; begin - result := TBATypedBlob_Proxy; + result := TBATypedBlob_Proxy.MakeProxy(self, mode); end; procedure TBATypedBlob.SetContentTypeContent(NewValue: String); @@ -2178,7 +3138,7 @@ procedure TBATypedBlob.SetContentTypeContent(NewValue: String); PreChange; FContentType := NewValue; SetToNonNull; - Changed(beValueChanged, [NewValue]); + Changed(beValueChanged, [AsStream.fData]); end; { TBAMoment } @@ -2186,15 +3146,24 @@ procedure TBATypedBlob.SetContentTypeContent(NewValue: String); procedure TBAMoment.SetDataValue(NewValue: TDateTime); begin BoldClearLastFailure; +{$IFDEF NoNegativeDates} + if IsPartOfSystem then + begin + if (NewValue < 0) then + BoldRaiseLastFailure(self, 'SetDataValue', 'Attempt to set date before 1899-12-30'); + if (NewValue >= 1000*365) then + BoldRaiseLastFailure(self, 'SetDataValue', 'Attempt to set date after 2899-12-30'); + end; +{$ENDIF} if not CanSetValue(NewValue, nil) then - BoldRaiseLastFailure(self, 'SetDataValue', ''); // do not localize + BoldRaiseLastFailure(self, 'SetDataValue', ''); if IsNull or (FValue <> NewValue) then begin if not StartModify then - BoldRaiseLastFailure(self, 'SetDataValue', ''); // do not localize + BoldRaiseLastFailure(self, 'SetDataValue', ''); try - SetContent(NewValue); + SetDateTimeContent(NewValue); EndModify; except FailModify; @@ -2205,30 +3174,41 @@ procedure TBAMoment.SetDataValue(NewValue: TDateTime); function TBAMoment.CanSetValue(NewValue: TDateTime; Subscriber: TBoldSubscriber): Boolean; begin - result := MaySetValue(NewValue, Subscriber) and - SendQuery(bqMaySetValue, [NewValue], Subscriber); + result := MaySetValue(NewValue, Subscriber); +{$IFNDEF BOLD_NO_QUERIES} + result := result and SendQuery(bqMaySetValue, [NewValue], Subscriber) +{$ENDIF} end; function TBAMoment.MaySetValue(NewValue: TDateTime; Subscriber: TBoldSubscriber): Boolean; begin - result := True; +{$IFDEF NoNegativeDates} + result := not IsPartOfSystem or ((NewValue >= 0) and (NewValue < 1000*365000)); +{$ELSE} + result := true; +{$ENDIF} end; function TBAMoment.GetAsDateTime: TDateTime; begin BoldClearLastFailure; if not CanRead(nil) then - BoldRaiseLastFailure(self, 'GetAsDateTime', ''); // do not localize + BoldRaiseLastFailure(self, 'GetAsDateTime', ''); EnsureNotNull; {ensures current} Result := FValue; end; +function TBAMoment.GetAsFloat: Double; +begin + Result := GetAsDateTime; +end; + function TBAMoment.GetAsDate: TDateTime; begin BoldClearLastFailure; if not CanRead(nil) then - BoldRaiseLastFailure(self, 'GetAsDate', ''); // do not localize + BoldRaiseLastFailure(self, 'GetAsDate', ''); EnsureNotNull; {ensures current} Result := Int(fValue);; end; @@ -2237,7 +3217,7 @@ function TBAMoment.GetAsTime: TDateTime; begin BoldClearLastFailure; if not CanRead(nil) then - BoldRaiseLastFailure(self, 'GetAsTime', ''); // do not localize + BoldRaiseLastFailure(self, 'GetAsTime', ''); EnsureNotNull; {ensures current} Result := frac(fValue); end; @@ -2247,6 +3227,11 @@ procedure TBAMoment.SetAsDateTime(Value: TDateTime); SetDataValue(Value); end; +procedure TBAMoment.SetAsInteger(Value: integer); +begin + SetAsDate(Value); +end; + procedure TBAMoment.SetAsDate(Value: TDateTime); begin if IsNull then @@ -2319,14 +3304,39 @@ function TBAMoment.CompareToAs(CompType: TBoldCompareType; BoldElement: TBoldEle Result := inherited CompareToAs(CompType, BoldElement); end; -procedure TBAMoment.SetContent(NewValue: TDateTime); +procedure TBAMoment.FreeContent; +begin + inherited; + FValue := 0; +end; + +procedure TBAMoment.SetDateTimeContent(NewValue: TDateTime); +var + bContentIsNull: Boolean; + sOldValue: TDateTime; begin - if ContentIsNull or (FValue <> NewValue) then +{$IFDEF NoNegativeDates} + if IsPartOfSystem then + begin + if NewValue < 0 then + raise EBoldInternal.Create('TBAMoment.SetContent setting a negative value. Should have been prevented by MaySetValue'); + if NewValue >=1000*365 then + raise EBoldInternal.Create('TBAMoment.SetContent setting a too big value. Should have been prevented by MaySetValue'); + end; +{$ENDIF} + bContentIsNull := ContentIsNull; + if (BoldPersistenceState = bvpsInvalid) or + ContentIsNull or (FValue <> NewValue) then begin PreChange; + sOldValue := fValue; FValue := NewValue; SetToNonNull; - Changed(beValueChanged, [NewValue]); + if bContentIsNull then begin + Changed(beValueChanged, [NewValue]); + end else begin + Changed(beValueChanged, [NewValue, sOldValue]); + end; end; end; @@ -2337,7 +3347,7 @@ function TBAMoment_Proxy.GetContentAsDate: TDateTime; procedure TBAMoment_Proxy.SetContentAsDate(NewValue: TDateTime); begin - ProxedMoment.SetContent(Int(NewValue) + GetContentAsTime); + ProxedMoment.SetDateTimeContent(Int(NewValue) + GetContentAsTime); end; function TBAMoment_Proxy.GetContentAsTime: TDateTime; @@ -2352,17 +3362,20 @@ function TBAMoment_Proxy.GetContentAsDateTime: TDateTime; procedure TBAMoment_Proxy.SetContentAsDateTime(NewValue: TDateTime); begin - ProxedMoment.SetContent(NewValue); + ProxedMoment.SetDateTimeContent(NewValue); end; procedure TBAMoment_Proxy.SetContentAsTime(NewValue: TDateTime); begin - ProxedMoment.SetContent(frac(NewValue) + GetContentAsDate); + ProxedMoment.SetDateTimeContent(frac(NewValue) + GetContentAsDate); end; procedure TBAMoment.SetEmptyValue; begin - SetAsDateTime(0); + if Assigned(BoldAttributeRTInfo) and not BoldAttributeRTInfo.AllowNull then + SetAsDateTime(0) + else + SetContentToNull; end; function TBAMoment.GetDays: Word; @@ -2407,17 +3420,69 @@ function TBAMoment.GetYears: Word; Result := Year; end; +function TBAMoment.IsEqualToValue(const Value: IBoldValue): Boolean; +var + vDateTime: IBoldDateTimeContent; + vDate: IBoldDateContent; + vTime: IBoldTimeContent; +begin + Assert(Assigned(Value), ClassName + '.IsEqualToValue: Value can not be nil.'); + if Value.QueryInterface(IBoldDateTimeContent, vDateTime) = S_OK then + begin + if Self.IsNull and vDateTime.IsNull then + result := true + else + if Self.IsNull or vDateTime.IsNull then + result := false + else + result := Self.asDateTime = vDateTime.asDateTime + end + else + if Value.QueryInterface(IBoldDateContent, vDate) = S_OK then + begin + if Self.IsNull and vDate.IsNull then + result := true + else + if Self.IsNull or vDate.IsNull then + result := false + else + result := Self.asDate = vDate.asDate + end + else + if Value.QueryInterface(IBoldTimeContent, vTime) = S_OK then + begin + if Self.IsNull and vTime.IsNull then + result := true + else + if Self.IsNull or vTime.IsNull then + result := false + else + result := Self.asTime = vTime.asTime + end + else + result := inherited IsEqualToValue(Value); +end; + +function TBAMoment.IsNullOrZero: boolean; +begin + result := isNull or (GetAsDateTime = 0); +end; + +function TBAMoment.IsVariantTypeCompatible(const Value: Variant): Boolean; +begin + result := (VarType(Value) in [varDate, varDouble, varInteger, varInt64]); +end; + { TBADateTime } -procedure TBADateTime.SetStringRepresentation(Representation: TBoldRepresentation; Value: string); +procedure TBADateTime.SetStringRepresentation(Representation: TBoldRepresentation; const Value: string); begin if not ValidateString(Value, Representation) then - BoldRaiseLastFailure(self, Meth_SetStringRepresentation, sStringValidationFailed); + BoldRaiseLastFailure(self, 'SetStringRepresentation', 'String validation failed'); if Representation = brDefault then - // FIXME: What if only date supplied? if Value = '' then SetToNull - else if upperCase(Value) = DEFAULTNOW then + else if upperCase(Value) = '' then SetDataValue(now) else SetDataValue(StrToDateTime(Value)) @@ -2437,15 +3502,15 @@ function TBADateTime.GetStringRepresentation(Representation: TBoldRepresentation function TBADateTime.ValidateCharacter(C: Char; Representation: TBoldRepresentation): Boolean; begin - Result := C in ['0'..'9', ' ', FormatSettings.TimeSeparator, FormatSettings.DateSeparator]; + Result := CharInSet(C, ['0'..'9', ' ', {$IFDEF BOLD_DELPHI16_OR_LATER}FormatSettings.{$ENDIF}TimeSeparator, {$IFDEF BOLD_DELPHI16_OR_LATER}FormatSettings.{$ENDIF}DateSeparator]); end; -function TBADateTime.ValidateString(Value: string; Representation: TBoldRepresentation): Boolean; +function TBADateTime.ValidateString(const Value: string; Representation: TBoldRepresentation): Boolean; begin try if value = '' then result := CanSetToNull(nil) - else if upperCase(Value) = DEFAULTNOW then + else if upperCase(Value) = '' then result := true else begin @@ -2454,19 +3519,19 @@ function TBADateTime.ValidateString(Value: string; Representation: TBoldRepresen end; except Result := False; - FormatFailure(value, 'datetime'); // do not localize + FormatFailure(value, 'datetime'); end; end; {---TBADate---} -procedure TBADate.SetStringRepresentation(Representation: TBoldRepresentation; Value: string); +procedure TBADate.SetStringRepresentation(Representation: TBoldRepresentation; const Value: string); begin if not ValidateString(Value, Representation) then - BoldRaiseLastFailure(self, Meth_SetStringRepresentation, sStringValidationFailed); + BoldRaiseLastFailure(self, 'SetStringRepresentation', 'String validation failed'); if Representation = brDefault then if Value = '' then SetToNull - else if upperCase(Value) = DEFAULTNOW then + else if upperCase(Value) = '' then SetDataValue(now) else try @@ -2489,15 +3554,15 @@ function TBADate.GetStringRepresentation(Representation: TBoldRepresentation): s function TBADate.ValidateCharacter(C: Char; Representation: TBoldRepresentation): Boolean; begin - Result := C in ['0'..'9', FormatSettings.DateSeparator]; + Result := CharInSet(C, ['0'..'9', {$IFDEF BOLD_DELPHI16_OR_LATER}FormatSettings.{$ENDIF}DateSeparator]); end; -function TBADate.ValidateString(Value: string; Representation: TBoldRepresentation): Boolean; +function TBADate.ValidateString(const Value: string; Representation: TBoldRepresentation): Boolean; begin try if value = '' then result := CanSetToNull(nil) - else if upperCase(Value) = DEFAULTNOW then + else if upperCase(Value) = '' then result := true else begin @@ -2506,19 +3571,19 @@ function TBADate.ValidateString(Value: string; Representation: TBoldRepresentati end; except Result := False; - FormatFailure(value, 'date'); // do not localize + FormatFailure(value, 'date'); end; end; {---TBATime---} -procedure TBATime.SetStringRepresentation(Representation: TBoldRepresentation; Value: string); +procedure TBATime.SetStringRepresentation(Representation: TBoldRepresentation; const Value: string); begin if not ValidateString(Value, Representation) then - BoldRaiseLastFailure(self, Meth_SetStringRepresentation, sStringValidationFailed); + BoldRaiseLastFailure(self, 'SetStringRepresentation', 'String validation failed'); if Representation = brDefault then if Value = '' then SetToNull - else if upperCase(Value) = DEFAULTNOW then + else if upperCase(Value) = '' then SetDataValue(now) else SetDataValue(StrToTime(Value)) @@ -2538,15 +3603,15 @@ function TBATime.GetStringRepresentation(Representation: TBoldRepresentation): s function TBATime.ValidateCharacter(C: Char; Representation: TBoldRepresentation): Boolean; begin - Result := C in ['0'..'9', FormatSettings.TimeSeparator]; + Result := CharInSet(C, ['0'..'9', {$IFDEF BOLD_DELPHI16_OR_LATER}FormatSettings.{$ENDIF}TimeSeparator]); end; -function TBATime.ValidateString(Value: string; Representation: TBoldRepresentation): Boolean; +function TBATime.ValidateString(const Value: string; Representation: TBoldRepresentation): Boolean; begin try if value = '' then result := CanSetToNull(nil) - else if upperCase(Value) = DEFAULTNOW then + else if upperCase(Value) = '' then result := true else begin @@ -2555,7 +3620,7 @@ function TBATime.ValidateString(Value: string; Representation: TBoldRepresentati end; except Result := False; - FormatFailure(value, 'time'); // do not localize + FormatFailure(value, 'time'); end; end; @@ -2582,9 +3647,10 @@ function TBAValueSetValue.GetStringRepresentation(Representation: TBoldRepresent Result := FStringRepresentations.Strings[Representation]; end; -procedure TBAValueSetValue.SetStringRepresentation(Representation: TBoldRepresentation; Value: string); +procedure TBAValueSetValue.SetStringRepresentation(Representation: TBoldRepresentation; const Value: string); begin - EnsureValidString(Value, Representation); + if not ValidateString(Value, Representation) then + BoldRaiseLastFailure(nil, 'SetStringRepresentation', 'String validation failed'); FStringRepresentations.Strings[Representation] := Value; end; @@ -2608,6 +3674,23 @@ function TBAValueSetValue.GetStringRepresentationCount: Integer; Result := FStringRepresentations.Count; end; +function TBAValueSetValue.CompareToAs(CompareType: TBoldCompareType; + BoldElement: TBoldElement): Integer; +begin + if BoldElement is TBAValueSetValue then + begin + if (TBAValueSetValue(BoldElement).AsInteger = AsInteger) then + Result := 0 + else + if AsInteger > TBAValueSetValue(BoldElement).AsInteger then + Result := 1 + else + Result := -1; + end + else + Result := inherited CompareToAs(CompareType, BoldElement); +end; + procedure TBAValueSetValue.DefaultSubscribe(Subscriber: TBoldSubscriber; RequestedEvent: TBoldEvent = breReEvaluate); begin if mutable then @@ -2620,9 +3703,10 @@ procedure TBAValueSetValue.GetAsList(ResultList: TBoldIndirectElement); end; {---TBAValueSetValueList---} + constructor TBAValueSetValueList.Create; begin - inherited; + inherited Create; FValueList := TList.Create; end; @@ -2675,28 +3759,38 @@ function TBAValueSetValueList.GetFirstValue: TBAValueSetValue; function TBAValueSetValueList.FindByString(Representation: TBoldRepresentation; Value: string): TBAValueSetValue; var - I: Integer; + i, j: Integer; + aValue: TBAValueSetValue; begin Result := nil; for I := 0 to FValueList.Count - 1 do - if CompareText(TBAValueSetValue(FValueList.Items[I]).StringRepresentation[Representation], Value) = 0 then - begin - Result := FValueList.Items[I]; - break; - end; + begin + aValue := TBAValueSetValue(FValueList.Items[I]); + for j := 0 to aValue.StringRepresentationCount - 1 do + if SameText(aValue.StringRepresentation[j], Value) then + begin + Result := FValueList.Items[I]; + exit; + end; + end; end; function TBAValueSetValueList.FindByText(Representation: TBoldRepresentation; Value: string): TBAValueSetValue; var - I: Integer; + i, j: Integer; + aValue: TBAValueSetValue; begin Result := nil; for I := 0 to FValueList.Count - 1 do - if AnsiCompareText(TBAValueSetValue(FValueList.Items[I]).StringRepresentation[Representation], Value) = 0 then - begin - Result := FValueList.Items[I]; - break; - end; + begin + aValue := TBAValueSetValue(FValueList.Items[I]); + for j := 0 to aValue.StringRepresentationCount - 1 do + if AnsiSameText(aValue.StringRepresentation[j], Value) then + begin + Result := FValueList.Items[I]; + exit; + end; + end; end; procedure TBAValueSetValueList.ToStrings(Representation: TBoldRepresentation; theStrings: TStrings); @@ -2715,33 +3809,39 @@ procedure TBAValueSetValueList.ToStringsWithNil end; -procedure TBADateTime.AssignValue(Source: IBoldValue); +procedure TBADateTime.AssignValue(const Source: IBoldValue); var s: IBoldDateTimeContent; begin if source.QueryInterface(IBoldDateTimeContent, S) = S_OK then SetDataValue(s.AsDateTime) else - raise EBold.CreateFmt(sUnknownTypeOfSource, [classname, Meth_AssignValue]); + raise EBold.CreateFmt('%s.AssignValue: unknown type of source', [classname]); +end; + +constructor TBADateTime.CreateWithValue(Value: TDateTime); +begin + inherited Create; + asDateTime := Value; end; -procedure TBADateTime.AssignContentValue(Source: IBoldValue); +procedure TBADateTime.AssignContentValue(const Source: IBoldValue); var s: IBoldDateTimeContent; begin if not assigned(source) and CanSetToNull(nil) then SetContentToNull else if not assigned(source) then - SetContent(0) + SetDateTimeContent(0) else if source.QueryInterface(IBoldDateTimeContent, S) = S_OK then begin if s.IsNull then SetContentToNull else - SetContent(s.AsDateTime) + SetDateTimeContent(s.AsDateTime) end else - raise EBold.CreateFmt(sUnknownTypeOfSource, [classname, Meth_AssignContentValue]); + raise EBold.CreateFmt('%s.AssignContentValue: unknown type of source', [classname]); end; function TBADateTime.ProxyInterface(const IId: TGUID; Mode: TBoldDomainElementProxyMode; out Obj): Boolean; @@ -2749,14 +3849,19 @@ function TBADateTime.ProxyInterface(const IId: TGUID; Mode: TBoldDomainElementPr if IsEqualGuid(IID, IBoldDateTimeContent) or IsEqualGuid(IID, IBoldDateContent) or IsEqualGuid(IID, IBoldTimeContent) then - Result := RetrieveProxyInterface(IID, Mode, obj, 'IBold[Date][Time]Content') // do not localize + Result := RetrieveProxyInterface(IID, Mode, obj, 'IBold[Date][Time]Content') else result := inherited ProxyInterface(IID, Mode, Obj); end; -function TBADateTime.ProxyClass: TBoldMember_ProxyClass; +function TBADateTime.GetFreeStandingClass: TBoldFreeStandingElementClass; begin - result := TBADateTime_Proxy; + result := TBFSDateTime; +end; + +function TBADateTime.GetProxy(Mode: TBoldDomainElementProxyMode): TBoldMember_Proxy; +begin + result := TBADateTime_Proxy.MakeProxy(self, mode); end; { TBAValueSet } @@ -2765,14 +3870,14 @@ procedure TBAValueSet.SetDataValue(NewValue: TBAValueSetValue); begin BoldClearLastFailure; if not CanSetValue(NewValue, nil) then - BoldRaiseLastFailure(self, 'SetDataValue', ''); // do not localize + BoldRaiseLastFailure(self, 'SetDataValue', ''); if not Assigned(NewValue) then - raise EBold.Create(sInvalidValue); + raise EBold.CreateFmt('%s: Invalid value', [ClassName]); - if IsNull or (FValue <> NewValue) then + if IsNull or not (FValue.IsEqual(NewValue)) then begin if not StartModify then - BoldRaiseLastFailure(self, 'SetDataValue', ''); // do not localize + BoldRaiseLastFailure(self, 'SetDataValue', ''); try SetContent(NewValue); EndModify; @@ -2787,19 +3892,24 @@ function TBAValueSet.GetStringRepresentation(Representation: TBoldRepresentation begin CheckIllegalValue; if IsNull then {IsNull ensures current} {IsNull checks MayRead} - Result := '' //FIXME: raise Exception? + Result := '' else Result := FValue.StringRepresentation[Representation]; end; -procedure TBAValueSet.SetStringRepresentation(Representation: TBoldRepresentation; Value: string); +class function TBAValueSet.GetValues: TBAValueSetValueList; +begin + result := nil; +end; + +procedure TBAValueSet.SetStringRepresentation(Representation: TBoldRepresentation; const Value: string); var ValueSetValue: TBAValueSetValue; begin if not ValidateString(Value, Representation) then - BoldRaiseLastFailure(self, Meth_SetStringRepresentation, sStringValidationFailed); + BoldRaiseLastFailure(self, 'SetStringRepresentation', 'String validation failed'); ValueSetValue := Values.FindByString(Representation, Value); - assert(assigned(ValueSetValue), sCannotFindValueSetValue); + assert(assigned(ValueSetValue), 'ValidateString said OK, but SetStringRepresentation can not find a valuesetvalue'); SetDataValue(ValueSetValue) end; @@ -2808,7 +3918,7 @@ function TBAValueSet.GetAsInteger: Integer; BoldClearLastFailure; CheckIllegalValue; if not CanRead(nil) then - BoldRaiseLastFailure(self, 'GetAsInteger', ''); // do not localize + BoldRaiseLastFailure(self, 'GetAsInteger', ''); EnsureNotNull; {ensures current} Result := FValue.AsInteger; end; @@ -2819,12 +3929,15 @@ procedure TBAValueSet.SetAsInteger(Value: Integer); SetDataValue(Values.FindByInteger(Value)); end; -function TBAValueSet.ValidateString(Value: string; Representation: TBoldRepresentation): Boolean; +function TBAValueSet.ValidateString(const Value: string; Representation: TBoldRepresentation): Boolean; var ValueSetvalue: TBAValueSetValue; strList: TStringList; Str: String; begin + result := false; + if Value = '' then + exit; ValueSetValue := Values.FindByString(Representation, Value); Result := Assigned(ValueSetvalue); @@ -2834,7 +3947,7 @@ function TBAValueSet.ValidateString(Value: string; Representation: TBoldRepresen try Values.ToStrings(Representation, strList); Str := BoldSeparateStringList(StrList, ', ', '(', ')'); - SetBoldLastFailureReason(TBoldFailureReason.CreateFmt(sUnknownStringValue, [Value, Str], self)); + SetBoldLastFailureReason(TBoldFailureReason.CreateFmt('Unknown stringvalue ''%s'', Allowed values: %s', [Value, Str], self)); finally StrList.Free; end; @@ -2885,14 +3998,42 @@ function TBAValueSet.CompareToAs(CompType: TBoldCompareType; BoldElement: TBoldE Result := inherited CompareToAs(CompType, BoldElement); end; end + else + if BoldElement is TBAValueSetValue then + begin + // Since TBAValueSetValue has no BoldType we compare both Integer and String values to make sure they are the same + if (AsInteger = TBAValueSetValue(BoldElement).AsInteger) and (TBAValueSetValue(BoldElement).AsString = AsString) then + Result := 0 + else + Result := -1; + end + else + if BoldElement is TBAInteger then + begin + // Since TBAValueSetValue has no BoldType we compare both Integer and String values to make sure they are the same + if (AsInteger = TBAInteger(BoldElement).AsInteger) {and (TBAValueSetValue(BoldElement).AsString = AsString)} then + Result := 0 + else + Result := -1; + end + else + if BoldElement is TBAString then + begin + if (AsString = TBAString(BoldElement).AsString) then + Result := 0 + else + Result := -1; + end else Result := inherited CompareToAs(CompType, BoldElement); end; function TBAValueSet.CanSetValue(NewValue: TBAValueSetValue; Subscriber: TBoldSubscriber): Boolean; begin - result := MaySetValue(NewValue, Subscriber) and - SendQuery(bqMaySetValue, [NewValue], Subscriber); + result := MaySetValue(NewValue, Subscriber); +{$IFNDEF BOLD_NO_QUERIES} + result := result and SendQuery(bqMaySetValue, [NewValue], Subscriber) +{$ENDIF} end; function TBAValueSet.MaySetValue(NewValue: TBAValueSetValue; @@ -2901,36 +4042,45 @@ function TBAValueSet.MaySetValue(NewValue: TBAValueSetValue; result := True; end; -procedure TBAValueSet.InitializeMember(OwningElement: TBoldDomainElement; - ElementTypeInfo: TBoldElementTypeInfo); +procedure TBAValueSet.Initialize; begin inherited; if not Assigned(Values) then - raise EBold.CreateFmt(sValuesNotInitialized, [ClassName]); + raise EBold.CreateFmt('%s: Values not properly initalized', [ClassName]); if assigned(values.FValueList) and (values.fValueList.count <> 0) then FValue := Values.GetFirstValue else setToNull; end; -procedure TBAValueSet.AssignValue(Source: IBoldValue); +procedure TBAValueSet.AssignValue(const Source: IBoldValue); var s: IBoldIntegerContent; begin if source.QueryInterface(IBoldIntegerContent, S) = S_OK then SetDataValue(Values.FindByInteger(s.AsInteger)) else - raise EBold.CreateFmt(sUnknownTypeOfSource, [classname, Meth_AssignValue]); + raise EBold.CreateFmt('%s.AssignValue: unknown type of source', [classname]); end; procedure TBAValueSet.SetContent(NewValue: TBAValueSetValue); +var + bContentIsNull: Boolean; + sOldValue: TBAValueSetValue; begin - if ContentIsNull or (FValue <> NewValue) then + bContentIsNull := ContentIsNull; + if (BoldPersistenceState = bvpsInvalid) or + bContentIsNull or not (fValue.IsEqual(NewValue)) then begin PreChange; - FValue := NewValue; + sOldValue := fValue; + fValue := NewValue; SetToNonNull; - Changed(beValueChanged, [NewValue]); + if bContentIsNull then begin + Changed(beValueChanged, [NewValue]); + end else begin + Changed(beValueChanged, [NewValue, sOldValue]); + end; end; end; @@ -2958,6 +4108,11 @@ function TBAValueSet.GetContentAsInteger: Integer; result := FValue.AsInteger; end; +function TBAValueSet.GetFreeStandingClass: TBoldFreeStandingElementClass; +begin + result := TBFSInteger; +end; + procedure TBAValueSet.SetContentAsInteger(NewValue: Integer); begin SetContent(Values.FindByInteger(NewValue)); @@ -2968,7 +4123,7 @@ procedure TBAValueSet_Proxy.SetContentAsInteger(NewValue: Integer); ProxedValueSet.ContentAsInteger:= NewValue; end; -procedure TBAValueSet.AssignContentValue(Source: IBoldValue); +procedure TBAValueSet.AssignContentValue(const Source: IBoldValue); var s: IBoldIntegerContent; begin @@ -2984,31 +4139,34 @@ procedure TBAValueSet.AssignContentValue(Source: IBoldValue); SetContent(Values.FindByInteger(s.AsInteger)) end else - raise EBold.CreateFmt(sUnknownTypeOfSource, [classname, Meth_AssignContentValue]); + raise EBold.CreateFmt('%s.AssignContentValue: unknown type of source', [classname]); end; function TBAValueSet.ProxyInterface(const IId: TGUID; Mode: TBoldDomainElementProxyMode; out Obj): Boolean; begin if IsEqualGuid(IID, IBoldIntegerContent) or IsEqualGuid(IID, IBoldStringContent) then - Result := RetrieveProxyInterface(IID, Mode, obj, 'IBoldString/IntegerContent') // do not localize + Result := RetrieveProxyInterface(IID, Mode, obj, 'IBoldString/IntegerContent') else result := inherited ProxyInterface(IID, Mode, Obj); end; -function TBAValueSet.ProxyClass: TBoldMember_ProxyClass; +function TBAValueSet.GetProxy(Mode: TBoldDomainElementProxyMode): TBoldMember_Proxy; begin - result := TBAValueSet_Proxy; + result := TBAValueSet_Proxy.MakeProxy(self, mode); end; procedure TBAValueSet.SetEmptyValue; begin if Values.Count > 0 then - AsInteger := Values[0].AsInteger + begin + if AsInteger <> Values.GetFirstValue.AsInteger then + AsInteger := Values.GetFirstValue.AsInteger + end else if not assigned(BoldAttributeRTInfo) or BoldAttributeRTInfo.AllowNull then SetToNull else - raise EBold.CreateFmt(sNoLegalValuesAvailable, [classname, '']); //FIXME: Missing parameter + raise EBold.CreateFmt('%s.SetEmptyValue: There are no legal values, and null is not allowed for this attribute (%s)', [classname, '']); end; procedure TBAValueSet.CheckIllegalValue; @@ -3016,9 +4174,9 @@ procedure TBAValueSet.CheckIllegalValue; if not IsNull and not Assigned(FValue) then begin if BoldPersistenceState = bvpsCurrent then - raise EBold.Create(sBadDataInDB) + raise EBold.Create('Illegal value in valueset. Bad data in database?') else - raise EBold.Create(sCannotRead) + raise EBold.Create('Illegal value in valueset. Cannot read.') end; end; @@ -3029,12 +4187,25 @@ function TBAValueSet.CompareToEnumLiteral(const str: String): Boolean; BoldExpandName(AsString, '', xtExpression, -1, nccTrue)) end; +procedure TBAValueSet.FreeContent; +begin + inherited; + if Values.Count > 0 then + fValue := Values.GetFirstValue; +end; + { TBABoolean } +constructor TBABoolean.CreateWithValue(Value: Boolean); +begin + inherited Create; + AsBoolean := Value; +end; + function TBABoolean.GetAsBoolean: Boolean; begin BoldClearLastFailure; if not CanRead(nil) then - BoldRaiseLastFailure(self, 'GetAsBoolean', ''); // do not localize + BoldRaiseLastFailure(self, 'GetAsBoolean', ''); EnsureNotNull; {ensures current} Result := Boolean(GetContentAsInteger); end; @@ -3044,127 +4215,182 @@ procedure TBABoolean.SetAsBoolean(Value: Boolean); SetAsInteger(Integer(Value)); end; -function TBABoolean.GetValues: TBAValueSetValueList; +class function TBABoolean.GetValues: TBAValueSetValueList; begin if not Assigned(_BooleanValues) then begin _BooleanValues := TBAValueSetValueList.Create; + //representation 1 2 3 + //--------------------------------------------- _BooleanValues.Add(Ord(False), ['N', 'F', 'False']); // do not localize _BooleanValues.Add(Ord(True), ['Y', 'T', 'True']); // do not localize +{ + _BooleanValues.Add(Ord(False), ['F', 'F', 'False']); + _BooleanValues.Add(Ord(False), ['False','F', 'False']); + _BooleanValues.Add(Ord(False), ['N', 'F', 'False']); + _BooleanValues.Add(Ord(True), ['T', 'T', 'True']); + _BooleanValues.Add(Ord(True), ['True', 'T', 'True']); + _BooleanValues.Add(Ord(True), ['Y', 'T', 'True']); +} end; Result := _BooleanValues; end; +function TBABoolean.IsEqualToValue(const Value: IBoldValue): Boolean; +var + vBoolean: IBoldBooleanContent; +begin + Assert(Assigned(Value), ClassName + '.IsEqualToValue: Value can not be nil.'); + if Value.QueryInterface(IBoldBooleanContent, vBoolean) = S_OK then + begin + if IsNull and vBoolean.IsNull then + result := true + else + if IsNull or vBoolean.IsNull then + result := false + else + result := Self.AsBoolean = vBoolean.asBoolean; + end + else + result := inherited IsEqualToValue(Value); +end; + +function TBABoolean.IsVariantTypeCompatible(const Value: Variant): Boolean; +begin + result := (VarType(Value) in [varBoolean]); +end; + function TBAInteger.GetAsVariant: Variant; begin - Result := AsInteger; + if IsNull then + Result := Null + else + Result := AsInteger; +end; + +function TBAInteger.GetFreeStandingClass: TBoldFreeStandingElementClass; +begin + result := TBFSInteger; end; procedure TBAInteger.SetAsVariant(const Value: Variant); begin - AsInteger := Value; + if IsVariantTypeCompatible(Value) then + AsInteger := Value + else + inherited SetAsVariant(Value); end; function TBAFloat.GetAsVariant: Variant; begin - Result := AsFloat; + if IsNull then + Result := Null + else + Result := AsFloat; +end; + +function TBAFloat.GetFreeStandingClass: TBoldFreeStandingElementClass; +begin + result := TBFSFloat; end; procedure TBAFloat.SetAsVariant(const Value: Variant); begin - AsFloat := Value; + if IsVariantTypeCompatible(Value) then + AsFloat := Value + else + inherited SetAsVariant(Value); end; function TBACurrency.GetAsVariant: Variant; begin - Result := AsCurrency; + if IsNull then + Result := Null + else + Result := AsCurrency; end; -procedure TBACurrency.SetAsVariant(const Value: Variant); +function TBACurrency.GetFreeStandingClass: TBoldFreeStandingElementClass; begin - AsCurrency := Value; + result := TBFSCurrency; end; -function TBABlob.GetAsVariant: Variant; -var - P: Pointer; - Data: string; - Size: Integer; +procedure TBACurrency.SetAsVariant(const Value: Variant); begin - // return byte array - Data := GetAsBlob; - Size := Length(Data); - if Size > 0 then - begin - Result := VarArrayCreate([0, Size], varByte); - P := VarArrayLock(Result); - try - Move(Pointer(Data)^, P^, Size); - finally - VarArrayUnlock(Result); - end; - end + if IsVariantTypeCompatible(Value) then + AsCurrency := Value else - Result := Null; + inherited SetAsVariant(Value); end; -procedure TBABlob.SetAsVariant(const Value: Variant); -var - P: Pointer; - Data: string; - Size: Integer; +function TBAMoment.GetAsVariant: Variant; begin - if VarIsArray(Value) and ((VarType(Value) and varTypeMask) = varByte) and - (VarArrayDimCount(Value) = 1) then - begin - Size := VarArrayHighBound(Value, 1); - SetLength(Data, Size); - P := VarArrayLock(Value); - try - Move(P^, Pointer(Data)^, Size); - finally - VarArrayUnlock(Value); - end; - SetAsBlob(Data); - end - else if VarIsNull(Value) then - begin - SetAsBlob(''); - end + if IsNull then + Result := Null else - begin - SetAsBlob(Value); - end; + Result := GetAsDateTime; end; -function TBAMoment.GetAsVariant: Variant; +function TBAMoment.GetAttributeTypeInfoForType: TBoldElementTypeInfo; begin - Result := GetAsDateTime; + if not Assigned(AttributeTypeInfo) then + begin + AttributeTypeInfo := inherited GetAttributeTypeInfoForType; + SubscribeToSystem; + end; + result := AttributeTypeInfo; end; procedure TBAMoment.SetAsVariant(const Value: Variant); begin - SetAsDateTime(Value); + if IsVariantTypeCompatible(Value) then + SetAsDateTime(Value) + else + inherited SetAsVariant(Value); end; function TBAValueSet.GetAsVariant: Variant; begin - Result := AsInteger; + if IsNull then + Result := Null + else + Result := AsString; +end; + +function TBAValueSet.GetAttributeTypeInfoForType: TBoldElementTypeInfo; +begin + if not Assigned(AttributeTypeInfo) then + begin + AttributeTypeInfo := inherited GetAttributeTypeInfoForType; + SubscribeToSystem; + end; + result := AttributeTypeInfo; end; procedure TBAValueSet.SetAsVariant(const Value: Variant); begin - AsInteger := Value; + AsString := Value; end; function TBABoolean.GetAsVariant: Variant; begin - Result := AsBoolean; + if IsNull then + Result := Null + else + Result := AsBoolean; +end; + +function TBABoolean.GetFreeStandingClass: TBoldFreeStandingElementClass; +begin + result := TBFSBoolean; end; procedure TBABoolean.SetAsVariant(const Value: Variant); begin - AsBoolean := Value; + if IsVariantTypeCompatible(Value) then + AsBoolean := Value + else + inherited SetAsVariant(Value); end; function TBAValueSetValueList.GetCount: integer; @@ -3183,24 +4409,36 @@ function TBAValueSetValue.GetBoldType: TBoldElementTypeInfo; result := nil; end; -procedure TBADate.AssignValue(Source: IBoldValue); +procedure TBADate.AssignValue(const Source: IBoldValue); var s: IBoldDateContent; begin if source.QueryInterface(IBoldDateContent, S) = S_OK then SetDataValue(s.AsDate) else - raise EBold.CreateFmt(sUnknownTypeOfSource, [classname, Meth_AssignValue]); + raise EBold.CreateFmt('%s.AssignValue: unknown type of source', [classname]); +end; + +constructor TBADate.CreateWithValue(Value: TDateTime); +begin + inherited Create; + asDate := Value; end; -procedure TBATime.AssignValue(Source: IBoldValue); +procedure TBATime.AssignValue(const Source: IBoldValue); var s: IBoldTimeContent; begin if source.QueryInterface(IBoldTimeContent, S) = S_OK then SetDataValue(s.AsTime) else - raise EBold.CreateFmt(sUnknownTypeOfSource, [classname, Meth_AssignValue]); + raise EBold.CreateFmt('%s.AssignValue: unknown type of source', [classname]); +end; + +constructor TBATime.CreateWithValue(Value: TDateTime); +begin + inherited Create; + AsTime := Value; end; function TBABoolean_Proxy.GetContentAsBoolean: Boolean; @@ -3213,45 +4451,45 @@ procedure TBABoolean_Proxy.SetContentAsBoolean(NewValue: Boolean); SetContentAsInteger(Integer(NewValue)); end; -procedure TBADate.AssignContentValue(Source: IBoldValue); +procedure TBADate.AssignContentValue(const Source: IBoldValue); var s: IBoldDateContent; begin if not assigned(source) and CanSetToNull(nil) then SetContentToNull else if not assigned(source) then - SetContent(0) + SetDateTimeContent(0) else if source.QueryInterface(IBoldDateContent, S) = S_OK then begin if s.IsNull then SetContentToNull else - SetContent(s.AsDate) + SetDateTimeContent(s.AsDate) end else - raise EBold.CreateFmt(sUnknownTypeOfSource, [classname, Meth_AssignContentValue]); + raise EBold.CreateFmt('%s.AssignContentValue: unknown type of source', [classname]); end; -procedure TBATime.AssignContentValue(Source: IBoldValue); +procedure TBATime.AssignContentValue(const Source: IBoldValue); var s: IBoldTimeContent; begin if not assigned(source) and CanSetToNull(nil) then SetContentToNull else if not assigned(source) then - SetContent(0) + SetDateTimeContent(0) else if source.QueryInterface(IBoldTimeContent, S) = S_OK then begin if s.IsNull then SetContentToNull else - SetContent(s.AsTime) + SetDateTimeContent(s.AsTime) end else - raise EBold.CreateFmt(sUnknownTypeOfSource, [classname, Meth_AssignContentValue]); + raise EBold.CreateFmt('%s.AssignContentValue: unknown type of source', [classname]); end; -procedure TBABoolean.AssignContentValue(Source: IBoldValue); +procedure TBABoolean.AssignContentValue(const Source: IBoldValue); var s: IBoldBooleanContent; begin @@ -3273,16 +4511,17 @@ procedure TBABoolean.AssignContentValue(Source: IBoldValue); function TBABoolean.ProxyInterface(const IId: TGUID; Mode: TBoldDomainElementProxyMode; out Obj): Boolean; begin if IsEqualGuid(IID, IBoldBooleanContent) then - Result := RetrieveProxyInterface(IID, Mode, obj, 'IBoldBooleanContent') // do not localize + Result := RetrieveProxyInterface(IID, Mode, obj, 'IBoldBooleanContent') else result := inherited ProxyInterface(IID, Mode, Obj); end; -function TBABoolean.ProxyClass: TBoldMember_ProxyClass; +function TBABoolean.GetProxy(Mode: TBoldDomainElementProxyMode): TBoldMember_Proxy; begin - result := TBABoolean_Proxy; + result := TBABoolean_Proxy.MakeProxy(self, mode); end; + { TBAConstraint } procedure TBAConstraint.DefaultSubscribe(Subscriber: TBoldSubscriber; RequestedEvent: TBoldEvent = breReEvaluate); @@ -3312,7 +4551,7 @@ procedure TBAConstraint.CalculateConstraint; asBoolean := false; end; -destructor TBAConstraint.Destroy; +destructor TBAConstraint.destroy; begin FreeAndNil(fElementSubscriber); inherited; @@ -3331,7 +4570,21 @@ function TBAConstraint.GetStringRepresentation(Representation: TBoldRepresentati 10: if assigned(constraint) then result := Constraint.ModelName; 11: if assigned(constraint) then - result := Constraint.ConstraintMessage; + begin + {$IFDEF OCLConstraintMessages} + if (OwningElement is TBoldDomainElement) then + begin + if Assigned(OwningElement.Evaluator.ExpressionType(Constraint.ConstraintMessage, OwningElement.BoldType, false)) then + result := TBoldDomainElement(OwningElement).EvaluateExpressionAsString(Constraint.ConstraintMessage, brDefault) + else + result := Constraint.ConstraintMessage; + end + else + {$ENDIF} + begin + result := Constraint.ConstraintMessage; + end; + end; 12: if assigned(constraint) then result := Constraint.ConstraintExpression; 13: if Owningelement is TBoldDomainElement then @@ -3343,9 +4596,16 @@ function TBAConstraint.GetStringRepresentation(Representation: TBoldRepresentati end; end; -procedure TBAConstraint.Initialize(Constraint: TBoldConstraintRTInfo; OwningElement: TBoldElement); +procedure TBAConstraint.InitializeConstraint(Constraint: TBoldConstraintRTInfo; OwningElement: TBoldElement); var ResType: TBoldElementTypeInfo; +const + sInvalidConstraint = 'Invalid Constraint: %s %s%s'; + sInvalidConstraintMessage = 'Invalid Constraint message: %s %s%s'; + sUnknownConstraintType = 'unknown type of constraint expression: %s (in context: %s)'; + sUnknownConstraintMessageType = 'unknown type of constraint message: %s (in context: %s)'; + sConstraintNotBoolean = 'Constraint is not Boolean: %s (in context %s)'; + sConstraintMessageString = 'Constraint message is not String: %s (in context %s)'; begin fOwningElement := OwningElement; if assigned(fOwningElement) then @@ -3357,18 +4617,38 @@ procedure TBAConstraint.Initialize(Constraint: TBoldConstraintRTInfo; OwningElem resType := Owningelement.Evaluator.ExpressionType(Constraint.ConstraintExpression, OwningElement.BoldType, true); except on e: Exception do - raise EBold.CreateFmt(sInvalidConstraint, [Constraint.ConstraintExpression, BOLDCRLF, e.message]); + raise EBold.CreateFmt('Invalid Constraint: %s ' + BOLDCRLF + '%s', [Constraint.ConstraintExpression, e.message]); end; if not assigned(ResType) then - raise EBold.CreateFmt(sUnknownConstraintType, [Constraint.ConstraintExpression, OwningElement.BoldType.AsString]); + raise EBold.CreateFmt('unknown type of constraint expression: %s (in context: %s)', [Constraint.ConstraintExpression, OwningElement.BoldType.AsString]); if not ResType.ConformsTo((BoldType.SystemTypeInfo as TboldSystemTypeInfo).AttributeTypeInfoByDelphiName[TBABoolean.ClassName]) then - raise EBold.CreateFmt(sConstraintNotBoolean, [Constraint.ConstraintExpression, OwningElement.BoldType.AsString]); + raise EBold.CreateFmt('Constraint is not Boolean: %s (in context %s)', [Constraint.ConstraintExpression, OwningElement.BoldType.AsString]); + + {$IFDEF OCLConstraintMessages} + if Constraint.ConstraintMessage <> '' then + begin + try + resType := Owningelement.Evaluator.ExpressionType(Constraint.ConstraintMessage, OwningElement.BoldType, false); + if not Assigned(resType) then + resType := Owningelement.Evaluator.ExpressionType(QuotedStr(Constraint.ConstraintMessage), OwningElement.BoldType, false); + except + on e: Exception do + raise EBold.CreateFmt(sInvalidConstraintMessage, [Constraint.ConstraintMessage, TBoldDomainElement(OwningElement).DisplayName, e.message]); + end; + + if not assigned(ResType) then + raise EBold.CreateFmt(sUnknownConstraintMessageType, [Constraint.ConstraintMessage, OwningElement.BoldType.AsString]); + + if not ResType.ConformsTo((BoldType.SystemTypeInfo as TboldSystemTypeInfo).AttributeTypeInfoByDelphiName[TBAString.ClassName]) then + raise EBold.CreateFmt(sConstraintMessageString, [Constraint.ConstraintMessage, OwningElement.BoldType.AsString]); + end; + {$ENDIF} end; end; -procedure TBAConstraint.InitializeMember(OwningElement: TBoldDomainElement; ElementTypeInfo: TBoldElementTypeInfo); +procedure TBAConstraint.Initialize; begin inherited; fElementSubscriber := TBoldPassthroughSubscriber.Create(Receive); @@ -3389,7 +4669,16 @@ procedure TBAConstraint.SubscribeToStringRepresentation( RequestedEvent: TBoldEvent = breReEvaluate); begin case Representation of - 10..13: ; // do nothing, static values... + 10: ; // do nothing, static values... + 11: + {$IFDEF OCLConstraintMessages} + if assigned(OwningElement) and (Constraint.ConstraintMessage <> '') then + begin + if Assigned(OwningElement.Evaluator.ExpressionType(Constraint.ConstraintMessage, OwningElement.BoldType, false)) then + OwningElement.SubscribeToExpression(Constraint.ConstraintMessage, Subscriber, RequestedEvent = breReSubscribe); + end + {$ENDIF}; + 12..13: ; // do nothing, static values... 14: if assigned(OwningElement) then OwningElement.SubscribeToStringRepresentation(brDefault, Subscriber, RequestedEvent); else inherited; @@ -3400,49 +4689,71 @@ procedure TBAConstraint.Assign(Source: TBoldElement); begin inherited; if Source is TBAConstraint then - Initialize(TBAConstraint(Source).Constraint, TBAConstraint(Source).OwningElement); + InitializeConstraint(TBAConstraint(Source).Constraint, TBAConstraint(Source).OwningElement); end; { TBAString_Proxy } function TBAString_Proxy.GetProxedString: TBAString; begin - result := ProxedElement as TBAString; + result := ProxedMember as TBAString; +end; + +class function TBAString_Proxy.MakeProxy(ProxedMember: TBoldMember; + Mode: TBoldDomainElementProxyMode): TBoldMember_Proxy; +begin + Result := fLastUsed[Mode]; + // Reuse proxy if we hold only reference + if Assigned(Result) and (Result.RefCount =1) then + begin + Result.Retarget(ProxedMember, Mode); + end + else + begin + Result := Create(ProxedMember, Mode); + fLastUsed[Mode] := Result; + fLastUsedAsInterface[Mode] := Result; // Inc refcount + end; end; { TBAInteger_Proxy } function TBAInteger_Proxy.GetProxedInteger: TBAInteger; begin - result := ProxedElement as TBAInteger; + result := ProxedMember as TBAInteger; end; { TBAFloat_Proxy } function TBAFloat_Proxy.GetProxedFloat: TBAFloat; begin - result := ProxedElement as TBAFloat; + result := ProxedMember as TBAFloat; end; { TBACurrency_Proxy } function TBACurrency_Proxy.GetProxedCurrency: TBACurrency; begin - result := ProxedElement as TBACurrency; + result := ProxedMember as TBACurrency; end; { TBABlob_Proxy } function TBABlob_Proxy.GetProxedBlob: TBABlob; begin - result := ProxedElement as TBABlob; + result := ProxedMember as TBABlob; +end; + +function TBABlob_Proxy.SupressEvents: Boolean; +begin + result := ProxedBlob.SupressEvents; end; { TBAValueSet_Proxy } function TBAValueSet_Proxy.GetProxedvalueSet: TBAValueSet; begin - result := ProxedElement as TBAValueSet; + result := ProxedMember as TBAValueSet; end; { TBABoolean_Proxy } @@ -3450,7 +4761,7 @@ function TBAValueSet_Proxy.GetProxedvalueSet: TBAValueSet; function TBADate.ProxyInterface(const IId: TGUID; Mode: TBoldDomainElementProxyMode; out Obj): Boolean; begin if IsEqualGuid(IID, IBoldDateContent) then - Result := RetrieveProxyInterface(IID, Mode, obj, 'IBoldDateContent') // do not localize + Result := RetrieveProxyInterface(IID, Mode, obj, 'IBoldDateContent') else result := inherited ProxyInterface(IID, Mode, Obj); end; @@ -3458,19 +4769,24 @@ function TBADate.ProxyInterface(const IId: TGUID; Mode: TBoldDomainElementProxyM function TBATime.ProxyInterface(const IId: TGUID; Mode: TBoldDomainElementProxyMode; out Obj): Boolean; begin if IsEqualGuid(IID, IBoldTimeContent) then - Result := RetrieveProxyInterface(IID, Mode, obj, 'IBoldTimeContent') // do not localize + Result := RetrieveProxyInterface(IID, Mode, obj, 'IBoldTimeContent') else result := inherited ProxyInterface(IId, Mode, Obj); end; -function TBADate.ProxyClass: TBoldMember_ProxyClass; +function TBADate.GetFreeStandingClass: TBoldFreeStandingElementClass; +begin + result := TBFSDate; +end; + +function TBADate.GetProxy(Mode: TBoldDomainElementProxyMode): TBoldMember_Proxy; begin - result := TBADate_Proxy; + result := TBADate_Proxy.MakeProxy(self, mode); end; -function TBATime.ProxyClass: TBoldMember_ProxyClass; +function TBATime.GetProxy(Mode: TBoldDomainElementProxyMode): TBoldMember_Proxy; begin - result := TBATime_Proxy; + result := TBATime_Proxy.MakeProxy(self, mode); end; { TBATypedBlob_Proxy } @@ -3482,7 +4798,7 @@ function TBATypedBlob_Proxy.GetContentTypeContent: String; function TBATypedBlob_Proxy.GetProxedTypedBlob: TBATypedBlob; begin - result := ProxedElement as TBATypedBlob; + result := ProxedMember as TBATypedBlob; end; procedure TBATypedBlob_Proxy.SetContentTypeContent(const NewValue: String); @@ -3492,7 +4808,7 @@ procedure TBATypedBlob_Proxy.SetContentTypeContent(const NewValue: String); function TBAMoment_Proxy.GetProxedMoment: TBAMoment; begin - result := ProxedElement as TBAMoment; + result := ProxedMember as TBAMoment; end; function TBATime.GetAsSeconds: cardinal; @@ -3500,11 +4816,20 @@ function TBATime.GetAsSeconds: cardinal; Result := Seconds + (Minutes * 60) + (Hours * 3600); end; +function TBATime.GetFreeStandingClass: TBoldFreeStandingElementClass; +begin + result := TBFSTime; +end; + initialization with BoldMemberTypes do begin AddMemberTypeDescriptor(TBoldAttribute, alAbstract); AddMemberTypeDescriptor(TBAString, alConcrete); + AddMemberTypeDescriptor(TBAAnsiString, alConcrete); + AddMemberTypeDescriptor(TBAUnicodeString, alConcrete); + AddMemberTypeDescriptor(TBAText, alConcrete); + AddMemberTypeDescriptor(TBAUnicodeText, alConcrete); AddMemberTypeDescriptor(TBATrimmedString, alConcrete); AddMemberTypeDescriptor(TBANumeric, alAbstract); AddMemberTypeDescriptor(TBAInteger, alConcrete); @@ -3528,12 +4853,17 @@ initialization end; finalization - FreeAndNil(_BooleanValues); + FreeAndNil(TBABoolean._BooleanValues); + FreeAndNil(_SystemSubscriber); if BoldMemberTypesAssigned then with BoldMemberTypes do begin RemoveDescriptorByClass(TBoldAttribute); RemoveDescriptorByClass(TBAString); + RemoveDescriptorByClass(TBAAnsiString); + RemoveDescriptorByClass(TBAUnicodeString); + RemoveDescriptorByClass(TBAText); + RemoveDescriptorByClass(TBAUnicodeText); RemoveDescriptorByClass(TBATrimmedString); RemoveDescriptorByClass(TBANumeric); RemoveDescriptorByClass(TBAInteger); @@ -3557,4 +4887,3 @@ finalization end; end. - diff --git a/Source/ObjectSpace/BORepresentation/BoldDerivedValueSet.pas b/Source/ObjectSpace/BORepresentation/BoldDerivedValueSet.pas index 56475a1..5509b60 100644 --- a/Source/ObjectSpace/BORepresentation/BoldDerivedValueSet.pas +++ b/Source/ObjectSpace/BORepresentation/BoldDerivedValueSet.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldDerivedValueSet; interface @@ -23,7 +26,6 @@ implementation uses SysUtils, BoldDefs, - BoldCoreConsts, BoldSystemRT; procedure TBADerivedValueSetValueList.AddMembers(Int: Integer; Members: Array of TBoldMember); @@ -51,13 +53,13 @@ constructor TBADerivedValueSetValueList.create(System: TBoldSystem; ClassToFollo ClassTypeInfo := System.BoldSystemTypeInfo.ClassTypeInfoByExpressionName[ClassToFollow]; if not assigned(ClassTypeInfo) then - raise Ebold.createFmt(sNoClassCalledX, [ClassName, ClassToFollow]); + raise Ebold.createFmt('%s.create: No class called %s', [ClassName, ClassToFollow]); RTAttr := ClassTypeInfo.MemberRTInfoByExpressionName[IntValueAttribute]; if not assigned(RTAttr) then - raise Ebold.createFmt(sNoAttributeCalledX, [ClassName, ClassToFollow, IntValueAttribute]); + raise Ebold.createFmt('%s.create: No attribute called %s.%s', [ClassName, ClassToFollow, IntValueAttribute]); if not RTAttr.MemberClass.InheritsFrom(TBAInteger) then - raise Ebold.createFmt(sXIsNotAnInteger, [ClassName, ClassToFollow, IntValueAttribute]); + raise Ebold.createFmt('%s.create: %s.%s is not an integer', [ClassName, ClassToFollow, IntValueAttribute]); IntIndex := RTAttr.Index; @@ -68,16 +70,16 @@ constructor TBADerivedValueSetValueList.create(System: TBoldSystem; ClassToFollo begin RTAttr := ClassTypeInfo.MemberRTInfoByExpressionName[StrValueAttributes[i]]; if not assigned(RTAttr) then - raise Ebold.createFmt(sNoAttributeCalledX, [ClassName, ClassToFollow, StrValueAttributes[i]]); + raise Ebold.createFmt('%s.create: No attribute called %s.%s', [ClassName, ClassToFollow, StrValueAttributes[i]]); if not RTAttr.MemberClass.InheritsFrom(TBoldAttribute) then - raise Ebold.createFmt(sXIsNotAnAttribute, [ClassName, ClassToFollow, StrValueAttributes[i]]); + raise Ebold.createFmt('%s.create: %s.%s is not an Attribute', [ClassName, ClassToFollow, StrValueAttributes[i]]); IndexArr[i] := RTAttr.Index; end; ObjectList := System.Classes[ClassTypeInfo.TopSortedIndex]; if objectlist.count = 0 then - raise EBold.CreateFmt(sNoValuesInValueSetList, [Classname, ClassTypeInfo.ExpressionName]); + raise EBold.CreateFmt('%s.Create: No values in valuesetlist: %s', [Classname, ClassTypeInfo.ExpressionName]); for i := 0 to ObjectList.count - 1 do begin for j := 0 to High(StrValueAttributes) do @@ -86,4 +88,6 @@ constructor TBADerivedValueSetValueList.create(System: TBoldSystem; ClassToFollo end; end; +initialization + end. diff --git a/Source/ObjectSpace/BORepresentation/BoldDomainElement.pas b/Source/ObjectSpace/BORepresentation/BoldDomainElement.pas index 15ed0db..fbd71ef 100644 --- a/Source/ObjectSpace/BORepresentation/BoldDomainElement.pas +++ b/Source/ObjectSpace/BORepresentation/BoldDomainElement.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldDomainElement; interface @@ -11,13 +14,12 @@ interface type {forward declarations of all classes} TBoldDomainElementProxyMode = ( - bdepContents, // actual contents of member -// bDepObjectSpace, // the "fronside" inteferace, not used yet - bdepPMOut, // Interface to Persistence mapper - bdepPMIn, // Interface from Persistence mapper - bdepUnDo, //Interface To/From UnDo-handler - bdepInternalInitialize, // - bdRemove // ... + bdepContents, + bdepPMOut, + bdepPMIn, + bdepUnDo, + bdepInternalInitialize, + bdRemove ); type TBoldDomainElement = class; @@ -31,54 +33,64 @@ TBoldDomainElement = class(TBoldElement) private FOwningElement: TBoldDomainElement; protected - function GetDisplayName: String; virtual; abstract; + function GetDisplayName: String; override; function GetBoldDirty: Boolean; virtual; abstract; function MayCommit: Boolean; virtual; - procedure ReceiveEventFromOwned(Originator: TObject; OriginalEvent: TBoldEvent); virtual; + function GetBoldSystem: TBoldDomainElement; virtual; + procedure ReceiveEventFromOwned(Originator: TObject; OriginalEvent: TBoldEvent; const Args: array of const); virtual; +{$IFNDEF BOLD_NO_QUERIES} function ReceiveQueryFromOwned(Originator: TObject; OriginalEvent: TBoldEvent; const Args: array of const; Subscriber: TBoldSubscriber): Boolean; virtual; +{$ENDIF} procedure StateError(S: string); virtual; public - constructor Create(OwningElement: TBoldDomainElement); virtual; + constructor CreateWithOwner(OwningElement: TBoldDomainElement); virtual; function ProxyInterface(const IId: TGUID; Mode: TBoldDomainElementProxyMode; out Obj): Boolean; virtual; + procedure Discard; virtual; abstract; + procedure Invalidate; virtual; function CanCommit: Boolean; procedure SendEvent(OriginalEvent: TBoldEvent); override; procedure SendExtendedEvent(OriginalEvent: TBoldEvent; const Args: array of const); override; - function SendQuery(OriginalEvent: TBoldEvent; const Args: array of const; Subscriber: TBoldSubscriber): Boolean; override; +{$IFNDEF BOLD_NO_QUERIES} + function SendQuery(OriginalEvent: TBoldEvent; const Args: array of const; Subscriber: TBoldSubscriber; Originator: TObject = nil): Boolean; override; +{$ENDIF} property BoldDirty: Boolean read GetBoldDirty; property BoldPersistent: Boolean index befPersistent read GetElementFlag; property OwningElement: TBoldDomainElement read FOwningElement; - property DisplayName: String read GetDisplayName; + property BoldSystem: TBoldDomainElement read GetBoldSystem; end; { TBoldDomainElement_Proxy } TBoldDomainElement_Proxy = class(TBoldRefCountedObject) private fMode: TBoldDomainElementProxyMode; - fProxedElement: TBoldDomainElement; protected procedure UnsupportedMode(Mode: TBoldDomainElementProxyMode; Func: string); + procedure Retarget(Mode: TBoldDomainElementProxyMode); {$IFDEF BOLD_INLINE} inline; {$ENDIF} public - constructor Create(ProxedElement: TBoldDomainElement; Mode: TBoldDomainElementProxyMode); - property ProxedElement: TBoldDomainElement read fProxedElement; + constructor Create(Mode: TBoldDomainElementProxyMode); property Mode: TBoldDomainElementProxyMode read fMode; end; { TBoldDomainElementCollectionTraverser } TBoldDomainElementCollectionTraverser = class(TBoldIndexableListTraverser) private - function GetItem: TBoldDomainElement; + function GetItem: TBoldDomainElement; {$IFDEF BOLD_INLINE} inline; {$ENDIF} public property Item: TBoldDomainElement read GetItem; + property Current: TBoldDomainElement read GetItem; end; { TBoldDomainElementCollection } TBoldDomainElementCollection = class(TBoldUnorderedIndexableList) + private + class var IX_DomainElementCollection: integer; protected function TraverserClass: TBoldIndexableListTraverserClass; override; public - constructor create; - procedure Add(item: TBoldDomainElement); - function Includes(item: TBoldDomainElement): Boolean; + constructor Create; + function GetEnumerator: TBoldDomainElementCollectionTraverser; + procedure Add(item: TBoldDomainElement); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function Includes(item: TBoldDomainElement): Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} function CreateTraverser: TBoldDomainElementCollectionTraverser; end; @@ -90,13 +102,10 @@ implementation BoldIndex, BoldHashIndexes; -var - IX_DomainElementCollection: integer = -1; - type TBoldDomainElementCollectionIndex = class(TBoldObjectHashIndex) protected - function ItemAsKeyObject(Item: TObject): TObject; override; + function ItemASKeyObject(Item: TObject): TObject; override; end; { TBoldDomainElement } @@ -109,7 +118,7 @@ procedure TBoldDomainElement.StateError(S: string); if Assigned(Self) then MyClassName := ClassName else - MyClassName := ''; // do not localize + MyClassName := ''; if Assigned(Self) and Assigned(OwningElement) then MyOwnerClassname := OwningElement.ClassName + '.' else @@ -140,52 +149,73 @@ procedure TBoldDomainElement.SetBoldPersistent(Value: Boolean); end; *) -constructor TBoldDomainElement.Create(OwningElement: TBoldDomainElement); +constructor TBoldDomainElement.CreateWithOwner(OwningElement: TBoldDomainElement); begin - inherited Create; FOwningElement := OwningElement; end; +function TBoldDomainElement.GetBoldSystem: TBoldDomainElement; +begin + result := nil; + if Assigned(OwningElement) then + result := OwningElement.BoldSystem + else + if self.ClassName = 'TBoldSystem' then + result := self; +end; + +function TBoldDomainElement.GetDisplayName: String; +begin + result := Inherited GetDisplayName; + if Assigned(OwningElement) then + result := OwningElement.DisplayName + '.' + result; +end; + procedure TBoldDomainElement.SendEvent(OriginalEvent: TBoldEvent); begin if Assigned(OwningElement) then - OwningElement.ReceiveEventFromOwned(self, OriginalEvent); - inherited; // SendEvent(Originator, OriginalEvent); + OwningElement.ReceiveEventFromOwned(self, OriginalEvent, []); + inherited; end; +{$IFNDEF BOLD_NO_QUERIES} function TBoldDomainElement.SendQuery( OriginalEvent: TBoldEvent; const Args: array of const; - Subscriber: TBoldSubscriber): Boolean; + Subscriber: TBoldSubscriber; Originator: TObject = nil): Boolean; begin result := True; if Assigned(OwningElement) then - result := OwningElement.ReceiveQueryFromOwned(self, OriginalEvent, Args, Subscriber); - if result then - result := inherited SendQuery(OriginalEvent, Args, Subscriber); + result := OwningElement.ReceiveQueryFromOwned(Originator, OriginalEvent, Args, Subscriber); + result := result and inherited SendQuery(OriginalEvent, Args, Subscriber, Originator); end; +{$ENDIF} -procedure TBoldDomainElement.ReceiveEventFromOwned(Originator: TObject; OriginalEvent: TBoldEvent); +procedure TBoldDomainElement.ReceiveEventFromOwned(Originator: TObject; OriginalEvent: TBoldEvent; const Args: array of const); begin - // Intentionally left blank end; +{$IFNDEF BOLD_NO_QUERIES} function TBoldDomainElement.ReceiveQueryFromOwned(Originator: TObject; OriginalEvent: TBoldEvent; const Args: array of const; Subscriber: TBoldSubscriber): Boolean; begin result := True; end; +{$ENDIF} procedure TBoldDomainElement.SendExtendedEvent(OriginalEvent: TBoldEvent; const Args: array of const); begin if Assigned(OwningElement) then - OwningElement.ReceiveEventFromOwned(self, OriginalEvent); + OwningElement.ReceiveEventFromOwned(self, OriginalEvent, Args); inherited; end; function TBoldDomainElement.CanCommit: Boolean; begin - result := MayCommit and SendQuery(bqMayCommit, [], nil); + result := MayCommit; +{$IFNDEF BOLD_NO_QUERIES} + result := result and SendQuery(bqMayCommit, [], nil); +{$ENDIF} end; function TBoldDomainElement.MayCommit: Boolean; @@ -198,12 +228,21 @@ function TBoldDomainElement.ProxyInterface(const IId: TGUID; Mode: TBoldDomainEl result := false; end; +procedure TBoldDomainElement.Invalidate; +begin +// do nothing +end; + { TBoldDomainElement_Proxy } -constructor TBoldDomainElement_Proxy.Create(ProxedElement: TBoldDomainElement; Mode: TBoldDomainElementProxyMode); +constructor TBoldDomainElement_Proxy.Create(Mode: TBoldDomainElementProxyMode); begin inherited create; - fProxedElement := ProxedElement; + fMode := Mode; +end; + +procedure TBoldDomainElement_Proxy.Retarget(Mode: TBoldDomainElementProxyMode); +begin fMode := Mode; end; @@ -219,7 +258,7 @@ procedure TBoldDomainElementCollection.Add(item: TBoldDomainElement); inherited Add(item); end; -constructor TBoldDomainElementCollection.create; +constructor TBoldDomainElementCollection.Create; begin inherited create; OwnsEntries := false; @@ -228,14 +267,17 @@ constructor TBoldDomainElementCollection.create; function TBoldDomainElementCollection.CreateTraverser: TBoldDomainElementCollectionTraverser; begin - result := TBoldDomainElementCollectionTraverser(inherited CreateTraverser); - Assert(Result is TBoldDomainElementCollectionTraverser); + result := inherited CreateTraverser as TBoldDomainElementCollectionTraverser; +end; + +function TBoldDomainElementCollection.GetEnumerator: TBoldDomainElementCollectionTraverser; +begin + result := CreateTraverser; end; function TBoldDomainElementCollection.Includes(item: TBoldDomainElement): Boolean; begin - Assert((Indexes[IX_DomainElementCollection] is TBoldDomainElementCollectionIndex)); - result := assigned(TBoldDomainElementCollectionIndex(Indexes[IX_DomainElementCollection]).FindByObject(Item)); + result := assigned(TBoldObjectHashIndex(Indexes[IX_DomainElementCollection]).FindByObject(Item)); end; function TBoldDomainElementCollectionIndex.ItemASKeyObject(Item: TObject): TObject; @@ -252,8 +294,11 @@ function TBoldDomainElementCollection.TraverserClass: TBoldIndexableListTraverse function TBoldDomainElementCollectionTraverser.GetItem: TBoldDomainElement; begin - Assert((inherited item) is TBoldDomainElement); result := TBoldDomainElement(inherited item); + Assert(result is TBoldDomainElement); end; +initialization + TBoldDomainElementCollection.IX_DomainElementCollection := -1; + end. diff --git a/Source/ObjectSpace/BORepresentation/BoldElementList.pas b/Source/ObjectSpace/BORepresentation/BoldElementList.pas index 1764518..83c5963 100644 --- a/Source/ObjectSpace/BORepresentation/BoldElementList.pas +++ b/Source/ObjectSpace/BORepresentation/BoldElementList.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldElementList; interface @@ -22,12 +25,14 @@ TBoldElementList = class(TBoldList) function GetElement(index: Integer): TBoldElement; override; function IncludesElement(Item: TBoldElement): Boolean; override; function IndexOfElement(Item: TBoldElement): Integer; override; - procedure InitializeMember(AOwningElement: TBoldDomainElement; ElementTypeInfo: TBoldElementTypeInfo); override; + procedure Initialize; override; procedure InsertElement(index: Integer; Element: TBoldElement); override; procedure SetElement(index: Integer; Value: TBoldElement); override; function InternalAddNew: TBoldElement; override; function GetCanCreateNew: Boolean; override; - function ProxyClass: TBoldMember_ProxyClass; override; + procedure InternalClear; override; + function GetProxy(Mode: TBoldDomainElementProxyMode): TBoldMember_Proxy; override; + //function ProxyClass: TBoldMember_ProxyClass; override; public procedure Assign(Source: TBoldElement); override; procedure InsertNew(index: Integer); override; @@ -49,7 +54,7 @@ implementation BoldSubscription, BoldSystemRT, BoldIndexableList, - BoldCoreConsts; + BoldRev; type { TBoldIndexableElementList } @@ -67,7 +72,7 @@ TBoldElementListController = class(TBoldListController) property List: TBoldIndexableElementList read fList; function GetStreamName: string; override; public - constructor Create(OwningList: TBoldList); + constructor Create(OwningList: TBoldList); override; destructor Destroy; override; procedure AddElement(Element: TBoldElement); override; function GetElement(index: Integer): TBoldElement; override; @@ -83,16 +88,15 @@ TBoldElementListController = class(TBoldListController) procedure TBoldElementList.AddElement(Element: TBoldElement); begin - if (ListController.IndexOfElement(Element) = -1) or DuplicateControl then + if (DuplicateMode = bldmAllow) or (ListController.IndexOfElement(Element) = -1) or DuplicateControl then begin - listcontroller.AddElement(Element); + ListController.AddElement(Element); Changed(beItemAdded, [Element]); end; end; procedure TBoldElementList.AllocateData; begin - // do nothing end; procedure TBoldElementList.Assign(Source: TBoldElement); @@ -105,7 +109,6 @@ procedure TBoldElementList.Assign(Source: TBoldElement); procedure TBoldElementList.FreeData; begin - // do nothing end; function TBoldElementList.GetCanCreateNew: Boolean; @@ -118,11 +121,25 @@ function TBoldElementList.GetCount: Integer; result := ListController.Count; end; +procedure TBoldElementList.InternalClear; +var + i: integer; +begin + for i := Count - 1 downto 0 do + RemoveByIndex(I); +end; + function TBoldElementList.GetElement(index: Integer): TBoldElement; begin result := ListController.GetElement(index); end; +function TBoldElementList.GetProxy( + Mode: TBoldDomainElementProxyMode): TBoldMember_Proxy; +begin + raise EBoldInternal.Create('TBoldElementList.GetProxy called'); +end; + function TBoldElementList.IncludesElement(Item: TBoldElement): Boolean; begin result := ListController.IncludesElement(item); @@ -133,7 +150,7 @@ function TBoldElementList.IndexOfElement(Item: TBoldElement): Integer; result := ListController.IndexOfElement(item); end; -procedure TBoldElementList.InitializeMember(AOwningElement: TBoldDomainElement; ElementTypeInfo: TBoldElementTypeInfo); +procedure TBoldElementList.Initialize; begin ListController := TBoldElementListController.Create(self); DuplicateMode := bldmAllow; @@ -148,12 +165,12 @@ procedure TBoldElementList.InsertElement(index: Integer; procedure TBoldElementList.InsertNew(index: Integer); begin - raise EBold.CreateFmt(sOperationNotAllowed, [className, 'InsertNew']); // do not localize + raise EBold.CreateFmt('%s.InsertNew: This operation is not allowed', [className]); end; function TBoldElementList.InternalAddNew: TBoldElement; begin - raise EBold.CreateFmt(sOperationNotAllowed, [className, 'InternalAddNew']); // do not localize + raise EBold.CreateFmt('%s.InternalAddNew: This operation is not allowed', [className]); end; procedure TBoldElementList.Move(CurIndex, NewIndex: Integer); @@ -161,10 +178,12 @@ procedure TBoldElementList.Move(CurIndex, NewIndex: Integer); ListController.Move(CurIndex, NewIndex); end; +(* function TBoldElementList.ProxyClass: TBoldMember_ProxyClass; begin - raise EBold.CreateFmt(sOperationNotAllowed, [className, 'ProxyClass']); // do not localize + raise EBold.CreateFmt('%s.ProxyClass: This operation is not allowed', [className]); end; +*) procedure TBoldElementList.RemoveByIndex(index: Integer); begin @@ -187,13 +206,14 @@ procedure TBoldElementListController.AddElement(Element: TBoldElement); constructor TBoldElementListController.Create(OwningList: TBoldList); begin + inherited; fList := TBoldIndexableElementList.Create; fList.OwnsEntries := false; end; function TBoldElementListController.CreateNew: TBoldElement; begin - raise EBold.Create(sNotImplemented); + raise EBold.Create('not implemented'); end; destructor TBoldElementListController.Destroy; @@ -214,13 +234,14 @@ function TBoldElementListController.GetCount: Integer; function TBoldElementListController.GetElement(index: Integer): TBoldElement; begin - result := list.Items[index] as TBoldElement; + result := TBoldElement(list.Items[index]); + Assert(result is TBoldElement, result.classname); end; function TBoldElementListController.GetStreamName: string; begin result := ''; - raise EBold.create(sNotImplemented); + raise EBold.create('not implemented'); end; function TBoldElementListController.IncludesElement(Item: TBoldElement): Boolean; @@ -250,7 +271,7 @@ procedure TBoldElementListController.RemoveByIndex(index: Integer); procedure TBoldElementListController.SetElement(index: Integer; Value: TBoldElement); begin - Raise EBold.Create(sCannotSetElementsInTypeLists); + List.Items[index] := Value; end; { TBoldElementListFactory } @@ -260,6 +281,5 @@ class function TBoldElementListFactory.CreateList(aSystem: TBoldSystem): TBoldEl result := TBoldElementList.CreateWithTypeInfo(aSystem.BoldSystemTypeInfo.ListTypeInfoByElement[nil]); end; +initialization end. - - diff --git a/Source/ObjectSpace/BORepresentation/BoldExternalObjectSpaceEventHandler.pas b/Source/ObjectSpace/BORepresentation/BoldExternalObjectSpaceEventHandler.pas index 1ede901..e26f855 100644 --- a/Source/ObjectSpace/BORepresentation/BoldExternalObjectSpaceEventHandler.pas +++ b/Source/ObjectSpace/BORepresentation/BoldExternalObjectSpaceEventHandler.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldExternalObjectSpaceEventHandler; interface @@ -9,50 +12,88 @@ interface BoldSubscription, BoldAbstractDequeuer, BoldDefaultID, - BoldAbstractPropagatorHandle; + BoldAbstractPropagatorHandle, + BoldElementList, + BoldDomainElement, + BoldId, +{$IFDEF UseBoldOSSMessage} + BoldOSSMessage, +{$ENDIF} + BoldDefs; type TBoldClassChangedEvent = procedure (TheClass: TBoldObjectList) of object; TBoldEmbeddedStateChangedEvent = procedure (BoldObject: TBoldObject) of object; TBoldNonEmbeddedStateChangedEvent = procedure (BoldMember: TBoldMember) of object; - TBoldConflictEvent = procedure (BoldObject: TBoldObject) of object; + TBoldConflictEvent = procedure (ABoldElement: TBoldDomainElement) of object; TBoldLockLostEvent = procedure (LockName: String) of object; TBoldDoDisconnectEvent = procedure(aMessage: String; RemainDisconnectedMSec: integer) of object; TBoldExternalObjectSpaceEventHandler = class; - TBoldExternalObjectSpaceEventHandler = class(TBoldAbstractDequeuer) + EOSS = class(EBold) + end; + + EOSSConflict = class(EOSS) + private + FList: TBoldList; + public + constructor Create(AList: TBoldList); + destructor Destroy; override; + property List: TBoldList read FList; + end; + + TIdListArray = array of TBoldObjectIdList; + + TBoldExternalObjectSpaceEventHandler = class(TBoldStringDequeuer) private fBoldSystemHandle: TBoldSystemHandle; fPropagatorHandle: TBoldAbstractPropagatorHandle; fPTSubscriber: TBoldPassthroughSubscriber; + fConflictingElements: TBoldElementList; {*** User events ***} - fOnClassChangedEvent: TBoldClassChangedEvent; - fOnEmbeddedStateChanged: TBoldEmbeddedStateChangedEvent; - fOnNonEmbeddedStateChanged: TBoldNonEmbeddedStateChangedEvent; fOnConflict: TBoldConflictEvent; fOnLockLost: TBoldLockLostEvent; - fOnObjectDeleted: TBoldEmbeddedStateChangedEvent; - fHandleNilObjects: Boolean; fDoDisconnect: TBoldDoDisconnectEvent; {*** End user events ***} + fOnClassChangedEvent: TBoldClassChangedEvent; + fOnEmbeddedStateChanged: TBoldEmbeddedStateChangedEvent; + fOnNonEmbeddedStateChanged: TBoldNonEmbeddedStateChangedEvent; + fOnObjectDeleted: TBoldEmbeddedStateChangedEvent; + fKeepClassesCurrent: boolean; + fObjectFetchArray: TIdListArray; + fIdFetchArray: TIdListArray; + fUseMemberLevelOSS: boolean; procedure SetPropagatorHandle(Value: TBoldAbstractPropagatorHandle); procedure SetBoldSystemHandle(aSystemHandle: TBoldSystemHandle); procedure _Receive(Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent); function GetObjectByID(ObjectID: TBoldDefaultID): TBoldObject; procedure Subscribe(const DoSubscribe: Boolean); protected - procedure HandleMessage(aMsg: String); override; - procedure ClassChanged(ClassName: String); virtual; - procedure EmbeddedStateOfObjectChanged(ObjectID: TBoldDefaultID); virtual; - procedure NonEmbeddedStateOfObjectChanged(MemberName: String; ObjectID: TBoldDefaultID); virtual; - procedure ObjectDeleted(ObjectId: TBoldDefaultID); virtual; - procedure LockLost(LockName: String); virtual; - procedure Conflict(BoldObject: TBoldObject); + procedure HandleMessage(const aMsg: String); override; +{$IFDEF UseBoldOSSMessage} + procedure HandleObjectMessage(const AOSSMessage: TOSSMessage); +{$ENDIF} + procedure ClassChanged(const ClassName: String); virtual; + procedure MemberChanged(const ClassName, MemberName: String; ObjectID: TBoldDefaultID); virtual; + procedure EmbeddedStateOfObjectChanged(const ClassName: String; ObjectID: TBoldDefaultID); virtual; + procedure NonEmbeddedStateOfObjectChanged(const ClassName: String; const MemberName: String; ObjectID: TBoldDefaultID); virtual; + procedure ObjectCreated(const ClassName: String; ObjectId: TBoldDefaultID); virtual; + procedure ObjectDeleted(const ClassName: String;ObjectId: TBoldDefaultID); virtual; + procedure LockLost(const LockName: String); virtual; + procedure Conflict(AElement: TBoldDomainElement); virtual; + procedure ClearFetchList; + procedure FetchObject(ID: TBoldObjectId); + procedure FetchMember(Member: TBoldMember); + procedure FetchId(ID: TBoldObjectId); + procedure FetchLists; procedure Notification(AComponent: TComponent; Operation: TOperation); override; + function GetBoldSystem: TBoldSystem; + property BoldSystem: TBoldSystem read GetBoldSystem; + property ConflictingElements: TBoldElementList read fConflictingElements; public constructor Create(AOwner: TComponent); override; destructor Destroy; override; - property HandleNilObjects: Boolean read fHandleNilObjects write fHandleNilObjects; + procedure DequeueAll; override; published property BoldSystemHandle: TBoldSystemHandle read fBoldSystemHandle write SetBoldSystemHandle; property OnClassChanged: TBoldClassChangedEvent read fOnClassChangedEvent write fOnClassChangedEvent; @@ -63,6 +104,8 @@ TBoldExternalObjectSpaceEventHandler = class(TBoldAbstractDequeuer) property OnConflict: TBoldConflictEvent read fOnConflict write fOnConflict; property OnDoDisconnect: TBoldDoDisconnectEvent read fDoDisconnect write fDoDisconnect; property PropagatorHandle: TBoldAbstractPropagatorHandle read fPropagatorHandle write SetPropagatorHandle; + property KeepClassesCurrent: boolean read fKeepClassesCurrent write fKeepClassesCurrent default true; + property UseMemberLevelOSS: boolean read fUseMemberLevelOSS write fUseMemberLevelOSS; end; implementation @@ -70,10 +113,8 @@ implementation uses SysUtils, BoldObjectSpaceExternalEvents, - BoldDomainElement, BoldValueSpaceInterfaces, - BoldDefs, - BoldCoreConsts; + BoldSystemRT; { TBoldDequeuer } @@ -81,11 +122,25 @@ constructor TBoldExternalObjectSpaceEventHandler.Create(aOwner: TComponent); begin inherited Create(aOwner); fPTSubscriber := TBoldPassthroughSubscriber.Create(_Receive); + fConflictingElements := TBoldElementList.Create; + fKeepClassesCurrent := true; +end; + +procedure TBoldExternalObjectSpaceEventHandler.DequeueAll; +begin + ClearFetchList; + try + inherited DequeueAll; + FetchLists; + finally + ClearFetchList; + end; end; destructor TBoldExternalObjectSpaceEventHandler.Destroy; begin FreeAndNil(fPTSubscriber); + FreeAndNil(fConflictingElements); inherited; end; @@ -106,115 +161,295 @@ procedure TBoldExternalObjectSpaceEventHandler._Receive(Originator: TObject; BoldSystemHandle := nil; end; -procedure TBoldExternalObjectSpaceEventHandler.HandleMessage(aMsg: String); +procedure TBoldExternalObjectSpaceEventHandler.HandleMessage(const aMsg: String); var ClassName, MemberName, LockName: String; SubsType: TBoldObjectSpaceSubscriptionType; - ObjectID: TBoldDefaultID; + ObjectID, ExactId: TBoldDefaultID; temp: string; + vEvents: TStringList; + vEvent: string; + i: integer; begin if not assigned(fBoldSystemHandle) then - raise EBold.CreateFmt(sEventHandlerNotConnected, [self.ClassName, name]); + raise EBold.CreateFmt('%s.HandleMessage: The Eventhandler (%s) is not connected to a systemhandle. Unable to handle messages', [self.ClassName, name]); if not assigned(fBoldSystemHandle.System) then - raise EBold.CreateFmt(sSystemHandleNotActive, [self.ClassName, fBoldSystemHandle.name]); - if pos('DISCONNECT:', aMsg) = 1 then // do not localize - begin - if Assigned(fPropagatorHandle) then - fPropagatorHandle.Connected := false; - if assigned(OnDoDisconnect) then + raise EBold.CreateFmt('%s.HandleMessage: The systemhandle (%s) is not active. Unable to handle messages', [self.ClassName, fBoldSystemHandle.name]); + vEvents := TStringList.Create; + vEvents.CommaText := aMsg; + try + for I := 0 to vEvents.Count - 1 do begin - temp := copy(aMsg, pos(':', aMsg)+1, maxint); - OnDoDisconnect( - copy(temp, pos(':', temp)+1, maxint), - StrToIntDef(copy(temp, 1, pos(':', temp)-1), -1) - ); - end; - end - else - begin - ObjectID := TBoldDefaultID.Create; - try - SubsType := TBoldObjectSpaceExternalEvent.DecodeExternalEvent(aMsg, - ClassName, - MemberName, - LockName, - ObjectID); - case SubsType of - bsClassChanged: ClassChanged(ClassName); - bsEmbeddedStateOfObjectChanged: EmbeddedStateOfObjectChanged(ObjectID); - bsObjectDeleted: ObjectDeleted(ObjectId); - bsNonEmbeddedStateOfObjectChanged: NonEmbeddedStateOfObjectChanged(MemberName, ObjectID); - bsLockLost: LockLost(LockName); + vEvent := Trim(vEvents[i]); + if pos('DISCONNECT:', vEvent) = 1 then + begin + if Assigned(fPropagatorHandle) then + fPropagatorHandle.Connected := false; + if assigned(OnDoDisconnect) then + begin + temp := copy(vEvent, pos(':', vEvent)+1, maxint); + OnDoDisconnect( + copy(temp, pos(':', temp)+1, maxint), + StrToIntDef(copy(temp, 1, pos(':', temp)-1), -1) + ); + end; + end + else + begin + ExactId := nil; + ObjectID := TBoldDefaultID.Create; + try + SubsType := TBoldObjectSpaceExternalEvent.DecodeExternalEvent(vEvent, + ClassName, + MemberName, + LockName, + ObjectID); + if (ClassName <> '') then + ExactId := ObjectID.CloneWithClassId(BoldSystem.BoldSystemTypeInfo.ClassTypeInfoByExpressionName[ClassName].TopSortedIndex, true) as TBoldDefaultID + else + ExactId := ObjectID.Clone as TBoldDefaultId; + case SubsType of + bsClassChanged: ClassChanged(ClassName); + bsMemberChanged: MemberChanged(ClassName, MemberName, ExactId); + bsEmbeddedStateOfObjectChanged: EmbeddedStateOfObjectChanged(ClassName, ExactId); + bsObjectCreated: ObjectCreated(ClassName, ExactId); + bsObjectDeleted: ObjectDeleted(ClassName, ExactId); + bsNonEmbeddedStateOfObjectChanged: NonEmbeddedStateOfObjectChanged(ClassName, MemberName, ExactId); + bsLockLost: LockLost(LockName); + end; + finally + FreeAndNil(ObjectID); + FreeAndNil(ExactId); + end; end; - finally - FreeAndNil(ObjectID); end; + finally + vEvents.free; end; end; -procedure TBoldExternalObjectSpaceEventHandler.ClassChanged(ClassName: String); +{$IFDEF UseBoldOSSMessage} +procedure TBoldExternalObjectSpaceEventHandler.HandleObjectMessage( + const AOSSMessage: TOSSMessage); var - theClass: TBoldObjectList; + vEvents: TStringList; + vEvent: string; + i: integer; begin - theClass := fBoldSystemHandle.System.ClassByExpressionName[ClassName]; - if Assigned(theClass) then + if not assigned(fBoldSystemHandle) then + raise EBold.CreateFmt('%s.HandleMessage: The Eventhandler (%s) is not connected to a systemhandle. Unable to handle messages', [self.ClassName, name]); + if not assigned(fBoldSystemHandle.System) then + raise EBold.CreateFmt('%s.HandleMessage: The systemhandle (%s) is not active. Unable to handle messages', [self.ClassName, fBoldSystemHandle.name]); + vEvents := TStringList.Create; + vEvents.Text := AOSSMessage.Events; + try + case AOSSMessage.MessageType of + mtFail:; // TODO: anything to do here ? maybe at least call event OnFail + mtSync : + begin + for I := 0 to vEvents.count-1 do + begin + vEvent := vEvents[i]; + HandleMessage(vEvent); + end; + end; + end; + finally + vEvents.free; + end; +end; +{$ENDIF} + +procedure TBoldExternalObjectSpaceEventHandler.ClassChanged(const ClassName: String); +var + ClassTypeInfo: TBoldClassTypeInfo; + ClassList: TBoldObjectList; +begin + ClassTypeInfo := BoldSystem.BoldSystemTypeInfo.ClassTypeInfoByExpressionName[ClassName]; + if not Assigned(ClassTypeInfo) then + raise EOSS.CreateFmt('Cannot find the class %s in the system.', [ClassName]); + if Assigned(fOnClassChangedEvent) then begin - if Assigned(fOnClassChangedEvent) then - fOnClassChangedEvent(theClass) - else - theClass.Invalidate; + ClassList := BoldSystem.Classes[ClassTypeInfo.TopSortedIndex]; + fOnClassChangedEvent(ClassList); end else - raise EBold.CreateFmt(sClassNotInSystem, [ClassName]); + repeat + ClassList := BoldSystem.Classes[ClassTypeInfo.TopSortedIndex]; + ClassList.Invalidate; + ClassTypeInfo := ClassTypeInfo.SuperClassTypeInfo; + until not Assigned(ClassTypeInfo); + SendExtendedEvent(self, boeClassChanged, [ClassName]); end; procedure TBoldExternalObjectSpaceEventHandler.EmbeddedStateOfObjectChanged( - ObjectID: TBoldDefaultID); + const ClassName: String; ObjectID: TBoldDefaultID); var CurrObj: TBoldObject; begin CurrObj := GetObjectByID(ObjectID); + if Assigned(fOnEmbeddedStateChanged) then + fOnEmbeddedStateChanged(CurrObj) + else if Assigned(CurrObj) then begin - if Assigned(fOnEmbeddedStateChanged) then - fOnEmbeddedStateChanged(CurrObj) - else + if not UseMemberLevelOSS then begin if (CurrObj.BoldDirty) then Conflict(CurrObj) else + begin + if CurrObj.ObjectHasSubscribers then + FetchObject(ObjectId); CurrObj.Invalidate; + end; end; - end - else if HandleNilObjects and Assigned(fOnEmbeddedStateChanged) then - fOnEmbeddedStateChanged(nil); + end; + SendExtendedEvent(self, boeEmbeddedStateOfObjectChanged, [CurrObj, className, ObjectId, CurrObj]); +end; + +procedure TBoldExternalObjectSpaceEventHandler.ClearFetchList; +var + i: integer; +begin + for I := 0 to high(fObjectFetchArray) do + begin + fObjectFetchArray[i].Free; + fObjectFetchArray[i] := nil; + end; + for I := 0 to high(fIdFetchArray) do + begin + fIdFetchArray[i].Free; + fIdFetchArray[i] := nil; + end; +end; + +procedure TBoldExternalObjectSpaceEventHandler.FetchId(ID: TBoldObjectId); +var + IdList: TBoldObjectIdList; +begin + Assert(Id.TopSortedIndexExact); + if (Length(fObjectFetchArray) > Id.TopSortedIndex) and Assigned(fObjectFetchArray[Id.TopSortedIndex]) then + begin + if fObjectFetchArray[Id.TopSortedIndex].IdInList[Id] then + exit; + end; + if Id.TopSortedIndex >= Length(fIdFetchArray) then + SetLength(fIdFetchArray, Id.TopSortedIndex+1); + IdList := fIdFetchArray[Id.TopSortedIndex]; + if not Assigned(IdList) then + begin + IdList := TBoldObjectIdList.Create; + fIdFetchArray[Id.TopSortedIndex] := IdList; + end; + IdList.AddIfNotInList(Id); +end; + +procedure TBoldExternalObjectSpaceEventHandler.FetchObject(ID: TBoldObjectId); +var + IdList: TBoldObjectIdList; +begin + Assert(Id.TopSortedIndexExact); + // first remove from IDFetchList if found + if (Length(fIdFetchArray) > Id.TopSortedIndex) and Assigned(fIdFetchArray[Id.TopSortedIndex]) then + begin + if fIdFetchArray[Id.TopSortedIndex].IdInList[Id] then + begin + fIdFetchArray[Id.TopSortedIndex].Remove(Id); + end; + end; + if Id.TopSortedIndex >= Length(fObjectFetchArray) then + SetLength(fObjectFetchArray, Id.TopSortedIndex+1); + IdList := fObjectFetchArray[Id.TopSortedIndex]; + if not Assigned(IdList) then + begin + IdList := TBoldObjectIdList.Create; + fObjectFetchArray[Id.TopSortedIndex] := IdList; + end; + IdList.AddIfNotInList(Id); +end; + +procedure TBoldExternalObjectSpaceEventHandler.FetchLists; +var + i: integer; + ClassTypeInfo: TBoldClassTypeInfo; + IDList: TBoldObjectIdList; + List: TBoldObjectList; + ClassList: TBoldObjectList; + TopSortedClasses: TBoldClassTypeInfoList; + vBoldSystem: TBoldSystem; +begin + vBoldSystem := BoldSystem; + TopSortedClasses := vBoldSystem.BoldSystemTypeInfo.TopSortedClasses; + for I := 0 to high(fIdFetchArray) do + begin + if Assigned(fIdFetchArray[i]) then + begin + IdList := fIdFetchArray[i]; + BoldSystem.FetchIdList(IdList, false); + end; + end; + for I := 0 to high(fObjectFetchArray) do + begin + if Assigned(fObjectFetchArray[i]) then + begin + IdList := fObjectFetchArray[i]; + BoldSystem.FetchIdList(IdList, true); + end; + end; +end; + +procedure TBoldExternalObjectSpaceEventHandler.FetchMember(Member: TBoldMember); +begin +// fMemberFetchList.Add(Member); end; procedure TBoldExternalObjectSpaceEventHandler.NonEmbeddedStateOfObjectChanged( - MemberName: String; ObjectID: TBoldDefaultID); + const ClassName: String; const MemberName: String; ObjectID: TBoldDefaultID); var CurrObj: TBoldObject; CurrMember: TBoldMember; + i: integer; begin CurrMember := nil; CurrObj := GetObjectByID(ObjectID); if Assigned(CurrObj) then - CurrMember := CurrObj.BoldMemberByExpressionName[MemberName]; - + begin + i := CurrObj.BoldMemberIndexByExpressionName[MemberName]; + if i = -1 then + raise EOSS.CreateFmt('Class %s does not have a member "%s", check OSS settings of other clients.', [CurrObj.DisplayName, MemberName]); + CurrMember := CurrObj.BoldMemberIfAssigned[i]; + end; if Assigned(CurrMember) then begin if Assigned(fOnNonEmbeddedStateChanged) then fOnNonEmbeddedStateChanged(CurrMember) else + if CurrMember.BoldDirty then + Conflict(CurrMember) + else + begin +// if CurrMember.MemberHasSubscribers then +// FetchMember(CurrMember); CurrMember.Invalidate; + end; end; + SendExtendedEvent(self, boeNonEmbeddedStateOfObjectChanged, [ObjectID, CurrObj, CurrMember, ClassName, MemberName]); end; procedure TBoldExternalObjectSpaceEventHandler.Conflict( - BoldObject: TBoldObject); + AElement: TBoldDomainElement); begin + fConflictingElements.Add(AElement); if Assigned(fOnConflict) then - fOnConflict(BoldObject); + fOnConflict(AElement); +end; + +function TBoldExternalObjectSpaceEventHandler.GetBoldSystem: TBoldSystem; +begin + result := nil; + if Assigned(fBoldSystemHandle) then + result := fBoldSystemHandle.System; end; function TBoldExternalObjectSpaceEventHandler.GetObjectByID(ObjectID: TBoldDefaultID): TBoldObject; @@ -227,29 +462,150 @@ function TBoldExternalObjectSpaceEventHandler.GetObjectByID(ObjectID: TBoldDefau Result := CurrLocator.BoldObject; end; -procedure TBoldExternalObjectSpaceEventHandler.LockLost(LockName: String); +procedure TBoldExternalObjectSpaceEventHandler.LockLost(const LockName: String); begin if Assigned(fOnLockLost) then fOnLockLost(LockName); end; -procedure TBoldExternalObjectSpaceEventHandler.ObjectDeleted(ObjectId: TBoldDefaultID); +procedure TBoldExternalObjectSpaceEventHandler.MemberChanged( + const ClassName, MemberName: String; ObjectID: TBoldDefaultID); var CurrObj: TBoldObject; + CurrMember: TBoldMember; + SizeOfInvalidatedList : Integer; + SizeOfInvalidatedListCategory : String; + sl: TStringList; + i,j: integer; + vHasConflicts: boolean; begin + CurrMember := nil; + CurrObj := GetObjectByID(ObjectID); + if Assigned(CurrObj) and UseMemberLevelOSS then + begin +// if CurrObj.BoldDirty then +// Conflict(CurrObj) +// else +// begin +// if CurrObj.ObjectHasSubscribers then +// FetchObject(ObjectId); +// CurrObj.Invalidate; + + sl := TStringList.Create; + try + sl.CommaText := MemberName; + vHasConflicts := false; + for i := 0 to sl.Count - 1 do + begin + j := CurrObj.BoldMemberIndexByExpressionName[sl[i]]; + if j = -1 then + raise EOSS.CreateFmt('Class %s does not have a member "%s", check OSS settings of other clients.', [CurrObj.DisplayName, MemberName]); + CurrMember := CurrObj.BoldMemberIfAssigned[j]; + if Assigned(CurrMember) then + begin + sl.Objects[i] := CurrMember; + if CurrMember.BoldDirty then + begin + vHasConflicts := true; + Conflict(CurrMember); + end; + end; + end; + if vHasConflicts then + begin + CurrObj.Discard; + exit; + end; +{ for I := sl.Count - 1 downto 0 do + begin + CurrMember := TBoldMember(sl.Objects[i]); + if Assigned(CurrMember) then + begin + if (CurrMember.BoldPersistenceState in [bvpsModified]) then + begin + vHasConflicts := true; + Conflict(CurrMember); // this is a conflict caused by local objectspace reacting to invalidate, treat it differently ? + end + else + if (CurrMember.BoldPersistenceState in [bvpsCurrent]) then + begin + CurrMember.Invalidate; + continue; // skip the sl.Delete(i) in order to keep invalidated members in list and refetch them + end; + sl.Delete(i); + end; + end; +} + if not vHasConflicts then + FetchObject(ObjectId); +// BoldSystem.FetchMembersWithObject(CurrObj, sl.CommaText); + finally + sl.free; + end; + +// end; + end; + SendExtendedEvent(self, boeMemberChanged, [ClassName, MemberName, ObjectId, CurrObj]); +end; + +procedure TBoldExternalObjectSpaceEventHandler.ObjectCreated(const ClassName: String; + ObjectId: TBoldDefaultID); +var + ClassTypeInfo: TBoldClassTypeInfo; + ClassList: TBoldObjectList; + BoldObject: TBoldObject; + Handled: boolean; +begin + ClassTypeInfo := BoldSystem.BoldSystemTypeInfo.ClassTypeInfoByExpressionName[ClassName]; + if not Assigned(ClassTypeInfo) then + raise EOSS.CreateFmt('Cannot find the class %s in the system.', [ClassName]); + BoldObject := nil; + Handled := false; + repeat + ClassList := BoldSystem.Classes[ClassTypeInfo.TopSortedIndex]; + if KeepClassesCurrent and (ClassList.BoldPersistenceState <> bvpsInvalid) then + begin + if not Handled then + begin + case ClassList.BoldPersistenceState of + bvpsCurrent: FetchObject(ObjectId); + bvpsTransient: FetchId(ObjectId); + end; + Handled := true; + end; + end + else + ClassList.Invalidate; + ClassTypeInfo := ClassTypeInfo.SuperClassTypeInfo; + until not Assigned(ClassTypeInfo); + SendExtendedEvent(self, boeObjectCreated, [ClassName, ObjectId, BoldObject]); +end; + +procedure TBoldExternalObjectSpaceEventHandler.ObjectDeleted(const ClassName: String; ObjectId: TBoldDefaultID); +var + ClassTypeInfo: TBoldClassTypeInfo; + ClassList: TBoldObjectList; + CurrObj: TBoldObject; +begin + ClassTypeInfo := BoldSystem.BoldSystemTypeInfo.ClassTypeInfoByExpressionName[ClassName]; + if not Assigned(ClassTypeInfo) then + raise EOSS.CreateFmt('Cannot find the class %s in the system.', [ClassName]); CurrObj := GetObjectByID(ObjectID); if Assigned(CurrObj) then begin if Assigned(fOnObjectDeleted) then fOnObjectDeleted(CurrObj) else + if (CurrObj.BoldDirty) then + Conflict(CurrObj) + else begin - if (CurrObj.BoldDirty) then - Conflict(CurrObj) - else - CurrObj.AsIBoldObjectContents[bdepPMIn].BoldExistenceState := besDeleted; + CurrObj.AsIBoldObjectContents[bdepPMIn].BoldExistenceState := besDeleted; + if CurrObj.BoldPersistenceState = bvpsInvalid then + CurrObj.SendEvent(beObjectDeleted); end; end; + SendExtendedEvent(self, boeObjectDeleted, [ClassName, ObjectId, CurrObj]); end; procedure TBoldExternalObjectSpaceEventHandler.Notification( @@ -293,4 +649,20 @@ procedure TBoldExternalObjectSpaceEventHandler.Subscribe( fPTSubscriber.CancelAllSubscriptions; end; +{ EOSSConflict } + +constructor EOSSConflict.Create(AList: TBoldList); +begin + FList := AList.Clone as TBoldList; + self.message := AList.AsDebugCommaText(); +end; + +destructor EOSSConflict.Destroy; +begin + FList.free; + inherited; +end; + +initialization + end. diff --git a/Source/ObjectSpace/BORepresentation/BoldLinks.pas b/Source/ObjectSpace/BORepresentation/BoldLinks.pas index 737da6e..ad4bf69 100644 --- a/Source/ObjectSpace/BORepresentation/BoldLinks.pas +++ b/Source/ObjectSpace/BORepresentation/BoldLinks.pas @@ -1,3 +1,7 @@ + +{ Global compiler directives } +{$include bold.inc} + unit BoldLinks; interface @@ -8,7 +12,8 @@ interface BoldDomainElement, BoldId, BoldElements, - BoldSubscription; + BoldSubscription, + BoldFreeStandingValues; type {forward declarations of all classes} @@ -24,7 +29,6 @@ TBoldLinkObjectSingleLinkController = class; { TBoldDirectSingleLinkController } TBoldDirectSingleLinkController = class(TBoldAbstractObjectReferenceController) private - FOrderno: Integer; fLocator: TBoldObjectLocator; procedure AddToOtherEnd(Mode: TBoldLinkUnlinkMode); procedure RemoveFromOtherEnd(Mode: TBoldLinkUnlinkMode); @@ -33,19 +37,36 @@ TBoldDirectSingleLinkController = class(TBoldAbstractObjectReferenceController function MayUpdate: Boolean; override; procedure PreDiscard; override; procedure SetFromId(Id: TBoldObjectId; Mode: TBoldDomainElementProxyMode); virtual; - procedure SetOrderNo(NewORderNo: Integer; Mode: TBoldDomainElementProxyMode); function GetStreamName: String; override; - function ProxyClass: TBoldMember_ProxyClass; override; + function GetFreeStandingClass: TBoldFreeStandingElementClass; override; + function GetProxy(Member: TBoldMember; Mode: TBoldDomainElementProxyMode): TBoldMember_Proxy; override; + procedure SetOrderNo(NewORderNo: Integer; Mode: TBoldDomainElementProxyMode); virtual; abstract; + function GetOrderNo: Integer; virtual; abstract; public procedure MakeDbCurrent; override; function GetOtherEndController(aLocator: TBoldObjectLocator; AllowForceOtherEnd: Boolean): TBoldAbstractController; - procedure SetAndModifyOrderNo(index: Integer); + procedure SetAndModifyOrderNo(index: Integer); virtual;abstract; procedure Unlink(OldLocator: TBoldObjectLocator; Mode: TBoldLinkUnlinkMode); override; procedure LinkTo(NewLocator: TBoldObjectLocator; updateOrderNo: Boolean; Mode: TBoldLinkUnlinkMode); override; function ProxyInterface(const IId: TGUID; Mode: TBoldDomainElementProxyMode; out Obj): Boolean; override; function GetLocator: TBoldObjectLocator; override; procedure SetLocator(NewLocator: TBoldObjectLocator); override; - property OrderNo: Integer read fOrderNo; + property OrderNo: Integer read GetOrderNo; + end; + + TBoldOrderedDirectSingleLinkController = class(TBoldDirectSingleLinkController) + private + fOrderno: Integer; + public + procedure SetAndModifyOrderNo(index: Integer); override; + procedure SetOrderNo(NewORderNo: Integer; Mode: TBoldDomainElementProxyMode); override; + function GetOrderNo: Integer; override; + end; + + TBoldUnOrderedDirectSingleLinkController = class(TBoldDirectSingleLinkController) + procedure SetAndModifyOrderNo(index: Integer); override; + procedure SetOrderNo(NewOrderNo: Integer; Mode: TBoldDomainElementProxyMode); override; + function GetOrderNo: Integer; override; end; { TBoldIndirectSingleLinkController } @@ -53,16 +74,17 @@ TBoldIndirectSingleLinkController = class(TBoldAbstractObjectReferenceControll private fLinkObjectLocator: TBoldObjectLocator; fOtherEndLocator: TBoldObjectLocator; - function GetLinkObjectOwnLinkController(LinkObject: TBoldObject): TBoldLinkObjectSingleLinkController; - function GetLinkObjectOtherLinkController(LinkObject: TBoldObject): TBoldLinkObjectSingleLinkController; - function GetLinkObjectRoleController: TBoldLinkObjectReferenceController; + function GetLinkObjectOwnLinkController(LinkObject: TBoldObject): TBoldLinkObjectSingleLinkController; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetLinkObjectOtherLinkController(LinkObject: TBoldObject): TBoldLinkObjectSingleLinkController; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetLinkObjectRoleController: TBoldLinkObjectReferenceController; {$IFDEF BOLD_INLINE} inline; {$ENDIF} protected function MayUpdate: Boolean; override; function NewLink(OtherLocator: TBoldObjectLocator; Mode: TBoldLinkUnlinkMode): TBoldObject; procedure DeleteLink(Mode: TBoldLinkUnlinkMode); procedure SetFromIds(Id1, Id2: TBoldObjectId; Mode: TBoldDomainElementProxyMode); function GetStreamName: String; override; - function ProxyClass: TBoldMember_ProxyClass; override; + function GetFreeStandingClass: TBoldFreeStandingElementClass; override; + function GetProxy(Member: TBoldMember; Mode: TBoldDomainElementProxyMode): TBoldMember_Proxy; override; public procedure MakeDbCurrent; override; function AssertIntegrity: Boolean; override; @@ -81,10 +103,11 @@ TBoldMultiLinkController = class(TBoldAbstractObjectListController) function GetCanCreateNew: Boolean; override; function CreateNew: TBoldElement; override; function IsInOrder: Boolean; virtual; abstract; - procedure Resort; virtual; abstract; // order after orderno of other end + procedure Resort; virtual; abstract; public procedure MarkPossiblyOutOfOrder; - procedure EnsureOrder; + procedure EnsureOrder; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure DoEnsureOrder; {$IFDEF BOLD_INLINE} inline; {$ENDIF} end; { TBoldDirectMultiLinkController } @@ -94,12 +117,13 @@ TBoldDirectMultiLinkController = class(TBoldMultiLinkController) procedure ReOrder; property LocatorList: TBoldObjectLocatorList read fLocatorList; protected - function GetOtherEndController(Locator: TBoldObjectLocator): TBoldDirectSingleLinkController; + function GetOtherEndController(Locator: TBoldObjectLocator): TBoldDirectSingleLinkController; {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure SingleLinkUnlink(Locator: TBoldObjectLocator; OldLocator: TBoldObjectLocator;Mode: TBoldLinkUnlinkMode); - procedure SingleLinkLinkTo(Locator: TBoldObjectLocator; NewLocator: TBoldObjectLocator; updateOrderNo: Boolean; Mode: TBoldLinkUnlinkMode); + procedure SingleLinkLinkTo(Locator: TBoldObjectLocator; NewLocator: TBoldObjectLocator; updateOrderNo: Boolean; Mode: TBoldLinkUnlinkMode; aOrderNo: integer = -1); procedure SetFromIdList(ListOfOtherEnd: TBoldObjectIdList; Mode: TBoldDomainElementProxyMode); function GetStreamName: String; override; - function ProxyClass: TBoldMember_ProxyClass; override; + function GetFreeStandingClass: TBoldFreeStandingElementClass; override; + function GetProxy(Member: TBoldMember; Mode: TBoldDomainElementProxyMode): TBoldMember_Proxy; override; procedure PrepareClear; override; function CompareOrderNo(Index1, Index2: integer): integer; procedure Exchange(Index1, Index2: integer); @@ -107,7 +131,7 @@ TBoldDirectMultiLinkController = class(TBoldMultiLinkController) procedure ClearNoLongerReferring(NewList: TBoldObjectIdList); procedure Resort; override; public - constructor Create(OwningList: TBoldObjectList); + constructor Create(OwningList: TBoldObjectList); reintroduce; destructor Destroy; override; procedure LinkTo(NewLocator: TBoldObjectLocator; updateOrderNo: Boolean; Mode: TBoldLinkUnlinkMode); override; procedure Unlink(OldLocator: TBoldObjectLocator; Mode: TBoldLinkUnlinkMode); override; @@ -132,31 +156,32 @@ TBoldIndirectMultiLinkController = class(TBoldMultiLinkController) private fLinkLocatorList: TBoldObjectLocatorList; fReferredList: TBoldObjectLocatorList; - function GetLinkObjectOwnLinkController(LinkObject: TBoldObject): TBoldLinkObjectSingleLinkController; - function GetLinkObjectOtherLinkController(LinkObject: TBoldObject): TBoldLinkObjectSingleLinkController; + function GetLinkObjectOwnLinkController(LinkObject: TBoldObject): TBoldLinkObjectSingleLinkController; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetLinkObjectOtherLinkController(LinkObject: TBoldObject): TBoldLinkObjectSingleLinkController; {$IFDEF BOLD_INLINE} inline; {$ENDIF} function NewLink(OtherLocator: TBoldObjectLocator; Mode: TBoldLinkUnlinkMode): TBoldObject; - function GetLinkObjectListController: TBoldLinkObjectListController; + function GetLinkObjectListController: TBoldLinkObjectListController; {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure DeleteLink(LinkObjectLocator: TBoldObjectLocator; Mode: TBoldLinkUnlinkMode); procedure ReOrder; property LinkLocatorList: TBoldObjectLocatorList read fLinkLocatorList; property ReferredLocatorList: TBoldObjectLocatorList read FReferredList; - function ControllerForLinkMember: TBoldAbstractObjectListController; + function ControllerForLinkMember: TBoldAbstractObjectListController; {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure ClearNoLongerReferring(NewList: TBoldObjectIdList); protected procedure SetFromIDLists(ListOfLinkObjects: TBoldObjectIdList; ListOfOtherEnd: TBoldObjectIdList; Mode: TBoldDomainElementProxyMode); function GetStreamName: String; override; - function ProxyClass: TBoldMember_ProxyClass; override; + function GetFreeStandingClass: TBoldFreeStandingElementClass; override; + function GetProxy(Member: TBoldMember; Mode: TBoldDomainElementProxyMode): TBoldMember_Proxy; override; procedure PrepareClear; override; function CompareOrderNo(Index1, Index2:integer): integer; procedure Exchange(Index1, Index2: integer); function IsInOrder: Boolean; override; procedure Resort; override; public - constructor Create(OwningList: TBoldObjectList); + constructor Create(OwningList: TBoldObjectList); reintroduce; destructor Destroy; override; function AssertIntegrity: Boolean; override; procedure LinkTo(NewLocator: TBoldObjectLocator; updateOrderNo: Boolean; Mode: TBoldLinkUnlinkMode); override; - procedure Unlink(OldLocator: TBoldObjectLocator; Mode: TBoldLinkUnlinkMode); override; + procedure UnLink(OldLocator: TBoldObjectLocator; Mode: TBoldLinkUnlinkMode); override; function GetCount: Integer; override; function GetLocator(index: Integer): TBoldObjectLocator; override; function GetLocatorByQualifiersAndSubscribe(MemberList: TBoldMemberList; Subscriber: TBoldSubscriber): TBoldObjectLocator; override; @@ -176,13 +201,14 @@ TBoldIndirectMultiLinkController = class(TBoldMultiLinkController) { TBoldLinkObjectListController } TBoldLinkObjectListController = class(TBoldAbstractObjectListController) private - function GetLocatorList: TBoldObjectLocatorList; - function GetMainListController: TBOldIndirectMultiLinkController; - function GetMainList: TBoldObjectList; + function GetLocatorList: TBoldObjectLocatorList; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetMainListController: TBOldIndirectMultiLinkController; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetMainList: TBoldObjectList; {$IFDEF BOLD_INLINE} inline; {$ENDIF} property LocatorList: TBoldObjectLocatorList read GetLocatorList; protected function GetStreamName: string; override; - function ProxyClass: TBoldMember_ProxyClass; override; + function GetFreeStandingClass: TBoldFreeStandingElementClass; override; + function GetProxy(Member: TBoldMember; Mode: TBoldDomainElementProxyMode): TBoldMember_Proxy; override; public function GetCount: Integer; override; function GetLocator(index: Integer): TBoldObjectLocator; override; @@ -199,9 +225,9 @@ TBoldLinkObjectListController = class(TBoldAbstractObjectListController) end; { TBoldLinkObjectSingleLinkController } - TBoldLinkObjectSingleLinkController = class(TBoldDirectSingleLinkController) + TBoldLinkObjectSingleLinkController = class(TBoldOrderedDirectSingleLinkController) private - function OtherInnerLinkController: TBoldLinkObjectSingleLinkController; + function OtherInnerLinkController: TBoldLinkObjectSingleLinkController; {$IFDEF BOLD_INLINE} inline; {$ENDIF} protected procedure SetFromId(Id: TBoldObjectId; Mode: TBoldDomainElementProxyMode); override; public @@ -212,7 +238,8 @@ TBoldLinkObjectSingleLinkController = class(TBoldDirectSingleLinkController) TBoldLinkObjectReferenceController = class(TBoldAbstractObjectReferenceController) protected function GetStreamName: string; override; - function ProxyClass: TBoldMember_ProxyClass; override; + function GetFreeStandingClass: TBoldFreeStandingElementClass; override; + function GetProxy(Member: TBoldMember; Mode: TBoldDomainElementProxyMode): TBoldMember_Proxy; override; public function GetLocator: TBoldObjectLocator; override; procedure SetLocator(NewLocator: TBoldObjectLocator); override; @@ -229,7 +256,8 @@ implementation uses SysUtils, Classes, - BoldCoreConsts, + TypInfo, + BoldGuard, BoldStreams, BoldValueSpaceInterfaces, @@ -238,77 +266,84 @@ implementation BoldDefs, BoldValueInterfaces, BoldIndexableList, - BoldSystemRT; + BoldSystemRT, + BoldMath, + BoldObjectListControllers, + BoldLogHandler; {---Proxies---} + { TBoldDirectSingleLinkController_Proxy } type TBoldDirectSingleLinkController_Proxy = class(TBoldMember_Proxy, IBoldObjectIdRef) private - function GetDirectSingleLinkController: TBoldDirectSingleLinkController; - // IBoldObjectIdRef - procedure SetFromId(Id: TBoldObjectId); - function GetId: TBoldObjectID; - function GetOrderNo: integer; + class var fLastUsed: array[TBoldDomainElementProxyMode] of TBoldMember_Proxy; + class var fLastUsedAsInterface: array[TBoldDomainElementProxyMode] of IBoldValue; + function GetDirectSingleLinkController: TBoldDirectSingleLinkController; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure SetFromId(Id: TBoldObjectId; Adopt: Boolean); + function GetId: TBoldObjectID; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetOrderNo: integer; {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure SetOrderNo(NewOrder: Integer); protected - procedure AssignContentValue(Source: IBoldValue); override; + procedure AssignContentValue(const Source: IBoldValue); override; + class function MakeProxy(ProxedMember: TBoldMember; Mode: TBoldDomainElementProxyMode): TBoldMember_Proxy; override; property DirectSingleLInkController: TBoldDirectSingleLinkController read GetDirectSingleLinkController; end; { TBoldIndirectSingleLinkController_Proxy } TBoldIndirectSingleLinkController_Proxy = class(TBoldMember_Proxy, IBoldObjectIdRefPair) private - function GetInDirectSingleLinkController: TBoldInDirectSingleLinkController; - // IBoldObjectIdRefPair + function GetInDirectSingleLinkController: TBoldInDirectSingleLinkController; {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure SetFromIds(Id1, Id2: TBoldObjectId); - function GetId1: TBoldObjectID; - function GetId2: TBoldObjectID; - function GetOrderNo: integer; + function GetId1: TBoldObjectID; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetId2: TBoldObjectID; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetOrderNo: integer; {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure SetOrderNo(NewOrder: Integer); protected - procedure AssignContentValue(Source: IBoldValue); override; + procedure AssignContentValue(const Source: IBoldValue); override; property InDirectSingleLInkController: TBoldInDirectSingleLinkController read GetInDirectSingleLinkController; end; { TBoldDirectMultiLinkController_Proxy } TBoldDirectMultiLinkController_Proxy = class(TBoldMember_Proxy, IBoldObjectIdListRef) private - function GetDirectMultiLinkController: TBoldDirectMultiLinkController; - // IBoldObjectIdListRef + class var fLastUsed: array[TBoldDomainElementProxyMode] of TBoldMember_Proxy; + class var fLastUsedAsInterface: array[TBoldDomainElementProxyMode] of IBoldValue; + function GetDirectMultiLinkController: TBoldDirectMultiLinkController; {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure SetFromIdList(IdLIst: TBoldObjectIdList); - function GetIdList(Index: Integer): TBoldObjectID; - function GetCount: integer; + procedure SetList(IdList: TBoldObjectIdList); + function GetIdList(Index: Integer): TBoldObjectID; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetCount: integer; {$IFDEF BOLD_INLINE} inline; {$ENDIF} protected - procedure AssignContentValue(Source: IBoldValue); override; + procedure AssignContentValue(const Source: IBoldValue); override; property DirectMultiLinkController: TBoldDirectMultiLinkController read GetDirectMultiLinkController; + class function MakeProxy(ProxedMember: TBoldMember; Mode: TBoldDomainElementProxyMode): TBoldMember_Proxy; override; end; { TBoldInDirectMultiLinkController_Proxy } TBoldInDirectMultiLinkController_Proxy = class(TBoldMember_Proxy, IBoldObjectIdListRefPair) private - function GetInDirectMultiLinkController: TBoldInDirectMultiLinkController; - // IBoldObjectIdListRefPair - function GetIdList1(Index: Integer): TBoldObjectID; - function GetIdList2(Index: Integer): TBoldObjectID; + function GetInDirectMultiLinkController: TBoldInDirectMultiLinkController; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetIdList1(Index: Integer): TBoldObjectID; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetIdList2(Index: Integer): TBoldObjectID; {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure SetFromIdLists(IdList1, IdList2: TBoldObjectIdList); - function GetCount: integer; + function GetCount: integer; {$IFDEF BOLD_INLINE} inline; {$ENDIF} protected - procedure AssignContentValue(Source: IBoldValue); override; + procedure AssignContentValue(const Source: IBoldValue); override; property InDirectMultiLinkController: TBoldInDirectMultiLinkController read GetInDirectMultiLinkController; end; { TBoldDirectSingleLinkController_Proxy } -procedure TBoldDirectSingleLinkController_Proxy.AssignContentValue(Source: IBoldValue); +procedure TBoldDirectSingleLinkController_Proxy.AssignContentValue(const Source: IBoldValue); var s: IBoldObjectIdRef; ObjRef: TBoldObjectReference; begin if (not (Assigned(Source) and (source.QueryInterface(IBoldObjectIDRef, S) = S_OK))) then - raise EBold.CreateFmt(sUnknownTypeOfSource, [classname, 'AssignContentValue']); // do not localize - SetFromId(s.Id); - if Mode <>bdepContents then { TODO : Check why Orderno not included in contents } + raise EBold.CreateFmt('%s.AssignContentValue: unknown type of source', [classname]); + SetFromId(s.Id, false); + if Mode <>bdepContents then SetOrderNo(s.OrderNo); if Mode in [bdepUnDo, bdepContents] then begin @@ -333,15 +368,35 @@ function TBoldDirectSingleLinkController_Proxy.GetId: TBoldObjectID; function TBoldDirectSingleLinkController_Proxy.GetOrderNo: integer; begin - Result := DirectSingleLInkController.OrderNo; + Result := DirectSingleLInkController.OrderNo; end; -procedure TBoldDirectSingleLinkController_Proxy.SetFromId(Id: TBoldObjectId); +class function TBoldDirectSingleLinkController_Proxy.MakeProxy( + ProxedMember: TBoldMember; + Mode: TBoldDomainElementProxyMode): TBoldMember_Proxy; +begin + Result := fLastUsed[Mode]; + // Reuse proxy if we hold only reference + if Assigned(Result) and (Result.RefCount =1) then + begin + Result.Retarget(ProxedMember, Mode); + end + else + begin + Result := Create(ProxedMember, Mode); + fLastUsed[Mode] := Result; + fLastUsedAsInterface[Mode] := Result; // Inc refcount + end; +end; + +procedure TBoldDirectSingleLinkController_Proxy.SetFromId(Id: TBoldObjectId; adopt: Boolean); begin if Mode in [bdepPMIn, bdepContents, bdepUndo, bdepInternalInitialize] then DirectSingleLInkController.SetFromId(Id, Mode) else - UnsupportedMode(Mode, 'SetFromId'); // do not localize + UnsupportedMode(Mode, 'SetFromId'); + if Adopt then + Id.Free; end; procedure TBoldDirectSingleLinkController_Proxy.SetOrderNo(NewOrder: Integer); @@ -349,17 +404,17 @@ procedure TBoldDirectSingleLinkController_Proxy.SetOrderNo(NewOrder: Integer); if Mode in [bdepPMIn, bdepUnDo, bdepContents] then DirectSingleLInkController.SetOrderNo(NewOrder, Mode) else - UnsupportedMode(Mode, 'SetOrderNo'); // do not localize + UnsupportedMode(Mode, 'SetOrderNo'); end; { TBoldIndirectSingleLinkController_Proxy } -procedure TBoldIndirectSingleLinkController_Proxy.AssignContentValue(Source: IBoldValue); +procedure TBoldIndirectSingleLinkController_Proxy.AssignContentValue(const Source: IBoldValue); var s: IBoldObjectIdRefPair; begin if (not Assigned(Source)) or (source.QueryInterface(IBoldObjectIDRefPair, S) <> S_OK) then - raise EBold.CreateFmt(sUnknownTypeOfSource, [classname, 'AssignContentValue']); // do not localize + raise EBold.CreateFmt('%s.AssignContentValue: unknown type of source', [classname]); SetFromIds(s.Id1, s.Id2); end; @@ -386,7 +441,7 @@ function TBoldIndirectSingleLinkController_Proxy.GetInDirectSingleLinkController function TBoldIndirectSingleLinkController_Proxy.GetOrderNo: integer; begin - Result := 0; // Indirect link has no orderno + Result := 0; end; procedure TBoldIndirectSingleLinkController_Proxy.SetFromIds(Id1, Id2: TBoldObjectId); @@ -394,17 +449,17 @@ procedure TBoldIndirectSingleLinkController_Proxy.SetFromIds(Id1, Id2: TBoldObje if Mode in [bdepContents, bdepPMIn] then InDirectSingleLInkController.SetFromIds(Id1, Id2, Mode) else - UnsupportedMode(Mode, 'SetFromId'); // do not localize + UnsupportedMode(Mode, 'SetFromId'); end; procedure TBoldIndirectSingleLinkController_Proxy.SetOrderNo(NewOrder: Integer); begin - UnsupportedMode(Mode, 'SetOrderNo'); // do not localize + UnsupportedMode(Mode, 'SetOrderNo'); end; { TBoldDirectMultiLinkController_Proxy } -procedure TBoldDirectMultiLinkController_Proxy.AssignContentValue(Source: IBoldValue); +procedure TBoldDirectMultiLinkController_Proxy.AssignContentValue(const Source: IBoldValue); var s: IBoldObjectIdListRef; i: Integer; @@ -413,8 +468,9 @@ procedure TBoldDirectMultiLinkController_Proxy.AssignContentValue(Source: IBoldV begin G := TBoldGuard.Create(anIdList); if (not Assigned(Source)) or (source.QueryInterface(IBoldObjectIDListRef, S) <> S_OK) then - raise EBold.CreateFmt(sUnknownTypeOfSource, [classname, 'AssignContentValue']); // do not localize + raise EBold.CreateFmt('%s.AssignContentValue: unknown type of source', [classname]); anIdList := TBoldObjectIdList.Create; + anIdList.Capacity := s.Count; for i := 0 to s.Count - 1 do anIdList.Add(s.IdList[i]); SetFromIdList(anIdList) @@ -435,17 +491,51 @@ function TBoldDirectMultiLinkController_Proxy.GetIdList(Index: Integer): TBoldOb Result := DirectMultiLinkController.LocatorList[Index].BoldObjectId; end; +class function TBoldDirectMultiLinkController_Proxy.MakeProxy( + ProxedMember: TBoldMember; + Mode: TBoldDomainElementProxyMode): TBoldMember_Proxy; +begin + Result := fLastUsed[Mode]; + // Reuse proxy if we hold only reference + if Assigned(Result) and (Result.RefCount =1) then + begin + Result.Retarget(ProxedMember, Mode); + end + else + begin + Result := Create(ProxedMember, Mode); + fLastUsed[Mode] := Result; + fLastUsedAsInterface[Mode] := Result; // Inc refcount + end; +end; + procedure TBoldDirectMultiLinkController_Proxy.SetFromIdList(IdList: TBoldObjectIdList); begin if Mode in [bdepContents, bdepPMIn] then DirectMultiLinkController.SetFromIdList(IdLIst, Mode) else - UnsupportedMode(Mode, 'SetFromIdList'); // do not localize + UnsupportedMode(Mode, 'SetFromIdList'); +end; + +procedure TBoldDirectMultiLinkController_Proxy.SetList( + IdList: TBoldObjectIdList); +var + i: integer; + LocatorList: TBoldObjectLocatorList; +begin + IdList.Clear; + LocatorList := DirectMultiLinkController.LocatorList; + if LocatorList.Count > 0 then + begin + IdList.Capacity := LocatorList.Count; + for I := 0 to LocatorList.Count - 1 do + IdList.Add(LocatorList[I].BoldObjectId); + end; end; { TBoldInDirectMultiLinkController_Proxy } -procedure TBoldInDirectMultiLinkController_Proxy.AssignContentValue(Source: IBoldValue); +procedure TBoldInDirectMultiLinkController_Proxy.AssignContentValue(const Source: IBoldValue); var s: IBoldObjectIdListRefPair; i: Integer; @@ -455,13 +545,19 @@ procedure TBoldInDirectMultiLinkController_Proxy.AssignContentValue(Source: IBol begin G := TBoldGuard.Create(anIdList1, anIdList2); if (not Assigned(source)) or (source.QueryInterface(IBoldObjectIDListRefPair, S) <> S_OK) then - raise EBold.CreateFmt(sUnknownTypeOfSource, [classname, 'AssignContentValue']); // do not localize + raise EBold.CreateFmt('%s.AssignContentValue: unknown type of source', [classname]); anIdList1 := TBoldObjectIdList.Create; anIdList2 := TBoldObjectIdList.Create; - for i := 0 to s.Count - 1 do + i := s.Count; + if i > 0 then begin - anIdList1.Add(s.IdList1[i]); - anIdList2.Add(s.IdList2[i]); + anIdList1.Capacity := i; + anIdList2.Capacity := i; + for i := 0 to s.Count - 1 do + begin + anIdList1.Add(s.IdList1[i]); + anIdList2.Add(s.IdList2[i]); + end; end; SetFromIDLists(anIdList1, anIdList2) end; @@ -492,11 +588,32 @@ procedure TBoldInDirectMultiLinkController_Proxy.SetFromIdLists(IdList1, if Mode in [bdepPMIn, bDepContents] then InDirectMultiLinkController.SetFromIdLists(IdList1, IdList2, Mode) else - UnsupportedMode(Mode, 'SetFromIdLists'); // do not localize + UnsupportedMode(Mode, 'SetFromIdLists'); end; { TBoldDirectMultiLinkController } +function TBoldDirectMultiLinkController.GetOtherEndController(Locator: TBoldObjectLocator): TBoldDirectSingleLinkController; +begin + result := GetControllerForMember(Locator.EnsuredBoldObject.BoldMembers[RoleRTInfo.IndexOfOtherEnd]) as TBoldDirectSingleLinkController; +end; + +procedure TBoldMultiLinkController.DoEnsureOrder; +begin + if (fMayBeOutOfOrder) then + begin + if not IsInOrder then + Resort; + fMayBeOutOfOrder := false; + end; +end; + +procedure TBoldMultiLinkController.EnsureOrder; +begin + if (fMayBeOutOfOrder) then + DoEnsureOrder; +end; + procedure TBoldDirectMultiLinkController.AddLocator(Locator: TBoldObjectLocator); var OtherEndController: TBoldDirectSingleLinkController; @@ -506,13 +623,13 @@ procedure TBoldDirectMultiLinkController.AddLocator(Locator: TBoldObjectLocator) try BoldClearLastFailure; if not StartModify then - BoldRaiseLastFailure(OwningList, 'AddLocator', ''); // do not localize + BoldRaiseLastFailure(OwningList, 'AddLocator', ''); PreChange; LocatorList.Add(Locator); OtherEndController := GetOtherEndController(Locator); OtherEndController.LinkTo(OwningList.OwningObject.BoldObjectLocator, true, blulMarkModified); - if OwningObjectList.BoldRoleRtInfo.IsOrdered then - OtherEndController.SetAndModifyOrderNo(LocatorList.IndexOf(Locator)); // Complexity warning: A loop of adds will take O(n^2) + if RoleRTInfo.IsOrdered then + OtherEndController.SetAndModifyOrderNo(LocatorList.IndexOf(Locator)); Changed(beItemAdded, [Locator]); EndModify; @@ -535,10 +652,103 @@ destructor TBoldDirectMultiLinkController.Destroy; inherited; end; +type + TMultiLinkItem = class(TObject) + public + OrderNo: Integer; + ObjectId: TBoldObjectId; + end; + + TIndirectMultiLinkItem = class(TMultiLinkItem) + public + OtherObjectId: TBoldObjectId; + end; + + +function _CompareOrderNo(Item1, Item2: Pointer): Integer; +begin + Result := TMultiLinkItem(Item1).OrderNo - TMultiLinkItem(Item2).OrderNo; +end; + procedure TBoldDirectMultiLinkController.MakeDbCurrent; +{$IFDEF FetchFromClassList} + procedure FetchFromClassList; + var + ClassList: TBoldObjectList; + lBoldObjectIdList: TBoldObjectIdList; + lBoldGuard: IBoldGuard; + lBoldObject: TBoldObject; + lBoldObjectReference: TBoldObjectReference; + lOwnBoldObjectLocator: TBoldObjectLocator; + lMultiLinkItem: TMultiLinkItem; + lSortList: TList; + i: integer; + lIsOrdered: boolean; + CheckType: boolean; + lIndexOfOtherEnd: Integer; + lTopSortedIndex: integer; + OtherEndBoldClassTypeInfo: TBOldClassTypeInfo; + lTopSortedClasses: TBoldClassTypeInfoList; + begin + lBoldGuard := TBoldGuard.Create(lBoldObjectIdList, lSortList); + OtherEndBoldClassTypeInfo := RoleRTInfo.ClassTypeInfoOfOtherEnd; + lTopSortedIndex := RoleRTInfo.ClassTypeInfoOfOtherEnd.TopSortedIndex; + ClassList := BoldSystem.Classes[lTopSortedIndex]; + lOwnBoldObjectLocator := OwningObject.BoldObjectLocator; + lBoldObjectIdList := TBoldObjectIdList.Create; + lTopSortedClasses := BoldSystem.BoldSystemTypeInfo.TopSortedClasses; + if RoleRTInfo.IsOrdered then + lSortList := TList.Create; + lIsOrdered := RoleRTInfo.IsOrdered; + lIndexOfOtherEnd := RoleRTInfo.IndexOfOtherEnd; + CheckType := ClassList.BoldPersistenceState <> bvpsCurrent; + if CheckType then + ClassList := TBoldClassListController(GetControllerForMember(ClassList)).ClosestLoadedClassList{.FilterOnType(RoleRTInfo.ClassTypeInfoOfOtherEnd)}; + for i := 0 to ClassList.Count - 1 do + begin + if CheckType and (ClassList.Locators[i].BoldObjectID.TopSortedIndex < lTopSortedIndex) or + not ClassList.Locators[i].BoldClassTypeInfo.BoldIsA(OtherEndBoldClassTypeInfo) then + Continue; + lBoldObject := ClassList[i]; + lBoldObjectReference := lBoldObject.BoldMembers{IfAssigned}[lIndexOfOtherEnd] as TBoldObjectReference; + if Assigned(lBoldObjectReference) and (lBoldObjectReference.Locator = lOwnBoldObjectLocator) then + begin + if lIsOrdered then + begin + lMultiLinkItem := TMultiLinkItem.Create; + lMultiLinkItem.ObjectId := lBoldObject.BoldObjectLocator.BoldObjectId; + lMultiLinkItem.OrderNo := (GetControllerForMember(lBoldObjectReference) as TBoldDirectSingleLinkController).OrderNo; + lSortList.Add(lMultiLinkItem); + end + else + begin + lBoldObjectIdList.Add(lBoldObject.BoldObjectLocator.BoldObjectId); + end; + end; + end; + if lIsOrdered then + begin + lSortList.Sort(_CompareOrderNo); + for i := 0 to lSortList.Count - 1 do + begin + lMultiLinkItem := TMultiLinkItem(lSortList[i]); + lBoldObjectIdList.Add(lMultiLinkItem.ObjectId); + lMultiLinkItem.free; + end; + end; + + SetFromIdList(lBoldObjectIdList, bdepContents); + OwningObjectList.BoldPersistenceState := bvpsCurrent; + end; +{$ENDIF} begin EnsureOrder; - DbFetchOwningMember; +{$IFDEF FetchFromClassList} + if TBoldClassListController(GetControllerForMember(BoldSystem.Classes[RoleRTInfo.ClassTypeInfoOfOtherEnd.TopSortedIndex])).IsCurrentOrSuperClassIsCurrent then + FetchFromClassList + else +{$ENDIF} + DbFetchOwningMember; end; function TBoldDirectMultiLinkController.GetCount: Integer; @@ -557,13 +767,13 @@ function TBoldDirectMultiLinkController.GetLocatorByQualifiersAndSubscribe(Membe EnsureOrder; if not LocatorList.HasMembersIndex then begin - if assigned(OwningObjectList.BoldRoleRTInfo) and OwningObjectList.BoldRoleRTInfo.isQualified then + if assigned(RoleRTInfo) and RoleRTInfo.isQualified then begin OwningObjectList.EnsureObjects; - LocatorList.InitMembersIndex(OwningObjectList, OwningObjectList.BoldRoleRTInfo.Qualifiers) + LocatorList.InitMembersIndex(OwningObjectList, RoleRTInfo.Qualifiers) end else - raise EBold.CreateFmt(sRolenotQualified, [ClassName]); + raise EBold.CreateFmt('%s.GetLocatorByQualifiers: Object list does not have a member index or role is not qualified', [ClassName]); end; result := LocatorList.GetLocatorByAttributesAndSubscribe(MemberList, Subscriber); end; @@ -586,7 +796,7 @@ procedure TBoldDirectMultiLinkController.InsertLocator(index: Integer; Locator: try BoldClearLastFailure; if not StartModify then - BoldRaiseLastFailure(OwningList, 'InsertLocator', ''); // do not localize + BoldRaiseLastFailure(OwningList, 'InsertLocator', ''); PreChange; LocatorList.Insert(Index, Locator); @@ -603,19 +813,22 @@ procedure TBoldDirectMultiLinkController.InsertLocator(index: Integer; Locator: procedure TBoldDirectMultiLinkController.linkto(NewLocator: TBoldObjectLocator; updateOrderNo: Boolean; Mode: TBoldLinkUnlinkMode) ; begin - Assert((Mode <> blulMarkAdjusted) or (OwningList.BoldPersistenceState = bvpsCurrent)); - Assert(not IncludesLocator(NewLocator)); + Assert((Mode <> blulMarkAdjusted) or (OwningList.BoldPersistenceState = bvpsCurrent), OwningMember.DisplayName); + if IncludesLocator(NewLocator) then // this used to be an assert, but we now just exit + begin + exit; + end; BoldClearLastFailure; if Mode = blulMarkModified then if not StartModify then - BoldRaiseLastFailure(OwningList, 'Linkto', ''); // do not localize + BoldRaiseLastFailure(OwningList, 'Linkto', ''); PreChange; LocatorList.Add(NewLocator); if Mode = blulMarkAdjusted then OwningObjectList.Adjusted := True; - if updateOrderNo and OwningObjectList.BoldRoleRtInfo.IsOrdered then - GetOtherEndController(NewLocator).SetAndModifyOrderNo(LocatorList.IndexOf(NewLocator)); // Complexity warning: A loop of adds will take O(n^2) + if updateOrderNo and RoleRTInfo.IsOrdered then + GetOtherEndController(NewLocator).SetAndModifyOrderNo(LocatorList.IndexOf(NewLocator)); //TODO - This could have side effect when mode is blulMarkAdjusted Changed(beItemAdded, [NewLocator]); if Mode = blulMarkModified then EndModify; @@ -624,11 +837,13 @@ procedure TBoldDirectMultiLinkController.linkto(NewLocator: TBoldObjectLocator; procedure TBoldDirectMultiLinkController.Move(CurrentIndex, NewIndex: Integer); begin EnsureOrder; + if not RoleRTInfo.IsOrdered then + exit; BoldSystem.StartTransaction; try BoldClearLastFailure; if not StartModify then - BoldRaiseLastFailure(OwningList, 'Move', ''); // do not localize + BoldRaiseLastFailure(OwningList, 'Move', ''); PreChange; LocatorList.Move(CurrentIndex, NewIndex); @@ -653,7 +868,7 @@ procedure TBoldDirectMultiLinkController.RemoveByIndex(index: Integer); try BoldClearLastFailure; if not StartModify then - BoldRaiseLastFailure(OwningList, 'RemoveByIndex', ''); // do not localize + BoldRaiseLastFailure(OwningList, 'RemoveByIndex', ''); Locator := LocatorList[index]; PreChange; @@ -671,31 +886,30 @@ procedure TBoldDirectMultiLinkController.RemoveByIndex(index: Integer); procedure TBoldDirectMultiLinkController.ReOrder; var -{$IFOPT C+} // if Assertions on +{$IFOPT C+} index: Integer; {$ENDIF} I: Integer; Locator: TBoldObjectLocator; begin - if not OwningObjectList.BoldRoleRtInfo.IsOrdered then + if not RoleRTInfo.IsOrdered then exit; -{$IFOPT C+} // if Assertions on - index := OwningObjectList.BoldRoleRtInfo.IndexOfOtherEnd; +{$IFOPT C+} + index := RoleRTInfo.IndexOfOtherEnd; Assert(index <> -1); {$ENDIF} for I := 0 to LocatorList.Count - 1 do begin Locator := LocatorList[I]; - Locator.EnsureBoldObject; // Note, can give fetch during fetch, save till all fetched + Locator.EnsureBoldObject; GetOtherEndController(Locator).SetAndModifyOrderNo(I); end; end; procedure TBoldDirectMultiLinkController.SetFromIdList(ListOfOtherEnd: TBoldObjectIdList; Mode: TBoldDomainElementProxyMode); var + BoldSystem: TBoldSystem; NewListOfOtherEnd: TBoldObjectIdlist; - - // Ajdust NewListOfOtherEnd, return true if adjusted function AdjustList: boolean; procedure SafeCopyOptimisticValues; var @@ -712,8 +926,9 @@ procedure TBoldDirectMultiLinkController.SetFromIdList(ListOfOtherEnd: TBoldObje IndexOfOtherEnd: Integer; BoldClassTypeInfoOfOtherEnd: TBoldClassTypeInfo; begin - BoldClassTypeInfoOfOtherEnd := OwningObjectList.BoldRoleRtInfo.ClassTypeInfoOfOtherEnd; - IndexOfOtherEnd := OwningObjectList.BoldRoleRtInfo.IndexOfOtherEnd; + BoldSystem := self.BoldSystem; + BoldClassTypeInfoOfOtherEnd := RoleRTInfo.ClassTypeInfoOfOtherEnd; + IndexOfOtherEnd := RoleRTInfo.IndexOfOtherEnd; Result := False; {Adjust list} for I := newListOfOtherEnd.Count - 1 downto 0 do @@ -776,11 +991,13 @@ procedure TBoldDirectMultiLinkController.SetFromIdList(ListOfOtherEnd: TBoldObje PreserveOrder: Boolean; WasAdjusted: Boolean; LinkUnlinkMode: TBoldLinkUnlinkMode; + OrderHasChanged: boolean; + OwningBoldObjectLocator: TBoldObjectLocator; G: IBoldGuard; begin G := TBoldGuard.Create(NewListOfOtherEnd); PreChangeCalled := True; - if (mode = bdepPMIn) and (OwningMember.OwningObject.BoldObjectLocator.BoldObjectId.TimeStamp <> BOLDMAXTIMESTAMP) then // fetching old temporal versi + if (mode = bdepPMIn) and (OwningList.OwningObject.IsHistoricVersion) then mode := bdepContents; if assigned(ListOfOtherEnd) then NewListOfOtherEnd := ListOfOtherEnd.Clone @@ -796,9 +1013,10 @@ procedure TBoldDirectMultiLinkController.SetFromIdList(ListOfOtherEnd: TBoldObje LinkUnlinkMode := blulMarkAdjusted else LinkUnlinkMode := blulNone; - PreserveOrder := (mode = bdepContents) or ((mode = bdepPMIn) and OwningObjectList.BoldRoleRTInfo.IsOrdered and not WasAdjusted); - + PreserveOrder := (mode = bdepContents) or ((mode = bdepPMIn) and RoleRTInfo.IsOrdered and not WasAdjusted); + OwningBoldObjectLocator := OwningList.OwningObject.BoldObjectLocator; {we now have a list with the right objects} + OrderHasChanged := false; for I := GetCount - 1 downto 0 do begin OldLocator := LocatorList[i]; @@ -806,7 +1024,7 @@ procedure TBoldDirectMultiLinkController.SetFromIdList(ListOfOtherEnd: TBoldObje begin PreChangeIfNeeded; if mode = bdepPMIn then - SingleLinkUnlink(LocatorList[I], OwningList.OwningObject.BoldObjectLocator, LinkUnlinkMode); + SingleLinkUnlink(LocatorList[I], OwningBoldObjectLocator, LinkUnlinkMode); LocatorList.RemoveByIndex(I); Changed(beItemDeleted, [OldLocator]); end; @@ -821,43 +1039,51 @@ procedure TBoldDirectMultiLinkController.SetFromIdList(ListOfOtherEnd: TBoldObje begin PreChangeIfNeeded; if mode = bdepPMIn then - SingleLinkLinkTo(NewLocator, OwningList.OwningObject.BoldObjectLocator, false, LinkUnlinkMode); + SingleLinkLinkTo(NewLocator, OwningBoldObjectLocator, false, LinkUnlinkMode); LocatorList.Add(NewLocator); Changed(beItemAdded, [NewLocator]); end else if NewLocator = LocatorList[i] then - // All in order, do nothing - else if LocatorList.IndexOf(NewLocator) <> -1 then // locator in list, but at wrong place + else if LocatorList.IndexOf(NewLocator) <> -1 then begin PreChangeIfNeeded; LocatorList.Move(LocatorList.IndexOf(NewLocator), I); - Changed(beOrderChanged, []); + OrderHasChanged := true; end else - begin // locator not in list, insert it, + begin PreChangeIfNeeded; if mode = bdepPMIn then - SingleLinkLinkTo(NewLocator, OwningList.OwningObject.BoldObjectLocator, false, LinkUnlinkMode); + SingleLinkLinkTo(NewLocator, OwningBoldObjectLocator, false, LinkUnlinkMode); LocatorList.Insert(I, NewLocator); Changed(beItemAdded, [NewLocator]); end; end; end - else // Ignore Order + else begin - for I := 0 to NewListOfOtherEnd.Count - 1 do + if NewListOfOtherEnd.Count > 0 then begin - NewLocator := AssertedLocatorForId(NewListOfOtherEnd[I]); - if not IncludesLocator(NewLocator) then + LocatorList.Capacity := NewListOfOtherEnd.Count; + for I := 0 to NewListOfOtherEnd.Count - 1 do begin - PreChangeIfNeeded; - if mode = bdepPMIn then - SingleLinkLinkTo(NewLocator, OwningList.OwningObject.BoldObjectLocator, false, LinkUnlinkMode); - LocatorList.Add(NewLocator); - Changed(beItemAdded, [NewLocator]); + NewLocator := AssertedLocatorForId(NewListOfOtherEnd[I]); + if not IncludesLocator(NewLocator) then + begin + PreChangeIfNeeded; + if mode = bdepPMIn then + SingleLinkLinkTo(NewLocator, OwningBoldObjectLocator, false, LinkUnlinkMode); + LocatorList.Add(NewLocator); + Changed(beItemAdded, [NewLocator]); + end; end; end; end; + if OrderHasChanged then + begin + ReOrder; + Changed(beOrderChanged, []); + end; end; procedure TBoldDirectMultiLinkController.SetLocator(index: Integer; Locator: TBoldObjectLocator); @@ -867,7 +1093,7 @@ procedure TBoldDirectMultiLinkController.SetLocator(index: Integer; Locator: TBo try BoldClearLastFailure; if not StartModify then - BoldRaiseLastFailure(OwningList, 'SetLocator', ''); // do not localize + BoldRaiseLastFailure(OwningList, 'SetLocator', ''); PreChange; GetOtherEndController(LocatorList[index]).UnLink(OwningList.OwningObject.BoldObjectLocator, blulMarkModified); @@ -889,14 +1115,34 @@ function TBoldDirectMultiLinkController.GetStreamName: String; Result := BoldContentName_ObjectIdListRef; end; +function TBoldDirectMultiLinkController.GetFreeStandingClass: TBoldFreeStandingElementClass; +begin + Result := TBFSObjectIdListref; +end; + procedure TBoldDirectMultiLinkController.Unlink(OldLocator: TBoldObjectLocator; Mode: TBoldLinkUnlinkMode); begin - Assert((Mode <> blulMarkAdjusted) or (OwningList.BoldPersistenceState = bvpsCurrent)); - Assert(IncludesLocator(OldLocator)); + Assert((Mode <> blulMarkAdjusted) or (OwningList.BoldPersistenceState = bvpsCurrent), OwningMember.DisplayName); + if (Mode=blulMarkAdjusted) and (not IncludesLocator(OldLocator)) then //PATCH + begin + exit; //PATCH + end; + //The prevoius assert prevents unlink to work when controller is bvpsInvalid + //Current implementation of GetOtherEndController never return Invaild Members so this it not a problem + //But if the other end has fetched a new value from db and is current GetOtherEndController will return it + //This will lead to data corruption - Unlink will set correct value to nil! + + // PATCH + // changed from Assert(IncludesLocator(OldLocator)) to if, it's safe to exit if OldLocator is already removed - Daniel + if not IncludesLocator(OldLocator) then + begin + exit; + end; + BoldClearLastFailure; if Mode = blulMarkModified then if not StartModify then - BoldRaiseLastFailure(OwningList, 'Unlink', ''); // do not localize + BoldRaiseLastFailure(OwningList, 'Unlink', ''); PreChange; LocatorList.Remove(OldLocator); @@ -911,22 +1157,21 @@ function TBoldDirectMultiLinkController.ProxyInterface(const IId: TGUID; Mode: T begin if IsEqualGuid(IID, IBoldObjectIdListRef) then begin - result := ProxyClass.create(self.OwningList, Mode).GetInterface(IID, obj); + result := GetProxy(self.OwningList, Mode).GetInterface(IID, obj); if not result then - raise EBoldInternal.CreateFmt('ProxyClass for %s did not implement IBoldObjectIdListRef', [ClassName]); // do not localize + raise EBoldInternal.CreateFmt('ProxyClass for %s did not implement IBoldObjectIdListRef', [ClassName]); end else result := inherited ProxyInterface(IID, Mode, Obj); end; -function TBoldDirectMultiLinkController.ProxyClass: TBoldMember_ProxyClass; +function TBoldDirectMultiLinkController.GetProxy(Member: TBoldMember; Mode: TBoldDomainElementProxyMode): TBoldMember_Proxy; begin - result := TBoldDirectmultiLinkController_Proxy; + result := TBoldDirectmultiLinkController_Proxy.MakeProxy(Member ,Mode); end; procedure TBoldDirectMultiLinkController.FreeContent; begin - { TODO : Clear embedded links in locators. } LocatorList.Clear; end; @@ -935,6 +1180,11 @@ procedure TBoldDirectMultiLinkController.PrepareClear; OwningObjectList.EnsureObjects; end; +procedure TBoldDirectMultiLinkController.Exchange(Index1, Index2: integer); +begin + LocatorList.Exchange(Index1, Index2); +end; + procedure TBoldDirectMultiLinkController.Resort; begin BoldSort(0, LocatorList.Count - 1, CompareOrderNo, Exchange); @@ -948,11 +1198,11 @@ function TBoldDirectMultiLinkController.IsInOrder: Boolean; OrderNo1, OrderNo2: integer; begin Result := True; - if OwningObjectList.BoldRoleRTInfo.IsOrdered then + if RoleRTInfo.IsOrdered then for i:= 0 to LocatorList.Count - 2 do begin - OrderNo1 := GetOtherEndController(LocatorList[i]).FOrderno; - OrderNo2 := GetOtherEndController(LocatorList[i + 1]).FOrderno; + OrderNo1 := GetOtherEndController(LocatorList[i]).GetOrderno; + OrderNo2 := GetOtherEndController(LocatorList[i + 1]).GetOrderno; Result := (OrderNo1 <= OrderNo2); if not Result then Exit; @@ -963,19 +1213,14 @@ function TBoldDirectMultiLinkController.CompareOrderNo(Index1, Index2: integer): var OrderNo1, OrderNo2: integer; begin - if OwningObjectList.BoldRoleRTInfo.RoleRTInfoOfOtherEnd.IsSingleRole then + if RoleRTInfo.RoleRTInfoOfOtherEnd.IsSingleRole then begin - OrderNo1 := GetOtherEndController(LocatorList[Index1]).FOrderNo; - OrderNo2 := GetOtherEndController(LocatorList[Index2]).FOrderNo; + OrderNo1 := GetOtherEndController(LocatorList[Index1]).GetOrderNo; + OrderNo2 := GetOtherEndController(LocatorList[Index2]).GetOrderNo; Result := (OrderNo1 - OrderNo2); end else - raise EBold.Create(sOtherEndMustBeSingle); -end; - -procedure TBoldDirectMultiLinkController.Exchange(Index1, Index2: integer); -begin - LocatorList.Exchange(Index1, Index2); + raise EBold.Create('Cannot call compare if OtherEnd is not a single role'); end; procedure TBoldDirectMultiLinkController.ClearNoLongerReferring(NewList: TBoldObjectIdList); @@ -991,14 +1236,18 @@ procedure TBoldDirectMultiLinkController.ClearNoLongerReferring(NewList: TBoldOb OtherEndController: TBoldDirectSingleLinkController; Locator: TBoldObjectLocator; OwnLocator: TBoldObjectLocator; + BoldSystem: TBoldSystem; + TopSortedClasses: TBoldClassTypeInfoList; begin G := TBoldGuard.Create(Traverser); + BoldSystem := self.BoldSystem; Traverser := BoldSystem.Locators.CreateTraverser; - OwnLocator := OwningMember.OwningObject.BoldObjectLocator; - while not Traverser.EndOfList do + OwnLocator := OwningList.OwningObject.BoldObjectLocator; + TopSortedClasses := BoldSystem.BoldSystemTypeInfo.TopSortedClasses; + while Traverser.MoveNext do begin Locator := Traverser.Locator; - if BoldSystem.BoldSystemTypeInfo.TopSortedClasses[Locator.BoldObjectId.TopSortedIndex].BoldIsA(BoldClassTypeInfoOfOtherEnd) then // + if Locator.BoldClassTypeInfo.BoldIsA(BoldClassTypeInfoOfOtherEnd) then begin if assigned(Locator.BoldObject) then begin @@ -1015,7 +1264,6 @@ procedure TBoldDirectMultiLinkController.ClearNoLongerReferring(NewList: TBoldOb else if (EmbeddedIndex <> -1) and (Locator.EmbeddedSingleLinks[EmbeddedIndex] = OwnLocator) then ObjectList.AddLocator(Locator); end; - Traverser.Next; end; end; @@ -1026,9 +1274,9 @@ procedure TBoldDirectMultiLinkController.ClearNoLongerReferring(NewList: TBoldOb OtherEndController: TBoldDirectSingleLinkController; begin Assert(Assigned(NewList)); - EmbeddedIndex := OwningObjectList.BoldRoleRtInfo.RoleRTInfoOfOtherEnd.EmbeddedLinkIndex; - IndexOfOtherEnd := OwningObjectList.BoldRoleRtInfo.IndexOfOtherEnd; - BoldClassTypeInfoOfOtherEnd := OwningObjectList.BoldRoleRtInfo.ClassTypeInfoOfOtherEnd; + EmbeddedIndex := RoleRTInfo.RoleRTInfoOfOtherEnd.EmbeddedLinkIndex; + IndexOfOtherEnd := RoleRTInfo.IndexOfOtherEnd; + BoldClassTypeInfoOfOtherEnd := RoleRTInfo.ClassTypeInfoOfOtherEnd; if (OwningList.BoldPersistenceState = bvpsCurrent) then ListOfReferring := OwningObjectList else @@ -1049,21 +1297,21 @@ procedure TBoldDirectMultiLinkController.ClearNoLongerReferring(NewList: TBoldOb OtherEndController := GetOtherEndController(aLocator); if Assigned(OtherEndController) then begin - Assert(OtherEndController.OwningMember.BoldPersistenceState in [bvpsCurrent, bvpsInvalid]); + Assert(OtherEndController.OwningReference.BoldPersistenceState in [bvpsCurrent, bvpsInvalid]); OtherEndController.FLocator := nil; - if OtherEndController.OwningMember.BoldPersistenceState <> bvpsInvalid then + if OtherEndController.OwningReference.BoldPersistenceState <> bvpsInvalid then begin - OtherEndController.OwningMember.BoldPersistenceState := bvpsInvalid; - OtherEndController.OwningMember.SendEvent(beValueInvalid); + OtherEndController.OwningReference.BoldPersistenceState := bvpsInvalid; + OtherEndController.OwningReference.SendEvent(beValueInvalid); end; OtherEndController.OwningReference.HasOldValues := false; end - else // member for other end not instantiated. + else begin - EmbeddedIndex := OwningObjectList.BoldRoleRtInfo.RoleRTInfoOfOtherEnd.EmbeddedLinkIndex; + EmbeddedIndex := RoleRTInfo.RoleRTInfoOfOtherEnd.EmbeddedLinkIndex; if (EmbeddedIndex <> -1) and (aLocator.EmbeddedSingleLinks[EmbeddedIndex] <> nil) then begin - Assert(aLocator.EmbeddedSingleLinks[EmbeddedIndex] = OwningMember.OwningObject.BoldObjectLocator); + Assert(aLocator.EmbeddedSingleLinks[EmbeddedIndex] = OwningObjectList.OwningObject.BoldObjectLocator); aLocator.EmbeddedSingleLinks[EmbeddedIndex] := nil; end; end; @@ -1082,7 +1330,7 @@ procedure TBoldDirectMultiLinkController.Clear; try BoldClearLastFailure; if not StartModify then - BoldRaiseLastFailure(OwningList, 'Clear', ''); // do not localize + BoldRaiseLastFailure(OwningList, 'Clear', ''); PreChange; while count > 0 do @@ -1109,17 +1357,21 @@ procedure TBoldDirectSingleLinkController.AddToOtherEnd(Mode: TBoldLinkUnlinkMod OtherEndController: TBoldAbstractController; begin OtherEndController := GetOtherEndController(fLocator, Mode <> blulMarkAdjusted); - if Assigned(OtherEndController) and ((Mode <> blulMarkAdjusted) or (OtherEndController.OwningMember.BoldPersistenceState = bvpsCurrent)) then + if Assigned(OtherEndController) and ((Mode <> blulMarkAdjusted) or (OtherEndController.OwningMember.BoldPersistenceState = bvpsCurrent)) then OtherEndController.linkto(OwningReference.OwningObject.BoldObjectLocator, Mode <> blulMarkAdjusted, Mode); end; -procedure TBoldDirectSingleLinkController.SetAndModifyOrderNo(index: Integer); +function TBoldOrderedDirectSingleLinkController.GetOrderNo: Integer; +begin + Result := fOrderNo; +end; + +procedure TBoldOrderedDirectSingleLinkController.SetAndModifyOrderNo(index: Integer); begin - // Note: Setting Orderno does not send a message, but does make member modified. if index <> FOrderno then begin if not StartModify then - BoldRaiseLastFailure(OwningReference, 'SetAndModifyOrderNo', ''); // do not localize + BoldRaiseLastFailure(OwningReference, 'SetAndModifyOrderNo', ''); PreChange; fOrderNo := Index; EndModify; @@ -1138,19 +1390,19 @@ function TBoldDirectSingleLinkController.GetOtherEndController(aLocator: TBoldOb result := nil; if not assigned(aLocator) then exit; - if OwningReference.BoldRoleRtInfo.IndexOfOtherEnd = -1 then + if RoleRTInfo.IndexOfOtherEnd = -1 then exit; - if AllowForceOtherEnd and OwningReference.BoldRoleRtInfo.ForceOtherEnd then + if AllowForceOtherEnd and RoleRTInfo.ForceOtherEnd then begin aLocator.EnsureBoldObject; - aLocator.BoldObject.BoldMembers[OwningReference.BoldRoleRtInfo.IndexOfOtherEnd].EnsureContentsCurrent; + aLocator.BoldObject.BoldMembers[RoleRTInfo.IndexOfOtherEnd].EnsureContentsCurrent; end; if not assigned(aLocator.BoldObject) then exit; - aMember := aLocator.BoldObject.BoldMembers[OwningReference.BoldRoleRtInfo.IndexOfOtherEnd]; + aMember := aLocator.BoldObject.BoldMembers[RoleRTInfo.IndexOfOtherEnd]; if aMember.BoldPersistenceState = bvpsInvalid then exit; @@ -1163,12 +1415,12 @@ procedure TBoldDirectSingleLinkController.LinkTo(NewLocator: TBoldObjectLocator; BoldClearLastFailure; if Mode = blulMarkModified then if not StartModify then - BoldRaiseLastFailure(OwningReference, 'linkto', ''); // do not localize + BoldRaiseLastFailure(OwningReference, 'linkto', ''); if fLocator <> NewLocator then begin RemoveFromOtherEnd(Mode); InternalSetLocator(NewLocator); - if OwningMember.BoldPersistenceState = bvpsInvalid then + if OwningReference.BoldPersistenceState = bvpsInvalid then OwningReference.HasOldValues := True; end; if Mode = blulMarkModified then @@ -1180,7 +1432,7 @@ procedure TBoldDirectSingleLinkController.RemoveFromOtherEnd(Mode: TBoldLinkUnli OtherEndController: TBoldAbstractController; OldLocatorRelevant: Boolean; begin - OldLocatorRelevant := ((OwningMember.BoldPersistenceState <> bvpsInvalid) or OwningReference.HasOldValues); + OldLocatorRelevant := ((OwningReference.BoldPersistenceState <> bvpsInvalid) or OwningReference.HasOldValues); if OldLocatorRelevant then begin OtherEndController := GetOtherEndController(fLocator, Mode <> blulMarkAdjusted); @@ -1191,6 +1443,7 @@ procedure TBoldDirectSingleLinkController.RemoveFromOtherEnd(Mode: TBoldLinkUnli procedure TBoldDirectSingleLinkController.SetFromId(Id: TBoldObjectId; Mode: TBoldDomainElementProxyMode); var + BoldSystem: TBoldSystem; NewLocator: TBoldObjectLocator; procedure SafeCopyOptimisticValues; @@ -1199,20 +1452,19 @@ procedure TBoldDirectSingleLinkController.SetFromId(Id: TBoldObjectId; Mode: TBo begin Value := NewValueInOptimisticLocking as IBoldObjectIdRef; if Assigned(Value) then - Value.SetFromId(Id); + Value.SetFromId(Id, false); end; - // Adjust Newlocator procedure AdjustNewLocator; var i: integer; obj: TBoldObject; OtherEndController: TBoldAbstractController; begin - // check if link modified at other (embedded) end - for i := 0 to OwningMember.BoldSystem.DirtyObjects.Count - 1 do + BoldSystem := self.BoldSystem; + for i := 0 to BoldSystem.DirtyObjects.Count - 1 do begin - Obj := TBoldObject(OwningMember.BoldSystem.DirtyObjects[i]); - if Obj.BoldClassTypeInfo.Conformsto(OwningReference.BoldRoleRTInfo.ClassTypeInfoOfOtherEnd) then + Obj := TBoldObject(BoldSystem.DirtyObjects[i]); + if Obj.BoldClassTypeInfo.Conformsto(RoleRTInfo.ClassTypeInfoOfOtherEnd) then begin OtherEndController := GetOtherEndController(Obj.BoldObjectLocator, false); if (OtherEndController is TBoldDirectSingleLinkController) and @@ -1229,19 +1481,22 @@ procedure TBoldDirectSingleLinkController.SetFromId(Id: TBoldObjectId; Mode: TBo var LinkUnlinkMode: TBoldLinkUnlinkMode; begin - if (mode = bdepPMIn) and (OwningMember.OwningObject.BoldObjectLocator.BoldObjectId.TimeStamp <> BOLDMAXTIMESTAMP) then // fetching old temporal versi + if (mode = bdepPMIn) and (OwningReference.OwningObject.IsHistoricVersion) then mode := bdepContents; NewLocator := LocatorForId(Id); - if (mode = bdepPMIn) and not OwningReference.BoldRoleRTInfo.IsStoredInObject then // non-embedded end of 1-1 + if (mode = bdepPMIn) and not RoleRTInfo.IsStoredInObject then AdjustNewLocator; if Mode = bdepPmIn then LinkUnlinkMode := blulMarkAdjusted else LinkUnlinkMode := blulNone; - if ((OwningMember.BoldPersistenceState = bvpsInvalid) and not OwningReference.HasOldValues) or (fLocator <> NewLocator) then + if ((OwningReference.BoldPersistenceState = bvpsInvalid) and not OwningReference.HasOldValues) or (fLocator <> NewLocator) then begin + if Assigned(NewLocator) then + if not VerifyLocatorType(NewLocator, OwningReference.BoldRoleRTInfo.ClassTypeInfoOfOtherEnd, false) then + raise EBold.CreateFmt('%s.SetFromId: Object %s is incorrect type %s in %s. Expected type: %s', [ClassName, NewLocator.AsString, NewLocator.BoldClassTypeInfo.ExpressionName, OwningReference.debuginfo, OwningReference.BoldRoleRTInfo.ClassTypeInfoOfOtherEnd.ExpressionName]); if mode <> bdepInternalInitialize then PreChange; if mode in [bdepPMIn, bdepUndo] then @@ -1255,22 +1510,22 @@ procedure TBoldDirectSingleLinkController.SetFromId(Id: TBoldObjectId; Mode: TBo procedure TBoldDirectSingleLinkController.SetLocator(NewLocator: TBoldObjectLocator); begin - OwningMember.BoldSystem.StartTransaction; + BoldSystem.StartTransaction; try BoldClearLastFailure; if not StartModify then - BoldRaiseLastFailure(OwningReference, 'SetLocator', ''); // do not localize + BoldRaiseLastFailure(OwningReference, 'SetLocator', ''); - GetOtherEndController(NewLocator, True); // Makes sure other end is fetched if needed before changing this end + GetOtherEndController(NewLocator, True); RemoveFromOtherEnd(blulMarkModified); InternalSetLocator(NewLocator); AddToOtherEnd(blulMarkModified); - if not Assigned(fLocator) then + if not Assigned(fLocator) and RoleRTInfo.IsOrdered then SetAndModifyOrderNo(-1); EndModify; - OwningReference.BoldSystem.CommitTransaction; + BoldSystem.CommitTransaction; except - OwningReference.BoldSystem.RollbackTransaction; + BoldSystem.RollbackTransaction; raise; end; end; @@ -1279,6 +1534,9 @@ procedure TBoldDirectSingleLinkController.InternalSetLocator(NewLocator: TBoldOb begin if fLocator <> NewLocator then begin + if Assigned(NewLocator) then + if not VerifyLocatorType(NewLocator, OwningReference.BoldRoleRTInfo.ClassTypeInfoOfOtherEnd, false) then + raise EBold.CreateFmt('%s.InternalSetLocator: Object %s is incorrect type %s in %s. Expected type: %s', [ClassName, NewLocator.AsString, NewLocator.BoldClassTypeInfo.ExpressionName, OwningReference.debuginfo, OwningReference.BoldRoleRTInfo.ClassTypeInfoOfOtherEnd.ExpressionName]); PreChange; fLocator := NewLocator; Changed(beValueChanged, [NewLocator]); @@ -1290,19 +1548,52 @@ function TBoldDirectSingleLinkController.GetStreamName: String; Result := BoldContentName_ObjectIdRef; end; +function TBoldDirectSingleLinkController.GetFreeStandingClass: TBoldFreeStandingElementClass; +begin + result := TBFSObjectIdRef; +end; + procedure TBoldDirectSingleLinkController.Unlink(OldLocator: TBoldObjectLocator; Mode: TBoldLinkUnlinkMode); begin - Assert((Mode <> blulMarkAdjusted) or (Owningmember.BoldPersistenceState = bvpsCurrent)); - Assert(Not assigned(fLocator) or (fLocator = OldLocator)); +// Assert removed, remains to be verified if it causes other problems, so we log instead +// Assert((Mode <> blulMarkAdjusted) or (Owningmember.BoldPersistenceState = bvpsCurrent), OwningMember.DisplayName); + if not ((Mode <> blulMarkAdjusted) or (OwningReference.BoldPersistenceState = bvpsCurrent)) then + begin + BoldLog.LogFmt('TBoldDirectSingleLinkController.Unlink: BoldObjectId: %s, Mode: %s Member: %s, MemberPersistenceState: %s. OldLocator: %s; HasOldValues = %s', + [ + OwningMember.OwningObject.BoldObjectLocator.AsString, + TypInfo.GetEnumName(TypeInfo(TBoldLinkUnlinkMode), Ord(Mode)), + OwningMember.DisplayName, + TypInfo.GetEnumName(TypeInfo(TBoldValuePersistenceState), Ord(Owningmember.BoldPersistenceState)), + OldLocator.AsString, + BoolToStr(OwningReference.HasOldValues,True)]); + end; + if (Mode=blulMarkAdjusted) and (fLocator<>OldLocator) then //PATCH + begin + exit; //PATCH + end; + //The prevoius assert prevents unlink to work when controller is bvpsInvalid + //Current implementation of GetOtherEndController never return Invaild Members so this it not a problem + //But if the other end has fetched a new value from db and is current GetOtherEndController will return it + //This will lead to data corruption - Unlink will set correct value to nil! + +// Assert(Not assigned(fLocator) or (fLocator = OldLocator)); BoldClearLastFailure; if Mode = blulMarkModified then if not StartModify then - BoldRaiseLastFailure(OwningReference, 'Unlink', ''); // do not localize + BoldRaiseLastFailure(OwningReference, 'Unlink', ''); InternalSetLocator(nil); OwningReference.HasOldValues := False; - SetAndModifyOrderNo(-1); + + if RoleRTInfo.IsOrdered then + begin + if Mode = blulMarkModified then //PATCH + SetAndModifyOrderNo(-1) + else //PATCH + SetOrderNo(-1, bdepPMIn); //PATCH Do not call SetAndModifyOrderNo when Mode is bluMarkAdjustd - this creates an unwanted save + end; if Mode = blulMarkModified then EndModify; end; @@ -1316,15 +1607,10 @@ procedure TBoldDirectSingleLinkController.PreDiscard; begin OtherEndController := GetOtherEndController(Locator, false); if assigned(OtherEndController) and - not OtherEndController.OwningMember.BoldMemberRTInfo.IsStoredInObject and - not OtherEndController.OwningMember.OwningObject.BoldObjectIsNew then + not OtherEndController.RoleRTInfo.IsStoredInObject and + not OtherEndController.OwningObject.BoldObjectIsNew then begin - // normally, the other end will be a multilink, and not dirty, but if the - // other end is either a singlelink (single-single) or a multilink and the - // system is using an XML-Persistence (MultilinksAreStoredInObject) then we - // hope that the other end will be discarded separately. - if not OtherEndController.OwningMember.BoldDirty then - OtherEndController.OwningMember.Invalidate; + OtherEndController.OwningMember.Invalidate; end; end; end; @@ -1333,32 +1619,29 @@ procedure TBoldDirectSingleLinkController.PreDiscard; OldRef: IBoldValue; OldIdRef: IBoldObjectIdRef; begin - // remove the owningobject from the other end RemoveFromOtherEnd(blulNone); - - // Invalidate the old other end if it exists and is loaded OldRef := OwningReference.OldValue; if assigned(OldRef) then begin - // The OldValue must be an ObjectIdRef since this is a direct singlelink controller OldRef.QueryInterface(IBoldObjectIdRef, OldIdRef); if assigned(OldIdRef.Id) then - InvalidateNonembeddedOtherEnd(OwningReference.BoldSystem.EnsuredLocatorByID[OldIdRef.Id]); + InvalidateNonembeddedOtherEnd(BoldSystem.EnsuredLocatorByID[OldIdRef.Id]); end; + fLocator := nil; end; -function TBoldDirectSingleLinkController.ProxyClass: TBoldMember_ProxyClass; +function TBoldDirectSingleLinkController.GetProxy(Member: TBoldMember; Mode: TBoldDomainElementProxyMode): TBoldMember_Proxy; begin - result := TBoldDirectSingleLinkController_Proxy; + result := TBoldDirectSingleLinkController_Proxy.MakeProxy(Member ,Mode); end; function TBoldDirectSingleLinkController.ProxyInterface(const IId: TGUID; Mode: TBoldDomainElementProxyMode; out Obj): Boolean; begin if IsEqualGuid(IID, IBoldObjectIdRef) then begin - result := ProxyClass.create(self.OwningReference, Mode).GetInterface(IID, obj); + result := GetProxy(self.OwningReference, Mode).GetInterface(IID, obj); if not result then - raise EBoldInternal.CreateFmt('ProxyClass for %s did not implement IBoldObjectIdRef', [ClassName]); // do not localize + raise EBoldInternal.CreateFmt('ProxyClass for %s did not implement IBoldObjectIdRef', [ClassName]); end else result := inherited ProxyInterface(IID, Mode, Obj); @@ -1366,16 +1649,81 @@ function TBoldDirectSingleLinkController.ProxyInterface(const IId: TGUID; Mode: function TBoldDirectSingleLinkController.MayUpdate: Boolean; begin - result := not OwningReference.BoldRoleRTInfo.IsStoredInObject or + result := not RoleRTInfo.IsStoredInObject or not assigned(fLocator) or fLocator.ObjectIsPersistent; end; procedure TBoldDirectSingleLinkController.MakeDbCurrent; +{$IFDEF FetchFromClassList} + procedure FetchFromClassList; + var + BoldRoleRTInfo: TBoldRoleRTInfo; + OtherEndBoldClassTypeInfo: TBoldClassTypeInfo; + ClassList: TBoldObjectList; + BoldObjectId: TBoldObjectId; + BoldObject: TBoldObject; + IndexOfOtherEnd: Integer; + BoldObjectReference: TBoldObjectReference; + BoldMember: TBoldMember; + i: integer; + Locator: TBoldObjectLocator; + CheckType: boolean; + lTopSortedIndex: Integer; + lTopSortedClasses: TBoldClassTypeInfoList; + AllMembersLoaded: boolean; + begin + OtherEndBoldClassTypeInfo := RoleRTInfo.ClassTypeInfoOfOtherEnd; + IndexOfOtherEnd := RoleRTInfo.IndexOfOtherEnd; + lTopSortedIndex := RoleRTInfo.ClassTypeInfoOfOtherEnd.TopSortedIndex; + ClassList := BoldSystem.Classes[lTopSortedIndex]; + lTopSortedClasses := BoldSystem.BoldSystemTypeInfo.TopSortedClasses; + Locator := OwningReference.OwningObject.BoldObjectLocator; + BoldObjectId := nil; + CheckType := ClassList.BoldPersistenceState <> bvpsCurrent; + AllMembersLoaded := true; + if CheckType then + ClassList := TBoldClassListController(GetControllerForMember(ClassList)).ClosestLoadedClassList; + for i := ClassList.Count - 1 downto 0 do + begin + if CheckType and ((ClassList.Locators[i].BoldObjectID.TopSortedIndex < lTopSortedIndex) or + not ClassList.Locators[i].BoldClassTypeInfo.BoldIsA(OtherEndBoldClassTypeInfo)) then + Continue; + BoldMember := ClassList[i].BoldMemberIfAssigned[IndexOfOtherEnd]; + if Assigned(BoldMember) then + begin + if ((BoldMember as TBoldObjectReference).Locator = Locator) then + begin + BoldObjectId := ClassList[i].BoldObjectLocator.BoldObjectId; + break; + end; + end + else + AllMembersLoaded := false; + end; + if Assigned(BoldObjectId) or AllMembersLoaded then + begin + SetFromId(BoldObjectId, bdepContents); + OwningReference.BoldPersistenceState := bvpsCurrent; + end + else + begin + DbFetchOwningMember; + end; + end; +{$ENDIF} begin - DbFetchOwningMember; +{$IFDEF FetchFromClassList} + if RoleRTInfo.RoleRTInfoOfOtherEnd.IsSingleRole and + TBoldClassListController(GetControllerForMember(BoldSystem.Classes[RoleRTInfo.ClassTypeInfoOfOtherEnd.TopSortedIndex])).IsCurrentOrSuperClassIsCurrent then + begin + FetchFromClassList; + exit; + end; +{$ENDIF} + DbFetchOwningMember; end; -procedure TBoldDirectSingleLinkController.SetOrderNo(NewOrderNo: Integer; +procedure TBoldOrderedDirectSingleLinkController.SetOrderNo(NewOrderNo: Integer; Mode: TBoldDomainElementProxyMode); var OtherEndController: TBoldAbstractController; @@ -1391,6 +1739,22 @@ procedure TBoldDirectSingleLinkController.SetOrderNo(NewOrderNo: Integer; { TBoldIndirectSingleLinkController } +function TBoldIndirectSingleLinkController.GetLinkObjectOwnLinkController(LinkObject: TBoldObject): TBoldLinkObjectSingleLinkController; +begin + result := GetControllerForMember(LinkObject.BoldMembers[RoleRTInfo.OwnIndexInLinkClass]) as TBoldLinkObjectSingleLinkController; +end; + +function TBoldIndirectSingleLinkController.GetLinkObjectOtherLinkController( + LinkObject: TBoldObject): TBoldLinkObjectSingleLinkController; +begin + result := GetControllerForMember(LinkObject.BoldMembers[RoleRTInfo.OtherIndexInLinkClass]) as TBoldLinkObjectSingleLinkController; +end; + +function TBoldIndirectSingleLinkController.GetLinkObjectRoleController: TBoldLinkObjectReferenceController; +begin + result := ControllerForLinkRole as TBoldLinkObjectReferenceController; +end; + procedure TBoldIndirectSingleLinkController.DeleteLink(Mode: TBoldLinkUnlinkMode); var OldLinkObject: TBoldObject; @@ -1407,11 +1771,6 @@ procedure TBoldIndirectSingleLinkController.DeleteLink(Mode: TBoldLinkUnlinkMode end; end; -function TBoldIndirectSingleLinkController.GetLinkObjectOwnLinkController(LinkObject: TBoldObject): TBoldLinkObjectSingleLinkController; -begin - result := GetControllerForMember(LinkObject.BoldMembers[OwningReference.BoldRoleRtInfo.OwnIndexInLinkClass]) as TBoldLinkObjectSingleLinkController; -end; - function TBoldIndirectSingleLinkController.GetLocator: TBoldObjectLocator; begin result := fOtherEndLocator; @@ -1419,11 +1778,11 @@ function TBoldIndirectSingleLinkController.GetLocator: TBoldObjectLocator; procedure TBoldIndirectSingleLinkController.linkto(NewLocator: TBoldObjectLocator; updateOrderNo: Boolean; Mode: TBoldLinkUnlinkMode); begin - Assert((Mode <> blulMarkAdjusted) or (Owningmember.BoldPersistenceState = bvpsCurrent)); + Assert((Mode <> blulMarkAdjusted) or (OwningReference.BoldPersistenceState = bvpsCurrent), OwningMember.DisplayName); BoldClearLastFailure; if Mode = blulMarkModified then if not StartModify then - BoldRaiseLastFailure(OwningReference, 'Linkto', ''); // do not localize + BoldRaiseLastFailure(OwningReference, 'Linkto', ''); if fLinkObjectLocator <> NewLocator then begin @@ -1432,6 +1791,8 @@ procedure TBoldIndirectSingleLinkController.linkto(NewLocator: TBoldObjectLocato PreChange; fLinkObjectLocator := NewLocator; fOtherEndLocator := GetLinkObjectOtherLinkController(NewLocator.EnsuredBoldObject).fLocator; + if not VerifyLocatorType(fOtherEndLocator, OwningReference.BoldRoleRTInfo.ClassTypeInfoOfOtherEnd, false) then + raise EBold.CreateFmt('%s.linkto: Object %s is incorrect type %s in %s. Expected type: %s', [ClassName, fOtherEndLocator.AsString, fOtherEndLocator.BoldClassTypeInfo.ExpressionName, OwningReference.debuginfo, OwningReference.BoldRoleRTInfo.ClassTypeInfoOfOtherEnd.ExpressionName]); end; Changed(beValueChanged, [fOtherEndLocator]); GetLinkObjectRoleController.Changed(beValueChanged, [fLinkObjectLocator]); @@ -1440,15 +1801,35 @@ procedure TBoldIndirectSingleLinkController.linkto(NewLocator: TBoldObjectLocato end; function TBoldIndirectSingleLinkController.NewLink(OtherLocator: TBoldObjectLocator; Mode: TBoldLinkUnlinkMode): TBoldObject; +{$IFDEF ReuseDeletedLinkObjectOnRelink} + function FindLinkInOldValues: TBoldObject; + var + s: IBoldObjectIdRefPair; + begin + result := nil; + if Supports(OwningReference.OldValue, IBoldObjectIdRefPair, s) and Assigned(s.Id2) then + if s.Id2.IsEqual[OtherLocator.BoldObjectID] then + begin + result := BoldSystem.Locators.ObjectByID[s.Id1]; + Assert(result is RoleRTInfo.LinkClassTypeInfo.ObjectClass); + result.AsIBoldObjectContents[bdepContents].BoldExistenceState := besExisting; + result.AsIBoldObjectContents[bdepContents].BoldPersistenceState := bvpsCurrent; + end; + end; +{$ENDIF} var LinkObject: TBoldObject; LinkClassTypeInfo: TBoldClassTypeinfo; OtherEndController: TBoldAbstractController; begin - LinkClassTypeInfo := OwningReference.BoldRoleRTInfo.LinkClassTypeInfo; - LinkObject := TBoldObjectClass(LinkClassTypeInfo.ObjectClass).InternalCreateNewWithClassAndSystem(LinkClassTypeInfo, OwningReference.BoldSystem, + LinkClassTypeInfo := RoleRTInfo.LinkClassTypeInfo; +{$IFDEF ReuseDeletedLinkObjectOnRelink} + LinkObject := FindLinkInOldValues; + if not Assigned(LinkObject) then +{$ENDIF} + LinkObject := TBoldObjectClass(LinkClassTypeInfo.ObjectClass).InternalCreateNewWithClassAndSystem(LinkClassTypeInfo, BoldSystem, OtherLocator.ObjectIsPersistent and OwningReference.OwningObject.BoldPersistent); - OtherEndController := GetLinkObjectOtherLinkController(LinkObject).GetOtherEndController(OtherLocator, true); // Ensure other end fetched if forced + OtherEndController := GetLinkObjectOtherLinkController(LinkObject).GetOtherEndController(OtherLocator, true); GetLinkObjectOwnLinkController(LinkObject).LinkTo(OwningReference.OwningObject.BoldObjectLocator, true, Mode); GetLinkObjectOtherLinkController(LinkObject).LinkTo(OtherLocator, true, Mode); if Assigned(OtherEndController) then @@ -1468,17 +1849,16 @@ procedure TBoldIndirectSingleLinkController.SetFromIds(Id1, Id2: TBoldObjectId; if Assigned(Value) then Value.SetFromIds(Id1, Id2); end; - - // Adjust NewLinkLocator and NewOtherEndLocator procedure AdjustLocators; var BoldObject: TBoldObject; i: integer; BoldLinkClassTypeInfo: TBoldClassTypeInfo; IndexOfOwnEnd, IndexOfOtherEnd, EmbeddedIndexOfOwnEnd, EmbeddedIndexOfOtherEnd: integer; + BoldSystem: TBoldSystem; begin - IndexOfOwnEnd := OwningReference.BoldRoleRTInfo.OwnIndexInLinkClass; - IndexOfOtherEnd := OwningReference.BoldRoleRTInfo.OtherIndexInLinkClass; + IndexOfOwnEnd := RoleRTInfo.OwnIndexInLinkClass; + IndexOfOtherEnd := RoleRTInfo.OtherIndexInLinkClass; if Assigned(NewLinkLocator) then begin BoldObject := NewLinkLocator.BoldObject; @@ -1491,25 +1871,26 @@ procedure TBoldIndirectSingleLinkController.SetFromIds(Id1, Id2: TBoldObjectId; NewOtherEndLocator := nil; end end - else {object not loaded, set embedded links} { TODO : Is this really related to adjust? } + else {object not loaded, set embedded links} begin if Assigned(NewLinkLocator) then begin - EmbeddedIndexOfOwnEnd := OwningReference.BoldRoleRTInfo.LinkClassTypeInfo.AllMembers[IndexOfOwnEnd].EmbeddedLinkIndex; - EmbeddedIndexOfOtherEnd := OwningReference.BoldRoleRTInfo.LinkClassTypeInfo.AllMembers[IndexOfOtherEnd].EmbeddedLinkIndex; + EmbeddedIndexOfOwnEnd := RoleRTInfo.LinkClassTypeInfo.AllMembers[IndexOfOwnEnd].EmbeddedLinkIndex; + EmbeddedIndexOfOtherEnd := RoleRTInfo.LinkClassTypeInfo.AllMembers[IndexOfOtherEnd].EmbeddedLinkIndex; if (EmbeddedIndexOfOwnEnd <> -1) then - NewLinkLocator.EmbeddedSingleLinks[EmbeddedIndexOfOwnEnd] := OwningMember.OwningObject.BoldObjectLocator; + NewLinkLocator.EmbeddedSingleLinks[EmbeddedIndexOfOwnEnd] := OwningReference.OwningObject.BoldObjectLocator; if (EmbeddedIndexOfOtherEnd <> -1) then NewLinkLocator.EmbeddedSingleLinks[EmbeddedIndexOfOtherEnd] := NewOtherEndLocator; end; end; end; - for I := 0 to OwningMember.BoldSystem.DirtyObjects.Count - 1 do + BoldSystem := self.BoldSystem; + for I := 0 to BoldSystem.DirtyObjects.Count - 1 do begin - BoldLinkClassTypeInfo := OwningReference.BoldRoleRtInfo.LinkClassTypeInfo; - BoldObject := OwningMember.BoldSystem.DirtyObjects[I]; + BoldLinkClassTypeInfo := RoleRTInfo.LinkClassTypeInfo; + BoldObject := BoldSystem.DirtyObjects[I]; if (BoldObject.BoldClassTypeInfo.BoldIsA(BoldLinkClassTypeInfo)) and (BoldObject.BoldExistenceState = besExisting) and - (((BoldObject.BoldMembers[IndexOfOwnEnd]) as TBoldObjectReference).BoldObject = OwningMember.OwningObject) then + (((BoldObject.BoldMembers[IndexOfOwnEnd]) as TBoldObjectReference).BoldObject = OwningReference.OwningObject) then begin SafeCopyOptimisticValues; NewLinkLocator := BoldObject.BoldObjectLocator; @@ -1519,7 +1900,7 @@ procedure TBoldIndirectSingleLinkController.SetFromIds(Id1, Id2: TBoldObjectId; end; begin - if (mode = bdepPMIn) and (OwningMember.OwningObject.BoldObjectLocator.BoldObjectId.TimeStamp <> BOLDMAXTIMESTAMP) then // fetching old temporal versi + if (mode = bdepPMIn) and (OwningReference.OwningObject.IsHistoricVersion) then mode := bdepContents; NewLinkLocator := LocatorForId(Id1); NewOtherEndLocator := LocatorForId(Id2); @@ -1528,6 +1909,9 @@ procedure TBoldIndirectSingleLinkController.SetFromIds(Id1, Id2: TBoldObjectId; if fLinkObjectLocator <> NewLinkLocator then begin + if Assigned(NewOtherEndLocator) then + if not VerifyLocatorType(NewOtherEndLocator, OwningReference.BoldRoleRTInfo.ClassTypeInfoOfOtherEnd, false) then + raise EBold.CreateFmt('%s.SetFromIds: Object %s is incorrect type %s in %s. Expected type: %s', [ClassName, NewOtherEndLocator.AsString, NewOtherEndLocator.BoldClassTypeInfo.ExpressionName, OwningReference.debuginfo, OwningReference.BoldRoleRTInfo.ClassTypeInfoOfOtherEnd.ExpressionName]); PreChange; fLinkObjectLocator := NewLinkLocator; fOtherEndLocator := NewOtherEndLocator; @@ -1540,12 +1924,15 @@ procedure TBoldIndirectSingleLinkController.SetLocator(NewLocator: TBoldObjectLo begin if NewLocator = fLinkObjectLocator then exit; - - OwningReference.BoldSystem.StartTransaction; + BoldSystem.StartTransaction; try BoldClearLastFailure; if not StartModify then - BoldRaiseLastFailure(OwningReference, 'SetLocator', ''); // do not localize + BoldRaiseLastFailure(OwningReference, 'SetLocator', ''); + + if Assigned(NewLocator) then + if not VerifyLocatorType(NewLocator, OwningReference.BoldRoleRTInfo.ClassTypeInfoOfOtherEnd, false) then + raise EBold.CreateFmt('%s.SetLocator: Object %s is incorrect type %s in %s. Expected type: %s', [ClassName, NewLocator.AsString, NewLocator.BoldClassTypeInfo.ExpressionName, OwningReference.debuginfo, OwningReference.BoldRoleRTInfo.ClassTypeInfoOfOtherEnd.ExpressionName]); DeleteLink(blulMarkModified); PreChange; @@ -1555,11 +1942,11 @@ procedure TBoldIndirectSingleLinkController.SetLocator(NewLocator: TBoldObjectLo else fLinkObjectLocator := nil; Changed(beValueChanged, [NewLocator]); - GetLinkObjectRoleController. Changed(beValueChanged, [fLinkObjectLocator]); + GetLinkObjectRoleController.Changed(beValueChanged, [fLinkObjectLocator]); EndModify; - OwningReference.BoldSystem.CommitTransaction; + BoldSystem.CommitTransaction; except - OwningReference.BoldSystem.RollbackTransaction; + BoldSystem.RollbackTransaction; raise; end; end; @@ -1569,14 +1956,19 @@ function TBoldIndirectSingleLinkController.GetStreamName: String; Result := BoldContentName_ObjectIdRefPair; end; +function TBoldIndirectSingleLinkController.GetFreeStandingClass: TBoldFreeStandingElementClass; +begin + result := TBFSObjectIdRefPair; +end; + procedure TBoldIndirectSingleLinkController.Unlink(OldLocator: TBoldObjectLocator; Mode: TBoldLinkUnlinkMode); begin - Assert((Mode <> blulMarkAdjusted) or (Owningmember.BoldPersistenceState = bvpsCurrent)); + Assert((Mode <> blulMarkAdjusted) or (OwningReference.BoldPersistenceState = bvpsCurrent), OwningMember.DisplayName); Assert(fLinkObjectLocator = OldLocator); BoldClearLastFailure; if Mode = blulMarkModified then if not StartModify then - BoldRaiseLastFailure(OwningReference, 'Unlink', ''); // do not localize + BoldRaiseLastFailure(OwningReference, 'Unlink', ''); PreChange; fLinkObjectLocator := nil; @@ -1587,23 +1979,18 @@ procedure TBoldIndirectSingleLinkController.Unlink(OldLocator: TBoldObjectLocato EndModify; end; -function TBoldIndirectSingleLinkController.GetLinkObjectRoleController: TBoldLinkObjectReferenceController; -begin - result := ControllerForLinkRole as TBoldLinkObjectReferenceController; -end; - -function TBoldIndirectSingleLinkController.ProxyClass: TBoldMember_ProxyClass; +function TBoldIndirectSingleLinkController.GetProxy(Member: TBoldMember; Mode: TBoldDomainElementProxyMode): TBoldMember_Proxy; begin - result := TBoldIndirectSingleLinkController_Proxy; + result := TBoldIndirectSingleLinkController_Proxy.MakeProxy(Member ,Mode); end; function TBoldIndirectSingleLinkController.ProxyInterface(const IId: TGUID; Mode: TBoldDomainElementProxyMode; out Obj): Boolean; begin if IsEqualGuid(IID, IBoldObjectIdRefPair) then begin - result := ProxyClass.create(self.OwningReference, Mode).GetInterface(IID, obj); + result := GetProxy(self.OwningReference, Mode).GetInterface(IID, obj); if not result then - raise EBoldInternal.CreateFmt('ProxyClass for %s did not implement IBoldObjectIdRefPair', [ClassName]); // do not localize + raise EBoldInternal.CreateFmt('ProxyClass for %s did not implement IBoldObjectIdRefPair', [ClassName]); end else result := inherited ProxyInterface(IID, Mode, Obj); @@ -1611,16 +1998,10 @@ function TBoldIndirectSingleLinkController.ProxyInterface(const IId: TGUID; Mode function TBoldIndirectSingleLinkController.MayUpdate: Boolean; begin - result := not OwningReference.BoldRoleRTInfo.IsStoredInObject or + result := not RoleRTInfo.IsStoredInObject or not assigned(fLinkObjectLocator) or fLinkObjectLocator.ObjectIsPersistent; end; -function TBoldIndirectSingleLinkController.GetLinkObjectOtherLinkController( - LinkObject: TBoldObject): TBoldLinkObjectSingleLinkController; -begin - result := GetControllerForMember(LinkObject.BoldMembers[OwningReference.BoldRoleRtInfo.OtherIndexInLinkClass]) as TBoldLinkObjectSingleLinkController; -end; - function TBoldIndirectSingleLinkController.AssertIntegrity: Boolean; begin if fLinkObjectLocator = nil then @@ -1631,14 +2012,11 @@ function TBoldIndirectSingleLinkController.AssertIntegrity: Boolean; if Assigned(fLinkObjectLocator.BoldObject) then begin Assert(fLinkObjectLocator.BoldObject.BoldExistenceState = besExisting); - Assert(GetLinkObjectOwnLinkController(fLinkObjectLocator.BoldObject).fLocator = OwningMember.OwningObject.BoldObjectLocator); + Assert(GetLinkObjectOwnLinkController(fLinkObjectLocator.BoldObject).fLocator = OwningReference.OwningObject.BoldObjectLocator); Assert(GetLinkObjectOtherLinkController(fLinkObjectLocator.BoldObject).fLocator = fOtherEndLocator); - { TODO : Check included in other end, if loaded. } end - else // link object no loaded + else begin - { TODO : Check values in locator itself } - { TODO : Check included in other end, if loaded. } end; end; Result := True; @@ -1651,6 +2029,16 @@ procedure TBoldIndirectSingleLinkController.MakeDbCurrent; { TBoldIndirectMultiLinkController } +function TBoldIndirectMultiLinkController.GetLinkObjectOwnLinkController(LinkObject: TBoldObject): TBoldLinkObjectSingleLinkController; +begin + result := GetControllerForMember(LinkObject.BoldMembers[RoleRTInfo.OwnIndexInLinkClass]) as TBoldLinkObjectSingleLinkController; +end; + +function TBoldIndirectMultiLinkController.GetLinkObjectListController: TBoldLinkObjectListController; +begin + result := ControllerForLinkMember as TBoldLinkObjectListController; +end; + procedure TBoldIndirectMultiLinkController.AddLocator(Locator: TBoldObjectLocator); var LinkObject: TBoldObject; @@ -1660,15 +2048,15 @@ procedure TBoldIndirectMultiLinkController.AddLocator(Locator: TBoldObjectLocato try BoldClearLastFailure; if not StartModify then - BoldRaiseLastFailure(OwningList, 'AddLocator', ''); // do not localize + BoldRaiseLastFailure(OwningList, 'AddLocator', ''); PreChange; LinkObject := NewLink(Locator, blulMarkModified); LinkLocatorList.Add(LinkObject.BoldObjectLocator); ReferredLocatorList.Add(Locator); Assert(ReferredLocatorList.Count = LinkLocatorList.Count); - if OwningObjectList.BoldRoleRtInfo.IsOrdered then - GetLinkObjectOwnLinkController(LinkObject).SetAndModifyOrderNo(LinkLocatorList.IndexOf(LinkObject.BoldObjectLocator)); // Complexity warning: A loop of adds will take O(n^2) + if RoleRTInfo.IsOrdered then + GetLinkObjectOwnLinkController(LinkObject).SetAndModifyOrderNo(LinkLocatorList.IndexOf(LinkObject.BoldObjectLocator)); Changed(beItemAdded, [Locator]); GetLinkObjectListController.Changed(beItemAdded, [LinkObject.BoldObjectLocator]); EndModify; @@ -1686,6 +2074,12 @@ constructor TBoldIndirectMultiLinkController.Create(OwningList: TBoldObjectList) FReferredList := TBoldObjectLocatorList.Create; end; +function TBoldIndirectMultiLinkController.GetLinkObjectOtherLinkController( + LinkObject: TBoldObject): TBoldLinkObjectSingleLinkController; +begin + result := GetControllerForMember(LinkObject.BoldMembers[RoleRTInfo.OtherIndexInLinkClass]) as TBoldLinkObjectSingleLinkController; +end; + procedure TBoldIndirectMultiLinkController.DeleteLink(LinkObjectLocator: TBoldObjectLocator; Mode: TBoldLinkUnlinkMode); var OldLinkObject: TBoldObject; @@ -1693,8 +2087,8 @@ procedure TBoldIndirectMultiLinkController.DeleteLink(LinkObjectLocator: TBoldOb OldLinkObject := LinkObjectLocator.EnsuredBoldObject; GetLinkObjectOtherLinkController(OldLinkObject).RemoveFromOtherEnd(Mode); GetLinkObjectOtherLinkController(OldLinkObject).Unlink(GetLinkObjectOtherLinkController(OldLinkObject).fLocator, Mode); - GetLinkObjectOwnLinkController(OldLinkObject).PreChange; - GetLinkObjectOwnLinkController(OldLinkObject).Unlink(OwningMember.OwningObject.BoldObjectLocator, Mode); + GetLinkObjectOwnLinkController(OldLinkObject).PreChange; + GetLinkObjectOwnLinkController(OldLinkObject).Unlink(OwningObjectList.OwningObject.BoldObjectLocator, Mode); OldLinkObject.Delete; end; @@ -1706,9 +2100,107 @@ destructor TBoldIndirectMultiLinkController.Destroy; end; procedure TBoldIndirectMultiLinkController.MakeDbCurrent; +{$IFDEF FetchFromClassList} + procedure FetchFromClassList; + var + ClassList: TBoldObjectList; + lBoldGuard: IBoldGuard; + lBoldObject: TBoldObject; + lOtherIndexInLinkClass: Integer; + lOwnBoldObjectLocator: TBoldObjectLocator; + lLinkClassTypeInfo: TBoldClassTypeInfo; + lOwnIndexInLinkClass: integer; + lListOfLinkObjects: TBoldObjectIdList; + lListOfOtherEnd: TBoldObjectIdList; + lThisEndInLinkClass: TBoldObjectReference; + lOtherEndInLinkClass: TBoldObjectReference; + lTopSortedIndex: Integer; + lMultiLinkItem: TIndirectMultiLinkItem; + lSortList: TList; + i: integer; + lIsOrdered: boolean; + CheckType: boolean; + lTopSortedClasses: TBoldClassTypeInfoList; + begin + lBoldGuard := TBoldGuard.Create(lListOfLinkObjects, lListOfOtherEnd, lSortList); + lLinkClassTypeInfo := RoleRTInfo.LinkClassTypeInfo; + ClassList := BoldSystem.Classes[lLinkClassTypeInfo.TopSortedIndex]; + lTopSortedIndex := RoleRTInfo.ClassTypeInfoOfOtherEnd.TopSortedIndex; + lOtherIndexInLinkClass := RoleRTInfo.OtherIndexInLinkClass; + lOwnIndexInLinkClass := RoleRTInfo.OwnIndexInLinkClass ; + lTopSortedClasses := BoldSystem.BoldSystemTypeInfo.TopSortedClasses; + lListOfLinkObjects := TBoldObjectIdList.Create; + lListOfOtherEnd:= TBoldObjectIdList.Create; + lIsOrdered := RoleRTInfo.IsOrdered; + if lIsOrdered then + lSortList := TList.Create; + lOwnBoldObjectLocator := OwningObjectList.OwningObject.BoldObjectLocator; + CheckType := ClassList.BoldPersistenceState <> bvpsCurrent; + if CheckType then + ClassList := TBoldClassListController(GetControllerForMember(ClassList)).ClosestLoadedClassList; + Assert(Assigned(ClassList)); + for i := 0 to ClassList.Count - 1 do + begin + if CheckType and not ClassList.Locators[i].BoldClassTypeInfo.BoldIsA(lLinkClassTypeInfo) then + Continue; + lBoldObject := ClassList[i]; + lThisEndInLinkClass := lBoldObject.BoldMembers{IfAssigned}[lOwnIndexInLinkClass] as TBoldObjectReference; + if Assigned(lThisEndInLinkClass) and (lThisEndInLinkClass.Locator = lOwnBoldObjectLocator) then + begin + lOtherEndInLinkClass := lBoldObject.BoldMembers[lOtherIndexInLinkClass] as TBoldObjectReference; + Assert(Assigned(lOtherEndInLinkClass.Locator)); +{ + if not Assigned(lOtherEndInLinkClass.Locator) then + begin + if lOtherEndInLinkClass.BoldDirty then + lOtherEndInLinkClass.Discard; + Assert(Assigned(lOtherEndInLinkClass.Locator)); + end; +} + if lIsOrdered then + begin + lMultiLinkItem := TIndirectMultiLinkItem.Create; + lMultiLinkItem.ObjectId := lBoldObject.BoldObjectLocator.BoldObjectId; + lMultiLinkItem.OtherObjectId := lOtherEndInLinkClass.Locator.BoldObjectId; + lMultiLinkItem.OrderNo := (GetControllerForMember(lThisEndInLinkClass) as TBoldDirectSingleLinkController).OrderNo; + lSortList.Add(lMultiLinkItem); + end + else + begin + lListOfLinkObjects.Add(lBoldObject.BoldObjectLocator.BoldObjectId); + lListOfOtherEnd.Add(lOtherEndInLinkClass.Locator.BoldObjectId); + end; + end; + end; + if lIsOrdered then + begin + lSortList.Sort(_CompareOrderNo); + for i := 0 to lSortList.Count - 1 do + begin + lMultiLinkItem := TIndirectMultiLinkItem(lSortList[i]); + lListOfLinkObjects.Add(lMultiLinkItem.ObjectId); + lListOfOtherEnd.Add(lMultiLinkItem.OtherObjectId); + lMultiLinkItem.free; + end; + end; + +// DbFetchOwningMember; +// Assert(lListOfOtherEnd.count = OwningObjectList.Count); + SetFromIDLists(lListOfLinkObjects, lListOfOtherEnd, bdepContents); + OwningObjectList.BoldPersistenceState := bvpsCurrent; + end; +{$ENDIF} begin - EnsureOrder; - DbFetchOwningMember; + if OwningObjectList.BoldPersistenceState <> bvpsCurrent then + begin + EnsureOrder; +{$IFDEF FetchFromClassList} + if TBoldClassListController(GetControllerForMember(BoldSystem.Classes[RoleRTInfo.LinkClassTypeInfo.TopSortedIndex])).IsCurrentOrSuperClassIsCurrent then + FetchFromClassList + else +{$ENDIF} + DbFetchOwningMember; + end; end; function TBoldIndirectMultiLinkController.GetCount: Integer; @@ -1716,11 +2208,6 @@ function TBoldIndirectMultiLinkController.GetCount: Integer; Result := LinkLocatorList.Count; end; -function TBoldIndirectMultiLinkController.GetLinkObjectOwnLinkController(LinkObject: TBoldObject): TBoldLinkObjectSingleLinkController; -begin - result := GetControllerForMember(LinkObject.BoldMembers[OwningObjectList.BoldRoleRtInfo.OwnIndexInLinkClass]) as TBoldLinkObjectSingleLinkController; -end; - function TBoldIndirectMultiLinkController.GetLocator(index: Integer): TBoldObjectLocator; begin EnsureOrder; @@ -1732,13 +2219,13 @@ function TBoldIndirectMultiLinkController.GetLocatorByQualifiersAndSubscribe(Mem EnsureOrder; if not ReferredLocatorList.HasMembersIndex then begin - if assigned(OwningObjectList.BoldRoleRTInfo) and OwningObjectList.BoldRoleRTInfo.isQualified then + if assigned(RoleRTInfo) and RoleRTInfo.isQualified then begin OwningObjectList.EnsureObjects; - ReferredLocatorList.InitMembersIndex(OwningObjectList, OwningObjectList.BoldRoleRTInfo.Qualifiers) + ReferredLocatorList.InitMembersIndex(OwningObjectList, RoleRTInfo.Qualifiers) end else - raise EBold.CreateFmt(sRolenotQualified, [ClassName]); + raise EBold.CreateFmt('%s.GetLocatorByQualifiers: Object list does not have a member index or role is not qualified', [ClassName]); end; result := ReferredLocatorList.GetLocatorByAttributesAndSubscribe(MemberList, Subscriber); end; @@ -1763,7 +2250,7 @@ procedure TBoldIndirectMultiLinkController.InsertLocator(index: Integer; Locator try BoldClearLastFailure; if not StartModify then - BoldRaiseLastFailure(OwningList, 'InsertLocator', ''); // do not localize + BoldRaiseLastFailure(OwningList, 'InsertLocator', ''); PreChange; NewLinkLocator := NewLink(Locator, blulMarkModified).BoldObjectLocator; @@ -1784,19 +2271,22 @@ procedure TBoldIndirectMultiLinkController.linkto(NewLocator: TBoldObjectLocator var NewReferredLocator: TBoldObjectLocator; begin - Assert((Mode <> blulMarkAdjusted) or (OwningList.BoldPersistenceState = bvpsCurrent)); - Assert(not LinkLocatorList.LocatorInList[NewLocator], 'locator already in list'); + Assert((Mode <> blulMarkAdjusted) or (OwningList.BoldPersistenceState = bvpsCurrent), OwningMember.DisplayName); + if LinkLocatorList.LocatorInList[NewLocator] then // locator already in list so just exit, this used to be an assert - Daniel + begin + exit; + end; BoldClearLastFailure; if Mode = blulMarkModified then if not StartModify then - BoldRaiseLastFailure(OwningList, 'Linkto', ''); // do not localize + BoldRaiseLastFailure(OwningList, 'Linkto', ''); PreChange; NewReferredLocator := GetLinkObjectOtherLinkController(NewLocator.EnsuredBoldObject).fLocator; LinkLocatorList.Add(NewLocator); ReferredLocatorList.Add(NewReferredLocator); - if updateOrderNo and OwningObjectList.BoldRoleRtInfo.IsOrdered then - GetLinkObjectOwnLinkController(NewLocator.BoldObject).SetAndModifyOrderNo(LinkLocatorList.IndexOf(NewLocator)); // Complexity warning: A loop of adds will take O(n^2) + if updateOrderNo and RoleRTInfo.IsOrdered then + GetLinkObjectOwnLinkController(NewLocator.BoldObject).SetAndModifyOrderNo(LinkLocatorList.IndexOf(NewLocator)); //TODO - This could have side effect when mode is blulMarkAdjusted if Mode = blulMarkAdjusted then OwningObjectList.Adjusted := True; Changed(beItemAdded, [NewReferredLocator]); @@ -1808,14 +2298,14 @@ procedure TBoldIndirectMultiLinkController.linkto(NewLocator: TBoldObjectLocator procedure TBoldIndirectMultiLinkController.Move(CurrentIndex, NewIndex: Integer); begin EnsureOrder; - if not OwningObjectList.BoldRoleRtInfo.IsOrdered then + if not RoleRTInfo.IsOrdered then exit; BoldSystem.StartTransaction; try BoldClearLastFailure; if not StartModify then - BoldRaiseLastFailure(OwningList, 'Move', ''); // do not localize + BoldRaiseLastFailure(OwningList, 'Move', ''); PreChange; LinkLocatorList.Move(CurrentIndex, NewIndex); @@ -1832,16 +2322,41 @@ procedure TBoldIndirectMultiLinkController.Move(CurrentIndex, NewIndex: Integer) end; function TBoldIndirectMultiLinkController.NewLink(OtherLocator: TBoldObjectLocator; Mode: TBoldLinkUnlinkMode): TBoldObject; +{$IFDEF ReuseDeletedLinkObjectOnRelink} + function FindLinkInOldValues: TBoldObject; + var + s: IBoldObjectIdListRefPair; + i: integer; + begin + result := nil; + if Supports(OwningObjectList.OldValue, IBoldObjectIdListRefPair, s) then + for i := 0 to s.Count-1 do + begin + if s.IdList2[i].IsEqual[OtherLocator.BoldObjectID] then + begin + result := BoldSystem.Locators.ObjectByID[s.IdList1[i]]; + Assert(result is RoleRTInfo.LinkClassTypeInfo.ObjectClass); + result.AsIBoldObjectContents[bdepContents].BoldExistenceState := besExisting; + result.AsIBoldObjectContents[bdepContents].BoldPersistenceState := bvpsCurrent; + exit; + end; + end; + end; +{$ENDIF} var LinkObject: TBoldObject; LinkClassTypeInfo: TBoldClassTypeInfo; OtherEndController: TBoldAbstractController; begin - LinkClassTypeInfo := OwningObjectList.BoldRoleRTInfo.LinkClassTypeInfo; - LinkObject := TBoldObjectClass(LinkClassTypeInfo.ObjectClass).InternalCreateNewWithClassAndSystem(LinkClassTypeInfo, OwningMember.BoldSystem, - OtherLocator.ObjectIsPersistent and OwningMember.OwningObject.BoldPersistent); - OtherEndController := GetLinkObjectOtherLinkController(LinkObject).GetOtherEndController(OtherLocator, true); // Ensure other end fetched if forced - GetLinkObjectOwnLinkController(LinkObject).LinkTo(OwningMember.OwningObject.BoldObjectLocator, true, Mode); + LinkClassTypeInfo := RoleRTInfo.LinkClassTypeInfo; +{$IFDEF ReuseDeletedLinkObjectOnRelink} + LinkObject := FindLinkInOldValues; + if not Assigned(LinkObject) then +{$ENDIF} + LinkObject := TBoldObjectClass(LinkClassTypeInfo.ObjectClass).InternalCreateNewWithClassAndSystem(LinkClassTypeInfo, BoldSystem, + OtherLocator.ObjectIsPersistent and OwningObjectList.OwningObject.BoldPersistent); + OtherEndController := GetLinkObjectOtherLinkController(LinkObject).GetOtherEndController(OtherLocator, true); + GetLinkObjectOwnLinkController(LinkObject).LinkTo(OwningObjectList.OwningObject.BoldObjectLocator, true, Mode); GetLinkObjectOtherLinkController(LinkObject).LinkTo(OtherLocator, true, Mode); if Assigned(OtherEndController) then OtherEndController.LinkTo(LinkObject.BoldObjectLocator, false, Mode); @@ -1858,14 +2373,14 @@ procedure TBoldIndirectMultiLinkController.RemoveByIndex(index: Integer); try BoldClearLastFailure; if not StartModify then - BoldRaiseLastFailure(OwningList, 'RemoveByIndex', ''); // do not localize + BoldRaiseLastFailure(OwningList, 'RemoveByIndex', ''); PreChange; Locator := ReferredLocatorList[index]; LinkLocator := LinkLocatorList[index]; BoldSystem.DelayObjectDestruction; try - DeleteLink(LinkLocator, blulMarkModified); // This will remove from other end but not from own + DeleteLink(LinkLocator, blulMarkModified); LinkLocatorList.RemoveByIndex(index); ReferredLocatorList.RemoveByIndex(index); finally @@ -1884,22 +2399,22 @@ procedure TBoldIndirectMultiLinkController.RemoveByIndex(index: Integer); procedure TBoldIndirectMultiLinkController.ReOrder; var -{$IFOPT C+} // if Assertions on +{$IFOPT C+} index: Integer; {$ENDIF} I: Integer; Locator: TBoldObjectLocator; begin - if OwningObjectList.BoldRoleRtInfo.IsOrdered then + if RoleRTInfo.IsOrdered then begin -{$IFOPT C+} // if Assertions on - index := OwningObjectList.BoldRoleRtInfo.IndexOfOtherEnd; +{$IFOPT C+} + index := RoleRTInfo.IndexOfOtherEnd; Assert(index <> -1); {$ENDIF} for I := 0 to LinkLocatorList.Count - 1 do begin Locator := LinkLocatorList.Locators[I]; - Locator.EnsureBoldObject; // Note, can give fetch during fetch, save till all fetched + Locator.EnsureBoldObject; end; for I := 0 to LinkLocatorList.Count - 1 do begin @@ -1921,8 +2436,6 @@ procedure TBoldIndirectMultiLinkController.SetFromIDLists(ListOfLinkObjects, Lis if Assigned(Value) then Value.SetFromIdLists(ListOfLInkObjects, ListOfOtherEnd); end; - - // Adjust NewListOfLinkObjects,NewListOfOtherEnd. Return True if adjusted function AdjustLists: Boolean; var I: integer; @@ -1931,11 +2444,13 @@ procedure TBoldIndirectMultiLinkController.SetFromIDLists(ListOfLinkObjects, Lis IndexOfOtherEnd, IndexOfOwnEnd, EmbeddedIndexOfOtherEnd, EmbeddedIndexOfOwnEnd: Integer; LinkObjectLocator: TBoldObjectLocator; + BoldSystem: TBoldSystem; begin Result := False; - BoldLinkClassTypeInfo := OwningObjectList.BoldRoleRtInfo.LinkClassTypeInfo; - IndexOfOwnEnd := OwningObjectList.BoldRoleRTInfo.OwnIndexInLinkClass; - IndexOfOtherEnd := OwningObjectList.BoldRoleRTInfo.OtherIndexInLinkClass; + BoldLinkClassTypeInfo := RoleRTInfo.LinkClassTypeInfo; + IndexOfOwnEnd := RoleRTInfo.OwnIndexInLinkClass; + IndexOfOtherEnd := RoleRTInfo.OtherIndexInLinkClass; + BoldSystem := self.BoldSystem; {Adjust list} for I := NewListOfLinkObjects.Count - 1 downto 0 do begin @@ -1953,11 +2468,11 @@ procedure TBoldIndirectMultiLinkController.SetFromIDLists(ListOfLinkObjects, Lis NewListOfOtherEnd.RemoveByIndex(I); end; end - else {object not loaded, set embedded links} { TODO : Is this really related to adjust? } + else {object not loaded, set embedded links} begin LinkObjectLocator := AssertedLocatorForId(NewListOfLinkObjects[i]); - EmbeddedIndexOfOwnEnd := OwningObjectList.BoldRoleRTInfo.LinkClassTypeInfo.AllMembers[IndexOfOwnEnd].EmbeddedLinkIndex; - EmbeddedIndexOfOtherEnd := OwningObjectList.BoldRoleRTInfo.LinkClassTypeInfo.AllMembers[IndexOfOtherEnd].EmbeddedLinkIndex; + EmbeddedIndexOfOwnEnd := RoleRTInfo.LinkClassTypeInfo.AllMembers[IndexOfOwnEnd].EmbeddedLinkIndex; + EmbeddedIndexOfOtherEnd := RoleRTInfo.LinkClassTypeInfo.AllMembers[IndexOfOtherEnd].EmbeddedLinkIndex; if (EmbeddedIndexOfOwnEnd <> -1) then LinkObjectLocator.EmbeddedSingleLinks[EmbeddedIndexOfOwnEnd] := OwningList.OwningObject.BoldObjectLocator; if (EmbeddedIndexOfOtherEnd <> -1) then @@ -1989,7 +2504,6 @@ procedure TBoldIndirectMultiLinkController.SetFromIDLists(ListOfLinkObjects, Lis if not PreChangeCalled then begin PreChange; -// GetLinkObjectListController.PreChange; No need to save? PreChangeCalled := True; end; end; @@ -2003,7 +2517,7 @@ procedure TBoldIndirectMultiLinkController.SetFromIDLists(ListOfLinkObjects, Lis G: IBoldGuard; begin G := TBoldGuard.Create(NewListOfLinkObjects, NewListOfOtherEnd); - if (mode = bdepPMIn) and (OwningMember.OwningObject.BoldObjectLocator.BoldObjectId.TimeStamp <> BOLDMAXTIMESTAMP) then // fetching old temporal versi + if (mode = bdepPMIn) and (OwningObjectList.OwningObject.IsHistoricVersion) then mode := bdepContents; if assigned(ListOfLinkObjects) then begin @@ -2022,7 +2536,7 @@ procedure TBoldIndirectMultiLinkController.SetFromIDLists(ListOfLinkObjects, Lis WasAdjusted := False; if Mode = bdepPMIn then ClearNoLongerReferring(newListOfOtherEnd); - PreserveOrder := (mode = bdepContents) or ((mode = bdepPMIn) and OwningObjectList.BoldRoleRTInfo.IsOrdered and not WasAdjusted); + PreserveOrder := (mode = bdepContents) or ((mode = bdepPMIn) and RoleRTInfo.IsOrdered and not WasAdjusted); {we now have a list with the right objects} @@ -2053,8 +2567,7 @@ procedure TBoldIndirectMultiLinkController.SetFromIDLists(ListOfLinkObjects, Lis GetLinkObjectListController.Changed(beItemDeleted, [ObjectLocator]); end else if ObjectLocator = ReferredLocatorList[i] then - // All in order, do nothing - else if ReferredLocatorList.IndexOf(ObjectLocator) <> -1 then // locator in list, but at wrong place + else if ReferredLocatorList.IndexOf(ObjectLocator) <> -1 then begin PreChangeIfNeeded; LinkLocatorList.Move(ReferredLocatorList.IndexOf(ObjectLocator), I); @@ -2063,7 +2576,7 @@ procedure TBoldIndirectMultiLinkController.SetFromIDLists(ListOfLinkObjects, Lis GetLinkObjectListController.Changed(beOrderChanged, []); end else - begin // locator not in list, insert it, + begin PreChangeIfNeeded; NewLocator := AssertedLocatorForId(NewListOfLinkObjects[I]); LinkLocatorList.Insert(I, NewLocator); @@ -2077,8 +2590,7 @@ procedure TBoldIndirectMultiLinkController.SetFromIDLists(ListOfLinkObjects, Lis for I := 0 to NewListOfLinkObjects.Count - 1 do begin ObjectLocator := AssertedLocatorForId(NewListOfOtherEnd[i]); - // if the database contains linkobject duplicates, the lists could get out of sync, we must avoid - // adding two linkobjects for the same object + if not ReferredLocatorList.LocatorInList[ObjectLocator] then begin PreChangeIfNeeded; @@ -2101,7 +2613,7 @@ procedure TBoldIndirectMultiLinkController.SetLocator(index: Integer; Locator: T try BoldClearLastFailure; if not StartModify then - BoldRaiseLastFailure(OwningList, 'SetLocator', ''); // do not localize + BoldRaiseLastFailure(OwningList, 'SetLocator', ''); OldLinkLocator := LinkLocatorList[index]; PreChange; LinkLocatorList[index] := NewLink(Locator, blulMarkModified).BoldObjectLocator; @@ -2122,17 +2634,29 @@ function TBoldIndirectMultiLinkController.GetStreamName: String; result := BoldContentName_ObjectIdListRefPair; end; +function TBoldIndirectMultiLinkController.GetFreeStandingClass: TBoldFreeStandingElementClass; +begin + result := TBFSObjectIdListRefPair; +end; + procedure TBoldIndirectMultiLinkController.Unlink(OldLocator: TBoldObjectLocator; Mode: TBoldLinkUnlinkMode); var OldIndex: Integer; OldLinkLocator: TBoldObjectLocator; begin - Assert((Mode <> blulMarkAdjusted) or (OwningList.BoldPersistenceState = bvpsCurrent)); + Assert((Mode <> blulMarkAdjusted) or (OwningList.BoldPersistenceState = bvpsCurrent), OwningMember.DisplayName); + if not LinkLocatorList.LocatorInList[OldLocator] then + begin + BoldLog.LogFmt('TBoldIndirectMultiLinkController.Unlink: Locator %s (%s) not found in %s (%s) ', + [OldLocator.AsString, OldLocator.EnsuredBoldObject.DisplayName, + OwningMember.OwningObject.BoldObjectLocator.AsString, OwningObjectList.DisplayName]); + exit; + end; Assert(LinkLocatorList.LocatorInList[OldLocator]); BoldClearLastFailure; if Mode = blulMarkModified then if not StartModify then - BoldRaiseLastFailure(OwningList, 'Unlink', ''); // do not localize + BoldRaiseLastFailure(OwningList, 'Unlink', ''); PreChange; OldIndex := LinkLocatorList.IndexOf(OldLocator); @@ -2147,16 +2671,11 @@ procedure TBoldIndirectMultiLinkController.Unlink(OldLocator: TBoldObjectLocator EndModify; end; -function TBoldIndirectMultiLinkController.GetLinkObjectListController: TBoldLinkObjectListController; -begin - result := ControllerForLinkMember as TBoldLinkObjectListController; -end; - function TBoldIndirectMultiLinkController.ProxyInterface(const IId: TGUID; Mode: TBoldDomainElementProxyMode; out Obj): Boolean; begin if IsEqualGuid(IID, IBoldObjectIdListRefPair) then begin - result := ProxyClass.create(self.OwningList, Mode).GetInterface(IID, obj); + result := GetProxy(self.OwningList, Mode).GetInterface(IID, obj); if not result then raise EBoldInternal.CreateFmt('ProxyClass for %s did not implement IBoldObjectIdListRefPair', [ClassName]); end @@ -2164,9 +2683,9 @@ function TBoldIndirectMultiLinkController.ProxyInterface(const IId: TGUID; Mode: result := inherited ProxyInterface(IID, Mode, Obj); end; -function TBoldIndirectMultiLinkController.ProxyClass: TBoldMember_ProxyClass; +function TBoldIndirectMultiLinkController.GetProxy(Member: TBoldMember; Mode: TBoldDomainElementProxyMode): TBoldMember_Proxy; begin - result := TBoldIndirectMultiLinkController_Proxy; + result := TBoldIndirectMultiLinkController_Proxy.MakeProxy(Member, Mode); end; procedure TBoldIndirectMultiLinkController.FreeContent; @@ -2179,10 +2698,16 @@ procedure TBoldIndirectMultiLinkController.PrepareClear; var LinkList: TBoldObjectList; begin - LinkList := OwningList.OwningObject.BoldMembers[OwningObjectList.BoldRoleRtInfo.IndexOfLinkObjectRole] as TBoldObjectLIst; + LinkList := OwningList.OwningObject.BoldMembers[RoleRTInfo.IndexOfLinkObjectRole] as TBoldObjectLIst; LinkLIst.EnsureObjects; end; +procedure TBoldIndirectMultiLinkController.Exchange(Index1, Index2: integer); +begin + LinkLocatorList.Exchange(Index1, Index2); + ReferredLocatorList.Exchange(Index1, Index2); +end; + procedure TBoldIndirectMultiLinkController.Resort; begin BoldSort(0, LinkLocatorList.Count - 1, CompareOrderNo, Exchange); @@ -2196,11 +2721,10 @@ function TBoldIndirectMultiLinkController.IsInOrder: Boolean; CurrentObj, PreviousObj: TBoldObject; begin Result := True; - if OwningObjectList.BoldRoleRTInfo.IsOrdered then + if RoleRTInfo.IsOrdered then begin i := 0; CurrentObj := nil; - // Only compare those objects that are loaded. while result and (i < LinkLocatorList.Count - 1) do begin if Assigned(LinkLocatorList[i].BoldObject) then @@ -2209,7 +2733,7 @@ function TBoldIndirectMultiLinkController.IsInOrder: Boolean; CurrentObj := LinkLocatorList[i].BoldObject; if Assigned(PreviousObj) then - Result := GetLinkObjectOwnLinkController(PreviousObj).FOrderNo <= GetLinkObjectOwnLinkController(CurrentObj).FOrderNo; + Result := GetLinkObjectOwnLinkController(PreviousObj).GetOrderNo <= GetLinkObjectOwnLinkController(CurrentObj).GetOrderNo; end; Inc(i); end; @@ -2220,26 +2744,14 @@ function TBoldIndirectMultiLinkController.CompareOrderNo(Index1, Index2: integer var OrderNo1, OrderNo2: integer; begin - if OwningObjectList.BoldRoleRTInfo.RoleRTInfoOfOtherEnd.IsSingleRole then + if RoleRTInfo.RoleRTInfoOfOtherEnd.IsSingleRole then begin - OrderNo1 := GetLinkObjectOwnLinkController(LinkLocatorList[Index1].BoldObject).FOrderNo; - OrderNo2 := GetLinkObjectOwnLinkController(LinkLocatorList[Index2].BoldObject).FOrderNo; + OrderNo1 := GetLinkObjectOwnLinkController(LinkLocatorList[Index1].BoldObject).GetOrderNo; + OrderNo2 := GetLinkObjectOwnLinkController(LinkLocatorList[Index2].BoldObject).GetOrderNo; Result := (OrderNo1 - OrderNo2); end else - raise EBold.Create(sOtherEndMustBeSingle); -end; - -procedure TBoldIndirectMultiLinkController.Exchange(Index1, Index2: integer); -begin - LinkLocatorList.Exchange(Index1, Index2); - ReferredLocatorList.Exchange(Index1, Index2); -end; - -function TBoldIndirectMultiLinkController.GetLinkObjectOtherLinkController( - LinkObject: TBoldObject): TBoldLinkObjectSingleLinkController; -begin - result := GetControllerForMember(LinkObject.BoldMembers[OwningObjectList.BoldRoleRtInfo.OtherIndexInLinkClass]) as TBoldLinkObjectSingleLinkController; + raise EBold.Create('Cannot call compare if OtherEnd is not a single role'); end; function TBoldIndirectMultiLinkController.AssertIntegrity: Boolean; @@ -2256,12 +2768,9 @@ function TBoldIndirectMultiLinkController.AssertIntegrity: Boolean; Assert(LinkLocatorList[i].BoldObject.BoldExistenceState = besExisting); Assert(GetLinkObjectOwnLinkController(LinkLocatorList[i].BoldObject).fLocator = OwningObjectList.OwningObject.BoldObjectLocator); Assert(GetLinkObjectOtherLinkController(LinkLocatorList[i].BoldObject).fLocator = ReferredLocatorList[i]); - { TODO : Check included in other end, if loaded. } end - else // link object no loaded + else begin - { TODO : Check values in locator itself } - { TODO : Check included in other end, if loaded. } end; end; Result := True; @@ -2270,7 +2779,6 @@ function TBoldIndirectMultiLinkController.AssertIntegrity: Boolean; procedure TBoldIndirectMultiLinkController.ClearNoLongerReferring( NewList: TBoldObjectIdList); begin -{ TODO : What do we want to do here. Free actual link objects that are pointing at us? } end; procedure TBoldIndirectMultiLinkController.Clear; @@ -2283,7 +2791,7 @@ procedure TBoldIndirectMultiLinkController.Clear; try BoldClearLastFailure; if not StartModify then - BoldRaiseLastFailure(OwningList, 'RemoveByIndex', ''); // do not localize + BoldRaiseLastFailure(OwningList, 'RemoveByIndex', ''); PreChange; BoldSystem.DelayObjectDestruction; @@ -2293,7 +2801,7 @@ procedure TBoldIndirectMultiLinkController.Clear; ix := Count-1; Locator := ReferredLocatorList[ix]; LinkLocator := LinkLocatorList[ix]; - DeleteLink(LinkLocator, blulMarkModified); // This will remove from other end but not from own + DeleteLink(LinkLocator, blulMarkModified); LinkLocatorList.RemoveByIndex(ix); ReferredLocatorList.RemoveByIndex(ix); Changed(beItemDeleted, [Locator]); @@ -2316,28 +2824,18 @@ function TBoldIndirectMultiLinkController.ControllerForLinkMember: TBoldAbstract var LinkMember: TBoldMember; begin - LinkMember := OwningList.OwningObject.BoldMembers[OwningObjectList.BoldRoleRtInfo.Index+1]; + LinkMember := OwningList.OwningObject.BoldMembers[RoleRTInfo.Index+1]; result := GetControllerForMember(LinkMember) as TBoldAbstractObjectListController; end; function TBoldMultiLinkController.CreateNew: TBoldElement; begin - result := OwningList.BoldSystem.CreateNewObjectByExpressionName(OwningObjectList.BoldRoleRTInfo.ClassTypeInfoOfOtherEnd.ExpressionName); -end; - -procedure TBoldMultiLinkController.EnsureOrder; -begin - if (fMayBeOutOfOrder) then - begin - if not IsInOrder then - Resort; - fMayBeOutOfOrder := false; - end; + result := BoldSystem.CreateNewObjectFromClassTypeInfo(RoleRTInfo.ClassTypeInfoOfOtherEnd); end; function TBoldMultiLinkController.GetCanCreateNew: Boolean; begin - result := not OwningObjectList.BoldRoleRTInfo.ClassTypeInfoOfOtherEnd.IsAbstract; + result := not RoleRTInfo.ClassTypeInfoOfOtherEnd.IsAbstract; end; procedure TBoldDirectMultiLinkController.SingleLinkUnlink( @@ -2350,9 +2848,9 @@ procedure TBoldDirectMultiLinkController.SingleLinkUnlink( aObject := Locator.BoldObject; if Assigned(AObject) then GetOtherEndController(Locator).Unlink(OldLocator, Mode) - else // member for other end not instantiated. + else begin - EmbeddedIndex := OwningObjectList.BoldRoleRtInfo.RoleRTInfoOfOtherEnd.EmbeddedLinkIndex; + EmbeddedIndex := RoleRTInfo.RoleRTInfoOfOtherEnd.EmbeddedLinkIndex; if (EmbeddedIndex <> -1) then if Locator.EmbeddedSingleLinks[EmbeddedIndex] <> nil then begin @@ -2362,13 +2860,8 @@ procedure TBoldDirectMultiLinkController.SingleLinkUnlink( end; end; -function TBoldDirectMultiLinkController.GetOtherEndController(Locator: TBoldObjectLocator): TBoldDirectSingleLinkController; -begin - result := GetControllerForMember(Locator.EnsuredBoldObject.BoldMembers[OwningObjectList.BoldRoleRtInfo.IndexOfOtherEnd]) as TBoldDirectSingleLinkController; -end; - procedure TBoldDirectMultiLinkController.SingleLinkLinkTo(Locator, - NewLocator: TBoldObjectLocator; updateOrderNo: Boolean; Mode: TBoldLinkUnlinkMode); + NewLocator: TBoldObjectLocator; updateOrderNo: Boolean; Mode: TBoldLinkUnlinkMode; aOrderNo: integer); var aObject: TBoldObject; EmbeddedIndex: integer; @@ -2376,18 +2869,18 @@ procedure TBoldDirectMultiLinkController.SingleLinkLinkTo(Locator, aObject := Locator.BoldObject; if Assigned(AObject) then GetOtherEndController(Locator).LinkTo(NewLocator, UpdateOrderNo, Mode) - else // member for other end not instantiated. + else begin - EmbeddedIndex := OwningObjectList.BoldRoleRtInfo.RoleRTInfoOfOtherEnd.EmbeddedLinkIndex; + EmbeddedIndex := RoleRTInfo.RoleRTInfoOfOtherEnd.EmbeddedLinkIndex; Assert(EmbeddedIndex <> -1); - Assert((Locator.EmbeddedSingleLinks[EmbeddedIndex] = nil) or (Locator.EmbeddedSingleLinks[EmbeddedIndex] = NewLocator)); + //Assert(Locator.EmbeddedSingleLinks[EmbeddedIndex] = nil); Locator.EmbeddedSingleLinks[EmbeddedIndex] := NewLocator; end; end; procedure TBoldMultiLinkController.MarkPossiblyOutOfOrder; begin - if OwningObjectList.BoldRoleRTInfo.IsOrdered then + if RoleRTInfo.IsOrdered then fMayBeOutOfOrder := True; end; @@ -2396,7 +2889,7 @@ procedure TBoldMultiLinkController.MarkPossiblyOutOfOrder; function TBoldLinkObjectSingleLinkController.OtherInnerLinkController: TBoldLinkObjectSingleLinkController; begin result := GetControllerForMember(OwningReference.OwningObject.BoldMembers[ - OwningReference.BoldRoleRTInfo.RoleRTInfoOfOtherEnd.OtherIndexInLinkClass]) as TBoldLinkObjectSingleLinkController; + RoleRTInfo.RoleRTInfoOfOtherEnd.OtherIndexInLinkClass]) as TBoldLinkObjectSingleLinkController; end; procedure TBoldLinkObjectSingleLinkController.SetFromId(Id: TBoldObjectId; Mode: TBoldDomainElementProxyMode); @@ -2408,19 +2901,16 @@ procedure TBoldLinkObjectSingleLinkController.SetFromId(Id: TBoldObjectId; Mode: index: Integer; begin inherited; - // Note! This code adjust for a possible previous "flaw". When fetching the - // first of the two inner single links, its "other end" cannot be set up correctly - // since the value of other inner single link is not known. This code adjust - // that when the other inner single link is fetched. Note that this requires - // that both inner single links are fetched in the same operation. + + + + OtherInnerLink := OtherInnerLinkController; if assigned(OtherInnerLink.fLocator) then begin OtherOuterLink := OtherInnerLink.GetOtherEndController(OtherInnerLink.fLocator, false); - // will not be assigned if outerlink is bvpsInvalid if assigned(OtherOuterLink) then begin - // they have no suitable common superclass... if OtherOuterLink is TBoldIndirectMultiLinkController then begin OuterMulti := OtherOuterLink as TBoldIndirectMultiLinkController; @@ -2435,7 +2925,7 @@ procedure TBoldLinkObjectSingleLinkController.SetFromId(Id: TBoldObjectId; Mode: (OuterSingle.fOtherEndLocator = nil) then OuterSingle.fOtherEndLocator := fLocator; end else - raise EBold.CreateFmt(sUnexpectedControllerType, [classname, OtherOuterLink.classname]); + raise EBold.CreateFmt('%s.SetFromId: Unexpected type of controller: %s', [classname, OtherOuterLink.classname]); end; end; end; @@ -2443,7 +2933,7 @@ procedure TBoldLinkObjectSingleLinkController.SetFromId(Id: TBoldObjectId; Mode: procedure TBoldLinkObjectSingleLinkController.SetLocator(NewLocator: TBoldObjectLocator); begin if assigned(NewLocator) then - raise EBold.CreateFmt(sCannotChangeLinkObjectSingleLink, [ClassName]); + raise EBold.CreateFmt('%s.SetLocator: Cannot change a Link Object Single Link', [ClassName]); inherited; end; @@ -2451,7 +2941,7 @@ procedure TBoldLinkObjectSingleLinkController.SetLocator(NewLocator: TBoldObject procedure TBoldLinkObjectListController.AddLocator(Locator: TBoldObjectLocator); begin - raise EBold.CreateFmt(sInvalidForListOfLinkObjects, [ClassName, 'AddLocator']); // do not localize + raise EBold.CreateFmt('%s.AddLocator: Cannot add directly to a list of link objects', [ClassName]); end; procedure TBoldLinkObjectListController.MakeDbCurrent; @@ -2472,22 +2962,23 @@ function TBoldLinkObjectListController.GetLocator(index: Integer): TBoldObjectLo function TBoldLinkObjectListController.GetLocatorByQualifiersAndSubscribe(MemberList: TBoldMemberList; Subscriber: TBoldSubscriber): TBoldObjectLocator; begin - raise EBoldFeatureNotImplementedYet.CreateFmt('%s.GetLocatorByQualifiersAndSubscribe', [ClassName]); // do not localize -end; - -function TBoldLinkObjectListController.GetLocatorList: TBoldObjectLocatorList; -begin - result := GetMainListController.LinkLocatorList; + raise EBoldFeatureNotImplementedYet.CreateFmt('%s.GetLocatorByQualifiersAndSubscribe', [ClassName]); end; function TBoldLinkObjectListController.GetMainListController: TBOldIndirectMultiLinkController; var MainMember: TBoldMember; begin - MainMember := OwningList.OwningObject.BoldMembers[OwningObjectList.BoldRoleRtInfo.IndexOfMainRole]; + MainMember := OwningList.OwningObject.BoldMembers[RoleRTInfo.IndexOfMainRole]; result := GetControllerForMember(MainMember) as TBOldIndirectMultiLinkController; end; +function TBoldLinkObjectListController.GetLocatorList: TBoldObjectLocatorList; +begin + MakeDbCurrent; //PATCH This solves problem with invalidation of main role not propagating to link role + result := GetMainListController.LinkLocatorList; +end; + function TBoldLinkObjectListController.IncludesLocator(Locator: TBoldObjectLocator): Boolean; begin result := (LocatorList.IndexOf(Locator) <> -1) @@ -2500,32 +2991,37 @@ function TBoldLinkObjectListController.IndexOfLocator(Locator: TBoldObjectLocato procedure TBoldLinkObjectListController.InsertLocator(index: Integer; Locator: TBoldObjectLocator); begin - raise EBold.CreateFmt(sInvalidForListOfLinkObjects, [ClassName, 'InsertLocator']); // do not localize + raise EBold.CreateFmt('%s.InsertLocator: cannot insert into a list of link objects', [ClassName]); end; procedure TBoldLinkObjectListController.Move(CurrentIndex, NewIndex: Integer); begin - raise EBold.CreateFmt(sInvalidForListOfLinkObjects, [ClassName, 'Move']); // do not localize + raise EBold.CreateFmt('%s.Move: Cannot move items in a list of link objects', [ClassName]); end; procedure TBoldLinkObjectListController.RemoveByIndex(index: Integer); begin - raise EBold.CreateFmt(sInvalidForListOfLinkObjects, [ClassName, 'RemoveByIndex']); // do not localize + raise EBold.CreateFmt('%s.RemoveByIndex: Cannot remove from a list of link objects', [ClassName]); end; procedure TBoldLinkObjectListController.SetLocator(index: Integer; Locator: TBoldObjectLocator); begin - raise EBold.CreateFmt(sInvalidForListOfLinkObjects, [ClassName, 'SetLocator']); // do not localize + raise EBold.CreateFmt('%s.SetLocator: Cannot modify a list of link objects directly', [ClassName]); end; function TBoldLinkObjectListController.GetStreamName: string; begin - raise EBold.CreateFmt(sLocatedAbstractError, [Classname, 'GetStreamName']); // do not localize + raise EBold.CreateFmt('%s.GetStreamName: Abstract error', [Classname]); +end; + +function TBoldLinkObjectListController.GetFreeStandingClass: TBoldFreeStandingElementClass; +begin + raise EBold.CreateFmt('%s.GetFreeStandingClass: Abstract error', [Classname]); end; function TBoldLinkObjectListController.GetMainList: TBoldObjectList; begin - result := OwningList.OwningObject.BoldMembers[OwningObjectList.BoldRoleRtInfo.IndexOfMainRole] as TBoldObjectList; + result := OwningList.OwningObject.BoldMembers[RoleRTInfo.IndexOfMainRole] as TBoldObjectList; end; function TBoldLinkObjectListController.ProxyInterface(const IId: TGUID; Mode: TBoldDomainElementProxyMode; out Obj): Boolean; @@ -2539,21 +3035,28 @@ function TBoldLinkObjectListController.ProxyInterface(const IId: TGUID; Mode: TB result := false; end; -function TBoldLinkObjectListController.ProxyClass: TBoldMember_ProxyClass; +function TBoldLinkObjectListController.GetProxy(Member: TBoldMember; Mode: TBoldDomainElementProxyMode): TBoldMember_Proxy; begin raise EBoldInternal.Create('Can''t access Link Object List directly'); end; { TBoldLinkObjectReferenceController } + function TBoldLinkObjectReferenceController.GetLocator: TBoldObjectLocator; begin + MakeDbCurrent; //PATCH This solves problem with invalidation of main role not propagating to link role result := (ControllerForMainRole as TBoldIndirectSingleLinkController).fLinkObjectLocator; end; function TBoldLinkObjectReferenceController.GetStreamName: string; begin - raise EBold.CreateFmt(sLocatedAbstractError, [Classname, 'GetStreamName']); // do not localize + raise EBold.CreateFmt('%s.GetStreamName: Abstract error', [Classname]); +end; + +function TBoldLinkObjectReferenceController.GetFreeStandingClass: TBoldFreeStandingElementClass; +begin + raise EBold.CreateFmt('%s.GetFreeStandingClass: Abstract error', [Classname]); end; procedure TBoldLinkObjectReferenceController.MakeDbCurrent; @@ -2562,7 +3065,7 @@ procedure TBoldLinkObjectReferenceController.MakeDbCurrent; OwningReference.BoldPersistenceState := bvpsCurrent; end; -function TBoldLinkObjectReferenceController.ProxyClass: TBoldMember_ProxyClass; +function TBoldLinkObjectReferenceController.GetProxy(Member: TBoldMember; Mode: TBoldDomainElementProxyMode): TBoldMember_Proxy; begin raise EBoldInternal.Create('Can''t access objectreference directly'); end; @@ -2581,7 +3084,31 @@ function TBoldLinkObjectReferenceController.ProxyInterface( procedure TBoldLinkObjectReferenceController.SetLocator(NewLocator: TBoldObjectLocator); begin - raise EBold.CreateFmt(sCannotSetLinkObjectReference, [Classname]); + raise EBold.CreateFmt('%s.SetLocator: Cannot set a link object reference directy', [Classname]); +end; + +{ TBoldUnOrderedDirectSingleLinkController } + +function TBoldUnOrderedDirectSingleLinkController.GetOrderNo: Integer; +begin + Result := -1; +end; + +procedure TBoldUnOrderedDirectSingleLinkController.SetAndModifyOrderNo( + index: Integer); +begin + if OrderNo <> -1 then + raise EBoldInternal.Create('Orderno must -1 on an unordered role'); end; +procedure TBoldUnOrderedDirectSingleLinkController.SetOrderNo( + NewOrderNo: Integer; Mode: TBoldDomainElementProxyMode); +begin + if OrderNo <> -1 then + raise EBoldInternal.Create('Orderno must -1 on an unordered role'); +end; + +initialization + end. + diff --git a/Source/ObjectSpace/BORepresentation/BoldMLAttributes.pas b/Source/ObjectSpace/BORepresentation/BoldMLAttributes.pas index 7d061ba..b5e03ad 100644 --- a/Source/ObjectSpace/BORepresentation/BoldMLAttributes.pas +++ b/Source/ObjectSpace/BORepresentation/BoldMLAttributes.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldMLAttributes; interface @@ -34,7 +37,7 @@ TBAMLValueSetValue = class(TBAValueSetValue) protected function GetStringRepresentationCount: Integer; override; function GetStringRepresentation(Representation: TBoldRepresentation): string; override; - procedure SetStringRepresentation(Representation: TBoldRepresentation; Value: string); override; + procedure SetStringRepresentation(Representation: TBoldRepresentation; const Value: string); override; procedure AddMLString(Value: TBAMLString); function GetMLString(Representation: integer): TBAMLString; public @@ -47,7 +50,7 @@ TBAMLValueSetValue = class(TBAValueSetValue) TBAMLValueSetValueList = class(TBADerivedValueSetValueList) protected function FindByStringAndLanguage(Representation: integer; Value, Language: String): TBAValueSetValue; - procedure AddMembers(Int: Integer; Members: Array of TBoldMember); override; + procedure Addmembers(Int: Integer; Members: Array of TBoldMember); override; public end; @@ -57,8 +60,9 @@ TBAMLValueSet = class(TBAValueSet) function GetStringRepresentationByLanguage(Representation: integer; Languagename: String): String; procedure SetStringRepresentationByLanguage(Representation: integer; Languagename: String; NewValue: String); function GetStringBylanguage(representation: integer; LanguageName: String): TBAString; - procedure InitializeMember(OwningElement: TBoldDomainElement; ElementTypeInfo: TBoldElementTypeInfo); override; + procedure Initialize; override; public +// class function Getvalues: TBAValueSetValueList; override; procedure DefaultSubscribe(Subscriber: TBoldSubscriber; requestedEvent: TBoldEvent = breReEvaluate); override; procedure SubscribeToStringRepresentation(Representation: TBoldRepresentation; Subscriber: TBoldSubscriber; RequestedEvent: TBoldEvent = breReEvaluate); override; procedure SubscribeToLanguage(representation: integer; Language: String; Subscriber: TBoldSubscriber; requestedEvent: TBoldEvent); @@ -69,8 +73,8 @@ TBAMLValueSet = class(TBAValueSet) {--- TBALanguage ---} TBALanguage = class(TBAValueSet) protected - function GetValues: TBAValueSetValueList; override; - procedure InitializeMember(OwningElement: TBoldDomainElement; ElementTypeInfo: TBoldElementTypeInfo); override; + class function Getvalues: TBAValueSetValueList; override; + procedure Initialize; override; end; {--- TBAMLString ---} @@ -78,22 +82,23 @@ TBAMLString = class(TBAString) private fMLStrings: TStringList; procedure InternalSetDataValue(Representation:TBoldRepresentation; Value: String); - function GetContentAsBlob: String; - procedure SetContentAsBlob(const NewValue: String); + function GetContentAsBlob: TBoldAnsiString; + procedure SetContentAsBlob(const NewValue: TBoldAnsiString); function GetStringBylanguage(LanguageName: String): TBAString; protected - procedure AssignContentValue(Source: IBoldValue); override; + procedure AssignContentValue(const Source: IBoldValue); override; function GetStringRepresentation(Representation: TBoldRepresentation): string; override; - procedure SetStringRepresentation(Representation: TBoldRepresentation; Value: string); override; - procedure ReceiveEventFromOwned(originator: TObject; originalEvent: TBoldEvent); override; + procedure SetStringRepresentation(Representation: TBoldRepresentation; const Value: string); override; + procedure ReceiveEventFromOwned(originator: TObject; originalEvent: TBoldEvent; const Args: array of const); override; +{$IFNDEF BOLD_NO_QUERIES} function ReceiveQueryFromOwned(Originator: TObject; OriginalEvent: TBoldEvent; const Args: array of const; Subscriber: TBoldSubscriber): Boolean; override; +{$ENDIF} function StringClass: TBAStringClass; virtual; - procedure InitializeMember(OwningElement: TBoldDomainElement; ElementTypeInfo: TBoldElementTypeInfo); override; - function ProxyClass: TBoldMember_ProxyClass; override; + procedure Initialize; override; public - destructor Destroy; override; + destructor destroy; override; function GetStreamName: string; override; - function ValidateString(Value: string; Representation: TBoldRepresentation): Boolean; override; + function ValidateString(const Value: string; Representation: TBoldRepresentation): Boolean; override; function ValidateCharacter(C: Char; Representation: TBoldRepresentation): Boolean; override; procedure Assign(Source: TBoldElement); override; procedure DefaultSubscribe(Subscriber: TBoldSubscriber; requestedEvent: TBoldEvent = breReEvaluate); override; @@ -128,9 +133,9 @@ function BoldLanguageList: TBAValueSetValueList; BoldMLStringSecondaryFallBack: string = '< %s: %s >'; BoldMLStringUnknownFallback: string = '<< %s: %s >>'; - BoldMLLanguageClassName: String = 'LanguageClass'; // do not localize - BoldMLLanguageNameAttributeName: String = 'LanguageName'; // do not localize - BoldMLLanguageNumberAttributeName: String = 'LanguageNumber'; // do not localize + BoldMLLanguageClassName: String = 'LanguageClass'; + BoldMLLanguageNameAttributeName: String = 'LanguageName'; + BoldMLLanguageNumberAttributeName: String = 'LanguageNumber'; implementation @@ -141,8 +146,7 @@ implementation BoldTaggedValueSupport, BoldSystemRT, BoldMemberTypeDictionary, - BoldDefaultStreamNames, - BoldCoreConsts; + BoldDefaultStreamNames; var _BoldLanguageList: TBADerivedValueSetValueList; @@ -160,24 +164,24 @@ procedure EnsureLanguageList; MemberRTInfo: TBoldMemberRTInfo; begin if loadingOfLanguages then - raise EBold.create(sBootStrapProblem); + raise EBold.create('BootStrap-problem, Probably the Languagename is an MLString... Not allowed, sorry'); if not assigned(_BoldLanguageList) then begin LoadingOfLanguages := true; LanguageTypeInfo := TBoldSystem.DefaultSystem.BoldSystemTypeInfo.ClassTypeInfoByExpressionName[BoldMLLanguageClassName]; if not assigned(LanguageTypeInfo) then - raise EBold.CreateFmt(sNeedClassCalledX, [BoldMLLanguageClassName]); + raise EBold.CreateFmt('For MultiLanguage to work, you need a class called "%s"', [BoldMLLanguageClassName]); MemberRTinfo := LanguageTypeInfo.MemberRTInfoByExpressionName[BoldMLLanguageNameAttributeName]; if not assigned(memberRTInfo) then - raise EBold.CreateFmt(sNeedMemberCalledX, [BoldMLLanguageClassName, BoldMLLanguageNameAttributeName]); + raise EBold.CreateFmt('For MultiLanguage to work, Class %s needs a member (string) called "%s"', [BoldMLLanguageClassName, BoldMLLanguageNameAttributeName]); if not memberRTInfo.MemberClass.InheritsFrom(TBAString) then - raise EBold.CreateFmt(sMustBeTBAString, [BoldMLLanguageNameAttributeName, memberRTInfo.MemberClass.ClassName]); + raise EBold.CreateFmt('For MultiLanguage to work, %s must be a TBAString, now it is a %s', [BoldMLLanguageNameAttributeName, memberRTInfo.MemberClass.ClassName]); memberRTInfo := LanguageTypeInfo.MemberRTInfoByExpressionName[BoldMLLanguageNumberAttributeName]; if not assigned(memberRTInfo) then - raise EBold.CreateFmt(sNeedIntegerMemberX, [BoldMLLanguageClassName, BoldMLLanguageNumberAttributeName]); + raise EBold.CreateFmt('For MultiLanguage to work, Class %s needs a member (integer) called "%s"', [BoldMLLanguageClassName, BoldMLLanguageNumberAttributeName]); if not memberRTInfo.MemberClass.InheritsFrom(TBAInteger) then - raise EBold.CreateFmt(sMemberXMustBeInteger, [BoldMLLanguageNumberAttributeName, memberRTInfo.MemberClass.ClassName]); + raise EBold.CreateFmt('For MultiLanguage to work, %s must be a TBAInteger, now it is a %s', [BoldMLLanguageNumberAttributeName, memberRTInfo.MemberClass.ClassName]); _BoldLanguageList := TBADerivedValueSetValueList.Create(TBoldSystem.DefaultSystem, BoldMLLanguageClassName, BoldMLLanguageNumberAttributeName, [BoldMLLanguageNameAttributeName]); LoadingOfLanguages := false; @@ -196,7 +200,7 @@ procedure ValidateLanguage(LanguageName, Location: String); if (Languagename <> '') and not loadingOfLanguages and not assigned(_BoldLanguageList.FindByText(brDefault, LanguageName)) then - raise EBold.CreateFmt(sInvalidLanguageName, [Location, languagename]) + raise EBold.CreateFmt('%s: Invalid languagename %s', [Location, languagename]) end; function EnsureValuesForElement(BoldSystem: TBoldSystem): TBoldSystem; @@ -215,32 +219,32 @@ function EnsureValuesForElement(BoldSystem: TBoldSystem): TBoldSystem; if _Systems.IndexOf(Result) = -1 then begin _Systems.Add(result); - _PrimaryLanguages.Add(TBoldMemberfactory.CreateMemberFromBoldType(result.BoldSystemTypeInfo.AttributeTypeInfoByDelphiName['TBALanguage'])); // do not localize - _SecondaryLanguages.Add(TBoldMemberfactory.CreateMemberFromBoldType(result.BoldSystemTypeInfo.AttributeTypeInfoByDelphiName['TBALanguage'])); // do not localize + _PrimaryLanguages.Add(TBoldMemberfactory.CreateMemberFromBoldType(result.BoldSystemTypeInfo.AttributeTypeInfoByDelphiName['TBALanguage'])); + _SecondaryLanguages.Add(TBoldMemberfactory.CreateMemberFromBoldType(result.BoldSystemTypeInfo.AttributeTypeInfoByDelphiName['TBALanguage'])); end; end; function BoldPrimaryLanguage(BoldSystem: tBoldSystem): TBALanguage; begin - Boldsystem := EnsureValuesForElement(BoldSystem); // a nil-parameter will be translated to DefaultSsytem + Boldsystem := EnsureValuesForElement(BoldSystem); result := TBALanguage(_PrimaryLanguages[_Systems.IndexOf(BoldSystem)]) end; function BoldSecondaryLanguage(BoldSystem: TBoldSystem): TBALanguage; begin - Boldsystem := EnsureValuesForElement(BoldSystem); // a nil-parameter will be translated to DefaultSsytem + Boldsystem := EnsureValuesForElement(BoldSystem); result := TBALanguage(_SecondaryLanguages[_Systems.IndexOf(BoldSystem)]) end; procedure BoldSetPrimaryLanguageByName(BoldSystem: TBoldSystem; LanguageName: String); begin - ValidateLanguage(LanguageName, 'BoldSetPrimaryLanguageByName'); // do not localize + ValidateLanguage(LanguageName, 'BoldSetPrimaryLanguageByName'); BoldPrimaryLanguage(BoldSystem).AsString := LanguageName; end; procedure BoldSetSecondaryLanguageByName(BoldSystem: TBoldSystem; LanguageName: String); begin - ValidateLanguage(LanguageName, 'BoldSetSecondaryLanguageByName'); // do not localize + ValidateLanguage(LanguageName, 'BoldSetSecondaryLanguageByName'); BoldSecondaryLanguage(BoldSystem).AsString := LanguageName; end; @@ -269,15 +273,15 @@ function TBAMLValueSetValue.GetStringRepresentation(Representation: TBoldReprese if representation in [1..StringRepresentationCount] then result := fStringRepresentations[Representation - 1].AsString else - raise EBold.CreateFmt(sRepresentationNotSupported, [ClassName, representation]); + raise EBold.CreateFmt('%s: representation not supported %d', [ClassName, representation]); end; -procedure TBAMLValueSetValue.SetStringRepresentation(Representation: TBoldRepresentation; Value: string); +procedure TBAMLValueSetValue.SetStringRepresentation(Representation: TBoldRepresentation; const Value: string); begin if representation in [1..StringRepresentationCount] then fStringRepresentations[Representation - 1].AsString := Value else - raise EBold.CreateFmt(sRepresentationNotSupported, [ClassName, representation]); + raise EBold.CreateFmt('%s: Representation not supported %d', [ClassName, representation]); end; function TBAMLValueSetValue.GetMLString(Representation: integer): TBAMLString; @@ -285,7 +289,7 @@ function TBAMLValueSetValue.GetMLString(Representation: integer): TBAMLString; if representation in [1..StringRepresentationCount] then result := FStringRepresentations[Representation - 1] as TBAMLString else - raise EBold.CreateFmt(sRepresentationNotSupported, [ClassName, representation]); + raise EBold.CreateFmt('%s: Representation not supported %d', [ClassName, representation]); end; procedure TBAMLValueSetValue.AddMLString(Value: TBAMLString); @@ -305,7 +309,7 @@ procedure TBAMLValueSetValueList.Addmembers(Int: Integer; Members: Array of TBol for i := 0 to High(Members) do begin if not (members[i] is TBAMLString) then - raise EBold.CreateFmt(sMLValueSetsRequireMLStrings, [Members[i].Classname]); + raise EBold.CreateFmt('TBAMLValueSets can only use TBAMLStrings, not %s', [Members[i].Classname]); AddMLString(Members[i] as TBAMLString); end; end; @@ -336,7 +340,7 @@ procedure TBAMLValueSet.DefaultSubscribe(Subscriber: TBoldSubscriber; requestedE procedure TBAMLValueSet.SubscribeToLanguage(representation: integer; Language: String; Subscriber: TBoldSubscriber; requestedEvent: TBoldEvent); begin - ValidateLanguage(Language, ClassName + '.SubscribeToLanguage'); // do not localize + ValidateLanguage(Language, ClassName + '.SubscribeToLanguage'); GetStringBylanguage(Representation, Language).DefaultSubscribe(Subscriber, requestedEvent); end; @@ -346,7 +350,7 @@ function TBAMLValueSet.GetStringBylanguage(representation: integer; LanguageName TempML: TBAMLString; begin Result := nil; - ValidateLanguage(LanguageName, ClassName + '.GetStringByLanguage'); // do not localize + ValidateLanguage(LanguageName, ClassName + '.GetStringByLanguage'); temp := Values.FindByInteger(AsInteger); if temp is TBAMLValueSetValue then @@ -356,8 +360,7 @@ function TBAMLValueSet.GetStringBylanguage(representation: integer; LanguageName end; end; -procedure TBAMLValueSet.InitializeMember(OwningElement: TBoldDomainElement; - ElementTypeInfo: TBoldElementTypeInfo); +procedure TBAMLValueSet.Initialize; var x: TBAvalueSetValue; begin @@ -378,7 +381,7 @@ procedure TBAMLValueSet.InitializeMember(OwningElement: TBoldDomainElement; function TBAMLValueSet.GetStringRepresentationByLanguage(Representation: integer; LAnguagename: String): String; begin if IsNull then {IsNull ensures current} - Result := '' //FIXME: raise Exception? + Result := '' else Result := GetStringbylanguage(Representation, LanguageName).AsString; end; @@ -393,19 +396,23 @@ procedure TBAMLValueSet.SetStringRepresentationByLanguage(Representation: intege if assigned(MLValue) then AsInteger := MLValue.AsInteger else - raise EBold.Create(sInvalidValue); + raise EBold.CreateFmt('%s: Invalid value %s', [ClassName, NewValue]); end; {--- TBALanguage ---} -function TBALanguage.GetValues: TBAValueSetValueList; +class function TBALanguage.GetValues: TBAValueSetValueList; begin - EnsureLanguageList; - result := _BoldLanguageList; + result := nil; + if TBoldSystem.DefaultSystem.BoldSystemTypeInfo.ClassTypeInfoByExpressionName[BoldMLLanguageClassName] <> nil then + begin + EnsureLanguageList; + result := _BoldLanguageList; + end; end; {--- TBAMLString ---} -destructor TBAMLString.Destroy; +destructor TBAMLString.destroy; begin PrepareToDestroy; inherited; @@ -425,17 +432,18 @@ procedure TBAMLString.Assign(Source: TBoldElement); AsString := Source.AsString; end; -function TBAMLString.GetContentAsBlob: String; +function TBAMLString.GetContentAsBlob: TBoldAnsiString; begin - result := StringRepresentation[brMLString]; + result := TBoldAnsiString(StringRepresentation[brMLString]); end; -procedure TBAMLString.SetContentAsBlob(const NewValue: String); +procedure TBAMLString.SetContentAsBlob(const NewValue: TBoldAnsiString); begin - StringRepresentation[brMLString] := NewValue; + StringRepresentation[brMLString] := String(NewValue); end; -procedure TBAMLString.ReceiveEventFromOwned(originator: TObject; originalEvent: TBoldEvent); + +procedure TBAMLString.ReceiveEventFromOwned(originator: TObject; originalEvent: TBoldEvent; const Args: array of const); begin if originalEvent in beValueEvents then SendEvent(OriginalEvent); @@ -455,13 +463,13 @@ function TBAMLString.GetStringBylanguage(LanguageName: String): TBAString; StrPos: integer; BoldString: TBAString; begin - ValidateLanguage(LanguageName, ClassName + '.GetStringByLanguage'); // do not localize + ValidateLanguage(LanguageName, ClassName + '.GetStringByLanguage'); if LanguageName = '' then LanguageName := BoldPrimaryLanguage(BoldSystem).AsString; StrPos := fMLStrings.IndexOf(LanguageName); if StrPos = -1 then begin - BoldString := TBoldDomainElementClass(StringClass).Create(self) as TBAString; + BoldString := TBoldDomainElementClass(StringClass).CreateWithOwner(self) as TBAString; StrPos := fMLStrings.AddObject(languagename, BoldString); end; Result := TBAString(fMLStrings.Objects[StrPos]) @@ -484,19 +492,16 @@ function TBAMLString.GetStringRepresentation(Representation: TBoldRepresentation result := '' else begin - // check the current language DisplayLanguage := BoldPrimaryLanguage(BoldSystem); result := GetStringByLanguage(DisplayLanguage.AsString).AsString; if result = '' then begin - // check the default language DisplayLanguage := BoldSecondaryLanguage(BoldSystem); result := GetStringByLanguage(DisplayLanguage.AsString).AsString; if result <> '' then result := format(BoldMLStringSecondaryFallBack, [DisplayLanguage.AsString, Result]) else begin - // check any language for i := 0 to BoldLanguageList.count - 1 do begin result := GetStringByLAnguage(BoldLanguageList[i].AsString).AsString; @@ -539,7 +544,6 @@ procedure TBAMLString.InternalSetDataValue(Representation:TBoldRepresentation; V Delete(Value, 1, Pos(#255, Value)); LangValue := copy(Value, 1, pos(#255, Value) - 1); Delete(Value, 1, Pos(#255, Value)); - // make sure not to send any events GetStringBylanguage(Lang).ProxyInterface(IBoldStringContent, bdepContents, StringContent); StringContent.asString := LangValue; end; @@ -550,7 +554,7 @@ procedure TBAMLString.InternalSetDataValue(Representation:TBoldRepresentation; V end; end; -procedure TBAMLString.SetStringRepresentation(Representation: TBoldRepresentation; Value: string); +procedure TBAMLString.SetStringRepresentation(Representation: TBoldRepresentation; const Value: string); begin if representation in [brMLString, brDefault] then InternalSetDataValue(representation, Value) @@ -567,7 +571,7 @@ procedure TBAMLString.DefaultSubscribe(Subscriber: TBoldSubscriber; requestedEve procedure TBAMLString.SubscribeToLanguage(Language: String; Subscriber: TBoldSubscriber; requestedEvent: TBoldEvent); begin - ValidateLanguage(Language, ClassName + '.SubscribeToLanguage'); // do not localize + ValidateLanguage(Language, ClassName + '.SubscribeToLanguage'); GetStringBylanguage(Language).DefaultSubscribe(Subscriber, requestedEvent); end; @@ -603,7 +607,6 @@ function SubscribeAndTestEmpty: Boolean; begin Language := BoldSecondaryLanguage(self.BoldSystem); SubscribeAndTestEmpty; - // if empty, stringrep will fall back to a constant string, no need to subscribe end; end else @@ -624,7 +627,7 @@ function TBAMLString.ValidateCharacter(C: Char; Representation: TBoldRepresentat result := inherited ValidateCharacter(c, representation); end; -function TBAMLString.ValidateString(Value: string; +function TBAMLString.ValidateString(const Value: string; Representation: TBoldRepresentation): Boolean; begin if fMLStrings.count > 0 then @@ -633,8 +636,7 @@ function TBAMLString.ValidateString(Value: string; result := inherited ValidateString(value, representation); end; -procedure TBALanguage.InitializeMember(OwningElement: TBoldDomainElement; - ElementTypeInfo: TBoldElementTypeInfo); +procedure TBALanguage.Initialize; var y: TBAvalueSetValueList; x: TBAvalueSetValue; @@ -644,9 +646,7 @@ procedure TBALanguage.InitializeMember(OwningElement: TBoldDomainElement; if assigned(y) then begin - // first, check if there is a language with the value 0 x := y.FindByInteger(0); - // if not, try any language if not assigned(x) then x := y.GetFirstvalue; if assigned(x) then @@ -657,8 +657,7 @@ procedure TBALanguage.InitializeMember(OwningElement: TBoldDomainElement; SetContentToNull; end; -procedure TBAMLString.InitializeMember(OwningElement: TBoldDomainElement; - ElementTypeInfo: TBoldElementTypeInfo); +procedure TBAMLString.Initialize; begin inherited; fMlStrings := TStringList.create; @@ -671,7 +670,7 @@ procedure TBAMLValueSetValue.SubscribeToStringRepresentation( if representation in [1..StringRepresentationCount] then fStringRepresentations[Representation - 1].SubscribeToStringRepresentation(brDefault, subscriber, requestedEvent) else - raise EBold.CreateFmt(sRepresentationNotSupported, [ClassName]); + raise EBold.CreateFmt('%s: Representation not supported %d', [ClassName]); end; procedure TBAMLValueSet.SubscribeToStringRepresentation( @@ -680,7 +679,7 @@ procedure TBAMLValueSet.SubscribeToStringRepresentation( begin Values[AsInteger].SubscribeToStringRepresentation(Representation, subscriber, requestedEvent); end; - +{$IFNDEF BOLD_NO_QUERIES} function TBAMLString.ReceiveQueryFromOwned(Originator: TObject; OriginalEvent: TBoldEvent; const Args: array of const; Subscriber: TBoldSubscriber): Boolean; @@ -689,8 +688,8 @@ function TBAMLString.ReceiveQueryFromOwned(Originator: TObject; if OriginalEvent = bqMayModify then result := CanModify; end; - -procedure TBAMLString.AssignContentValue(Source: IBoldValue); +{$ENDIF} +procedure TBAMLString.AssignContentValue(const Source: IBoldValue); var s: IBoldBlobContent; begin @@ -699,31 +698,26 @@ procedure TBAMLString.AssignContentValue(Source: IBoldValue); if s.IsNull then SetContentToNull else - StringRepresentation[brMLString] := s.asBlob; + StringRepresentation[brMLString] := String(s.asBlob); end else - raise EBold.CreateFmt(sUnknownTypeOfSource, [classname, 'AssignContentValue']); // do not localize + raise EBold.CreateFmt('%s.AssignContentValue: unknown type of source', [classname]); end; { TBoldMLString_Proxy } function TBAMLString_Proxy.GetProxedMLString: TBAMLString; begin - result := ProxedElement as TBAMLString; -end; - -function TBAMLString.ProxyClass: TBoldMember_ProxyClass; -begin - result := TBAMLString_Proxy; + result := ProxedMember as TBAMLString; end; function TBAMLString.ProxyInterface(const IId: TGUID; Mode: TBoldDomainElementProxyMode; out Obj): Boolean; begin if IsEqualGuid(IID, IBoldBlobContent) then begin - result := ProxyClass.create(self, Mode).GetInterface(IID, obj); + result := TBAString_Proxy.MakeProxy(self, Mode).GetInterface(IID, obj); if not result then - raise EBoldInternal.CreateFmt(sProxyClassDidntImplementInterface, [ClassName]); + raise EBoldInternal.CreateFmt('ProxyClass for %s did not implement IBoldBlobContent', [ClassName]); end else result := inherited ProxyInterface(IID, Mode, Obj); @@ -738,7 +732,7 @@ function TBAMLSubString.StartModify: Boolean; if (OwningElement is TBoldMember) then begin if not (BoldPersistenceState in [bvpsCurrent, bvpsModified, bvpsTransient, bvpsInvalid]) then - StateError('StartModify'); // do not localize + StateError('StartModify'); result := CanModify; OwningMember := (OwningElement as TBoldMember); if result and assigned(OwningMember.BoldSystem) and assigned(OwningMember.OwningObject) and @@ -747,7 +741,7 @@ function TBAMLSubString.StartModify: Boolean; result := OwningMember.BoldSystem.PessimisticLockHandler.LockElement(OwningMember); if result then begin - if assigned(OwningMember.OwningObject) and not OwningMember.BoldSystem.InTransaction and StoreInUndo then // Object always has system + if assigned(OwningMember.OwningObject) and not OwningMember.BoldSystem.InTransaction and StoreInUndo then OwningMember.BoldSystem.UndoHandler.HandleMember(OwningMember.OwningObject.AsIBoldObjectContents[bdepContents], OwningMember.BoldMemberRTInfo.Index, OwningMember.AsIBoldValue[bdepContents]); DoStartModify; @@ -755,6 +749,7 @@ function TBAMLSubString.StartModify: Boolean; end else result := inherited StartModify; + end; function TBAMLValueSet.CompareToEnumLiteral(const str: String): Boolean; diff --git a/Source/ObjectSpace/BORepresentation/BoldOSSMessage.pas b/Source/ObjectSpace/BORepresentation/BoldOSSMessage.pas new file mode 100644 index 0000000..9a54df7 --- /dev/null +++ b/Source/ObjectSpace/BORepresentation/BoldOSSMessage.pas @@ -0,0 +1,166 @@ +unit BoldOSSMessage; + +interface + +uses + Classes; // for TPersistent +// SynCommons; // for TDateTimeMS +// BoldDefs; // for TBoldTimeStampType + +const + cOSSMessageSync = 'SYNC'; + cOSSMessageFail = 'FAIL'; + +type + TSessionId = Int64; + TBoldTimeStampType = integer; // copy from BoldDefs + TOSSMessageType = (mtSync, mtFail); + TDateTimeMS = TDateTime; + + TOSSMessage = class(TInterfacedPersistent) + private + fMessageType: TOSSMessageType; + fEvents: string; + fBoldTimeStamp: TBoldTimeStampType; + fTimeOfTimeStamp: TDateTimeMS; + fClientSendTime: TDateTimeMS; + fUser: string; + fApplication: string; + fComputer: string; + function GetAsString: string; + procedure SetAsString(const Value: string); + protected + procedure AssignTo(Dest: TPersistent); override; + public + constructor Create; overload; + constructor Create( + AMessageType: TOSSMessageType; + AEvents: string; + ABoldTimeStamp: TBoldTimeStampType; + ATimeOfTimeStamp: TDateTimeMS; + AClientSendTime: TDateTimeMS; + AUser: string = ''; + AComputer: string = ''; + AApplication: string = ''); overload; + destructor Destroy; override; + function Clone: TOSSMessage; + property AsString: string read GetAsString write SetAsString; + published + property MessageType: TOSSMessageType read fMessageType; + property Events: string read fEvents; + property BoldTimeStamp: TBoldTimeStampType read fBoldTimeStamp; + property TimeOfTimeStamp: TDateTimeMS read fTimeOfTimeStamp; + property ClientSendTime: TDateTimeMS read fClientSendTime; + // writeable properties, can be sent blank and filled in by service + property Computer: string read fComputer write fComputer; + property Application: string read fApplication write fApplication; + property User: string read fUser write fUser; + end; + +implementation + +uses + System.SysUtils, + BoldIsoDateTime, + TypInfo; + +{ TOSSMessage } + +constructor TOSSMessage.Create; +begin + inherited; +end; + +destructor TOSSMessage.Destroy; +begin + inherited; +end; + +function TOSSMessage.GetAsString: string; +var + sb: TStringBuilder; +begin + sb := TStringBuilder.Create; + try + sb.EnsureCapacity(Length(Events)+100); + sb.AppendLine(String((GetEnumName(TypeInfo(TOSSMessageType), Ord(MessageType))))); + sb.AppendLine(IntToStr(BoldTimeStamp)); + sb.AppendLine(AsISODateTimeMS(TimeOfTimeStamp)); + sb.AppendLine(AsISODateTimeMS(ClientSendTime)); + sb.AppendLine(User); + sb.AppendLine(Computer); + sb.AppendLine(Application); + sb.AppendLine(Events); + result := sb.ToString; + finally + sb.free; + end; +end; + +procedure TOSSMessage.SetAsString(const Value: string); +var + sl: TStringList; +begin + sl := TStringList.Create; + try + sl.Text := Value; + Assert(sl.Count = 8, 'Wrong count of lines in OSSMessage:' + IntToStr(sl.count)); + if sl[0] = 'mtSync' then + fMessageType := mtSync + else + if sl[0] = 'mtFail' then + fMessageType := mtFail + else + raise Exception.Create('Unknown MessageType'); + fBoldTimeStamp := StrToint(sl[1]); + fTimeOfTimeStamp :=ParseISODateTime(sl[2]); + fClientSendTime := ParseISODateTime(sl[3]); + fUser := sl[4]; + fComputer := sl[5]; + fApplication := sl[6]; + fEvents := sl[7]; + finally + sl.Free; + end; +end; + +constructor TOSSMessage.Create(AMessageType: TOSSMessageType; AEvents: string; + ABoldTimeStamp: TBoldTimeStampType; ATimeOfTimeStamp, + AClientSendTime: TDateTimeMS; + AUser: string; AComputer: string; AApplication: string); +begin + fMessageType := AMessageType; + fEvents := AEvents; + fBoldTimeStamp := ABoldTimeStamp; + fTimeOfTimeStamp := ATimeOfTimeStamp; + fClientSendTime := AClientSendTime; + fUser := AUser; + fComputer := AComputer; + fApplication := AApplication; +end; + +procedure TOSSMessage.AssignTo(Dest: TPersistent); +begin + if Dest is TOSSMessage then + with Dest as TOSSMessage do + begin + fMessageType := self.fMessageType; + fEvents := self.fEvents; + fBoldTimeStamp := self.fBoldTimeStamp; + fTimeOfTimeStamp := self.fTimeOfTimeStamp; + fClientSendTime := self.fClientSendTime; + fApplication := self.fApplication; + fUser := self.fUser; + fComputer := self.fComputer; + end + else + inherited; +end; + +function TOSSMessage.Clone: TOSSMessage; +begin + result := TOSSMessage.Create; + self.AssignTo(result); +end; + +end. diff --git a/Source/ObjectSpace/BORepresentation/BoldObjectListControllers.pas b/Source/ObjectSpace/BORepresentation/BoldObjectListControllers.pas index 0da5e82..76b4f7c 100644 --- a/Source/ObjectSpace/BORepresentation/BoldObjectListControllers.pas +++ b/Source/ObjectSpace/BORepresentation/BoldObjectListControllers.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldObjectListControllers; interface @@ -5,7 +8,7 @@ interface uses Classes, BoldSystem, - BoldObjectSpaceLists, + BoldObjectSpaceLists, BoldDomainElement, BoldValueInterfaces, BoldId, @@ -25,21 +28,23 @@ TBoldObjectList_Proxy = class; TBoldObjectListController = class(TBoldAbstractObjectListController) private FList: TBoldObjectAttributeIndexList; - FSubscriber: TBoldPassthroughSubscriber; + FSubscriber: TBoldExtendedPassthroughSubscriber; procedure _ReceiveObjectDeleted(Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent; const Args: array of const); - function GetLocatorList: TBoldObjectLocatorList; + function GetLocatorList: TBoldObjectLocatorList; {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure InternalRemoveByIndex(index: Integer); protected function CreateNew: TBoldElement; override; function GetStreamName: string; override; - function ProxyClass: TBoldMember_ProxyClass; override; + function GetProxy(Member: TBoldMember; Mode: TBoldDomainElementProxyMode): TBoldMember_Proxy; override; procedure SubscribeToObjectDeleted(Locator: TBoldObjectLocator); virtual; + function GetCapacity: integer; override; + procedure SetCapacity(const Value: integer); override; public - constructor Create(OwningList: TBoldObjectList); + constructor Create(OwningList: TBoldObjectList); reintroduce; destructor Destroy; override; procedure AddLocator(Locator: TBoldObjectLocator); override; procedure AssignContentValue(Source: IBoldValue); - procedure DropSubscriptions; + procedure DropSubscriptions; {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure Resubscribe; function GetCount: Integer; override; function GetLocator(index: Integer): TBoldObjectLocator; override; @@ -52,76 +57,123 @@ TBoldObjectListController = class(TBoldAbstractObjectListController) procedure RemoveByIndex(index: Integer); override; procedure SetLocator(index: Integer; Locator: TBoldObjectLocator); override; procedure FreeContent; override; + procedure Clear; override; property LocatorList: TBoldObjectLocatorList read GetLocatorList; end; +{ BoldPersistenceState: + bvpsInvalid: List contains just objcets that have been loaded or allloadedobjects + bvpsTransient: Means that all IDs are loaded + bvpsCurrent: Means all IDs and all Objects are loaded. +} { TBoldClassListController } TBoldClassListController = class(TBoldObjectListController) private fTimestamp: TBoldTimestampType; fAtTimeList: TList; + fClassTypeInfo: TBoldClassTypeInfo; + fSuperclasslist: TBoldObjectList; + fSuperClassController: TBoldClassListController; + fLoadedObjectCount: Integer; function GetAtTimeList: TList; procedure FillFromClassList(ObjectList: TBoldObjectList); procedure FillFromSystem; - function ClosestLoadedClassList: TBoldObjectList; property AtTimeList: TList read GetAtTimeList; - function GetIdList(Index: Integer): TBoldObjectID; + function GetIdList(Index: Integer): TBoldObjectID; {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure SetFromIdList(List: TBoldObjectIdList; Mode: TBoldDomainElementProxyMode); + procedure MarkAsAllIDsLoaded; + procedure MarkListCurrent; + procedure CheckStillCurrent; + procedure SetPersistenceState(APersistenceState: TBoldValuePersistenceState); protected function GetCanCreateNew: Boolean; override; - function GetClassTypeInfo: TBoldClassTypeInfo; function GetStringrepresentation: String; override; procedure SubscribeToObjectDeleted(Locator: TBoldObjectLocator); override; - property ClassTypeInfo: TBoldClassTypeInfo read GetClassTypeInfo; - function ProxyClass: TBoldMember_ProxyClass; override; + property ClassTypeInfo: TBoldClassTypeInfo read fClassTypeInfo; + function GetProxy(Member: TBoldMember; Mode: TBoldDomainElementProxyMode): TBoldMember_Proxy; override; public constructor Create(OwningList: TBoldObjectList); destructor Destroy; override; - procedure ReceiveClassEvent(BoldObject: TBoldObject; EVENT: TBoldEvent); + procedure ReceiveClassEvent(BoldObject: TBoldObject; Event: TBoldEvent); function ProxyInterface(const IId: TGUID; Mode: TBoldDomainElementProxyMode; out Obj): Boolean; override; function AtTime(Time: TBoldTimeStampType): TBoldMember; override; function HandlesAtTime: Boolean; override; procedure MakeDbCurrent; override; + procedure AddLocator(Locator: TBoldObjectLocator); override; procedure RemoveByIndex(index: Integer); override; + property LoadedObjectCount: Integer read fLoadedObjectCount; + function HasLoadedSuperClass: boolean; + function ClosestLoadedClassList: TBoldObjectList; + function IsCurrentOrSuperClassIsCurrent: boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} end; { TBoldObjectList_Proxy } TBoldObjectList_Proxy = class(TBoldMember_Proxy) private - function GetObjectListController: TBoldObjectListController; + function GetObjectListController: TBoldObjectListController; {$IFDEF BOLD_INLINE} inline; {$ENDIF} protected - procedure AssignContentValue(Source: IBoldValue); override; + procedure AssignContentValue(const Source: IBoldValue); override; property ObjectListController: TBoldObjectListController read GetObjectListController; end; { TBoldClassList_Proxy } TBoldClassList_Proxy = class(TBoldMember_Proxy, IBoldObjectIdListRef) private - function GetClassListController: TBoldClassListController; - // IBoldObjectIdListRef + function GetClassListController: TBoldClassListController; {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure SetFromIdList(IdLIst: TBoldObjectIdList); - function GetIdList(Index: Integer): TBoldObjectID; - function GetCount: integer; + procedure SetList(IdList: TBoldObjectIdList); + function GetIdList(Index: Integer): TBoldObjectID; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetCount: integer; {$IFDEF BOLD_INLINE} inline; {$ENDIF} protected property ClassListController: TBoldClassListController read GetClassListController; - procedure AssignContentValue(Source: IBoldValue); override; + procedure AssignContentValue(const Source: IBoldValue); override; end; +const + beClassListStateChanged = 31; // this is used so that we can subscribe to BoldPersistenceState of a class list + implementation uses SysUtils, BoldIndexableList, - BoldDefaultStreamNames, - BoldValueSpaceInterfaces, - BoldCoreConsts; + BoldDefaultStreamNames, + BoldValueSpaceInterfaces; { TBoldObjectListController } +constructor TBoldObjectListController.Create(OwningList: TBoldObjectList); +begin + inherited Create(OwningList); + FList := TBoldObjectLocatorList.Create; +end; + +destructor TBoldObjectListController.Destroy; +begin + FreeAndNil(FList); + FreeAndNil(FSubscriber); + inherited; +end; + +function TBoldObjectListController.GetLocatorList: TBoldObjectLocatorList; +begin + result := TBoldObjectLocatorList(FList); +end; + procedure TBoldObjectListController.AddLocator(Locator: TBoldObjectLocator); begin if not StartModify then - BoldRaiseLastFailure(OwningList, 'AddLocator', ''); // do not localize + BoldRaiseLastFailure(OwningList, 'AddLocator', ''); + +{$IFNDEF AllowCrossSystemLists} + if (BoldSystemCount > 1) and Assigned(BoldSystem) then + begin + Assert(Assigned(Locator), 'Locator not Assigned'); + Assert(Assigned(Locator.BoldSystem), 'Locator.BoldSystem not Assigned'); + if Locator.BoldSystem <> BoldSystem then + SetBoldLastFailureReason(TBoldFailureReason.CreateFmt('TBoldObjectListController.AddLocator: Locator from another system not allowed to be added to %s, Define conditional AllowCrossSystemLists if you want to allow this.', [OwningMember.DisplayName], OwningList)); + end; +{$ENDIF} LocatorList.Add(Locator); SubscribeToObjectDeleted(Locator); @@ -130,18 +182,9 @@ procedure TBoldObjectListController.AddLocator(Locator: TBoldObjectLocator); EndModify; end; -constructor TBoldObjectListController.Create(OwningList: TBoldObjectList); +function TBoldObjectListController.GetCapacity: integer; begin - inherited Create(OwningList); - FList := TBoldObjectLocatorList.Create; - FSubscriber := TBoldPassthroughSubscriber.CreateWithExtendedReceive(_ReceiveObjectDeleted); -end; - -destructor TBoldObjectListController.Destroy; -begin - FreeAndNil(FList); - FreeAndNil(FSubscriber); - inherited; + result := LocatorList.Capacity; end; function TBoldObjectListController.GetCount: Integer; @@ -163,21 +206,15 @@ function TBoldObjectListController.GetLocatorByQualifiersAndSubscribe(MemberList begin if assigned(OwningObjectList.BoldRoleRTInfo) and OwningObjectList.BoldRoleRTInfo.IsQualified then begin - // this handles qualified derived associations OwningObjectList.EnsureContentsCurrent; LocatorList.InitMembersIndex(OwningObjectList, OwningObjectList.BoldRoleRTInfo.Qualifiers); end else - raise EBold.CreateFmt(sRolenotQualified, [ClassName]); + raise EBold.CreateFmt('%s.GetLocatorByQualifiersAndSubscribe: Object list does not have a member index or role is not qualified', [ClassName]); end; result := List.GetLocatorByAttributesAndSubscribe(MemberList, Subscriber); end; -function TBoldObjectListController.GetLocatorList: TBoldObjectLocatorList; -begin - result := TBoldObjectLocatorList(FList); -end; - function TBoldObjectListController.IncludesLocator(Locator: TBoldObjectLocator): Boolean; begin Result := LocatorList.LocatorInList[Locator]; @@ -191,8 +228,16 @@ function TBoldObjectListController.IndexOfLocator(Locator: TBoldObjectLocator): procedure TBoldObjectListController.InsertLocator(index: Integer; Locator: TBoldObjectLocator); begin if not StartModify then - BoldRaiseLastFailure(OwningList, 'InsertLocator', ''); // do not localize - + BoldRaiseLastFailure(OwningList, 'InsertLocator', ''); +{$IFNDEF AllowCrossSystemLists} + if (BoldSystemCount > 1) and Assigned(BoldSystem) then + begin + Assert(Assigned(Locator), 'Locator not Assigned'); + Assert(Assigned(Locator.BoldSystem), 'Locator.BoldSystem not Assigned'); + if Locator.BoldSystem <> BoldSystem then + SetBoldLastFailureReason(TBoldFailureReason.CreateFmt('TBoldObjectListController.InsertLocator: Locator from another system not allowed to be inserted in %s, Define conditional AllowCrossSystemLists if you want to allow this.', [OwningMember.DisplayName], OwningList)); + end; +{$ENDIF} LocatorList.Insert(index, Locator); SubscribeToObjectDeleted(Locator); Changed(beItemAdded, [Locator]); @@ -203,7 +248,7 @@ procedure TBoldObjectListController.InsertLocator(index: Integer; Locator: TBold procedure TBoldObjectListController.Move(CurrentIndex, NewIndex: Integer); begin if not StartModify then - BoldRaiseLastFailure(OwningList, 'Move', ''); // do not localize + BoldRaiseLastFailure(OwningList, 'Move', ''); LocatorList.Move(CurrentIndex, NewIndex); Changed(beOrderChanged, []); @@ -223,20 +268,34 @@ procedure TBoldObjectListController.InternalRemoveByIndex(index: Integer); procedure TBoldObjectListController.RemoveByIndex(index: Integer); begin if not StartModify then - BoldRaiseLastFailure(OwningList, 'RemoveByIndex', ''); // do not localize + BoldRaiseLastFailure(OwningList, 'RemoveByIndex', ''); InternalRemoveByIndex(index); EndModify; end; +procedure TBoldObjectListController.SetCapacity(const Value: integer); +begin + LocatorList.Capacity := Value; +end; + procedure TBoldObjectListController.SetLocator(index: Integer; Locator: TBoldObjectLocator); begin if not StartModify then - BoldRaiseLastFailure(OwningList, 'SetLocator', ''); // do not localize + BoldRaiseLastFailure(OwningList, 'SetLocator', ''); if Locator = nil then RemoveByIndex(index) else begin +{$IFNDEF AllowCrossSystemLists} + if (BoldSystemCount > 1) and Assigned(BoldSystem) then + begin + Assert(Assigned(Locator), 'Locator not Assigned'); + Assert(Assigned(Locator.BoldSystem), 'Locator.BoldSystem not Assigned'); + if Locator.BoldSystem <> BoldSystem then + SetBoldLastFailureReason(TBoldFailureReason.CreateFmt('TBoldObjectListController.SetLocator: Locator from another system not allowed to be inserted in %s, Define conditional AllowCrossSystemLists if you want to allow this.', [OwningMember.DisplayName], OwningList)); + end; +{$ENDIF} LocatorList[index] := Locator; SubscribeToObjectDeleted(Locator); Changed(beItemReplaced, [Locator, Index]); @@ -252,7 +311,6 @@ function TBoldObjectListController.GetStreamname: string; procedure TBoldObjectListController.MakeDbCurrent; begin - // do nothing. Object lists are not persistent and therefore always current. end; procedure TBoldObjectListController._ReceiveObjectDeleted( @@ -263,53 +321,82 @@ procedure TBoldObjectListController._ReceiveObjectDeleted( var i: Integer; begin + {$IFDEF AllowCrossSystemLists} for i := Count - 1 downto 0 do if LocatorList[i].BoldSystem = System then InternalRemoveByIndex(i); + {$ELSE} + LocatorList.Clear; + {$ENDIF} + end; + + procedure RemoveLocator(Locator: TBoldObjectLocator); + begin + if LocatorList.LocatorInList[Locator] then + begin + LocatorList.Remove(Locator); + Changed(beItemDeleted, [Locator]); + end; end; var DeletedLocator: TBoldObjectLocator; begin - assert(originator is TBoldSystem); - case RequestedEvent of + assert(originator is TBoldObjectList); + case OriginalEvent of beLocatorDestroying, beObjectDeleted: begin assert(High(Args) = 0); assert(Args[0].vType = vtObject); - DeletedLocator := TBoldObject(Args[0].VObject).BoldObjectLocator; - if LocatorList.LocatorInList[DeletedLocator] then - begin - LocatorList.Remove(DeletedLocator); - Changed(beItemDeleted, [DeletedLocator]); - end; + Assert(Args[0].VObject is TBoldObjectLocator); + DeletedLocator := TBoldObjectLocator(Args[0].VObject); +// Assert(not Assigned(OwningList.Boldtype) or DeletedLocator.BoldObject.BoldClassTypeInfo.BoldIsA(TBoldListTypeInfo(OwningList.Boldtype).ListElementTypeInfo)); + RemoveLocator(DeletedLocator); end; beDestroying: begin - RemoveAllObjectsFromSystem(TBoldSystem(Originator)); + RemoveAllObjectsFromSystem(TBoldSystem(TBoldObjectList(Originator).OwningElement)); end; else - raise EBoldInternal.CreateFmt(sUnknownEvent, [classname]); + raise EBoldInternal.CreateFmt('%s._ReceiveObjectDeleted: Unknown event', [classname]); end; end; procedure TBoldObjectListController.SubscribeToObjectDeleted(Locator: TBoldObjectLocator); +var + ClassList: TBoldObjectList; begin - if OwningObjectList.SubscribeToObjectsInList then + with OwningObjectList do begin - // Object deleted - Locator.BoldSystem.AddSmallSubscription(FSubscriber, [beObjectDeleted], beObjectDeleted); - // System Destroyed - Locator.BoldSystem.AddSmallSubscription(FSubscriber, [beDestroying], beDestroying); + if not (SubscribeToLocatorsInList or SubscribeToObjectsInList) then + exit; + if Assigned(FSubscriber) then + exit + else + FSubscriber := TBoldExtendedPassthroughSubscriber.CreateWithExtendedReceive(_ReceiveObjectDeleted); + + if Assigned(OwningObjectList.BoldType) then + ClassList := Locator.BoldSystem.Classes[TBoldClassTypeInfo(TBoldListTypeInfo(OwningObjectList.BoldType).ListElementTypeInfo).TopSortedIndex] + else + ClassList := Locator.BoldSystem.Classes[0]; + + if SubscribeToLocatorsInList then + begin + if SubscribeToObjectsInList then + ClassList.AddSmallSubscription(FSubscriber, [beLocatorDestroying, beDestroying, beObjectDeleted], beLocatorDestroying) + else + ClassList.AddSmallSubscription(fSubscriber, [beLocatorDestroying], beLocatorDestroying); + end + else + if SubscribeToObjectsInList then + ClassList.AddSmallSubscription(FSubscriber, [beDestroying, beObjectDeleted], beLocatorDestroying); end; - if OwningObjectList.SubscribeToLocatorsInList then - Locator.BoldSystem.AddSmallSubscription(fSubscriber, [beLocatorDestroying], beLocatorDestroying); end; procedure TBoldObjectListController.DropSubscriptions; begin - FSubscriber.CancelAllSubscriptions; + FreeAndNil(FSubscriber); end; procedure TBoldObjectListController.Resubscribe; @@ -318,17 +405,36 @@ procedure TBoldObjectListController.Resubscribe; LastSystem: TBoldSystem; Locator: TBoldObjectLocator; begin - LastSystem := nil; - for i := 0 to Count - 1 do + Locator := (LocatorList.Any) as TBoldObjectLocator; + if Assigned(Locator) then begin - // only add subscriptions once per system for performance. - Locator := Locatorlist[i]; - if Locator.BoldSystem <> LastSystem then + SubscribeToObjectDeleted(Locator); + if BoldSystemCount > 1 then begin - SubscribeToObjectDeleted(LocatorList[i]); LastSystem := Locator.BoldSystem; + for i := 0 to Count - 1 do + begin + Locator := Locatorlist[i]; + if Locator.BoldSystem <> LastSystem then + begin + SubscribeToObjectDeleted(LocatorList[i]); + LastSystem := Locator.BoldSystem; + end; + end; end; - end; + end +end; + +procedure TBoldObjectListController.Clear; +var + i: integer; +begin + with OwningObjectList do + if MemberHasSubscribers or IsPartOfSystem then + inherited + else + LocatorList.Clear; + DropSubscriptions; end; procedure TBoldObjectListController.AssignContentValue(Source: IBoldValue); @@ -347,7 +453,7 @@ procedure TBoldObjectListController.AssignContentValue(Source: IBoldValue); Changed(beValueChanged, []); end else - raise EBold.CreateFmt(sUnknownTypeOfSource, [classname, 'AssignContentValue']); // do not localize + raise EBold.CreateFmt('%s.AssignContentValue: unknown type of source', [classname]); end; procedure TBoldObjectListController.FreeContent; @@ -355,29 +461,19 @@ procedure TBoldObjectListController.FreeContent; Locatorlist.Clear; end; -function TBoldObjectListController.ProxyClass: TBoldMember_ProxyClass; +function TBoldObjectListController.GetProxy(Member: TBoldMember; Mode: TBoldDomainElementProxyMode): TBoldMember_Proxy; begin - Result := TBoldObjectList_Proxy; + Result := TBoldObjectList_Proxy.Create(Member, Mode); end; { TBoldClassListController } function TBoldObjectListController.CreateNew: TBoldElement; var - ListtypeInfo: TBoldListTypeInfo; ClassTypeInfo: TBoldClassTypeInfo; begin - ListTypeInfo := TBoldListTypeInfo(OwningList.Boldtype); - ClassTypeInfo := TBoldClassTypeInfo(ListTypeInfo.ListElementTypeInfo); - result := TBoldObjectClass(ClassTypeInfo.ObjectClass).InternalCreateNewWithClassAndSystem(ClassTypeInfo, owningList.BoldSystem, True); -end; - -function TBoldClassListController.GetClassTypeInfo: TBoldClassTypeInfo; -var - listtypeInfo: TBoldLIstTypeInfo; -begin - ListTypeInfo := TBoldListTypeInfo(OwningList.Boldtype); - result := TBoldClassTypeInfo(ListTypeInfo.ListElementTypeInfo); + ClassTypeInfo := TBoldClassTypeInfo(TBoldListTypeInfo(OwningList.Boldtype).ListElementTypeInfo); + result := TBoldObjectClass(ClassTypeInfo.ObjectClass).InternalCreateNewWithClassAndSystem(ClassTypeInfo, BoldSystem, True); end; function TBoldClassListController.GetCanCreateNew: Boolean; @@ -385,12 +481,12 @@ function TBoldClassListController.GetCanCreateNew: Boolean; result := true; if result and ClassTypeInfo.IsAbstract then begin - SetBoldLastFailureReason(TBoldFailureReason.CreateFmt(sClassIsAbstract, [ClassTypeInfo.ExpressionName], OwningList)); + SetBoldLastFailureReason(TBoldFailureReason.CreateFmt('%s is an abstract class', [ClassTypeInfo.ExpressionName], OwningList)); result := false; end; if result and ClassTypeInfo.IsLinkClass then begin - SetBoldLastFailureReason(TBoldFailureReason.CreateFmt(sClassIsLinkClass, [ClassTypeInfo.ExpressionName], OwningList)); + SetBoldLastFailureReason(TBoldFailureReason.CreateFmt('%s is a LinkClass', [ClassTypeInfo.ExpressionName], OwningList)); result := false; end; end; @@ -402,11 +498,33 @@ function TBoldClassListController.GetStringrepresentation: String; procedure TBoldClassListController.FillFromClassList(ObjectList: TBoldObjectList); var - i: integer; + I: Integer; + iTopSortedIndex: Integer; + DestinationList: TBoldObjectList; + Locator: TBoldObjectLocator; begin - for i := 0 to ObjectList.Count - 1 do - if ObjectList[i].BoldClassTypeInfo.BoldIsA(ClassTypeinfo) then - OwningList.Add(ObjectList[i]); + iTopSortedIndex := ClassTypeinfo.TopSortedIndex; + DestinationList := OwningObjectList; + for I := 0 to ObjectList.Count - 1 do + begin + Locator := ObjectList.Locators[I]; + if Assigned(Locator.BoldObject) then + begin + if Locator.BoldObject.BoldClassTypeInfo.BoldIsA(ClassTypeInfo) then + DestinationList.AddLocator(Locator); + end + else + if Locator.BoldObjectID.TopSortedIndexExact and + ((Locator.BoldObjectID.TopSortedIndex = iTopSortedIndex) or + (Locator.BoldClassTypeInfo.BoldIsA(ClassTypeinfo))) then + begin + DestinationList.AddLocator(Locator); + iTopSortedIndex := Locator.BoldObjectID.TopSortedIndex; + end + else + if Locator.EnsuredBoldObject.BoldClassTypeInfo.BoldIsA(ClassTypeInfo) then + DestinationList.AddLocator(Locator); + end; end; procedure TBoldClassListController.FillFromSystem; @@ -414,8 +532,8 @@ procedure TBoldClassListController.FillFromSystem; Traverser: TBoldLocatorListTraverser; Locator: TBoldObjectLocator; begin - Traverser := OwningList.BoldSystem.Locators.CreateTraverser; - while not Traverser.EndOfList do + Traverser := BoldSystem.Locators.CreateTraverser; + while Traverser.MoveNext do begin Locator := Traverser.Locator; if assigned(Locator.BoldObject) and not Locator.BoldObject.BoldPersistent @@ -424,7 +542,6 @@ procedure TBoldClassListController.FillFromSystem; begin LocatorList.Add(Locator); end; - Traverser.Next; end; Traverser.Free; end; @@ -432,6 +549,7 @@ procedure TBoldClassListController.FillFromSystem; function TBoldClassListController.ClosestLoadedClassList: TBoldObjectList; var SuperClass: TBoldClassTypeInfo; + SuperClassList: TBoldObjectList; begin if fTimestamp <> BOLDMAXTIMESTAMP then begin @@ -440,11 +558,12 @@ function TBoldClassListController.ClosestLoadedClassList: TBoldObjectList; end; SuperClass := ClassTypeInfo.SuperClassTypeInfo; - while assigned(SuperClass) and (OwningList.BoldSystem.Classes[SuperClass.TopSortedIndex].BoldPersistenceState <> bvpsCurrent) do - SuperClass := SuperClass.SuperClassTypeInfo; + with BoldSystem do + while assigned(SuperClass) and (Classes[SuperClass.TopSortedIndex].BoldPersistenceState <> bvpsCurrent) do + SuperClass := SuperClass.SuperClassTypeInfo; if assigned(SuperClass) then - result := OwningList.BoldSystem.Classes[SuperClass.TopSortedIndex] + result := BoldSystem.Classes[SuperClass.TopSortedIndex] else result := nil; end; @@ -453,7 +572,7 @@ procedure TBoldClassListController.MakeDbCurrent; var SourceList: TBoldObjectList; begin - if ClassTypeinfo.Persistent and OwningList.BoldSystem.BoldPersistent then + if ClassTypeinfo.Persistent and BoldSystem.BoldPersistent then begin SourceList := ClosestLoadedClassList; @@ -464,60 +583,109 @@ procedure TBoldClassListController.MakeDbCurrent; end else FillFromSystem; - OwningList.BoldPersistenceState := bvpsTransient; + MarkAsAllIDsLoaded; end; -procedure TBoldClassListController.ReceiveClassEvent(BoldObject: TBoldObject; Event: TBoldEvent); -var - SuperClassTypeInfo: TBoldClassTypeInfo; - Superclasslist: TBoldObjectList; +procedure TBoldClassListController.MarkAsAllIDsLoaded; begin - SuperClassTypeInfo := ClassTypeInfo.SuperClassTypeInfo; - if Assigned(SuperClassTypeInfo) then + if fLoadedObjectCount = Count then + MarkListCurrent + else + SetPersistenceState(bvpsTransient); +end; + +procedure TBoldClassListController.MarkListCurrent; +begin + if (OwningList.BoldPersistenceState <> bvpsCurrent) and (fLoadedObjectCount = Count) then begin - SuperClassList := BoldSystem.Classes[SuperClassTypeInfo.TopSortedIndex]; - TBoldClassListController(GetControllerForMember(SuperClassList)).ReceiveClassEvent(BoldObject, EVENT); + SetPersistenceState(bvpsCurrent); end; - if Owninglist.BoldPersistenceState <> bvpsInvalid then - begin - case Event of - beObjectCreated: AddLocator(BoldObject.BoldObjectLocator); - beObjectDeleted: +end; + +procedure TBoldClassListController.ReceiveClassEvent(BoldObject: TBoldObject; Event: TBoldEvent); +begin + if Assigned(fSuperClassController) then + fSuperClassController.ReceiveClassEvent(BoldObject, Event); + case Event of + beObjectCreated: begin - // it is a linear operation to delete objects in the classlist - // invalidating it is also linear, but hopefully it does not have to be done as often. - // In the persistent case, invalidating has a different effect, since the classlist must be reloaded from db. - if ClassTypeInfo.Persistent and OwningList.BoldSystem.BoldPersistent then - LocatorList.Remove(BoldObject.BoldObjectLocator) - else - Owninglist.Invalidate; + inc(fLoadedObjectCount); + if Owninglist.BoldPersistenceState <> bvpsInvalid then + begin +// Assert(not LocatorList.Includes(BoldObject.BoldObjectLocator), 'Locator already in list on beObjectCreated.'); + AddLocator(BoldObject.BoldObjectLocator) + end; + Owninglist.Invalidate; end; - beObjectFetched: OwningList.SendEvent(beObjectFetched); - else - raise EBoldInternal.CreateFmt('%s.ReceiveClassEvent: Unknown event', [ClassName]); + beObjectDeleted: + begin + if Owninglist.BoldPersistenceState <> bvpsInvalid then + begin + if ClassTypeInfo.Persistent and BoldSystem.BoldPersistent then + LocatorList.Remove(BoldObject.BoldObjectLocator); + end; + Dec(fLoadedObjectCount); + Owninglist.Invalidate; + OwningList.SendExtendedEvent(Event, [BoldObject.BoldObjectLocator]); end; - end - else - if Event = beObjectFetched then + beObjectFetched: begin - OwningList.SendEvent(beObjectFetched); + inc(fLoadedObjectCount); + if Owninglist.IsCurrent then + begin +// Assert(not LocatorList.Includes(BoldObject.BoldObjectLocator), 'Locator already in list on beObjectFetched.'); + AddLocator(BoldObject.BoldObjectLocator); + OwningList.SendExtendedEvent(beValueInvalid, [BoldObject.BoldObjectLocator]); + end + else + if (Owninglist.BoldPersistenceState = bvpsTransient) and (fLoadedObjectCount = count) then + begin +// Assert(LocatorList.Includes(BoldObject.BoldObjectLocator), 'Locator not already in list on beObjectFetched.'); + MarkListCurrent; + OwningList.SendExtendedEvent(beValueInvalid, [BoldObject.BoldObjectLocator]); + end + else + Owninglist.Invalidate; end; - - + beObjectUnloaded: + begin + if not BoldObject.BoldObjectIsDeleted then + begin + Dec(fLoadedObjectCount); + if Owninglist.BoldPersistenceState = bvpsCurrent then + begin + SetPersistenceState(bvpsTransient); + OwningList.SendEvent(beValueInvalid); + end + else + Owninglist.Invalidate; + end; + end; + end; case event of beObjectCreated: OwningList.SendExtendedEvent(beItemAdded, [BoldObject.BoldObjectLocator]); beObjectDeleted: OwningList.SendExtendedEvent(beItemDeleted, [BoldObject.BoldObjectLocator]); + beObjectFetched: OwningList.SendExtendedEvent(beObjectFetched, [BoldObject.BoldObjectLocator]); + beObjectUnloaded: OwningList.SendExtendedEvent(beObjectUnloaded, [BoldObject.BoldObjectLocator]) + else + raise EBoldInternal.CreateFmt('%s.ReceiveClassEvent: Unknown event: %d', [ClassName, Event]); end; end; procedure TBoldClassListController.RemoveByIndex(index: Integer); begin + Assert(not LocatorList[index].EnsuredBoldObject.BoldObjectIsDeleted); LocatorList[Index].EnsuredBoldObject.Delete; end; procedure TBoldClassListController.SubscribeToObjectDeleted; begin - // remove behaviour from parent +end; + +procedure TBoldClassListController.CheckStillCurrent; +begin + if OwningList.isCurrent and (fLoadedObjectCount <> Count) then + SetPersistenceState(bvpsTransient); end; function TBoldClassListController.HandlesAtTime: Boolean; @@ -525,6 +693,22 @@ function TBoldClassListController.HandlesAtTime: Boolean; result := true; end; +function TBoldClassListController.HasLoadedSuperClass: boolean; +begin + result := ClosestLoadedClassList <> nil; +end; + +function TBoldClassListController.IsCurrentOrSuperClassIsCurrent: boolean; +begin + result := HasLoadedSuperClass or (OwningObjectList.BoldPersistenceState = bvpsCurrent); +end; + +procedure TBoldClassListController.AddLocator(Locator: TBoldObjectLocator); +begin + LocatorList.Add(Locator); + CheckStillCurrent; +end; + function TBoldClassListController.AtTime( Time: TBoldTimeStampType): TBoldMember; var @@ -540,8 +724,8 @@ function TBoldClassListController.AtTime( result := TBoldObjectList(AtTimeList[i]); if not assigned(result) then begin - result := TBoldObjectList.InternalCreateClassList(BoldSystem, OwningList.BoldType as TBoldListTypeInfo); - TBoldClassListController(GetControllerForMember(result)).fTimestamp := Time; + result := TBoldObjectList.InternalCreateClassList(BoldSystem, OwningList.BoldType as TBoldListTypeInfo); + TBoldClassListController(GetControllerForMember(result)).fTimestamp := Time; AtTimeList.Add(result); end; end; @@ -569,98 +753,77 @@ constructor TBoldClassListController.Create(OwningList: TBoldObjectList); begin inherited Create(OwningList); fTimestamp := BOLDMAXTIMESTAMP; + fClassTypeInfo := TBoldClassTypeInfo(TBoldListTypeInfo(OwningList.Boldtype).ListElementTypeInfo); + if Assigned(ClassTypeInfo.SuperClassTypeInfo) then + begin + fSuperClassList := BoldSystem.Classes[ClassTypeInfo.SuperClassTypeInfo.TopSortedIndex]; + fSuperClassController := TBoldClassListController(GetControllerForMember(fSuperClassList)); + end; + OwningList.DuplicateMode := bldmError; end; -function TBoldClassListController.ProxyClass: TBoldMember_ProxyClass; +function TBoldClassListController.GetProxy(Member: TBoldMember; Mode: TBoldDomainElementProxyMode): TBoldMember_Proxy; begin - Result := TBoldClassList_Proxy; + Result := TBoldClassList_Proxy.Create(Member, Mode); end; function TBoldClassListController.GetIdList(Index: Integer): TBoldObjectID; -var - aLocator: TBoldObjectLocator; begin - aLocator := LocatorList[Index]; - result := aLocator.BoldObjectId + result := LocatorList[Index].BoldObjectId; end; -{ -procedure TBoldClassListController.AddTransientFromSystem; -var - Traverser: TBoldLocatorListTraverser; - Locator: TBoldObjectLocator; -begin - Traverser := OwningList.BoldSystem.Locators.CreateTraverser; - while not Traverser.EndOfList do - begin - Locator := Traverser.Locator; - if assigned(Locator.BoldObject) and not Locator.BoldObject.BoldPersistent and Locator.BoldObject.BoldClassTypeInfo.BoldIsA(ClassTypeinfo) then - LocatorList.Add(Locator); - Traverser.Next; - end; - Traverser.Free; -end; -} - procedure TBoldClassListController.SetFromIdList( List: TBoldObjectIdList; Mode: TBoldDomainElementProxyMode); - procedure InternalAddLocator(NewLocator: TBoldObjectLocator); +var + BoldSystem: TBoldSystem; + + procedure InternalAddId(ID: TBoldObjectId); + var + Locator: TBoldObjectLocator; begin - Assert(Assigned(NewLocator)); - if not IncludesLocator(NewLocator) then + Locator := BoldSystem.EnsuredLocatorByID[ID]; + if not IncludesLocator(Locator) then begin PreChange; - LocatorList.Add(NewLocator); - Changed(beItemAdded, [NewLocator]); + LocatorList.Add(Locator); + Changed(beItemAdded, [Locator]); end; end; - procedure InternalAddId(ID: TBoldObjectId); - begin - InternalAddLocator(BoldSystem.EnsuredLocatorByID[ID]); - end; - +{$IFNDEF NoTransientInstancesOfPersistentClass} procedure AddTransientFromSystem(List:TBoldObjectIdList); var - Traverser: TBoldLocatorListTraverser; Locator: TBoldObjectLocator; begin - Traverser := OwningList.BoldSystem.Locators.CreateTraverser; - while not Traverser.EndOfList do - begin - Locator := Traverser.Locator; + if not BoldSystem.Locators.IsEmpty then + for Locator in BoldSystem.Locators do if assigned(Locator.BoldObject) and not Locator.BoldObject.BoldPersistent and Locator.BoldObject.BoldClassTypeInfo.BoldIsA(ClassTypeinfo) then List.Add(Locator.BoldObjectID); - Traverser.Next; - end; - Traverser.Free; end; +{$ENDIF} - var +var I: Integer; NewList: TBoldObjectIdlist; Locator: TBoldObjectLocator; TheObject: TBoldObject; - begin - + BoldSystem := self.BoldSystem; if assigned(List) then NewList := List.Clone else NewList := TBoldObjectidList.create; - + try if mode = bdepPMIn then begin - // remove objects that have been deleted in memory + if BoldSystem.BoldDirty then // Search for Deleted objects only if system is dirty. for I := NewList.Count - 1 downto 0 do begin Locator := BoldSystem.Locators.LocatorByID[NewList[i]]; if assigned(Locator) and assigned(Locator.BoldObject) and (Locator.BoldObject.BoldExistenceState = besDeleted) then NewList.RemoveByIndex(i); end; - - // Add New Objects for I := 0 to BoldSystem.DirtyObjects.Count - 1 do begin TheObject := TBoldObject(BoldSystem.DirtyObjects[I]); @@ -668,17 +831,28 @@ procedure TBoldClassListController.SetFromIdList( ((TheObject.BoldExistenceState = besExisting) and (TheObject.BoldPersistenceState = bvpsModified)) then NewList.add(TheObject.BoldObjectLocator.BoldObjectID) end; - +{$IFNDEF NoTransientInstancesOfPersistentClass} AddTransientFromSystem(NewList); +{$ENDIF} end; + for I := GetCount - 1 downto 0 do + if not NewList.IdInList[GetLocator(I).BoldObjectID] then + LocatorList.RemoveByIndex(I); + for I := 0 to NewList.Count - 1 do + InternalAddId(NewList[I]); + finally + NewList.Free; + end; +end; - // fix§up locator list with minimum impact - for I := GetCount - 1 downto 0 do - if not NewList.IdInList[GetLocator(I).BoldObjectID] then - LocatorList.RemoveByIndex(I); - for I := 0 to NewList.Count - 1 do - InternalAddId(NewList[I]); - NewList.Free; +procedure TBoldClassListController.SetPersistenceState( + APersistenceState: TBoldValuePersistenceState); +begin + with OwningList do + begin + BoldPersistenceState := APersistenceState; + SendEvent(beClassListStateChanged); + end; end; function TBoldClassListController.ProxyInterface(const IId: TGUID; Mode: TBoldDomainElementProxyMode; @@ -686,7 +860,7 @@ function TBoldClassListController.ProxyInterface(const IId: TGUID; Mode: TBoldDo begin if IsEqualGuid(IID, IBoldObjectIdListRef) then begin - result := ProxyClass.create(self.OwningList, Mode).GetInterface(IID, obj); + result := GetProxy(self.OwningList, Mode).GetInterface(IID, obj); if not result then raise EBoldInternal.CreateFmt('ProxyClass for %s did not implement IBoldObjectIdListRef', [ClassName]); end @@ -696,17 +870,17 @@ function TBoldClassListController.ProxyInterface(const IId: TGUID; Mode: TBoldDo { TBoldClassList_Proxy } -procedure TBoldClassList_Proxy.AssignContentValue(Source: IBoldValue); +function TBoldClassList_Proxy.GetClassListController: TBoldClassListController; begin - if Mode = bdepContents then - ClassListController.AssignContentValue(Source) - else - UnsupportedMode(Mode, 'AssignContentValue'); // do not localize + Result := TBoldClassListController(ProxedController); end; -function TBoldClassList_Proxy.GetClassListController: TBoldClassListController; +procedure TBoldClassList_Proxy.AssignContentValue(const Source: IBoldValue); begin - Result := TBoldClassListController(ProxedController); + if Mode = bdepContents then + ClassListController.AssignContentValue(Source) + else + UnsupportedMode(Mode, 'AssignContentValue'); end; function TBoldClassList_Proxy.GetCount: integer; @@ -721,25 +895,36 @@ function TBoldClassList_Proxy.GetIdList(Index: Integer): TBoldObjectID; procedure TBoldClassList_Proxy.SetFromIdList(IdLIst: TBoldObjectIdList); begin - if Mode = bdepPMIn then { TODO : Move in implementation to proxy } + if Mode = bdepPMIn then ClassListController.SetFromIdList(IdLIst, Mode) else - UnsupportedMode(Mode, 'SetFromIdList'); // do not localize + UnsupportedMode(Mode, 'SetFromIdList'); +end; + +procedure TBoldClassList_Proxy.SetList(IdList: TBoldObjectIdList); +var + i: integer; +begin + IdList.Clear; + for I := 0 to ClassListController.Count - 1 do + IdList.Add(ClassListController.GetIdList(i)); end; { TBoldObjectList_Proxy } -procedure TBoldObjectList_Proxy.AssignContentValue(Source: IBoldValue); +function TBoldObjectList_Proxy.GetObjectListController: TBoldObjectListController; +begin + Result := TBoldObjectListController(ProxedController); +end; + +procedure TBoldObjectList_Proxy.AssignContentValue(const Source: IBoldValue); begin if Mode = bdepContents then ObjectListController.AssignContentValue(Source) else - UnsupportedMode(Mode, 'AssignContentValue'); // do not localize + UnsupportedMode(Mode, 'AssignContentValue'); end; -function TBoldObjectList_Proxy.GetObjectListController: TBoldObjectListController; -begin - Result := TBoldObjectListController(ProxedController); -end; +initialization end. diff --git a/Source/ObjectSpace/BORepresentation/BoldObjectSpaceLists.pas b/Source/ObjectSpace/BORepresentation/BoldObjectSpaceLists.pas index 3e0fc38..492a3d8 100644 --- a/Source/ObjectSpace/BORepresentation/BoldObjectSpaceLists.pas +++ b/Source/ObjectSpace/BORepresentation/BoldObjectSpaceLists.pas @@ -1,14 +1,18 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldObjectSpaceLists; interface uses Classes, - BoldSubscription, + BoldSubscription, BoldSystem, BoldSystemRT, BoldIndex, - BoldIndexableList; + BoldIndexableList, + BoldHashIndexes; type TBoldObjectAttributeIndexList = class; @@ -18,24 +22,26 @@ TBoldMembersHashIndex = class; {---TBoldObjectAttributeIndexList---} TBoldObjectAttributeIndexList = class(TBoldIndexableList) private - function GetHasMembersIndex: Boolean; - function GetMembersIndex: TBoldMembersHashIndex; - function CreateMembersIndex(ObjectList: TBoldObjectList; MemberList: TBoldMemberRTInfoList): TBoldMembersHashIndex; - procedure NotifyMemberIndexBad; virtual; + class var IX_BoldQualifiers: integer; + function GetHasMembersIndex: Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetMembersIndex: TBoldMembersHashIndex; {$IFDEF BOLD_INLINE} inline; {$ENDIF} protected + procedure NotifyMemberIndexBad; virtual; procedure EnsureLazyCreateIndexes; virtual; + function CreateMembersIndex(ObjectList: TBoldObjectList; MemberList: TBoldMemberRTInfoList): TBoldMembersHashIndex; virtual; public procedure InitMembersIndex(ObjectList: TBoldObjectList; MemberList: TBoldMemberRTInfoList); property HasMembersIndex: Boolean read GetHasMembersIndex; - function GetLocatorByAttributesAndSubscribe(MemberList: TBoldMemberList; Subscriber: TBoldSubscriber): TBoldObjectLocator; + function GetLocatorByAttributesAndSubscribe(MemberList: TBoldMemberList; Subscriber: TBoldSubscriber): TBoldObjectLocator; {$IFDEF BOLD_INLINE} inline; {$ENDIF} end; {---TBoldObjectLocatorList---} TBoldObjectLocatorList = class(TBoldObjectAttributeIndexList) private - function GetLocatorIndex: TBoldLocatorHashIndex; - function GetLocators(index: Integer): TBoldObjectLocator; - procedure SetLocators(index: Integer; Value: TBoldObjectLocator); + class var IX_BoldObjectLocator: integer; + function GetLocatorIndex: TBoldLocatorHashIndex; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetLocators(index: Integer): TBoldObjectLocator; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure SetLocators(index: Integer; Value: TBoldObjectLocator); {$IFDEF BOLD_INLINE} inline; {$ENDIF} function GetLocatorInList(Locator: TBoldObjectLocator): Boolean; property LocatorIndex: TBoldLocatorHashIndex read GetLocatorIndex; protected @@ -43,9 +49,9 @@ TBoldObjectLocatorList = class(TBoldObjectAttributeIndexList) public constructor Create; constructor CreateFromObjectList(BoldObjectList: TBoldObjectList); - procedure Add(NewLocator: TBoldObjectLocator); + procedure Add(NewLocator: TBoldObjectLocator); {$IFDEF BOLD_INLINE} inline; {$ENDIF} function Clone: TBoldObjectLocatorList; - procedure Ensure(NewLocator: TBoldObjectLocator); + procedure Ensure(NewLocator: TBoldObjectLocator); {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure FillObjectList(BoldObjectList: TBoldObjectList); procedure MergeObjectList(BoldObjectList: TBoldObjectList); property Locators[index: Integer]: TBoldObjectLocator read GetLocators write SetLocators; default; @@ -59,15 +65,16 @@ TBoldMembersHashIndex = class(TBoldHashIndex) fMemberSubscriber: TBoldPassThroughSubscriber; fOwner: TBoldObjectAttributeIndexList; fObjectList: TBoldObjectList; - procedure _receiveMemberChanged(Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent); + fStringCompareMode: TBoldStringCompareMode; protected - constructor Create(Owner: TBoldObjectAttributeIndexList; ObjectList: TBoldObjectList; Members: TBoldMemberRTInfoList); function HashItem(Item: TObject): Cardinal; override; function Match(const Key; Item:TObject):Boolean; override; function Hash(const Key): Cardinal; override; - function LocatorFromItem(Item: TObject): TBoldObjectLocator; - function ObjectFromItem(Item: TObject): TBoldObject; + function LocatorFromItem(Item: TObject): TBoldObjectLocator; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function ObjectFromItem(Item: TObject): TBoldObject; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure _receiveMemberChanged(Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent); virtual; public + constructor Create(Owner: TBoldObjectAttributeIndexList; ObjectList: TBoldObjectList; Members: TBoldMemberRTInfoList; AStringCompareMode: TBoldStringCompareMode = bscCaseDependent); destructor Destroy; override; procedure Clear(DestroyObjects: Boolean = false); override; procedure Add(Item: TObject); override; @@ -79,11 +86,7 @@ implementation uses SysUtils, BoldId, - BoldHashIndexes; - -var - IX_BoldObjectLocator: integer = -1; - IX_BoldQualifiers: integer = -1; + BoldDefs; type {---TBoldMembersKey---} @@ -92,11 +95,28 @@ TBoldMembersKey = class FAttributeList: TBoldMemberList; FHash: Cardinal; public - constructor Create(Attributes: TBoldMemberList); + constructor Create(Attributes: TBoldMemberList; StringCompareMode: TBoldStringCompareMode); property AttributeList: TBoldMemberList read FAttributeList; function Hash: Cardinal; end; +function TBoldMembersHashIndex.LocatorFromItem(Item: TObject): TBoldObjectLocator; +begin + Assert(not Assigned(Item) or (Item is TBoldObjectLocator)); + result := TBoldObjectLocator(Item); +end; + +function TBoldMembersHashIndex.ObjectFromItem(Item: TObject): TBoldObject; +var + temp: TBoldObjectLocator; +begin + temp := LocatorFromItem(Item); + if assigned(temp) then + result := temp.EnsuredBoldObject + else + result := nil; +end; + procedure TBoldMembersHashIndex.Add(Item: TObject); var i: integer; @@ -114,12 +134,122 @@ procedure TBoldMembersHashIndex.Add(Item: TObject); end; end; + {---TBoldMembersHashIndex---} +constructor TBoldMembersHashIndex.Create(Owner: TBoldObjectAttributeIndexList; ObjectList: TBoldObjectList; Members: TBoldMemberRTInfoList; AStringCompareMode: TBoldStringCompareMode); +var + i: Integer; +begin + inherited Create; + FStringCompareMode := AStringCompareMode; + FMemberIndexList := TList.Create; + FMemberIndexList.Capacity := Members.Count; + for i := 0 to Members.Count - 1 do + FMemberIndexList.Add(TBoldMemberId.create(Members[i].index)); + fMemberSubscriber := TBoldPassThroughSubscriber.Create(_receiveMemberChanged); + fOwner := Owner; + fObjectList := ObjectList; +end; + +destructor TBoldMembersHashIndex.Destroy; +var + i: Integer; +begin + for i := FMemberIndexList.Count-1 downto 0 do { counting down avoids adjusting other pointers in list } + TObject(FMemberIndexList[i]).Free; + FreeAndNil(FMemberIndexList); + FreeAndNil(fMemberSubscriber); + inherited; +end; + +function TBoldMembersHashIndex.HashItem(Item: TObject): Cardinal; +var + i: Integer; + concatval: String; + index: Integer; + member: TBoldMember; + BoldObject: TBoldObject; +begin + concatval := ''; + BoldObject := ObjectFromItem(Item); + for i := 0 to FMemberIndexList.Count - 1 do + begin + Assert(TObject(FMemberIndexList[i]) is TBoldMemberId); + index := TBoldMemberId(FMemberIndexList[i]).MemberIndex; + member := BoldObject.BoldMembers[index]; + concatval := concatval + member.AsString; + end; + result := TBoldStringKey.HashString(concatval, fStringCompareMode); +end; + +function TBoldMembersHashIndex.Match(const Key; Item:TObject):Boolean; +var + MembersKey: TBoldMembersKey; + Member: TBoldMember; + BoldObject: TBoldObject; + i: Integer; +const + cStringType = 'String'; // to avoid using BoldAttributes unit +begin + MembersKey := TBoldMembersKey(Key); + BoldObject := ObjectFromItem(Item); + result := FMemberIndexList.Count = MembersKey.AttributeList.Count; + i := 0; + while result and (i < FMemberIndexList.Count) do + begin + Assert(TObject(FMemberIndexList[i]) is TBoldMemberId); + Member := BoldObject.BoldMembers[TBoldMemberId(FMemberIndexList[i]).MemberIndex]; + if (fStringCompareMode <> bscCaseDependent) and (Member.BoldType.AsString = cStringType) then + result := MembersKey.AttributeList[i].IsEqualAs(ctCaseInsensitive, Member) + else + result := MembersKey.AttributeList[i].IsEqual(Member); + inc(i); + end; +end; + +function TBoldMembersHashIndex.GetLocatorByAttributesAndSubscribe(MemberList: TBoldMemberList; Subscriber: TBoldSubscriber): TBoldObjectLocator; +var + Key: TBoldMembersKey; + i: integer; +begin + Key := TBoldMembersKey.Create(MemberList, fStringCompareMode); + try + result := LocatorFromItem(Find(Key)); + finally + Key.Free; + end; + + if assigned(subscriber) then + begin + if assigned(result) then + begin + for i := 0 to FMemberIndexList.Count - 1 do + result.EnsuredBoldObject.BoldMembers[TBoldMemberId(FMemberIndexList[i]).MemberIndex].DefaultSubscribe(subscriber, breReSubscribe); + end + else if assigned(fObjectList) then + fObjectList.AddSmallSubscription(Subscriber, [beQualifierChanged], breReSubscribe); + end; +end; + procedure TBoldMembersHashIndex._receiveMemberChanged(Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent); +var + Locator: TBoldObjectLocator; begin + if OriginalEvent = beValueChanged then + begin + Locator := (Originator as TBoldMember).OwningObject.BoldObjectLocator; + if not IsCorrectlyIndexed(Locator) then + begin + AutoResize := false; + RemoveChanged(Locator); + Add(locator); + AutoResize := true; + end; + end; if assigned(fObjectList) then fObjectList.SendEvent(beQualifierChanged); - fOwner.NotifyMemberIndexBad; // this will tell the owning locatorlist to destroy us. + if OriginalEvent <> beValueChanged then + fOwner.NotifyMemberIndexBad; end; procedure TBoldMembersHashIndex.Clear(DestroyObjects: Boolean = false); @@ -159,9 +289,12 @@ function TBoldObjectAttributeIndexList.GetHasMembersIndex: Boolean; procedure TBoldObjectAttributeIndexList.EnsureLazyCreateIndexes; begin - // nothing; end; +function TBoldObjectAttributeIndexList.GetMembersIndex: TBoldMembersHashIndex; +begin + result := TBoldMembersHashIndex(indexes[IX_BoldQualifiers]); +end; procedure TBoldObjectAttributeIndexList.NotifyMemberIndexBad; var @@ -174,13 +307,6 @@ procedure TBoldObjectAttributeIndexList.NotifyMemberIndexBad; end; end; -function TBoldObjectAttributeIndexList.GetMembersIndex: TBoldMembersHashIndex; -begin - result := TBoldMembersHashIndex(indexes[IX_BoldQualifiers]); -end; - - - {---TBoldObjectLocatorList---} constructor TBoldObjectLocatorList.Create; begin @@ -189,20 +315,31 @@ constructor TBoldObjectLocatorList.Create; OwnsEntries := False; end; +function TBoldObjectLocatorList.GetLocators(index: Integer): TBoldObjectLocator; +begin + Result := TBoldObjectLocator(Items[index]); +end; + +procedure TBoldObjectLocatorList.SetLocators(index: Integer; Value: TBoldObjectLocator); +begin + Items[index] := Value; +end; + +procedure TBoldObjectLocatorList.Add(NewLocator: TBoldObjectLocator); +begin + inherited Add(NewLocator); +end; + constructor TBoldObjectLocatorList.CreateFromObjectList(BoldObjectList: TBoldObjectList); var I: Integer; begin Create; + Capacity := BoldObjectList.Count; for I := 0 to BoldObjectList.Count - 1 do Add(BoldObjectList.Locators[I]); end; -function TBoldObjectLocatorList.GetLocators(index: Integer): TBoldObjectLocator; -begin - Result := TBoldObjectLocator(Items[index]); -end; - function TBoldObjectLocatorList.GetLocatorIndex: TBoldLocatorHashIndex; begin if UnorderedIndexCount = 0 then @@ -210,25 +347,28 @@ function TBoldObjectLocatorList.GetLocatorIndex: TBoldLocatorHashIndex; result := TBoldLocatorHashIndex(Indexes[IX_BoldObjectLocator]); end; - function TBoldObjectLocatorList.Clone: TBoldObjectLocatorList; var I: Integer; begin Result := TBoldObjectLocatorList.Create; + Result.Capacity := Capacity; for I := 0 to Count - 1 do Result.Add(Locators[I]); end; function TBoldObjectLocatorList.GetLocatorInList(Locator: TBoldObjectLocator): Boolean; begin - result := assigned(Locator); - if result then + Result := Assigned(Locator); + if Result then begin - if Count > 10 then - Result := Assigned(LocatorIndex.FindLocatorByLocator(Locator)) + case Count of + 0: result := false; + 1: result := Locators[0] = Locator; + 2..10: Result := IndexOf(Locator) <> -1; else - result := IndexOf(Locator) <> -1; + Result := Assigned(LocatorIndex.FindLocatorByLocator(Locator)); + end; end; end; @@ -250,11 +390,6 @@ procedure TBoldObjectLocatorList.FillObjectList(BoldObjectList: TBoldObjectList) BoldObjectList.Add(Locators[I].BoldObject); end; -procedure TBoldObjectLocatorList.Add(NewLocator: TBoldObjectLocator); -begin - inherited Add(NewLocator); -end; - procedure TBoldObjectLocatorList.EnsureLazyCreateIndexes; begin inherited; @@ -267,121 +402,9 @@ procedure TBoldObjectLocatorList.Ensure(NewLocator: TBoldObjectLocator); Add(NewLocator); end; - - -procedure TBoldObjectLocatorList.SetLocators(index: Integer; Value: TBoldObjectLocator); -begin - Items[index] := Value; -end; - - {---TBoldMembersHashIndex---} -constructor TBoldMembersHashIndex.Create(Owner: TBoldObjectAttributeIndexList; ObjectList: TBoldObjectList; Members: TBoldMemberRTInfoList); -var - i: Integer; -begin - inherited Create; - FMemberIndexList := TList.Create; - FMemberIndexList.Capacity := Members.Count; - for i := 0 to Members.Count - 1 do - FMemberIndexList.Add(TBoldMemberId.create(Members[i].index)); - fMemberSubscriber := TBoldPassThroughSubscriber.Create(_receiveMemberChanged); - fOwner := Owner; - fObjectList := ObjectList; -end; - -destructor TBoldMembersHashIndex.Destroy; -var - i: Integer; -begin - for i := 0 to FMemberIndexList.Count - 1 do - TObject(FMemberIndexList[i]).Free; - FreeAndNil(FMemberIndexList); - FreeAndNil(fMemberSubscriber); - inherited; -end; - -function TBoldMembersHashIndex.HashItem(Item: TObject): Cardinal; -var - i: Integer; - concatval: String; - index: Integer; - member: TBoldMember; - BoldObject: TBoldObject; -begin - concatval := ''; - BoldObject := ObjectFromItem(Item); - for i := 0 to FMemberIndexList.Count - 1 do - begin - Assert(TObject(FMemberIndexList[i]) is TBoldMemberId); - index := TBoldMemberId(FMemberIndexList[i]).MemberIndex; - member := BoldObject.BoldMembers[index]; - concatval := concatval + member.AsString; - end; - result := TBoldStringKey.HashString(concatval, bscCaseDependent); -end; - -function TBoldMembersHashIndex.Match(const Key; Item:TObject):Boolean; -var - MembersKey: TBoldMembersKey; - BoldObject: TBoldObject; - i: Integer; -begin - MembersKey := TBoldMembersKey(Key); - BoldObject := ObjectFromItem(Item); - result := FMemberIndexList.Count = MembersKey.AttributeList.Count; - i := 0; - while result and (i < FMemberIndexList.Count) do - begin - Assert(TObject(FMemberIndexList[i]) is TBoldMemberId); - result := MembersKey.AttributeList[i].IsEqual(BoldObject.BoldMembers[TBoldMemberId(FMemberIndexList[i]).MemberIndex]); - inc(i); - end; -end; - -function TBoldMembersHashIndex.ObjectFromItem(Item: TObject): TBoldObject; -var - temp: TBoldObjectLocator; -begin - temp := LocatorFromItem(Item); - if assigned(temp) then - result := temp.EnsuredBoldObject - else - result := nil; -end; - -function TBoldMembersHashIndex.LocatorFromItem(Item: TObject): TBoldObjectLocator; -begin - Assert(not Assigned(Item) or (Item is TBoldObjectLocator)); - result := TBoldObjectLocator(Item); -end; - -function TBoldMembersHashIndex.GetLocatorByAttributesAndSubscribe(MemberList: TBoldMemberList; Subscriber: TBoldSubscriber): TBoldObjectLocator; -var - Key: TBoldMembersKey; - i: integer; -begin - Key := TBoldMembersKey.Create(MemberList); - try - result := LocatorFromItem(Find(Key)); - finally - Key.Free; - end; - - if assigned(subscriber) then - begin - if assigned(result) then - begin - for i := 0 to FMemberIndexList.Count - 1 do - result.EnsuredBoldObject.BoldMembers[TBoldMemberId(FMemberIndexList[i]).MemberIndex].DefaultSubscribe(subscriber, breReSubscribe); - end - else if assigned(fObjectList) then - fObjectList.AddSmallSubscription(Subscriber, [beQualifierChanged], breReSubscribe); - end; -end; - {---TBoldMembersKey---} -constructor TBoldMembersKey.Create(Attributes: TBoldMemberList); +constructor TBoldMembersKey.Create(Attributes: TBoldMemberList; StringCompareMode: TBoldStringCompareMode); var i: Integer; concatval: String; @@ -389,7 +412,7 @@ constructor TBoldMembersKey.Create(Attributes: TBoldMemberList); FAttributeList := Attributes; for i := 0 to FAttributeList.Count - 1 do concatval := concatval + FAttributeList[i].AsString; - FHash := TBoldStringKey.HashString(concatval, bscCaseDependent); + FHash := TBoldStringKey.HashString(concatval, StringCompareMode); end; function TBoldMembersKey.Hash: Cardinal; @@ -402,4 +425,9 @@ function TBoldMembersHashIndex.Hash(const Key): Cardinal; Result := TBoldMembersKey(Key).Hash; end; +initialization + TBoldObjectAttributeIndexList.IX_BoldQualifiers := -1; + TBoldObjectLocatorList.IX_BoldObjectLocator := -1 + end. + diff --git a/Source/ObjectSpace/BORepresentation/BoldOptimisticLockingSupport.pas b/Source/ObjectSpace/BORepresentation/BoldOptimisticLockingSupport.pas index adf1585..c5e7574 100644 --- a/Source/ObjectSpace/BORepresentation/BoldOptimisticLockingSupport.pas +++ b/Source/ObjectSpace/BORepresentation/BoldOptimisticLockingSupport.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldOptimisticLockingSupport; interface @@ -19,7 +22,7 @@ TBoldOptimisticLockHandler = class(TBoldAbstractOptimisticLockHandler) procedure GetRegionsForRemoteMember(OwningId: TBoldObjectId; Regions: TBoldRegionLookup; OwningRoleRTInfo: TBoldRoleRTInfo); procedure GetRegionsForDirtyOtherEnds(ObjectList: TBoldObjectList; Regions: TBoldRegionLookup); - procedure CopyValue(TargetVS: IBoldValueSpace; var TargetObjectContents: IBoldObjectContents; TargetObjectId: TBoldObjectId; MemberIndex: integer; Value: IBoldValue; StreamName: String); + procedure CopyValue(const TargetVS: IBoldValueSpace; var TargetObjectContents: IBoldObjectContents; TargetObjectId: TBoldObjectId; MemberIndex: integer; const Value: IBoldValue; const StreamName: String); procedure RetrieveOptimisticLockingvalues(ObjectList: TBoldObjectlist; PreCondition: TBoldOptimisticLockingPrecondition); procedure GetRegionsForElement(Element: TBoldDomainElement; Regions: TBoldRegionLookup); procedure GetRegionsForDirtyMembersInList(ObjectList: TBoldObjectList; Regions: TBoldRegionLookup); @@ -45,8 +48,7 @@ implementation BoldIndexableList, BoldElements, BoldTaggedValueSupport, - BoldGuard, - BoldCoreConsts; + BoldGuard; { TBoldOptimisticLockHandler } @@ -74,10 +76,10 @@ procedure TBoldOptimisticLockHandler.AddOptimisticRegionLocks(ObjectList: TBoldO GetLockingValuesForRegions(Regions, PreCondition); end; -procedure TBoldOptimisticLockHandler.CopyValue(TargetVS: IBoldValueSpace; +procedure TBoldOptimisticLockHandler.CopyValue(const TargetVS: IBoldValueSpace; var TargetObjectContents: IBoldObjectContents; - TargetObjectId: TBoldObjectId; MemberIndex: integer; Value: IBoldValue; - StreamName: String); + TargetObjectId: TBoldObjectId; MemberIndex: integer; const Value: IBoldValue; + const StreamName: String); var MemberId: TBoldMemberId; NewValue: IBoldValue; @@ -97,33 +99,26 @@ procedure TBoldOptimisticLockHandler.CopyValue(TargetVS: IBoldValueSpace; procedure TBoldOptimisticLockHandler.GetRegionsForDirtyOtherEnds(ObjectList: TBoldObjectList; Regions: TBoldRegionLookup); var - ObjIx, MemberIx: integer; + ObjIx, i: integer; Obj: TBoldObject; ObjRef: TBoldObjectReference; OldRemoteId: TBoldObjectId; - Member: TBoldMember; begin - // must grab objects with "dirty" multilinks refered to by singlelinks in the original objectlist, if they are managed by atleast one region. for ObjIx := 0 to ObjectList.Count-1 do begin Obj := ObjectList[ObjIx]; - for MemberIx := 0 to Obj.BoldMemberCount-1 do + with Obj.BoldClassTypeInfo.AllRoles do + for i := 0 to Count-1 do + if Items[i].IsSingleRole then begin - if Obj.BoldMemberAssigned[MemberIx] then + ObjRef := Obj.BoldMemberIfAssigned[Items[i].index] as TBoldObjectReference; + if Assigned(ObjRef) and ObjRef.BoldDirty then begin - Member := Obj.BoldMembers[MemberIx]; - if member.BoldMemberRTInfo.IsSingleRole then - begin - if Member.BoldDirty and (Member is TBoldObjectReference) then - begin - ObjRef := Member as TBoldObjectReference; - OldRemoteId := GetRemotedfromIdRefValue(Objref.OldValue); - if assigned(OldRemoteId) then - GetRegionsForRemoteMember(OldRemoteId, Regions, ObjRef.BoldRoleRTInfo); - if assigned(ObjRef.Locator) then - GetRegionsForRemoteMember(ObjRef.Locator.BoldobjectId, Regions, ObjRef.BoldRoleRTInfo); - end; - end; + OldRemoteId := GetRemotedfromIdRefValue(Objref.OldValue); + if assigned(OldRemoteId) then + GetRegionsForRemoteMember(OldRemoteId, Regions, ObjRef.BoldRoleRTInfo); + if assigned(ObjRef.Locator) then + GetRegionsForRemoteMember(ObjRef.Locator.BoldobjectId, Regions, ObjRef.BoldRoleRTInfo); end; end; end; @@ -182,10 +177,9 @@ procedure TBoldOptimisticLockHandler.GetLockingValuesForRegions(Regions: TBoldRe Traverser: TBoldIndexableListTraverser; begin Traverser := Regions.CreateTraverser; - while not Traverser.EndOfList do + while Traverser.MoveNext do begin GetLockingValuesForRegion(Traverser.Item as TBoldRegion, PreCondition); - Traverser.Next; end; Traverser.Free; end; @@ -253,30 +247,23 @@ procedure TBoldOptimisticLockHandler.RetrieveOptimisticLockingvalues(ObjectList: BoldObject := ObjectList[ObjIx]; Mode := BoldObject.BoldClassTypeInfo.OptimisticLocking; NewObjectContents := nil; - // skip new objects, and objects with no locking at all if Mode in [bolmTimeStamp, bolmModifiedMembers, bolmAllMembers] then begin ObjectId := BoldObject.BoldObjectLocator.BoldObjectID; ObjectContents := OldValues.ObjectContentsByObjectId[ObjectId]; - - // Copy all members from the optimisticLockingArea, for MemberIx := 0 to BoldObject.BoldMemberCount - 1 do begin MemberRTInfo := BoldObject.BoldClassTypeInfo.AllMembers[MemberIx]; if MemberRTInfo.CanHaveOldValue then begin value := nil; - - // timestamp-mode should take only multiroles, othermodes should take all values in OptimisticLockingarea if assigned(ObjectContents) then begin if (Mode in [bolmModifiedMembers, bolmAllMembers]) or MemberRTInfo.EncouragesOptimisticLockingOnDeletedOnly then Value := ObjectContents.ValueByIndex[MemberIx] end; - // In Mode=Class and the member was not in optimistic locking area, steal it from the object (if it is loaded) - // always steal multiroles that are current - // on a deleted object, all multiroles are current + if not assigned(Value) and BoldObject.BoldMemberAssigned[MemberIx] and @@ -289,16 +276,12 @@ procedure TBoldOptimisticLockHandler.RetrieveOptimisticLockingvalues(ObjectList: Value := BoldObject.BoldMembers[MemberIx].AsIBoldValue[bdepContents]; end; end; - - // We should not optimistically check multilinks except for deleted objects if assigned(value) and MemberRTinfo.EncouragesOptimisticLockingOnDeletedOnly and not BoldObject.BoldObjectIsDeleted then value := nil; - // We should not check the values of innerlinks, they can not change, only the linkobject - // can appear/disappear. However, we must check that the object is not deleted, so we - // ensure the objectID in the valuespace + if assigned(value) and (MemberRTinfo.IsSingleRole) and ((MemberRTInfo as TBoldRoleRTInfo).RoleType = rtInnerLinkRole) then @@ -314,28 +297,23 @@ procedure TBoldOptimisticLockHandler.RetrieveOptimisticLockingvalues(ObjectList: begin RoleRTInfo := MemberRTInfo as TBoldRoleRTInfo; if (RoleRTInfo.RoleType = rtRole) and - BoldObject.BoldMemberAssigned[MemberIx] and BoldObject.BoldMembers[MemberIx].BoldDirty then + RoleRTInfo.RoleRTInfoOfOtherEnd.IsSingleRole and + not RoleRTInfo.RoleRTInfoOfOtherEnd.IsStoredInObject and + BoldObject.BoldMembers[MemberIx].BoldDirty then begin - // ensure existence of related objects unless they are new RelatedObject := (BoldObject.BoldMembers[MemberIx] as TBoldObjectReference).BoldObject; if assigned(relatedObject) and (not relatedObject.BoldObjectIsNew) then begin - RelatedObjectcontents := Precondition.ValueSpace.EnsuredObjectContentsByObjectId[RelatedObject.BoldObjectLocator.BoldObjectId]; - // for embedded singlelinks with nonembedded otherends we must optimistically lock the other end so no one - // else has decided to point to it. - if RoleRTInfo.RoleRTInfoOfOtherEnd.IsSingleRole and - not RoleRTInfo.RoleRTInfoOfOtherEnd.IsStoredInObject then + value := RelatedObject.BoldMembers[RoleRTInfo.IndexOfOtherEnd].OldValue; + if assigned(Value) then begin - value := RelatedObject.BoldMembers[RoleRTInfo.IndexOfOtherEnd].OldValue; - if assigned(Value) then - begin - CopyValue( - Precondition.ValueSpace, - RelatedObjectcontents, - RelatedObject.BoldObjectLocator.BoldObjectId, - RoleRTInfo.IndexOfOtherEnd, Value, - RelatedObject.BoldMembers[RoleRTInfo.IndexOfOtherEnd].AsIBoldValue[bdepContents].ContentName); - end; + RelatedObjectcontents := Precondition.ValueSpace.EnsuredObjectContentsByObjectId[RelatedObject.BoldObjectLocator.BoldObjectId]; + CopyValue( + Precondition.ValueSpace, + RelatedObjectcontents, + RelatedObject.BoldObjectLocator.BoldObjectId, + RoleRTInfo.IndexOfOtherEnd, Value, + RelatedObject.BoldMembers[RoleRTInfo.IndexOfOtherEnd].AsIBoldValue[bdepContents].ContentName); end; end; end; @@ -365,21 +343,20 @@ procedure TBoldOptimisticLockHandler.GetRegionsForRemoteMember(OwningId: TBoldOb if assigned(OwningId) then begin RemoteObj := System.EnsuredLocatorByID[OwningId].BoldObject; - // the remote object should really be there, but if it is not, there is really nothing we can do about it (except throw an exception ;-). if assigned(RemoteObj) then begin OtherEnd := RemoteObj.Boldmembers[OwningRoleRTInfo.IndexOfOtherEnd]; if OtherEnd.BoldPersistenceState = bvpsInvalid then begin if OwningRoleRTInfo.ForceOtherEnd then - raise EBold.CreateFmt(sRelatedRoleNotLoaded, [classname, OwningRoleRTInfo.AsString]); + raise EBold.CreateFmt('%s.GetRegionsForRemoteMember: The related role (of %s) is not loaded. Unable to ensure optimistic locking consistency', [classname, OwningRoleRTInfo.AsString]); end else GetRegionsForElement(OtherEnd, Regions); end else if OwningRoleRTInfo.ForceOtherEnd then - raise EBold.CreateFmt(sRelatedObjectNotLoaded, [classname, OwningRoleRTInfo.AsString]); + raise EBold.CreateFmt('%s.GetRegionsForRemoteMember: The related object (of %s) is not loaded. Unable to ensure optimistic locking consistency', [classname, OwningRoleRTInfo.AsString]); end; end; @@ -471,10 +448,9 @@ procedure TBoldOptimisticLockHandler.AddRegionsObjectsToEnclosure( Traverser: TBoldIndexableListTraverser; begin Traverser := Regions.CreateTraverser; - while not Traverser.EndOfList do + while Traverser.MoveNext do begin AddRegionObjectsToEnclosure(Traverser.Item as TBoldRegion, Enclosure, ValidateOnly, ListIsEnclosure); - Traverser.Next; end; Traverser.Free; end; @@ -484,4 +460,5 @@ function TBoldOptimisticLockHandler.GetRegionFactory: TBoldRegionFactory; result := System.RegionFactory as TBoldRegionFactory; end; +initialization end. diff --git a/Source/ObjectSpace/BORepresentation/BoldSystem.pas b/Source/ObjectSpace/BORepresentation/BoldSystem.pas index c2484ac..d2639cd 100644 --- a/Source/ObjectSpace/BORepresentation/BoldSystem.pas +++ b/Source/ObjectSpace/BORepresentation/BoldSystem.pas @@ -1,10 +1,14 @@ + +{ Global compiler directives } +{$include bold.inc} + unit BoldSystem; interface uses Classes, - Db, // Needed for GetAllInClassWithSQL... + Db, BoldBase, BoldStreams, BoldSystemRT, @@ -28,13 +32,17 @@ interface const {Query events} bqBaseSystem = bqMaxSubscription + 1; + {$IFNDEF BOLD_NO_QUERIES} {General} bqMayRead = bqBaseSystem + 0; + + bqMaySetValue = bqBaseSystem + 1; {TBoldAttribute} bqMaySetToNull = bqBaseSystem + 2; {TBoldList and TBoldObjectReference} bqMayClear = bqBaseSystem + 3; + {TBoldList} bqMayInsert = bqBaseSystem + 4; bqMayRemove = bqBaseSystem + 5; @@ -43,7 +51,7 @@ interface {Object creation/deletion (sent by system)} bqMayCreateObject = bqBaseSystem + 8; bqMayDeleteObject = bqBaseSystem + 9; - + {$ENDIF} bqMaxSystem = bqBaseSystem + 9; type @@ -68,24 +76,17 @@ TBoldAbstractPessimisticLockHandler = class; TBoldAbstractOptimisticLockHandler = class; TBoldAbstractUndoHandler = class; TBoldAbstractOldValueHandler = class; - TBoldAbstractTransActionHandler = class; TBoldAbstractSystemPersistenceHandler = class; TBoldAbstractRegionFactory = class; - - // Controllers TBoldAbstractController = class; TBoldListController = class; TBoldAbstractObjectListController = class; TBoldAbstractObjectReferenceController = class; - TBoldObjectReferenceController = class; { TODO : Move out } + TBoldObjectReferenceController = class; TBoldMemberFactory = class; - - // Proxies TBoldMember_Proxy = class; TBoldAttribute_Proxy = class; - - // Meta classes TBoldObjectClass = class of TBoldObject; TBoldAttributeClass = class of TBoldAttribute; TBoldMemberClass = class of TBoldMember; @@ -93,6 +94,7 @@ TBoldListClass = class of TBoldList; TBoldObjectListClass = class of TBoldObjectList; TBoldMember_ProxyClass = class of TBoldMember_Proxy; + TBoldMemberDeriver = class; { exceptions } EBoldOperationFailedForObjectList = class; @@ -129,7 +131,7 @@ TBoldAbstractPessimisticLockHandler = class(TBoldSystemExtension) { TBoldAbstractOptimisticLockHandler } TBoldAbstractOptimisticLockHandler = class(TBoldSystemExtension) private - function GetOldValues: IBoldValueSpace; + function GetOldValues: IBoldValueSpace; {$IFDEF BOLD_INLINE} inline; {$ENDIF} public procedure AddOptimisticLocks(ObjectList: TBoldObjectlist; PreCondition: TBoldOptimisticLockingPrecondition); virtual; abstract; procedure EnsureEnclosure(Obj: TBoldObject; Enclosure: TBoldObjectList; ValidateOnly: Boolean; var ListIsEnclosure: Boolean); virtual; abstract; @@ -139,11 +141,11 @@ TBoldAbstractOptimisticLockHandler = class(TBoldSystemExtension) { TBoldAbstractUndoHandler } TBoldAbstractUndoHandler = class(TBoldSystemExtension) protected - class function GetControllerForMember(Member: TBoldMember): TBoldAbstractController; + class function GetControllerForMember(Member: TBoldMember): TBoldAbstractController; {$IFDEF BOLD_INLINE}inline;{$ENDIF} procedure DeleteObject(BoldObject: TBoldObject); public - procedure HandleMember(ObjectContents: IBoldObjectContents; MemberIndex: integer; MemberValue: IBoldValue); virtual; abstract; - procedure HandleObject(Obj: IBoldObjectContents; RegardAsExisting: Boolean); virtual; abstract; + procedure HandleMember(const ObjectContents: IBoldObjectContents; MemberIndex: integer; const MemberValue: IBoldValue); virtual; abstract; + procedure HandleObject(const Obj: IBoldObjectContents; RegardAsExisting: Boolean); virtual; abstract; procedure PrepareUpdate(const ObjectList: TBoldObjectList); virtual; abstract; procedure ApplytranslationList(IdTranslationList: TBoldIdTranslationList); virtual; abstract; end; @@ -154,9 +156,9 @@ TBoldAbstractOldValueHandler = class(TBoldSystemExtension) function GetOldValues: IBoldValueSpace; virtual; abstract; function GetIsEmpty: Boolean; virtual; abstract; procedure PurgeEqualValues; virtual; abstract; - class function NewValueInValueSpace(BoldMember: TBoldMember; ValueSpace: IBoldValueSpace): IBoldValue; - class procedure CopyMemberToValueSpace(BoldMember: TBoldMember; ValueSpace: IBoldValueSpace); - class procedure CopyObjectToValueSpace(BoldObject: TBoldObject; ValueSpace: IBoldValueSpace); + class function NewValueInValueSpace(BoldMember: TBoldMember; const ValueSpace: IBoldValueSpace): IBoldValue; + class procedure CopyMemberToValueSpace(BoldMember: TBoldMember; const ValueSpace: IBoldValueSpace); + class procedure CopyObjectToValueSpace(BoldObject: TBoldObject; const ValueSpace: IBoldValueSpace); public procedure MemberValuePreChange(BoldMember: TBoldMember); virtual; abstract; procedure MemberPersistenceStatePreChange(BoldMember: TBoldMember; NewState: TBoldValuePersistenceState); virtual; abstract; @@ -166,42 +168,38 @@ TBoldAbstractOldValueHandler = class(TBoldSystemExtension) property IsEmpty: Boolean read GetIsEmpty; end; - { TBoldAbstractTransActionHandler } - TBoldAbstractTransActionHandler = class(TBoldAbstractOldValueHandler) - protected - function GetTransactionMode: TBoldSystemTransactionMode; virtual; abstract; - function GetTransactionState: TBoldTransactionState; virtual; abstract; - public - procedure StartTransaction(MinimalMode: TBoldSystemTransactionMode = stmNormal); virtual; abstract; - procedure CommitTransaction(MinimalMode: TBoldSystemTransactionMode = stmNormal); virtual; abstract; - procedure RollbackTransaction(MinimalMode: TBoldSystemTransactionMode = stmNormal); virtual; abstract; - property TransactionMode: TBoldSystemTransactionMode read GetTransactionMode; - property TransactionState: TBoldTransactionState read GetTransactionState; - end; { TBoldAbstractSystemPersistenceHandler } TBoldAbstractSystemPersistenceHandler = class(TBoldSystemExtension) private fOnPreUpdate: TNotifyEvent; + fOnPostUpdate: TNotifyEvent; protected function GetTimeStampOfLatestUpdate: TBoldTimeStampType; virtual; abstract; + function GetTimeOfLatestUpdate: TDateTime; virtual; abstract; public function EnsureEnclosure(ObjectList: TBoldObjectList; ValidateOnly: Boolean): Boolean; virtual; abstract; - procedure FetchLinksWithObjects(ObjectList: TBoldObjectList; const LinkName: string; FetchedObjects: TBoldObjectList); virtual; abstract; + procedure FetchLinksWithObjects(ObjectList: TBoldObjectList; const LinkName: string;FetchObjectsInLink: Boolean = True{; const FetchedObjectList: TBoldObjectList = nil});virtual; abstract; + procedure FetchMembersWithObjects(aBoldObjectList: TBoldObjectList; aBoldMemberIdList: TBoldMemberIdList); overload; virtual; abstract; + procedure FetchMembersWithObjects(aBoldObjectList: TBoldObjectList; AMemberCommaList: string); overload; virtual; abstract; procedure FetchObjectById(BoldObjectId: TBoldObjectId); virtual; abstract; procedure FetchMember(Member: TBoldMember); virtual; abstract; procedure FetchList(FetchList: TBoldObjectList); virtual; abstract; procedure FetchClass(ClassList: TBoldObjectList; Time: TBoldTimestampType); virtual; abstract; procedure GetAllWithCondition(aList: TBoldObjectList; Condition: TBoldCondition); virtual; abstract; procedure GetAllInClassWithSQL(aList: TBoldObjectList; AClass: TBoldObjectClass; WhereClause, OrderByClause: String; Params: TParams; JoinInheritedTables: Boolean; MaxAnswers: integer; Offset: integer);virtual; abstract; + procedure GetAllInClassWithRawSQL(aList: TBoldObjectList; AClass: TBoldObjectClass; SQL: String; Params: TParams; MaxAnswers: integer; Offset: integer);virtual; abstract; procedure UpdateDatabaseWithList(ObjectList: TBoldObjectList); virtual; abstract; function GetTimeForTimestamp(Timestamp: TBoldTimestampType): TDateTime; virtual; abstract; function GetTimestampForTime(ClockTime: TDateTime): TBoldTimestampType; virtual; abstract; property OnPreUpdate: TNotifyEvent read fOnPreUpdate write fOnPreUpdate; + property OnPostUpdate: TNotifyEvent read fOnPostUpdate write fOnPostUpdate; property TimeStampOfLatestUpdate: TBoldTimeStampType read GetTimeStampOfLatestUpdate; + property TimeOfLatestUpdate: TDateTime read GetTimeOfLatestUpdate; procedure EndFetchForAll(ObjectList: TBoldObjectList; MemberIdList: TBoldMemberIdList); procedure EndUpdateForAll(ObjectList: TBoldObjectList; Translationlist: TBoldIdTranslationlist); function StartUpdateForAll(ObjectList: TBoldObjectList): Boolean; + function CanEvaluateInPS(sOCL: string; aContext: TBoldElementTypeInfo = nil; const aVariableList: TBoldExternalVariableList = nil): Boolean; virtual; abstract; end; { TBoldAbstractRegionFactory } @@ -214,6 +212,10 @@ TBoldAbstractRegionFactory = class(TBoldMemoryManagedObject) procedure GetRegionsForElement(Element: TBoldDomainElement; ResultList: TList); virtual; abstract; end; +{$IFDEF ACCESSSTATISTICS} //// START PATCH ACCESSSTATISTICS //////////////////// + TArrayOfArrayOfIntegers = array of array of Integer; +{$ENDIF} //// END PATCH ACCESSSTATISTICS /////////////////////////////////////// + {---TBoldSystem---} TBoldSystem = class(TBoldDomainElement) private @@ -223,7 +225,8 @@ TBoldSystem = class(TBoldDomainElement) fDelayedDestructionCount: integer; fDelayedDestructionList: TList; fDirtyObjects: TList; {of TBoldObject} - fDirtyObjectsInvalid: Boolean; + FDiscardCount: Integer; + fFetchNesting: Integer; fEvaluator: TBoldEvaluator; fLocators: TBoldSystemLocatorList; FNewDirtyList: TBoldObjectList; @@ -242,78 +245,132 @@ TBoldSystem = class(TBoldDomainElement) fSystemPersistenceHandler: TBoldAbstractSystemPersistenceHandler; fUndoHandler: TBoldAbstractUndoHandler; fOnCreateApproximateObjectError: TBoldCreateApproximateObjectError; - procedure SetIsdefault(Value: boolean); + fDerivedMembers: TList; + fPersistenceControllerSubscriber: TBoldPassthroughSubscriber; + FDeletingObjectsDepth: Integer; +{$IFNDEF NoAutoSubscription} + fMembersReadDuringDerivation: TList; + fMembersReadDuringDerivationIndexArray: array of Integer; +{$ENDIF} + fSystemProxyCache: array[TBoldDomainElementProxyMode] of IBoldvalueSpace; + procedure SetIsDefault(Value: boolean); function GetIsDefault: boolean; - function RollBackAreaAssigned: boolean; + property RollBackAreaAssigned: Boolean index befRollbackAreaAssigned read GetElementFlag write SetElementFlag; procedure CopyMemberToRollBackBuffer(BoldMember: TBoldMember); procedure CopyObjectToRollBackBuffer(BoldObject: TBoldObject); procedure AddToTransaction(DomainElement: TBoldDomainElement); function CanCommit: Boolean; + procedure IncrementDeletingObjectsDepth; + procedure DecrementDeletingObjectsDepth; procedure DestroyObject(BoldObject: TBoldObject); procedure DirtyAsObjectList(ObjectList: TBoldObjectList); function FindClassByExpressionName(const ExpressionName: string): TBoldObjectList; function GetClassByExpressionName(const ExpressionName: string): TBoldObjectList; + function GetClassByObjectClass(AObjectClass: TBoldObjectClass): TBoldObjectList; function GetClassByIndex(index: Integer): TBoldObjectList; function GetDirtyObjects: TList; {of TBoldObject} - function GetEnsuredLocatorByID(ObjectID: TBoldObjectId): TBoldObjectLocator; - function GetTimeForTimestamp(Timestamp: TBoldTimestampType): TDateTime; - function GetTimestampForTime(ClockTime: TDateTime): TBoldTimestampType; + function GetDirtyObjectsAsBoldList(AClassType: TBoldObjectClass): TBoldObjectList; + function GetDirtyObjectsAsBoldListByClassExpressionName(const AClass: string): TBoldObjectList; + function GetAllDirtyObjectsAsBoldList: TBoldObjectList; + function GetEnsuredLocatorByID(ObjectID: TBoldObjectId): TBoldObjectLocator; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function GetTimeForTimestamp(Timestamp: TBoldTimestampType): TDateTime; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function GetTimestampForTime(ClockTime: TDateTime): TBoldTimestampType; {$IFDEF BOLD_INLINE}inline;{$ENDIF} procedure MarkObjectClean(BoldObject: TBoldObject); {called by TBoldObject} procedure MarkObjectDirty(BoldObject: TBoldObject); {called by TBoldObject} - procedure MarkObjectPossiblyCleaner(BoldObject: TBoldObject); {called by TBoldObject} - function GetAsIBoldvalueSpace(Mode: TBoldDomainElementProxyMode): IBoldvalueSpace; - procedure SetTransactionMode(const Value: TBoldSystemTransactionMode); + procedure MarkObjectPossiblyCleaner(BoldObject: TBoldObject); {$IFDEF BOLD_INLINE} inline; {$ENDIF} {called by TBoldObject} + function GetAsIBoldvalueSpace(Mode: TBoldDomainElementProxyMode): IBoldvalueSpace; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + procedure SetTransactionMode(const Value: TBoldSystemTransactionMode);{$IFDEF BOLD_INLINE}inline;{$ENDIF} procedure SetPessimisticLockHandler(const Value: TBoldAbstractPessimisticLockHandler); function GetOnPreUpdate: TNotifyEvent; procedure SetOnPreUpdate(const Value: TNotifyEvent); - function GetTimeStampOfLatestUpdate: TBoldTimeStampType; - function GetUndoHandler: TBoldAbstractUndoHandler; - function GetUndoHandlerInterface: IBoldUndoHandler; - function CanCreateObject(ClassTypeInfo: TBoldClassTypeInfo): boolean; - function CanDeleteObject(anObject: TBoldObject): boolean; - procedure DiscardPersistent; - procedure DiscardTransient; + function GetTimeStampOfLatestUpdate: TBoldTimeStampType; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function GetTimeOfLatestUpdate: TDateTime; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function GetUndoHandler: TBoldAbstractUndoHandler; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetUndoHandlerInterface: IBoldUndoHandler; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function CanCreateObject(ClassTypeInfo: TBoldClassTypeInfo): boolean; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function CanDeleteObject(anObject: TBoldObject): boolean; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + procedure MemberDerivationBegin(Member: TBoldMember); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure MemberDerivationEnd(Member: TBoldMember); + function GetIsProcessingTransactionOrUpdatingDatabase: Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure ReceiveFromPersistenceController(Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent); + function GetDiscarding: Boolean; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function GetIsFetching: Boolean; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + property DirtyObjectsInvalid: Boolean index befDirtyObjectsInvalid read GetElementFlag write SetElementFlag; + property IsFetching: Boolean read GetIsFetching; protected function GetBoldDirty: Boolean; override; function GetBoldType: TBoldElementTypeInfo; override; - function GetDisplayName: String; override; function GetEvaluator: TBoldEvaluator; override; function GetStringRepresentation(Representation: TBoldRepresentation): string; override; - procedure ReceiveEventFromOwned(originator: TObject; originalEvent: TBoldEvent); override; + procedure ReceiveEventFromOwned(originator: TObject; originalEvent: TBoldEvent; const Args: array of const); override; +{$IFNDEF BOLD_NO_QUERIES} + function ReceiveQueryFromOwned(Originator: TObject; OriginalEvent: TBoldEvent; const Args: array of const; Subscriber: TBoldSubscriber): Boolean; override; +{$ENDIF} property SystemPersistenceHandler: TBoldAbstractSystemPersistenceHandler read fSystemPersistenceHandler; - public - constructor Create(AOwningElement: TBoldDomainElement); override; - constructor CreateWithTypeInfo(AOwningElement: TBoldDomainElement; SystemTypeInfo: TBoldSystemTypeInfo; PersistenceController: TBoldPersistenceController; RegionFactory: TBoldAbstractRegionFactory = nil); + property OldValueHandler: TBoldAbstractOldValueHandler read fOldValueHandler; + public +{$IFDEF ACCESSSTATISTICS} //// START PATCH ACCESSSTATISTICS //////////////////// + fAccessStats: TArrayOfArrayOfIntegers; + fDeriveStats: TArrayOfArrayOfIntegers; + fInvalidateStats: TArrayOfArrayOfIntegers; + fModifyStats: TArrayOfArrayOfIntegers; +{$ENDIF} //// END PATCH ACCESSSTATISTICS /////////////////////////////////////// + constructor CreateWithTypeInfo(AOwningElement: TBoldDomainElement; SystemTypeInfo: TBoldSystemTypeInfo; PersistenceController: TBoldPersistenceController; RegionFactory: TBoldAbstractRegionFactory = nil); reintroduce; destructor Destroy; override; function AssertLinkIntegrity: Boolean; class function DefaultSystem: TBoldSystem; procedure MakeDefault; procedure EnsureCanDestroy; procedure AllowObjectDestruction; + function CanEvaluateInPS(sOCL: string; aContext: TBoldElementTypeInfo = nil; const aVariableList: TBoldExternalVariableList = nil): Boolean; procedure CommitTransaction(MinimalMode: TBoldSystemTransactionMode = stmNormal); function CreateExistingObjectByID(BoldObjectID: TBoldObjectId): TBoldObject; function CreateNewObjectByExpressionName(const ExpressionName: string; Persistent: Boolean = True): TBoldObject; + function CreateNewObjectFromClassTypeInfo(aClassTypeInfo: TBoldClassTypeInfo; Persistent: Boolean = True): TBoldObject; procedure DefaultSubscribe(Subscriber: TBoldSubscriber; RequestedEvent: TBoldEvent = breReEvaluate); override; - procedure DelayObjectDestruction; - procedure Discard; + procedure DelayObjectDestruction; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + procedure Discard; override; + function IsDerivingMembers: boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function CurrentDerivedMember: TBoldMember; {$IFDEF BOLD_INLINE} inline; {$ENDIF} function EnsureEnclosure(ObjectList: TBoldObjectList; ValidateOnly: Boolean): Boolean; - procedure FetchLinksWithObjects(ObjectList: TBoldObjectList; const LinkName: string; FetchedObjects: TBoldObjectList = nil); + procedure FetchLinksWithObjects(ObjectList: TBoldObjectList; const LinkName: string;FetchObjectsInLink: Boolean = True{; const FetchedObjectList: TBoldObjectList = nil}); + procedure FetchMembersWithObjects(aBoldObjectList: TBoldObjectList; aBoldMemberIdList: TBoldMemberIdList); overload; + procedure FetchMembersWithObjects(aBoldObjectList: TBoldObjectList; const AMemberCommaList: string); overload; + procedure FetchMembersWithObject(ABoldObject: TBoldObject; const AMemberCommaList: string); + procedure FetchIdList(FetchIdList: TBoldObjectIdList; AFetchObjects: boolean = true); procedure GetAllInClass(aList: TBoldObjectList; AClass: TBoldObjectClass); procedure GetAllWithCondition(aList: TBoldObjectList; Condition: TBoldCondition); procedure GetAllInClassWithSQL(aList: TBoldObjectList; AClass: TBoldObjectClass; WhereClause, OrderByClause: String; Params: TParams = nil; JoinInheritedTables: Boolean = true; MaxAnswers: integer = -1; Offset: integer = -1); + procedure GetAllInClassWithRawSQL(aList: TBoldObjectList; AClass: TBoldObjectClass; SQL: String; Params: TParams = nil; MaxAnswers: integer = -1; Offset: integer = -1); procedure GetAsList(ResultList: TBoldIndirectElement); override; - function InTransaction: boolean; + function InTransaction: boolean; {$IFDEF BOLD_INLINE}inline;{$ENDIF} procedure RollbackTransaction(MinimalMode: TBoldSystemTransactionMode = stmNormal); procedure StartTransaction(MinimalMode: TBoldSystemTransactionMode = stmNormal); function TryCommitTransaction(MinimalMode: TBoldSystemTransactionMode = stmNormal): Boolean; procedure UpdateDatabase; procedure UpdateDatabaseWithList(ObjectList: TBoldObjectList); + procedure UpdateDatabaseWithObjects(const aObjects: array of TBoldObject); function ProxyInterface(const IId: TGUID; Mode: TBoldDomainElementProxyMode; out Obj): Boolean; override; + procedure CheckIntegrity; + procedure DiscardPersistent(ADiscardTransientLinks: boolean = true); + procedure DiscardTransient; + function EnsureLocatorByID(ObjectID: TBoldObjectId; out ACreated: boolean): TBoldObjectLocator; + function ContainsDirtyObjectsOfClass(AClassType: TBoldObjectClass): boolean; + procedure RemoveDeletedObjects(IDList: TBoldObjectIdList); property IsDefault: Boolean read GetIsDefault write SetIsDefault; + property IsDestroying: Boolean index befIsDestroying read GetElementFlag write SetElementFlag; + property IsCommitting: Boolean index befIsCommitting read GetElementFlag write SetElementFlag; + property IsRollingBack: Boolean index befIsRollingBack read GetElementFlag write SetElementFlag; + property IsUpdatingDatabase: Boolean index befIsUpdatingDatabase read GetElementFlag write SetElementFlag; + property IsProcessingTransactionOrUpdatingDatabase: Boolean read GetIsProcessingTransactionOrUpdatingDatabase; property BoldSystemTypeInfo: TBoldSystemTypeInfo read fBoldSystemTypeInfo; property ClassByExpressionName[const ExpressionName: string]: TBoldObjectList read GetClassByExpressionName; + property ClassByObjectClass[ObjectClass: TBoldObjectClass]: TBoldObjectList read GetClassByObjectClass; property Classes[index: Integer]: TBoldObjectList read GetClassByIndex; property DirtyObjects: TList read GetDirtyObjects; + property DirtyObjectsAsBoldListByClass[AClassType: TBoldObjectClass]: TBoldObjectList read GetDirtyObjectsAsBoldList; + property DirtyObjectsAsBoldListByClassExpressionName[const AClass: string]: TBoldObjectList read GetDirtyObjectsAsBoldListByClassExpressionName; + property DirtyObjectsAsBoldList: TBoldObjectList read GetAllDirtyObjectsAsBoldList; property EnsuredLocatorByID[ObjectID: TBoldObjectId]: TBoldObjectLocator read GetEnsuredLocatorByID; property Locators: TBoldSystemLocatorList read fLocators; property PessimisticLockHandler: TBoldAbstractPessimisticLockHandler read fPessimisticLockHandler write SetPessimisticLockHandler; @@ -321,11 +378,13 @@ TBoldSystem = class(TBoldDomainElement) property RegionFactory: TBoldAbstractRegionFactory read fRegionFactory; property NewDirtyList: TBoldObjectList read FNewDirtyList write FNewDirtyList; property NewModifiedList: TBoldObjectList read FNewModifiedList write FNewModifiedList; + property TransactionNesting: Integer read fTransactionNesting; property PersistenceController: TBoldPersistenceController read fPersistenceController; property AsIBoldvalueSpace[Mode: TBoldDomainElementProxyMode]: IBoldvalueSpace read GetAsIBoldValueSpace; property TimeForTimestamp[Timestamp: TBoldTimestampType]: TDateTime read GetTimeForTimestamp; property TimestampForTime[ClockTime: TDateTime]: TBoldTimestampType read GetTimestampForTime; property TimeStampOfLatestUpdate: TBoldTimeStampType read GetTimeStampOfLatestUpdate; + property TimeOfLatestUpdate: TDateTime read GetTimeOfLatestUpdate; property TransactionMode: TBoldSystemTransactionMode read fTransactionMode write SetTransactionMode; property OnPreUpdate: TNotifyEvent read GetOnPreUpdate write SetOnPreUpdate; property OnOptimisticLockingFailed: TBoldOptimisticLockingFailedEvent read fOptimisticLockingFailed write fOptimisticLockingFailed; @@ -334,59 +393,73 @@ TBoldSystem = class(TBoldDomainElement) property OnCreateApproximateObjectError: TBoldCreateApproximateObjectError read fOnCreateApproximateObjectError write fOnCreateApproximateObjectError; end; - { TBoldLocatorListTraverser } + { TBoldLocatorListTraverser } TBoldLocatorListTraverser = class(TBoldIndexableListTraverser) private - function GetLocator: TBoldObjectLocator; + function GetLocator: TBoldObjectLocator; {$IFDEF BOLD_INLINE}inline;{$ENDIF} public - property locator: TBoldObjectLocator read GetLocator; + property Locator: TBoldObjectLocator read GetLocator; + property Current: TBoldObjectLocator read GetLocator; end; {---TBoldSystemLocatorList---} TBoldSystemLocatorList = class(TBoldUnOrderedIndexableList) private - function GetLocatorByID(ObjectID: TBoldObjectId): TBoldObjectLocator; - function GetObjectByID(ObjectID: TBoldObjectId): TBoldObject; + class var IX_BoldObjectId: integer; + function GetLocatorByID(ObjectID: TBoldObjectId): TBoldObjectLocator; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function GetObjectByID(ObjectID: TBoldObjectId): TBoldObject; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function GetObjectByIDString(const ID: string): TBoldObject; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function GetLocatorByIDString(const ID: string): TBoldObjectLocator; {$IFDEF BOLD_INLINE}inline;{$ENDIF} protected function TraverserClass: TBoldIndexableListTraverserClass; override; public constructor Create; + function GetEnumerator: TBoldLocatorListTraverser; procedure UpdateID(Locator: TBoldObjectLocator; NewObjectID: TBoldObjectId; AllowInternal: Boolean = false); function CreateTraverser: TBoldLocatorListTraverser; property LocatorByID[ObjectID: TBoldObjectId]: TBoldObjectLocator read GetLocatorByID; property ObjectByID[ObjectID: TBoldObjectId]: TBoldObject read GetObjectByID; + property LocatorByIdString[const ID: string]: TBoldObjectLocator read GetLocatorByIDString; + property ObjectByIdString[const ID: string]: TBoldObject read GetObjectByIDString; end; + TBoldLocatorArray = array of TBoldObjectLocator; + {---TBoldObjectLocator---} TBoldObjectLocator = class(TBoldMemoryManagedObject) private fBoldSystem: TBoldSystem; fBoldObject: TBoldObject; fBoldObjectID: TBoldObjectId; - fEmbeddedSingleLinks: TBoldObjectArray; + fEmbeddedSingleLinks: TBoldLocatorArray; constructor CreateWithObjectId(BoldSystem: TBoldSystem; BoldObjectID: TBoldObjectId); constructor CreateWithClassID(BoldSystem: TBoldSystem; TopSortedIndex: integer; Exact: Boolean); + procedure AddToLocators; procedure FetchBoldObject; procedure EmbeddedSingleLinksToObject; procedure EmbeddedSingleLinksFromObject; procedure FreeEmbeddedSingleLinksOfOtherEnd; - function GetAsString: string; - function GetEnsuredBoldObject: TBoldObject; - function GetObjectIsPersistent: Boolean; - function GetEmbeddedSingleLinks(EmbeddedIndex: integer): TBoldObjectLocator; + function GetAsString: string; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function GetEnsuredBoldObject: TBoldObject; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function GetObjectIsPersistent: Boolean; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function GetEmbeddedSingleLinks(EmbeddedIndex: integer): TBoldObjectLocator; {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure SetEmbeddedSingleLinks(EmbeddedIndex: integer; const Value: TBoldObjectLocator); - //procedure TypeAtLeast(TopSortedIndex: integer; Exact: Boolean); + function GetClassTypeInfo: TBoldClassTypeInfo; + procedure TryShrinkEmbeddedLinks; + protected + function GetDebugInfo: string; override; public destructor Destroy; override; function AtTime(Time: TBoldTimeStampType): TBoldObjectLocator; - procedure DiscardBoldObject; - procedure EnsureBoldObject; - function Hash: Cardinal; + procedure DiscardBoldObject(ADiscardTransientLinks: boolean = true); + procedure EnsureBoldObject; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function Hash: Cardinal; {$IFDEF BOLD_INLINE}inline;{$ENDIF} procedure UnloadBoldObject; property AsString: string read GetAsString; property BoldObject: TBoldObject read FBoldObject; property BoldObjectID: TBoldObjectId read fBoldObjectID; property BoldSystem: TBoldSystem read FBoldSystem; + property BoldClassTypeInfo: TBoldClassTypeInfo read GetClassTypeInfo; property EnsuredBoldObject: TBoldObject read GetEnsuredBoldObject; property ObjectIsPersistent: Boolean read GetObjectIsPersistent; property EmbeddedSingleLinks[EmbeddedIndex: integer]: TBoldObjectLocator read GetEmbeddedSingleLinks write SetEmbeddedSingleLinks; @@ -394,11 +467,12 @@ TBoldObjectLocator = class(TBoldMemoryManagedObject) {---TBoldObject---} TBoldObject = class(TBoldDomainElement) - private fBoldClassTypeInfo: TBoldClassTypeInfo; - fDynamicData: PPointerList; // Defined in Classes for TList + fMemberArray: array of TBoldMember; + fDeriverArray: array of TBoldMemberDeriver; FBoldObjectLocator: TBoldObjectLocator; + fTimeStamp: TBoldTimeStampType; constructor InternalCreateWithClassAndLocator(ClassTypeInfo: TBoldClassTypeInfo; Locator: TBoldObjectLocator); procedure CalculateMemberModified; function CanUnload: Boolean; @@ -412,24 +486,26 @@ TBoldObject = class(TBoldDomainElement) procedure EndUpdate(Translationlist: TBoldIdTranslationlist); procedure EndUpdateMembers(Translationlist: TBoldIdTranslationlist); procedure FailDelete; - function FindBoldMemberByExpressionName(const Name: string): TBoldMember; - function GetBoldExistenceState: TBoldExistenceState; - function GetBoldMemberCount: Integer; + procedure InternalUnLinkAll(AUnlinkPersistent: boolean = true); + procedure InternalDiscard(ADiscardPersistentLinks: boolean = true); + function GetBoldExistenceState: TBoldExistenceState; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetBoldMemberCount: Integer; {inline;} // inline causes a bug function GetBoldMembers(index: Integer): TBoldMember; - function GetBoldPersistenceState: TBoldValuePersistenceState; - function GetBoldSystem: TBoldSystem; - function GetBoldTime: TBoldTimestampType; + function GetBoldMemberDeriver(Member: TBoldMember): TBoldMemberDeriver; + function GetBoldMemberIfAssigned(index: Integer): TBoldMember; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetBoldPersistenceState: TBoldValuePersistenceState; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetBoldSystem: TBoldSystem; reintroduce; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetBoldTime: TBoldTimestampType; {$IFDEF BOLD_INLINE}inline;{$ENDIF} function GetGlobalId: string; - function GetIsModified: Boolean; - function GetIsReadOnly: Boolean; // implements method in IBoldObjectContents - function GetObjectHasSubscribers: Boolean; - function GetTimeStamp: TBoldTimeStampType; + function GetIsModified: Boolean; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function GetObjectHasSubscribers: Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetTimeStamp: TBoldTimeStampType; {$IFDEF BOLD_INLINE}inline;{$ENDIF} procedure InitializeObject(System: TBoldSystem; ClassTypeInfo: TBoldClassTypeInfo; Locator: TBoldObjectLocator; Persistent: Boolean); - function CreateMemberByIndex(Index: integer): TBoldMember; procedure InitializeMember(Member: TBoldMember; MemberRTInfo: TBoldMemberRTInfo; IsNewObject: Boolean); function MayUpdateMembers: Boolean; - procedure MemberBecomingClean(BoldMember: TBoldMember); - procedure MemberBecomingModified(BoldMember: TBoldMember); + procedure MemberBecomingClean(BoldMember: TBoldMember); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure MemberBecomingModified(BoldMember: TBoldMember); {inline;} // inline causes a bug + procedure MemberChangingValidity(BoldMemberRtInfo: TBoldMemberRtInfo; NewValue: TBoldValuePersistenceState); {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure SetBoldExistenceState(Value: TBoldExistenceState); procedure SetBoldPersistenceState(Value: TBoldValuePersistenceState); procedure SetIsReadOnly(NewValue: Boolean); @@ -437,41 +513,52 @@ TBoldObject = class(TBoldDomainElement) procedure SetTimeStamp(NewValue: TBoldTimeStampType); function StartDelete: Boolean; function InternalCanDelete(CheckedObjects: TBoldDomainElementCollection; Cascade: Boolean): Boolean; - function GetAsIBoldObjectContents(Mode: TBoldDomainElementProxyMode): IBoldObjectContents; - function GetBoldMemberAssigned(Index: integer): Boolean; - function GetBoldObjectIsNew: Boolean; - function GetBoldObjectIsDeleted: Boolean; - function GetBoldObjectExists: Boolean; - function GetDynamicDataSize: Integer; + function GetAsIBoldObjectContents(Mode: TBoldDomainElementProxyMode): IBoldObjectContents; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function GetBoldMemberAssigned(Index: integer): Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function SafeGetBoldMemberAssigned(Index: integer): Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetBoldObjectIsNew: Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetBoldObjectIsDeleted: Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetBoldObjectExists: Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} property InDirtyList: Boolean index befInDirtyList read GetElementFlag write SetElementFlag; - property IsReadOnly: Boolean read GetIsReadOnly; property MemberModified: Boolean index befMemberModified read GetElementFlag write SetElementFlag; property MemberModifiedKnown: Boolean index befMemberModifiedKnown read GetElementFlag write SetElementFlag; - property BoldStoresTimeStamp: boolean index befStoresTimeStamp read GetElementFlag; + property IsEffectiveInvalid: Boolean index befIsEffectiveInvalid read GetElementFlag write SetElementFlag; + property IsEffectiveInvalidKnown: Boolean index befIsEffectiveInvalidKnown read GetElementFlag write SetElementFlag; + property InDelayDestructionList: Boolean index befInDelayDestructionList read GetElementFlag write SetElementFlag; function GetBoldMemberByExpressionName(const Name: string): TBoldMember; function GetBoldMemberIndexByExpressionName(const Name: string): Integer; - //function GetEffectiveInvalid: Boolean; + function CalculateEffectiveInvalid: Boolean; + function GetEffectiveInvalid: Boolean; + procedure FreeDerivers; protected procedure CompleteCreate; virtual; procedure CompleteUpdate; virtual; + procedure CompleteRecreate; virtual; function GetBoldDirty: Boolean; override; function GetBoldType: TBoldElementTypeInfo; override; function GetDisplayName: String; override; function GetEvaluator: TBoldEvaluator; override; function GetStringRepresentation(Representation: TBoldRepresentation): string; override; - function GetDeriveMethodForMember(Member: TBoldMember): TBoldDeriveAndResubscribe; virtual; - function GetReverseDeriveMethodForMember(Member: TBoldMember): TBoldReverseDerive; virtual; + function GetDeriveMethodForMember(Member: TBoldMember): TBoldDeriveAndResubscribe; overload; virtual; + function GetDeriveMethodForMember(MemberIndex: Integer): TBoldDeriveAndResubscribe; overload; virtual; + function GetReverseDeriveMethodForMember(Member: TBoldMember): TBoldReverseDerive; overload; virtual; + function GetReverseDeriveMethodForMember(MemberIndex: Integer): TBoldReverseDerive; overload; virtual; function MayDelete: Boolean; virtual; function MayUpdate: Boolean; virtual; + function GetDeletingOrDeletingByDiscard: Boolean; procedure PrepareDelete; virtual; procedure PrepareUpdate; virtual; + procedure PrepareDiscard; virtual; + procedure InternalPrepareDeleteOrDeleteByDiscard; virtual; procedure StateError(S: String); override; function ValidateMember(const ObjectDelphiName, MemberDelphiName: String; GeneratedMemberIndex: integer; MemberClass: TBoldMemberClass): Boolean; procedure ToBeRemovedMemberAccessed(MemberRTInfo: TBoldMemberRTInfo); virtual; procedure ToBeRemovedMemberModified(MemberRTInfo: TBoldMemberRTInfo); virtual; procedure ToBeRemovedClassAccessed; virtual; + function InternalCanDeleteObject: Boolean; virtual; + procedure BeforeDiscard; virtual; + procedure AfterDiscard; virtual; public - // must be public so that links can call it when creating linkclasses constructor Create(AOwningElement: TBoldDomainElement; Persistent: Boolean = True); reintroduce; constructor InternalCreateNewWithClassAndSystem(ClassTypeInfo: TBoldClassTypeInfo; aSystem: TBoldSystem; Persistent: Boolean); destructor Destroy; override; @@ -482,23 +569,32 @@ TBoldObject = class(TBoldDomainElement) function CheckLinks(index: Integer): Boolean; procedure DefaultSubscribe(Subscriber: TBoldSubscriber; RequestedEvent: TBoldEvent = breReEvaluate); override; procedure Delete; - procedure Discard; + procedure Discard; override; + procedure DiscardPersistentMembers; procedure GetAsList(ResultList: TBoldIndirectElement); override; - procedure Invalidate; + procedure Invalidate; override; function IsEqualAs(CompareType: TBoldCompareType; BoldElement: TBoldElement): Boolean; override; - procedure ReceiveEventFromOwned(originator: TObject; originalEvent: TBoldEvent); override; + procedure ReceiveEventFromOwned(originator: TObject; originalEvent: TBoldEvent; const Args: array of const); override; +{$IFNDEF BOLD_NO_QUERIES} + function ReceiveQueryFromOwned(Originator: TObject; OriginalEvent: TBoldEvent; const Args: array of const; Subscriber: TBoldSubscriber): Boolean; override; +{$ENDIF} procedure ReRead; procedure SubscribeToStringRepresentation(Representation: TBoldRepresentation; Subscriber: TBoldSubscriber; RequestedEvent: TBoldEvent = breReEvaluate); override; procedure UnLinkAll; + procedure UnLinkAllPersistent; +{$IFNDEF CompareToOldValues} procedure MarkObjectDirty; +{$ENDIF} procedure ClearTouched; function ProxyInterface(const IId: TGUID; Mode: TBoldDomainElementProxyMode; out Obj): Boolean; override; + function FindBoldMemberByExpressionName(const Name: string): TBoldMember; property BoldClassTypeInfo: TBoldClassTypeInfo read fBoldClassTypeInfo; property BoldExistenceState: TBoldExistenceState read GetBoldExistenceState; property BoldMemberByExpressionName[const name: string]: TBoldMember read GetBoldMemberByExpressionName; property BoldMemberCount: Integer read GetBoldMemberCount; property BoldMemberIndexByExpressionName[const name: string]: Integer read GetBoldMemberIndexByExpressionName; property BoldMemberAssigned[index: Integer]: Boolean read GetBoldMemberAssigned; + property BoldMemberIfAssigned[index: Integer]: TBoldMember read GetBoldMemberIfAssigned; property BoldMembers[index: Integer]: TBoldMember read GetBoldMembers; property BoldObjectLocator: TBoldObjectLocator read FBoldObjectLocator; property BoldPersistenceState: TBoldValuePersistenceState read GetBoldPersistenceState; @@ -510,6 +606,12 @@ TBoldObject = class(TBoldDomainElement) property BoldObjectIsDeleted: Boolean read GetBoldObjectIsDeleted; property BoldObjectExists: Boolean read GetBoldObjectExists; property Touched: Boolean index befTouched read GetElementFlag; + property Discarding: Boolean index befDiscarding read GetElementFlag write SetElementFlag; + property Deleting: Boolean index befDeleting read GetElementFlag write SetElementFlag; + property DeletingOrDeletingByDiscard: Boolean read GetDeletingOrDeletingByDiscard; + property IsHistoricVersion: Boolean index befIsHistoricVersion read GetElementFlag; + property IsReadOnly: Boolean index befObjectReadOnly read GetElementFlag write SetElementFlag; + property EffectiveInvalid: Boolean read GetEffectiveInvalid; end; { TBoldMember } @@ -517,40 +619,44 @@ TBoldMember = class(TBoldDomainElement) private fBoldMetaType: TBoldMetaElement; procedure AdjustOldValues(Translationlist: TBoldIdTranslationlist); virtual; - procedure CalculateDerivedMemberWithExpression(DerivedObject: TObject; Subscriber: TBoldSubscriber); + procedure CalculateDerivedMemberWithExpression(Subscriber: TBoldSubscriber); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure CalculateDerivedMemberWithDeriveMethod(Subscriber: TBoldSubscriber); + procedure DeriveMember(Subscriber: TBoldSubscriber); + procedure ReverseDeriveMember(); procedure EndUpdate(Translationlist: TBoldIdTranslationlist); - function GetOwningObject: TBoldObject; - function GetBoldSystem: TBoldSystem; - function GetBoldMemberRTInfo: TBoldMemberRTInfo; - procedure _NotifyOutOfDate; + function GetOwningObject: TBoldObject; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetBoldSystem: TBoldSystem; reintroduce; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetBoldMemberRTInfo: TBoldMemberRTInfo; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure _NotifyOutOfDate; {$IFDEF BOLD_INLINE}inline;{$ENDIF} procedure DoSetInitialValue; virtual; - function FindASystem: TBoldSystem; - function GetDeriver: TBoldEventPluggedDeriver; + {$IFDEF LightMemberDeriver} + function GetDeriver: TBoldMemberDeriver; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + {$ENDIF} function GetElementTypeInfoForType: TBoldElementTypeInfo; virtual; - function GetIsPartOfSystem: Boolean; - function GetIsReadOnly(Flag: TBoldElementFlag): Boolean; - procedure InitializeStateToInvalid; - procedure InitializeStateToModified; - procedure InitializeStateToTransient; + function GetIsReadOnly(Flag: TBoldElementFlag): Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure InitializeStateToInvalid; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure InitializeStateToModified; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure InitializeStateToTransient; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure InitializeStateToCurrent; {$IFDEF BOLD_INLINE} inline; {$ENDIF} function InternalMayUpdate: Boolean; virtual; - function IsInvalid: Boolean; + function IsInvalid: Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetIsCurrent: Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure MakeDbCurrent; virtual; procedure ObjectBecomingPersistent; procedure InternalDiscard; - function GetAsIBoldValue(Mode: TBoldDomainElementProxyMode): IBoldValue; + function GetAsIBoldValue(Mode: TBoldDomainElementProxyMode): IBoldValue; {$IFDEF BOLD_INLINE}inline;{$ENDIF} function GetController: TBoldAbstractController; virtual; - procedure MarkMemberDirty; procedure AssignContentValueFromElement(source: TBoldElement); virtual; property HasDeriver: Boolean index befHasDeriver read GetElementFlag write SetElementFlag; - property OwnedByObject: Boolean index befOwnedByObject read GetElementFlag write SetElementFlag; - property IsReadOnly: Boolean index befMemberReadOnly read GetIsReadOnly write SetElementFlag; - function GetDeriverState: TBoldDeriverState; - procedure SetDeriverState(value: TBoldDeriverState); - function GetOldvalue: IBoldvalue; - constructor InternalCreate(OwningObject: TBoldObject; MemberRTInfo: TBoldMemberRTInfo; SetInitialValue: Boolean); + function GetDeriverState: TBoldDeriverState; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure SetDeriverState(value: TBoldDeriverState); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetOldValue: IBoldvalue; + constructor CreateAsObjectPart(OwningObject: TBoldObject; MemberRTInfo: TBoldMemberRTInfo); + procedure InitializeNonObjectOwned(ElementTypeInfo: TBoldElementTypeInfo); {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure PreDiscard; virtual; property DeriverState: TBoldDeriverState read GetDeriverState write SetDeriverState; protected + function FindASystem: TBoldSystem; procedure DoStartModify; procedure Changed(Event: TBoldEvent; const Args: array of const); procedure CompleteModify; virtual; @@ -558,13 +664,18 @@ TBoldMember = class(TBoldDomainElement) procedure EndModify; procedure FailModify; procedure FreeContent; virtual; + {$IFNDEF LightMemberDeriver} + function GetDeriver: TBoldMemberDeriver; virtual; + {$ENDIF} function GetBoldDirty: Boolean; override; - function GetBoldPersistenceState: TBoldValuePersistenceState; + function GetBoldPersistenceState: TBoldValuePersistenceState; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetPSStateIsInvalid: Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} function GetBoldType: TBoldElementTypeInfo; override; function GetDisplayName: String; override; function GetEvaluator: TBoldEvaluator; override; function GetStreamName: string; virtual; - procedure InitializeMember(AOwningElement: TBoldDomainElement; ElementTypeInfo: TBoldElementTypeInfo); virtual; + function GetFreeStandingClass: TBoldFreeStandingElementClass; virtual; + procedure Initialize; virtual; function MayModify: Boolean; virtual; function MayUpdate: Boolean; virtual; procedure PreChange; @@ -574,54 +685,68 @@ TBoldMember = class(TBoldDomainElement) procedure StateError(S: String); override; function StartModify: Boolean; virtual; function RetrieveProxyInterface(const IId: TGUID; Mode: TBoldDomainElementProxyMode; out Obj; const InterfaceName: string): Boolean; - function ProxyClass: TBoldMember_ProxyClass; virtual; abstract; + function GetProxy(Mode: TBoldDomainElementProxyMode): TBoldMember_Proxy; virtual; abstract; function CloneIfPossible: TBoldElement; override; + function GetIsPartOfSystem: Boolean; override; public constructor Create; reintroduce; - constructor CreateWithTypeInfo(ElementTypeInfo: TBoldElementTypeInfo); + constructor CreateWithTypeInfo(ElementTypeInfo: TBoldElementTypeInfo); override; destructor Destroy; override; function AtTime(Time: TBoldTimestampType): TBoldMember; virtual; function CanModify: Boolean; function CanUpdate: Boolean; - function MemberHasSubscribers: Boolean; - function Clone: TBoldMember; - function IsEqualToValue(Value: IBoldValue): Boolean; virtual; - function StoreInUndo: Boolean; { TODO : Move to RTInfo } - procedure Discard; - procedure EnsureContentsCurrent; + function MemberHasSubscribers: Boolean; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function Clone: TBoldMember; virtual; + function IsEqualToValue(const Value: IBoldValue): Boolean; virtual; + function StoreInUndo: Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure Discard; override; + procedure DoEnsureContentsCurrent; + procedure DoMarkTouched; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure EnsureContentsCurrent; {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure Refetch; procedure GetAsList(ResultList: TBoldIndirectElement); override; procedure GetAsValue(ResultElement: TBoldIndirectElement); override; - procedure Invalidate; - function CanRead(Subscriber: TBoldSubscriber): Boolean; + procedure Invalidate; override; + procedure MarkMemberDirty; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function CanRead(Subscriber: TBoldSubscriber): Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} function ObserverMayModify(Observer: TObject): Boolean; override; function ProxyInterface(const IId: TGUID; Mode: TBoldDomainElementProxyMode; out Obj): Boolean; override; property BoldMemberRTInfo: TBoldMemberRTInfo read GetBoldMemberRTInfo; property BoldSystem: TBoldSystem read GetBoldSystem; property BoldPersistenceState: TBoldValuePersistenceState read GetBoldPersistenceState write SetBoldPersistenceState; + property BoldPersistenceStateIsInvalid: Boolean read GetPSStateIsInvalid; + property IsCurrent: Boolean read GetIsCurrent; property Derived: Boolean index befDerived read GetElementFlag; - property Deriver: TBoldEventPluggedDeriver read GetDeriver; - property IsPartOfSystem: Boolean read GetIsPartOfSystem; + property Deriver: TBoldMemberDeriver read GetDeriver; property OwningObject: TBoldObject read GetOwningObject; property AsIBoldValue[Mode: TBoldDomainElementProxyMode]: IBoldValue read GetAsIBoldValue; property OldValue: IBoldValue read GetOldValue; property Touched: Boolean index befTouched read GetElementFlag; + property IsPreFetched: Boolean index befPreFetched read GetElementFlag write SetElementFlag; + property OwnedByObject: Boolean index befOwnedByObject read GetElementFlag write SetElementFlag; + property IsReadOnly: Boolean index befMemberReadOnly read GetIsReadOnly write SetElementFlag; end; { TBoldMember_Proxy } TBoldMember_Proxy = class(TBoldDomainElement_Proxy, IBoldValue, IBoldStreamable) private - function GetProxedMember: TBoldMember; - function GetProxedController: TBoldAbstractController; + fProxedMember: TBoldMember; + function GetProxedController: TBoldAbstractController; {$IFDEF BOLD_INLINE} inline; {$ENDIF} protected - property ProxedMember: TBoldMember read GetProxedMember; + property ProxedMember: TBoldMember read fProxedMember; property ProxedController: TBoldAbstractController read GetProxedController; - function GetContentName: String; - function GetStreamName: String; - procedure AssignContent(Source: IBoldValue); - procedure AssignContentValue(Source: IBoldValue); virtual; abstract; - function GetBoldPersistenceState: TBoldValuePersistenceState; - procedure SetBoldPersistenceState(Value: TBoldValuePersistenceState); + function GetContentName: String; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function GetStreamName: String; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function GetFreeStandingClass: TBoldFreeStandingElementClass; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function GetContentType: TBoldValueContentType; + procedure AssignContent(const Source: IBoldValue); + procedure AssignContentValue(const Source: IBoldValue); virtual; abstract; + function GetBoldPersistenceState: TBoldValuePersistenceState; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + procedure SetBoldPersistenceState(Value: TBoldValuePersistenceState); {$IFDEF BOLD_INLINE}inline;{$ENDIF} + constructor Create(ProxedMember: TBoldMember; Mode: TBoldDomainElementProxyMode); + public + class function MakeProxy(ProxedMember: TBoldMember; Mode: TBoldDomainElementProxyMode): TBoldMember_Proxy; virtual; + procedure Retarget(ProxedMember: TBoldMember; Mode: TBoldDomainElementProxyMode); {$IFDEF BOLD_INLINE} inline; {$ENDIF} end; { TBoldMemberFactory } @@ -634,67 +759,75 @@ TBoldMemberFactory = class(TBoldMemoryManagedObject) {---TBoldAttribute---} TBoldAttribute = class(TBoldMember) private - function GetBoldAttributeRTInfo: TBoldAttributeRTInfo; + function GetBoldAttributeRTInfo: TBoldAttributeRTInfo; {$IFDEF BOLD_INLINE} inline; {$ENDIF} function GetElementTypeInfoForType: TBoldElementTypeInfo; override; - function GetIsNull: Boolean; + function GetIsNull: Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure MakeDbCurrent; override; procedure NullFailure; protected - procedure AssignValue(Source: IBoldValue); virtual; abstract; - procedure AssignContentValue(Source: IBoldValue); virtual; abstract; + procedure AssignValue(const Source: IBoldValue); virtual; abstract; + procedure AssignContentValue(const Source: IBoldValue); virtual; abstract; procedure DoSetInitialValue; override; - function GetContentIsNull: Boolean; + property ContentIsNull: Boolean index befIsNull read GetElementFlag; class function EitherIsNull(Attribute1, Attribute2: TBoldAttribute): Boolean; - procedure EnsureNotNull; + procedure EnsureNotNull; {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure FormatFailure(const value, ExpectedDataType: String); + function GetAttributeTypeInfoForType: TBoldElementTypeInfo; virtual; function GetStreamName: string; override; + function StringCompare(CompareType: TBoldCompareType; const s1, s2: string): integer; function NullBiggest(BoldElement: TBoldElement): Integer; function NullSmallest(BoldElement: TBoldElement): Integer; procedure SetContentToNull; - procedure SetToNonNull; - property ContentIsNull: Boolean read GetContentIsNull; + procedure SetToNonNull; {$IFDEF BOLD_INLINE}inline;{$ENDIF} public + function GetAsVariant: Variant; override; + procedure SetAsVariant(const Value: Variant); override; function CompareToAs(CompType: TBoldCompareType; BoldElement: TBoldElement): Integer; override; procedure DefaultSubscribe(Subscriber: TBoldSubscriber; RequestedEvent: TBoldEvent = breReEvaluate); override; function CanSetToNull(Subscriber: TBoldSubscriber): Boolean; - function IsEqualToValue(Value: IBoldValue): Boolean; override; + function IsEqualToValue(const Value: IBoldValue): Boolean; override; procedure RecycleValue; procedure SetToNull; virtual; procedure Assign(Source: TBoldElement); override; function ProxyInterface(const IId: TGUID; Mode: TBoldDomainElementProxyMode; out Obj): Boolean; override; procedure SubscribeToStringRepresentation(Representation: TBoldRepresentation; Subscriber: TBoldSubscriber; RequestedEvent: TBoldEvent = breReEvaluate); override; procedure SetEmptyValue; virtual; + function ValidateVariant(const Value: Variant; Representation: TBoldRepresentation = brDefault): Boolean; override; + function IsVariantTypeCompatible(const Value: Variant): Boolean; virtual; property BoldAttributeRTInfo: TBoldAttributeRTInfo read GetBoldAttributeRTInfo; property IsNull: Boolean read GetIsNull; end; { TBoldAttribute_Proxy } - TBoldAttribute_Proxy = class(TBoldMember_Proxy, IBoldNullableValue) + TBoldAttribute_Proxy = class(TBoldMember_Proxy, IBoldNullableValue, IBoldStringRepresentable) private - function GetProxedAttribute: TBoldAttribute; + function GetProxedAttribute: TBoldAttribute; {$IFDEF BOLD_INLINE}inline;{$ENDIF} protected - procedure AssignContentValue(Source: IBoldValue); override; - procedure SetContentToNull; - function GetContentIsNull: Boolean; + procedure AssignContentValue(const Source: IBoldValue); override; + procedure SetContentToNull; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function GetContentIsNull: Boolean; {$IFDEF BOLD_INLINE}inline;{$ENDIF} property ProxedAttribute: TBoldAttribute read GetProxedAttribute implements IBoldNullableValue; + function GetStringRepresentation(representation:integer): String; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + procedure SetStringRepresentation(Representation: integer; const NewValue: String); {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function GetContentAsString: String; virtual; end; { TBoldFailureReason } TBoldFailureReason = class(TObject) private FMessageFormatStr: String; - fOriginator: TBoldDomainElement; + fOriginator: TBoldElement; fReason: string; fSubscriber: TBoldPassThroughSubscriber; procedure ReceiveOriginatorDestroy(Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent); protected function GetException(const Msg: String): EBoldFailure; virtual; public - constructor create(reason: String; Originator: TBoldDomainElement); - constructor CreateFmt(Reason: string; const args: array of const; Originator: TBoldDomainElement); + constructor Create(AReason: String; Originator: TBoldElement); + constructor CreateFmt(Reason: string; const args: array of const; Originator: TBoldElement); destructor Destroy; override; property MessageFormatStr: String read fMessageFormatStr write fMessageFormatStr; - property Originator: TBoldDomainElement read fOriginator; + property Originator: TBoldElement read fOriginator; property Reason: string read fReason; end; @@ -704,7 +837,7 @@ TBoldObjectReference = class(TBoldMember) fObjectReferenceController: TBoldAbstractObjectReferenceController; procedure AdjustOldValues(Translationlist: TBoldIdTranslationlist); override; function GetBoldObject: TBoldObject; - function GetBoldRoleRTInfo: TBoldRoleRTInfo; + function GetBoldRoleRTInfo: TBoldRoleRTInfo; {$IFDEF BOLD_INLINE}inline;{$ENDIF} function InternalMayUpdate: Boolean; override; procedure InternalSetLocator(NewLocator: TBoldObjectLocator); procedure MakeDbCurrent; override; @@ -716,27 +849,29 @@ TBoldObjectReference = class(TBoldMember) function GetOldEmbeddingOtherEndId: TBoldObjectId; procedure PreDiscard; override; procedure DoSetInitialValue; override; - function GetLocator: TBoldObjectLocator; + function GetLocator: TBoldObjectLocator; {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure SetLocator(NewLocator: TBoldObjectLocator); + function GetIsEmpty: boolean; protected function GetStreamName: String; override; + function GetFreeStandingClass: TBoldFreeStandingElementClass; override; function GetStringRepresentation(Representation: TBoldRepresentation): string; override; - procedure InitializeMember(AOwningElement: TBoldDomainElement; ElementTypeInfo: TBoldElementTypeInfo); override; - procedure SetStringRepresentation(Representation: TBoldRepresentation; Value: string); override; - function ProxyClass: TBoldMember_ProxyClass; override; + procedure Initialize; override; + procedure SetStringRepresentation(Representation: TBoldRepresentation; const Value: string); override; + function GetProxy(Mode: TBoldDomainElementProxyMode): TBoldMember_Proxy; override; public constructor CreateTypedReference(ObjectClass: TBoldObjectClass); destructor Destroy; override; procedure Assign(Source: TBoldElement); override; - function CanClear(Subscriber: TBoldSubscriber): Boolean; - function CanSet(NewObject: TBoldObject; Subscriber: TBoldSubscriber): Boolean; + function CanClear(Subscriber: TBoldSubscriber): Boolean; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function CanSet(NewObject: TBoldObject; Subscriber: TBoldSubscriber): Boolean; {$IFDEF BOLD_INLINE}inline;{$ENDIF} function CanSetLocator(NewLocator: TBoldObjectLocator; Subscriber: TBoldSubscriber): Boolean; procedure Clear; function CompareToAs(CompareType: TBoldCompareType; BoldElement: TBoldElement): Integer; override; procedure DefaultSubscribe(Subscriber: TBoldSubscriber; RequestedEvent: TBoldEvent = breReEvaluate); override; procedure GetAsList(ResultList: TBoldIndirectElement); override; function IsEqualAs(CompareType: TBoldCompareType; BoldElement: TBoldElement): Boolean; override; - function IsEqualToValue(Value: IBoldValue): Boolean; override; + function IsEqualToValue(const Value: IBoldValue): Boolean; override; function ObserverMayModify(Observer: TObject): Boolean; override; function ProxyInterface(const IId: TGUID; Mode: TBoldDomainElementProxyMode; out Obj): Boolean; override; procedure SubscribeToStringRepresentation(Representation: TBoldRepresentation; Subscriber: TBoldSubscriber; RequestedEvent: TBoldEvent = breReEvaluate); override; @@ -745,6 +880,21 @@ TBoldObjectReference = class(TBoldMember) property Locator: TBoldObjectLocator read GetLocator write SetLocator; property OldEmbeddingOtherEndId: TBoldObjectId read GetOldEmbeddingOtherEndId; property HasOldValues: Boolean index befHasOldValues read GetElementFlag write SetElementFlag; + property IsEmpty: boolean read GetIsEmpty; + end; + + TBoldListEnumerator = class + private + FIndex: Integer; + FList: TBoldList; + protected + property Index: Integer read fIndex; + property List: TBoldList read fList; + public + constructor Create(AList: TBoldList); + function GetCurrent: TBoldElement; + function MoveNext: Boolean; + property Current: TBoldElement read GetCurrent; end; { TBoldList } @@ -752,9 +902,15 @@ TBoldList = class(TBoldMember) private fListController: TBoldListController; function GetController: TBoldAbstractController; override; - function GetDuplicateMode: TBoldListDupMode; + function GetDuplicateMode: TBoldListDupMode; {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure PrepareClear; virtual; procedure SetDuplicateMode(NewMode: TBoldListDupMode); + function GetFirst: TBoldElement; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function GetLast: TBoldElement; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function GetEmpty: Boolean; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function DefaultCompare(Item1, Item2: TBoldElement): Integer; + function GetCapacity: integer; virtual; + procedure SetCapacity(const Value: integer); virtual; protected procedure AddElement(Element: TBoldElement); virtual; abstract; procedure AllocateData; virtual; @@ -767,7 +923,7 @@ TBoldList = class(TBoldMember) function GetStringRepresentation(Representation: TBoldRepresentation): string; override; function IncludesElement(Item: TBoldElement): Boolean; virtual; abstract; function IndexOfElement(Item: TBoldElement): Integer; virtual; abstract; - procedure InitializeMember(AOwningElement: TBoldDomainElement; ElementTypeInfo: TBoldElementTypeInfo); override; + procedure Initialize; override; procedure InsertElement(index: Integer; Element: TBoldElement); virtual; abstract; function InternalAddNew: TBoldElement; virtual; abstract; function GetCanCreateNew: Boolean; virtual; @@ -775,35 +931,59 @@ TBoldList = class(TBoldMember) procedure InternalClear; virtual; abstract; property ListController: TBoldListController read fListController write fListController; public + constructor CreateWithTypeInfo(ElementTypeInfo: TBoldElementTypeInfo); override; destructor Destroy; override; - procedure Add(Element: TBoldElement); + function GetEnumerator: TBoldListEnumerator; + procedure Add(Element: TBoldElement); {$IFDEF BOLD_INLINE}inline;{$ENDIF} procedure AddList(List: TBoldList); virtual; - function AddNew: TBoldElement; + procedure RemoveList(List: TBoldList); virtual; + procedure IntersectList(List: TBoldList); virtual; + function AddNew: TBoldElement; {$IFDEF BOLD_INLINE}inline;{$ENDIF} procedure AddToStrings(Representation: TBoldRepresentation; S: TStrings); - function CanClear(Subscriber: TBoldSubscriber): Boolean; + function CanClear(Subscriber: TBoldSubscriber): Boolean; {$IFDEF BOLD_INLINE}inline;{$ENDIF} function CanInsert(index: Integer; Element: TBoldElement; Subscriber: TBoldSubscriber): Boolean; virtual; function CanMove(CurIndex, NewIndex: Integer; Subscriber: TBoldSubscriber = nil): Boolean; virtual; function CanRemove(index: Integer; Subscriber: TBoldSubscriber): Boolean; virtual; function CanSet(index: Integer; Item: TBoldElement; Subscriber: TBoldSubscriber): Boolean; virtual; procedure Clear; + function CompareToAs(CompType: TBoldCompareType; BoldElement: TBoldElement): Integer; override; procedure DefaultSubscribe(Subscriber: TBoldSubscriber; RequestedEvent: TBoldEvent = breReEvaluate); override; procedure EnsureRange(FromIndex: integer; ToIndex: integer); virtual; procedure GetAsList(ResultList: TBoldIndirectElement); override; - function Includes(Item: TBoldElement): Boolean; - function IndexOf(Item: TBoldElement): Integer; + function Includes(Item: TBoldElement): Boolean; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function IncludesAny(aList: TBoldList): Boolean; + function IncludesAll(aList: TBoldList): Boolean; + function IndexOf(Item: TBoldElement): Integer; {$IFDEF BOLD_INLINE}inline;{$ENDIF} procedure Insert(index: Integer; Element: TBoldElement); procedure InsertNew(index: Integer); virtual; abstract; procedure Move(CurIndex, NewIndex: Integer); virtual; abstract; procedure MakeContentsImmutable; procedure Remove(Item: TBoldElement); virtual; procedure RemoveByIndex(index: Integer); virtual; abstract; - procedure Sort(CompareFunc: TBoldElementCompare); + procedure Sort(CompareFunc: TBoldElementCompare; FirstIndex, LastIndex: + Integer; SortMode: TBoldSortMode = BoldDefaultSortMode); overload; + procedure Sort(CompareFunc: TBoldElementCompare; SortMode: TBoldSortMode = + BoldDefaultSortMode); overload; + procedure Sort; overload; {$IFDEF BOLD_INLINE}inline;{$ENDIF} procedure ToStrings(Representation: TBoldRepresentation; S: TStrings); procedure ToStringsWithNil(Representation: TBoldRepresentation; S: TStrings; nilString: string); + function HasDuplicates: boolean; + function AsCommaText(AIncludeType: boolean = true; Representation: TBoldRepresentation = brDefault; const ASeparator: string = ','): string; + function AsDebugCommaText(const ASeparator: string = ','): string; property CanCreateNew: Boolean read GetCanCreateNew; property Count: Integer read GetCount; property DuplicateMode: TBoldListDupMode read GetDuplicateMode write SetDuplicateMode; property Elements[index: Integer]: TBoldElement read GetElement write SetElement; default; + property Empty: Boolean read GetEmpty; + property First: TBoldElement read GetFirst; + property Last: TBoldElement read GetLast; + property Capacity: integer read GetCapacity write SetCapacity; + end; + + TBoldMemberListEnumerator = class(TBoldListEnumerator) + public + function GetCurrent: TBoldMember; + property Current: TBoldMember read GetCurrent; end; {---TBoldMemberList---} @@ -816,8 +996,10 @@ TBoldMemberList = class(TBoldList) function CheckReplace(index: Integer; NewMember: TBoldMember): Boolean; procedure SetCloneMembers(const Value: Boolean); function GetBoldMember(index: Integer): TBoldMember; - procedure SetBoldMember(index: Integer; Value: TBoldMember); - procedure InternalAddWithoutCloning(Item: TBoldMember); // FIXME remove when TBoldClass no longer member + procedure SetBoldMember(index: Integer; Value: TBoldMember); {$IFDEF BOLD_INLINE}inline;{$ENDIF} + procedure InternalAddWithoutCloning(Item: TBoldMember); {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function GetCapacity: integer; override; + procedure SetCapacity(const Value: integer); override; property List: TList read faList; protected procedure AddElement(Element: TBoldElement); override; @@ -829,18 +1011,22 @@ TBoldMemberList = class(TBoldList) function GetElement(index: Integer): TBoldElement; override; function GetStreamName: String; override; function GetStringRepresentation(Representation: TBoldRepresentation): string; override; + procedure SetStringRepresentation(Representation: integer; const NewValue: String); override; function IncludesElement(Item: TBoldElement): Boolean; override; + function IncludesValue(Item: TBoldElement): Boolean; function IndexOfElement(Item: TBoldElement): Integer; override; - procedure InitializeMember(AOwningElement: TBoldDomainElement; ElementTypeInfo: TBoldElementTypeInfo); override; + procedure Initialize; override; procedure InsertElement(index: Integer; Element: TBoldElement); override; procedure SetElement(index: Integer; Value: TBoldElement); override; function InternalAddNew: TBoldElement; override; - function ProxyClass: TBoldMember_ProxyClass; override; + function GetProxy(Mode: TBoldDomainElementProxyMode): TBoldMember_Proxy; override; procedure InternalClear; override; public + function GetEnumerator: TBoldMemberListEnumerator; procedure Add(Item: TBoldMember); procedure Assign(Source: TBoldElement); override; - function IndexOf(Item: TBoldMember): Integer; + function IndexOf(Item: TBoldMember): Integer; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function IndexOfFirstEqualElement(Item: TBoldMember): Integer; procedure Insert(index: Integer; Item: TBoldMember); procedure InsertNew(index: Integer); override; procedure Move(CurIndex, NewIndex: Integer); override; @@ -849,29 +1035,40 @@ TBoldMemberList = class(TBoldList) property CloneMembers: Boolean read FCloneMembers write SetCloneMembers; end; + TBoldObjectListEnumerator = class(TBoldListEnumerator) + public + function GetCurrent: TBoldObject; + property Current: TBoldObject read GetCurrent; + end; + + TBoldObjectListLocatorEnumerator = class(TBoldListEnumerator) + public + function GetCurrent: TBoldObjectLocator; + property Current: TBoldObjectLocator read GetCurrent; + end; + {---TBoldObjectList ---} TBoldObjectList = class(TBoldList) private - function CheckAdd(NewLocator: TBoldObjectLocator): Boolean; - function CheckInsert(index: Integer; NewLocator: TBoldObjectLocator): Boolean; + function CheckAdd(NewLocator: TBoldObjectLocator): Boolean; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function CheckInsert(index: Integer; NewLocator: TBoldObjectLocator): Boolean; {$IFDEF BOLD_INLINE}inline;{$ENDIF} function CheckReplace(index: Integer; NewLocator: TBoldObjectLocator): Boolean; - function GetBoldRoleRTInfo: TBoldRoleRTInfo; - function GetObjectListController: TBoldAbstractObjectListController; + function GetBoldRoleRTInfo: TBoldRoleRTInfo; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function GetObjectListController: TBoldAbstractObjectListController; {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure MakeDbCurrent; override; - function GetSubscribeToObjectsInList: Boolean; + function GetSubscribeToObjectsInList: Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure SetSubscribeToObjectsInList(const Value: Boolean); - function GetSubscribeToLocatorsInList: Boolean; + function GetSubscribeToLocatorsInList: Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure SetSubscribeToLocatorsInList(const Value: Boolean); procedure InternalRemoveByIndex(index: Integer); procedure AssignContentValueFromElement(source: TBoldElement); override; procedure PrepareClear; override; - function GetBoldObject(index: Integer): TBoldObject; + function GetBoldObject(index: Integer): TBoldObject; {$IFDEF BOLD_INLINE}inline;{$ENDIF} function GetElementTypeInfoForType: TBoldElementTypeInfo; override; - function GetLocator(index: Integer): TBoldObjectLocator; + function GetLocator(index: Integer): TBoldObjectLocator; {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure SetBoldObject(index: Integer; NewObject: TBoldObject); procedure SetLocator(index: Integer; NewLocator: TBoldObjectLocator); function VerifyClass(aLocator: TBoldObjectLocator): Boolean; - property ObjectListController: TBoldAbstractObjectListController read GetObjectListController; protected procedure AddElement(Element: TBoldElement); override; procedure AllocateData; override; @@ -879,35 +1076,41 @@ TBoldObjectList = class(TBoldList) function GetCount: Integer; override; function GetElement(index: Integer): TBoldElement; override; function GetStreamName: String; override; + function GetFreeStandingClass: TBoldFreeStandingElementClass; override; function IncludesElement(Item: TBoldElement): Boolean; override; function IndexOfElement(Item: TBoldElement): Integer; override; - procedure InitializeMember(AOwningElement: TBoldDomainElement; ElementTypeInfo: TBoldElementTypeInfo); override; + procedure Initialize; override; procedure InsertElement(index: Integer; Element: TBoldElement); override; - procedure SetElement(index: Integer; Value: TBoldElement); override; - function ProxyClass: TBoldMember_ProxyClass; override; + function GetProxy(Mode: TBoldDomainElementProxyMode): TBoldMember_Proxy; override; procedure FreeContent; override; function InternalAddNew: TBoldElement; override; procedure InternalClear; override; + property ObjectListController: TBoldAbstractObjectListController read GetObjectListController; public - constructor InternalCreateClassList(System: TBoldSystem; ListTypeInfo: TBoldListTypeINfo); // used by ClassListController + function GetEnumerator: TBoldObjectListEnumerator; + function GetLocatorEnumerator: TBoldObjectListLocatorEnumerator; + constructor InternalCreateClassList(System: TBoldSystem; ListTypeInfo: TBoldListTypeInfo); constructor CreateTypedList(ObjectClass: TBoldObjectClass); - procedure Add(BoldObject: TBoldObject); + constructor CreateRootClassList; + procedure Add(BoldObject: TBoldObject); {$IFDEF BOLD_INLINE}inline;{$ENDIF} procedure AddList(List: TBoldList); override; procedure AddLocator(NewLocator: TBoldObjectLocator); procedure Assign(Source: TBoldElement); override; function AtTime(Time: TBoldTimestampType): TBoldMember; override; - function CreateObjectIdList: TBoldObjectIdList; - procedure EnsureObjects; + function CreateObjectIdList(WithoutDuplicates: boolean = false): TBoldObjectIdList; + procedure EnsureObjects; {$IFDEF BOLD_INLINE}inline;{$ENDIF} procedure EnsureRange(FromIndex: integer; ToIndex: integer); override; procedure FillFromIDList(ObjectIdList: TBoldObjectIdList; BoldSystem: TBoldSystem); - function GetByIndex(MemberList: TBoldMemberList): TBoldObject; + procedure RemoveDeletedObjects; + function FilterOnType(BoldClassTypeInfo: TBoldClassTypeInfo; IncludeSubclasses: boolean = true): TBoldObjectList; + function GetByIndex(MemberList: TBoldMemberList): TBoldObject; {$IFDEF BOLD_INLINE} inline; {$ENDIF} function GetByIndexAndSubscribe(MemberList: TBoldMemberList; Subscriber: TBoldSubscriber): TBoldObject; - function Includes(BoldObject: TBoldObject): Boolean; - function IndexOf(BoldObject: TBoldObject): Integer; - function IndexOfLocator(Locator: TBoldObjectLocator): Integer; + function Includes(BoldObject: TBoldObject): Boolean; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function IndexOf(BoldObject: TBoldObject): Integer; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function IndexOfLocator(Locator: TBoldObjectLocator): Integer; {$IFDEF BOLD_INLINE}inline;{$ENDIF} procedure InsertNew(index: Integer); override; - procedure Insert(index: Integer; BoldObject: TBoldObject); + procedure Insert(index: Integer; BoldObject: TBoldObject); {$IFDEF BOLD_INLINE}inline;{$ENDIF} procedure InsertLocator(index: Integer; Locator: TBoldObjectLocator); function LocatorInList(NewLocator: TBoldObjectLocator): Boolean; function CanInsert(index: Integer; Element: TBoldElement; Subscriber: TBoldSubscriber): Boolean; override; @@ -918,6 +1121,14 @@ TBoldObjectList = class(TBoldList) function ObserverMayModify(Observer: TObject): Boolean; override; function ProxyInterface(const IId: TGUID; Mode: TBoldDomainElementProxyMode; out Obj): Boolean; override; procedure RemoveByIndex(index: Integer); override; + procedure RemoveLocator(ALocator: TBoldObjectLocator); + procedure DeleteObjects; + function BeginUpdate: boolean; + procedure EndUpdate; + function IsEqualToValue(const Value: IBoldValue): Boolean; override; + function LeastCommonClassType(ABoldSystem: TBoldSystem): TBoldClassTypeInfo; + function Clone: TBoldMember; overload; override; + function Clone(ACopyDuplicateMode: boolean; ASubscribeToObjectsInList: boolean): TBoldMember; reintroduce; overload; property BoldObjects[index: Integer]: TBoldObject read GetBoldObject write SetBoldObject; default; property BoldRoleRTInfo: TBoldRoleRTInfo read GetBoldRoleRTInfo; property Locators[index: Integer]: TBoldObjectLocator read GetLocator write SetLocator; @@ -931,18 +1142,22 @@ TBoldObjectList = class(TBoldList) {---TBoldAbstractController---} TBoldAbstractController = class(TBoldMemoryManagedObject) protected + function GetRoleRTInfo: TBoldRoleRTInfo; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetBoldSystem: TBoldSystem; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetOwningObject: TBoldObject; {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure Changed(Event: TBoldEvent; const Args: array of const); function GetStreamName: string; virtual; abstract; + function GetFreeStandingClass: TBoldFreeStandingElementClass; virtual; function GetOwningMember: TBoldMember; virtual; abstract; - function LocatorForID(ObjectId: TBoldObjectId): TBoldObjectLocator; + function LocatorForID(ObjectId: TBoldObjectId): TBoldObjectLocator; {$IFDEF BOLD_INLINE}inline;{$ENDIF} function AssertedLocatorForID(ObjectId: TBoldObjectId): TBoldObjectLocator; - procedure PreChange; - function StartModify: Boolean; - class function GetControllerForMember(Member: TBoldMember): TBoldAbstractController; + procedure PreChange; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function StartModify: Boolean; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + class function GetControllerForMember(Member: TBoldMember): TBoldAbstractController; {$IFDEF BOLD_INLINE} inline; {$ENDIF} function NewValueInOptimisticLocking: IBoldValue; procedure DbFetchOwningMember; procedure DbFetchClassForMember(Timestamp: TBoldTimestampType); - procedure EndModify; + procedure EndModify; {$IFDEF BOLD_INLINE}inline;{$ENDIF} public function AssertIntegrity: Boolean; virtual; procedure Unlink(OldLocator: TBoldObjectLocator; Mode: TBoldLinkUnlinkMode); virtual; @@ -950,13 +1165,15 @@ TBoldAbstractController = class(TBoldMemoryManagedObject) function ProxyInterface(const IId: TGUID; Mode: TBoldDomainElementProxyMode; out Obj): Boolean; virtual; property StreamName: String read GetStreamName; property OwningMember: TBoldMember read GetOwningMember; + property OwningObject: TBoldObject read GetOwningObject; + property RoleRTInfo: TBoldRoleRTInfo read GetRoleRTInfo; + property BoldSystem: TBoldSystem read GetBoldSystem; end; {---TBoldListController---} TBoldListController = class(TBoldAbstractController) private fOwningList: TBoldList; - function GetBoldSystem: TBoldSystem; protected function GetOwningMember: TBoldMember; override; property OwningList: TBoldList read fOwningList; @@ -964,8 +1181,10 @@ TBoldListController = class(TBoldAbstractController) function GetCanCreateNew: Boolean; virtual; function CreateNew: TBoldElement; virtual; function GetStringrepresentation: String; virtual; + function GetCapacity: integer; virtual; + procedure SetCapacity(const Value: integer); virtual; public - constructor Create(OwningList: TBoldList); + constructor Create(OwningList: TBoldList); virtual; procedure AddElement(Element: TBoldElement); virtual; abstract; function GetElement(index: Integer): TBoldElement; virtual; abstract; function IncludesElement(Item: TBoldElement): Boolean; virtual; abstract; @@ -974,18 +1193,19 @@ TBoldListController = class(TBoldAbstractController) procedure Move(CurrentIndex: Integer; NewIndex: Integer); virtual; abstract; procedure RemoveByIndex(index: Integer); virtual; abstract; procedure SetElement(index: Integer; Value: TBoldElement); virtual; abstract; - property BoldSystem: TBoldSystem read GetBoldSystem; property CanCreateNew: Boolean read GetCanCreateNew; property Count: integer read GetCount; + property Capacity: integer read GetCapacity write SetCapacity; end; {---TBoldAbstractObjectListController---} TBoldAbstractObjectListController = class(TBoldListController) private protected - function GetObjectList: TBoldObjectList; + function GetDebugInfo: string; override; + function GetObjectList: TBoldObjectList; {$IFDEF BOLD_INLINE}inline;{$ENDIF} property OwningObjectList: TBoldObjectList read GetObjectList; - function ProxyClass: TBoldMember_ProxyClass; virtual; abstract; + function GetProxy(Member: TBoldMember; Mode: TBoldDomainElementProxyMode): TBoldMember_Proxy; virtual; abstract; procedure PrepareClear; virtual; public procedure AddElement(Element: TBoldElement); override; @@ -1019,7 +1239,7 @@ TBoldAbstractObjectReferenceController = class(TBoldAbstractController) function OtherEndControllerForLinkObject(Obj: TBoldObject): TBoldAbstractObjectReferenceController; function ControllerForLinkRole: TBoldAbstractObjectReferenceController; function ControllerForMainRole: TBoldAbstractObjectReferenceController; - function ProxyClass: TBoldMember_ProxyClass; virtual; abstract; + function GetProxy(Member: TBoldMember; Mode: TBoldDomainElementProxyMode): TBoldMember_Proxy; virtual; abstract; public constructor Create(Owner: TBoldObjectReference); virtual; function GetLocator: TBoldObjectLocator; virtual; abstract; @@ -1036,11 +1256,12 @@ TBoldObjectReferenceController = class(TBoldAbstractObjectReferenceController) procedure ObjectChangeReceive(Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent); protected function GetStreamName: string; override; - function ProxyClass: TBoldMember_ProxyClass; override; + function GetFreeStandingClass: TBoldFreeStandingElementClass; override; + function GetProxy(Member: TBoldMember; Mode: TBoldDomainElementProxyMode): TBoldMember_Proxy; override; public constructor Create(Owner: TBoldObjectReference); override; destructor Destroy; override; - procedure AssignContentValue(Source: IBoldValue); + procedure AssignContentValue(const Source: IBoldValue); function GetLocator: TBoldObjectLocator; override; procedure SetLocator(NewLocator: TBoldObjectLocator); override; procedure MakeDbCurrent; override; @@ -1079,126 +1300,315 @@ TBoldLocatorHashIndex = class(TBoldHashIndex) {$ENDIF} + + TBoldMemberDeriver = class({$IFDEF LightMemberDeriver}TBoldAbstractDeriver{$ELSE}TBoldEventPluggedDeriver{$ENDIF}) + strict private + fDerivedMember: TBoldMember; + strict protected + procedure SetInternalDeriverState(const Value: TBoldDeriverState); override; + function GetInternalDeriverState: TBoldDeriverState; override; + procedure DoNotifyOutOfDate; override; + function GetDerivedObject: TObject; override; + procedure DoDeriveAndSubscribe(subscribe: Boolean); override; + procedure DoReverseDerive; override; + function GetCanReverseDerive: Boolean; override; + public + constructor Create(Member: TBoldMember); + destructor Destroy; override; + property DerivedMember: TBoldMember read fDerivedMember; + property CanReverseDerive: Boolean read GetCanReverseDerive; + end; + + IBoldSystemObjectContents = interface + ['{FB4110D9-C06D-4E92-B6A9-242D8836BC79}'] + function EnsureMemberAndGetValueByIndex(Member: TBoldMember): IBoldValue; + end; + + TBoldSystemFreeStandingObjectContents = class(TBoldFreeStandingObjectContents, IBoldSystemObjectContents) + function EnsureMemberAndGetValueByIndex(Member: TBoldMember): IBoldValue; + end; + function GetBoldLastFailureReason: TBoldFailureReason; procedure SetBoldLastFailureReason(const Value: TBoldFailureReason); -procedure BoldRaiseLastFailure(originator: TBoldDomainElement; const MethodName: String; const DefaultMessage: String); -procedure BoldClearLastFailure; +procedure BoldRaiseLastFailure(originator: TBoldElement; const MethodName: String; const DefaultMessage: String); +procedure BoldClearLastFailure; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + +//PATCH +function GetTransactionInfo(aSystem: TBoldSystem): string; + +function BoldSystemCount: integer; +function BoldSystems(Index: integer): TBoldSystem; + +function TopSortedIndex2ClassName(ATopSortedIndex: integer): string; +function VerifyLocatorType(ALocator: TBoldObjectLocator; AExpectedClassType: TBoldClassTypeInfo; ARaise: boolean = true): Boolean; + +var + G_LastFailureReason: TBoldFailureReason = nil; implementation uses SysUtils, - BoldMemoryManager, + Variants, + Windows, BoldLogHandler, BoldGuard, BoldLinks, BoldObjectListControllers, BoldOcl, Typinfo, - BoldOptimisticLockingSupport, // could be avoided with factory - BoldSystemPersistenceHandler, // could be avoided with factory - BoldSystemOldValueHandler, // could be avoided with factory, will need mechanism for selectiing several + BoldOptimisticLockingSupport, + BoldSystemPersistenceHandler, + BoldSystemOldValueHandler, BoldExternalizedReferences, BoldDefaultId, BoldTaggedValueSupport, BoldUndoHandler, - BoldDefaultStreamNames, - BoldCoreConsts; +{$IFDEF SpanFetch} + AttracsSpanFetchManager, +{$ENDIF} + BoldDefaultStreamNames, + BoldAttributes, + BoldFreeStandingValueFactories, + BoldMath; var - G_ExternalDerivers: TBoldExternalizedReferenceList; - G_LastFailureReason: TBoldFailureReason = nil; G_DefaultBoldSystem: TBoldSystem = nil; - IX_BoldObjectId: integer = -1; + _BoldSystemList: TList; + +procedure BoldSystemActivated(ABoldSystem: TBoldSystem); +begin + if not Assigned(_BoldSystemList) then + _BoldSystemList := TList.Create; + _BoldSystemList.Add(ABoldSystem); +end; + +procedure BoldSystemDeActivated(ABoldSystem: TBoldSystem); +begin + if Assigned(_BoldSystemList) then + _BoldSystemList.Remove(ABoldSystem); +end; + +function BoldSystems(Index: integer): TBoldSystem; +begin + if (Index < 0) or (Index > BoldSystemCount-1) then + raise EBold.Create('Index out of bounds in function BoldSystems(Index: integer): TBoldSystem;'); + result := TBoldSystem(_BoldSystemList[Index]); +end; + +function BoldSystemCount: integer; +begin + if Assigned(_BoldSystemList) then + result := _BoldSystemList.Count + else + result := 0; +end; -// Utility functions -// If object exists, just return it, otherwise create it and set existance and persistencestate. +var + _BoldSystemInternalLog: TStringList; -function EnsureObjectInFsValueSpace(BoldObject: TBoldObject; ValueSpace: TBoldFreeStandingValueSpace): TBoldFreeStandingObjectContents; +procedure _BoldInternalLog(const AMessage: string); var - ObjectId: TBoldObjectId; + i: integer; +begin + if not Assigned(_BoldSystemInternalLog) then + begin + _BoldSystemInternalLog := TStringList.Create; + _BoldSystemInternalLog.Sorted := true; + _BoldSystemInternalLog.Duplicates := dupIgnore; + end; + i := _BoldSystemInternalLog.Count; + _BoldSystemInternalLog.Add(AMessage); + if _BoldSystemInternalLog.Count > i then + BoldLog.Log(AMessage); +end; + +procedure LogDerivationSideEffects(BoldMember: TBoldMember); +var + vBoldSystem: TBoldSystem; + vMessage: string; +begin + vBoldSystem := BoldMember.BoldSystem; + Assert(Assigned(vBoldSystem)); + Assert(vBoldSystem.CurrentDerivedMember <> nil); + if vBoldSystem.CurrentDerivedMember.GetBoldMemberRTInfo.IsReverseDerived then + vMessage := Format('Reverse Derivation side effects detected, derived member: %s. Dirty member: %s.', [vBoldSystem.CurrentDerivedMember.BoldMemberRTInfo.ExpressionName, BoldMember.BoldMemberRTInfo.ExpressionName]) + else + vMessage := Format('Derivation side effects detected, derived member: %s. Dirty member: %s.', [vBoldSystem.CurrentDerivedMember.BoldMemberRTInfo.ExpressionName, BoldMember.BoldMemberRTInfo.ExpressionName]); + _BoldInternalLog(vMessage); +end; + +procedure LogDerivationDeleteSideEffects(BoldObject: TBoldObject); +var + vBoldSystem: TBoldSystem; + vMessage: string; +begin + vBoldSystem := BoldObject.BoldSystem; + Assert(Assigned(vBoldSystem)); + Assert(vBoldSystem.CurrentDerivedMember <> nil); + if vBoldSystem.CurrentDerivedMember.GetBoldMemberRTInfo.IsReverseDerived then + vMessage := Format('Reverse Derivation side effects detected, derived member: %s. Deleted object: %s.', [vBoldSystem.CurrentDerivedMember.BoldMemberRTInfo.ExpressionName, BoldObject.BoldClassTypeInfo.AsString]) + else + vMessage := Format('Derivation side effects detected, derived member: %s. Deleted object: %s.', [vBoldSystem.CurrentDerivedMember.BoldMemberRTInfo.ExpressionName, BoldObject.BoldClassTypeInfo.AsString ]); + _BoldInternalLog(vMessage); +end; + +procedure LogDerivationCreateSideEffects(BoldObject: TBoldObject); +var + vBoldSystem: TBoldSystem; + vMessage: string; +begin + vBoldSystem := BoldObject.BoldSystem; + Assert(Assigned(vBoldSystem)); + Assert(vBoldSystem.CurrentDerivedMember <> nil); + if vBoldSystem.CurrentDerivedMember.GetBoldMemberRTInfo.IsReverseDerived then + vMessage := Format('Reverse Derivation side effects detected, derived member: %s. Created object: %s.', [vBoldSystem.CurrentDerivedMember.BoldMemberRTInfo.ExpressionName, BoldObject.BoldClassTypeInfo.AsString]) + else + vMessage := Format('Derivation side effects detected, derived member: %s. Created object: %s.', [vBoldSystem.CurrentDerivedMember.BoldMemberRTInfo.ExpressionName, BoldObject.BoldClassTypeInfo.AsString]); + _BoldInternalLog(vMessage); +end; + +function MemberCanBeModified(MemberRtInfo: TBoldMemberRtInfo; BoldSystem: TBoldSystem): Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} +begin + Result := assigned(MemberRtInfo) and + (MemberRtInfo.IsStoredInObject or + (MemberRtInfo.IsMultiRole and + (assigned(BoldSystem.PersistenceController) and + BoldSystem.PersistenceController.MultilinksAreStoredInObject))); +end; + +//PATCH +function GetTransactionInfo(aSystem: TBoldSystem): string; +begin + Result := 'GetTransactionInfo raised exception'; + try + Result := Format('TransactionNesting:%d TransactionRollbackOnly:%s TransactionMode:%d', + [aSystem.fTransactionNesting, + BoolToStr(aSystem.fTransactionRollbackOnly, True), + Ord(aSystem.fTransactionMode)]); + Result := Result + Format(' TransactionList.Count:%d', [aSystem.fTransactionList.Count]); + except + {Eat} + end; +end; +//PATCH + +function TopSortedIndex2ClassName(ATopSortedIndex: integer): string; +begin + result := TBoldSystem.DefaultSystem.BoldSystemTypeInfo.TopSortedClasses[ATopSortedIndex].ExpressionName; +end; + +function TBoldObject.GetBoldExistenceState: TBoldExistenceState; +begin + result := TBoldExistenceState(GetInternalState(BoldExistenceStateMask, BoldESShift)); +end; + +function TBoldObject.GetBoldPersistenceState: TBoldValuePersistenceState; +begin + result := TBoldValuePersistenceState(GetInternalState(BoldPersistenceStateMask, BoldPSShift)); +end; + +function TBoldSystem.GetUndoHandler: TBoldAbstractUndoHandler; +begin + if not Assigned(fUndoHandler) then + fUndoHandler := TBoldUndoHandler.Create(self); + Result := fUndoHandler; +end; + +function TBoldSystem.GetUndoHandlerInterface: IBoldUndoHandler; begin - Assert(assigned(ValueSpace)); - ObjectId := BoldObject.BoldObjectLocator.BoldObjectID; - Result := ValueSpace.GetFSObjectContentsByObjectId(ObjectID); - if not assigned(Result) then + Result := UndoHandler as IBoldUndoHandler; +end; + +function EnsureObjectInFsValueSpace(BoldObject: TBoldObject; ValueSpace: TBoldFreeStandingValueSpace; out ACreated: boolean): TBoldFreeStandingObjectContents; overload; +begin + Assert(Assigned(ValueSpace)); + result := ValueSpace.GetEnsuredFSObjectContentsByObjectId(BoldObject.BoldObjectLocator.BoldObjectId, ACreated); + if ACreated then begin - Result := ValueSpace.GetEnsuredFSObjectContentsByObjectId(ObjectId); - Result.BoldExistenceState := BoldObject.BoldExistenceState; - Result.BoldPersistenceState := BoldObject.BoldPersistenceState; + result.BoldExistenceState := BoldObject.BoldExistenceState; + result.BoldPersistenceState := BoldObject.BoldPersistenceState; + result.TimeStamp := BoldObject.GetTimeStamp; end; end; +function EnsureObjectInFsValueSpace(BoldObject: TBoldObject; ValueSpace: TBoldFreeStandingValueSpace): TBoldFreeStandingObjectContents; overload; +var + lCreated: boolean; +begin + result := EnsureObjectInFsValueSpace(BoldObject, ValueSpace, lCreated); +end; + + type + {---TBoldLocatorIdHashIndex---} TBoldLocatorIdHashIndex = class(TBoldHashIndex) protected - function ItemAsLocator(Item: TObject): TBoldObjectLocator; virtual; + function ItemAsLocator(Item: TObject): TBoldObjectLocator; {$IFDEF BOLD_INLINE} inline; {$ENDIF} {virtual;} // no need to be virtual until we actually override it somewhere function HashItem(Item: TObject): Cardinal; override; function Match(const Key; Item:TObject):Boolean; override; function Hash(const Key): Cardinal; override; public - function FindLocatorById(BoldObjectId: TBoldObjectId): TBoldObjectLocator; + function FindLocatorById(BoldObjectId: TBoldObjectId): TBoldObjectLocator; {$IFDEF BOLD_INLINE} inline; {$ENDIF} end; { TBoldSystem_Proxy } TBoldSystem_Proxy = class(TBoldDomainElement_Proxy, IBoldValueSpace) private - function GetProxedSystem: TBoldSystem; - // IBoldValueSpace + fProxedSystem: TBoldSystem; procedure AllObjectIds(resultList: TBoldObjectIdList; OnlyLoaded: Boolean); procedure ApplytranslationList(IdTranslationList: TBoldIdTranslationList); - procedure ApplyValueSpace(ValueSpace: IBoldValueSpace; IgnorePersistenceState: Boolean); + procedure ApplyValueSpace(const ValueSpace: IBoldValueSpace; IgnorePersistenceState: Boolean); procedure EnsureObjectContents(ObjectId: TBoldObjectId); procedure EnsureObjectId(ObjectId: TBoldObjectId); procedure ExactifyIDs(TranslationList: TBoldIdTranslationList); function GetHasContentsForId(ObjectId: TBoldObjectId): boolean; function GetObjectContentsByObjectId(ObjectId: TBoldObjectId): IBoldObjectContents; function GetEnsuredObjectContentsByObjectId(ObjectId: TBoldObjectId): IBoldObjectContents; + function GetEnsuredObjectContentsByObjectIdAndCheckIfCreated(ObjectId: TBoldObjectId; out aBoldObjectContents: IBoldObjectContents): boolean; + function IdCount: integer; + function IsEmpty: boolean; protected - property ProxedSystem: TBoldSystem read GetProxedSystem; + property ProxedSystem: TBoldSystem read fProxedSystem; + public + constructor Create(ProxedSystem: TBoldSystem; Mode: TBoldDomainElementProxyMode); end; { TBoldObject_Proxy } TBoldObject_Proxy = class(TBoldDomainElement_Proxy, IBoldObjectContents) private - function GetProxedObject: TBoldObject; - // IBoldObjectContents + fProxedObject: TBoldObject; procedure EnsureMember(MemberId: TBoldMemberId; const ContentName: string); - function GetBoldExistenceState: TBoldExistenceState; - function GetBoldMemberCount: Integer; - function GetBoldPersistenceState: TBoldValuePersistenceState; - function GetGlobalId: string; - function GetIsModified: Boolean; - function GetIsReadOnly: Boolean; - function GetObjectId: TBoldObjectId; + function EnsureMemberAndGetValueByIndex(MemberIndex: Integer; const ContentName: string): IBoldValue; + function GetBoldExistenceState: TBoldExistenceState; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function GetBoldMemberCount: Integer; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function GetBoldPersistenceState: TBoldValuePersistenceState; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function GetGlobalId: string; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function GetIsModified: Boolean; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function GetIsReadOnly: Boolean; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function GetObjectId: TBoldObjectId; {$IFDEF BOLD_INLINE}inline;{$ENDIF} function GetValueByIndex(I: Integer): IBoldValue; - function GetValueByMemberId(MemberId: TBoldMemberID):IBoldValue; - function GetTimeStamp: TBoldTimeStampType; - procedure SetBoldExistenceState(Value: TBoldExistenceState); - procedure SetBoldPersistenceState(Value: TBoldValuePersistenceState); - procedure SetGlobalId(const NewValue: string); - procedure SetIsReadOnly(NewValue: Boolean); - procedure SetTimeStamp(NewValue: TBoldTimeStampType); + function GetValueByMemberId(MemberId: TBoldMemberID):IBoldValue; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function GetTimeStamp: TBoldTimeStampType; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + procedure SetBoldExistenceState(Value: TBoldExistenceState); {$IFDEF BOLD_INLINE}inline;{$ENDIF} + procedure SetBoldPersistenceState(Value: TBoldValuePersistenceState); {$IFDEF BOLD_INLINE}inline;{$ENDIF} + procedure SetGlobalId(const NewValue: string); {$IFDEF BOLD_INLINE}inline;{$ENDIF} + procedure SetIsReadOnly(NewValue: Boolean); {$IFDEF BOLD_INLINE}inline;{$ENDIF} + procedure SetTimeStamp(NewValue: TBoldTimeStampType); {$IFDEF BOLD_INLINE}inline;{$ENDIF} protected - property ProxedObject: TBoldObject read GetProxedObject; + constructor Create(ProxedObject: TBoldObject; Mode: TBoldDomainElementProxyMode); + property ProxedObject: TBoldObject read fProxedObject; end; { TBoldObjectReference_Proxy } TBoldObjectReference_Proxy = class(TBoldMember_Proxy) protected - procedure AssignContentValue(Source: IBoldValue); override; - end; - - TBoldMemberDeriver = class(TBoldEventPluggedDeriver) - protected - procedure SetInternalDeriverState(const Value: TBoldDeriverState); override; - function GetInternalDeriverState: TBoldDeriverState; override; + procedure AssignContentValue(const Source: IBoldValue); override; end; -// Utility functions -function GetValueFromValuespace(ValueSpace: IBoldValueSpace; Id: TBoldObjectId; MemberIndex: integer): IBoldValue; +function GetValueFromValuespace(const ValueSpace: IBoldValueSpace; Id: TBoldObjectId; MemberIndex: integer): IBoldValue; var MemberId: TBoldMemberId; ObjectContents: IBoldObjectContents; @@ -1224,7 +1634,7 @@ procedure SetBoldLastFailureReason(const Value: TBoldFailureReason); G_LastFailureReason := value; end; -procedure BoldRaiseLastFailure(originator: TBoldDomainElement; const MethodName: String; const DefaultMessage: String); +procedure BoldRaiseLastFailure(originator: TBoldElement; const MethodName: String; const DefaultMessage: String); var OriginatorStr: String; MessageStr: String; @@ -1247,10 +1657,10 @@ procedure BoldRaiseLastFailure(originator: TBoldDomainElement; const MethodName: if MessageStr = '' then MessageStr := DefaultMessage; if MessageStr = '' then - MessageStr := sReasonUnknown; + MessageStr := 'Reason unknown'; if MessageFormatStr = '' then - MessageFormatStr := sFailureMessage; + MessageFormatStr := '%s.%s failed: %s'; if Assigned(G_LastFailureReason) then Failure := G_LastFailureReason.GetException(Format(MessageFormatStr, [OriginatorStr, MethodName, MessageStr])) @@ -1295,13 +1705,34 @@ function TBoldLocatorIdHashIndex.FindLocatorById(boldObjectId:TboldObjectId): TB Result := TBoldObjectLocator(Find(boldObjectId)); end; + constructor TBoldSystemLocatorList.Create; begin inherited; SetIndexCapacity(1); + IX_BoldObjectId := -1; SetIndexVariable(IX_BoldObjectId, AddIndex(TBoldLocatorIdHashIndex.Create)); end; +{$IFDEF ATINDEXDEBUG} +//PATCH +function TBoldSystemLocatorList.GetDebugInfo: string; +begin + Result := 'TBoldSystemLocatorList.Count:'+IntToStr(Count)+#13#10+ + (Indexes[0] as TBoldLocatorIdHashIndex).GetDebugInfo; +end; +{$ENDIF} + +function TBoldSystemLocatorList.GetEnumerator: TBoldLocatorListTraverser; +begin + result := CreateTraverser; +end; + +function TBoldSystemLocatorList.GetLocatorByID(ObjectID: TBoldObjectId): TBoldObjectLocator; +begin + Result := TBoldObjectLocator(TBoldHashIndex(Indexes[IX_BoldObjectId]).Find(ObjectID)); +end; + function TBoldSystemLocatorList.GetObjectByID(ObjectID: TBoldObjectId): TBoldObject; var Locator: TBoldObjectLocator; @@ -1313,9 +1744,31 @@ function TBoldSystemLocatorList.GetObjectByID(ObjectID: TBoldObjectId): TBoldObj Result := nil; end; -function TBoldSystemLocatorList.GetLocatorByID(ObjectID: TBoldObjectId): TBoldObjectLocator; +function TBoldSystemLocatorList.GetObjectByIDString( + const ID: string): TBoldObject; +var + ObjectID: TBoldDefaultID; +begin + ObjectId := TBoldDefaultID.CreateWithClassID(0, false); + try + ObjectId.AsInteger := StrToInt(Id); + result := GetObjectByID(ObjectId); + finally + ObjectID.free; + end; +end; + +function TBoldSystemLocatorList.GetLocatorByIDString(const ID: string): TBoldObjectLocator; +var + ObjectID: TBoldDefaultID; begin - Result := TBoldLocatorIdHashIndex(Indexes[IX_BoldObjectId]).FindLocatorById(ObjectID); + ObjectId := TBoldDefaultID.CreateWithClassID(0, false); + try + ObjectId.AsInteger := StrToInt(Id); + result := GetLocatorByID(ObjectId); + finally + ObjectID.free; + end; end; function TBoldSystem.GetEnsuredLocatorByID(ObjectID: TBoldObjectId): TBoldObjectLocator; @@ -1327,12 +1780,20 @@ function TBoldSystem.GetEnsuredLocatorByID(ObjectID: TBoldObjectId): TBoldObject end; end; +function TBoldSystem.EnsureLocatorByID(ObjectID: TBoldObjectId; out ACreated: boolean): TBoldObjectLocator; +begin + Result := Locators.GetLocatorByID(ObjectID); + ACreated := not Assigned(Result); + if ACreated then + Result := TBoldObjectLocator.CreateWithObjectId(Self, ObjectID) +end; + constructor TBoldObjectLocator.CreateWithObjectId(BoldSystem: TBoldSystem; BoldObjectID: TBoldObjectId); begin inherited Create; fBoldSystem := BoldSystem; fBoldObjectID := BoldObjectId.Clone; - BoldSystem.Locators.Add(Self); + AddToLocators; end; constructor TBoldObjectLocator.CreateWithClassID(BoldSystem: TBoldSystem; TopSortedIndex: integer; Exact: Boolean); @@ -1340,7 +1801,7 @@ constructor TBoldObjectLocator.CreateWithClassID(BoldSystem: TBoldSystem; TopSor inherited Create; FBoldSystem := BoldSystem; fBoldObjectID := TBoldInternalObjectId.CreateWithClassID(TopSortedIndex, Exact); - BoldSystem.Locators.Add(Self); + AddToLocators; end; function TBoldObjectLocator.GetAsString: string; @@ -1348,12 +1809,21 @@ function TBoldObjectLocator.GetAsString: string; Result := fBoldObjectID.AsString; end; +function TBoldObjectLocator.GetDebugInfo: string; +begin + if Assigned(FBoldObject) then + result := FBoldObject.DebugInfo + else + result := AsString; +end; + destructor TBoldObjectLocator.Destroy; begin if Assigned(FBoldObject) then - raise EBoldInternal.CreateFmt(sBoldObjectAssigned, [ClassName]); + raise EBoldInternal.CreateFmt('%s.Destroy: BoldObject assigned', [ClassName]); + if not BoldSystem.IsDestroying then + BoldSystem.Locators.RemoveFromAllIndexes(Self); FreeAndNil(fBoldObjectID); - FreeAndNil(fEmbeddedSingleLinks); inherited; end; @@ -1369,39 +1839,53 @@ procedure TBoldObjectLocator.UnloadBoldObject; begin BoldClearLastFailure; if not BoldObject.CanUnload then - BoldRaiseLastFailure(nil, 'TBoldObjectLocator.UnloadBoldObject', ''); // do not localize + BoldRaiseLastFailure(nil, 'TBoldObjectLocator.UnloadBoldObject', ''); + if not BoldSystem.isDestroying then + BoldObject.SendEvent(beObjectUnloaded); BoldSystem.MarkObjectClean(BoldObject); BoldObject.FreePublisher; BoldObject.FBoldObjectLocator := nil; - EmbeddedSingleLinksFromObject; - FreeEmbeddedSingleLinksOfOtherEnd; + if not BoldSystem.isDestroying then + begin + EmbeddedSingleLinksFromObject; + FreeEmbeddedSingleLinksOfOtherEnd; + end; FreeAndNil(fBoldObject); end; end; -procedure TBoldObjectLocator.DiscardBoldObject; +procedure TBoldObjectLocator.DiscardBoldObject(ADiscardTransientLinks: boolean = true); begin if Assigned(BoldObject) then - BoldObject.Discard; + begin + if ADiscardTransientLinks then + BoldObject.Discard + else + BoldObject.DiscardPersistentMembers; + end; end; procedure TBoldObjectLocator.FetchBoldObject; begin - if BoldObjectID.IsStorable then - BoldSystem.fSystemPersistenceHandler.FetchObjectById(BoldObjectID) - else - raise EBoldInternal.CreateFmt('%s.FetchBoldObject: Can''t fetch Internal object', [Classname]); + if not BoldObjectID.NonExisting then + begin + if not BoldObjectID.IsStorable then + raise EBoldInternal.CreateFmt('%s.FetchBoldObject: Can''t fetch Internal object', [Classname]); + BoldSystem.fSystemPersistenceHandler.FetchObjectById(BoldObjectID); + end; end; function TBoldObjectLocator.GetEnsuredBoldObject: TBoldObject; begin - if not assigned(self) then - result := nil - else + if Assigned(Self) then begin EnsureBoldObject; - result := BoldObject; + Result := BoldObject; + end + else + begin + Result := nil end; end; @@ -1411,14 +1895,12 @@ function TBoldObjectLocator.Hash: Cardinal; end; { TBoldSystem } -constructor TBoldSystem.Create(AOwningElement: TBoldDomainElement); -begin - raise EBold.CreateFmt(sIllegalConstruction, [ClassName]); -end; function TBoldSystem.GetAsIBoldvalueSpace(Mode: TBoldDomainElementProxyMode): IBoldvalueSpace; begin - ProxyInterface(IBoldValueSpace, Mode, result); + if not Assigned(fSystemProxyCache[Mode]) then + ProxyInterface(IBoldValueSpace, Mode, fSystemProxyCache[Mode]); + result := fSystemProxyCache[Mode]; end; constructor TBoldSystem.CreateWithTypeInfo(AOwningElement: TBoldDomainElement; SystemTypeInfo: TBoldSystemTypeInfo; PersistenceController: TBoldPersistenceController; RegionFactory: TBoldAbstractRegionFactory = nil); @@ -1426,36 +1908,106 @@ constructor TBoldSystem.CreateWithTypeInfo(AOwningElement: TBoldDomainElement; S I: Integer; ListTypeInfo: TBoldListTypeInfo; ListClass: TBoldObjectListClass; + +{$IFDEF ACCESSSTATISTICS} //// START PATCH ACCESSSTATISTICS //////////////////// + procedure InitAccessStats; + var + I: Integer; + ClassTypeInfo: TBoldClassTypeInfo; + begin + SetLength(fAccessStats, SystemTypeInfo.TopSortedClasses.Count); + SetLength(fDeriveStats, SystemTypeInfo.TopSortedClasses.Count); + SetLength(fInvalidateStats, SystemTypeInfo.TopSortedClasses.Count); + SetLength(fModifyStats, SystemTypeInfo.TopSortedClasses.Count); + for I := 0 to SystemTypeInfo.TopSortedClasses.Count-1 do + begin + ClassTypeInfo := SystemTypeInfo.TopSortedClasses[I]; + SetLength(fAccessStats[I], ClassTypeInfo.AllMembersCount); + SetLength(fDeriveStats[I], ClassTypeInfo.AllMembersCount); + SetLength(fInvalidateStats[I], ClassTypeInfo.AllMembersCount); + SetLength(fModifyStats[I], ClassTypeInfo.AllMembersCount); + end; + end; +{$ENDIF} //// END PATCH ACCESSSTATISTICS /////////////////////////////////////// + begin - inherited Create(AOwningElement); + inherited CreateWithOwner(AOwningElement); fTransactionMode := stmNormal; fOldValueHandler := TBoldOldValueHandler.Create(Self); fBoldSystemTypeInfo := SystemTypeInfo; SetElementFlag(befpersistent, SystemTypeInfo.Persistent and assigned(PersistenceController)); + Assert((PersistenceController = nil) or (PersistenceController is TBoldPersistenceController)); fPersistenceController := PersistenceController; + fPersistenceControllerSubscriber := TBoldPassthroughSubscriber.Create(ReceiveFromPersistenceController); + if Assigned(fPersistenceController) then + begin + fPersistenceController.AddSmallSubscription(fPersistenceControllerSubscriber, [beDestroying], beDestroying); +// fPersistenceController.SubscribeToPeristenceEvents(fPersistenceControllerSubscriber); + fPersistenceController.AddSubscription(fPersistenceControllerSubscriber, bpeStartFetch, bpeStartFetch); + fPersistenceController.AddSubscription(fPersistenceControllerSubscriber, bpeEndFetch, bpeEndFetch); + end; fDirtyObjects := TList.Create; - fDirtyObjectsInvalid := False; + DirtyObjectsInvalid := False; fClasses := TBoldMemberList.Create; fClasses.fBoldMetaType := BoldSystemTypeInfo.ListTypeInfoByElement[nil]; fLocators := TBoldSystemLocatorList.Create; fLocators.OwnsEntries := True; fDelayedDestructionList := TList.Create; fTransactionList := TBoldDomainElementCollection.Create; - + fDerivedMembers := TList.Create; +{$IFNDEF NoAutoSubscription} + fMembersReadDuringDerivation := TList.Create; +{$ENDIF} for I := 0 to SystemTypeInfo.TopSortedClasses.Count - 1 do begin - ListTypeInfo := SystemTypeInfo.ListTypeInfoByElement[SystemTypeInfo.TopSortedClasses[i]]; + ListTypeInfo := SystemTypeInfo.TopSortedClasses[i].ListTypeInfo; ListClass := TBoldObjectListClass(ListTypeInfo.ListClass); fClasses.InternalAddWithoutCloning(ListClass.InternalCreateClassList(self, ListTypeInfo)); end; - fClasses.MakeImmutable; fOptimisticLockHandler := TBoldOptimisticLockHandler.Create(self); fSystemPersistenceHandler := TBoldSystemPersistenceHandler.Create(self); fRegionFactory := RegionFactory; - if assigned(fRegionFactory) then fRegionFactory.fSystem := Self; + fRollbackArea := TBoldFreeStandingValueSpace.create; + fValidValueArea := TBoldFreeStandingValueSpace.create; + + +{$IFDEF ACCESSSTATISTICS} //// START PATCH ACCESSSTATISTICS //////////////////// + InitAccessStats; +{$ENDIF} //// END PATCH ACCESSSTATISTICS /////////////////////////////////////// + BoldSystemActivated(self); +end; + +function TBoldSystem.IsDerivingMembers: boolean; +begin + result := fDerivedMembers.Count > 0; +end; + +function TBoldSystem.CurrentDerivedMember: TBoldMember; +begin + if IsDerivingMembers then + result := fDerivedMembers[fDerivedMembers.count-1] + else + result := nil; +end; + +function TBoldMember.GetPSStateIsInvalid: Boolean; +begin + result := (StateAndFlagBank and BoldPersistenceStateMask) = (Cardinal(bvpsInvalid) shl BoldPSShift); +end; + +function TBoldObject.GetBoldMemberCount: Integer; +begin + Result := BoldClassTypeInfo.AllMembersCount; +end; + +function TBoldObject.GetBoldMemberAssigned(Index: integer): Boolean; +begin + if Cardinal(index) >= Cardinal(Length(fMemberArray)) then + raise EBold.CreateFmt('%s.GetBoldMemberAssigned: Index out of range (%d but max is %d)', [ClassName, Index, BoldMemberCount-1]); + result := assigned(fMemberArray[Index]); end; destructor TBoldSystem.Destroy; @@ -1463,48 +2015,50 @@ destructor TBoldSystem.Destroy; Traverser: TBoldLocatorListTraverser; i: integer; bo: TBoldObject; + bm: TBoldMember; + Locator: TBoldObjectLocator; begin + // CheckIntegrity; EnsureCanDestroy; + IsDestroying := True; PrepareToDestroy; IsDefault := False; FreeAndNil(fEvaluator); - FreeAndNil(fClasses); // will destroy classes + FreeAndNil(fClasses); + + for i := 0 to length(fSystemProxyCache) -1 do + fSystemProxyCache[TBoldDomainElementProxyMode(i)] := nil; - // discard all derived members first Traverser := Locators.CreateTraverser; - while not Traverser.EndOfList do + while Traverser.MoveNext do begin if assigned(Traverser.Locator.BoldObject) then begin bo := Traverser.Locator.BoldObject; for i := 0 to bo.BoldMemberCount - 1 do begin - if bo.BoldMemberAssigned[i] and bo.BoldMembers[i].Derived then + if bo.BoldMemberAssigned[i] then begin - if (bo.BoldMembers[i].BoldPersistenceState <> bvpsInvalid) then + bm := bo.BoldMembers[i]; + if bm.Derived and (not bm.BoldPersistenceStateIsInvalid) then begin - bo.BoldMembers[i].Invalidate; - bo.BoldMembers[i].Deriver.MarkSubscriptionOutOfDate; + bm.Invalidate; + bo.GetBoldMemberDeriver(bm).MarkSubscriptionOutOfDate; end; end; end; end; - Traverser.Next; end; Traverser.Free; if Assigned(fLocators) then - begin - Traverser := Locators.CreateTraverser; - while not Traverser.EndOfList do - begin - if assigned(Traverser.Locator.BoldObject) then - Traverser.Locator.UnloadBoldObject; - Traverser.Next; - end; - Traverser.Free; - end; + for Locator in fLocators do + if assigned(Locator.BoldObject) then + Locator.UnloadBoldObject; + FreeAndNil(fRollbackArea); + FreeAndNil(fValidValueArea); + FreeAndNil(fPersistenceControllerSubscriber); FreeAndNil(fLocators); FreeAndNil(fDirtyObjects); FreeAndNil(fDelayedDestructionList); @@ -1513,6 +2067,11 @@ destructor TBoldSystem.Destroy; FreeAndNil(fOptimisticLockHandler); FreeAndNil(fSystemPersistenceHandler); FreeAndNil(fUndoHandler); + FreeAndNil(fDerivedMembers); +{$IFNDEF NoAutoSubscription} + FreeAndNil(fMembersReadDuringDerivation); +{$ENDIF} + BoldSystemDeActivated(self); inherited Destroy; end; @@ -1521,12 +2080,17 @@ class function TBoldSystem.DefaultSystem: TBoldSystem; Result := G_DefaultBoldSystem end; +function TBoldSystem.GetIsFetching: Boolean; +begin + Result := fFetchNesting > 0; +end; + function TBoldSystem.GetClassByIndex(index: Integer): TBoldObjectList; begin if Assigned(fClasses) then begin - Assert(fClasses[index] is TBoldObjectList); Result := TBoldObjectList(fClasses[index]); + Assert(Result is TBoldObjectList); end else Result := nil; @@ -1540,7 +2104,13 @@ function TBoldSystem.CreateNewObjectByExpressionName(const ExpressionName: strin if Assigned(ClassTypeInfo) then Result := TBoldObjectClass(ClassTypeInfo.ObjectClass).InternalCreateNewWithClassAndSystem(ClassTypeInfo, Self, Persistent) else - raise EBold.CreateFmt(sNoSuchClass, [ClassName, 'CreateNewObjectByExpressionName', ExpressionName]); // do not localize + raise EBold.CreateFmt('%s.CreateNewObjectByExpressionName: System contains no class named: %s', [ClassName, ExpressionName]); +end; + +function TBoldSystem.CreateNewObjectFromClassTypeInfo(aClassTypeInfo: TBoldClassTypeInfo; Persistent: Boolean = True): TBoldObject; +begin + Assert(Assigned(aClassTypeInfo), 'aClassTypeInfo param is nil in CreateNewObjectFromClassTypeInfo.'); + Result := TBoldObjectClass(aClassTypeInfo.ObjectClass).InternalCreateNewWithClassAndSystem(aClassTypeInfo, Self, Persistent); end; function TBoldSystem.CreateExistingObjectByID(BoldObjectID: TBoldObjectId): TBoldObject; @@ -1552,7 +2122,7 @@ function TBoldSystem.CreateExistingObjectByID(BoldObjectID: TBoldObjectId): TBol if not BoldObjectID.TopSortedIndexExact then if ClassTypeInfo.IsAbstract or not assigned(OnCreateApproximateObjectError) then - raise EBold.CreateFmt(sCannotCreateInexact, + raise EBold.CreateFmt('Can not create objects with approximate type. ID: %s Class: %s', [BoldObjectId.AsString, ClassTypeInfo.ModelName]); Locator := EnsuredLocatorByID[BoldObjectID]; @@ -1584,12 +2154,23 @@ function TBoldSystem.GetClassByExpressionName(const ExpressionName: string): TBo begin Result := FindClassByExpressionName(ExpressionName); if not Assigned(Result) then - raise EBold.CreateFmt(sNoSuchClass, [ClassName, 'GetClassByExpressionName', ExpressionName]); // FIXME // do not localize + raise EBold.CreateFmt('%s.GetClassByExpressionName: System has no class named: %s', [ClassName, ExpressionName]); end; -procedure TBoldSystem.MarkObjectDirty(BoldObject: TBoldObject); {called by TBoldObject} +function TBoldSystem.GetClassByObjectClass( + AObjectClass: TBoldObjectClass): TBoldObjectList; +var + ClassTypeInfo: TBoldClassTypeInfo; +begin + ClassTypeInfo := BoldSystemTypeInfo.TopSortedClasses.ItemsByObjectClass[AObjectClass]; + if not Assigned(ClassTypeInfo) then + raise EBold.CreateFmt('%s.GetClassByObjectClass: System has no class : %s', [ClassName, AObjectClass.ClassName]); + Result := Classes[ClassTypeInfo.TopSortedIndex]; +end; + +procedure TBoldSystem.MarkObjectDirty(BoldObject: TBoldObject); {called by TBoldObject} begin - if BoldObject.BoldPersistent then + if Self.BoldPersistent and BoldObject.BoldPersistent then begin if Assigned(NewDirtyList) then NewDirtyList.Add(BoldObject); @@ -1600,22 +2181,32 @@ procedure TBoldSystem.MarkObjectDirty(BoldObject: TBoldObject); {called by TBold begin fDirtyObjects.Add(BoldObject); BoldObject.InDirtyList := True; + BoldObject.SendExtendedEvent(beObjectBecomingDirty, [BoldObject]); + if not DirtyObjectsInvalid then + SendExtendedEvent(beDirtyListInvalidOrItemDeleted, [BoldObject]); end; end; end; procedure TBoldSystem.MarkObjectClean(BoldObject: TBoldObject); {called by TBoldObject} +var + i: integer; begin if BoldObject.InDirtyList and BoldObject.BoldPersistent then begin fDirtyObjects.Remove(BoldObject); BoldObject.InDirtyList := False; - if (Assigned(NewDirtyList) and NewDirtyList.Includes(BoldObject)) then - NewDirtyList.Remove(BoldObject); + if Assigned(NewDirtyList) then + begin + i := NewDirtyList.IndexOf(BoldObject); + if i <> -1 then + NewDirtyList.RemoveByIndex(i);// Remove(BoldObject); + end; - if not fDirtyObjectsInvalid then - SendEvent(beDirtyListInvalidOrItemDeleted); + BoldObject.SendExtendedEvent(beObjectBecomingClean, [BoldObject]); + if not DirtyObjectsInvalid then + SendExtendedEvent(beDirtyListInvalidOrItemDeleted, [BoldObject]); end; end; @@ -1631,7 +2222,7 @@ ClassList := classes[ClassTypeInfo.TopSortedIndex]; alist.AddList(ClassList); end else - raise EBold.CreateFmt(sClassDoesNotBelongHere, [className, aClass.ClassName]); + raise EBold.CreateFmt('%s.GetAllInClass: %s does not belong to this system', [className, aClass.ClassName]); end; procedure TBoldSystem.GetAllWithCondition(aList: TBoldObjectList; Condition: TBoldCondition); @@ -1644,59 +2235,155 @@ procedure TBoldSystem.GetAllInClassWithSQL(aList: TBoldObjectList; AClass: TBold SystemPersistenceHandler.GetAllInClassWithSQL(AList, AClass, WhereClause, OrderByClause, Params, JoinInheritedTables, MAxAnswers, Offset); end; -procedure TBoldSystem.FetchLinksWithObjects(ObjectList: TBoldObjectList; const LinkName: string; FetchedObjects: TBoldObjectList = nil); +procedure TBoldSystem.GetAllInClassWithRawSQL(aList: TBoldObjectList; AClass: TBoldObjectClass; SQL: String; Params: TParams = nil; MaxAnswers: integer = -1; Offset: integer = -1); +begin + SystemPersistenceHandler.GetAllInClassWithRawSQL(AList, AClass, SQL, Params, MaxAnswers, Offset); +end; + +procedure TBoldSystem.FetchLinksWithObjects(ObjectList: TBoldObjectList; const LinkName: string;FetchObjectsInLink: Boolean = True{; const FetchedObjectList: TBoldObjectList = nil}); +begin + SystemPersistenceHandler.FetchLinksWithObjects(ObjectList, LinkName,FetchObjectsInLink{, FetchedObjectList}); +end; + +procedure TBoldSystem.FetchMembersWithObjects(aBoldObjectList: TBoldObjectList; aBoldMemberIdList: TBoldMemberIdList); +begin + SystemPersistenceHandler.FetchMembersWithObjects(aBoldObjectList, aBoldMemberIdList); +end; + +procedure TBoldSystem.FetchMembersWithObjects(aBoldObjectList: TBoldObjectList; const AMemberCommaList: string); +begin + SystemPersistenceHandler.FetchMembersWithObjects(aBoldObjectList, AMemberCommaList); +end; + +procedure TBoldSystem.FetchMembersWithObject(ABoldObject: TBoldObject; const AMemberCommaList: string); +var + BoldObjectList: TBoldObjectList; +begin + BoldObjectList := TBoldObjectList.Create; + try + BoldObjectList.Add(ABoldObject); + FetchMembersWithObjects(BoldObjectList, AMemberCommaList); + finally + BoldObjectList.free; + end; +end; + +procedure TBoldSystem.FetchIdList(FetchIdList: TBoldObjectIdList; AFetchObjects: boolean = true); +var + lObjectList: TBoldObjectList; + i: integer; +begin + if FetchIdList.Count > 0 then + begin + lObjectList := TBoldObjectList.Create; + try + lObjectList.FillFromIDList(FetchIdList, self); + if AFetchObjects then + SystemPersistenceHandler.FetchList(lObjectList); + finally + lObjectList.free; + end; + end; +end; + +function TBoldList.GetEmpty: Boolean; begin - SystemPersistenceHandler.FetchLinksWithObjects(ObjectList, LinkName, FetchedObjects); + result := count = 0; end; procedure TBoldSystem.DirtyAsObjectList(ObjectList: TBoldObjectList); var i: Integer; begin - for i := 0 to DirtyObjects.Count - 1 do - ObjectList.Add(TBoldObject(DirtyObjects[i])); + if ObjectList.BeginUpdate then + try + if ObjectList.Empty or (ObjectList.DuplicateMode = bldmAllow) then + with ObjectList.ObjectListController do + for I := 0 to DirtyObjects.Count - 1 do + AddLocator(TBoldObject(DirtyObjects[i]).BoldObjectLocator) + else + for I := 0 to DirtyObjects.Count - 1 do + ObjectList.AddLocator(TBoldObject(DirtyObjects[i]).BoldObjectLocator) + finally + ObjectList.EndUpdate; + end; end; procedure TBoldSystem.UpdateDatabase; var g: IBoldGuard; - aList: TBoldObjectList; + List: TBoldObjectList; begin - g := TBoldGuard.Create(aList); - aList := TBoldObjectList.CreateWithTypeInfo(BoldSystemTypeInfo.ListTypeInfoByElement[BoldSystemTypeInfo.RootClassTypeInfo]); - DirtyAsObjectList(alist); - UpdateDatabaseWithList(aList); + if not BoldDirty then + exit; + g := TBoldGuard.Create(List); + List := TBoldObjectList.Create;// BoldSystemTypeInfo.RootClassTypeInfo.ListTypeInfo.CreateElement as TBoldObjectList; + list.SetInternalState(BoldDuplicateModeMask, BoldDMShift, Integer(bldmAllow)); + list.SubscribeToObjectsInList := false; + list.Capacity := DirtyObjects.Count; + DirtyAsObjectList(list); + UpdateDatabaseWithList(List); end; procedure TBoldSystem.UpdateDatabaseWithList(ObjectList: TBoldObjectList); begin - if Assigned(fUndoHandler) then - fUndoHandler.PrepareUpdate(ObjectList); - SystemPersistenceHandler.UpdateDatabaseWithList(ObjectList); - fOldValueHandler.PurgeEqualValues; - // when all objects are saved, there should be nothing in the oldvalues-handler -{ - if (DirtyObjects.Count = 0) and not (fOldValueHandler.IsEmpty) then - BoldLog.Log('OldValueHandler is not empty after a complete save'); -} + Assert(not IsUpdatingDatabase, 'TBoldSystem.UpdateDatabaseWithList: Reentry detected.'); + IsUpdatingDatabase := True; + try + SystemPersistenceHandler.UpdateDatabaseWithList(ObjectList); + if (DirtyObjects.Count > 0) then + fOldValueHandler.PurgeEqualValues + else + begin +// fOldValueHandler.PurgeEqualValues; +// if not fOldValueHandler.IsEmpty then +// Assert(fOldValueHandler.IsEmpty); + // optimization: if there are no dirty objects do not PurgeEqualValue, just destroy OldValues instead. + FreeAndNil(fOldValueHandler); + fOldValueHandler := TBoldOldValueHandler.Create(Self); + end; + finally + IsUpdatingDatabase := False; + end; end; -procedure TBoldSystem.DiscardPersistent; +procedure TBoldSystem.UpdateDatabaseWithObjects( + const aObjects: array of TBoldObject); +var + i: integer; + List: TBoldObjectList; +begin + if high(aObjects) = -1 then exit; + List := TBoldObjectList.Create; + list.SubscribeToObjectsInList := false; + try + for i := low(aObjects) to high(aObjects) do + if aObjects[i] <> nil then + List.Add(aObjects[i]); + UpdateDatabaseWithList(List); + finally + List.Free; + end; +end; + +procedure TBoldSystem.DiscardPersistent(ADiscardTransientLinks: boolean); var LocalDirtyObjects: TList; i: integer; begin DelayObjectDestruction; try - // The while construction is to ensure that objects that get dirty due to - // discarding an object in the list are also discarded - // (Most likely to happen with links that are saved within another object or - // by themselves) while DirtyObjects.Count > 0 do begin - LocalDirtyObjects := DirtyObjects; // this is just to clean the list from non-dirty objects - for i := LocalDirtyObjects.Count - 1 downto 0 do - TBoldObject(LocalDirtyObjects[i]).BoldObjectLocator.DiscardBoldObject; + LocalDirtyObjects := DirtyObjects; + i := LocalDirtyObjects.Count - 1; + repeat + i := MinIntValue([i, LocalDirtyObjects.Count - 1]); + TBoldObject(LocalDirtyObjects[i]).BoldObjectLocator.DiscardBoldObject(ADiscardTransientLinks); + dec(i); + while i >= LocalDirtyObjects.Count do + dec(i); + until (i < 0) or (LocalDirtyObjects.Count = 0); end; finally AllowObjectDestruction; @@ -1707,14 +2394,20 @@ procedure TBoldSystem.DiscardTransient; var g: IBoldGuard; Traverser: TBoldLocatorListTraverser; + Locator: TBoldObjectLocator; begin g := TBoldGuard.Create(Traverser); Traverser := Locators.CreateTraverser; - while not Traverser.EndOfList do - begin - if assigned(Traverser.Locator.BoldObject) and not Traverser.Locator.BoldObject.BoldPersistent then - Traverser.Locator.DiscardBoldObject; - Traverser.Next; +// DelayObjectDestruction; + try + while Traverser.MoveNext do + begin + Locator := Traverser.Locator; + if assigned(Traverser.Locator.BoldObject) and not Locator.BoldObject.BoldPersistent then + Locator.DiscardBoldObject; + end; + finally +// AllowObjectDestruction; end; end; @@ -1728,7 +2421,6 @@ procedure TBoldSystem.Discard; procedure TBoldSystem.DefaultSubscribe(Subscriber: TBoldSubscriber; RequestedEvent: TBoldEvent = breReEvaluate); begin - // FIXME what here? end; procedure TBoldSystem.GetAsList(ResultList: TBoldIndirectElement); @@ -1745,26 +2437,90 @@ function TBoldSystem.GetDirtyObjects: TList; var i: Integer; begin - if fDirtyObjectsInvalid then + if DirtyObjectsInvalid then begin - i := 0; - while i < fDirtyObjects.Count do - if assigned(fDirtyObjects[i]) - and not TBoldObject(fDirtyObjects[i]).BoldDirty then - MarkObjectClean(TBoldObject(fDirtyObjects[i])) - else - inc(i); + i := fDirtyObjects.Count-1; + while (i >= 0) and (i < fDirtyObjects.Count) do + begin + if assigned(fDirtyObjects[i]) and not TBoldObject(fDirtyObjects[i]).BoldDirty then + MarkObjectClean(TBoldObject(fDirtyObjects[i])); + dec(i); + end; fDirtyObjects.Pack; - fDirtyObjectsInvalid := False; + DirtyObjectsInvalid := False; end; result := fDirtyObjects; end; +function TBoldSystem.GetDirtyObjectsAsBoldList(AClassType: TBoldObjectClass): TBoldObjectList; +var + i: integer; +begin + if not Assigned(AClassType) then + AClassType := TBoldObjectClass(BoldSystemTypeInfo.RootClassTypeInfo.ObjectClass); + result := TBoldObjectList.CreateTypedList(AClassType); + result.DuplicateMode := bldmAllow; + result.SubscribeToObjectsInList := false; + with result.ObjectListController, GetDirtyObjects do + for I := 0 to Count - 1 do + if TBoldObject(Items[i]) is AClassType then + AddLocator(TBoldObject(Items[i]).BoldObjectLocator); +end; + +function TBoldSystem.GetDirtyObjectsAsBoldListByClassExpressionName( + const AClass: string): TBoldObjectList; +var + ClassTypeInfo: TBoldClassTypeInfo; + AClassType: TBoldObjectClass; +begin + result := nil; + ClassTypeInfo := BoldSystemTypeInfo.ClassTypeInfoByExpressionName[AClass]; + if Assigned(ClassTypeInfo) then + begin + AClassType := TBoldObjectClass(ClassTypeInfo.ObjectClass); + result := GetDirtyObjectsAsBoldList(AClassType); + end; +end; + +function TBoldSystem.GetAllDirtyObjectsAsBoldList: TBoldObjectList; +begin + result := GetDirtyObjectsAsBoldList(nil); +end; + procedure TBoldSystem.MarkObjectPossiblyCleaner(BoldObject: TBoldObject); begin - if not fDirtyObjectsInvalid then - SendEvent(beDirtyListInvalidOrItemDeleted); - fDirtyObjectsInvalid := True; + if not DirtyObjectsInvalid then + begin + DirtyObjectsInvalid := True; + SendExtendedEvent(beDirtyListInvalidOrItemDeleted, [BoldObject]); + end; +end; + +procedure TBoldSystem.MemberDerivationBegin(Member: TBoldMember); +begin + fDerivedMembers.Add(Member); +{$IFNDEF NoAutoSubscription} + if fDerivedMembers.count > Length(fMembersReadDuringDerivationIndexArray) then + SetLength(fMembersReadDuringDerivationIndexArray, fDerivedMembers.count); + fMembersReadDuringDerivationIndexArray[fDerivedMembers.count-1] := fMembersReadDuringDerivation.Count; +{$ENDIF} +end; + +procedure TBoldSystem.MemberDerivationEnd(Member: TBoldMember); +var + i: integer; + vAccessedMember: TBoldMember; +begin +{$IFNDEF NoAutoSubscription} + for i := fMembersReadDuringDerivation.Count - 1 downto fMembersReadDuringDerivationIndexArray[fDerivedMembers.count-1] do + begin + vAccessedMember := TBoldMember(fMembersReadDuringDerivation[i]); + if Assigned(vAccessedMember) then + vAccessedMember.DefaultSubscribe(Member.Deriver); // place the subscription + fMembersReadDuringDerivation.Delete(i); + end; +{$ENDIF} + fDerivedMembers.Remove(Member); end; function TBoldSystem.GetBoldDirty: Boolean; @@ -1782,21 +2538,31 @@ procedure TBoldSystem.AllowObjectDestruction; var i: Integer; anObject: TBoldObject; + aList: TList; begin if fDelayedDestructionCount <= 0 then - raise EBold.CreateFmt(sDestructionNestingMismatch, [classname]); + raise EBold.CreateFmt('%s.AllowObjectDestruction: Called without a previous matching call to DelayObjectDestruction', [classname]); dec(fDelayedDestructionCount); if fDelayedDestructionCount = 0 then begin - for i := 0 to fDelayedDestructionList.Count - 1 do - begin - Assert(TObject(fDelayedDestructionList[i]) is TBoldObject); - anObject := TBoldObject(fDelayedDestructionList[i]); - if (anObject.BoldPersistenceState <> bvpsModified) and - (anObject.BoldExistenceState <> besExisting) then - DestroyObject(anObject); + while fDelayedDestructionList.Count > 0 do begin + aList := TList.Create; + try + aList.Assign(fDelayedDestructionList); + fDelayedDestructionList.count := 0; + for i := aList.Count - 1 downto 0 do begin + Assert(TObject(aList[i]) is TBoldObject); + anObject := TBoldObject(aList[i]); + if (anObject.BoldPersistenceState <> bvpsModified) and + (anObject.BoldExistenceState <> besExisting) then + begin + DestroyObject(anObject); + end; + end; + finally + aList.Free; + end; end; - fDelayedDestructionList.Clear; end; end; @@ -1809,62 +2575,151 @@ procedure TBoldSystem.DestroyObject(BoldObject: TBoldObject); var aLocator: TBoldObjectLocator; begin + if not Assigned(BoldObject) then //Patch + Exit; //PATCH Do not try to delete nil pointer. (This is for safty. No proof that it is needed.) if (BoldObject.BoldPersistenceState = bvpsModified) or (BoldObject.BoldExistenceState = besExisting) then - raise EBold.CreateFmt(sObjectNotDestroyable, [classname]); - if fDelayedDestructionCount > 0 then - fDelayedDestructionList.Add(BoldObject) + raise EBold.CreateFmt('%s.DestroyObject: Object is not destroyable. Either modified or existing.', [classname]); + BoldObject.FreeDerivers; + if (fDelayedDestructionCount > 0) then + begin + if not BoldObject.InDelayDestructionList then + begin + fDelayedDestructionList.Add(BoldObject); + BoldObject.InDelayDestructionList := true; + end; + end else begin aLocator := BoldObject.BoldObjectLocator; - SendExtendedEvent(beLocatorDestroying, [BoldObject]); - aLocator.UnloadBoldObject; - Locators.Remove(aLocator); + // If we got an exception duriung destoy, we might get an half uninitialized BoldObject without Locator next time. + if Assigned(aLocator) then //PATCH + begin + SendExtendedEvent(beLocatorDestroying, [BoldObject]); + aLocator.UnloadBoldObject; + Locators.Remove(aLocator); + end; end; end; +function TBoldObjectList.GetObjectListController: TBoldAbstractObjectListController; +begin + Result := TBoldAbstractObjectListController(ListController); + Assert(result is TBoldAbstractObjectListController); +end; + procedure TBoldSystem.ReceiveEventFromOwned(originator: TObject; - originalEvent: TBoldEvent); + originalEvent: TBoldEvent; const Args: array of const); var ClassList: TBoldObjectList; begin - if (OriginalEvent in [beObjectCreated, beObjectDeleted, beObjectFetched]) - and (originator is TBoldObject) - then + if (originalEvent in [beObjectCreated, beObjectDeleted, beObjectFetched, beObjectUnloaded, beCompleteModify]) + and (originator is TBoldObject) then begin - ClassList := Classes[TBoldObject(Originator).BoldClassTypeInfo.TopSortedIndex]; - Assert(ClassList.ObjectListController is TBoldClassListController); - TBoldClassListController(ClassList.ObjectListController).ReceiveClassEvent(TBoldObject(Originator), OriginalEvent); + if originalEvent in [beObjectCreated, beObjectDeleted, beObjectFetched, beObjectUnloaded] then + begin + ClassList := Classes[TBoldObject(Originator).BoldClassTypeInfo.TopSortedIndex]; + Assert(ClassList.ObjectListController is TBoldClassListController); + TBoldClassListController(ClassList.ObjectListController).ReceiveClassEvent(TBoldObject(Originator), OriginalEvent); + end; SendExtendedEvent(originalEvent, [originator]); + end + else +{$IFDEF BoldSystemBroadcastMemberEvents} + if (originalEvent in beBroadcastMemberEvents) and ((Originator is TBoldObject) or (Originator is TBoldMember) and (TBoldMember(Originator).OwnedByObject)) then + Publisher.SendExtendedEvent(Originator, originalEvent, Args); +{$ENDIF} +end; + +procedure TBoldSystem.ReceiveFromPersistenceController(Originator: TObject; + OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent); +begin + if (OriginalEvent = beDestroying) and (fPersistenceController = Originator) then + fPersistenceController := nil + else + case OriginalEvent of + bpeStartFetch: Inc(fFetchNesting); + bpeEndFetch: + begin + Dec(fFetchNesting); + Assert(fFetchNesting >= 0, 'Negative fetch nesting'); + end; end; end; +{$IFNDEF BOLD_NO_QUERIES} +function TBoldSystem.ReceiveQueryFromOwned(Originator: TObject; + OriginalEvent: TBoldEvent; const Args: array of const; + Subscriber: TBoldSubscriber): Boolean; +begin + result := SendQuery(OriginalEvent, Args, Subscriber, Originator); +end; +{$ENDIF} function TBoldSystem.CanCreateObject(ClassTypeInfo: TBoldClassTypeInfo): boolean; begin +{$IFDEF BOLD_NO_QUERIES} + result := true; +{$ELSE} result := SendQuery(bqMayCreateObject, [ClassTypeInfo], nil); + {$ENDIF} end; -class function TBoldAbstractOldValueHandler.NewValueInValueSpace(BoldMember: TBoldMember; ValueSpace: IBoldValueSpace): IBoldValue; -var - ObjectContents: IBoldObjectContents; - MemberId: TBoldmemberId; - G: IBoldGuard; +function TBoldMember.GetIsPartOfSystem: Boolean; begin - G := TBoldGuard.Create(MemberId); - ObjectContents := ValueSpace.EnsuredObjectContentsByObjectId[BoldMember.OwningObject.BoldObjectLocator.BoldObjectId]; - MemberId := TBoldMemberId.Create(BoldMember.BoldMemberRTInfo.Index); - if assigned(ObjectContents.ValueByMemberId[MemberId]) then - result := nil + result := OwnedByObject or (OwningElement is TBoldSystem); +end; + +function TBoldMember.GetBoldMemberRTInfo: TBoldMemberRTInfo; +begin + if OwnedByObject then + begin + assert(fBoldMetaType is TBoldMemberRtInfo); + result := TBoldMemberRTInfo(fBoldMetaType); + end + else + result := nil; +end; + +function TBoldMember.GetIsReadOnly(Flag: TBoldElementFlag): Boolean; +begin + result := GetElementFlag(Flag) or + (assigned(BoldMemberRTInfo) and BoldMemberRTInfo.IsStoredInObject and OwningObject.IsReadOnly); +end; + +function TBoldMember.GetOwningObject: TBoldObject; +begin + if OwnedByObject then + begin + Result := TBoldObject(OwningElement); + Assert(result is TBoldObject); + end + else + begin + Assert(not (OwningElement is TBoldObject)); + Result := nil; + end; +end; + +function TBoldMember.GetBoldSystem: TBoldSystem; +begin + if OwnedByObject then + begin + Assert(OwningElement is TBoldObject); + Result := TBoldObject(OwningElement).BoldSystem + end else begin - ObjectContents.EnsureMember(MemberId, BoldMember.GetStreamName); - result := ObjectContents.ValueByMemberId[MemberId]; + result := OwningElement as TBoldSystem; end; end; function TBoldSystem.CanDeleteObject(anObject: TBoldObject): boolean; begin +{$IFDEF BOLD_NO_QUERIES} + result := true; +{$ELSE} result := SendQuery(bqMayDeleteObject, [AnObject], nil); +{$ENDIF} end; function TBoldSystem.GetBoldType: TBoldElementTypeInfo; @@ -1872,11 +2727,6 @@ function TBoldSystem.GetBoldType: TBoldElementTypeInfo; result := BoldSystemTypeInfo; end; -function TBoldSystem.GetDisplayName: String; -begin - result := boldType.ExpressionName; -end; - function TBoldSystem.GetEvaluator: TBoldEvaluator; begin if not assigned(fEvaluator) then @@ -1894,32 +2744,46 @@ function TBoldSystem.GetIsDefault: Boolean; Result := Self = G_DefaultBoldSystem; end; -procedure TBoldSystem.SetIsdefault(Value: Boolean); +function TBoldSystem.GetIsProcessingTransactionOrUpdatingDatabase: Boolean; +begin + Result := IsCommitting or IsRollingBack or IsUpdatingDatabase; +end; + +procedure TBoldSystem.SetIsDefault(Value: Boolean); begin - if Value then - G_DefaultBoldSystem := Self - else if IsDefault then - G_DefaultBoldSystem := nil; + if Value then + begin + G_DefaultBoldSystem := Self + end + else + if (self = G_DefaultBoldSystem) then + G_DefaultBoldSystem := nil; +end; + +function TBoldSystem.InTransaction: boolean; +begin + Result := fTransactionNesting <> 0; end; procedure TBoldSystem.StartTransaction(MinimalMode: TBoldSystemTransactionMode = stmNormal); begin +{$IFNDEF NoObjectSpaceTransactions} if MinimalMode <= TransactionMode then begin if not InTransaction then begin Assert(not RollbackAreaAssigned); - fRollbackArea := TBoldFreeStandingValueSpace.create; - fValidValueArea := TBoldFreeStandingValueSpace.create; + RollbackAreaAssigned := true; DelayObjectDestruction; end; inc(fTransactionNesting); end; +{$ENDIF} end; procedure TBoldSystem.CommitTransaction(MinimalMode: TBoldSystemTransactionMode = stmNormal); - function OrdernoDiffers(Value: IBoldValue; member: TBoldMember):Boolean; + function OrdernoDiffers(const Value: IBoldValue; member: TBoldMember):Boolean; begin Result := (member is TBoldObjectReference) and (TBoldObjectReference(member).GetController is TBoldDirectSingleLinkController) and @@ -1938,7 +2802,8 @@ procedure TBoldSystem.CommitTransaction(MinimalMode: TBoldSystemTransactionMode RegardAsExisting: Boolean; ObjIdRef: IBoldObjectIdRef; begin - { TODO : Lots of finishing } + if FRollBackArea.IsEmpty then + exit; G := TBoldGuard.Create(ObjectIds); ObjectIds := TBoldObjectIdList.Create; FRollBackArea.AllObjectIds(ObjectIDs, false); @@ -1946,18 +2811,18 @@ procedure TBoldSystem.CommitTransaction(MinimalMode: TBoldSystemTransactionMode begin ObjectContents := FRollBackArea.GetFSObjectContentsByObjectId(ObjectIds[O]); BoldObject := Locators.GetObjectByID(ObjectIds[O]); - assert(assigned(BoldObject)); // DelayDestruction should ensure that + assert(assigned(BoldObject)); RegardAsExisting := (((BoldObject.BoldPersistenceState = bvpsCurrent) and (BoldObject.BoldExistenceState = besExisting)) or ((BoldObject.BoldPersistenceState = bvpsModified) and (BoldObject.BoldExistenceState = besDeleted))) and - (ObjectContents.BoldExistenceState = besNotCreated); // was transacted at fetch - Assert(not RegardAsExisting); // Remove when tested enough + (ObjectContents.BoldExistenceState = besNotCreated); + Assert(not RegardAsExisting); UndoHandler.HandleObject(ObjectContents, RegardAsExisting); - for M := 0 to ObjectContents.MemberCount - 1 do + for M := ObjectContents.MemberCount - 1 downto 0 do begin - Value := ObjectContents.ValueByIndex[m]; + Value := ObjectContents.ValueByIndex[m]; if Assigned(Value) and BoldObject.BoldMemberAssigned[M] and BoldObject.BoldMembers[M].StoreInUndo then begin BoldMember := BoldObject.BoldMembers[M]; @@ -1969,13 +2834,13 @@ procedure TBoldSystem.CommitTransaction(MinimalMode: TBoldSystemTransactionMode Value := nil; end; end; - if (BoldObject.BoldExistenceState = besDeleted) then // deleted object, save all remaining values + if (BoldObject.BoldExistenceState = besDeleted) then begin for M := 0 to BoldObject.BoldMemberCount - 1 do if BoldObject.BoldMemberAssigned[M] and BoldObject.BoldMembers[M].StoreInUndo then begin - Value := BoldObject.BoldMembers[M].AsIBoldValue[bdepContents]; // Store as contents, UnDO only used in other direction - if BoldObject.BoldMembers[M].BoldPersistenceState <> bvpsInvalid then + Value := BoldObject.BoldMembers[M].AsIBoldValue[bdepContents]; + if (not BoldObject.BoldMembers[M].BoldPersistenceStateIsInvalid) then UndoHandler.HandleMember(ObjectContents, M, Value); Value := nil; end; @@ -1984,10 +2849,11 @@ procedure TBoldSystem.CommitTransaction(MinimalMode: TBoldSystemTransactionMode end; begin +{$IFNDEF NoObjectSpaceTransactions} if MinimalMode <= TransactionMode then begin if not InTransaction then - raise EBold.CreateFmt(sUnmatchedCommit, [classname]); + raise EBold.CreateFmt('%s.CommitTransaction: Unmatched call to commit. Transaction not started.', [classname]); if fTransactionNesting = 1 then begin @@ -1995,49 +2861,63 @@ procedure TBoldSystem.CommitTransaction(MinimalMode: TBoldSystemTransactionMode fTransactionList.Clear; if not fTransactionRollbackOnly then begin - if TBoldUndoHandler(UndoHandler).UndoState=busNormal then - HandleOldValues; - FreeAndNil(fRollbackArea); - FreeAndNil(fValidValueArea); - dec(fTransactionNesting); - AllowObjectDestruction; + Dec(fTransactionNesting); //PATCH If we get to this point we MUST decrease the counter to zero so we don't get stuck forever. + IsCommitting := True; + try + if UndoHandlerInterface.Enabled and (TBoldUndoHandler(UndoHandler).UndoState=busNormal) then + HandleOldValues; + finally //PATCH To strengten Transaction against exceptions + try //PATCH To strengten Transaction against exceptions + fRollbackArea.Clear; + finally + try + fValidValueArea.Clear; + finally + RollbackAreaAssigned := false; + AllowObjectDestruction; //PATCH Make sure this is called even if we get an exception when destroying valuespaces. + IsCommitting := false; + end; + end; + end; end else - BoldRaiseLastFailure(self, 'CommitTransaction', sCommitNotAllowed); // do not localize + BoldRaiseLastFailure(self, 'CommitTransaction', 'Transaction not allowed to be commited'); end else dec(fTransactionNesting); end; +{$ENDIF} end; procedure TBoldSystem.RollbackTransaction(MinimalMode: TBoldSystemTransactionMode = stmNormal); -var - aRollbackArea: TBoldFreestandingValueSpace; - aValidValueArea: TBoldFreestandingValueSpace; begin +{$IFNDEF NoObjectSpaceTransactions} if MinimalMode <= TransactionMode then begin if not InTransaction then - raise EBold.CreateFmt(sUnmatchedRollback, [classname]); - + raise EBold.CreateFmt('%s.RollbackTransaction: Unmatched call to rollback. Transaction not started.', [classname]); if fTransactionNesting = 1 then begin - aRollbackArea := fRollbackArea; - fRollbackArea := nil; // so rollback doesn't write to rollback area itself - aValidValueArea := fValidValueArea; - fValidValueArea := nil; - AsIBoldvalueSpace[bdepContents].ApplyValueSpace(aRollbackArea, false); - aRollbackArea.Free; - aValidValueArea.Free; - AllowObjectDestruction; - fTransactionList.Clear; - fTransactionRollbackOnly := false; - SendEvent(beRolledBack); + IsRollingBack := True; + try + fTransactionRollbackOnly := True; //PATCH + RollbackAreaAssigned := false; + AsIBoldvalueSpace[bdepContents].ApplyValueSpace(fRollbackArea, false); + finally + dec(fTransactionNesting); + IsRollingBack := False; + fRollbackArea.clear; + fValidValueArea.clear; + AllowObjectDestruction; + fTransactionList.Clear; + fTransactionRollbackOnly := false; + SendEvent(beRolledBack); + end; end else - fTransactionRollbackOnly := true; - dec(fTransactionNesting); + dec(fTransactionNesting); end; +{$ENDIF} end; function TBoldSystem.CanCommit: Boolean; @@ -2047,48 +2927,110 @@ function TBoldSystem.CanCommit: Boolean; begin g := TBoldGuard.Create(Traverser); try +{$IFDEF BOLD_NO_QUERIES} + result := true; +{$ELSE} result := SendQuery(bqMayCommit, [], nil); +{$ENDIF} Traverser := fTransactionList.CreateTraverser; - while result and not Traverser.EndOfList do + while result and Traverser.MoveNext do begin result := Traverser.item.CanCommit; - Traverser.Next; end; except result := false; end; end; -class procedure TBoldAbstractOldValueHandler.CopyMemberToValueSpace(BoldMember: TBoldMember; ValueSpace: IBoldValueSpace); +function TBoldSystemFreeStandingObjectContents.EnsureMemberAndGetValueByIndex( + Member: TBoldMember): IBoldValue; + + function CreateInstance( + Member: TBoldMember): TBoldFreeStandingValue; + var + ElementClass: TBoldFreeStandingElementClass; + begin + ElementClass := Member.GetFreeStandingClass; + if Assigned(ElementClass) then + result := ElementClass.Create as TBoldFreeStandingValue + else + raise EBold.createFmt('%s.CreateInstance: No freestanding class registered for name %s', [classname, Member.DisplayName]); + end; + var - Value: IBoldValue; - BoldObject: TBoldObject; + Index: integer; begin - Assert(assigned(valuespace)); - - BoldObject := BoldMember.OwningObject; - Assert(Assigned(BoldObject)); - CopyObjectToValueSpace(BoldObject, ValueSpace); - Value := NewValueInValueSpace(BoldMember, ValueSpace); - if Assigned(Value) then - Value.AssignContent(BoldMember.AsIBoldValue[bdepContents]); + Index := Member.BoldMemberRTInfo.index; + EnsureMemberListLength(Index); + if not assigned(fMemberlist[Index]) then + fMemberlist[Index] := CreateInstance(Member); + Result := fMemberlist[Index]; end; -class procedure TBoldAbstractOldValueHandler.CopyObjectToValueSpace(BoldObject: TBoldObject; ValueSpace: IBoldValueSpace); +class function TBoldAbstractOldValueHandler.NewValueInValueSpace(BoldMember: TBoldMember; const ValueSpace: IBoldValueSpace): IBoldValue; var - anObjectContents: IBoldObjectContents; - anObjectId: TBoldObjectId; + ObjectContents: IBoldObjectContents; + MemberIndex: Integer; + BoldSystemObjectContents: IBoldSystemObjectContents; begin - assert(assigned(ValueSpace)); + ObjectContents := ValueSpace.EnsuredObjectContentsByObjectId[BoldMember.OwningObject.BoldObjectLocator.BoldObjectId]; + MemberIndex := BoldMember.BoldMemberRTInfo.Index; + if assigned(ObjectContents.ValueByIndex[MemberIndex]) then + result := nil + else + begin + if Supports(ObjectContents, IBoldSystemObjectContents, BoldSystemObjectContents) then + result := BoldSystemObjectContents.EnsureMemberAndGetValueByIndex(BoldMember) + else + result := ObjectContents.EnsureMemberAndGetValueByIndex(MemberIndex, BoldMember.GetStreamName); + end; +end; + +class procedure TBoldAbstractOldValueHandler.CopyMemberToValueSpace(BoldMember: TBoldMember; const ValueSpace: IBoldValueSpace); + + function GetMemberFromContents(const ObjectContents: IBoldObjectContents): IBoldValue; + var + BoldSystemObjectContents: IBoldSystemObjectContents; + begin + if Supports(ObjectContents, IBoldSystemObjectContents, BoldSystemObjectContents) then + result := BoldSystemObjectContents.EnsureMemberAndGetValueByIndex(BoldMember) + else + result := ObjectContents.EnsureMemberAndGetValueByIndex(BoldMember.BoldMemberRTInfo.Index, BoldMember.GetStreamName); + end; +var + ObjectContents: IBoldObjectContents; + Member: IBoldValue; +begin + Assert(Assigned(Valuespace)); + Assert(Assigned(BoldMember)); + Assert(Assigned(BoldMember.OwningObject)); + Member := nil; + if ValueSpace.GetEnsuredObjectContentsByObjectIdAndCheckIfCreated(BoldMember.OwningObject.BoldObjectLocator.BoldObjectId, ObjectContents) then + with BoldMember.OwningObject do + begin + ObjectContents.BoldExistenceState := BoldExistenceState; + ObjectContents.BoldPersistenceState := BoldPersistenceState; + ObjectContents.TimeStamp := GetTimeStamp; + Member := GetMemberFromContents(ObjectContents); + end + else + if not assigned(ObjectContents.ValueByIndex[BoldMember.BoldMemberRTInfo.Index]) then + begin + Member := GetMemberFromContents(ObjectContents); + end; + if Assigned(Member) then + Member.AssignContent(BoldMember.AsIBoldValue[bdepContents]); +end; - anObjectId := BoldObject.BoldObjectLocator.BoldObjectID; - anObjectContents := ValueSpace.ObjectContentsByObjectId[anObjectID]; - if not assigned(anObjectContents) then +class procedure TBoldAbstractOldValueHandler.CopyObjectToValueSpace(BoldObject: TBoldObject; const ValueSpace: IBoldValueSpace); +var + aBoldObjectContents: IBoldObjectContents; +begin + Assert(Assigned(ValueSpace)); + if ValueSpace.GetEnsuredObjectContentsByObjectIdAndCheckIfCreated(BoldObject.BoldObjectLocator.BoldObjectId, aBoldObjectContents) then begin - ValueSpace.EnsureObjectContents(anObjectID); - anObjectContents := ValueSpace.ObjectContentsByObjectId[anObjectId]; - anObjectContents.BoldExistenceState := BoldObject.BoldExistenceState; - anObjectContents.BoldPersistenceState := BoldObject.BoldPersistenceState; + aBoldObjectContents.BoldExistenceState := BoldObject.BoldExistenceState; + aBoldObjectContents.BoldPersistenceState := BoldObject.BoldPersistenceState; end; end; @@ -2097,44 +3039,45 @@ procedure TBoldSystem.CopyMemberToRollBackBuffer(BoldMember: TBoldMember); Value: IBoldValue; FSObjectContents: TBoldFreeStandingObjectContents; MemberIndex: integer; + Created: boolean; begin - if RollBackAreaAssigned then + if RollBackAreaAssigned {$IFDEF DisableRollbackDuringFetch} and not IsFetching {$ENDIF} then begin MemberIndex := BoldMember.BoldMemberRTInfo.index; - FSObjectContents := EnsureObjectInFsValueSpace(BoldMember.OwningObject, fRollbackArea); - Value := FSObjectContents.ValueByIndex[BoldMember.BoldMemberRTInfo.Index]; + FSObjectContents := EnsureObjectInFsValueSpace(BoldMember.OwningObject, fRollbackArea, Created); + if Created then + Value := nil + else + Value := FSObjectContents.ValueByIndex[BoldMember.BoldMemberRTInfo.Index]; if Assigned(Value) then begin if (Value.BoldPersistenceState = bvpsInvalid) then begin - FSObjectContents := EnsureObjectInFsValueSpace(BoldMember.OwningObject, fValidValueArea); - if not Assigned(FSObjectContents.ValueByIndex[MemberIndex]) then - begin - FSObjectContents.EnsureMemberByIndex(MemberIndex, BoldMember.GetStreamName); - FSObjectContents.ValueByIndex[MemberIndex].AssignContent(BoldMember.AsIBoldValue[bdepContents]); - end; + FSObjectContents := EnsureObjectInFsValueSpace(BoldMember.OwningObject, fValidValueArea, Created); + TBoldSystemFreeStandingObjectContents(FSObjectContents).EnsureMemberAndGetValueByIndex(BoldMember).AssignContent(BoldMember.AsIBoldValue[bdepContents]);; end; end else begin Assert (not( (BoldMember is TBOldObjectReference) and - (BoldMember.BoldPersistenceState = bvpsInvalid) and + (BoldMember.BoldPersistenceStateIsInvalid) and TBOldObjectReference(BoldMember).HasOldValues and ((TBOldObjectReference(BoldMember).fObjectReferenceController as TBoldDirectSingleLinkController).GetLocator = nil) )); - FSObjectContents.EnsureMemberByIndex(MemberIndex, BoldMember.GetStreamName); - FSObjectContents.ValueByIndex[MemberIndex].AssignContent(BoldMember.AsIBoldValue[bdepContents]); + Value := BoldMember.AsIBoldValue[bdepContents]; + TBoldSystemFreeStandingObjectContents(FSObjectContents).EnsureMemberAndGetValueByIndex(BoldMember).AssignContent(Value); end; end; end; procedure TBoldSystem.CopyObjectToRollBackBuffer(BoldObject: TBoldObject); begin - if RollBackAreaAssigned then - EnsureObjectInFsValueSpace(BoldObject, fRollBackArea); + if RollBackAreaAssigned {$IFDEF DisableRollbackDuringFetch} and not IsFetching {$ENDIF} then + EnsureObjectInFsValueSpace(BoldObject, fRollBackArea); end; + procedure TBoldSystem.AddToTransaction(DomainElement: TBoldDomainElement); begin if RollbackAreaAssigned and not fTransactionList.Includes(DomainElement) then @@ -2156,7 +3099,7 @@ function TBoldSystem.ProxyInterface(const IId: TGUID; Mode: TBoldDomainElementPr begin if IsEqualGuid(IID, IBoldValueSpace) then begin - result := TBoldSystem_Proxy.create(self, Mode).GetInterface(IID, obj); + result := TBoldSystem_Proxy.Create(self, Mode).GetInterface(IID, obj); if not result then raise EBoldInternal.CreateFmt('ProxyClass for %s did not implement IBoldValueSpace', [ClassName]); end @@ -2164,14 +3107,53 @@ function TBoldSystem.ProxyInterface(const IId: TGUID; Mode: TBoldDomainElementPr result := inherited ProxyInterface(IID, Mode, Obj); end; -function TBoldSystem.InTransaction: boolean; +procedure TBoldSystem.CheckIntegrity; +var + Traverser: TBoldLocatorListTraverser; + i: integer; + bo: TBoldObject; + bm: TBoldMember; begin - Result := fTransactionNesting <> 0; + Traverser := Locators.CreateTraverser; + while Traverser.MoveNext do + begin + if assigned(Traverser.Locator.BoldObject) then + begin + + if not (Traverser.Locator.BoldObject is TBoldObject) then + raise Exception.Create('broken object'); + bo := Traverser.Locator.BoldObject; + for i := 0 to bo.BoldMemberCount - 1 do + begin + + if bo.BoldMemberAssigned[i] then + begin + + bm := bo.BoldMembers[i]; + if not (bm is TBoldMember) then + raise Exception.Create('broken member'); + end; + end; + end; + end; + Traverser.Free; + +end; + +procedure TBoldSystem.IncrementDeletingObjectsDepth; +begin + Inc(FDeletingObjectsDepth); + if FDeletingObjectsDepth = 1 then begin +// SendEvent(beStartObjectDeletion); + end; end; -function TBoldSystem.RollBackAreaAssigned: boolean; +procedure TBoldSystem.DecrementDeletingObjectsDepth; begin - Result := Assigned(fRollBackArea); + if FDeletingObjectsDepth = 1 then begin +// SendEvent(beEndObjectDeletion); + end; + Dec(FDeletingObjectsDepth); end; { EnsureCanDestroy will raise an exception if there are constraints @@ -2179,11 +3161,11 @@ function TBoldSystem.RollBackAreaAssigned: boolean; procedure TBoldSystem.EnsureCanDestroy; begin if InTransaction then - raise EBold.CreateFmt(sDestroy_TransactionNesting, [ClassName, fTransactionNesting, BoldSystemTypeInfo.Modelname]); + raise EBold.CreateFmt('%s.Destroy; TransactionNesting = %d', [ClassName, fTransactionNesting]); if RollbackAreaAssigned then - raise EBold.CreateFmt(sDestroy_RollbackAreaAssigned, [ClassName, BoldSystemTypeInfo.Modelname]); + raise EBold.CreateFmt('%s.Destroy; RollBackArea still assigned', [ClassName]); if BoldDirty then - raise EBold.CreateFmt(sDestroy_DirtyObjects, [ClassName, BoldSystemTypeInfo.Modelname]); + raise EBold.CreateFmt('%s.Destroy: Destroying system with dirty objects', [ClassName]); end; function TBoldSystem.GetTimeForTimestamp(Timestamp: TBoldTimestampType): TDateTime; @@ -2201,7 +3183,7 @@ procedure TBoldSystem.SetTransactionMode(const Value: TBoldSystemTransactionMode if value <> fTransactionMode then begin if InTransaction then - raise EBold.CreateFmt(sNotAllowedInTransaction, [classname]); + raise EBold.CreateFmt('%s.SetTransactionMode: Not allowed while inside a transaction', [classname]); fTransactionMode := Value; end; end; @@ -2209,7 +3191,7 @@ procedure TBoldSystem.SetTransactionMode(const Value: TBoldSystemTransactionMode procedure TBoldSystem.SetPessimisticLockHandler(const Value: TBoldAbstractPessimisticLockHandler); begin if assigned(fPessimisticLockHandler) then - raise EBold.CreateFmt(sCannotChangeLockHandler, [classname]); + raise EBold.CreateFmt('%s.SetPessimisticLockHandler: Can not change lock handler on a running system', [classname]); fPessimisticLockHandler := Value; end; @@ -2228,16 +3210,9 @@ function TBoldSystem.GetTimeStampOfLatestUpdate: TBoldTimeStampType; Result := SystemPersistenceHandler.TimeStampOfLatestUpdate end; -function TBoldSystem.GetUndoHandler: TBoldAbstractUndoHandler; +function TBoldSystem.GetTimeOfLatestUpdate: TDateTime; begin - if not Assigned(fUndoHandler) then - fUndoHandler := TBoldUndoHandler.Create(self); - Result := fUndoHandler; -end; - -function TBoldSystem.GetUndoHandlerInterface: IBoldUndoHandler; -begin - Result := UndoHandler as IBoldUndoHandler; + Result := SystemPersistenceHandler.TimeOfLatestUpdate end; function TBoldSystem.AssertLinkIntegrity: Boolean; @@ -2249,7 +3224,7 @@ function TBoldSystem.AssertLinkIntegrity: Boolean; begin G := TBoldGuard.Create(Traverser); Traverser := Locators.CreateTraverser; - while not Traverser.EndOfList do + while Traverser.MoveNext do begin if assigned(Traverser.Locator.BoldObject) then begin @@ -2259,49 +3234,144 @@ function TBoldSystem.AssertLinkIntegrity: Boolean; and (bo.BoldMembers[i].GetController <> nil) then bo.BoldMembers[i].GetController.AssertIntegrity; end; - Traverser.Next; end; Result := True; end; +function TBoldSystem.CanEvaluateInPS(sOCL: string; + aContext: TBoldElementTypeInfo = nil; + const aVariableList: TBoldExternalVariableList = nil): Boolean; +begin + Result := SystemPersistenceHandler.CanEvaluateInPS(sOCL, aContext, aVariableList); +end; + +function TBoldSystem.GetDiscarding: Boolean; +begin + Result := FDiscardCount > 0; +end; + +function TBoldSystem.ContainsDirtyObjectsOfClass(AClassType: TBoldObjectClass): boolean; +var + i: integer; + List: TList; +begin + result := false; + List := DirtyObjects; + for I := List.Count - 1 downto 0 do + begin + if TBoldObject(List[i]) is AClassType then + begin + result := true; + exit; + end; + end; +end; + +procedure TBoldSystem.RemoveDeletedObjects(IDList: TBoldObjectIdList); +var + i: integer; + TranslationList: TBoldIdTranslationList; +begin + TranslationList := TBoldIdTranslationList.Create; + try + PersistenceController.PMExactifyIDs(IdList, TranslationList, true); + for I := TranslationList.Count - 1 downto 0 do + if TranslationList.NewIds[i].NonExisting then + IdList.Remove(IdList.IDByID[TranslationList.OldIds[i]]); + finally + TranslationList.Free; + end; +end; + { TBoldObject } + function TBoldObject.GetDeriveMethodForMember(Member: TBoldMember): TBoldDeriveAndResubscribe; +begin + Result := GetDeriveMethodForMember(Member.BoldmemberRTInfo.Index); +end; + +function TBoldObject.GetDeriveMethodForMember(MemberIndex: Integer): TBoldDeriveAndResubscribe; begin result := nil; - if Member.BoldmemberRTInfo.IsDerived and - (Member.BoldMemberRTInfo.DeriveExpression <> '') then - result := Member.CalculateDerivedMemberWithExpression; end; function TBoldObject.GetReverseDeriveMethodForMember(Member: TBoldMember): TBoldReverseDerive; +begin + result := GetReverseDeriveMethodForMember(Member.BoldmemberRTInfo.Index); +end; + +function TBoldObject.GetReverseDeriveMethodForMember(MemberIndex: Integer): TBoldReverseDerive; begin result := nil; end; function TBoldObject.GetBoldMembers(index: Integer): TBoldMember; + procedure InternalRaise; + var + ID: String; + begin + if Assigned(FBoldObjectLocator) then + ID := FBoldObjectLocator.BoldObjectID.AsString + else + ID := '(NoID)'; + raise EBold.CreateFmt('%s[Id=%s].GetBoldMembers: Index out of range (%d but max is %d)', [ClassName, id, Index, BoldMemberCount-1]); + end; +var + MemberRTInfo: TBoldMemberRTInfo; begin - if (index < 0) or (index >= BoldMemberCount) then - raise EBold.CreateFmt(sIndexOutOfRange, [ClassName, 'GetBoldMembers', Index, BoldMemberCount]); // do not localize - Result := FDynamicData^[index]; + if Cardinal(index) >= Cardinal(Length(fMemberArray)) then + InternalRaise; + Result := fMemberArray[index]; if not assigned(result) then begin - if (BoldObjectLocator.BoldObjectID.TimeStamp <> BOLDMAXTIMESTAMP) and + if IsHistoricVersion and BoldClassTypeInfo.AllMembers[index].IsNonVersionedInVersionedClass then result := AtTime(BOLDMAXTIMESTAMP).BoldMembers[index] else begin - result := CreateMemberByIndex(index); - fDynamicData^[index] := result; - InitializeMember(result, BoldClassTypeInfo.AllMembers[index] {MemberRTInfo}, GetElementFlag(befObjectWasCreatedNew)); + MemberRTInfo := BoldClassTypeInfo.AllMembers[Index]; + result := TBoldMemberClass(MemberRTInfo.MemberClass).CreateAsObjectPart(Self, MemberRTInfo); + fMemberArray[index] := result; + InitializeMember(result, MemberRTInfo, GetElementFlag(befObjectWasCreatedNew)); end; end; end; -function TBoldObject.GetBoldMemberAssigned(Index: integer): Boolean; +function TBoldObject.GetBoldMemberDeriver(Member: TBoldMember): TBoldMemberDeriver; +var + index: integer; + procedure InternalRaise; + begin + raise EBold.CreateFmt('%s[Id=%s].GetBoldMemberDeriver: Index out of range (%d but max is %d)', [ClassName, self.FBoldObjectLocator.BoldObjectID.AsString, Index, BoldClassTypeInfo.DerivedMemberCount-1]); + end; +begin + index := Member.BoldMemberRTInfo.DeriverIndex; + if Cardinal(index) >= Cardinal(Length(fDeriverArray)) then + begin + if Cardinal(index) >= Cardinal(BoldClassTypeInfo.DerivedMemberCount) then + InternalRaise; + SetLength(fDeriverArray, BoldClassTypeInfo.DerivedMemberCount); + end; + result := fDeriverArray[index]; + if not Assigned(Result) then + begin + Result := TBoldMemberDeriver.Create(Member); + fDeriverArray[index] := Result; + Member.HasDeriver := True; + end; + +end; + +function TBoldObject.SafeGetBoldMemberAssigned(Index: integer): Boolean; begin - if (index < 0) or (index >= BoldMemberCount) then - raise EBold.CreateFmt(sIndexOutOfRange, [ClassName, 'GetBoldMemberAssigned', Index, BoldMemberCount]); // do not localize - result := assigned(fDynamicData^[Index]); + result := assigned(fMemberArray[Index]); +end; + +function TBoldObject.GetBoldMemberIfAssigned(index: Integer): TBoldMember; +begin + if Cardinal(Index) >= Cardinal(Length(fMemberArray)) then + raise EBold.CreateFmt('%s.GetBoldMemberIfAssigned: Index out of range (%d but max is %d)', [ClassName, Index, BoldMemberCount-1]); + Result := fMemberArray[index]; end; function TBoldObject.GetBoldObjectIsDeleted: Boolean; @@ -2311,17 +3381,10 @@ function TBoldObject.GetBoldObjectIsDeleted: Boolean; function TBoldObject.GetBoldObjectIsNew: Boolean; begin - // newly created and yet not stored obejcts result := (BoldExistenceState = besExisting) and (BoldPersistenceState = bvpsModified); - // transient objects result := result or (BoldPersistenceState = bvpsTransient); end; -function TBoldObject.GetBoldMemberCount: Integer; -begin - Result := BoldClassTypeInfo.AllMembersCount; -end; - function TBoldObject.GetStringRepresentation(Representation: TBoldRepresentation): string; begin if BoldClassTypeInfo.defaultstringrepresentation <> '' then @@ -2332,7 +3395,7 @@ function TBoldObject.GetStringRepresentation(Representation: TBoldRepresentation (BoldMembers[Representation] is TBoldAttribute) then Result := BoldMembers[Representation].AsString else - Result := Format('%s:%s', [BoldObjectLocator.AsString, BoldClassTypeInfo.ModelName]); // do not localize + Result := Format('%s:%s', [BoldObjectLocator.AsString, BoldClassTypeInfo.ModelName]); end; end; @@ -2350,8 +3413,8 @@ procedure TBoldObject.SubscribeToStringRepresentation(Representation: TBoldRepre function TBoldObject.GetBoldSystem: TBoldSystem; begin - Assert(OwningElement is TBoldSystem); Result := TBoldSystem(OwningElement); + Assert(result is TBoldSystem); end; function TBoldObject.GetAsIBoldObjectContents(Mode: TBoldDomainElementProxyMode): IBoldObjectContents; @@ -2359,46 +3422,25 @@ function TBoldObject.GetAsIBoldObjectContents(Mode: TBoldDomainElementProxyMode) ProxyInterface(IBoldObjectContents, Mode, result); end; - -function TBoldObject.CreateMemberByIndex(Index: integer): TBoldMember; -var - MemberRTInfo: TBoldMemberRTInfo; -begin - MemberRTInfo := BoldClassTypeInfo.AllMembers[Index]; - result := TBoldMemberClass(MemberRTInfo.MemberClass).InternalCreate(Self, MemberRTInfo, - GetElementFlag(befObjectWasCreatedNew) and not MemberRTInfo.IsDerived); -end; - procedure TBoldObject.InitializeObject(System: TBoldSystem; ClassTypeInfo: TBoldClassTypeInfo; Locator: TBoldObjectLocator; Persistent: Boolean); -var - DynamicDataSize: integer; begin if ClassTypeInfo.IsAbstract then - raise EBold.CreateFmt(sCannotInstansiateAbstractClass, [ClassTypeInfo.ExpressionName]); + raise EBold.CreateFmt('%s.InitializeObject: Can''t instansiate abstract class', [ClassTypeInfo.ExpressionName]); if ClassTypeInfo.IsImported then - raise EBold.CreateFmt(sCannotInstansiateImportedClass, [ClassTypeInfo.ExpressionName]); + raise EBold.CreateFmt('%s.InitializeObject: Can''t instansiate imported class', [ClassTypeInfo.ExpressionName]); fBoldClassTypeInfo := ClassTypeInfo; SetElementFlag(befObjectWasCreatedNew, not Assigned(Locator)); SetElementFlag(befPersistent, System.BoldPersistent and ClassTypeInfo.Persistent and Persistent); - SetElementFlag(befStoresTimeStamp, BoldClassTypeInfo.OptimisticLocking = bolmTimeStamp); - - DynamicDataSize := GetDynamicDataSize; - if DynamicDataSize > 0 then - begin - fDynamicData := BoldMemoryManager_.AllocateMemory(DynamicDataSize); - FillChar(fDynamicData^, DynamicDataSize, 0); - end else - fDynamicData := nil; - - if BoldStoresTimeStamp then - fDynamicData^[BoldMemberCount] := Pointer(-1); // marco added ^ x3 + SetLength(fMemberArray, BoldMemberCount); + fTimeStamp := -1; if Assigned(Locator) then begin FBoldObjectLocator := Locator; BoldObjectLocator.FBoldObject := Self; BoldObjectLocator.EmbeddedSingleLinksToObject; + SetElementFlag(befIsHistoricVersion, BoldObjectLocator.BoldObjectID.TimeStamp <> BOLDMAXTIMESTAMP); end else begin @@ -2409,16 +3451,65 @@ procedure TBoldObject.InitializeObject(System: TBoldSystem; ClassTypeInfo: TBold ToBeRemovedClassAccessed; end; +procedure TBoldMember.InitializeStateToModified; +begin + SetInternalState(BoldPersistenceStateMask, BoldPSShift, Integer(bvpsModified)); +end; + +procedure TBoldMember.InitializeStateToInvalid; +begin + SetInternalState(BoldPersistenceStateMask, BoldPSShift, Integer(bvpsInvalid)); +end; + +function TBoldMember.GetBoldPersistenceState: TBoldValuePersistenceState; +begin + result := TBoldValuePersistenceState((StateAndFlagBank and BoldPersistenceStateMask) shr BoldPSShift); +end; + +procedure TBoldMember.InitializeStateToTransient; +begin + SetInternalState(BoldPersistenceStateMask, BoldPSShift, Integer(bvpsTransient)); +end; + +procedure TBoldMember.InitializeStateToCurrent; +begin + SetInternalState(BoldPersistenceStateMask, BoldPSShift, Integer(bvpsCurrent)); +end; + +function TBoldAttribute.GetAttributeTypeInfoForType: TBoldElementTypeInfo; +begin + result := FindASystem.BoldSystemTypeInfo.AttributeTypeInfoByDelphiName[Self.ClassName] +end; + +function TBoldAttribute.GetBoldAttributeRTInfo: TBoldAttributeRTInfo; +begin + Result := TBoldAttributeRTInfo(BoldMemberRTInfo); + Assert((not Assigned(result)) or (result is TBoldAttributeRTInfo)); +end; + procedure TBoldObject.InitializeMember(Member: TBoldMember; MemberRTInfo: TBoldMemberRTInfo; IsNewObject: Boolean); begin if IsNewobject then begin {New object} - if Member.BoldPersistent then - Member.InitializeStateToModified + if MemberCanBeModified(MemberRtInfo, BoldSystem) then + begin + if Member.BoldPersistent then + Member.InitializeStateToModified + else + Member.InitializeStateToTransient; + Member.DoSetInitialValue; + end else if Member.Derived then Member.InitializeStateToInvalid + else if Member.BoldPersistent then // Non-embedded Role starts as current since noone has associations to a new object + begin + Member.InitializeStateToCurrent; + end else + begin Member.InitializeStateToTransient; + Member.DoSetInitialValue; + end; end else begin {Old object} @@ -2430,15 +3521,13 @@ procedure TBoldObject.InitializeMember(Member: TBoldMember; MemberRTInfo: TBoldM (TBoldRoleRTInfo(MemberRTInfo).roleType in [rtInnerLinkRole, rtLinkRole]) then Member.InitializeStateToInvalid else + begin Member.InitializeStateToTransient; + if Assigned(Member.BoldMemberRTInfo) and Member.BoldMemberRTInfo.IsAttribute and TBoldAttribute(Member).BoldAttributeRtInfo.HasInitialValue then + Member.DoSetInitialValue; + end; end; - if IsNewObject and not memberRTInfo.IsDerived then - Member.DoSetInitialValue; - - if memberRTInfo.IsDerived and (MemberRTInfo.DeriveExpression <> '') then - Member.Deriver.OnDeriveAndSubscribe := Member.CalculateDerivedMemberWithExpression; - if MemberRTInfo.ToBeRemoved and not IsNewObject then ToBeRemovedMemberAccessed(MemberRTInfo); end; @@ -2448,7 +3537,7 @@ constructor TBoldObject.InternalCreateWithClassAndLocator(ClassTypeInfo: TBoldCl SetInternalState(BoldExistenceStateMask, BoldESShift, Integer(besExisting)); SetInternalState(BoldPersistenceStateMask, BoldPSShift, Integer(bvpsInvalid)); Assert(Assigned(Locator.BoldSystem)); - inherited Create(Locator.BoldSystem); + inherited CreateWithOwner(Locator.BoldSystem); InitializeObject(Locator.BoldSystem, ClassTypeInfo, Locator, True); EndReCreate; end; @@ -2458,46 +3547,60 @@ constructor TBoldObject.Create(AOwningElement: TBoldDomainElement; Persistent: B System: TBoldSystem; aClass: TBoldClassTypeInfo; begin + IsEffectiveInvalidKnown := false; SetInternalState(BoldExistenceStateMask, BoldESShift, Integer(besNotCreated)); SetInternalState(BoldPersistenceStateMask, BoldPSShift, Integer(bvpsCurrent)); if AOwningElement = nil then begin System := TBoldSystem.DefaultSystem; if not assigned(system) then - raise EBold.CreateFmt(sNoDefaultSystem, [ClassName]); + raise EBold.CreateFmt('%s.Create: unable to find a default system', [ClassName]); end else if AOwningElement is TBoldSystem then System := TBoldSystem(AOwningElement) else - raise EBold.CreateFmt(sOwningElementMustBeSystem, [ClassName]); + raise EBold.CreateFmt('%s.Create: OwningElement must be a TBoldSystem', [ClassName]); aClass := System.BoldSystemTypeInfo.TopSortedClasses.ItemsByObjectClass[ClassType]; if not assigned(aClass) then begin if not System.BoldSystemTypeInfo.UseGeneratedCode then - raise EBold.CreateFmt(sGeneratedCodeNotUsed + BOLDCRLF + - sGeneratedCode_HowToFix, + raise EBold.CreateFmt('%s.Create: The system does not use generated code...' + BOLDCRLF + + 'You must use BoldSystem.CreateNewObjectByExpressionName (or tell the SystemTypeInfoHandle to use the generated code)', [ClassName]) else - raise EBold.CreateFmt(sNoClassInformation, [ClassName, classname]) + raise EBold.CreateFmt('%s.Create: Unknown error, unable to find class information for %s', [ClassName, classname]) end; if aClass.IsLinkClass then - raise EBold.CreateFmt(sCannotCreateAssociationClass, [classname]); + raise EBold.CreateFmt('%s.Create: Cannot create instance of association class', [classname]); InternalCreateNewWithClassAndSystem(aClass, System, Persistent); end; -procedure TBoldObject.ReceiveEventFromOwned(originator: TObject; originalEvent: TBoldEvent); + +procedure TBoldObject.ReceiveEventFromOwned(originator: TObject; originalEvent: TBoldEvent; const Args: array of const); begin if (BoldExistenceState = besExisting) and (originalEvent in beValueEvents) then - SendEvent(beMemberChanged); - + SendExtendedEvent(beMemberChanged, [Originator]); +{$IFDEF BoldSystemBroadcastMemberEvents} + if (BoldExistenceState = besExisting) and + (originalEvent in beBroadcastMemberEvents) then + BoldSystem.ReceiveEventFromOwned(Originator, OriginalEvent, Args); // broadcast member events through BoldSystem +{$ENDIF} if (originalEvent in beValueEvents) and assigned(BoldSystem.NewModifiedList) and (not (Originator is TBoldMember) or (not TBoldMember(Originator).Derived)) then BoldSystem.NewModifiedList.Add(self); end; +{$IFNDEF BOLD_NO_QUERIES} +function TBoldObject.ReceiveQueryFromOwned(Originator: TObject; + OriginalEvent: TBoldEvent; const Args: array of const; + Subscriber: TBoldSubscriber): Boolean; +begin + result := SendQuery(OriginalEvent, Args, Subscriber, Originator); +end; +{$ENDIF} destructor TBoldObject.Destroy; var I: Integer; @@ -2505,7 +3608,6 @@ destructor TBoldObject.Destroy; begin if BoldExistenceState = besNotCreated then begin - // OwningElement might not be set if constructor failed if assigned(OwningElement) then begin if assigned(BoldObjectLocator) then @@ -2521,19 +3623,15 @@ destructor TBoldObject.Destroy; else begin if Assigned(BoldObjectLocator) then - raise EBold.CreateFmt(sIllegalDirectDestruction, [ClassName]); + raise EBold.CreateFmt('%s.Destroy: Can''t destroy a BoldObject directly. ' + + 'Call Id.Unload to unload from memory or Delete to delete object', [ClassName]); end; PrepareToDestroy; - - if Assigned(fDynamicData) then - begin - for i := 0 to BoldMemberCount - 1 do - if GetBoldMemberAssigned(i) then - BoldMembers[i].Free; - BoldMemorymanager_.DeAllocateMemory(fDynamicData, GetDynamicDataSize); - end; - + FreeDerivers; + for i := 0 to Length(fMemberArray) - 1 do + FreeAndNil(fMemberArray[i]); + SetLength(fMemberArray, 0); inherited Destroy; end; @@ -2541,34 +3639,54 @@ procedure TBoldObject.DefaultSubscribe(Subscriber: TBoldSubscriber; RequestedEve begin end; -procedure TBoldObject.UnLinkAll; +procedure TBoldObject.InternalUnLinkAll(AUnlinkPersistent: boolean); var - M: Integer; - MemberRTInfo: TBoldMemberRTInfo; + i, MemberIndex: Integer; + RoleRTInfo: TBoldRoleRTInfo; + Saved: boolean; begin - for M := 0 to BoldClassTypeInfo.AllMembers.Count - 1 do + Saved := BoldObjectLocator.BoldObjectID.IsStorable; + for i := 0 to BoldClassTypeInfo.AllRoles.Count - 1 do begin - MemberRTInfo := BoldClassTypeInfo.AllMembers[M]; - if MemberRTInfo.IsRole and MemberRTInfo.IsDerived then + RoleRTInfo := BoldClassTypeInfo.AllRoles[i]; + MemberIndex := RoleRTInfo.index; + if not Saved and not SafeGetBoldMemberAssigned(MemberIndex) then + continue; // can skip nil members if not persistent + if RoleRTInfo.IsDerived then + begin + if SafeGetBoldMemberAssigned(MemberIndex) then + BoldMembers[MemberIndex].Invalidate; + end + else if not AUnlinkPersistent and not RoleRTInfo.Persistent then begin - if GetBoldMemberAssigned(m) then - BoldMembers[m].Invalidate; + // do not discard transient roles end - else if MemberRTInfo.isMultiRole then + else if RoleRTInfo.isMultiRole then begin - if ((MemberRTInfo as TBoldRoleRTInfo).RoleType = rtRole) and - ((BoldMembers[M] as TBoldObjectList).Count <> 0) then - (BoldMembers[M] as TBoldObjectList).Clear; + if (RoleRTInfo.RoleType = rtRole) and + ((BoldMembers[MemberIndex] as TBoldObjectList).Count <> 0) then + (BoldMembers[MemberIndex] as TBoldObjectList).Clear; end - else if MemberRTInfo.isSingleRole then + else if RoleRTInfo.isSingleRole then begin - if ((MemberRTInfo as TBoldRoleRTInfo).RoleType = rtRole) and - assigned((BoldMembers[M] as TBoldObjectReference).Locator) then - (BoldMembers[M] as TBoldObjectReference).Clear; + if (RoleRTInfo.RoleType = rtRole) and + assigned((BoldMembers[MemberIndex] as TBoldObjectReference).Locator) then + (BoldMembers[MemberIndex] as TBoldObjectReference).Clear; end; end; end; +procedure TBoldObject.UnLinkAll; +begin + InternalUnLinkAll(True); +end; + +procedure TBoldObject.UnLinkAllPersistent; +begin + InternalUnLinkAll(False); +end; + +{$IFNDEF CompareToOldValues} procedure TBoldObject.MarkObjectDirty; var i: integer; @@ -2576,14 +3694,13 @@ procedure TBoldObject.MarkObjectDirty; if BoldDirty then exit; for i := 0 to BoldMemberCount - 1 do - if GetBoldMemberAssigned(i) and + if SafeGetBoldMemberAssigned(i) and BoldMembers[i].BoldMemberRTInfo.IsStoredInObject and (BoldMembers[i].BoldPersistenceState = bvpsCurrent) then begin BoldMembers[i].MarkMemberDirty; exit; end; - // if we could not find a loaded member, then take the first that is persistent. for i := 0 to BoldMemberCount - 1 do if BoldMembers[i].BoldMemberRTInfo.IsStoredInObject and (BoldMembers[i].BoldPersistenceState = bvpsCurrent) then @@ -2591,12 +3708,15 @@ procedure TBoldObject.MarkObjectDirty; BoldMembers[i].MarkMemberDirty; exit; end; - raise EBold.CreateFmt(sNoPersistentMembers, [classname]); + raise EBold.CreateFmt('%s.MarkObjectDirty: There are no persistent members', [classname]); end; +{$ENDIF} procedure TBoldObject.ReRead; begin - Invalidate; +// Invalidate; +// patch - do not invalidate, it invalidates all members, just fetch instead +// fetching will update only members with fresh value from db, leaving unomdified members valid BoldSystem.SystemPersistenceHandler.FetchObjectById(BoldObjectLocator.BoldObjectID); end; @@ -2678,7 +3798,7 @@ function TBoldObject.InternalCanDelete(CheckedObjects: TBoldDomainElementCollect if not result then begin - SetBoldLastFailureReason(TBoldFailureReason.Create(sObjectIsreadOnly, self)); + SetBoldLastFailureReason(TBoldFailureReason.Create('Object is read only', self)); exit; end; @@ -2693,22 +3813,34 @@ function TBoldObject.InternalCanDelete(CheckedObjects: TBoldDomainElementCollect begin Assert(MemberRTInfo is TBoldRoleRTInfo); RoleRTInfo := TBoldRoleRTInfo(MemberRTInfo); - // in a transient system links that do not exist must be empty - if BoldSystem.BoldPersistent or GetBoldMemberAssigned(i) then + if BoldSystem.BoldPersistent or SafeGetBoldMemberAssigned(i) then begin if not RoleRTInfo.IsDerived and (RoleRTInfo.RoleType = rtRole) then begin case RoleRTInfo.DeleteAction of - daCascade: result := not cascade or (result and CascadeCanDelete(BoldMembers[i])); - daAllow: ; // do nothing - daProhibit: result := result and CheckEmpty(BoldMembers[i]); + daCascade: + begin + result := not cascade or (result and CascadeCanDelete(BoldMembers[i])); + if not result then + SetBoldLastFailureReason(TBoldFailureReason.Create('Related object via associationEnd ' + BoldMembers[i].DisplayName + ' has denied cascade delete.', self)); + end; + daAllow: ; + daProhibit: + begin + result := result and CheckEmpty(BoldMembers[i]); + if not result then + SetBoldLastFailureReason(TBoldFailureReason.Create('Object is related to other objects via associationEnd:'+ BoldMembers[i].DisplayName + ' and has DeleteAction set to daProhibit.', self)); + end; end; end else begin - // linkobjects will always be deleted when the original object is deleted, so we must cascade the question if RoleRTInfo.RoleType = rtLinkRole then - result := result and CascadeCanDelete(BoldMembers[i]) ; + begin + result := result and CascadeCanDelete(BoldMembers[i]); + if not result then + SetBoldLastFailureReason(TBoldFailureReason.Create('LinkObject:'+ BoldMembers[i].DisplayName + ' denied cascade delete.', self)); + end; end; if not result then break; @@ -2717,9 +3849,17 @@ function TBoldObject.InternalCanDelete(CheckedObjects: TBoldDomainElementCollect end; if result then - result := SendQuery(bqMayDelete, [], nil) and BoldSystem.CanDeleteObject(self) - else - SetBoldLastFailureReason(TBoldFailureReason.Create(sObjectHasRelations, self)); + begin + result := BoldSystem.CanDeleteObject(self); +{$IFNDEF BOLD_NO_QUERIES} + result := Result and BoldSystem.CanDeleteObject(self); +{$ENDIF} + end; +end; + +function TBoldObject.InternalCanDeleteObject: Boolean; +begin + Result := True; end; function TBoldObject.CanDelete: Boolean; @@ -2765,50 +3905,119 @@ procedure TBoldObject.Delete; if Member is TBoldObjectList then TBoldObjectList(Member).Clear else if member is TBoldObjectReference then - TBoldObjectReference(member).BoldObject := nil; + TBoldObjectReference(member).Clear; + end; + + procedure PreFetchLinks; + var + i: integer; + vRoleRTInfo: TBoldRoleRTInfo; + LinkList: TStringList; + begin + if not BoldPersistent then + exit; + LinkList := TStringList.Create; + try + for i := 0 to BoldClassTypeInfo.AllRolesCount - 1 do + begin + vRoleRTInfo := BoldClassTypeInfo.AllRoles[i]; + if not vRoleRTInfo.IsDerived and (vRoleRTInfo.RoleType in [rtRole, rtInnerLinkRole]) then + case vRoleRTInfo.DeleteAction of + daCascade, daAllow: + LinkList.Add(vRoleRTInfo.ExpressionName); + end; + end; + finally + BoldSystem.FetchMembersWithObject(Self, LinkList.CommaText); +// BoldSystem.FetchLinksWithObjects(AList, LinkList.CommaText); + LinkList.free; + end; end; procedure DoDelete; var - MemberRTInfo: TBoldMemberRTInfo; RoleRTInfo: TBoldRoleRTInfo; i: integer; begin - for i := 0 to BoldMemberCount - 1 do +// PreFetchLinks; + for i := 0 to BoldClassTypeInfo.AllRolesCount - 1 do begin - MemberRTInfo := BoldClassTypeInfo.AllMembers[i]; - - if MemberRTInfo.IsRole then - begin - Assert(MemberRTInfo is TBoldRoleRTInfo); - RoleRTInfo := TBoldRoleRTInfo(MemberRTInfo); + RoleRTInfo := BoldClassTypeInfo.AllRoles[i]; if not RoleRTInfo.IsDerived and (RoleRTInfo.RoleType in [rtRole, rtInnerLinkRole]) then begin case RoleRTInfo.DeleteAction of - daCascade: CascadeDelete(BoldMembers[i]); - daAllow: ClearRelation(BoldMembers[i]); - daProhibit: ;// do nothing, should always be empty by now + daCascade: + begin + if BoldPersistent or BoldMemberAssigned[RoleRTInfo.index] then + CascadeDelete(BoldMembers[RoleRTInfo.index]); + end; + daAllow: + begin + if BoldPersistent or BoldMemberAssigned[RoleRTInfo.index] then + ClearRelation(BoldMembers[RoleRTInfo.index]); + end; + daProhibit: ; + end; + end; + end; + end; + +{$IFNDEF NoAutoSubscription} + procedure ProcessDeleteInDerivation; + var + i: integer; + begin + // Clear any Members of deleted object that were acccesed during derivation + // and were supposed to be subscribed to in MemberDerivationEnd + with BoldSystem.fMembersReadDuringDerivation do + for i := 0 to Count - 1 do + if (Items[i] <> nil) and (TBoldMember(Items[i]).OwningObject = self) then + Items[i] := nil; + LogDerivationDeleteSideEffects(self); + end; +{$ENDIF} +begin + if (not Deleting) and (not DeletingOrDeletingByDiscard) then begin + BoldSystem.DelayObjectDestruction; + Deleting := True; + try + BoldClearLastFailure; + if InternalCanDeleteObject then begin + BoldSystem.IncrementDeletingObjectsDepth; + try + BoldSystem.StartTransaction(stmNormal); + try + if not StartDelete then + BoldRaiseLastFailure(self, 'Delete', 'StartDelete precondition not met'); + DoDelete; + EndDelete; + {$IFNDEF NoAutoSubscription} + if BoldSystem.IsDerivingMembers then + ProcessDeleteInDerivation; + {$ENDIF} + BoldSystem.CommitTransaction(stmNormal); + except + FailDelete; + BoldSystem.RollbackTransaction(stmNormal); + raise; end; + finally + BoldSystem.DecrementDeletingObjectsDepth; end; end; + finally + Deleting := False; + BoldSystem.AllowObjectDestruction; end; end; +end; +function TBoldObject.GetDeletingOrDeletingByDiscard: Boolean; begin - BoldClearLastFailure; - if not StartDelete then - BoldRaiseLastFailure(self, 'Delete', sPreconditionNotMet); // do not localize - try - BoldSystem.StartTransaction(stmNormal); - DoDelete; - EndDelete; - BoldSystem.CommitTransaction(stmNormal); - except - FailDelete; - BoldSystem.RollbackTransaction(stmNormal); - raise; - end; + Result := Deleting or + (Discarding and BoldObjectIsNew) or + BoldObjectIsDeleted; end; function TBoldObject.FindBoldMemberByExpressionName(const Name: string): TBoldMember; @@ -2826,7 +4035,7 @@ function TBoldObject.GetBoldMemberByExpressionName(const Name: string): TBoldMem begin Result := FindBoldMemberByExpressionName(Name); if not Assigned(Result) then - raise EBold.CreateFmt(sNoSuchMember, [ClassName, Name]); + raise EBold.CreateFmt('%s: No member named %s', [ClassName, Name]); end; function TBoldObject.GetBoldMemberIndexByExpressionName(const Name: string): Integer; @@ -2850,7 +4059,7 @@ function TBoldObject.IsEqualAs(CompareType: TBoldCompareType; BoldElement: TBold Result := BoldElement = Self; end; else - raise EBold.CreateFmt(sUnknownCompareType, [ClassName, 'IsEqualAs']); // do not localize + raise EBold.CreateFmt('%s.IsEqualAs: Unknown CompareType', [ClassName]); end; end; @@ -2859,7 +4068,7 @@ procedure TBoldObject.GetAsList(ResultList: TBoldIndirectElement); NewList: TBoldList; begin Assert(BoldType.SystemTypeInfo is TBoldSystemTypeInfo); - NewList := TBoldObjectList.CreateWithTypeInfo(TBoldSystemTypeInfo(BoldType.SystemTypeInfo).ListTypeInfoByElement[BoldType]); + NewList := BoldClassTypeInfo.ListTypeInfo.CreateElement as TBoldList; NewList.Add(Self); NewList.MakeImmutable; ResultList.SetOwnedValue(NewList); @@ -2887,6 +4096,7 @@ procedure TBoldObject.EndReCreate; begin SetBoldExistenceState(besExisting); SetBoldPersistenceState(bvpsCurrent); + CompleteRecreate; sendevent(beObjectFetched); end; @@ -2902,7 +4112,7 @@ function TBoldObject.StartDelete: Boolean; begin g := TBoldGuard.Create(List); if not (BoldExistenceState = besExisting) then - StateError('StartDelete'); // do not localize + StateError('StartDelete'); list := TBoldDomainElementCollection.Create; result := InternalCanDelete(list, false); @@ -2918,7 +4128,7 @@ procedure TBoldObject.EndDelete; SetBoldExistenceState(besDeleted); case BoldPersistenceState of bvpsModified: SetBoldPersistenceState(bvpsCurrent); - bvpsTransient: ; // do nothing + bvpsTransient: ; bvpsCurrent: SetBoldPersistenceState(bvpsModified); end; if BoldPersistenceState <> bvpsModified then @@ -2944,11 +4154,12 @@ function TBoldObject.GetBoldDirty: Boolean; end; end; -{ -function TBoldObject.GetEffectiveInvalid: Boolean; +function TBoldObject.CalculateEffectiveInvalid: Boolean; var i: Integer; + Member: TBoldMemberRTInfo; begin + if GetElementFlag(befObjectWasCreatedNew) then begin result := false; @@ -2957,23 +4168,56 @@ function TBoldObject.GetEffectiveInvalid: Boolean; for i := 0 to BoldMemberCount - 1 do begin - if (not BoldClassTypeInfo.AllMembers[i].DelayedFetch) and - (BoldClassTypeInfo.AllMembers[i].Persistent) and - (not GetBoldMemberAssigned(i) or (BoldMembers[i].BoldPersistenceState = bvpsInvalid)) then + if (not SafeGetBoldMemberAssigned(i) or (BoldMembers[i].BoldPersistenceState = bvpsInvalid)) then begin - result := True; - exit; + Member := BoldClassTypeInfo.AllMembers[i]; + if (not Member.DelayedFetch) and (Member.Persistent) then + begin + result := True; + exit; + end; end; end; result := False; end; -} + +function TBoldObject.GetEffectiveInvalid: Boolean; +begin + if not IsEffectiveInvalidKnown then + begin + IsEffectiveInvalid := CalculateEffectiveInvalid; + IsEffectiveInvalidKnown := true; + end; + result := IsEffectiveInvalid; +end; + +procedure TBoldObject.FreeDerivers; +var + i: integer; + Deriver: TBoldMemberDeriver; +begin + for I := 0 to Length(fDeriverArray) - 1 do + begin + Deriver := fDeriverArray[i]; + if Assigned(Deriver) then + begin + Deriver.DerivedMember.HasDeriver := false; + Deriver.Free; + fDeriverArray[i] := nil; + end; + end; + SetLength(fDeriverArray, 0); +end; + procedure TBoldObject.MemberBecomingModified(BoldMember: TBoldMember); begin MemberModified := true; MemberModifiedKnown := true; BoldSystem.MarkObjectDirty(self); + BoldMember.SendExtendedEvent(beMemberBecomingDirty, [BoldMember]); + if BoldSystem.IsDerivingMembers then + LogDerivationSideEffects(BoldMember); end; procedure TBoldObject.MemberBecomingClean(BoldMember: TBoldMember); @@ -2981,10 +4225,27 @@ procedure TBoldObject.MemberBecomingClean(BoldMember: TBoldMember); if MemberModified then begin MemberModifiedKnown := False; + BoldMember.SendExtendedEvent(beMemberBecomingClean, [BoldMember]); BoldSystem.MarkObjectPossiblyCleaner(self); end; end; +procedure TBoldObject.MemberChangingValidity(BoldMemberRtInfo: TBoldMemberRtInfo; NewValue: TBoldValuePersistenceState); +begin + if (not IsEffectiveInvalidKnown) then + Exit; + if (BoldMemberRtInfo.DelayedFetch) or (not BoldMemberRtInfo.Persistent) then + Exit; + if (NewValue = bvpsInvalid) then + begin + IsEffectiveInvalid := true; + IsEffectiveInvalidKnown := true; + end + else + if IsEffectiveInvalidKnown then + IsEffectiveInvalidKnown := false; +end; + procedure TBoldObject.CalculateMemberModified; var i: Integer; @@ -2994,11 +4255,11 @@ procedure TBoldObject.CalculateMemberModified; if BoldPersistent then for i := 0 to BoldMemberCount - 1 do begin - if GetBoldMemberAssigned(i) then + if SafeGetBoldMemberAssigned(i) then MemberModified := BoldMembers[i].BoldDirty else MemberModified := GetElementFlag(befObjectWasCreatedNew) and - BoldClassTypeInfo.AllMembers[i].IsStoredInObject and + MemberCanBeModified(BoldClassTypeInfo.AllMembers[i], BoldSystem) and Assigned(BoldSystem.PersistenceController); if MemberModified then Exit; @@ -3007,12 +4268,15 @@ procedure TBoldObject.CalculateMemberModified; procedure TBoldObject.CompleteCreate; begin - // intentionally left blank end; +procedure TBoldObject.CompleteReCreate; +begin +end; + + procedure TBoldObject.CompleteUpdate; begin - // intentionally left blank end; @@ -3023,7 +4287,6 @@ function TBoldObject.MayUpdate: Boolean; procedure TBoldObject.PrepareUpdate; begin - // intentionally left blank end; function TBoldObject.MayDelete: Boolean; @@ -3032,6 +4295,17 @@ function TBoldObject.MayDelete: Boolean; end; procedure TBoldObject.PrepareDelete; +begin +end; + +procedure TBoldObject.PrepareDiscard; +begin + if BoldObjectIsNew then begin + InternalPrepareDeleteOrDeleteByDiscard; + end; +end; + +procedure TBoldObject.InternalPrepareDeleteOrDeleteByDiscard; begin // intentionally left blank end; @@ -3044,6 +4318,7 @@ procedure TBoldObject.DoStartDelete; procedure TBoldObject.DoStartUpdate; begin +// SendEvent(bePrepareUpdate); PrepareUpdate; PrepareUpdateMembers; end; @@ -3068,10 +4343,7 @@ function TBoldObject.MayUpdateMembers: Boolean; begin for i := 0 to BoldMemberCount - 1 do begin - // we should add a guard here that checks BoldMemberAssigned. - // a nonassigned member can reasonably not prevent an update - // do not add this until enough testing can be performed prior to release - if MemberProhibitsUpdate(BoldMembers[i]) then + if SafeGetBoldMemberAssigned(i) and MemberProhibitsUpdate(BoldMembers[i]) then begin result := False; exit; @@ -3086,7 +4358,7 @@ procedure TBoldObject.EndUpdateMembers(Translationlist: TBoldIdTranslationlist); Member: TBoldMember; begin for i := 0 to BoldMemberCount - 1 do - if GetBoldMemberAssigned(i) then + if SafeGetBoldMemberAssigned(i) then begin Member := BoldMembers[i]; if Member.BoldPersistent and @@ -3172,29 +4444,41 @@ function TBoldObject.MayFetchMembers(MemberIdList: TBoldMemberIdList): Boolean; procedure TBoldObject.EndFetchMembers(MemberIdList: TBoldMemberIdList); - procedure IfNecessaryEndFetchMember(Member: TBoldMember); + procedure IfNecessaryEndFetchMember(aBoldMember: TBoldMember); {$IFDEF BOLD_INLINE} inline; {$ENDIF} begin - if assigned(Member) and (Member.BoldPersistenceState = bvpsInvalid) then - Member.BoldPersistenceState := bvpsCurrent; + if Assigned(aBoldMember) and (aBoldMember.BoldPersistenceState = bvpsInvalid) then + begin + aBoldMember.BoldPersistenceState := bvpsCurrent; + end; end; var i: Integer; - aMember: TBoldMember; + MemberRtInfo: TBoldMemberRTInfo; begin if assigned(MemberIdList) then + begin for i := 0 to MemberIdList.Count - 1 do - IfNecessaryEndFetchMember(BoldMembers[MemberIdList[i].MemberIndex]) + IfNecessaryEndFetchMember(BoldMembers[MemberIdList[i].MemberIndex]); + end else + begin for i := 0 to BoldMemberCount - 1 do begin - if not BoldClassTypeInfo.AllMembers[i].DelayedFetch then + memberRtInfo := BoldClassTypeInfo.AllMembers[i]; + if not memberRtInfo.DelayedFetch and + not MemberRtInfo.IsDerived then begin - aMember := BoldMembers[i]; - if aMember.BoldPersistent then - IfNecessaryEndFetchMember(aMember); + if BoldMembers[i].BoldPersistent then + IfNecessaryEndFetchMember(BoldMembers[i]); end; end; + end; +end; + +procedure TBoldObject.BeforeDiscard; +begin + Inc(BoldSystem.FDiscardCount); end; procedure TBoldObject.BoldMakePersistent; @@ -3204,17 +4488,17 @@ procedure TBoldObject.BoldMakePersistent; if not BoldPersistent then begin if BoldPersistenceState <> bvpsTransient then - StateError('BoldMakePersistent'); // do not localize + StateError('BoldMakePersistent'); if not Assigned(BoldClassTypeInfo) or (not BoldClassTypeInfo.Persistent) or (not BoldSystem.BoldPersistent) then - raise EBold.CreateFmt(sCannotMakePersistent, [ClassName]); + raise EBold.CreateFmt('%s: Can''t make object persistent', [ClassName]); if BoldClassTypeInfo.IsLinkClass then for i := BoldClassTypeInfo.FirstOwnMemberIndex to BoldMemberCount - 1 do if BoldMembers[i].BoldMemberRTInfo.IsSingleRole and (TBoldRoleRTInfo(BoldMembers[i].BoldMemberRTInfo).RoleType = rtInnerLinkRole) and not (BoldMembers[i] as TBoldObjectReference).Locator.ObjectIsPersistent then - raise EBold.CreateFmt(sCannotMakeLinkPersistent, [Classname]); + raise EBold.CreateFmt('%s: Can''t make link object persistent. Linked object is transient.', [Classname]); SetElementFlag(befPersistent, true); SetBoldPersistenceState(bvpsModified); @@ -3231,16 +4515,20 @@ procedure TBoldObject.SetIsReadOnly(NewValue: Boolean); function TBoldObject.GetTimeStamp: TBoldTimeStampType; begin - if BoldStoresTimeStamp then - result := TBoldTimeStampType(fDynamicData^[BoldMemberCount]) - else - result := -1; + result := fTimeStamp; end; procedure TBoldObject.SetTimeStamp(NewValue: TBoldTimeStampType); +var + OldTimeStamp: TBoldTimeStampType; begin - if BoldStoresTimeStamp then - fDynamicData^[BoldMemberCount] := Pointer(NewValue); + if fTimeStamp <> NewValue then + begin + OldTimeStamp := fTimeStamp; + fTimeStamp := NewValue; + if OldTimeStamp <> -1 then // this will not send event on initial fetch, only on subsequent ones + SendExtendedEvent(beObjectTimestampChanged, [OldTimeStamp, NewValue]); + end; end; function TBoldObject.GetObjectHasSubscribers: Boolean; @@ -3258,40 +4546,47 @@ function TBoldObject.GetObjectHasSubscribers: Boolean; procedure TBoldObject.StateError(S: String); begin - inherited StateError(format('%s (ExistenceState: %s PersistenceState: %s)', // do not localize - [s, GetEnumName(TypeInfo(TBoldExistenceState), Ord(BoldExistenceState)), + inherited StateError(format('%s ID:%s (ExistenceState: %s PersistenceState: %s)', + [s, BoldObjectLocator.AsString, GetEnumName(TypeInfo(TBoldExistenceState), Ord(BoldExistenceState)), GetEnumName(TypeInfo(TBoldValuePersistenceState), Ord(BoldPersistenceState))])); end; procedure TBoldObject.ToBeRemovedMemberAccessed(MemberRTInfo: TBoldMemberRTInfo); begin - BoldLog.LogFmt(sToBeRemovedAccessed, [dateTimeToStr(now), BoldClassTypeInfo.ExpressionName, MemberRTInfo.ExpressionName]); + BoldLog.LogFmt('%s: Accessed member flagged as "ToBeRemoved": %s.%s', [dateTimeToStr(now), BoldClassTypeInfo.ExpressionName, MemberRTInfo.ExpressionName]); end; procedure TBoldObject.ToBeRemovedMemberModified(MemberRTInfo: TBoldMemberRTInfo); begin - BoldLog.LogFmt(sToBeRemovedModified, [dateTimeToStr(now), BoldClassTypeInfo.ExpressionName, MemberRTInfo.ExpressionName]); + BoldLog.LogFmt('%s: Modified member flagged as "ToBeRemoved": %s.%s', [dateTimeToStr(now), BoldClassTypeInfo.ExpressionName, MemberRTInfo.ExpressionName]); end; procedure TBoldObject.ToBeRemovedClassAccessed; begin - BoldLog.LogFmt(sToBeRemovedObjectAccessed, [dateTimeToStr(now), BoldClassTypeInfo.ExpressionName]); + BoldLog.LogFmt('%s: Accessed an object flagged as "ToBeRemoved": %s', [dateTimeToStr(now), BoldClassTypeInfo.ExpressionName]); end; constructor TBoldObject.InternalCreateNewWithClassAndSystem( ClassTypeInfo: TBoldClassTypeInfo; aSystem: TBoldSystem; Persistent: Boolean); begin +{$IFDEF NoTransientInstancesOfPersistentClass} + if not Persistent and ClassTypeInfo.Persistent and aSystem.BoldPersistent then + raise EBold.Create('Transient instance of persistent class not allowed due to conditional define NoTransientInstancesOfPersistentClass.'); +{$ENDIF} + IsEffectiveInvalidKnown := false; if not aSystem.CanCreateObject(ClassTypeInfo) then - BoldRaiseLastFailure(aSystem, 'InternalCreateNewWithClassAndSystem', // do not localize - format(sCannotCreateOfType, [ClassTypeInfo.ExpressionName])); + BoldRaiseLastFailure(aSystem, 'InternalCreateNewWithClassAndSystem', + format('System does not allow creating objects of type %s', [ClassTypeInfo.ExpressionName])); aSystem.StartTransaction(stmNormal); try SetInternalState(BoldExistenceStateMask, BoldESShift, Integer(besNotCreated)); SetInternalState(BoldPersistenceStateMask, BoldPSShift, Integer(bvpsCurrent)); - inherited Create(aSystem); + inherited CreateWithOwner(aSystem); InitializeObject(aSystem, ClassTypeInfo, nil, Persistent); EndCreate; aSystem.CommitTransaction(stmNormal); + if BoldSystem.IsDerivingMembers then + LogDerivationCreateSideEffects(self); except aSystem.RollbackTransaction(stmNormal); raise; @@ -3305,17 +4600,17 @@ function TBoldObject.GetBoldType: TBoldElementTypeInfo; function TBoldObject.CanUpdate: Boolean; begin - result := MayUpdate and SendQuery(bqMayUpdate, [], nil); -end; - -function TBoldObject.GetIsReadOnly: Boolean; -begin - result := GetElementFlag(befObjectReadOnly); + result := MayUpdate; +{$IFNDEF BOLD_NO_QUERIES} + result := result and SendQuery(bqMayUpdate, [], nil); +{$ENDIF} end; function TBoldObject.GetDisplayName: String; begin - result := ClassName; + result := BoldType.AsString; // not inherited as typically we want ClassName instead of BusinessClasses.ClassName + if Assigned(BoldObjectLocator) then + result := '['+BoldObjectLocator.AsString + ']' + result; end; function TBoldObject.GetEvaluator: TBoldEvaluator; @@ -3327,7 +4622,7 @@ function TBoldObject.CanUnload: Boolean; begin result := not BoldDirty; if not result then - SetBoldLastFailureReason(TBoldFailureReason.create(sObjectIsDirty, self)); + SetBoldLastFailureReason(TBoldFailureReason.create('Object is dirty', self)); end; procedure TBoldObject.Invalidate; @@ -3335,40 +4630,70 @@ procedure TBoldObject.Invalidate; i: Integer; begin if BoldDirty then - raise EBold.CreateFmt(sCannotInvalidateDirtyObject, [classname]); - for i := 0 to BoldMemberCount - 1 do - if BoldMembers[i].BoldPersistent then - BoldMembers[i].Invalidate; + raise EBold.CreateFmt('%s.Invalidate: Can''t invalidate dirty object, use discard first', [classname]); + for i := 0 to BoldClassTypeInfo.AllMembersCount - 1 do + if BoldClassTypeInfo.AllMembers[i].Persistent and BoldMembers[i].BoldPersistent then + BoldMembers[i].Invalidate; end; -procedure TBoldObject.Discard; +procedure TBoldObject.InternalDiscard(ADiscardPersistentLinks: boolean); var i: Integer; begin - if BoldSystem.fTransactionNesting <> 0 then - raise EBold.Create(sCannotDiscardInTransaction); - - if not BoldObjectLocator.BoldObjectID.IsStorable then - UnlinkAll; + if (not Discarding) and (not Deleting) then begin + BoldSystem.DelayObjectDestruction; + Discarding := True; + BeforeDiscard; + try + if BoldSystem.fTransactionNesting <> 0 then + raise EBold.Create('Can not discard an object while the system inside a transaction'); + PrepareDiscard; + if not BoldObjectLocator.BoldObjectID.IsStorable then + begin + if ADiscardPersistentLinks then + UnlinkAll + else + UnLinkAllPersistent; + end; - for i := 0 to BoldMemberCount - 1 do - if BoldMemberAssigned[i] then - BoldMembers[i].InternalDiscard; + for i := 0 to BoldMemberCount - 1 do + if BoldMemberAssigned[i] then + begin + // if ADiscardPersistentLinks = false then do not discard non persistent roles + if ADiscardPersistentLinks or not (BoldMembers[i].BoldMemberRTInfo.IsRole and not BoldMembers[i].BoldPersistent) then + BoldMembers[i].InternalDiscard; + end; - if BoldObjectIsNew then - begin - SetBoldExistenceState(besDeleted); - SetBoldPersistenceState(bvpsCurrent); - BoldSystem.DestroyObject(self); - end - else if (BoldPersistenceState = bvpsModified) and - (BoldExistenceState = besDeleted) then - begin - SetBoldExistenceState(besExisting); - SetBoldPersistenceState(bvpsCurrent); + if BoldObjectIsNew then + begin + SetBoldExistenceState(besDeleted); + SetBoldPersistenceState(bvpsCurrent); + BoldSystem.DestroyObject(self); + end + else if (BoldPersistenceState = bvpsModified) and + (BoldExistenceState = besDeleted) then + begin + SetBoldExistenceState(besExisting); + SetBoldPersistenceState(bvpsCurrent); + end; + finally + AfterDiscard; + Discarding := False; + BoldSystem.AllowObjectDestruction; + end; end; end; +procedure TBoldObject.Discard; +begin + InternalDiscard(true); +end; + +procedure TBoldObject.DiscardPersistentMembers; +begin + InternalDiscard(false); +end; + procedure TBoldObject.SetBoldExistenceState(Value: TBoldExistenceState); begin if Value <> BoldExistenceState then @@ -3400,28 +4725,23 @@ procedure TBoldObject.SetBoldPersistenceState(Value: TBoldValuePersistenceState) end; end; -function TBoldObject.GetBoldExistenceState: TBoldExistenceState; -begin - result := TBoldExistenceState(GetInternalState(BoldExistenceStateMask, BoldESShift)); -end; - -function TBoldObject.GetBoldPersistenceState: TBoldValuePersistenceState; -begin - result := TBoldValuePersistenceState(GetInternalState(BoldPersistenceStateMask, BoldPSShift)); -end; - function TBoldObject.ProxyInterface(const IId: TGUID; Mode: TBoldDomainElementProxyMode; out Obj): Boolean; begin if IsEqualGuid(IID, IBoldObjectContents) then begin - result := TBoldObject_Proxy.create(self, Mode).GetInterface(IID, obj); + result := TBoldObject_Proxy.Create(self, Mode).GetInterface(IID, obj); if not result then - raise EBoldInternal.CreateFmt(sInterfaceNotImplemented, [ClassName]); + raise EBoldInternal.CreateFmt('ProxyClass for %s did not implement IBoldObjectContents', [ClassName]); end else result := inherited ProxyInterface(IID, Mode, Obj); end; +procedure TBoldObject.AfterDiscard; +begin + Dec(BoldSystem.FDiscardCount); +end; + function TBoldObject.AtTime(Time: TBoldTimestampType): TBoldObject; begin result := BoldObjectLocator.AtTime(time).EnsuredBoldObject; @@ -3437,7 +4757,7 @@ procedure TBoldObject.PrepareUpdateMembers; i: integer; begin for i := 0 to BoldMemberCount - 1 do - if GetBoldMemberAssigned(i) and BoldMembers[i].BoldDirty then + if SafeGetBoldMemberAssigned(i) and BoldMembers[i].BoldDirty then BoldMembers[i].PrepareUpdate; end; @@ -3447,43 +4767,47 @@ function TBoldObject.GetBoldObjectExists: Boolean; end; function TBoldObject.ValidateMember(const ObjectDelphiName, MemberDelphiName: String; GeneratedMemberIndex: integer; MemberClass: TBoldMemberClass): Boolean; + + procedure InternalRaise(ExceptionClass: ExceptClass; const Msg: string; const Args: array of const); + begin + raise ExceptionClass.CreateFmt(Msg, args) + end; + +const + sValidate_NoSuchMember = 'Class %s has no member %s. (Generated code might be out of sync with model)'; + sValidate_MemberNotAssigned = 'Unable to access member %s.%s: %0:s is not assigned!'; + sValidate_WrongMember = 'Class %s member at index %d is %s, expected %s. (Generated code might be out of sync with model)'; + sValidate_MemberIndexOutOfSync = 'Member indexes in generated code out of sync with model (%s.%s has %d in code and %d in model)'; + sValidate_InvalidMemberType = 'Invalid member type for %s.%s. Expected %s, was %s (Generated code might be out of sync with model)'; + sValidate_InternalError = 'Internal Error: Member %s.%s is not assigned'; var Member: TBoldMember; MemberRTInfo: TBoldMemberRTInfo; begin if not assigned(self) then - raise EBold.CreateFmt(sValidate_MemberNotAssigned, - [ObjectDelphiName, MemberDelphiName]); - - MemberRTInfo := BoldClassTypeInfo.AllMembers.ItemsByDelphiName[MemberDelphiName] as TBoldMemberRTInfo; - - if not assigned(MemberRTInfo) then - raise EBold.CreateFmt(sValidate_NoSuchMember, - [ObjectDelphiName, MemberDelphiName]); - - if (GeneratedMemberIndex <> -1) and (MemberRTInfo.index <> GeneratedMemberIndex) then - raise EBold.CreateFmt(sValidate_MemberIndexOutOfSynch, [ - ObjectDelphiName, MemberDelphiName, GeneratedMemberIndex, MemberRTInfo.index]); + InternalRaise(EBold, sValidate_MemberNotAssigned, [ObjectDelphiName, MemberDelphiName, ObjectDelphiName]); - Member := BoldMembers[MemberRTInfo.index]; + if Cardinal(GeneratedMemberIndex) >= Cardinal(BoldMemberCount) then + begin + MemberRTInfo := BoldClassTypeInfo.AllMembers.ItemsByDelphiName[MemberDelphiName] as TBoldMemberRTInfo; + if not assigned(MemberRTInfo) then + InternalRaise(EBold, sValidate_NoSuchMember, [ObjectDelphiName, MemberDelphiName]); + InternalRaise(EBold, sValidate_MemberIndexOutOfSync, [ObjectDelphiName, MemberDelphiName, GeneratedMemberIndex, MemberRTInfo.index]); + end; + Member := BoldMembers[GeneratedMemberIndex]; if not assigned(Member) then - raise EBoldInternal.CreateFmt('Internal Error: Member %s.%s is not assigned', - [ObjectDelphiName, MemberDelphiName]); + InternalRaise(EBoldInternal, sValidate_InternalError, [ObjectDelphiName, MemberDelphiName]); if not (Member is MemberClass) then - raise EBold.CreateFmt(sValidate_InvalidMemberType, - [ObjectDelphiName, MemberDelphiName, MemberClass.ClassName, Member.ClassName]); + InternalRaise(EBold, sValidate_InvalidMemberType, [ObjectDelphiName, MemberDelphiName, MemberClass.ClassName, Member.ClassName]); - result := true; -end; + MemberRTInfo := Member.BoldMemberRTInfo; -function TBoldObject.GetDynamicDataSize: Integer; -begin - Result := BoldMemberCount * SizeOf(Pointer); + if MemberRTInfo.DelphiName <> MemberDelphiName then + InternalRaise(EBold, sValidate_WrongMember, [ObjectDelphiName, GeneratedMemberIndex, MemberDelphiName, MemberRTInfo.DelphiName]); - if BoldStoresTimeStamp then - Result := Result + SizeOf(TBoldTimeStampType); + result := true; end; procedure TBoldObject.ClearTouched; @@ -3516,107 +4840,227 @@ function TBoldMember.GetStreamName: string; raise EBoldInternal.Createfmt('%s.GetStreamName: Method is abstract, please implement', [classname]); end; -function TBoldMember.GetBoldMemberRTInfo: TBoldMemberRTInfo; +function TBoldMember.GetFreeStandingClass: TBoldFreeStandingElementClass; begin - if OwnedByObject then - begin - assert(fBoldMetaType is TBoldMemberRtInfo); - result := TBoldMemberRTInfo(fBoldMetaType); - end - else - result := nil; + raise EBoldInternal.Createfmt('%s.GetFreeStandingClass: Method is abstract, please implement', [classname]); +end; + +function TBoldMember.GetDeriverState: TBoldDeriverState; +begin + result := TBoldDeriverState(GetInternalState(BoldDerivationStateMask, BoldDSShift)); +end; + +procedure TBoldMember.SetDeriverState(value: TBoldDeriverState); +begin + SetInternalState(BoldDerivationStateMask, BoldDSShift, integer(Value)); end; -constructor TBoldMember.InternalCreate(OwningObject: TBoldObject; MemberRTInfo: TBoldMemberRTInfo; SetInitialValue: Boolean); +constructor TBoldMember.CreateAsObjectPart(OwningObject: TBoldObject; MemberRTInfo: TBoldMemberRTInfo); begin + inherited CreateWithOwner(OwningObject); fBoldMetaType := MemberRTInfo; OwnedByObject := True; - - if assigned(MemberRtInfo) then + SetElementFlag(befPersistent, OwningObject.BoldPersistent and MemberRTInfo.Persistent); + if MemberRTInfo.IsDerived then begin - InitializeMember(OwningObject, MemberRTInfo.BoldType); + DeriverState := bdsSubscriptionOutOfDate; + SetElementFlag(befDerived, true); end else - InitializeMember(OwningObject, nil); + SetElementFlag(befDerived, false); + Initialize; +end; + +procedure TBoldMember.DeriveMember(Subscriber: TBoldSubscriber); +begin + if IsPartOfSystem then + BoldSystem.MemberDerivationBegin(self); + try + if BoldmemberRTInfo.IsDerived and + (BoldMemberRTInfo.DeriveExpression <> '') then + CalculateDerivedMemberWithExpression(Subscriber) + else + CalculateDerivedMemberWithDeriveMethod(Subscriber); + IsPreFetched := false; + finally + if IsPartOfSystem then + BoldSystem.MemberDerivationEnd(self); + end; end; destructor TBoldMember.Destroy; +{$IFNDEF NoAutoSubscription} +// Clear any references to member in list of accesed members during derivation + procedure ClearDerivationReferences; + var + i: integer; + begin + with BoldSystem.fMembersReadDuringDerivation do + for i := 0 to Count - 1 do + if Items[i] = self then +// if (Items[i] <> nil) and (TBoldMember(Items[i]) = self) then + Items[i] := nil; + end; +{$ENDIF} begin +{$IFNDEF NoAutoSubscription} + if Assigned(OwningObject) and BoldSystem.IsDerivingMembers then + ClearDerivationReferences; +{$ENDIF} PrepareToDestroy; - if HasDeriver then - G_ExternalDerivers.ReferencedObjects[self] := nil; inherited Destroy; end; -function TBoldMember.GetOwningObject: TBoldObject; -begin - if OwnedByObject then - begin - Assert(OwningElement is TBoldObject); - Result := TBoldObject(OwningElement) - end - else +procedure TBoldMember.CalculateDerivedMemberWithDeriveMethod( + Subscriber: TBoldSubscriber); +var + DeriveMethod: TMethod; + {$IFDEF EXPRESSION_OVERRIDES_DOUBLE_DERIVE} + Expression, s: string; + ie: TBoldIndirectElement; + nonMatch: boolean; + + function DerivationMatches(oclValue: TBoldElement): boolean; + var + selfasList, valueAsList: TBoldObjectList; + i: Integer; begin - Assert(not (OwningElement is TBoldObject)); - Result := nil; + if (self is TBoldObjectReference) then + begin + if oclValue = nil then + Result := ((self as TBoldObjectReference).Locator = nil) + else if oclValue is TBoldObject then + Result := oclvalue = (self as TBoldObjectReference).BoldObject + else if oclValue is TBoldObjectReference then + Result := (oclvalue as TBoldObjectReference).Locator = (self as TBoldObjectReference).Locator + else + Result := false; + end + else if (self is TBoldObjectList) and (oclValue is TBoldObjectList) then + begin + selfAsList := self as TBoldObjectList; + valueAsList := oclValue as TBoldObjectList; + if selfAsList.Count <> valueAsList.Count then + Result := false + else + begin + Result := true; + for I := 0 to selfAsList.Count - 1 do + if selfAsList[i] <> valueAsList[i] then + Result := false; + end; + end + else if IsEqual(oclValue) then + Result := true + else if (self is TBAFLoat) and + (oclValue is TBAFLoat) and + (abs((self as TBAFLoat).AsFloat - (oclValue as TBAFLoat).asFloat) < 0.011) then + result := true + else + result := false; end; -end; - -function TBoldMember.GetBoldSystem: TBoldSystem; +{$ENDIF} begin - if OwnedByObject then + DeriveMethod.Code := BoldmemberRTInfo.Derivemethod; + if DeriveMethod.Code = nil then begin - Assert(OwningElement is TBoldObject); - Result := TBoldObject(OwningElement).BoldSystem + DeriveMethod := TMethod(OwningObject.GetDeriveMethodForMember(Self)); + BoldmemberRTInfo.Derivemethod := DeriveMethod.Code; + if BoldmemberRTInfo.Derivemethod = nil then + raise EBoldInternal.CreateFmt('Derivation method not found for %s, check model.', [displayName]); end - else if not assigned(OwningElement) then - result := nil else - begin - Assert(OwningElement is TBoldSystem); - result := TBoldSystem(OwningElement) - end; + DeriveMethod.Data := OwningObject; + TBoldDeriveAndResubscribe(DeriveMethod)(self, Subscriber); + {$IFDEF EXPRESSION_OVERRIDES_DOUBLE_DERIVE} + Expression := TExpressionOverride.GetOclDerivationForCodeDerived(self.BoldMemberRTInfo); + if Expression <> '' then + begin + ie := TBoldIndirectElement.Create; + try + try + OwningObject.evaluateAndSubscribeToExpression(Expression, subscriber, ie, false); + if Assigned(ie.Value) and (ie.value is TBoldmember) then + TBoldMember(ie.value).EnsureContentsCurrent; + nonMatch := true; + + if not DerivationMatches(ie.Value) then + raise EBold.Create(Format('OclDerivationOverride for %s.%s gives %s, code gives %s', + [BoldMemberRTInfo.ClassTypeInfo.ExpressionName, BoldMemberRTInfo.ExpressionName, ie.Value.AsString, AsString])); + nonmatch := false; + except + on e: Exception do + begin + if not nonmatch then + begin + if Assigned(OwningObject) then + s := 'ID:' + OwningObject.BoldObjectLocator.AsString + else + s := 'not owned.' + s := format('Failed to derive %s: %s' + BOLDCRLF + + 'OCL expression: %s' + BOLDCRLF + + 'Owner: %s' + BOLDCRLF + + 'Error: %s', [DisplayName, BoldType.AsString, Expression, s, e.Message]); + if assigned(ie.value) and not ie.value.BoldType.conformsto(boldtype) then + s := format(s + BOLDCRLF+ + 'Possible Reason: %s does not conform to %s', [ie.value.BoldType.AsString, boldtype.AsString]); + raise EBold.Create(s); + end; + end; + end; + finally + FreeAndNil(ie); + end; + end; + {$ENDIF} end; -procedure TBoldMember.CalculateDerivedMemberWithExpression(DerivedObject: TObject; Subscriber: TBoldSubscriber); +procedure TBoldMember.CalculateDerivedMemberWithExpression(Subscriber: TBoldSubscriber); var ie: TBoldIndirectElement; - g: IBoldGuard; + Expression: string; s: string; begin - g := TBoldGuard.Create(ie); ie := TBoldIndirectElement.Create; try - OwningObject.evaluateAndSubscribeToExpression(BoldMemberRTInfo.DeriveExpression, subscriber, ie, false); - if Assigned(ie.Value) and (ie.value is TBoldmember) then - TBoldMember(ie.value).EnsureContentsCurrent; - AssignContentValueFromElement(ie.Value); - except - on e: Exception do - begin - s := format(sFailedToDerive + BOLDCRLF + - sOCLExpressionError, [DisplayName, BoldType.AsString, BoldMemberRTInfo.DeriveExpression, e.Message]); - if assigned(ie.value) and not ie.value.BoldType.conformsto(boldtype) then - s := format(s + BOLDCRLF+ - sPossiblyBadConformance, [ie.value.BoldType.AsString, boldtype.AsString]); - raise EBold.Create(s); + try + {$IFDEF EXPRESSION_OVERRIDES} + Expression := TExpressionOverride.GetOclDerivationOverride(self.BoldMemberRTInfo); + if Expression = '' then + {$ENDIF} + Expression := BoldMemberRTInfo.DeriveExpression; + OwningObject.evaluateAndSubscribeToExpression(Expression, subscriber, ie, false); + if Assigned(ie.Value) and (ie.value is TBoldmember) then + TBoldMember(ie.value).EnsureContentsCurrent; + AssignContentValueFromElement(ie.Value); + except + on e: Exception do + begin + s := format('Failed to derive %s: %s (ID:%s)' + BOLDCRLF + + 'OCL expression: %s' + BOLDCRLF + + 'Error: %s', [DisplayName, BoldType.AsString, OwningObject.BoldObjectLocator.AsString, Expression, e.Message]); + if assigned(ie.value) and not ie.value.BoldType.conformsto(boldtype) then + s := format(s + BOLDCRLF+ + 'Possible Reason: %s does not conform to %s', [ie.value.BoldType.AsString, boldtype.AsString]); + raise EBold.Create(s); + end; end; + finally + FreeAndNil(ie); end; end; function TBoldMember.ProxyInterface(const IId: TGUID; Mode: TBoldDomainElementProxyMode; out Obj): Boolean; begin if IsEqualGuid(IID, IBoldValue) or IsEqualGuid(IID, IBoldStreamable) then - Result := RetrieveProxyInterface(IID, Mode, obj, 'IBoldValue/IBoldStreamable') // do not localize + Result := RetrieveProxyInterface(IID, Mode, obj, 'IBoldValue/IBoldStreamable') else result := inherited ProxyInterface(IID, Mode, Obj); end; function TBoldMember.ObserverMayModify(Observer: TObject): Boolean; begin - Result := CanModify and - ((ModifiedValueHolder = nil) or - (ModifiedValueHolder = Observer)); + result := inherited ObserverMayModify(Observer) and CanModify; end; procedure TBoldMember.GetAsList(ResultList: TBoldIndirectElement); @@ -3640,7 +5084,7 @@ procedure TBoldMember.GetAsValue(ResultElement: TBoldIndirectElement); function TBoldMember.StartModify: Boolean; begin if not (BoldPersistenceState in [bvpsCurrent, bvpsModified, bvpsTransient, bvpsInvalid]) then - StateError('StartModify'); // do not localize + StateError('StartModify'); result := CanModify; if result and assigned(BoldSystem) and assigned(OwningObject) and assigned(BoldSystem.PessimisticLockHandler) and @@ -3648,34 +5092,81 @@ function TBoldMember.StartModify: Boolean; result := BoldSystem.PessimisticLockHandler.LockElement(self); if result then begin - if assigned(OwningObject) and not BoldSystem.InTransaction and StoreInUndo then // Object always has system + if assigned(OwningObject) and not BoldSystem.InTransaction and StoreInUndo then BoldSystem.UndoHandler.HandleMember(OwningObject.AsIBoldObjectContents[bdepContents], BoldMemberRTInfo.Index, AsIBoldValue[bdepContents]); DoStartModify; end; end; + procedure TBoldMember.EndModify; -begin - if (BoldPersistenceState in [bvpsCurrent, bvpsInvalid]) and - assigned(BoldMemberRTInfo) and - (BoldMemberRTInfo.IsStoredInObject or - // this test should be moved to a DataMappingModel, and not the persistenceController - // it is needed for FileMapper since it has to store multilinks - (BoldMemberRTInfo.IsMultiRole and - (assigned(BoldSystem.PersistenceController) and - BoldSystem.PersistenceController.MultilinksAreStoredInObject))) then +{$IFDEF CompareToOldValues} +var + vOldValue: IBoldValue; + function OrdernoDiffers(const Value: IBoldValue; member: TBoldMember):Boolean; begin + Result := (member is TBoldObjectReference) and + (TBoldObjectReference(member).GetController is TBoldDirectSingleLinkController) and + ((Value as IBoldObjectIdRef).OrderNo <> TBoldDirectSingleLinkController(TBoldObjectReference(member).GetController).OrderNo); + end; +{$ENDIF} +var +{$IFDEF ACCESSSTATISTICS} //// START PATCH ACCESSSTATISTICS //////////////////// + G_BoldMemberRTInfo: TBoldMemberRTInfo; + G_OwningElement: TBoldDomainElement; + G_BoldSystem: TBoldSystem; +{$ENDIF} //// END PATCH ACCESSSTATISTICS /////////////////////////////////////// + System: TBoldSystem; +begin + System := BoldSystem; +{$IFNDEF CompareToOldValues} + if (BoldPersistenceState in [bvpsCurrent, bvpsInvalid]) and MemberCanBeModified(BoldMemberRTinfo, System) then BoldPersistenceState := bvpsModified; +{$ELSE} + if (BoldPersistenceState <> bvpsTransient) and OwnedByObject and BoldPersistent then + begin + vOldValue := OldValue; + if Assigned(vOldValue) and IsEqualToValue(vOldValue) and not OrdernoDiffers(vOldValue, self) then + begin + vOldValue := nil; + BoldPersistenceState := bvpsCurrent + end + else + begin + if (BoldPersistenceState <> bvpsModified) and MemberCanBeModified(BoldMemberRTinfo, System) then + BoldPersistenceState := bvpsModified; + end; end; +{$ENDIF} if Derived and not (DeriverState in bdsIsDeriving) then Deriver.ReverseDerive; CompleteModify; - SendEvent(beCompleteModify); - if assigned(OwningObject) then + SendExtendedEvent(beCompleteModify, [self]); + if OwnedByObject then begin - BoldSystem.AddToTransaction(OwningObject); - BoldSystem.AddToTransaction(self); + System.AddToTransaction(OwningObject); + System.AddToTransaction(self); + end; + {$IFDEF ACCESSSTATISTICS} //// START PATCH ACCESSSTATISTICS ////////////////// + //The messy code is for getting better performance /FH + if OwnedByObject then + begin + G_BoldMemberRTInfo := TBoldMemberRTInfo(fBoldMetaType); + G_OwningElement := OwningElement; + if (G_OwningElement<>nil) then + begin + if (G_OwningElement is TBoldObject) then + begin + G_BoldSystem := TBoldSystem(TBoldObject(G_OwningElement).OwningElement); + Inc(G_BoldSystem.fModifyStats[G_BoldMemberRTInfo.ClassTypeInfo.TopSortedIndex, G_BoldMemberRTInfo.index]); + end + else + begin + Inc(TBoldSystem(G_OwningElement).fModifyStats[G_BoldMemberRTInfo.ClassTypeInfo.TopSortedIndex, G_BoldMemberRTInfo.index]); + end; + end; end; + {$ENDIF} //// END PATCH ACCESSSTATISTICS ///////////////////////////////////// end; procedure TBoldMember.FailModify; @@ -3690,7 +5181,6 @@ procedure TBoldMember.EndUpdate(Translationlist: TBoldIdTranslationlist); procedure TBoldMember.AdjustOldValues(Translationlist: TBoldIdTranslationlist); begin - // intentionally left blank end; function TBoldMember.GetBoldDirty: Boolean; @@ -3710,22 +5200,19 @@ function TBoldMember.MayModify: Boolean; procedure TBoldMember.PrepareModify; begin - // intentionally left blank end; procedure TBoldMember.CompleteModify; begin - // intentionally left blank end; procedure TBoldMember.CompleteUpdate; begin - // intentionally left blank end; + procedure TBoldMember.PrepareUpdate; begin - // intentionally left blank end; procedure TBoldMember.DoStartModify; @@ -3744,129 +5231,264 @@ function TBoldMember.CanModify: Boolean; result := Mutable; if not result then begin - SetBoldLastFailureReason(TBoldFailureReason.Create(sMemberIsImmutable, self)); + SetBoldLastFailureReason(TBoldFailureReason.Create('Member is immutable', self)); + exit; + end; + + if assigned(OwningObject) and OwningObject.BoldObjectIsDeleted and not Derived and not OwningObject.Discarding then + begin + Result := false; + SetBoldLastFailureReason(TBoldFailureReason.CreateFmt('Can not modify member %s, owning object is deleted.', [DisplayName], self)); exit; end; result := not IsReadOnly; if not result then begin - SetBoldLastFailureReason(TBoldFailureReason.Create(sMemberIsreadOnly, self)); + SetBoldLastFailureReason(TBoldFailureReason.Create('Member is read only', self)); exit; end; if Derived then - Result := (DeriverState in bdsIsDeriving) or Deriver.CanReverseDerive; + Result := (DeriverState in bdsIsDeriving) or (Deriver.CanReverseDerive); if not result then begin - SetBoldLastFailureReason(TBoldFailureReason.Create(sMemberIsreadOnlyDerived, self)); + SetBoldLastFailureReason(TBoldFailureReason.Create('Member is read-only derived', self)); exit; end; - result := not assigned(OwningObject) or (OwningObject.BoldTime = BOLDMAXTIMESTAMP); - if not result then + if assigned(OwningObject) then begin - SetBoldLastFailureReason(TBoldFailureReason.Create(sMemberIsHistory, self)); - exit; + if OwningObject.IsHistoricVersion then + begin + Result := false; + SetBoldLastFailureReason(TBoldFailureReason.Create('Member belongs to historical object', self)); + exit; + end; end; - result := MayModify and SendQuery(bqMayModify, [], nil); + result := result and MayModify; +{$IFNDEF BOLD_NO_QUERIES} + result := result and SendQuery(bqMayModify, [], nil); +{$ENDIF} end; function TBoldMember.CanUpdate: Boolean; begin - result := InternalMayUpdate and MayUpdate and SendQuery(bqMayUpdate, [], nil); + result := InternalMayUpdate and MayUpdate; +{$IFNDEF BOLD_NO_QUERIES} + result := result and SendQuery(bqMayUpdate, [], nil); +{$ENDIF} +end; + +procedure TBoldMember.DoMarkTouched; +begin + SetElementFlag(befTouched, true); + if assigned(owningObject) then + OwningObject.SetElementFlag(befTouched, true); end; procedure TBoldMember.EnsureContentsCurrent; begin - inherited; - if (BoldPersistenceState = bvpsInvalid) and - not GetElementFlag(befEnsuringCurrent) then - begin - SetElementFlag(befEnsuringCurrent, true); - try - if Derived then - begin - if DeriverState <> bdsCurrent then - Deriver.EnsureCurrent; - if not (DeriverState in bdsIsDeriving) then - BoldPersistenceState := bvpsTransient; - end - else - MakeDbCurrent; - finally - SetElementFlag(befEnsuringCurrent, false); - end; - end; - if not GetElementFlag(befTouched) then - begin - SetElementFlag(befTouched, true); - if assigned(owningObject) then - OwningObject.SetElementFlag(befTouched, true); - end; + if (StateAndFlagBank and BoldPersistenceStateMask) = (Cardinal(bvpsInvalid) shl BoldPSShift) then + DoEnsureContentsCurrent; + if not GetElementFlag(befTouched) then + DoMarkTouched; +{$IFNDEF NoAutoSubscription} + if IsPartOfSystem and BoldSystem.IsDerivingMembers and (BoldSystem.CurrentDerivedMember <> self) and Mutable and not BoldSystem.IsCommitting then + BoldSystem.fMembersReadDuringDerivation.Add(self); +{$ENDIF} +end; + +procedure TBoldMember.DoEnsureContentsCurrent; +{$IFDEF ACCESSSTATISTICS} //// START PATCH ACCESSSTATISTICS //////////////////// +var + G_BoldMemberRTInfo: TBoldMemberRTInfo; + G_OwningElement: TBoldDomainElement; + G_BoldSystem: TBoldSystem; +{$ENDIF} //// END PATCH ACCESSSTATISTICS /////////////////////////////////////// +begin + if not GetElementFlag(befEnsuringCurrent) then + begin + if Derived then + begin + {$IFDEF SpanFetch} + if IsPartOfSystem and not IsPrefetched then + begin + AttracsSpanFetchManager.PrefetchDerivedMember(self); + IsPrefetched := true; + end; + {$ENDIF} + end; + + SetElementFlag(befEnsuringCurrent, true); + try + if Derived then + begin + if DeriverState <> bdsCurrent then + begin + Deriver.EnsureCurrent; + {$IFDEF ACCESSSTATISTICS} //// START PATCH ACCESSSTATISTICS ////////// + //The messy code is for getting better performance /FH + if OwnedByObject then + begin + G_BoldMemberRTInfo := TBoldMemberRTInfo(fBoldMetaType); + G_OwningElement := OwningElement; + if (G_OwningElement<>nil) then + begin + if (G_OwningElement is TBoldObject) then + begin + G_BoldSystem := TBoldSystem(TBoldObject(G_OwningElement).OwningElement); + Inc(G_BoldSystem.fDeriveStats[G_BoldMemberRTInfo.ClassTypeInfo.TopSortedIndex, G_BoldMemberRTInfo.index]); + end + else + begin + Inc(TBoldSystem(G_OwningElement).fDeriveStats[G_BoldMemberRTInfo.ClassTypeInfo.TopSortedIndex, G_BoldMemberRTInfo.index]); + end; + end; + end; + {$ENDIF} //// END PATCH ACCESSSTATISTICS ///////////////////////////// + end; + if not (DeriverState in bdsIsDeriving) then + BoldPersistenceState := bvpsTransient; + end + else + MakeDbCurrent; + finally + SetElementFlag(befEnsuringCurrent, false); + end; + end; + {$IFDEF ACCESSSTATISTICS} //// START PATCH ACCESSSTATISTICS ////////////////// + //The messy code is for getting better performance /FH + if OwnedByObject then + begin + G_BoldMemberRTInfo := TBoldMemberRTInfo(fBoldMetaType); + G_OwningElement := OwningElement; + if (G_OwningElement<>nil) then + begin + if (G_OwningElement is TBoldObject) then + begin + G_BoldSystem := TBoldSystem(TBoldObject(G_OwningElement).OwningElement); + Inc(G_BoldSystem.fAccessStats[G_BoldMemberRTInfo.ClassTypeInfo.TopSortedIndex, G_BoldMemberRTInfo.index]); + end + else + begin + Inc(TBoldSystem(G_OwningElement).fAccessStats[G_BoldMemberRTInfo.ClassTypeInfo.TopSortedIndex, G_BoldMemberRTInfo.index]); + end; + end; + end; + {$ENDIF} //// END PATCH ACCESSSTATISTICS ///////////////////////////////////// + end; procedure TBoldMember.Invalidate; +var + aLinkMember: TBoldMember; +{$IFDEF ACCESSSTATISTICS} //// START PATCH ACCESSSTATISTICS //////////////////// + G_BoldMemberRTInfo: TBoldMemberRTInfo; + G_OwningElement: TBoldDomainElement; + G_BoldSystem: TBoldSystem; +{$ENDIF} //// END PATCH ACCESSSTATISTICS /////////////////////////////////////// begin if not (BoldPersistenceState in [bvpsCurrent, bvpsInvalid, bvpsTransient]) then - StateError('Invalidate'); // do not localize + StateError('Invalidate'); if assigned(BoldMemberRTInfo) and not BoldMemberRTInfo.IsDerived and (BoldPersistenceState = bvpsTransient) then - raise EBold.CreateFmt(sCannotInvalidateTransient, [classname, displayname]); + raise EBold.CreateFmt('%s.Invalidate: Can''t invalidate transient member: %s', [classname, displayname]); if BoldPersistenceState in [bvpsCurrent, bvpsTransient] then begin + if not Derived and OwnedByObject and OwningObject.BoldObjectIsNew then + raise EBold.CreateFmt('%s.Invalidate: Can''t invalidate member of a new unsaved object: %s', [classname, displayname]); BoldPersistenceState := bvpsInvalid; if HasDeriver then Deriver.MarkOutOfdate; FreeContent; SendEvent(beValueInvalid); + {$IFDEF ACCESSSTATISTICS} //// START PATCH ACCESSSTATISTICS ////////////////// + //The messy code is for getting better performance /FH + if OwnedByObject then + begin + G_BoldMemberRTInfo := TBoldMemberRTInfo(fBoldMetaType); + G_OwningElement := OwningElement; + if (G_OwningElement<>nil) then + begin + if (G_OwningElement is TBoldObject) then + begin + G_BoldSystem := TBoldSystem(TBoldObject(G_OwningElement).OwningElement); + Inc(G_BoldSystem.fInvalidateStats[G_BoldMemberRTInfo.ClassTypeInfo.TopSortedIndex, G_BoldMemberRTInfo.index]); + end + else + begin + Inc(TBoldSystem(G_OwningElement).fInvalidateStats[G_BoldMemberRTInfo.ClassTypeInfo.TopSortedIndex, G_BoldMemberRTInfo.index]); + end; + end; + end; + {$ENDIF} //// END PATCH ACCESSSTATISTICS ///////////////////////////////////// + /// + // n:n-associations: always invalidate LinkRole with MainRole. + // On OSS-Sync for example only the MainRole gets invalid. + // Likewise in TBoldObject.Invalidate, because the LinkRole is not persistent. + if (BoldMemberRTInfo is TBoldRoleRTInfo) and + (TBoldRoleRTInfo(BoldMemberRTInfo).IndexOfLinkObjectRole <> -1) then + begin + aLinkMember := OwningObject.BoldMembers[TBoldRoleRTInfo(BoldMemberRTInfo).IndexOfLinkObjectRole]; + if (aLinkMember.BoldPersistenceState <> bvpsModified) and + ((aLinkMember.BoldPersistenceState <> bvpsTransient) or + (aLinkMember.BoldMemberRTInfo.IsDerived)) then + begin + aLinkMember.Invalidate; + end; + end; end; end; function TBoldMember.CanRead(Subscriber: TBoldSubscriber): Boolean; begin - result := SendQuery(bqMayRead, [], Subscriber); -end; - -procedure TBoldMember.InitializeStateToModified; -begin - SetInternalState(BoldPersistenceStateMask, BoldPSShift, Integer(bvpsModified)); -end; - -procedure TBoldMember.InitializeStateToInvalid; -begin - SetInternalState(BoldPersistenceStateMask, BoldPSShift, Integer(bvpsInvalid)); -end; - -function TBoldMember.GetBoldPersistenceState: TBoldValuePersistenceState; -begin - result := TBoldValuePersistenceState(GetInternalState(BoldPersistenceStateMask, BoldPSShift)); + result := true; +// result := SendQuery(bqMayRead, [], Subscriber); end; procedure TBoldMember.SetBoldPersistenceState( Value: TBoldValuePersistenceState); var OldPState: TBoldValuePersistenceState; + OwningObj: TBoldObject; + rtInfo: TBoldMemberRtInfo; begin OldPState := BoldPersistenceState; if Value <> OldPState then begin - if Assigned(OwningObject) then - OwningObject.BoldSystem.fOldValueHandler.MemberPersistenceStatePreChange(self, Value); + OwningObj := OwningObject; + RtInfo := BoldMemberRTInfo; + if Assigned(OwningObj) then + OwningObj.BoldSystem.fOldValueHandler.MemberPersistenceStatePreChange(self, Value); SetInternalState(BoldPersistenceStateMask, BoldPSShift, integer(value)); - if OwnedByObject and BoldMemberRTInfo.IsSingleRole and (not Derived) and (not TBoldObjectReference(self).BoldRoleRTInfo.IsIndirect)and (Value = bvpsInvalid) then - TBoldObjectReference(self).HasOldValues := ((TBoldObjectReference(self).fObjectReferenceController as TBoldDirectSingleLinkController).GetLocator <> nil); - if not derived and assigned(OwningObject) then + if Assigned(OwningObj) and (Value = bvpsInvalid) and RtInfo.IsSingleRole and (not Derived) and (not TBoldObjectReference(self).BoldRoleRTInfo.IsIndirect) then begin + if OwningObj.Discarding then + TBoldObjectReference(Self).HasOldValues := False + else +// Original Bold code was: +// TBoldObjectReference(self).HasOldValues := ((TBoldObjectReference(self).fObjectReferenceController as TBoldDirectSingleLinkController).GetLocator <> nil); +// But this assert can fail: +// Assert(TBoldObjectReference(self).fObjectReferenceController is TBoldDirectSingleLinkController, TBoldObjectReference(self).fObjectReferenceController.CLassName ); +// Controller can also be TBoldLinkObjectReferenceController instead of TBoldDirectSingleLinkController. Both descend from TBoldAbstractObjectReferenceController +// It is not clear if intention here was to only handle TBoldDirectSingleLinkController, or it handle all TBoldAbstractObjectReferenceController descendants ? +// TBoldAbstractObjectReferenceController is used, but needs to be tested + TBoldObjectReference(self).HasOldValues := ((TBoldObjectReference(self).fObjectReferenceController as TBoldAbstractObjectReferenceController).GetLocator <> nil); + end; + if not derived and assigned(OwningObj) then + begin + if (value = bvpsInvalid) or (OldPState = bvpsInvalid) then + OwningObj.MemberChangingValidity(RtInfo, value); if Value = bvpsModified then - OwningObject.MemberBecomingModified(self) + OwningObj.MemberBecomingModified(self) else if OldPState = bvpsModified then - OwningObject.MemberBecomingClean(self); + OwningObj.MemberBecomingClean(self); end; end; end; @@ -3875,23 +5497,9 @@ procedure TBoldMember.MakeDbCurrent; begin end; -function TBoldMember.GetDeriver: TBoldEventPluggedDeriver; +function TBoldMember.GetDeriver: TBoldMemberDeriver; begin - Assert((G_ExternalDerivers.ReferencedObjects[self] = nil) - or (G_ExternalDerivers.ReferencedObjects[self] is TBoldMemberDeriver)); - result := TBoldMemberDeriver(G_ExternalDerivers.ReferencedObjects[self]); - if not Assigned(Result) then - begin - Result := TBoldMemberDeriver.Create(Self); - if assigned(OwningObject) then - begin - result.OnDeriveAndSubscribe := OwningObject.GetDeriveMethodForMember(self); - result.OnReverseDerive := OwningObject.GetReverseDeriveMethodForMember(self); - end; - Result.OnNotifyOutOfdate := _NotifyOutOfDate; - G_ExternalDerivers.ReferencedObjects[Self] := Result; - SetElementFlag(befHasDeriver, True); - end; + Result := OwningObject.GetBoldMemberDeriver(self) end; procedure TBoldMember._NotifyOutOfDate; @@ -3907,7 +5515,7 @@ procedure TBoldMember.StateError(S: String); Membername := '(' + BoldMemberRTInfo.ExpressionName + ') ' else Membername := ''; - inherited StateError(format('%s %s(PersistenceState: %s)', // do not localize + inherited StateError(format('%s %s(PersistenceState: %s)', [s, MemberName, GetEnumName(TypeInfo(TBoldValuePersistenceState), Ord(BoldPersistenceState))])); end; @@ -3949,54 +5557,50 @@ function TBoldMember.Clone: TBoldMember; end; end; -constructor TBoldMember.Create; +procedure TBoldMember.Initialize; begin - InitializeMember(nil, nil); end; -function TBoldMember.GetIsPartOfSystem: Boolean; +procedure TBoldMember.InitializeNonObjectOwned(ElementTypeInfo: TBoldElementTypeInfo); begin - result := OwnedByObject or (OwningElement is TBoldSystem); + SetElementFlag(befPersistent, false); + if assigned(ElementTypeInfo) then + fBoldMetaType := ElementTypeInfo + else + fBoldMetaType := GetElementTypeInfoForType; + Initialize; end; -function TBoldMember.GetIsReadOnly(Flag: TBoldElementFlag): Boolean; +constructor TBoldMember.Create; begin - result := GetElementFlag(Flag) or - (assigned(BoldMemberRTInfo) and BoldMemberRTInfo.IsStoredInObject and OwningObject.IsReadOnly); + inherited CreateWithOwner(nil); + InitializeNonObjectOwned(nil); end; -procedure TBoldMember.InitializeMember(AOwningElement: TBoldDomainElement; - ElementTypeInfo: TBoldElementTypeInfo); -begin - inherited Create(AOwningElement); - - Assert(OwnedByObject = ( assigned(fBoldMetaType) and (fBoldMetaType is TBoldMemberRtInfo))); - if OwnedByObject then - begin - SetElementFlag(befDerived, BoldMemberRTInfo.IsDerived); - SetElementFlag(befPersistent, (AOwningElement is TBoldDomainElement) and TBoldDomainElement(AOwningElement).BoldPersistent and BoldMemberRTInfo.Persistent); - if Derived then - DeriverState := bdsSubscriptionOutOfDate; - end - else +procedure TBoldMember.InternalDiscard; +{$IFNDEF NoAutoSubscription} + procedure ClearDerivationReferences; + var + i: integer; begin - SetElementFlag(befPersistent, false); - if assigned(ElementTypeInfo) then - fBoldMetaType := ElementTypeInfo - else - fBoldMetaType := GetElementTypeInfoForType; + // Clear any references to member from the list of members acccesed during derivation + with BoldSystem.fMembersReadDuringDerivation do + for i := 0 to Count - 1 do + if (Items[i] <> nil) and (TBoldMember(Items[i]) = self) then + Items[i] := nil; end; -end; - -procedure TBoldMember.InternalDiscard; +{$ENDIF} begin if BoldPersistenceState in [bvpsModified, bvpsTransient] then begin PreDiscard; +{$IFNDEF NoAutoSubscription} + if Assigned(BoldSystem) and BoldSystem.IsDerivingMembers then + ClearDerivationReferences; +{$ENDIF} case BoldPersistenceState of bvpsModified: begin - // if the object is not stored yet, then we can not set the member - // to invalid, since it can not be fetched... + if not OwningObject.BoldObjectLocator.BoldObjectID.IsStorable then BoldPersistenceState := bvpsCurrent else @@ -4005,7 +5609,7 @@ procedure TBoldMember.InternalDiscard; FreeContent; SendEvent(beValueInvalid); end; - bvpsTransient: if not Derived then + bvpsTransient: if not Derived and mutable then DoSetInitialValue; end; end; @@ -4016,7 +5620,7 @@ procedure TBoldMember.Discard; if OwningObject.BoldObjectLocator.BoldObjectID.IsStorable then InternalDiscard else - raise EBold.CreateFmt(sCannotDiscardUnsavedSingleLinks, [ClassName]); + raise EBold.CreateFmt('%s.Discard: This is not allowed for single members on objects that are not saved, discard the whole object', [ClassName]); end; procedure TBoldMember.PreDiscard; @@ -4053,15 +5657,12 @@ function TBoldMember.InternalMayUpdate: Boolean; result := True; end; -procedure TBoldMember.InitializeStateToTransient; -begin - SetInternalState(BoldPersistenceStateMask, BoldPSShift, Integer(bvpsTransient)); -end; - procedure TBoldMember.PreChange; begin +{$IFNDEF NoObjectSpaceTransactions} if assigned(OwningObject) and not BoldMemberRTInfo.IsDerived then - OwningObject.BoldSystem.CopyMemberToRollbackBuffer(self); + BoldSystem.CopyMemberToRollbackBuffer(self); +{$ENDIF} end; procedure TBoldMember.DoSetInitialValue; @@ -4089,29 +5690,33 @@ function TBoldMember.CloneIfPossible: TBoldElement; function TBoldMember.RetrieveProxyInterface(const IId: TGUID; Mode: TBoldDomainElementProxyMode; out Obj; const InterfaceName: string): Boolean; begin - result := ProxyClass.create(self, Mode).GetInterface(IID, obj); + result := GetProxy(Mode).GetInterface(IID, obj); if not result then - raise EBoldInternal.CreateFmt(sProxyClassDidNotImplementInterface, [ProxyClass.ClassName, ClassName, InterfaceName]); + raise EBoldInternal.CreateFmt('ProxyClass for %s did not implement %s', [ClassName, InterfaceName]); +end; + +procedure TBoldMember.ReverseDeriveMember; +var + ReverseDeriveMethod: TMethod; +begin + ReverseDeriveMethod.Code := BoldmemberRTInfo.ReverseDeriveMethod; + if ReverseDeriveMethod.Code = nil then + begin + ReverseDeriveMethod := TMethod(OwningObject.GetReverseDeriveMethodForMember(Self)); + BoldmemberRTInfo.ReverseDeriveMethod := ReverseDeriveMethod.Code; + end + else + ReverseDeriveMethod.Data := OwningObject; + TBoldReverseDerive(ReverseDeriveMethod)(self); end; procedure TBoldMember.AssignContentValueFromElement(source: TBoldElement); begin if not assigned(source) then -// AssignContentValue(nil) else if source is TBoldMember then AsIBoldValue[bdepContents].AssignContent(TBoldMember(source).AsIBoldValue[bdepContents]) else - raise EBold.CreateFmt(sUnknownTypeOfSource, [classname, 'AssignContentValuefromElement']); // do not localize -end; - -function TBoldMember.GetDeriverState: TBoldDeriverState; -begin - result := TBoldDeriverState(GetInternalState(BoldDerivationStateMask, BoldDSShift)); -end; - -procedure TBoldMember.SetDeriverState(value: TBoldDeriverState); -begin - SetInternalState(BoldDerivationStateMask, BoldDSShift, integer(Value)); + raise EBold.CreateFmt('%s.AssignContentValuefromElement: Unknown source: %s', [classname, Source.BoldType.AsString]); end; function TBoldMember.GetOldValue: IBoldValue; @@ -4119,7 +5724,7 @@ function TBoldMember.GetOldValue: IBoldValue; ObjectContents: IBoldObjectContents; begin result := nil; - if assigned(OwningObject) and assigned(BoldSystem) then + if OwnedByObject and not OwningObject.BoldObjectIsNew then begin ObjectContents := BoldSystem.fOldValueHandler.OldValues.GetObjectContentsByObjectId(OwningObject.BoldObjectLocator.BoldObjectID) as IBoldObjectContents; if assigned(ObjectContents) then @@ -4136,48 +5741,65 @@ function TBoldMember.MemberHasSubscribers: Boolean; function TBoldMember.StoreInUndo: Boolean; begin - Result := Assigned(BoldMemberRTinfo) and (not BoldMemberRTInfo.IsDerived) and - (BoldMemberRTInfo.IsAttribute or - (TBoldRoleRTInfo(BoldMemberRTInfo).RoleType = rtRole) and(not (TBoldRoleRTInfo(BoldMemberRTInfo).IsMultiRole or TBoldRoleRTInfo(BoldMemberRTInfo).IsIndirect)) or - (TBoldRoleRTInfo(BoldMemberRTInfo).RoleType = rtInnerLinkRole) - ); + Result := Assigned(BoldMemberRTinfo) and BoldMemberRTinfo.StoreInUndo; end; -function TBoldMember.IsEqualToValue(Value: IBoldValue): Boolean; -begin{ TODO : Make part of IBoldVAlue } - raise Ebold.Create(sIsEqualToValueNotImplemented); +function TBoldMember.IsEqualToValue(const Value: IBoldValue): Boolean; +begin + raise Ebold.Create('TBoldMember.IsEqualToValue: not implemented for memberclass ' + ClassName); end; -function TBoldAttribute.IsEqualToValue(Value: IBoldValue): Boolean; +function TBoldAttribute.IsEqualToValue(const Value: IBoldValue): Boolean; var MemberOfSameType: TBoldMember; G: IBoldGuard; -begin{ TODO : Make part of IBoldVAlue } - // Messy - G := TBoldGuard.Create(MemberOfSameType); - if assigned(BoldType) then - MemberOfSameType := TBoldMemberFactory.CreateMemberFromBoldType(BoldType) +{$IFDEF StringAttributeComparison} + s: IBoldStringRepresentable; +{$ENDIF} +begin + Assert(Assigned(Value), ClassName + '.IsEqualToValue: Value can not be nil.'); +{$IFDEF StringAttributeComparison} + if Value.QueryInterface(IBoldStringRepresentable, S) = S_OK then + result := StringCompare(ctDefault, Self.AsString, s.StringRepresentation[brDefault]) = 0 else - MemberOfSameType := TBoldMemberClass(classtype).Create; - MemberOfSameType.AsIBoldValue[bdepContents ].AssignContent(Value); - MemberOfSameType.BoldPersistenceState := bvpsTransient; - Result := IsEqual(MemberOfSameType); +{$ENDIF} + begin + G := TBoldGuard.Create(MemberOfSameType); + if assigned(BoldType) then + MemberOfSameType := TBoldMemberFactory.CreateMemberFromBoldType(BoldType) + else + MemberOfSameType := TBoldMemberClass(classtype).Create; + MemberOfSameType.AsIBoldValue[bdepContents].AssignContent(Value); + MemberOfSameType.BoldPersistenceState := bvpsTransient; + Result := IsEqual(MemberOfSameType); + end; +end; + +function TBoldAttribute.IsVariantTypeCompatible(const Value: Variant): Boolean; +begin + result := true; end; -function TBoldObjectReference.IsEqualToValue(Value: IBoldValue): Boolean; +function TBoldObjectReference.IsEqualToValue(const Value: IBoldValue): Boolean; var IdRef: IBoldObjectIdRef; IdRefPair: IBoldObjectIdRefPair; ValueId : TBoldObjectId; -begin{ TODO : Make part of IBoldVAlue } +begin + Assert(Assigned(Value), ClassName + '.IsEqualToValue: Value can not be nil.'); if Supports(Value, IBoldObjectIdRef,IdRef) then ValueId := Idref.id else if Supports(Value, IBoldObjectIdRefPair,IdRefPair) then - ValueId := IdRefPair.Id1 + begin + if (BoldRoleRTInfo.RoleType = rtRole) and Assigned(BoldRoleRTInfo.LinkClassTypeInfo) then + ValueId := IdRefPair.Id2 + else + ValueId := IdRefPair.Id1 + end else - raise EBoldInternal.Create('Internal error'); + raise EBold.Create('Internal error'); if Assigned(Locator) and Assigned(ValueId) then - Result := Locator.BoldObjectID.IsEqual[ValueId] + Result := Locator.BoldObjectID.IsEqual[ValueId] else Result := (Locator = nil) and (ValueId = nil); end; @@ -4195,18 +5817,12 @@ procedure TBoldAttribute.DefaultSubscribe(Subscriber: TBoldSubscriber; Requested AddSmallSubscription(Subscriber, [beValueChanged, beValueInvalid], RequestedEvent); end; -function TBoldAttribute.GetBoldAttributeRTInfo: TBoldAttributeRTInfo; -begin - Assert((not Assigned(BoldMemberRTInfo)) or (BoldMemberRTInfo is TBoldAttributeRTInfo)); - Result := TBoldAttributeRTInfo(BoldMemberRTInfo); -end; - function TBoldAttribute.GetIsNull: Boolean; begin EnsureContentsCurrent; BoldClearLastFailure; if not CanRead(nil) then - BoldRaiseLastFailure(self, 'GetIsNull', ''); // do not localize + BoldRaiseLastFailure(self, 'GetIsNull', ''); Result := ContentIsNull; end; @@ -4214,12 +5830,12 @@ procedure TBoldAttribute.SetToNull; begin BoldClearLastFailure; if not CanSetToNull(nil) then - BoldRaiseLastFailure(self, 'SetToNull', ''); // do not localize + BoldRaiseLastFailure(self, 'SetToNull', ''); if not IsNull then begin if not StartModify then - BoldRaiseLastFailure(self, 'SetToNull', sStartModifyPreconditionNotMet); // do not localize + BoldRaiseLastFailure(self, 'SetToNull', 'StartModify precondition not met'); try SetContentToNull; EndModify; @@ -4230,10 +5846,59 @@ procedure TBoldAttribute.SetToNull; end; end; + +function UnicodeCompareLen(CaseSensitive: Boolean; s1, s2 : string; n : Integer) : Integer; +const + CSTR_EQUAL = 2; +begin + if CaseSensitive then + Result:=CompareStringEx(nil, 0, PWideChar(s1), n, PWideChar(s2), n, nil, nil, 0)-CSTR_EQUAL + else + Result:=CompareStringEx(nil, NORM_IGNORECASE, PWideChar(s1), n, PWideChar(s2), n, nil, nil, 0)-CSTR_EQUAL +end; + +function UnicodeCompareText(CaseSensitive: Boolean; const s1, s2 : UnicodeString) : Integer; +var + n1, n2, dn : Integer; +begin + if S1<>'' then begin + if S2<>'' then begin + n1:=Length(s1); + n2:=Length(s2); + dn:=n1-n2; + if dn<0 then begin + Result:=UnicodeCompareLen(CaseSensitive, s1, s2, n1); + if Result=0 then + Result:=-1; + end else begin + Result:=UnicodeCompareLen(CaseSensitive, S1, s2, n2); + if (Result=0) and (dn>0) then + Result:=1; + end; + end else Result:=1; + end else if S2<>'' then + Result:=-1 + else Result:=0; +end; + +function TBoldAttribute.StringCompare(CompareType: TBoldCompareType; const s1, s2: string): integer; +begin + case CompareType of + ctDefault, ctCaseInsensitive: + Result := UnicodeCompareText(false, s1, s2); + ctAsString, ctCaseSensitive: + Result := UnicodeCompareText(true, s1, s2); + else + raise EBold.CreateFmt('Unsupported CompareType in StringCompare.', [ClassName]); + end; +end; + function TBoldAttribute.CanSetToNull(Subscriber: TBoldSubscriber): Boolean; begin - result := ((not Assigned(BoldAttributeRTInfo)) or BoldAttributeRTInfo.AllowNull) and - SendQuery(bqMaySetToNull, [], Subscriber); + result := ((not Assigned(BoldAttributeRTInfo)) or BoldAttributeRTInfo.AllowNull); +{$IFNDEF BOLD_NO_QUERIES} + Result := result and SendQuery(bqMaySetToNull, [], Subscriber); +{$ENDIF} if not result then nullfailure; end; @@ -4241,7 +5906,7 @@ function TBoldAttribute.CanSetToNull(Subscriber: TBoldSubscriber): Boolean; function TBoldAttribute.ProxyInterface(const IId: TGUID; Mode: TBoldDomainElementProxyMode; out Obj): Boolean; begin if IsEqualGuid(IID, IBoldNullableValue) then - Result := RetrieveProxyInterface(IID, Mode, obj, 'IBoldNullableValue') // do not localize + Result := RetrieveProxyInterface(IID, Mode, obj, 'IBoldNullableValue') else result := inherited ProxyInterface(IID, Mode, Obj); end; @@ -4251,6 +5916,16 @@ procedure TBoldAttribute.SubscribeToStringRepresentation(Representation: TBoldRe DefaultSubscribe(Subscriber, RequestedEvent); end; +function TBoldAttribute.ValidateVariant(const Value: Variant; + Representation: TBoldRepresentation): Boolean; +begin + result := true; + if VarIsNull(Value) then + result := CanSetToNull(nil) + else if not IsVariantTypeCompatible(Value) then + result := inherited ValidateVariant(Value, Representation); +end; + procedure TBoldAttribute.SetToNonNull; begin SetElementFlag(befIsNull, False); @@ -4259,7 +5934,14 @@ procedure TBoldAttribute.SetToNonNull; procedure TBoldAttribute.EnsureNotNull; begin if IsNull then - raise EBoldAccessNullValue.CreateFmt(sNullValueAccess, [DisplayName]); + begin +{$IFNDEF NoNilAttributeExceptions} + if OwnedByObject then + raise EBoldAccessNullValue.CreateFmt('%s: Attempt to access Value of Attribute that is null. OwningObject: %s', [DisplayName, OwningObject.BoldObjectLocator.AsString]) + else + raise EBoldAccessNullValue.CreateFmt('%s: Attempt to access Value of Attribute that is null', [DisplayName]); +{$ENDIF} + end; end; procedure TBoldAttribute.MakeDbCurrent; @@ -4267,10 +5949,10 @@ procedure TBoldAttribute.MakeDbCurrent; if OwningObject.BoldObjectLocator.BoldObjectID.IsStorable then OwningObject.BoldSystem.SystemPersistenceHandler.FetchMember(self) else - raise EBoldInternal.CreateFmt(sObjectIDIsInternal, [BoldType.AsString]); + raise EBoldInternal.CreateFmt('%s.MakeDbCurrent: Attribute belongs to object with internal ID', [BoldType.AsString]); end; -class function TBoldAttribute.EitherIsNull(Attribute1, Attribute2: TBoldAttribute): Boolean; +class function TBoldAttribute.EitherIsNull(Attribute1, Attribute2: TBoldAttribute): Boolean; begin Result := Attribute1.IsNull or Attribute2.IsNull; end; @@ -4329,12 +6011,19 @@ function TBoldMember.IsInvalid: Boolean; result := BoldPersistenceState = bvpsInvalid; end; +function TBoldMember.GetIsCurrent: Boolean; +begin + result := BoldPersistenceState = bvpsCurrent; +end; + function TBoldMember.GetDisplayName: String; begin if assigned(BoldMemberRTInfo) then - result := BoldMemberRTInfo.ClassTypeInfo.ExpressionName + '.' + BoldMemberRTInfo.ExpressionName + result := BoldMemberRTInfo.ExpressionName else - result := ClassName; + result := inherited GetDisplayName; // ClassName; + if OwnedByObject then + result := OwningObject.DisplayName + '.' + result; end; procedure TBoldAttribute.NullFailure; @@ -4343,23 +6032,37 @@ procedure TBoldAttribute.NullFailure; begin CurrentFailureReason := GetBoldLastFailureReason; if not assigned(CurrentFailureReason) then - SetBoldLastFailureReason(TBoldFailureReason.Create(sNullValueNotAllowed, self)); + SetBoldLastFailureReason(TBoldFailureReason.Create('Null value not allowed', self)); end; procedure TBoldAttribute.FormatFailure(const value, ExpectedDataType: String); begin - SetBoldLastFailureReason(TBoldFailureReason.CreateFmt(sFailure_Invalid, [value, expectedDataType], self)); + SetBoldLastFailureReason(TBoldFailureReason.CreateFmt('%s is not a valid %s', [value, expectedDataType], self)); +end; + +function TBoldAttribute.GetAsVariant: Variant; +begin + if IsNull then + Result := Null + else + Result := inherited GetAsVariant; end; -function TBoldAttribute.GetContentIsNull: Boolean; +procedure TBoldAttribute.SetAsVariant(const Value: Variant); begin - Result := GetElementFlag(befIsNull); + if VarIsNull(Value) then + SetToNull + else + inherited; end; procedure TBoldAttribute.SetContentToNull; begin if not ContentIsNull then begin +{$IFDEF NoNilAttributeExceptions} + FreeContent; +{$ENDIF} SetElementFlag(befIsNull, True); Changed(beValueChanged, []); end; @@ -4369,21 +6072,28 @@ procedure TBoldAttribute.DoSetInitialValue; var InitialValue: string; begin - if Assigned(BoldAttributeRTInfo) and BoldAttributeRtInfo.HasInitialValue then + if Assigned(BoldAttributeRTInfo) then begin - InitialValue := BoldAttributeRTInfo.InitialValue; - if CompareText(InitialValue, '') = 0 then // do not localize - SetToNull - else - try - AsString := InitialValue; - except - on e: Exception do - begin - Raise EBold.CreateFmt(sIllegalInitialValue, - [InitialValue, BoldAttributeRTInfo.AsString, BOLDCRLF, e.message]); + if BoldAttributeRtInfo.HasInitialValue then + begin + InitialValue := BoldAttributeRTInfo.InitialValue; + if CompareText(InitialValue, '') = 0 then + SetToNull + else + try + AsString := InitialValue; + except + on e: Exception do + begin + Raise EBold.CreateFmt('Illegal InitialValue (%s) for attribute %s. ErrorMessage: ' + BOLDCRLF + '%s', + [InitialValue, BoldAttributeRTInfo.AsString, e.message]); + end; end; - end; + end + else + begin + SetEmptyValue; + end; end; end; @@ -4408,7 +6118,7 @@ procedure TBoldAttribute.Assign(Source: TBoldElement); procedure TBoldAttribute.SetEmptyValue; begin - raise Ebold.CreateFmt(sMethodNotImplemented, [classname, 'SetEmptyValue']); // do not localize + raise Ebold.CreateFmt('%s.SetEmptyValue: Operation not implemented', [classname]); end; { TBoldObjectReference } @@ -4426,12 +6136,17 @@ procedure TBoldObjectReference.DefaultSubscribe(Subscriber: TBoldSubscriber; Req AddSmallSubscription(Subscriber, [beValueChanged, beValueInvalid], RequestedEvent); end; +function TBoldObjectReference.GetIsEmpty: boolean; +begin + result := not Assigned(Locator); +end; + function TBoldObjectReference.GetLocator: TBoldObjectLocator; begin EnsureContentsCurrent; BoldClearLastFailure; if not CanRead(nil) then - BoldRaiseLastFailure(self, 'GetLocator', ''); // do not localize + BoldRaiseLastFailure(self, 'GetLocator', ''); Result := ReferenceController.GetLocator; end; @@ -4440,7 +6155,7 @@ function TBoldObjectReference.GetBoldObject: TBoldObject; aLocator: TBoldObjectLocator; begin aLocator := Locator; {CanRead, EnsureContentsCurrent called by GetLocator} - if not Assigned(aLocator) then + if not Assigned(aLocator) or aLocator.BoldObjectID.NonExisting then Result := nil else begin @@ -4466,7 +6181,7 @@ procedure TBoldObjectReference.InternalSetLocator(NewLocator: TBoldObjectLocator begin BoldClearLastFailure; if not CanSetLocator(NewLocator, nil) then - BoldRaiseLastFailure(self, 'SetLocator', ''); // do not localize + BoldRaiseLastFailure(self, 'SetLocator', ''); ReferenceController.SetLocator(NewLocator); end; end; @@ -4476,14 +6191,16 @@ procedure TBoldObjectReference.SetBoldObject(NewObject: TBoldObject); if Assigned(NewObject) then Locator := NewObject.BoldObjectLocator else - Clear; // this will cause "CanClear" to be checked before the "CanSetLocator" + Clear; end; procedure TBoldObjectReference.Clear; begin + if not Assigned(Locator) then + exit; BoldClearLastFailure; if not canClear(nil) then - BoldRaiseLastFailure(self, 'Clear', ''); // do not localize + BoldRaiseLastFailure(self, 'Clear', ''); Locator := nil; end; @@ -4495,11 +6212,10 @@ function TBoldObjectReference.GetStringRepresentation(Representation: TBoldRepre Result := ''; end; -procedure TBoldObjectReference.SetStringRepresentation(Representation: TBoldRepresentation; Value: string); +procedure TBoldObjectReference.SetStringRepresentation(Representation: TBoldRepresentation; const Value: string); begin if Assigned(BoldObject) then BoldObject.SetStringRepresentation(Representation, Value); - //FixMe: is it an error trying to set the stringrep of a singlelink without value? end; function TBoldObjectReference.IsEqualAs(CompareType: TBoldCompareType; BoldElement: TBoldElement): Boolean; @@ -4515,7 +6231,7 @@ function TBoldObjectReference.IsEqualAs(CompareType: TBoldCompareType; BoldEleme case CompareType of ctDefault: Result := BoldObject.IsEqualAs(CompareType, BoldElement); else - raise EBold.CreateFmt(sUnknownCompareType, [ClassName, 'IsEqualAs']); // do not localize + raise EBold.CreateFmt('%s.IsEqualAs: Unknown Comparetype', [ClassName]); end; end else @@ -4527,9 +6243,12 @@ procedure TBoldObjectReference.GetAsList(ResultList: TBoldIndirectElement); NewList: TBoldObjectList; begin Assert(BoldType.SystemTypeInfo is TBoldSystemTypeInfo); - NewList := TBoldObjectList.CreateWithTypeInfo(TBoldSystemTypeInfo(BoldType.SystemTypeInfo).ListTypeInfoByElement[BoldType]); + NewList := TBoldObjectList.CreateWithTypeInfo(BoldType.ListTypeInfo); if Assigned(BoldObject) then - NewList.Add(BoldObject); + begin + NewList.Capacity := 1; + NewList.ObjectListController.AddLocator(BoldObject.BoldObjectLocator); + end; NewList.MakeImmutable; ResultList.SetOwnedValue(NewList); end; @@ -4557,6 +6276,11 @@ function TBoldObjectReference.GetStreamName: String; Result := ReferenceController.StreamName; end; +function TBoldObjectReference.GetFreeStandingClass: TBoldFreeStandingElementClass; +begin + result := ReferenceController.GetFreeStandingClass; +end; + procedure TBoldObjectReference.Assign(Source: TBoldElement); begin if not assigned(Source) then @@ -4584,9 +6308,9 @@ function TBoldObjectReference.CompareToAs(CompareType: TBoldCompareType; BoldEle else if not assigned(BoldElement) then CompareObj := nil else - raise EBold.CreateFmt(sUnknownObjectType, [ClassName, BoldElement.ClassName]); + raise EBold.CreateFmt('%s.CompareToAs: unknown type of object (%s)', [ClassName, BoldElement.ClassName]); - if CompareObj = BoldObject then // covers the case of both = nil + if CompareObj = BoldObject then result := 0 else if not assigned(CompareObj) then result := 1 @@ -4599,12 +6323,35 @@ function TBoldObjectReference.CompareToAs(CompareType: TBoldCompareType; BoldEle function TBoldObjectReference.CanSetLocator(NewLocator: TBoldObjectLocator; Subscriber: TBoldSubscriber): Boolean; begin - if assigned(newLocator) and assigned(OwningObject) and (OwningObject.BoldSystem <> NewLocator.BoldSystem) then - result := false + result := VerifyClass(NewLocator); +{$IFNDEF BOLD_NO_QUERIES} + result := result and SendQuery(bqMaySetValue, [NewLocator], Subscriber) +{$ENDIF} +end; + +function VerifyLocatorType(ALocator: TBoldObjectLocator; AExpectedClassType: TBoldClassTypeInfo; ARaise: boolean = true): Boolean; +var + KnownClass: TBoldClassTypeInfo; +begin + if Assigned(AExpectedClassType) and assigned(aLocator) then + begin + Assert(AExpectedClassType is TBoldClassTypeInfo); + KnownClass := aLocator.BoldClassTypeInfo; + Assert(Assigned(KnownClass)); + if KnownClass.ConformsTo(AExpectedClassType) then + result := true + else if aLocator.BoldObjectId.TopSortedIndexExact then + result := false + else + result := AExpectedClassType.ConformsTo(knownclass); + if not result and ARaise then + raise EBold.CreateFmt('Locator is: %s, expected: %s ', [KnownClass.ExpressionName, AExpectedClassType.ExpressionName]); + end else - result := VerifyClass(NewLocator) and SendQuery(bqMaySetValue, [NewLocator], Subscriber); + result := true; end; + function TBoldObjectReference.VerifyClass(aLocator: TBoldObjectLocator): Boolean; var AllowedClass, KnownClass: TBoldClassTypeInfo; @@ -4614,15 +6361,15 @@ function TBoldObjectReference.VerifyClass(aLocator: TBoldObjectLocator): Boolean Assert(BoldType is TBoldClassTypeInfo); Assert(BoldType.SystemTypeInfo is TBoldSystemTypeInfo); AllowedClass := TBoldClassTypeInfo(BoldType); - KnownClass := TBoldSystemTypeInfo(BoldType.SystemTypeInfo).TopSortedClasses[aLocator.BoldObjectId.TopSortedIndex]; + KnownClass := aLocator.BoldClassTypeInfo; if KnownClass.ConformsTo(AllowedClass) then result := true else if aLocator.BoldObjectId.TopSortedIndexExact then result := false - else // if it looks wrong, but the classID is inexact, then we will allow it if it _could_ be right... + else result := allowedClass.ConformsTo(knownclass); if not result then - SetBoldLastFailureReason(TBoldFailureReason.CreateFmt(sCannotSetSuchReference, [KnownClass.ExpressionName, AllowedClass.ExpressionName], self)); + SetBoldLastFailureReason(TBoldFailureReason.CreateFmt('Can not set a %s in a %s-reference', [KnownClass.ExpressionName, AllowedClass.ExpressionName], self)); end else result := true; @@ -4642,16 +6389,16 @@ constructor TBoldObjectReference.CreateTypedReference(ObjectClass: TBoldObjectCl var aSystem: TBoldSystem; begin + inherited CreateWithOwner(nil); aSystem := TBoldSystem.DefaultSystem; if assigned(aSystem) then - InitializeMember(nil, aSystem.BoldSystemTypeInfo.TopSortedClasses.ItemsByObjectClass[ObjectClass]) + InitializeNonObjectOwned(aSystem.BoldSystemTypeInfo.TopSortedClasses.ItemsByObjectClass[ObjectClass]) else - InitializeMember(nil, nil); + InitializeNonObjectOwned(nil); HasOldValues := false; end; -procedure TBoldObjectReference.InitializeMember( - AOwningElement: TBoldDomainElement; ElementTypeInfo: TBoldElementTypeInfo); +procedure TBoldObjectReference.Initialize; begin inherited; if not assigned(BoldMemberRTInfo) or BoldMemberRTInfo.IsDerived then @@ -4667,8 +6414,10 @@ procedure TBoldObjectReference.InitializeMember( fObjectReferenceController := TBoldLinkObjectReferenceController.Create(Self) else if IsIndirect then fObjectReferenceController := TBoldIndirectSingleLinkController.Create(Self) + else if OtherEndOrdered then + fObjectReferenceController := TBoldOrderedDirectSingleLinkController.Create(Self) else - fObjectReferenceController := TBoldDirectSingleLinkController.Create(Self); + fObjectReferenceController := TBoldUnOrderedDirectSingleLinkController.Create(Self) end; end; end; @@ -4693,7 +6442,11 @@ function TBoldObjectReference.GetBoldRoleRTInfo: TBoldRoleRTInfo; function TBoldObjectReference.CanClear(Subscriber: TBoldSubscriber): Boolean; begin +{$IFDEF BOLD_NO_QUERIES} + result := true; +{$ELSE} result := SendQuery(bqMayClear, [], Subscriber); +{$ENDIF} end; function TBoldObjectReference.InternalMayUpdate: Boolean; @@ -4701,9 +6454,9 @@ function TBoldObjectReference.InternalMayUpdate: Boolean; result := ReferenceController.MayUpdate; end; -function TBoldObjectReference.ProxyClass: TBoldMember_ProxyClass; +function TBoldObjectReference.GetProxy(Mode: TBoldDomainElementProxyMode): TBoldMember_Proxy; begin - result := ReferenceController.ProxyClass; + result := ReferenceController.GetProxy(self, Mode); end; procedure TBoldObjectReference.AssignContentValueFromElement(source: TBoldElement); @@ -4726,7 +6479,7 @@ procedure TBoldObjectReference.AdjustOldValues(Translationlist: TBoldIdTranslati OldLink: IBoldValue; OldValues: IBoldValueSpace; - procedure GetOldValueAsIdLists(IdList1, IdList2: TBoldObjectIdList; Oldvalue: IBoldValue); + procedure GetOldValueAsIdLists(IdList1, IdList2: TBoldObjectIdList; const Oldvalue: IBoldValue); var i: integer; IdList: IBoldObjectIdListRef; @@ -4747,7 +6500,7 @@ procedure TBoldObjectReference.AdjustOldValues(Translationlist: TBoldIdTranslati end; end; - procedure RemoveIdFromLink(LinkId: TBoldObjectId; OldLink: IBoldValue); + procedure RemoveIdFromLink(LinkId: TBoldObjectId; const OldLink: IBoldValue); var IdRef: IBoldObjectIdRef; IdRefPair: IBoldObjectIdRefPair; @@ -4755,7 +6508,7 @@ procedure TBoldObjectReference.AdjustOldValues(Translationlist: TBoldIdTranslati FreestandingListPair: IBoldFreeStandingIdListPair; begin if OldLink.QueryInterface(IBoldObjectIdref, IdRef) = S_OK then - IdRef.SetFromId(nil) + IdRef.SetFromId(nil, false) else if OldLink.QueryInterface(IBoldObjectIdrefPair, IdRefPair) = S_OK then IdRefPair.SetFromIds(nil, nil) else if OldLink.QueryInterface(IBoldFreeStandingIdList, FreestandingList) = S_OK then @@ -4766,7 +6519,7 @@ procedure TBoldObjectReference.AdjustOldValues(Translationlist: TBoldIdTranslati raise EBoldInternal.CreateFmt('%s.AdjustOldValues (RemoveIdFromLink): Unknown type of link', [Classname]); end; - procedure AddIdToLink(Id1, Id2: TBoldObjectId; OldLink: IBoldValue); + procedure AddIdToLink(Id1, Id2: TBoldObjectId; const OldLink: IBoldValue); var IdRef: IBoldObjectIdRef; IdRefPair: IBoldObjectIdRefPair; @@ -4774,7 +6527,7 @@ procedure TBoldObjectReference.AdjustOldValues(Translationlist: TBoldIdTranslati FreestandingListPair: IBoldFreeStandingIdListPair; begin if OldLink.QueryInterface(IBoldObjectIdref, IdRef) = S_OK then - IdRef.SetFromId(TranslationList.TranslateToNewId[Id1]) + IdRef.SetFromId(TranslationList.TranslateToNewId[Id1], false) else if OldLink.QueryInterface(IBoldObjectIdrefPair, IdRefPair) = S_OK then IdRefPair.SetFromIds(TranslationList.TranslateToNewId[Id1], TranslationList.TranslateToNewId[Id2]) else if OldLink.QueryInterface(IBoldFreeStandingIdList, FreestandingList) = S_OK then @@ -4791,13 +6544,11 @@ procedure TBoldObjectReference.AdjustOldValues(Translationlist: TBoldIdTranslati begin inherited; - // this happens for direct singlelinks and for innerlinks. - // Either way, the Role that should be adjusted is always the one pointed out by BoldRoleRTInfo.IndexOfOtherEnd + Oldvalues := OwningObject.BoldSystem.fOldValueHandler.Oldvalues; if BoldRoleRTInfo.IsStoredInObject then begin - // fix to remove deleted objects from Oldvalues OldRef := OldValue as IBoldObjectIdRef; if assigned(OldRef) and Assigned(OldRef.Id) then begin @@ -4805,7 +6556,7 @@ procedure TBoldObjectReference.AdjustOldValues(Translationlist: TBoldIdTranslati if assigned(OldObjectContents) then begin OldLink := OldObjectContents.ValueByIndex[BoldRoleRTInfo.IndexOfOtherEnd]; - if assigned(OldLink) then + if assigned(OldLink) and (OldLink.BoldPersistenceState <> bvpsInvalid) {?} then RemoveIdFromLink(OwningObject.BoldObjectLocator.BoldObjectId, OldLink); end; end; @@ -4833,7 +6584,7 @@ procedure TBoldObjectReference.AdjustOldValues(Translationlist: TBoldIdTranslati procedure TBoldObjectReference.DoSetInitialValue; begin - if BoldRoleRTInfo.RoleType = rtRole then // only regular roles have an inital value. + if BoldRoleRTInfo.RoleType = rtRole then BoldObject := nil; end; @@ -4854,6 +6605,27 @@ function TBoldObjectReference.GetOldEmbeddingOtherEndId: TBoldObjectId; end; end; +{ TBoldListEnumerator } + +constructor TBoldListEnumerator.Create(AList: TBoldList); +begin + inherited Create; + FIndex := -1; + FList := AList; +end; + +function TBoldListEnumerator.GetCurrent: TBoldElement; +begin + Result := List[FIndex]; +end; + +function TBoldListEnumerator.MoveNext: Boolean; +begin + Result := Index < List.Count - 1; + if Result then + Inc(FIndex); +end; + { TBoldList } destructor TBoldList.Destroy; @@ -4872,7 +6644,7 @@ procedure TBoldList.DefaultSubscribe(Subscriber: TBoldSubscriber; RequestedEvent procedure TBoldList.AllocateData; begin - raise EBold.CreateFmt(sLocatedAbstractError, [ClassName, 'AllocateData']); // do not localize + raise EBold.CreateFmt('%s.AllocateData is abstract. Implementation required', [ClassName]); end; function TBoldList.GetController: TBoldAbstractController; @@ -4882,41 +6654,84 @@ function TBoldList.GetController: TBoldAbstractController; function TBoldList.GetStringRepresentation(Representation: TBoldRepresentation): string; begin - result := ListController.GetStringRepresentation +{$IFDEF BOLDJSON} + if Representation = brJson then + Result := BoldElementToJsonString(Self) + else +{$ENDIF} + result := ListController.GetStringRepresentation end; procedure TBoldList.Clear; begin + if count = 0 then + exit; BoldClearLastFailure; PrepareClear; if mutable and not CanClear(nil) then - BoldRaiseLastFailure(self, 'Clear', ''); // do not localize - - // Speed optimizing -// if Derived and Deriver.IsDeriving then -// begin -// for i := count - 1 downto 0 do -// ListController.RemoveByIndex(i); -// end -// else -// begin - if assigned(BoldSYstem) then + BoldRaiseLastFailure(self, 'Clear', ''); + + if assigned(BoldSystem) then BoldSystem.StartTransaction; try InternalClear; - if assigned(BoldSYstem) then + if assigned(BoldSystem) then BoldSystem.CommitTransaction; except if assigned(BoldSYstem) then BoldSystem.RollbackTransaction; raise; end; -// end; end; -function TBoldList.Includes(Item: TBoldElement): Boolean; +function TBoldList.IndexOf(Item: TBoldElement): Integer; +begin + result := IndexOfElement(Item); +end; + +function TBoldList.Includes(Item: TBoldElement): Boolean; +begin + Result := IncludesElement(Item); +end; + +function TBoldList.IncludesAny(aList: TBoldList): Boolean; +var + i: integer; +begin + for i := 0 to aList.Count - 1 do + begin + if includes(aList[i]) then + begin + result := true; + exit; + end; + end; + result := false; +end; + +function TBoldList.IncludesAll(aList: TBoldList): Boolean; +var + i: integer; +begin + result := true; + for i := 0 to aList.Count - 1 do + begin + if not includes(aList[i]) then + begin + result := false; + exit; + end; + end; +end; + +procedure TBoldList.SetCapacity(const Value: integer); begin - Result := IncludesElement(Item); + ListController.Capacity := Value +end; + +function TBoldList.GetDuplicateMode: TBoldListDupMode; +begin + result := TBoldListDupMode(GetInternalState(BoldDuplicateModeMask, BoldDMShift)); end; procedure TBoldList.SetDuplicateMode(NewMode: TBoldListDupMode); @@ -4926,7 +6741,8 @@ procedure TBoldList.SetDuplicateMode(NewMode: TBoldListDupMode); begin OldMode := GetDuplicateMode; if (NewMode <> OldMode) and (NewMode = bldmMerge) then - begin // warning: Timecomplexity is O(n2) + begin + // TODO: This is very inefficient, improve it i := 0; while i < Count do begin @@ -4941,10 +6757,63 @@ procedure TBoldList.SetDuplicateMode(NewMode: TBoldListDupMode); inc(i); end; end; - SetInternalState(BoldDuplicateModeMask, BoldDMShift, Integer(NewMode)); end; +function TBoldList.HasDuplicates: boolean; +var + i, j: integer; + SortedList: TBoldList; + G: IBoldGuard; +begin + result := false; + if Count < 2 then + exit; + if DuplicateMode = bldmAllow then + begin + if Count < 10 then // actually test to determine the correct number + begin + // implementation fast enough for few elements + i := 0; + while i < Count do + begin + j := i + 1; + while j < Count do + begin + if Elements[i].IsEqual(Elements[j]) then + begin + result := true; + exit; + end + else + inc(j); + end; + inc(i); + end; + end + else + begin + // Clone, sort, then compare neighbouring values only + G := TBoldGuard.Create(SortedList); +// SortedList := Clone as TBoldList; + if Assigned(BoldType) then + SortedList := TBoldMemberFactory.CreateMemberFromBoldType(BoldType) as TBoldList + else + SortedList := TBoldMemberClass(ClassType).Create as TBoldList; + if SortedList is TBoldMemberList then + TBoldMemberList(SortedList).CloneMembers := true; // if CloneMembers = true then sorting messes up the list. + SortedList.AddList(self); + SortedList.Sort; + for i := 1 to SortedList.Count - 1 do + if SortedList[i].IsEqual(SortedList[i-1]) then + begin + result := true; + exit; + end; + end; + end; +end; + procedure TBoldList.Remove(Item: TBoldElement); var I: Integer; @@ -4954,34 +6823,125 @@ procedure TBoldList.Remove(Item: TBoldElement); if I <> -1 then RemoveByIndex(I) else - raise EBold.CreateFmt(sItemNotInList, [ClassName]); + raise EBold.CreateFmt('%s.Remove: Item not in list', [ClassName]); +end; + +procedure TBoldList.Insert(index: Integer; Element: TBoldElement); +begin + if not mutable then MutableError('InsertElementToList'); + InsertElement(index, Element); end; procedure TBoldList.Add(Element: TBoldElement); begin if not mutable then - MutableError('AddToList'); // do not localize + MutableError('AddToList'); AddElement(Element); end; procedure TBoldList.AddList(List: TBoldList); var I: Integer; + vBoldSystem: TBoldSystem; begin - if not mutable then MutableError('AddListToList'); // do not localize - for I := 0 to List.Count - 1 do - AddElement(List[I]); + if not mutable then MutableError('AddListToList'); + i := List.Count; + if i > 0 then + begin + vBoldSystem := BoldSystem; + if Assigned(vBoldSystem) then + vBoldSystem.StartTransaction(stmNormal); + try + if (i > 4) then + begin + if DuplicateMode = bldmAllow then + Capacity := Count + i; + if i > Count then + Capacity := i; + end; + for I := 0 to i - 1 do + AddElement(List[I]); + if Assigned(vBoldSystem) then + vBoldSystem.CommitTransaction(stmNormal); + except + if Assigned(vBoldSystem) then + vBoldSystem.RollbackTransaction(stmNormal); + raise; + end; + end; end; -function TBoldList.IndexOf(Item: TBoldElement): Integer; +procedure TBoldList.RemoveList(List: TBoldList); +var + i, j: Integer; + vBoldSystem: TBoldSystem; begin - result := IndexOfElement(Item); + if not Mutable then MutableError('TBoldList.RemoveList'); // do not localize + EnsureContentsCurrent; + if Empty or List.Empty then + exit; + vBoldSystem := BoldSystem; + if Assigned(vBoldSystem) then + vBoldSystem.StartTransaction(stmNormal); + try + if List.Count < count then + for i := List.Count - 1 downto 0 do + begin + // IndexOf() is faster in BoldList, BoldMemberList, yet slower in BoldObjectList so we reimplement this method there + j := IndexOf(List[i]); + if j <> -1 then + RemoveByIndex(j); + end + else + begin + i := count - 1; + repeat + if List.Includes( Elements[i] ) then + begin + RemoveByIndex(i); + i := count - 1; // this a safeguard in case removing 1 element consequently removes others too + end + else + dec(i); + until i = -1 + end; + if Assigned(vBoldSystem) then + vBoldSystem.CommitTransaction(stmNormal); + except + if Assigned(vBoldSystem) then + vBoldSystem.RollbackTransaction(stmNormal); + raise; + end; end; -procedure TBoldList.Insert(index: Integer; Element: TBoldElement); +procedure TBoldList.IntersectList(List: TBoldList); +var + i, j: Integer; + vBoldSystem: TBoldSystem; begin - if not mutable then MutableError('InsertElementToList'); // do not localize - InsertElement(index, Element); + if not Mutable then MutableError('TBoldList.RemoveList'); // do not localize + EnsureContentsCurrent; + vBoldSystem := BoldSystem; + if Assigned(vBoldSystem) then + vBoldSystem.StartTransaction(stmNormal); + try + i := count - 1; + repeat + if not List.Includes( Elements[i] ) then + begin + RemoveByIndex(i); + i := count - 1; // this a safeguard in case removing 1 element consequently removes others too + end + else + dec(i); + until i = -1; + if Assigned(vBoldSystem) then + vBoldSystem.CommitTransaction(stmNormal); + except + if Assigned(vBoldSystem) then + vBoldSystem.RollbackTransaction(stmNormal); + raise; + end; end; function TBoldList.GetCanCreateNew: Boolean; @@ -4989,11 +6949,16 @@ function TBoldList.GetCanCreateNew: Boolean; result := CanModify and assigned(ListController) and ListController.CanCreateNew; end; +function TBoldList.GetCapacity: integer; +begin + result := ListController.Capacity; +end; + procedure TBoldList.EnsureCanCreateNew; begin BoldClearLastFailure; if not CanCreateNew then - BoldRaiseLastFailure(self, 'EnsureCanCreateNew', sCannotCreateNewElement); // do not localize + BoldRaiseLastFailure(self, 'EnsureCanCreateNew', 'Can''t create new element'); end; function TBoldList.CreateNew: TBoldElement; @@ -5002,6 +6967,13 @@ function TBoldList.CreateNew: TBoldElement; result := ListController.CreateNew; end; +constructor TBoldList.CreateWithTypeInfo(ElementTypeInfo: TBoldElementTypeInfo); +begin + if Assigned(ElementTypeInfo) and not (ElementTypeInfo is TBoldListTypeInfo) then + ElementTypeInfo := ElementTypeInfo.ListTypeInfo; + inherited; +end; + function TBoldList.AddNew: TBoldElement; begin result := InternalAddNew; @@ -5032,6 +7004,46 @@ procedure TBoldList.ToStringsWithNil(Representation: TBoldRepresentation; S: TSt AddToStrings(Representation, S); end; +function TBoldList.AsCommaText(AIncludeType: boolean; Representation: TBoldRepresentation; const ASeparator: string): string; +var + i: integer; + s: string; +begin + result := ''; + for I := 0 to Count - 1 do + begin + if Assigned(Elements[i]) then + begin + s := Elements[i].StringRepresentation[Representation]; + if AIncludeType then + s := Elements[i].ClassName + ':' + s; + end + else + s := 'nil'; + if i < count-1 then + s := s + ASeparator; + result := result + s; + end; +end; + +function TBoldList.AsDebugCommaText(const ASeparator: string = ','): string; +var + i: integer; + s: string; +begin + result := ''; + for I := 0 to Count - 1 do + begin + if Assigned(Elements[i]) then + s := Elements[i].DebugInfo + else + s := 'nil'; + if i < count-1 then + s := s + ASeparator; + result := result + s; + end; +end; + procedure TBoldList.GetAsList(ResultList: TBoldIndirectElement); begin ResultList.SetReferenceValue(Self); @@ -5039,47 +7051,88 @@ procedure TBoldList.GetAsList(ResultList: TBoldIndirectElement); procedure TBoldList.EnsureRange(FromIndex, ToIndex: integer); begin - // do nothing end; function TBoldList.canInsert(index: Integer; Element: TBoldElement; Subscriber: TBoldSubscriber): Boolean; begin +{$IFDEF BOLD_NO_QUERIES} + result := true; +{$ELSE} result := SendQuery(bqMayInsert, [index, Element], Subscriber); +{$ENDIF} end; function TBoldList.CanRemove(index: Integer; Subscriber: TBoldSubscriber): Boolean; begin +{$IFDEF BOLD_NO_QUERIES} + result := true; +{$ELSE} result := SendQuery(bqMayRemove, [index], Subscriber); +{$ENDIF} end; function TBoldList.CanMove(CurIndex, NewIndex: Integer; Subscriber: TBoldSubscriber = nil): Boolean; begin - result := (NewIndex >= 0) and (NewIndex < Count) and - SendQuery(bqMayMove, [CurIndex, NewIndex], Subscriber); + result := (NewIndex >= 0) and (NewIndex < Count); +{$IFNDEF BOLD_NO_QUERIES} + result := result and SendQuery(bqMayMove, [CurIndex, NewIndex], Subscriber); +{$ENDIF} end; function TBoldList.CanSet(index: Integer; Item: TBoldElement; Subscriber: TBoldSubscriber): Boolean; begin +{$IFDEF BOLD_NO_QUERIES} + result := true; +{$ELSE} result := SendQuery(bqMayReplace, [index, Item], Subscriber); +{$ENDIF} end; constructor TBoldMember.CreateWithTypeInfo(ElementTypeInfo: TBoldElementTypeInfo); begin - InitializeMember(nil, ElementTypeInfo); + inherited CreateWithOwner(nil); + InitializeNonObjectOwned(ElementTypeInfo); end; -procedure TBoldList.Sort(CompareFunc: TBoldElementCompare); +procedure TBoldList.Sort(CompareFunc: TBoldElementCompare; FirstIndex, + LastIndex: Integer; SortMode: TBoldSortMode = BoldDefaultSortMode); + + ////////////////////////////////////////////////////////////////////////////// + // Insertion Sort: // + // stable, inplace, but only fast on small lists // + ////////////////////////////////////////////////////////////////////////////// + procedure InsertSort(Left, Right: Integer; SCompare: TBoldElementCompare); + var + I, J: Integer; + T: TBoldElement; + begin + for I := Left + 1 to Right do begin + if SCompare(Elements[I], Elements[I - 1]) < 0 then begin + J := I; + T := Elements[J]; + while (J > Left) and (SCompare(T, Elements[J - 1]) < 0) do begin + Elements[J] := Elements[J - 1]; + Dec(J); + end; + Elements[J] := T; + end; + end; + end; - procedure QuickSort(L, R: Integer; - SCompare: TBoldElementCompare); + ////////////////////////////////////////////////////////////////////////////// + // Quick Sort: // + // fast, inplace (without help array), // + // but NOT stable (sorting changes within same elements) // + ////////////////////////////////////////////////////////////////////////////// + procedure QuickSort(Left, Right: Integer; SCompare: TBoldElementCompare); var I, J: Integer; P: TBoldElement; begin repeat - I := L; - J := R; - P := Elements[(L + R) shr 1]; + I := Left; + J := Right; + P := Elements[(Left + Right) shr 1]; repeat while SCompare(Elements[I], P) < 0 do Inc(I); @@ -5096,15 +7149,232 @@ procedure TBoldList.Sort(CompareFunc: TBoldElementCompare); Dec(J); end; until I > J; - if L < J then - QuickSort(L, J, SCompare); - L := I; - until I >= R; + if Left < J then + QuickSort(Left, J, SCompare); + Left := I; + until I >= Right; + end; + + ////////////////////////////////////////////////////////////////////////////// + // Merge Sort - Inplace Variant: // + // http://thomas.baudel.name/Visualisation/VisuTri/inplacestablesort.html // + // stable, inplace, but slower than Quicksort and normal Mergesort // + ////////////////////////////////////////////////////////////////////////////// + function Lower(Left, Right, Val: Integer; SCompare: TBoldElementCompare): + Integer; + var + iLen: Integer; + iHalf: Integer; + iMid: Integer; + begin + iLen := Right - Left; + while iLen > 0 do begin + iHalf := iLen div 2; + iMid := Left + iHalf; + if SCompare(Elements[iMid], Elements[Val]) < 0 then begin + Left := iMid + 1; + iLen := iLen - iHalf - 1; + end else begin + iLen := iHalf; + end; + end; + Result := Left; + end; + + function Upper(Left, Right, Val: Integer; SCompare: TBoldElementCompare): + Integer; + var + iLen: Integer; + iHalf: Integer; + iMid: Integer; + begin + iLen := Right - Left; + while iLen > 0 do begin + iHalf := iLen div 2; + iMid := Left + iHalf; + if SCompare(Elements[Val], Elements[iMid]) < 0 then begin + iLen := iHalf; + end else begin + Left := iMid + 1; + iLen := iLen - iHalf - 1; + end; + end; + Result := Left; + end; + + function GCD(M, N: Integer): Integer; + var + T: Integer; + begin + while (N <> 0) do begin + T := M mod N; + M := N; N := T; + end; + Result := M; + end; + + procedure Rotate(Left, Middle, Right: Integer; SCompare: TBoldElementCompare); + var + N: Integer; + SavedElement: TBoldElement; + Shift: Integer; + P1, P2: Integer; + begin + if (Left <> Middle) and (Right <> Middle) then begin + N := GCD(Right - Left, Middle - Left); + while N <> 0 do begin + Dec(N); + SavedElement := Elements[Left + N]; + Shift := Middle - Left; + P1 := Left + N; + P2 := Left + N + Shift; + while (P2 <> Left + N) do begin + Elements[P1] := Elements[P2]; + P1 := P2; + if Right - P2 > Shift then begin + Inc(P2, Shift); + end else begin + P2 := Left + (Shift - (Right - P2)); + end; + end; + Elements[P1] := SavedElement; + end; + end; + end; + + procedure MergeInplace(Left, Pivot, Right, Len1, Len2: Integer; SCompare: + TBoldElementCompare); + var + iFirstCut, iSecondCut: Integer; + iLen11, iLen22: Integer; + iNewMid: Integer; + begin + if (Len1 <> 0) and (Len2 <> 0) then begin + if Len1 + Len2 = 2 then begin + if SCompare(Elements[Pivot], Elements[Left]) < 0 then begin + if Pivot < Left then begin + Move(Pivot, Left); + Move(Left - 1, Pivot); + end else begin + Move(Left, Pivot); + Move(Pivot - 1, Left); + end; + end; + end else begin + if Len1 > Len2 then begin + iLen11 := Len1 div 2; + iFirstCut := Left + iLen11; + iSecondCut := Lower(Pivot, Right, iFirstCut, SCompare); + iLen22 := iSecondCut - Pivot; + end else begin + iLen22 := Len2 div 2; + iSecondCut := Pivot + iLen22; + iFirstCut := Upper(Left, Pivot, iSecondCut, SCompare); + iLen11 := iFirstCut - Left; + end; + Rotate(iFirstCut, Pivot, iSecondCut, SCompare); + iNewMid := iFirstCut + iLen22; + MergeInplace(Left, iFirstCut, iNewMid, iLen11, iLen22, SCompare); + MergeInplace(iNewMid, iSecondCut, Right, Len1 - iLen11, Len2 - iLen22, SCompare); + end; + end; + end; + + procedure MergeSortInplace(Left, Right: Integer; SCompare: TBoldElementCompare); + var + Middle: Integer; + begin + if Right - Left < 8 then begin + InsertSort(Left, Right, SCompare); + end else begin + Middle := (Left + Right) div 2; + MergeSortInplace(Left, Middle, SCompare); + MergeSortInplace(Middle, Right, SCompare); + MergeInplace(Left, Middle, Right, Middle - Left, Right - Middle, SCompare); + end; + end; + + ////////////////////////////////////////////////////////////////////////////// + // Merge Sort: // + // http://www.iti.fh-flensburg.de/lang/algorithmen/sortieren/merge/merge.htm// + // fastest, stable, // + // but not fully inplace (help array with only n/2 is needed) // + ////////////////////////////////////////////////////////////////////////////// + procedure DoMergeSort(var HelpArray: array of Pointer; Left, Right: Integer; + SCompare: TBoldElementCompare); + var + m: Integer; + i, j, k: Integer; + begin + if Left < Right then begin + if Right - Left < 4 then begin + InsertSort(Left, Right, SCompare); + end else begin + m := (Left + Right) div 2; + DoMergeSort(HelpArray, Left, m, SCompare); + DoMergeSort(HelpArray, m + 1, Right, SCompare); + + i := 0; + j := Left; + // Copy first half of elements in help array + while j <= m do begin + HelpArray[i] := Elements[j]; + Inc(i); + Inc(j); + end; + + i := 0; + k := Left; + // Copy back the next largest element + while (k < j) and (j <= Right) do begin + if SCompare(HelpArray[i], Elements[j]) <= 0 then begin + Elements[k] := HelpArray[i]; + Inc(i); + end else begin + Elements[k] := Elements[j]; + Inc(j); + end; + Inc(k); + end; + + // Copy back the rest of help array if existing + while k < j do begin + Elements[k] := HelpArray[i]; + Inc(k); + Inc(i); + end; + end; + end; + end; + + procedure MergeSort(Left, Right: Integer; SCompare: TBoldElementCompare); + var + HelpArray: array of Pointer; + begin + SetLength(HelpArray, (Count + 1) div 2); + DoMergeSort(HelpArray, FirstIndex, LastIndex, CompareFunc); + SetLength(HelpArray, 0); + end; + +begin + if Assigned(Self) and (Count > 1) then begin + case SortMode of + smQuickSort: QuickSort(FirstIndex, LastIndex, CompareFunc); + smMergeSort: MergeSort(FirstIndex, LastIndex, CompareFunc); + smMergeSortInplace: MergeSortInplace(FirstIndex, LastIndex, CompareFunc); + end; end; +end; + +procedure TBoldList.Sort(CompareFunc: TBoldElementCompare; SortMode: + TBoldSortMode = BoldDefaultSortMode); +begin + Sort(CompareFunc, 0, Count - 1, SortMode); +end; +procedure TBoldList.Sort; begin - if (self <> nil) and (Count > 0) then - QuickSort(0, Count - 1, CompareFunc); + Sort(DefaultCompare, 0, Count - 1); end; function TBoldList.DuplicateControl: Boolean; @@ -5115,32 +7385,71 @@ function TBoldList.DuplicateControl: Boolean; bldmMerge: Result := False; bldmError: - raise EBold.CreateFmt(sDuplicateInList, [ClassName]); + raise EBold.CreateFmt('%s.DuplicateControl: Duplicate value in list', [ClassName]); else - raise EBoldInternal.CreateFmt(sUnknownDuplicationMode, [ClassName]); + raise EBoldInternal.CreateFmt('%s.DuplicateControl: Unknown duplication mode', [ClassName]); end; end; -procedure TBoldList.InitializeMember(AOwningElement: TBoldDomainElement; - ElementTypeInfo: TBoldElementTypeInfo); +procedure TBoldList.Initialize; begin inherited; AllocateData; end; +function TBoldList.CompareToAs(CompType: TBoldCompareType; BoldElement: TBoldElement): Integer; +begin + if BoldElement is TBoldList then + begin + if TBoldList(BoldElement).Count <> Count then + result := -1 + else + if IncludesAll(TBoldList(BoldElement)) then + result := 0 + else + result := -1 + end + else + Result := inherited CompareToAs(CompType, BoldElement); +end; + function TBoldList.CanClear(Subscriber: TBoldSubscriber): Boolean; begin +{$IFDEF BOLD_NO_QUERIES} + result := true; +{$ELSE} result := SendQuery(bqMayClear, [], Subscriber); +{$ENDIF} end; -function TBoldList.GetDuplicateMode: TBoldListDupMode; +function TBoldList.DefaultCompare(Item1, Item2: TBoldElement): Integer; begin - result := TBoldListDupMode(GetInternalState(BoldDuplicateModeMask, BoldDMShift)); + Result := Item1.CompareTo(Item2); +end; + +function TBoldList.GetEnumerator: TBoldListEnumerator; +begin + result := TBoldListEnumerator.Create(Self); +end; + +function TBoldList.GetFirst: TBoldElement; +begin + if empty then + result := nil + else + result := Elements[0]; +end; + +function TBoldList.GetLast: TBoldElement; +begin + if empty then + result := nil + else + result := Elements[count-1]; end; procedure TBoldList.PrepareClear; begin - // do nothing end; procedure TBoldList.MakeContentsImmutable; @@ -5151,6 +7460,13 @@ procedure TBoldList.MakeContentsImmutable; Elements[I].MakeImmutable; end; +{ TBoldMemberListEnumerator } + +function TBoldMemberListEnumerator.GetCurrent: TBoldMember; +begin + Result := List[Index] as TBoldMember; +end; + { TBoldMemberList } procedure TBoldMemberList.AllocateData; @@ -5174,10 +7490,10 @@ procedure TBoldMemberList.Assign(Source: TBoldElement); I: Integer; begin if not (Source is TBoldMemberList) then - raise EBold.CreateFmt(sSourceNotBoldMemberList, [ClassName, Source.ClassName]); + raise EBold.CreateFmt('%s.Assign: Source is not a BoldMemberList (%s)', [ClassName, Source.ClassName]); SourceList := TBoldMemberList(Source); for I := 0 to SourceList.Count - 1 do - Add(SourceList[I]); // Addoperator will clone each element before adding to list + Add(SourceList[I]); end; procedure TBoldMemberList.AddElement(Element: TBoldElement); @@ -5185,11 +7501,11 @@ procedure TBoldMemberList.AddElement(Element: TBoldElement); EnsureContentsCurrent; BoldClearLastFailure; if not CanInsert(-1, Element, nil) then - BoldRaiseLastFailure(self, 'AddElement', ''); // do not localize + BoldRaiseLastFailure(self, 'AddElement', ''); if Element is TBoldMember then Add(TBoldMember(Element)) else - raise EBold.CreateFmt(sElementNotBoldMember, [ClassName, 'AddElement']); // do not localize + raise EBold.CreateFmt('%s.AddElement: Element not a TBoldMember', [ClassName]); end; procedure TBoldMemberList.InsertElement(index: Integer; Element: TBoldElement); @@ -5197,11 +7513,11 @@ procedure TBoldMemberList.InsertElement(index: Integer; Element: TBoldElement); EnsureContentsCurrent; BoldClearLastFailure; if not CanInsert(index, Element, nil) then - BoldRaiseLastFailure(self, 'InsertElement', ''); // do not localize + BoldRaiseLastFailure(self, 'InsertElement', ''); if Element is TBoldMember then Insert(index, TBoldMember(Element)) else - raise EBold.CreateFmt(sElementNotBoldMember, [ClassName, 'InsertElement']); // do not localize + raise EBold.CreateFmt('%s.InsertElement: Element not a TBoldMember', [ClassName]); end; function TBoldMemberList.GetElement(index: Integer): TBoldElement; @@ -5209,10 +7525,15 @@ function TBoldMemberList.GetElement(index: Integer): TBoldElement; EnsureContentsCurrent; BoldClearLastFailure; if not CanRead(nil) then - BoldRaiseLastFailure(self, 'GetElement', ''); // do not localize + BoldRaiseLastFailure(self, 'GetElement', ''); Result := TBoldElement(List[index]); end; +function TBoldMemberList.GetEnumerator: TBoldMemberListEnumerator; +begin + result := TBoldMemberListEnumerator.Create(self) +end; + procedure TBoldMemberList.SetElement(index: Integer; Value: TBoldElement); begin EnsureContentsCurrent; @@ -5220,7 +7541,7 @@ procedure TBoldMemberList.SetElement(index: Integer; Value: TBoldElement); begin BoldClearLastFailure; if not CanSet(index, Value, nil) then - BoldRaiseLastFailure(self, 'SetElement', ''); // do not localize + BoldRaiseLastFailure(self, 'SetElement', ''); if CloneMembers then begin TBoldMember(List[index]).Free; @@ -5238,7 +7559,7 @@ function TBoldMemberList.GetCount: Integer; EnsureContentsCurrent; BoldClearLastFailure; if not CanRead(nil) then - BoldRaiseLastFailure(self, 'GetCount', ''); // do not localize + BoldRaiseLastFailure(self, 'GetCount', ''); Result := List.Count; end; @@ -5263,8 +7584,8 @@ procedure TBoldMemberList.RemoveByIndex(index: Integer); function TBoldMemberList.GetBoldMember(index: Integer): TBoldMember; begin EnsureContentsCurrent; - Assert(Elements[index] is TBoldMember); Result := TBoldMember(Elements[index]); + Assert(Result is TBoldMember); end; procedure TBoldMemberList.SetBoldMember(index: Integer; Value: TBoldMember); @@ -5274,22 +7595,24 @@ procedure TBoldMemberList.SetBoldMember(index: Integer; Value: TBoldMember); procedure TBoldMemberList.Add(Item: TBoldMember); begin - if CloneMembers then - List.Add(TBoldMember(Item.Clone)) - else - if CheckAdd(Item) then + if CheckAdd(Item) then + begin + if CloneMembers then + List.Add(TBoldMember(Item.Clone)) + else List.Add(Item) + end; end; procedure TBoldMemberList.Move(CurIndex, NewIndex: Integer); begin - if not mutable then MutableError('MoveElementInList'); // do not localize + if not mutable then MutableError('MoveElementInList'); EnsureContentsCurrent; List.Move(CurIndex, NewIndex); Changed(beOrderChanged, []); end; -procedure TBoldMemberList.InternalAddWithoutCloning(Item: TBoldMember); // FIXME remove when TBoldClass no longer member +procedure TBoldMemberList.InternalAddWithoutCloning(Item: TBoldMember); begin List.Add(Item); end; @@ -5299,7 +7622,10 @@ procedure TBoldMemberList.Insert(index: Integer; Item: TBoldMember); if assigned(Item) then begin if CloneMembers then - List.Insert(index, TBoldMember(Item.Clone)) + begin + if CheckInsert(index, Item) then + List.Insert(index, TBoldMember(Item.Clone)); + end else begin if CheckInsert(index, Item) then @@ -5312,12 +7638,48 @@ procedure TBoldMemberList.Insert(index: Integer; Item: TBoldMember); function TBoldMemberList.GetStreamName: String; begin - raise EBoldFeatureNotImplementedYet.CreateFmt(sMethodNotImplemented, [ClassName, 'GetStreamName']); // do not localize + raise EBoldFeatureNotImplementedYet.CreateFmt('%s.GetStreamName: Not Implemented', [ClassName]); end; function TBoldMemberList.GetStringRepresentation(Representation: TBoldRepresentation): string; +var + sl: TStringList; +begin + sl := TStringList.Create; + try + ToStrings(Representation, sl); + result := sl.text; + finally + sl.free; + end; +end; + +procedure TBoldMemberList.SetStringRepresentation(Representation: integer; const NewValue: String); +var + sl: TStringList; + ElementTypeInfo: TBoldElementTypeInfo; + Element: TBoldElement; + i: integer; begin - result := IntToStr(Count); + ElementTypeInfo := (BoldType as TBoldListTypeInfo).ListElementTypeInfo; + self.Clear; + sl := TStringList.Create; + try + Sl.CommaText := NewValue; + for I := 0 to sl.count-1 do + begin + Element := ElementTypeInfo.CreateElement; + try + Element.AsString := sl[i]; + self.AddElement(Element); + finally + if CloneMembers then + Element.free; + end; + end; + finally + sl.free; + end; end; function TBoldMemberList.IndexOfElement(Item: TBoldElement): Integer; @@ -5333,31 +7695,55 @@ function TBoldMemberList.IncludesElement(Item: TBoldElement): Boolean; result := IndexOfElement(Item) <> -1; end; +function TBoldMemberList.IndexOfFirstEqualElement(Item: TBoldMember): Integer; +begin + if assigned(Item) then + for result := 0 to List.Count - 1 do + begin + if TBoldElement(List[result]).BoldType.ConformsTo(Item.BoldType) and TBoldElement(List[result]).IsEqual(Item) then + exit; + end; + result := -1; +end; + +function TBoldMemberList.IncludesValue(Item: TBoldElement): Boolean; +var + i: integer; +begin + result := false; + for I := 0 to Count - 1 do + if Elements[i].IsEqual(Item) then + begin + result := true; + exit; + end; +end; + +procedure TBoldMemberList.SetCapacity(const Value: integer); +begin + faList.Capacity := Value; +end; + procedure TBoldMemberList.SetCloneMembers(const Value: Boolean); begin if (count = 0) or (fCloneMembers = Value) then FCloneMembers := Value else - raise EBold.CreateFmt(sOnlyAllowedOnEmptyLists, [ClassName]); + raise EBold.CreateFmt('%s.SetCloneMembers: Only allowed on empty lists', [ClassName]); end; function TBoldMemberList.CheckAdd(NewMember: TBoldMember): Boolean; begin if (not Assigned(NewMember)) then Result := False // Adding nil does nothing - else if not Includes(NewMember) then - Result := True else - Result := DuplicateControl; + result := (DuplicateMode = bldmAllow) or not IncludesValue(NewMember) or DuplicateControl; end; function TBoldMemberList.CheckInsert(index: Integer; NewMember: TBoldMember): Boolean; begin assert(assigned(NewMember), 'nil not allowed, should have been filtered out before'); - if Includes(NewMember) then - Result := DuplicateControl - else - result := True; + result := (DuplicateMode = bldmAllow) or not IncludesValue(NewMember) or DuplicateControl; end; function TBoldMemberList.CheckReplace(index: Integer; NewMember: TBoldMember): Boolean; @@ -5373,8 +7759,7 @@ function TBoldMemberList.CheckReplace(index: Integer; NewMember: TBoldMember): B Result := DuplicateControl; end; -procedure TBoldMemberList.InitializeMember( - AOwningElement: TBoldDomainElement; ElementTypeInfo: TBoldElementTypeInfo); +procedure TBoldMemberList.Initialize; begin inherited; DuplicateMode := bldmAllow; @@ -5394,6 +7779,11 @@ function TBoldMemberList.GetCanCreateNew: Boolean; (TBoldListTypeInfo(BoldType).ListElementTypeInfo is TBoldAttributeTypeInfo); end; +function TBoldMemberList.GetCapacity: integer; +begin + result := faList.Capacity; +end; + function TBoldMemberList.InternalAddNew: TBoldElement; begin result := CreateNew; @@ -5405,9 +7795,10 @@ procedure TBoldMemberList.InsertNew(index: Integer); var Elem: TBoldElement; begin - Elem := CreateNew; - Assert(Elem is TBoldMember); + Elem := nil; try + Elem := CreateNew; + Assert(Elem is TBoldMember); Insert(index, TBoldMember(Elem)); if CloneMembers then FreeAndNil(Elem); @@ -5416,7 +7807,8 @@ procedure TBoldMemberList.InsertNew(index: Integer); raise end; end; -function TBoldMemberList.ProxyClass: TBoldMember_ProxyClass; + +function TBoldMemberList.GetProxy(Mode: TBoldDomainElementProxyMode): TBoldMember_Proxy; begin raise EBoldInternal.Create('No proxy for TBoldMemberList yet'); end; @@ -5429,6 +7821,21 @@ procedure TBoldMemberList.InternalClear; RemoveByIndex(I); end; + +{ TBoldObjectListEnumerator } + +function TBoldObjectListEnumerator.GetCurrent: TBoldObject; +begin + Result := List[Index] as TBoldObject; +end; + +{ TBoldObjectListLocatorEnumerator } + +function TBoldObjectListLocatorEnumerator.GetCurrent: TBoldObjectLocator; +begin + Result := TBoldObjectList(List).Locators[Index] as TBoldObjectLocator; +end; + { TBoldObjectList } constructor TBoldObjectList.CreateTypedList(ObjectClass: TBoldObjectClass); @@ -5436,14 +7843,26 @@ constructor TBoldObjectList.CreateTypedList(ObjectClass: TBoldObjectClass); aSystem: TBoldSystem; ClassTypeInfo: TBoldClassTypeInfo; begin + inherited CreateWithOwner(nil); aSystem := TBoldSystem.DefaultSystem; if not assigned(aSystem) then - raise EBold.CreateFmt(sCannotFindSystem, [classname]); + raise EBold.CreateFmt('%s.CreateTypedList: Can not find system', [classname]); ClassTypeInfo := aSystem.BoldSystemTypeInfo.TopSortedClasses.ItemsByObjectClass[ObjectClass]; if not assigned(ClassTypeInfo) then - raise EBold.CreateFmt(sClassIsNotBusinessClass, [classname, ObjectClass.ClassName]); + raise EBold.CreateFmt('%s.CreateTypedList: %s is not a business class', [classname, ObjectClass.ClassName]); + InitializeNonObjectOwned(ClassTypeInfo.ListTypeInfo); +end; - InitializeMember(nil, aSystem.BoldSystemTypeInfo.ListTypeInfoByElement[ClassTypeInfo]); +constructor TBoldObjectList.CreateRootClassList; +var + aSystem: TBoldSystem; + ClassTypeInfo: TBoldClassTypeInfo; +begin + aSystem := TBoldSystem.DefaultSystem; + if not assigned(aSystem) then + raise EBold.CreateFmt('%s.CreateRootClassList: Can not find system', [classname]); + ClassTypeInfo := aSystem.BoldSystemTypeInfo.TopSortedClasses[0]; + CreateWithTypeInfo(ClassTypeInfo.ListTypeInfo); end; procedure TBoldObjectList.AllocateData; @@ -5453,15 +7872,19 @@ procedure TBoldObjectList.AllocateData; function TBoldObjectList.InternalAddNew: TBoldElement; var Obj: TBoldObject; + aSystem: TBoldSystem; begin - Result := CreateNew; - Obj := result as TBoldObject; - Obj.BoldSystem.StartTransaction; + aSystem := FindASystem; + if not assigned(aSystem) then + raise EBold.CreateFmt('%s.InternalAddNew: Can not find system', [classname]); + aSystem.StartTransaction; try + Result := CreateNew; + Obj := result as TBoldObject; Add(Obj); - Obj.BoldSystem.CommitTransaction; + aSystem.CommitTransaction; except - Obj.BoldSystem.RollBackTransaction; + aSystem.RollBackTransaction; raise; end; end; @@ -5469,14 +7892,18 @@ function TBoldObjectList.InternalAddNew: TBoldElement; procedure TBoldObjectList.InsertNew(index: Integer); var Obj: TBoldObject; + aSystem: TBoldSystem; begin - Obj := CreateNew as TBoldObject; - Obj.BoldSystem.StartTransaction; + aSystem := FindASystem; + if not assigned(aSystem) then + raise EBold.CreateFmt('%s.InsertNew: Can not find system', [classname]); + aSystem.StartTransaction; try + Obj := CreateNew as TBoldObject; Insert(index, Obj); - Obj.BoldSystem.CommitTransaction; + aSystem.CommitTransaction; except - Obj.BoldSystem.RollBackTransaction; + aSystem.RollBackTransaction; raise; end; end; @@ -5499,22 +7926,73 @@ procedure TBoldObjectList.AddElement(Element: TBoldElement); if Element is TBoldObject then AddLocator(TBoldObject(Element).BoldObjectLocator) else - raise EBold.CreateFmt(sElementNotBoldObject, [ClassName, 'AddElement']); // do not localize + if Element is TBoldObjectReference then + AddLocator(TBoldObjectReference(Element).Locator) + else + if Element is TBoldObjectList then + AddList(TBoldObjectList(Element)) + else + raise EBold.CreateFmt('%s.AddElement: Element %s is not a TBoldObject', [ClassName, Element.ClassName]); end; end; procedure TBoldObjectList.AddList(List: TBoldList); var - I: Integer; + i,j: Integer; ObjectList: TBoldObjectList; + vDuplicateMode: TBoldListDupMode; + vBoldSystem: TBoldSystem; begin if not mutable then - MutableError('AddListToList'); // do not localize + MutableError('AddListToList'); if not (List is TBoldObjectList) then - raise EBold.CreateFmt(sListNotObjectList, [ClassName]); - ObjectList := List as TBoldObjectList; - for I := 0 to ObjectList.Count - 1 do - AddLocator(ObjectList.Locators[I]); + raise EBold.CreateFmt('%s.AddList: List not a TBoldObjectList', [ClassName]); + i := List.Count; + if i > 0 then + begin + BeginUpdate; + try + vBoldSystem := BoldSystem; + if Assigned(vBoldSystem) then + vBoldSystem.StartTransaction(stmNormal); + try + if (i > 4) then + begin + if DuplicateMode = bldmAllow then + Capacity := Count + i; + if i > Count then + Capacity := i; + end; + vDuplicateMode := DuplicateMode; + try + if (Count = 0) and (List.DuplicateMode <> bldmAllow) then + DuplicateMode := bldmAllow; + ObjectList := List as TBoldObjectList; + j := 0; + while (j < i) do + begin + AddLocator(ObjectList.Locators[j]); + if i = List.count then + inc(j) + else // source list changed, we assume that current element has been removed + begin + i := List.count; + end; + end; + finally + SetInternalState(BoldDuplicateModeMask, BoldDMShift, Integer(vDuplicateMode)); + end; + if Assigned(vBoldSystem) then + vBoldSystem.CommitTransaction(stmNormal); + except + if Assigned(vBoldSystem) then + vBoldSystem.RollbackTransaction(stmNormal); + raise; + end; + finally + EndUpdate; + end; + end; end; procedure TBoldObjectList.InsertElement(index: Integer; Element: TBoldElement); @@ -5524,22 +8002,13 @@ procedure TBoldObjectList.InsertElement(index: Integer; Element: TBoldElement); if Element is TBoldObject then InsertLocator(index, TBoldObject(Element).BoldObjectLocator) else - raise EBold.CreateFmt(sElementNotBoldObject, [ClassName, 'InsertElement']); // do not localize + raise EBold.CreateFmt('%s.InsertElement: Element not a TBoldObject', [ClassName]); end; end; function TBoldObjectList.GetElement(index: Integer): TBoldElement; -var - aLocator: TBoldObjectLocator; begin - aLocator := GetLocator(index); - if Assigned(aLocator) then - begin - aLocator.EnsureBoldObject; - Result := aLocator.BoldObject; - end - else - Result := nil; + Result := GetLocator(index).EnsuredBoldObject; end; procedure TBoldObjectList.SetElement(index: Integer; Value: TBoldElement); @@ -5547,9 +8016,9 @@ procedure TBoldObjectList.SetElement(index: Integer; Value: TBoldElement); if Value is TBoldObject then SetLocator(index, TBoldObject(Value).BoldObjectLocator) else if not assigned(Value) then - raise EBold.CreateFmt(sElementIsNil, [classname]) + raise EBold.CreateFmt('%s.SetElement: Element is nil', [classname]) else - raise EBold.CreateFmt(sElementNotBoldObject, [classname, 'SetElement']); // do not localize + raise EBold.CreateFmt('%s.SetElement: Element not a TBoldObject', [classname]); end; function TBoldObjectList.IndexOfElement(Item: TBoldElement): Integer; @@ -5573,16 +8042,20 @@ function TBoldObjectList.GetCount: Integer; EnsureContentsCurrent; BoldClearLastFailure; if not CanRead(nil) then - BoldRaiseLastFailure(self, 'GetCount', ''); // do not localize + BoldRaiseLastFailure(self, 'GetCount', ''); result := ListController.GetCount; end; function TBoldObjectList.GetLocator(index: Integer): TBoldObjectLocator; + procedure InternalRaise(self: TBoldObjectList); inline; + begin + BoldRaiseLastFailure(self, 'GetLocator', ''); + end; begin EnsureContentsCurrent; BoldClearLastFailure; if not CanRead(nil) then - BoldRaiseLastFailure(self, 'GetLocator', ''); // do not localize + InternalRaise(self); result := ObjectListController.GetLocator(index); end; @@ -5592,11 +8065,27 @@ procedure TBoldObjectList.Assign(Source: TBoldElement); I: Integer; begin if not (Source is TBoldObjectList) then - raise EBold.CreateFmt(sSourceNotObjectList, [ClassName, Source.ClassName]); + raise EBold.CreateFmt('%s.Assign: Source is not a TBoldObjectList (%s)', [ClassName, Source.ClassName]); SourceList := TBoldObjectList(Source); - Clear; - for i := SourceList.Count - 1 downto 0 do // WARNING: TimeComplexity O2? How to ensure correct order when looping down? /Joho - InsertLocator(0, SourceList.Locators[I]); + if assigned(BoldSystem) then + BoldSystem.StartTransaction; + try + InternalClear; + Capacity := SourceList.Count; + if DuplicateMode = bldmAllow then + with ObjectListController do // using With ObjectListController skips the duplicate check on Insert + for i := SourceList.Count - 1 downto 0 do + InsertLocator(0, SourceList.Locators[I]) + else + for i := SourceList.Count - 1 downto 0 do + InsertLocator(0, SourceList.Locators[I]); + if assigned(BoldSystem) then + BoldSystem.CommitTransaction; + except + if assigned(BoldSystem) then + BoldSystem.RollbackTransaction; + raise; + end; end; procedure TBoldObjectList.SetLocator(index: Integer; NewLocator: TBoldObjectLocator); @@ -5606,7 +8095,7 @@ procedure TBoldObjectList.SetLocator(index: Integer; NewLocator: TBoldObjectLoca begin BoldClearLastFailure; if not CanSetLocator(index, NewLocator, nil) then - BoldRaiseLastFailure(self, 'SetLocator', ''); // do not localize + BoldRaiseLastFailure(self, 'SetLocator', ''); ObjectListController.SetLocator(index, NewLocator); end else @@ -5624,6 +8113,40 @@ procedure TBoldObjectList.SetBoldObject(index: Integer; NewObject: TBoldObject); SetElement(index, NewObject); end; +function TBoldObjectList.CheckAdd(NewLocator: TBoldObjectLocator): Boolean; +begin + if not Assigned(NewLocator) then + Result := False + else if OwnedByObject and (BoldSystem <> NewLocator.BoldSystem) then + result := false + else + Result := (DuplicateMode = bldmAllow) or not ObjectListController.IncludesLocator(NewLocator) or DuplicateControl; +end; + +function TBoldObjectList.CheckReplace(index: Integer; NewLocator: TBoldObjectLocator): Boolean; +begin + if not assigned(NewLocator) then + result := false + else if OwnedByObject and (BoldSystem <> NewLocator.BoldSystem) then + result := false + else if not ObjectListController.IncludesLocator(NewLocator) then + Result := True + else if IndexOfLocator(NewLocator) = index then + Result := False + else + Result := DuplicateControl; +end; + +function TBoldObjectList.CheckInsert(index: Integer; + NewLocator: TBoldObjectLocator): Boolean; +begin + assert(assigned(NewLocator), 'nil not allowed, should have been filtered out before'); + if OwnedByObject and (BoldSystem <> NewLocator.BoldSystem) then + result := false + else + Result := (DuplicateMode = bldmAllow) or not ObjectListController.IncludesLocator(NewLocator) or DuplicateControl; +end; + procedure TBoldObjectList.AddLocator(NewLocator: TBoldObjectLocator); begin EnsureContentsCurrent; @@ -5631,7 +8154,7 @@ procedure TBoldObjectList.AddLocator(NewLocator: TBoldObjectLocator); begin BoldClearLastFailure; if not CanInsertLocator(-1, NewLocator, nil) then - BoldRaiseLastFailure(self, 'AddLocator', ''); // do not localize + BoldRaiseLastFailure(self, 'AddLocator', ''); ObjectListController.AddLocator(NewLocator); end; end; @@ -5643,10 +8166,12 @@ procedure TBoldObjectList.Add(BoldObject: TBoldObject); procedure TBoldObjectList.Move(CurIndex, NewIndex: Integer); begin - if not mutable then MutableError('MoveElementInList'); // do not localize + if CurIndex = NewIndex then + exit; + if not mutable then MutableError('MoveElementInList'); BoldClearLastFailure; if not CanMove(CurIndex, NewIndex, nil) then - BoldRaiseLastFailure(self, 'Move', ''); // do not localize + BoldRaiseLastFailure(self, 'Move', ''); EnsureContentsCurrent; ListController.Move(CurIndex, NewIndex); end; @@ -5658,9 +8183,9 @@ procedure TBoldObjectList.InsertLocator(index: Integer; Locator: TBoldObjectLoca begin if CheckInsert(index, Locator) then begin - BoldClearLastFailure; + BoldClearLastFailure; if not CanInsertLocator(index, Locator, nil) then - BoldRaiseLastFailure(self, 'InsertLocator', ''); // do not localize + BoldRaiseLastFailure(self, 'InsertLocator', ''); ObjectListController.InsertLocator(index, Locator) end else @@ -5689,15 +8214,24 @@ procedure TBoldObjectList.RemoveByIndex(index: Integer); if not mutable then MutableError(IntToStr(index)); BoldClearLastFailure; if not CanRemove(index, nil) then - BoldRaiseLastFailure(self, 'RemoveByIndex', ''); // do not localize + BoldRaiseLastFailure(self, 'RemoveByIndex', ''); InternalRemoveByIndex(index); end; +procedure TBoldObjectList.RemoveLocator(ALocator: TBoldObjectLocator); +var + i: integer; +begin + i := IndexOfLocator(ALocator); + if i <> -1 then + RemoveByIndex(i); +end; + function TBoldObjectList.IndexOfLocator(Locator: TBoldObjectLocator): Integer; begin BoldClearLastFailure; if not CanRead(nil) then - BoldRaiseLastFailure(self, 'IndexOfLocator', ''); // do not localize + BoldRaiseLastFailure(self, 'IndexOfLocator', ''); EnsureContentsCurrent; result := ObjectListController.IndexOfLocator(Locator); end; @@ -5707,44 +8241,110 @@ function TBoldObjectList.Includes(BoldObject: TBoldObject): Boolean; result := IncludesElement(BoldObject); end; +function TBoldObjectList.LeastCommonClassType(ABoldSystem: TBoldSystem): TBoldClassTypeInfo; +var + i: integer; + vSystemTypeInfo: TBoldSystemTypeInfo; +begin + Result := nil; + if Empty then + exit; + if not Assigned(ABoldSystem) then + begin + ABoldSystem := BoldObjects[0].BoldSystem; + end; + vSystemTypeInfo := ABoldSystem.BoldSystemTypeInfo; + Result := Locators[0].BoldClassTypeInfo; + for i := 1 to Count - 1 do + Result := Result.LeastCommonSuperClass(Locators[i].BoldClassTypeInfo); +end; + function TBoldObjectList.LocatorInList(NewLocator: TBoldObjectLocator): Boolean; begin BoldClearLastFailure; if not CanRead(nil) then - BoldRaiseLastFailure(self, 'LocatorInList', ''); // do not localize + BoldRaiseLastFailure(self, 'LocatorInList', ''); EnsureContentsCurrent; result := ObjectListController.IncludesLocator(NewLocator); end; -function TBoldObjectList.CreateObjectIdList: TBoldObjectIdList; +function TBoldObjectList.CreateObjectIdList(WithoutDuplicates: boolean): TBoldObjectIdList; var I: Integer; begin Result := TBoldObjectIdList.Create; + Result.Capacity := Count; for I := 0 to Count - 1 do - Result.Add(Locators[I].BoldObjectID); + if WithoutDuplicates and (DuplicateMode = bldmAllow) then + Result.AddIfNotInList(Locators[I].BoldObjectID) + else + Result.Add(Locators[I].BoldObjectID); end; procedure TBoldObjectList.FillFromIDList(ObjectIdList: TBoldObjectIdList; BoldSystem: TBoldSystem); var I: Integer; begin - for I := 0 to ObjectIdList.Count - 1 do - AddLocator(BoldSystem.EnsuredLocatorByID[ObjectIdList[I]]); + if ObjectIdList.Count > 0 then + begin + Assert(ObjectListController is TBoldObjectListController, 'TBoldObjectList.FillFromIDList: Unsupported Controller: ' + ObjectListController.ClassName); + Capacity := ObjectIdList.Count; + if BeginUpdate then + try + for I := 0 to ObjectIdList.Count - 1 do + AddLocator(BoldSystem.EnsuredLocatorByID[ObjectIdList[I]]); + finally + EndUpdate; + end; + end; end; -function TBoldObjectList.GetByIndex(MemberList: TBoldMemberList): TBoldObject; +function TBoldObjectList.FilterOnType(BoldClassTypeInfo: TBoldClassTypeInfo; IncludeSubclasses: boolean): TBoldObjectList; +var + I: Integer; + iTopSortedIndex: Integer; + SystemTypeInfo: TBoldSystemTypeInfo; +begin + result := TBoldObjectList.Create; + result.DuplicateMode := bldmAllow; + iTopSortedIndex := BoldClassTypeInfo.TopSortedIndex; + SystemTypeInfo := BoldClassTypeInfo.SystemTypeInfo; + EnsureObjects; + for I := 0 to Count - 1 do + begin + if (Locators[I].BoldObjectID.TopSortedIndex = iTopSortedIndex) or (IncludeSubclasses + and Locators[I].BoldClassTypeInfo.BoldIsA(BoldClassTypeInfo)) then + Result.AddLocator(Locators[I]); + end; +end; + +procedure TBoldObjectList.RemoveDeletedObjects; +var + idList: TBoldObjectIdList; + i: integer; begin - result := GetByIndexAndSubscribe(MemberList, nil); + if not Assigned(BoldSystem) then + raise EBold.CreateFmt('%s.RemoveDeletedObjects: BoldSystem is needed to remove deleted objects.', [ClassName]); + EnsureContentsCurrent; + idList := CreateObjectIdList; + try + BoldSystem.RemoveDeletedObjects(IdList); + for I := count -1 downto 0 do + if not idList.Includes(self[i]) then + self.RemoveByIndex(i); + finally + idList.Free; + end; end; function TBoldObjectList.GetByIndexAndSubscribe(MemberList: TBoldMemberList; Subscriber: TBoldSubscriber): TBoldObject; var Locator: TBoldObjectLocator; begin + EnsureContentsCurrent; //PATCH - Needs to call makedbcurrent or calculate derivied link if invalid!!! BoldClearLastFailure; if not CanRead(nil) then - BoldRaiseLastFailure(self, 'GetByIndex', ''); // do not localize + BoldRaiseLastFailure(self, 'GetByIndex', ''); Locator := ObjectListController.GetLocatorByQualifiersAndSubscribe(MemberList, Subscriber); if Assigned(Locator) then result := Locator.EnsuredBoldObject @@ -5752,6 +8352,11 @@ function TBoldObjectList.GetByIndexAndSubscribe(MemberList: TBoldMemberList; Sub Result := nil; end; +function TBoldObjectList.GetByIndex(MemberList: TBoldMemberList): TBoldObject; +begin + result := GetByIndexAndSubscribe(MemberList, nil); +end; + function TBoldObjectList.VerifyClass(aLocator: TBoldObjectLocator): Boolean; var AllowedClass, KnownClass: TBoldClassTypeInfo; @@ -5762,26 +8367,27 @@ function TBoldObjectList.VerifyClass(aLocator: TBoldObjectLocator): Boolean; Assert(TBoldListTypeInfo(BoldType).ListElementTypeInfo is TBoldClassTypeInfo); Assert(BoldType.SystemTypeInfo is TBoldSystemTypeInfo); AllowedClass := TBoldClassTypeInfo(TBoldListTypeInfo(BoldType).ListElementTypeInfo); - KnownClass := TBoldSystemTypeInfo(BoldType.SystemTypeInfo).TopSortedClasses[aLocator.BoldObjectId.TopSortedIndex]; - if KnownClass.ConformsTo(AllowedClass) then - Result := true - else if aLocator.BoldObjectId.TopSortedIndexExact then - Result := false - else // if it looks wrong, but the classID is inexact, then we will allow it if it _could_ be right... - Result := AllowedClass.ConformsTo(knownclass); - if not result then - SetBoldLastFailureReason(TBoldFailureReason.CreateFmt(sItemNotAllowedInList, [KnownClass.ExpressionName, AllowedClass.ExpressionName], self)); + if AllowedClass.TopSortedIndex = 0 then // it's the root class so we allow anything + begin + Result := True; + end + else + begin + KnownClass := aLocator.BoldClassTypeInfo; + if KnownClass.ConformsTo(AllowedClass) then + Result := true + else if aLocator.BoldObjectId.TopSortedIndexExact then + Result := false + else + Result := AllowedClass.ConformsTo(knownclass); + if not result then + SetBoldLastFailureReason(TBoldFailureReason.CreateFmt('Can not put a %s in a %sList', [aLocator.debuginfo, self.debuginfo], self)); + end; end else result := true; end; -function TBoldObjectList.GetObjectListController: TBoldAbstractObjectListController; -begin - Assert(ListController is TBoldAbstractObjectListController); - Result := TBoldAbstractObjectListController(ListController) -end; - function TBoldObjectList.ProxyInterface(const IId: TGUID; Mode: TBoldDomainElementProxyMode; out Obj): Boolean; begin assert(assigned(ListController)); @@ -5800,41 +8406,58 @@ function TBoldObjectList.GetStreamName: String; Result := ObjectListController.StreamName; end; -procedure TBoldObjectList.EnsureObjects; +function TBoldObjectList.GetFreeStandingClass: TBoldFreeStandingElementClass; begin - EnsureRange(0, Count - 1); + Result := ObjectListController.GetFreeStandingClass; end; procedure TBoldObjectList.EnsureRange(FromIndex, ToIndex: integer); -var - FetchList: TBoldObjectList; - i: integer; - aSystem: TBoldSystem; - Locator: TBoldObjectLocator; - function RestrictRange(value, min, max: integer): integer; - begin - if value < min then - result := min - else if value > max then - result := max - else - result := value; - end; -begin - if Count > 0 then - begin - aSystem := nil; - FetchList := TBoldObjectList.Create; + procedure CheckObjects(min, max: integer); + var + FetchList: TBoldObjectList; + i: integer; + aSystem: TBoldSystem; + Locator: TBoldObjectLocator; + FullRange: boolean; + begin + aSystem := self.BoldSystem; + FetchList := nil; + FullRange := Count = max-min+1; + if FullRange then + begin + for i := min to max do + begin // first pass check if empty + if not assigned(aSystem) then + aSystem := Locators[i].BoldSystem; + if Assigned(Locators[i].BoldObject) then + begin + FullRange := false; + break + end; + end; + if FullRange and assigned(aSystem) then + begin + aSystem.SystemPersistenceHandler.FetchList(self); + exit; + end; + end; try - for i := RestrictRange(FromIndex, 0, count - 1) to RestrictRange(ToIndex, 0, count - 1) do + aSystem := nil; + for i := min to max do begin Locator := Locators[i]; - if not assigned(Locator.BoldObject) (*or - Locator.BoldObject.EffectiveInvalid*) then + // "or Locator.BoldObject.EffectiveInvalid" was commented out, but has been uncommented + if (not assigned(Locator.BoldObject) or Locator.BoldObject.EffectiveInvalid) and not Locator.BoldObjectID.NonExisting then begin if not assigned(aSystem) then + begin aSystem := Locator.BoldSystem; + FetchList := TBoldObjectList.Create; + FetchList.SubscribeToObjectsInList := false; + FetchList.DuplicateMode := bldmAllow; + FetchList.Capacity := max-min+1; + end; assert(Locator.BoldSystem = aSystem); FetchList.AddLocator(Locator); end; @@ -5842,19 +8465,41 @@ procedure TBoldObjectList.EnsureRange(FromIndex, ToIndex: integer); if assigned(aSystem) then aSystem.SystemPersistenceHandler.FetchList(FetchList); finally - FetchList.Free; + FreeAndNil(FetchList); end; end; + + function RestrictRange(value, min, max: integer): integer; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + begin + if value < min then + result := min + else if value > max then + result := max + else + result := value; + end; +var + vCount, x,y: integer; +begin + vCount := count; + if vCount = 0 then + exit; + x := RestrictRange(FromIndex, 0, vCount - 1); + y := RestrictRange(ToIndex, 0, vCount - 1); + CheckObjects(x,y); +end; + +procedure TBoldObjectList.EnsureObjects; +begin + EnsureRange(0, Count - 1); end; function TBoldObjectList.CanInsertLocator(index: Integer; Locator: TBoldObjectLocator; Subscriber: TBoldSubscriber): Boolean; begin - if not assigned(locator) then - result := false - else if ownedByObject and (locator.BoldSystem <> OwningObject.BoldSystem) then - result := false - else - result := VerifyClass(Locator) and SendQuery(bqMayInsert, [index, Locator], Subscriber); + result := VerifyClass(Locator); +{$IFNDEF BOLD_NO_QUERIES} + result := result and SendQuery(bqMayInsert, [index, Locator], Subscriber); +{$ENDIF} end; function TBoldObjectList.CanInsert(index: Integer; Element: TBoldElement; Subscriber: TBoldSubscriber): Boolean; @@ -5873,67 +8518,27 @@ function TBoldObjectList.CanSet(index: Integer; Element: TBoldElement; Subscribe function TBoldObjectList.CanSetLocator(index: Integer; Locator: TBoldObjectLocator; Subscriber: TBoldSubscriber): Boolean; begin - if not assigned(locator) then - result := false - else if ownedByObject and (locator.BoldSystem <> OwningObject.BoldSystem) then - result := false - else - result := VerifyClass(Locator) and SendQuery(bqMayReplace, [index, Locator], Subscriber); + result := VerifyClass(Locator); +{$IFNDEF BOLD_NO_QUERIES} + result := result and SendQuery(bqMayReplace, [index, Locator], Subscriber); +{$ENDIF} end; constructor TBoldObjectList.InternalCreateClassList(System: TBoldSystem; ListTypeInfo: TBoldListTypeInfo); begin - InitializeMember(System, ListTypeInfo); - DuplicateMode := bldmMerge; + inherited CreateWithOwner(system); + InitializeNonObjectOwned(ListTypeInfo); + SetInternalState(BoldDuplicateModeMask, BoldDMShift, Integer(bldmMerge{bldmError})); InitializeStateToInvalid; end; -function TBoldObjectList.CheckAdd(NewLocator: TBoldObjectLocator): Boolean; -begin - if not Assigned(NewLocator) then - Result := False // Adding nil does nothing - else if assigned(OwningObject) and (OwningObject.BoldSystem <> NewLocator.BoldSystem) then - result := false - else if not ObjectListController.IncludesLocator(NewLocator) then // LocatorInList ensures current, and we don't want that - Result := True - else - Result := DuplicateControl; -end; - -function TBoldObjectList.CheckReplace(index: Integer; NewLocator: TBoldObjectLocator): Boolean; -begin - if not assigned(NewLocator) then - result := false - else if assigned(OwningObject) and (OwningObject.BoldSystem <> NewLocator.BoldSystem) then - result := false - else if not ObjectListController.IncludesLocator(NewLocator) then - Result := True - else if IndexOfLocator(NewLocator) = index then - Result := False - else - Result := DuplicateControl; -end; - -function TBoldObjectList.CheckInsert(index: Integer; - NewLocator: TBoldObjectLocator): Boolean; -begin - assert(assigned(NewLocator), 'nil not allowed, should have been filtered out before'); - if assigned(OwningObject) and (OwningObject.BoldSystem <> NewLocator.BoldSystem) then - result := false - else if ObjectListController.IncludesLocator(NewLocator) then - result := DuplicateControl - else - result := True; -end; - -procedure TBoldObjectList.InitializeMember( - AOwningElement: TBoldDomainElement; ElementTypeInfo: TBoldElementTypeInfo); +procedure TBoldObjectList.Initialize; begin - inherited InitializeMember(AOwningElement, ElementTypeInfo); + inherited Initialize; DuplicateMode := bldmMerge; if not assigned(BoldMemberRTInfo) then begin - if assigned(AOwningElement) and (AOwningElement is TBoldSystem) then + if assigned(OwningElement) and (OwningElement is TBoldSystem) then ListController := TBoldClassListController.Create(Self) else begin @@ -5953,7 +8558,7 @@ procedure TBoldObjectList.InitializeMember( else ListController := TBoldDirectMultiLinkController.Create(Self) else - raise EBold.CreateFmt(sCannotCreateController, [ClassName]); + raise EBold.CreateFmt('%s.InitializeMember: Cannot create controller. Unknown Type.', [ClassName]); end; end; @@ -5975,13 +8580,12 @@ procedure TBoldObjectList.SetSubscribeToObjectsInList(const Value: Boolean); if value <> SubscribeToObjectsInList then begin SetElementFlag(befSubscribeToObjectsInList, value); - // the other subscription flag might be set... - (ListController as TBoldObjectListController).DropSubscriptions; // FIXME add to abstract controller - (ListController as TBoldObjectListController).Resubscribe; // FIXME add to abstract controller + (ListController as TBoldObjectListController).DropSubscriptions; + (ListController as TBoldObjectListController).Resubscribe; end; end else - raise EBold.CreateFmt(sCanOnlyChangeForStandAloneLists, [ClassName, 'SetSubscribeToObjectsInList']); // do not localize + raise EBold.CreateFmt('%s.SetSubscribeToObjectsInList: You can only change this property for stand-alone object lists', [ClassName]); end; function TBoldObjectList.GetSubscribeToLocatorsInList: Boolean; @@ -5996,18 +8600,68 @@ procedure TBoldObjectList.SetSubscribeToLocatorsInList(const Value: Boolean); if value <> SubscribeToLocatorsInList then begin SetElementFlag(befSubscribeToLocatorsInList, value); - // the other subscription flag might be set... (ListController as TBoldObjectListController).DropSubscriptions; (ListController as TBoldObjectListController).Resubscribe; end; end else - raise EBold.CreateFmt(sCanOnlyChangeForStandAloneLists, [ClassName, 'SetSubscribeToLocatorsInList']); // do not localize + raise EBold.CreateFmt('%s.SetSubscribeToLocatorsInList: You can only change this property for stand-alone object lists', [ClassName]); +end; + +function TBoldObjectList.Clone(ACopyDuplicateMode: boolean; ASubscribeToObjectsInList: boolean): TBoldMember; + + procedure FastAddList(AList: TBoldObjectList); + var + I: Integer; + vController: TBoldAbstractObjectListController; + begin + vController := ObjectListController as TBoldAbstractObjectListController; + TBoldObjectList(result).Capacity := AList.Count; + if TBoldObjectList(result).BeginUpdate then + try + with TBoldObjectList(result).ObjectListController do + for I := 0 to AList.Count - 1 do + AddLocator(vController.GetLocator(i)); + finally + TBoldObjectList(result).EndUpdate; + end; + end; + + +begin + if Assigned(BoldType) then + Result := TBoldMemberFactory.CreateMemberFromBoldType(BoldType) + else + Result := TBoldMemberClass(ClassType).Create; + if assigned(BoldSystem) then + BoldSystem.StartTransaction; + try + Result.BoldPersistenceState := bvpsTransient; + TBoldObjectList(Result).SubscribeToObjectsInList := ASubscribeToObjectsInList; + // using SetInternalState to avoid the duplicate check when setting it bldmMerge + Result.SetInternalState(BoldDuplicateModeMask, BoldDMShift, Integer(bldmAllow)); + if Count > 0 then + FastAddList(self); + if ACopyDuplicateMode then + Result.SetInternalState(BoldDuplicateModeMask, BoldDMShift, Integer(DuplicateMode)); + if assigned(BoldSystem) then + BoldSystem.CommitTransaction; + except + Result.Free; + if assigned(BoldSystem) then + BoldSystem.RollbackTransaction; + raise; + end; +end; + +function TBoldObjectList.Clone: TBoldMember; +begin + result := Clone(True, SubscribeToObjectsInList); end; -function TBoldObjectList.ProxyClass: TBoldMember_ProxyClass; +function TBoldObjectList.GetProxy(Mode: TBoldDomainElementProxyMode): TBoldMember_Proxy; begin - result := ObjectListController.ProxyClass; + result := ObjectListController.GetProxy(Self, Mode); end; function TBoldObjectList.AtTime(Time: TBoldTimestampType): TBoldMember; @@ -6018,6 +8672,19 @@ function TBoldObjectList.AtTime(Time: TBoldTimestampType): TBoldMember; result := inherited AtTime(Time); end; +function TBoldObjectList.BeginUpdate: boolean; +begin +// result := ObjectListController.StartModify; +// SendEvent(beBeginUpdate); + result := true; +end; + +procedure TBoldObjectList.EndUpdate; +begin +// ObjectListController.EndModify; +// SendEvent(beEndUpdate); +end; + procedure TBoldObjectList.FreeContent; begin inherited; @@ -6028,15 +8695,29 @@ procedure TBoldObjectList.AssignContentValueFromElement(source: TBoldElement); var i: integer; SourceList: TBoldObjectList; - Controller: TBoldObjectListController; + DestinationController: TBoldObjectListController; begin if (source is TBoldObjectList) and (ListController is TBoldObjectListController) then begin - Controller := ListController as TBoldObjectListController; SourceList := source as TBoldObjectList; - Controller.LocatorList.Clear; - for i := 0 to SourceList.Count - 1 do - Controller.Locatorlist.Add(SourceList.Locators[i]); + Clear; + if SourceList.Count = 0 then + exit; + Capacity := SourceList.Count; + if (DuplicateMode = bldmAllow) and not (hasSubscribers) then + begin + DestinationController := ListController as TBoldObjectListController; + with DestinationController.LocatorList do + begin + for i := 0 to SourceList.Count - 1 do + Add(SourceList.GetLocator(i)); + end; + end + else + begin + for I := 0 to SourceList.Count - 1 do + AddLocator(SourceList.Locators[i]); + end; end else inherited; @@ -6052,6 +8733,115 @@ procedure TBoldObjectList.InternalClear; ObjectListController.Clear; end; +procedure TBoldObjectList.DeleteObjects; +var + vBoldSystem: TBoldSystem; + + procedure FetchClass(AList: TBoldObjectList; AClass: TBoldClassTypeInfo); + var + i: integer; + vRoleRTInfo: TBoldRoleRTInfo; + begin + for i := 0 to AClass.AllRolesCount - 1 do + begin + vRoleRTInfo := AClass.AllRoles[i]; + if not vRoleRTInfo.IsDerived then + begin + case vRoleRTInfo.DeleteAction of + daCascade, daAllow: + begin + vBoldSystem.FetchLinksWithObjects(AList, vRoleRTInfo.ExpressionName); + end; + end; + end; + end; + end; + +var + vCommonClass: TBoldClassTypeInfo; + vSubClass: TBoldClassTypeInfo; + vSubclasses: TList; + vList: TBoldObjectList; + i: integer; +begin + EnsureObjects; + if empty then + exit; + vBoldSystem := BoldObjects[0].BoldSystem; + vCommonClass := LeastCommonClassType(vBoldSystem); + FetchClass(self, vCommonClass); + if vCommonClass.HasSubclasses then + begin + vSubclasses := TList.Create; + try + for I := 0 to Count - 1 do + begin + vSubClass := Locators[i].BoldObject.BoldClassTypeInfo; + if vSubClass <> vCommonClass then + begin + if vSubclasses.IndexOf(vSubClass) = -1 then + begin + vSubclasses.Add(vSubClass); + vList := FilterOnType(vSubClass, true); + try + FetchClass(vList, vSubClass); + finally + vList.free; + end; + end; + end; + end; + finally + vSubclasses.free; + end; + end; + + vBoldSystem.StartTransaction(); + vList := self.Clone as TBoldObjectList; + try + vList.SubscribeToObjectsInList := false; + vList.SubscribeToLocatorsInList := false; + for I := vList.Count - 1 downto 0 do + if not vList[i].BoldObjectIsDeleted then + vList[i].Delete + finally + vList.free; + vBoldSystem.CommitTransaction(); + end; +end; + +function TBoldObjectList.IsEqualToValue(const Value: IBoldValue): Boolean; +var + IdListRef: IBoldObjectIdListRef; + IdListRefPair: IBoldObjectIdListRefPair; + i: integer; +begin + result := false; + Assert(Assigned(Value), ClassName + '.IsEqualToValue: Value can not be nil.'); + if Supports(Value, IBoldObjectIdListRef, IdListRef) then + begin + result := IdListRef.Count = count; + if result then + for I := 0 to Count - 1 do + begin + result := result and Locators[i].BoldObjectID.IsEqual[IdListRef.IdList[i]]; + if not result then + exit; + end; + end + else if Supports(Value, IBoldObjectIdListRefPair, IdListRefPair) then + begin + result := IdListRefPair.count = count; + if result then + for I := 0 to Count - 1 do + begin + result := result and Locators[i].BoldObjectID.IsEqual[IdListRefPair.IdList2[i]]; + if not result then + exit; + end; + end; +end; + { TBoldListController } constructor TBoldListController.Create(OwningList: TBoldList); @@ -6061,17 +8851,17 @@ constructor TBoldListController.Create(OwningList: TBoldList); function TBoldListController.CreateNew: TBoldElement; begin - raise EBold.Create(sCannotCreateNewElement); + raise EBold.CreateFmt('%s.CreateNew: Can not create new elements', [ClassName]); end; -function TBoldListController.GetBoldSystem: TBoldSystem; +function TBoldListController.GetCanCreateNew: Boolean; begin - result := OwningList.BoldSystem; + result := false; end; -function TBoldListController.GetCanCreateNew: Boolean; +function TBoldListController.GetCapacity: integer; begin - result := false; + result := MaxInt; end; function TBoldListController.GetOwningMember: TBoldMember; @@ -6085,6 +8875,11 @@ function TBoldListController.GetStringrepresentation: String; Result := IntToStr(Count); end; +procedure TBoldListController.SetCapacity(const Value: integer); +begin + // nothing +end; + { TBoldAbstractObjectListController } procedure TBoldAbstractObjectListController.AddElement(Element: TBoldElement); @@ -6110,6 +8905,14 @@ procedure TBoldAbstractObjectListController.FreeContent; begin end; +function TBoldAbstractObjectListController.GetDebugInfo: string; +begin + if Assigned(OwningObjectList) then + result := Format('%s(%s)', [ClassName, OwningObjectList.DebugInfo]) + else + result := inherited GetDebugInfo +end; + function TBoldAbstractObjectListController.GetElement(index: Integer): TBoldElement; var aLocator: TBoldObjectLocator; @@ -6121,8 +8924,8 @@ function TBoldAbstractObjectListController.GetElement(index: Integer): TBoldElem function TBoldAbstractObjectListController.GetObjectList: TBoldObjectList; begin - Assert(inherited OwningList is TBoldObjectList); result := TBoldObjectList(inherited OwningList); + Assert(result is TBoldObjectList); end; function TBoldAbstractObjectListController.HandlesAtTime: Boolean; @@ -6150,7 +8953,6 @@ procedure TBoldAbstractObjectListController.InsertElement(index: Integer; Elemen procedure TBoldAbstractObjectListController.PrepareClear; begin - // do nothing end; procedure TBoldAbstractObjectListController.SetElement(index: Integer; Value: TBoldElement); @@ -6182,6 +8984,7 @@ constructor TBoldAbstractObjectReferenceController.Create(Owner: TBoldObjectRefe fOwningReference := Owner; end; + function TBoldAbstractObjectReferenceController.GetOwningMember: TBoldMember; begin Result := OwningReference; @@ -6204,17 +9007,21 @@ procedure TBoldAbstractObjectReferenceController.PreDiscard; begin end; -function TBoldObjectReferenceController.ProxyClass: TBoldMember_ProxyClass; +function TBoldObjectReferenceController.GetProxy(Member: TBoldMember; Mode: TBoldDomainElementProxyMode): TBoldMember_Proxy; begin - result := TBoldObjectReference_Proxy; + result := TBoldObjectReference_Proxy.MakeProxy(Member, Mode); end; { TBoldAbstractController } +function TBoldAbstractController.GetBoldSystem: TBoldSystem; +begin + result := OwningMember.BoldSystem; +end; + function TBoldAbstractController.AssertIntegrity: Boolean; begin Result := True; - // DO nothing, make abstract virtual later end; procedure TBoldAbstractController.Changed(Event: TBoldEvent; @@ -6246,9 +9053,23 @@ class function TBoldAbstractController.GetControllerForMember(Member: TBoldMembe result := Member.GetController; end; +function TBoldAbstractController.GetFreeStandingClass: TBoldFreeStandingElementClass; +begin + raise EBoldInternal.Createfmt('%s.GetFreeStandingClass: Method is abstract, please implement', [classname]); +end; + +function TBoldAbstractController.GetOwningObject: TBoldObject; +begin + result := OwningMember.OwningObject; +end; + +function TBoldAbstractController.GetRoleRTInfo: TBoldRoleRTInfo; +begin + result := OwningMember.BoldMemberRtInfo as TBoldRoleRTInfo; +end; + procedure TBoldAbstractController.linkto(NewLocator: TBoldObjectLocator; updateOrderNo: Boolean; Mode: TBoldLinkUnlinkMode); begin - // do nothing end; function TBoldAbstractController.LocatorForID( @@ -6277,7 +9098,6 @@ function TBoldAbstractController.StartModify: Boolean; procedure TBoldAbstractController.Unlink(OldLocator: TBoldObjectLocator; Mode: TBoldLinkUnlinkMode); begin - // do nothing end; function TBoldAbstractController.AssertedLocatorForID(ObjectId: TBoldObjectId): TBoldObjectLocator; @@ -6294,7 +9114,7 @@ procedure TBoldAbstractController.DbFetchClassForMember(TimeStamp: TBoldTimestam { TBoldObjectReferenceController } -procedure TBoldObjectReferenceController.AssignContentValue(Source: IBoldValue); +procedure TBoldObjectReferenceController.AssignContentValue(const Source: IBoldValue); var s: IBoldObjectIdRef; begin @@ -6303,10 +9123,10 @@ procedure TBoldObjectReferenceController.AssignContentValue(Source: IBoldValue); if Assigned(OwningReference) then fLocator := OwningReference.BoldSystem.EnsuredLocatorByID[s.Id] else - raise EBold.Create(sObjectRefMustBePartOfObject); + raise EBold.Create('AssignContentValue, ObjectReference must be part of Object'); end else - raise EBold.CreateFmt(sUnknownTypeOfSource, [classname, 'AssignContentValue']); // do not localize + raise EBold.CreateFmt('%s.AssignContentValue: unknown type of source', [classname]); end; constructor TBoldObjectReferenceController.Create(Owner: TBoldObjectReference); @@ -6321,6 +9141,11 @@ destructor TBoldObjectReferenceController.Destroy; inherited; end; +function TBoldObjectReferenceController.GetFreeStandingClass: TBoldFreeStandingElementClass; +begin + result := TBFSObjectIdRef; +end; + function TBoldObjectReferenceController.GetLocator: TBoldObjectLocator; begin result := fLocator; @@ -6330,7 +9155,7 @@ function TBoldObjectReferenceController.GetStreamName: string; begin result := BoldContentName_ObjectIdRef; end; - + procedure TBoldObjectReferenceController.MakeDbCurrent; begin raise EBoldInternal.CreateFmt('%s.MakeDBcurrent: This is only possible for link-controllers', [ClassName]); @@ -6347,7 +9172,7 @@ procedure TBoldObjectReferenceController.ObjectChangeReceive( procedure TBoldObjectReferenceController.SetLocator(NewLocator: TBoldObjectLocator); begin if not StartModify then - BoldRaiseLastFailure(OwningReference, 'SetLocator', ''); // do not localize + BoldRaiseLastFailure(OwningReference, 'SetLocator', ''); fLocator := NewLocator; Changed(beValueChanged, [NewLocator]); @@ -6374,8 +9199,8 @@ function TBoldLocatorHashIndex.HashItem(Item: TObject): Cardinal; function TBoldLocatorHashIndex.ItemAsLocator(Item: TObject): TBoldObjectLocator; begin - Assert(Item is TBoldObjectLocator); Result := TBoldObjectLocator(Item); + Assert(result is TBoldObjectLocator); end; function TBoldLocatorHashIndex.Match(const Key; Item: TObject): Boolean; @@ -6387,22 +9212,30 @@ function TBoldObjectList.GetElementTypeInfoForType: TBoldElementTypeInfo; var aSystem: TBoldSystem; begin - aSystem := FindASystem; + result := nil; + //TODO: check (System.BoldSystemTypeInfo.UseGeneratedCode) + if (ClassType <> TBoldObjectList) then // this will not work with systems that have no generated code + begin + aSystem := FindASystem; + if assigned(aSystem) then + result := aSystem.BoldSystemTypeInfo.ListTypes.ItemByListClass[self.ClassType] + end; +end; - if assigned(aSystem) then - result := aSystem.BoldSystemTypeInfo.ListTypes.ItemsByDelphiName[self.classname] - else - result := nil; +function TBoldObjectList.GetEnumerator: TBoldObjectListEnumerator; +begin + result := TBoldObjectListEnumerator.Create(self) end; -function TBoldAttribute.GetElementTypeInfoForType: TBoldElementTypeInfo; -var - aSystem: TBoldSystem; +function TBoldObjectList.GetLocatorEnumerator: TBoldObjectListLocatorEnumerator; begin - aSystem := FindASystem; + result := TBoldObjectListLocatorEnumerator.Create(self) +end; - if assigned(aSystem) then - result := aSystem.BoldSystemTypeInfo.AttributeTypeInfoByDelphiName[Self.ClassName] +function TBoldAttribute.GetElementTypeInfoForType: TBoldElementTypeInfo; +begin + if FindASystem <> nil then + result := GetAttributeTypeInfoForType else result := nil; end; @@ -6410,17 +9243,17 @@ function TBoldAttribute.GetElementTypeInfoForType: TBoldElementTypeInfo; procedure TBoldAttribute.RecycleValue; begin if Assigned(OwningObject) then - raise EBold.Create(sCannotRecyclePartOfObject); + raise EBold.Create('TBoldAttribute.RecycleValue: Can''t recycle part of object'); PrepareToDestroy; SetElementFlag(befImmutable, False); end; { TBoldFailureReason } -constructor TBoldFailureReason.create(reason: String; - Originator: TBoldDomainElement); +constructor TBoldFailureReason.create(AReason: String; + Originator: TBoldElement); begin - fReason := reason; + fReason := AReason; fOriginator := Originator; if assigned(fOriginator) then begin @@ -6430,7 +9263,7 @@ constructor TBoldFailureReason.create(reason: String; end; constructor TBoldFailureReason.CreateFmt(Reason: string; - const args: array of const; Originator: TBoldDomainElement); + const args: array of const; Originator: TBoldElement); begin Create(Format(Reason, Args), Originator); end; @@ -6464,26 +9297,17 @@ destructor EBoldFailure.Destroy; { TBoldMemberFactory } class function TBoldMemberFactory.CreateMemberFromBoldType(BoldType: TBoldElementTypeInfo): TBoldMember; -var - MemberClass: TBoldMemberClass; begin + if not assigned(BoldType) then + raise EBold.CreateFmt('%s.CreateMemberFromBoldType: Invalid BoldType (nil)', [ClassName]); if BoldType is TBoldListTypeInfo then - MemberClass := TBoldMemberClass(TBoldListTypeInfo(BoldType).ListClass) - else if BoldType is TBoldAttributeTypeInfo then - MemberClass := TBoldMemberClass(TBoldAttributeTypeInfo(BoldType).AttributeClass) - else if BoldType is TBoldClassTypeInfo then - MemberClass := TBoldObjectReference + result := TBoldMemberClass(TBoldListTypeInfo(BoldType).ListClass).CreateWithTypeInfo(BoldType) else begin - if assigned(BoldType) then - raise EBold.CreateFmt(sInvalidBoldType, [ClassName, BoldType.ClassName]) - else - raise EBold.CreateFmt(sInvalidBoldType_Nil, [ClassName]); + if (BoldType.ElementClass = nil) then + raise EBold.CreateFmt('%s.CreateMemberFromBoldType: Invalid BoldType (%s)', [ClassName, BoldType.ClassName]); + result := BoldType.CreateElement as TBoldMember; end; - if assigned(MemberClass) then - result := MemberClass.CreateWithTypeInfo(BoldType) - else - raise EBold.CreateFmt(sDelphiClassNotInstalled, [ClassName, BoldType.ExpressionName, BoldType.DelphiName]) end; class function TBoldMemberFactory.CreateMemberFromExpressionName(SystemTypeInfo: TBoldSystemTypeInfo; const Name: String): TBoldMember; @@ -6492,7 +9316,7 @@ class function TBoldMemberFactory.CreateMemberFromExpressionName(SystemTypeInfo: begin BoldType := SystemTypeInfo.ElementTypeInfoByExpressionName[Name]; if not assigned(BoldType) then - raise EBold.CreateFmt(sUnableToFindType, [classname, name]); + raise EBold.CreateFmt('%s.CreateMemberFromExpressionName: Unable to find a type for "%s"', [classname, name]); result := CreateMemberFromBoldType(BoldType); end; @@ -6501,6 +9325,11 @@ function TBoldObjectLocator.GetObjectIsPersistent: Boolean; result := not assigned(BoldObject) or BoldObject.BoldPersistent; end; +procedure TBoldObjectLocator.AddToLocators; +begin + BoldSystem.Locators.Add(Self); +end; + function TBoldObjectLocator.AtTime(Time: TBoldTimeStampType): TBoldObjectLocator; var NewId: TBoldObjectId; @@ -6522,37 +9351,62 @@ function TBoldObjectLocator.AtTime(Time: TBoldTimeStampType): TBoldObjectLocator { TBoldMember_Proxy } -procedure TBoldMember_Proxy.AssignContent(Source: IBoldValue); +procedure TBoldMember_Proxy.AssignContent(const Source: IBoldValue); begin + Assert(assigned(Source), 'TBoldMember_Proxy.AssignContent: Source = nil.'); AssignContentValue(Source); Assert ((Mode <> bdepPMIn) or (Source.BoldPersistenceState = bvpsCurrent)); ProxedMember.SetBoldPersistenceState(Source.BoldPersistenceState); end; +constructor TBoldMember_Proxy.Create(ProxedMember: TBoldMember; + Mode: TBoldDomainElementProxyMode); +begin + inherited Create(Mode); + fProxedMember := ProxedMember; +end; + function TBoldMember_Proxy.GetBoldPersistenceState: TBoldValuePersistenceState; begin result := ProxedMember.BoldPersistenceState; end; +function TBoldMember_Proxy.GetContentType: TBoldValueContentType; +begin + result := ProxedMember.GetFreeStandingClass.ContentType; +end; + function TBoldMember_Proxy.GetContentName: String; begin result := ProxedMember.GetStreamName; end; +function TBoldMember_Proxy.GetFreeStandingClass: TBoldFreeStandingElementClass; +begin + result := ProxedMember.GetFreeStandingClass; +end; + function TBoldMember_Proxy.GetStreamName: String; begin result := ProxedMember.GetStreamName; end; -function TBoldMember_Proxy.GetProxedController: TBoldAbstractController; +class function TBoldMember_Proxy.MakeProxy(ProxedMember: TBoldMember; + Mode: TBoldDomainElementProxyMode): TBoldMember_Proxy; begin - Result := ProxedMember.GetController; + Result := Self.Create(ProxedMember, Mode); end; -function TBoldMember_Proxy.GetProxedMember: TBoldMember; +procedure TBoldMember_Proxy.Retarget(ProxedMember: TBoldMember; + Mode: TBoldDomainElementProxyMode); begin - Assert(ProxedElement is TBoldMember); - result := TBoldMember(ProxedElement); + inherited Retarget(Mode); + fProxedMember := ProxedMember; +end; + +function TBoldMember_Proxy.GetProxedController: TBoldAbstractController; +begin + Result := ProxedMember.GetController; end; procedure TBoldMember_Proxy.SetBoldPersistenceState(Value: TBoldValuePersistenceState); @@ -6562,7 +9416,12 @@ procedure TBoldMember_Proxy.SetBoldPersistenceState(Value: TBoldValuePersistence { TBoldAttribute_Proxy } -procedure TBoldAttribute_Proxy.AssignContentValue(Source: IBoldValue); +function TBoldAttribute_Proxy.GetProxedAttribute: TBoldAttribute; +begin + result := TBoldAttribute(ProxedMember); +end; + +procedure TBoldAttribute_Proxy.AssignContentValue(const Source: IBoldValue); begin ProxedAttribute.AssignContentValue(Source); end; @@ -6572,15 +9431,26 @@ procedure TBoldAttribute_Proxy.SetContentToNull; ProxedAttribute.SetContentToNull; end; +procedure TBoldAttribute_Proxy.SetStringRepresentation(Representation: integer; + const NewValue: String); +begin + ProxedAttribute.StringRepresentation[Representation] := NewValue; +end; + +function TBoldAttribute_Proxy.GetContentAsString: String; +begin + Result := GetStringRepresentation(brDefault); +end; + function TBoldAttribute_Proxy.GetContentIsNull; begin - Result := ProxedAttribute.GetContentIsNull; + Result := ProxedAttribute.ContentIsNull; end; -function TBoldAttribute_Proxy.GetProxedAttribute: TBoldAttribute; +function TBoldAttribute_Proxy.GetStringRepresentation( + representation: integer): String; begin - Assert(ProxedElement is TBoldAttribute); - result := TBoldAttribute(ProxedElement); + result := ProxedAttribute.StringRepresentation[Representation]; end; { TBoldSystem_Proxy } @@ -6591,11 +9461,10 @@ procedure TBoldSystem_Proxy.AllObjectIds(resultList: TBoldObjectIdList; Traverser: TBoldLocatorListTraverser; begin Traverser := ProxedSystem.Locators.CreateTraverser; - while not Traverser.EndOfList do + while Traverser.MoveNext do begin if not OnlyLoaded or assigned(Traverser.Locator.BoldObject) then ResultList.Add(Traverser.Locator.BoldObjectID); - Traverser.Next; end; Traverser.Free; end; @@ -6606,18 +9475,18 @@ procedure TBoldSystem_Proxy.ApplytranslationList( I: Integer; Locator: TBoldObjectLocator; begin + if IdTranslationList.Count = 0 then + exit; for I := 0 to IdTranslationList.Count - 1 do begin if Assigned(IdTranslationList.OldIDs[I]) then begin Locator := ProxedSystem.Locators.LocatorByID[IdTranslationList.OldIDs[I]]; if Assigned(IdTranslationList.NewIDs[I]) then - // Id changed value ProxedSystem.Locators.UpdateId(Locator, IdTranslationList.NewIds[i]) end else begin - // Loaded an ID that might or might not be in-core already ProxedSystem.EnsuredLocatorByID[IdTranslationList.NewIDs[I]]; end; end; @@ -6625,17 +9494,17 @@ procedure TBoldSystem_Proxy.ApplytranslationList( ProxedSystem.fOldValueHandler.OldValues.ApplytranslationList(IdTranslationList); end; -procedure TBoldSystem_Proxy.ApplyValueSpace(ValueSpace: IBoldValueSpace; +procedure TBoldSystem_Proxy.ApplyValueSpace(const ValueSpace: IBoldValueSpace; IgnorePersistenceState: Boolean); - procedure ApplyObjectContents(BoldObject: TBoldObject; ObjectContents: IBoldObjectContents); + procedure ApplyObjectContents(BoldObject: TBoldObject; const ObjectContents: IBoldObjectContents); var i: Integer; aValue: IBoldValue; begin BoldObject.SetBoldExistenceState(ObjectContents.BoldExistenceState); BoldObject.SetBoldPersistenceState(ObjectContents.BoldPersistenceState); - for i := 0 to BoldObject.BoldMemberCount - 1 do + for i := BoldObject.BoldMemberCount - 1 downto 0 do begin aValue := ObjectContents.valueByIndex[i]; if assigned(aValue) then @@ -6665,6 +9534,15 @@ procedure TBoldSystem_Proxy.ApplyValueSpace(ValueSpace: IBoldValueSpace; end; end; + + +constructor TBoldSystem_Proxy.Create(ProxedSystem: TBoldSystem; + Mode: TBoldDomainElementProxyMode); +begin + inherited Create(Mode); + fProxedSystem := ProxedSystem; +end; + procedure TBoldSystem_Proxy.EnsureObjectContents(ObjectId: TBoldObjectId); begin if not assigned(ProxedSystem.Locators.ObjectByID[ObjectId]) then @@ -6676,7 +9554,7 @@ procedure TBoldSystem_Proxy.EnsureObjectId(ObjectId: TBoldObjectId); ObjectLocator: TBoldObjectLocator; begin ObjectLocator := ProxedSystem.GetEnsuredLocatorById(ObjectId); - if not ObjectLocator.BoldObjectID.TopSortedIndexExact and { TODO : Try to promote } + if not ObjectLocator.BoldObjectID.TopSortedIndexExact and ObjectId.TopSortedIndexExact then ProxedSystem.Locators.UpdateID(ObjectLocator, ObjectId); end; @@ -6685,9 +9563,14 @@ procedure TBoldSystem_Proxy.ExactifyIDs( TranslationList: TBoldIdTranslationList); var i: Integer; + ObjectLocator: TBoldObjectLocator; begin for i := 0 to TranslationList.Count - 1 do - ProxedSystem.Locators.UpdateId(ProxedSystem.Locators.LocatorByID[TranslationList.OldIds[i]], TranslationList.NewIds[i]); + begin + ObjectLocator := ProxedSystem.Locators.LocatorByID[TranslationList.OldIds[i]]; + if Assigned(ObjectLocator) then + ProxedSystem.Locators.UpdateId(ObjectLocator, TranslationList.NewIds[i]); + end; end; function TBoldSystem_Proxy.GetEnsuredObjectContentsByObjectId( @@ -6698,6 +9581,16 @@ function TBoldSystem_Proxy.GetEnsuredObjectContentsByObjectId( result := ProxedSystem.CreateExistingObjectByID(ObjectID).AsIBoldObjectContents[Mode]; end; +function TBoldSystem_Proxy.GetEnsuredObjectContentsByObjectIdAndCheckIfCreated( + ObjectId: TBoldObjectId; + out aBoldObjectContents: IBoldObjectContents): boolean; +begin + aBoldObjectContents := GetObjectContentsByObjectId(ObjectID); + result := not Assigned(aBoldObjectContents); + if result then + aBoldObjectContents := ProxedSystem.CreateExistingObjectByID(ObjectID).AsIBoldObjectContents[Mode]; +end; + function TBoldSystem_Proxy.GetHasContentsForId(ObjectId: TBoldObjectId): boolean; begin result := Assigned(ProxedSystem.Locators.ObjectByID[ObjectId]) @@ -6715,31 +9608,53 @@ function TBoldSystem_Proxy.GetObjectContentsByObjectId( result := nil; end; -function TBoldSystem_Proxy.GetProxedSystem: TBoldSystem; +function TBoldSystem_Proxy.IdCount: integer; begin - Assert(ProxedElement is TBoldSystem); - result := TBoldSystem(ProxedElement); + result := ProxedSystem.Locators.Count; end; +function TBoldSystem_Proxy.IsEmpty: boolean; +var + Traverser: TBoldLocatorListTraverser; +begin + result := true; + Traverser := ProxedSystem.Locators.CreateTraverser; + while Traverser.MoveNext do + begin + if assigned(Traverser.Locator.BoldObject) then + begin + result := false; + break + end; + end; + Traverser.Free; +end; { TBoldObject_Proxy } +constructor TBoldObject_Proxy.Create(ProxedObject: TBoldObject; + Mode: TBoldDomainElementProxyMode); +begin + inherited Create(Mode); + fProxedObject := ProxedObject; +end; + procedure TBoldObject_Proxy.EnsureMember(MemberId: TBoldMemberId; const ContentName: string); +begin + EnsureMemberAndGetValueByIndex(MemberId.MemberIndex, ContentName); +end; + +function TBoldObject_Proxy.EnsureMemberAndGetValueByIndex(MemberIndex: Integer; + const ContentName: string): IBoldValue; var Member: TBoldMember; begin - if MemberId.MemberIndex >= ProxedObject.BoldMembercount then - raise eBold.CreateFmt(sNotEnoughMembers, [classname, MemberId.MemberIndex]); - Member := ProxedObject.BoldMembers[MemberId.MemberIndex]; - if CompareText(Member.GetStreamName, ContentName) <> 0 then - raise EBold.CreateFmt(sUnexpectedStreamType, + Member := ProxedObject.BoldMembers[MemberIndex]; + if not SameText(Member.GetStreamName, ContentName) then + raise EBold.CreateFmt('%s.EnsureMember: %s was expected to stream as %s, but does stream as %s, check TypeNameHandle settings', [classname, Member.DisplayName, ContentName, Member.GetStreamName]); - -// FIXME: Make sure below works for BoldDirectSingleLink vs BoldObjectReference FIXME FIXME FIXME -// if AnsiCompareText(BoldMembers[MemberId.MemberIndex].TypeExpressionName, TypeExpressionName) <> 0 then -// raise EBold.CreateFmt('TBoldObject.EnsureMember: Member was of wrong type (was %s, should have been: %s', -// [BoldMembers[MemberId.MemberIndex].TypeExpressionName, TypeExpressionName]); + Result := GetValueByIndex(MemberIndex); end; function TBoldObject_Proxy.GetBoldExistenceState: TBoldExistenceState; @@ -6777,15 +9692,9 @@ function TBoldObject_Proxy.GetObjectId: TBoldObjectId; result := ProxedObject.BoldObjectLocator.BoldObjectId; end; -function TBoldObject_Proxy.GetProxedObject: TBoldObject; -begin - Assert(ProxedElement is TBoldObject); - result := TBoldObject(ProxedElement); -end; - procedure TBoldSystemLocatorList.UpdateID(Locator: TBoldObjectLocator; NewObjectID: TBoldObjectId; AllowInternal: Boolean); begin - if NewObjectID.IsStorable or AllowInternal then + if (NewObjectID.IsStorable or AllowInternal) or NewObjectID.NonExisting then begin if assigned(Locator.BoldObject) then Locator.BoldObject.SendEvent(bePreUpdateId); @@ -6811,16 +9720,15 @@ function TBoldObject_Proxy.GetValueByIndex(I: Integer): IBoldValue; function IncludeInPmOut: boolean; begin - Result := (Member.BoldPersistenceState <> bvpsInvalid) and + Result := (not Member.BoldPersistenceStateIsInvalid) and (not Member.Derived) and ((Member.BoldMemberRTInfo is TBoldAttributeRTInfo) or (TBoldRoleRTInfo(Member.BoldMemberRTInfo).RoleType in [rtRole, rtInnerLinkRole])); end; begin - if ProxedObject.BoldObjectIsNew or ProxedObject.BoldmemberAssigned[i] then - Member := ProxedObject.BoldMembers[i] - else - Member := nil; + Member := ProxedObject.GetBoldMemberIfAssigned(i); + if not ASsigned(Member) and ProxedObject.BoldObjectIsNew then + Member := ProxedObject.BoldMembers[i]; if Assigned(Member) and ((Mode <> bdepPmOut) or IncludeInPmOut) then Result := Member.AsIBoldValue[Mode] @@ -6881,8 +9789,8 @@ destructor EBoldOperationFailedForObjectList.Destroy; function TBoldLocatorListTraverser.GetLocator: TBoldObjectLocator; begin - Assert(item is TBoldObjectLocator); result := TBoldObjectLocator(item); + Assert(result is TBoldObjectLocator); end; function TBoldSystemLocatorList.CreateTraverser: TBoldLocatorListTraverser; @@ -6897,16 +9805,43 @@ function TBoldSystemLocatorList.TraverserClass: TBoldIndexableListTraverserClass { TBoldMemberDeriver } +constructor TBoldMemberDeriver.Create(Member: TBoldMember); +begin + inherited Create; + fDerivedMember := Member; +end; + +destructor TBoldMemberDeriver.Destroy; +begin + inherited; +end; + +procedure TBoldMemberDeriver.DoDeriveAndSubscribe(subscribe: Boolean); +begin + if Subscribe then + DerivedMember.DeriveMember(Self) + else + DerivedMember.DeriveMember(nil); +end; + +procedure TBoldMemberDeriver.DoNotifyOutOfDate; +begin + DerivedMember._NotifyOutOfDate; +end; + +function TBoldMemberDeriver.GetDerivedObject: TObject; +begin + Result := fDerivedMember; +end; + function TBoldMemberDeriver.GetInternalDeriverState: TBoldDeriverState; begin - Assert(DerivedObject is TBoldMember); - result := TBoldMember(DerivedObject).GetDeriverState; + result := DerivedMember.GetDeriverState; end; procedure TBoldMemberDeriver.SetInternalDeriverState(const Value: TBoldDeriverState); begin - Assert(DerivedObject is TBoldMember); - TBoldMember(DerivedObject).DeriverState := Value; + DerivedMember.DeriverState := Value; end; { TBoldAbstractOptimisticLockHandler } @@ -6923,135 +9858,126 @@ constructor TBoldSystemExtension.Create(System: TBoldSystem); fSystem := System; end; -(* -procedure TBoldObjectLocator.TypeAtLeast(TopSortedIndex: integer; Exact: Boolean); -var - OldId: TBoldObjectId; +function TBoldObjectLocator.GetClassTypeInfo: TBoldClassTypeInfo; begin - if (TopSortedIndex > BoldObjectId.TopSortedIndex) {Topsorted so more exact is always bigger} - or (Exact and not BoldObjectId.TopSortedIndexExact) then - begin - OldId := BoldObjectId; - fBoldObjectId := OldId.CloneWithClassId(TopSortedIndex, Exact); - OldId.Free; - end + if Assigned(BoldObjectId) then + result := BoldSystem.BoldSystemTypeInfo.TopSortedClasses[BoldObjectId.TopSortedIndex] + else + result := nil; end; -*) function TBoldObjectLocator.GetEmbeddedSingleLinks(EmbeddedIndex: integer): TBoldObjectLocator; begin - if Assigned(fEmbeddedSingleLinks) and - (EmbeddedIndex < fEmbeddedSingleLinks.Count) then - Result := TBoldObjectLocator(fEmbeddedSingleLinks[EmbeddedIndex]) - else - Result := nil; + if embeddedindex < Length(fEmbeddedSingleLinks) then + Result := fEmbeddedSingleLinks[EmbeddedIndex] + else + Result := nil; end; procedure TBoldObjectLocator.SetEmbeddedSingleLinks(EmbeddedIndex: integer; const Value: TBoldObjectLocator); begin - if not Assigned(fEmbeddedSingleLinks) then - fEmbeddedSingleLinks := TBoldObjectArray.Create(EmbeddedIndex + 1, []); - with fEmbeddedSingleLinks do - begin - if EmbeddedIndex >= Count then - Count := EmbeddedIndex + 1; - Items[EmbeddedIndex] := Value; - if Value = nil then {May be able to strip end} - begin - while (Count > 0) and (Items[Count - 1] = nil) do - Count := Count - 1; - if Count = 0 then - FreeAndNil(fEmbeddedSingleLinks) - else if Capacity > Count then - Capacity := Count; - end; - end; + if embeddedindex >= Length(fEmbeddedSingleLinks) then + SetLength(fEmbeddedSingleLinks, EmbeddedIndex+1); + fEmbeddedSingleLinks[EmbeddedIndex] := Value; + if Value = nil then + TryShrinkEmbeddedLinks; +end; + +procedure TBoldObjectLocator.TryShrinkEmbeddedLinks; +var + NewLength: integer; + OldLength: integer; +begin + OldLength := Length(fEmbeddedSingleLinks); + NewLength := OldLength; + while (NewLength > 0) and (not Assigned(fEmbeddedSingleLinks[NewLength-1])) do + Dec(NewLength); + if (NewLength = 0) or (NewLength < (OldLength - 3)) then + SetLength(fEmbeddedSingleLinks, NewLength); end; procedure TBoldObjectLocator.EmbeddedSingleLinksFromObject; var - m: integer; - EmbeddedIndex: integer; + i: integer; ObjectReferece: TBoldObjectReference; RoleRtInfo: TBoldRoleRTInfo; begin - for m := 0 to BoldObject.BoldClassTypeInfo.AllMembers.Count - 1 do + for i := 0 to BoldObject.BoldClassTypeInfo.AllRoles.Count - 1 do + begin + RoleRtInfo := TBoldRoleRTInfo(BoldObject.BoldClassTypeInfo.AllRoles[i]); + if (RoleRtInfo.EmbeddedLinkIndex <> -1) and BoldObject.BoldMemberAssigned[RoleRtInfo.index] then begin - EmbeddedIndex := BoldObject.BoldClassTypeInfo.AllMembers[m].EmbeddedLinkIndex; - if (EmbeddedIndex <> -1) and BoldObject.BoldMemberAssigned[m] then - begin - Assert(BoldObject.BoldClassTypeInfo.AllMembers[m] is TBoldRoleRTInfo); - Assert(BoldObject.BoldMembers[m] is TBoldObjectReference); - RoleRtInfo := TBoldRoleRTInfo(BoldObject.BoldClassTypeInfo.AllMembers[m]); - ObjectReferece := TBoldObjectReference(BoldObject.BoldMembers[m]); - if (ObjectReferece.BoldPersistenceState = bvpsCurrent) and - (RoleRtInfo.indexOfOtherEnd <> -1) and // if other end exists as is loaded, we must keep reference. - (ObjectReferece.Locator <> nil) and - (ObjectReferece.Locator.BoldObject <> nil) and - ObjectReferece.Locator.BoldObject.BoldMemberAssigned[RoleRtInfo.indexOfOtherEnd] then - EmbeddedSingleLinks[EmbeddedIndex] := ObjectReferece.Locator; - end; + Assert(BoldObject.BoldMembers[RoleRtInfo.Index] is TBoldObjectReference); + ObjectReferece := TBoldObjectReference(BoldObject.BoldMembers[RoleRtInfo.index]); + if (ObjectReferece.BoldPersistenceState = bvpsCurrent) and + (RoleRtInfo.indexOfOtherEnd <> -1) and + (ObjectReferece.Locator <> nil) and + (ObjectReferece.Locator.BoldObject <> nil) and + ObjectReferece.Locator.BoldObject.BoldMemberAssigned[RoleRtInfo.indexOfOtherEnd] then + EmbeddedSingleLinks[RoleRtInfo.EmbeddedLinkIndex] := ObjectReferece.Locator; end; + end; end; procedure TBoldObjectLocator.EmbeddedSingleLinksToObject; var - m: integer; - EmbeddedIndex: integer; + i: integer; ObjRef: TBoldObjectReference; + RoleRtInfo: TBoldRoleRTInfo; begin - if Assigned(fEmbeddedSingleLinks) then + if Length(fEmbeddedSingleLinks) > 0 then begin - for m := 0 to BoldObject.BoldClassTypeInfo.AllMembers.Count - 1 do + for i := 0 to BoldObject.BoldClassTypeInfo.AllRoles.Count - 1 do begin - EmbeddedIndex := BoldObject.BoldClassTypeInfo.AllMembers[m].EmbeddedLinkIndex; - if (EmbeddedIndex <> -1) and (EmbeddedSingleLinks[EmbeddedIndex] <> nil) then + RoleRtInfo := BoldObject.BoldClassTypeInfo.AllRoles[i]; + if (RoleRtInfo.EmbeddedLinkIndex <> -1) and (EmbeddedSingleLinks[RoleRtInfo.EmbeddedLinkIndex] <> nil) then begin - Assert(BoldObject.BoldMembers[m] is TBoldObjectReference); - ObjRef := TBoldObjectReference(BoldObject.BoldMembers[m]); - (ObjRef.AsIBoldValue[bdepInternalInitialize] as IBoldObjectIdRef).SetFromId(EmbeddedSingleLinks[EmbeddedIndex].BoldObjectID); + Assert(BoldObject.BoldMembers[RoleRtInfo.index] is TBoldObjectReference); + ObjRef := TBoldObjectReference(BoldObject.BoldMembers[RoleRtInfo.Index]); + (ObjRef.AsIBoldValue[bdepInternalInitialize] as IBoldObjectIdRef).SetFromId(EmbeddedSingleLinks[RoleRtInfo.EmbeddedLinkIndex].BoldObjectID, false); assert((ObjRef.AsIBoldValue[bdepContents] as IBoldObjectIdRef).BoldPersistenceState = bvpsInvalid); -// (ObjRef.AsIBoldValue[bdepInternalInitialize] as IBoldObjectIdRef).BoldPersistenceState := bvpsInvalid; ObjRef.HasOldValues := True; end; end; - FreeAndNil(fEmbeddedSingleLinks); + SetLength(fEmbeddedSingleLinks, 0); end; end; procedure TBoldObjectLocator.FreeEmbeddedSingleLinksOfOtherEnd; var - m: integer; - i: integer; + i,m: integer; SingleLink: TBoldObjectReference; MultiLink: TBoldObjectList; + RoleInfo: TBoldRoleRTInfo; begin - for m := 0 to BoldObject.BoldClassTypeInfo.AllMembers.Count - 1 do + for i := 0 to BoldObject.BoldClassTypeInfo.AllRoles.Count - 1 do begin - if BoldObject.BoldClassTypeInfo.AllMembers[m].IsRole and - (TBoldRoleRTInfo(BoldObject.BoldClassTypeInfo.AllMembers[m]).RoleType = rtLinkRole) and - BoldObject.BoldMemberAssigned[m] and - (BoldObject.BoldMembers[m].BoldPersistenceState = bvpsCurrent) then + RoleInfo := BoldObject.BoldClassTypeInfo.AllRoles[i]; + if (RoleInfo.RoleType = rtLinkRole) and + (RoleInfo.IndexOfMainRole=RoleInfo.index) and + BoldObject.BoldMemberAssigned[RoleInfo.Index] and + (BoldObject.BoldMembers[RoleInfo.Index].BoldPersistenceState = bvpsCurrent) then + begin + if BoldObject.BoldMembers[RoleInfo.Index] is TBoldObjectReference then begin - if BoldObject.BoldMembers[m] is TBoldObjectReference then - begin - SingleLink := TBoldObjectReference(BoldObject.BoldMembers[m]); - if Assigned(SingleLink.Locator) and Assigned(SingleLink.Locator.fEmbeddedSingleLinks) then - SingleLink.Locator.EmbeddedSingleLinks[SingleLink.BoldRoleRTInfo.RoleRTInfoOfOtherEnd.EmbeddedLinkIndex] := nil; - end - else - begin - multiLink := BoldObject.BoldMembers[m] as TBoldObjectList; - for i := 0 to Multilink.Count - 1 do - if Assigned(Multilink.Locators[i].fEmbeddedSingleLinks) then // FIXME which locator for indirects? - Multilink.Locators[i].EmbeddedSingleLinks[MultiLink.BoldRoleRTInfo.RoleRTInfoOfOtherEnd.EmbeddedLinkIndex] := nil; - end; + SingleLink := TBoldObjectReference(BoldObject.BoldMembers[RoleInfo.Index]); + if Assigned(SingleLink.Locator) and (Length(SingleLink.Locator.fEmbeddedSingleLinks) > 0) then + SingleLink.Locator.EmbeddedSingleLinks[RoleInfo.RoleRTInfoOfOtherEnd.EmbeddedLinkIndex] := nil; + end + else + begin + multiLink := BoldObject.BoldMembers[RoleInfo.Index] as TBoldObjectList; + for m := 0 to Multilink.Count - 1 do + if Length(Multilink.Locators[m].fEmbeddedSingleLinks) > 0 then + Multilink.Locators[m].EmbeddedSingleLinks[RoleInfo.RoleRTInfoOfOtherEnd.EmbeddedLinkIndex] := nil; end; + end; end; end; { TBoldAbstractUndoHandler } + procedure TBoldAbstractUndoHandler.DeleteObject(BoldObject: TBoldObject); begin if BoldObject.BoldPersistenceState <> bvpsModified then @@ -7066,13 +9992,13 @@ class function TBoldAbstractUndoHandler.GetControllerForMember(Member: TBoldMemb { TBoldObjectReference_Proxy } -procedure TBoldObjectReference_Proxy.AssignContentValue(Source: IBoldValue); +procedure TBoldObjectReference_Proxy.AssignContentValue(const Source: IBoldValue); begin Assert(ProxedController is TBoldObjectReferenceController); if Mode = bdepContents then TBoldObjectReferenceController(ProxedController).AssignContentValue(Source) else - UnsupportedMode(Mode, 'AssignContentValue'); // do not localize + UnsupportedMode(Mode, 'AssignContentValue'); end; function TBoldLocatorIdHashIndex.Hash(const Key): Cardinal; @@ -7090,7 +10016,7 @@ procedure TBoldAbstractSystemPersistenceHandler.EndFetchForAll( begin for i := 0 to ObjectList.Count - 1 do begin - anObject := ObjectList[i]; + anObject := ObjectList.Locators[i].BoldObject; if assigned(anObject) then anObject.EndFetchMembers(MemberIdList); end; @@ -7119,7 +10045,7 @@ procedure TBoldAbstractSystemPersistenceHandler.EndUpdateForAll( end; function TBoldAbstractSystemPersistenceHandler.StartUpdateForAll(ObjectList: TBoldObjectList): Boolean; - +{$IFNDEF NoMayUpdate} function MayUpdateForAll: Boolean; function ObjectProhibitsUpdate(anObject: TBoldObject): Boolean; @@ -7160,19 +10086,47 @@ function TBoldAbstractSystemPersistenceHandler.StartUpdateForAll(ObjectList: TBo IfNecessaryDoStartUpdateObject(anObject); end; end; - +{$ENDIF} begin +{$IFNDEF NoMayUpdate} result := MayUpdateForAll; if result then DoStartUpdateForAll; +{$ELSE} + result := true; +{$ENDIF} end; -initialization - G_ExternalDerivers := TBoldExternalizedReferenceList.Create; - G_ExternalDerivers.ManageReferencedObject := true; -finalization - G_ExternalDerivers.Free; -end. +procedure TBoldMemberDeriver.DoReverseDerive; +begin + SetDeriverState(bdsReverseDeriving); + if CanReversederive then + DerivedMember.ReverseDeriveMember; + case deriverstate of + bdsReverseDeriving: SetDeriverState(bdsOutOfDate); + bdsReverseDerivingSubscriptionOutOfDate: SetDeriverState(bdsSubscriptionOutOfDate); + end; +end; + +function TBoldMemberDeriver.GetCanReverseDerive: Boolean; +begin + Result := fDerivedMember.GetBoldMemberRTInfo.IsReverseDerived; +end; + +procedure InitDebugMethods; +begin + exit; + TBoldSystemLocatorList.Create.LocatorByIDString['']; + TBoldSystemLocatorList.Create.ObjectByIDString['']; + TopSortedIndex2ClassName(0); +end; +initialization + BoldFreeStandingObjectContentsClass := TBoldSystemFreeStandingObjectContents; + InitDebugMethods; +finalization + FreeAndNil(_BoldSystemList); + FreeAndNil(_BoldSystemInternalLog); +end. diff --git a/Source/ObjectSpace/BORepresentation/BoldSystemOldValuehandler.pas b/Source/ObjectSpace/BORepresentation/BoldSystemOldValuehandler.pas index 2c39fd1..a672410 100644 --- a/Source/ObjectSpace/BORepresentation/BoldSystemOldValuehandler.pas +++ b/Source/ObjectSpace/BORepresentation/BoldSystemOldValuehandler.pas @@ -1,5 +1,7 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldSystemOldValuehandler; -// Implementation of Old values in the form used for the optimistic locking support. interface @@ -31,7 +33,9 @@ TBoldOldValueHandler = class(TBoldAbstractOldValueHandler) implementation uses - SysUtils; + SysUtils, + BoldRev; + { TBoldOldValueHandler } @@ -54,20 +58,29 @@ function TBoldOldValueHandler.GetIsEmpty: Boolean; ObjectIdList: TBoldObjectIdList; ObjectContents: TBoldFreeStandingObjectContents; value: TBoldFreeStandingValue; - begin - result := true; + result := fOldValues.IdCount = 0; + if result then + exit; ObjectIdList := TBoldObjectIdList.Create; - fOldValues.AllObjectIds(objectIdList, false); - for i := 0 to ObjectIdList.Count-1 do - begin - ObjectContents := fOldValues.GetFSObjectContentsByObjectId(ObjectIdList[i]); - if assigned(objectContents) then - for m := 0 to ObjectContents.MemberCount do - begin - value := ObjectContents.FSValueByIndex[m]; - result := result and not assigned(value); - end; + try + fOldValues.AllObjectIds(objectIdList, false); // do we really need ALL objects ? + for i := 0 to ObjectIdList.Count-1 do + begin + ObjectContents := fOldValues.GetFSObjectContentsByObjectId(ObjectIdList[i]); + if assigned(objectContents) then + for m := 0 to ObjectContents.MemberCount do + begin + value := ObjectContents.FSValueByIndex[m]; + if assigned(value) then + begin + result := false; + exit; + end; + end; + end; + finally + ObjectIdList.Free; end; end; @@ -81,12 +94,17 @@ procedure TBoldOldValueHandler.MemberPersistenceStatePreChange( var aFSObjectContent: TBoldFreeStandingObjectContents; begin - // note! multilinks can have an oldvalue even if they are current. If they are invalidated, we drop the old value + if fOldValues.IsEmpty then + exit; if (BoldMember.BoldPersistenceState in [bvpsModified, bvpsCurrent]) and (NewState in [bvpsCurrent, bvpsInvalid]) then begin aFSObjectContent := fOldValues.GetFSObjectContentsByObjectId(BoldMember.OwningObject.BoldObjectLocator.BoldObjectID); if assigned(aFSObjectContent) then + begin aFSObjectContent.RemoveMemberByIndex(BoldMember.BoldMemberRTInfo.Index); + if aFSObjectContent.IsEmpty then + fOldValues.RemoveFSObjectContents(aFSObjectContent); + end; end; end; @@ -123,6 +141,7 @@ procedure TBoldOldValueHandler.PurgeEqualValues; value: TBoldFreeStandingValue; Id: TBoldObjectId; Member: TBoldMember; + bEqual: Boolean; function IdListPairEqual(IdList: TBFSObjectIdListrefPair; ObjectList: TBoldObjectList): Boolean; var @@ -152,6 +171,14 @@ procedure TBoldOldValueHandler.PurgeEqualValues; result := not assigned(ObjectRef.Locator) end; + function IdEqual(IdRef: TBFSObjectIdRef; ObjectRef: TBoldObjectReference): Boolean; + begin + if Assigned(IdRef.Id) then + result := assigned(ObjectRef.Locator) and IdRef.Id.IsEqual[ObjectRef.Locator.BoldObjectID] + else + result := not assigned(ObjectRef.Locator) + end; + begin ObjectIdList := TBoldObjectIdList.Create; try @@ -173,31 +200,67 @@ procedure TBoldOldValueHandler.PurgeEqualValues; value := ObjectContents.FSValueByIndex[m]; if assigned(value) then begin - if not Locator.BoldObject.BoldMemberAssigned[m] then - ObjectContents.RemoveMemberByIndex(m) - else - begin + if not Locator.BoldObject.BoldMemberAssigned[m] then begin + ObjectContents.RemoveMemberByIndex(m); + end else begin Member := Locator.BoldObject.BoldMembers[m]; - if Member.BoldPersistenceState = bvpsInvalid then - ObjectContents.RemoveMemberByIndex(m) // invalidate should have handled this case already... - else if (value is TBFSObjectIdListrefPair) and - IdListPairEqual(value as TBFSObjectIdListRefPair, Member as TBoldObjectList) then - ObjectContents.RemoveMemberByIndex(m) - else if (value is TBFSObjectIdListRef) and - IdListEqual(value as TBFSObjectIdListRef, Member as TBoldObjectList) then - ObjectContents.RemoveMemberByIndex(m) - else if (value is TBFSObjectIdRefPair) and - IdPairEqual(value as TBFSObjectIdRefPair, Member as TBoldObjectReference) then - ObjectContents.RemoveMemberByIndex(m) + if Member.BoldPersistenceState = bvpsInvalid then begin + ObjectContents.RemoveMemberByIndex(m); // invalidate should have handled this case already... + end else if (value is TBFSObjectIdListrefPair) then begin + if IdListPairEqual(TBFSObjectIdListRefPair(value), + Member as TBoldObjectList) then + begin + ObjectContents.RemoveMemberByIndex(m); + end; + end else if (value is TBFSObjectIdListRef) then begin + if IdListEqual(TBFSObjectIdListRef(value), + Member as TBoldObjectList) then + begin + ObjectContents.RemoveMemberByIndex(m); + end; + end else if (value is TBFSObjectIdRefPair) then begin + if IdPairEqual(TBFSObjectIdRefPair(value), + Member as TBoldObjectReference) then + begin + ObjectContents.RemoveMemberByIndex(m); + end; + end else if (value is TBFSObjectIdRef) then begin + if IdEqual(TBFSObjectIdRef(value), + Member as TBoldObjectReference) then + begin + ObjectContents.RemoveMemberByIndex(m); + end; + end else if (Member is TBoldAttribute) and + Member.IsEqualToValue(value) then + begin + ObjectContents.RemoveMemberByIndex(m); + end; end; end; end; + + bEqual := True; + // Is there no longer any difference, OldValue can be completely removed + for m := 0 to ObjectContents.MemberCount do begin + value := ObjectContents.FSValueByIndex[m]; + if Assigned(value) then begin + bEqual := False; + Break; + end; + end; + if bEqual then begin + fOldValues.RemoveFSObjectContentsByObjectId(Id); + end; end; end; end; finally ObjectIdList.Free; end; + + fOldValues.ClearWhenObjectContentsEmpty; end; +initialization + end. diff --git a/Source/ObjectSpace/BORepresentation/BoldSystemPersistenceHandler.pas b/Source/ObjectSpace/BORepresentation/BoldSystemPersistenceHandler.pas index a476fe9..0d8ce80 100644 --- a/Source/ObjectSpace/BORepresentation/BoldSystemPersistenceHandler.pas +++ b/Source/ObjectSpace/BORepresentation/BoldSystemPersistenceHandler.pas @@ -1,6 +1,8 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldSystemPersistenceHandler; -// This unit contains implementations of functions in TBoldSystem related to persistence -// which could resonably have been separated, but are provided on TBoldSystem for user convenience + interface @@ -11,7 +13,8 @@ interface BoldSystem, BoldId, BoldPersistenceController, - BoldCondition; + BoldCondition, + BoldElements; type { forward declarations } @@ -22,28 +25,35 @@ TBoldTimeMappingCache = class; TBoldSystemPersistenceHandler = class(TBoldAbstractSystemPersistenceHandler) private fTimeStampOfLatestUpdate: TBoldTimeStampType; + fTimeOfLatestUpdate: TDateTime; fTimestampToTimeCache: TBoldTimeMappingCache; fTimeToTimestampCache: TBoldTimeMappingCache; - procedure DoPreUpdate; - function GetPersistenceController: TBoldPersistenceController; + procedure DoPreUpdate(ObjectList: TBoldObjectList); + procedure DoPostUpdate(ObjectList: TBoldObjectList); + function GetPersistenceController: TBoldPersistenceController; {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure PMFetch(ObjectList: TBoldObjectList; MemberIdList: TBoldMemberIdList); protected function GetTimeStampOfLatestUpdate: TBoldTimeStampType; override; + function GetTimeOfLatestUpdate: TDateTime; override; property PersistenceController: TBoldPersistenceController read GetPersistenceController; public constructor Create(System: TBoldSystem); override; destructor Destroy; override; function EnsureEnclosure(ObjectList: TBoldObjectList; ValidateOnly: Boolean): Boolean; override; - procedure FetchLinksWithObjects(ObjectList: TBoldObjectList; const LinkName: string; FetchedObjects: TBoldObjectList); override; + procedure FetchMembersWithObjects(aBoldObjectList: TBoldObjectList; aBoldMemberIdList: TBoldMemberIdList); override; + procedure FetchMembersWithObjects(aBoldObjectList: TBoldObjectList; AMemberCommaList: string); override; + procedure FetchLinksWithObjects(ObjectList: TBoldObjectList; const LinkName: string; FetchObjectsInLink: Boolean = True{; const FetchedObjectList: TBoldObjectList = nil}); override; procedure FetchList(FetchList: TBoldObjectList); override; procedure FetchObjectById(BoldObjectId: TBoldObjectId); override; procedure FetchMember(Member: TBoldMember); override; procedure FetchClass(ClassList: TBoldObjectList; Time: TBoldTimestampType); override; procedure GetAllWithCondition(aList: TBoldObjectList; Condition: TBoldCondition); override; procedure GetAllInClassWithSQL(aList: TBoldObjectList; AClass: TBoldObjectClass; WhereClause, OrderByClause: String; Params: TParams; JoinInheritedTables: Boolean; MaxAnswers: integer; Offset: integer); override; + procedure GetAllInClassWithRawSQL(aList: TBoldObjectList; AClass: TBoldObjectClass; SQL: String; Params: TParams; MaxAnswers: integer; Offset: integer);override; function GetTimeForTimestamp(Timestamp: TBoldTimestampType): TDateTime; override; function GetTimestampForTime(ClockTime: TDateTime): TBoldTimestampType; override; - procedure UpdateDatabaseWithList(ObjectList: TBoldObjectList); override; + procedure UpdateDatabaseWithList(ObjectList: TBoldObjectList); override; + function CanEvaluateInPS(sOCL: string; aContext: TBoldElementTypeInfo = nil; const aVariableList: TBoldExternalVariableList = nil): Boolean; override; end; { TBoldTimeMappingCache } @@ -60,11 +70,14 @@ TBoldTimeMappingCache = class(TBoldMemoryManagedObject) procedure Add(Timestamp: TBoldTimestampType; ClockTime: TDateTime); end; + implementation uses + Classes, SysUtils, - BoldvalueInterfaces, + BoldSubscription, + BoldValueInterfaces, BoldValueSpaceInterfaces, BoldDomainElement, BoldSystemRT, @@ -72,31 +85,46 @@ implementation BoldUpdatePrecondition, BoldGuard, BoldMath, - BoldCoreConsts; + BoldRev; { TBoldSystemPersistenceHandler } +function TBoldSystemPersistenceHandler.CanEvaluateInPS(sOCL: string; + aContext: TBoldElementTypeInfo; + const aVariableList: TBoldExternalVariableList): Boolean; +begin + Result := PersistenceController.CanEvaluateInPS(sOCL, System, aContext, aVariableList); +end; + constructor TBoldSystemPersistenceHandler.Create(System: TBoldSystem); begin Inherited Create(System); fTimeStampOfLatestUpdate := -1; + fTimeOfLatestUpdate := 0; fTimestampToTimeCache := TBoldTimeMappingCache.Create(100); fTimeToTimestampCache := TBoldTimeMappingCache.Create(20); end; -procedure TBoldSystemPersistenceHandler.DoPreUpdate; +procedure TBoldSystemPersistenceHandler.DoPreUpdate(ObjectList: TBoldObjectList); begin + System.SendExtendedEvent(beBeginUpdate, [ObjectList]); if Assigned(OnPreUpdate) then - OnPreUpdate(self); + OnPreUpdate(ObjectList); +end; + +procedure TBoldSystemPersistenceHandler.DoPostUpdate( + ObjectList: TBoldObjectList); +begin + System.SendExtendedEvent(beEndUpdate, [ObjectList]); + if Assigned(OnPostUpdate) then + OnPostUpdate(ObjectList); end; function TBoldSystemPersistenceHandler.EnsureEnclosure(ObjectList: TBoldObjectList; ValidateOnly: Boolean): Boolean; -// TODO: The enclosure should include the expanded "regions" of all objects in the list var - I, M : Integer; + I,J,M : Integer; ExamineBoldObject: TBoldObject; ListIsEnclosure: Boolean; - MemberRTInfo: TBoldMemberRTInfo; RoleRTInfo: TBoldRoleRTInfo; OtherEnd: TBoldObjectReference; ObjectReference: TBoldObjectReference; @@ -110,7 +138,8 @@ function TBoldSystemPersistenceHandler.EnsureEnclosure(ObjectList: TBoldObjectLi if not ValidateOnly then begin if (Locator.BoldObjectId is TBoldInternalObjectId) and not assigned(Locator.BoldObject) then - assert(false, 'Internal Error, a deleted non-saved object got into the enclosure, try to figure out why...') + assert(false, Format('Internal Error, a deleted non-saved object got into the enclosure, while processing Object ID:%s(%s), Role:%s. Locator.Id:%s.', + [ExamineBoldObject.Displayname, ExamineBoldObject.BoldObjectLocator.AsString, RoleRTInfo.asString, Locator.BoldObjectId.AsString])) else ObjectList.AddLocator(Locator); end; @@ -143,13 +172,11 @@ function TBoldSystemPersistenceHandler.EnsureEnclosure(ObjectList: TBoldObjectLi begin if RoleRTInfo.IsMultiRole then begin - // Indirect MultiLink for i := 0 to (OldValue as IBoldObjectIdListRefPair).Count-1 do AddIdToEnclosure((OldValue as IBoldObjectIdListRefPair).IdList1[i]); end else begin - // Indirect SingleLink AddIdToEnclosure((OldValue as IBoldObjectIdRefPair).Id1); end; end @@ -157,13 +184,11 @@ function TBoldSystemPersistenceHandler.EnsureEnclosure(ObjectList: TBoldObjectLi begin if RoleRTInfo.IsMultiRole then begin - // Direct Multilink for i := 0 to (OldValue as IBoldObjectIdListRef).Count-1 do AddIdToEnclosure((OldValue as IBoldObjectIdListRef).IdList[i]); end else begin - // Direct Singlelink if RoleRTInfo.RoleRTInfoOfOtherEnd.IsStoredInObject then AddIdToEnclosure((OldValue as IBoldObjectIdRef).Id); end; @@ -171,59 +196,125 @@ function TBoldSystemPersistenceHandler.EnsureEnclosure(ObjectList: TBoldObjectLi end; end; +var + OldCount: Integer; //PATCH begin +{$IFDEF NoEnsureEnclosure} + exit; +{$ENDIF} ListIsEnclosure := true; i := 0; while i < ObjectList.Count do - begin + begin + OldCount := ObjectList.Count; //PATCH ExamineBoldObject := ObjectList[i]; - for M := 0 to ExamineBoldObject.BoldClassTypeInfo.AllMembers.Count - 1 do + if OldCount<=ObjectList.Count then //PATCH + Inc(i); //PATCH + for J := 0 to ExamineBoldObject.BoldClassTypeInfo.AllRoles.Count - 1 do begin - MemberRTInfo := ExamineBoldObject.BoldClassTypeInfo.AllMembers[M]; - if memberRTInfo.IsRole then + RoleRTInfo := ExamineBoldObject.BoldClassTypeInfo.AllRoles[J]; + M := RoleRTInfo.Index; + if RoleRTInfo.IsSingleRole and RoleRTInfo.Persistent and RoleRTInfo.IsStoredInObject and + ExamineBoldObject.BoldMemberAssigned[M] and (ExamineBoldObject.BoldMembers[M].BoldPersistenceState = bvpsModified) then begin - RoleRTInfo := MemberRTInfo as TBoldRoleRTInfo; - - if RoleRTInfo.IsSingleRole and RoleRTInfo.Persistent and RoleRTInfo.IsStoredInObject and - ExamineBoldObject.BoldMemberAssigned[M] and - (ExamineBoldObject.BoldMembers[M].BoldPersistenceState = bvpsModified) then + ObjectReference := ExamineBoldObject.BoldMembers[M] as TBoldObjectReference; + if Assigned(ObjectReference.Locator) and not ObjectReference.Locator.ObjectIsPersistent then + raise EBold.CreateFmt('Can not update Object "%s", role "%s" points to object "%s" which is transient.', [ExamineBoldObject.DisplayName, ExamineBoldObject.BoldMembers[M].BoldMemberRTInfo.ExpressionName, ObjectReference.BoldObject.DisplayName]); + if RoleRTInfo.RoleRTInfoOfOtherEnd.IsStoredInObject then begin - // singlelinks should include the other end if it is stored or belongs to a new object - ObjectReference := ExamineBoldObject.BoldMembers[M] as TBoldObjectReference; - if RoleRTInfo.RoleRTInfoOfOtherEnd.IsStoredInObject then - begin - AddLocatorToEnclosure(ObjectReference.Locator); - AddOldValuesForRole(ObjectReference, RoleRTInfo); - end - else + AddLocatorToEnclosure(ObjectReference.Locator); + AddOldValuesForRole(ObjectReference, RoleRTInfo); + end + else + begin + AddUnsavedLocatorToEnclosure(ObjectReference.Locator); + if RoleRTInfo.RoleRTInfoOfOtherEnd.IsSingleRole then begin - AddUnsavedLocatorToEnclosure(ObjectReference.Locator); - if RoleRTInfo.RoleRTInfoOfOtherEnd.IsSingleRole then + + if assigned(ObjectReference.Locator) and assigned(ObjectReference.Locator.BoldObject) then begin - // the other end is single-nonembedded, so we must include the old value of that link in our enclosure - // to make sure that the unlinking of that link is saved at the same time. - if assigned(ObjectReference.Locator) and assigned(ObjectReference.Locator.BoldObject) then - begin - OtherEnd := ObjectReference.Locator.BoldObject.BoldMembers[RoleRTInfo.IndexOfOtherEnd] as TBoldObjectReference; - AddIdToEnclosure(OtherEnd.OldEmbeddingOtherEndId); - end; + OtherEnd := ObjectReference.Locator.BoldObject.BoldMembers[RoleRTInfo.IndexOfOtherEnd] as TBoldObjectReference; + AddIdToEnclosure(OtherEnd.OldEmbeddingOtherEndId); end; end; end; + end; - if ExamineBoldObject.BoldObjectIsDeleted then - begin - AddOldValuesForRole(ExamineBoldObject.BoldMembers[M], RoleRTInfo); - end; + if ExamineBoldObject.BoldObjectIsDeleted then + begin + AddOldValuesForRole(ExamineBoldObject.BoldMembers[M], RoleRTInfo); end; end; System.OptimisticLockHandler.EnsureEnclosure(ExamineBoldObject, ObjectList, ValidateOnly, ListIsEnclosure); - inc(i); + //PATCH MOVED UP Inc(i); end; result := ListIsEnclosure; end; -procedure TBoldSystemPersistenceHandler.FetchLinksWithObjects(ObjectList: TBoldObjectList; const LinkName: string; FetchedObjects: TBoldObjectList); +procedure TBoldSystemPersistenceHandler.FetchMembersWithObjects( + aBoldObjectList: TBoldObjectList; aBoldMemberIdList: TBoldMemberIdList); +var + ListToFetch: TBoldObjectList; + vObject: TBoldObject; + i,j: integer; +begin + ListToFetch := TBoldObjectList.Create; + try + for i := 0 to aBoldObjectList.Count - 1 do + begin + vObject := aBoldObjectList.Locators[i].BoldObject; + if not Assigned(vObject) then + ListToFetch.AddLocator(aBoldObjectList.Locators[i]) + else + if Assigned(aBoldMemberIdList) then + begin + for j := 0 to aBoldMemberIdList.Count - 1 do + if not vObject.BoldMemberAssigned[aBoldMemberIdList[j].MemberIndex] then + begin + ListToFetch.Add(vObject); + break; + end; + end + else + ListToFetch.Add(vObject); + end; + PMFetch(ListToFetch, aBoldMemberIdList); + finally + ListToFetch.free; + end; +end; + +procedure TBoldSystemPersistenceHandler.FetchMembersWithObjects( + aBoldObjectList: TBoldObjectList; AMemberCommaList: string); +var + sl: TStringList; + i,j: integer; + vMemberIdList: TBoldMemberIdList; + vLeastCommonClassType: TBoldClassTypeInfo; +begin + if aBoldObjectList.Empty then + exit; + sl := TStringList.Create; + vMemberIdList := TBoldMemberIdList.Create; + try + sl.CommaText := AMemberCommaList; + vLeastCommonClassType := aBoldObjectList.LeastCommonClassType(System); + for i := 0 to sl.Count - 1 do + begin + j := vLeastCommonClassType.MemberIndexByExpressionName[sl[i]]; + if j = -1 then + raise EBold.CreateFmt('Member %s not found in class %s.', [sl[i], vLeastCommonClassType.ExpressionName]); + if vLeastCommonClassType.AllMembers[j].Persistent then + vMemberIdList.Add(TBoldMemberId.create(j)); + end; + FetchMembersWithObjects(aBoldObjectList, vMemberIdList); + finally + vMemberIdList.free; + sl.free; + end; +end; + +procedure TBoldSystemPersistenceHandler.FetchLinksWithObjects(ObjectList: TBoldObjectList; const LinkName: string;FetchObjectsInLink: Boolean = True{; const FetchedObjectList: TBoldObjectList = nil}); var CommonClass: TBoldClassTypeInfo; I, J: Integer; @@ -243,77 +334,79 @@ procedure TBoldSystemPersistenceHandler.FetchLinksWithObjects(ObjectList: TBoldO end; begin - Guard := tBoldGuard.Create(FetchList, MemberIdList); - - if not System.BoldPersistent or (ObjectList.Count = 0) then + if not System.BoldPersistent then exit; - - FetchList := TBoldObjectList.create; - MemberIdList := TBoldMemberIdList.Create; - ObjectList.EnsureObjects; - - // Find common class - CommonClass := ObjectList[0].BoldClassTypeInfo; - for I := 1 to ObjectList.Count - 1 do + if ObjectList.Count > 0 then begin - CommonClass := CommonClass.LeastCommonSuperClass(ObjectList[I].BoldClassTypeInfo); - if ObjectList[I].BoldSystem <> System then - raise EBoldFeatureNotImplementedYet.Create(sCannotFetchWithLinksFromMultipleSystems); - end; + Guard := TBoldGuard.Create(FetchList, MemberIdList); + FetchList := TBoldObjectList.Create; + FetchList.SubscribeToObjectsInList := False; + MemberIdList := TBoldMemberIdList.Create; + CommonClass := ObjectList[0].BoldClassTypeInfo; + for I := 1 to ObjectList.Count - 1 do + begin + CommonClass := CommonClass.LeastCommonSuperClass(ObjectList[I].BoldClassTypeInfo); + if ObjectList[I].BoldSystem <> System then + raise EBoldFeatureNotImplementedYet.Create('Can''t Fetch with link objects from multiple systems'); + end; - if not Assigned(CommonClass) then - raise EBold.CreateFmt(sNoCommonSuperClass, [ClassName]); + if not Assigned(CommonClass) then + raise EBold.CreateFmt('%s.FetchLinksWithObjects: Objects have no common superClass', [ClassName]); - MemberRTInfo := CommonClass.MemberRTInfoByExpressionName[LinkName]; - if not (MemberRTInfo is TBoldRoleRTInfo) then - raise EBold.CreateFmt(sNoRoleCalledX, [ClassName, CommonClass.ExpressionName, LinkName]); + MemberRTInfo := CommonClass.MemberRTInfoByExpressionName[LinkName]; + if not (MemberRTInfo is TBoldRoleRTInfo) then + raise EBold.CreateFmt('%s.FetchLinksWithObjects: class %s has no role called %s', [ClassName, CommonClass.ExpressionName, LinkName]); - roleRTInfo := MemberRTInfo as TBoldRoleRTInfo; + roleRTInfo := MemberRTInfo as TBoldRoleRTInfo; - if not roleRTInfo.IsStoredInObject and RoleRTInfo.Persistent and (RoleRTInfo.RoleType = rtRole) then - begin - for I := 0 to ObjectList.Count - 1 do - if ObjectList[I].BoldMembers[roleRTInfo.index].BoldPersistenceState = bvpsInvalid then - FetchList.Add(ObjectList[I]); - if FetchList.count > 0 then + if not roleRTInfo.IsStoredInObject and RoleRTInfo.Persistent and (RoleRTInfo.RoleType = rtRole) then begin - MemberIdList.Add(TBoldMemberId.Create(MemberRTInfo.index)); - PMFetch(FetchList, MemberIdList); + for I := 0 to ObjectList.Count - 1 do + if ObjectList[I].BoldMembers[roleRTInfo.index].BoldPersistenceState = bvpsInvalid then + FetchList.Add(ObjectList[I]); + if FetchList.count > 0 then + begin + MemberIdList.Add(TBoldMemberId.Create(MemberRTInfo.index)); + PMFetch(FetchList, MemberIdList); + end; end; - end; - - FetchList.Clear; - for I := 0 to ObjectList.Count - 1 do - begin - if roleRTInfo.IsMultiRole then - begin - MultiLink := ObjectList[I].BoldMembers[roleRTInfo.index] as TBoldObjectList; - for J := 0 to MultiLink.Count - 1 do - InternalAddLocator(MultiLink.Locators[J]); - end - else + FetchList.Clear; + for I := 0 to ObjectList.Count - 1 do begin - SingleLink := ObjectList[I].BoldMembers[roleRTInfo.index] as TBoldObjectReference; - InternalAddLocator(SingleLink.Locator); + if roleRTInfo.IsMultiRole then + begin + Assert(ObjectList[I].BoldMembers[roleRTInfo.index] is TBoldObjectList); + MultiLink := TBoldObjectList(ObjectList[I].BoldMembers[roleRTInfo.index]); + for J := 0 to MultiLink.Count - 1 do + InternalAddLocator(MultiLink.Locators[J]); + end + else + begin + Assert(ObjectList[I].BoldMembers[roleRTInfo.index] is TBoldObjectReference); + SingleLink := TBoldObjectReference(ObjectList[I].BoldMembers[roleRTInfo.index]); + InternalAddLocator(SingleLink.Locator); + end; end; + if (FetchList.Count>0) and FetchObjectsInLink then + PMFetch(FetchList, nil); end; - if FetchList.Count > 0 then - PMFetch(FetchList, nil); - if Assigned(FetchedObjects) then - FetchedObjects.Assign(FetchList); end; procedure TBoldSystemPersistenceHandler.FetchObjectById(BoldObjectId: TBoldObjectId); var ObjectList: TBoldObjectList; begin + PersistenceController.SendExtendedEvent(bpeStartFetchObjectById, [BoldObjectId]); ObjectList := TBoldObjectList.Create; + ObjectList.SubscribeToObjectsInList := false; + ObjectList.duplicateMode := bldmAllow; try ObjectList.AddLocator(System.EnsuredLocatorByID[BoldObjectID]); PMFetch(ObjectList, nil); finally ObjectList.Free; + PersistenceController.SendExtendedEvent(bpeEndFetchObjectById, [BoldObjectId]); end; end; @@ -324,11 +417,10 @@ procedure TBoldSystemPersistenceHandler.GetAllWithCondition(aList: TBoldObjectLi ObjectIdList: TBoldObjectIdList; begin if not assigned(PersistenceController) then - raise EBold.Create(sNoPersistenceController); + raise EBold.Create('Unable to fetch object ID''s. No PersistenceController...'); ObjectIdList := TBoldObjectIdList.Create; try PersistenceController.PMFetchIDListWithCondition(ObjectIdList, System.AsIBoldvalueSpace[bdepPMIn], fmNormal, Condition, NOTVALIDCLIENTID); - // remove objects that have been deleted in memory for I := ObjectIdList.Count - 1 downto 0 do begin Locator := System.Locators.LocatorByID[ObjectIdList[i]]; @@ -341,12 +433,57 @@ procedure TBoldSystemPersistenceHandler.GetAllWithCondition(aList: TBoldObjectLi end; end; +procedure TBoldSystemPersistenceHandler.GetAllInClassWithRawSQL( + aList: TBoldObjectList; AClass: TBoldObjectClass; SQL: String; + Params: TParams; MaxAnswers, Offset: integer); +var + Condition: TBoldRawSQLCondition; + LocalParams: TParams; + ClasstypeInfo: TBoldClasstypeInfo; + Guard: IBoldGuard; +begin + Guard := TBoldGuard.Create(Condition, LocalParams); + Condition := TBoldRawSQLCondition.Create; + Condition.SQL := SQL; + Condition.MaxAnswers := MaxAnswers; + Condition.Offset := Offset; + if assigned(aClass) then + begin + ClassTypeInfo := System.BoldSystemTypeInfo.TopSortedClasses.ItemsByObjectClass[AClass]; + if Assigned(ClassTypeInfo) then + Condition.TopSortedIndex := ClassTypeInfo.TopSortedIndex + else + raise EBold.CreateFmt('%s.GetAllInClassWithSQL: "%s" is not a class in the model', [classname, aClass.ClassName]); + end + else + raise EBold.CreateFmt('%s.GetAllInClassWithSQL: Must not be called without a class-parameter', [classname]); + + if not assigned(Params) then + begin + LocalParams := TParams.Create(nil); + Condition.Params := LocalParams; + end + else + begin + Condition.Params := PArams; + LocalParams := nil; + end; + PersistenceController.SendExtendedEvent(bpeStartFetchAllInClassWithRawSQL, [aList, AClass, Condition]); + try + GetAllWithCondition(aList, Condition); + finally + PersistenceController.SendExtendedEvent(bpeEndFetchAllInClassWithRawSQL, [aList, AClass, Condition]); + end; +end; + procedure TBoldSystemPersistenceHandler.GetAllInClassWithSQL(aList: TBoldObjectList; AClass: TBoldObjectClass; WhereClause, OrderByClause: String; Params: TParams; JoinInheritedTables: Boolean; MaxAnswers: integer; Offset: integer); var Condition: TBoldSQLCondition; LocalParams: TParams; ClasstypeInfo: TBoldClasstypeInfo; + Guard: IBoldGuard; begin + Guard := TBoldGuard.Create(Condition, LocalParams); Condition := TBoldSQLCondition.Create; Condition.WhereFragment := WhereClause; Condition.OrderBy := OrderByClause; @@ -359,10 +496,10 @@ procedure TBoldSystemPersistenceHandler.GetAllInClassWithSQL(aList: TBoldObjectL if Assigned(ClassTypeInfo) then Condition.TopSortedIndex := ClassTypeInfo.TopSortedIndex else - raise EBold.CreateFmt(sNoSuchClassInModel, [classname, aClass.ClassName]); + raise EBold.CreateFmt('%s.GetAllInClassWithSQL: "%s" is not a class in the model', [classname, aClass.ClassName]); end else - raise EBold.CreateFmt(sClassParameterMissing, [classname]); + raise EBold.CreateFmt('%s.GetAllInClassWithSQL: Must not be called without a class-parameter', [classname]); if not assigned(Params) then begin @@ -374,12 +511,11 @@ procedure TBoldSystemPersistenceHandler.GetAllInClassWithSQL(aList: TBoldObjectL Condition.Params := PArams; LocalParams := nil; end; - + PersistenceController.SendExtendedEvent(bpeStartFetchAllInClassWithSQL, [aList, AClass, Condition]); try GetAllWithCondition(aList, Condition); finally - Condition.Free; - LocalParams.Free; + PersistenceController.SendExtendedEvent(bpeEndFetchAllInClassWithSQL, [aList, AClass, Condition]); end; end; @@ -393,25 +529,23 @@ procedure TBoldSystemPersistenceHandler.UpdateDatabaseWithList(ObjectList: TBold Precondition: TBoldOptimisticLockingPrecondition; begin if System.InTransaction then - raise EBold.Create(sCannotUpdateWhileInTransaction); + raise EBold.Create('Can not update the database while in a transaction'); + if not assigned(PersistenceController) then + raise EBold.Create('Unable to UpdateDatabaseWithList. No PersistenceController.'); System.DelayObjectDestruction; ObjectsToUpdate := ObjectList.Clone as TBoldObjectList; try for i := ObjectsToUpdate.Count-1 downto 0 do - begin - if ObjectsToUpdate.Locators[i].BoldSystem <> System then - raise EBold.CreateFmt(sForeignObjectInUpdate, [classname]); if not assigned(ObjectsToUpdate.Locators[i].BoldObject) or not ObjectsToUpdate[i].BoldPersistent then ObjectsToUpdate.RemoveByIndex(i); - end; if ObjectsToUpdate.Count > 0 then begin - DoPreUpdate; EnsureEnclosure(ObjectsToUpdate, false); - ObjectIdList := ObjectsToUpdate.CreateObjectIdList; + DoPreUpdate(ObjectsToUpdate); + ObjectIdList := ObjectsToUpdate.CreateObjectIdList(true); aTranslationList := TBoldIdTranslationList.Create; if System.BoldSystemTypeInfo.OptimisticLocking = bolmOff then Precondition := nil @@ -423,21 +557,19 @@ procedure TBoldSystemPersistenceHandler.UpdateDatabaseWithList(ObjectList: TBold FreeAndNil(PreCondition); end; - //TODO: in the future, call another function to add optimistic locking data for optimistic region locking - //TODO: If the model wants optimistic locking, but none of the classes of objects to be updated, - // the precondition should be freed. + try if assigned(System.PessimisticLockHandler) and not System.PessimisticLockHandler.EnsureLocks then - raise EBold.CreateFmt(sRequiredLocksNotHeld, [classname]); + raise EBold.CreateFmt('%s.UpdateDatabaseWithList: Not allowed to update. No longer holding the required locks.', [classname]); BoldClearLastfailure; try if not StartUpdateForAll(ObjectsToUpdate) then - BoldRaiseLastFailure(System, 'UpdateDatabaseWithList', sStartUpdateFailed); // do not localize + BoldRaiseLastFailure(System, 'UpdateDatabaseWithList', 'StartUpdate failed'); - PersistenceController.PMUpdate(ObjectIdList, System.AsIBoldvalueSpace[bdepPMOut], nil, Precondition, aTranslationList, fTimeStampOfLatestUpdate, NOTVALIDCLIENTID); + PersistenceController.PMUpdate(ObjectIdList, System.AsIBoldvalueSpace[bdepPMOut], System.OptimisticLockHandler.OldValues, Precondition, aTranslationList, fTimeStampOfLatestUpdate, fTimeOfLatestUpdate, NOTVALIDCLIENTID); if assigned(Precondition) and Precondition.Failed then begin if assigned(system.OnOptimisticLockingFailed) then @@ -457,12 +589,15 @@ procedure TBoldSystemPersistenceHandler.UpdateDatabaseWithList(ObjectList: TBold for i := 0 to ObjectsToUpdate.Count - 1 do ObjectsToUpdate[i].AsIBoldObjectContents[bdepPMIn].TimeStamp := TimeStampOfLatestUpdate; EndUpdateForAll(ObjectsToUpdate, aTranslationList); + if Assigned(System.UndoHandler) then + System.UndoHandler.PrepareUpdate(ObjectList); end; + DoPostUpdate(ObjectList); except on e: Exception do begin if GetBoldLastFailureReason <> nil then - BoldRaiseLastFailure(System, 'UpdateDatabaseWithlist', e.message) // do not localize + BoldRaiseLastFailure(System, 'UpdateDatabaseWithlist', e.message) else raise; end; @@ -487,6 +622,11 @@ function TBoldSystemPersistenceHandler.GetTimeStampOfLatestUpdate: TBoldTimeStam Result := fTimeStampOfLatestUpdate; end; +function TBoldSystemPersistenceHandler.GetTimeOfLatestUpdate: TDateTime; +begin + Result := fTimeOfLatestUpdate; +end; + function TBoldSystemPersistenceHandler.GetPersistenceController: TBoldPersistenceController; begin Result := System.PersistenceController; @@ -499,8 +639,11 @@ procedure TBoldSystemPersistenceHandler.FetchMember(Member: TBoldMember); MemberId: TBoldMemberId; Guard: IBoldguard; begin + PersistenceController.SendExtendedEvent(bpeStartFetchMember, [Member]); Guard := TBoldGuard.Create(ObjectList, MemberIdList); ObjectList := TBoldObjectList.Create; + ObjectList.SubscribeToObjectsInList := false; + ObjectList.DuplicateMode := bldmAllow; ObjectList.Add(Member.OwningObject); if Member.BoldMemberRTInfo.DelayedFetch then begin @@ -509,6 +652,7 @@ procedure TBoldSystemPersistenceHandler.FetchMember(Member: TBoldMember); MemberIdList.Add(MemberId); end; PMFetch(ObjectList, MemberIdList); + PersistenceController.SendExtendedEvent(bpeEndFetchMember, [Member]); end; procedure TBoldSystemPersistenceHandler.FetchClass(ClassList: TBoldObjectList; Time: TBoldTimestampType); @@ -519,8 +663,9 @@ procedure TBoldSystemPersistenceHandler.FetchClass(ClassList: TBoldObjectList; T ListInterface: IBoldObjectIdListRef; begin if not assigned(PersistenceController) then - raise EBold.Create(sNoPersistenceController); + raise EBold.Create('Unable to fetch object ID''s. No PersistenceController.'); ClassTypeInfo := (ClassList.BoldType as TBoldListTypeInfo).ListElementTypeInfo as TBoldClassTypeInfo; + PersistenceController.SendExtendedEvent(bpeStartFetchClass, [ClassTypeInfo]); ObjectIdList := TBoldObjectIdList.Create; Condition := TBoldConditionWithClass.Create; @@ -534,6 +679,7 @@ procedure TBoldSystemPersistenceHandler.FetchClass(ClassList: TBoldObjectList; T finally FreeAndNil(Condition); FreeAndNil(ObjectIdList); + PersistenceController.SendExtendedEvent(bpeEndFetchClass, [ClassTypeInfo]); end; end; @@ -570,15 +716,13 @@ procedure TBoldSystemPersistenceHandler.PMFetch(ObjectList: TBoldObjectList; Mem var ObjectIdList: TBoldObjectIdList; Guard: IBoldGuard; - i: integer; begin - Guard := TBoldguard.Create(ObjectidList); - if Objectlist.Count > 0 then + if not assigned(PersistenceController) then + raise EBold.Create('Unable to PMFetch. No PersistenceController...'); + if (Objectlist.Count > 0) then begin - ObjectIdList := TBoldObjectIdList.Create; - for i := 0 to Objectlist.Count-1 do - ObjectIdList.Add(ObjectList.Locators[i].BoldObjectID); - + Guard := TBoldguard.Create(ObjectidList); + ObjectIdList := Objectlist.CreateObjectIdList(true); PersistenceController.PMFetch(ObjectIdList, System.AsIBoldvalueSpace[bdepPMIn], MemberIdList, fmNormal, NOTVALIDCLIENTID); EndFetchForAll(ObjectList, MemberIdList); end; @@ -632,4 +776,5 @@ function TBoldTimeMappingCache.TimestampForTime(ClockTime: TDateTime; result := false; end; +initialization end. diff --git a/Source/ObjectSpace/BORepresentation/BoldTypeList.pas b/Source/ObjectSpace/BORepresentation/BoldTypeList.pas index 6e2bab2..977b519 100644 --- a/Source/ObjectSpace/BORepresentation/BoldTypeList.pas +++ b/Source/ObjectSpace/BORepresentation/BoldTypeList.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldTypeList; interface @@ -7,7 +10,8 @@ interface BoldSubscription, BoldSystem, BoldDomainElement, - BoldElements; + BoldElements, + BoldDefs; type { forward declarations } @@ -24,12 +28,13 @@ TBoldTypeList = class(TBoldList) function GetElement(index: Integer): TBoldElement; override; function IncludesElement(Item: TBoldElement): Boolean; override; function IndexOfElement(Item: TBoldElement): Integer; override; - procedure InitializeMember(AOwningElement: TBoldDomainElement; ElementTypeInfo: TBoldElementTypeInfo); override; + procedure Initialize; override; procedure InsertElement(index: Integer; Element: TBoldElement); override; procedure SetElement(index: Integer; Value: TBoldElement); override; function InternalAddNew: TBoldElement; override; - function ProxyClass: TBoldMember_ProxyClass; override; + function GetProxy(Mode: TBoldDomainElementProxyMode): TBoldMember_Proxy; override; procedure InternalClear; override; + function GetStringRepresentation(Representation: TBoldRepresentation): string; override; public procedure Assign(Source: TBoldElement); override; procedure DefaultSubscribe(Subscriber: TBoldSubscriber; RequestedEvent: TBoldEvent = breReEvaluate); override; @@ -48,10 +53,8 @@ implementation uses SysUtils, - BoldDefs, BoldMetaElementList, - BoldSystemRT, - BoldCoreConsts; + BoldSystemRT; type { TBoldTypeListController } @@ -65,7 +68,7 @@ TBoldTypeListController = class(TBoldListController) property List: TBoldElementTypeInfoList read fList; function GetStreamName: string; override; public - constructor Create(OwningList: TBoldList); + constructor Create(OwningList: TBoldList); override; destructor Destroy; override; procedure AddElement(Element: TBoldElement); override; function GetElement(index: Integer): TBoldElement; override; @@ -81,13 +84,12 @@ TBoldTypeListController = class(TBoldListController) procedure TBoldTypeList.AddElement(Element: TBoldElement); begin - if (ListController.IndexOfElement(element) = -1) or DuplicateControl then - listcontroller.AddElement(element); + if (DuplicateMode = bldmAllow) or (ListController.IndexOfElement(element) = -1) or DuplicateControl then + ListController.AddElement(element); end; procedure TBoldTypeList.AllocateData; begin - // do nothing end; procedure TBoldTypeList.Assign(Source: TBoldElement); @@ -105,7 +107,6 @@ procedure TBoldTypeList.DefaultSubscribe(Subscriber: TBoldSubscriber; RequestedE procedure TBoldTypeList.FreeData; begin - // do nothing end; function TBoldTypeList.GetCount: Integer; @@ -118,6 +119,16 @@ function TBoldTypeList.GetElement(index: Integer): TBoldElement; result := ListController.GetElement(index); end; +function TBoldTypeList.GetProxy(Mode: TBoldDomainElementProxyMode): TBoldMember_Proxy; +begin + raise EBold.CreateFmt('%s.GetProxy: Not available in this class.', [classname]) +end; + +function TBoldTypeList.GetStringRepresentation(Representation: TBoldRepresentation): string; +begin + result := IntToStr(Count); +end; + function TBoldTypeList.IncludesElement(Item: TBoldElement): Boolean; begin result := ListController.IncludesElement(item); @@ -128,7 +139,7 @@ function TBoldTypeList.IndexOfElement(Item: TBoldElement): Integer; result := ListController.IndexOfElement(item); end; -procedure TBoldTypeList.InitializeMember(AOwningElement: TBoldDomainElement; ElementTypeInfo: TBoldElementTypeInfo); +procedure TBoldTypeList.Initialize; begin ListController := TBoldTypeListController.Create(self); DuplicateMode := bldmAllow; @@ -142,12 +153,12 @@ procedure TBoldTypeList.InsertElement(index: Integer; Element: TBoldElement); procedure TBoldTypeList.InsertNew(index: Integer); begin - raise EBold.CreateFmt(sCannotInsertTypes, [classname]) + raise EBold.CreateFmt('%s.InsertNew: Types can not be inserted like this', [classname]) end; function TBoldTypeList.InternalAddNew: TBoldElement; begin - raise EBold.CreateFmt(sCannotAddTypes, [classname]) + raise EBold.CreateFmt('%s.InternalAddNew: Types can not be added like this', [classname]) end; procedure TBoldTypeList.InternalClear; @@ -163,10 +174,12 @@ procedure TBoldTypeList.Move(CurIndex, NewIndex: Integer); ListController.Move(CurIndex, NewIndex); end; +(* function TBoldTypeList.ProxyClass: TBoldMember_ProxyClass; begin - raise EBold.CreateFmt(sAbstractError_InterfaceNotSupported, [ClassName]); + raise EBold.CreateFmt('Abstract error: %s.ProxyClass (IBoldValue not supported!)', [ClassName]); end; +*) procedure TBoldTypeList.RemoveByIndex(index: Integer); begin @@ -185,7 +198,7 @@ procedure TBoldTypeListController.AddElement(Element: TBoldElement); if element is TBoldElementTypeInfo then list.Add(element as TBoldElementTypeInfo) else - raise EBold.CreateFmt(sCannotAddElement, [element.ClassName]); + raise EBold.CreateFmt('Can not add element: %s', [element.ClassName]); end; constructor TBoldTypeListController.Create(OwningList: TBoldList); @@ -196,7 +209,7 @@ constructor TBoldTypeListController.Create(OwningList: TBoldList); function TBoldTypeListController.CreateNew: TBoldElement; begin - raise EBold.Create(sCannotCreateNewInTypeLists); + raise EBold.Create('Can not create new in Typelists'); end; destructor TBoldTypeListController.Destroy; @@ -223,7 +236,7 @@ function TBoldTypeListController.GetElement(index: Integer): TBoldElement; function TBoldTypeListController.GetStreamName: string; begin result := ''; - raise EBold.create(sNotImplemented); + raise EBold.create('not implemented'); end; function TBoldTypeListController.IncludesElement(Item: TBoldElement): Boolean; @@ -241,6 +254,7 @@ procedure TBoldTypeListController.InsertElement(index: Integer; Element: TBoldE list.Insert(index, element); end; + procedure TBoldTypeListController.Move(CurrentIndex, NewIndex: Integer); begin list.Move(CurrentIndex, NewIndex); @@ -253,7 +267,7 @@ procedure TBoldTypeListController.RemoveByIndex(index: Integer); procedure TBoldTypeListController.SetElement(index: Integer; Value: TBoldElement); begin - raise Ebold.Create(sCannotSetElementsInTypeLists); + raise Ebold.Create('Can not set elements in TypeLists'); end; { TBoldTypeListFactory } @@ -264,4 +278,5 @@ class function TBoldTypeListFactory.CreateList(elementTypeInfo: TBoldElementType result := TBoldTypeList.CreateWithTypeInfo(ListTypeInfoByElement[TypeTypeInfo]); end; +initialization end. diff --git a/Source/ObjectSpace/COM/BoldComObjectSpace.pas b/Source/ObjectSpace/COM/BoldComObjectSpace.pas index 079c7ca..d4aacc5 100644 --- a/Source/ObjectSpace/COM/BoldComObjectSpace.pas +++ b/Source/ObjectSpace/COM/BoldComObjectSpace.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldComObjectSpace; interface @@ -45,8 +48,7 @@ implementation uses SysUtils, BoldComUtils, - BoldComObjectSpace_TLB, - BoldComConst; + BoldComObjectSpace_TLB; var G_TypeLibrary: ITypeLib = nil; @@ -56,9 +58,11 @@ function BoldComObjectSpaceTypeLibrary: ITypeLib; if not Assigned(G_TypeLibrary) then begin if Failed(LoadRegTypeLib(LIBID_BoldComObjectSpace,1,0,0,G_TypeLibrary)) then - raise EBoldCom.Create(sUnableToLoadComObjectSpace); + raise EBoldCom.Create('Unable to load type library (BoldComObjectSpace)'); end; Result := G_TypeLibrary; end; +initialization + end. diff --git a/Source/ObjectSpace/COM/BoldComObjectSpaceAdapters.pas b/Source/ObjectSpace/COM/BoldComObjectSpaceAdapters.pas index 6bdb6cb..2f36d6a 100644 --- a/Source/ObjectSpace/COM/BoldComObjectSpaceAdapters.pas +++ b/Source/ObjectSpace/COM/BoldComObjectSpaceAdapters.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldComObjectSpaceAdapters; interface @@ -633,8 +636,7 @@ implementation BoldComUtils, BoldComObj, BoldComServer, - BoldComObjectSpace, - BoldComConst; + BoldComObjectSpace; procedure CreateIndirectAdapter(IndirectElement: TBoldIndirectElement; const IID: TGUID; out Obj); var @@ -660,13 +662,13 @@ procedure CreateIndirectAdapter(IndirectElement: TBoldIndirectElement; const IID if not Assigned(Adapter) then begin if Owner then Adaptee.Free; - raise EBoldCom.CreateFmt(sNoAdapterRegistered, [Adaptee.ClassName]); + raise EBoldCom.CreateFmt('No adapter registered for %s', [Adaptee.ClassName]); end; UnknownAdapter := Adapter; if UnknownAdapter.QueryInterface(IID,Obj) <> 0 then begin UnknownAdapter := nil; - raise EBoldCom.CreateFmt(sUnsupportedInterface, [Adapter.ClassName]); + raise EBoldCom.CreateFmt('%s: Unsupported interface', [Adapter.ClassName]); end; end; end; @@ -1081,12 +1083,12 @@ procedure TBoldComElementAdapter.Set_AsString(const Value: WideString); function TBoldComElementAdapter.Get_AsVariant: OleVariant; begin - Result := AsElement.GetAsVariant; + Result := AsElement.AsVariant; end; procedure TBoldComElementAdapter.Set_AsVariant(Value: OleVariant); begin - AsElement.SetAsVariant(Value); + AsElement.AsVariant := Value; end; function TBoldComElementAdapter.Get_BoldType: IBoldElementTypeInfo; @@ -1599,7 +1601,7 @@ procedure TBoldComObjectAdapter.LinkObject(const RoleName: WideString; else if LinkObj is TBoldObjectList then TBoldObjectList(LinkObj).Add(BoldObj) else - raise EBoldCom.CreateFmt(sRoleDoesNotExist, [ClassName, 'LinkObject', RoleName]); // do not localize + raise EBoldCom.CreateFmt('%.LinkObject: Role %s does not exist', [ClassName, RoleName]); end; end; @@ -1644,7 +1646,7 @@ procedure TBoldComObjectAdapter.UnlinkObject(const RoleName: WideString; end; end else - raise EBoldCom.CreateFmt(sRoleDoesNotExist, [ClassName, 'UnlinkObject', RoleName]); // do not localize + raise EBoldCom.CreateFmt('%.UnlinkObject: Role %s does not exist', [ClassName, RoleName]); end; function TBoldComObjectAdapter.Get_BoldClassTypeInfo: IBoldClassTypeInfo; @@ -1673,17 +1675,17 @@ function TBoldComObjectAdapter.Get_BoldMember(Index: OleVariant): IBoldMember; function TBoldComObjectAdapter.Get_BoldMemberValue(Index: OleVariant): OleVariant; begin if BoldVariantIsType(Index,varOleStr) then - Result := AsObject.BoldMemberByExpressionName[Index].GetAsVariant + Result := AsObject.BoldMemberByExpressionName[Index].AsVariant else - Result := AsObject.BoldMembers[Index].GetAsVariant; + Result := AsObject.BoldMembers[Index].AsVariant; end; procedure TBoldComObjectAdapter.Set_BoldMemberValue(Index: OleVariant; Value: OleVariant); begin if BoldVariantIsType(Index,varOleStr) then - AsObject.BoldMemberByExpressionName[Index].SetAsVariant(Value) + AsObject.BoldMemberByExpressionName[Index].AsVariant := Value else - AsObject.BoldMembers[Index].SetAsVariant(Value); + AsObject.BoldMembers[Index].AsVariant := Value; end; function TBoldComObjectAdapter.Get_BoldMemberValues: OleVariant; @@ -1704,7 +1706,7 @@ function TBoldComObjectAdapter.Get_BoldMemberValues: OleVariant; begin Member := ThisObject.BoldMembers[MemberIndex]; NameArray[MemberIndex] := Member.BoldMemberRtInfo.ExpressionName; - DataArray[MemberIndex] := Member.GetAsVariant; + DataArray[MemberIndex] := Member.AsVariant; end; Result := VarArrayCreate([0, 1], varVariant); Result[0] := NameArray; @@ -1728,7 +1730,7 @@ procedure TBoldComObjectAdapter.Set_BoldMemberValues(Values: OleVariant); end; end else - raise EBoldCom.CreateFmt(sUnknownDataFormat, [ClassName]); + raise EBoldCom.CreateFmt('%s.BoldMemberValues: Unknown data format', [ClassName]); end; function TBoldComObjectAdapter.Get_BoldPersistenceState: Integer; @@ -1838,6 +1840,7 @@ procedure TBoldComMemberAdapter.ReceiveEvent(Originator: TObject; inherited; end; + {-- TBoldComAttributeAdapter -----------------------------------------------------} constructor TBoldComAttributeAdapter.Create(AdaptableObject: TBoldAdaptableObject; @@ -2345,7 +2348,7 @@ function TBoldComSystemHandleAdapter.GetData(DataFlags: Integer; Result := True; This := AsSystemHandle; if dataflags = DF_HANDLEID then - NamedValues := BoldCreateNamedValues(['HandleId'], [integer(this)]) // do not localize + NamedValues := BoldCreateNamedValues(['HandleId'], [integer(this)]) else begin BoldComCreateAdapter(This.Value, False, IBoldElement, Value); @@ -2361,9 +2364,9 @@ function TBoldComSystemHandleAdapter.GetData(DataFlags: Integer; BoldList := nil; ListElementType := nil; NamedValues := BoldCreateNamedValues( - ['HandleId', // do not localize - 'Active', // do not localize - 'Persistent'], // do not localize + ['HandleId', + 'Active', + 'Persistent'], [Integer(This), This.Active, This.Persistent]); @@ -2373,7 +2376,6 @@ function TBoldComSystemHandleAdapter.GetData(DataFlags: Integer; function TBoldComSystemHandleAdapter.SetData(DataFlags: Integer; const Value: IBoldElement; NamedValues: OleVariant): WordBool; begin - // not allowed to set Result := False; end; @@ -2406,7 +2408,7 @@ function TBoldComDerivedHandleAdapter.GetData(DataFlags: Integer; Result := True; This := AsDerivedHandle; if dataflags = DF_HANDLEID then - NamedValues := BoldCreateNamedValues(['HandleId'], [integer(this)]) // do not localize + NamedValues := BoldCreateNamedValues(['HandleId'], [integer(this)]) else begin BoldComCreateAdapter(This.Value, False, IBoldElement, Value); @@ -2419,12 +2421,12 @@ function TBoldComDerivedHandleAdapter.GetData(DataFlags: Integer; BoldList := nil; ListElementType := nil; NamedValues := BoldCreateNamedValues( - ['HandleId', // do not localize - 'StaticSystemHandle', // do not localize - 'Enabled', // do not localize - 'RootHandle', // do not localize - 'RootTypeName', // do not localize - 'Subscribe'], // do not localize + ['HandleId', + 'StaticSystemHandle', + 'Enabled', + 'RootHandle', + 'RootTypeName', + 'Subscribe'], [Integer(This), Integer(This.StaticSystemHandle), This.Enabled, @@ -2443,7 +2445,7 @@ function TBoldComDerivedHandleAdapter.SetData(DataFlags: Integer; This := AsDerivedHandle; if (DataFlags and DF_STATICSYSTEMHANDLE) <> 0 then begin - HandleId := BoldGetNamedValue(NamedValues,'StaticSystemHandle'); // do not localize + HandleId := BoldGetNamedValue(NamedValues,'StaticSystemHandle'); if HandleId = 0 then This.StaticSystemHandle := nil else @@ -2451,11 +2453,11 @@ function TBoldComDerivedHandleAdapter.SetData(DataFlags: Integer; end; if (DataFlags and DF_ENABLED) <> 0 then begin - This.Enabled := BoldGetNamedValue(NamedValues, 'Enabled'); // do not localize + This.Enabled := BoldGetNamedValue(NamedValues, 'Enabled'); end; if (DataFlags and DF_ROOTHANDLE) <> 0 then begin - HandleId := BoldGetNamedValue(NamedValues, 'RootHandle'); // do not localize + HandleId := BoldGetNamedValue(NamedValues, 'RootHandle'); if HandleId = 0 then This.RootHandle := nil else @@ -2463,11 +2465,11 @@ function TBoldComDerivedHandleAdapter.SetData(DataFlags: Integer; end; if (DataFlags and DF_ROOTTYPENAME) <> 0 then begin - This.RootTypeName := BoldGetNamedValue(NamedValues, 'RootTypeName'); // do not localize + This.RootTypeName := BoldGetNamedValue(NamedValues, 'RootTypeName'); end; if (DataFlags and DF_SUBSCRIBE) <> 0 then begin - This.Subscribe := BoldGetNamedValue(NamedValues, 'Subscribe'); // do not localize + This.Subscribe := BoldGetNamedValue(NamedValues, 'Subscribe'); end; end; @@ -2500,7 +2502,7 @@ function TBoldComExpressionHandleAdapter.GetData(DataFlags: Integer; Result := True; This := AsExpressionHandle; if dataflags = DF_HANDLEID then - NamedValues := BoldCreateNamedValues(['HandleId'], [integer(this)]) // do not localize + NamedValues := BoldCreateNamedValues(['HandleId'], [integer(this)]) else begin BoldComCreateAdapter(This.Value, False, IBoldElement, Value); @@ -2513,14 +2515,14 @@ function TBoldComExpressionHandleAdapter.GetData(DataFlags: Integer; BoldList := nil; ListElementType := nil; NamedValues := BoldCreateNamedValues( - ['HandleId', // do not localize - 'StaticSystemHandle', // do not localize - 'Enabled', // do not localize - 'RootHandle', // do not localize - 'RootTypeName', // do not localize - 'Subscribe', // do not localize - 'Expression', // do not localize - 'EvaluateInPS'], // do not localize + ['HandleId', + 'StaticSystemHandle', + 'Enabled', + 'RootHandle', + 'RootTypeName', + 'Subscribe', + 'Expression', + 'EvaluateInPS'], [Integer(This), Integer(This.StaticSystemHandle), This.Enabled, @@ -2541,7 +2543,7 @@ function TBoldComExpressionHandleAdapter.SetData(DataFlags: Integer; This := AsExpressionHandle; if (DataFlags and DF_STATICSYSTEMHANDLE) <> 0 then begin - HandleId := BoldGetNamedValue(NamedValues, 'StaticSystemHandle'); // do not localize + HandleId := BoldGetNamedValue(NamedValues, 'StaticSystemHandle'); if HandleId = 0 then This.StaticSystemHandle := nil else @@ -2549,11 +2551,11 @@ function TBoldComExpressionHandleAdapter.SetData(DataFlags: Integer; end; if (DataFlags and DF_ENABLED) <> 0 then begin - This.Enabled := BoldGetNamedValue(NamedValues, 'Enabled'); // do not localize + This.Enabled := BoldGetNamedValue(NamedValues, 'Enabled'); end; if (DataFlags and DF_ROOTHANDLE) <> 0 then begin - HandleId := BoldGetNamedValue(NamedValues, 'RootHandle'); // do not localize + HandleId := BoldGetNamedValue(NamedValues, 'RootHandle'); if HandleId = 0 then This.RootHandle := nil else @@ -2561,19 +2563,19 @@ function TBoldComExpressionHandleAdapter.SetData(DataFlags: Integer; end; if (DataFlags and DF_ROOTTYPENAME) <> 0 then begin - This.RootTypeName := BoldGetNamedValue(NamedValues, 'RootTypeName'); // do not localize + This.RootTypeName := BoldGetNamedValue(NamedValues, 'RootTypeName'); end; if (DataFlags and DF_SUBSCRIBE) <> 0 then begin - This.Subscribe := BoldGetNamedValue(NamedValues, 'Subscribe'); // do not localize + This.Subscribe := BoldGetNamedValue(NamedValues, 'Subscribe'); end; if (DataFlags and DF_EXPRESSION) <> 0 then begin - This.Expression := BoldGetNamedValue(NamedValues, 'Expression'); // do not localize + This.Expression := BoldGetNamedValue(NamedValues, 'Expression'); end; if (DataFlags and DF_EVALUATEINPS) <> 0 then begin - This.EvaluateInPs := BoldGetNamedValue(NamedValues,'EvaluateInPS'); // do not localize + This.EvaluateInPs := BoldGetNamedValue(NamedValues,'EvaluateInPS'); end; end; @@ -2606,7 +2608,7 @@ function TBoldComCursorHandleAdapter.GetData(DataFlags: Integer; Result := True; This := AsCursorHandle; if dataflags = DF_HANDLEID then - NamedValues := BoldCreateNamedValues(['HandleId'], [integer(this)]) // do not localize + NamedValues := BoldCreateNamedValues(['HandleId'], [integer(this)]) else begin BoldComCreateAdapter(This.Value, False, IBoldElement, Value); @@ -2622,15 +2624,15 @@ function TBoldComCursorHandleAdapter.GetData(DataFlags: Integer; BoldComCreateAdapter(This.List, False, IBoldList, BoldList); BoldComCreateAdapter(This.ListElementType, False, IBoldElementTypeInfo, ListElementType); NamedValues := BoldCreateNamedValues( - ['HandleId', // do not localize - 'StaticSystemHandle', // do not localize - 'Enabled', // do not localize - 'RootHandle', // do not localize - 'RootTypeName', // do not localize - 'Subscribe', // do not localize - 'Count', // do not localize - 'CurrentIndex', // do not localize - 'AutoFirst'], // do not localize + ['HandleId', + 'StaticSystemHandle', + 'Enabled', + 'RootHandle', + 'RootTypeName', + 'Subscribe', + 'Count', + 'CurrentIndex', + 'AutoFirst'], [Integer(This), Integer(This.StaticSystemHandle), This.Enabled, @@ -2653,7 +2655,7 @@ function TBoldComCursorHandleAdapter.SetData(DataFlags: Integer; This := AsCursorHandle; if (DataFlags and DF_STATICSYSTEMHANDLE) <> 0 then begin - HandleId := BoldGetNamedValue(NamedValues, 'StaticSystemHandle'); // do not localize + HandleId := BoldGetNamedValue(NamedValues, 'StaticSystemHandle'); if HandleId = 0 then This.StaticSystemHandle := nil else @@ -2662,12 +2664,12 @@ function TBoldComCursorHandleAdapter.SetData(DataFlags: Integer; if (DataFlags and DF_ENABLED) <> 0 then begin - This.Enabled := BoldGetNamedValue(NamedValues, 'Enabled'); // do not localize + This.Enabled := BoldGetNamedValue(NamedValues, 'Enabled'); end; if (DataFlags and DF_ROOTHANDLE) <> 0 then begin - HandleId := BoldGetNamedValue(NamedValues, 'RootHandle'); // do not localize + HandleId := BoldGetNamedValue(NamedValues, 'RootHandle'); if HandleId = 0 then This.RootHandle := nil else @@ -2676,24 +2678,24 @@ function TBoldComCursorHandleAdapter.SetData(DataFlags: Integer; if (DataFlags and DF_ROOTTYPENAME) <> 0 then begin - This.RootTypeName := BoldGetNamedValue(NamedValues, 'RootTypeName'); // do not localize + This.RootTypeName := BoldGetNamedValue(NamedValues, 'RootTypeName'); end; if (DataFlags and DF_SUBSCRIBE) <> 0 then begin - This.Subscribe := BoldGetNamedValue(NamedValues, 'Subscribe'); // do not localize + This.Subscribe := BoldGetNamedValue(NamedValues, 'Subscribe'); end; if (DataFlags and DF_CURRENTINDEX) <> 0 then begin - NewIndex := BoldGetNamedValue(NamedValues,'CurrentIndex'); // do not localize + NewIndex := BoldGetNamedValue(NamedValues,'CurrentIndex'); if assigned(this.list) and (NewIndex < this.list.Count) and (newIndex >= -1) then This.CurrentIndex := NewIndex; end; if (DataFlags and DF_AUTOFIRST) <> 0 then begin - This.AutoFirst := BoldGetNamedValue(NamedValues, 'AutoFirst'); // do not localize + This.AutoFirst := BoldGetNamedValue(NamedValues, 'AutoFirst'); end; end; @@ -2726,7 +2728,7 @@ function TBoldComListHandleAdapter.GetData(DataFlags: Integer; Result := True; This := AsListHandle; if dataflags = DF_HANDLEID then - NamedValues := BoldCreateNamedValues(['HandleId'], [integer(this)]) // do not localize + NamedValues := BoldCreateNamedValues(['HandleId'], [integer(this)]) else begin BoldComCreateAdapter(This.Value, False, IBoldElement, Value); @@ -2742,17 +2744,17 @@ function TBoldComListHandleAdapter.GetData(DataFlags: Integer; BoldComCreateAdapter(This.List, False, IBoldList, BoldList); BoldComCreateAdapter(This.ListElementType, False, IBoldElementTypeInfo, ListElementType); NamedValues := BoldCreateNamedValues( - ['HandleId', // do not localize - 'StaticSystemHandle', // do not localize - 'Enabled', // do not localize - 'RootHandle', // do not localize - 'RootTypeName', // do not localize - 'Subscribe', // do not localize - 'Count', // do not localize - 'CurrentIndex', // do not localize - 'AutoFirst', // do not localize - 'Expression', // do not localize - 'EvaluateInPS'], // do not localize + ['HandleId', + 'StaticSystemHandle', + 'Enabled', + 'RootHandle', + 'RootTypeName', + 'Subscribe', + 'Count', + 'CurrentIndex', + 'AutoFirst', + 'Expression', + 'EvaluateInPS'], [Integer(This), Integer(This.StaticSystemHandle), This.Enabled, @@ -2777,7 +2779,7 @@ function TBoldComListHandleAdapter.SetData(DataFlags: Integer; This := AsListHandle; if (DataFlags and DF_STATICSYSTEMHANDLE) <> 0 then begin - HandleId := BoldGetNamedValue(NamedValues, 'StaticSystemHandle'); // do not localize + HandleId := BoldGetNamedValue(NamedValues, 'StaticSystemHandle'); if HandleId = 0 then This.StaticSystemHandle := nil else @@ -2786,7 +2788,7 @@ function TBoldComListHandleAdapter.SetData(DataFlags: Integer; if (DataFlags and DF_ROOTHANDLE) <> 0 then begin - HandleId := BoldGetNamedValue(NamedValues, 'RootHandle'); // do not localize + HandleId := BoldGetNamedValue(NamedValues, 'RootHandle'); if HandleId = 0 then This.RootHandle := nil else @@ -2795,40 +2797,41 @@ function TBoldComListHandleAdapter.SetData(DataFlags: Integer; if (DataFlags and DF_ROOTTYPENAME) <> 0 then begin - This.RootTypeName := BoldGetNamedValue(NamedValues, 'RootTypeName'); // do not localize + This.RootTypeName := BoldGetNamedValue(NamedValues, 'RootTypeName'); end; if (DataFlags and DF_SUBSCRIBE) <> 0 then begin - This.Subscribe := BoldGetNamedValue(NamedValues, 'Subscribe'); // do not localize + This.Subscribe := BoldGetNamedValue(NamedValues, 'Subscribe'); end; if (DataFlags and DF_EXPRESSION) <> 0 then begin - This.Expression := BoldGetNamedValue(NamedValues, 'Expression'); // do not localize + This.Expression := BoldGetNamedValue(NamedValues, 'Expression'); end; if (DataFlags and DF_ENABLED) <> 0 then begin - This.Enabled := BoldGetNamedValue(NamedValues, 'Enabled'); // do not localize + This.Enabled := BoldGetNamedValue(NamedValues, 'Enabled'); end; if (DataFlags and DF_CURRENTINDEX) <> 0 then begin - NewIndex := BoldGetNamedValue(NamedValues,'CurrentIndex'); // do not localize + NewIndex := BoldGetNamedValue(NamedValues,'CurrentIndex'); if assigned(this.list) and (NewIndex < this.list.Count) and (newIndex >= -1) then This.CurrentIndex := NewIndex; end; if (DataFlags and DF_AUTOFIRST) <> 0 then begin - This.AutoFirst := BoldGetNamedValue(NamedValues,'AutoFirst'); // do not localize + This.AutoFirst := BoldGetNamedValue(NamedValues,'AutoFirst'); end; if (DataFlags and DF_EVALUATEINPS) <> 0 then begin - This.EvaluateInPs := BoldGetNamedValue(NamedValues,'EvaluateInPS'); // do not localize + This.EvaluateInPs := BoldGetNamedValue(NamedValues,'EvaluateInPS'); end; + end; {-- TBoldComReferenceHandleAdapter --------------------------------------------} @@ -2860,7 +2863,7 @@ function TBoldComReferenceHandleAdapter.GetData(DataFlags: Integer; Result := True; This := AsReferenceHandle; if dataflags = DF_HANDLEID then - NamedValues := BoldCreateNamedValues(['HandleId'], [integer(this)]) // do not localize + NamedValues := BoldCreateNamedValues(['HandleId'], [integer(this)]) else begin BoldComCreateAdapter(This.Value, False, IBoldElement, Value); @@ -2873,9 +2876,9 @@ function TBoldComReferenceHandleAdapter.GetData(DataFlags: Integer; BoldList := nil; ListElementType := nil; NamedValues := BoldCreateNamedValues( - ['HandleId', // do not localize - 'StaticSystemHandle', // do not localize - 'StaticValueTypeName'], // do not localize + ['HandleId', + 'StaticSystemHandle', + 'StaticValueTypeName'], [Integer(This), Integer(This.StaticSystemHandle), This.StaticValueTypeName]); @@ -2896,7 +2899,7 @@ function TBoldComReferenceHandleAdapter.SetData(DataFlags: Integer; if (DataFlags and DF_STATICSYSTEMHANDLE) <> 0 then begin - HandleId := BoldGetNamedValue(NamedValues, 'StaticSystemHandle'); // do not localize + HandleId := BoldGetNamedValue(NamedValues, 'StaticSystemHandle'); if HandleId = 0 then This.StaticSystemHandle := nil else @@ -2905,7 +2908,7 @@ function TBoldComReferenceHandleAdapter.SetData(DataFlags: Integer; if (DataFlags and DF_STATICVALUETYPENAME) <> 0 then begin - This.StaticValueTypeName := BoldGetNamedValue(NamedValues, 'StaticValueTypeName'); // do not localize + This.StaticValueTypeName := BoldGetNamedValue(NamedValues, 'StaticValueTypeName'); end; end; @@ -2938,7 +2941,7 @@ function TBoldComSQLHandleAdapter.GetData(DataFlags: Integer; Result := True; This := AsSQLHandle; if dataflags = DF_HANDLEID then - NamedValues := BoldCreateNamedValues(['HandleId'], [integer(this)]) // do not localize + NamedValues := BoldCreateNamedValues(['HandleId'], [integer(this)]) else begin BoldComCreateAdapter(This.Value, False, IBoldElement, Value); @@ -2951,12 +2954,12 @@ function TBoldComSQLHandleAdapter.GetData(DataFlags: Integer; BoldList := nil; ListElementType := nil; NamedValues := BoldCreateNamedValues( - ['HandleId', // do not localize - 'StaticSystemHandle', // do not localize - 'ClassExpressionName', // do not localize - 'ClearBeforeExecute', // do not localize - 'SQLOrderByClause', // do not localize - 'SQLWhereClause'], // do not localize + ['HandleId', + 'StaticSystemHandle', + 'ClassExpressionName', + 'ClearBeforeExecute', + 'SQLOrderByClause', + 'SQLWhereClause'], [Integer(This), Integer(This.StaticSystemHandle), This.ClassExpressionName, @@ -2976,16 +2979,16 @@ function TBoldComSQLHandleAdapter.SetData(DataFlags: Integer; This := AsSQLHandle; if DataFlags = -1 then begin - Action := BoldGetnamedValue(NamedValues, 'Action'); // do not localize - if SameText(Action, 'ExecuteSQL') then // do not localize + Action := BoldGetnamedValue(NamedValues, 'Action'); + if SameText(Action, 'ExecuteSQL') then this.ExecuteSQL - else if SameText(Action, 'ClearList') then // do not localize + else if SameText(Action, 'ClearList') then this.ClearList end else begin if (DataFlags and DF_STATICSYSTEMHANDLE) <> 0 then begin - HandleId := BoldGetNamedValue(NamedValues, 'StaticSystemHandle'); // do not localize + HandleId := BoldGetNamedValue(NamedValues, 'StaticSystemHandle'); if HandleId = 0 then This.StaticSystemHandle := nil else @@ -2993,19 +2996,19 @@ function TBoldComSQLHandleAdapter.SetData(DataFlags: Integer; end; if (DataFlags and DF_CLASSEXPRESSIONNAME) <> 0 then begin - This.ClassExpressionName := BoldGetNamedValue(NamedValues, 'ClassExpressionName'); // do not localize + This.ClassExpressionName := BoldGetNamedValue(NamedValues, 'ClassExpressionName'); end; if (DataFlags and DF_CLEARBEFOREEXECUTE) <> 0 then begin - This.ClearBeforeExecute := BoldGetNamedValue(NamedValues, 'ClearBeforeExecute'); // do not localize + This.ClearBeforeExecute := BoldGetNamedValue(NamedValues, 'ClearBeforeExecute'); end; if (DataFlags and DF_SQLORDERBYCLAUSE) <> 0 then begin - This.SQLOrderByClause := BoldGetNamedValue(NamedValues, 'SQLOrderByClause'); // do not localize + This.SQLOrderByClause := BoldGetNamedValue(NamedValues, 'SQLOrderByClause'); end; if (DataFlags and DF_SQLWHERECLAUSE) <> 0 then begin - This.SQLWhereClause := BoldGetNamedValue(NamedValues, 'SQLWhereClause'); // do not localize + This.SQLWhereClause := BoldGetNamedValue(NamedValues, 'SQLWhereClause'); end; end; end; @@ -3039,7 +3042,7 @@ function TBoldComVariableHandleAdapter.GetData(DataFlags: Integer; Result := True; This := AsVariableHandle; if dataflags = DF_HANDLEID then - NamedValues := BoldCreateNamedValues(['HandleId'], [integer(this)]) // do not localize + NamedValues := BoldCreateNamedValues(['HandleId'], [integer(this)]) else begin BoldComCreateAdapter(This.Value, False, IBoldElement, Value); @@ -3052,10 +3055,10 @@ function TBoldComVariableHandleAdapter.GetData(DataFlags: Integer; BoldList := nil; ListElementType := nil; NamedValues := BoldCreateNamedValues( - ['HandleId', // do not localize - 'StaticSystemHandle', // do not localize - 'ValueTypeName', // do not localize - 'InitialValues'], // do not localize + ['HandleId', + 'StaticSystemHandle', + 'ValueTypeName', + 'InitialValues'], [Integer(This), Integer(This.StaticSystemHandle), This.ValueTypeName, @@ -3073,7 +3076,7 @@ function TBoldComVariableHandleAdapter.SetData(DataFlags: Integer; This := AsVariableHandle; if (DataFlags and DF_STATICSYSTEMHANDLE) <> 0 then begin - HandleId := BoldGetNamedValue(NamedValues, 'StaticSystemHandle'); // do not localize + HandleId := BoldGetNamedValue(NamedValues, 'StaticSystemHandle'); if HandleId = 0 then This.StaticSystemHandle := nil else @@ -3081,13 +3084,13 @@ function TBoldComVariableHandleAdapter.SetData(DataFlags: Integer; end; if (DataFlags and DF_VALUETYPENAME) <> 0 then begin - This.ValueTypeName := BoldGetNamedValue(NamedValues, 'ValueTypeName'); // do not localize + This.ValueTypeName := BoldGetNamedValue(NamedValues, 'ValueTypeName'); end; if (DataFlags and DF_INITIALVALUES) <> 0 then begin Temp := TStringList.Create; try - BoldVariantToStrings(BoldGetNamedValue(NamedValues, 'InitialValues'),Temp); // do not localize + BoldVariantToStrings(BoldGetNamedValue(NamedValues, 'InitialValues'),Temp); This.InitialValues.Assign(Temp); finally Temp.Free; @@ -3180,7 +3183,6 @@ function TBoldComObjectReferenceAdapter.QueryInterface(const IId: TGUID; initialization BoldComRegisterAdapter(TBoldComElementAdapter,TBoldElement); - // type info BoldComRegisterAdapter(TBoldComMetaElementAdapter,TBoldMetaElement); BoldComRegisterAdapter(TBoldComElementTypeInfoAdapter,TBoldElementTypeInfo); BoldComRegisterAdapter(TBoldComTypeTypeInfoAdapter,TBoldTypeTypeInfo); @@ -3189,7 +3191,6 @@ initialization BoldComRegisterAdapter(TBoldComListTypeInfoAdapter,TBoldListTypeInfo); BoldComRegisterAdapter(TBoldComAttributeTypeInfoAdapter,TBoldAttributeTypeInfo); BoldComRegisterAdapter(TBoldComSystemTypeInfoAdapter,TBoldSystemTypeInfo); - // domain & system BoldComRegisterAdapter(TBoldComDomainElementAdapter,TBoldDomainElement); BoldComRegisterAdapter(TBoldComObjectAdapter,TBoldObject); BoldComRegisterAdapter(TBoldComMemberAdapter,TBoldMember); @@ -3199,9 +3200,7 @@ initialization BoldComRegisterAdapter(TBoldComObjectListAdapter,TBoldObjectList); BoldComRegisterAdapter(TBoldComMemberListAdapter,TBoldMemberList); BoldComRegisterAdapter(TBoldComSystemAdapter,TBoldSystem); - // attributes BoldComRegisterAdapter(TBoldComBlobAdapter,TBABlob); - // handles BoldComRegisterAdapter(TBoldComElementHandleAdapter,TBoldElementHandle); BoldComRegisterAdapter(TBoldComSystemHandleAdapter,TBoldSystemHandle); BoldComRegisterAdapter(TBoldComDerivedHandleAdapter,TBoldDerivedHandle); diff --git a/Source/ObjectSpace/COM/BoldComObjectSpace_TLB.pas b/Source/ObjectSpace/COM/BoldComObjectSpace_TLB.pas index 22c6d32..e7ae589 100644 --- a/Source/ObjectSpace/COM/BoldComObjectSpace_TLB.pas +++ b/Source/ObjectSpace/COM/BoldComObjectSpace_TLB.pas @@ -1,44 +1,39 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldComObjectSpace_TLB; -// ************************************************************************ // -// WARNING -// ------- -// The types declared in this file were generated from data read from a -// Type Library. If this type library is explicitly or indirectly (via -// another type library referring to this type library) re-imported, or the -// 'Refresh' command of the Type Library Editor activated while editing the -// Type Library, the contents of this file will be regenerated and all -// manual modifications will be lost. -// ************************************************************************ // - -// PASTLWTR : 1.1 -// File generated on 2002-05-02 15:54:08 from Type Library described below. - -// ************************************************************************ // -// Type Lib: D:\bold\BfD\Source\ObjectSpace\COM\BoldComObjectSpace.tlb (1) -// LIBID: {D28A8F60-C8DD-11D3-89A9-444553540000} -// LCID: 0 -// Helpfile: -// DepndLst: -// (1) v2.0 stdole, (C:\WINNT\System32\stdole2.tlb) -// (2) v4.0 StdVCL, (C:\WINNT\System32\STDVCL40.DLL) -// ************************************************************************ // -{$TYPEDADDRESS OFF} // Unit must be compiled without type-checked pointers. + + + + + + + + + + + + + + + + + + + +{$TYPEDADDRESS OFF} interface uses Windows, ActiveX, Classes, Graphics, OleCtrls, StdVCL; - - -// *********************************************************************// -// GUIDS declared in the TypeLibrary. Following prefixes are used: -// Type Libraries : LIBID_xxxx -// CoClasses : CLASS_xxxx -// DISPInterfaces : DIID_xxxx -// Non-DISP interfaces: IID_xxxx -// *********************************************************************// + + + + + + const - // TypeLibrary Major and minor versions BoldComObjectSpaceMajorVersion = 1; BoldComObjectSpaceMinorVersion = 0; @@ -67,9 +62,7 @@ interface IID_IBoldElementHandle: TGUID = '{71446D80-01C9-4E3C-95A7-D74445C0776C}'; type -// *********************************************************************// -// Forward declaration of types defined in TypeLibrary -// *********************************************************************// + IBoldElement = interface; IBoldElementDisp = dispinterface; IBoldMetaElement = interface; @@ -113,11 +106,9 @@ interface IBoldElementHandle = interface; IBoldElementHandleDisp = dispinterface; -// *********************************************************************// -// Interface: IBoldElement -// Flags: (4416) Dual OleAutomation Dispatchable -// GUID: {E8E2859A-0BAA-4DD9-8B26-A0AE5DEC87DF} -// *********************************************************************// + + + IBoldElement = interface(IDispatch) ['{E8E2859A-0BAA-4DD9-8B26-A0AE5DEC87DF}'] procedure AddSmallSubscription(const ClientId: WideString; SubscriberId: Integer; @@ -178,11 +169,9 @@ interface property HasAdaptee: WordBool read Get_HasAdaptee; end; -// *********************************************************************// -// DispIntf: IBoldElementDisp -// Flags: (4416) Dual OleAutomation Dispatchable -// GUID: {E8E2859A-0BAA-4DD9-8B26-A0AE5DEC87DF} -// *********************************************************************// + + + IBoldElementDisp = dispinterface ['{E8E2859A-0BAA-4DD9-8B26-A0AE5DEC87DF}'] procedure AddSmallSubscription(const ClientId: WideString; SubscriberId: Integer; @@ -232,11 +221,9 @@ interface property HasAdaptee: WordBool readonly dispid 129; end; -// *********************************************************************// -// Interface: IBoldMetaElement -// Flags: (4416) Dual OleAutomation Dispatchable -// GUID: {78994402-CA6E-11D3-89A9-444553540000} -// *********************************************************************// + + + IBoldMetaElement = interface(IBoldElement) ['{78994402-CA6E-11D3-89A9-444553540000}'] function Get_DelphiName: WideString; safecall; @@ -247,11 +234,9 @@ interface property ModelName: WideString read Get_ModelName; end; -// *********************************************************************// -// DispIntf: IBoldMetaElementDisp -// Flags: (4416) Dual OleAutomation Dispatchable -// GUID: {78994402-CA6E-11D3-89A9-444553540000} -// *********************************************************************// + + + IBoldMetaElementDisp = dispinterface ['{78994402-CA6E-11D3-89A9-444553540000}'] property DelphiName: WideString readonly dispid 201; @@ -304,11 +289,9 @@ interface property HasAdaptee: WordBool readonly dispid 129; end; -// *********************************************************************// -// Interface: IBoldElementTypeInfo -// Flags: (4416) Dual OleAutomation Dispatchable -// GUID: {78994404-CA6E-11D3-89A9-444553540000} -// *********************************************************************// + + + IBoldElementTypeInfo = interface(IBoldMetaElement) ['{78994404-CA6E-11D3-89A9-444553540000}'] function ConformsTo(const ElementTypeInfo: IBoldElementTypeInfo): WordBool; safecall; @@ -318,11 +301,9 @@ interface property SystemTypeInfo: IBoldSystemTypeInfo read Get_SystemTypeInfo; end; -// *********************************************************************// -// DispIntf: IBoldElementTypeInfoDisp -// Flags: (4416) Dual OleAutomation Dispatchable -// GUID: {78994404-CA6E-11D3-89A9-444553540000} -// *********************************************************************// + + + IBoldElementTypeInfoDisp = dispinterface ['{78994404-CA6E-11D3-89A9-444553540000}'] function ConformsTo(const ElementTypeInfo: IBoldElementTypeInfo): WordBool; dispid 301; @@ -378,20 +359,16 @@ interface property HasAdaptee: WordBool readonly dispid 129; end; -// *********************************************************************// -// Interface: IBoldTypeTypeInfo -// Flags: (4416) Dual OleAutomation Dispatchable -// GUID: {68A9FC6D-D646-11D3-89A9-444553540000} -// *********************************************************************// + + + IBoldTypeTypeInfo = interface(IBoldElementTypeInfo) ['{68A9FC6D-D646-11D3-89A9-444553540000}'] end; -// *********************************************************************// -// DispIntf: IBoldTypeTypeInfoDisp -// Flags: (4416) Dual OleAutomation Dispatchable -// GUID: {68A9FC6D-D646-11D3-89A9-444553540000} -// *********************************************************************// + + + IBoldTypeTypeInfoDisp = dispinterface ['{68A9FC6D-D646-11D3-89A9-444553540000}'] function ConformsTo(const ElementTypeInfo: IBoldElementTypeInfo): WordBool; dispid 301; @@ -447,11 +424,9 @@ interface property HasAdaptee: WordBool readonly dispid 129; end; -// *********************************************************************// -// Interface: IBoldClassTypeInfo -// Flags: (4416) Dual OleAutomation Dispatchable -// GUID: {969E6924-D4A6-11D3-89A9-444553540000} -// *********************************************************************// + + + IBoldClassTypeInfo = interface(IBoldElementTypeInfo) ['{969E6924-D4A6-11D3-89A9-444553540000}'] function LeastCommonSuperClass(const ClassTypeInfo: IBoldClassTypeInfo): IBoldClassTypeInfo; safecall; @@ -481,11 +456,9 @@ interface property TopSortedIndex: Integer read Get_TopSortedIndex; end; -// *********************************************************************// -// DispIntf: IBoldClassTypeInfoDisp -// Flags: (4416) Dual OleAutomation Dispatchable -// GUID: {969E6924-D4A6-11D3-89A9-444553540000} -// *********************************************************************// + + + IBoldClassTypeInfoDisp = dispinterface ['{969E6924-D4A6-11D3-89A9-444553540000}'] function LeastCommonSuperClass(const ClassTypeInfo: IBoldClassTypeInfo): IBoldClassTypeInfo; dispid 401; @@ -554,20 +527,16 @@ interface property HasAdaptee: WordBool readonly dispid 129; end; -// *********************************************************************// -// Interface: IBoldNilTypeInfo -// Flags: (4416) Dual OleAutomation Dispatchable -// GUID: {969E6926-D4A6-11D3-89A9-444553540000} -// *********************************************************************// + + + IBoldNilTypeInfo = interface(IBoldClassTypeInfo) ['{969E6926-D4A6-11D3-89A9-444553540000}'] end; -// *********************************************************************// -// DispIntf: IBoldNilTypeInfoDisp -// Flags: (4416) Dual OleAutomation Dispatchable -// GUID: {969E6926-D4A6-11D3-89A9-444553540000} -// *********************************************************************// + + + IBoldNilTypeInfoDisp = dispinterface ['{969E6926-D4A6-11D3-89A9-444553540000}'] function LeastCommonSuperClass(const ClassTypeInfo: IBoldClassTypeInfo): IBoldClassTypeInfo; dispid 401; @@ -636,22 +605,18 @@ interface property HasAdaptee: WordBool readonly dispid 129; end; -// *********************************************************************// -// Interface: IBoldListTypeInfo -// Flags: (4416) Dual OleAutomation Dispatchable -// GUID: {969E6928-D4A6-11D3-89A9-444553540000} -// *********************************************************************// + + + IBoldListTypeInfo = interface(IBoldElementTypeInfo) ['{969E6928-D4A6-11D3-89A9-444553540000}'] function Get_ListElementTypeInfo: IBoldElementTypeInfo; safecall; property ListElementTypeInfo: IBoldElementTypeInfo read Get_ListElementTypeInfo; end; -// *********************************************************************// -// DispIntf: IBoldListTypeInfoDisp -// Flags: (4416) Dual OleAutomation Dispatchable -// GUID: {969E6928-D4A6-11D3-89A9-444553540000} -// *********************************************************************// + + + IBoldListTypeInfoDisp = dispinterface ['{969E6928-D4A6-11D3-89A9-444553540000}'] property ListElementTypeInfo: IBoldElementTypeInfo readonly dispid 401; @@ -708,22 +673,18 @@ interface property HasAdaptee: WordBool readonly dispid 129; end; -// *********************************************************************// -// Interface: IBoldAttributeTypeInfo -// Flags: (4416) Dual OleAutomation Dispatchable -// GUID: {969E692A-D4A6-11D3-89A9-444553540000} -// *********************************************************************// + + + IBoldAttributeTypeInfo = interface(IBoldElementTypeInfo) ['{969E692A-D4A6-11D3-89A9-444553540000}'] function Get_SuperAttributeTypeInfo: IBoldAttributeTypeInfo; safecall; property SuperAttributeTypeInfo: IBoldAttributeTypeInfo read Get_SuperAttributeTypeInfo; end; -// *********************************************************************// -// DispIntf: IBoldAttributeTypeInfoDisp -// Flags: (4416) Dual OleAutomation Dispatchable -// GUID: {969E692A-D4A6-11D3-89A9-444553540000} -// *********************************************************************// + + + IBoldAttributeTypeInfoDisp = dispinterface ['{969E692A-D4A6-11D3-89A9-444553540000}'] property SuperAttributeTypeInfo: IBoldAttributeTypeInfo readonly dispid 401; @@ -780,11 +741,9 @@ interface property HasAdaptee: WordBool readonly dispid 129; end; -// *********************************************************************// -// Interface: IBoldSystemTypeInfo -// Flags: (4416) Dual OleAutomation Dispatchable -// GUID: {969E6922-D4A6-11D3-89A9-444553540000} -// *********************************************************************// + + + IBoldSystemTypeInfo = interface(IBoldElementTypeInfo) ['{969E6922-D4A6-11D3-89A9-444553540000}'] function Get_AttributeTypeInfoByExpressionName(const Name: WideString): IBoldAttributeTypeInfo; safecall; @@ -827,11 +786,9 @@ interface property ValueTypeNameList: IUnknown read Get_ValueTypeNameList; end; -// *********************************************************************// -// DispIntf: IBoldSystemTypeInfoDisp -// Flags: (4416) Dual OleAutomation Dispatchable -// GUID: {969E6922-D4A6-11D3-89A9-444553540000} -// *********************************************************************// + + + IBoldSystemTypeInfoDisp = dispinterface ['{969E6922-D4A6-11D3-89A9-444553540000}'] property AttributeTypeInfoByExpressionName[const Name: WideString]: IBoldAttributeTypeInfo readonly dispid 401; @@ -906,11 +863,9 @@ interface property HasAdaptee: WordBool readonly dispid 129; end; -// *********************************************************************// -// Interface: IBoldDomainElement -// Flags: (4416) Dual OleAutomation Dispatchable -// GUID: {78994406-CA6E-11D3-89A9-444553540000} -// *********************************************************************// + + + IBoldDomainElement = interface(IBoldElement) ['{78994406-CA6E-11D3-89A9-444553540000}'] function Get_BoldDirty: WordBool; safecall; @@ -923,11 +878,9 @@ interface property OwningElement: IBoldDomainElement read Get_OwningElement; end; -// *********************************************************************// -// DispIntf: IBoldDomainElementDisp -// Flags: (4416) Dual OleAutomation Dispatchable -// GUID: {78994406-CA6E-11D3-89A9-444553540000} -// *********************************************************************// + + + IBoldDomainElementDisp = dispinterface ['{78994406-CA6E-11D3-89A9-444553540000}'] property BoldDirty: WordBool readonly dispid 201; @@ -981,11 +934,9 @@ interface property HasAdaptee: WordBool readonly dispid 129; end; -// *********************************************************************// -// Interface: IBoldObject -// Flags: (4416) Dual OleAutomation Dispatchable -// GUID: {7C5C21FF-D247-11D3-89A9-444553540000} -// *********************************************************************// + + + IBoldObject = interface(IBoldDomainElement) ['{7C5C21FF-D247-11D3-89A9-444553540000}'] procedure BoldMakePersistent; safecall; @@ -1022,11 +973,9 @@ interface property SessionId: OleVariant read Get_SessionId; end; -// *********************************************************************// -// DispIntf: IBoldObjectDisp -// Flags: (4416) Dual OleAutomation Dispatchable -// GUID: {7C5C21FF-D247-11D3-89A9-444553540000} -// *********************************************************************// + + + IBoldObjectDisp = dispinterface ['{7C5C21FF-D247-11D3-89A9-444553540000}'] procedure BoldMakePersistent; dispid 301; @@ -1099,11 +1048,9 @@ interface property HasAdaptee: WordBool readonly dispid 129; end; -// *********************************************************************// -// Interface: IBoldMember -// Flags: (4416) Dual OleAutomation Dispatchable -// GUID: {7C5C2201-D247-11D3-89A9-444553540000} -// *********************************************************************// + + + IBoldMember = interface(IBoldDomainElement) ['{7C5C2201-D247-11D3-89A9-444553540000}'] function Clone: IBoldMember; safecall; @@ -1126,11 +1073,9 @@ interface property OwningObject: IBoldObject read Get_OwningObject; end; -// *********************************************************************// -// DispIntf: IBoldMemberDisp -// Flags: (4416) Dual OleAutomation Dispatchable -// GUID: {7C5C2201-D247-11D3-89A9-444553540000} -// *********************************************************************// + + + IBoldMemberDisp = dispinterface ['{7C5C2201-D247-11D3-89A9-444553540000}'] function Clone: IBoldMember; dispid 301; @@ -1195,11 +1140,9 @@ interface property HasAdaptee: WordBool readonly dispid 129; end; -// *********************************************************************// -// Interface: IBoldAttribute -// Flags: (4416) Dual OleAutomation Dispatchable -// GUID: {7C5C25A5-D247-11D3-89A9-444553540000} -// *********************************************************************// + + + IBoldAttribute = interface(IBoldMember) ['{7C5C25A5-D247-11D3-89A9-444553540000}'] procedure SetToNull; safecall; @@ -1211,11 +1154,9 @@ interface property IsNull: WordBool read Get_IsNull; end; -// *********************************************************************// -// DispIntf: IBoldAttributeDisp -// Flags: (4416) Dual OleAutomation Dispatchable -// GUID: {7C5C25A5-D247-11D3-89A9-444553540000} -// *********************************************************************// + + + IBoldAttributeDisp = dispinterface ['{7C5C25A5-D247-11D3-89A9-444553540000}'] procedure SetToNull; dispid 401; @@ -1284,11 +1225,9 @@ interface property HasAdaptee: WordBool readonly dispid 129; end; -// *********************************************************************// -// Interface: IBoldObjectReference -// Flags: (4416) Dual OleAutomation Dispatchable -// GUID: {7C5C2608-D247-11D3-89A9-444553540000} -// *********************************************************************// + + + IBoldObjectReference = interface(IBoldMember) ['{7C5C2608-D247-11D3-89A9-444553540000}'] function CanSet(const NewObject: IBoldObject): WordBool; safecall; @@ -1299,11 +1238,9 @@ interface property BoldRoleRTInfo: IUnknown read Get_BoldRoleRTInfo; end; -// *********************************************************************// -// DispIntf: IBoldObjectReferenceDisp -// Flags: (4416) Dual OleAutomation Dispatchable -// GUID: {7C5C2608-D247-11D3-89A9-444553540000} -// *********************************************************************// + + + IBoldObjectReferenceDisp = dispinterface ['{7C5C2608-D247-11D3-89A9-444553540000}'] function CanSet(const NewObject: IBoldObject): WordBool; dispid 401; @@ -1371,11 +1308,9 @@ interface property HasAdaptee: WordBool readonly dispid 129; end; -// *********************************************************************// -// Interface: IBoldListCore -// Flags: (4416) Dual OleAutomation Dispatchable -// GUID: {4153813B-4DE9-4A17-B747-7091A839BBFA} -// *********************************************************************// + + + IBoldListCore = interface(IBoldMember) ['{4153813B-4DE9-4A17-B747-7091A839BBFA}'] procedure AddList(const List: IBoldListCore); safecall; @@ -1398,11 +1333,9 @@ interface property DuplicateMode: Integer read Get_DuplicateMode write Set_DuplicateMode; end; -// *********************************************************************// -// DispIntf: IBoldListCoreDisp -// Flags: (4416) Dual OleAutomation Dispatchable -// GUID: {4153813B-4DE9-4A17-B747-7091A839BBFA} -// *********************************************************************// + + + IBoldListCoreDisp = dispinterface ['{4153813B-4DE9-4A17-B747-7091A839BBFA}'] procedure AddList(const List: IBoldListCore); dispid 401; @@ -1481,11 +1414,9 @@ interface property HasAdaptee: WordBool readonly dispid 129; end; -// *********************************************************************// -// Interface: IBoldList -// Flags: (4416) Dual OleAutomation Dispatchable -// GUID: {798895F6-E991-432B-9F37-7998BA769199} -// *********************************************************************// + + + IBoldList = interface(IBoldListCore) ['{798895F6-E991-432B-9F37-7998BA769199}'] procedure Add(const Element: IBoldElement); safecall; @@ -1502,11 +1433,9 @@ interface property Elements[Index: Integer]: IBoldElement read Get_Elements write Set_Elements; end; -// *********************************************************************// -// DispIntf: IBoldListDisp -// Flags: (4416) Dual OleAutomation Dispatchable -// GUID: {798895F6-E991-432B-9F37-7998BA769199} -// *********************************************************************// + + + IBoldListDisp = dispinterface ['{798895F6-E991-432B-9F37-7998BA769199}'] procedure Add(const Element: IBoldElement); dispid 501; @@ -1595,11 +1524,9 @@ interface property HasAdaptee: WordBool readonly dispid 129; end; -// *********************************************************************// -// Interface: IBoldObjectList -// Flags: (4416) Dual OleAutomation Dispatchable -// GUID: {75A31152-D30E-11D3-89A9-444553540000} -// *********************************************************************// + + + IBoldObjectList = interface(IBoldList) ['{75A31152-D30E-11D3-89A9-444553540000}'] function Get_BoldObjects(Index: Integer): IBoldObject; safecall; @@ -1612,11 +1539,9 @@ interface property SubscribeToObjectsInList: WordBool read Get_SubscribeToObjectsInList write Set_SubscribeToObjectsInList; end; -// *********************************************************************// -// DispIntf: IBoldObjectListDisp -// Flags: (4416) Dual OleAutomation Dispatchable -// GUID: {75A31152-D30E-11D3-89A9-444553540000} -// *********************************************************************// + + + IBoldObjectListDisp = dispinterface ['{75A31152-D30E-11D3-89A9-444553540000}'] property BoldObjects[Index: Integer]: IBoldObject dispid 601; @@ -1708,11 +1633,9 @@ interface property HasAdaptee: WordBool readonly dispid 129; end; -// *********************************************************************// -// Interface: IBoldMemberList -// Flags: (4416) Dual OleAutomation Dispatchable -// GUID: {75A31154-D30E-11D3-89A9-444553540000} -// *********************************************************************// + + + IBoldMemberList = interface(IBoldList) ['{75A31154-D30E-11D3-89A9-444553540000}'] function Get_BoldMembers(Index: Integer): IBoldMember; safecall; @@ -1720,11 +1643,9 @@ interface property BoldMembers[Index: Integer]: IBoldMember read Get_BoldMembers write Set_BoldMembers; end; -// *********************************************************************// -// DispIntf: IBoldMemberListDisp -// Flags: (4416) Dual OleAutomation Dispatchable -// GUID: {75A31154-D30E-11D3-89A9-444553540000} -// *********************************************************************// + + + IBoldMemberListDisp = dispinterface ['{75A31154-D30E-11D3-89A9-444553540000}'] property BoldMembers[Index: Integer]: IBoldMember dispid 601; @@ -1814,11 +1735,9 @@ interface property HasAdaptee: WordBool readonly dispid 129; end; -// *********************************************************************// -// Interface: IBoldSystem -// Flags: (4416) Dual OleAutomation Dispatchable -// GUID: {8A530C40-D017-11D3-89A9-444553540000} -// *********************************************************************// + + + IBoldSystem = interface(IBoldDomainElement) ['{8A530C40-D017-11D3-89A9-444553540000}'] function CreateNewMember(const ExpressionName: WideString): IBoldMember; safecall; @@ -1840,11 +1759,9 @@ interface property LoadedObjects: IBoldObjectList read Get_LoadedObjects; end; -// *********************************************************************// -// DispIntf: IBoldSystemDisp -// Flags: (4416) Dual OleAutomation Dispatchable -// GUID: {8A530C40-D017-11D3-89A9-444553540000} -// *********************************************************************// + + + IBoldSystemDisp = dispinterface ['{8A530C40-D017-11D3-89A9-444553540000}'] function CreateNewMember(const ExpressionName: WideString): IBoldMember; dispid 301; @@ -1911,20 +1828,16 @@ interface property HasAdaptee: WordBool readonly dispid 129; end; -// *********************************************************************// -// Interface: IBoldBlob -// Flags: (4416) Dual OleAutomation Dispatchable -// GUID: {68A9F8C2-D646-11D3-89A9-444553540000} -// *********************************************************************// + + + IBoldBlob = interface(IBoldAttribute) ['{68A9F8C2-D646-11D3-89A9-444553540000}'] end; -// *********************************************************************// -// DispIntf: IBoldBlobDisp -// Flags: (4416) Dual OleAutomation Dispatchable -// GUID: {68A9F8C2-D646-11D3-89A9-444553540000} -// *********************************************************************// + + + IBoldBlobDisp = dispinterface ['{68A9F8C2-D646-11D3-89A9-444553540000}'] procedure SetToNull; dispid 401; @@ -1993,11 +1906,9 @@ interface property HasAdaptee: WordBool readonly dispid 129; end; -// *********************************************************************// -// Interface: IBoldElementHandle -// Flags: (4416) Dual OleAutomation Dispatchable -// GUID: {71446D80-01C9-4E3C-95A7-D74445C0776C} -// *********************************************************************// + + + IBoldElementHandle = interface(IDispatch) ['{71446D80-01C9-4E3C-95A7-D74445C0776C}'] procedure AddSmallSubscription(const ClientId: WideString; SubscriberId: Integer; @@ -2015,11 +1926,9 @@ interface function SetData(DataFlags: Integer; const Value: IBoldElement; NamedValues: OleVariant): WordBool; safecall; end; -// *********************************************************************// -// DispIntf: IBoldElementHandleDisp -// Flags: (4416) Dual OleAutomation Dispatchable -// GUID: {71446D80-01C9-4E3C-95A7-D74445C0776C} -// *********************************************************************// + + + IBoldElementHandleDisp = dispinterface ['{71446D80-01C9-4E3C-95A7-D74445C0776C}'] procedure AddSmallSubscription(const ClientId: WideString; SubscriberId: Integer; diff --git a/Source/ObjectSpace/COM/BoldComponentValidatorCom.pas b/Source/ObjectSpace/COM/BoldComponentValidatorCom.pas index 4159ee5..a36d7ee 100644 --- a/Source/ObjectSpace/COM/BoldComponentValidatorCom.pas +++ b/Source/ObjectSpace/COM/BoldComponentValidatorCom.pas @@ -1,6 +1,7 @@ -unit BoldComponentValidatorCom; -// this unit is currently only an empty replacement of BoldComponentValidator +{ Global compiler directives } +{$include bold.inc} +unit BoldComponentValidatorCom; interface @@ -13,5 +14,9 @@ TBoldComponentValidatorCom = class end; implementation +uses + BoldRev; + +initialization end. diff --git a/Source/ObjectSpace/Core/BoldCoreConsts.pas b/Source/ObjectSpace/Core/BoldCoreConsts.pas index 19fd870..2d3e11a 100644 --- a/Source/ObjectSpace/Core/BoldCoreConsts.pas +++ b/Source/ObjectSpace/Core/BoldCoreConsts.pas @@ -87,6 +87,7 @@ interface sDeleteWithLinks = 'Can''t delete object with links to others'; sNoMemberNamed = 'Class %s has no member named %s'; sMemberNotPartofSystem = 'Member not part of system'; + sIsEqualUnknownType = '%s.IsEqual: Unknown comparetype'; sNullValueNotAllowed = 'Null Value Not Allowed for Attribute'; sNullEqualError = 'NullEqual is void of meaning'; sRelinkBadCall = 'Internal error: Only Callable for TBoldSinglelink and TBoldMultiLink'; @@ -98,6 +99,7 @@ interface sTypeError = 'type error'; sObjectNotInMultiLink = 'Attempt to remove object not in multilink'; sCallToAbstractMethodOnCustomMapper = '%s.%s: This method is abstract, implement custom method as %s.%s'; + sStringIsNotAnsiString = 'String contains invalid characters'; //BoldAttributes sInvalidValue = 'Invalid value'; @@ -433,3 +435,4 @@ interface implementation end. + diff --git a/Source/ObjectSpace/Core/BoldElements.pas b/Source/ObjectSpace/Core/BoldElements.pas index 21fc017..cd195c7 100644 --- a/Source/ObjectSpace/Core/BoldElements.pas +++ b/Source/ObjectSpace/Core/BoldElements.pas @@ -1,5 +1,8 @@ -unit BoldElements; +{ Global compiler directives } +{$include bold.inc} +unit BoldElements; + interface uses @@ -26,22 +29,34 @@ interface BoldDefaultRegionModeShift = 24; BoldDefaultRegionModeMask = 7 shl BoldDefaultRegionModeShift; // 00000111 - used in TBoldRoleRTInfo - {flags for BoldElement} befImmutable = BoldElementFlag0; befHasModifiedValueHolder = BoldElementFlag1; - {flags for BusinessElement} + {flags for DomainElement} befPersistent = BoldElementFlag2; befTouched = BoldElementFlag3; + {flags for BoldSystem} + befRollbackAreaAssigned = BoldElementFlag4; + befIsDestroying = BoldElementFlag5; + befIsCommitting = BoldElementFlag6; + befIsRollingBack = BoldElementFlag7; + befIsUpdatingDatabase = BoldElementFlag8; + befDirtyObjectsInvalid = BoldElementFlag9; + {flags for BoldObject} befInDirtyList = BoldElementFlag4; befMemberModified = BoldElementFlag5; befMemberModifiedKnown = BoldElementFlag6; befObjectReadOnly = BoldElementFlag7; befObjectWasCreatedNew = BoldElementFlag8; - befStoresTimeStamp = BoldElementFlag9; + befIsHistoricVersion = BoldElementFlag10; + befIsEffectiveInvalid = BoldElementFlag11; + befIsEffectiveInvalidKnown = BoldElementFlag12; + befInDelayDestructionList = BoldElementFlag13; + befDiscarding = BoldElementFlag14; + befDeleting = BoldElementFlag15; {flags for BoldMember} befIsNull = BoldElementFlag4; @@ -51,15 +66,15 @@ interface befHasRtInfo = BoldElementFlag8; befEnsuringCurrent = BoldElementFlag9; befOwnedByObject = BoldElementFlag10; - + befPreFetched = BoldElementFlag11; {flags for BoldObjectList} - befAdjusted = BoldElementFlag11; - befSubscribeToObjectsInList = BoldElementFlag12; - befSubscribeToLocatorsInList = BoldElementFlag13; + befAdjusted = BoldElementFlag12; + befSubscribeToObjectsInList = BoldElementFlag13; + befSubscribeToLocatorsInList = BoldElementFlag14; {flags for BoldObjectReference} - befHasOldValues = BoldElementFlag11; + befHasOldValues = BoldElementFlag12; {flags for BoldElementTypeInfo} BoldValueTypeShift = 24; @@ -95,25 +110,26 @@ interface befMemberPersistent = BoldElementFlag2; befDelayedFetch = BoldElementFlag3; befIsStoredInObject = BoldElementFlag4; - befIsMultiRole = BoldElementFlag5; - befIsSingleRole = BoldElementFlag6; - befIsDerived = BoldElementFlag7; // always false for roles... - befIsReverseDerived = BoldElementFlag8; - befIsNonVersionedInVersionedClass = BoldElementFlag9; - befMemberToBeRemoved = BoldElementFlag10; + befIsAttribute = BoldElementFlag5; + befIsMultiRole = BoldElementFlag6; + befIsSingleRole = BoldElementFlag7; + befIsDerived = BoldElementFlag8; + befIsReverseDerived = BoldElementFlag9; + befIsNonVersionedInVersionedClass = BoldElementFlag10; + befMemberToBeRemoved = BoldElementFlag11; {Flags for BoldRoleRTInfo} - befIsIndirect = BoldElementFlag11; - befIsNavigable = BoldElementFlag12; - befIsOrdered = BoldElementFlag13; - befOtherEndOrdered = BoldElementFlag14; - befMandatory = BoldElementFlag15; - befForceOtherEnd = BoldElementFlag16; - befQualifiedMulti = BoldElementFlag17; + befIsIndirect = BoldElementFlag12; + befIsNavigable = BoldElementFlag13; + befIsOrdered = BoldElementFlag14; + befOtherEndOrdered = BoldElementFlag15; + befMandatory = BoldElementFlag16; + befForceOtherEnd = BoldElementFlag17; + befQualifiedMulti = BoldElementFlag18; {Flags for BoldAttributeRTInfo} - befHasInitalvalue = BoldElementFlag11; - befAllowNull = BoldElementFlag12; + befHasInitalvalue = BoldElementFlag12; + befAllowNull = BoldElementFlag13; type {forward declarations of all classes} @@ -121,6 +137,7 @@ TBoldEvaluator = class; TBoldElement = class; TBoldMetaElement = class; TBoldElementTypeInfo = class; + TBoldListTypeInfo = class; TBoldIndirectElement = class; TBoldDirectElement = TBoldElement; TBoldExternalVariable = class; @@ -134,11 +151,11 @@ TBoldElementClass = class of TBoldElement; IBoldOCLComponent = interface ['{60D40422-8710-11D3-A2C8-EA14D4000000}'] function GetContextType: TBoldElementTypeInfo; - procedure SetExpression(Expression: String); + procedure SetExpression(const Value: TBoldExpression); function GetVariableList: TBoldExternalVariableList; - function GetExpression: String; + function GetExpression: TBoldExpression; property ContextType: TBoldElementTypeInfo read GetContextType; - property Expression: String read GetExpression write SetExpression; + property Expression: TBoldExpression read GetExpression write SetExpression; property VariableList: TBoldExternalVariableList read GetVariableList; end; @@ -146,44 +163,73 @@ TBoldElementClass = class of TBoldElement; TBoldExternalVariable = class(TBoldMemoryManagedObject) private fName: String; + fEvaluator: TBoldEvaluator; protected function GetValue: TBoldElement; virtual; abstract; function GetValueType: TBoldElementTypeInfo; virtual; abstract; public constructor Create(const Name: String); + destructor Destroy; override; property Value: TBoldElement read GetValue; property Name: String read fName; property ValueType: TBoldElementTypeInfo read GetValueType; + property Evaluator: TBoldEvaluator read fEvaluator write fEvaluator; + end; + + TBoldExternalVariableListTraverser = class(TBoldArrayTraverser) + public + function GetCurrent: TBoldExternalVariable; + property Current: TBoldExternalVariable read GetCurrent; end; { TBoldExternalVariableList } TBoldExternalVariableList = class(TBoldObjectArray) private function GetVariables(index: integer): TBoldExternalVariable; + function GetVariableByName(const aName: string): TBoldExternalVariable; + function GetAsCommaText: string; public - constructor create; - procedure Add(Variable: TBoldExternalVariable); + constructor Create(aOwnsVariables: boolean = true); + class function CreateWithStringVariable(AName: string; AValue: string): TBoldExternalVariableList; + class function CreateWithElementVariable(AName: string; AValue: TBoldElement): TBoldExternalVariableList; + function GetEnumerator: TBoldExternalVariableListTraverser; + procedure Add(Variable: TBoldExternalVariable); overload; + procedure Add(AName: string; AValue: string); overload; + procedure Add(AName: string; AValue: TBoldElement); overload; + function RefersToVariable(const Ocl: string): boolean; property Variables[index: integer]: TBoldExternalVariable read GetVariables; default; + property VariableByName[const aName: string]: TBoldExternalVariable read GetVariableByName; + property AsCommaText: string read GetAsCommaText; end; {---TBoldEvaluator---} TBoldEvaluator = class(TBoldMemoryManagedObject) + protected + function GetVariableCount: integer; virtual; abstract; + function GetVariable(index: integer): TBoldIndirectElement; virtual; abstract; + function GetVariableByName(const aName: string): TBoldIndirectElement; virtual; abstract; public - procedure DefineVariable(const VariableName: string; VarValue: TBoldElement; VariableType: TBoldElementTypeInfo; OwnValue: Boolean); virtual; abstract; - procedure Evaluate(Ocl: string; Root: TBoldElement; Subscriber: TBoldSubscriber; ResubscribeAll: Boolean; resultElement: TBoldIndirectElement; EvaluateInPS: Boolean = false; const VariableList: TBoldExternalVariableList = nil); virtual; abstract; + procedure DefineVariable(const VariableName: string; VarValue: TBoldElement; VariableType: TBoldElementTypeInfo; OwnValue, IsConstant: Boolean); overload; virtual; abstract; + procedure DefineVariable(const VariableName: string; Variable: TBoldExternalVariable ); overload; virtual; abstract; + procedure UndefineVariable(Variable: TBoldExternalVariable); virtual; abstract; + procedure Evaluate(Ocl: string; Root: TBoldElement; Subscriber: TBoldSubscriber = nil; ResubscribeAll: Boolean = false; resultElement: TBoldIndirectElement = nil; EvaluateInPS: Boolean = false; const VariableList: TBoldExternalVariableList = nil); virtual; abstract; function ExpressionType(const Ocl: string; Context: TBoldElementTypeInfo; ReRaise: Boolean; const VariableList: TBoldExternalVariableList = nil): TBoldElementTypeInfo; virtual; abstract; procedure SetLookupOclDefinition(value: TBoldLookUpOclDefinition); virtual; abstract; + property Variables[index: integer]: TBoldIndirectElement read GetVariable; + property VariableByName[const aName: string]: TBoldIndirectElement read GetVariableByName; + property VariableCount: integer read GetVariableCount; end; {---TBoldElement---} TBoldElement = class(TBoldSubscribableObject) - private + strict private function GetModifiedValueHolder: TObject; procedure SetModifiedValueHolder(Value: TObject); - function GetMutable: Boolean; + function GetMutable: Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} protected + function GetDisplayName: String; virtual; function GetStringRepresentation(Representation: TBoldRepresentation): string; virtual; - procedure SetStringRepresentation(Representation: TBoldRepresentation; Value: string); virtual; + procedure SetStringRepresentation(Representation: TBoldRepresentation; const Value: string); virtual; procedure CompareError(BoldElement: TBoldElement); procedure AssignError(BoldElement: TBoldElement); procedure MutableError(const NewValue: string); @@ -191,40 +237,52 @@ TBoldElement = class(TBoldSubscribableObject) function GetEvaluator: TBoldEvaluator; virtual; function GetBoldType: TBoldElementTypeInfo; virtual; abstract; function CloneIfPossible: TBoldElement; virtual; + function GetContextString: string; override; + function GetIsPartOfSystem: Boolean; virtual; public + constructor CreateWithTypeInfo(ElementTypeInfo: TBoldElementTypeInfo); virtual; destructor Destroy; override; procedure DefaultSubscribe(Subscriber: TBoldSubscriber; RequestedEvent: TBoldEvent = breReEvaluate); virtual; abstract; procedure PrepareToDestroy; function GetAsVariant: Variant; virtual; - procedure SetAsVariant(const Value: Variant); virtual; + procedure SetAsVariant(const Value: Variant); virtual; function IsEqual(BoldElement: TBoldElement): Boolean; function CompareTo(BoldElement: TBoldElement): Integer; function CompareToAs(CompareType: TBoldCompareType; BoldElement: TBoldElement): Integer; virtual; function IsEqualAs(CompareType: TBoldCompareType; BoldElement: TBoldElement): Boolean; virtual; procedure Assign(Source: TBoldElement); virtual; function ValidateCharacter(C: Char; Representation: TBoldRepresentation): Boolean; virtual; - function ValidateString(Value: string; Representation: TBoldRepresentation): Boolean; virtual; + function ValidateString(const Value: string; Representation: TBoldRepresentation): Boolean; virtual; + function ValidateVariant(const Value: Variant; Representation: TBoldRepresentation = brDefault): Boolean; virtual; procedure EnsureValidString(const Value: string; Representation: TBoldRepresentation); procedure SubscribeToStringRepresentation(Representation: TBoldRepresentation; Subscriber: TBoldSubscriber; RequestedEvent: TBoldEvent = breReEvaluate); virtual; function ObserverMayModify(Observer: TObject): Boolean; virtual; function ObserverMayModifyAsString(Representation: TBoldRepresentation; observer: TBoldSubscriber): Boolean; virtual; - procedure RegisterModifiedValueHolder(observer: TObject); - procedure UnRegisterModifiedValueHolder(observer: TObject); - procedure MakeImmutable; + procedure RegisterModifiedValueHolder(observer: TObject); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure UnRegisterModifiedValueHolder(observer: TObject); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure MakeImmutable; {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure GetAsList(ResultList: TBoldIndirectElement); virtual; abstract; procedure GetAsValue(resultElement: TBoldIndirectElement); virtual; procedure SubscribeToExpression(const Expression: TBoldExpression; Subscriber: TBoldSubscriber; Resubscribe: Boolean = false; EvaluateInPS: Boolean = false; const VariableList: TBoldExternalVariableList = nil); procedure EvaluateExpression(const Expression: TBoldExpression; resultElement: TBoldIndirectElement; EvaluateInPS: Boolean = false; const VariableList: TBoldExternalVariableList = nil); function EvaluateExpressionAsDirectElement(const Expression: TBoldExpression; const VariableList: TBoldExternalVariableList = nil): TBoldElement; procedure EvaluateAndSubscribeToExpression(const Expression: TBoldExpression; Subscriber: TBoldSubscriber; resultElement: TBoldIndirectElement; Resubscribe: Boolean = false; EvaluateInPS: Boolean = false; const VariableList: TBoldExternalVariableList = nil); - function EvaluateExpressionAsString(const Expression: TBoldExpression; Representation: TBoldRepresentation; EvaluateInPS: Boolean = false; const VariableList: TBoldExternalVariableList = nil): string; + function EvaluateExpressionAsString(const Expression: TBoldExpression; Representation: TBoldRepresentation = brDefault; EvaluateInPS: Boolean = false; const VariableList: TBoldExternalVariableList = nil): string; + function EvaluateExpressionAsBoolean(const Expression: TBoldExpression; EvaluateInPS: Boolean = false; const VariableList: TBoldExternalVariableList = nil): Boolean; + function EvaluateExpressionAsInteger(const Expression: TBoldExpression; EvaluateInPS: Boolean = false; const VariableList: TBoldExternalVariableList = nil): Integer; + function EvaluateExpressionAsFloat(const Expression: TBoldExpression; EvaluateInPS: Boolean = false; const VariableList: TBoldExternalVariableList = nil): Double; + function EvaluateExpressionAsCurrency(const Expression: TBoldExpression; EvaluateInPS: Boolean = false; const VariableList: TBoldExternalVariableList = nil): Currency; + function EvaluateExpressionAsDateTime(const Expression: TBoldExpression; EvaluateInPS: Boolean = false; const VariableList: TBoldExternalVariableList = nil): TDateTime; function EvaluateExpressionAsNewElement(const Expression: TBoldExpression; EvaluateInPS: Boolean = false; const VariableList: TBoldExternalVariableList = nil): TBoldElement; property Evaluator: TBoldEvaluator read GetEvaluator; property BoldType: TBoldElementTypeInfo read GetBoldType; property StringRepresentation[Representation: TBoldRepresentation]: string read GetStringRepresentation write SetStringRepresentation; property AsString: string index brDefault read GetStringRepresentation write SetStringRepresentation; + property AsVariant: variant read GetAsVariant write SetAsVariant; property ModifiedValueHolder: TObject read GetModifiedValueHolder; property Mutable: Boolean read GetMutable; + property DisplayName: String read GetDisplayName; + property IsPartOfSystem: Boolean read GetIsPartOfSystem; end; {---TBoldMetaElement---} @@ -235,6 +293,7 @@ TBoldMetaElement = class(TBoldElement) fExpressionName: string; protected function GetStringRepresentation(Representation: TBoldRepresentation): string; override; + function GetDisplayName: String; override; public function IsEqualAs(CompareType: TBoldCompareType; BoldElement: TBoldElement): Boolean; override; constructor Create(const ModelName: string; const ExpressionName: string; const DelphiName: string); @@ -248,25 +307,47 @@ TBoldMetaElement = class(TBoldElement) {---TBoldElementTypeInfo---} TBoldElementTypeInfo = class(TBoldMetaElement) private - fSystemTypeInfo: TBoldElementTypeInfo; // FixMe this shouldn't be stored in every ValueTypeINfo + fSystemTypeInfo: TBoldElementTypeInfo; function GetValueType: TBoldValueTypeSet; protected function GetEvaluator: TBoldEvaluator; override; procedure SetValueType(NewValue: TBoldValueTypeSet); + function GetListTypeInfo: TBoldListTypeInfo; virtual; public constructor Create(const ModelName: string; const ExpressionName: string; const DelphiName: string; SystemTypeInfo: TBoldElementTypeInfo); procedure GetAsList(ResultList: TBoldIndirectElement); override; function ConformsTo(Element: TBoldElementTypeInfo): Boolean; virtual; abstract; + function ElementClass: TBoldElementClass; virtual; + function CreateElement: TBoldElement; virtual; property SystemTypeInfo: TBoldElementTypeInfo read fSystemTypeInfo; property BoldValueType: TBoldValueTypeSet read GetValueType; + property ListTypeInfo: TBoldListTypeInfo read GetListTypeInfo; + end; + + {---TBoldListTypeInfo---} + TBoldListTypeInfo = class(TBoldElementTypeInfo) + private + fListClass: TClass; + fListElementTypeInfo: TBoldElementTypeInfo; + protected + function GetBoldType: TBoldElementTypeInfo; override; + function GetStringRepresentation(Representation: TBoldRepresentation): string; override; + function GetListTypeInfo: TBoldListTypeInfo; override; + public + constructor Create(ListElementTypeInfo: TBoldElementTypeInfo; SystemTypeInfo: TBoldElementTypeInfo; ListClass: TClass); + function ConformsTo(CompareElement: TBoldElementTypeInfo): Boolean; override; + function CreateElement: TBoldElement; override; + property ListClass: TClass read fListClass; + property ListElementTypeInfo: TBoldElementTypeInfo read fListElementTypeInfo; end; {---TBoldIndirectElement---} TBoldIndirectElement = class(TBoldFlaggedObject) private fValue: TBoldElement; - function GetValue: TBoldElement; property WriteableOwnsValue: Boolean index befOwnsValue read GetElementFlag write SetElementFlag; + protected + function ContextObject: TObject; override; public destructor Destroy; override; procedure SetReferenceValue(NewValue: TBoldElement); @@ -274,7 +355,7 @@ TBoldIndirectElement = class(TBoldFlaggedObject) procedure TransferValue(Target: TBoldIndirectElement); function RelinquishValue: TBoldElement; property OwnsValue: Boolean index befOwnsValue read GetElementFlag; - property Value: TBoldElement read GetValue; + property Value: TBoldElement read fValue; end; {---TBoldSubscribableComponentViaBoldElem---} @@ -284,18 +365,25 @@ TBoldSubscribableComponentViaBoldElem = class(TBoldSubscribableComponent) implementation uses - SysUtils, - BoldUtils, + BoldExternalizedReferences, BoldOclError, - Typinfo, BoldTypeList, // circular reference BoldElements->BoldTypelist->BoldSystem->BoldElements - BoldExternalizedReferences, - BoldCoreConsts; + BoldAttributes, + BoldOclVariables, + BoldUtils, + SysUtils, + Variants, + Windows, + Typinfo, + Classes; +const + sOCLResultError = 'Expression: ''%s '' returned incorrect result. Expected: %s. Currently: %s.'; + beModifiedValueHolderDestroying = 303; var G_ExternalModifiedValueHolders: TBoldExternalizedReferenceList; -function TBoldElement.EvaluateExpressionAsString(const Expression: TBoldExpression; Representation: TBoldRepresentation; EvaluateInPS: Boolean = false; const VariableList: TBoldExternalVariableList = nil): string; +function TBoldElement.EvaluateExpressionAsString(const Expression: TBoldExpression; Representation: TBoldRepresentation = brDefault; EvaluateInPS: Boolean = false; const VariableList: TBoldExternalVariableList = nil): string; var E: TBoldIndirectElement; begin @@ -326,6 +414,69 @@ procedure TBoldElement.EvaluateExpression(const Expression: TBoldExpression; res EvaluateAndSubscribeToExpression(Expression, nil, resultElement, False, EvaluateInPS, VariableList); end; +function TBoldElement.EvaluateExpressionAsBoolean( + const Expression: TBoldExpression; EvaluateInPS: Boolean; + const VariableList: TBoldExternalVariableList): Boolean; +var + E: TBoldIndirectElement; +begin + Result := False; + E := TBoldIndirectElement.Create; + try + EvaluateExpression(Expression, E, EvaluateInPS, VariableList); + if Assigned(E.Value) then + if E.Value is TBABoolean then + Result := TBABoolean(E.Value).AsBoolean + else + raise EBold.CreateFmt(sOCLResultError, [Expression, + TBABoolean.ClassName, E.Value.ClassName]) + finally + E.Free; + end; +end; + +function TBoldElement.EvaluateExpressionAsCurrency( + const Expression: TBoldExpression; EvaluateInPS: Boolean; + const VariableList: TBoldExternalVariableList): Currency; +var + E: TBoldIndirectElement; +begin + Result := 0; + E := TBoldIndirectElement.Create; + try + EvaluateExpression(Expression, E, EvaluateInPS, VariableList); + if Assigned(E.Value) then + if E.Value is TBACurrency then + Result := TBACurrency(E.Value).AsCurrency + else + raise EBold.CreateFmt(sOCLResultError, [Expression, + TBACurrency.ClassName, E.Value.ClassName]) + finally + E.Free; + end; +end; + +function TBoldElement.EvaluateExpressionAsDateTime( + const Expression: TBoldExpression; EvaluateInPS: Boolean; + const VariableList: TBoldExternalVariableList): TDateTime; +var + E: TBoldIndirectElement; +begin + Result := 0; + E := TBoldIndirectElement.Create; + try + EvaluateExpression(Expression, E, EvaluateInPS, VariableList); + if Assigned(E.Value) then + if E.Value is TBADateTime then + Result := TBADateTime(E.Value).AsDateTime + else + raise EBold.CreateFmt(sOCLResultError, [Expression, + TBADateTime.ClassName, E.Value.ClassName]) + finally + E.Free; + end; +end; + function TBoldElement.EvaluateExpressionAsDirectElement(const Expression: TBoldExpression; const VariableList: TBoldExternalVariableList = nil): TBoldElement; var E: TBoldIndirectElement; @@ -342,6 +493,49 @@ function TBoldElement.EvaluateExpressionAsDirectElement(const Expression: TBoldE end; end; +function TBoldElement.EvaluateExpressionAsFloat( + const Expression: TBoldExpression; + EvaluateInPS: Boolean; const VariableList: TBoldExternalVariableList): Double; +var + E: TBoldIndirectElement; +begin + Result := 0; + E := TBoldIndirectElement.Create; + try + EvaluateExpression(Expression, E, EvaluateInPS, VariableList); + if Assigned(E.Value) then + if E.Value is TBAFloat then + Result := TBAFloat(E.Value).AsFloat + else + raise EBold.CreateFmt(sOCLResultError, [Expression, + TBAFloat.ClassName, E.Value.ClassName]) + finally + E.Free; + end; +end; + +function TBoldElement.EvaluateExpressionAsInteger( + const Expression: TBoldExpression; + EvaluateInPS: Boolean; + const VariableList: TBoldExternalVariableList): Integer; +var + E: TBoldIndirectElement; +begin + Result := 0; + E := TBoldIndirectElement.Create; + try + EvaluateExpression(Expression, E, EvaluateInPS, VariableList); + if Assigned(E.Value) then + if E.Value is TBAInteger then + Result := TBAInteger(E.Value).AsInteger + else + raise EBold.CreateFmt(sOCLResultError, [Expression, + TBAInteger.ClassName, E.Value.ClassName]) + finally + E.Free; + end; +end; + {---TBoldElement---} function TBoldElement.GetEvaluator: TBoldEvaluator; @@ -349,8 +543,9 @@ function TBoldElement.GetEvaluator: TBoldEvaluator; if assigned(BoldType) then Result := BoldType.Evaluator else - raise EBold.CreateFmt(sCannotGetEvaluatorWithoutType, [classname]); + raise EBold.CreateFmt('%s.GetEvaluator: Element has no type, can not get evaluator', [classname]); end; + destructor TBoldElement.Destroy; begin PrepareToDestroy; @@ -365,12 +560,14 @@ procedure TBoldElement.PrepareToDestroy; function TBoldElement.GetStringRepresentation(Representation: TBoldRepresentation): string; begin - raise EBold.CreateFmt(sRepresentationNotSupported, [ClassName, Representation]); + raise EBold.CreateFmt('%s.GetStringRepresentation: Representation %d not supported', + [ClassName, Representation]); end; -procedure TBoldElement.SetStringRepresentation(Representation: TBoldRepresentation; Value: string); +procedure TBoldElement.SetStringRepresentation(Representation: TBoldRepresentation; const Value: string); begin - raise EBold.CreateFmt(sRepresentationNotSupported, [ClassName, Representation]); + raise EBold.CreateFmt('%s.SetStringRepresentation: Representation %d not supported', + [ClassName, Representation]); end; procedure TBoldElement.SubscribeToStringRepresentation(Representation: TBoldRepresentation; Subscriber: TBoldSubscriber; RequestedEvent: TBoldEvent); @@ -382,7 +579,7 @@ function TBoldElement.ValidateCharacter(C: Char; Representation: TBoldRepresenta Result := True; end; -function TBoldElement.ValidateString(Value: string; Representation: TBoldRepresentation): Boolean; +function TBoldElement.ValidateString(const Value: string; Representation: TBoldRepresentation): Boolean; var I: Integer; begin @@ -395,9 +592,17 @@ function TBoldElement.ValidateString(Value: string; Representation: TBoldReprese end; end; +function TBoldElement.ValidateVariant(const Value: Variant; + Representation: TBoldRepresentation): Boolean; +begin + result := ValidateString(VarToStr(Value), Representation); +end; + function TBoldElement.ObserverMayModify(Observer: TObject): Boolean; begin - Result := False; + Result := Mutable and + ((ModifiedValueHolder = nil) or + (ModifiedValueHolder = Observer)); end; function TBoldElement.ObserverMayModifyAsString(Representation: TBoldRepresentation; Observer: TBoldSubscriber): Boolean; @@ -406,71 +611,109 @@ function TBoldElement.ObserverMayModifyAsString(Representation: TBoldRepresentat end; procedure TBoldElement.RegisterModifiedValueHolder(observer: TObject); + + procedure InternalRaise(Self: TBoldElement; Value: TObject); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + var + LockedBy: string; + begin + if Value is TBoldMemoryManagedObject then + LockedBy := TBoldMemoryManagedObject(Value).DebugInfo + else + if Value is TComponent then + begin + LockedBy := TComponent(Value).Name; + if LockedBy = '' then + LockedBy := Value.ClassName; + end + else + LockedBy := Value.ClassName; + raise EBold.CreateFmt('%s: Member already under modification by %s', [self.DisplayName, LockedBy]) + end; + +var + Value: TObject; begin - if Assigned(ModifiedValueHolder) and (ModifiedValueHolder <> observer) then - raise EBold.CreateFmt(sMemberAlreadyModified, [ClassName]) + if GetElementFlag(befHasModifiedValueHolder) then + begin + Value := ModifiedValueHolder; + if Assigned(Value) and (Value <> observer) then + InternalRaise(Self, Observer); + end else SetModifiedValueHolder(observer); end; procedure TBoldElement.UnRegisterModifiedValueHolder(observer: TObject); begin - // FIXME grid if (ModifiedValueHolder <> observer) then - // raise EBoldInternal.Create('Internal Error') - // else SetModifiedValueHolder(nil); end; function TBoldElement.IsEqual(BoldElement: TBoldElement): Boolean; begin - Result := IsEqualAs(ctDefault, BoldElement); + Result := (self = BoldElement) or IsEqualAs(ctDefault, BoldElement); end; function TBoldElement.IsEqualAs(CompareType: TBoldCompareType; BoldElement: TBoldElement): Boolean; begin - Result := CompareToAs(CompareType, BoldElement) = 0; + Result := (self = BoldElement) or (CompareToAs(CompareType, BoldElement) = 0); end; function TBoldElement.CompareTo(BoldElement: TBoldElement): Integer; begin - Result := CompareToAs(ctDefault, BoldElement); + if (self = BoldElement) then + result := 0 + else + result := CompareToAs(ctDefault, BoldElement); end; function TBoldElement.CompareToAs(CompareType: TBoldCompareType; BoldElement: TBoldElement): Integer; begin - raise EBold.CreateFmt(sLocatedAbstractError, [ClassName, 'CompareToAs']); // do not localize + raise EBold.CreateFmt('%s.CompareToAs is abstract', [ClassName]); end; procedure TBoldElement.Assign(Source: TBoldElement); begin if assigned(Source) then - raise EBold.CreateFmt(sAssignNotSupported, [ClassName, Source.ClassName]) + raise EBold.CreateFmt('%s.Assign does not support assigning from %s', [ClassName, Source.ClassName]) else - raise EBold.CreateFmt(sAssignNilNotSupported, [ClassName]) + raise EBold.CreateFmt('%s.Assign does not support assigning nil', [ClassName]) end; procedure TBoldElement.CompareError(BoldElement: TBoldElement); begin if Assigned(BoldElement) then - raise EBold.CreateFmt(sCompareNotSupported, [ClassName, BoldElement.ClassName]) + raise EBold.CreateFmt('%s: Cannot compare with a %s', [ClassName, BoldElement.ClassName]) else - raise EBold.CreateFmt(sCompareNilNotSupported, [ClassName]); + raise EBold.CreateFmt('%s: Cannot compare to nil', [ClassName]); end; procedure TBoldElement.AssignError(BoldElement: TBoldElement); begin if Assigned(BoldElement) then - raise EBold.CreateFmt(sAssignNotSupported, [ClassName, BoldElement.ClassName]) + raise EBold.CreateFmt('%s: Cannot assign a %s', [ClassName, BoldElement.ClassName]) else - raise EBold.CreateFmt(sAssignNilNotSupported, [ClassName]); + raise EBold.CreateFmt('%s: Cannot assign nil', [ClassName]); end; procedure TBoldElement.CompareTypeError(CompType: TBoldCompareType; BoldElement: TBoldElement); +var + ElementName: string; begin - raise EBold.CreateFmt(sInvalidCompareType, + if Assigned(BoldElement) + then + ElementName := BoldElement.ClassName + else + ElementName := 'nil'; + raise EBold.CreateFmt('%s: Comparetype ''%s'' not supported when comparing to %s', [ClassName, GetEnumName(TypeInfo(TBoldCompareType), Ord(CompType)), - BoldElement.ClassName]); + ElementName]); +end; + +constructor TBoldElement.CreateWithTypeInfo( + ElementTypeInfo: TBoldElementTypeInfo); +begin + end; procedure TBoldElement.MakeImmutable; @@ -480,7 +723,7 @@ procedure TBoldElement.MakeImmutable; procedure TBoldElement.MutableError(const NewValue: string); begin - raise EBold.CreateFmt(sTriedToChangeImmutableElement, [ClassName, AsString, NewValue]); + raise EBold.CreateFmt('%s: Tried to change the value of an immutable element from ''%s'' to ''%s''', [ClassName, AsString, NewValue]); end; procedure TBoldElement.GetAsValue(resultElement: TBoldIndirectElement); @@ -492,7 +735,7 @@ procedure TBoldElement.EnsureValidString(const Value: string; Representation: TBoldRepresentation); begin if not ValidateString(Value, Representation) then - raise EBoldAssertionFailed.Create(sStringValidationFailed); + raise EBoldAssertionFailed.CreateFmt('%s.EnsureValidString: String validation failed', [Classname]); end; function TBoldElement.GetAsVariant: Variant; @@ -500,16 +743,34 @@ function TBoldElement.GetAsVariant: Variant; Result := AsString; end; +function TBoldElement.GetContextString: string; +begin + result := DisplayName; +end; + +function TBoldElement.GetDisplayName: String; +begin + if Assigned(BoldType) then + result := BoldType.AsString + else + result := ClassName; +end; + procedure TBoldElement.SetAsVariant(const Value: Variant); begin AsString := Value; end; +function TBoldElement.GetIsPartOfSystem: Boolean; +begin + result := true; // always true for System and Objects, and overriden for Member +end; + {---TBoldMetaElement---} procedure TBoldMetaElement.DefaultSubscribe(Subscriber: TBoldSubscriber; RequestedEvent: TBoldEvent = breReEvaluate); begin if Mutable then - raise EBold.CreateFmt(sCannotSubscribeToMutableMetaElements, [ClassName]); + raise EBold.CreateFmt('%s.DefaultSubscribe: Subscription on mutable MetaElements is not possible', [ClassName]); end; constructor TBoldMetaElement.Create(const ModelName: string; const ExpressionName: string; const DelphiName: string); @@ -528,7 +789,12 @@ function TBoldMetaElement.GetStringRepresentation(Representation: TBoldRepresent procedure TBoldMetaElement.GetAsList(ResultList: TBoldIndirectElement); begin - raise EBoldFeatureNotImplementedYet.Create(sMetaElementGetAsListNotImplemented); + raise EBoldFeatureNotImplementedYet.Create('TBoldMetaElement.GetAsList has not been implemented yet.'); +end; + +function TBoldMetaElement.GetDisplayName: String; +begin + result := ExpressionName; end; {---TBoldElementTypeInfo---} @@ -538,6 +804,18 @@ constructor TBoldElementTypeInfo.Create(const ModelName: string; const Expressio fSystemTypeInfo := SystemTypeInfo; end; +function TBoldElementTypeInfo.ElementClass: TBoldElementClass; +begin + result := nil; +end; + +function TBoldElementTypeInfo.CreateElement: TBoldElement; +const + sInvalidBoldType = '%s.CreateElement: Invalid BoldType (%s)'; +begin + raise EBold.CreateFmt(sInvalidBoldType, [ClassName, asString]) +end; + procedure TBoldElementTypeInfo.GetAsList(ResultList: TBoldIndirectElement); var list: TBoldTypeList; @@ -552,10 +830,16 @@ function TBoldElementTypeInfo.GetEvaluator: TBoldEvaluator; Result := SystemTypeInfo.GetEvaluator; end; +function TBoldElementTypeInfo.GetListTypeInfo: TBoldListTypeInfo; +begin + raise EBold.CreateFmt('%s.GetListTypeInfo is not overriden, implement it.', [classname]); +end; + {---TBoldIndirectElement---} + destructor TBoldIndirectElement.Destroy; begin - if OwnsValue then + if OwnsValue and not fValue.IsPartOfSystem then FreeAndNil(fValue) else fValue := nil; @@ -577,7 +861,7 @@ procedure TBoldIndirectElement.SetReferenceValue(NewValue: TBoldElement); end else if OwnsValue then - raise EBold.CreateFmt(sNewValueAlreadyOwned, [ClassName]); + raise EBold.Create('TBoldInDirectElement.SetReferenceValue: New value alread owned!'); WriteableOwnsValue := False; end; @@ -617,9 +901,9 @@ function TBoldIndirectElement.RelinquishValue: TBoldElement; WriteableOwnsValue := False; end; -function TBoldIndirectElement.GetValue: TBoldElement; +function TBoldIndirectElement.ContextObject: TObject; begin - Result := fValue; + result := fValue; end; function TBoldElement.GetModifiedValueHolder: TObject; @@ -652,9 +936,9 @@ procedure TBoldElement.EvaluateAndSubscribeToExpression( AddSmallSubscription(Subscriber, [beDestroying], breReSubscribe); except on E: EBoldOCLAbort do - raise EBold.CreateFmt(sOCLExpressionError, [E.Ocl, E.Message]); + raise EBold.CreateFmt('OCL Expression: %s' + BOLDCRLF + 'Error: %s' + BOLDCRLF, [E.Ocl, E.Message]); on E: EBoldOCLError do - raise EBold.CreateFmt(sOCLExpressionError, [E.Ocl, E.Message]); + raise EBold.CreateFmt('OCL Expression: %s' + BOLDCRLF + 'Error: %s' + BOLDCRLF, [E.Ocl, E.Message]); end; end; @@ -676,6 +960,14 @@ constructor TBoldExternalVariable.Create(const Name: String); fName := Name; end; +destructor TBoldExternalVariable.Destroy; +begin + if Assigned(fEvaluator) then + fEvaluator.UndefineVariable(self); + fEvaluator := nil; + inherited; +end; + { TBoldExternalOclVariableList } procedure TBoldExternalVariableList.Add(Variable: TBoldExternalVariable); @@ -683,9 +975,71 @@ procedure TBoldExternalVariableList.Add(Variable: TBoldExternalVariable); inherited Add(Variable); end; -constructor TBoldExternalVariableList.create; +procedure TBoldExternalVariableList.Add(AName, AValue: string); +begin + Add(TBoldOclVariable.CreateStringVariable(AName, AValue)); +end; + +procedure TBoldExternalVariableList.Add(AName: string; AValue: TBoldElement); +begin + Add(TBoldOclVariable.Create(AName, AValue)); +end; + +constructor TBoldExternalVariableList.Create(aOwnsVariables: boolean = true); +begin + if aOwnsVariables then + inherited create(4, [bcoDataOwner]) + else + inherited create(4, []); +end; + +class function TBoldExternalVariableList.CreateWithElementVariable( + AName: string; AValue: TBoldElement): TBoldExternalVariableList; +begin + result := TBoldExternalVariableList.Create; + result.Add(TBoldOclVariable.Create(AName, AValue)); +end; + +class function TBoldExternalVariableList.CreateWithStringVariable(AName, + AValue: string): TBoldExternalVariableList; +begin + result := TBoldExternalVariableList.Create; + result.Add(TBoldOclVariable.CreateStringVariable(AName, AValue)); +end; + +function TBoldExternalVariableList.GetAsCommaText: string; +var + i: integer; + sl: TStringList; +begin + result := ''; + sl:= TStringList.Create; + try + for I := 0 to Count - 1 do + sl.Add(Variables[i].Name); + result := sl.CommaText; + finally + sl.free; + end; +end; + +function TBoldExternalVariableList.GetEnumerator: TBoldExternalVariableListTraverser; begin - inherited create(4, [bcoDataOwner]); + result := TBoldExternalVariableListTraverser.Create(self); +end; + +function TBoldExternalVariableList.GetVariableByName( + const aName: string): TBoldExternalVariable; +var + i: integer; +begin + result := nil; + for I := 0 to Count - 1 do + if CompareText(Variables[i].Name, aName) = 0 then + begin + result := Variables[i]; + break; + end; end; function TBoldExternalVariableList.GetVariables(index: integer): TBoldExternalVariable; @@ -693,6 +1047,17 @@ function TBoldExternalVariableList.GetVariables(index: integer): TBoldExternalVa result := Items[index] as TBoldExternalVariable; end; +function TBoldExternalVariableList.RefersToVariable(const Ocl: string): boolean; +var + i: integer; +begin + result := true; + for i := 0 to Count-1 do + if BoldCaseIndependentPos(Variables[i].Name, Ocl) > 0 then + exit; + result := false; +end; + function TBoldMetaElement.IsEqualAs(CompareType: TBoldCompareType; BoldElement: TBoldElement): Boolean; begin @@ -728,13 +1093,79 @@ function TBoldElement.CloneIfPossible: TBoldElement; Result := nil; end; +{---TBoldListTypeInfo---} +constructor TBoldListTypeInfo.Create(ListElementTypeInfo: TBoldElementTypeInfo; SystemTypeInfo: TBoldElementTypeInfo; ListClass: TClass); +begin + if assigned(ListElementTypeInfo) then + inherited Create(ListElementTypeInfo.ModelName + 'List', + 'Collection(' + ListElementTypeInfo.ExpressionName + ')', + ListElementTypeInfo.Delphiname + 'List', SystemTypeInfo) + else + inherited Create('Collection()', 'Collection()', 'Collection()', SystemTypeInfo); + fListElementTypeInfo := ListElementTypeInfo; + SetValueType(bvtList); + fListClass := ListClass; +end; + +function TBoldListTypeInfo.CreateElement: TBoldElement; +begin + result := TBoldElementClass(ListClass).CreateWithTypeInfo(self); +end; + +function TBoldListTypeInfo.ConformsTo(CompareElement: TBoldElementTypeInfo): Boolean; +var + CompareListTypeInfo: TBoldListTypeInfo; +begin + if CompareElement is TBoldListTypeInfo then + begin + CompareListTypeInfo := TBoldListTypeInfo(CompareElement); + Result := not assigned(CompareListTypeInfo.ListElementTypeInfo) or + (assigned(ListElementTypeInfo) and + ListElementTypeInfo.ConformsTo(CompareListTypeInfo.ListElementTypeInfo)); + end + else + Result := False; +end; + +function TBoldListTypeInfo.GetStringRepresentation(Representation: TBoldRepresentation): string; +begin + if assigned(ListElementTypeInfo) then + Result := 'Collection(' + ListElementTypeInfo.AsString + ')' + else + Result := 'Collection()'; +end; + +function TBoldListTypeInfo.GetBoldType: TBoldElementTypeInfo; +begin + result := SystemTypeInfo.BoldType; +end; + +function TBoldListTypeInfo.GetListTypeInfo: TBoldListTypeInfo; +begin + result := self; +end; + +procedure InitDebugMethods; +var + List: TBoldExternalVariableList; +begin + exit; + List := nil; + List.AsCommaText; +end; + +{ TBoldExternalVariableListTraverser } + +function TBoldExternalVariableListTraverser.GetCurrent: TBoldExternalVariable; +begin + result := ObjectArray[index] as TBoldExternalVariable; +end; + initialization G_ExternalModifiedValueHolders := TBoldExternalizedReferenceList.Create; + InitDebugMethods; finalization G_ExternalModifiedValueHolders.free; end. - - - diff --git a/Source/ObjectSpace/Core/BoldMetaElementList.pas b/Source/ObjectSpace/Core/BoldMetaElementList.pas index 1e28373..8034cf9 100644 --- a/Source/ObjectSpace/Core/BoldMetaElementList.pas +++ b/Source/ObjectSpace/Core/BoldMetaElementList.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldMetaElementList; interface @@ -11,15 +14,25 @@ interface TBoldMetaElementList = class; TBoldElementTypeInfoList = class; + TBoldMetaElementListTraverser = class(TBoldIndexableListTraverser) + public + function GetCurrent: TBoldMetaElement; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + property Current: TBoldMetaElement read GetCurrent; + end; + { TBoldMetaElementList } TBoldMetaElementList = class(TBoldIndexableList) private - function GetItem(index: Integer): TBoldMetaElement; - function GetItemByExpressionName(const ExpressionName: string): TBoldMetaElement; - function GetItemByDelphiName(const DelphiName: string): TBoldMetaElement; - function GetItemByModelName(const ModelName: string): TBoldMetaElement; + function GetItem(index: Integer): TBoldMetaElement; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetItemByExpressionName(const ExpressionName: string): TBoldMetaElement; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetItemByDelphiName(const DelphiName: string): TBoldMetaElement; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetItemByModelName(const ModelName: string): TBoldMetaElement; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + class var IX_ExpressionName: integer; + class var IX_DelphiName: integer; + class var IX_ModelName: integer; public constructor Create; + function GetEnumerator: TBoldMetaElementListTraverser; procedure Add(Item: TBoldMetaElement); property Items[index: Integer]: TBoldMetaElement read GetItem; default; property ItemsByExpressionName[const ExpressionName: string]: TBoldMetaElement read GetItemByExpressionName; @@ -27,14 +40,21 @@ TBoldMetaElementList = class(TBoldIndexableList) property ItemsByModelName[const ModelName: string]: TBoldMetaElement read GetItemByModelName; end; + TBoldElementTypeInfoListTraverser = class(TBoldIndexableListTraverser) + public + function GetCurrent: TBoldElementTypeInfo; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + property Current: TBoldElementTypeInfo read GetCurrent; + end; + { TBoldElementTypeInfoList } TBoldElementTypeInfoList = class(TBoldMetaElementList) private - function GetItem(index: Integer): TBoldElementTypeInfo; - function GetItemByExpressionName(const ExpressionName: string): TBoldElementTypeInfo; - function GetItemByDelphiName(const DelphiName: string): TBoldElementTypeInfo; - function GetItemByModelName(const ModelName: string): TBoldElementTypeInfo; + function GetItem(index: Integer): TBoldElementTypeInfo; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetItemByExpressionName(const ExpressionName: string): TBoldElementTypeInfo; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetItemByDelphiName(const DelphiName: string): TBoldElementTypeInfo; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetItemByModelName(const ModelName: string): TBoldElementTypeInfo; {$IFDEF BOLD_INLINE} inline; {$ENDIF} public + function GetEnumerator: TBoldElementTypeInfoListTraverser; procedure Add(Item: TBoldElementTypeInfo); property Items[index: Integer]: TBoldElementTypeInfo read GetItem; default; property ItemsByExpressionName[const ExpressionName: string]: TBoldElementTypeInfo read GetItemByExpressionName; @@ -45,14 +65,8 @@ TBoldElementTypeInfoList = class(TBoldMetaElementList) implementation uses - SysUtils, BoldHashIndexes, - BoldUtils; - -var - IX_ExpressionName: integer = -1; - IX_DelphiName: integer = -1; - IX_ModelName: integer = -1; + BoldRev; type {---TExpressionNameIndex---} @@ -102,6 +116,11 @@ constructor TBoldMetaElementList.Create; SetIndexVariable(IX_ModelName, AddIndex(TModelNameIndex.Create)); end; +function TBoldMetaElementList.GetEnumerator: TBoldMetaElementListTraverser; +begin + result := CreateTraverser as TBoldMetaElementListTraverser; +end; + function TBoldMetaElementList.GetItem(index: Integer): TBoldMetaElement; begin Result := TBoldMetaElement(inherited Items[index]); @@ -109,12 +128,12 @@ function TBoldMetaElementList.GetItem(index: Integer): TBoldMetaElement; function TBoldMetaElementList.GetItemByExpressionName(const ExpressionName: string): TBoldMetaElement; begin - Result := TBoldMetaElement(TBoldValueTypeNameIndex(Indexes[IX_ExpressionName]).FindByString(ExpressionName)); + Result := TBoldMetaElement(TBoldStringHashIndex(Indexes[IX_ExpressionName]).FindByString(ExpressionName)); end; function TBoldMetaElementList.GetItemByDelphiName(const DelphiName: string): TBoldMetaElement; begin - Result := TBoldMetaElement(TDelphiNameIndex(Indexes[IX_DelphiName]).FindByString(DelphiName)); + Result := TBoldMetaElement(TBoldStringHashIndex(Indexes[IX_DelphiName]).FindByString(DelphiName)); end; procedure TBoldMetaElementList.Add(Item: TBoldMetaElement); @@ -124,7 +143,7 @@ procedure TBoldMetaElementList.Add(Item: TBoldMetaElement); function TBoldMetaElementList.GetItemByModelName(const ModelName: string): TBoldMetaElement; begin - Result := TBoldMetaElement(TModelNameIndex(Indexes[IX_ModelName]).FindByString(ModelName)); + Result := TBoldMetaElement(TBoldStringHashIndex(Indexes[IX_ModelName]).FindByString(ModelName)); end; { TBoldElementTypeInfoList } @@ -134,6 +153,11 @@ procedure TBoldElementTypeInfoList.Add(Item: TBoldElementTypeInfo); inherited add(item); end; +function TBoldElementTypeInfoList.GetEnumerator: TBoldElementTypeInfoListTraverser; +begin + result := CreateTraverser as TBoldElementTypeInfoListTraverser; +end; + function TBoldElementTypeInfoList.GetItem(index: Integer): TBoldElementTypeInfo; begin result := TBoldElementTypeInfo(inherited GetItem(index)); @@ -154,4 +178,25 @@ function TBoldElementTypeInfoList.GetItemByModelName(const ModelName: string): T result := TBoldElementTypeInfo(inherited GetItemByModelName(ModelName)); end; +{ TBoldMetaElementListTraverser } + +function TBoldMetaElementListTraverser.GetCurrent: TBoldMetaElement; +begin + result := inherited GetItem as TBoldMetaElement; +end; + +{ TBoldElementTypeInfoListTraverser } + +function TBoldElementTypeInfoListTraverser.GetCurrent: TBoldElementTypeInfo; +begin + result := inherited GetItem as TBoldElementTypeInfo; +end; + + +initialization + TBoldMetaElementList.IX_ExpressionName := -1; + TBoldMetaElementList.IX_DelphiName := -1; + TBoldMetaElementList.IX_ModelName := -1; + end. + diff --git a/Source/ObjectSpace/IDE/AttributeWizard/BoldAttributeWizard.pas b/Source/ObjectSpace/IDE/AttributeWizard/BoldAttributeWizard.pas index 72e7b8c..fb2b00a 100644 --- a/Source/ObjectSpace/IDE/AttributeWizard/BoldAttributeWizard.pas +++ b/Source/ObjectSpace/IDE/AttributeWizard/BoldAttributeWizard.pas @@ -1,6 +1,7 @@ -unit BoldAttributeWizard; -// NB! The attribute wizard is disabled in BCB. Check the Register-procedure +{ Global compiler directives } +{$include bold.inc} +unit BoldAttributeWizard; interface @@ -10,7 +11,7 @@ interface BoldTemplateExpander; type - { TAttributeWizard } + TAttributeWizard = class(TProjectWizard, IUnitGenerator) private procedure GenerateUnit(const UnitName: string; Template: TBoldTemplateHolder); @@ -34,25 +35,22 @@ implementation BoldWAdatamodule, BoldWAMainForm, BoldIDEMenus, - dialogs, - BoldCoreConsts; + dialogs; var AttributeWizardInitialized: Boolean = false; procedure Register; begin - {$IFDEF BOLD_DELPHI} InitExpert; RegisterPackageWizard(AttributeWizard); - {$ENDIF} end; procedure InitExpert; begin dmAttributeWizard := TdmAttributeWizard.Create(nil); - AttributeWizard := TAttributeWizard.Create('Bold.AttributeWizard', sBoldAttributeWizard, [], 3, 'Bold'); // do not localize - BoldMenuExpert; // ensure "Bold" menu has been created + AttributeWizard := TAttributeWizard.Create('Bold.AttributeWizard', 'Bold Attribute Wizard', [], 3, 'Bold'); + BoldMenuExpert; AttributeWizard.AddMenuItem(dmAttributeWizard.AttributeWizardMenu); AttributeWizardInitialized := true; end; @@ -64,7 +62,7 @@ procedure DoneExpert; AttributeWizardInitialized := false; end; - { TAttributeWizard } +{ TAttributeWizard } procedure TAttributeWizard.Execute; begin MainForm := TMainForm.Create(nil); @@ -75,46 +73,38 @@ procedure TAttributeWizard.Execute; procedure TAttributeWizard.GenerateUnit(const UnitName: string; Template: TBoldTemplateHolder); var -// CurrentProject: IOTAProject; Creator: TUnitCreator; NewModule: IOTAModule; SourceEditor: IOTASourceEditor; aUnitName, aFileName, aClassName: string; FullName: string; begin -// GetCurrentProject(CurrentProject); - //create a module, needs an IOTACreator + Creator := TUnitCreator.Create; - //get a new file and unit name from Delphi (BorlandIDEServices as IOTAModuleServices).GetNewModuleAndClassName('', aUnitName, aClassName, aFileName); - //use the new unitname if user has not specified one. if (length(UnitName) <> 0) then aUnitName := UnitName; - Template.Variables.SetVariable('UNITNAME', aUnitName); // do not localize + Template.Variables.SetVariable('UNITNAME', aUnitName); NewModule := nil; try FullName := Format('%s%s',[ExtractFilePath(aFileName), aUnitName]); -// NewModule := Creator.CreateUnit(Format('%s%s',[ExtractFilePath(aFileName), aUnitName]), Template.ExpandedTemplate.Text, CurrentProject as IOTAModule); NewModule := Creator.CreateUnit(FullName, Template.ExpandedTemplate.Text, nil); except on e: Exception do - MessageDlg(Format(sUnableToCreateUnit, [FullName, e.Message]), mtError, [mbOk], 0); + MessageDlg(Format('Unable to create unit %s, check unit name (Reason: %s)', [FullName, e.Message]), mtError, [mbOk], 0); end; - // save file -// NewModule.Save(true, true); - //add to project -// if Assigned(CurrentProject) then -// CurrentProject.AddFile(NewModule.GetFileName, true); - // show in editor + + + + + if assigned(NewModule) then begin SourceEditor := NewModule.GetModuleFileEditor(0) as IOTASourceEditor; (SourceEditor as IOTAEditor).Show; end; - // show the source editor, bring it to front - //!!Delphi4 -// (BorlandIDEServices as IOTAEditorServices).GetTopView.GetEditWindow.Form.show; + end; initialization diff --git a/Source/ObjectSpace/IDE/AttributeWizard/BoldOTACodeGen.pas b/Source/ObjectSpace/IDE/AttributeWizard/BoldOTACodeGen.pas index aa979ce..bdcee63 100644 --- a/Source/ObjectSpace/IDE/AttributeWizard/BoldOTACodeGen.pas +++ b/Source/ObjectSpace/IDE/AttributeWizard/BoldOTACodeGen.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldOTACodeGen; interface @@ -23,13 +26,11 @@ TUnitCreator = class(TNotifierObject, IOTACreator, IOTAModuleCreator) fSource: string; public constructor Create; - // IOTACreator methods function GetCreatorType: string; function GetExisting: Boolean; function GetFileSystem: string; function GetOwner: IOTAModule; function GetUnnamed: Boolean; - //IOTAModuleCreator methods function GetAncestorName: string; function GetImplFileName: string; function GetIntfFileName: string; @@ -144,7 +145,6 @@ function TUnitCreator.NewIntfSource(const ModuleIdent, FormIdent, AncestorIdent: procedure TUnitCreator.FormCreated(const FormEditor: IOTAFormEditor); begin -// end; function TUnitCreator.CreateUnit(const FileName, Source: string; Owner: IOTAModule): IOTAModule; @@ -171,4 +171,6 @@ function TUnitFile.GetAge: TDateTime; Result:= -1; end; +initialization + end. diff --git a/Source/ObjectSpace/IDE/AttributeWizard/BoldVclUtils.pas b/Source/ObjectSpace/IDE/AttributeWizard/BoldVclUtils.pas index ffcdfed..ddfec09 100644 --- a/Source/ObjectSpace/IDE/AttributeWizard/BoldVclUtils.pas +++ b/Source/ObjectSpace/IDE/AttributeWizard/BoldVclUtils.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldVclUtils; interface @@ -30,7 +33,6 @@ procedure ExchangeRows(var StringGrid: TStringGrid; a, b: Integer); i: Integer; begin if ((a < StringGrid.RowCount) AND (b < StringGrid.RowCount) AND (a <> 0) AND (b <> 0)) then - //ExchangeRows for i:= 0 to StringGrid.ColCount - 1 do StringGrid.Cols[i].Exchange(a,b); end; @@ -74,7 +76,6 @@ procedure ShiftDown(var StringGrid: TStringGrid; StartRow: Integer); begin if ((StartRow >= StringGrid.FixedRows) AND (StartRow < StringGrid.RowCount)) then begin - // append an empty to the stringgrid AppendRow(StringGrid); for i := (StringGrid.RowCount -1) downto (StartRow + 1) do ExchangeRows(StringGrid,i, i - 1); @@ -85,7 +86,6 @@ procedure SelectCell(var StringGrid: TStringGrid; const Col, Row: integer); var t: TGridRect; begin - // Selecting a cell in the stringGrid t.Left := Col ; t.Right := Col ; t.Top := Row; @@ -95,7 +95,6 @@ procedure SelectCell(var StringGrid: TStringGrid; const Col, Row: integer); procedure AppendRow(var StringGrid: TStringGrid); begin - // append an empty to the stringgrid if not IsEmptyStr(Trim(StringGrid.Rows[StringGrid.RowCount - 1].Text)) then begin StringGrid.RowCount := StringGrid.RowCount + 1; @@ -120,4 +119,6 @@ function IsEmptyStr(const str: string): Boolean; Result := (length(trim(str)) = 0); end; +initialization + end. diff --git a/Source/ObjectSpace/IDE/AttributeWizard/BoldWAClassInfo.pas b/Source/ObjectSpace/IDE/AttributeWizard/BoldWAClassInfo.pas index 38f1a53..fb4ec9e 100644 --- a/Source/ObjectSpace/IDE/AttributeWizard/BoldWAClassInfo.pas +++ b/Source/ObjectSpace/IDE/AttributeWizard/BoldWAClassInfo.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldWAClassInfo; interface @@ -60,13 +63,13 @@ constructor TClassInfo.Create(id: string); inherited Create; Create; fDelphiName := id; - Parent := 'TObject'; // do not localize + Parent := 'TObject'; end; destructor TClassInfo.Destroy; begin FreeAndNil(fmethods); - inherited Destroy; + inherited destroy; end; function TClassInfo.getMethods(const Visibility: TVisibility;var Item: TMethodInfo; var I: Integer): Boolean; @@ -167,4 +170,6 @@ procedure TClassInfoList.Clear; Remove(TClassInfo(fList[Index])); end; +initialization + end. diff --git a/Source/ObjectSpace/IDE/AttributeWizard/BoldWACustomAttr.pas b/Source/ObjectSpace/IDE/AttributeWizard/BoldWACustomAttr.pas index d2094d0..43f75f6 100644 --- a/Source/ObjectSpace/IDE/AttributeWizard/BoldWACustomAttr.pas +++ b/Source/ObjectSpace/IDE/AttributeWizard/BoldWACustomAttr.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldWACustomAttr; interface @@ -64,13 +67,12 @@ implementation function StrToAccessType(str: string): TAccessType; begin - if (AnsiCompareText(str,'READONLY') = 0) then // do not localize + if (AnsiCompareText(str,'READONLY') = 0) then Result := atReadOnly - else if (AnsiCompareText(str,'WRITEONLY') = 0) then // do not localize + else if (AnsiCompareText(str,'WRITEONLY') = 0) then Result := atWriteOnly - else if (AnsiCompareText(str,'READ/WRITE') = 0) then // do not localize + else if (AnsiCompareText(str,'READ/WRITE') = 0) then Result := atReadWrite - // default in ReadOnly else Result := atReadOnly ; end; @@ -112,17 +114,15 @@ procedure TCustomAttribute.AssignMethodsToTemplate(var Template: TBoldTemplateHo function BooleanToStr(value: Boolean): string; begin if value then - Result := 'true' // do not localize + Result := 'true' else - Result := 'false'; // do not localize + Result := 'false'; end; begin - // init count array if Methods.Count = 0 then Exit; for v:= stPrivate to stPublished do aCount[v]:= 0; - // get new methods for i:= 0 to Methods.Count - 1 do begin Item := Methods[i]; @@ -130,8 +130,8 @@ procedure TCustomAttribute.AssignMethodsToTemplate(var Template: TBoldTemplateHo vasString := Item.TVisibilityToStr(Item.Visibility); if Item.IsOverriden then begin - Template.Variables.Add(Format('%s',[Item.Name]), 'true', []); // do not localize - Template.Variables.Add(Format('%s',[vasString]), 'true', []); // do not localize + Template.Variables.Add(Format('%s',[Item.Name]), 'true', []); + Template.Variables.Add(Format('%s',[vasString]), 'true', []); end else begin @@ -139,18 +139,18 @@ procedure TCustomAttribute.AssignMethodsToTemplate(var Template: TBoldTemplateHo Signature := Item.Params + ': ' + Item.ReturnType + ';' else Signature := Item.Params + ';'; - Template.Variables.Add(format('%sMETHODTYPE.%d',[vAsString,aCount[v]]), Item.methodTypeAsString, []); // do not localize - Template.Variables.Add(format('%sMETHODNAME.%d',[vAsString,aCount[v]]), Item.Name, []); // do not localize - Template.Variables.Add(format('%sMETHODSIGNATURE.%d',[vAsString,aCount[v]]), Signature , []); // do not localize + Template.Variables.Add(format('%sMETHODTYPE.%d',[vAsString,aCount[v]]), Item.methodTypeAsString, []); + Template.Variables.Add(format('%sMETHODNAME.%d',[vAsString,aCount[v]]), Item.Name, []); + Template.Variables.Add(format('%sMETHODSIGNATURE.%d',[vAsString,aCount[v]]), Signature , []); if mdOverride in Methods[i].mDirectives then - Template.Variables.Add(format('%sMETHODDIRECTIVES.%d', [vAsString,aCount[v]]), ' override;', []); // do not localize - Template.Variables.Add(Format('%s',[vasString]), 'true', []); // do not localize + Template.Variables.Add(format('%sMETHODDIRECTIVES.%d', [vAsString,aCount[v]]), ' override;', []); + Template.Variables.Add(Format('%s',[vasString]), 'true', []); Inc(aCount[v]); end; - end;// for + end; for v:= stPrivate to stPublished do begin - Template.Variables.Add(TMethodInfo.TVisibilityToStr(v)+'METHODCOUNT', IntToStr(aCount[v]), []); // do not localize + Template.Variables.Add(TMethodInfo.TVisibilityToStr(v)+'METHODCOUNT', IntToStr(aCount[v]), []); Template.Variables.Add(TMethodInfo.TVisibilityToStr(v), BooleanToStr(aCount[v] <> 0), []); end; end; @@ -233,4 +233,6 @@ procedure TPropertyInfoList.Clear; Remove(TPropertyInfo(fList[Index])); end; +initialization + end. diff --git a/Source/ObjectSpace/IDE/AttributeWizard/BoldWACustomAttrForm1.pas b/Source/ObjectSpace/IDE/AttributeWizard/BoldWACustomAttrForm1.pas index 8a274f6..6b4ca33 100644 --- a/Source/ObjectSpace/IDE/AttributeWizard/BoldWACustomAttrForm1.pas +++ b/Source/ObjectSpace/IDE/AttributeWizard/BoldWACustomAttrForm1.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldWACustomAttrForm1; interface @@ -26,14 +29,11 @@ interface const YES = '1'; NO = '0'; - // StringGridMethods columns COL_METHOD_VISIBILITY = 0; COL_METHOD_TYPE = 1; COL_METHOD_NAME = 2; COL_METHOD_PARAMS = 3; COL_METHOD_RETURNTYPE = 4; - - //StringGridProperties columns COL_PROPERTY_NAME = 0; COL_PROPERTY_TYPE = 1; COL_PROPERTY_ACCESSTYPE = 2; @@ -114,7 +114,7 @@ TCustomAttrForm1 = class(TForm, IWizardForm) procedure StringGridMethodsDrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect; State: TGridDrawState); procedure FormDestroy(Sender: TObject); - function getTypeDictionary: TBoldTypeNameDictionary; + function getTypeDictionary: TBoldTypeNameDictionary; procedure edUnitnameChange(Sender: TObject); function DelphiToBDEType(const DelphiType: string): string; function DelphiToAccessorType(const DelphiType: string): string; @@ -159,7 +159,7 @@ TCustomAttrForm1 = class(TForm, IWizardForm) function GetDefaultMapperName(const ClassName: string; const NumOfProperties: integer): string; property SteppedBack: Boolean read GetSteppedBack default false; property UnitGenerator: IUnitGenerator read getUnitGeneratorIntf write setUnitGeneratorIntf; - property EnableNext: TEnableNextEvent write setEnableNext; // CallBack function + property EnableNext: TEnableNextEvent write setEnableNext; end; function BooleanToStr(value: Boolean): string; @@ -182,9 +182,9 @@ implementation function BooleanToStr(value: Boolean): string; begin if value then - Result := 'true' // do not localize + Result := 'true' else - Result := 'false'; // do not localize + Result := 'false'; end; procedure TCustomAttrForm1.EnableNextBtn(const Enable: Boolean); @@ -210,13 +210,12 @@ destructor TCustomAttrForm1.Destroy; begin FreeAndNil(fMgrStringGridProperties); FreeAndNil(fMgrStringGridMethods); - inherited Destroy; + inherited destroy; end; procedure TCustomAttrForm1.Initialize; begin Align := alClient; - // hide all control fields cbPropertyTypes.Visible := false; cbAccessTypes.Visible := false; cbMethodTypes.Visible := false; @@ -227,11 +226,11 @@ procedure TCustomAttrForm1.Initialize; edMethodSignature.Visible := false; { StringGridMethods } - StringGridMethods.Cells[COL_METHOD_TYPE,0] := 'Method type'; // do not localize - StringGridMethods.Cells[COL_METHOD_NAME,0] := 'Name'; // do not localize - StringGridMethods.Cells[COL_METHOD_PARAMS,0] := 'Parameters'; // do not localize - StringGridMethods.Cells[COL_METHOD_RETURNTYPE,0] := 'Return Type'; // do not localize - StringGridMethods.Cells[COL_METHOD_VISIBILITY,0] := 'Visibility'; // do not localize + StringGridMethods.Cells[COL_METHOD_TYPE,0] := 'Method type'; + StringGridMethods.Cells[COL_METHOD_NAME,0] := 'Name'; + StringGridMethods.Cells[COL_METHOD_PARAMS,0] := 'Parameters'; + StringGridMethods.Cells[COL_METHOD_RETURNTYPE,0] := 'Return Type'; + StringGridMethods.Cells[COL_METHOD_VISIBILITY,0] := 'Visibility'; fMgrStringGridMethods.addCtrlForColumn(cbMethodTypes, TComboBox, COL_METHOD_TYPE); fMgrStringGridMethods.addCtrlForColumn(edMethodName, TEdit, COL_METHOD_NAME); fMgrStringGridMethods.addCtrlForColumn(edMethodSignature, TEdit, COL_METHOD_PARAMS); @@ -239,21 +238,18 @@ procedure TCustomAttrForm1.Initialize; fMgrStringGridMethods.addCtrlForColumn(cbVisibility, TComboBox, COL_METHOD_VISIBILITY); { StringGridProperties } - StringGridProperties.Cells[COL_PROPERTY_NAME,0] := 'Name'; // do not localize - StringGridProperties.Cells[COL_PROPERTY_TYPE,0] := 'Type'; // do not localize - StringGridProperties.Cells[COL_PROPERTY_ACCESSTYPE,0] := 'Access type'; // do not localize + StringGridProperties.Cells[COL_PROPERTY_NAME,0] := 'Name'; + StringGridProperties.Cells[COL_PROPERTY_TYPE,0] := 'Type'; + StringGridProperties.Cells[COL_PROPERTY_ACCESSTYPE,0] := 'Access type'; fMgrStringGridProperties.addCtrlForColumn(edPropertyName, TEdit, COL_PROPERTY_NAME); fMgrStringGridProperties.addCtrlForColumn(cbPropertyTypes, TComboBox, COL_PROPERTY_TYPE); fMgrStringGridProperties.addCtrlForColumn(cbAccessTypes, TComboBox, COL_PROPERTY_ACCESSTYPE); fOverrideMethodsParser := TClassParser.Create(TStringStream.Create(MemoMethodsToOverride.Lines.Text)); fOverrideMethodsParser.Start; - - // display base classes GetBaseClasses(cbParent.Items); DisplayOverrideMethods(CheckListBoxOverride.Items); - //set proper view PageControl1.ActivePage := tsClassDef; end; @@ -280,7 +276,6 @@ function TCustomAttrForm1.Next: integer; if PageControl1.ActivePage = tsClassDef then begin Result := wfaNext; - //check the class definition if IsValidClassDef then begin PageControl1.ActivePage := tsProperties; @@ -325,31 +320,28 @@ procedure TCustomAttrForm1.Finish; UnitNamePrefix := NewAttribute.ExpressionName else UnitNamePrefix := NewAttribute.UnitName; - PMapperUnitName := Format('%sPMapper',[UnitNamePrefix]); // do not localize - InterfaceUnitName := Format('%sInterface',[UnitNamePrefix]); // do not localize - InterfaceName := Format('I%s',[NewAttribute.ExpressionName]); // do not localize - MapperName :=Format('%sPMapper',[NewAttribute.DelphiName]); // do not localize + PMapperUnitName := Format('%sPMapper',[UnitNamePrefix]); + InterfaceUnitName := Format('%sInterface',[UnitNamePrefix]); + InterfaceName := Format('I%s',[NewAttribute.ExpressionName]); + MapperName :=Format('%sPMapper',[NewAttribute.DelphiName]); try - // set the attribute template variables with attrdatamodule.AttributeTemplate do begin - Variables.Add('UNITNAME', NewAttribute.UnitName, []); // do not localize - Variables.Add('EXPRESSIONNAME', NewAttribute.ExpressionName, []); // do not localize - Variables.Add('DELPHINAME', NewAttribute.DelphiName, []); // do not localize - Variables.Add('SUPERCLASS', NewAttribute.Parent, []); // do not localize - Variables.Add('INTERFACENAME', InterfaceName, []); // do not localize - Variables.Add('INTERFACEUNITNAME', InterfaceUnitName, []); // do not localize + Variables.Add('UNITNAME', NewAttribute.UnitName, []); + Variables.Add('EXPRESSIONNAME', NewAttribute.ExpressionName, []); + Variables.Add('DELPHINAME', NewAttribute.DelphiName, []); + Variables.Add('SUPERCLASS', NewAttribute.Parent, []); + Variables.Add('INTERFACENAME', InterfaceName, []); + Variables.Add('INTERFACEUNITNAME', InterfaceUnitName, []); if (NewAttribute.Properties.Count > 0) then begin - // new mapper and interface classes - Variables.Add('MAPPERNAME',MapperName,[]); // do not localize - Variables.Add('CONTENTNAME', Format('ContentName_%s', [NewAttribute.ExpressionName]), []); // do not localize + Variables.Add('MAPPERNAME',MapperName,[]); + Variables.Add('CONTENTNAME', Format('ContentName_%s', [NewAttribute.ExpressionName]), []); end else begin - // parent's mapper and interface classes - Variables.Add('MAPPERNAME',Format('',[NewAttribute.Parent]),[]); // do not localize - Variables.Add('CONTENTNAME', Format('', [NewAttribute.Parent]), []); // do not localize + Variables.Add('MAPPERNAME',Format('',[NewAttribute.Parent]),[]); + Variables.Add('CONTENTNAME', Format('', [NewAttribute.Parent]), []); end end; NewAttribute.AssignMethodsToTemplate(attrdatamodule.AttributeTemplate); @@ -358,29 +350,27 @@ procedure TCustomAttrForm1.Finish; begin with attrdatamodule.InterfaceTemplate do begin - Variables.Add('SUPERINTERFACENAME', BaseInterfaceName, []); // do not localize - Variables.Add('INTERFACENAME',InterfaceName, []); // do not localize - Variables.Add('UNITNAME',InterfaceUnitName, []); // do not localize - Variables.Add('INTERFACEGUID',BoldCreateGUIDAsString, []); // do not localize - Variables.Add('FREESTANDINGDELPHINAME','TBFS' + NewAttribute.ExpressionName,[]); // do not localize - Variables.Add('FREESTANDINGSUPERCLASS','TBoldFreeStandingNullableValue',[]); // do not localize - Variables.Add('INTERFACEUNITNAME',Format('%sInterface',[NewAttribute.UnitName]), []); // do not localize - Variables.Add('EXPRESSIONNAME', NewAttribute.ExpressionName, []); // do not localize + Variables.Add('SUPERINTERFACENAME', BaseInterfaceName, []); + Variables.Add('INTERFACENAME',InterfaceName, []); + Variables.Add('UNITNAME',InterfaceUnitName, []); + Variables.Add('INTERFACEGUID',BoldCreateGUIDAsString, []); + Variables.Add('FREESTANDINGDELPHINAME','TBFS' + NewAttribute.ExpressionName,[]); + Variables.Add('FREESTANDINGSUPERCLASS','TBoldFreeStandingNullableValue',[]); + Variables.Add('INTERFACEUNITNAME',Format('%sInterface',[NewAttribute.UnitName]), []); + Variables.Add('EXPRESSIONNAME', NewAttribute.ExpressionName, []); end; AssignProperties(NewAttribute, attrdatamodule.InterfaceTemplate); - //set the PMapper template's variables with attrdatamodule.MapperTemplate do begin - Variables.Add('MAPPERNAME',NewAttribute.DelphiName+ 'PMapper',[]); // do not localize - Variables.Add('SUPERMAPPERNAME',getDefaultMapperName(NewAttribute.parent, NewAttribute.Properties.Count) ,[]); // do not localize - Variables.Add('STREAMCONSTANT', 'StreamName',[]); // do not localize - Variables.Add('INTERFACEUNITNAME',InterfaceUnitName, []); // do not localize - Variables.Add('UNITNAME', PMapperUnitName, []); // do not localize - Variables.Add('INTERFACENAME',InterfaceName, []); // do not localize + Variables.Add('MAPPERNAME',NewAttribute.DelphiName+ 'PMapper',[]); + Variables.Add('SUPERMAPPERNAME',getDefaultMapperName(NewAttribute.parent, NewAttribute.Properties.Count) ,[]); + Variables.Add('STREAMCONSTANT', 'StreamName',[]); + Variables.Add('INTERFACEUNITNAME',InterfaceUnitName, []); + Variables.Add('UNITNAME', PMapperUnitName, []); + Variables.Add('INTERFACENAME',InterfaceName, []); end; AssignProperties(NewAttribute, attrdatamodule.MapperTemplate); end; - // Generate Code if Assigned(UnitGenerator) then UnitGenerator.GenerateUnit(NewAttribute.UnitName, attrdatamodule.AttributeTemplate); if (NewAttribute.Properties.Count > 0) then @@ -454,8 +444,7 @@ procedure TCustomAttrForm1.GetNewAttribute(var NewAttribute: TCustomAttribute); ExpressionName := edExpressionName.Text; UnitName := trim(edUnitname.Text); Properties.Clear; - // Properties - // row 0 is for the column titles + for i:= 1 to StringGridProperties.RowCount - 1 do if not IsEmptyStr(StringGridProperties.Rows[i].Text) then begin @@ -463,27 +452,25 @@ procedure TCustomAttrForm1.GetNewAttribute(var NewAttribute: TCustomAttribute); StrToAccessType(StringGridProperties.Cells[2,i]))); end; Methods.Clear; - //new methods - // row 0 is for the column titles + for i := 1 to StringGridMethods.RowCount - 1 do if not IsEmptyStr(StringGridMethods.Rows[i].Text) then begin NewMethod := TMethodInfo.Create; -// NewMethod.methodType := StrToMethodType(Trim(StringGridMethods.Cells[COL_METHOD_TYPE,i])); -// NewMethod.Name := Trim(StringGridMethods.Cells[COL_METHOD_NAME,i]); -// NewMethod.Params := Trim(StringGridMethods.Cells[COL_METHOD_PARAMS,i]) ; -// if (Newmethod.Params[1] <> '(') then -// NewMethod.Params := Format('(%s',[NewMethod.Params]); -// if (NewMethod.Params[length(NewMethod.Params)] <> ')') then -// NewMethod.Params := Format('%s)',[NewMethod.Params]); -// NewMethod.ReturnType := Trim(StringGridMethods.Cells[COL_METHOD_RETURNTYPE, i]); -// NewMethod.Visibility := StrToVisibility(Trim(StringGridMethods.Cells[COL_METHOD_VISIBILITY, i])); + + + + + + + + NewMethod.Assign(TMethodInfo.StrToMethodType(Trim(StringGridMethods.Cells[COL_METHOD_TYPE,i])), Trim(StringGridMethods.Cells[COL_METHOD_NAME,i]), Trim(StringGridMethods.Cells[COL_METHOD_PARAMS,i]), Trim(StringGridMethods.Cells[COL_METHOD_RETURNTYPE, i]), TMethodInfo.StrToVisibility(Trim(StringGridMethods.Cells[COL_METHOD_VISIBILITY, i])), []); Methods.Add(NewMethod); - end; //if - // get override methods + end; + for i:= 0 to CheckListBoxOverride.Items.Count - 1 do if CheckListBoxOverride.Checked[i] then begin @@ -493,7 +480,7 @@ procedure TCustomAttrForm1.GetNewAttribute(var NewAttribute: TCustomAttribute); temp.Visibility, [mdOverride]); Methods.Add(NewMethod); end; - end; //with + end; end; { FormCreate } @@ -555,39 +542,37 @@ procedure TCustomAttrForm1.AssignProperties(var NewAttribute: TCustomAttribute; i: integer; aProperty: TPropertyInfo; begin - //set the properties for i:= 0 to NewAttribute.Properties.Count - 1 do begin aProperty := NewAttribute.Properties[i]; - Template.Variables.Add(Format('FIELDNAME.%d',[i]), aProperty.Name, []); // do not localize - Template.Variables.Add(Format('FIELDTYPE.%d',[i]), aProperty.pType, []); // do not localize - Template.Variables.Add(Format('FIELDBDETYPE.%d',[i]), DelphiToBDEType(aProperty.pType), []); // do not localize - Template.Variables.Add(Format('FIELDACCESSORTYPE.%d',[i]), DelphiToAccessorType(aProperty.pType), []); // do not localize + Template.Variables.Add(Format('FIELDNAME.%d',[i]), aProperty.Name, []); + Template.Variables.Add(Format('FIELDTYPE.%d',[i]), aProperty.pType, []); + Template.Variables.Add(Format('FIELDBDETYPE.%d',[i]), DelphiToBDEType(aProperty.pType), []); + Template.Variables.Add(Format('FIELDACCESSORTYPE.%d',[i]), DelphiToAccessorType(aProperty.pType), []); if (aProperty.AccessType = atWriteOnly) then - Template.Variables.Add(Format('FIELDREADABLE.%d',[i]), NO, []) // do not localize + Template.Variables.Add(Format('FIELDREADABLE.%d',[i]), NO, []) else - Template.Variables.Add(Format('FIELDREADABLE.%d',[i]), YES, []); // do not localize + Template.Variables.Add(Format('FIELDREADABLE.%d',[i]), YES, []); if (aProperty.AccessType = atReadOnly) then - Template.Variables.Add(Format('FIELDWRITABLE.%d',[i]), NO, []) // do not localize + Template.Variables.Add(Format('FIELDWRITABLE.%d',[i]), NO, []) else - Template.Variables.Add(Format('FIELDWRITABLE.%d',[i]), YES, []); // do not localize - end; //for - Template.Variables.Add('FIELDCOUNT', IntToStr(NewAttribute.Properties.Count), []); // do not localize + Template.Variables.Add(Format('FIELDWRITABLE.%d',[i]), YES, []); + end; + Template.Variables.Add('FIELDCOUNT', IntToStr(NewAttribute.Properties.Count), []); if (NewAttribute.Properties.Count > 0) then begin - Template.Variables.SetVariable('PUBLIC', 'true'); // do not localize - Template.Variables.SetVariable('PRIVATE', 'true'); // do not localize - Template.Variables.SetVariable('PROTECTED', 'true'); // do not localize - Template.Variables.Add('INTERFACEDCLASS',YES, []); // do not localize + Template.Variables.SetVariable('PUBLIC', 'true'); + Template.Variables.SetVariable('PRIVATE', 'true'); + Template.Variables.SetVariable('PROTECTED', 'true'); + Template.Variables.Add('INTERFACEDCLASS',YES, []); end else - Template.Variables.Add('INTERFACEDCLASS', NO, []); // do not localize + Template.Variables.Add('INTERFACEDCLASS', NO, []); end; procedure TCustomAttrForm1.GetBaseClasses(list: TStrings); var i: integer; -// ClassInfo: TClassInfo; begin { // create parser object, free in finalizer, classes hard coded fAttributeClassParser := TClassParser.Create(TStringStream.Create(MemoBoldClasses.Lines.Text)); @@ -596,8 +581,6 @@ procedure TCustomAttrForm1.GetBaseClasses(list: TStrings); while fAttributeClassParser.getClasses(ClassInfo, i) do if Assigned(ClassInfo) then cbParent.Items.Add(ClassInfo.DelphiName);} - - // get base classes from a TypeNameDictionary TypeDictionary.AddDefaultMappings; list.BeginUpdate; list.Clear; @@ -660,6 +643,7 @@ procedure TCustomAttrForm1.ActionStringGridInsertExecute(Sender: TObject); fMgrStringGridMethods.Add else MessageDlg('Invalid method entry', mtInformation, [mbOk], 0); + end; procedure TCustomAttrForm1.ActionStringGridDeleteExecute(Sender: TObject); @@ -670,6 +654,7 @@ procedure TCustomAttrForm1.ActionStringGridDeleteExecute(Sender: TObject); fMgrStringGridMethods.Delete; end; + procedure TCustomAttrForm1.cbParentChange(Sender: TObject); var i: integer; @@ -818,42 +803,42 @@ procedure TCustomAttrForm1.edUnitnameChange(Sender: TObject); function TCustomAttrForm1.DelphiToBDEType(const DelphiType: string): string; begin - if (CompareText(DelphiType,'integer') = 0)then // do not localize - Result := 'ftInteger' // do not localize - else if (CompareText(DelphiType,'real') = 0) then // do not localize - Result := 'ftFloat' // do not localize - else if (CompareText(DelphiType,'extended') = 0) then // do not localize - Result := 'ftFloat' // do not localize - else if (CompareText(DelphiType,'cardinal')= 0) then // do not localize - Result := 'ftInteger' // do not localize - else if (CompareText(DelphiType,'char') = 0) then // do not localize - Result := 'ftFixedChar' // do not localize - else if (CompareText(DelphiType,'string')= 0) then // do not localize - Result := 'ftString' // do not localize - else if (CompareText(DelphiType,'boolean')= 0) then // do not localize - Result := 'ftBoolean' // do not localize + if (CompareText(DelphiType,'integer') = 0)then + Result := 'ftInteger' + else if (CompareText(DelphiType,'real') = 0) then + Result := 'ftFloat' + else if (CompareText(DelphiType,'extended') = 0) then + Result := 'ftFloat' + else if (CompareText(DelphiType,'cardinal')= 0) then + Result := 'ftInteger' + else if (CompareText(DelphiType,'char') = 0) then + Result := 'ftFixedChar' + else if (CompareText(DelphiType,'string')= 0) then + Result := 'ftString' + else if (CompareText(DelphiType,'boolean')= 0) then + Result := 'ftBoolean' else - Result := ''; // do not localize + Result := ''; end; function TCustomAttrForm1.DelphiToAccessorType(const DelphiType: string): string; begin - if (CompareText(DelphiType,'integer') = 0) then // do not localize - Result := 'Integer' // do not localize - else if (CompareText(DelphiType,'real') = 0) then // do not localize - Result := 'Double' // do not localize - else if (CompareText(DelphiType,'extended') = 0) then // do not localize - Result := 'Double' // do not localize - else if (CompareText(DelphiType,'cardinal') = 0) then // do not localize - Result := 'Integer' // do not localize - else if (CompareText(DelphiType, 'char') = 0) then // do not localize - Result := 'Char' // do not localize - else if (CompareText(DelphiType,'string') = 0) then // do not localize - Result := 'String' // do not localize - else if (CompareText(DelphiType,'boolean') = 0) then // do not localize - Result := 'Boolean' // do not localize + if (CompareText(DelphiType,'integer') = 0) then + Result := 'Integer' + else if (CompareText(DelphiType,'real') = 0) then + Result := 'Double' + else if (CompareText(DelphiType,'extended') = 0) then + Result := 'Double' + else if (CompareText(DelphiType,'cardinal') = 0) then + Result := 'Integer' + else if (CompareText(DelphiType, 'char') = 0) then + Result := 'Char' + else if (CompareText(DelphiType,'string') = 0) then + Result := 'String' + else if (CompareText(DelphiType,'boolean') = 0) then + Result := 'Boolean' else - Result := ''; // do not localize + Result := ''; end; procedure TCustomAttrForm1.tsOverrideShow(Sender: TObject); @@ -861,4 +846,5 @@ procedure TCustomAttrForm1.tsOverrideShow(Sender: TObject); CheckListBoxOverride.SetFocus; end; +initialization end. diff --git a/Source/ObjectSpace/IDE/AttributeWizard/BoldWAInputFormUnit.pas b/Source/ObjectSpace/IDE/AttributeWizard/BoldWAInputFormUnit.pas index e128f86..02de31f 100644 --- a/Source/ObjectSpace/IDE/AttributeWizard/BoldWAInputFormUnit.pas +++ b/Source/ObjectSpace/IDE/AttributeWizard/BoldWAInputFormUnit.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldWAInputFormUnit; interface @@ -7,7 +10,7 @@ interface Messages, Classes, Graphics, - Controls, + Controls, Forms, Dialogs, StdCtrls, @@ -111,4 +114,6 @@ procedure TInputForm.FormCloseQuery(Sender: TObject; CanClose := true; end; +initialization + end. diff --git a/Source/ObjectSpace/IDE/AttributeWizard/BoldWAInterfaces.pas b/Source/ObjectSpace/IDE/AttributeWizard/BoldWAInterfaces.pas index 7b41ef7..3df44f1 100644 --- a/Source/ObjectSpace/IDE/AttributeWizard/BoldWAInterfaces.pas +++ b/Source/ObjectSpace/IDE/AttributeWizard/BoldWAInterfaces.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldWAInterfaces; interface @@ -33,7 +36,7 @@ interface procedure setEnableNext(Value: TEnableNextEvent); property SteppedBack: Boolean read GetSteppedBack; property UnitGenerator: IUnitGenerator read getUnitGeneratorIntf write setUnitGeneratorIntf; - property EnableNext: TEnableNextEvent write setEnableNext; //CallBack function + property EnableNext: TEnableNextEvent write setEnableNext; end; IUnitGenerator = interface @@ -42,4 +45,9 @@ interface implementation +uses + BoldRev; + +initialization + end. diff --git a/Source/ObjectSpace/IDE/AttributeWizard/BoldWAMainForm.pas b/Source/ObjectSpace/IDE/AttributeWizard/BoldWAMainForm.pas index 82b07ee..e25a5da 100644 --- a/Source/ObjectSpace/IDE/AttributeWizard/BoldWAMainForm.pas +++ b/Source/ObjectSpace/IDE/AttributeWizard/BoldWAMainForm.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldWAMainForm; interface @@ -139,7 +142,6 @@ procedure TMainForm.FormCreate(Sender: TObject); HelpFile := ATTRIBUTEWIZARDHELPFILE; attrdatamodule := Tattrdatamodule.Create(MainForm); Initialize; - //create input form InputForm := TInputForm.Create(MainForm); end; @@ -184,7 +186,7 @@ function TMainForm.GetWizFormIntf(Selection: TUserSelection): IWizardForm; begin Result := nil; end; - end; //case + end; PreviousSelection := Selection; end; @@ -198,6 +200,6 @@ procedure TMainForm.FormDestroy(Sender: TObject); FreeAndNil(InputForm); end; -end. - +initialization +end. diff --git a/Source/ObjectSpace/IDE/AttributeWizard/BoldWAMethodInfo.pas b/Source/ObjectSpace/IDE/AttributeWizard/BoldWAMethodInfo.pas index 11cc4aa..66007d6 100644 --- a/Source/ObjectSpace/IDE/AttributeWizard/BoldWAMethodInfo.pas +++ b/Source/ObjectSpace/IDE/AttributeWizard/BoldWAMethodInfo.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldWAMethodInfo; interface @@ -132,10 +135,10 @@ procedure TMethodInfo.Assign(amethodType: TMethodType; amethodName, aParams, aRe function TMethodInfo.MethodTypeAsString: string; begin case methodType of - mtProcedure: Result := 'procedure'; // do not localize - mtFunction: Result := 'function'; // do not localize - mtConstructor: Result := 'constructor'; // do not localize - mtDestructor: Result := 'destructor'; // do not localize + mtProcedure: Result := 'procedure'; + mtFunction: Result := 'function'; + mtConstructor: Result := 'constructor'; + mtDestructor: Result := 'destructor'; else Result := ''; end; end; @@ -144,17 +147,17 @@ function TMethodInfo.mDirectivesAsString: string; begin Result := ''; if mdVirtual in mDirectives then - Result := Result + 'virtual; '; // do not localize + Result := Result + 'virtual; '; if mdAbstract in mDirectives then - Result := Result + 'abstract; '; // do not localize + Result := Result + 'abstract; '; if mdDynamic in mDirectives then - Result := Result + 'dynamic; '; // do not localize + Result := Result + 'dynamic; '; if mdOverride in mDirectives then - Result := Result + 'override; '; // do not localize + Result := Result + 'override; '; if mdOverload in mDirectives then - Result := Result + 'overload; '; // do not localize + Result := Result + 'overload; '; if mdReintroduce in mDirectives then - Result := Result + 'reintroduce; '; // do not localize + Result := Result + 'reintroduce; '; end; function TMethodInfo.IsOverriden: Boolean; @@ -164,13 +167,13 @@ function TMethodInfo.IsOverriden: Boolean; class function TMethodInfo.StrToMethodType(str: string): TMethodType; begin - if (UpperCase(str) = UpperCase('procedure'))then // do not localize + if (UpperCase(str) = UpperCase('procedure'))then Result := mtProcedure - else if (UpperCase(str) = UpperCase('function')) then // do not localize + else if (UpperCase(str) = UpperCase('function')) then Result := mtFunction - else if (UpperCase(str) = UpperCase('constructor')) then // do not localize + else if (UpperCase(str) = UpperCase('constructor')) then Result := mtConstructor - else if (UpperCase(str) = UpperCase('destructor')) then // do not localize + else if (UpperCase(str) = UpperCase('destructor')) then Result := mtDestructor else Result := mtNone; @@ -179,23 +182,23 @@ class function TMethodInfo.StrToMethodType(str: string): TMethodType; class function TMethodInfo.TVisibilityToStr(v: TVisibility): string; begin case v of - stPublic: Result := 'public'; // do not localize - stPrivate: Result := 'private'; // do not localize - stPublished: Result := 'published'; // do not localize - stProtected: Result := 'protected'; // do not localize + stPublic: Result := 'public'; + stPrivate: Result := 'private'; + stPublished: Result := 'published'; + stProtected: Result := 'protected'; else raise Exception.Create('Error: Visiblity of method not specified'); end; end; class function TMethodInfo.StrToVisibility(v: string): TVisibility; begin - if (Trim(v) = 'private') then // do not localize + if (Trim(v) = 'private') then Result := stprivate - else if (Trim(v) = 'protected') then // do not localize + else if (Trim(v) = 'protected') then Result := stprotected - else if (Trim(v) = 'public') then // do not localize + else if (Trim(v) = 'public') then Result := stpublic - else if (Trim(v) = 'published') then // do not localize + else if (Trim(v) = 'published') then Result := stpublished else raise Exception.Create('TVisibility: Error converting string'); end; @@ -287,5 +290,5 @@ procedure TMethodInfoList.Clear; initialization finalization - FreeAndNil(G_VirtualMethods); + FreeAndNil(G_VirtualMethods); end. diff --git a/Source/ObjectSpace/IDE/AttributeWizard/BoldWAStringGridManager.pas b/Source/ObjectSpace/IDE/AttributeWizard/BoldWAStringGridManager.pas index 741cc07..577eb1f 100644 --- a/Source/ObjectSpace/IDE/AttributeWizard/BoldWAStringGridManager.pas +++ b/Source/ObjectSpace/IDE/AttributeWizard/BoldWAStringGridManager.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldWAStringGridManager; interface @@ -55,7 +58,7 @@ destructor TGridColumnControl.Destroy; Control := nil; ControlClass := nil; AssociatedColumn := 0; - inherited Destroy; + inherited destroy; end; constructor TStringGridManager.Create(aStringGrid: TStringGrid); @@ -156,12 +159,11 @@ procedure TStringGridManager.EditCell(var StringGrid: TStringGrid; ACol, ARow: I if (Ctrl is TComboBox) then with (Ctrl as TComboBox) do begin - // disable the combo box's ChangeEvent ChangeEvent := OnChange; OnChange := nil; - if (IsEmptyStr(fStringGrid.Cells[ACol, ARow]) and (CompareText(Ctrl.Name, 'cbAccessTypes') = 0)) // do not localize + if (IsEmptyStr(fStringGrid.Cells[ACol, ARow]) and (CompareText(Ctrl.Name, 'cbAccessTypes') = 0)) then - ItemIndex := 0 // set a default value + ItemIndex := 0 else ItemIndex := Items.IndexOf(fStringGrid.Cells[ACol, ARow]); SetFocus; @@ -201,10 +203,10 @@ procedure TStringGridManager.ControlOnExit(Sender: TObject); procedure TStringGridManager.GetCtrlSelection(Ctrl: TWinControl; Hide: Boolean); begin - if (Ctrl is TComboBox) then //if control is a TComboBox + if (Ctrl is TComboBox) then with (Ctrl as TComboBox) do begin - if ((ItemIndex = -1) and not IsEmptyStr(Text)) then //Get the edited text and display in the grid + if ((ItemIndex = -1) and not IsEmptyStr(Text)) then fStringGrid.Cells[fStringGrid.Selection.right, fStringGrid.Selection.top] := Text else fStringGrid.Cells[fStringGrid.Selection.right, fStringGrid.Selection.top] := Items[ItemIndex]; @@ -226,7 +228,6 @@ procedure TStringGridManager.Add; Break; end; AppendRow(fStringGrid); - // select the first column of the inserted row SelectCell(fStringGrid, 0, fStringGrid.RowCount - 1); Edit; end; @@ -285,4 +286,6 @@ procedure TStringGridManager.Edit; end; end; +initialization + end. diff --git a/Source/ObjectSpace/IDE/AttributeWizard/BoldWASubClassForm1.pas b/Source/ObjectSpace/IDE/AttributeWizard/BoldWASubClassForm1.pas index 7da4ab5..7351eda 100644 --- a/Source/ObjectSpace/IDE/AttributeWizard/BoldWASubClassForm1.pas +++ b/Source/ObjectSpace/IDE/AttributeWizard/BoldWASubClassForm1.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldWASubClassForm1; interface @@ -61,7 +64,7 @@ TSubClassForm1 = class(TForm, IWizardForm) procedure EnableNextBtn(const Enable: Boolean); public { Public declarations } - constructor Create(AOwner: TComponent); override; + constructor create(AOwner: TComponent); override; procedure AssignParent(aParent: TWinControl); procedure ClearParent; procedure Initialize; @@ -75,7 +78,7 @@ TSubClassForm1 = class(TForm, IWizardForm) property MethodCount: Integer read getMethodCount; property UnitGenerator: IUnitGenerator read getUnitGeneratorIntf write setUnitGeneratorIntf; property SteppedBack: Boolean read GetSteppedBack default false; - property EnableNext: TEnableNextEvent write setEnableNext; //CallBack function + property EnableNext: TEnableNextEvent write setEnableNext; end; var @@ -109,11 +112,9 @@ procedure TSubClassForm1.Initialize; Align := alClient; fBoldClassParser := TClassParser.Create(TStringStream.Create(MemoBoldClasses.Lines.Text)); fBoldClassParser.Start; - // display class names in combo box i:= 0; while fBoldClassParser.getClasses(Item, i) do if Assigned(Item) then cbParent.Items.Add(Item.DelphiName); - //set proper view PageControl1.ActivePage := tsClassDef; end; @@ -169,7 +170,6 @@ procedure TSubClassForm1.cbParentChange(Sender: TObject); Item: TMethodInfo; ListItem: TListItem; begin - // display class methods in CheckListBox EnableNextBtn(IsValidClassDef); ClassName := cbParent.Text; if IsEmptyStr(Trim(ClassName)) then Exit; @@ -214,7 +214,6 @@ function TSubClassForm1.Next: integer; if PageControl1.ActivePage = tsClassDef then begin Result := wfaNext; - //check the class definition if IsValidClassDef then begin PageControl1.ActivePage := tsOverride; @@ -236,17 +235,15 @@ procedure TSubClassForm1.Finish; NewAttribute := TCustomAttribute.Create; try getNewAttribute(NewAttribute); - // set template variables with attrdatamodule.SubClassedAttrTemplate do begin - Variables.Add('UNITNAME', NewAttribute.UnitName, []); // do not localize - Variables.Add('EXPRESSIONNAME', NewAttribute.ExpressionName, []); // do not localize - Variables.Add('DELPHINAME', NewAttribute.DelphiName, []); // do not localize - Variables.Add('SUPERCLASS', NewAttribute.Parent, []); // do not localize - Variables.Add('METHODCOUNT', InttoStr(NewAttribute.Methods.Count), []); // do not localize + Variables.Add('UNITNAME', NewAttribute.UnitName, []); + Variables.Add('EXPRESSIONNAME', NewAttribute.ExpressionName, []); + Variables.Add('DELPHINAME', NewAttribute.DelphiName, []); + Variables.Add('SUPERCLASS', NewAttribute.Parent, []); + Variables.Add('METHODCOUNT', InttoStr(NewAttribute.Methods.Count), []); end; NewAttribute.AssignMethodsToTemplate(attrdatamodule.SubClassedAttrTemplate); - // generate code UnitGenerator.GenerateUnit(NewAttribute.UnitName, attrdatamodule.SubClassedAttrTemplate); finally FreeAndNil(NewAttribute); @@ -288,13 +285,11 @@ procedure TSubClassForm1.GetNewAttribute(var NewAttribute: TCustomAttribute); begin with NewAttribute do begin - //get class definition ExpressionName := Trim(edExpressionName.Text); UnitName := trim(edUnitname.Text); DelphiName := Trim(edDelphiName.Text); Parent := Trim(cbParent.Text); Methods.Clear; - // get override methods CurrentClass := fBoldClassParser.getClassbyName(Parent); for i:= 0 to ListViewOverride.Items.Count - 1 do if ListViewOverride.Items[i].Checked then @@ -307,8 +302,8 @@ procedure TSubClassForm1.GetNewAttribute(var NewAttribute: TCustomAttribute); NewMethod.Visibility := CurrentClass.Methods[i].Visibility ; NewMethod.mDirectives := [mdOverride]; Methods.Add(NewMethod); - end; //if checked - end; //with + end; + end; end; procedure TSubClassForm1.edDelphiNameChange(Sender: TObject); @@ -328,4 +323,6 @@ procedure TSubClassForm1.edUnitnameChange(Sender: TObject); fUnitName_Locked := (Trim(edExpressionName.text) = Trim(edUnitName.Text)); end; +initialization + end. diff --git a/Source/ObjectSpace/IDE/AttributeWizard/BoldWAValueSetDlg.pas b/Source/ObjectSpace/IDE/AttributeWizard/BoldWAValueSetDlg.pas index a990d3a..7f2fad6 100644 --- a/Source/ObjectSpace/IDE/AttributeWizard/BoldWAValueSetDlg.pas +++ b/Source/ObjectSpace/IDE/AttributeWizard/BoldWAValueSetDlg.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldWAValueSetDlg; interface @@ -54,7 +57,6 @@ implementation function TValueSetDlg.IsValidInput: Boolean; begin - //validate input Result := not((IsEmptyStr(Trim(edValueName.Text)) or IsEmptyStr(Trim(Memo1.Lines.Text)))) end; @@ -122,7 +124,6 @@ function TValueSetDlg.Edit(const Old_Name, Old_Reps: string;var New_Name, New_Re ShowModal; Result := (fOk); New_Name := Trim(edValueName.Text); - // get rid of empty lines tempList := TStringList.Create(); for i:= 0 to Memo1.Lines.Count - 1 do if (length(Memo1.Lines[i]) <> 0) then @@ -147,4 +148,6 @@ procedure TValueSetDlg.FormCreate(Sender: TObject); fOk := false; end; +initialization + end. diff --git a/Source/ObjectSpace/IDE/AttributeWizard/BoldWAValueSetForm1.pas b/Source/ObjectSpace/IDE/AttributeWizard/BoldWAValueSetForm1.pas index d3b4e15..23a8afb 100644 --- a/Source/ObjectSpace/IDE/AttributeWizard/BoldWAValueSetForm1.pas +++ b/Source/ObjectSpace/IDE/AttributeWizard/BoldWAValueSetForm1.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldWAValueSetForm1; interface @@ -74,7 +77,7 @@ TValueSetForm1 = class(TForm, IWizardForm) procedure edDelphiNameChange(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure edUnitNameChange(Sender: TObject); - procedure tsValuesShow(Sender: TObject); // init template and generate unit + procedure tsValuesShow(Sender: TObject); private { Private declarations } fStage: TStageType; @@ -89,7 +92,7 @@ TValueSetForm1 = class(TForm, IWizardForm) public { Public declarations } constructor Create(AOwner: TComponent); override; - procedure AssignParent(aParent: TWinControl); + procedure AssignParent(aParent: TWinControl); procedure ClearParent; procedure Initialize; function Next: integer; @@ -101,7 +104,7 @@ TValueSetForm1 = class(TForm, IWizardForm) property Stage: TStageType read fStage; property SteppedBack: Boolean read GetSteppedBack default false ; property UnitGenerator: IUnitGenerator read getUnitGeneratorIntf write setUnitGeneratorIntf; - property EnableNext: TEnableNextEvent write setEnableNext; //CallBack function + property EnableNext: TEnableNextEvent write setEnableNext; end; var @@ -121,9 +124,9 @@ implementation function BooleanToStr(value: Boolean): string; begin if value then - Result := 'true' // do not localize + Result := 'true' else - Result := 'false'; // do not localize + Result := 'false'; end; constructor TValueSetForm1.Create(AOwner: TComponent); @@ -188,7 +191,6 @@ procedure TValueSetForm1.DeleteValue; item: TListItem; index: integer; begin - //delete selected item if Assigned(ListViewValues.Selected) and (ListViewValues.Items.Count <> 0) then begin item := ListViewValues.Selected; @@ -261,7 +263,6 @@ function TValueSetForm1.Next: integer; if PageControl1.ActivePage = tsClassDef then begin Result := wfaNext; - // check input if IsValidClassDef then begin PageControl1.ActivePage := tsValues; @@ -287,40 +288,35 @@ procedure TValueSetForm1.Finish; i, j, NumberOfValues: Integer; Values: TStringList; begin - // get class definition ExpressionName := Trim(edExpressionName.Text); UnitName := Trim(edUnitName.Text) ; DelphiName := Trim(edDelphiName.Text); ValuePrefix := Trim(edValuePrefix.Text); NumberOfValues := ListViewValues.Items.Count; - // set template variables with attrdatamodule.ValueSetTemplate do begin - Variables.Add('UNITNAME', UnitName, []); // do not localize - Variables.Add('EXPRESSIONNAME', ExpressionName, []); // do not localize - Variables.Add('DELPHINAME', DelphiName, []); // do not localize -// Variables.Add('VALUEPREFIX', ValuePrefix, []); // do not localize - Variables.Add('VALUECOUNT', InttoStr(NumberOfValues), []); // do not localize - // get the values + Variables.Add('UNITNAME', UnitName, []); + Variables.Add('EXPRESSIONNAME', ExpressionName, []); + Variables.Add('DELPHINAME', DelphiName, []); + Variables.Add('VALUECOUNT', InttoStr(NumberOfValues), []); Values := TStringList.Create; try - Variables.Add('VALUES', BooleanToStr(ListViewValues.Items.Count > 0), []); // do not localize + Variables.Add('VALUES', BooleanToStr(ListViewValues.Items.Count > 0), []); for i:= 0 to ListViewValues.Items.Count - 1 do begin Values.CommaText := ListViewValues.Items[i].SubItems[0]; - Variables.Add(format('VALUENAME.%d',[i]), ListViewValues.Items[i].Caption, []); // do not localize - Variables.Add(format('VALUEREPRESENTATIONCOUNT.%d',[i]), IntToStr(Values.Count), []); // do not localize + Variables.Add(format('VALUENAME.%d',[i]), ListViewValues.Items[i].Caption, []); + Variables.Add(format('VALUEREPRESENTATIONCOUNT.%d',[i]), IntToStr(Values.Count), []); for j:= 0 to Values.Count - 1 do begin Rep := PChar(Values[j]); - Variables.Add(format('VALUEREPRESENTATION.%d.%d',[i,j]), AnsiExtractQuotedStr(Rep, ''''), []); // do not localize + Variables.Add(format('VALUEREPRESENTATION.%d.%d',[i,j]), AnsiExtractQuotedStr(Rep, ''''), []); end; end; finally FreeAndNil(Values); end; end; - // generate code UnitGenerator.GenerateUnit(UnitName, attrdatamodule.ValueSetTemplate); end; @@ -361,7 +357,6 @@ procedure TValueSetForm1.Initialize; begin Align := alClient; self.TabOrder := 0; - //set the proper view PageControl1.ActivePage := tsClassDef; end; @@ -385,7 +380,7 @@ procedure TValueSetForm1.ActionInsertExecute(Sender: TObject); begin fEditMode := emInsert; InsertValue; - EnableNextBtn(ListViewValues.Items.Count > 0); + EnableNextBtn(ListViewValues.Items.Count > 0); end; procedure TValueSetForm1.ActionDeleteExecute(Sender: TObject); @@ -447,7 +442,9 @@ procedure TValueSetForm1.edUnitNameChange(Sender: TObject); procedure TValueSetForm1.tsValuesShow(Sender: TObject); begin bbInsert.SetFocus; - tsValues.Parent.HelpContext := tsValues.HelpContext; + tsValues.Parent.HelpContext := tsValues.HelpContext; end; +initialization + end. diff --git a/Source/ObjectSpace/IDE/AttributeWizard/BoldWAdatamodule.pas b/Source/ObjectSpace/IDE/AttributeWizard/BoldWAdatamodule.pas index af91ccc..91baffd 100644 --- a/Source/ObjectSpace/IDE/AttributeWizard/BoldWAdatamodule.pas +++ b/Source/ObjectSpace/IDE/AttributeWizard/BoldWAdatamodule.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldWAdatamodule; interface @@ -28,6 +31,12 @@ TdmAttributeWizard = class(TDataModule) implementation +uses + SysUtils, + BoldUtils; + {$R *.dfm} +initialization + end. diff --git a/Source/ObjectSpace/IDE/AttributeWizard/BoldWAdmTemplates.pas b/Source/ObjectSpace/IDE/AttributeWizard/BoldWAdmTemplates.pas index e850aa2..d5a2dd0 100644 --- a/Source/ObjectSpace/IDE/AttributeWizard/BoldWAdmTemplates.pas +++ b/Source/ObjectSpace/IDE/AttributeWizard/BoldWAdmTemplates.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldWAdmTemplates; interface diff --git a/Source/ObjectSpace/IDE/AttributeWizard/BoldWCodeInformer.pas b/Source/ObjectSpace/IDE/AttributeWizard/BoldWCodeInformer.pas index fe7fd4a..6346c2a 100644 --- a/Source/ObjectSpace/IDE/AttributeWizard/BoldWCodeInformer.pas +++ b/Source/ObjectSpace/IDE/AttributeWizard/BoldWCodeInformer.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldWCodeInformer; interface @@ -110,13 +113,13 @@ function TClassParser.getMethodbyTreeIndex(MethodIndex: integer): TMethodInfo; function TClassParser.IsProcedure(Scanner: TScanner): Boolean; begin Result := True; - if Scanner.IsIdentifier('procedure') then // do not localize + if Scanner.IsIdentifier('procedure') then fMethodType := mtProcedure - else if Scanner.IsIdentifier('function') then // do not localize + else if Scanner.IsIdentifier('function') then fMethodType := mtFunction - else if Scanner.IsIdentifier('constructor') then // do not localize + else if Scanner.IsIdentifier('constructor') then fMethodType := mtConstructor - else if Scanner.IsIdentifier('destructor') then // do not localize + else if Scanner.IsIdentifier('destructor') then fMethodType := mtDestructor else Result := false; @@ -137,7 +140,6 @@ procedure TClassParser.ScannerToken(Sender: TObject); procedure AddMethod; begin - //Add Method with Sender as TScanner do begin if Trim(fParam) = COLUMN then fParam := ''; @@ -151,20 +153,20 @@ procedure TClassParser.ScannerToken(Sender: TObject); fCurrentClass.addMethod(TMethodInfo.Create(fMethodType,fProcName, fParam, fReturnType, fVisibility, Pointer(fCurrentClass))) ; fCodeType := ctNone; end - end; + end; end; begin with Sender as TScanner do begin str := token; - if IsIdentifier('implementation') then // do not localize + if IsIdentifier('implementation') then begin fInImplementation := true; fInInterface := false; fCodeType := ctNone; end - else if IsIdentifier('interface') then // do not localize + else if IsIdentifier('interface') then begin fInImplementation := false; fInInterface := true; @@ -172,15 +174,15 @@ procedure TClassParser.ScannerToken(Sender: TObject); end else if fInInterface then begin - if IsIdentifier('public') then // do not localize + if IsIdentifier('public') then fVisibility := stPublic - else if IsIdentifier('protected') then // do not localize + else if IsIdentifier('protected') then fVisibility := stProtected - else if IsIdentifier('published') then // do not localize + else if IsIdentifier('published') then fVisibility := stPublished - else if IsIdentifier('private') then // do not localize + else if IsIdentifier('private') then fVisibility := stPrivate - else if IsIdentifier('end') then // do not localize + else if IsIdentifier('end') then fCodeType := ctIdentifier else if {NewLine and }IsProcedure(TScanner(Sender)) then begin @@ -223,15 +225,14 @@ procedure TClassParser.ScannerToken(Sender: TObject); end else if (fCodeType = ctReturnType) then AddMethod - else if (fCodeType = ctClass) and IsIdentifier('of') then // do not localize + else if (fCodeType = ctClass) and IsIdentifier('of') then fCodeType := ctNone else if (fCodeType = ctIdentifier) and (TokenType = '=') then fCodeType := ctEqual - else if (fCodeType = ctEqual) and IsIdentifier('class') then // do not localize + else if (fCodeType = ctEqual) and IsIdentifier('class') then fCodeType := ctClass else if (fCodeType = ctClass) and (TokenType <> ';') then begin - //Add Class fClasses.Add(TClassInfo.Create(fClassToken)); fCodeType := ctNone; end @@ -260,4 +261,6 @@ procedure TClassParser.Start; end; end; +initialization + end. diff --git a/Source/ObjectSpace/IDE/AttributeWizard/BoldWProjectWizard.pas b/Source/ObjectSpace/IDE/AttributeWizard/BoldWProjectWizard.pas index 56363a2..64d9776 100644 --- a/Source/ObjectSpace/IDE/AttributeWizard/BoldWProjectWizard.pas +++ b/Source/ObjectSpace/IDE/AttributeWizard/BoldWProjectWizard.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldWProjectWizard; interface @@ -71,7 +74,6 @@ function TProjectWizard.GetCurrentProject(var Project: IOTAProject): Boolean; Result := false; Project := nil; ModuleServices := (BorlandIDEServices as IOTAModuleServices); - // get the current module CurrentModule:= ModuleServices.CurrentModule; if Assigned(CurrentModule) then begin @@ -80,17 +82,16 @@ function TProjectWizard.GetCurrentProject(var Project: IOTAProject): Boolean; Project := CurrentModule as IOTAProject; Result := true; end; - // go one level up to owners if not Result then - if (CurrentModule.OwnerCount > 0) then + if (CurrentModule.GetOwnerCount > 0) then for i:= 0 to CurrentModule.OwnerCount - 1 do - if (CurrentModule.Owners[i].QueryInterface(IOTAProject, Project) = S_OK) then + if (CurrentModule.GetOwner(i).QueryInterface(IOTAProject, Project) = S_OK) then begin - Project := CurrentModule.Owners[i] as IOTAProject; + Project := CurrentModule.GetOwner(i) as IOTAProject; Result := true; Break; - end; //if - // find a project amongst the open modules + end; + if not Result then if (ModuleServices.ModuleCount > 0) then for i:=0 to ModuleServices.GetModuleCount - 1 do @@ -100,20 +101,17 @@ function TProjectWizard.GetCurrentProject(var Project: IOTAProject): Boolean; Result := true; Break; end; - end; //if + end; end; procedure TProjectWizard.CreateModule; begin end; -//procedure TProjectWizard.GetcomponentProps(Props: TListBox); -//begin -//end; -//function TProjectWizard.GetAttributes: TStringList; -//begin -//end; + + + {TOTAProject} @@ -130,14 +128,12 @@ function TOTAProject.GetModuleCount: Integer; procedure TOTAProject.AddFile(const AFileName: string; IsUnitOrForm: Boolean); begin - //!!Delphi4 -// IProject.AddFile(AFileName, IsUnitOrForm); + end; procedure TOTAProject.RemoveFile(const AFileName: string); begin - //!!Delphi4 -// IProject.RemoveFile(AFileName); + end; function TOTAProject.GetModule(Index: Integer): IOTAModuleInfo; @@ -147,8 +143,7 @@ function TOTAProject.GetModule(Index: Integer): IOTAModuleInfo; function TOTAProject.CloseModule(ForceClosed: Boolean): Boolean; begin - //!!Delphi4 -// Result := IProject.CloseModule(ForceClosed); + Result := false; end; @@ -183,8 +178,8 @@ function TOTAProject.IsForm(Index: Integer): Boolean; begin ModuleInfo := IProject.GetModule(Index); Result := false; -/// Result := (ModuleInfo.GetModuleType = 0); end; -end. +initialization +end. diff --git a/Source/ObjectSpace/IDE/AttributeWizard/BoldWScanner.pas b/Source/ObjectSpace/IDE/AttributeWizard/BoldWScanner.pas index 885e3a5..d34efbb 100644 --- a/Source/ObjectSpace/IDE/AttributeWizard/BoldWScanner.pas +++ b/Source/ObjectSpace/IDE/AttributeWizard/BoldWScanner.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldWScanner; interface @@ -125,7 +128,7 @@ procedure TScanner.SkipComment(CommentType: Char); ; '/': begin - while GetChar(Ch) and not (Ch in [BOLDLF, BOLDCR]) do + while GetChar(Ch) and not CharInSet(Ch, [BOLDLF, BOLDCR]) do ; Dec(fBufptr); end; @@ -207,7 +210,7 @@ procedure TScanner.GetString(Delim: Char); while GetChar(Ch) do begin fToken := fToken + Ch; - if Ch in [BOLDLF, BOLDCR] then + if CharInSet(Ch, [BOLDLF, BOLDCR]) then begin Dec(fBufPtr); Exit; @@ -236,7 +239,7 @@ procedure TScanner.GetIdentifier(FirstChar: Char); fTokenType := ttIdentifier; while GetChar(Ch) do begin - if not (Ch in ['a'..'z', 'A'..'Z', '0'..'9', '_', '.']) then + if not CharInSet(Ch, ['a'..'z', 'A'..'Z', '0'..'9', '_', '.']) then begin { put it back} Dec(fBufPtr); @@ -290,24 +293,24 @@ procedure TScanner.GetNumber(FirstChar: Char); begin fToken := FirstChar; fTokenType := ttInteger; - while GetChar(Ch) and (Ch in ['0'..'9']) do + while GetChar(Ch) and CharInSet(Ch, ['0'..'9']) do fToken := fToken + Ch; if Ch = '.' then begin fTokenType := ttFloat; fToken := fToken + Ch; - while GetChar(Ch) and (Ch in ['0'..'9']) do + while GetChar(Ch) and CharInSet(Ch, ['0'..'9']) do fToken := fToken + Ch; end; - if Ch in ['e', 'E'] then + if CharInSet(Ch, ['e', 'E']) then begin fTokenType := ttFloat; fToken := fToken + Ch; - if GetChar(Ch) and (Ch in ['+', '-']) then + if GetChar(Ch) and CharInSet(Ch, ['+', '-']) then fToken := fToken + Ch; - while Ch in ['0'..'9'] do + while CharInSet(Ch, ['0'..'9']) do begin fToken := fToken + Ch; if not GetChar(Ch) then @@ -387,4 +390,6 @@ procedure TScanner.Scan(Stream: TStream); end; end; +initialization + end. diff --git a/Source/ObjectSpace/IDE/BoldComponentValidatorIDE.pas b/Source/ObjectSpace/IDE/BoldComponentValidatorIDE.pas index 8589007..b8550df 100644 --- a/Source/ObjectSpace/IDE/BoldComponentValidatorIDE.pas +++ b/Source/ObjectSpace/IDE/BoldComponentValidatorIDE.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldComponentValidatorIDE; interface @@ -18,8 +21,8 @@ TBoldComponentValidatorIDE = class(TBoldComponentValidator) fMenuItemCurrent: TMenuItem; procedure ChangeFocus; public - constructor Create; - destructor Destroy; override; + constructor create; + destructor destroy; override; procedure ValidateIOTAModule(Module: IOTAModule); procedure ValidateFormEditor(FormEditor: IOTAFormEditor); procedure ValidateIOTAModules; @@ -39,8 +42,7 @@ implementation BoldLogHandler, BoldGuard, BoldIDEMenus, - BoldEnvironment, - BoldCoreConsts; + BoldEnvironment; var G_BoldComponentValidatorIDE: TBoldComponentValidatorIDE = nil; @@ -50,15 +52,16 @@ procedure Register; G_BoldComponentValidatorIDE := TBoldComponentValidatorIDE.Create; end; + { TBoldComponentValidatorIDE } constructor TBoldComponentValidatorIDE.create; begin - fMenuItemAll := BoldMenuExpert.AddMenuItem('mnuValidateAllForms', // do not localize - sValidateAllForms, + fMenuItemAll := BoldMenuExpert.AddMenuItem('mnuValidateAllForms', + 'Validate All Forms', ValidateAllMenuAction, True); - fMenuItemCurrent := BoldMenuExpert.AddMenuItem('mnuValidateCurrentForm', // do not localize - sValidateCurrentForm, + fMenuItemCurrent := BoldMenuExpert.AddMenuItem('mnuValidateCurrentForm', + 'Validate Current Form', ValidateCurrentMenuAction, True); end; @@ -92,7 +95,7 @@ procedure TBoldComponentValidatorIDE.ValidateIOTAModule(Module: IOTAModule); Editor := Module.GetModuleFileEditor(i); if Editor.QueryInterface(IOTAFormEditor, FormEditor) = S_OK then begin - BoldLog.LogFmtIndent(sValidatingForm, [FormEditor.FileName]); + BoldLog.LogFmtIndent('Validating form %s', [FormEditor.FileName]); ValidateFormEditor(FormEditor); HasEditor := True; BoldLog.Dedent; @@ -100,10 +103,10 @@ procedure TBoldComponentValidatorIDE.ValidateIOTAModule(Module: IOTAModule); end; except on e: Exception do - BoldLog.LogFmt(sFailedToValidate, [Module.FileName, e.Message]); + BoldLog.LogFmt('Failed to validate %s. %s', [Module.FileName, e.Message]); end; if not HasEditor then - BoldLog.LogFmt(sNothingToValidate, [Module.FileName]); + BoldLog.LogFmt('Nothing to validate in %s', [Module.FileName]); end; procedure TBoldComponentValidatorIDE.ValidateIOTAModules; @@ -117,11 +120,10 @@ procedure TBoldComponentValidatorIDE.ValidateIOTAModules; FileNames: TStringList; Guard: IBoldGuard; begin - // Filenames of open modules are stored and not revalidated later. Guard := TBoldGuard.Create(FileNames); FileNames := TStringList.Create; ModuleServices := (BorlandIDEServices as IOTAModuleServices); - BoldLog.LogIndent(sValidatingAllOpenModules); + BoldLog.LogIndent('Validating all open modules'); BoldLog.ProgressMax := ModuleServices.GetModuleCount; ChangeFocus; for i := 0 to ModuleServices.GetModuleCount - 1 do @@ -133,13 +135,13 @@ procedure TBoldComponentValidatorIDE.ValidateIOTAModules; BoldLog.Dedent; ChangeFocus; - BoldLog.LogIndent(sLookingForDefaultProject); + BoldLog.LogIndent('Starting looking project group with default project'); for i := 0 to ModuleServices.GetModuleCount - 1 do begin if ModuleServices.GetModule(i).QueryInterface(IOTAProjectGroup, ProjectGroup) = S_OK then begin Project := ProjectGroup.ActiveProject; - BoldLog.LogFmt(sDefaultProject, [Project.FileName]); + BoldLog.LogFmt('Default project: %s', [Project.FileName]); Break; end; end; @@ -148,12 +150,12 @@ procedure TBoldComponentValidatorIDE.ValidateIOTAModules; ChangeFocus; if not Assigned(Project) then begin - BoldLog.LogIndent(sLookingForAnyProject); + BoldLog.LogIndent('Starting looking for any project'); for i := 0 to ModuleServices.GetModuleCount - 1 do begin if ModuleServices.GetModule(i).QueryInterface(IOTAProject, Project) = S_OK then begin - BoldLog.LogFmt(sFoundProject, [Project.FileName]); + BoldLog.LogFmt('Found project: %s', [Project.FileName]); Break; end; end; @@ -209,8 +211,6 @@ procedure TBoldComponentValidatorIDE.ValidateIOTAComponent(Component: IOTACompon if assigned(RealComponent) then ValidateComponent(RealComponent, NamePrefix); - //if not ValidateComponent(RealComponent, NamePrefix) then - // fLastFailedComponent := Component; for i := 0 to Component.GetComponentCount - 1 do ValidateIOTAComponent(Component.GetComponent(i), NamePrefix + ComponentName + '.'); @@ -242,7 +242,7 @@ procedure TBoldComponentValidatorIDE.ValidateCurrentMenuAction(Sender: TObject); CompleteLog; end else - raise Exception.Create(sNoValidateableModuleAvailable); + raise Exception.Create('No module available for validation'); end; procedure TBoldComponentValidatorIDE.ChangeFocus; @@ -256,4 +256,3 @@ finalization FreeAndNil(G_BoldComponentValidatorIDE); end. - diff --git a/Source/ObjectSpace/IDE/BoldExternalObjectSpaceEventHandlerReg.pas b/Source/ObjectSpace/IDE/BoldExternalObjectSpaceEventHandlerReg.pas index 006dcc9..7d33105 100644 --- a/Source/ObjectSpace/IDE/BoldExternalObjectSpaceEventHandlerReg.pas +++ b/Source/ObjectSpace/IDE/BoldExternalObjectSpaceEventHandlerReg.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldExternalObjectSpaceEventHandlerReg; interface @@ -36,3 +39,4 @@ procedure Register; end; end. + diff --git a/Source/ObjectSpace/IDE/BoldWSimpleMenuWizard.pas b/Source/ObjectSpace/IDE/BoldWSimpleMenuWizard.pas index 32c7a10..7d89f27 100644 --- a/Source/ObjectSpace/IDE/BoldWSimpleMenuWizard.pas +++ b/Source/ObjectSpace/IDE/BoldWSimpleMenuWizard.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldWSimpleMenuWizard; interface @@ -21,20 +24,20 @@ TSimpleMenuWizard = class(TNotifierObject,IOTAWizard, IOTANotifier) fState: TWizardState; fParentMenuName: string; fMenuItemIndex: integer; - function GetIDString: string; // IOTAWizard + function GetIDString: string; function GetName: string; function GetState: TWizardState; procedure InsertMenuItem(Action: TInsertAction; InsertPosition: Integer; targetName: string; var PopupMenu: TPopUpMenu); function IsInIDE: boolean; protected - procedure Initialize; virtual; //add initialization code here, called in constructor + procedure Initialize; virtual; public constructor Create(const vname, vIDString: string; const vState: TWizardState; const InsertPosition: integer; const vParentMenuName: string); procedure AddMenuItem(var PopupMenu: TPopupMenu); procedure Execute; virtual; - procedure AfterSave; virtual; // IOTANotifier + procedure AfterSave; virtual; procedure BeforeSave; virtual; procedure Modified; virtual; procedure Destroyed; virtual; @@ -117,7 +120,6 @@ procedure TSimpleMenuWizard.InsertMenuItem(Action: TInsertAction; InsertPosition ACaption: string; begin if not IsInIDE then Exit; -// for compatibility with Delphi4 targetItem := nil; ACaption := StripHotkey(targetName); for I := 0 to (BorlandIDEServices as INTAServices).getMainMenu.Items.Count - 1 do @@ -126,29 +128,22 @@ procedure TSimpleMenuWizard.InsertMenuItem(Action: TInsertAction; InsertPosition targetItem := (BorlandIDEServices as INTAServices).getMainMenu.Items[I]; System.Break; end; -// targetItem := (BorlandIDEServices as INTAServices).getMainMenu.Items.Find(targetName); if Assigned(targetItem) then begin - //get the parent item if (Action = iaChild) then begin - //create a child of the target item parentItem := targetItem; end else begin - //get the target's parent parentItem := targetItem.Parent; if (Action = iaAfter) then Inc(InsertPosition); end; - //insert for I := PopupMenu.Items.Count - 1 downto 0 do begin - //remove the item from the popup menu Item := PopupMenu.Items[i]; PopupMenu.Items.Delete(i); - // then add it to delphi's menu if Assigned(parentItem) then begin fMenuItem := Item; @@ -171,32 +166,8 @@ function TSimpleMenuWizard.IsInIDE: boolean; procedure TSimpleMenuWizard.Initialize; begin -// end; -end. - - - - - - - - - - - - - - - - - - - - - - - - +initialization +end. diff --git a/Source/ObjectSpace/Interfaces/BoldUndoInterfaces.pas b/Source/ObjectSpace/Interfaces/BoldUndoInterfaces.pas index 8f798ab..573d1c2 100644 --- a/Source/ObjectSpace/Interfaces/BoldUndoInterfaces.pas +++ b/Source/ObjectSpace/Interfaces/BoldUndoInterfaces.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldUndoInterfaces; interface @@ -11,7 +14,7 @@ interface IBoldUndoList = interface; IBoldUndoHandler = interface; - TBoldUndoState = (busNormal, busUndoing, busRedoing); + TBoldUndoState = (busNormal, busUndoing, busRedoing); IBoldUndoBlock = interface ['{F56612C3-7D33-4D60-9737-71ECE8E54D56}'] @@ -26,45 +29,50 @@ interface IBoldUndoList = interface ['{C4FF7FBB-C14A-4B2D-82C5-BED76B80D81B}'] function GetCount: Integer; - function GetItems(Index: integer): IBoldUndoBlock; - function GetItemsByName(Name: string): IBoldUndoBlock; + function GetItem(Index: integer): IBoldUndoBlock; + function GetItemByName(const Name: string): IBoldUndoBlock; function GetTopBlock: IBoldUndoBlock; - function IndexOf(BlockName: string): integer; + function IndexOf(const BlockName: string): integer; function CanMoveBlock(CurIndex, NewIndex: integer): Boolean; - procedure MergeBlocks(DestinationBlockName, SourceBlockName: string); - procedure MoveToTop(BlockName: string); + procedure MergeBlocks(const DestinationBlockName, SourceBlockName: string); + procedure MoveToTop(const BlockName: string); procedure MoveBlock(CurIndex, NewIndex: integer); - procedure RenameBlock(OldName, NewName: string); - function RemoveBlock(BlockName: string): Boolean; + procedure RenameBlock(const OldName, NewName: string); + function RemoveBlock(const BlockName: string): Boolean; property Count: Integer read GetCount; - property Items[Index: integer]: IBoldUndoBlock read GetItems; default; - property ItemsByName[Name: string]: IBoldUndoBlock read GetItemsByName; + property Items[Index: integer]: IBoldUndoBlock read GetItem; default; + property ItemByName[const Name: string]: IBoldUndoBlock read GetItemByName; property TopBlock: IBoldUndoBlock read GetTopBlock; + function GetContainsChanges: Boolean; + property ContainsChanges: Boolean read GetContainsChanges; end; IBoldUndoHandler = interface ['{FCAC02E0-0067-41F1-B755-C6F162EA40E7}'] function GetUndoList: IBoldUndoList; function GetRedoList: IBoldUndoList; - function GetUniqueBlockName(SuggestedName: string): string; - function CanUndoBlock(BlockName: string): Boolean; - function CanRedoBlock(BlockName: string):Boolean; + function GetUniqueBlockName(const SuggestedName: string): string; + function CanUndoBlock(const BlockName: string): Boolean; + function CanRedoBlock(const BlockName: string):Boolean; function GetEnabled: Boolean; procedure SetEnabled(value: Boolean); procedure UndoLatest; procedure RedoLatest; - procedure UndoBlock(BlockName: string); - procedure RedoBlock(BlockName: string); - procedure SetNamedCheckPoint(CheckPointName: string); + procedure UndoBlock(const BlockName: string); + procedure RedoBlock(const BlockName: string); + procedure SetNamedCheckPoint(const CheckPointName: string); procedure SetCheckPoint; procedure ClearAllUndoBlocks; property UndoList: IBoldUndoList read GetUndoList; property RedoList: IBoldUndoList read GetRedoList; property Enabled: Boolean read GetEnabled write SetEnabled; - // add state here end; implementation +uses + BoldRev; + +initialization end. diff --git a/Source/ObjectSpace/Ocl/BoldORed.pas b/Source/ObjectSpace/Ocl/BoldORed.pas index 11b5087..2ea69ae 100644 --- a/Source/ObjectSpace/Ocl/BoldORed.pas +++ b/Source/ObjectSpace/Ocl/BoldORed.pas @@ -1,6 +1,6 @@ -// as long as the distribution question of sandstone libs is not solved, -// this unit is used as an include file by BoldOCL +{ Global compiler directives } +{$include bold.inc} unit BoldORed; interface @@ -24,6 +24,7 @@ implementation type TBoldOclCollectionType = (tboNoCollection, tboBag, tboSet, tboSequence, tboCollection, tboCopyArg1, tboMinCollection); + {$I BoldOclConstructors.inc} constructor AYaccStackElement.Create; @@ -96,31 +97,31 @@ function AYaccClass.Reduce(TheProduction, TheSize: Longint): SSYaccStackElement; AYaccexpressionAnd: { expression -> expression AND expression } - result := Make2Operation('and', stack(0), stack(2), stack(1).lexeme.offset); // do not localize + result := Make2Operation('and', stack(0), stack(2), stack(1).lexeme.offset); AYaccexpressionOr: { expression -> expression OR expression } - result := Make2Operation('or', stack(0), stack(2), stack(1).lexeme.offset); // do not localize + result := Make2Operation('or', stack(0), stack(2), stack(1).lexeme.offset); AYaccexpressionXor: { expression -> expression XOR expression } - result := Make2Operation('xor', stack(0), stack(2), stack(1).lexeme.offset); // do not localize + result := Make2Operation('xor', stack(0), stack(2), stack(1).lexeme.offset); AYaccexpressionImp: { expression -> expression IMPLIES expression } - result := Make2Operation('implies', stack(0), stack(2), stack(1).lexeme.offset); // do not localize + result := Make2Operation('implies', stack(0), stack(2), stack(1).lexeme.offset); AYaccexpressionEQ: { expression -> expression = expression } - result := Make2Operation('=', stack(0), stack(2), stack(1).lexeme.offset); // do not localize + result := Make2Operation('=', stack(0), stack(2), stack(1).lexeme.offset); AYaccexpressionLT: { expression -> expression < expression } - result := Make2Operation('<', stack(0), stack(2), stack(1).lexeme.offset); // do not localize + result := Make2Operation('<', stack(0), stack(2), stack(1).lexeme.offset); AYaccexpressionGT: { expression -> expression > expression } - result := Make2Operation('>', stack(0), stack(2), stack(1).lexeme.offset); // do not localize + result := Make2Operation('>', stack(0), stack(2), stack(1).lexeme.offset); AYaccexpressionLE: @@ -158,11 +159,11 @@ function AYaccClass.Reduce(TheProduction, TheSize: Longint): SSYaccStackElement; AYaccexpressionNOT: { expression -> NOT expression } - result := Make1Operation('not', stack(1), stack(0).lexeme.offset); // do not localize + result := Make1Operation('not', stack(1), stack(0).lexeme.offset); AYaccifExpression: { ifExpression -> if expression then expression else expression endif } - result := Make3Operation('if', stack(1), stack(3), stack(5), stack(0).lexeme.offset); // do not localize + result := Make3Operation('if', stack(1), stack(3), stack(5), stack(0).lexeme.offset); AYaccpostFixFirst: { postFixExpression -> primaryExpression } @@ -318,7 +319,6 @@ function AYaccClass.Reduce(TheProduction, TheSize: Longint): SSYaccStackElement; AYacccollectionKind_Collection: { collectionKind -> Collection } -// Result := MakeCollectionKind(tboCollection, stack(0).lexeme.offset); raise EBoldOCLAbort.CreateFmt(boeCollectionNotValidLiteral, [stack(0).lexeme.offset]); @@ -332,11 +332,11 @@ function AYaccClass.Reduce(TheProduction, TheSize: Longint): SSYaccStackElement; AYaccexpressionDivI: { expression -> expression IntDIV expression } - result := Make2Operation('div', stack(0), stack(2), stack(1).lexeme.offset); // do not localize + result := Make2Operation('div', stack(0), stack(2), stack(1).lexeme.offset); AYaccexpressionMod: { expression -> expression MOD expression } - result := Make2Operation('mod', stack(0), stack(2), stack(1).lexeme.offset); // do not localize + result := Make2Operation('mod', stack(0), stack(2), stack(1).lexeme.offset); AYaccfeatureCallParameters1: { featureCallParameters -> (actualParameterList) } @@ -385,4 +385,6 @@ function AYaccClass.Reduce(TheProduction, TheSize: Longint): SSYaccStackElement; end; end; +initialization + end. diff --git a/Source/ObjectSpace/Ocl/BoldOcl.pas b/Source/ObjectSpace/Ocl/BoldOcl.pas index 7b0604b..1a4732e 100644 --- a/Source/ObjectSpace/Ocl/BoldOcl.pas +++ b/Source/ObjectSpace/Ocl/BoldOcl.pas @@ -1,19 +1,27 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldOcl; interface uses Classes, + vcl.ExtCtrls, BoldBase, BoldSystemRT, BoldOclClasses, BoldElements, BoldSystem, + BoldAttributes, BoldIndexableList, BoldLogHandler, BoldOclRTDebug, BoldSubscription; +var + _BoldOCLPSEvaluationConditionBlockSize: Integer = -1; + type { forward declaration } TBoldOclEntry = class; @@ -32,6 +40,9 @@ TBoldOclEntry = class(TBoldMemoryManagedObject) OwnedByDictionary: Boolean; Ocl: TBoldOclNode; UsedByOtherEvaluation: Boolean; + Evaluations: Integer; + AccumulatedTicks: Int64; + LastWarnedTicks: Int64; constructor Create(const Str: string; OclNode: TBoldOclNode); destructor Destroy; override; end; @@ -39,7 +50,8 @@ TBoldOclEntry = class(TBoldMemoryManagedObject) { TBoldOClDictionary } TBoldOClDictionary = class(TBoldIndexableList) private - function GetOcl(const Expr: string): TBoldOclEntry; + class var IX_OCLEntry: integer; + function GetOcl(const Expr: string): TBoldOclEntry; {$IFDEF BOLD_INLINE} inline; {$ENDIF} public constructor Create; procedure AddOcl(ENTRY: TBoldOclEntry); @@ -49,6 +61,7 @@ TBoldOClDictionary = class(TBoldIndexableList) { TBoldOcl } TBoldOcl = class(TBoldRTEvaluator) private + fMaxMemberNameArray: array of Integer; fOclDictionary: TBoldOClDictionary; fSymbolTable: TBoldSymbolDictionary; fSystemTypeInfo: TBoldSystemTypeInfo; @@ -60,23 +73,60 @@ TBoldOcl = class(TBoldRTEvaluator) fBooleanType: TBoldAttributeTypeInfo; fDateType: TBoldAttributeTypeInfo; fTimeType: TBoldAttributeTypeInfo; + fDateTimeType: TBoldAttributeTypeInfo; + fTrueBool: TBABoolean; fCanEvaluate: Boolean; fOnLookUpOclDefinition: TBoldLookUpOclDefinition; - function SyntacticParse(const Ocl: string; StoreInDictionary: Boolean; var ResultEntry: TBoldOclEntry; Context: TBoldElementTypeInfo): TBoldIndirectElement; - function SemanticCheck(Ocl: string; Context: TBoldElementTypeInfo; StoreInDictionary: Boolean; var ResultEntry: TBoldOclEntry; Env: TBoldOclEnvironment): TBoldIndirectElement; + fTodayVar: TBADate; + fNowVar: TBADateTime; + fTodayTimer, fNowTimer: TTimer; + fParses: Integer; + fDictionaryHits: Integer; + fExpresionTypeCount: Integer; + fExpressionTypeTicks: Int64; + fEvaluationCount: Integer; + fEvaluationTicks: Int64; + procedure CalculateMaxMemberNameLength; + function SyntacticParse(const Ocl: string; StoreInDictionary: Boolean; Context: TBoldElementTypeInfo): TBoldOclEntry; function LookupOclDefinition(const name: string):string; procedure PSEvaluation(const Expr: string; Root: TBoldElement; ResultEntry: TBoldOclEntry; Env: TBoldOclEnvironment); procedure AddVarsToEnv(Env: TBoldOCLEnvironment; const VariableList: TBoldExternalVariableList; Initializevalues: Boolean); + function GetGlobalEnv: TBoldOclEnvironment; + procedure TodayTimerEvent(Sender: TObject); + procedure NowTimerEvent(Sender: TObject); + protected + function GetVariableCount: integer; override; + function GetVariable(index: integer): TBoldIndirectElement; override; + function GetVariableByName(const aName: string): TBoldIndirectElement; override; public constructor Create(SystemTypeInfo: TBoldSystemTypeInfo; BoldSystem: TBoldSystem); destructor Destroy; override; + property GlobalEnv: TBoldOclEnvironment read GetGlobalEnv; property SymbolTable: TBoldSymbolDictionary read fsymbolTable; property BoldSystem: TBoldSystem read fBoldSystem; - procedure DefineVariable(const VariableName: String; VarValue: TBoldElement; VariableType: TBoldElementTypeInfo; OwnValue: Boolean); override; - procedure Evaluate(Ocl: string; Root: TBoldElement; Subscriber: TBoldSubscriber; ResubscribeAll: Boolean; resultElement: TBoldIndirectElement; EvaluateInPS: Boolean = false; const VariableList: TBoldExternalVariableList = nil); override; + property Parses: Integer read fParses; + property ExpresionTypeCount: Integer read fExpresionTypeCount; + property ExpressionTypeTicks: Int64 read fExpressionTypeTicks; + property EvaluationCount: Integer read fEvaluationCount; + property EvaluationTicks: Int64 read fEvaluationTicks; + property DictionaryHits: Integer read fDictionaryHits; + function SemanticCheck(Ocl: string; Context: TBoldElementTypeInfo; const VariableList: TBoldExternalVariableList = nil; StoreInDictionary: Boolean = true; Env: TBoldOclEnvironment = nil): TBoldOclEntry; + procedure DoneWithEntry(var oclEntry: TBoldOclEntry); + procedure DefineVariable(const VariableName: String; VarValue: TBoldElement; + VariableType: TBoldElementTypeInfo; OwnValue, IsConstant: Boolean); override; + procedure DefineVariable(const VariableName: string; Variable: TBoldExternalVariable ); override; + procedure UndefineVariable(Variable: TBoldExternalVariable); override; + procedure Evaluate(Ocl: string; Root: TBoldElement; Subscriber: TBoldSubscriber = nil; ResubscribeAll: Boolean = false; resultElement: TBoldIndirectElement = nil; EvaluateInPS: Boolean = false; const VariableList: TBoldExternalVariableList = nil); override; function ExpressionType(const Ocl: string; Context: TBoldElementTypeInfo; ReRaise: Boolean; const VariableList: TBoldExternalVariableList = nil): TBoldElementTypeInfo; override; - function RTInfo(const Ocl: string; Context: TBoldElementTypeInfo; ReRaise: Boolean): TBoldMemberRTInfo; override; + function RTInfo(const Ocl: string; Context: TBoldElementTypeInfo; ReRaise: Boolean; const VariableList: TBoldExternalVariableList = nil): TBoldMemberRTInfo; override; procedure SetLookupOclDefinition(value: TBoldLookUpOclDefinition); override; + property StringType: TBoldAttributeTypeInfo read fStringType; + property IntegerType: TBoldAttributeTypeInfo read fIntegerType; + property FloatType: TBoldAttributeTypeInfo read fFloatType; + property BooleanType: TBoldAttributeTypeInfo read fBooleanType; + property DateType: TBoldAttributeTypeInfo read fDateType; + property TimeType: TBoldAttributeTypeInfo read fTimeType; + property DateTimeType: TBoldAttributeTypeInfo read fDateTimeType; end; var @@ -86,51 +136,57 @@ TBoldOcl = class(TBoldRTEvaluator) BoldOCLRTDebugger: TBoldOCLRTDebugger = nil; BoldOclParserTablePath: String = ''; -procedure BoldOCLLog(const s: string); +procedure BoldOCLLog(aRoot: TBoldElement; const s: string; aResult: TBoldIndirectElement); procedure BoldForceNelCompatibility; +{$IFDEF OCLDummyValueBug} +type + TDummyValueDifferentResultEvent = procedure(const Expression: string; Context: TBoldElement; ResultWithDummy, ResultWithoutDummy: TBoldIndirectElement) of object; +var + OnDummyValueDifferentResult: TDummyValueDifferentResultEvent; +{$ENDIF} + implementation uses + // VCL SysUtils, - BoldAttributes, + DateUtils, + Math, + + // Bold + BoldUtils, BoldCondition, BoldDefs, - BoldOclSymbolImplementations, + BoldHashIndexes, BoldOclError, + BoldOclEvaluator, BoldOclLightWeightNodeMaker, BoldOclLightWeightNodes, - BoldOclEvaluator, BoldOclSemantics, + BoldOclSymbolImplementations, + BoldORed, + BoldMath, + BoldSSExcept, BoldSSLexU, BoldSSYaccU, - BoldSSExcept, - BoldORed, - BoldHashIndexes, - BoldCoreConsts; - -{.$R *.res} + BoldGuard; var - IX_OCLEntry: integer = -1; G_OclScannerTable: SSLexTable = nil; G_OclParserTable: SSYaccTable = nil; function OclScannerTable: SSLexTable; begin if not assigned(G_OclScannerTable) then - begin - G_OclScannerTable := SSLexTable.CreateResource(HInstance, 'OCLSCANNERTABLE', 'SCANNERTABLE'); // do not localize - end; + G_OclScannerTable := SSLexTable.Create; result := G_OclScannerTable; end; function OclParserTable: SSYaccTable; begin if not assigned(G_OclParserTable) then - begin - G_OclParserTable := SSYaccTable.CreateResource(HInstance, 'OCLPARSERTABLE', 'PARSERTABLE'); // do not localize - end; + G_OclParserTable := SSYaccTable.Create; result := G_OclParserTable; end; @@ -144,14 +200,35 @@ TOCLIndex = class(TBoldCaseSensitiveStringHashIndex) { TOCLIndex } function TOCLIndex.ItemAsKeyString(Item: TObject): string; begin - Result := TBoldOclEntry(Item).OclString; + with TBoldOclEntry(Item) do + if Assigned(Context) then + Result := Context.ExpressionName + ':' + OclString + else + Result := OclString +end; + +procedure TBoldOcl.CalculateMaxMemberNameLength; +var + i,j: integer; + ClassInfo: TBoldClassTypeInfo; + vLength: integer; +begin + SetLength(fMaxMemberNameArray, fSystemTypeInfo.TopSortedClasses.Count); + for i := 0 to fSystemTypeInfo.TopSortedClasses.Count - 1 do + begin + ClassInfo := fSystemTypeInfo.TopSortedClasses[i]; + vLength := 0; + for j := 0 to ClassInfo.AllMembersCount - 1 do + vLength := Max(vLength, Length(ClassInfo.AllMembers[j].ExpressionName)); + fMaxMemberNameArray[i] := vLength; + end; end; constructor TBoldOcl.Create(SystemTypeInfo: TBoldSystemTypeInfo; BoldSystem: TBoldSystem); var TrueConst: TBABoolean; FalseConst: TBABoolean; - MaxTimeStamp: TBAInteger; // this type must mirror the type of TBoldTimeStampType + MaxTimeStamp: TBAInteger; begin fSystemTypeInfo := SystemTypeInfo; fBoldSystem := BoldSystem; @@ -159,26 +236,43 @@ constructor TBoldOcl.Create(SystemTypeInfo: TBoldSystemTypeInfo; BoldSystem: TBo fCanEvaluate := true; fSymbolTable := TBoldSymbolDictionary.Create(SystemTypeInfo, BoldSystem, fCanEvaluate); InitializeSymbolTable(fSymbolTable); - fStringType := fSystemTYpeInfo.AttributeTypeInfoByExpressionName['String']; // do not localize - fIntegerType := fSystemTYpeInfo.AttributeTypeInfoByExpressionName['Integer']; // do not localize - fFloatType := fSystemTYpeInfo.AttributeTypeInfoByExpressionName['Float']; // do not localize - fBooleanType := fSystemTYpeInfo.AttributeTypeInfoByExpressionName['Boolean']; // do not localize - fTimeType := fSystemTYpeInfo.AttributeTypeInfoByExpressionName['Time']; // do not localize - fDateType := fSystemTYpeInfo.AttributeTypeInfoByExpressionName['Date']; // do not localize - - TrueConst := TBoldMemberFactory.CreateMemberFromBoldType(fBooleanType) as TBABoolean; - trueConst.AsBoolean := true; - DefineVariable('true', TrueConst, fBooleanType, true); // do not localize + fStringType := fSystemTypeInfo.AttributeTypeInfoByExpressionName['String']; + fIntegerType := fSystemTypeInfo.AttributeTypeInfoByExpressionName['Integer']; + fFloatType := fSystemTypeInfo.AttributeTypeInfoByExpressionName['Float']; + fBooleanType := fSystemTypeInfo.AttributeTypeInfoByExpressionName['Boolean']; + fTimeType := fSystemTypeInfo.AttributeTypeInfoByExpressionName['Time']; + fDateType := fSystemTypeInfo.AttributeTypeInfoByExpressionName['Date']; + fDateTimeType := fSystemTypeInfo.AttributeTypeInfoByExpressionName['DateTime']; // do not localize + + fTrueBool := TBoldMemberFactory.CreateMemberFromBoldType(fBooleanType) as TBABoolean; + fTrueBool.AsBoolean := true; + DefineVariable('true', fTrueBool, fBooleanType, True, True); // do not localize FalseConst := TBoldMemberFactory.CreateMemberFromBoldType(fBooleanType) as TBABoolean;; FalseConst.AsBoolean := False; - DefineVariable('false', FalseConst, fBooleanType, true); // do not localize + DefineVariable('false', FalseConst, fBooleanType, True, True); // do not localize + + DefineVariable('nil', nil, SystemTypeInfo.NilTypeInfo, False, True); // do not localize MaxTimeStamp := TBoldMemberFactory.CreateMemberFromBoldType(fIntegerType) as TBAInteger; MaxTimeStamp.AsInteger := BOLDMAXTIMESTAMP; - DefineVariable('timeStampNow', MaxTimeStamp, fIntegerType, true); // do not localize - - DefineVariable('nil', nil, SystemTypeInfo.NilTypeInfo, false); // do not localize + DefineVariable('timeStampNow', MaxTimeStamp, fIntegerType, True, False); // do not localize + + fTodayVar := TBoldMemberFactory.CreateMemberFromBoldType(fDateType) as TBADate; + fTodayTimer := TTimer.Create(nil); + fTodayTimer.OnTimer := TodayTimerEvent; + fTodayTimer.Enabled := True; + TodayTimerEvent(nil); + DefineVariable('today', fTodayVar, fDateType, True, False); // do not localize + + // Now is rounded to full minutes and is only refreshed once per minute + fNowVar := TBoldMemberFactory.CreateMemberFromBoldType(fDateTimeType) as TBADateTime; + fNowTimer := TTimer.Create(nil); + fNowTimer.OnTimer := NowTimerEvent; + fNowTimer.Enabled := True; + NowTimerEvent(nil); + DefineVariable('now', fNowVar, fDateTimeType, True, False); // do not localize + CalculateMaxMemberNameLength; end; destructor TBoldOcl.Destroy; @@ -186,24 +280,30 @@ destructor TBoldOcl.Destroy; FreeAndNil(fOclDictionary); FreeAndNil(fSymbolTable); FreeAndNil(fGlobalEnv); + FreeAndNil(fTodayTimer); + FreeAndNil(fNowTimer); inherited; end; { TBoldOCL } -procedure TBoldOcl.DefineVariable(const VariableName: String; VarValue: TBoldElement; VariableType: TBoldElementTypeInfo; OwnValue: Boolean); +procedure TBoldOcl.DefineVariable(const VariableName: String; VarValue: + TBoldElement; VariableType: TBoldElementTypeInfo; OwnValue, IsConstant: + Boolean); var NewVar: TBoldOCLVariableBinding; begin - if not assigned(fGlobalEnv) then - fGlobalEnv := TBoldOclEnvironment.Create(nil); - - NewVar := fGlobalEnv.Lookup(Uppercase(VariableName)); + NewVar := GlobalEnv.Find(VariableName); + if NewVar is TBoldOclVariableBindingExternal then + begin + GlobalEnv.RemoveBinding(NewVar); + FreeAndNil(NewVar); + end; if not assigned(NewVar) then begin NewVar := TBoldOclVariableBinding.Create; - NewVar.VariableName := VariableName; - fGlobalEnv.pushBinding(NewVar); + NewVar.VariableName := LowerCase(Copy(VariableName,1,1)) + Copy(VariableName,2,MaxInt); + GlobalEnv.pushBinding(NewVar); end; if assigned(VariableType) then @@ -215,9 +315,56 @@ procedure TBoldOcl.DefineVariable(const VariableName: String; VarValue: TBoldEle NewVar.SetOwnedValue(VarValue) else NewVar.SetReferenceValue(VarValue); + + // Variables like true, false, nil are always the same + if IsConstant then begin + NewVar.IsConstant := True; + if Assigned(NewVar.Value) then begin + NewVar.Value.MakeImmutable; + end; + end; +end; + +procedure TBoldOcl.DefineVariable(const VariableName: string; + Variable: TBoldExternalVariable); +var + LookupVar: TBoldOCLVariableBinding; + NewVar: TBoldOclVariableBindingExternal; + vName: string; +begin + if self = fSystemTypeInfo.Evaluator then + raise EBold.CreateFmt('%s: Variable can not be registered with meta evaluator.', [VariableName]); + if Assigned(Variable.Evaluator) and (Variable.Evaluator <> self) then + raise EBold.CreateFmt('%s: Variable already registered with another evaluator.', [VariableName]); + vName := LowerCase(Copy(VariableName,1,1)) + Copy(VariableName,2,MaxInt); + LookupVar := GlobalEnv.Find(vName); + if not assigned(LookupVar) then + begin + NewVar := TBoldOclVariableBindingExternal.Create; + NewVar.VariableName := vName; + GlobalEnv.pushBinding(NewVar); + end + else + if not (LookupVar is TBoldOclVariableBindingExternal) then + begin + NewVar := TBoldOclVariableBindingExternal.Create; + NewVar.VariableName := vName; + GlobalEnv.ReplaceBinding(vName, NewVar); + end + else + begin + NewVar := LookupVar as TBoldOclVariableBindingExternal; + end; + NewVar.ExternalVariable := Variable; + Variable.Evaluator := self; +end; + +procedure TBoldOcl.UndefineVariable(Variable: TBoldExternalVariable); +begin + GlobalEnv.RemoveVariable(Variable); end; -function TBoldOcl.SyntacticParse(const Ocl: string; StoreInDictionary: Boolean; var ResultEntry: TBoldOclEntry; Context: TBoldElementTypeInfo): TBoldIndirectElement; +function TBoldOcl.SyntacticParse(const Ocl: string; StoreInDictionary: Boolean; Context: TBoldElementTypeInfo): TBoldOclEntry; var Lexer: SSLex; Parser: AYaccClass; @@ -228,7 +375,7 @@ function TBoldOcl.SyntacticParse(const Ocl: string; StoreInDictionary: Boolean; begin FixedExpr := ocl; for i := 1 to length(FixedExpr) do - if FixedExpr[i] in [#9, BOLDLF, #12, BOLDCR] then + if CharInSet(FixedExpr[i], [#9, BOLDLF, #12, BOLDCR]) then FixedExpr[i] := ' '; if (pos('«', FixedExpr) <> 0) or (pos('»', FixedExpr) <> 0) then begin @@ -237,39 +384,38 @@ function TBoldOcl.SyntacticParse(const Ocl: string; StoreInDictionary: Boolean; begin case Ocl[i] of '''': begin - //QuotePos := i; // assignment never read, reset further down. + // QuotePos := i; InQuote := not InQuote; end; '«', '»': if not InQuote then - raise EBoldOclAbort.CreateFmt(sExpressionNotComplete, [i]); + raise EBoldOclAbort.CreateFmt('%d: Expression not complete', [i]); end; end; end; + if Assigned(Context) then + Result := fOclDictionary.OclEntryByExpressionString[Context.ExpressionName + ':' + Ocl] + else + Result := fOclDictionary.OclEntryByExpressionString[Ocl]; - // ---------------------- BEGIN MUTEX to make OCLEvaluator threadsafe - - ResultEntry := fOclDictionary.OclEntryByExpressionString[Ocl]; - - if assigned(ResultEntry) then + if assigned(Result) then begin - if resultEntry.Ocl.IsConstant or (not ResultEntry.UsedByOtherEvaluation and (ResultEntry.Context = Context)) then + if Result.Ocl.IsConstant or (not Result.UsedByOtherEvaluation) then begin - ResultEntry.UsedByOtherEvaluation := true; - Result := ResultEntry.Ocl; + Result.UsedByOtherEvaluation := true; + inc(fDictionaryHits); exit; - end - else - begin - ResultEntry := nil; - StoreInDictionary := false; - end + end; + StoreInDictionary := false; end; - // ------------------------- END MUTEX - + inc(fParses); Result := nil; + {$IFDEF BOLD_UNICODE} + Consumer := SSLexStringConsumer.Create(PAnsiChar(AnsiString(FixedExpr))); + {$ELSE} Consumer := SSLexStringConsumer.Create(PChar(FixedExpr)); + {$ENDIF} Lexer := ALexClass.Create(Consumer, OclScannerTable); Parser := AYaccClass.CreateLex(Lexer, OclParserTable); @@ -289,16 +435,16 @@ function TBoldOcl.SyntacticParse(const Ocl: string; StoreInDictionary: Boolean; QuotePos := 0; ParenPos := 0; - if Pos('SSLex0105e: Invalid token,', e.message) <> 0 then // do not localize + if Pos('SSLex0105e: Invalid token,', e.message) <> 0 then for i := 1 to Length(Ocl) do begin if Ocl[i] = '''' then InQuote := not InQuote; - if not InQuote and not (Ocl[i] in [' ', #9, BOLDCR, '0'..'9', 'a'..'z', 'A'..'Z', '_', '[', ']', '{', '}', + if not InQuote and not CharInSet(Ocl[i], [' ', #9, BOLDCR, '0'..'9', 'a'..'z', 'A'..'Z', '_', '[', ']', '{', '}', '(', ')', '+', '-', '*', '/', '=', '>', '<', ',', '.', '@', '|', '''', ':', '#', '«', '»']) then raise EBoldOclAbort.CreateFmt(boeInvalidcharacter,[i - 1]); end; - if Pos('SSYacc0105e: SyncErr failed, no valid token', e.message) <> 0 then // do not localize + if Pos('SSYacc0105e: SyncErr failed, no valid token', e.message) <> 0 then begin Paren := 0; for i := 1 to Length(Ocl) do @@ -322,7 +468,7 @@ function TBoldOcl.SyntacticParse(const Ocl: string; StoreInDictionary: Boolean; if InQuote then raise EBoldOclAbort.CreateFmt(boeunterminatedQoute, [QuotePos - 1]); end; - raise EBoldOclAbort.CreateFmt('%d:' + e.message, [e.Position]); // do not localize + raise EBoldOclAbort.CreateFmt('%d:' + e.message, [e.Position]); end; on e: EBoldOclAbort do begin @@ -338,7 +484,7 @@ function TBoldOcl.SyntacticParse(const Ocl: string; StoreInDictionary: Boolean; end; on e: Exception do begin - raise; // EBoldOclAbort.CreateFmt('%d:' + E.message, [-1]); + raise; end; end; finally @@ -346,83 +492,95 @@ function TBoldOcl.SyntacticParse(const Ocl: string; StoreInDictionary: Boolean; Lexer.Free; if assigned(Parser.finalvalue) then begin - ResultEntry := TBoldOclEntry.Create(Ocl, Parser.finalvalue.Node); - ResultEntry.UsedByOtherEvaluation := true; - Result := ResultEntry.Ocl; + Result := TBoldOclEntry.Create(Ocl, Parser.finalvalue.Node); + Result.UsedByOtherEvaluation := true; + Result.Context := Context; end; Parser.Free; end; if StoreInDictionary then begin - fOclDictionary.AddOcl(ResultEntry); - ResultEntry.OwnedByDictionary := True; + fOclDictionary.AddOcl(Result); + Result.OwnedByDictionary := True; end; end; -function TBoldOcl.SemanticCheck(Ocl: string; Context: TBoldElementTypeInfo; StoreInDictionary: Boolean; var ResultEntry: TBoldOclEntry; Env: TBoldOclEnvironment): TBoldIndirectElement; +function TBoldOcl.SemanticCheck(Ocl: string; Context: TBoldElementTypeInfo; const VariableList: TBoldExternalVariableList = nil; StoreInDictionary: Boolean = true; Env: TBoldOclEnvironment = nil): TBoldOclEntry; var Visitor: TBoldOclSemanticsVisitor; EnvSize: Integer; + HasVariables: boolean; + Guard: IBoldGuard; begin + Result := nil; + HasVariables := Assigned(VariableList) and VariableList.RefersToVariable(Ocl); + if not Assigned(Env) then + begin + if HasVariables then + begin + Guard := TBoldGuard.Create(Env); + Env := TBoldOclEnvironment.Create(GlobalEnv) + end + else + Env := GlobalEnv; + end; + AddVarsToEnv(Env, VariableList, true); + StoreInDictionary := StoreInDictionary and not HasVariables; // do not store in dict if there are variables (until subscriptions are implemented) + try if ocl[1] = '%' then ocl := LookupOclDefinition(copy(ocl, 2, maxint)); - SyntacticParse(Ocl, StoreInDictionary, ResultEntry, Context); + Result := SyntacticParse(Ocl, StoreInDictionary, Context); + - // The reason for the last part in this if-statement is that the evaluation of a nil-root to a nil-value is - // dependant on the raising of an exception in the semantic check, so therefor we can not skip it through the - // shortcut below. If the previous evaluation was made with a nil-context we still need to get the exception - // to be caught in the evaluator. - if (not ResultEntry.firstSemanticPass and + + if (not Result.firstSemanticPass and assigned(Context) and - context.ConformsTo(ResultEntry.Context)) or - (assigned(ResultEntry.Ocl) and ResultEntry.ocl.IsConstant) then + context.ConformsTo(Result.Context)) or + (assigned(Result.Ocl) and Result.ocl.IsConstant) then begin - Result := ResultEntry.Ocl; exit; end; - ResultEntry.Context := Context; - ResultEntry.Model := fSystemTYpeInfo; + Result.Context := Context; + Result.Model := fSystemTYpeInfo; EnvSize := Env.Count; - ResultEntry.SelfVar.Free; - ResultEntry.SelfVar := TBoldOclVariableBinding.Create; - ResultEntry.SelfVar.VariableName := 'Self'; // do not localize + Result.SelfVar.Free; + Result.SelfVar := TBoldOclVariableBinding.Create; + Result.SelfVar.VariableName := 'Self'; - ResultEntry.SelfVar.BoldType := ResultEntry.Context; + Result.SelfVar.BoldType := Result.Context; - Env.pushBinding(ResultEntry.SelfVar); + Env.pushBinding(Result.SelfVar); - Visitor := TBoldOclSemanticsVisitor.Create(ResultEntry.Model, self, SymbolTable, Env); + Visitor := TBoldOclSemanticsVisitor.Create(Result.Model, self, SymbolTable, Env); if BoldNelCompatibility and (pos('(', ocl) <> 0) then Visitor.IgnoreNelCompatibility := true; - try try - Visitor.Traverse(ResultEntry.Ocl); + Visitor.Traverse(Result.Ocl); except on e: EBoldOclAbort do begin - e.Ocl := ResultEntry.OclString; - ResultEntry.Context := nil; + e.Ocl := Result.OclString; + Result.Context := nil; raise; end; on e: EBoldOclError do begin - e.Ocl := ResultEntry.OclString; - ResultEntry.Context := nil; + e.Ocl := Result.OclString; + Result.Context := nil; raise; end; on e: Exception do begin - // Parsträdet behöver inte raderas, det är ju syntaktiskt korrekt. - ResultEntry.Context := nil; - raise EBoldOclAbort.CreateFmt('%d: %s', [-1, e.message]); // do not localize + Result.Context := nil; + raise EBoldOclAbort.CreateFmt('%d: %s', [-1, e.message]); end; end; finally @@ -432,37 +590,44 @@ function TBoldOcl.SemanticCheck(Ocl: string; Context: TBoldElementTypeInfo; Stor raise EBoldOclInternalError.CreateFmt(boeEnvSizeError, [0, EnvSize, Env.Count]); end; - ResultEntry.firstSemanticPass := False; + Result.firstSemanticPass := False; - Result := ResultEntry.Ocl; except on e: EBoldOclAbort do begin e.Ocl := Ocl; e.FixError; + if Assigned(Result) and not result.OwnedByDictionary then + FreeAndNil(result); raise; end; on e: EBoldOclError do begin e.Ocl := Ocl; e.FixError; + if Assigned(Result) and not result.OwnedByDictionary then + FreeAndNil(result); + raise; + end + else + begin + if Assigned(Result) and not result.OwnedByDictionary then + FreeAndNil(result); raise; end; end; end; -function TBoldOcl.RTInfo(const Ocl: string; Context: TBoldElementTypeInfo; ReRaise: Boolean): TBoldMemberRTInfo; +function TBoldOcl.RTInfo(const Ocl: string; Context: TBoldElementTypeInfo; ReRaise: Boolean; const VariableList: TBoldExternalVariableList): TBoldMemberRTInfo; var ResultEntry: TBoldOclEntry; - Env: TBoldOclEnvironment; begin Result := nil; ResultEntry := nil; - Env := TBoldOclEnvironment.Create(fGlobalEnv); try try if ocl <> '' then - SemanticCheck(Ocl, Context, false, ResultEntry, Env); + ResultEntry := SemanticCheck(Ocl, Context, VariableList, false); if assigned(ResultEntry) and (ResultEntry.Ocl is TBoldOclMember) then Result := (ResultEntry.Ocl as TBoldOclMember).RTInfo; @@ -481,25 +646,16 @@ function TBoldOcl.RTInfo(const Ocl: string; Context: TBoldElementTypeInfo; ReRai end; end; finally - if assigned(ResultEntry) then - begin - if ResultEntry.OwnedByDictionary then - ResultEntry.UsedByOtherEvaluation := false - else - begin - ResultEntry.Free; - ResultEntry := nil; - end; - end; - Env.Free; + DoneWithEntry(ResultEntry); end; end; function TBoldOcl.ExpressionType(const Ocl: string; Context: TBoldElementTypeInfo; ReRaise: Boolean; const VariableList: TBoldExternalVariableList = nil): TBoldElementTypeInfo; var ResultEntry: TBoldOclEntry; - Env: TBoldOclEnvironment; + StartTicks, EndTicks: Int64; begin + StartTicks := UserTimeInTicks; Result := nil; ResultEntry := nil; if trim(ocl) = '' then @@ -508,11 +664,9 @@ function TBoldOcl.ExpressionType(const Ocl: string; Context: TBoldElementTypeInf end else begin - Env := TBoldOclEnvironment.Create(fGlobalEnv); - AddVarsToEnv(Env, VariableList, false); try try - SemanticCheck(Ocl, Context, false, ResultEntry, Env); + ResultEntry := SemanticCheck(Ocl, Context, VariableList); if assigned(ResultEntry) then Result := ResultEntry.Ocl.BoldType; except @@ -530,21 +684,36 @@ function TBoldOcl.ExpressionType(const Ocl: string; Context: TBoldElementTypeInf end; end; finally - if assigned(ResultEntry) then - begin - if ResultEntry.OwnedByDictionary then - ResultEntry.UsedByOtherEvaluation := false - else - begin - ResultEntry.Free; - ResultEntry := nil; - end; - end; - Env.Free; + DoneWithEntry(ResultEntry); + EndTicks := userTimeInTicks; + INC(fExpresionTypeCount); + fExpressionTypeTicks := fExpressionTypeTicks + EndTicks - StartTicks; end; end; end; +function TBoldOcl.GetGlobalEnv: TBoldOclEnvironment; +begin + if not assigned(fGlobalEnv) then + fGlobalEnv := TBoldOclEnvironment.Create(nil); + result := fGlobalEnv; +end; + +function TBoldOcl.GetVariable(index: integer): TBoldIndirectElement; +begin + result := GlobalEnv.Bindings[Index]; +end; + +function TBoldOcl.GetVariableByName(const aName: string): TBoldIndirectElement; +begin + result := GlobalEnv.Lookup(aName); +end; + +function TBoldOcl.GetVariableCount: integer; +begin + result := GlobalEnv.count; +end; + function MapResubscribe(Resubscribe: Boolean): TBoldRequestedEvent; begin if Resubscribe then @@ -556,16 +725,21 @@ function MapResubscribe(Resubscribe: Boolean): TBoldRequestedEvent; var OclCounter: integer; -procedure TBoldOcl.Evaluate(Ocl: string; ROOT: TBoldElement; Subscriber: TBoldSubscriber; ResubscribeAll: Boolean; resultElement: TBoldIndirectElement; EvaluateInPS: Boolean = false; const VariableList: TBoldExternalVariableList = nil); + +procedure TBoldOcl.Evaluate(Ocl: string; Root: TBoldElement; Subscriber: TBoldSubscriber = nil; ResubscribeAll: Boolean = false; resultElement: TBoldIndirectElement = nil; EvaluateInPS: Boolean = false; const VariableList: TBoldExternalVariableList = nil); + +procedure _Evaluate(Ocl: string; Root: TBoldElement; Subscriber: TBoldSubscriber = nil; ResubscribeAll: Boolean = false; resultElement: TBoldIndirectElement = nil; EvaluateInPS: Boolean = false; const VariableList: TBoldExternalVariableList = nil); var LocalContext : TBoldElementTypeInfo; EvaluatorVisitor: TBoldOclEvaluatorVisitor; ResultEntry: TBoldOclEntry; Env: TBoldOclEnvironment; CurrentComponentPath: String; + StartTicks, EndTicks, Ticks, Freq: Int64; begin + StartTicks := UserTimeInTicks; if not fCanEvaluate then - raise EBoldOclError.Create(sTypesMissingFromEvaluator); + raise EBoldOclError.Create('This evaluator can not be used for evaluation, since some types are missing'); ResultEntry := nil; Env := nil; @@ -578,10 +752,8 @@ procedure TBoldOcl.Evaluate(Ocl: string; ROOT: TBoldElement; Subscriber: TBoldSu else CurrentComponentPath := ''; - BoldOCLLog(Ocl); - try - Inc(OclCounter); + try if assigned(ROOT) then LocalContext := ROOT.BoldType else @@ -603,25 +775,32 @@ procedure TBoldOcl.Evaluate(Ocl: string; ROOT: TBoldElement; Subscriber: TBoldSu exit; end; + if assigned(ResultElement) and (Root is TBoldObject) + and (Length(Ocl) <= fMaxMemberNameArray[TBoldObject(Root).BoldClassTypeInfo.TopSortedIndex]) then + begin + ResultElement.SetReferenceValue(TBoldObject(Root).FindBoldMemberByExpressionName(ocl)); + if Assigned(ResultElement.Value) then + begin + if assigned(Subscriber) then + ResultElement.Value.DefaultSubscribe(Subscriber, MapResubscribe(ResubscribeAll)); + exit; + end; + end; + if assigned(BoldOclRTDebugger) and BoldOclRTDebugger.HasFixFor(ocl, LocalContext) then ocl := BoldOclRTDebugger.GetFixFor(Ocl, LocalContext); try try - Env := TBoldOclEnvironment.Create(fGlobalEnv); - AddVarsToEnv(Env, VariableList, true); -// try - SemanticCheck(Ocl, LocalContext, not assigned(VariableList), resultEntry, Env); -// finally -// Env.Free; -// end; + Env := TBoldOclEnvironment.Create(GlobalEnv); + resultEntry := SemanticCheck(Ocl, LocalContext, VariableList, true, Env); + except on e: EBoldOclAbort do begin if not assigned(ROOT) and assigned(ResultEntry) then begin - // ^no root ^but syntactically correct, semantically erroneous if assigned(ResultElement) then resultElement.SetReferenceValue(nil); exit; @@ -633,7 +812,6 @@ procedure TBoldOcl.Evaluate(Ocl: string; ROOT: TBoldElement; Subscriber: TBoldSu begin if not assigned(ROOT) and assigned(ResultEntry) then begin - // ^no root ^but syntactically correct, semantically erroneous if assigned(ResultElement) then resultElement.SetReferenceValue(nil); exit; @@ -656,7 +834,7 @@ procedure TBoldOcl.Evaluate(Ocl: string; ROOT: TBoldElement; Subscriber: TBoldSu end else begin - EvaluatorVisitor := TBoldOclEvaluatorVisitor.Create(Subscriber, ResubscribeAll, fSystemtypeInfo, BoldSystem, fStringType, fIntegerType, fFloatType, fDateType, fTimeType); + EvaluatorVisitor := TBoldOclEvaluatorVisitor.Create(Subscriber, ResubscribeAll, fSystemtypeInfo, BoldSystem, fTrueBool,fBooleanType,fStringType, fIntegerType, fFloatType, fDateType, fTimeType); try ResultEntry.Ocl.AcceptVisitor(EvaluatorVisitor); finally @@ -664,12 +842,16 @@ procedure TBoldOcl.Evaluate(Ocl: string; ROOT: TBoldElement; Subscriber: TBoldSu end; end; ResultEntry.EvaluatedOnce := True; - if assigned(ResultElement) then - begin - if ResultEntry.Ocl.IsConstant then - resultElement.SetReferenceValue(ResultEntry.Ocl.Value) - else + if assigned(ResultElement) then begin + if ResultEntry.Ocl.IsConstant and + // see finally below: when ResultEntry is freed, the ResultElement + // becomes invalid. In this case Value must be transferred in this place. + ResultEntry.OwnedByDictionary then + begin + resultElement.SetReferenceValue(ResultEntry.Ocl.Value); + end else begin ResultEntry.Ocl.TransferValue(ResultElement); + end; if BoldNelCompatibility and (ResultElement.Value is TBoldClassTypeInfo) and assigned(fBoldSystem) then @@ -728,19 +910,48 @@ procedure TBoldOcl.Evaluate(Ocl: string; ROOT: TBoldElement; Subscriber: TBoldSu end; finally + BoldOCLLog(ROOT, Ocl, resultElement); + Inc(OclCounter); Env.Free; - if assigned(ResultEntry) then + if Assigned(ResultEntry) then begin - if ResultEntry.OwnedByDictionary then - ResultEntry.UsedByOtherEvaluation := false - else + INC(ResultEntry.Evaluations); + INC(fEvaluationCount); + + EndTicks := UserTimeInTicks; + Ticks := EndTicks - StartTicks; + if Ticks > 0 then begin - ResultEntry.Free; - ResultEntry := nil; + fEvaluationTicks := fEvaluationTicks + Ticks; + ResultEntry.AccumulatedTicks:= ResultEntry.AccumulatedTicks + Ticks; end; end; + DoneWithEntry(ResultEntry); end; end; +{$IFDEF OCLDummyValueBug} +var + IE: TBoldIndirectElement; +{$ENDIF} +begin + OclUseTemporaryDummyValue := true; + _Evaluate(Ocl, ROOT, Subscriber, ResubscribeAll, resultElement, EvaluateInPS, VariableList); +{$IFDEF OCLDummyValueBug} + if Assigned(OnDummyValueDifferentResult) and Assigned(resultElement) then + try + IE := TBoldIndirectElement.Create; + OclUseTemporaryDummyValue := false; + _Evaluate(Ocl, ROOT, Subscriber, ResubscribeAll, IE, EvaluateInPS, VariableList); + if not (((Assigned(resultElement.Value) and Assigned(Ie.Value)) or (not Assigned(resultElement.Value) and not Assigned(Ie.Value)))) then + OnDummyValueDifferentResult(Ocl, Root, resultElement, Ie) + else + if not resultElement.Value.IsEqual(IE.Value) then + OnDummyValueDifferentResult(Ocl, Root, resultElement, Ie); + finally + ie.free; + end; +{$ENDIF} +end; { TBoldOClDictionary } constructor TBoldOClDictionary.Create; @@ -752,7 +963,7 @@ constructor TBoldOClDictionary.Create; function TBoldOClDictionary.GetOcl(const Expr: string): TBoldOclEntry; begin - Result := TBoldOclEntry(TOCLIndex(indexes[IX_OCLEntry]).FindByString(Expr)); + Result := TBoldOclEntry(TBoldCaseSensitiveStringHashIndex(indexes[IX_OCLEntry]).FindByString(Expr)); end; procedure TBoldOClDictionary.AddOcl(ENTRY: TBoldOclEntry); @@ -776,11 +987,24 @@ destructor TBoldOclEntry.Destroy; inherited; end; -procedure BoldOCLLog(const s: string); +procedure BoldOCLLog(aRoot: TBoldElement; const s: string; aResult: TBoldIndirectElement); +var + vRoot: string; + vResult: string; begin if assigned(BoldOCLLogHandler) then - BoldOclLogHandler.Log(formatDateTime('c: ', now)+ // do not localize - format('OCL %4d - %s', [OclCounter, trim(s)])); // do not localize + begin + if Assigned(aRoot) then + vRoot := aRoot.BoldType.AsString + else + vRoot := 'nil'; + if Assigned(aResult) and Assigned(aResult.Value) then + vResult := aResult.value.AsString + else + vResult := 'nil'; + BoldOclLogHandler.Log(formatDateTime('c: ', now)+ + format('OCL %4d - %s:%s:%s', [OclCounter, vRoot, trim(s), vResult])); + end; end; function TBoldOcl.LookupOclDefinition(const name: string): string; @@ -788,7 +1012,7 @@ function TBoldOcl.LookupOclDefinition(const name: string): string; if assigned(fOnLookUpOclDefinition) then result := fOnLookUpOclDefinition(Name) else - raise EBoldOCLError.CreateFmt(sCannotFindOCLDefinitionWithoutRepository, ['%'+Name]); + raise EBoldOCLError.CreateFmt('0: Can not find OCL definition for %s, no repository installed', ['%'+Name]); end; procedure TBoldOcl.SetLookupOclDefinition(value: TBoldLookUpOclDefinition); @@ -798,13 +1022,48 @@ procedure TBoldOcl.SetLookupOclDefinition(value: TBoldLookUpOclDefinition); procedure TBoldOcl.PSEvaluation(const Expr: string; Root: TBoldElement; ResultEntry: TBoldOclEntry; Env: TBoldOclEnvironment); var - OclCondition: TBoldOclCondition; - i: integer; - ClassTypeInfo: TBoldClassTypeInfo; LocalBoldSystem: TBoldSystem; + ClassTypeInfo: TBoldClassTypeInfo; OLWNodeMaker: TBoldOLWNodeMaker; resList: TBoldObjectList; + aResultType: TBoldElementTypeInfo; + bNoBlockPSEvaluation: Boolean; + + function ExecuteOclCondition(CurrentOLCondition: TBoldOclCondition): Boolean; + var + aResultConList: TBoldObjectList; + begin + Result := False; + if Assigned(CurrentOLCondition) then begin + CurrentOLCondition.RootNode := OLWNodeMaker.RootNode; + ClassTypeInfo := (aResultType as TBoldListTypeInfo).ListElementTypeInfo as TBoldClassTypeInfo; + CurrentOLCondition.TopSortedIndex := ClassTypeInfo.TopSortedIndex; + if bNoBlockPSEvaluation then begin + CurrentOLCondition.RootNode := OLWNodeMaker.RootNode; + ResList := TBoldMemberFactory.CreateMemberFromBoldType(aResultType) as TBoldObjectList; + LocalBoldSystem.GetAllWithCondition(resList, CurrentOLCondition); + resultEntry.Ocl.SetOwnedValue(ResList); + end else begin + aResultConList := TBoldMemberFactory.CreateMemberFromBoldType(aResultType) as TBoldObjectList; + try + LocalBoldSystem.GetAllWithCondition(aResultConList, CurrentOLCondition); + ResList.AddList(aResultConList); + finally + aResultConList.Free; + end; + end; + end; + end; + +var + OclCondition: TBoldOclCondition; + i: integer; RootAsList: TBoldObjectList; + ObjectCount: Integer; + Block: Integer; + Start, Stop: Integer; +const + sInvalidForSQLEvaluation = 'Root %s: %s is not allowed for SQL-evaluation'; begin LocalBoldSystem := BoldSystem; if not assigned(LocalBoldSystem) then @@ -830,28 +1089,65 @@ procedure TBoldOcl.PSEvaluation(const Expr: string; Root: TBoldElement; ResultEn OclCondition.Env.Add(TBoldOLWVariableBinding(OLWNodeMaker.ExternalVarBindings[i])); OLWNodeMaker.ExternalVarBindings.Clear; - if Root is TBoldObject then - OclCondition.Context.Add((Root as TBoldObject).BoldObjectLocator.BoldObjectID) - else if Root is TBoldObjectList then - begin - RootAsList := Root as TBoldObjectList; - RootAsList.EnsureObjects; - for i := 0 to RootAsList.Count - 1 do - OclCondition.Context.Add(RootAsList[i].BoldObjectLocator.BoldObjectID) - end - else if assigned(root) and not (Root is TBoldSystem) then - raise EBoldOclError.CreateFmt(sInvalidForSQLEvaluation, [Root.AsString, Root.ClassName]); + aResultType := ResultEntry.Ocl.BoldType; + if aResultType is TBoldClassTypeInfo then begin + aResultType := TBoldClassTypeInfo(aResultType).ListTypeInfo; + end; - OclCondition.RootNode := OLWNodeMaker.RootNode; - ResList := TBoldMemberFactory.CreateMemberFromBoldType(ResultEntry.Ocl.BoldType) as TBoldObjectList; - ClassTypeInfo := (ResultEntry.Ocl.BoldType as TBoldListTypeInfo).ListElementTypeInfo as TBoldClassTypeInfo; - OclCondition.TopSortedIndex := ClassTypeInfo.TopSortedIndex; - LocalBoldSystem.GetAllWithCondition(resList, OclCondition); - resultEntry.Ocl.SetOwnedValue(ResList); + bNoBlockPSEvaluation := + (_BoldOCLPSEvaluationConditionBlockSize = -1) OR + ((Root is TBoldObjectList) and + ((Pos(UpperCase('->orderBy'), UpperCase(Expr)) > 0) or + (Pos(UpperCase('->orderDescending'), UpperCase(Expr)) > 0) or + (Pos(UpperCase('->difference'), UpperCase(Expr)) > 0) or + (Pos(UpperCase('->symmetricDifference'), UpperCase(Expr)) > 0) + ) + ); + + if bNoBlockPSEvaluation then begin + if Root is TBoldObject then + OclCondition.Context.Add((Root as TBoldObject).BoldObjectLocator.BoldObjectID) + else if Root is TBoldObjectList then + begin + RootAsList := Root as TBoldObjectList; + RootAsList.EnsureObjects; + for i := 0 to RootAsList.Count - 1 do + OclCondition.Context.Add(RootAsList[i].BoldObjectLocator.BoldObjectID) + end + else if assigned(root) and not (Root is TBoldSystem) then + raise EBoldOclError.CreateFmt(sInvalidForSQLEvaluation, [Root.AsString, Root.ClassName]); + + ExecuteOclCondition(OclCondition); + end else begin + ResList := TBoldMemberFactory.CreateMemberFromBoldType(aResultType) as TBoldObjectList; + if Root is TBoldObject then begin + OclCondition.Context.Add((Root as TBoldObject).BoldObjectLocator.BoldObjectID); + ExecuteOclCondition(OclCondition); + end else if Root is TBoldObjectList then begin + RootAsList := Root as TBoldObjectList; + RootAsList.EnsureObjects; + ObjectCount := RootAsList.Count - 1; + for Block := 0 to (ObjectCount div _BoldOCLPSEvaluationConditionBlockSize) do + begin + Start := Block * _BoldOCLPSEvaluationConditionBlockSize; + Stop := MinIntValue([Pred(Succ(Block) * _BoldOCLPSEvaluationConditionBlockSize), ObjectCount]); + OclCondition.Context.Clear; + for i := Start to Stop do begin + OclCondition.Context.Add(RootAsList[i].BoldObjectLocator.BoldObjectID); + end; + ExecuteOclCondition(OclCondition); + end; + end else if assigned(root) and not (Root is TBoldSystem) then begin + raise EBoldOclError.CreateFmt(sInvalidForSQLEvaluation, [Root.AsString, Root.ClassName]); + end else begin + ExecuteOclCondition(OclCondition); + end; + resultEntry.Ocl.SetOwnedValue(ResList); + end; - end - else + end else begin raise EBoldOclError.CreateFmt('%d:%s', [OLWNodeMaker.FailurePosition, OLWNodeMaker.FailureReason]); // do not localize + end; finally OclCondition.Free; @@ -879,6 +1175,39 @@ procedure TBoldOcl.AddVarsToEnv(Env: TBoldOCLEnvironment; end; end; +procedure TBoldOcl.DoneWithEntry(var oclEntry: TBoldOclEntry); +begin + if Assigned(oclEntry) then + begin + if oclEntry.OwnedByDictionary then + oclEntry.UsedByOtherEvaluation := false + else + begin + oclEntry.Free; + oclEntry := nil; + end; + end; +end; + +procedure TBoldOcl.TodayTimerEvent(Sender: TObject); +begin + fTodayTimer.Interval := MilliSecondsBetween( Now, Today+1 ); + fTodayVar.AsDate := Today; +end; + +procedure TBoldOcl.NowTimerEvent(Sender: TObject); +var + vTime: TDateTime; +begin + vTime := RecodeMilliSecond(now, 0); + vTime := RecodeSecond(vTime, 0); + fNowVar.AsDateTime := vTime; + vTime := IncMinute(vTime); + fNowTimer.Interval := MilliSecondsBetween( Now, vTime ); + if (fNowTimer.Interval = 0) or (fNowTimer.Interval > MSecsPerSec * SecsPerMin) then + fNowTimer.Interval := MSecsPerSec * SecsPerMin +end; + procedure BoldForceNelCompatibility; begin BoldNelCompatibility := true; @@ -886,6 +1215,7 @@ procedure BoldForceNelCompatibility; end; initialization + TBoldOClDictionary.IX_OCLEntry := -1; finalization FreeAndNil(G_OclParserTable); diff --git a/Source/ObjectSpace/Ocl/BoldOclClasses.pas b/Source/ObjectSpace/Ocl/BoldOclClasses.pas index a211f08..89b6dbc 100644 --- a/Source/ObjectSpace/Ocl/BoldOclClasses.pas +++ b/Source/ObjectSpace/Ocl/BoldOclClasses.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldOclClasses; interface @@ -12,12 +15,13 @@ interface BoldSystemRT; type + TBOCollectionKind = (OCLSet, OCLBag, OCLSequence); TBoldOCLIteratorSpecifier = (OclNoIterator, OclSelect, OclReject, OCLCollect, OclIterate, OclExists, OclForAll, OclOrderBy, OclOrderDescending, OclUnique); TBoldOclDeduceMethod = (tbodNo, tbodCopyLoopVar, tbodCopyArg1, tbodCopyArg1Elem, tbodCopyArg2, tbodCopyArg3, tbodLCC, tbodLCC23, tbodListofArg2, TbodObjectlist, - tbodType, tbodTypecast, tbodArg1AsList, tbodListFromArg2); + tbodType, tbodTypecast, tbodArg1Type, tbodArg1AsList, tbodListFromArg2); TBoldOCL_Operation = procedure (Args: array of TBoldIndirectElement; Result: TBoldIndirectElement); @@ -54,26 +58,7 @@ {//} TBoldOclSymbolParameters = record {//} SystemTypeInfo: TBoldSystemTypeInfo; {//} end; - -{ TBoldOclNodeList } - TBoldOclNodeList = class(TBoldMemoryManagedObject) - private - FList: TList; - function GetItem(index: Integer): TBoldOclNode; - procedure PutItem(index: Integer; Value: TBoldOclNode); - public - property Items[index: Integer]: TBoldOclNode read GetItem write PutItem; default; - constructor Create; - destructor Destroy; override; - function Add(Item: TBoldOclNode): Integer; - procedure Clear; - procedure ClearAndFree; - procedure Delete(index: Integer); - procedure Insert(index: Integer; Item: TBoldOclNode); - procedure Move(CurIndex, NewIndex: Integer); - function Remove(Item: TBoldOclNode): Integer; - function Count: Integer; - end; + TBoldOclNodeList = array of TBoldOclNode; { TBoldOclEnvironment } TBoldOclEnvironment = class(TBoldMemoryManagedObject) @@ -83,17 +68,23 @@ TBoldOclEnvironment = class(TBoldMemoryManagedObject) fList: TList; function GetCount: integer; function GetBindings(Index: integer): TBoldOclVariableBinding; + function GetBindingsAsCommaText: string; public constructor Create(OuterScope: TBoldOclEnvironment); property Count: integer read GetCount; - destructor Destroy; override; + destructor destroy; override; procedure pushBinding(B: TBoldOclVariableBinding); function popBinding: TBoldOclVariableBinding; - function Lookup(S: string): TBoldOclVariableBinding; + procedure ReplaceBinding(name: string; Binding: TBoldOclVariableBinding); + procedure RemoveBinding(Binding: TBoldOclVariableBinding); + procedure RemoveVariable(Variable: TBoldExternalVariable); + function Lookup(const S: string): TBoldOclVariableBinding; function lookupSelf: TBoldOclVariableBinding; + function Find(const S: string): TBoldOclVariableBinding; function CurrentImplicitVariable: TBoldOclVariableBinding; function MakeGenSymName: string; property Bindings[Index: integer]: TBoldOclVariableBinding read GetBindings; default; + property BindingsAsCommaText: string read GetBindingsAsCommaText; end; { TBoldOclVisitor } @@ -101,7 +92,7 @@ TBoldOclVisitor = class(TBoldMemoryManagedObject) public procedure VisitTBoldOclNode(N: TBoldOclNode); virtual; procedure VisitTBoldOclListCoercion(N: TBoldOclListCoercion); virtual; - procedure VisitTBoldOclCollectionLiteral(N: TBoldOclCollectionLIteral); virtual; + procedure VisitTBoldOclCollectionLIteral(N: TBoldOclCollectionLIteral); virtual; procedure VisitTBoldOclOperation(N: TBoldOclOperation); virtual; procedure VisitTBoldOclIteration(N: TBoldOclIteration); virtual; procedure VisitTBoldOclMember(N: TBoldOclMember); virtual; @@ -109,7 +100,7 @@ TBoldOclVisitor = class(TBoldMemoryManagedObject) procedure VisitTBoldOclLiteral(N: TBoldOclLiteral); virtual; procedure VisitTBoldOclStrLiteral(N: TBoldOclStrLiteral); virtual; procedure VisitTBoldOclNumericLiteral(N: TBoldOclNumericLiteral); virtual; - procedure VisitTBoldOclEnumLiteral(N: TBoldOclEnumLiteral); virtual; + procedure VisitTBoldOclENumLiteral(N: TBoldOclEnumLiteral); virtual; procedure VisitTBoldOclIntLiteral(N: TBoldOclIntLiteral); virtual; procedure VisitTBoldOclMomentLiteral(N: TBoldOclMomentLiteral); virtual; procedure VisitTBoldOclDateLiteral(N: TBoldOclDateLiteral); virtual; @@ -124,16 +115,16 @@ TBoldOclNode = class(TBoldIndirectElement) protected fBoldType: TBoldElementTypeInfo; procedure SetBoldType(NewType: TBoldElementTypeInfo); - function GetBoldType: TBoldElementTypeInfo; + function GetBoldType: TBoldElementTypeInfo; virtual; public Position: Integer; - constructor Create; + constructor Create; virtual; procedure AcceptVisitor(V: TBoldOclVisitor); virtual; property BoldType: TBoldElementTypeInfo read GetBoldType write SetBoldType; property NeedsListCoercion: Boolean index befNeedsListCoercion read GetElementFlag write SetElementFlag; property IsConstant: Boolean index befIsConstant read GetElementFlag write SetElementFlag; property Resubscribe: boolean index befResubscribe read GetElementFlag write SetElementFlag; - property HastemporaryDummyValue: boolean index befHastemporaryDummyValue read GetElementFlag write SetElementFlag; + property HasTemporaryDummyValue: boolean index befHastemporaryDummyValue read GetElementFlag write SetElementFlag; end; { TBoldOclTypeNode } @@ -147,7 +138,7 @@ TBoldOclTypeNode = class(TBoldOclNode) TBoldOCLListCoercion = class(TBoldOCLNode) public Child: TBoldOCLNode; - destructor Destroy; override; + destructor destroy; override; procedure AcceptVisitor(V: TBoldOclVisitor); override; end; @@ -180,7 +171,7 @@ TBoldOclMember = class(TBoldOclNode) MemberIndex: Integer; Qualifier: TBoldOclNodeList; RTInfo: TBoldMemberRTInfo; - constructor Create; + constructor Create; override; destructor Destroy; override; procedure AcceptVisitor(V: TBoldOclVisitor); override; end; @@ -198,18 +189,26 @@ TBoldOclMethod = class(TBoldOclOperation) TBoldOclVariableBinding = class(TBoldOclNode) public VariableName: string; - TypeNameList: TStringList; //For temporary use only. The parser stores the type - //info from a select(i:Person|i<>self.employer) - //but this must be moved to the oclNode.ExpressionType + TypeNameList: TStringList; destructor Destroy; override; procedure AcceptVisitor(V: TBoldOclVisitor); override; end; + TBoldOclVariableBindingExternal = class(TBoldOclVariableBinding) + private + fExternalVariable: TBoldExternalVariable; + protected + function GetBoldType: TBoldElementTypeInfo; override; + public + destructor Destroy; override; + property ExternalVariable: TBoldExternalVariable read fExternalVariable write fExternalVariable; + end; + { TBoldOclVariableReference } TBoldOclVariableReference = class(TBoldOclNode) public VariableName: string; - VariableBinding: TBoldOclVariableBinding; // Not to be traversed... + VariableBinding: TBoldOclVariableBinding; procedure AcceptVisitor(V: TBoldOclVisitor); override; end; @@ -290,11 +289,12 @@ TBoldOclEnumLiteral = class(TBoldOclLiteral) TBoldSymbolDictionary = class(TBoldIndexableList) private fhelp: TBoldOclSymbolHelp; - function GetSymbol(const Name: string): TBoldOclSymbol; + function GetSymbol(const Name: string): TBoldOclSymbol; {$IFDEF BOLD_INLINE} inline; {$ENDIF} function GetSymbolByIndex(index: Integer): TBoldOclSymbol; + class var IX_SymbolName: integer; public constructor Create(SystemTypeInfo: TBoldSystemTypeInfo; BoldSystem: TBoldSystem; var ErrorsEncountered: Boolean); - destructor Destroy; override; + destructor destroy; override; property help: TBoldOclSymbolHelp read fHelp; property SymbolByName[const name: string]: TBoldOclSymbol read GetSymbol; property Symbols[i: Integer]: TBoldOclSymbol read GetSymbolByIndex; @@ -321,11 +321,12 @@ TBoldOclSymbolHelp = class(TBoldMemoryManagedObject) fNumericListType, fMomentListType, fStringListType, + fIntegerListType, fTypeListType: TBoldListTypeInfo; fSystemTypeInfo: tBoldSystemTypeInfo; - procedure fMakeNew(el: TBoldIndirectElement; NewType: TBoldElementTypeInfo); public constructor create(SystemTypeInfo: tBoldSystemTypeInfo; BoldSystem: TBoldSystem; var ErrorsEncountered: Boolean); + procedure MakeNew(el: TBoldOCLNode; NewType: TBoldElementTypeInfo); function CreateNewMember(BoldType: TBoldElementTypeInfo): TBoldMember; property SystemTypeInfo: TBoldSystemTypeInfo read fSystemTypeInfo; property NumericType: TBoldAttributeTypeInfo read fNumericType; @@ -345,25 +346,29 @@ TBoldOclSymbolHelp = class(TBoldMemoryManagedObject) property NumericListType: TBoldListTypeInfo read fNumericListType; property MomentListType: TBoldListTypeInfo read fMomentListType; property StringListType: TBoldListTypeInfo read fStringListType; + property IntegerListType: TBoldListTypeInfo read fIntegerListType; property TypeListType: TBoldListTypeInfo read fTypeListType; property ObjectListType: TBoldListTypeInfo read fObjectListType; - procedure MakeNewNumeric(El: TBoldIndirectElement; value: Double); - procedure MakeNewTime(El: TBoldIndirectElement; value: TDateTime); - procedure MakeNewDateTime(El: TBoldIndirectElement; value: TDateTime); - procedure MakeNewDate(El: TBoldIndirectElement; value: TDateTime); - procedure MakeNewBoolean(El: TBoldIndirectElement; value: Boolean); - procedure MakeNewInteger(El: TBoldIndirectElement; value: integer); - procedure MakeNewString(El: TBoldIndirectElement; const value: string); - procedure MakeNewCurrency(El: TBoldIndirectElement; value: currency); + procedure MakeNewNumeric(El: TBoldOCLNode; value: Double); + procedure MakeNewTime(El: TBoldOCLNode; value: TDateTime); + procedure MakeNewDateTime(El: TBoldOCLNode; value: TDateTime); + procedure MakeNewDate(El: TBoldOCLNode; value: TDateTime); + procedure MakeNewBoolean(El: TBoldOCLNode; value: Boolean); + procedure MakeNewInteger(El: TBoldOCLNode; value: integer); + procedure MakeNewString(El: TBoldOCLNode; const value: string); + procedure MakeNewCurrency(El: TBoldOCLNode; value: currency); + procedure MakeNewNull(el: TBoldOCLNode; NewType: TBoldElementTypeInfo); procedure TransferOrClone(source, dest: TBoldIndirectElement); end; + ShortCircuitType = (csNone, csAnd, csOr, csIf); + { TBoldOclSymbol } TBoldOclSymbol = class(TBoldMemoryManagedObject) private fHelp: TBoldOCLSymbolHelp; fSymbolName: String; - fFormalArguments: TList; + fFormalArguments: array of TBoldElementTypeInfo; fDeduceMethod: TBoldOclDeduceMethod; fResultType: TBoldElementTypeInfo; fIsDotNotation: Boolean; @@ -372,27 +377,28 @@ TBoldOclSymbol = class(TBoldMemoryManagedObject) fArgsNeedCommonType: Boolean; protected procedure InternalInit(const Name: string; - const Args: array of TBoldElementTypeInfo; + Args: array of TBoldElementTypeInfo; DeduceMethod: TBoldOclDeduceMethod; resultType: TBoldElementTypeInfo; IsPostfix: Boolean; HelpContext: integer; ArgsNeedCommonType: Boolean = false); - function GetFormalArguments(index: integer): TBoldElementTypeInfo; - function GetNumberOfArgs: integer; + function GetFormalArguments(index: integer): TBoldElementTypeInfo; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetNumberOfArgs: integer; {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure Init; virtual; abstract; - function XBoolean(Elem: TBoldElement): Boolean; - function XCurrency(Elem: TBoldElement): Currency; - function XInteger(Elem: TBoldElement): Integer; - function XList(Elem: TBoldElement): tBoldList; - function XDateTime(Elem: TBoldElement): TDateTime; - function XNumeric(Elem: TBoldElement): Double; - function XString(Elem: TBoldElement): String; - function XType(Elem: TBoldElement): TBoldElementTypeInfo; + class function XBoolean(Elem: TBoldElement): Boolean; static; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + class function XCurrency(Elem: TBoldElement): Currency; static; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + class function XInteger(Elem: TBoldElement): Integer; static; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + class function XList(Elem: TBoldElement): tBoldList; static; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + class function XDateTime(Elem: TBoldElement): TDateTime; static; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + class function XNumeric(Elem: TBoldElement): Double; static; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + class function XString(Elem: TBoldElement): String; static; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + class function XType(Elem: TBoldElement): TBoldElementTypeInfo; static; {$IFDEF BOLD_INLINE} inline; {$ENDIF} property Help: TBoldOclSymbolHelp read fHelp; public constructor Create(Help: TBoldOclSymbolHelp); destructor Destroy; override; + function GetShortCircuitType: ShortCircuitType; virtual; procedure Evaluate(const Params: TBoldOclSymbolParameters); virtual; abstract; procedure SQL(const Args: Array of String; var result: String); virtual; property DeduceMethod: tBoldOclDeduceMethod read fDeduceMethod; @@ -413,90 +419,10 @@ implementation BoldHashIndexes, BoldDefs, BoldOclError, - BoldAttributes, - BoldCoreConsts; - -var - IX_SymbolName: integer = -1; - -constructor TBoldOclNodeList.Create; -begin - inherited; - FList := TList.Create; -end; - -destructor TBoldOclNodeList.Destroy; -begin - FreeAndNil(FList); - inherited; -end; - -function TBoldOclNodeList.GetItem(index: Integer): TBoldOclNode; -begin - Assert((not Assigned(FList[index])) or (tObject(FList[index]) is TBoldOCLNode)); - Result := TBoldOCLNode(FList[index]); -end; - -procedure TBoldOclNodeList.PutItem(index: Integer; Value: TBoldOclNode); -begin - FList[index] := Value; -end; - -function TBoldOclNodeList.Add(Item: TBoldOclNode): Integer; -begin - Result := FList.Add(Item); -end; - -procedure TBoldOclNodeList.Clear; -begin - FList.Clear; -end; - -procedure TBoldOclNodeList.ClearAndFree; -var - I: Integer; -begin - for I := Count - 1 downto 0 do - begin - Items[I].Free; - items[i] := nil; - end; - FList.Clear; -end; - -procedure TBoldOclNodeList.Delete(index: Integer); -begin - FList.Delete(index); - FList.Pack; -end; - -procedure TBoldOclNodeList.Insert(index: Integer; Item: TBoldOclNode); -begin - FList.Insert(index, Item); -end; - -procedure TBoldOclNodeList.Move(CurIndex, NewIndex: Integer); -begin - FList.Move(CurIndex, NewIndex); -end; - -function TBoldOclNodeList.Remove(Item: TBoldOclNode): Integer; -begin - Result := FList.Remove(Item); -end; - -function TBoldOclNodeList.Count: Integer; -begin - Result := FList.Count -end; - -//======================================================================= -//== TBoldOCLNodes and decendants constructors and destructors -//======================================================================= + BoldAttributes; procedure TBoldOclNode.AcceptVisitor(V: TBoldOclVisitor); begin - // Do nothing end; constructor TBoldOclNode.Create; @@ -506,39 +432,33 @@ constructor TBoldOclNode.Create; end; destructor TBoldOclMember.Destroy; +var + i: Integer; begin FreeAndNil(MemberOf); - if assigned(Qualifier) then - Qualifier.Clearandfree; - FreeAndNil(Qualifier); + for i := 0 to Length(Qualifier)- 1 do + Qualifier[i].Free; inherited; end; destructor TBoldOCLCollectionLiteral.Destroy; +var + i: Integer; begin FreeAndNil(RangeStart); FreeAndNil(RangeStop); - if assigned(elements) then - begin - Elements.Clearandfree; - FreeAndNil(Elements) - end; + for i := 0 to Length(Elements) - 1 do + Elements[i].Free; inherited; end; destructor TBoldOclOperation.Destroy; -var I: Integer; +var + I: Integer; begin - if assigned(Args) then - begin - for I := 0 to Args.Count - 1 do - begin - TBoldOclNode(Args[I]).Free; - Args[I] := nil; - end; - FreeAndNil(Args); - end; + for I := 0 to Length(Args) - 1 do + Args[I].Free; inherited; end; @@ -568,9 +488,7 @@ constructor TBoldOclMember.Create; RTInfo := nil; end; -//======================================================================= -//== TBoldOCLNode and descendants Visitor mechanism -//======================================================================= + procedure TBoldOclTypeNode.AcceptVisitor(V: TBoldOclVisitor); begin @@ -662,9 +580,6 @@ procedure TBoldOclVisitor.VisitTBoldOclMomentLiteral(N: TBoldOclMomentLiteral); procedure TBoldOclVisitor.VisitTBoldOclTimeLiteral(N: TBoldOclTimeLiteral); begin end; -//======================================================================= -//== TBoldOCLEnvironment -//======================================================================= constructor TBoldOclEnvironment.Create(OuterScope: TBoldOclEnvironment); begin @@ -674,7 +589,7 @@ constructor TBoldOclEnvironment.Create(OuterScope: TBoldOclEnvironment); fList := TList.Create; end; -destructor TBoldOCLEnvironment.Destroy; +destructor TBoldOCLEnvironment.destroy; var tempBinding: TBoldOclVariableBinding; begin @@ -694,7 +609,6 @@ function TBoldOCLEnvironment.GetCount: integer; procedure TBoldOclEnvironment.pushBinding(B: TBoldOclVariableBinding); begin - b.variableName := uppercase(b.variableName); fList.Add(B); end; @@ -704,14 +618,55 @@ function TBoldOclEnvironment.popBinding: TBoldOclVariableBinding; fList.Delete(Count - 1); end; -function TBoldOclEnvironment.Lookup(S: string): TBoldOclVariableBinding; -var I: Integer; +procedure TBoldOclEnvironment.ReplaceBinding(name: string; + Binding: TBoldOclVariableBinding); +var + i: integer; begin I := fList.Count - 1; - s := uppercase(s); while I >= 0 do begin - if Bindings[I].VariableName = S then + if CompareText(Bindings[I].VariableName, name) = 0 then + begin + TObject(fList.Items[i]).free; + fList.Items[i] := Binding; + exit; + end; + Dec(I); + end; +end; + +procedure TBoldOclEnvironment.RemoveBinding(Binding: TBoldOclVariableBinding); +begin + fList.Remove(Binding); +end; + +procedure TBoldOclEnvironment.RemoveVariable(Variable: TBoldExternalVariable); +var + i: integer; +begin + I := fList.Count - 1; + while I >= 0 do + begin + if Bindings[I] is TBoldOclVariableBindingExternal and (TBoldOclVariableBindingExternal(Bindings[I]).ExternalVariable = Variable) then + begin + Variable.Evaluator := nil; + TObject(fList[i]).free; + fList.Delete(i); + exit; + end; + Dec(I); + end; +end; + +function TBoldOclEnvironment.Find(const S: string): TBoldOclVariableBinding; +var + I: Integer; +begin + I := fList.Count - 1; + while I >= 0 do + begin + if CompareText(Bindings[I].VariableName, s) = 0 then begin Result := Bindings[i]; exit; @@ -724,9 +679,39 @@ function TBoldOclEnvironment.Lookup(S: string): TBoldOclVariableBinding; Result := nil; end; +function TBoldOclEnvironment.Lookup(const S: string): TBoldOclVariableBinding; +var + I: Integer; + ResolvedBinding: TBoldOclVariableBinding; + ExternalVariable: TBoldExternalVariable; +begin + I := fList.Count - 1; + while I >= 0 do + begin + if CompareText(Bindings[I].VariableName, s) = 0 then + begin + Result := Bindings[i]; + if result is TBoldOclVariableBindingExternal then + begin + ExternalVariable := TBoldOclVariableBindingExternal(result).ExternalVariable; + if Assigned(ExternalVariable) then + result.SetReferenceValue(ExternalVariable.Value) + else + result.SetReferenceValue(nil); + end; + exit; + end; + Dec(I); + end; + if assigned(fOuterScope) then + result := fOuterScope.Lookup(S) + else + Result := nil; +end; + function TBoldOclEnvironment.lookupSelf: TBoldOclVariableBinding; begin - Result := Lookup('SELF'); // do not localize + Result := Lookup('SELF'); end; function TBoldOclEnvironment.CurrentImplicitVariable: TBoldOclVariableBinding; @@ -736,7 +721,7 @@ function TBoldOclEnvironment.CurrentImplicitVariable: TBoldOclVariableBinding; function TBoldOclEnvironment.MakeGenSymName: string; begin - Result := IntToStr(GenSymCounter) + '#GenSym'; // do not localize + Result := IntToStr(GenSymCounter) + '#GenSym'; Inc(GenSymCounter); end; @@ -764,16 +749,16 @@ procedure InstallAttribute(const Name: String; var AttrTypeInfo: TBoldAttributeT begin AttrTypeInfo := SystemTypeInfo.AttributeTypeInfoByExpressionName[Name]; if not assigned(AttrTypeINfo) then - SignalError(sMissingOCLType, [Name]); + SignalError('Missing required OCL-type: %s. Update your TypeNameHandle', [Name]); if not assigned(AttrTypeInfo.AttributeClass) then - SignalError(sMissingDelphiType, [Name, AttrTypeInfo.DelphiName]) + SignalError('Missing DelphiType of %s (please install %s)', [Name, AttrTypeInfo.DelphiName]) else begin case exact of true: if AttrTypeInfo.AttributeClass <> AttrClass then - SignalError(sTypeMustBeX, [Name, AttrClass.ClassName, AttrTypeInfo.AttributeClass.ClassName]); + SignalError('The %s type must BE %s (was: %s). Update your TypeNameHandle', [Name, AttrClass.ClassName, AttrTypeInfo.AttributeClass.ClassName]); false: if not AttrTypeInfo.AttributeClass.InheritsFrom(AttrClass) then - SignalError(sTypeMustInheritFromX, [Name, AttrClass.ClassName, AttrTypeInfo.AttributeClass.ClassName]); + SignalError('The %s type must inherit from %s (%s doesn''t).', [Name, AttrClass.ClassName, AttrTypeInfo.AttributeClass.ClassName]); end; end; end; @@ -782,17 +767,17 @@ procedure InstallAttribute(const Name: String; var AttrTypeInfo: TBoldAttributeT inherited create; fSystemTypeInfo := SystemTypeInfo; fTypeType := SystemTypeInfo.BoldType as TBoldTypeTypeInfo; - InstallAttribute('Numeric', fNumericType, TBANumeric, true); // do not localize - InstallAttribute('Float', fRealType, TBAFloat, false); // do not localize - InstallAttribute('String', fStringType, TBAString, false); // do not localize - InstallAttribute('Integer', fIntegerType, TBAInteger, false); // do not localize - InstallAttribute('Boolean', fBooleanType, TBABoolean, false); // do not localize - InstallAttribute('Currency', fCurrencyType, TBACurrency, false); // do not localize - InstallAttribute('Moment', fMomentType, TBAMoment, false); // do not localize - InstallAttribute('Constraint', fConstraintType, TBAConstraint, false); // do not localize - InstallAttribute('Date', fDateType, TBADate, false); // do not localize - InstallAttribute('DateTime', fDateTimeType, TBADateTime, false); // do not localize - InstallAttribute('Time', fTimeType, TBATime, false); // do not localize + InstallAttribute('Numeric', fNumericType, TBANumeric, true); + InstallAttribute('Float', fRealType, TBAFloat, false); + InstallAttribute('String', fStringType, TBAString, false); + InstallAttribute('Integer', fIntegerType, TBAInteger, false); + InstallAttribute('Boolean', fBooleanType, TBABoolean, false); + InstallAttribute('Currency', fCurrencyType, TBACurrency, false); + InstallAttribute('Moment', fMomentType, TBAMoment, false); + InstallAttribute('Constraint', fConstraintType, TBAConstraint, false); + InstallAttribute('Date', fDateType, TBADate, false); + InstallAttribute('DateTime', fDateTimeType, TBADateTime, false); + InstallAttribute('Time', fTimeType, TBATime, false); fObjectType := SystemTypeInfo.RootClassTypeInfo; fListType := SystemTypeInfo.ListTypeInfoByElement[nil]; @@ -801,78 +786,87 @@ procedure InstallAttribute(const Name: String; var AttrTypeInfo: TBoldAttributeT fTypeListType := SystemTypeInfo.ListTypeInfoByElement[TypeType]; fObjectListType := SystemTypeInfo.ListTypeInfoByElement[ObjectType]; fStringListType := SystemTypeInfo.ListTypeInfoByElement[StringType]; + fIntegerListType := SystemTypeInfo.ListTypeInfoByElement[IntegerType]; end; -procedure TBoldOclSymbolHelp.fMakeNew(el: TBoldIndirectElement; NewType: TBoldElementTypeInfo); +procedure TBoldOclSymbolHelp.MakeNew(el: TBoldOCLNode; NewType: TBoldElementTypeInfo); begin - // if we do not own it, or it is not there, then create new element - if not el.OwnsValue or not assigned(el.Value) then + if el.OwnsValue and assigned(el.Value) then + begin + if el.value is TBoldAttribute then + TBoldAttribute(el.Value).RecycleValue; + end + else + begin - if (el is TBoldOCLNode) and - assigned(TBoldOclNode(el).BoldType) and - TBoldOclNode(el).BoldType.ConformsTo(NewType) then - el.SetOwnedValue(CreateNewMember(TBoldOclNode(el).BoldType)) + if assigned(el.BoldType) and + el.BoldType.ConformsTo(NewType) then + el.SetOwnedValue(CreateNewMember(el.BoldType)) else el.SetOwnedValue(CreateNewMember(NewType)) end - else - // always recycle the value, we must tell the rest of the world that this is now a new vlaue. - if el.value is TBoldAttribute then - TBoldAttribute(el.Value).RecycleValue; end; -procedure TBoldOclSymbolHelp.MakeNewNumeric(El: TBoldIndirectElement; value: Double); +procedure TBoldOclSymbolHelp.MakeNewNull(el: TBoldOCLNode; + NewType: TBoldElementTypeInfo); begin - fMakeNew(el, RealType); + MakeNew(el, NewType); + if (el.Value is TBoldAttribute) then + (el.Value as TBoldAttribute).SetToNull; +end; + +procedure TBoldOclSymbolHelp.MakeNewNumeric(El: TBoldOCLNode; value: Double); +begin + MakeNew(el, RealType); Assert(El.Value is TBAFloat); TBAFloat(El.Value).AsFloat := Value; end; -procedure TBoldOclSymbolHelp.MakeNewCurrency(El: TBoldIndirectElement; value: currency); +procedure TBoldOclSymbolHelp.MakeNewCurrency(El: TBoldOCLNode; value: currency); begin - fMakeNew(el, CurrencyType); + MakeNew(el, CurrencyType); Assert(El.Value is TBACurrency); TBACurrency(El.Value).Ascurrency := Value; end; -procedure TBoldOclSymbolHelp.MakeNewString(El: TBoldIndirectElement; const value: String); +procedure TBoldOclSymbolHelp.MakeNewString(El: TBoldOCLNode; const value: String); begin - fMakeNew(el, StringType); + MakeNew(el, StringType); Assert(El.Value is TBAString); TBAString(El.Value).AsString := Value; end; -procedure TBoldOclSymbolHelp.MakeNewInteger(El: TBoldIndirectElement; value: integer); +procedure TBoldOclSymbolHelp.MakeNewInteger(El: TBoldOCLNode; value: integer); begin - fMakeNew(el, Integertype); + MakeNew(el, Integertype); Assert(El.Value is TBAInteger); TBAInteger(El.Value).AsInteger := Value; end; -procedure TBoldOclSymbolHelp.MakeNewTime(El: TBoldIndirectElement; value: TDateTime); +procedure TBoldOclSymbolHelp.MakeNewTime(El: TBoldOCLNode; value: TDateTime); begin - fMakeNew(el, TimeType); + MakeNew(el, TimeType); Assert(El.Value is TBATime); TBATime(El.Value).AsTime := Value; end; -procedure TBoldOclSymbolHelp.MakeNewDateTime(El: TBoldIndirectElement; value: TDateTime); +procedure TBoldOclSymbolHelp.MakeNewDateTime(El: TBoldOCLNode; value: TDateTime); begin - fMakeNew(el, DateTimeType); + MakeNew(el, DateTimeType); Assert(El.Value is TBADateTime); TBADateTime(El.Value).AsDateTime := Value; end; -procedure TBoldOclSymbolHelp.MakeNewDate(El: TBoldIndirectElement; value: TDateTime); +procedure TBoldOclSymbolHelp.MakeNewDate(El: TBoldOCLNode; value: TDateTime); begin - fMakeNew(el, DateType); + MakeNew(el, DateType); Assert(El.Value is TBADate); TBADate(El.Value).AsDate := Value; end; -procedure TBoldOclSymbolHelp.MakeNewBoolean(El: TBoldIndirectElement; value: Boolean); +procedure TBoldOclSymbolHelp.MakeNewBoolean(El: TBoldOCLNode; value: Boolean); begin - fMakeNew(el, BooleanType); + MakeNew(el, BooleanType); Assert(El.Value is TBABoolean); TBABoolean(El.Value).AsBoolean := Value; end; @@ -892,20 +886,20 @@ procedure TBoldOclSymbolHelp.TransferorClone(source, dest: TBoldIndirectElement) {-- TBoldOclSymbol -- } procedure TBoldOclSymbol.InternalInit(const Name: string; - const Args: array of TBoldElementTypeInfo; + Args: array of TBoldElementTypeInfo; DeduceMethod: TBoldOclDeduceMethod; resultType: TBoldElementTypeInfo; IsPostfix: Boolean; HelpContext: Integer; ArgsNeedCommonType: Boolean = false); var - i: integer; + i:Integer; begin fSymbolName := Name; fHelpContext := HelpContext; - for i := 0 to High(Args) do - fFormalArguments.Add(Args[i]); - + SetLength(fFormalArguments, Length(args)); + for i := 0 to Length(args) - 1 do + fFormalArguments[i] := args[i]; if assigned(ResultType) then fResultType := ResultType else @@ -916,12 +910,17 @@ procedure TBoldOclSymbol.InternalInit(const Name: string; function TBoldOclSymbol.GetFormalArguments(index: integer): TBoldElementTypeInfo; begin - result := TBoldElementTypeInfo(fFormalArguments[index]); + result := fFormalArguments[index]; end; function TBoldOclSymbol.GetNumberOfArgs: integer; begin - result := fFormalArguments.Count; + result := Length(fFormalArguments); +end; + +function TBoldOclSymbol.GetShortCircuitType: ShortCircuitType; +begin + Result := csNone; end; procedure TBoldOclSymbol.SQL(const Args: Array of String; var result: String); @@ -933,7 +932,6 @@ constructor TBoldOclSymbol.Create(Help: TBoldOclSymbolHelp); begin Inherited create; fHelp := help; - fFormalArguments := TList.create; Init; fIsDotNotation := isPostFix and (not assigned(FormalArguments[0]) or @@ -942,11 +940,10 @@ constructor TBoldOclSymbol.Create(Help: TBoldOclSymbolHelp); destructor TBoldOclSymbol.Destroy; begin - FreeAndNil(fFormalArguments); inherited; end; -function TBoldOclSymbol.XBoolean(Elem: TBoldElement): Boolean; +class function TBoldOclSymbol.XBoolean(Elem: TBoldElement): Boolean; begin if elem is TBABoolean then result := TBABoolean(Elem).AsBoolean @@ -954,7 +951,7 @@ function TBoldOclSymbol.XBoolean(Elem: TBoldElement): Boolean; result := false; end; -function TBoldOclSymbol.XInteger(Elem: TBoldElement): Integer; +class function TBoldOclSymbol.XInteger(Elem: TBoldElement): Integer; begin if (elem is TBAInteger) and not TBAInteger(elem).IsNull then result := TBAInteger(Elem).AsInteger @@ -962,7 +959,7 @@ function TBoldOclSymbol.XInteger(Elem: TBoldElement): Integer; result := 0; end; -function TBoldOclSymbol.XDateTime(Elem: TBoldElement): TDateTime; +class function TBoldOclSymbol.XDateTime(Elem: TBoldElement): TDateTime; begin if elem is TBADate then result := TBADate(Elem).AsDate @@ -974,7 +971,7 @@ function TBoldOclSymbol.XDateTime(Elem: TBoldElement): TDateTime; result := 0; end; -function TBoldOclSymbol.XNumeric(Elem: TBoldElement): Double; +class function TBoldOclSymbol.XNumeric(Elem: TBoldElement): Double; begin if elem is TBANumeric then result := TBANumeric(Elem).AsFloat @@ -982,7 +979,7 @@ function TBoldOclSymbol.XNumeric(Elem: TBoldElement): Double; result := 0; end; -function TBoldOclSymbol.Xcurrency(Elem: TBoldElement): currency; +class function TBoldOclSymbol.Xcurrency(Elem: TBoldElement): currency; begin if elem is TBACurrency then result := TBACurrency(Elem).Ascurrency @@ -990,7 +987,7 @@ function TBoldOclSymbol.Xcurrency(Elem: TBoldElement): currency; result := 0; end; -function TBoldOclSymbol.XString(Elem: TBoldElement): String; +class function TBoldOclSymbol.XString(Elem: TBoldElement): String; begin if assigned(elem) then result := Elem.AsString @@ -998,7 +995,7 @@ function TBoldOclSymbol.XString(Elem: TBoldElement): String; result := ''; end; -function TBoldOclSymbol.XType(Elem: TBoldElement): TBoldElementTypeInfo; +class function TBoldOclSymbol.XType(Elem: TBoldElement): TBoldElementTypeInfo; begin if elem is TBoldElementTypeInfo then result := TBoldElementTypeInfo(Elem) @@ -1006,7 +1003,7 @@ function TBoldOclSymbol.XType(Elem: TBoldElement): TBoldElementTypeInfo; result := nil; end; -function TBoldOclSymbol.XList(Elem: TBoldElement): tBoldList; +class function TBoldOclSymbol.XList(Elem: TBoldElement): tBoldList; begin if elem is TBoldList then result := TBoldList(Elem) @@ -1036,7 +1033,7 @@ constructor TBoldSymbolDictionary.Create(SystemTypeInfo: TBoldSystemTypeInfo; Bo SetIndexVariable(IX_SymbolName, AddIndex(TSymbolNameIndex.Create)); end; -destructor TBoldSymbolDictionary.Destroy; +destructor TBoldSymbolDictionary.destroy; begin FreeAndNil(fHelp); inherited; @@ -1044,7 +1041,7 @@ destructor TBoldSymbolDictionary.Destroy; function TBoldSymbolDictionary.GetSymbol(const Name: string): TBoldOclSymbol; begin - Result := TBoldOclSymbol(TSymbolNameIndex(indexes[IX_SymbolName]).FindByString(Name));; + Result := TBoldOclSymbol(TBoldStringHashIndex(indexes[IX_SymbolName]).FindByString(Name)); end; function TBoldSymbolDictionary.GetSymbolByIndex(index: Integer): TBoldOclSymbol; @@ -1066,6 +1063,18 @@ function TBoldOclEnvironment.GetBindings( result := TBoldOclVariableBinding(fList[index]) end; +function TBoldOclEnvironment.GetBindingsAsCommaText: string; +var + i: integer; + sl: TStringList; +begin + sl := TStringList.Create; + for I := 0 to Count - 1 do + Sl.Add(Bindings[i].VariableName); + result := sl.commaText; + sl.free; +end; + { TBoldOCLMomentLiteral } procedure TBoldOCLMomentLiteral.AcceptVisitor(V: TBoldOclVisitor); @@ -1107,10 +1116,39 @@ procedure TBoldOclTimeLiteral.SetDateTimeValue(const Value: TDateTime); fDateTimeValue := Value; end; -destructor TBoldOCLListCoercion.Destroy; +destructor TBoldOCLListCoercion.destroy; begin FreeAndNil(Child); inherited; end; +{ TBoldOclVariableBindingExternal } + +destructor TBoldOclVariableBindingExternal.Destroy; +begin + inherited; +end; + +function TBoldOclVariableBindingExternal.GetBoldType: TBoldElementTypeInfo; +begin + if Assigned(ExternalVariable) then + result := ExternalVariable.ValueType + else + result := nil; +end; + +{$WARNINGS OFF} +procedure InitDebugMethods; +var + env: TBoldOclEnvironment; +begin + Exit; + env.BindingsAsCommaText; // This is used to force compiler to include BindingsAsCommaText +end; +{$WARNINGS ON} + +initialization + TBoldSymbolDictionary.IX_SymbolName := -1; + InitDebugMethods; + end. diff --git a/Source/ObjectSpace/Ocl/BoldOclConstructors.inc b/Source/ObjectSpace/Ocl/BoldOclConstructors.inc index 5914d02..7adabf1 100644 --- a/Source/ObjectSpace/Ocl/BoldOclConstructors.inc +++ b/Source/ObjectSpace/Ocl/BoldOclConstructors.inc @@ -2,22 +2,22 @@ function MakeList( First : AYaccStackElement; Offs : integer ) : AYaccStackElement; begin - result := AYaccStackElement.CreateOffs( offs ); - result.List := TList.Create; - Result.List.Add( First.Clone ); + result := AYaccStackElement.CreateOffs( offs ); + result.List := TList.Create; + Result.List.Add( First.Clone ); end; function PushList( First, List : AYaccStackElement; Offs : integer ) : AYaccStackElement; begin - result := AYaccStackElement.CreateOffs( Offs ); - result.list := list.list; - result.list.insert( 0, first.clone ); + result := AYaccStackElement.CreateOffs( Offs ); + result.list := list.list; + result.list.insert( 0, first.clone ); end; function MakeEmptyList : AYaccStackElement; begin - result := AYaccStackElement.CreateOffs( 0 ); - result.List := TList.Create; + result := AYaccStackElement.CreateOffs( 0 ); + result.List := TList.Create; end; procedure ReleaseList( List : AYaccStackElement ); @@ -28,61 +28,70 @@ procedure ReleaseList( List : AYaccStackElement ); var i : integer; begin - if assigned( LIst.LIst ) then begin - for i := 0 to list.list.count-1 do begin - AYaccStackElement( List.List[i] ).free; - end; - list.list.free; - end; + if assigned( LIst.LIst ) then begin + for i := 0 to list.list.count-1 do begin + AYaccStackElement( List.List[i] ).free; + end; + list.list.free; + end; end; procedure RetrieveNodeList( ParseList : AYaccStackElement; var NodeList : TBoldOCLNodeList ); var - i : integer; + i, OldLength : integer; begin - if not assigned( ParseList ) then exit; - if assigned( ParseList.List ) then begin - if not assigned( Nodelist ) then - Nodelist := TBoldOCLNodeList.create; - for i := 0 to ParseList.List.Count-1 do - Nodelist.Add( AYaccStackElement( ParseList.List[i] ).Node ); - ReleaseList( ParseList ); - end; + if not assigned( ParseList ) then exit; + if assigned( ParseList.List ) then + begin + OldLength := Length(Nodelist); + SetLength(NodeList, OldLength + ParseList.List.Count); + for i := 0 to ParseList.List.Count-1 do + Nodelist[i+OldLength] := AYaccStackElement( ParseList.List[i] ).Node ; + ReleaseList( ParseList ); + end; end; function Make1Operation( const OpName : String; arg1 : AYaccStackElement; Offs : integer ) : AYaccStackElement; +var + OP: TBoldOclOperation; begin - result := AYaccStackElement.CreateOffs( Arg1.Offset ); - result.Node := TBoldOclOperation.Create; - Result.Node.Position := Offs; - TBoldOclOperation( result.Node ).args := TBoldOCLNodeList.create; - TBoldOclOperation( result.Node ).args.add( arg1.Node ); - TBoldOclOperation( result.Node ).OperationName := OpName; + result := AYaccStackElement.CreateOffs( Arg1.Offset ); + OP:= TBoldOclOperation.Create; + result.Node := OP; + Result.Node.Position := Offs; + SetLength(OP.args,1); + OP.args[0] := arg1.Node; + OP.OperationName := OpName; end; function Make2Operation(const OpName : String; arg1, arg2 : AYaccStackElement; Offs : integer ) : AYaccStackElement; +var + OP: TBoldOclOperation; begin - result := AYaccStackElement.CreateOffs( offs ); - result.Node := TBoldOclOperation.Create; - Result.Node.Position := Offs; - TBoldOclOperation( result.Node ).args := TBoldOClNodeList.create; - TBoldOclOperation( result.Node ).args.add( arg1.Node ); - TBoldOclOperation( result.Node ).args.add( arg2.Node ); - TBoldOclOperation( result.Node ).OperationName := OpName; + result := AYaccStackElement.CreateOffs( offs ); + OP:= TBoldOclOperation.Create; + result.Node := OP; + Result.Node.Position := Offs; + SetLength(OP.args,2); + OP.args[0] := arg1.Node; + OP.args[1] := arg2.Node; + OP.OperationName := OpName; end; function Make3Operation(const OpName : String; arg1, arg2, arg3 : AYaccStackElement; Offs : integer ) : AYaccStackElement; +var + OP: TBoldOclOperation; begin - result := AYaccStackElement.CreateOffs( offs ); - result.Node := TBoldOclOperation.Create; - Result.Node.Position := Offs; - - TBoldOclOperation( result.Node ).args := TBoldOCLNodeList.create; - TBoldOclOperation( result.Node ).args.add( arg1.Node ); - TBoldOclOperation( result.Node ).args.add( arg2.Node ); - TBoldOclOperation( result.Node ).args.add( arg3.Node ); - TBoldOclOperation( result.Node ).OperationName := OpName; + result := AYaccStackElement.CreateOffs( offs ); + OP:= TBoldOclOperation.Create; + result.Node := OP; + Result.Node.Position := Offs; + SetLength(OP.args,3); + OP.args[0] := arg1.Node; + OP.args[1] := arg2.Node; + OP.args[2] := arg3.Node; + OP.OperationName := OpName; end; function MakeUnaryMinus(const OpName : String; arg1 : AYaccStackElement; Offs : integer ) : AYaccStackElement; @@ -120,16 +129,25 @@ end; function MakeName( Name : AYaccStackElement; Offs : integer ) : AYaccStackElement; begin - result := AYaccStackElement.CreateOffs( Offs ); - Result.Name := BoldSharedStringManager.GetSharedString(Name.Lexeme.Buffer); - if Result.Name[1] in ['A'..'Z'] then Result.NameIsType := true; + result := AYaccStackElement.CreateOffs( Offs ); + {$IFDEF BOLD_UNICODE} + Result.Name := BoldSharedStringManager.GetSharedString(string(AnsiString(Name.Lexeme.Buffer))); + if CharInSet(Result.Name[1], ['A'..'Z']) then Result.NameIsType := true; + {$ELSE} + Result.Name := BoldSharedStringManager.GetSharedString(Name.Lexeme.Buffer); + if Result.Name[1] in ['A'..'Z'] then Result.NameIsType := true; + {$ENDIF} end; function MakeDeclarator( VarName, VarType : AYaccStackElement; Offs : integer ) : AYaccStackElement; begin result := AYaccStackElement.CreateOffs( Offs ); if assigned( varName ) then - result.Name := BoldSharedStringManager.GetSharedString(VarName.Lexeme.Buffer); + {$IFDEF BOLD_UNICODE} + result.Name := BoldSharedStringManager.GetSharedString(string(AnsiString(VarName.Lexeme.Buffer))); + {$ELSE} + result.Name := BoldSharedStringManager.GetSharedString(string(AnsiString(VarName.Lexeme.Buffer))); + {$ENDIF} if assigned( varType ) then begin result.DeclaratorTypeList := VarType.List; result.SimpleTypeSpecifierIsEnum := VarType.SimpleTypeSpecifierIsEnum; @@ -157,7 +175,6 @@ begin LiteralCollection.RangeStop := ExprListOrRange.Stop; end else begin LiteralCollection.IsRange := false; - LiteralCollection.Elements := TBoldOCLNodeList.Create; RetrieveNodeList( ExprListOrRange, LiteralCollection.Elements ); end; @@ -198,9 +215,13 @@ begin // value := TBAString.Create(nil); if assigned( Str ) then begin + {$IFDEF BOLD_UNICODE} + s := string(AnsiString(Str.Lexeme.Buffer)); + {$ELSE} s := Str.Lexeme.Buffer; - s := StringReplace(s, '\''', '''', [rfReplaceAll]); - s := StringReplace(s, '\\', '\', [rfReplaceAll]); + {$ENDIF} + s := StringReplace(s, '\''', '''', [rfReplaceAll]); + s := StringReplace(s, '\\', '\', [rfReplaceAll]); Node.StrValue := BoldSharedStringManager.GetSharedString(s); end else @@ -218,7 +239,11 @@ begin node := TBoldOCLIntLiteral.create; // value := TBAInteger.Create(nil); try + {$IFDEF BOLD_UNICODE} + Node.IntValue := StrToInt( string(AnsiString(Int.Lexeme.Buffer)) ); + {$ELSE} Node.IntValue := StrToInt( Int.Lexeme.Buffer ); + {$ENDIF} // value.MakeImmutable; except on eConvertError do @@ -232,13 +257,23 @@ end; function MakeLiteralDate(Date: AYaccStackElement; Offs: integer ) : AYaccStackElement; var node : TBoldOCLDateLiteral; + {$IFDEF BOLD_UNICODE} + sDate: string; + {$ENDIF} y, m, d: integer; begin result := AYaccStackElement.CreateOffs( offs ); node := TBoldOCLDateLiteral.create; + {$IFDEF BOLD_UNICODE} + sDate := string(AnsiString(Date.lexeme.buffer)); + y := StrToInt(copy(sDate, 2, 4)); + m := StrToInt(copy(sDate, 7, 2)); + d := StrToInt(copy(sDate, 10, 2)); + {$ELSE} y := StrToInt(copy(Date.lexeme.buffer, 2, 4)); m := StrToInt(copy(Date.lexeme.buffer, 7, 2)); d := StrToInt(copy(Date.lexeme.buffer, 10, 2)); + {$ENDIF} try Node.DateValue := EncodeDate(y, m, d); except @@ -251,16 +286,26 @@ end; function MakeLiteralTime(Time: AYaccStackElement; Offs: integer ) : AYaccStackElement; var - node : TBoldOCLDateLiteral; + node : TBoldOCLTimeLiteral; + {$IFDEF BOLD_UNICODE} + sTime: string; + {$ENDIF} h, m, s: integer; begin result := AYaccStackElement.CreateOffs( offs ); - node := TBoldOCLDateLiteral.create; + node := TBoldOCLTimeLiteral.create; + {$IFDEF BOLD_UNICODE} + sTime := string(AnsiString(Time.lexeme.buffer)); + h := StrToInt(copy(sTime, 2, 2)); + m := StrToInt(copy(sTime, 5, 2)); + s := StrToIntDef(copy(sTime, 8, 2), 0); + {$ELSE} h := StrToInt(copy(Time.lexeme.buffer, 2, 2)); m := StrToInt(copy(Time.lexeme.buffer, 5, 2)); s := StrToIntDef(copy(Time.lexeme.buffer, 8, 2), 0); + {$ENDIF} try - Node.DateValue := EncodeTime(h, m, s, 0); + Node.TimeValue := EncodeTime(h, m, s, 0); except on eConvertError do raise EBoldOCLAbort.CreateFmt( boeConversionError, [offs, Time.Lexeme.Buffer, 'Time']); @@ -281,12 +326,19 @@ begin node := TBoldOCLNumericLiteral.create; // value := TBAFloat.Create(nil); try + {$IFDEF BOLD_UNICODE} + TempFloatString := string(AnsiString(Float.Lexeme.Buffer)); + {$ELSE} TempFloatString := Float.Lexeme.Buffer; - if FormatSettings.DecimalSeparator <> '.' then TempFloatString[POs('.', TempFloatString)] := FormatSettings.DecimalSeparator; + {$ENDIF} + if {$IFDEF BOLD_DELPHI16_OR_LATER}FormatSettings.{$ENDIF}DecimalSeparator <> '.' then + begin + TempFloatString[POs('.', TempFloatString)] := {$IFDEF BOLD_DELPHI16_OR_LATER}FormatSettings.{$ENDIF}DecimalSeparator; + end; Node.FloatValue := StrTofloat( TempFloatString ); except on eConvertError do begin - raise EBoldOCLAbort.CreateFmt( boeConversionError, [offs, Float.Lexeme.Buffer, 'real']); + raise EBoldOCLAbort.CreateFmt( boeConversionError, [offs, Float.Lexeme.Buffer, 'real']); end; end; result.node := node; @@ -449,10 +501,10 @@ begin ReleaseList( Name ); end; - TBoldOclOperation( Result.Node ).args := TBoldOCLNodeList.Create; + SetLength(TBoldOclOperation( Result.Node ).args, 1); if assigned( Context ) then - TBoldoclOperation( Result.Node ).Args.Add( Context.Node ) + TBoldoclOperation( Result.Node ).Args[0] := Context.Node else raise EBoldOCLAbort.CreateFmt( boeOperationWithOutContext, [offs]); diff --git a/Source/ObjectSpace/Ocl/BoldOclError.pas b/Source/ObjectSpace/Ocl/BoldOclError.pas index 97ceafc..e05b11f 100644 --- a/Source/ObjectSpace/Ocl/BoldOclError.pas +++ b/Source/ObjectSpace/Ocl/BoldOclError.pas @@ -1,10 +1,12 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldOclError; interface uses SysUtils, - Classes, BoldDefs; resourceString @@ -42,7 +44,6 @@ interface boeVariableNotAssigned = '%d:This variable (%s) has no value or type'; boeSubscribeBeforeEval = '%d:You can not subscribe to an expression that has not been evaluated'; boeCollectionNotValidLiteral = '%d:You can not create a literal of type "Collection", try Set, Sequence or Bag instead'; -// boeTryingMemberOfNilPtr = '%d:Trying to take a member of a nil-reference'; boeElementnotConformToCollection = '%d:All elements in a collection literal must conform to a common type, this one doesn''t'; boeRangeMustBeInt = '%d:Ranges can only consist of integers'; boeInvalidCharacter = '%d:Expression contains an invalid character'; @@ -58,6 +59,7 @@ interface boeMemberofType = '%d:Types can not have members (tried %s.%s)'; boeMemberofAttr = '%d:Attributes can not have members (tried %s.%s)'; boeEnvSizeError = '%d:Started with %d vars, ended up with %d...'; + boeEnumValueNotFound = '%d:Enum value (%s) not found in any registed ValueSet'; {//} boeunknownExprtypeinDeduce = '%d:Unable to deduce type of expression ' + BOLDCRLF + {//} 'Operation: %s ' + BOLDCRLF + {//} '%s' + BOLDCRLF + @@ -65,10 +67,7 @@ interface boeOperationNotOclable = '%d:Operation %s is not OCLCompatible'; - // BoldOCLRunTimeErrors -// borteFirstOnEmptyList = 'Tried to take first element of an empty list'; -// borteLastOnEmptyList = 'Tried to take last element of an empty list'; borteAtIndexOutOfBounds = '%d:Tried to take element #%d of a list with %d elements'; borteDivisionByZero = '%d:Division By Zero'; borteInvalidCast = '%d:Invalid OCL-cast, tried to cast a %s to a %s'; @@ -82,7 +81,6 @@ interface type EBoldOCLAbort = class(EAbort) -// EBoldOCLAbort = class(Exception) public Position: integer; Ocl: String; @@ -107,6 +105,9 @@ EBoldOclRunTimeError = class(EBoldOclError); implementation +uses + BoldRev; + procedure EBoldOClAbort.FixError; begin if not errorFixed then @@ -148,5 +149,5 @@ function EBoldOClError.ErrorPointer: String; result := StringOfChar(' ', Position) + '^'; end; +initialization end. - diff --git a/Source/ObjectSpace/Ocl/BoldOclEvaluator.pas b/Source/ObjectSpace/Ocl/BoldOclEvaluator.pas index c5e86e5..f130902 100644 --- a/Source/ObjectSpace/Ocl/BoldOclEvaluator.pas +++ b/Source/ObjectSpace/Ocl/BoldOclEvaluator.pas @@ -1,9 +1,11 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldOclEvaluator; interface uses - Classes, BoldSystem, BoldSystemRT, BoldElements, @@ -21,6 +23,8 @@ TBoldOclEvaluatorVisitor = class(TBoldOclVisitor) fTimeType: TBoldAttributeTypeInfo; fDateType: TBoldAttributeTypeInfo; fFloatType: TBoldAttributeTypeInfo; + fBooleanType: TBoldAttributeTypeInfo; + fTrueBool: TBABoolean; CurrentSystem: tBoldSystem; fResubscribeAll: Boolean; function MakeNewString: TBAString; @@ -30,7 +34,7 @@ TBoldOclEvaluatorVisitor = class(TBoldOclVisitor) function MakeNewFloat: TBAFloat; function CreateNewMember(BoldType: TBoldElementTypeInfo): TBoldMember; public - constructor Create(Subscriber: TBoldSubscriber; ResubscribeAll: Boolean; SystemTypeInfo: TBoldSystemTypeInfo; BoldSystem: TBoldSystem; StringType, IntegerType, FloatType, DateType, TimeType: TBoldAttributeTypeInfo); + constructor Create(Subscriber: TBoldSubscriber; ResubscribeAll: Boolean; SystemTypeInfo: TBoldSystemTypeInfo; BoldSystem: TBoldSystem; TrueBool: TBABoolean; BooleanType, StringType, IntegerType, FloatType, DateType, TimeType: TBoldAttributeTypeInfo); procedure VisitTBoldOclListCoercion(N: TBoldOclListCoercion); override; procedure VisitTBoldOclMethod(N: TBoldOclmethod); override; @@ -38,27 +42,31 @@ TBoldOclEvaluatorVisitor = class(TBoldOclVisitor) procedure VisitTBoldOclIteration(N: TBoldOclIteration); override; procedure VisitTBoldOclMember(N: TBoldOclMember); override; procedure VisitTBoldOclVariableReference(N: TBoldOclVariableReference); override; - procedure VisitTBoldOclEnumLiteral(N: TBoldOclEnumLiteral); override; + procedure VisitTBoldOclENumLiteral(N: TBoldOclEnumLiteral); override; procedure VisitTBoldOclStrLiteral(N: TBoldOclStrLiteral); override; procedure VisitTBoldOclNumericLiteral(N: TBoldOclNumericLiteral); override; procedure VisitTBoldOclDateLiteral(N: TBoldOclDateLiteral); override; procedure VisitTBoldOclTimeLiteral(N: TBoldOclTimeLiteral); override; procedure VisitTBoldOclIntLiteral(N: TBoldOclIntLiteral); override; - procedure VisitTBoldOclCollectionLiteral(N: TBoldOclCollectionLiteral); override; + procedure VisitTBoldOclCollectionLIteral(N: TBoldOclCollectionLiteral); override; procedure SubScribeToElem(N: TBoldOclNode); end; +var + OclUseTemporaryDummyValue: boolean = true; + implementation uses + Classes, SysUtils, - BoldUtils, BoldDefs, BoldOclError, - BoldBase, - BoldCoreConsts; + BoldContainers, + BoldBase; -constructor TBoldOclEvaluatorVisitor.Create(Subscriber: TBoldSubscriber; ResubscribeAll: Boolean; SystemTypeInfo: TBoldSystemTypeInfo; BoldSystem: TBoldSystem; StringType, IntegerType, FloatType, DateType, TimeType: TBoldAttributeTypeInfo); +constructor TBoldOclEvaluatorVisitor.Create(Subscriber: TBoldSubscriber; ResubscribeAll: Boolean; SystemTypeInfo: TBoldSystemTypeInfo; + BoldSystem: TBoldSystem; TrueBool: TBABoolean; BooleanType, StringType, IntegerType, FloatType, DateType, TimeType: TBoldAttributeTypeInfo); begin inherited Create; CurrentSubscriber := Subscriber; @@ -69,10 +77,12 @@ constructor TBoldOclEvaluatorVisitor.Create(Subscriber: TBoldSubscriber; Resubsc fFloatType := FloatType; fDAteType := DateType; fTimeType := TimeType; + fBooleanType := BooleanType; + fTrueBool := TrueBool; fResubscribeAll := ResubscribeAll; end; -function MapResubscribe(Resubscribe: Boolean): TBoldRequestedEvent; +function MapResubscribe(Resubscribe: Boolean): TBoldRequestedEvent; {$IFDEF BOLD_INLINE} inline; {$ENDIF} begin if Resubscribe then Result := breReSubscribe @@ -81,56 +91,91 @@ function MapResubscribe(Resubscribe: Boolean): TBoldRequestedEvent; end; type - TBoldOCLSortClass = class(TBoldMemoryManagedObject) + PBoldOCLSortData = ^TBoldOCLSortData; + TBoldOCLSortData = record SortArg: TBoldElement; SortObj: TBoldElement; end; + TBoldOCLSortArray = class(TBoldArray) + private + function Get(Index: Integer): TBoldOCLSortData; + procedure Put(Index: Integer; Item: TBoldOCLSortData); + protected + function GetItemSize: Integer; override; + public + property Items[Index: Integer]: TBoldOCLSortData read Get write Put; default; + end; + +function TBoldOCLSortArray.Get(Index: Integer): TBoldOCLSortData; +begin + inherited Get(Index,Result); +end; + +function TBoldOCLSortArray.GetItemSize: Integer; +begin + Result := SizeOf(TBoldOCLSortData); +end; + +procedure TBoldOCLSortArray.Put(Index: Integer; Item: TBoldOCLSortData); +begin + inherited Put(Index, Item); +end; + function BoldOCLInternalSortWrapper(Item1, Item2: Pointer): Integer; begin - Result := TBoldOCLSortClass(Item1).SortArg.CompareTo(TBoldOCLSortClass(Item2).SortArg); + Result := PBoldOCLSortData(Item1).SortArg.CompareTo(PBoldOCLSortData(Item2).SortArg); end; function BoldOCLInternalReverseSortWrapper(Item1, Item2: Pointer): Integer; begin - Result := - TBoldOCLSortClass(Item1).SortArg.CompareTo(TBoldOCLSortClass(Item2).SortArg); + Result := - PBoldOCLSortData(Item1).SortArg.CompareTo(PBoldOCLSortData(Item2).SortArg); end; procedure Sortlist(Node: TBoldOclIteration; BoldList: TBoldList; SortKeyHolder: TBoldIndirectElement; Order: TBoldOclIteratorSpecifier); var - Sortlist: TList; - SortObj: TBoldOCLSortClass; + SortList: TBoldOCLSortArray; + SortData: TBoldOCLSortData; i : Integer; arglist: TBoldList; NewList: TBoldList; begin - arglist := SortKeyHolder.Value as TBoldList; - Sortlist := TList.Create; - for i := 0 to BoldList.Count - 1 do begin - SortObj := TBoldOCLSortClass.Create; - SortObj.SortArg := arglist[i]; - SortObj.SortObj := BoldList[i]; - Sortlist.Add(Pointer(SortObj)); - end; + case BoldList.Count of + 0: ; + 1: (node.Value as TBoldList).Add(BoldList[0]); + else + begin + arglist := SortKeyHolder.Value as TBoldList; + SortList := TBoldOCLSortArray.Create(BoldList.Count, []); + try + SortList.Count := BoldList.Count; + for i := 0 to BoldList.Count - 1 do begin + SortData.SortArg := ArgList[i]; + SortData.SortObj := BoldList[i]; + SortList[i] := SortData; + end; - case Order of - OclOrderBy: Sortlist.SORT(BoldOCLInternalSortWrapper); - OclOrderDescending: Sortlist.SORT(BoldOCLInternalReverseSortWrapper); - end; + case Order of + OclOrderBy: SortList.Sort(BoldOCLInternalSortWrapper); + OclOrderDescending: SortList.Sort(BoldOCLInternalReverseSortWrapper); + end; - NewList := node.Value as TBoldLIst; + NewList := node.Value as TBoldLIst; - for i := 0 to BoldList.Count - 1 do begin - NewList.Add(TBoldOCLSortClass(Sortlist[i]).SortObj); - TBoldOCLSortClass(Sortlist[i]).Free; + for i := 0 to BoldList.Count - 1 do begin + SortData := SortList[i]; + NewList.Add(SortData.SortObj); + end; + finally + Sortlist.Free; + end; + end; end; - Sortlist.Free; end; procedure TBoldOclEvaluatorVisitor.SubScribeToElem(N: TBoldOclNode); begin - // to avoid putting a default-subscribe on objects (which will subscribe to all members - // if n.resubscribe and (n.value is TBoldObject) then exit; + if assigned(N.Value) and assigned(CurrentSubscriber) and not n.OwnsValue then N.Value.DefaultSubscribe(CurrentSubscriber, MapResubscribe(N.Resubscribe or fResubscribeAll)) end; @@ -171,56 +216,63 @@ procedure TBoldOclEvaluatorVisitor.VisitTBoldOclmethod(N: TBoldOclMethod); end; procedure TBoldOclEvaluatorVisitor.VisitTBoldOclOperation(N: TBoldOclOperation); + + procedure ClearIfReferenced(ie: TBoldIndirectElement); + begin + if not ie.OwnsValue then + ie.SetReferenceValue(nil); + + end; var i : Integer; backupResubscribeAll: Boolean; OperationParams: TBoldOclSymbolParameters; + ArgI: TBoldOclNode; begin - if SameText(N.OperationName, 'if') then // do not localize - begin - backupResubscribeAll := fResubscribeAll; - fResubscribeAll := True; - N.Args[0].AcceptVisitor(self); - fResubscribeAll := backupResubscribeAll; - if assigned(n.args[0].value) and (N.Args[0].Value as TBABoolean).AsBoolean then - N.Args[1].AcceptVisitor(self) - else - N.Args[2].AcceptVisitor(self); - end - else if SameText(N.OperationName, 'except') then // do not localize - begin - backupResubscribeAll := fResubscribeAll; - fResubscribeAll := True; - try + case N.Symbol.GetShortCircuitType of + csIf: + begin + backupResubscribeAll := fResubscribeAll; + fResubscribeAll := True; N.Args[0].AcceptVisitor(self); - N.Args[0].TransferValue(N); - except - // if an exception occurs, go for the alternative and silence the exception - N.Args[1].AcceptVisitor(self); - N.Args[1].TransferValue(N); + fResubscribeAll := backupResubscribeAll; + if assigned(n.args[0].value) and (N.Args[0].Value as TBABoolean).AsBoolean then + begin + N.Args[1].AcceptVisitor(self); + ClearIfReferenced(N.Args[2]); + end + else + begin + N.Args[2].AcceptVisitor(self); + ClearIfReferenced(N.Args[1]); + end; + end; + + csOr: + begin + fResubscribeAll := True; + N.Args[0].AcceptVisitor(self); + if (not assigned(n.args[0].value)) or not (N.Args[0].Value as TBABoolean).AsBoolean then + N.Args[1].AcceptVisitor(self) + else + ClearIfReferenced(N.Args[1]); + end; + + csAnd: + begin + fResubscribeAll := True; + N.Args[0].AcceptVisitor(self); + if assigned(n.args[0].value) and (N.Args[0].Value as TBABoolean).AsBoolean then + N.Args[1].AcceptVisitor(self) + else + ClearIfReferenced(N.Args[1]); + end; + + else + begin + for i := 0 to Length(N.Args) - 1 do + N.Args[i].AcceptVisitor(self); end; - fResubscribeAll := backupResubscribeAll; - SubScribeToElem(N); - exit; - end - else if SameText(N.OperationName, 'or') then // do not localize - begin - fResubscribeAll := True; - N.Args[0].AcceptVisitor(self); - if (not assigned(n.args[0].value)) or not (N.Args[0].Value as TBABoolean).AsBoolean then - N.Args[1].AcceptVisitor(self) - end - else if SameText(N.OperationName, 'and') then // do not localize - begin - fResubscribeAll := True; - N.Args[0].AcceptVisitor(self); - if assigned(n.args[0].value) and (N.Args[0].Value as TBABoolean).AsBoolean then - N.Args[1].AcceptVisitor(self) - end - else - begin - for i := 0 to N.Args.Count - 1 do - N.Args[i].AcceptVisitor(self); end; try @@ -228,35 +280,46 @@ procedure TBoldOclEvaluatorVisitor.VisitTBoldOclOperation(N: TBoldOclOperation); try for i := 0 to n.Symbol.numberOfArgs-1 do begin - if not assigned(n.args[i].value) and (n.args[i].BoldType is TBoldAttributeTypeInfo) and - not (n.args[i].BoldType as TBoldAttributeTypeInfo).IsAbstract then + Argi := n.args[i]; + if not assigned(Argi.value) and (Argi.BoldType is TBoldAttributeTypeInfo) and + not (Argi.BoldType as TBoldAttributeTypeInfo).IsAbstract then begin - n.args[i].SetOwnedValue(TBoldMemberFactory.CreateMemberFromBoldType(n.args[i].BoldType)); - n.args[i].HastemporaryDummyValue := true; - end; - if n.args[i].value is tBoldObjectReference then - OperationParams.values[i] := (n.args[i].value as tBoldObjectReference).BoldObject + if Argi.BoldType = fBooleanType then + Argi.SetReferenceValue(fTrueBool) + else + begin + if OclUseTemporaryDummyValue then + begin + Argi.SetOwnedValue(TBoldMemberFactory.CreateMemberFromBoldType(Argi.BoldType)); + Argi.HasTemporaryDummyValue := true; + end + else + Argi.SetReferenceValue(nil); + end; + end + else if Argi.value is TBoldObjectReference then + OperationParams.values[i] := (Argi.value as TBoldObjectReference).BoldObject else - OperationParams.values[i] := n.args[i].value; - OperationParams.Nodes[i] := n.args[i]; + OperationParams.values[i] := Argi.value; + OperationParams.Nodes[i] := Argi; end; OperationParams.Result := N; OperationParams.SubScriber := CurrentSubscriber; OperationParams.System := CurrentSystem; OperationParams.SystemTypeInfo := CurrentSystemTypeInfo; n.Symbol.Evaluate(OperationParams); - + if OPerationParams.result.OwnsValue and assigned(OPerationParams.result.value) then OPerationParams.result.Value.MakeImmutable; finally - // if-statements don't evaluate all arguments, so we must throw away the rest so that literals can be reevaluated the next time. for i := 0 to n.Symbol.numberOfArgs-1 do begin - if n.args[i].HastemporaryDummyValue then + Argi := n.args[i]; + if Argi.HasTemporaryDummyValue then begin - n.args[i].SetReferenceValue(nil); - n.args[i].HastemporaryDummyValue := false; + Argi.SetReferenceValue(nil); + Argi.HasTemporaryDummyValue := false; end; end; end; @@ -268,9 +331,8 @@ procedure TBoldOclEvaluatorVisitor.VisitTBoldOclOperation(N: TBoldOclOperation); end; end; - if assigned(n.value) and not assigned(n.value.Boldtype) then + if assigned(n.value) and not assigned(n.value.Boldtype) and not (n.Value is TBAValueSetValue) then // TBAValueSetValue does not have a type by design raise EBoldInternal.CreateFmt('Result of evaluation of operation %s has no type', [n.OperationName]); -// n.value.BoldType := n.ExpressionType; SubScribeToElem(N); end; @@ -324,8 +386,6 @@ procedure TBoldOclEvaluatorVisitor.VisitTBoldOclIteration(N: TBoldOclIteration); SortKeyHolder := TBoldOclNode.Create; SortKeys := TBoldMemberList.Create; SortKeys.DuplicateMode := bldmAllow; - - // if the sort argument is not a real member (has RTinfo) then we must clone it SortArgIsRTMember := (N.Args[1] is TBoldOclMember) and Assigned((N.Args[1] as TBoldOclMember).RTInfo); SortKeys.CloneMembers := not SortArgIsRTMember; @@ -345,8 +405,7 @@ procedure TBoldOclEvaluatorVisitor.VisitTBoldOclIteration(N: TBoldOclIteration); begin for i := Sortkeys.Count-1 downto 0 do begin - // if we had to create dummy-sortkeys that are not owned by the list, - // we must take care of them here + if not assigned(Sortkeys[i].OwningObject) then begin TempSortKey := SortKeys[i]; @@ -388,7 +447,7 @@ procedure TBoldOclEvaluatorVisitor.VisitTBoldOclIteration(N: TBoldOclIteration); List.EnsureRange(0, List.Count-1); for i := 0 to List.Count - 1 do begin - n.LoopVar.BoldType := nil; // reset static boldtype + n.LoopVar.BoldType := nil; N.LoopVar.SetReferenceValue(List[i]); N.Args[1].AcceptVisitor(self); OperationParams.values[0] := n.args[1].Value; @@ -413,7 +472,7 @@ procedure TBoldOclEvaluatorVisitor.VisitTBoldOclMember(N: TBoldOclMember); Role: TBoldObjectList; begin MemberList := TBoldMemberList.Create; - for i := 0 to n.Qualifier.count-1 do + for i := 0 to Length(n.Qualifier)-1 do MemberList.Add(n.Qualifier[i].value as TBoldMember); role := Obj.BoldMembers[n.MemberIndex] as TBoldObjectList; if assigned(CurrentSubscriber) then @@ -434,6 +493,7 @@ procedure TBoldOclEvaluatorVisitor.VisitTBoldOclMember(N: TBoldOclMember); Result := CreateNewMember(n.BoldType) as TBoldMemberList; Result.DuplicateMode := bldmAllow; index := N.memberindex; + Result.Capacity := OldObjectList.Count; for i := 0 to OldObjectList.Count - 1 do begin LoopObject := OldObjectList[i]; Result.Add(LoopObject.BoldMembers[index]); @@ -452,7 +512,7 @@ procedure TBoldOclEvaluatorVisitor.VisitTBoldOclMember(N: TBoldOclMember); function retrieveMultiLink: TBoldObjectList; var - i, j : Integer; + i : Integer; roleList: TBoldObjectList; tempSystem: TBoldSystem; begin @@ -467,7 +527,7 @@ procedure TBoldOclEvaluatorVisitor.VisitTBoldOclMember(N: TBoldOclMember); Result := CreateNewMember(n.BoldType) as TBoldObjectList; Result.DuplicateMode := bldmAllow; if assigned(n.Qualifier) then - for i := 0 to N.qualifier.Count - 1 do + for i := 0 to Length(N.qualifier) - 1 do N.Qualifier[i].AcceptVisitor(self); for i := 0 to OldObjectList.Count - 1 do @@ -480,9 +540,7 @@ procedure TBoldOclEvaluatorVisitor.VisitTBoldOclMember(N: TBoldOclMember); roleList := LoopObject.BoldMembers[N.memberindex] as TBoldObjectList; if assigned(CurrentSubscriber) then roleList.DefaultSubscribe(CurrentSubscriber, MapResubscribe(N.Resubscribe)); - - for J := 0 to roleList.Count - 1 do - Result.Add(roleList[J]); + Result.AddList(roleList); end; end; end; @@ -517,7 +575,7 @@ procedure TBoldOclEvaluatorVisitor.VisitTBoldOclMember(N: TBoldOclMember); begin N.MemberOf.AcceptVisitor(self); - if assigned(n.MemberOf.value) then begin + if assigned(n.MemberOf.value) then begin // and not ((n.MemberOf.Value is TBoldObjectReference) and (n.TBoldObjectReference(MemberOf.Value).BoldObject = nil)) case N.MemberOf.Value.BoldType.BoldValueType of bvtSystem: N.SetReferenceValue(retrieveClass); bvtClass: begin @@ -527,13 +585,13 @@ procedure TBoldOclEvaluatorVisitor.VisitTBoldOclMember(N: TBoldOclMember); else if N.MemberOf.Value is TBoldObject then Obj := TBoldObject(N.MemberOf.Value) else if assigned(n.Memberof.Value) then - raise EBold.CreateFmt(sUnknownTypeOfMemberOf,[N.MemberOf.Value.ClassName]); + raise EBold.CreateFmt('unknown type of memberof: %s',[N.MemberOf.Value.ClassName]); - if assigned(Obj) then + if assigned(Obj) and assigned(Obj.BoldObjectLocator) then begin if assigned(n.Qualifier) then begin - for i := 0 to N.qualifier.Count - 1 do + for i := 0 to Length(N.qualifier) - 1 do N.Qualifier[i].AcceptVisitor(self); n.SetReferenceValue(RetrieveQualifiedSingle(obj)); end else @@ -555,11 +613,11 @@ procedure TBoldOclEvaluatorVisitor.VisitTBoldOclMember(N: TBoldOclMember); bvtAttr: N.SetOwnedValue(retrieveAttribute); bvtClass: N.SetOwnedValue(RetrieveSingleLink); bvtList: N.SetOwnedValue(retrieveMultiLink) - else raise EBold.CreateFmt(sUnknownTypeOfMember,[N.MemberType.ClassName]); + else raise EBold.CreateFmt('unknown type of member: %s',[N.MemberType.ClassName]); end; end; else - raise EBold.CreateFmt(sUnknownTypeOfMember,[N.MemberOf.Value.BoldType.ClassName]); + raise EBold.CreateFmt('unknown type of member: %s',[N.MemberOf.Value.BoldType.ClassName]); end; SubScribeToElem(N); @@ -574,14 +632,15 @@ procedure TBoldOclEvaluatorVisitor.VisitTBoldOclVariableReference(N: TBoldOclVar VariableValue := N.VariableBinding.Value; N.SetReferenceValue(VariableValue); if assigned(currentSubscriber) and Assigned(VariableValue) then - VariableValue.DefaultSubscribe(CurrentSubscriber, MapResubscribe(N.Resubscribe or fResubscribeAll)); // CHECKME -// Har fattas väl ett abbonememang på variablen som sådan?? Går bra så länge variablerna är konstanter. -// Janne + VariableValue.DefaultSubscribe(CurrentSubscriber, MapResubscribe(N.Resubscribe or fResubscribeAll)); + + end; procedure TBoldOclEvaluatorVisitor.VisitTBoldOclENumLiteral(N: TBoldOclEnumLiteral); begin - + if not assigned(n.value) then + n.SetReferenceValue(CurrentSystemTypeInfo.FindValueSetByName(N.Name)); end; procedure TBoldOclEvaluatorVisitor.VisitTBoldOclCollectionLIteral(N: TBoldOclCollectionLiteral); @@ -605,13 +664,12 @@ procedure TBoldOclEvaluatorVisitor.VisitTBoldOclCollectionLIteral(N: TBoldOclCol raise EBoldOclRunTimeError.CreateFmt(boertRangeNotAssigned, [n.RangeStart.Position]); tempInteger := MakeNewInteger; -// TempInteger.BoldType := N.RangeStart.BoldType; for i := (N.RangeStart.Value as TBAInteger).AsInteger to (N.RangeStop.Value as TBAInteger).AsInteger do begin TempInteger.AsInteger := i; BoldList.Add(tempInteger); end; end else begin - for i := 0 to N.Elements.Count - 1 do begin + for i := 0 to Length(N.Elements) - 1 do begin N.Elements[i].AcceptVisitor(self); BoldList.Add(N.Elements[i].Value); end; @@ -705,4 +763,6 @@ function TBoldOclEvaluatorVisitor.MakeNewTime: TBATime; result := CreateNewMember(fTimeType) as TBATime; end; +initialization + end. diff --git a/Source/ObjectSpace/Ocl/BoldOclLightWeightNodeMaker.pas b/Source/ObjectSpace/Ocl/BoldOclLightWeightNodeMaker.pas index 2335a5b..62c67ff 100644 --- a/Source/ObjectSpace/Ocl/BoldOclLightWeightNodeMaker.pas +++ b/Source/ObjectSpace/Ocl/BoldOclLightWeightNodeMaker.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldOclLightWeightNodeMaker; interface @@ -62,8 +65,8 @@ implementation SysUtils, BoldDefs, BoldElements, - BoldCoreConsts, - BoldAttributes; + BoldAttributes, + BoldOcl; { TBoldOLWNodeMaker } @@ -77,13 +80,15 @@ constructor TBoldOLWNodeMaker.create(OclRootNode: TBoldOclNode; SystemTypeInfo: fEnv := Env; if not (OclRootNode.BoldType is TBoldListTypeInfo) or not OclRootNode.BoldType.ConformsTo(SystemTypeInfo.RootClassTypeInfo.ListTypeInfo) then - SetFailure(0, format(sPSResultMustBeObjectList, [OclRootNode.BoldType.AsString])); - + begin + if not (OclRootNode.BoldType is TBoldClassTypeInfo) or not OclRootNode.BoldType.ConformsTo(SystemTypeInfo.RootClassTypeInfo) then + SetFailure(0, format('Result of PS-evaluation must be an objectlist (was type: %s)', [OclRootNode.BoldType.AsString])); + end; if not assigned(System) then - SetFailure(0, sPSEvalrequiresSystem); + SetFailure(0, 'PS-evaluation can not be performed without a system'); end; -destructor TBoldOLWNodeMaker.Destroy; +destructor TBoldOLWNodeMaker.destroy; var i: integer; begin @@ -121,7 +126,7 @@ function TBoldOLWNodeMaker.OLWBindingForVarBinding( procedure TBoldOLWNodeMaker.VisitTBoldOclCollectionLIteral(N: TBoldOclCollectionLIteral); begin - SetFailure(n.Position, sCollectionLiteralsNotSupported); + SetFailure(n.Position, 'OLWNodes does not support CollectionLiterals'); end; procedure TBoldOLWNodeMaker.VisitTBoldOclEnumLiteral(N: TBoldOclEnumLiteral); @@ -143,7 +148,7 @@ procedure TBoldOLWNodeMaker.VisitTBoldOclIteration(N: TBoldOclIteration); OLWIteration := TBoldOLWIteration.create(n.Position, n.OperationName, RootNode as TBoldOLWVariableBinding); - for i := 0 to n.Args.Count-1 do + for i := 0 to Length(n.Args)-1 do begin n.Args[i].AcceptVisitor(self); OLWIteration.Args.Add(RootNode); @@ -172,7 +177,7 @@ procedure TBoldOLWNodeMaker.VisitTBoldOclMember(N: TBoldOclMember); begin inherited; n.MemberOf.AcceptVisitor(self); - IsBoolean := n.BoldType.ConformsTo(((n.BoldType.SystemTypeInfo) as TBoldSystemTypeInfo).AttributeTypeInfoByExpressionName['Boolean']); // do not localize + IsBoolean := n.BoldType.ConformsTo(TBoldOCL(n.BoldType.evaluator).BooleanType); OLWMember := TBoldOLWMember.Create(n.Position, n.MemberName, n.MemberIndex, RootNode, IsBoolean); if not n.RTInfo.Persistent then @@ -188,11 +193,11 @@ procedure TBoldOLWNodeMaker.VisitTBoldOclMember(N: TBoldOclMember); end; end; if not EffectivePersistent then - SetFailure(n.Position, format(sTransientMembersCannoteUsed, [n.RTInfo.ExpressionName])); + SetFailure(n.Position, format('Non persistent members (%s) can not be used in OLWNodes', [n.RTInfo.ExpressionName])); end; if assigned(n.Qualifier) then - for i := 0 to n.Qualifier.Count-1 do + for i := 0 to Length(n.Qualifier)-1 do begin n.Qualifier[i].AcceptVisitor(self); OLWMember.Qualifier.Add(RootNode); @@ -202,12 +207,11 @@ procedure TBoldOLWNodeMaker.VisitTBoldOclMember(N: TBoldOclMember); procedure TBoldOLWNodeMaker.VisitTBoldOclMethod(N: TBoldOclMethod); begin - SetFailure(n.Position, sMethodsNotSupported); + SetFailure(n.Position, 'OLWNodes does not support methods'); end; procedure TBoldOLWNodeMaker.VisitTBoldOclNode(N: TBoldOclNode); begin - // abstract class end; procedure TBoldOLWNodeMaker.VisitTBoldOclNumericLiteral(N: TBoldOclNumericLiteral); @@ -225,11 +229,12 @@ procedure TBoldOLWNodeMaker.VisitTBoldOclOperation(N: TBoldOclOperation); LiteralType: TBoldElementTypeInfo; BooleanType: TBoldAttributeTypeInfo; ValueSet: TBAValueSet; + ValueSetValue: TBAValueSetValue; begin if n.ClassType = TBoldOclOperation then begin OLWOperation := TBoldOLWOperation.create(n.Position, n.OperationName); - for i := 0 to n.Args.Count-1 do + for i := 0 to Length(n.Args)-1 do begin n.Args[i].AcceptVisitor(self); OLWOperation.Args.Add(RootNode); @@ -257,30 +262,39 @@ procedure TBoldOLWNodeMaker.VisitTBoldOclOperation(N: TBoldOclOperation); Literal := OLWOperation.args[1] as TBoldOLWEnumLiteral; end; - BooleanType := (n.Boldtype.SystemTypeInfo as TBoldSystemTypeInfo).AttributeTypeInfoByExpressionName['Boolean']; // do not localize + BooleanType := TBoldOCL(n.BoldType.evaluator).BooleanType; if n.args[0].BoldType.ConformsTo(BooleanType) and n.args[1].BoldType.ConformsTo(BooleanType) then - SetFailure(n.Position, sUseBooleanOperations); + SetFailure(n.Position, 'Can not compare two booleans to each other with "=" or "<>", use boolean operations instead'); if assigned(Literal) then begin if LiteralType.ConformsTo(BooleanType) then - SetFailure(n.Position, sUseBooleanOperationsWithLiterals); + SetFailure(n.Position, 'Can not compare boolean values to literals when converting to SQL, use boolean operations instead'); - if LiteralType.ConformsTo((LiteralType.SystemTypeInfo as TBoldSystemTypeInfo).AttributeTypeInfoByExpressionName['ValueSet']) then // do not localize + if LiteralType.ConformsTo((LiteralType.SystemTypeInfo as TBoldSystemTypeInfo).ValueSetTypeInfo) then begin ValueSet := TBoldMemberFactory.CreateMemberFromBoldType(LiteralType) as TBAValueSet; - if assigned(ValueSet.Values.FindByString(brDefault, LiteralName)) then - begin - ValueSet.AsString := LIteralName; - Literal.IntValue := ValueSet.AsInteger; - end - else - SetFailure(n.Position, format(sEnumNameNotValid, [LiteralName, LiteralType.ExpressionName])); + try + // Do not compare default representation on first place, because it is not + // well suited for a comparison. Instead first compare short representation, + // which should be used to represent the enum value itself, instead of a translation. + ValueSetValue := ValueSet.Values.FindByString(brShort, LiteralName); + if ValueSetValue = nil then begin + ValueSetValue := ValueSet.Values.FindByString(brDefault, LiteralName); + end; + if Assigned(ValueSetValue) then begin + Literal.IntValue := ValueSetValue.AsInteger; + end else begin + SetFailure(n.Position, format('EnumName (%s) not valid for %s', [LiteralName, LiteralType.ExpressionName])); + end; + finally + ValueSet.Free; + end; end else - SetFailure(n.Position, format(sEnumComparedToNonEnum, [LiteralName, LiteralType.ExpressionName])); + SetFailure(n.Position, format('Enum (%s) compared to a non Enum (%s)', [LiteralName, LiteralType.ExpressionName])); end; end; end; @@ -297,7 +311,7 @@ procedure TBoldOLWNodeMaker.VisitTBoldOclTypeNode(N: TBoldOclTypeNode); if n.Value is TBoldClassTypeInfo then fRootNode := TBoldOLWTypeNode.Create(n.Position, N.typeName, (n.Value as TBoldClassTypeInfo).TopSortedIndex) else - SetFailure(n.Position, Format(sTypeNotSupported, [n.TypeName])); + SetFailure(n.Position, 'OLWNodes does not support the type ' + n.TypeName); end; procedure TBoldOLWNodeMaker.VisitTBoldOclVariableBinding(N: TBoldOclVariableBinding); @@ -332,7 +346,7 @@ procedure TBoldOLWNodeMaker.VisitTBoldOclVariableBinding(N: TBoldOclVariableBind VarBind.ExternalVarvalue := -1; end else if n.Value is TBoldAttribute then - VarBind.ExternalVarvalue := n.Value.GetAsVariant; + VarBind.ExternalVarvalue := n.Value.AsVariant; Varbindings.Add(n); OLWvarBindings.Add(VarBind); @@ -343,7 +357,7 @@ procedure TBoldOLWNodeMaker.VisitTBoldOclVariableBinding(N: TBoldOclVariableBind else begin fRootNode := TBoldOLWVariableBinding.Create(N.Position, n.VariableName, -1); - setFailure(n.Position, Format(sLoopVariablesMustBeClassType, [n.BoldType.AsString])); + setFailure(n.Position, Format('LoopVariables can only have class type, not %s', [n.BoldType.AsString])); end; end; @@ -375,4 +389,5 @@ procedure TBoldOLWNodeMaker.VisitTBoldOclTimeLiteral( fRootNode := TBoldOLWTimeLiteral.Create(n.Position, n.TimeValue); end; +initialization end. diff --git a/Source/ObjectSpace/Ocl/BoldOclLightWeightNodes.pas b/Source/ObjectSpace/Ocl/BoldOclLightWeightNodes.pas index 4441804..59508f0 100644 --- a/Source/ObjectSpace/Ocl/BoldOclLightWeightNodes.pas +++ b/Source/ObjectSpace/Ocl/BoldOclLightWeightNodes.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldOclLightWeightNodes; interface @@ -67,15 +70,15 @@ TBoldOLWNodeList = class(TBoldNonRefCountedObject, IBoldStreamable) private fList: TList; fOwnsObjects: Boolean; - function GetItem(index: Integer): TBoldOLWNode; - procedure PutItem(index: Integer; Value: TBoldOLWNode); + function GetItem(index: Integer): TBoldOLWNode; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + procedure PutItem(index: Integer; Value: TBoldOLWNode); {$IFDEF BOLD_INLINE}inline;{$ENDIF} function GetStreamName: string; - function GetCount: integer; - function GetIndexOf(Node: TBoldOLWNode): integer; + function GetCount: integer; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function GetIndexOf(Node: TBoldOLWNode): integer; {$IFDEF BOLD_INLINE}inline;{$ENDIF} public constructor Create; destructor Destroy; override; - function Add(Item: TBoldOLWNode): Integer; + function Add(Item: TBoldOLWNode): Integer; {$IFDEF BOLD_INLINE}inline;{$ENDIF} procedure TraverseList(V: TBoldOLWNodeVisitor); virtual; property Items[index: Integer]: TBoldOLWNode read GetItem write PutItem; default; property Count: integer read GetCount; @@ -83,6 +86,7 @@ TBoldOLWNodeList = class(TBoldNonRefCountedObject, IBoldStreamable) property OwnsObjects: Boolean read fOwnsObjects write fOwnsObjects; end; + TBoldOLWNode = class(TBoldNonRefCountedObject, IBoldStreamable) private fPosition: integer; @@ -94,6 +98,7 @@ TBoldOLWNode = class(TBoldNonRefCountedObject, IBoldStreamable) property Position: Integer read fPosition; end; + TBoldOLWTypeNode = class(TBoldOLWNode) private fTypeName: String; @@ -213,7 +218,7 @@ TBoldOLWStrLiteral = class(TBoldOLWLiteral) end; TBoldOLWMomentLiteral = class(TBoldOLWLiteral) - private + protected fMomentValue: TDateTime; public constructor Create(Position: integer; MomentValue: TDateTime); @@ -221,24 +226,20 @@ TBoldOLWMomentLiteral = class(TBoldOLWLiteral) TBoldOLWDateLiteral = class(TBoldOLWMomentLiteral) private - function GetDateValue: TDateTime; - procedure SetDateValue(const Value: TDateTime); protected function GetStreamName: string; override; public procedure AcceptVisitor(V: TBoldOLWNodeVisitor); override; - property DateValue: TDateTime read GetDateValue write SetDateValue; + property DateValue: TDateTime read fMomentValue write fMomentValue; end; TBoldOLWTimeLiteral = class(TBoldOLWMomentLiteral) private - function GetTimeValue: TDateTime; - procedure SetTimeValue(const Value: TDateTime); protected function GetStreamName: string; override; public procedure AcceptVisitor(V: TBoldOLWNodeVisitor); override; - property TimeValue: TDateTime read GetTimeValue write SetTimeValue; + property TimeValue: TDateTime read fMomentValue write fMomentValue; end; @@ -282,10 +283,9 @@ implementation uses SysUtils, - MSXML_TLB, + {$IFDEF OXML}OXmlPDOM{$ELSE}MSXML_TLB{$ENDIF}, BoldXMLStreaming, BoldDefaultStreamNames, - BoldCoreConsts, BoldDefs; const @@ -309,7 +309,6 @@ implementation type TBoldXMLOCLConditionStreamer = class(TBoldXMLConditionWithClassStreamer) - // RootNode, Context, Env, OclExpr protected function GetStreamName: string; override; public @@ -329,14 +328,12 @@ TBoldXMLOLWNodeListStreamer = class(TBoldXMLObjectStreamer) TBoldXMLOLWNodeStreamer = class(TBoldXMLObjectStreamer) - // Position public procedure WriteObject(Obj: TBoldInterfacedObject; Node: TBoldXMLNode); override; procedure ReadObject(Obj: TObject; Node: TBoldXMLNode); override; end; TBoldXMLOLWTypeNodeStreamer = class(TBoldXMLOLWNodeStreamer) - // TypeName, TopSortedIndex protected function GetStreamName: string; override; public @@ -346,7 +343,6 @@ TBoldXMLOLWTypeNodeStreamer = class(TBoldXMLOLWNodeStreamer) end; TBoldXMLOLWListCoercionStreamer = class(TBoldXMLOLWNodeStreamer) - // Child protected function GetStreamName: string; override; public @@ -356,7 +352,6 @@ TBoldXMLOLWListCoercionStreamer = class(TBoldXMLOLWNodeStreamer) end; TBoldXMLOLWOperationStreamer = class(TBoldXMLOLWNodeStreamer) - // Args, OperationName protected function GetStreamName: string; override; public @@ -366,7 +361,6 @@ TBoldXMLOLWOperationStreamer = class(TBoldXMLOLWNodeStreamer) end; TBoldXMLOLWIterationStreamer = class(TBoldXMLOLWOperationStreamer) - // LoopVar protected function GetStreamName: string; override; public @@ -376,7 +370,6 @@ TBoldXMLOLWIterationStreamer = class(TBoldXMLOLWOperationStreamer) end; TBoldXMLOLWMemberStreamer = class(TBoldXMLOLWNodeStreamer) - // MemberIndex, MemberName, MemberOf, Qualifier, IsBoolean protected function GetStreamName: string; override; public @@ -386,7 +379,6 @@ TBoldXMLOLWMemberStreamer = class(TBoldXMLOLWNodeStreamer) end; TBoldXMLOLWVariableBindingStreamer = class(TBoldXMLOLWNodeStreamer) - // VariableName, TopSortedIndex, ExternalVarValue, IsLoopVar, RefCount protected function GetStreamName: string; override; public @@ -397,7 +389,6 @@ TBoldXMLOLWVariableBindingStreamer = class(TBoldXMLOLWNodeStreamer) TBoldXMLOLWVariableReferenceStreamer = class(TBoldXMLOLWNodeStreamer) - // VariableBinding protected function GetStreamName: string; override; public @@ -407,7 +398,6 @@ TBoldXMLOLWVariableReferenceStreamer = class(TBoldXMLOLWNodeStreamer) end; TBoldXMLOLWStrLiteralStreamer = class(TBoldXMLOLWNodeStreamer) - // StrValue protected function GetStreamName: string; override; public @@ -417,7 +407,6 @@ TBoldXMLOLWStrLiteralStreamer = class(TBoldXMLOLWNodeStreamer) end; TBoldXMLOLWFloatLiteralStreamer = class(TBoldXMLOLWNodeStreamer) - // FloatValue protected function GetStreamName: string; override; public @@ -427,7 +416,6 @@ TBoldXMLOLWFloatLiteralStreamer = class(TBoldXMLOLWNodeStreamer) end; TBoldXMLOLWIntLiteralStreamer = class(TBoldXMLOLWNodeStreamer) - // IntValue protected function GetStreamName: string; override; public @@ -437,7 +425,6 @@ TBoldXMLOLWIntLiteralStreamer = class(TBoldXMLOLWNodeStreamer) end; TBoldXMLOLWDateLiteralStreamer = class(TBoldXMLOLWNodeStreamer) - // DateValue protected function GetStreamName: string; override; public @@ -447,7 +434,6 @@ TBoldXMLOLWDateLiteralStreamer = class(TBoldXMLOLWNodeStreamer) end; TBoldXMLOLWTimeLiteralStreamer = class(TBoldXMLOLWNodeStreamer) - // TimeValue protected function GetStreamName: string; override; public @@ -459,7 +445,6 @@ TBoldXMLOLWTimeLiteralStreamer = class(TBoldXMLOLWNodeStreamer) TBoldXMLOLWEnumLiteralStreamer = class(TBoldXMLOLWNodeStreamer) - // name, IntValue protected function GetStreamName: string; override; public @@ -493,7 +478,7 @@ constructor TBoldOLWOperation.create(Position: integer; const OperationName: Str destructor TBoldOLWOperation.Destroy; begin FreeAndNil(fArgs); - inherited; + inherited; end; @@ -656,7 +641,7 @@ procedure TBoldOLWVariableBinding.AddRef; begin inc(fRefCount); if (fRefCount > 1) and not fIsLoopVar then - raise EBold.Create(sExternalVarsCanOnlyBeReferencedOnce); + raise EBold.Create('external variables (and self) can currently only be referenced once'); end; constructor TBoldOLWVariableBinding.Create(Position: integer; const VariableName: String; TopSortedIndex: integer); @@ -678,12 +663,14 @@ procedure TBoldOLWStrLiteral.AcceptVisitor(V: TBoldOLWNodeVisitor); v.VisitTBoldOLWStrLiteral(self); end; + constructor TBoldOLWStrLiteral.Create(Position: integer; const StrValue: String); begin inherited Create(Position); fStrValue := StrValue; end; + function TBoldOLWStrLiteral.GetStreamName: string; begin result := OLWStrLiteralStreamName; @@ -923,12 +910,12 @@ procedure TBoldXMLOCLConditionStreamer.ReadObject(Obj: TObject; Condition := Obj as TBoldOclCondition; Bindings := TBoldOLWNodeList.Create; Bindings.OwnsObjects := false; - Node.AddStateObject('Bindings', Bindings); // do not localize - Condition.fEnv := Node.ReadSubnodeObject('Env', OLWNodeListStreamName) as TBoldOLWNodeList; // do not localize - Condition.fRootNode := Node.ReadSubnodeObject('RootNode', '') as TBoldOLWNode; // do not localize - Condition.fContext := Node.ReadSubnodeObject('Context', BOLDOBJECTIDLISTNAME) as TBoldObjectidList; // do not localize - Condition.fOclExpr := Node.ReadSubNodeString('OCL'); // do not localize - Node.RemoveStateObject('Bindings'); // do not localize + Node.AddStateObject('Bindings', Bindings); + Condition.fEnv := Node.ReadSubnodeObject('Env', OLWNodeListStreamName) as TBoldOLWNodeList; + Condition.fRootNode := Node.ReadSubnodeObject('RootNode', '') as TBoldOLWNode; + Condition.fContext := Node.ReadSubnodeObject('Context', BOLDOBJECTIDLISTNAME) as TBoldObjectidList; + Condition.fOclExpr := Node.ReadSubNodeString('OCL'); + Node.RemoveStateObject('Bindings'); Bindings.Free; end; @@ -942,14 +929,14 @@ procedure TBoldXMLOCLConditionStreamer.WriteObject( Condition := Obj as TBoldOclCondition; Bindings := TBoldOLWNodeList.Create; Bindings.OwnsObjects := false; - Node.AddStateObject('Bindings', Bindings); // do not localize + Node.AddStateObject('Bindings', Bindings); - Node.WriteSubnodeObject('Env', OLWNodeListStreamName, Condition.fEnv); // do not localize - Node.WriteSubNodeObject('RootNode', '', Condition.fRootNode); // do not localize - Node.WriteSubnodeObject('Context', BOLDOBJECTIDLISTNAME, Condition.fContext); // do not localize - Node.WriteSubNodeString('OCL', Condition.fOclExpr); // do not localize + Node.WriteSubnodeObject('Env', OLWNodeListStreamName, Condition.fEnv); + Node.WriteSubNodeObject('RootNode', '', Condition.fRootNode); + Node.WriteSubnodeObject('Context', BOLDOBJECTIDLISTNAME, Condition.fContext); + Node.WriteSubNodeString('OCL', Condition.fOclExpr); - Node.RemoveStateObject('Bindings'); // do not localize + Node.RemoveStateObject('Bindings'); Bindings.free; end; @@ -964,7 +951,7 @@ procedure TBoldXMLOLWNodeStreamer.ReadObject(Obj: TObject; begin inherited; OLWNode := obj as TBoldOLWNode; - OLWNode.fPosition := Node.ReadSubNodeInteger('Position'); // do not localize + OLWNode.fPosition := Node.ReadSubNodeInteger('Position'); end; procedure TBoldXMLOLWNodeStreamer.WriteObject(Obj: TBoldInterfacedObject; @@ -974,7 +961,7 @@ procedure TBoldXMLOLWNodeStreamer.WriteObject(Obj: TBoldInterfacedObject; begin inherited; OLWNode := obj as TBoldOLWNode; - Node.WriteSubNodeInteger('Position', OLWNode.fPosition); // do not localize + Node.WriteSubNodeInteger('Position', OLWNode.fPosition); end; { TBoldXMLOLWTypeNodeStreamer } @@ -996,8 +983,8 @@ procedure TBoldXMLOLWTypeNodeStreamer.ReadObject(Obj: TObject; begin inherited; OLWTypeNode := Obj as TBoldOLWTypeNode; - OLWTypeNode.fTypeName := Node.ReadSubNodeString('TypeName'); // do not localize - OLWTypeNode.fTopSortedIndex := Node.ReadSubNodeInteger('TopSortedIndex'); // do not localize + OLWTypeNode.fTypeName := Node.ReadSubNodeString('TypeName'); + OLWTypeNode.fTopSortedIndex := Node.ReadSubNodeInteger('TopSortedIndex'); end; procedure TBoldXMLOLWTypeNodeStreamer.WriteObject( @@ -1007,8 +994,8 @@ procedure TBoldXMLOLWTypeNodeStreamer.WriteObject( begin inherited; OLWTypeNode := Obj as TBoldOLWTypeNode; - Node.WriteSubNodeString('TypeName', OLWTypeNode.TypeName); // do not localize - Node.WriteSubNodeInteger('TopSortedIndex', OLWTypeNode.TopSortedIndex); // do not localize + Node.WriteSubNodeString('TypeName', OLWTypeNode.TypeName); + Node.WriteSubNodeInteger('TopSortedIndex', OLWTypeNode.TopSortedIndex); end; { TBoldXMLOLWListCoercionStreamer } @@ -1030,7 +1017,7 @@ procedure TBoldXMLOLWListCoercionStreamer.ReadObject(Obj: TObject; begin inherited; ListCoercion := obj as TBoldOLWListCoercion; - LIstCoercion.fChild := Node.readSubNodeObject('Child', '') as TBoldOLWNode; // do not localize + LIstCoercion.fChild := Node.readSubNodeObject('Child', '') as TBoldOLWNode; end; procedure TBoldXMLOLWListCoercionStreamer.WriteObject( @@ -1040,7 +1027,7 @@ procedure TBoldXMLOLWListCoercionStreamer.WriteObject( begin inherited; ListCoercion := obj as TBoldOLWListCoercion; - Node.WriteSubNodeObject('Child', '', ListCoercion.fChild); // do not localize + Node.WriteSubNodeObject('Child', '', ListCoercion.fChild); end; { TBoldXMLOLWOperationStreamer } @@ -1062,8 +1049,8 @@ procedure TBoldXMLOLWOperationStreamer.ReadObject(Obj: TObject; begin inherited; OLWOperation := Obj as TBoldOLWOperation; - OLWOperation.fArgs := Node.readSubNodeObject('Args', '') as TBoldOLWNodeList; // do not localize - OLWOperation.fOperationName := Node.ReadSubNodeString('OperationName'); // do not localize + OLWOperation.fArgs := Node.readSubNodeObject('Args', '') as TBoldOLWNodeList; + OLWOperation.fOperationName := Node.ReadSubNodeString('OperationName'); end; procedure TBoldXMLOLWOperationStreamer.WriteObject( @@ -1073,8 +1060,8 @@ procedure TBoldXMLOLWOperationStreamer.WriteObject( begin inherited; OLWOperation := Obj as TBoldOLWOperation; - Node.WriteSubNodeObject('Args', '', OLWOperation.fArgs); // do not localize - Node.WriteSubNodeString('OperationName', OLWOperation.fOperationName); // do not localize + Node.WriteSubNodeObject('Args', '', OLWOperation.fArgs); + Node.WriteSubNodeString('OperationName', OLWOperation.fOperationName); end; { TBoldXMLOLWIterationStreamer } @@ -1094,12 +1081,12 @@ procedure WriteBindingToStream(Binding: TBoldOLWVariableBinding; Node: TBoldXMLN BindingIndex: integer; Bindings: TBoldOLWNodeList; begin - Bindings := Node.GetStateObject('Bindings') as TBoldOLWNodeList; // do not localize + Bindings := Node.GetStateObject('Bindings') as TBoldOLWNodeList; BindingIndex := Bindings.IndexOf[Binding]; - Node.WriteSubNodeInteger('BindingIndex', BindingIndex); // do not localize + Node.WriteSubNodeInteger('BindingIndex', BindingIndex); if BindingIndex = -1 then begin - Node.WriteSubNodeObject('Binding', OLWVariableBindingStreamName, Binding); // do not localize + Node.WriteSubNodeObject('Binding', OLWVariableBindingStreamName, Binding); Bindings.Add(Binding); end; end; @@ -1109,15 +1096,15 @@ function ReadBindingFromStream(Node: TBoldXMLNode): TBoldOLWVariableBinding; BindingIndex: integer; Bindings: TBoldOLWNodeList; begin - Bindings := Node.GetStateObject('Bindings') as TBoldOLWNodeList; // do not localize - BindingIndex := Node.ReadSubNodeInteger('BindingIndex'); // do not localize + Bindings := Node.GetStateObject('Bindings') as TBoldOLWNodeList; + BindingIndex := Node.ReadSubNodeInteger('BindingIndex'); if BindingIndex <> -1 then begin Result := Bindings[BindingIndex] as tBoldOLWVariableBinding; end else begin - Result := Node.ReadSubNodeObject('Binding', OLWVariableBindingStreamName) as TBoldOLWVariableBinding; // do not localize + Result := Node.ReadSubNodeObject('Binding', OLWVariableBindingStreamName) as TBoldOLWVariableBinding; Bindings.Add(result); end; end; @@ -1161,11 +1148,11 @@ procedure TBoldXMLOLWMemberStreamer.ReadObject(Obj: TObject; begin inherited; OLWMember := Obj as TBoldOLWMember; - OLWMember.fMemberIndex := Node.ReadSubNodeInteger('MemberIndex'); // do not localize - OLWMember.fMemberName := Node.ReadSubNodeString('MemberName'); // do not localize - OLWMember.fMemberOf := Node.ReadSubNodeObject('MemberOf', '') as TBoldOLWNode; // do not localize - OLWMember.fQualifier := Node.ReadSubNodeObject('Qualifier', OLWNodeListStreamName) as TBoldOLWNodeList; // do not localize - OLWMember.fIsBoolean := Node.ReadSubNodeBoolean('IsBoolean'); // do not localize + OLWMember.fMemberIndex := Node.ReadSubNodeInteger('MemberIndex'); + OLWMember.fMemberName := Node.ReadSubNodeString('MemberName'); + OLWMember.fMemberOf := Node.ReadSubNodeObject('MemberOf', '') as TBoldOLWNode; + OLWMember.fQualifier := Node.ReadSubNodeObject('Qualifier', OLWNodeListStreamName) as TBoldOLWNodeList; + OLWMember.fIsBoolean := Node.ReadSubNodeBoolean('IsBoolean'); end; procedure TBoldXMLOLWMemberStreamer.WriteObject(Obj: TBoldInterfacedObject; @@ -1175,11 +1162,11 @@ procedure TBoldXMLOLWMemberStreamer.WriteObject(Obj: TBoldInterfacedObject; begin inherited; OLWMember := Obj as TBoldOLWMember; - Node.WriteSubNodeInteger('MemberIndex', OLWMember.fMemberIndex); // do not localize - Node.WriteSubNodeString('MemberName', OLWMember.fMemberName); // do not localize - Node.WriteSubNodeObject('MemberOf', '', OLWMember.fMemberOf); // do not localize - Node.WriteSubNodeObject('Qualifier', OLWNodeListStreamName, OLWMember.fQualifier); // do not localize - Node.WriteSubNodeBoolean('IsBoolean', OLWMember.fIsBoolean); // do not localize + Node.WriteSubNodeInteger('MemberIndex', OLWMember.fMemberIndex); + Node.WriteSubNodeString('MemberName', OLWMember.fMemberName); + Node.WriteSubNodeObject('MemberOf', '', OLWMember.fMemberOf); + Node.WriteSubNodeObject('Qualifier', OLWNodeListStreamName, OLWMember.fQualifier); + Node.WriteSubNodeBoolean('IsBoolean', OLWMember.fIsBoolean); end; { TBoldXMLOLWVariableBindingStreamer } @@ -1201,11 +1188,11 @@ procedure TBoldXMLOLWVariableBindingStreamer.ReadObject(Obj: TObject; begin inherited; OLWBinding := Obj as TBoldOLWVariableBinding; - OLWBinding.fVariableName := Node.ReadSubNodeString('VariableName'); // do not localize - OLWBinding.fTopSortedIndex := Node.ReadSubNodeInteger('TopSortedIndex'); // do not localize - OLWBinding.fIsLoopVar := Node.ReadSubNodeBoolean('IsLoopVar'); // do not localize - OLWBinding.fRefCount := Node.ReadSubNodeInteger('RefCount'); // do not localize - OLWBinding.fExternalVarValue := Node.ReadSubNodeString('ExternalVarValue'); // FIXME // do not localize + OLWBinding.fVariableName := Node.ReadSubNodeString('VariableName'); + OLWBinding.fTopSortedIndex := Node.ReadSubNodeInteger('TopSortedIndex'); + OLWBinding.fIsLoopVar := Node.ReadSubNodeBoolean('IsLoopVar'); + OLWBinding.fRefCount := Node.ReadSubNodeInteger('RefCount'); + OLWBinding.fExternalVarValue := Node.ReadSubNodeString('ExternalVarValue'); end; procedure TBoldXMLOLWVariableBindingStreamer.WriteObject( @@ -1215,11 +1202,11 @@ procedure TBoldXMLOLWVariableBindingStreamer.WriteObject( begin inherited; OLWBinding := Obj as TBoldOLWVariableBinding; - Node.WriteSubNodeString('VariableName', OLWBinding.fVariableName); // do not localize - Node.WriteSubNodeInteger('TopSortedIndex', OLWBinding.fTopSortedIndex); // do not localize - Node.WriteSubNodeBoolean('IsLoopVar', OLWBinding.fIsLoopVar); // do not localize - Node.WriteSubNodeInteger('RefCount', OLWBinding.fRefCount); // do not localize - Node.WriteSubNodeString('ExternalVarValue', OLWBinding.fExternalVarValue); // FIXME // do not localize + Node.WriteSubNodeString('VariableName', OLWBinding.fVariableName); + Node.WriteSubNodeInteger('TopSortedIndex', OLWBinding.fTopSortedIndex); + Node.WriteSubNodeBoolean('IsLoopVar', OLWBinding.fIsLoopVar); + Node.WriteSubNodeInteger('RefCount', OLWBinding.fRefCount); + Node.WriteSubNodeString('ExternalVarValue', OLWBinding.fExternalVarValue); end; { TBoldXMLOLWVariableReferenceStreamer } @@ -1273,7 +1260,7 @@ procedure TBoldXMLOLWStrLiteralStreamer.ReadObject(Obj: TObject; begin inherited; StrLiteral := obj as TBoldOLWStrLiteral; - StrLiteral.fStrValue := Node.ReadSubNodeString('StrValue'); // do not localize + StrLiteral.fStrValue := Node.ReadSubNodeString('StrValue'); end; procedure TBoldXMLOLWStrLiteralStreamer.WriteObject( @@ -1283,7 +1270,7 @@ procedure TBoldXMLOLWStrLiteralStreamer.WriteObject( begin inherited; StrLiteral := obj as TBoldOLWStrLiteral; - Node.WriteSubNodeString('StrValue', StrLiteral.fStrValue); // do not localize + Node.WriteSubNodeString('StrValue', StrLiteral.fStrValue); end; { TBoldXMLOLWIntLiteralStreamer } @@ -1305,7 +1292,7 @@ procedure TBoldXMLOLWIntLiteralStreamer.ReadObject(Obj: TObject; begin inherited; IntLiteral := obj as TBoldOLWIntLiteral; - IntLiteral.fIntValue := Node.ReadSubNodeInteger('IntValue'); // do not localize + IntLiteral.fIntValue := Node.ReadSubNodeInteger('IntValue'); end; procedure TBoldXMLOLWIntLiteralStreamer.WriteObject( @@ -1315,7 +1302,7 @@ procedure TBoldXMLOLWIntLiteralStreamer.WriteObject( begin inherited; IntLiteral := obj as TBoldOLWIntLiteral; - Node.WriteSubNodeInteger('IntValue', IntLiteral.fIntValue); // do not localize + Node.WriteSubNodeInteger('IntValue', IntLiteral.fIntValue); end; { TBoldXMLOLWFloatLiteralStreamer } @@ -1337,7 +1324,7 @@ procedure TBoldXMLOLWFloatLiteralStreamer.ReadObject(Obj: TObject; begin inherited; FloatLiteral := obj as TBoldOLWFloatLiteral; - FloatLiteral.fFloatValue := Node.ReadSubNodeFloat('FloatValue'); // do not localize + FloatLiteral.fFloatValue := Node.ReadSubNodeFloat('FloatValue'); end; procedure TBoldXMLOLWFloatLiteralStreamer.WriteObject( @@ -1347,9 +1334,10 @@ procedure TBoldXMLOLWFloatLiteralStreamer.WriteObject( begin inherited; FloatLiteral := obj as TBoldOLWFloatLiteral; - Node.WriteSubNodeFloat('FloatValue', FloatLiteral.fFloatValue); // do not localize + Node.WriteSubNodeFloat('FloatValue', FloatLiteral.fFloatValue); end; + { TBoldXMLOLWEnumLiteralStreamer } function TBoldXMLOLWEnumLiteralStreamer.CreateObject: TObject; @@ -1369,8 +1357,8 @@ procedure TBoldXMLOLWEnumLiteralStreamer.ReadObject(Obj: TObject; begin inherited; EnumLiteral := obj as TBoldOLWEnumLiteral; - EnumLiteral.fName := Node.ReadSubNodeString('Name'); // do not localize - EnumLiteral.fIntValue := Node.ReadSubNodeInteger('IntValue'); // do not localize + EnumLiteral.fName := Node.ReadSubNodeString('Name'); + EnumLiteral.fIntValue := Node.ReadSubNodeInteger('IntValue'); end; procedure TBoldXMLOLWEnumLiteralStreamer.WriteObject( @@ -1380,8 +1368,8 @@ procedure TBoldXMLOLWEnumLiteralStreamer.WriteObject( begin inherited; EnumLiteral := obj as TBoldOLWEnumLiteral; - Node.WriteSubNodeString('Name', EnumLIteral.fName); // do not localize - Node.WriteSubNodeInteger('IntValue', EnumLIteral.fIntValue); // do not localize + Node.WriteSubNodeString('Name', EnumLIteral.fName); + Node.WriteSubNodeInteger('IntValue', EnumLIteral.fIntValue); end; { TBoldXMLOLWNodeListStreamer } @@ -1400,22 +1388,43 @@ procedure TBoldXMLOLWNodeListStreamer.ReadObject(Obj: TObject; Node: TBoldXMLNode); var OLWList: TBoldOLWNodeList; + {$IFDEF OXML} + aNodeEnumerator: TXMLChildNodeListEnumerator; + aNode: PXMLNode; + {$ELSE} aNodeList: IXMLDOMNodeList; aNode: IXMLDOMNode; + {$ENDIF} aSubNode: TBoldXMLNode; begin inherited; OLWList := Obj as TBoldOLWNodeList; + {$IFDEF OXML} + aNodeEnumerator := Node.XMLDomElement.ChildNodes.GetEnumerator; + try + while aNodeEnumerator.MoveNext do + begin + aNode := aNodeEnumerator.Current; + aSubNode := Node.MakeNodeForElement(aNode); + if aSubNode.Accessor = 'Node' then // do not localize + OLWList.Add(aSubNode.ReadObject('') as TBoldOLWNode); + aSubNode.Free; + end; + finally + aNodeEnumerator.Free; + end; + {$ELSE} aNodeList := Node.XMLDomElement.childNodes; aNode := aNodeList.nextNode; while assigned(aNode) do begin aSubNode := Node.MakeNodeForElement(aNode as IXMLDOMElement); - if aSubNode.Accessor = 'Node' then // do not localize + if aSubNode.Accessor = 'Node' then OLWList.Add(aSubNode.ReadObject('') as TBoldOLWNode); aSubNode.Free; aNode := aNodeList.nextNode; end; + {$ENDIF} end; procedure TBoldXMLOLWNodeListStreamer.WriteObject( @@ -1429,7 +1438,7 @@ procedure TBoldXMLOLWNodeListStreamer.WriteObject( OLWList := Obj as TBoldOLWNodeList; for i := 0 to OLWList.Count-1 do begin - aSubNode := Node.NewSubNode('Node'); // do not localize + aSubNode := Node.NewSubNode('Node'); aSubNode.WriteObject('', OLWList[i]); aSubNode.Free; end; @@ -1454,7 +1463,7 @@ procedure TBoldXMLOLWDateLiteralStreamer.ReadObject(Obj: TObject; begin inherited; DateLiteral := obj as TBoldOLWDateLiteral; - DateLiteral.DateValue := Node.ReadSubNodeDate('DateValue'); // do not localize + DateLiteral.DateValue := Node.ReadSubNodeDate('DateValue'); end; @@ -1465,7 +1474,7 @@ procedure TBoldXMLOLWDateLiteralStreamer.WriteObject( begin inherited; DateLiteral := obj as TBoldOLWDateLiteral; - Node.WriteSubNodeDate('DateValue', DateLIteral.DateValue); // do not localize + Node.WriteSubNodeDate('DateValue', DateLIteral.DateValue); end; { TBoldXMLOLWTimeLiteralStreamer } @@ -1487,7 +1496,7 @@ procedure TBoldXMLOLWTimeLiteralStreamer.ReadObject(Obj: TObject; begin inherited; TimeLiteral := obj as TBoldOLWTimeLiteral; - TimeLiteral.TimeValue := Node.ReadSubNodeTime('TimeValue'); // do not localize + TimeLiteral.TimeValue := Node.ReadSubNodeTime('TimeValue'); end; @@ -1498,7 +1507,7 @@ procedure TBoldXMLOLWTimeLiteralStreamer.WriteObject( begin inherited; TimeLiteral := obj as TBoldOLWTimeLiteral; - Node.WriteSubNodeTime('TimeValue', TimeLIteral.TimeValue); // do not localize + Node.WriteSubNodeTime('TimeValue', TimeLIteral.TimeValue); end; { TBoldOLWMomentLiteral } @@ -1518,21 +1527,11 @@ procedure TBoldOLWDateLiteral.AcceptVisitor(V: TBoldOLWNodeVisitor); v.VisitTBoldOLWDateLiteral(self); end; -function TBoldOLWDateLiteral.GetDateValue: TDateTime; -begin - result := fMomentValue; -end; - function TBoldOLWDateLiteral.GetStreamName: string; begin result := OLWDateLiteralStreamName; end; -procedure TBoldOLWDateLiteral.SetDateValue(const Value: TDateTime); -begin - fMomentValue := Value; -end; - { TBoldOLWTimeLiteral } procedure TBoldOLWTimeLiteral.AcceptVisitor(V: TBoldOLWNodeVisitor); @@ -1546,17 +1545,8 @@ function TBoldOLWTimeLiteral.GetStreamName: string; result := OLWTimeLiteralStreamName; end; -function TBoldOLWTimeLiteral.GetTimeValue: TDateTime; -begin - result := fMomentValue; -end; - -procedure TBoldOLWTimeLiteral.SetTimeValue(const Value: TDateTime); -begin - fMomentValue := Value; -end; - initialization + TBoldXMLStreamerRegistry.MainStreamerRegistry.RegisterStreamer(TBoldXMLOCLConditionStreamer.Create); TBoldXMLStreamerRegistry.MainStreamerRegistry.RegisterStreamer(TBoldXMLOLWNodeListStreamer.Create); TBoldXMLStreamerRegistry.MainStreamerRegistry.RegisterStreamer(TBoldXMLOLWTypeNodeStreamer.Create); diff --git a/Source/ObjectSpace/Ocl/BoldOclRTDebug.pas b/Source/ObjectSpace/Ocl/BoldOclRTDebug.pas index 1a011f5..37562b9 100644 --- a/Source/ObjectSpace/Ocl/BoldOclRTDebug.pas +++ b/Source/ObjectSpace/Ocl/BoldOclRTDebug.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldOclRTDebug; interface @@ -16,4 +19,8 @@ TBoldOclRTDebugger = class (TBoldMemoryManagedObject) implementation +uses + BoldRev; + +initialization end. diff --git a/Source/ObjectSpace/Ocl/BoldOclSemantics.pas b/Source/ObjectSpace/Ocl/BoldOclSemantics.pas index a834c1c..651a320 100644 --- a/Source/ObjectSpace/Ocl/BoldOclSemantics.pas +++ b/Source/ObjectSpace/Ocl/BoldOclSemantics.pas @@ -1,9 +1,11 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldOclSemantics; interface uses - Classes, BoldSystemRT, BoldElements, BoldOclClasses; @@ -27,7 +29,7 @@ TBoldOclSemanticsVisitor = class(TBoldOclVisitor) procedure AddListCoercionOnArgs(N: TBoldOCLOperation); procedure CheckArgumentType(actArg: TBoldOCLNode; FormArg: TBoldElementTypeInfo); procedure DeduceBoldType(N: TBoldOCLOperation); - function FindSymbol(name: string): TBoldOclSymbol; + function FindSymbol(const name: string): TBoldOclSymbol; function LeastCommonSuperClass(C1, C2: TBoldClassTypeInfo): TBoldClassTypeInfo; function LeastCommonSuperType(AttributeTypeInfo1, AttributeTypeInfo2: TBoldAttributetypeInfo): TBoldAttributeTypeInfo; procedure PushResubscribe(var ReSubscribe, OldReSubscribe: Boolean); @@ -46,15 +48,15 @@ TBoldOclSemanticsVisitor = class(TBoldOclVisitor) procedure VisitTBoldOclOperation(N: TBoldOCLOperation); override; procedure VisitTBoldOclStrLiteral(N: TBoldOclStrLiteral); override; procedure VisitTBoldOclTypeNode(N: TBoldOclTypeNode); override; - procedure VisitTBoldOclVariableReference(N: TBoldOCLVariableReference); override; + procedure VisitTBoldOclVariablereference(N: TBoldOCLVariableReference); override; property IgnoreNelCompatibility: Boolean read fIgnoreNelCompatibility write fIgnoreNelCompatibility; end; implementation uses + Classes, SysUtils, - BoldCoreConsts, BoldUtils, BoldOclError, BoldOcl; @@ -64,7 +66,7 @@ implementation 'No DeduceMethod', 'Same type as loopvariable', 'Same type as arg1', 'Same type as listelement of arg1', 'Same type as arg2', 'Same type as arg3', 'Least common supertype of arg1 and arg2', 'Least common supertype of arg2 and arg3', - 'Same type as listelement of arg2', 'Type is ObjectList', 'Type is Metatype', 'Type is arg2 (typecast)', 'Arg1 as a list', 'a list with the type of Arg2'); + 'Same type as listelement of arg2', 'Type is ObjectList', 'Type is Metatype', 'Type is arg2 (typecast)', 'Type is arg1 ', 'Arg1 as a list', 'a list with the type of Arg2'); constructor TBoldOclSemanticsVisitor.Create(Model: TBoldSystemTypeInfo; Evaluator: TBoldEvaluator; SymTab: TBoldSymbolDictionary; Env: TBoldOclEnvironment); begin @@ -87,7 +89,7 @@ procedure TBoldOclSemanticsVisitor.CheckArgumentType(actArg: TBoldOCLNode; FormA begin if not actArg.BoldType.ConformsTo(FormArg) then raise EBoldOCLAbort.CreateFmt(boeNoConform, - [actArg.Position, actArg.BoldType.ExpressionName, FormArg.ExpressionName]); + [actArg.Position, actArg.BoldType.AsString, FormArg.AsString]); end; { else begin if actArg.BoldType is TBoldSystemtypeInfo then @@ -105,8 +107,7 @@ procedure TBoldOclSemanticsVisitor.Traverse(var Node: TBoldOCLNode); TempNode: TBoldOCLLIstCoercion; LocalReSubscribe: Boolean; begin - // It is not certain the listcoercion will be needed in the current context - // so we remove it here and then it might be reinserted again later. + if Node is TBoldOCLLIstCoercion then begin TempNode := TBoldOCLLIstCoercion(Node); @@ -120,7 +121,6 @@ procedure TBoldOclSemanticsVisitor.Traverse(var Node: TBoldOCLNode); Node.SetReferenceValue(nil); LocalReSubscribe := ReSubscribe; -// Node.Evaluator := fEvaluator; try Node.AcceptVisitor(self); ReSubscribe := LocalReSubscribe; @@ -143,8 +143,7 @@ procedure TBoldOclSemanticsVisitor.TraverseList(List: TBoldOCLNodeList; begin for I := Start to Stop do begin - // It is not certain the listcoercion will be needed in the current context - // so we remove it here and then it might be reinserted again later. + if List[I] is TBoldOCLLIstCoercion then begin TempNode := TBoldOCLLIstCoercion(List[I]); @@ -172,7 +171,7 @@ procedure TBoldOclSemanticsVisitor.TraverseList(List: TBoldOCLNodeList; end; end; -function TBoldOclSemanticsVisitor.FindSymbol(name: string): TBoldOclSymbol; +function TBoldOclSemanticsVisitor.FindSymbol(const name: string): TBoldOclSymbol; begin result := Symboltable.SymbolByName[name]; end; @@ -182,7 +181,7 @@ procedure TBoldOclSemanticsVisitor.AddListCoercionOnArgs(N: TBoldOCLOperation); I: Integer; CoercionNode: TBoldOCLLIstCoercion; begin - for I := 0 to N.Args.Count - 1 do + for I := 0 to Length(N.Args) - 1 do begin if N.Args[I].NeedsListCoercion then begin @@ -208,9 +207,6 @@ procedure FixImplicitCollect; i: integer; begin - // This is an implicit Collect. Change NodeType! - - // We really have to create a new node since the old one will be freed when replaced by the replacementNode!!! if n is TBoldOclMethod then begin @@ -222,7 +218,6 @@ procedure FixImplicitCollect; NewOperation := TBoldOclOperation.Create; OldNode0 := n.args[0]; - n.args.Delete(0); VarName := fEnv.MakeGenSymName; VarNode := TBoldOClVariableReference.Create; @@ -231,37 +226,33 @@ procedure FixImplicitCollect; NewOperation.OperationName := n.OperationName; NewOperation.Position := n.Position; - NewOperation.Args := TBoldOclNodeLIst.create; - NewOperation.Args.add(VarNode); - for i := 0 to n.args.count - 1 do + SetLength(NewOperation.Args, Length(n.args)); + NewOperation.Args[0] := VarNode; + for i := 1 to Length(n.args) - 1 do begin - NewOperation.args.Add(n.args[0]); - n.Args.Delete(0); + NewOperation.args[i] := n.args[i]; end; + SetLength(n.Args, 0); CollectNode := TBoldOclIteration.Create; collectNode.IteratorSpecifier := OclCollect; - CollectNode.OperationName := 'Collect'; // do not localize + CollectNode.OperationName := 'Collect'; collectNode.Position := n.Position; - CollectNode.Args := TBoldOClNodeList.create; - CollectNode.Args.Add(OldNode0); - CollectNode.Args.Add(NewOperation); + SetLength(CollectNode.Args, 2); + CollectNode.Args[0] := OldNode0; + CollectNode.Args[1] := NewOperation; VarBind := TBoldOCLVariableBinding.Create; VarBind.VariableName := VarName; CollectNode.LoopVar := VarBind; - // Now Traverse the node and make sure we put the correct node in the replacementNode-variable - - tempList := TBoldOclNodeList.create; - TempLIst.Add(CollectNode); + SetLength(TempList, 1); + TempList[0] := CollectNode; try - TraverseList(tempLIst, 0, 0); + TraverseList(TempList, 0, 0); finally - // even if things fail, it is better to have the new node than no node at all. - ReplacementNode := TempLIst[0]; - TempLIst[0] := nil; - TempList.Free; + ReplacementNode := TempList[0]; + SetLength(TempList, 0); end; end; @@ -279,10 +270,9 @@ procedure FixImplicitCollect; N.IsConstant := True; try - // boolean shortcut must force resubscribe on the shortcutting node - if SameText(N.OperationName, 'if') or // do not localize - SameText(N.OperationName, 'or') or // do not localize - SameText(N.OperationName, 'and') then // do not localize + if SameText(N.OperationName, 'if') or + SameText(N.OperationName, 'or') or + SameText(N.OperationName, 'and') then begin OldResubscribe := Resubscribe; Resubscribe := true; @@ -299,12 +289,12 @@ procedure FixImplicitCollect; exit; end; - if N.Args.Count <> N.Symbol.NumberOfArgs then - raise EBoldOCLAbort.CreateFmt(boeWrongnumberofargs, [N.Position, N.Symbol.NumberOfArgs, N.Args.Count]); + if Length(N.Args) <> N.Symbol.NumberOfArgs then + raise EBoldOCLAbort.CreateFmt(boeWrongnumberofargs, [N.Position, N.Symbol.NumberOfArgs, Length(N.Args)]); - TraverseList(N.Args, 1, N.Args.Count - 1); + TraverseList(N.Args, 1, Length(N.Args) - 1); - for I := 0 to N.Args.Count - 1 do + for I := 0 to Length(N.Args) - 1 do begin N.IsConstant := N.IsConstant and N.Args[I].IsConstant; CheckArgumentType(N.Args[I], N.Symbol.FormalArguments[i]); @@ -322,7 +312,7 @@ procedure FixImplicitCollect; if not Type2.ConformsTo(type1) and not Type1.ConformsTo(Type2) then - raise EBoldOCLAbort.CreateFmt(sArgumentsDoNotConform, [n.Position, n.Symbol.SymbolName, Type1.AsString, type2.AsString]); + raise EBoldOCLAbort.CreateFmt('%d: In "%s", one of the arguments must conform to the other (%s and %s does not)', [n.Position, n.Symbol.SymbolName, Type1.AsString, type2.AsString]); end; except on e: Exception do @@ -342,8 +332,8 @@ procedure TBoldOclSemanticsVisitor.VisitTBoldOclIteration(N: TBoldOclIteration); if not assigned(N.Symbol) then raise EBoldOCLAbort.CreateFmt(boeUndefinedOperation, [N.Position, N.OperationName]); - if N.Args.Count <> N.Symbol.NumberOfArgs then - raise EBoldOCLAbort.CreateFmt(boeWrongnumberofargs, [N.Position, N.Symbol.NumberOfArgs, N.Args.Count]); + if Length(N.Args) <> N.Symbol.NumberOfArgs then + raise EBoldOCLAbort.CreateFmt(boeWrongnumberofargs, [N.Position, N.Symbol.NumberOfArgs, Length(N.Args)]); PushResubscribe(ReSubscribe, OldReSubscribe); @@ -354,16 +344,13 @@ procedure TBoldOclSemanticsVisitor.VisitTBoldOclIteration(N: TBoldOclIteration); ReSubscribe := OldReSubscribe; if not assigned(N.LoopVar) then - // CHECKME N.LoopVar := TBoldOclVariableBinding.Create(n); N.LoopVar := TBoldOclVariableBinding.Create; if N.LoopVar.VariableName = '' then N.LoopVar.VariableName := fEnv.MakeGenSymName; - - // we must coerce the first arguement before using its type AddListCoercionOnArgs(N); - n.LoopVar.SetReferenceValue(nil); // reset dynamic boldtype + n.LoopVar.SetReferenceValue(nil); if not assigned(N.LoopVar.BoldType) then if n.args[0].BoldType is TBoldListTypeInfo then @@ -372,8 +359,8 @@ procedure TBoldOclSemanticsVisitor.VisitTBoldOclIteration(N: TBoldOclIteration); raise EBoldOCLInternalError.CreateFmt(boeUnKnownTypeOfLoopVar, [N.Position, N.Args[0].BoldType.ClassName]); fEnv.PushBinding(N.LoopVar); try - TraverseList(N.Args, 1, N.Args.Count - 1); - for I := 1 to N.Args.Count - 1 do + TraverseList(N.Args, 1, Length(N.Args) - 1); + for I := 1 to Length(N.Args) - 1 do begin N.IsConstant := N.IsConstant and N.Args[I].IsConstant; CheckArgumentType(N.Args[I], N.Symbol.FormalArguments[i]); @@ -395,6 +382,7 @@ procedure TBoldOclSemanticsVisitor.VisitTBoldOclIteration(N: TBoldOclIteration); function TBoldOclSemanticsVisitor.TestForOperation(n: TBoldOclNode): Boolean; var TempOperation: TBoldOCLOperation; + nAsMethod: TBoldOclMethod; i: integer; PossibleOperation: TBoldOclSymbol; OpName: String; @@ -406,7 +394,7 @@ function TBoldOclSemanticsVisitor.TestForOperation(n: TBoldOclNode): Boolean; else if n is TBoldOclMethod then OpName := TBoldOclMethod(n).OperationName else - raise EBoldOclInternalError.CreateFmt('%d:Illegal call for TestForOperation', [n.Position]); // do not localize + raise EBoldOclInternalError.CreateFmt('%d:Illegal call for TestForOperation', [n.Position]); PossibleOperation := FindSymbol(OpName); @@ -416,34 +404,31 @@ function TBoldOclSemanticsVisitor.TestForOperation(n: TBoldOclNode): Boolean; TempOperation.Symbol := PossibleOperation; TempOperation.ReSubscribe := Resubscribe; TempOperation.OperationName := OpName; - TempOperation.Args := TBoldOCLNodeList.Create; if n is TBoldOclMember then begin - TempOperation.args.add(TBoldOclMember(n).Memberof); + SetLength(TempOperation.Args, 1); + TempOperation.args[0] := TBoldOclMember(n).Memberof; TBoldOclMember(n).Memberof := nil; end else if n is TBoldOclMethod then begin - TempOperation.args.add(TBoldOclMethod(n).Methodof); - for i := 0 to TBoldOclMethod(n).args.count - 1 do + nAsMethod := TBoldOclMethod(n); + SetLength(TempOperation.Args, Length(nAsMethod.args)+1); + TempOperation.args[0] := nAsMethod.Methodof; + for i := 0 to Length(nAsMethod.args) - 1 do begin - TempOperation.args.add(TBoldOclMethod(n).args[i]); - TBoldOclMethod(n).args[i] := nil; + TempOperation.args[i+1] := nAsMethod.args[i]; + nAsMethod.args[i] := nil; end; - TBoldOclMethod(n).Methodof := nil; + nAsMethod.Methodof := nil; end; TempOperation.Position := n.Position; try - TempOperation.AcceptVisitor(self); // HAs to traverse the whole subtree again :-( + TempOperation.AcceptVisitor(self); finally - //Now, publish the operation to be exchanged to. if not assigned(ReplacementNode) then ReplacementNode := TempOperation else - // this occurs if the operation was also a part of an implicit collect such as - // Person.allInstances.constraints, in that case, the replacementnode will - // refer to a copy of the tempoperation, and the copy will have stolen the - // arguments already (see FixImplicitCollect) TempOperation.Free; end; Result := true; @@ -455,6 +440,7 @@ procedure TBoldOclSemanticsVisitor.VisitTBoldOclMethod(N: TBoldOclMethod); VarRef: TBoldOCLVariableReference; MethodRTInfo: TBoldMethodRTInfo; ClassTypeInfo: TBoldClassTypeInfo; + I, L: Integer; begin if not assigned(N.MethodOf) then begin @@ -476,7 +462,11 @@ procedure TBoldOclSemanticsVisitor.VisitTBoldOclMethod(N: TBoldOclMethod); if not n.MethodOf_AddedToArgs then begin - n.Args.Insert(0, n.MethodOf); + L := Length(n.Args); + SetLength(n.Args, (L+1)); + for I := 0 to L-1 do + n.Args[i+1] := n.Args[I]; + n.Args[0] := n.MethodOf; n.MethodOf_AddedToArgs := true; end; @@ -489,14 +479,13 @@ procedure TBoldOclSemanticsVisitor.VisitTBoldOclMethod(N: TBoldOclMethod); ClassTypeInfo := TBoldListTypeInfo(n.MethodOf.BoldType).ListElementTypeInfo as TBoldClassTypeInfo; if not assigned(classTypeInfo) then - raise EBoldOclInternalError.CreateFmt(sMethodNotoperatingOnClass, [N.Position, N.OperationName]); + raise EBoldOclInternalError.CreateFmt('%d: Method (%s) is not operating on a class...', [N.Position, N.OperationName]); MethodRTInfo := ClassTypeInfo.Methods.ItemsByExpressionName[n.OperationName]; if not assigned(MethodRTInfo) then raise EBoldOCLAbort.CreateFmt(boeUndefinedOperation, [N.Position, N.OperationName]); N.Symbol := nil; -// N.Symbol := MethodRTInfo.OclSymbol as TBoldOclSymbol; if not assigned(N.Symbol) then raise EBoldOCLAbort.CreateFmt(boeOperationNotOclable, [N.Position, N.OperationName]); @@ -536,7 +525,6 @@ procedure TBoldOclSemanticsVisitor.VisitTBoldOclMember(N: TBoldOclMember); end else begin - // The Current node will be replaced with a var-reference inside Traverse VarRef := TBoldOCLVariableReference.Create; Varref.VariableBinding := Binding; Varref.VariableName := N.Membername; @@ -558,10 +546,9 @@ procedure TBoldOclSemanticsVisitor.VisitTBoldOclMember(N: TBoldOclMember); if not assigned(ElementType) then - // this is most likely due to absence of a context. Current member is assumed to have - // an implicit Self-var-reference, but it has no context. - // It also occurs when trying to evaluate an empty single-link and is then taken care of by - // the TBoldOCL.CheckSemantics + + + raise EBoldOCLAbort.CreateFmt(boeVariableNotAssigned, [N.Position, '']); case ElementType.BoldValueType of @@ -573,7 +560,7 @@ procedure TBoldOclSemanticsVisitor.VisitTBoldOclMember(N: TBoldOclMember); if not assigned(ClassTypeInfo) then raise EBoldOCLAbort.CreateFmt(boeUnknownclass, [N.Position, N.Membername]); N.BoldType := CurrentSystemTypeInfo.ListTypeInfoByElement[ClassTypeInfo]; - n.MemberType := nil; // needed if the expression has been evaluated in another context previously + n.MemberType := nil; end; end; bvtClass: begin @@ -610,23 +597,21 @@ procedure TBoldOclSemanticsVisitor.VisitTBoldOclMember(N: TBoldOclMember); roleRTInfo := nil; if not assigned(RoleRTInfo) then - raise EBoldOclAbort.CreateFmt(sOnlyRolesCanBeQualified, [n.position]); + raise EBoldOclAbort.CreateFmt('%d: Only roles may be qualified', [n.position]); if not RoleRTInfo.IsQualified then - raise EBoldOclAbort.CreateFmt(sXIsNotAQualifiedRole, [n.position, ClassTypeInfo.ExpressionName, RoleRTInfo.ExpressionName]); - if N.Qualifier.Count <> RoleRTInfo.Qualifiers.count then - raise EBoldOCLAbort.CreateFmt(boeWrongnumberofargs, [N.Position, RoleRTInfo.Qualifiers.count, N.Qualifier.Count]); + raise EBoldOclAbort.CreateFmt('%d: %s.%s is not a qualified role', [n.position, ClassTypeInfo.ExpressionName, RoleRTInfo.ExpressionName]); + if Length(N.Qualifier) <> RoleRTInfo.Qualifiers.count then + raise EBoldOCLAbort.CreateFmt(boeWrongnumberofargs, [N.Position, RoleRTInfo.Qualifiers.count, Length(N.Qualifier)]); if RoleRTInfo.IsQualifiedMulti or - // qualified access starting from an objectlist (assigned(n.MemberOf) and (n.MemberOf.BoldType is TBoldListTypeInfo)) then begin -// raise EBoldOclAbort.CreateFmt('%d: %s.%s - Qualified relations with multiplicity > 1 not supported', [n.position, ClassTypeInfo.ExpressionName, RoleRTInfo.ExpressionName]); n.BoldType := n.MemberType end else n.BoldType := RoleRTInfo.ClassTypeInfoOfOtherEnd; - TraverseList(N.qualifier, 0, N.Qualifier.Count - 1); + TraverseList(N.qualifier, 0, Length(N.Qualifier) - 1); for i := 0 to RoleRTInfo.Qualifiers.count - 1 do CheckArgumentType(n.Qualifier[i], RoleRTInfo.Qualifiers[i].BoldType); @@ -660,7 +645,7 @@ procedure TBoldOclSemanticsVisitor.VisitTBoldOclVariablereference(N: TBoldOCLVar N.BoldType := N.VariableBinding.BoldType; if not assigned(N.BoldType) then - raise EBoldOCLAbort.CreateFmt(boeVariableNotAssigned, [N.Position, n.VariableName]); + raise EBoldOCLAbort.CreateFmt(boeVariableNotAssigned, [N.Position, n.VariableName]); end; procedure TBoldOCLSemanticsVisitor.VisitTBoldOCLTypeNode(n: TBoldOclTypeNode); @@ -711,7 +696,7 @@ procedure TBoldOCLSemanticsVisitor.VisitTBoldOCLTypeNode(n: TBoldOclTypeNode); procedure TBoldOclSemanticsVisitor.VisitTBoldOclStrLiteral(N: TBoldOclStrLiteral); begin - N.BoldType := CurrentSystemTypeInfo.AttributeTypeInfoByExpressionName['String']; // do not localize + N.BoldType := TBoldOcl(fEvaluator).StringType; N.IsConstant := True; end; @@ -735,8 +720,7 @@ function TBoldOclSemanticsVisitor.LeastCommonSuperType(AttributeTypeInfo1, Attri else if AttributeTypeInfo2.BoldIsA(AttributeTypeInfo1) then Result := AttributeTypeInfo1 else if AttributeTypeInfo2.AttributeClass=AttributeTypeInfo1.AttributeClass then - // attributes with the same delphitype will conform to each other, but they will not support BoldIsA - // either attribute will do as good as result from here + result := AttributeTypeInfo1 else Result := LeastCommonSuperType(AttributeTypeInfo1.SuperAttributeTypeInfo, AttributeTypeInfo2); @@ -753,7 +737,7 @@ procedure TBoldOclSemanticsVisitor.VisitTBoldOclCollectionLiteral(N: TBoldOclCol begin Traverse(N.rangeStart); Traverse(N.rangeStop); - IntType := CurrentSystemTypeInfo.AttributeTypeInfoByExpressionName['Integer']; // do not localize + IntType := TBoldOcl(fEvaluator).IntegerType; if not N.rangeStart.BoldType.ConformsTo(IntType) then raise EBoldOCLAbort.CreateFmt(boeRangeMustBeInt, [N.rangeStart.Position]); if not N.rangeStop.BoldType.ConformsTo(IntType) then @@ -763,18 +747,18 @@ procedure TBoldOclSemanticsVisitor.VisitTBoldOclCollectionLiteral(N: TBoldOclCol end else begin - if N.Elements.Count = 0 then + if Length(N.Elements) = 0 then begin N.BoldType := CurrentSystemTypeInfo.ListTypeInfoByElement[nil]; end else begin - TraverseList(N.Elements, 0, N.Elements.Count - 1); + TraverseList(N.Elements, 0, Length(N.Elements) - 1); N.IsConstant := N.Elements[0].IsConstant; if N.Elements[0].BoldType is TBoldClasstypeInfo then begin TopClass := N.Elements[0].BoldType as TBoldClassTypeInfo; - for I := 1 to N.Elements.Count - 1 do + for I := 1 to Length(N.Elements) - 1 do begin N.IsConstant := N.IsConstant and N.Elements[I].IsConstant; if not (N.Elements[I].BoldType is TBoldClassTypeInfo) then @@ -786,7 +770,7 @@ procedure TBoldOclSemanticsVisitor.VisitTBoldOclCollectionLiteral(N: TBoldOclCol else begin TopType := N.Elements[0].BoldType as TBoldAttributetypeInfo; - for I := 1 to N.Elements.Count - 1 do + for I := 1 to Length(N.Elements) - 1 do begin if not (N.Elements[I].BoldType is TBoldAttributeTypeInfo) then raise EBoldOCLAbort.CreateFmt(boeElementnotConformToCollection, [N.Elements[I].Position]); @@ -799,24 +783,28 @@ procedure TBoldOclSemanticsVisitor.VisitTBoldOclCollectionLiteral(N: TBoldOclCol end; end; end; - // n.IsConstant := False; // Needed as long as values are transfered out of the OCL-nodes end; procedure TBoldOclSemanticsVisitor.VisitTBoldOclNumericLiteral(N: TBoldOclNumericLiteral); begin - N.BoldType := CurrentSystemTypeInfo.AttributeTypeInfoByExpressionName['Float']; // do not localize + N.BoldType := TBoldOcl(fEvaluator).FloatType; N.IsConstant := True; end; procedure TBoldOclSemanticsVisitor.VisitTBoldOclEnumLiteral(N: TBoldOclEnumLiteral); +var + vElement: TBoldElement; + vTypeInfo: TBoldElementTypeInfo; begin - N.BoldType := CurrentSystemTypeInfo.AttributeTypeInfoByExpressionName['ValueSet']; // do not localize + if not CurrentSystemTypeInfo.FindValueSetAndTypeByName(N.Name, vElement, vTypeInfo) then + raise EBoldOCLAbort.CreateFmt(boeEnumValueNotFound, [N.Position, N.Name]); + N.BoldType := vTypeInfo; //CurrentSystemTypeInfo.ValueSetTypeInfo; N.IsConstant := True; end; procedure TBoldOclSemanticsVisitor.VisitTBoldOclIntLiteral(N: TBoldOclIntLiteral); begin - N.BoldType := CurrentSystemTypeInfo.AttributeTypeInfoByExpressionName['Integer']; // do not localize + N.BoldType := TBoldOcl(fEvaluator).IntegerType; N.IsConstant := True; end; @@ -841,10 +829,8 @@ procedure TBoldOclSemanticsVisitor.DeduceBoldType(N: TBoldOCLOperation); else N.BoldType := CurrentSystemTypeInfo.ListTypeInfoByElement[N.Args[0].BoldType]; -// tbodBoolean: N.BoldType := CurrentModel.AttributeTypeByExpressionName['Boolean']; -// tbodInteger: N.BoldType := CurrentModel.AttributeTypeByExpressionName['Integer']; -// tbodreal: N.BoldType := CurrentModel.AttributeTypeByExpressionName['Float']; -// tbodString: N.BoldType := CurrentModel.AttributeTypeByExpressionName['String']; + + tbodListofArg2: begin if N.Args[1].BoldType.BoldValueType = bvtList then @@ -899,6 +885,14 @@ procedure TBoldOclSemanticsVisitor.DeduceBoldType(N: TBoldOCLOperation); else N.BoldType := nil; + if not assigned(N.BoldType) then + begin + if arg1 is TBoldNilTypeInfo then + N.BoldType := arg2 + else + if arg2 is TBoldNilTypeInfo then + N.BoldType := arg1 + end; if not assigned(N.BoldType) then raise EBoldOCLAbort.CreateFmt(boeNoCommonSuperclass, [N.Position, arg1.ExpressionName, arg2.ExpressionName]); @@ -908,6 +902,7 @@ procedure TBoldOclSemanticsVisitor.DeduceBoldType(N: TBoldOCLOperation); end; tbodType: n.BoldType := N.Args[0].BoldType.BoldType; tbodTypeCast: n.BoldType := n.Args[1].value as TBoldElementTypeInfo; + tbodArg1Type: n.BoldType := n.Args[0].value as TBoldElementTypeInfo; tbodObjectList: if assigned(n.args[0].Value) then n.BoldType := CurrentSystemTypeInfo.ListTypeInfoByElement[n.args[0].Value as TBoldElementTypeInfo]; @@ -916,8 +911,8 @@ procedure TBoldOclSemanticsVisitor.DeduceBoldType(N: TBoldOCLOperation); if not assigned(n.BoldType) then begin ArgTypes := TStringList.Create; - for i := 0 to n.args.count - 1 do - ArgTypes.Add(Format('Arg %s: %s', [IntToStr(i + 1), n.args[i].BoldType.AsString])); // do not localize + for i := 0 to Length(n.args) - 1 do + ArgTypes.Add(Format('Arg %s: %s', [IntToStr(i + 1), n.args[i].BoldType.AsString])); ContextStr := BoldSeparateStringList(ArgTypes, ', ', '', ''); ArgTypes.Free; @@ -927,14 +922,15 @@ procedure TBoldOclSemanticsVisitor.DeduceBoldType(N: TBoldOCLOperation); procedure TBoldOclSemanticsVisitor.VisitTBoldOclDateLiteral(N: TBoldOclDateLiteral); begin - N.BoldType := CurrentSystemTypeInfo.AttributeTypeInfoByExpressionName['Date']; // do not localize + N.BoldType := TBoldOcl(fEvaluator).DateType; N.IsConstant := True; end; procedure TBoldOclSemanticsVisitor.VisitTBoldOclTimeLiteral(N: TBoldOclTimeLiteral); begin - N.BoldType := CurrentSystemTypeInfo.AttributeTypeInfoByExpressionName['Time']; // do not localize + N.BoldType := TBoldOcl(fEvaluator).TimeType; N.IsConstant := True; end; +initialization end. diff --git a/Source/ObjectSpace/Ocl/BoldOclSymbolImplementations.pas b/Source/ObjectSpace/Ocl/BoldOclSymbolImplementations.pas index 05e2987..74c8614 100644 --- a/Source/ObjectSpace/Ocl/BoldOclSymbolImplementations.pas +++ b/Source/ObjectSpace/Ocl/BoldOclSymbolImplementations.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldOclSymbolImplementations; interface @@ -12,6 +15,7 @@ implementation uses SysUtils, + DateUtils, BoldElements, BoldAttributes, BoldOclError, @@ -21,10 +25,12 @@ implementation BoldSystemRT, BoldSystem, Classes, + Variants, + Math, BoldSubscription, - BoldValueSpaceInterfaces, // besExisting is defined here... - BoldRegularExpression, - BoldCoreConsts; + BoldValueSpaceInterfaces, + System.RegularExpressions, + BoldIsoDateTime; var G_OCLOperations: TList = nil; @@ -42,6 +48,18 @@ procedure RegisterOCLOperation(OperationClass: TBoldOclSymbolClass); OCLOperations.Add(OperationClass); end; +function ExtractDateTimeFromMoment(moment: TBAMoment): TDateTime; +begin + if Moment is TBADateTime then + Result := (Moment as TBADateTime).asDateTime + else if Moment is TBADate then + Result := (Moment as TBADate).asDate + else if Moment is TBATime then + Result := (Moment as TBATime).asTime + else + Result := 0; +end; + type TBOS_AbstractCompare = class(TBoldOclSymbol) @@ -63,14 +81,6 @@ TBOS_NotEqual = class(TBOS_AbstractCompare) procedure Evaluate(const Params: TBoldOclSymbolParameters); override; end; - TBOS_Except = class(TBoldOclSymbol) - protected - procedure Init; override; - public - procedure Evaluate(const Params: TBoldOclSymbolParameters); override; - end; - - TBOS_Add = class(TBoldOclSymbol) protected procedure Init; override; @@ -134,6 +144,13 @@ TBOS_strToInt = class(TBoldOclSymbol) procedure Evaluate(const Params: TBoldOclSymbolParameters); override; end; + TBOS_strToFloat = class(TBoldOclSymbol) + protected + procedure Init; override; + public + procedure Evaluate(const Params: TBoldOclSymbolParameters); override; + end; + TBOS_Min = class(TBoldOclSymbol) protected procedure Init; override; @@ -183,6 +200,13 @@ TBOS_Div = class(TBoldOclSymbol) procedure Evaluate(const Params: TBoldOclSymbolParameters); override; end; + TBOS_SafeDivZero = class(TBoldOclSymbol) + protected + procedure Init; override; + public + procedure Evaluate(const Params: TBoldOclSymbolParameters); override; + end; + TBOS_Mod = class(TBoldOclSymbol) protected procedure Init; override; @@ -225,6 +249,13 @@ TBOS_SubString = class(TBoldOclSymbol) procedure Evaluate(const Params: TBoldOclSymbolParameters); override; end; + TBOS_Contains = class(TBoldOclSymbol) + protected + procedure Init; override; + public + procedure Evaluate(const Params: TBoldOclSymbolParameters); override; + end; + TBOS_Pad = class(TBoldOclSymbol) protected procedure Init; override; @@ -239,7 +270,19 @@ TBOS_PostPad = class(TBoldOclSymbol) procedure Evaluate(const Params: TBoldOclSymbolParameters); override; end; - TBOS_FormatNumeric = class(TBoldOclSymbol) + TBOS_Format = class(TBoldOclSymbol) + protected + procedure Init; override; + public + procedure Evaluate(const Params: TBoldOclSymbolParameters); override; + end; + + TBOS_FormatNumeric = class(TBOS_Format) + protected + procedure Init; override; + end; + + TBOS_FormatFloat = class(TBoldOclSymbol) protected procedure Init; override; public @@ -253,6 +296,20 @@ TBOS_FormatDateTime = class(TBoldOclSymbol) procedure Evaluate(const Params: TBoldOclSymbolParameters); override; end; + TBOS_AsISODateTime = class(TBoldOclSymbol) + protected + procedure Init; override; + public + procedure Evaluate(const Params: TBoldOclSymbolParameters); override; + end; + + TBOS_AsISODate = class(TBoldOclSymbol) + protected + procedure Init; override; + public + procedure Evaluate(const Params: TBoldOclSymbolParameters); override; + end; + TBOS_StrToDate = class(TBoldOclSymbol) protected procedure Init; override; @@ -274,9 +331,66 @@ TBOS_StrToDateTime = class(TBoldOclSymbol) procedure Evaluate(const Params: TBoldOclSymbolParameters); override; end; + TBOS_DayOfDate = class(TBoldOclSymbol) + protected + procedure Init; override; + public + procedure Evaluate(const Params: TBoldOclSymbolParameters); override; + end; + + TBOS_MonthOfDate = class(TBoldOclSymbol) + protected + procedure Init; override; + public + procedure Evaluate(const Params: TBoldOclSymbolParameters); override; + end; + + TBOS_YearOfDate = class(TBoldOclSymbol) + protected + procedure Init; override; + public + procedure Evaluate(const Params: TBoldOclSymbolParameters); override; + end; + + TBOS_WeekOfDate = class(TBoldOclSymbol) + protected + procedure Init; override; + public + procedure Evaluate(const Params: TBoldOclSymbolParameters); override; + end; + + TBOS_DayOfWeekOfDate = class(TBoldOclSymbol) + protected + procedure Init; override; + public + procedure Evaluate(const Params: TBoldOclSymbolParameters); override; + end; + + TBOS_HoursBetween = class(TBoldOclSymbol) + protected + procedure Init; override; + public + procedure Evaluate(const Params: TBoldOclSymbolParameters); override; + end; + + TBOS_MinutesBetween = class(TBoldOclSymbol) + protected + procedure Init; override; + public + procedure Evaluate(const Params: TBoldOclSymbolParameters); override; + end; + + TBOS_SecondsBetween = class(TBoldOclSymbol) + protected + procedure Init; override; + public + procedure Evaluate(const Params: TBoldOclSymbolParameters); override; + end; + TBOS_or = class(TBoldOclSymbol) protected procedure Init; override; + function GetShortCircuitType: ShortCircuitType; override; public procedure Evaluate(const Params: TBoldOclSymbolParameters); override; end; @@ -284,6 +398,7 @@ TBOS_or = class(TBoldOclSymbol) TBOS_and = class(TBoldOclSymbol) protected procedure Init; override; + function GetShortCircuitType: ShortCircuitType; override; public procedure Evaluate(const Params: TBoldOclSymbolParameters); override; end; @@ -312,6 +427,7 @@ TBOS_implies = class(TBoldOclSymbol) TBOS_if = class(TBoldOclSymbol) protected procedure Init; override; + function GetShortCircuitType: ShortCircuitType; override; public procedure Evaluate(const Params: TBoldOclSymbolParameters); override; end; @@ -372,12 +488,6 @@ TBOS_Sum = class(TBoldOclSymbol) procedure Evaluate(const Params: TBoldOclSymbolParameters); override; end; - TBOS_SumTime = class(TBoldOclSymbol) - protected - procedure Init; override; - public - procedure Evaluate(const Params: TBoldOclSymbolParameters); override; - end; TBOS_Maxvalue = class(TBoldOclSymbol) protected @@ -509,12 +619,14 @@ TBOS_Append = class(TBoldOclSymbol) public procedure Evaluate(const Params: TBoldOclSymbolParameters); override; end; + TBOS_Prepend = class(TBoldOclSymbol) protected procedure Init; override; public procedure Evaluate(const Params: TBoldOclSymbolParameters); override; end; + TBOS_SubSequence = class(TBoldOclSymbol) protected procedure Init; override; @@ -565,7 +677,28 @@ TBOS_asString = class(TBoldOclSymbol) procedure Evaluate(const Params: TBoldOclSymbolParameters); override; end; - TBOS_dateTimeAsFloat = class(TBoldOclSymbol) + TBOS_AsFloat = class(TBoldOclSymbol) + protected + procedure Init; override; + public + procedure Evaluate(const Params: TBoldOclSymbolParameters); override; + end; + + TBOS_FloatAsDateTime = class(TBoldOclSymbol) + protected + procedure Init; override; + public + procedure Evaluate(const Params: TBoldOclSymbolParameters); override; + end; + + TBOS_datePart = class(TBoldOclSymbol) + protected + procedure Init; override; + public + procedure Evaluate(const Params: TBoldOclSymbolParameters); override; + end; + + TBOS_asDateTime = class(TBoldOclSymbol) protected procedure Init; override; public @@ -645,6 +778,14 @@ TBOS_AllInstances = class(TBoldOclSymbol) procedure Evaluate(const Params: TBoldOclSymbolParameters); override; end; + TBOS_NullValue = class(TBoldOclSymbol) + protected + procedure Init; override; + public + procedure Evaluate(const Params: TBoldOclSymbolParameters); override; + end; + + TBOS_AllLoadedObjects = class(TBoldOclSymbol) protected procedure Init; override; @@ -796,431 +937,602 @@ TBOS_TimeToTimeStamp = class(TBoldOclSymbol) procedure Evaluate(const Params: TBoldOclSymbolParameters); override; end; + TBOS_IndexOf = class(TBoldOclSymbol) + protected + procedure Init; override; + public + procedure Evaluate(const Params: TBoldOclSymbolParameters); override; + end; + + TBOS_ReverseCollection = class(TBoldOclSymbol) + protected + procedure Init; override; + public + procedure Evaluate(const Params: TBoldOclSymbolParameters); override; + end; + + TBOS_asCommaText = class(TBoldOclSymbol) + protected + procedure Init; override; + public + procedure Evaluate(const Params: TBoldOclSymbolParameters); override; + end; + + TBOS_separate = class(TBoldOclSymbol) + protected + procedure Init; override; + public + procedure Evaluate(const Params: TBoldOclSymbolParameters); override; + end; + + TBOS_CommaSeparatedStringToCollection = class(TBoldOclSymbol) + protected + function GetListTypeInfo: TBoldListTypeInfo; virtual; abstract; + public + procedure Evaluate(const Params: TBoldOclSymbolParameters); override; + end; + + TBOS_CommaSeparatedStringToStringCollection = class(TBOS_CommaSeparatedStringToCollection) + protected + procedure Init; override; + function GetListTypeInfo: TBoldListTypeInfo; override; + end; + + TBOS_CommaSeparatedStringToIntegerCollection = class(TBOS_CommaSeparatedStringToCollection) + protected + procedure Init; override; + function GetListTypeInfo: TBoldListTypeInfo; override; + end; + + TBOS_Trim = class(TBoldOclSymbol) + protected + procedure Init; override; + public + procedure Evaluate(const Params: TBoldOclSymbolParameters); override; + end; + + TBOS_HasDuplicates = class(TBoldOclSymbol) + protected + procedure Init; override; + public + procedure Evaluate(const Params: TBoldOclSymbolParameters); override; + end; + + TBOS_BoldId = class(TBoldOclSymbol) + protected + procedure Init; override; + public + procedure Evaluate(const Params: TBoldOclSymbolParameters); override; + end; + + TBOS_Power = class(TBoldOCLSymbol) + protected + procedure Init; override; + public + procedure Evaluate(const Params: TBoldOclSymbolParameters); override; + end; + + TBOS_Sqrt = class(TBoldOCLSymbol) + protected + procedure Init; override; + public + procedure Evaluate(const Params: TBoldOclSymbolParameters); override; + end; + procedure TBOS_Equal.Init; begin - InternalInit('=', [nil, nil], tbodNo, HELP.BooleanType, False, 100); + InternalInit('=', [nil, nil], tbodNo, HELP.BooleanType, False, 100, true); end; procedure TBOS_NotEqual.Init; begin - InternalInit('<>', [nil, nil], tbodNo, HELP.BooleanType, False, 101); // do not localize -end; - -procedure TBOS_Except.Init; -begin - InternalInit('except', [nil, nil], tbodLCC, nil, true, 101); // do not localize + InternalInit('<>', [nil, nil], tbodNo, HELP.BooleanType, False, 101, true); end; procedure TBOS_Add.Init; begin - InternalInit('+', [nil, nil], tbodLCC, nil, False, 102); // do not localize + InternalInit('+', [nil, nil], tbodLCC, nil, False, 102); end; procedure TBOS_Subtract.Init; begin - InternalInit('-',[HELP.NumericType, HELP.NumericType], tbodLCC, nil, False, 103); // do not localize + InternalInit('-',[HELP.NumericType, HELP.NumericType], tbodLCC, nil, False, 103); end; procedure TBOS_UnaryMinus.Init; begin - InternalInit('unary-', [HELP.NumericType], tbodCopyArg1, nil, False, 104); // do not localize + InternalInit('unary-', [HELP.NumericType], tbodCopyArg1, nil, False, 104); end; procedure TBOS_Multiply.Init; begin - InternalInit('*', [HELP.NumericType, HELP.NumericType], tbodLCC, nil, False, 105); // do not localize + InternalInit('*', [HELP.NumericType, HELP.NumericType], tbodLCC, nil, False, 105); end; procedure TBOS_Divide.Init; begin - InternalInit('/', [HELP.NumericType, HELP.NumericType], tbodNo, HELP.RealType, False, 106); // do not localize + InternalInit('/', [HELP.NumericType, HELP.NumericType], tbodNo, HELP.RealType, False, 106); +end; + +procedure TBOS_SafeDivZero.Init; +begin + InternalInit('safediv', [Help.NumericType, Help.NumericType], tbodNo, Help.NumericType, True, 106); end; procedure TBOS_Abs.Init; begin - InternalInit('abs', [HELP.NumericType], tbodCopyArg1, nil, True, 107); // do not localize + InternalInit('abs', [HELP.NumericType], tbodCopyArg1, nil, True, 107); end; procedure TBOS_Floor.Init; begin - InternalInit('floor', [HELP.NumericType], tbodNo, HELP.IntegerType, True, 108); // do not localize + InternalInit('floor', [HELP.NumericType], tbodNo, HELP.IntegerType, True, 108); end; procedure TBOS_Round.Init; begin - InternalInit('round', [HELP.NumericType], tbodNo, HELP.IntegerType, True, 109); // do not localize + InternalInit('round', [HELP.NumericType], tbodNo, HELP.IntegerType, True, 109); end; procedure TBOS_strToInt.Init; begin - InternalInit('strToInt', [HELP.stringType], tbodNo, HELP.IntegerType, True, 109); // do not localize + InternalInit('strToInt', [HELP.stringType], tbodNo, HELP.IntegerType, True, 109); +end; + +procedure TBOS_strToFloat.Init; +begin + InternalInit('strToFloat', [HELP.stringType], tbodNo, HELP.RealType, True, 109); end; procedure TBOS_Max.Init; begin - InternalInit('max', [HELP.NumericType, HELP.NumericType], tbodLCC, nil, True, 110); // do not localize + InternalInit('max', [HELP.NumericType, HELP.NumericType], tbodLCC, nil, True, 110); end; + procedure TBOS_Min.Init; begin - InternalInit('min', [HELP.NumericType, HELP.NumericType], tbodLCC, nil, True, 111); // do not localize + InternalInit('min', [HELP.NumericType, HELP.NumericType], tbodLCC, nil, True, 111); end; procedure TBOS_Less.Init; begin - InternalInit('<', [nil, nil], tbodNo, HELP.BooleanType, False, 112); // do not localize + InternalInit('<', [nil, nil], tbodNo, HELP.BooleanType, False, 112); end; + procedure TBOS_Greater.Init; begin - InternalInit('>', [nil, nil], tbodNo, HELP.BooleanType, False, 113); // do not localize + InternalInit('>', [nil, nil], tbodNo, HELP.BooleanType, False, 113); end; + procedure TBOS_LessEQ.Init; begin - InternalInit('<=', [nil, nil], tbodNo, HELP.BooleanType, False, 114); // do not localize + InternalInit('<=', [nil, nil], tbodNo, HELP.BooleanType, False, 114); end; + procedure TBOS_GreaterEQ.Init; begin - InternalInit('>=', [nil, nil], tbodNo, HELP.BooleanType, False, 115); // do not localize + InternalInit('>=', [nil, nil], tbodNo, HELP.BooleanType, False, 115); end; procedure TBOS_Div.Init; begin - InternalInit('div', [HELP.IntegerType, HELP.IntegerType], tbodNo, HELP.IntegerType, False, 116); // do not localize + InternalInit('div', [HELP.IntegerType, HELP.IntegerType], tbodNo, HELP.IntegerType, False, 116); end; + procedure TBOS_Mod.Init; begin - InternalInit('mod', [HELP.IntegerType, HELP.IntegerType], tbodNo, HELP.IntegerType, False, 117); // do not localize + InternalInit('mod', [HELP.IntegerType, HELP.IntegerType], tbodNo, HELP.IntegerType, False, 117); end; procedure TBOS_Length.Init; begin - InternalInit('length', [HELP.StringType], tbodNo, HELP.IntegerType, True, 118); // do not localize + InternalInit('length', [HELP.StringType], tbodNo, HELP.IntegerType, True, 118); end; + procedure TBOS_concat.Init; begin - InternalInit('concat', [HELP.StringType, HELP.StringType], tbodNo, HELP.StringType, True, 119); // do not localize + InternalInit('concat', [HELP.StringType, HELP.StringType], tbodNo, HELP.StringType, True, 119); end; + procedure TBOS_ToUpper.Init; begin - InternalInit('toUpper', [HELP.StringType], tbodNo, HELP.StringType, True, 120); // do not localize + InternalInit('toUpper', [HELP.StringType], tbodNo, HELP.StringType, True, 120); end; + procedure TBOS_toLower.Init; begin - InternalInit('toLower', [HELP.StringType], tbodNo, HELP.StringType, True, 121); // do not localize + InternalInit('toLower', [HELP.StringType], tbodNo, HELP.StringType, True, 121); end; + procedure TBOS_SubString.Init; begin - InternalInit('subString', [HELP.StringType, HELP.IntegerType, HELP.IntegerType], tbodNo, HELP.StringType, True, 122); // do not localize + InternalInit('subString', [HELP.StringType, HELP.IntegerType, HELP.IntegerType], tbodNo, HELP.StringType, True, 122); +end; + +procedure TBOS_Contains.Init; +begin + InternalInit('contains', [HELP.StringType, HELP.StringType], tbodNo, HELP.BooleanType, True, 122); end; procedure TBOS_Pad.Init; begin - InternalInit('pad', [HELP.StringType, HELP.IntegerType, HELP.StringType], tbodNo, HELP.StringType, True, 123); // do not localize + InternalInit('pad', [HELP.StringType, HELP.IntegerType, HELP.StringType], tbodNo, HELP.StringType, True, 123); end; procedure TBOS_PostPad.Init; begin - InternalInit('postPad', [HELP.StringType, HELP.IntegerType, HELP.StringType], tbodNo, HELP.StringType, True, 124); // do not localize + InternalInit('postPad', [HELP.StringType, HELP.IntegerType, HELP.StringType], tbodNo, HELP.StringType, True, 124); +end; + +procedure TBOS_format.Init; +begin + InternalInit('format', [HELP.NumericType, HELP.StringType], tbodNo, HELP.StringType, True, 124); +end; + +procedure TBOS_FormatFloat.Init; +begin + InternalInit('formatFloat', [HELP.NumericType, HELP.StringType], tbodNo, HELP.StringType, True, 124); end; procedure TBOS_formatNumeric.Init; begin - InternalInit('formatNumeric', [HELP.NumericType, HELP.StringType], tbodNo, HELP.StringType, True, 124); // do not localize + InternalInit('formatNumeric', [HELP.NumericType, HELP.StringType], tbodNo, HELP.StringType, True, 124); end; procedure TBOS_formatDateTime.Init; begin - InternalInit('formatDateTime', [HELP.MomentType, HELP.StringType], tbodNo, HELP.StringType, True, 124); // do not localize + InternalInit('formatDateTime', [HELP.MomentType, HELP.StringType], tbodNo, HELP.StringType, True, 124); +end; + +procedure TBOS_AsISODateTime.Init; +begin + InternalInit('asISODateTime', [HELP.MomentType], tbodNo, HELP.StringType, True, 124); +end; + +procedure TBOS_AsISODate.Init; +begin + InternalInit('asISODate', [HELP.MomentType], tbodNo, HELP.StringType, True, 124); end; procedure TBOS_StrToDate.Init; begin - InternalInit('strToDate', [HELP.StringType], tbodNo, HELP.DateType, True, 124); // do not localize + InternalInit('strToDate', [HELP.StringType], tbodNo, HELP.DateType, True, 124); end; procedure TBOS_StrToTime.Init; begin - InternalInit('strToTime', [HELP.StringType], tbodNo, HELP.TimeType, True, 124); // do not localize + InternalInit('strToTime', [HELP.StringType], tbodNo, HELP.TimeType, True, 124); end; procedure TBOS_StrToDateTime.Init; begin - InternalInit('strToDateTime', [HELP.StringType], tbodNo, HELP.DateTimeType, True, 124); // do not localize + InternalInit('strToDateTime', [HELP.StringType], tbodNo, HELP.DateTimeType, True, 124); +end; + +function TBOS_or.GetShortCircuitType: ShortCircuitType; +begin + Result := csOr; end; procedure TBOS_or.Init; begin - InternalInit('or', [HELP.BooleanType, HELP.BooleanType], tbodNo, HELP.BooleanType, True, 125); // do not localize + InternalInit('or', [HELP.BooleanType, HELP.BooleanType], tbodNo, HELP.BooleanType, True, 125); +end; + +function TBOS_and.GetShortCircuitType: ShortCircuitType; +begin + Result := csAnd; end; + procedure TBOS_and.Init; begin - InternalInit('and', [HELP.BooleanType, HELP.BooleanType], tbodNo, HELP.BooleanType, True, 126); // do not localize + InternalInit('and', [HELP.BooleanType, HELP.BooleanType], tbodNo, HELP.BooleanType, True, 126); end; + procedure TBOS_xor.Init; begin - InternalInit('xor', [HELP.BooleanType, HELP.BooleanType], tbodNo, HELP.BooleanType, True, 127); // do not localize + InternalInit('xor', [HELP.BooleanType, HELP.BooleanType], tbodNo, HELP.BooleanType, True, 127); end; + procedure TBOS_implies.Init; begin - InternalInit('implies', [HELP.BooleanType, HELP.BooleanType], tbodNo, HELP.BooleanType, True, 128); // do not localize + InternalInit('implies', [HELP.BooleanType, HELP.BooleanType], tbodNo, HELP.BooleanType, True, 128); end; + procedure TBOS_not.Init; begin - InternalInit('not', [HELP.BooleanType], tbodNo, HELP.BooleanType, True, 129); // do not localize + InternalInit('not', [HELP.BooleanType], tbodNo, HELP.BooleanType, True, 129); +end; + +function TBOS_if.GetShortCircuitType: ShortCircuitType; +begin + Result := csIf; end; procedure TBOS_if.Init; begin - InternalInit('if', [HELP.BooleanType, nil, nil], tbodLCC23, nil, True, 130); // do not localize + InternalInit('if', [HELP.BooleanType, nil, nil], tbodLCC23, nil, True, 130); end; procedure TBOS_Size.Init; begin - InternalInit('size', [HELP.ListType], tbodNo, HELP.IntegerType, True, 131); // do not localize + InternalInit('size', [HELP.ListType], tbodNo, HELP.IntegerType, True, 131); end; + procedure TBOS_includes.Init; begin - InternalInit('includes', [HELP.ListType, nil], tbodNo, HELP.BooleanType, True, 132, true); // do not localize + InternalInit('includes', [HELP.ListType, nil], tbodNo, HELP.BooleanType, True, 132, true); end; + procedure TBOS_Count.Init; begin - InternalInit('count', [HELP.ListType, nil], tbodNo, HELP.IntegerType, True, 133, true); // do not localize + InternalInit('count', [HELP.ListType, nil], tbodNo, HELP.IntegerType, True, 133, true); end; + procedure TBOS_IncludesAll.Init; begin - InternalInit('includesAll', [HELP.ListType, HELP.ListType], tbodNo, HELP.BooleanType, True, 134, true); // do not localize + InternalInit('includesAll', [HELP.ListType, HELP.ListType], tbodNo, HELP.BooleanType, True, 134, true); end; + procedure TBOS_isEmpty.Init; begin - InternalInit('isEmpty', [HELP.ListType], tbodNo, HELP.BooleanType, True, 135); // do not localize + InternalInit('isEmpty', [HELP.ListType], tbodNo, HELP.BooleanType, True, 135); end; procedure TBOS_NotEmpty.Init; begin - InternalInit('notEmpty', [HELP.ListType], tbodNo, HELP.BooleanType, True, 136); // do not localize + InternalInit('notEmpty', [HELP.ListType], tbodNo, HELP.BooleanType, True, 136); end; + procedure TBOS_Sum.Init; begin - InternalInit('sum', [HELP.NumericListType], tbodCopyArg1Elem, nil, True, 137); // do not localize + InternalInit('sum', [HELP.NumericListType], tbodCopyArg1Elem, nil, True, 137); end; procedure TBOS_MinValue.Init; begin - InternalInit('minValue', [HELP.NumericListType], tbodCopyArg1Elem, nil, True, 138); // do not localize + InternalInit('minValue', [HELP.NumericListType], tbodCopyArg1Elem, nil, True, 138); end; + procedure TBOS_Maxvalue.Init; begin - InternalInit('maxValue', [HELP.NumericListType], tbodCopyArg1Elem, nil, True, 139); // do not localize + InternalInit('maxValue', [HELP.NumericListType], tbodCopyArg1Elem, nil, True, 139); end; + procedure TBOS_Average.Init; begin - InternalInit('average', [HELP.NumericListType], tbodNo, HELP.RealType, True, 140); // do not localize + InternalInit('average', [HELP.NumericListType], tbodNo, HELP.RealType, True, 140); end; + procedure TBOS_Exists.Init; begin - InternalInit('exists', [HELP.ListType, HELP.BooleanType], tbodNo, HELP.BooleanType, True, 141); // do not localize + InternalInit('exists', [HELP.ListType, HELP.BooleanType], tbodNo, HELP.BooleanType, True, 141); end; + procedure TBOS_ForAll.Init; begin - InternalInit('forAll', [HELP.ListType, HELP.BooleanType], tbodNo, HELP.BooleanType, True, 142); // do not localize + InternalInit('forAll', [HELP.ListType, HELP.BooleanType], tbodNo, HELP.BooleanType, True, 142); end; + procedure TBOS_union.Init; begin - InternalInit('union', [HELP.ListType, HELP.ListType], tbodLCC, nil, True, 143); // do not localize + InternalInit('union', [HELP.ListType, HELP.ListType], tbodLCC, nil, True, 143); end; + procedure TBOS_Intersection.Init; begin - InternalInit('intersection', [HELP.ListType, HELP.ListType], tbodLCC, nil, True, 144, true); // do not localize + InternalInit('intersection', [HELP.ListType, HELP.ListType], tbodLCC, nil, True, 144, true); end; + procedure TBOS_difference.Init; begin - InternalInit('difference', [HELP.ListType, HELP.ListType], tbodCopyArg1, nil, True, 145, true); // do not localize + InternalInit('difference', [HELP.ListType, HELP.ListType], tbodCopyArg1, nil, True, 145, true); end; + procedure TBOS_Including.Init; begin - InternalInit('including', [HELP.ListType, HELP.ObjectType], tbodLCC, nil, True, 146); // do not localize + InternalInit('including', [HELP.ListType, HELP.ObjectType], tbodLCC, nil, True, 146); end; + procedure TBOS_excluding.Init; begin - InternalInit('excluding', [HELP.ListType, HELP.ObjectType], tbodCopyArg1, nil, True, 147); // do not localize + InternalInit('excluding', [HELP.ListType, HELP.ObjectType], tbodCopyArg1, nil, True, 147); end; + procedure TBOS_SymmetricDifference.Init; begin - InternalInit('symmetricDifference', [HELP.ListType, HELP.ListType], tbodLCC, nil, True, 148); // do not localize + InternalInit('symmetricDifference', [HELP.ListType, HELP.ListType], tbodLCC, nil, True, 148); end; + procedure TBOS_Select.Init; begin - InternalInit('select', [HELP.ListType, HELP.BooleanType], tbodCopyArg1, nil, True, 149); // do not localize + InternalInit('select', [HELP.ListType, HELP.BooleanType], tbodCopyArg1, nil, True, 149); end; + procedure TBOS_reject.Init; begin - InternalInit('reject', [HELP.ListType, HELP.BooleanType], tbodCopyArg1, nil, True, 150); // do not localize + InternalInit('reject', [HELP.ListType, HELP.BooleanType], tbodCopyArg1, nil, True, 150); end; + procedure TBOS_collect.Init; begin - InternalInit('collect', [HELP.ListType, nil], tbodListofArg2, nil, True, 151); // do not localize + InternalInit('collect', [HELP.ListType, nil], tbodListofArg2, nil, True, 151); end; + procedure TBOS_AsSequence.Init; begin - InternalInit('asSequence', [HELP.ListType], tbodArg1AsList, nil, True, 152); // do not localize + InternalInit('asSequence', [HELP.ListType], tbodArg1AsList, nil, True, 152); end; + procedure TBOS_AsBag.Init; begin - InternalInit('asBag', [HELP.ListType], tbodArg1AsList, nil, True, 153); // do not localize + InternalInit('asBag', [HELP.ListType], tbodArg1AsList, nil, True, 153); end; + procedure TBOS_AsSet.Init; begin - InternalInit('asSet', [HELP.ListType], tbodArg1AsList, nil, True, 154); // do not localize + InternalInit('asSet', [HELP.ListType], tbodArg1AsList, nil, True, 154); end; + procedure TBOS_Append.Init; begin - InternalInit('append', [HELP.ListType, HELP.ObjectType], tbodLCC, nil, True, 155); // do not localize + InternalInit('append', [HELP.ListType, HELP.ObjectType], tbodLCC, nil, True, 155); end; + procedure TBOS_Prepend.Init; begin - InternalInit('prepend', [HELP.ListType, HELP.ObjectType], tbodLCC, nil, True, 156); // do not localize + InternalInit('prepend', [HELP.ListType, HELP.ObjectType], tbodLCC, nil, True, 156); end; + procedure TBOS_SubSequence.Init; begin - InternalInit('subSequence', [HELP.ListType, HELP.IntegerType, HELP.IntegerType], tbodCopyArg1, nil, True, 157); // do not localize + InternalInit('subSequence', [HELP.ListType, HELP.IntegerType, HELP.IntegerType], tbodCopyArg1, nil, True, 157); end; + procedure TBOS_at.Init; begin - InternalInit('at', [HELP.ListType, HELP.IntegerType], tbodCopyArg1Elem, nil, True, 158); // do not localize + InternalInit('at', [HELP.ListType, HELP.IntegerType], tbodCopyArg1Elem, nil, True, 158); end; + procedure TBOS_first.Init; begin - InternalInit('first', [HELP.ListType], tbodCopyArg1Elem, nil, True, 159); // do not localize + InternalInit('first', [HELP.ListType], tbodCopyArg1Elem, nil, True, 159); end; + procedure TBOS_last.Init; begin - InternalInit('last', [HELP.ListType], tbodCopyArg1Elem, nil, True, 160); // do not localize + InternalInit('last', [HELP.ListType], tbodCopyArg1Elem, nil, True, 160); end; procedure TBOS_orderby.Init; begin - InternalInit('orderby', [HELP.ListType, nil], tbodCopyArg1, nil, True, 161); // do not localize + InternalInit('orderby', [HELP.ListType, nil], tbodCopyArg1, nil, True, 161); end; + procedure TBOS_orderDescending.Init; begin - InternalInit('orderdescending', [HELP.ListType, nil], tbodCopyArg1, nil, True, 162); // do not localize + InternalInit('orderdescending', [HELP.ListType, nil], tbodCopyArg1, nil, True, 162); end; - - procedure TBOS_asString.Init; begin - InternalInit('asString', [nil], tbodNo, HELP.StringType, True, 163); // do not localize + InternalInit('asString', [nil], tbodNo, HELP.StringType, True, 163); +end; + +procedure TBOS_datePart.Init; +begin + InternalInit('datePart', [HELP.MomentType], tbodNo, HELP.DateType, True, 163); end; -procedure TBOS_dateTimeAsFloat.Init; +procedure TBOS_asDateTime.Init; begin - InternalInit('dateTimeAsFloat', [HELP.MomentType], tbodNo, HELP.RealType, True, 163); // do not localize + InternalInit('asDateTime', [HELP.MomentType], tbodNo, HELP.DateTimeType, True, 163); end; procedure TBOS_TypeName.Init; begin - InternalInit('typename', [HELP.TypeType], tbodNo, HELP.StringType, True, 164); // do not localize + InternalInit('typename', [HELP.TypeType], tbodNo, HELP.StringType, True, 164); end; procedure TBOS_Attributes.Init; begin - InternalInit('attributes', [HELP.TypeType], tbodNo, HELP.StringListType, True, 165); // do not localize + InternalInit('attributes', [HELP.TypeType], tbodNo, HELP.StringListType, True, 165); end; procedure TBOS_AssociationEnds.Init; begin - InternalInit('associationEnds', [HELP.TypeType], tbodNo, HELP.StringListType, True, 166); // do not localize + InternalInit('associationEnds', [HELP.TypeType], tbodNo, HELP.StringListType, True, 166); end; {procedure TBOS_Operations.Init; begin - InternalInit('operations', [HELP.TypeType], tbodNo, HELP.StringListType, True, 167); // do not localize + InternalInit('operations', [HELP.TypeType], tbodNo, HELP.StringListType, True, 167); end; } procedure TBOS_SuperTypes.Init; begin - InternalInit('superTypes', [HELP.TypeType], tbodNo, HELP.TypeListType, True, 168); // do not localize + InternalInit('superTypes', [HELP.TypeType], tbodNo, HELP.TypeListType, True, 168); end; procedure TBOS_AllSuperTypes.Init; begin - InternalInit('allSuperTypes', [HELP.TypeType], tbodNo, HELP.TypeListType, True, 169); // do not localize + InternalInit('allSuperTypes', [HELP.TypeType], tbodNo, HELP.TypeListType, True, 169); end; procedure TBOS_AllSubClasses.Init; begin - InternalInit('allSubClasses', [HELP.TypeType], tbodNo, HELP.TypeListType, True, 169); // do not localize + InternalInit('allSubClasses', [HELP.TypeType], tbodNo, HELP.TypeListType, True, 169); end; procedure TBOS_AllInstances.Init; begin - InternalInit('allInstances', [HELP.TypeType], tbodObjectList, nil, True, 170); // do not localize + InternalInit('allInstances', [HELP.TypeType], tbodObjectList, nil, True, 170); end; procedure TBOS_AllLoadedObjects.Init; begin - InternalInit('allLoadedObjects', [HELP.TypeType], tbodObjectList, nil, True, 170); // do not localize + InternalInit('allLoadedObjects', [HELP.TypeType], tbodObjectList, nil, True, 170); end; procedure TBOS_emptyList.Init; begin - InternalInit('emptyList', [HELP.TypeType], tbodObjectList, nil, True, 170); // do not localize + InternalInit('emptyList', [HELP.TypeType], tbodObjectList, nil, True, 170); end; procedure TBOS_oclType.Init; begin - InternalInit('oclType', [nil], tbodNo, HELP.TypeType, True, 171); // do not localize + InternalInit('oclType', [nil], tbodNo, HELP.TypeType, True, 171); end; procedure TBOS_oclIsKindOf.Init; begin - InternalInit('oclIsKindOf', [nil, Help.TypeType], tbodNo, HELP.BooleanType, True, 172); // do not localize + InternalInit('oclIsKindOf', [nil, Help.TypeType], tbodNo, HELP.BooleanType, True, 172); end; procedure TBOS_OclIsTypeOf.Init; begin - InternalInit('oclIsTypeOf', [nil, Help.TypeType], tbodNo, HELP.BooleanType, True, 173); // do not localize + InternalInit('oclIsTypeOf', [nil, Help.TypeType], tbodNo, HELP.BooleanType, True, 173); end; procedure TBOS_OclAsType.Init; begin - InternalInit('oclAsType', [nil, Help.TypeType], tbodTypeCast, nil, True, 174); // do not localize + InternalInit('oclAsType', [nil, Help.TypeType], tbodTypeCast, nil, True, 174); end; procedure TBOS_SafeCast.Init; begin - InternalInit('safeCast', [nil, Help.TypeType], tbodTypeCast, nil, True, 174); // do not localize + InternalInit('safeCast', [nil, Help.TypeType], tbodTypeCast, nil, True, 174); end; procedure TBOS_sqlLike.Init; begin - InternalInit('sqlLike', [help.StringType, help.StringType], tbodNo, Help.BooleanType, True, 175); // do not localize + InternalInit('sqlLike', [help.StringType, help.StringType], tbodNo, Help.BooleanType, True, 175); end; procedure TBOS_SqlLikeCaseInsensitive.Init; begin - InternalInit('sqlLikeCaseInsensitive', [help.StringType, help.StringType], tbodNo, Help.BooleanType, True, 176); // do not localize + InternalInit('sqlLikeCaseInsensitive', [help.StringType, help.StringType], tbodNo, Help.BooleanType, True, 176); end; procedure TBOS_RegExpMatch.Init; begin - InternalInit('regExpMatch', [help.StringType, help.StringType], tbodNo, Help.BooleanType, True, 177); // do not localize + InternalInit('regExpMatch', [help.StringType, help.StringType], tbodNo, Help.BooleanType, True, 177); end; procedure TBOS_InDateRange.Init; begin - InternalInit('inDateRange', [help.MomentType, help.NumericType, help.NumericType], tbodNo, Help.BooleanType, True, 178); // do not localize + InternalInit('inDateRange', [help.MomentType, help.NumericType, help.NumericType], tbodNo, Help.BooleanType, True, 178); end; procedure TBOS_InTimeRange.Init; begin - InternalInit('inTimeRange', [help.MomentType, help.NumericType, help.NumericType], tbodNo, Help.BooleanType, True, 179); // do not localize + InternalInit('inTimeRange', [help.MomentType, help.NumericType, help.NumericType], tbodNo, Help.BooleanType, True, 179); end; procedure TBOS_isNull.Init; begin - InternalInit('isNull', [nil], tbodNo, HELP.BooleanType, True, 180); // do not localize + InternalInit('isNull', [nil], tbodNo, HELP.BooleanType, True, 180); end; procedure TBOS_Constraints.Init; @@ -1228,63 +1540,87 @@ procedure TBOS_Constraints.Init; ConstraintListTypeInfo: TBoldListTypeInfo; begin ConstraintListTypeInfo := Help.SystemTypeInfo.ListTypeInfoByElement[Help.ConstraintType]; - InternalInit('constraints', [nil], tbodNo, ConstraintListTypeInfo, True, 181); // do not localize + InternalInit('constraints', [nil], tbodNo, ConstraintListTypeInfo, True, 181); end; procedure TBOS_AtTime.Init; begin - InternalInit('atTime', [help.ObjectType, help.IntegerType], tbodCopyArg1, nil, True, 182); // do not localize + InternalInit('atTime', [help.ObjectType, help.IntegerType], tbodCopyArg1, nil, True, 182); end; procedure TBOS_ObjectTimeStamp.Init; begin - InternalInit('objectTimeStamp', [help.ObjectType], tbodNo, Help.IntegerType, True, 182); // do not localize + InternalInit('objectTimeStamp', [help.ObjectType], tbodNo, Help.IntegerType, True, 182); end; - procedure TBOS_allInstancesAtTime.Init; begin - InternalInit('allInstancesAtTime', [help.TypeType, help.IntegerType], tbodObjectList, nil, True, 183); // do not localize + InternalInit('allInstancesAtTime', [help.TypeType, help.IntegerType], tbodObjectList, nil, True, 183); end; procedure TBOS_existing.Init; begin - InternalInit('existing', [help.ObjectType], tbodNo, HELP.BooleanType, True, 184); // do not localize + InternalInit('existing', [help.ObjectType], tbodNo, HELP.BooleanType, True, 184); end; procedure TBOS_FilterOnType.Init; begin - InternalInit('filterOnType', [help.ListType, help.TypeType], tbodListFromArg2, nil, True, 185); // do not localize + InternalInit('filterOnType', [help.ListType, help.TypeType], tbodListFromArg2, nil, True, 185); end; procedure TBOS_BoldTime.Init; begin - InternalInit('boldTime', [help.ObjectType], tbodno, help.integerType, True, 186); // do not localize + InternalInit('boldTime', [help.ObjectType], tbodno, help.integerType, True, 186); end; procedure TBOS_TimeStampToTime.Init; begin - InternalInit('timeStampToTime', [help.IntegerType], tbodno, help.DateTimeType, True, 187); // do not localize + InternalInit('timeStampToTime', [help.IntegerType], tbodno, help.DateTimeType, True, 187); end; procedure TBOS_TimeToTimeStamp.Init; begin - InternalInit('timeToTimeStamp', [help.DateTimeType], tbodno, help.IntegerType, True, 188); // do not localize + InternalInit('timeToTimeStamp', [help.DateTimeType], tbodno, help.IntegerType, True, 188); end; -procedure TBOS_SumTime.Init; +procedure TBOS_StringRepresentation.Init; begin - InternalInit('sumTime', [HELP.MomentListType], tbodNo, Help.DateTimeType, True, 189); // do not localize + InternalInit('stringRepresentation', [nil, help.integerType], tbodNo, HELP.StringType, True, 190); end; -procedure TBOS_StringRepresentation.Init; +procedure TBOS_TaggedValue.Init; begin - InternalInit('stringRepresentation', [nil, help.integerType], tbodNo, HELP.StringType, True, 190); // do not localize + InternalInit('taggedValue', [help.ObjectType, help.StringType], tbodNo, HELP.StringType, True, 190); end; -procedure TBOS_TaggedValue.Init; +procedure TBOS_IndexOf.Init; +begin + InternalInit('indexOf', [HELP.ListType, nil{HELP.ObjectType}], tbodNo, HELP.IntegerType, True, 191, true); +end; + +procedure TBOS_ReverseCollection.Init; +begin + InternalInit('reverseCollection', [HELP.ListType], tbodCopyArg1, nil, True, 192); +end; + +procedure TBOS_HasDuplicates.Init; +begin + InternalInit('hasDuplicates', [HELP.ListType], tbodNo, HELP.BooleanType, True, 193); +end; + +procedure TBOS_BoldId.Init; +begin + InternalInit('boldID', [Help.ObjectType], tbodNo, Help.IntegerType, True, 194); +end; + +procedure TBOS_Power.Init; begin - InternalInit('taggedValue', [help.ObjectType, help.StringType], tbodNo, HELP.StringType, True, 190); // do not localize + InternalInit('power', [Help.NumericType, Help.NumericType], tbodNo, Help.RealType, True, 0); +end; + +procedure TBOS_Sqrt.Init; +begin + InternalInit('sqrt', [Help.NumericType], tbodNo, Help.RealType, True, 0); end; {-- SymbolImplementations --} @@ -1306,7 +1642,7 @@ function TBOS_AbstractCompare.CompareEnumLiterals(const Params: TBoldOclSymbolPa if Str = '' then str := (Params.nodes[1] as TBoldOClEnumLiteral).Name else - raise EBoldOclRunTimeError.CreateFmt(sCannotCompareEnumLiterals, + raise EBoldOclRunTimeError.CreateFmt('%d: Enum literals can not be compared to other enum literals (%s and %s)', [0, str, (Params.nodes[1] as TBoldOClEnumLiteral).Name]); end else if Params.Values[1] is TBAValueSet then @@ -1321,6 +1657,8 @@ procedure TBOS_Equal.Evaluate(const Params: TBoldOclSymbolParameters); HELP.MakeNewBoolean(Params.Result, CompareEnumLiterals(Params)) else if not assigned(Params.values[0]) then Help.MakeNewBoolean(Params.Result, not Assigned(Params.values[1])) + else if not Assigned(Params.values[1]) then + Help.MakeNewBoolean(Params.Result, false) else HELP.MakeNewBoolean(Params.Result, Params.values[0].IsEqual(Params.values[1])); end; @@ -1331,16 +1669,12 @@ procedure TBOS_NotEqual.Evaluate(const Params: TBoldOclSymbolParameters); HELP.MakeNewBoolean(Params.Result, not CompareEnumLiterals(Params)) else if not assigned(Params.values[0]) then Help.MakeNewBoolean(Params.Result, Assigned(Params.values[1])) + else if not Assigned(Params.values[1]) then + Help.MakeNewBoolean(Params.Result, true) else HELP.MakeNewBoolean(Params.Result, not Params.values[0].IsEqual(Params.values[1])); end; -procedure TBOS_Except.Evaluate(const Params: TBoldOclSymbolParameters); -begin - // this operation does not need to do anything as it is all handled by the evaluator - // this method is never called... -end; - {-- Real operations --} @@ -1394,14 +1728,36 @@ procedure TBOS_Multiply.Evaluate(const Params: TBoldOclSymbolParameters); end; procedure TBOS_Divide.Evaluate(const Params: TBoldOclSymbolParameters); + + procedure RaiseError; + begin + raise EBoldOclRuntimeError.CreateFmt(borteDivisionByZero, [0]); + end; + begin try HELP.MakeNewNumeric(Params.Result, XNumeric(Params.values[0]) / XNumeric(Params.values[1])); except + on e: EInvalidOp do + RaiseError; on e: EDivByZero do - raise EBoldOclRuntimeError.CreateFmt(borteDivisionByZero, [0]); + RaiseError; on e: EZeroDivide do - raise EBoldOclRuntimeError.CreateFmt(borteDivisionByZero, [0]); + RaiseError; + end; +end; + +{ TBOS_SafeDivZero } + +procedure TBOS_SafeDivZero.Evaluate( + const Params: TBoldOclSymbolParameters); +begin + try + HELP.MakeNewNumeric(Params.Result, XNumeric(Params.values[0]) / XNumeric(Params.values[1])); + except + on e: EInvalidOp do; + on e: EDivByZero do; + on e: EZeroDivide do; end; end; @@ -1427,23 +1783,56 @@ procedure TBOS_Round.Evaluate(const Params: TBoldOclSymbolParameters); procedure TBOS_StrToInt.Evaluate(const Params: TBoldOclSymbolParameters); begin - HELP.MakeNewInteger(Params.Result, StrToIntDef(XString(Params.values[0]), 0)); + HELP.MakeNewInteger(Params.Result, StrToInt(XString(Params.values[0]))); +end; + +procedure TBOS_strToFloat.Evaluate(const Params: TBoldOclSymbolParameters); +begin + HELP.MakeNewNumeric(Params.Result, StrToFloat(XString(Params.values[0]))); end; procedure TBOS_Max.Evaluate(const Params: TBoldOclSymbolParameters); +var + result: TBoldElement; begin - if Params.Result.BoldType.ConformsTo(HELP.integerType) then - HELP.MakeNewInteger(Params.Result, MaxIntValue([XInteger(Params.values[0]),XInteger(Params.values[1])])) + result := Params.values[0]; + if Assigned(result) and Assigned(Params.values[1]) then + begin + if result.CompareTo(Params.Values[1]) = -1 then + result := Params.values[1]; + end + else + if not Assigned(result) then + result := Params.values[1]; + if not Assigned(result) then + HELP.MakeNewNull(Params.Result, Params.Result.BoldType) else - HELP.MakeNewNumeric(Params.Result, maxValue([XNumeric(Params.values[0]),XNumeric(Params.values[1])])); + begin + HELP.MakeNew(Params.Result, Params.Result.BoldType); + Params.Result.Value.Assign(Result); + end; end; procedure TBOS_Min.Evaluate(const Params: TBoldOclSymbolParameters); +var + result: TBoldElement; begin - if Params.Result.BoldType.ConformsTo(HELP.integerType) then - HELP.MakeNewInteger(Params.Result, MinIntValue([XInteger(Params.values[0]),XInteger(Params.values[1])])) + result := Params.values[0]; + if Assigned(result) and Assigned(Params.values[1]) then + begin + if result.CompareTo(Params.Values[1]) = 1 then + result := Params.values[1]; + end + else + if not Assigned(result) then + result := Params.values[1]; + if not Assigned(result) then + HELP.MakeNewNull(Params.Result, Params.Result.BoldType) else - HELP.MakeNewNumeric(Params.Result, MinValue([XNumeric(Params.values[0]),XNumeric(Params.values[1])])); + begin + HELP.MakeNew(Params.Result, Params.Result.BoldType); + Params.Result.Value.Assign(Result); + end; end; procedure TBOS_Less.Evaluate(const Params: TBoldOclSymbolParameters); @@ -1530,6 +1919,15 @@ procedure TBOS_SubString.Evaluate(const Params: TBoldOclSymbolParameters); HELP.MakeNewString(Params.Result, S); end; +procedure TBOS_Contains.Evaluate(const Params: TBoldOclSymbolParameters); +var + s, subs : string; +begin + S := XString(Params.values[0]); + Subs := XString(Params.values[1]); + HELP.MakeNewBoolean(Params.Result, Pos(Subs, S) > 0); +end; + procedure TBOS_Pad.Evaluate(const Params: TBoldOclSymbolParameters); var Finallength: Integer; @@ -1578,32 +1976,50 @@ procedure TBOS_PostPad.Evaluate(const Params: TBoldOclSymbolParameters); Help.MakeNewString(Params.Result, PaddedStr); end; -procedure TBOS_FormatNumeric.Evaluate(const Params: TBoldOclSymbolParameters); +procedure TBOS_Format.Evaluate(const Params: TBoldOclSymbolParameters); begin help.MakeNewString(params.result, format(XString(Params.values[1]), [XNumeric(Params.values[0])])); end; +procedure TBOS_FormatFloat.Evaluate(const Params: TBoldOclSymbolParameters); +begin + help.MakeNewString(params.result, formatFloat(XString(Params.values[1]), XNumeric(Params.values[0]))); +end; + +procedure TBOS_AsISODateTime.Evaluate(const Params: TBoldOclSymbolParameters); +var + Moment: TBAMoment; +begin + Moment := Params.values[0] as TBAMoment; + if not Assigned(moment) or moment.IsNull then + HELP.MakeNewNull(Params.Result, Params.Result.BoldType) + else + help.MakeNewString(params.result, formatDateTime(cIsoDateTimeFormat, ExtractDateTimeFromMoment(Moment))); +end; + +procedure TBOS_AsISODate.Evaluate(const Params: TBoldOclSymbolParameters); +var + Moment: TBAMoment; +begin + Moment := Params.values[0] as TBAMoment; + if not Assigned(moment) or moment.IsNull then + HELP.MakeNewNull(Params.Result, Params.Result.BoldType) + else + help.MakeNewString(params.result, formatDateTime(cIsoDateFormat, ExtractDateTimeFromMoment(Moment))); +end; + procedure TBOS_FormatDateTime.Evaluate(const Params: TBoldOclSymbolParameters); var Moment: TBAMoment; - val: TDateTime; begin Moment := Params.values[0] as TBAMoment; - if moment.IsNull then + if not Assigned(moment) or moment.IsNull then begin help.MakeNewString(params.result, ''); end else begin - if Moment is TBADateTime then - val := (Moment as TBADateTime).asDateTime - else if Moment is TBADate then - val := (Moment as TBADate).asDate - else if Moment is TBATime then - val := (Moment as TBATime).asTime - else - val := 0; - help.MakeNewString(params.result, formatDateTime(XString(Params.values[1]), val)); + help.MakeNewString(params.result, formatDateTime(XString(Params.values[1]), ExtractDateTimeFromMoment(Moment))); end; end; @@ -1682,6 +2098,7 @@ procedure TBOS_Count.Evaluate(const Params: TBoldOclSymbolParameters); else begin Elem := Params.values[1]; + List.EnsureRange(0, List.Count - 1); for i := 0 to List.Count - 1 do if List[i].IsEqual(Elem) then inc(Count); HELP.MakeNewInteger(Params.Result, Count); @@ -1706,9 +2123,9 @@ procedure TBOS_IncludesAll.Evaluate(const Params: TBoldOclSymbolParameters); begin IncludesAll := True; - while (i < list2.Count) and IncludesAll do + while (i < list1.Count) and IncludesAll do begin - IncludesAll := IncludesAll and list1.Includes(list2[i]); + IncludesAll := IncludesAll and list2.Includes(list1[i]); inc(i); end; HELP.MakeNewBoolean(Params.Result, IncludesAll); @@ -1734,7 +2151,7 @@ procedure TBOS_NotEmpty.Evaluate(const Params: TBoldOclSymbolParameters); List := XList(Params.values[0]); if not assigned(list) then - HELP.MakeNewBoolean(Params.Result, true) + HELP.MakeNewBoolean(Params.Result, false) else HELP.MakeNewBoolean(Params.Result, List.Count <> 0); end; @@ -1744,29 +2161,25 @@ procedure TBOS_IsNull.Evaluate(const Params: TBoldOclSymbolParameters); if Params.values[0] is TBoldAttribute then HELP.MakeNewBoolean(Params.Result, (Params.values[0] as TBoldAttribute).IsNull) else - HELP.MakeNewBoolean(Params.Result, false); + HELP.MakeNewBoolean(Params.Result, Params.values[0] = nil); end; procedure TBOS_Select.Evaluate(const Params: TBoldOclSymbolParameters); - // First argument is the evaluated expression, the second argument is the object begin if Assigned(XList(Params.Result.value)) and XBoolean(Params.values[0]) then XList(Params.Result.value).Add(Params.values[1]); end; procedure TBOS_reject.Evaluate(const Params: TBoldOclSymbolParameters); - // First argument is the evaluated expression, the second argument is the object begin - if Assigned(XList(Params.Result.value)) and not XBoolean(Params.values[0]) then + if not (Assigned(XList(Params.Result.value)) and XBoolean(Params.values[0])) then XList(Params.Result.value).Add(Params.values[1]); end; procedure TBOS_collect.Evaluate(const Params: TBoldOclSymbolParameters); - // First argument is the evaluated expression, the second argument is the object var ResultList: TBoldList; SourceList: TBoldList; - i: integer; begin ResultList := XList(Params.Result.value); if assigned(Resultlist) then @@ -1774,12 +2187,12 @@ procedure TBOS_collect.Evaluate(const Params: TBoldOclSymbolParameters); sourceList := XList(Params.values[0]); if assigned(SourceList) then begin - for i := 0 to SourceList.Count - 1 do - ResultList.add(SourceList[i]); + ResultList.AddList(SourceList); end else begin - resultList.Add(Params.values[0]); + if Assigned(Params.values[0]) then + resultList.Add(Params.values[0]); end; end; end; @@ -1789,7 +2202,7 @@ procedure TBOS_GenericOrder.Evaluate(const Params: TBoldOclSymbolParameters); SortList: TBoldMemberList; DummyValue: TBoldAttribute; begin - Sortlist := XList(Params.Result.value) as tBoldMemberList; + Sortlist := XList(Params.Result.value) as TBoldMemberList; if Assigned(SortList) then begin if assigned(Params.values[0]) then @@ -1828,84 +2241,77 @@ procedure TBOS_Sum.Evaluate(const Params: TBoldOclSymbolParameters); Sum := 0 else for i := 0 to List.Count - 1 do - Sum := Sum + XNumeric(List[i]); + if not TBoldAttribute(List[i]).IsNull then + Sum := Sum + XNumeric(List[i]); if ListElementType.ConformsTo(HELP.IntegerType) then HELP.MakeNewInteger(Params.Result, Round(Sum)) else if ListElementType.ConformsTo(HELP.CurrencyType) then HELP.MakeNewCurrency(Params.Result, Sum) + else if ListElementType.ConformsTo(HELP.TimeType) then + HELP.MakeNewDateTime(Params.Result, Sum) else HELP.MakeNewNumeric(Params.Result, Sum); end; - -procedure TBOS_SumTime.Evaluate(const Params: TBoldOclSymbolParameters); -var - Sum : TDateTime; - i : Integer; - List : TBoldList; -begin - Sum := 0; - List := XList(Params.values[0]); - - if assigned(list) then - for i := 0 to List.Count - 1 do - Sum := Sum + XDateTime(List[i]); - - HELP.MakeNewDateTime(Params.Result, Sum) -end; - - procedure TBOS_Maxvalue.Evaluate(const Params: TBoldOclSymbolParameters); var - MAX : Double; + Max : Variant; i : Integer; List : TBoldList; ListElementType: TBoldElementTypeInfo; begin + Max := Null; List := XList(Params.values[0]); ListElementType := Params.Result.BoldType; - if not assigned(list) or (list.Count = 0) then - Max := 0 - else + if assigned(list) then + for i := 0 to List.Count - 1 do begin - MAX := xNumeric(List[0]); - for i := 1 to List.Count - 1 do + if not TBoldAttribute(List[i]).IsNull then begin - if MAX < XNumeric(List[i]) then - MAX := XNumeric(List[i]) + if VarIsNull(Max) or (Max < XNumeric(List[i])) then + Max := XNumeric(List[i]); end; end; - if ListElementType.ConformsTo(HELP.IntegerType) then - HELP.MakeNewInteger(Params.Result, Round(MAX)) + if VarIsNull(Max) then + HELP.MakeNewNull(Params.Result, Params.Result.BoldType) + else if ListElementType.ConformsTo(HELP.IntegerType) then + HELP.MakeNewInteger(Params.Result, Round(Max)) else if ListElementType.ConformsTo(HELP.CurrencyType) then - HELP.MakeNewCurrency(Params.Result, MAX) + HELP.MakeNewCurrency(Params.Result, Max) + else if ListElementType.ConformsTo(HELP.MomentType) then + HELP.MakeNewDateTime(Params.Result, Max) else - HELP.MakeNewNumeric(Params.Result, MAX); + HELP.MakeNewNumeric(Params.Result, Max); end; procedure TBOS_MinValue.Evaluate(const Params: TBoldOclSymbolParameters); var - Min : Double; + Min : Variant; i : Integer; List : TBoldList; ListElementType: TBoldElementTypeInfo; begin + Min := Null; List := XList(Params.values[0]); - ListElementType := Params.Result.Boldtype; - if not assigned(list) or (List.Count = 0) then - min := 0 - else + ListElementType := Params.Result.BoldType; + if assigned(list) then + for i := 0 to List.Count - 1 do begin - Min := XNumeric(List[0]); - for i := 1 to List.Count - 1 do - if Min > XNumeric(List[i]) then Min := XNumeric(List[i]); + if not TBoldAttribute(List[i]).IsNull then + begin + if VarIsNull(Min) or (Min > XNumeric(List[i])) then + Min := XNumeric(List[i]); + end; end; - - if ListElementType.ConformsTo(HELP.IntegerType) then + if VarIsNull(Min) then + HELP.MakeNewNull(Params.Result, Params.Result.BoldType) + else if ListElementType.ConformsTo(HELP.IntegerType) then HELP.MakeNewInteger(Params.Result, Round(Min)) else if ListElementType.ConformsTo(HELP.CurrencyType) then HELP.MakeNewCurrency(Params.Result, Min) + else if ListElementType.ConformsTo(HELP.MomentType) then + HELP.MakeNewDateTime(Params.Result, Min) else HELP.MakeNewNumeric(Params.Result, Min); end; @@ -1923,21 +2329,18 @@ procedure TBOS_Average.Evaluate(const Params: TBoldOclSymbolParameters); else begin for i := 0 to List.Count - 1 do - begin - Sum := Sum + XNumeric(List[i]); - end; + if not TBoldAttribute(List[i]).IsNull then + Sum := Sum + XNumeric(List[i]); HELP.MakeNewNumeric(Params.Result, Sum / List.Count); end; end; procedure TBOS_ForAll.Evaluate(const Params: TBoldOclSymbolParameters); - // First argument is the evaluated expression, the second argument is the object begin (Params.Result.Value as TBABoolean).AsBoolean := XBoolean(Params.Result.value) and xBoolean(Params.values[0]); end; procedure TBOS_Exists.Evaluate(const Params: TBoldOclSymbolParameters); - // First argument is the evaluated expression, the second argument is the object begin (Params.Result.Value as TBABoolean).AsBoolean := XBoolean(Params.Result.value) or XBoolean(Params.values[0]); end; @@ -1945,14 +2348,37 @@ procedure TBOS_Exists.Evaluate(const Params: TBoldOclSymbolParameters); procedure TBOS_includes.Evaluate(const Params: TBoldOclSymbolParameters); var List: TBoldList; + Element: TBoldElement; + aObj: TBoldObject; i : Integer; temp: Boolean; begin temp := False; List := XList(Params.values[0]); - If Assigned(List) then - for i := 0 to List.Count - 1 do - temp := temp or (List[i].IsEqual(Params.values[1])); + if Assigned(List) and (List.Count > 0) then begin + Element := Params.Values[1]; + if List is TBoldObjectList then begin + // Optimization for ObjectLists: check for locator. + // No need to ensure objects for equality check + aObj := nil; + if Element is TBoldObject then begin + aObj := TBoldObject(Element); + end else if Element is TBoldObjectReference then begin + aObj := TBoldObjectReference(Element).BoldObject; + end; + if Assigned(aObj) then begin + temp := TBoldObjectList(List).LocatorInList(aObj.BoldObjectLocator); + end; + end else begin + List.EnsureRange(0, List.Count - 1); + for i := 0 to List.Count - 1 do begin + if List[i].IsEqual(Element) then begin + temp := True; + Break; + end; + end; + end; + end; HELP.MakeNewBoolean(Params.Result, temp); end; @@ -1962,7 +2388,6 @@ procedure TBOS_union.Evaluate(const Params: TBoldOclSymbolParameters); Help.TransferOrClone(Params.nodes[1], Params.Result) else begin - // if the result is a supertype of the two parameters, then we can not reuse either list. if assigned(Params.nodes[0].BoldType) and assigned(Params.nodes[1].BoldType) and not Params.nodes[1].BoldType.conformsto(Params.nodes[0].BoldType) then begin @@ -1980,6 +2405,7 @@ procedure TBOS_Intersection.Evaluate(const Params: TBoldOclSymbolParameters); var i : Integer; resList, list1, list2: TBoldList; +aResListObject, aList1Object, aList2Object: TBoldObjectList; begin list1 := XList(Params.values[0]); list2 := XList(Params.values[1]); @@ -1991,24 +2417,36 @@ procedure TBOS_Intersection.Evaluate(const Params: TBoldOclSymbolParameters); begin if list2.Count < list1.Count then begin - // Make sure we loop over the shortes list. resList := list1; list1 := list2; list2 := resList; end; resList := help.CreateNewMember(Params.Result.BoldType) as TBoldList; - for i := 0 to list1.Count - 1 do - if list2.Includes(list1[i]) then - resList.Add(list1[i]); + + // Optimization for ObjectLists + // Thus, the objects no longer need to be fechted during OCL evaluation + if resList is TBoldObjectList then begin + aList1Object := TBoldObjectList(list1); + aList2Object := TBoldObjectList(list2); + aResListObject := TBoldObjectList(resList); + for i := 0 to aList1Object.Count - 1 do + if aList2Object.LocatorInList(aList1Object.Locators[i]) then + aResListObject.AddLocator(aList1Object.Locators[i]); + end else begin + for i := 0 to list1.Count - 1 do + if list2.Includes(list1[i]) then + resList.Add(list1[i]); + end; Params.Result.SetOwnedValue(resList); end; end; procedure TBOS_difference.Evaluate(const Params: TBoldOclSymbolParameters); var - i, p : Integer; + i, p: Integer; list1, list2: TBoldList; + aList1Object, aList2Object: TBoldObjectList; begin if not assigned(XList(Params.values[0])) then Params.Result.SetReferenceValue(nil) @@ -2019,11 +2457,22 @@ procedure TBOS_difference.Evaluate(const Params: TBoldOclSymbolParameters); HELP.TransferOrClone(Params.nodes[0], Params.Result); list2 := XList(Params.values[1]); list1 := XList(Params.Result.value); - for i := 0 to list2.Count - 1 do - begin - p := list1.IndexOf(List2[i]); - if p <> -1 then - list1.RemoveByIndex(p); + if (list1 is TBoldObjectList) and (list2 is TBoldObjectList) then begin + aList1Object := TBoldObjectList(list1); + aList2Object := TBoldObjectList(list2); + for i := 0 to aList2Object.Count - 1 do + begin + p := aList1Object.IndexOfLocator(aList2Object.Locators[i]); + if p <> -1 then + aList1Object.RemoveByIndex(p); + end; + end else begin + for i := 0 to list2.Count - 1 do + begin + p := list1.IndexOf(List2[i]); + if p <> -1 then + list1.RemoveByIndex(p); + end; end; end; end; @@ -2057,6 +2506,7 @@ procedure TBOS_SymmetricDifference.Evaluate(const Params: TBoldOclSymbolParamete var i : Integer; resList, list1, list2: TBoldList; + aResListObject, aList1Object, aList2Object: TBoldObjectList; begin list1 := XList(Params.values[0]); list2 := XList(Params.values[1]); @@ -2067,18 +2517,33 @@ procedure TBOS_SymmetricDifference.Evaluate(const Params: TBoldOclSymbolParamete else begin resList := help.CreateNewMember(Params.Result.BoldType) as TBoldList; - for i := 0 to list1.Count - 1 do - if not list2.Includes(list1[i]) then resList.Add(list1[i]); - - for i := 0 to list2.Count - 1 do - if not list1.Includes(list2[i]) then resList.Add(list2[i]); + // Optimization for ObjectLists + if resList is TBoldObjectList then begin + aResListObject := TBoldObjectList(resList); + aList1Object := TBoldObjectList(list1); + aList2Object := TBoldObjectList(list2); + + for i := 0 to aList1Object.Count - 1 do + if not aList2Object.LocatorInList(aList1Object.Locators[i]) then + aResListObject.AddLocator(aList1Object.Locators[i]); + + for i := 0 to aList2Object.Count - 1 do + if not aList1Object.LocatorInList(aList2Object.Locators[i]) then + aResListObject.AddLocator(aList2Object.Locators[i]); + end else begin + for i := 0 to list1.Count - 1 do + if not list2.Includes(list1[i]) then resList.Add(list1[i]); + + for i := 0 to list2.Count - 1 do + if not list1.Includes(list2[i]) then resList.Add(list2[i]); + end; Params.Result.SetOwnedValue(ResList); end; end; procedure TBOS__ListCopier.CopyListToResult(const Params: TBoldOclSymbolParameters); var - temp: TBoldIndirectElement; + temp: TBoldIndirectElement; begin if assigned(Params.values[0]) then begin @@ -2109,10 +2574,17 @@ procedure TBOS_AsBag.Evaluate(const Params: TBoldOclSymbolParameters); procedure TBOS_AsSet.Evaluate(const Params: TBoldOclSymbolParameters); begin - CopyListToResult(params); - - if assigned(xlist(Params.Result.value)) then - XList(Params.Result.value).DuplicateMode := bldmMerge; + if not assigned(XList(Params.values[0])) then + Params.Result.SetReferenceValue(nil) + else + if xlist(params.Values[0]).DuplicateMode = bldmAllow then + begin + Params.Result.SetOwnedValue(TBoldMemberFactory.CreateMemberFromBoldType(params.Values[0].BoldType)); + xlist(Params.Result.value).DuplicateMode := bldmMerge; + xlist(Params.Result.value).AddList(XList(params.Values[0])); + end + else + CopyListToResult(params); end; procedure TBOS_Append.Evaluate(const Params: TBoldOclSymbolParameters); @@ -2134,22 +2606,31 @@ procedure TBOS_SubSequence.Evaluate(const Params: TBoldOclSymbolParameters); i : Integer; Start, Stop: Integer; resList, List: TBoldList; + aResListObject, aListObject: TBoldObjectList; begin - if not assigned(xlist(Params.values[0])) then - raise EBoldOclRunTimeError.CreateFmt(boeArgrtIsNotList, [0, '->subSequence']); // do not localize - List := XList(Params.values[0]); + resList := help.CreateNewMember(Params.Result.BoldType) as TBoldList; + Params.Result.SetOwnedValue(resList); + if not assigned(List) then + exit; + Start := XInteger(Params.values[1])- 1; Stop := XInteger(Params.values[2])- 1; - resList := help.CreateNewMember(Params.Result.BoldType) as TBoldList; - if Start < 0 then Start := 0; if Stop > List.Count - 1 then Stop := List.Count - 1; - for i := Start to Stop do - resList.Add(List[i]); - Params.Result.SetOwnedValue(resList); + // Optimization for ObjectLists + // Thus, the objects no longer need to be fechted during OCL evaluation + if resList is TBoldObjectList then begin + aListObject := TBoldObjectList(List); + aResListObject := TBoldObjectList(resList); + for i := Start to Stop do + aResListObject.AddLocator(aListObject.Locators[i]); + end else begin + for i := Start to Stop do + resList.Add(List[i]); + end; end; procedure TBOS_at.Evaluate(const Params: TBoldOclSymbolParameters); @@ -2158,6 +2639,7 @@ procedure TBOS_at.Evaluate(const Params: TBoldOclSymbolParameters); P : Integer; EL: TBoldElement; begin + EL := nil; List := XList(Params.values[0]); if not assigned(list) then Params.Result.SetReferenceValue(nil) @@ -2165,12 +2647,18 @@ procedure TBOS_at.Evaluate(const Params: TBoldOclSymbolParameters); begin P := XInteger(Params.values[1]) - 1; try - EL := List[P]; + if (P >= 0) and (P < List.Count) then begin + EL := List[P]; + end; except on e:EListError do raise EBoldOclRunTimeError.CreateFmt(borteAtIndexOutOfBounds, [0, p, list.Count]); end; - EL.GetAsValue(Params.Result); + if Assigned(EL) then begin + EL.GetAsValue(Params.Result); + end else begin + Params.Result.SetOwnedValue(nil); + end; end; end; @@ -2211,19 +2699,30 @@ procedure TBOS_last.Evaluate(const Params: TBoldOclSymbolParameters); end; procedure TBOS_asString.Evaluate(const Params: TBoldOclSymbolParameters); - // First argument is the evaluated expression, the second argument is the object ; Subscriber: TBoldSubscriber begin HELP.MakeNewString(Params.Result, XString(Params.values[0])); if assigned(Params.values[0]) then Params.values[0].SubscribeToStringRepresentation(brDefault, Params.subscriber, breReEvaluate); end; -procedure TBOS_dateTimeAsFloat.Evaluate(const Params: TBoldOclSymbolParameters); - // First argument is the evaluated expression, the second argument is the object ; Subscriber: TBoldSubscriber +procedure TBOS_datePart.Evaluate(const Params: TBoldOclSymbolParameters); +var + vMoment: TBAMoment; begin - HELP.MakeNewNumeric(Params.Result, XDateTime(Params.values[0])); + vMoment := Params.values[0] as TBAMoment; + if Assigned(vMoment) and not vMoment.IsNull then + HELP.MakeNewDateTime(Params.Result, INT(XDateTime(Params.values[0]))) + else + Params.Result.SetReferenceValue(nil); end; +procedure TBOS_asDateTime.Evaluate(const Params: TBoldOclSymbolParameters); +begin + if Assigned(Params.values[0]) then + HELP.MakeNewDateTime(Params.Result, XDateTime(Params.values[0])) + else + Params.Result.SetReferenceValue(nil); +end; procedure TBOS_StringRepresentation.Evaluate(const Params: TBoldOclSymbolParameters); var @@ -2275,11 +2774,14 @@ procedure TBOS_oclType.Evaluate(const Params: TBoldOclSymbolParameters); end; procedure TBOS_OclAsType.Evaluate(const Params: TBoldOclSymbolParameters); +var + Parm1Type: TBoldElementTypeInfo; begin - if not assigned(xtype(Params.values[1])) then - raise EBoldOclRunTimeError.CreateFmt(boeArgrtIsNottype, [0, '->oclAsType']); // do not localize + Parm1Type := xtype(Params.values[1]); + if not assigned(Parm1Type) then + raise EBoldOclRunTimeError.CreateFmt(boeArgrtIsNottype, [0, '->oclAsType']); - if not assigned(Params.values[0]) or Params.values[0].BoldType.ConformsTo(XType(Params.values[1])) then + if not assigned(Params.values[0]) or Params.values[0].BoldType.ConformsTo(Parm1Type) then Params.Result.SetReferenceValue(Params.values[0]) else raise EBoldOclRunTimeError.CreateFmt(borteInvalidCast, [0, Params.values[0].BoldType.AsString, Params.values[1].AsString]); @@ -2288,7 +2790,7 @@ procedure TBOS_OclAsType.Evaluate(const Params: TBoldOclSymbolParameters); procedure TBOS_SafeCast.Evaluate(const Params: TBoldOclSymbolParameters); begin if not assigned(xtype(Params.values[1])) then - raise EBoldOclRunTimeError.CreateFmt(boeArgrtIsNottype, [0, '.safeCast']); // do not localize + raise EBoldOclRunTimeError.CreateFmt(boeArgrtIsNottype, [0, '.safeCast']); if not assigned(Params.values[0]) or Params.values[0].BoldType.ConformsTo(XType(Params.values[1])) then Params.Result.SetReferenceValue(Params.values[0]) @@ -2298,19 +2800,25 @@ procedure TBOS_SafeCast.Evaluate(const Params: TBoldOclSymbolParameters); procedure TBOS_oclIsKindOf.Evaluate(const Params: TBoldOclSymbolParameters); +var + Parm1Type: TBoldElementTypeInfo; begin - if not assigned(xtype(Params.values[1])) then - raise EBoldOclRunTimeError.CreateFmt(boeArgrtIsNottype, [0, '->oclIsKindOf']); // do not localize + Parm1Type := xtype(Params.values[1]); + if not assigned(Parm1Type) then + raise EBoldOclRunTimeError.CreateFmt(boeArgrtIsNottype, [0, '->oclIsKindOf']); - HELP.MakeNewBoolean(Params.Result, assigned(Params.values[0]) and Params.values[0].BoldType.ConformsTo(Xtype(Params.values[1]))); + HELP.MakeNewBoolean(Params.Result, assigned(Params.values[0]) and Params.values[0].BoldType.ConformsTo(Parm1Type)); end; procedure TBOS_OclIsTypeOf.Evaluate(const Params: TBoldOclSymbolParameters); +var + Parm1Type: TBoldElementTypeInfo; begin - if not assigned(xtype(Params.values[1])) then - raise EBoldOclRunTimeError.CreateFmt(boeArgrtIsNottype, [0, '->oclIsTypeOf']); // do not localize + Parm1Type := xtype(Params.values[1]); + if not assigned(Parm1Type) then + raise EBoldOclRunTimeError.CreateFmt(boeArgrtIsNottype, [0, '->oclIsTypeOf']); - HELP.MakeNewBoolean(Params.Result, assigned(Params.values[0]) and (Params.values[0].BoldType = Xtype(Params.values[1]))); + HELP.MakeNewBoolean(Params.Result, assigned(Params.values[0]) and (Params.values[0].BoldType = Parm1Type)); end; procedure TBOS_AllInstances.Evaluate(const Params: TBoldOclSymbolParameters); @@ -2328,13 +2836,13 @@ procedure TBOS_AllInstances.Evaluate(const Params: TBoldOclSymbolParameters); if assigned(Params.System) then Params.Result.SetReferenceValue(Params.System.Classes[ClassTypeInfo.TopSortedIndex]) else - raise EBoldOclRunTimeError.Create(sUnableToGetAllInstances); + raise EBoldOclRunTimeError.Create('0: Unable to get allInstances. This evaluator has no system'); end else if Params.values[0] is TBoldAttributeTypeInfo then begin AttributeTypeInfo := Params.values[0] as TBoldAttributeTypeInfo; - if AttributeTypeInfo.ConformsTo(Params.SystemTypeInfo.AttributeTypeInfoByExpressionName['ValueSet']) then // do not localize + if AttributeTypeInfo.ConformsTo(Params.SystemTypeInfo.ValueSetTypeInfo) then begin With Params.SystemTypeInfo do begin @@ -2347,8 +2855,6 @@ procedure TBOS_AllInstances.Evaluate(const Params: TBoldOclSymbolParameters); Free; end; -// StrList.Sort; - for i := 0 to StrList.Count - 1 do ValueSetlist.AddNew.StringRepresentation[brDefault] := StrList[i]; StrList.Free; @@ -2373,26 +2879,26 @@ procedure TBOS_AllLoadedObjects.Evaluate(const Params: TBoldOclSymbolParameters) ClassList := Params.System.Classes[ClassTypeInfo.TopSortedIndex]; if assigned(Params.Subscriber) then - ClassList.AddSmallSubscription(params.subscriber, [beItemAdded, beItemDeleted, beObjectFetched], breReEvaluate); + ClassList.AddSmallSubscription(params.subscriber, [beItemAdded, beItemDeleted, beObjectFetched, beObjectUnloaded], breReEvaluate); if ClassList.BoldPersistenceState <> bvpsCurrent then begin ObjectList := help.CreateNewMember(Params.Result.BoldType) as TBoldObjectList; + ObjectList.DuplicateMode := bldmAllow; Params.Result.SetOwnedValue(ObjectList); Traverser := Params.System.Locators.CreateTraverser; - while not Traverser.EndOfList do + while Traverser.MoveNext do + with Traverser.Locator do begin - if assigned(Traverser.Locator.BoldObject) and - Traverser.Locator.Boldobject.BoldType.ConformsTo(ClassTypeInfo) then - ObjectList.Add(Traverser.Locator.Boldobject); - Traverser.Next; + if assigned(BoldObject) and Boldobject.BoldType.ConformsTo(ClassTypeInfo) then + ObjectList.AddLocator(Traverser.Locator); end; Traverser.Free; end else Params.Result.SetReferenceValue(ClassList); end else - raise EBoldOclRunTimeError.Create(sUnableToGetAllLoadedObjects); + raise EBoldOclRunTimeError.Create('0: Unable to get allLoadedObjects. This evaluator has no system'); end; procedure TBOS_EmptyList.Evaluate(const Params: TBoldOclSymbolParameters); @@ -2535,72 +3041,35 @@ procedure TBOS_AllSubClasses.Evaluate(const Params: TBoldOclSymbolParameters); end; end; -var - RegExp: TRegularExpression; - SQLRegExp: TRegularExpression; - -function FixSQLRegExp(S: String): String; -var - i: integer; -begin - Result := #11; - for i := 1 to Length(S) do - case S[i] of - '%': Result := Result + #1 + #8; - '_': Result := Result + #1; - else Result := Result + S[i]; - end; - Result := Result + #6; -end; - -Procedure InitSQLRegExp; +function EscapeRegEx(const ASource: string): string; begin - if not assigned(SQLRegExp) then - begin - SQLRegExp := TRegularExpression.Create; - with SQLRegExp.MetaCharacters do - begin - AnyChar := #1; - CharSetClose := #2; - CharSetComplement := #3; - CharSetOpen := #4; - CharSetRange := #5; - EndOfLine := #6; - QuoteChar := #7; - Repeat0OrMoreTimes := #8; - Repeat1OrMoreTimes := #9; - StartOfLine := #11; - end; - end; -end; - -procedure InitRegExp; -begin - if not assigned(RegExp) then - RegExp := TRegularExpression.Create; + result := StringReplace(ASource, '[', '\[', [rfReplaceAll]); + result := StringReplace(result, '%', '', [rfReplaceAll]); end; procedure TBOS_SQLLike.Evaluate(const Params: TBoldOclSymbolParameters); +var + s: string; begin - InitSQLRegExp; - SQlRegExp.RegularExpression := FixSqlRegExp(XString(Params.values[1])); - SqlRegExp.CaseSensitive := true; - Help.MakeNewBoolean(Params.Result, SQLRegExp.SearchString(XString(Params.values[0])) <> 0); + s := XString(Params.values[1]); + s := EscapeRegEx(s); + Help.MakeNewBoolean(Params.Result, TRegEx.IsMatch(XString(Params.values[0]), s)); end; procedure TBOS_SQLLikeCaseInSensitive.Evaluate(const Params: TBoldOclSymbolParameters); +var + s: string; begin - InitSQLRegExp; - SQlRegExp.RegularExpression := FixSqlRegExp(XString(Params.values[1])); - SqlRegExp.CaseSensitive := False; - Help.MakeNewBoolean(Params.Result, SQLRegExp.SearchString(XString(Params.values[0])) <> 0); + s := XString(Params.values[1]); + s := EscapeRegEx(s); + Help.MakeNewBoolean(Params.Result, TRegEx.IsMatch(XString(Params.values[0]), s, [roIgnoreCase])); end; procedure TBOS_RegExpMatch.Evaluate(const Params: TBoldOclSymbolParameters); +var + RegExp: TRegEx; begin - InitRegExp; - RegExp.RegularExpression := XString(Params.values[1]); - Help.MakeNewBoolean(Params.Result, RegExp.SearchString(XString(Params.values[0])) <> 0); + Help.MakeNewBoolean(Params.Result, TRegEx.IsMatch(XString(Params.values[0]), XString(Params.values[1]), [])); end; procedure TBOS_InDateRange.Evaluate(const Params: TBoldOclSymbolParameters); @@ -2609,20 +3078,13 @@ procedure TBOS_InDateRange.Evaluate(const Params: TBoldOclSymbolParameters); Start, Stop, val: TDateTime; begin Moment := Params.values[0] as TBAMoment; - if moment.IsNull then + if not Assigned(Moment) or (Moment.IsNull or (Params.values[1] as TBoldAttribute).IsNull or (Params.values[2] as TBoldAttribute).IsNull) then begin help.MakeNewBoolean(params.result, false); end else begin - if Moment is TBADateTime then - val := (Moment as TBADateTime).asDateTime - else if Moment is TBADate then - val := (Moment as TBADate).asDate - else if Moment is TBATime then - val := (Moment as TBATime).asTime - else - val := 0; + Val := ExtractDateTimeFromMoment(Moment); val := trunc(val); @@ -2638,20 +3100,20 @@ procedure TBOS_InTimeRange.Evaluate(const Params: TBoldOclSymbolParameters); Start, Stop, val: TDateTime; begin Moment := Params.values[0] as TBAMoment; - if Moment is TBADateTime then - val :=(Moment as TBADateTime).asDateTime - else if Moment is TBADate then - val :=(Moment as TBADate).asDate - else if Moment is TBATime then - val :=(Moment as TBATime).asTime + if not Assigned(Moment) or (moment.IsNull or (Params.values[1] as TBoldAttribute).IsNull or (Params.values[2] as TBoldAttribute).IsNull) then + begin + help.MakeNewBoolean(params.result, false); + end else - val := 0; + begin + Val := ExtractDateTimeFromMoment(Moment); - Val := Frac(val); + Val := Frac(val); - Start := frac((Params.values[1] as TBANumeric).AsFloat); - Stop := frac((Params.values[2] as TBANumeric).AsFloat); - Help.MakeNewBoolean(Params.Result, (val >= start) and (val <= stop)); + Start := frac((Params.values[1] as TBANumeric).AsFloat); + Stop := frac((Params.values[2] as TBANumeric).AsFloat); + Help.MakeNewBoolean(Params.Result, (CompareTime(val,Start)>=0) and (CompareTime(val,stop)<=0)); + end; end; procedure TBOS_Constraints.Evaluate(const Params: TBoldOclSymbolParameters); @@ -2661,7 +3123,7 @@ procedure TBOS_Constraints.Evaluate(const Params: TBoldOclSymbolParameters); procedure AddConstraint(IncomingConstraint: TBoldConstraintRTInfo; element: TBoldElement); begin with ResList.AddNew as TBAConstraint do - Initialize(IncomingConstraint, element); + InitializeConstraint(IncomingConstraint, element); end; var @@ -2730,10 +3192,10 @@ procedure TBOS_AllInstancesAtTime.Evaluate(const Params: TBoldOclSymbolParameter if assigned(Params.System) then Params.Result.SetReferenceValue(Params.System.Classes[ClassTypeInfo.TopSortedIndex].atTime(NewTime)) else - raise EBoldOclRunTimeError.Create(sUnableToGetAllInstances); + raise EBoldOclRunTimeError.Create('0: Unable to get allInstances. This evaluator has no system'); end else - raise EBoldOclRunTimeError.Create(sAllInstancesAtTimeOnlyAllowedOnClasses); + raise EBoldOclRunTimeError.Create('0: AllInstancesAtTime only allowed on classes'); end; procedure TBOS_Existing.Evaluate(const Params: TBoldOclSymbolParameters); @@ -2746,12 +3208,52 @@ procedure TBOS_FilterOnType.Evaluate(const Params: TBoldOclSymbolParameters); IncomingList: TBoldList; i: integer; OutList: TBoldList; + aIncommingListObject, + aOutListObject: TBoldObjectList; + aClasses: TBoldClassTypeInfoList; + iTopSortedIndex: Integer; + Locator: TBoldObjectLocator; + FilterType: TBoldElementTypeInfo; begin IncomingList := XList(Params.values[0]); OutList := TBoldMemberFactory.CreateMemberFromBoldType(params.Result.BoldType) as TBoldList; - for i := 0 to IncomingList.Count - 1 do - if IncomingList[i].BoldType.ConformsTo(Params.values[1] as TBoldElementTypeInfo) then - OutList.Add(IncomingList[i]); + FilterType := Params.values[1] as TBoldElementTypeInfo; + if Assigned(IncomingList) then + begin + // Optimization for ObjectLists + if OutList is TBoldObjectList then begin + aIncommingListObject := TBoldObjectList(IncomingList); + aOutListObject := TBoldObjectList(OutList); + aClasses := Help.SystemTypeInfo.TopSortedClasses; + iTopSortedIndex := -1; + aIncommingListObject.EnsureObjects; + for i := 0 to aIncommingListObject.Count - 1 do begin + Locator := aIncommingListObject.Locators[i]; + if Locator.BoldObjectID.TopSortedIndexExact then + begin + if (iTopSortedIndex = Locator.BoldObjectID.TopSortedIndex) or (Locator.BoldClassTypeInfo.ConformsTo(FilterType)) then + begin + aOutListObject.AddLocator(Locator); + iTopSortedIndex := Locator.BoldObjectID.TopSortedIndex; // this is to skip ConformsTo with objects of repeated type + end; + end + else + if Locator.EnsuredBoldObject.BoldType.ConformsTo(FilterType) then + aOutListObject.AddLocator(Locator); + end; + end else begin + //Prefetch + if Assigned(IncomingList) then begin + IncomingList.EnsureRange(0, IncomingList.Count - 1); + for i := 0 to IncomingList.Count - 1 do begin + if IncomingList[i].BoldType.ConformsTo(FilterType) then + begin + OutList.Add(IncomingList[i]); + end; + end; + end; + end; + end; params.result.SetOwnedValue(OutList); end; @@ -2770,29 +3272,492 @@ procedure TBOS_TimeToTimeStamp.Evaluate(const Params: TBoldOclSymbolParameters); help.MakeNewInteger(Params.Result, Params.System.TimestampForTime[(Params.values[0] as TBAdateTime).AsDateTime]); end; +procedure TBOS_indexOf.Evaluate(const Params: TBoldOclSymbolParameters); +var + Index: Integer; + List: TBoldList; + aObj: TBoldObject; + i: Integer; +begin + Index := -1; + List := XList(Params.values[0]); + if List is TBoldObjectList then begin + // Optimization for ObjectLists: check for locator. + // No need to ensure objects for equality check + aObj := nil; + if Params.values[1] is TBoldObject then begin + aObj := TBoldObject(Params.values[1]); + end else if Params.values[1] is TBoldObjectReference then begin + aObj := TBoldObjectReference(Params.values[1]).BoldObject; + end; + if Assigned(aObj) then begin + Index := TBoldObjectList(List).IndexOfLocator(aObj.BoldObjectLocator); + end; + end else if Assigned(List) then begin + List.EnsureRange(0, List.Count - 1); + for i := 0 to List.Count - 1 do begin + if List[i].IsEqual(Params.values[1]) then begin + Index := i; + Break; + end; + end; + end; + HELP.MakeNewInteger(Params.Result, Index); +end; + +procedure TBOS_reverseCollection.Evaluate(const Params: TBoldOclSymbolParameters); +var + List, resList: TBoldLIst; + i: Integer; +begin + List := XList(Params.values[0]); + resList := help.CreateNewMember(Params.Result.BoldType) as TBoldList; + resList.Capacity := List.Count; + if List is TBoldObjectList then begin + // Optimization for ObjectLists: check for locator. + // No need to ensure objects for equality check + for i := List.Count - 1 downto 0 do begin + TBoldObjectList(resList).AddLocator(TBoldObjectList(List).Locators[i]); + end; + end else if Assigned(List) then begin + for i := List.Count - 1 downto 0 do begin + resList.Add(List[i]); + end; + end; + + Params.Result.SetOwnedValue(resList); +end; + procedure InitializeSymbolTable(SymTab: TBoldSymbolDictionary); var i: integer; begin + SymTab.Capacity := SymTab.Count + OCLOperations.Count; for i := 0 to OCLOperations.Count - 1 do SymTab.Add(TBoldOclSymbolClass(OCLOperations[i]).Create(SymTab.Help)); end; +{ TBOS_CommaText } + +procedure TBOS_asCommaText.Init; +begin + InternalInit('asCommaText', [HELP.{String}ListType], tbodNo, HELP.StringType, True, 193); +end; + +procedure TBOS_asCommaText.Evaluate(const Params: TBoldOclSymbolParameters); +var + List : TBoldList; + sl: TStringList; + i: Integer; +begin + sl := TStringList.Create; + try + List := XList(Params.values[0]); + for i := 0 to List.Count - 1 do + sl.Add(XString(List[i])); + HELP.MakeNewString(Params.Result, sl.CommaText); + finally + FreeAndNil(sl); + end; +end; + +procedure TBOS_separate.Init; +begin + InternalInit('separate', [HELP.StringListType, HELP.StringType], tbodNo, HELP.StringType, True, 194); +end; + +procedure TBOS_separate.Evaluate(const Params: TBoldOclSymbolParameters); +var + List : TBoldList; + ResultString: string; + Separator: string; + i: Integer; +begin + ResultString := ''; + List := XList(Params.values[0]); + Separator := XString(Params.values[1]); + for i := 0 to List.Count - 1 do + begin + if i > 0 then + ResultString := ResultString + Separator; + ResultString := ResultString + XString(List[i]); + end; + HELP.MakeNewString(Params.Result, ResultString); +end; + +{ TBOS_CommaSeparatedStringToCollection } + +procedure TBOS_CommaSeparatedStringToCollection.Evaluate( + const Params: TBoldOclSymbolParameters); +var + lStringList: TStringList; + lBoldMember: TBoldMember; + lBoldMemberList: TBoldMemberList; + lIndexStringList: integer; + lElementTypeInfo : TBoldElementTypeInfo; +begin + lStringList := TStringList.Create; + try + lStringList.CommaText := (Params.Values[0].AsString); + lBoldMemberList := Help.CreateNewMember(GetListTypeInfo) as TBoldMemberList; + lElementTypeInfo := GetListTypeInfo.ListElementTypeInfo; + for lIndexStringList := 0 to lStringList.Count - 1 do + begin + lBoldMember := Help.CreateNewMember(lElementTypeInfo) as TBoldMember; + lBoldMember.AsString := lStringList[lIndexStringList]; + lBoldMemberList.Add(lBoldMember); + lBoldMember.free; + end; + Params.Result.SetOwnedValue(lBoldMemberList); + finally + lStringList.free; + end; +end; + +{ TBOS_CommaSeparatedStringToStringCollection } + +procedure TBOS_CommaSeparatedStringToStringCollection.Init; +begin + InternalInit('toStringCollection', [Help.StringType], tbodNo, GetListTypeInfo, True, 0); +end; + +function TBOS_CommaSeparatedStringToStringCollection.GetListTypeInfo: TBoldListTypeInfo; +begin + result := Help.StringListType; +end; + +{ TBOS_CommaSeparatedStringToIntegerCollection } + +procedure TBOS_CommaSeparatedStringToIntegerCollection.Init; +begin + InternalInit('toIntegerCollection', [Help.StringType], tbodNo, GetListTypeInfo, True, 0); +end; + + +function TBOS_CommaSeparatedStringToIntegerCollection.GetListTypeInfo: TBoldListTypeInfo; +begin + result := Help.IntegerListType; +end; + +{ TBOS_intAsFloat } + +procedure TBOS_AsFloat.Evaluate(const Params: TBoldOclSymbolParameters); +begin + HELP.MakeNewNumeric(Params.Result, XNumeric(Params.values[0])); +end; + +procedure TBOS_AsFloat.Init; +begin + InternalInit('asFloat', [HELP.NumericType], tbodNo, HELP.RealType, True, 163); +end; + +{ TBOS_FloatAsDateTime } + +procedure TBOS_FloatAsDateTime.Evaluate(const Params: TBoldOclSymbolParameters); +begin + HELP.MakeNewDateTime(Params.Result, XNumeric(Params.Values[0])); +end; + +procedure TBOS_FloatAsDateTime.Init; +begin + InternalInit('floatAsDateTime', [HELP.NumericType], tbodNo, HELP.DateTimeType, True, 163); +end; + +{ TBOS_NullValue } + +procedure TBOS_NullValue.Evaluate(const Params: TBoldOclSymbolParameters); +begin + HELP.MakeNewNull(Params.Result, XType(Params.values[0])); +end; + +procedure TBOS_NullValue.Init; +begin + InternalInit('nullValue', [HELP.TypeType], tbodArg1Type, nil, True, 170); +end; + +{ TBOS_DayOfDate } + +procedure TBOS_DayOfDate.Evaluate(const Params: TBoldOclSymbolParameters); +var + Moment: TBAMoment; + LYear, LMonth, LDay: Word; +begin + Moment := Params.values[0] as TBAMoment; + if not Assigned(Moment) then + Params.Result.SetReferenceValue(nil) + else + begin + if Moment.IsNull then + LYear := 0 + else + DecodeDate(ExtractDateTimeFromMoment(Moment), LYear, LMonth, LDay); + HELP.MakeNewInteger(Params.Result, LDay); + end; +end; + +procedure TBOS_DayOfDate.Init; +begin + InternalInit('day', [HELP.MomentType], tbodNo, HELP.IntegerType, True, 124); + +end; + +procedure TBOS_MonthOfDate.Evaluate(const Params: TBoldOclSymbolParameters); +var + Moment: TBAMoment; + LYear, LMonth, LDay: Word; +begin + Moment := Params.values[0] as TBAMoment; + if not Assigned(Moment) then + Params.Result.SetReferenceValue(nil) + else + begin + if Moment.IsNull then + LMonth := 0 + else + DecodeDate(ExtractDateTimeFromMoment(Moment), LYear, LMonth, LDay); + HELP.MakeNewInteger(Params.Result, LMonth); + end; +end; + +procedure TBOS_MonthOfDate.Init; +begin + InternalInit('month', [HELP.MomentType], tbodNo, HELP.IntegerType, True, 124); +end; + +procedure TBOS_YearOfDate.Evaluate(const Params: TBoldOclSymbolParameters); +var + Moment: TBAMoment; + LYear, LMonth, LDay: Word; +begin + Moment := Params.values[0] as TBAMoment; + if not Assigned(Moment) then + Params.Result.SetReferenceValue(nil) + else + begin + if Moment.IsNull then + LYear := 0 + else + DecodeDate(ExtractDateTimeFromMoment(Moment), LYear, LMonth, LDay); + HELP.MakeNewInteger(Params.Result, LYear); + end; +end; + +procedure TBOS_YearOfDate.Init; +begin + InternalInit('year', [HELP.MomentType], tbodNo, HELP.IntegerType, True, 124); +end; + +procedure TBOS_WeekOfDate.Evaluate(const Params: TBoldOclSymbolParameters); +var + Moment: TBAMoment; + LYear, LWeek, LDOW: Word; +begin + Moment := Params.values[0] as TBAMoment; + if not Assigned(Moment) then + Params.Result.SetReferenceValue(nil) + else + begin + if Moment.IsNull then + LWeek := 0 + else + DecodeDateWeek(ExtractDateTimeFromMoment(Moment), LYear, LWeek, LDOW); + HELP.MakeNewInteger(Params.Result, LWeek); + end; +end; + +procedure TBOS_WeekOfDate.Init; +begin + InternalInit('week', [HELP.MomentType], tbodNo, HELP.IntegerType, True, 124); +end; + +procedure TBOS_DayOfWeekOfDate.Evaluate(const Params: TBoldOclSymbolParameters); +var + Moment: TBAMoment; + LYear, LWeek, LDOW: Word; +begin + Moment := Params.values[0] as TBAMoment; + if not Assigned(Moment) then + Params.Result.SetReferenceValue(nil) + else + begin + if Moment.IsNull then + LDOW := 0 + else + DecodeDateWeek(ExtractDateTimeFromMoment(Moment), LYear, LWeek, LDOW); + HELP.MakeNewInteger(Params.Result, LDOW); + end; +end; + +procedure TBOS_DayOfWeekOfDate.Init; +begin + InternalInit('dayOfWeek', [HELP.MomentType], tbodNo, HELP.IntegerType, True, 124); +end; + +{ TBOS_Trim } + +procedure TBOS_Trim.Evaluate(const Params: TBoldOclSymbolParameters); +begin + Help.MakeNewString(Params.Result, StringReplace(Trim(XString(Params.Values[0])), BOLDCRLF, ' ', [rfReplaceAll])); +end; + +procedure TBOS_Trim.Init; +begin + InternalInit('trim', [Help.StringType], tbodNo, Help.StringType, True, 124); +end; + +{ TBOS_HasDuplicates } + +procedure TBOS_HasDuplicates.Evaluate(const Params: TBoldOclSymbolParameters); +var + list: TBoldLIst; +begin + List := XList(Params.values[0]); + if not assigned(list) then + Help.MakeNewBoolean(Params.Result, false) + else + HELP.MakeNewBoolean(Params.Result, List.HasDuplicates); +end; + +{ TBOS_BoldId } + +procedure TBOS_BoldId.Evaluate(const Params: TBoldOclSymbolParameters); +var + S: String; + Locator: TBoldObjectLocator; +begin + if assigned(Params.Values[0]) then + begin + Locator := (Params.Values[0] as TBoldObject).BoldObjectLocator; + s := Locator.BoldObjectID.AsString; + if not Locator.BoldObjectID.IsStorable then + Locator.BoldObject.AddSmallSubscription(Params.subscriber, [bePostUpdateID ], breResubscribe); + Help.MakeNewInteger(Params.Result,StrToInt(s)); + end + else + HELP.MakeNewNull(Params.Result, Params.Result.BoldType) +end; + +{ TBOS_SecondsBetween } + +procedure TBOS_SecondsBetween.Evaluate( + const Params: TBoldOclSymbolParameters); +var + i:integer; +begin + if (Params.values[0] = nil) or (Params.values[0] as TBoldAttribute).IsNull + or (Params.values[1] = nil) or (Params.values[1] as TBoldAttribute).IsNull then + Params.Result.SetReferenceValue(nil) + else + begin + i := SecondsBetween(XDateTime(Params.Values[0]),XDateTime(Params.Values[1])); + Help.MakeNewInteger(Params.Result,i); + end; +end; + +procedure TBOS_SecondsBetween.Init; +begin + InternalInit('secondsBetween',[Help.MomentType,Help.MomentType],tbodNo,Help.IntegerType,True,0); +end; + +function HoursBetween(const ANow, AThen: TDateTime): Int64; +begin + Result := Round(HourSpan(ANow, AThen)); + if ANow < AThen then + Result := -Result; +end; + +function MinutesBetween(const ANow, AThen: TDateTime): Int64; +begin + Result := Round(MinuteSpan(ANow, AThen)); + if ANow < AThen then + Result := -Result; +end; + +function SecondsBetween(const ANow, AThen: TDateTime): Int64; +begin + Result := Round(SecondSpan(ANow, AThen)); + if ANow < AThen then + Result := -Result; +end; + +{ TBOS_MinutesBetween } + +procedure TBOS_MinutesBetween.Evaluate( + const Params: TBoldOclSymbolParameters); +var + i:integer; +begin + if (Params.values[0] = nil) or (Params.values[0] as TBoldAttribute).IsNull + or (Params.values[1] = nil) or (Params.values[1] as TBoldAttribute).IsNull then + Params.Result.SetReferenceValue(nil) + else + begin + i := MinutesBetween(XDateTime(Params.Values[0]),XDateTime(Params.Values[1])); + Help.MakeNewInteger(Params.Result,i); + end; +end; + +procedure TBOS_MinutesBetween.Init; +begin + InternalInit('minutesBetween',[Help.MomentType,Help.MomentType],tbodNo,Help.IntegerType,True,0); +end; + +{ TBOS_HoursBetween } + +procedure TBOS_HoursBetween.Evaluate( + const Params: TBoldOclSymbolParameters); +var + i:integer; +begin + if (Params.values[0] = nil) or (Params.values[0] as TBoldAttribute).IsNull + or (Params.values[1] = nil) or (Params.values[1] as TBoldAttribute).IsNull then + Params.Result.SetReferenceValue(nil) + else + begin + i := HoursBetween(XDateTime(Params.Values[0]),XDateTime(Params.Values[1])); + Help.MakeNewInteger(Params.Result,i); + end; +end; + +procedure TBOS_HoursBetween.Init; +begin + InternalInit('hoursBetween',[Help.MomentType, Help.MomentType],tbodNo,Help.IntegerType,True,0); +end; + +{ TBOS_Power } + +procedure TBOS_Power.Evaluate(const Params: TBoldOclSymbolParameters); +begin + if (Params.values[0] = nil) or (Params.values[1] = nil) then + Params.Result.SetReferenceValue(nil) + else + Help.MakeNewNumeric(Params.Result, Power(XNumeric(Params.values[0]), XNumeric(Params.values[1]))); +end; + +{ TBOS_Sqrt } + +procedure TBOS_Sqrt.Evaluate(const Params: TBoldOclSymbolParameters); +begin + if (Params.values[0] = nil) then + Params.Result.SetReferenceValue(nil) + else + Help.MakeNewNumeric(Params.Result, Sqrt(XNumeric(Params.values[0]))); +end; + initialization - SQLRegExp := nil; - RegExp := nil; RegisterOclOperation(TBOS_Equal); RegisterOclOperation(TBOS_NotEqual); - RegisterOclOperation(TBOS_Except); RegisterOclOperation(TBOS_Add); RegisterOclOperation(TBOS_Subtract); RegisterOclOperation(TBOS_UnaryMinus); RegisterOclOperation(TBOS_Multiply); RegisterOclOperation(TBOS_Divide); + RegisterOclOperation(TBOS_SafeDivZero); RegisterOclOperation(TBOS_Abs); RegisterOclOperation(TBOS_Floor); RegisterOclOperation(TBOS_Round); RegisterOclOperation(TBOS_strToInt); + RegisterOclOperation(TBOS_strToFloat); RegisterOclOperation(TBOS_Min); RegisterOclOperation(TBOS_Max); RegisterOclOperation(TBOS_Less); @@ -2806,6 +3771,7 @@ initialization RegisterOclOperation(TBOS_ToUpper); RegisterOclOperation(TBOS_toLower); RegisterOclOperation(TBOS_SubString); + RegisterOclOperation(TBOS_Contains); RegisterOclOperation(TBOS_Pad); RegisterOclOperation(TBOS_PostPad); RegisterOclOperation(TBOS_or); @@ -2822,7 +3788,6 @@ initialization RegisterOclOperation(TBOS_isNull); RegisterOclOperation(TBOS_NotEmpty); RegisterOclOperation(TBOS_Sum); - RegisterOclOperation(TBOS_SumTime); RegisterOclOperation(TBOS_Maxvalue); RegisterOclOperation(TBOS_MinValue); RegisterOclOperation(TBOS_Average); @@ -2849,12 +3814,16 @@ initialization RegisterOclOperation(TBOS_orderby); RegisterOclOperation(TBOS_orderDescending); RegisterOclOperation(TBOS_asString); - RegisterOclOperation(TBOS_dateTimeAsFloat); + RegisterOclOperation(TBOS_AsFloat); + RegisterOclOperation(TBOS_FloatAsDateTime); + RegisterOclOperation(TBOS_datePart); + RegisterOclOperation(TBOS_asDateTime); RegisterOclOperation(TBOS_stringRepresentation); RegisterOclOperation(TBOS_TaggedValue); RegisterOclOperation(TBOS_TypeName); RegisterOclOperation(TBOS_Attributes); RegisterOclOperation(TBOS_AssociationEnds); + RegisterOclOperation(TBOS_NullValue); { RegisterOclOperation(TBOS_Operations); } @@ -2876,8 +3845,12 @@ initialization RegisterOclOperation(TBOS_InDateRange); RegisterOclOperation(TBOS_InTimeRange); RegisterOclOperation(TBOS_Constraints); + RegisterOclOperation(TBOS_Format); RegisterOclOperation(TBOS_FormatNumeric); + RegisterOclOperation(TBOS_FormatFloat); RegisterOclOperation(TBOS_FormatDateTime); + RegisterOclOperation(TBOS_AsISODate); + RegisterOclOperation(TBOS_AsISODateTime); RegisterOclOperation(TBOS_StrToDateTime); RegisterOclOperation(TBOS_StrToDate); RegisterOclOperation(TBOS_StrToTime); @@ -2889,10 +3862,27 @@ initialization RegisterOclOperation(TBOS_BoldTime); RegisterOclOperation(TBOS_TimeStampToTime); RegisterOclOperation(TBOS_TimeToTimeStamp); + RegisterOclOperation(TBOS_IndexOf); + RegisterOclOperation(TBOS_ReverseCollection); + RegisterOclOperation(TBOS_asCommaText); + RegisterOclOperation(TBOS_separate); + RegisterOclOperation(TBOS_DayOfDate); + RegisterOclOperation(TBOS_MonthOfDate); + RegisterOclOperation(TBOS_YearOfDate); + RegisterOclOperation(TBOS_DayOfWeekOfDate); + RegisterOclOperation(TBOS_WeekOfDate); + RegisterOCLOperation(TBOS_HoursBetween); + RegisterOCLOperation(TBOS_MinutesBetween); + RegisterOCLOperation(TBOS_SecondsBetween); + RegisterOclOperation(TBOS_Trim); + RegisterOclOperation(TBOS_HasDuplicates); + RegisterOclOperation(TBOS_CommaSeparatedStringToStringCollection); + RegisterOclOperation(TBOS_CommaSeparatedStringToIntegerCollection); + RegisterOclOperation(TBOS_BoldId); + RegisterOclOperation(TBOS_Power); + RegisterOclOperation(TBOS_Sqrt); finalization - SqlRegExp.Free; - RegExp.Free; FreeAndNil(G_OCLOperations); end. diff --git a/Source/ObjectSpace/Ocl/BoldSSExcept.pas b/Source/ObjectSpace/Ocl/BoldSSExcept.pas index da8c5db..62e0b3b 100644 --- a/Source/ObjectSpace/Ocl/BoldSSExcept.pas +++ b/Source/ObjectSpace/Ocl/BoldSSExcept.pas @@ -1,5 +1,6 @@ -{$DEFINE SANDSTONEREDISTRIBUTABLE} +{ Global compiler directives } +{$include bold.inc} unit BoldSSExcept; interface @@ -35,17 +36,11 @@ interface SSExceptionYaccBadResource ); - type - { forward declarations } - SSException = class; - - { SSException } SSException = class(EAbort) public Position: integer; Id: SSExceptionError; - constructor Create(TheId: SSExceptionError; FmtStr: string); constructor CreateName(TheId: SSExceptionError; FmtStr: string; Name: PChar); constructor CreateLong(TheId: SSExceptionError; TheFmtStr: string; TheLong: Longint); @@ -63,26 +58,26 @@ constructor SSException.Create(TheId: SSExceptionError; FmtStr: string); constructor SSException.CreateName(TheId: SSExceptionError; FmtStr: string; Name: PChar); begin - inherited Create(Format(FmtStr, [String(Name)])); + inherited Create(Format(FmtStr, [string(Name)])); Id := TheId; Position := 0; end; -constructor SSException.CreateLong(TheId: SSExceptionError; TheFmtStr: string; TheLong: Longint); +constructor SSException.CreateLong(TheId: SSExceptionError; TheFmtStr: string; TheLong: Integer); begin - inherited Create(Format(StringReplace(TheFmtStr, '%ld', '%d', []), [TheLong])); // do not localize + inherited Create(Format(StringReplace(TheFmtStr, '%ld', '%d', [rfReplaceAll]), [TheLong])); Id := TheId; Position := 0; end; -constructor SSException.CreateLongLongNameLen(TheId: SSExceptionError; FmtStr: string; - Long0, Long1: Longint; TheName: PChar; TheLen: Word); +constructor SSException.CreateLongLongNameLen(TheId: SSExceptionError; + FmtStr: string; Long0, Long1: Integer; TheName: PChar; TheLen: Word); var Name: PChar; begin GetMem(Name, TheLen + 1); StrMove(Name, TheName, TheLen); - inherited Create(Format(StringReplace(FmtStr, '%ld', '%d', [rfReplaceAll]), [Long0, Long1, string(Name)])); // do not localize + inherited Create(Format(StringReplace(FmtStr, '%ld', '%d', [rfReplaceAll]), [Long0, Long1, string(Name)])); FreeMem(Name, TheLen + 1); Id := TheId; Position := Long1; diff --git a/Source/ObjectSpace/Ocl/BoldSSLexU.pas b/Source/ObjectSpace/Ocl/BoldSSLexU.pas index 1bc8f6e..921e14a 100644 --- a/Source/ObjectSpace/Ocl/BoldSSLexU.pas +++ b/Source/ObjectSpace/Ocl/BoldSSLexU.pas @@ -1,294 +1,233 @@ + +{ Global compiler directives } +{$include bold.inc} + unit BoldSSLexU; interface uses Classes, - WinTypes, - WinProcs, BoldBase; -procedure SSAux; - -function SSHugeInc(ThePointer: Pointer; TheInc: Longint): Pointer; -procedure SSHugeCopy(TheCopyTo: Pointer; TheCopyFrom: Pointer; TheLength: Longint); - -{$IFDEF SSAUX} -{$I SSAUXDEF.PAS} -{$ENDIF} - const - SSHugeIncVal = 8; - SSLexMaxRead = $7fffffff; {32767} - SSLexMaxCopy = $7fffffff; {32767} SSLexConsumerBof = -1; - SSLexMaxBlock = $7fffffff-1; {32528} SSLexStateInvalid = -1; - SSLexBufferMax = $7fffffff; {32767} - SSLexThreshold = 65536; SSLexStructMax = 65520; - SSLexPairTable = $53534C58; SSLexFinalStateFlagsContextStart = $01; - SSLexFinalStateFlagsStartOfLine = $02; - SSLexFinalStateFlagsPop = $08; - SSLexFinalStateFlagsFinal = $10; - SSLexFinalStateFlagsPush = $20; - SSLexFinalStateFlagsIgnore = $40; - SSLexFinalStateFlagsContextEnd = $80; - SSLexFinalStateFlagsReduce = $100; - - SSLexMsgFileOpen = 'SSLex0101e: Error opening file, %s'; - SSLexMsgFileRead = 'SSLex0102e: Invalid file length or read error, %s'; - SSLexMsgLexemeLength = 'SSLex0103e: Lexeme too long, %ld'; - SSLexMsgBadTable = 'SSLex0104e: Invalid table, %s'; + SSLexFinalStateFlagsStartOfLine = $02; + SSLexFinalStateFlagsPop = $08; + SSLexFinalStateFlagsFinal = $10; + SSLexFinalStateFlagsPush = $20; + SSLexFinalStateFlagsIgnore = $40; + SSLexFinalStateFlagsContextEnd = $80; + SSLexFinalStateFlagsReduce = $100; + SSLexMsgError = 'SSLex0105e: Invalid token, Line %ld, Offset %ld, %s'; SSLexMsgBadList = 'SSLex0106e: Invalid expression list index, %ld'; SSLexMsgMissingPart = 'SSLex0107e: Table or consumer missing, required'; - SSLexMsgFindResource = 'SSLex0108e: Unable to locate resource, %s'; - SSLexMsgBadResource = 'SSLex0109e: Bad resource format, %s'; - SSLifoMsgStackTop = 'SSLifo0002e: No top, stack empty'; SSLifoMsgStackPop = 'SSLifo0004e: Cannot pop empty stack'; - SSLexMsgOutOfMemory = 'SSLex1000e: Out of memory'; - -type - SSArrayOfPointer = array[ 0..(SSLexStructMax div sizeof(Pointer))] of Pointer; - PSSArrayOfPointer = ^SSArrayOfPointer; - - type - SSStack = class(TBoldMemoryManagedObject) - public - Incr : Integer; - Size : Integer; - TopOfStack : Integer; - PArray : PSSArrayOfPointer; - - constructor Create; - procedure Pop; -{ procedure PopAll;} - function Top: Pointer; - procedure Push(ThePointer: Pointer); - destructor Destroy; override; -end; - + SSLexLexeme = class; + SSYaccStackElement = class; + SSLexRoot = class; + SSArrayOfSSYaccStackElement = array[0..(SSLexStructMax div SizeOf(Pointer))] of SSYaccStackElement; + PSSArrayOfSSYaccStackElement = ^SSArrayOfSSYaccStackElement; -type - SSLexTableBase = record - Size : Longint; - TableType : Longint; - Reserved : array[ 0..6] of Longint; -end; - -type - SSLexTableHeader = record - TableType : Longint; - Size : Longint; - Reserved0 : array[ 0..7] of Longint; - Rows : Longint; - Push : Longint; - Index : Longint; - Final : Longint; - Reserved1 : array[ 0..7] of Longint; -end; + SSLexRoot = class(TBoldMemoryManagedObject) + end; -type - SSLexTableRow = record - Size : Longint; -end; + SSYaccStackElement = class(SSLexRoot) + public + Lexeme: SSLexLexeme; + State: Longint; + Use: Longint; + constructor Create; + procedure RefInc; + function RefDec: Boolean; + procedure SetLexeme(TheLexeme: SSLexLexeme); + destructor Destroy; override; + end; -type - SSLexTableRowEntry = record - StartPoint: Longint; - EndPoint : Longint; - State : Longint; -end; + SSStack = class(SSLexRoot) + public + Incr: Integer; + Size: Integer; + TopOfStack: Integer; + PArray: PSSArrayOfSSYaccStackElement; + constructor Create; + procedure Pop; + function Top: SSLexRoot; + procedure Push(TheSSYaccStackElement: SSLexRoot); + destructor Destroy; override; + end; -type - SSLexTableIndex = record - Row : Longint; -end; + TEntry = record + StartPoint: Longint; + EndPoint: Longint; + State: Longint; + end; -type - SSLexFinalState = record - Token : Longint; - Push : Longint; - Flags : Longint; - Reserved: array[ 0..3] of Longint; -end; + TRow = record + Token: ShortInt; + Push: ShortInt; + Flags: ShortInt; + Entries: array of TEntry; + end; -type - PSSLexTableBase = ^SSLexTableBase; - PSSLexTableHeader = ^SSLexTableHeader; - PSSLexTableRow = ^SSLexTableRow; - PSSLexTableRowEntry = ^SSLexTableRowEntry; - PSSLexTableIndex = ^SSLexTableIndex; - PSSLexFinalState = ^SSLexFinalState; - SSLexRowArray = array[ 0..(SSLexStructMax div sizeof(PSSLexTableRow))] of PSSLexTableRow; - SSLexFinalArray = array[ 0..((SSLexStructMax div sizeof(SSLexFinalState))-1)] of SSLexFinalState; - SSLexRowOffsetArray = array[ 0..(SSLexStructMax div sizeof(Longint))] of Longint; - SSLexRowEntryArray = array[ 0..((SSLexStructMax div sizeof(SSLexTableRowEntry))-1)] of SSLexTableRowEntry; - PSSLexRowArray = ^SSLexRowArray; - PSSLexFinalArray = ^SSLexFinalArray; - PSSLexRowOffsetArray = ^SSLexRowOffsetArray; - PSSLexRowEntryArray = ^SSLexRowEntryArray; + TRows = array of TRow; -type - SSLexExpressionList = class(TBoldMemoryManagedObject) + SSLexExpressionList = class(SSYaccStackElement) public - Buffer : Pointer; - Size : Longint; - Index : Longint; - Final : Longint; - Rows : Longint; - PPRows : PSSLexRowArray; - PFinalStates: PSSLexFinalArray; - - constructor Create; - constructor CreateBuffer(TheHeader: PSSLexTableHeader; TheFile: PChar); - procedure Open; - destructor Destroy; override; - + ARows: TRows; function LookupState(TheToken, TheState: Longint): Longint; - function LookupFinal(TheState: Longint): PSSLexFinalState; -end; + end; -type SSLexExpressionListStack = class(SSStack) - public - function Top: SSLexExpressionList; - procedure Push(TheList: SSLexExpressionList); -end; + function Top: SSLexExpressionList; + procedure Push(TheList: SSLexExpressionList); + end; -type - SSLexTable = class(TBoldMemoryManagedObject) + SSLexTable = class(SSLexRoot) public ExpressionLists: TList; - NumLists : Integer; - - constructor Create(FileName: String); - constructor CreateResource(TheInstance: THandle; TheName, TheType: PChar); - function GetExpressionList(TheList: Longint): SSLexExpressionList; - destructor Destroy; override; -end; + LexTab: array[0..1] of TRows; + constructor Create; + destructor Destroy; override; + function GetExpressionList(TheList: Longint): SSLexExpressionList; + procedure FullTab; + end; -type - SSLexLexeme = class(TBoldMemoryManagedObject) + SSLexLexeme = class(SSLexRoot) public - Buffer: PChar; - Use : Integer; - Line : Longint; + Buffer: PAnsiChar; + Use: Integer; + Line: Longint; Offset: Longint; Length: Longint; - Token : Cardinal; // was LongInt, changed to foor Delphi-hints - - constructor Create(TheData: PChar; TheLength, TheLine, TheOffset: Longint); - procedure RefInc; - function RefDec: Boolean; - destructor Destroy; override; -end; + Token: Cardinal; + constructor Create(TheData: PAnsiChar; TheLength, TheLine, TheOffset: Longint); + procedure RefInc; + function RefDec: Boolean; + destructor Destroy; override; + end; -type SSLexConsumerMode = (SSLexBinaryMode, SSLexTextMode); - SSLexConsumer = class(TBoldMemoryManagedObject) + + SSLexConsumer = class(SSLexRoot) public - Buffer : PChar; - Bof : Longint; - Line : Longint; - Offset : Longint; - BuffLen : Longint; - BuffInc : Longint; - Current : Longint; - MarkLine : Longint; - MarkOffset : Longint; - ScanLine : Longint; - ScanOffset : Longint; - EndOfData : Boolean; - Start : Longint; - Index : Integer; - DataLen : Longint; - Mark : Longint; - MarkContext : Longint; - MarkContextLine : Longint; + Buffer: PAnsiChar; + Bof: Longint; + Line: Longint; + Offset: Longint; + BuffLen: Longint; + BuffInc: Longint; + Current: Longint; + MarkLine: Longint; + MarkOffset: Longint; + ScanLine: Longint; + ScanOffset: Longint; + EndOfData: Boolean; + Start: Longint; + Index: Integer; + DataLen: Longint; + Mark: Longint; + MarkContext: Longint; + MarkContextLine: Longint; MarkContextOffset: Longint; - Mode : SSLexConsumerMode; - - constructor Create(TheIncrement: Longint; - TheMode: SSLexConsumerMode); - destructor Destroy; override; - - function Next: Boolean; virtual; - function NextBuffer: Longint; virtual; - - procedure MarkFinal; - procedure FlushLexeme; - procedure FlushLexemeAll; - procedure SetContextFinal; - procedure MarkContextFinal; - procedure FlushStartOfLine; - function Lexeme: SSLexLexeme; - function LexemeAll: SSLexLexeme; -{ function ShiftBuffer(var TheOffset, TheFill: Longint): Boolean; - function ExpandBuffer(var TheOffset, TheFill: Longint): Boolean; - } -end; + Mode: SSLexConsumerMode; + + constructor Create(TheIncrement: Longint; TheMode: SSLexConsumerMode); + destructor Destroy; override; + function Next: Boolean; virtual; + function NextBuffer: Longint; virtual; + procedure MarkFinal; + procedure FlushLexeme; + procedure FlushLexemeAll; + procedure SetContextFinal; + procedure MarkContextFinal; + procedure FlushStartOfLine; + function Lexeme: SSLexLexeme; + function LexemeAll: SSLexLexeme; + end; -type SSLexStringConsumer = class(SSLexConsumer) public - constructor Create(TheString: PChar); -end; + constructor Create(TheString: PAnsiChar); + end; -type SSLexFileConsumer = class(SSLexConsumer) public Handle: Integer; + end; -{ constructor Create(TheFileName: PChar; TheLength, TheIncrement: Longint; - TheMode: SSLexConsumerMode); - function NextBuffer: Longint; override; - function ReadData(TheBuffer: PChar; TheLength: Longint): Longint; - procedure Close; - destructor Destroy; override; - } -end; - -type - SSLex = class(TBoldMemoryManagedObject) + SSLex = class(SSLexRoot) public - State : Longint; - Table : SSLexTable; - Consumer: SSLexConsumer; - List : SSLexExpressionList; - Stack : SSLexExpressionListStack; - - constructor Create(TheConsumer: SSLexConsumer; TheTable: SSLexTable); -{ procedure Reset;} - procedure PopExpressionList; - function Next: SSLexLexeme; - procedure PushExpressionList(TheList: Longint); - procedure GotoExpressionList(TheList: Longint); - procedure ProcessExpressionList(ThePFinal: PSSLexFinalState); -{ function IsCurrentExpressionList(TheList: Longint): Boolean;} - - function Error: SSLexLexeme; virtual; - function Complete(TheToken: Longint): SSLexLexeme; virtual; - function TokenToString(TheToken: Longint): string; virtual; - destructor Destroy; override; + State: Longint; + Table: SSLexTable; + Consumer: SSLexConsumer; + List: SSLexExpressionList; + Stack: SSLexExpressionListStack; + + constructor Create(TheConsumer: SSLexConsumer; TheTable: SSLexTable); + + procedure PopExpressionList; + function Next: SSLexLexeme; + procedure PushExpressionList(TheList: Longint); + procedure GotoExpressionList(TheList: Longint); + procedure ProcessExpressionList(ThePFinal: TRow); + function Error: SSLexLexeme; virtual; + function Complete(TheToken: Longint): SSLexLexeme; virtual; + function TokenToString(TheToken: Longint): string; virtual; + destructor Destroy; override; + end; + -end; implementation uses - BoldSSExcept, - BoldCoreConsts, - SysUtils; + BoldSSExcept, SysUtils; + +constructor SSYaccStackElement.Create; +begin + inherited Create; + Lexeme := nil; + State := 0; + Use := 0; +end; + +procedure SSYaccStackElement.SetLexeme(TheLexeme: SSLexLexeme); +begin + if TheLexeme <> nil then + TheLexeme.RefInc; + if (Lexeme <> nil) and Lexeme.RefDec then + Lexeme.Free; + Lexeme := TheLexeme; +end; + +procedure SSYaccStackElement.RefInc; +begin + Inc(Use); +end; + +function SSYaccStackElement.RefDec: Boolean; +begin + Dec(Use); + Result := Use = 0; +end; -constructor SSLexConsumer.Create(TheIncrement: Longint; - TheMode: SSLexConsumerMode); +destructor SSYaccStackElement.Destroy; +begin + if (Lexeme <> nil) and Lexeme.RefDec then + Lexeme.Free; + inherited; +end; + +constructor SSLexConsumer.Create(TheIncrement: Integer; TheMode: SSLexConsumerMode); begin inherited Create; BuffInc := TheIncrement; @@ -305,7 +244,7 @@ destructor SSLexConsumer.Destroy; begin if Buffer <> nil then FreeMem(Buffer, BuffLen); - inherited Destroy; + inherited; end; procedure SSLexConsumer.MarkFinal; @@ -342,7 +281,7 @@ procedure SSLexConsumer.FlushLexeme; begin Start := Mark; Index := Mark; - Line := Line + MarkLine; + Inc(Line, MarkLine); Offset := MarkOffset; ScanLine := 0; ScanOffset := MarkOffset; @@ -351,129 +290,62 @@ procedure SSLexConsumer.FlushLexeme; procedure SSLexConsumer.FlushLexemeAll; begin Start := Index; - Line := Line + ScanLine; + Inc(Line, ScanLine); Offset := ScanOffset; ScanLine := 0; end; - function SSLexConsumer.Next: Boolean; var NewLen: Integer; - begin - if EndOfData = True then - Result := False + if EndOfData = True then + Result := False + else + begin + if Bof <> 0 then + begin + Current := Bof; + Bof := 0; + Result := True; + end else + begin + if Index >= DataLen then begin - if Bof <> 0 then + NewLen := NextBuffer; + if NewLen = 0 then begin - Current := Bof; - Bof := 0; - Result := True; + EndOfData := True; + Result := False; end - else - begin - if Index >= DataLen then - begin - NewLen := NextBuffer; - if NewLen = 0 then - begin - EndOfData := True; - Result := False; - end - else - begin - DataLen := DataLen + NewLen; - Result := True; - end - end else + begin + Inc(DataLen, NewLen); Result := True; - - - if Result = True then - begin - Current := Longint(Buffer[ Index]); - Inc(Index); - if Current = Ord($0A) then - begin - Inc(ScanLine); - ScanOffset := 1; - end - else - Inc(ScanOffset); - end end; - end; - -end; - -{function SSLexConsumer.ShiftBuffer(var TheOffset, TheFill: Longint): Boolean; -var - StartOfData: PChar; - -begin - if ((Start = 0) and (DataLen = 0)) then - begin - TheOffset := 0; - TheFill := BuffLen; - Result := False; - end - else if Start = 0 then - Result := True - else - begin - TheOffset := DataLen - Start; - if Offset <> 0 then - begin - StartOfData := Buffer + Start; - StrMove(Buffer, StartOfData, TheOffset); - TheFill := BuffLen - TheOffset; - Index := Index - Start; - Mark := Mark - Start; - MarkContext := MarkContext - Start; - DataLen := DataLen - Start; - Start := 0; - Result := False; end - else - begin - TheOffset := 0; - DataLen := 0; - Index := 0; - Start := 0; - TheFill := BuffLen; - Result := False; - end - end -end; + else + Result := True; -function SSLexConsumer.ExpandBuffer(var TheOffset, TheFill: Longint): Boolean; -var - NewBuff: PChar; - NewLen : Longint; + if Result = True then + begin + Current := Longint(Buffer[Index]); + Inc(Index); + if Current = Ord($0A) then + begin + Inc(ScanLine); + ScanOffset := 1; + end + else + Inc(ScanOffset); + end; + end; + end; -begin - if (BuffInc = 0) or (BuffLen >= SSLexBufferMax) then - Result := True - else - begin - NewLen := BuffLen + BuffInc; - if NewLen > SSLexBufferMax then - NewLen := SSLexBufferMax; - GetMem(NewBuff, NewLen); - StrMove(NewBuff, Buffer, BuffLen); - TheOffset := DataLen; - FreeMem(Buffer, BuffLen); - Buffer := NewBuff; - TheFill := NewLen - DataLen; - BuffLen := NewLen; - Result := False; - end end; - } -constructor SSLexStringConsumer.Create(TheString: PChar); + +constructor SSLexStringConsumer.Create(TheString: PAnsiChar); begin inherited Create(0, SSLexBinaryMode); DataLen := StrLen(TheString); @@ -481,144 +353,28 @@ constructor SSLexStringConsumer.Create(TheString: PChar); GetMem(Buffer, BuffLen); StrMove(Buffer, TheString, BuffLen); end; -(* -constructor SSLexFileConsumer.Create(TheFileName: PChar; - TheLength, TheIncrement: Longint; TheMode: SSLexConsumerMode); -var - Size : Longint; - NewException : SSException; - -begin - inherited Create(TheIncrement, TheMode); - DataLen := 0; - Mode := TheMode; - BuffLen := TheLength; - BuffInc := TheIncrement; - Handle := _lopen(TheFileName, OF_READ); - if Handle = -1 { HFILE_ERROR } then - begin - NewException := SSException.CreateName(SSExceptionLexFileOpen, SSLexMsgFileOpen, TheFileName); - raise NewException; - end - else - begin - Size := _llseek(Handle, 0, 2); - if Size < BuffLen then - BuffLen := Size; - if BuffLen > SSLexBufferMax then - BuffLen := SSLexBufferMax; - GetMem(Buffer, BuffLen); - _llseek(Handle, 0, 0); - DataLen := ReadData(Buffer, BuffLen); - if (DataLen = 0) then - Close; - end -end; - -function SSLexFileConsumer.ReadData(TheBuffer: PChar; TheLength: Longint): Longint; -var - TestChar : Byte; - IntBuff : PChar; - i : Integer; - SaveLength: Integer; - -begin - Result := 0; - if Mode = SSLexTextMode then - begin - GetMem(IntBuff, TheLength); - SaveLength := TheLength; - TheLength := _lread(Handle, IntBuff, TheLength); - for i := 0 to TheLength - 1 do - begin - TestChar := PByteArray(IntBuff)^[ i]; - if (TestChar <> $0D) and (TestChar <> $1A) then - begin - PByteArray(TheBuffer)^[ 0] := PByteArray(IntBuff)^[ i]; - Inc(Result); - TheBuffer := TheBuffer + 1; - end; - end; - FreeMem(IntBuff, SaveLength); - end - else - Result := _lread(Handle, TheBuffer, TheLength); -end; - -procedure SSLexFileConsumer.Close; -begin - if Handle <> 0 then - begin - _lclose(Handle); - Handle := 0; - end -end; - -function SSLexFileConsumer.NextBuffer: Longint; -var - TestChar: Char; - TestLen: Longint; - Offset, Fill: Longint; - NewException: SSException; - -begin - if Handle <> 0 then - begin - if (ShiftBuffer(Offset, Fill) and ExpandBuffer(Offset, Fill)) then - begin - TestLen := _lread(Handle, PChar(@TestChar), 1); - if TestLen <> 0 then - begin - NewException := SSException.CreateLong(SSExceptionLexLexemeLength, SSLexMsgLexemeLength, BuffLen); - raise NewException; - end - else - begin - Close; - Result := 0; - end - end - else - begin - Result := ReadData(Buffer + Offset, Fill); - if (Result = 0) then - Close; - end - end - else - Result := 0; - -end; - -destructor SSLexFileConsumer.Destroy; -begin - Close; - inherited Destroy; -end; -*) function SSLexConsumer.Lexeme: SSLexLexeme; var - Length : Longint; + Length: Longint; begin - Length := Mark - Start; - Result := SSLexLexeme.Create(Buffer + Start, Length, Line, Offset); - FlushLexeme; + Length := Mark - Start; + Result := SSLexLexeme.Create(PAnsiChar(Buffer) + Start, Length, Line, Offset); + FlushLexeme; end; function SSLexConsumer.LexemeAll: SSLexLexeme; begin - Result := SSLexLexeme.Create(Buffer + Start, Index - Start, Line, Offset); + Result := SSLexLexeme.Create(PAnsiChar(Buffer) + Start, Index - Start, Line, Offset); FlushLexemeAll; end; - -constructor SSLexLexeme.Create(TheData: PChar; TheLength, TheLine, TheOffset: Longint); +constructor SSLexLexeme.Create(TheData: PAnsiChar; TheLength, TheLine, TheOffset: Integer); begin inherited Create; GetMem(Buffer, TheLength + 1); StrMove(Buffer, TheData, TheLength); - PByteArray(Buffer)^[ TheLength] := $0; + PByteArray(Buffer)[TheLength] := 0; Length := TheLength; Line := TheLine; Offset := TheOffset; @@ -627,23 +383,26 @@ constructor SSLexLexeme.Create(TheData: PChar; TheLength, TheLine, TheOffset: Lo procedure SSLexLexeme.RefInc; begin - Assert(Use>=0); + if Use < 0 then + Assert(False, 'Assertion failure'); Inc(Use); end; function SSLexLexeme.RefDec: Boolean; begin Dec(Use); - Result := (Use = 0); - Assert(Use >= 0); + Result := Use = 0; + if Use < 0 then + Assert(False, 'Assertion failure'); end; destructor SSLexLexeme.Destroy; begin - Assert(Use=0); + if Use <> 0 then + Assert(False, 'Assertion failure'); if Buffer <> nil then FreeMem(Buffer, Length); - inherited Destroy; + inherited; end; function SSLexConsumer.NextBuffer: Longint; @@ -651,231 +410,85 @@ function SSLexConsumer.NextBuffer: Longint; Result := 0; end; -function SSHugeInc(ThePointer: Pointer; TheInc: Longint): Pointer; -begin - Result := PChar(ThePointer) + TheInc; -end; - -constructor SSLexTable.Create(FileName: String); +constructor SSLexTable.Create; var - i : Integer; - Current : Longint; - FileHandle : TFileStream; - Base : SSLexTableBase; - Header : SSLexTableHeader; - ExprList : SSLexExpressionList; - + i: Integer; + ExprList: SSLexExpressionList; begin inherited Create; - SSAux; - ExpressionLists := nil; - if not FileExists(FileName) then - raise Exception.CreateFmt(sFileDoesNotExist, [FileName]); - - FileHandle := TFileStream.Create(FileName, fmOpenRead); - FileHandle.Read(Base, sizeOf(Base)); - if Base.TableType <> SSLexPairTable then - raise SSException.CreateName(SSExceptionLexBadTable, SSLexMsgBadTable, PChar(FileName)); + FullTab; - NumLists := Base.Size; ExpressionLists := TList.Create; - for i := 0 to NumLists - 1 do + for i := 0 to Length(LexTab) - 1 do begin - Current := FileHandle.Position; - FileHandle.Read(Header, SizeOf(Header)); ExprList := SSLexExpressionList.Create; - GetMem(ExprList.Buffer, Header.Size); - ExprList.Size := Header.Size; - ExprList.Final := Header.Final; - ExprList.Index := Header.Index; - ExprList.Rows := Header.Rows; - FileHandle.Position := Current; - FileHandle.Read(ExprList.Buffer^, ExprList.Size); - ExprList.Open; + ExprList.ARows := LexTab[i]; ExpressionLists.Insert(i, ExprList); end; - FreeAndNil(FileHandle); -end; - -constructor SSLexTable.CreateResource(TheInstance: THandle; TheName, TheType: PChar); -var - LoadHandle : THandle; - FindHandle : THandle; - Resource : Pointer; - i : Integer; - NewException: SSException; - Base : SSLexTableBase; - Header : SSLexTableHeader; - ExprList : SSLexExpressionList; - -begin - inherited Create; - LoadHandle := 0; // to prevent compiler warning - SSAux; - Resource := nil; - ExpressionLists := nil; - FindHandle := FindResource(TheInstance, TheName, TheType); - if (FindHandle <> 0) then - begin - LoadHandle := LoadResource(TheInstance, FindHandle); - if (LoadHandle <> 0) then - Resource := LockResource(LoadHandle); - end; - if (Resource = nil) then - begin - NewException := SSException.CreateName(SSExceptionLexFindResource, SSLexMsgFindResource, TheType); - raise NewException; - end - else - begin - SSHugeCopy(@Base, Resource, sizeof(Base)); - if Base.TableType <> SSLexPairTable then - begin - NewException := SSException.CreateName(SSExceptionLexBadResource, SSLexMsgBadResource, TheType); - raise NewException; - end; - NumLists := Base.Size; - ExpressionLists := TList.Create; - Resource := SSHugeInc(Resource, sizeof(Base)); - for i := 0 to NumLists - 1 do - begin - SSHugeCopy(@Header, Resource, sizeof(Header)); - ExprList := SSLexExpressionList.Create; - Getmem(ExprList.Buffer, Header.Size); - ExprList.Size := Header.Size; - ExprList.Final := Header.Final; - ExprList.Index := Header.Index; - ExprList.Rows := Header.Rows; - SSHugeCopy(ExprList.Buffer, Resource, ExprList.Size); - ExprList.Open; - ExpressionLists.Insert(i, ExprList); - Resource := SSHugeInc(Resource, ExprList.Size); - end; - FreeResource(LoadHandle); - end end; -constructor SSLexExpressionList.CreateBuffer(TheHeader: PSSLexTableHeader; TheFile: PChar); -var -// i : Integer; - NewException: SSException; - Header : SSLexTableHeader; -begin - inherited Create; - SSHugeCopy(@Header, TheHeader, sizeof(SSLexTableHeader)); - if Header.TableType <> SSLexPairTable then - begin - NewException := SSException.CreateName(SSExceptionLexBadTable, SSLexMsgBadTable, TheFile); - raise NewException; - end; - GetMem(Buffer, Header.Size); //Buffer := SSHugeAlloc(Header.Size, Handle); - Size := Header.Size; - Final := Header.Final; - Index := Header.Index; - Rows := Header.Rows; - SSHugeCopy(Buffer, TheHeader, Size); - Open; -end; - -function SSLexTable.GetExpressionList(TheList: Longint): SSLexExpressionList; +function SSLexTable.GetExpressionList(TheList: Integer): SSLexExpressionList; var AnException: SSException; begin - if (TheList < 0) or (TheList >= ExpressionLists.Count) then - begin + if (TheList < 0) or (ExpressionLists.Count <= TheList) then + begin AnException := SSException.CreateLong(SSExceptionBadList, SSLexMsgBadList, TheList); raise AnException; - end; - Result := ExpressionLists.Items[ TheList]; -end; - -procedure SSLexExpressionList.Open; -var - i : Integer; - PRowOffsets: PSSLexRowOffsetArray; -begin - PPRows := SSHugeInc(Buffer, Index); - PRowOffsets := Pointer(PPRows); - PFinalStates := SSHugeInc(Buffer, Final); - for i := 0 to Rows - 1 do - PPRows^[ i] := SSHugeInc(Buffer, PRowOffsets^[ i]); -end; - -procedure SSHugeCopy(TheCopyTo: Pointer; TheCopyFrom: Pointer; TheLength: Longint); -begin - Move(TheCopyFrom^, TheCopyTo^, TheLength); + end; + Result := ExpressionLists[TheList]; end; - -function SSLexExpressionList.LookupState(TheToken, TheState: Longint): Longint; +function SSLexExpressionList.LookupState(TheToken, TheState: Integer): Longint; var - i : Integer; - PRow : PSSLexTableRow; - PEntry : PSSLexTableRowEntry; - PEntries: PSSLexRowEntryArray; - + i: Integer; + Row: TRow; + Entry: TEntry; begin Result := SSLexStateInvalid; - PRow := PPRows^[ TheState]; - PEntries := PSSLexRowEntryArray(PChar(PRow) + sizeof(SSLexTableRow)); - for i := 0 to PRow^.Size - 1 do - begin - PEntry := @PEntries^[ i]; + Row := ARows[TheState]; + for i := 0 to Length(Row.Entries) - 1 do + begin + Entry := Row.Entries[i]; if TheToken = SSLexConsumerBof then + begin + if Entry.StartPoint = SSLexConsumerBof then begin - if PEntry^.StartPoint = SSLexConsumerBof then - begin - Result := PEntry^.State; - Break; - end - end - else if TheToken < PEntry^.StartPoint then - Break - else - begin - if TheToken <= PEntry^.EndPoint then - begin - Result := PEntry^.State; + Result := Entry.State; Break; - end end; + end + else if TheToken < Entry.StartPoint then + begin + Break; + end + else if TheToken <= Entry.EndPoint then + begin + Result := Entry.State; + Break; end; -end; - -function SSLexExpressionList.LookupFinal(TheState: Longint): PSSLexFinalState; -begin - Result := @PFinalStates^[ TheState]; + end; end; destructor SSLexTable.Destroy; var - i : Integer; + i: Integer; List: SSLexExpressionList; begin if ExpressionLists <> nil then - begin + begin for i := 0 to ExpressionLists.Count - 1 do - begin - List := ExpressionLists.Items[ i]; + begin + List := ExpressionLists[i]; List.Free; - end; + + LexTab[i] := nil; end; + end; ExpressionLists.Free; - inherited Destroy; -end; - -constructor SSLexExpressionList.Create; -begin - inherited Create; - Buffer := nil; -end; -destructor SSLexExpressionList.Destroy; -begin - if Buffer <> nil then - FreeMem(Buffer, Size); - inherited Destroy; + inherited; end; constructor SSLex.Create(TheConsumer: SSLexConsumer; TheTable: SSLexTable); @@ -885,22 +498,16 @@ constructor SSLex.Create(TheConsumer: SSLexConsumer; TheTable: SSLexTable); inherited Create; Stack := nil; if (TheTable = nil) or (TheConsumer = nil) then - begin + begin AnException := SSException.Create(SSExceptionMissingPart, SSLexMsgMissingPart); raise AnException; - end; + end; Table := TheTable; Consumer := TheConsumer; Stack := SSLexExpressionListStack.Create; PushExpressionList(0); end; -{procedure SSLex.Reset; -begin - Stack.PopAll; - Stack.Push(Table.GetExpressionList(0)); -end; - } procedure SSLex.PopExpressionList; begin Stack.Pop; @@ -909,82 +516,77 @@ procedure SSLex.PopExpressionList; function SSLex.Next: SSLexLexeme; var - Consumed : Boolean; - PFinal : PSSLexFinalState; - PTempFinal : PSSLexFinalState; + Consumed: Boolean; + RFinal, RTempFinal: TRow; begin - result := nil; + Result := nil; while True do - begin + begin State := 0; Result := nil; Consumed := False; - PFinal := List.LookupFinal(State); + RFinal := List.ARows[State]; while Consumer.Next do - begin + begin Consumed := True; State := List.LookupState(Consumer.Current, State); if State = SSLexStateInvalid then - Break - else - begin - PTempFinal := List.LookupFinal(State); - if (PTempFinal^.Flags and SSLexFinalStateFlagsFinal) <> 0 then - begin - Consumer.MarkFinal; - PFinal := PTempFinal; - end; - if (PTempFinal^.Flags and SSLexFinalStateFlagsContextStart) <> 0 then - Consumer.MarkContextFinal; - end; + begin + Break; end; + RTempFinal := List.ARows[State]; + if RTempFinal.Flags and SSLexFinalStateFlagsFinal <> 0 then + begin + Consumer.MarkFinal; + RFinal := RTempFinal; + end; + if RTempFinal.Flags and SSLexFinalStateFlagsContextStart <> 0 then + Consumer.MarkContextFinal; + end; - if Consumed = False then + if not Consumed then Break; - if (PFinal^.Flags and SSLexFinalStateFlagsContextEnd) <> 0 then + if RFinal.Flags and SSLexFinalStateFlagsContextEnd <> 0 then Consumer.SetContextFinal; - if (PFinal^.Flags and SSLexFinalStateFlagsIgnore) <> 0 then - begin + if RFinal.Flags and SSLexFinalStateFlagsIgnore <> 0 then + begin Consumer.FlushLexeme; - ProcessExpressionList(PFinal); + ProcessExpressionList(RFinal); Continue; - end; + end; - if (PFinal^.Flags and SSLexFinalStateFlagsFinal) = 0 then - begin + if RFinal.Flags and SSLexFinalStateFlagsFinal = 0 then + begin Result := Error; if Result <> nil then - Break - else - begin - Consumer.FlushLexemeAll; - Continue; - end; - end; + Break; + + Consumer.FlushLexemeAll; + Continue; + end; - ProcessExpressionList(PFinal); - if (PFinal^.Flags and SSLexFinalStateFlagsStartOfLine) <> 0 then + ProcessExpressionList(RFinal); + if RFinal.Flags and SSLexFinalStateFlagsStartOfLine <> 0 then if (Consumer.Line <> 1) and (Consumer.Offset <> 1) then Consumer.FlushStartOfLine; - Result := Complete(PFinal^.Token); + Result := Complete(RFinal.Token); if Result <> nil then - Break - end; - + Break; + end; end; -procedure SSLex.ProcessExpressionList(ThePFinal: PSSLexFinalState); +procedure SSLex.ProcessExpressionList(ThePFinal: TRow); begin - if ((ThePFinal^.Flags and SSLexFinalStateFlagsPop) <> 0) and - ((ThePFinal^.Flags and SSLexFinalStateFlagsPush) <> 0) then - GotoExpressionList(ThePFinal^.Push) - else if (ThePFinal^.Flags and SSLexFinalStateFlagsPop) <> 0 then + if (ThePFinal.Flags and SSLexFinalStateFlagsPop <> 0) + and (ThePFinal.Flags and SSLexFinalStateFlagsPush <> 0) then + GotoExpressionList(ThePFinal.Push) + else if (ThePFinal.Flags and SSLexFinalStateFlagsPop <> 0) then PopExpressionList - else if (ThePFinal^.Flags and SSLexFinalStateFlagsPush) <> 0 then - PushExpressionList(ThePFinal^.Push); + else if (ThePFinal.Flags and SSLexFinalStateFlagsPush <> 0) then + PushExpressionList(ThePFinal.Push); end; procedure SSLex.PushExpressionList(TheList: Longint); @@ -999,29 +601,20 @@ procedure SSLex.GotoExpressionList(TheList: Longint); PushExpressionList(TheList); end; -{function SSLex.IsCurrentExpressionList(TheList: Longint): Boolean; -begin - if Table.GetExpressionList(TheList) = Stack.Top then - Result := True - else - Result := False; -end; -} - function SSLex.Error: SSLexLexeme; var - Lexeme : SSLexLexeme; + Lexeme: SSLexLexeme; AnException: SSException; begin Lexeme := Consumer.LexemeAll; - AnException := SSException.CreateLongLongNameLen(SSExceptionLexError, - SSLexMsgError, Lexeme.Line, Lexeme.Offset, Lexeme.Buffer, Lexeme.Length); + AnException := SSException.CreateLongLongNameLen(SSExceptionLexError, SSLexMsgError, + Lexeme.Line, Lexeme.Offset, PChar(string(Lexeme.Buffer)), Lexeme.Length); raise AnException; end; -function SSLex.TokenToString(TheToken: Longint): String; +function SSLex.TokenToString(TheToken: Longint): string; begin - result := ''; + Result := ''; end; function SSLex.Complete(TheToken: Longint): SSLexLexeme; @@ -1033,12 +626,12 @@ function SSLex.Complete(TheToken: Longint): SSLexLexeme; destructor SSLex.Destroy; begin Stack.Free; - inherited Destroy; + inherited; end; function SSLexExpressionListStack.Top: SSLexExpressionList; begin - Result := inherited Top; + Result := inherited Top as SSLexExpressionList; end; procedure SSLexExpressionListStack.Push(TheList: SSLexExpressionList); @@ -1051,7 +644,7 @@ constructor SSStack.Create; inherited Create; Size := 32; Incr := 32; - GetMem(PArray, Size * sizeof(Pointer)); + GetMem(PArray, Size * SizeOf(Pointer)); TopOfStack := 0; end; @@ -1060,66 +653,886 @@ procedure SSStack.Pop; AnException: SSException; begin if TopOfStack = 0 then - begin + begin AnException := SSException.Create(SSExceptionStackPop, SSLifoMsgStackPop); raise AnException; - end; + end; Dec(TopOfStack); end; -{procedure SSStack.PopAll; -begin - TopOfStack := 0; -end; - } -function SSStack.Top: Pointer; +function SSStack.Top: SSLexRoot; var AnException: SSException; begin if TopOfStack = 0 then - begin + begin AnException := SSException.Create(SSExceptionStackTop, SSLifoMsgStackTop); raise AnException; - end; - Result := PArray^[ TopOfStack - 1]; + end; + Result := PArray[TopOfStack - 1]; end; -procedure SSStack.Push(ThePointer: Pointer); +procedure SSStack.Push(TheSSYaccStackElement: SSLexRoot); var - i : Integer; - NewSize : Integer; - PNewArray: PSSArrayOfPointer; + i: Integer; + NewSize: Integer; + PNewArray: PSSArrayOfSSYaccStackElement; begin if TopOfStack >= Size then - begin + begin NewSize := Size + Incr; - GetMem(PNewArray, NewSize * sizeof(Pointer)); + GetMem(PNewArray, NewSize * SizeOf(Pointer)); for i := 0 to TopOfStack - 1 do - PNewArray^[ i] := PArray^[ i]; - FreeMem(PArray, Size * sizeof(Pointer)); + PNewArray[i] := PArray[i]; + FreeMem(PArray, Size * SizeOf(Pointer)); PArray := PNewArray; Size := NewSize; - end; + end; - PArray^[ TopOfStack] := ThePointer; + PArray[TopOfStack] := TheSSYaccStackElement as SSYaccStackElement; Inc(TopOfStack); end; destructor SSStack.Destroy; begin - FreeMem(PArray, Size * sizeof(Pointer)); + FreeMem(PArray, Size * SizeOf(Pointer)); inherited; end; -{$IFDEF SSAUX} -{$I SSAUXFUN.PAS} -{$ELSE} -procedure SSAux; +procedure SSLexTable.FullTab; +var + Row: TRow; + N: Integer; + + procedure R(T, P, F, C: ShortInt); + begin + with Row do + begin + Token := T; + Push := P; + Flags := F; + SetLength(Entries, C); + N := 0; + end; + end; + + procedure RE(B, E, S: Longint); + begin + with Row.Entries[N] do + begin + StartPoint := B; + EndPoint := E; + State := S; + end; + Inc(N); + end; + begin + {$REGION 'Full LexTab'} + + // === LexTab[0] === + + SetLength(LexTab[0], 111); + // [0, 0] + R(0, 0, 0, 45); + RE(9, 10, 1); + RE(32, 32, 1); + RE(35, 35, 12); + RE(39, 39, 14); + RE(40, 40, 16); + RE(41, 41, 18); + RE(42, 42, 20); + RE(43, 43, 22); + RE(44, 44, 24); + RE(45, 45, 26); + RE(46, 46, 28); + RE(47, 47, 30); + RE(48, 57, 32); + RE(58, 58, 34); + RE(60, 60, 36); + RE(61, 61, 38); + RE(62, 62, 40); + RE(64, 64, 42); + RE(65, 65, 44); + RE(66, 66, 46); + RE(67, 67, 48); + RE(68, 82, 44); + RE(83, 83, 50); + RE(84, 90, 44); + RE(91, 91, 52); + RE(93, 93, 54); + RE(97, 97, 56); + RE(98, 99, 60); + RE(100, 100, 58); + RE(101, 101, 62); + RE(102, 104, 60); + RE(105, 105, 64); + RE(106, 108, 60); + RE(109, 109, 66); + RE(110, 110, 102); + RE(111, 111, 68); + RE(112, 115, 60); + RE(116, 116, 70); + RE(117, 119, 60); + RE(120, 120, 101); + RE(121, 122, 60); + RE(123, 123, 72); + RE(124, 124, 74); + RE(125, 125, 76); + RE(-1, -1, 78); + LexTab[0][0] := Row; + // [0, 1] + R(1, 0, 80, 0); + LexTab[0][1] := Row; + // [0, 2] + R(0, 0, 0, 1); + RE(48, 57, 11); + LexTab[0][2] := Row; + // [0, 3] + R(0, 0, 0, 1); + RE(48, 57, 5); + LexTab[0][3] := Row; + // [0, 4] + R(0, 0, 0, 1); + RE(48, 57, 2); + LexTab[0][4] := Row; + // [0, 5] + R(0, 0, 0, 2); + RE(48, 57, 7); + RE(58, 58, 109); + LexTab[0][5] := Row; + // [0, 6] + R(0, 0, 0, 1); + RE(45, 45, 4); + LexTab[0][6] := Row; + // [0, 7] + R(0, 0, 0, 1); + RE(48, 57, 9); + LexTab[0][7] := Row; + // [0, 8] + R(0, 0, 0, 1); + RE(48, 57, 6); + LexTab[0][8] := Row; + // [0, 9] + R(0, 0, 0, 1); + RE(45, 45, 10); + LexTab[0][9] := Row; + // [0, 10] + R(0, 0, 0, 1); + RE(48, 57, 8); + LexTab[0][10] := Row; + // [0, 11] + R(6, 0, 16, 0); + LexTab[0][11] := Row; + // [0, 12] + R(34, 0, 16, 1); + RE(48, 57, 3); + LexTab[0][12] := Row; + // [0, 13] + R(7, 0, 16, 0); + LexTab[0][13] := Row; + // [0, 14] + R(8, 1, 48, 0); + LexTab[0][14] := Row; + // [0, 15] + R(7, 0, 16, 1); + RE(58, 58, 110); + LexTab[0][15] := Row; + // [0, 16] + R(11, 0, 16, 0); + LexTab[0][16] := Row; + // [0, 17] + R(26, 0, 16, 0); + LexTab[0][17] := Row; + // [0, 18] + R(12, 0, 16, 0); + LexTab[0][18] := Row; + // [0, 19] + R(37, 0, 16, 0); + LexTab[0][19] := Row; + // [0, 20] + R(23, 0, 16, 0); + LexTab[0][20] := Row; + // [0, 21] + R(3, 0, 16, 1); + RE(48, 57, 21); + LexTab[0][21] := Row; + // [0, 22] + R(21, 0, 16, 0); + LexTab[0][22] := Row; + // [0, 23] + R(36, 0, 16, 0); + LexTab[0][23] := Row; + // [0, 24] + R(27, 0, 16, 0); + LexTab[0][24] := Row; + // [0, 25] + R(20, 0, 16, 0); + LexTab[0][25] := Row; + // [0, 26] + R(22, 0, 16, 1); + RE(62, 62, 17); + LexTab[0][26] := Row; + // [0, 27] + R(19, 0, 16, 0); + LexTab[0][27] := Row; + // [0, 28] + R(25, 0, 16, 1); + RE(46, 46, 19); + LexTab[0][28] := Row; + // [0, 29] + R(18, 0, 16, 0); + LexTab[0][29] := Row; + // [0, 30] + R(24, 0, 16, 0); + LexTab[0][30] := Row; + // [0, 31] + R(39, 0, 16, 4); + RE(48, 57, 44); + RE(65, 90, 44); + RE(95, 95, 44); + RE(97, 122, 44); + LexTab[0][31] := Row; + // [0, 32] + R(2, 0, 16, 2); + RE(46, 46, 106); + RE(48, 57, 32); + LexTab[0][32] := Row; + // [0, 33] + R(5, 0, 16, 6); + RE(48, 57, 44); + RE(65, 90, 44); + RE(95, 95, 44); + RE(97, 102, 44); + RE(103, 103, 31); + RE(104, 122, 44); + LexTab[0][33] := Row; + // [0, 34] + R(38, 0, 16, 1); + RE(58, 58, 23); + LexTab[0][34] := Row; + // [0, 35] + R(42, 0, 16, 4); + RE(48, 57, 44); + RE(65, 90, 44); + RE(95, 95, 44); + RE(97, 122, 44); + LexTab[0][35] := Row; + // [0, 36] + R(16, 0, 16, 2); + RE(61, 61, 27); + RE(62, 62, 25); + LexTab[0][36] := Row; + // [0, 37] + R(5, 0, 16, 6); + RE(48, 57, 44); + RE(65, 90, 44); + RE(95, 95, 44); + RE(97, 109, 44); + RE(110, 110, 35); + RE(111, 122, 44); + LexTab[0][37] := Row; + // [0, 38] + R(17, 0, 16, 0); + LexTab[0][38] := Row; + // [0, 39] + R(5, 0, 16, 6); + RE(48, 57, 44); + RE(65, 90, 44); + RE(95, 95, 44); + RE(97, 110, 44); + RE(111, 111, 37); + RE(112, 122, 44); + LexTab[0][39] := Row; + // [0, 40] + R(15, 0, 16, 1); + RE(61, 61, 29); + LexTab[0][40] := Row; + // [0, 41] + R(5, 0, 16, 6); + RE(48, 57, 44); + RE(65, 90, 44); + RE(95, 95, 44); + RE(97, 104, 44); + RE(105, 105, 39); + RE(106, 122, 44); + LexTab[0][41] := Row; + // [0, 42] + R(28, 0, 16, 0); + LexTab[0][42] := Row; + // [0, 43] + R(5, 0, 16, 6); + RE(48, 57, 44); + RE(65, 90, 44); + RE(95, 95, 44); + RE(97, 115, 44); + RE(116, 116, 41); + RE(117, 122, 44); + LexTab[0][43] := Row; + // [0, 44] + R(5, 0, 16, 4); + RE(48, 57, 44); + RE(65, 90, 44); + RE(95, 95, 44); + RE(97, 122, 44); + LexTab[0][44] := Row; + // [0, 45] + R(5, 0, 16, 6); + RE(48, 57, 44); + RE(65, 90, 44); + RE(95, 95, 44); + RE(97, 98, 44); + RE(99, 99, 43); + RE(100, 122, 44); + LexTab[0][45] := Row; + // [0, 46] + R(5, 0, 16, 5); + RE(48, 57, 44); + RE(65, 90, 44); + RE(95, 95, 44); + RE(97, 97, 33); + RE(98, 122, 44); + LexTab[0][46] := Row; + // [0, 47] + R(5, 0, 16, 6); + RE(48, 57, 44); + RE(65, 90, 44); + RE(95, 95, 44); + RE(97, 100, 44); + RE(101, 101, 45); + RE(102, 122, 44); + LexTab[0][47] := Row; + // [0, 48] + R(5, 0, 16, 6); + RE(48, 57, 44); + RE(65, 90, 44); + RE(95, 95, 44); + RE(97, 110, 44); + RE(111, 111, 51); + RE(112, 122, 44); + LexTab[0][48] := Row; + // [0, 49] + R(5, 0, 16, 6); + RE(48, 57, 44); + RE(65, 90, 44); + RE(95, 95, 44); + RE(97, 107, 44); + RE(108, 108, 47); + RE(109, 122, 44); + LexTab[0][49] := Row; + // [0, 50] + R(5, 0, 16, 6); + RE(48, 57, 44); + RE(65, 90, 44); + RE(95, 95, 44); + RE(97, 100, 44); + RE(101, 101, 67); + RE(102, 122, 44); + LexTab[0][50] := Row; + // [0, 51] + R(5, 0, 16, 6); + RE(48, 57, 44); + RE(65, 90, 44); + RE(95, 95, 44); + RE(97, 107, 44); + RE(108, 108, 49); + RE(109, 122, 44); + LexTab[0][51] := Row; + // [0, 52] + R(9, 0, 16, 0); + LexTab[0][52] := Row; + // [0, 53] + R(41, 0, 16, 4); + RE(48, 57, 44); + RE(65, 90, 44); + RE(95, 95, 44); + RE(97, 122, 44); + LexTab[0][53] := Row; + // [0, 54] + R(10, 0, 16, 0); + LexTab[0][54] := Row; + // [0, 55] + R(5, 0, 16, 6); + RE(48, 57, 44); + RE(65, 90, 44); + RE(95, 95, 44); + RE(97, 100, 44); + RE(101, 101, 53); + RE(102, 122, 44); + LexTab[0][55] := Row; + // [0, 56] + R(4, 0, 16, 6); + RE(48, 57, 60); + RE(65, 90, 60); + RE(95, 95, 60); + RE(97, 109, 60); + RE(110, 110, 71); + RE(111, 122, 60); + LexTab[0][56] := Row; + // [0, 57] + R(5, 0, 16, 6); + RE(48, 57, 44); + RE(65, 90, 44); + RE(95, 95, 44); + RE(97, 98, 44); + RE(99, 99, 55); + RE(100, 122, 44); + LexTab[0][57] := Row; + // [0, 58] + R(4, 0, 16, 6); + RE(48, 57, 60); + RE(65, 90, 60); + RE(95, 95, 60); + RE(97, 104, 60); + RE(105, 105, 75); + RE(106, 122, 60); + LexTab[0][58] := Row; + // [0, 59] + R(5, 0, 16, 6); + RE(48, 57, 44); + RE(65, 90, 44); + RE(95, 95, 44); + RE(97, 109, 44); + RE(110, 110, 57); + RE(111, 122, 44); + LexTab[0][59] := Row; + // [0, 60] + R(4, 0, 16, 4); + RE(48, 57, 60); + RE(65, 90, 60); + RE(95, 95, 60); + RE(97, 122, 60); + LexTab[0][60] := Row; + // [0, 61] + R(5, 0, 16, 6); + RE(48, 57, 44); + RE(65, 90, 44); + RE(95, 95, 44); + RE(97, 100, 44); + RE(101, 101, 59); + RE(102, 122, 44); + LexTab[0][61] := Row; + // [0, 62] + R(4, 0, 16, 8); + RE(48, 57, 60); + RE(65, 90, 60); + RE(95, 95, 60); + RE(97, 107, 60); + RE(108, 108, 91); + RE(109, 109, 60); + RE(110, 110, 89); + RE(111, 122, 60); + LexTab[0][62] := Row; + // [0, 63] + R(40, 0, 16, 4); + RE(48, 57, 44); + RE(65, 90, 44); + RE(95, 95, 44); + RE(97, 122, 44); + LexTab[0][63] := Row; + // [0, 64] + R(4, 0, 16, 8); + RE(48, 57, 60); + RE(65, 90, 60); + RE(95, 95, 60); + RE(97, 101, 60); + RE(102, 102, 96); + RE(103, 108, 60); + RE(109, 109, 98); + RE(110, 122, 60); + LexTab[0][64] := Row; + // [0, 65] + R(5, 0, 16, 6); + RE(48, 57, 44); + RE(65, 90, 44); + RE(95, 95, 44); + RE(97, 116, 44); + RE(117, 117, 61); + RE(118, 122, 44); + LexTab[0][65] := Row; + // [0, 66] + R(4, 0, 16, 6); + RE(48, 57, 60); + RE(65, 90, 60); + RE(95, 95, 60); + RE(97, 110, 60); + RE(111, 111, 92); + RE(112, 122, 60); + LexTab[0][66] := Row; + // [0, 67] + R(5, 0, 16, 8); + RE(48, 57, 44); + RE(65, 90, 44); + RE(95, 95, 44); + RE(97, 112, 44); + RE(113, 113, 65); + RE(114, 115, 44); + RE(116, 116, 63); + RE(117, 122, 44); + LexTab[0][67] := Row; + // [0, 68] + R(4, 0, 16, 6); + RE(48, 57, 60); + RE(65, 90, 60); + RE(95, 95, 60); + RE(97, 113, 60); + RE(114, 114, 86); + RE(115, 122, 60); + LexTab[0][68] := Row; + // [0, 69] + R(45, 0, 16, 4); + RE(48, 57, 60); + RE(65, 90, 60); + RE(95, 95, 60); + RE(97, 122, 60); + LexTab[0][69] := Row; + // [0, 70] + R(4, 0, 16, 6); + RE(48, 57, 60); + RE(65, 90, 60); + RE(95, 95, 60); + RE(97, 103, 60); + RE(104, 104, 82); + RE(105, 122, 60); + LexTab[0][70] := Row; + // [0, 71] + R(4, 0, 16, 6); + RE(48, 57, 60); + RE(65, 90, 60); + RE(95, 95, 60); + RE(97, 99, 60); + RE(100, 100, 69); + RE(101, 122, 60); + LexTab[0][71] := Row; + // [0, 72] + R(13, 0, 16, 0); + LexTab[0][72] := Row; + // [0, 73] + R(43, 0, 16, 4); + RE(48, 57, 60); + RE(65, 90, 60); + RE(95, 95, 60); + RE(97, 122, 60); + LexTab[0][73] := Row; + // [0, 74] + R(35, 0, 16, 0); + LexTab[0][74] := Row; + // [0, 75] + R(4, 0, 16, 6); + RE(48, 57, 60); + RE(65, 90, 60); + RE(95, 95, 60); + RE(97, 117, 60); + RE(118, 118, 73); + RE(119, 122, 60); + LexTab[0][75] := Row; + // [0, 76] + R(14, 0, 16, 0); + LexTab[0][76] := Row; + // [0, 77] + R(31, 0, 16, 4); + RE(48, 57, 60); + RE(65, 90, 60); + RE(95, 95, 60); + RE(97, 122, 60); + LexTab[0][77] := Row; + // [0, 78] + R(-1, 0, 80, 0); + LexTab[0][78] := Row; + // [0, 79] + R(4, 0, 16, 6); + RE(48, 57, 60); + RE(65, 90, 60); + RE(95, 95, 60); + RE(97, 100, 60); + RE(101, 101, 77); + RE(102, 122, 60); + LexTab[0][79] := Row; + // [0, 80] + R(48, 0, 16, 4); + RE(48, 57, 60); + RE(65, 90, 60); + RE(95, 95, 60); + RE(97, 122, 60); + LexTab[0][80] := Row; + // [0, 81] + R(32, 0, 16, 4); + RE(48, 57, 60); + RE(65, 90, 60); + RE(95, 95, 60); + RE(97, 122, 60); + LexTab[0][81] := Row; + // [0, 82] + R(4, 0, 16, 6); + RE(48, 57, 60); + RE(65, 90, 60); + RE(95, 95, 60); + RE(97, 100, 60); + RE(101, 101, 105); + RE(102, 122, 60); + LexTab[0][82] := Row; + // [0, 83] + R(4, 0, 16, 6); + RE(48, 57, 60); + RE(65, 90, 60); + RE(95, 95, 60); + RE(97, 101, 60); + RE(102, 102, 81); + RE(103, 122, 60); + LexTab[0][83] := Row; + // [0, 84] + R(30, 0, 16, 4); + RE(48, 57, 60); + RE(65, 90, 60); + RE(95, 95, 60); + RE(97, 122, 60); + LexTab[0][84] := Row; + // [0, 85] + R(33, 0, 16, 4); + RE(48, 57, 60); + RE(65, 90, 60); + RE(95, 95, 60); + RE(97, 122, 60); + LexTab[0][85] := Row; + // [0, 86] + R(46, 0, 16, 4); + RE(48, 57, 60); + RE(65, 90, 60); + RE(95, 95, 60); + RE(97, 122, 60); + LexTab[0][86] := Row; + // [0, 87] + R(4, 0, 16, 6); + RE(48, 57, 60); + RE(65, 90, 60); + RE(95, 95, 60); + RE(97, 108, 60); + RE(109, 109, 85); + RE(110, 122, 60); + LexTab[0][87] := Row; + // [0, 88] + R(4, 0, 16, 6); + RE(48, 57, 60); + RE(65, 90, 60); + RE(95, 95, 60); + RE(97, 115, 60); + RE(116, 116, 90); + RE(117, 122, 60); + LexTab[0][88] := Row; + // [0, 89] + R(4, 0, 16, 8); + RE(48, 57, 60); + RE(65, 90, 60); + RE(95, 95, 60); + RE(97, 99, 60); + RE(100, 100, 103); + RE(101, 116, 60); + RE(117, 117, 87); + RE(118, 122, 60); + LexTab[0][89] := Row; + // [0, 90] + R(47, 0, 16, 4); + RE(48, 57, 60); + RE(65, 90, 60); + RE(95, 95, 60); + RE(97, 122, 60); + LexTab[0][90] := Row; + // [0, 91] + R(4, 0, 16, 6); + RE(48, 57, 60); + RE(65, 90, 60); + RE(95, 95, 60); + RE(97, 114, 60); + RE(115, 115, 79); + RE(116, 122, 60); + LexTab[0][91] := Row; + // [0, 92] + R(4, 0, 16, 6); + RE(48, 57, 60); + RE(65, 90, 60); + RE(95, 95, 60); + RE(97, 99, 60); + RE(100, 100, 94); + RE(101, 122, 60); + LexTab[0][92] := Row; + // [0, 93] + R(49, 0, 16, 4); + RE(48, 57, 60); + RE(65, 90, 60); + RE(95, 95, 60); + RE(97, 122, 60); + LexTab[0][93] := Row; + // [0, 94] + R(44, 0, 16, 4); + RE(48, 57, 60); + RE(65, 90, 60); + RE(95, 95, 60); + RE(97, 122, 60); + LexTab[0][94] := Row; + // [0, 95] + R(4, 0, 16, 6); + RE(48, 57, 60); + RE(65, 90, 60); + RE(95, 95, 60); + RE(97, 114, 60); + RE(115, 115, 93); + RE(116, 122, 60); + LexTab[0][95] := Row; + // [0, 96] + R(29, 0, 16, 4); + RE(48, 57, 60); + RE(65, 90, 60); + RE(95, 95, 60); + RE(97, 122, 60); + LexTab[0][96] := Row; + // [0, 97] + R(4, 0, 16, 6); + RE(48, 57, 60); + RE(65, 90, 60); + RE(95, 95, 60); + RE(97, 100, 60); + RE(101, 101, 95); + RE(102, 122, 60); + LexTab[0][97] := Row; + // [0, 98] + R(4, 0, 16, 6); + RE(48, 57, 60); + RE(65, 90, 60); + RE(95, 95, 60); + RE(97, 111, 60); + RE(112, 112, 99); + RE(113, 122, 60); + LexTab[0][98] := Row; + // [0, 99] + R(4, 0, 16, 6); + RE(48, 57, 60); + RE(65, 90, 60); + RE(95, 95, 60); + RE(97, 107, 60); + RE(108, 108, 104); + RE(109, 122, 60); + LexTab[0][99] := Row; + // [0, 100] + R(4, 0, 16, 6); + RE(48, 57, 60); + RE(65, 90, 60); + RE(95, 95, 60); + RE(97, 113, 60); + RE(114, 114, 80); + RE(115, 122, 60); + LexTab[0][100] := Row; + // [0, 101] + R(4, 0, 16, 6); + RE(48, 57, 60); + RE(65, 90, 60); + RE(95, 95, 60); + RE(97, 110, 60); + RE(111, 111, 100); + RE(112, 122, 60); + LexTab[0][101] := Row; + // [0, 102] + R(4, 0, 16, 6); + RE(48, 57, 60); + RE(65, 90, 60); + RE(95, 95, 60); + RE(97, 110, 60); + RE(111, 111, 88); + RE(112, 122, 60); + LexTab[0][102] := Row; + // [0, 103] + R(4, 0, 16, 6); + RE(48, 57, 60); + RE(65, 90, 60); + RE(95, 95, 60); + RE(97, 104, 60); + RE(105, 105, 83); + RE(106, 122, 60); + LexTab[0][103] := Row; + // [0, 104] + R(4, 0, 16, 6); + RE(48, 57, 60); + RE(65, 90, 60); + RE(95, 95, 60); + RE(97, 104, 60); + RE(105, 105, 97); + RE(106, 122, 60); + LexTab[0][104] := Row; + // [0, 105] + R(4, 0, 16, 6); + RE(48, 57, 60); + RE(65, 90, 60); + RE(95, 95, 60); + RE(97, 109, 60); + RE(110, 110, 84); + RE(111, 122, 60); + LexTab[0][105] := Row; + // [0, 106] + R(0, 0, 0, 1); + RE(48, 57, 21); + LexTab[0][106] := Row; + // [0, 107] + R(0, 0, 0, 1); + RE(48, 57, 13); + LexTab[0][107] := Row; + // [0, 108] + R(0, 0, 0, 1); + RE(48, 57, 15); + LexTab[0][108] := Row; + // [0, 109] + R(0, 0, 0, 1); + RE(48, 57, 108); + LexTab[0][109] := Row; + // [0, 110] + R(0, 0, 0, 1); + RE(48, 57, 107); + LexTab[0][110] := Row; + + // === LexTab[1] === + + SetLength(LexTab[1], 6); + // [1, 0] + R(50, 0, 16, 7); + RE(0, 9, 2); + RE(11, 38, 2); + RE(39, 39, 4); + RE(40, 91, 2); + RE(92, 92, 1); + RE(93, 65535, 2); + RE(-1, -1, 5); + LexTab[1][0] := Row; + // [1, 1] + R(50, 0, 16, 4); + RE(0, 9, 2); + RE(11, 91, 2); + RE(92, 92, 3); + RE(93, 65535, 2); + LexTab[1][1] := Row; + // [1, 2] + R(50, 0, 16, 5); + RE(0, 9, 2); + RE(11, 38, 2); + RE(40, 91, 2); + RE(92, 92, 1); + RE(93, 65535, 2); + LexTab[1][2] := Row; + // [1, 3] + R(50, 0, 16, 4); + RE(0, 9, 2); + RE(11, 91, 2); + RE(92, 92, 3); + RE(93, 65535, 2); + LexTab[1][3] := Row; + // [1, 4] + R(51, 0, 24, 0); + LexTab[1][4] := Row; + // [1, 5] + R(-1, 0, 80, 0); + LexTab[1][5] := Row; + + {$ENDREGION} end; -{$ENDIF} -end. +end. diff --git a/Source/ObjectSpace/Ocl/BoldSSYaccU.pas b/Source/ObjectSpace/Ocl/BoldSSYaccU.pas index 48b9981..ff75f10 100644 --- a/Source/ObjectSpace/Ocl/BoldSSYaccU.pas +++ b/Source/ObjectSpace/Ocl/BoldSSYaccU.pas @@ -1,3 +1,4 @@ + unit BoldSSYaccU; {$RANGECHECKS OFF} @@ -5,420 +6,166 @@ interface uses - Classes, - WinTypes, - WinProcs, - BoldSSLexU, - BoldBase; + Classes, BoldSSLexU, BoldBase; const - SSYaccPairTableMaxSize = 65528; - SSYaccPairTableId = $53535943; - SSYaccPairTableRowFlagsSync = $0001; SSYaccPairTableRowFlagsError = $0002; SSYaccPairTableRowFlagsSyncAll = $0004; - SSYaccPairTableRowFlagsDuplicate = $0008; SSYaccPairTableRowFlagsSyncPossible = $0005; - SSYaccPairTableEntryMask = $f8000000; SSYaccPairTableEntrySync = $80000000; SSYaccPairTableEntryShift = $40000000; SSYaccPairTableEntryReduce = $20000000; SSYaccPairTableEntryAccept = $10000000; SSYaccPairTableEntryConflict = $08000000; - SSYaccPairTableEntryMax = $07ffffff; + SSYaccPairTableEntryMax = $07FFFFFF; SSYaccEofString = 'eof'; SSYaccErrorString = 'error'; - SSYaccEofToken = $ffffffff; - SSYaccErrorToken = $fffffffe; - SSYaccMsgFileOpen = 'SSYacc0101e: Open file failed, %s'; + SSYaccEofToken = $FFFFFFFF; + SSYaccErrorToken = $FFFFFFFE; + SSYaccMsgParse = 'SSYacc0102e: Parse failed, invalid table'; SSYaccMsgEof = 'SSYacc0103e: Attempted read past eof'; SSYaccMsgMissingTable = 'SSYacc0109e: Table missing, required'; SSYaccMsgMissingLexer = 'SSYacc0110e: Lexer missing, required'; - SSYaccMsgRead = 'SSYacc0111e: Error reading table, %s'; - SSYaccMsgTableSize = 'SSYacc0112e: Table too big'; SSYaccMsgElement = 'SSYacc0108e: Invalid index on ElementFromxxx'; SSYaccMsgSyncErrToken = 'SSYacc0105e: SyncErr failed, no valid token'; SSYaccMsgSyncErrEof = 'SSYacc0106e: SyncErr failed, eof'; - SSYaccMsgFindResource = 'SSYacc0107e: Unable to locate resource, %s'; - SSYaccMsgBadResource = 'SSYacc0108e: Invalid resource, %s'; type - SSArrayOfLongint = array[ 0..(SSLexStructMax div sizeof(Longint))] of Longint; + SSArrayOfLongint = array[0..(SSLexStructMax div SizeOf(Longint))] of Longint; PSSArrayOfLongint = ^SSArrayOfLongint; -type SSSetOfLongint = class(TBoldMemoryManagedObject) public - Incr : Longint; - Size : Longint; - Count : Longint; - PArray : PSSArrayOfLongint; - - constructor Create(TheSize, TheInc: Longint); - function Insert(TheItem: Longint): Boolean; - function Contains(TheItem: Longint): Boolean; - destructor Destroy; override; -end; + Incr: Longint; + Size: Longint; + Count: Longint; + PArray: PSSArrayOfLongint; + + constructor Create(TheSize, TheInc: Longint); + function Insert(TheItem: Longint): Boolean; + function Contains(TheItem: Longint): Boolean; + destructor Destroy; override; + end; -type - SSYaccPairTable = record - TableType : Longint; - Prods : Longint; - States : Longint; - RowOffset : Longint; - ProdOffset: Longint; -end; + TYProd = record + Size: Byte; + Leftside: Word; + end; -type - SSYaccPairTableRow = record - Flags : Longint; - Gotos : Longint; - Actions : Longint; -end; + TYEntry = record + Entry: Longint; + Token: Longint; + end; -type - SSYaccPairTableEntry = record - Entry : Longint; - Token : Longint; -end; + TYRow = record + Flags: Byte; + Gotos: Byte; + Actions: Byte; + Entries: array of TYEntry; + end; -type - SSYaccPairTableProd = record - Size : Longint; - Leftside : Longint; -end; + TYRows = array of TYRow; + TYProds = array of TYProd; -type SSYaccAction = (ShiftAction, ErrorAction, ReduceAction, AcceptAction, ConflictAction); - PSSYaccPairTable = ^SSYaccPairTable; - PSSYaccPairTableRow = ^SSYaccPairTableRow; - PSSYaccPairTableProd = ^SSYaccPairTableProd; - PSSYaccPairTableEntry = ^SSYaccPairTableEntry; - SSYaccEntryArray = array[ 0..(SSLexStructMax div sizeof(SSYaccPairTableEntry))] of SSYaccPairTableEntry; - PSSYaccEntryArray = ^SSYaccEntryArray; - SSYaccProdArray = array[ 0..(SSLexStructMax div sizeof(SSYaccPairTableProd))] of SSYaccPairTableProd; - PSSYaccProdArray = ^SSYaccProdArray; - SSYaccRowArray = array[ 0..(SSLexStructMax div sizeof(PSSYaccPairTableRow))] of PSSYaccPairTableRow; - SSYaccRowOffsetArray = array[ 0..(SSLexStructMax div sizeof(Longint))] of Longint; - PSSYaccRowArray = ^SSYaccRowArray; - PSSYaccRowOffsetArray = ^SSYaccRowOffsetArray; - -type - SSYaccStackElement = class(TBoldMemoryManagedObject) - public - Lexeme: SSLexLexeme; - State : Longint; - Use : Longint; - - constructor Create; - procedure RefInc; - function RefDec: Boolean; - procedure SetLexeme(TheLexeme: SSLexLexeme); - destructor Destroy; override; -end; -type SSYaccStack = class(SSStack) public - function Top: SSYaccStackElement; - procedure Push(TheElement: SSYaccStackElement); - destructor Destroy; override; -end; + function Top: SSYaccStackElement; + procedure Push(TheElement: SSYaccStackElement); + destructor Destroy; override; + end; -type SSYaccTable = class(TBoldMemoryManagedObject) public - LarTableList: TList; - Size : Longint; - PPRowArray : PSSYaccRowArray; - PTable : PSSYaccPairTable; - PProdArray : PSSYaccProdArray; - - constructor Create(FileName: String); - constructor CreateResource(TheInstance: THandle; TheName, TheType: PChar); - function LarTables: Longint; - function Productions: Longint; - function RowSize(TheRow: PSSYaccPairTableRow): Longint; - procedure GetLarTables(TheBuffer: Pointer; TheNumber: Word; TheFile: PChar); - destructor Destroy; override; -end; + RowArray: TYRows; + ProdArray: TYProds; + constructor Create; + destructor Destroy; override; + procedure FullTab; + end; -type SSYaccLexemeCache = class(TList) public + constructor Create; + function Dequeue: SSLexLexeme; + procedure Enqueue(TheLexeme: SSLexLexeme); + function Get(TheIndex: Longint): SSLexLexeme; + destructor Destroy; override; + end; - constructor Create; - function Dequeue: SSLexLexeme; - procedure Enqueue(TheLexeme: SSLexLexeme); - function Get(TheIndex: Longint): SSLexLexeme; - destructor Destroy; override; -end; - -type SSYacc = class(TBoldMemoryManagedObject) public - Lex : SSLex; - ErrorInd : Boolean; - AbortInd : Boolean; - EndOfInput : Boolean; - Cache : Longint; - State : Longint; - ShiftedSinceError: Longint; - Leftside : Longint; - Production : Longint; - ProductionSize : Longint; - Table : SSYaccTable; - Lookahead : SSLexLexeme; - LarLookahead : SSLexLexeme; - Stack : SSYaccStack; - EndLexeme : SSLexLexeme; - Action : SSYaccAction; - LexemeCache : SSYaccLexemeCache; - Element : SSYaccStackElement; - ExprList : SSLexExpressionList; - -{ constructor Create(TheTable: SSTable);} - constructor CreateLex(TheLexer: SSLex; TheTable: SSYaccTable); -{ procedure Reset;} - procedure SetEof; - procedure SyncErr; - function Parse: Boolean; - function DoShift: Boolean; - function DoReduce: Boolean; - function DoConflict: Boolean; - function DoLarError: Boolean; -{ procedure SetLex(TheLex: SSLex);} - procedure Pop(TheNumber: Longint); - procedure DoGoto(TheGoto: Longint); - function GetLexemeCache: SSLexLexeme; - procedure LookupGoto(TheGoto: Longint); - procedure LookupAction(TheToken: Longint); - function GetLexeme(Look: Boolean): Boolean; - function DoGetLexeme(Look: Boolean): Boolean; - procedure SetLookahead(TheLexeme: SSLexLexeme); - procedure SetLarLookahead(TheLexeme: SSLexLexeme); - procedure SetElement(TheElement: SSYaccStackElement); - function GetAction(PEntry: PSSYaccPairTableEntry): SSYaccAction; -{ function ElementFromStack(TheDepth: Longint): SSYaccStackElement;} - function ElementFromProduction(TheIndex: Longint): SSYaccStackElement; -{ function ValidLookaheads(TheState: Longint; var TheCount: Longint): PSSArrayOfLongint;} - - function NextLexeme: SSLexLexeme; virtual; - function Shift: SSYaccStackElement; virtual; - function StackElement: SSYaccStackElement; virtual; - function LarLook(TheLexeme: SSLexLexeme): Boolean; virtual; - function Error(TheState: Longint; TheLookahead: SSLexLexeme): Boolean; virtual; - function LarError(TheState: Longint; TheLookahead, TheLarLookahead: SSLexLexeme): Boolean; virtual; - function Reduce(TheProduction, TheProductionSize: Longint): SSYaccStackElement; virtual; - - destructor Destroy; override; -end; + Lex: SSLex; + ErrorInd: Boolean; + AbortInd: Boolean; + EndOfInput: Boolean; + Cache: Longint; + State: Longint; + ShiftedSinceError: Longint; + Leftside: Longint; + Production: Longint; + ProductionSize: Longint; + Table: SSYaccTable; + Lookahead: SSLexLexeme; + LarLookahead: SSLexLexeme; + Stack: SSYaccStack; + EndLexeme: SSLexLexeme; + Action: SSYaccAction; + LexemeCache: SSYaccLexemeCache; + Element: SSYaccStackElement; + ExprList: SSLexExpressionList; + constructor CreateLex(TheLexer: SSLex; TheTable: SSYaccTable); + procedure SetEof; + procedure SyncErr; + function Parse: Boolean; + function DoShift: Boolean; + function DoReduce: Boolean; + function DoConflict: Boolean; + function DoLarError: Boolean; + procedure Pop(TheNumber: Longint); + procedure DoGoto(TheGoto: Longint); + function GetLexemeCache: SSLexLexeme; + procedure LookupGoto(TheGoto: Longint); + procedure LookupAction(TheToken: Longint); + function GetLexeme(Look: Boolean): Boolean; + function DoGetLexeme(Look: Boolean): Boolean; + procedure SetLookahead(TheLexeme: SSLexLexeme); + procedure SetLarLookahead(TheLexeme: SSLexLexeme); + procedure SetElement(TheElement: SSYaccStackElement); + function GetAction(YEntry: TYEntry): SSYaccAction; + function ElementFromProduction(TheIndex: Longint): SSYaccStackElement; + function NextLexeme: SSLexLexeme; virtual; + function Shift: SSYaccStackElement; virtual; + function StackElement: SSYaccStackElement; virtual; + function LarLook(TheLexeme: SSLexLexeme): Boolean; virtual; + function Error(TheState: Longint; TheLookahead: SSLexLexeme): Boolean; virtual; + function LarError(TheState: Longint; TheLookahead, TheLarLookahead: SSLexLexeme): Boolean; virtual; + function Reduce(TheProduction, TheProductionSize: Longint): SSYaccStackElement; virtual; + destructor Destroy; override; + end; implementation uses - BoldSSExcept, - SysUtils, - BoldCoreConsts, - BoldUtils; + BoldSSExcept, SysUtils, AnsiStrings; -constructor SSYaccTable.Create(FileName: String); -var - i : Word; - FileStream: TFileStream; - BaseSize : Longint; - PLarTables : Pointer; - PRowOffsetArray: PSSYaccRowOffsetArray; +constructor SSYaccTable.Create; begin - SSAux; - - if not FileExists(FileName) then - raise Exception.CreateFmt(sFileDoesNotExist, [FileName]); - - FileStream := TFileStream.Create(FileName, fmOpenRead); - - Size := FileStream.Size; - - Getmem(PTable, FileStream.Size); - FileStream.Read(PTable^, Size); - FileStream.Free; - - if PTable^.TableType <> SSYaccPairTableId then - begin - FreeMem(Ptable, Size); - PTable := nil; - raise SSException.CreateName(SSExceptionYaccRead, SSYaccMsgRead, PChar(FileName)); - end; - - BaseSize := sizeof(SSYaccPairTable) + sizeof(SSYaccPairTableProd) * - Productions + sizeof(PSSYaccPairTableRow) * PTable^.States; - if BaseSize > SSYaccPairTableMaxSize then - begin - FreeMem(PTable, Size); - PTable := nil; - raise SSException.Create(SSExceptionYaccTableSize, SSYaccMsgTableSize); - end; - - PProdArray := PSSYaccProdArray(SSHugeInc(PTable, PTable^.ProdOffset)); - PPRowArray := PSSYaccRowArray(SSHugeInc(PTable, sizeof(SSYaccPairTable))); - PRowOffsetArray := PSSYaccRowOffsetArray(PPRowArray); - PLarTables := SSHugeInc(PTable, PTable^.RowOffset); - for i := 0 to PTable^.States - 1 do - begin - PPRowArray^[ i] := PSSYaccPairTableRow(SSHugeInc(PTable, PRowOffsetArray^[ i])); - PLarTables := SSHugeInc(PPRowArray^[ i], RowSize(PPRowArray^[ i])); - end; - - if (LarTables > 0) then - GetLarTables(PLarTables, LarTables, PChar(Filename)); -end; - -constructor SSYaccTable.CreateResource(TheInstance: THandle; TheName, TheType: PChar); -var - i : Word; - FindHandle : THandle; - LoadHandle : THandle; - Resource : Pointer; - BaseSize : Longint; - PLarTables : Pointer; - NewException : SSException; - PRowOffsetArray: PSSYaccRowOffsetArray; -begin - SSAux; - LoadHandle := 0; // to prevent compiler warning - Resource := nil; - FindHandle := FindResource(TheInstance, TheName, TheType); - if (FindHandle <> 0) then - begin - LoadHandle := LoadResource(TheInstance, FindHandle); - if (LoadHandle <> 0) then - Resource := LockResource(LoadHandle); - end; - if (Resource = nil) then - begin - NewException := SSException.CreateName(SSExceptionYaccFindResource, SSYaccMsgFindResource, TheType); - raise NewException; - end; - - Size := SizeOfResource(TheInstance, FindHandle); - GetMem(PTable, Size); - SSHugeCopy(PTable, Resource, Size); - FreeResource(LoadHandle); - - if PTable^.TableType <> SSYaccPairTableId then - begin - FreeMem(PTable, Size); - PTable := nil; - NewException := SSException.CreateName(SSExceptionYaccBadResource, SSYaccMsgBadResource, TheType); - raise NewException; - end; - - BaseSize := sizeof(SSYaccPairTable) + sizeof(SSYaccPairTableProd) * - Productions + sizeof(PSSYaccPairTableRow) * PTable^.States; - if BaseSize > SSYaccPairTableMaxSize then - begin - FreeMem(PTable, Size); - PTable := nil; - NewException := SSException.Create(SSExceptionYaccTableSize, SSYaccMsgTableSize); - raise NewException; - end; - - PProdArray := PSSYaccProdArray(SSHugeInc(PTable, PTable^.ProdOffset)); - PPRowArray := PSSYaccRowArray(SSHugeInc(PTable, sizeof(SSYaccPairTable))); - PRowOffsetArray := PSSYaccRowOffsetArray(PPRowArray); - PLarTables := SSHugeInc(PTable, PTable^.RowOffset); - for i := 0 to PTable^.States - 1 do - begin - PPRowArray^[ i] := PSSYaccPairTableRow(SSHugeInc(PTable, PRowOffsetArray^[ i])); - PLarTables := SSHugeInc(PPRowArray^[ i], RowSize(PPRowArray^[ i])); - end; - - if (LarTables > 0) then - GetLarTables(PLarTables, LarTables, TheType); -end; - -function SSYaccTable.RowSize(TheRow: PSSYaccPairTableRow): Longint; -var - Entries: Longint; -begin - Entries := TheRow^.Gotos + TheRow^.Actions; - if (TheRow^.Flags and SSYaccPairTableRowFlagsError) <> 0 then - Inc(Entries); - Result := SizeOf(SSYaccPairTableEntry) * Entries + SizeOf(SSYaccPairTableRow); -end; - -procedure SSYaccTable.GetLarTables(TheBuffer: Pointer; TheNumber: Word; TheFile: PChar); -var - i : Word; - Header : SSLexTableHeader; - ExprList: SSLexExpressionList; -begin - LarTableList := TList.Create; - for i := 0 to TheNumber - 1 do - begin - SSHugeCopy(@Header, TheBuffer, sizeof(Header)); - ExprList := SSLexExpressionList.CreateBuffer(TheBuffer, TheFile); - LarTableList.Insert(i, ExprList); - TheBuffer := SSHugeInc(TheBuffer, Header.Size); - end -end; - -function SSYaccTable.Productions: Longint; -begin - Result := PTable^.Prods and $0000ffff; -end; - -function SSYaccTable.LarTables: Longint; -begin - Result := PTable^.Prods shr 16; + FullTab; end; destructor SSYaccTable.Destroy; begin - if PTable <> nil then - FreeMem(Ptable, Size); - inherited; -end; - -constructor SSYaccStackElement.Create; -begin - inherited Create; - Lexeme := nil; - State := 0; - Use := 0; -end; - -procedure SSYaccStackElement.SetLexeme(TheLexeme: SSLexLexeme); -begin - if TheLexeme <> nil then - TheLexeme.RefInc; - if (Lexeme <> nil) and (Lexeme.RefDec) then - Lexeme.Free; - Lexeme := TheLexeme; -end; - -procedure SSYaccStackElement.RefInc; -begin - Inc(Use); -end; - -function SSYaccStackElement.RefDec: Boolean; -begin - Dec(Use); - Result := (Use = 0); -end; - -destructor SSYaccStackElement.Destroy; -begin - if (Lexeme <> nil) and (Lexeme.RefDec) then - Lexeme.Free; + RowArray := nil; + ProdArray := nil; inherited; end; function SSYaccStack.Top: SSYaccStackElement; begin - Result := inherited Top; + Result := inherited Top as SSYaccStackElement; end; procedure SSYaccStack.Push(TheElement: SSYaccStackElement); @@ -429,43 +176,20 @@ procedure SSYaccStack.Push(TheElement: SSYaccStackElement); destructor SSYaccStack.Destroy; var - i : Integer; + i: Integer; Element: SSYaccStackElement; begin for i := 0 to TopOfStack - 1 do - begin - Element := PArray^[ i]; + begin +{$WARN UNSAFE_CODE OFF} + Element := PArray^[i]; +{$WARN UNSAFE_CODE ON} if Element.RefDec then Element.Free; - end; - inherited Destroy; + end; + inherited; end; -{constructor SSYacc.Create(TheTable: SSYaccTable); -var - AnException: SSException; -begin - inherited Create; - EndLexeme := nil; - Stack := nil; - Lex := nil; - EndOfInput := False; - ErrorInd := False; - ShiftedSinceError := 0; - AbortInd := False; - if TheTable = nil then - begin - AnException := SSException.Create(SSExceptionYaccMissingTable, SSYaccMsgMissingTable); - raise AnException; - end; - Table := TheTable; - Stack := SSYaccStack.Create; - Element := StackElement; - Element.RefInc; - Stack.Push(Element); - LexemeCache := SSYaccLexemeCache.Create; -end; -} constructor SSYacc.CreateLex(TheLexer: SSLex; TheTable: SSYaccTable); var AnException: SSException; @@ -479,10 +203,10 @@ constructor SSYacc.CreateLex(TheLexer: SSLex; TheTable: SSYaccTable); ShiftedSinceError := 0; AbortInd := False; if TheTable = nil then - begin + begin AnException := SSException.Create(SSExceptionYaccMissingTable, SSYaccMsgMissingTable); raise AnException; - end; + end; Lex := TheLexer; Table := TheTable; Stack := SSYaccStack.Create; @@ -494,88 +218,81 @@ constructor SSYacc.CreateLex(TheLexer: SSLex; TheTable: SSYaccTable); procedure SSYacc.SetEof; var - EofString: PChar; + EofString: PAnsiChar; begin EndOfInput := True; - EofString := StrNew(SSYaccEofString); - EndLexeme := SSLexLexeme.Create(EofString, StrLen(EofString), 0, 0); + EofString := AnsiStrings.StrNew(PAnsiChar(SSYaccEofString)); + EndLexeme := SSLexLexeme.Create(EofString, AnsiStrings.StrLen(EofString), 0, 0); EndLexeme.Token := SSYaccEofToken; EndLexeme.RefInc; - StrDispose(EofString); + AnsiStrings.StrDispose(EofString); end; -{procedure SSYacc.SetLex(TheLex: SSLex); -begin - Lex := TheLex; -end; - } -procedure SSYacc.LookupAction(TheToken: Longint); +procedure SSYacc.LookupAction(TheToken: Integer); var - i : Integer; - PEntryArray: PSSYaccEntryArray; - PCurrentRow: PSSYaccPairTableRow; - PProd : PSSYaccPairTableProd; - PEntry : PSSYaccPairTableEntry; + i: Integer; + CurrentRow: TYRow; + YEntry: TYEntry; + Prod: TYProd; + EntryIndex: Integer; begin - PEntry := nil; - PCurrentRow := Table.PPRowArray^[ State]; - PEntryArray := PSSYaccEntryArray(PChar(PCurrentRow) + sizeof(SSYaccPairTableRow)); - for i := 0 to PCurrentRow^.Actions - 1 do - if PEntryArray^[ i].Token = TheToken then - begin - PEntry := @PEntryArray^[ i]; + EntryIndex := -1; + CurrentRow := Table.RowArray[State]; + for i := 0 to CurrentRow.Actions - 1 do + if CurrentRow.Entries[i].Token = TheToken then + begin + EntryIndex := i; + YEntry := CurrentRow.Entries[i]; Break; - end; + end; - if PEntry = nil then + if EntryIndex = -1 then Action := ErrorAction else - begin - Action := GetAction(PEntry); + begin + Action := GetAction(YEntry); case Action of ShiftAction: - State := PEntry^.Entry and SSYaccPairTableEntryMax; + State := YEntry.Entry and SSYaccPairTableEntryMax; ReduceAction: begin - Production := PEntry^.Entry and SSYaccPairTableEntryMax; - PProd := @Table.PProdArray^[ Production]; - Leftside := PProd^.Leftside; - ProductionSize := PProd^.Size; + Production := YEntry.Entry and SSYaccPairTableEntryMax; + Prod := Table.ProdArray[Production]; + Leftside := Prod.Leftside; + ProductionSize := Prod.Size; end; ConflictAction: begin - ExprList := Table.LarTableList.Items[ PEntry^.Entry and SSYaccPairTableEntryMax]; - end; + end; end; - end; + end; end; -function SSYacc.GetAction(PEntry: PSSYaccPairTableEntry): SSYaccAction; +function SSYacc.GetAction(YEntry: TYEntry): SSYaccAction; begin - if (PEntry^.Entry and SSYaccPairTableEntryShift) <> 0 then + if YEntry.Entry and SSYaccPairTableEntryShift <> 0 then Result := ShiftAction - else if (PEntry^.Entry and SSYaccPairTableEntryReduce) <> 0 then + else if YEntry.Entry and SSYaccPairTableEntryReduce <> 0 then Result := ReduceAction - else if (PEntry^.Entry and SSYaccPairTableEntryAccept) <> 0 then + else if YEntry.Entry and SSYaccPairTableEntryAccept <> 0 then Result := AcceptAction - else if (PEntry^.Entry and SSYaccPairTableEntryConflict) <> 0 then + else if YEntry.Entry and SSYaccPairTableEntryConflict <> 0 then Result := ConflictAction else Result := ErrorAction; end; -function SSYacc.LarError(TheState: Longint; TheLookahead, TheLarLookahead: SSLexLexeme): Boolean; +function SSYacc.LarError(TheState: Integer; TheLookahead, TheLarLookahead: SSLexLexeme): Boolean; begin Result := Error(TheState, TheLookahead); end; -function SSYacc.Reduce(TheProduction, TheProductionSize: Longint): SSYaccStackElement; +function SSYacc.Reduce(TheProduction, TheProductionSize: Integer): SSYaccStackElement; begin - result := nil; + Result := nil; end; - function SSYacc.LarLook(TheLexeme: SSLexLexeme): Boolean; begin Result := False; @@ -585,40 +302,39 @@ function SSYacc.DoLarError: Boolean; begin ErrorInd := True; Result := LarError(State, Lookahead, LarLookahead); - if (Result = False) then + if not Result then ShiftedSinceError := 0; end; -procedure SSYacc.LookupGoto(TheGoto: Longint); +procedure SSYacc.LookupGoto(TheGoto: Integer); var - i : Integer; - EndIndex : Longint; + i, EndIndex: Integer; AnException: SSException; - PEntryArray: PSSYaccEntryArray; - PCurrentRow: PSSYaccPairTableRow; - PEntry : PSSYaccPairTableEntry; + CurrentRow: TYRow; + YEntry: TYEntry; + EntryIndex: Integer; begin - PEntry := nil; - PCurrentRow := Table.PPRowArray^[ State]; - EndIndex := PCurrentRow^.Actions + PCurrentRow^.Gotos - 1; - PEntryArray := PSSYaccEntryArray(PChar(PCurrentRow) + sizeof(SSYaccPairTableRow)); - for i := PCurrentRow^.Actions to EndIndex do - if PEntryArray^[ i].Token = TheGoto then - begin - PEntry := @PEntryArray^[ i]; + EntryIndex := -1; + CurrentRow := Table.RowArray[State]; + EndIndex := CurrentRow.Actions + CurrentRow.Gotos - 1; + for i := CurrentRow.Actions to EndIndex do + if CurrentRow.Entries[i].Token = TheGoto then + begin + EntryIndex := i; + YEntry := CurrentRow.Entries[i]; Break; - end; + end; - if PEntry = nil then - begin + if EntryIndex = -1 then + begin AnException := SSException.Create(SSExceptionYaccParse, SSYaccMsgParse); raise AnException; - end; + end; - State := PEntry^.Entry and SSYaccPairTableEntryMax; + State := YEntry.Entry and SSYaccPairTableEntryMax; end; -procedure SSYacc.DoGoto(TheGoto: Longint); +procedure SSYacc.DoGoto(TheGoto: Integer); begin LookupGoto(Leftside); Element.State := State; @@ -631,10 +347,10 @@ function SSYacc.NextLexeme: SSLexLexeme; AnException: SSException; begin if Lex = nil then - begin + begin AnException := SSException.Create(SSExceptionYaccMissingLexer, SSYaccMsgMissingLexer); raise AnException; - end; + end; Result := Lex.Next; end; @@ -646,58 +362,61 @@ function SSYacc.StackElement: SSYaccStackElement; function SSYacc.Parse: Boolean; var AnException: SSException; -// AnElement : SSYaccStackElement; begin Result := DoGetLexeme(True); - if Result = True then Exit; + if Result = True then + Exit; while True do - begin + begin if AbortInd = True then Break; case Action of ShiftAction: begin - Result := DoShift; - if (Result = True) then Break; + Result := DoShift; + if Result = True then + Break; end; ReduceAction: begin - Result := DoReduce; - if (Result = True) then Break; + Result := DoReduce; + if Result = True then + Break; end; ErrorAction: begin - ErrorInd := True; - if Error(State, Lookahead) then + ErrorInd := True; + if Error(State, Lookahead) then begin - Result := True; - Break; + Result := True; + Break; end; - ShiftedSinceError := 0; + ShiftedSinceError := 0; end; ConflictAction: begin - Result := DoConflict; - if (Result = True) then Break; + Result := DoConflict; + if Result = True then + Break; end; AcceptAction: begin - Result := ErrorInd; - Break; + Result := ErrorInd; + Break; end; - else - begin + else + begin AnException := SSException.Create(SSExceptionYaccParse, SSYaccMsgParse); raise AnException; - end; end; end; + end; end; function SSYacc.DoShift: Boolean; @@ -706,14 +425,14 @@ function SSYacc.DoShift: Boolean; if Element = nil then Result := True else - begin + begin Element.SetLexeme(Lookahead); Element.State := State; Stack.Push(Element); Result := DoGetLexeme(True); - if Result = False then + if not Result then Inc(ShiftedSinceError); - end; + end; end; function SSYacc.DoReduce: Boolean; @@ -726,79 +445,80 @@ function SSYacc.DoReduce: Boolean; if Element = nil then Result := True else - begin + begin Pop(ProductionSize); DoGoto(Leftside); - end; + end; end; function SSYacc.GetLexemeCache: SSLexLexeme; begin Result := nil; - if (Cache <> MaxLongInt) then - begin + if Cache <> MaxLongint then + begin Result := LexemeCache.Get(Cache); Inc(Cache); - end; - if (Result = nil) then - begin - Cache := MaxLongInt; + end; + if Result = nil then + begin + Cache := MaxLongint; Result := NextLexeme; - if (Result = nil) then - begin + if Result = nil then + begin SetEof; Result := EndLexeme; - end; end; + end; LexemeCache.Enqueue(Result); end; function SSYacc.DoConflict: Boolean; var - LarState : Longint; - PFinal : PSSLexFinalState; - PProd : PSSYaccPairTableProd; + LarState: Longint; + PFinal: TRow; + Prod: TYProd; begin Cache := 0; LarState := ExprList.LookupState(Lookahead.Token, 0); SetLarLookahead(GetLexemeCache); - while (LarLookahead <> nil) do - begin + while LarLookahead <> nil do + begin LarState := ExprList.LookupState(LarLookahead.Token, LarState); - if (State = SSLexStateInvalid) then Break; - PFinal := ExprList.LookupFinal(LarState); - if (PFinal^.Flags and SSLexFinalStateFlagsFinal) <> 0 then + if State = SSLexStateInvalid then + Break; + PFinal := ExprList.ARows[LarState]; + if PFinal.Flags and SSLexFinalStateFlagsFinal <> 0 then + begin + if PFinal.Flags and SSLexFinalStateFlagsReduce <> 0 then begin - if (PFinal^.Flags and SSLexFinalStateFlagsReduce) <> 0 then - begin - Production := PFinal^.Token; - PProd := @Table.PProdArray^[ Production]; - Leftside := PProd^.Leftside; - ProductionSize := PProd^.Size; + Production := PFinal.Token; + Prod := Table.ProdArray[Production]; + Leftside := Prod.Leftside; + ProductionSize := Prod.Size; Result := DoReduce; Exit; - end + end else - begin - State := PFinal^.Token; + begin + State := PFinal.Token; Result := DoShift; Exit; - end; end; - SetLarLookahead(GetLexemeCache); end; + SetLarLookahead(GetLexemeCache); + end; Result := DoLarError; end; function SSYacc.DoGetLexeme(Look: Boolean): Boolean; begin SetLookahead(LexemeCache.Dequeue); - if (Lookahead <> nil) then - begin + if Lookahead <> nil then + begin Result := LarLook(Lookahead); - if ((Result = False) and (Look = True)) then + if (Result = False) and (Look = True) then LookupAction(Lookahead.Token); - end + end else Result := GetLexeme(Look); end; @@ -808,19 +528,19 @@ function SSYacc.GetLexeme(Look: Boolean): Boolean; AnException: SSException; begin if EndOfInput = True then - begin + begin AnException := SSException.Create(SSExceptionYaccEof, SSYaccMsgEof); raise AnException; - end; + end; SetLookahead(NextLexeme); if Lookahead = nil then - begin + begin SetEof; SetLookahead(EndLexeme); - end; + end; - if (Look) then + if Look then LookupAction(Lookahead.Token); Result := False; end; @@ -857,23 +577,23 @@ function SSYacc.Shift: SSYaccStackElement; Result := StackElement; end; -procedure SSYacc.Pop(TheNumber: Longint); +procedure SSYacc.Pop(TheNumber: Integer); var - i : Integer; + i: Integer; TopElement: SSYaccStackElement; begin for i := 0 to TheNumber - 1 do - begin + begin TopElement := Stack.Top; Stack.Pop; if (TopElement <> nil) and TopElement.RefDec then TopElement.Free; - end; + end; TopElement := Stack.Top; State := TopElement.State; end; -function SSYacc.Error(TheState: Longint; TheLookahead: SSLexLexeme): Boolean; +function SSYacc.Error(TheState: Integer; TheLookahead: SSLexLexeme): Boolean; begin SyncErr; Result := False; @@ -881,236 +601,191 @@ function SSYacc.Error(TheState: Longint; TheLookahead: SSLexLexeme): Boolean; procedure SSYacc.SyncErr; var - ErrorString: PChar; - i, j : Integer; + ErrorString: PAnsiChar; + i, j: Integer; AnException: SSException; ErrorLexeme: SSLexLexeme; - SetOfToken : SSSetOfLongint; - PEntryArray: PSSYaccEntryArray; - AnElement : SSYaccStackElement; - PRow : PSSYaccPairTableRow; - PErrorRow : PSSYaccPairTableRow; - PEntry : PSSYaccPairTableEntry; - TempCardinal1, TempCardinal2, TempCardinal3, TempCardinal4: Cardinal; // used to avoid warning from DelphiParser + SetOfToken: SSSetOfLongint; + AnElement: SSYaccStackElement; + Row, ErrorRow: TYRow; + YEntry: TYEntry; + TempCardinal1, TempCardinal2, TempCardinal3, TempCardinal4: Cardinal; begin SetOfToken := SSSetOfLongint.Create(16, 16); for i := 0 to Stack.TopOfStack - 1 do - begin - AnElement := Stack.PArray^[ i]; - PRow := Table.PPRowArray^[ AnElement.State]; - PEntryArray := PSSYaccEntryArray(PChar(PRow) + sizeof(SSYaccPairTableRow)); - if (PRow^.Flags and SSYaccPairTableRowFlagsSyncPossible) <> 0 then - for j := 0 to PRow^.Actions - 1 do - begin - PEntry := @PEntryArray^[ j]; - TempCardinal1 := PRow^.Flags; + begin + AnElement := Stack.PArray[i]; + Row := Table.RowArray[AnElement.State]; + if Row.Flags and SSYaccPairTableRowFlagsSyncPossible <> 0 then + for j := 0 to Row.Actions - 1 do + begin + YEntry := Row.Entries[j]; + TempCardinal1 := Row.Flags; TempCardinal2 := SSYaccPairTableRowFlagsSyncAll; - tempCardinal3 := PEntry^.Entry; - tempCardinal4 := SSYaccPairTableEntrySync; + TempCardinal3 := YEntry.Entry; + TempCardinal4 := SSYaccPairTableEntrySync; - if ((TempCardinal1 and TempCardinal2) or - (TempCardinal3 and TempCardinal4)) <> 0 then - SetOfToken.Insert(PEntry^.Token); - end; - if (PRow^.Flags and SSYaccPairTableRowFlagsError) <> 0 then - begin - PEntry := @PEntryArray^[ PRow^.Actions + PRow^.Gotos]; - PErrorRow := Table.PPRowArray^[ PEntry^.Entry and SSYaccPairTableEntryMax]; - PEntryArray := PSSYaccEntryArray(PChar(PErrorRow) + sizeof(SSYaccPairTableRow)); - for j := 0 to PRow^.Actions - 1 do - SetOfToken.Insert(PEntryArray^[ j].Token); - end + if (TempCardinal1 and TempCardinal2) or (TempCardinal3 and TempCardinal4) <> 0 then + SetOfToken.Insert(YEntry.Token); + end; + if Row.Flags and SSYaccPairTableRowFlagsError <> 0 then + begin + YEntry := Row.Entries[Row.Actions + Row.Gotos]; + ErrorRow := Table.RowArray[YEntry.Entry and SSYaccPairTableEntryMax]; + for j := 0 to Row.Actions - 1 do + SetOfToken.Insert(ErrorRow.Entries[j].Token); end; + end; if SetOfToken.Count = 0 then - begin + begin SetOfToken.Free; AnException := SSException.Create(SSExceptionYaccSyncErrToken, SSYaccMsgSyncErrToken); raise AnException; - end; + end; while True do - begin + begin if SetOfToken.Contains(Lookahead.Token) then Break; -// SetLookahead(NextLexeme); -// if Lookahead = nil then - if (DoGetLexeme(False)) then - begin + + if DoGetLexeme(False) then + begin SetOfToken.Free; AnException := SSException.Create(SSExceptionYaccSyncErrEof, SSYaccMsgSyncErrEof); raise AnException; - end; end; + end; SetOfToken.Free; while True do + begin + Row := Table.RowArray[State]; + if Row.Flags and SSYaccPairTableRowFlagsError <> 0 then begin - PRow := Table.PPRowArray^[ State]; - if (PRow^.Flags and SSYaccPairTableRowFlagsError) <> 0 then - begin - PEntryArray := PSSYaccEntryArray(PChar(PRow) + sizeof(SSYaccPairTableRow)); - PEntry := @PEntryArray^[ PRow^.Actions + PRow^.Gotos]; - State := PEntry^.Entry and SSYaccPairTableEntryMax; + YEntry := Row.Entries[Row.Actions + Row.Gotos]; + State := YEntry.Entry and SSYaccPairTableEntryMax; LookupAction(Lookahead.Token); if Action <> ErrorAction then - begin - ErrorString := StrNew(SSYaccErrorString); - ErrorLexeme := SSLexLexeme.Create(ErrorString, StrLen(ErrorString), 0, 0); + begin + ErrorString := AnsiStrings.StrNew(PAnsiChar(SSYaccErrorString)); + ErrorLexeme := SSLexLexeme.Create(ErrorString, AnsiStrings.StrLen(ErrorString), 0, 0); ErrorLexeme.Token := SSYaccErrorToken; - StrDispose(ErrorString); + AnsiStrings.StrDispose(ErrorString); SetElement(StackElement); Element.Lexeme := ErrorLexeme; Element.State := State; Stack.Push(Element); Break; - end end; - if (PRow^.Flags and SSYaccPairTableRowFlagsSyncPossible) <> 0 then - begin + end; + if Row.Flags and SSYaccPairTableRowFlagsSyncPossible <> 0 then + begin LookupAction(Lookahead.Token); if Action <> ErrorAction then Break; - end; + end; Pop(1); - end + end; end; -{function SSYacc.ElementFromStack(TheDepth: Longint): SSYaccStackElement; -var - AnException: SSException; -begin - if TheDepth > Stack.TopOfStack then - begin - AnException := SSException.Create(SSExceptionYaccElement, SSYaccMsgElement); - raise AnException; - end; - - Result := Stack.PArray^[ TheDepth]; -end; -} function SSYacc.ElementFromProduction(TheIndex: Longint): SSYaccStackElement; var AnException: SSException; begin TheIndex := Stack.TopOfStack - ProductionSize + TheIndex; if (TheIndex < 0) or (TheIndex >= Stack.TopOfStack) then - begin + begin AnException := SSException.Create(SSExceptionYaccElement, SSYaccMsgElement); raise AnException; - end; + end; - Result := Stack.PArray^[ TheIndex]; + Result := Stack.PArray[TheIndex]; end; -{procedure SSYacc.Reset; -begin - State := 0; - ShiftedSinceError := 0; - if (EndLexeme <> nil) and EndLexeme.RefDec then - EndLexeme.Free; - ErrorInd := False; - AbortInd := False; - EndOfInput := False; - Stack.Free; - Stack := SSYaccStack.Create; - SetElement(StackElement); - Stack.Push(Element); -end; - } destructor SSYacc.Destroy; begin - if (LarLookahead <> nil) and (LarLookahead.RefDec) then + if (LarLookahead <> nil) and LarLookahead.RefDec then LarLookahead.Free; - if (EndLexeme <> nil) and (EndLexeme.RefDec) then + if (EndLexeme <> nil) and EndLexeme.RefDec then EndLexeme.Free; Stack.Free; - if (Lookahead <> nil) and (Lookahead.RefDec) then - Lookahead.Free; - if (Element <> nil) and (Element.RefDec) then - Element.Free; + if (Lookahead <> nil) and Lookahead.RefDec then + Lookahead.Free; + if (Element <> nil) and Element.RefDec then + Element.Free; LexemeCache.Free; inherited; end; -constructor SSSetOfLongint.Create(TheSize, TheInc: Longint); +constructor SSSetOfLongint.Create(TheSize, TheInc: Integer); begin inherited Create; Size := TheSize; Incr := TheInc; Count := 0; - GetMem(PArray, Size * sizeof(Longint)); +{$WARN UNSAFE_CODE OFF} + GetMem(PArray, Size * SizeOf(Longint)); +{$WARN UNSAFE_CODE ON} end; -function SSSetOfLongint.Insert(TheItem: Longint): Boolean; +function SSSetOfLongint.Insert(TheItem: Integer): Boolean; var - i : Integer; - NewSize : Longint; + i: Integer; + NewSize: Longint; PNewArray: PSSArrayOfLongint; begin Result := True; for i := 0 to Count - 1 do - if PArray^[ i] = TheItem then - begin + if PArray[i] = TheItem then + begin Result := False; Break; - end; + end; if Result = True then - begin + begin if Count >= Size then - begin + begin NewSize := Size + Incr; - GetMem(PNewArray, NewSize * sizeof(Longint)); +{$WARN UNSAFE_CODE OFF} + GetMem(PNewArray, NewSize * SizeOf(Longint)); +{$WARN UNSAFE_CODE ON} for i := 0 to Count - 1 do - PNewArray^[ i] := PArray^[ i]; - FreeMem(PArray, Size * sizeof(Longint)); + PNewArray[i] := PArray[i]; +{$WARN UNSAFE_CODE OFF} + FreeMem(PArray, Size * SizeOf(Longint)); +{$WARN UNSAFE_CODE ON} Size := NewSize; PArray := PNewArray; - end; - PArray^[ Count] := TheItem; + end; + PArray[Count] := TheItem; Inc(Count); - end + end; end; -function SSSetOfLongint.Contains(TheItem: Longint): Boolean; +function SSSetOfLongint.Contains(TheItem: Integer): Boolean; var - i : Integer; + i: Integer; begin Result := False; for i := 0 to Count - 1 do - if PArray^[ i] = TheItem then - begin + if PArray[i] = TheItem then + begin Result := True; Break; - end; + end; end; destructor SSSetOfLongint.Destroy; begin - FreeMem(PArray, Size * sizeof(Longint)); +{$WARN UNSAFE_CODE OFF} + FreeMem(PArray, Size * SizeOf(Longint)); +{$WARN UNSAFE_CODE ON} inherited Destroy; end; -{function SSYacc.ValidLookaheads(TheState: Longint; var TheCount: Longint): PSSArrayOfLongint; -var - i : Integer; - PEntryArray: PSSYaccEntryArray; - PRow : PSSYaccPairTableRow; - PEntry : PSSYaccPairTableEntry; -begin - PRow := Table.PPRowArray^[ TheState]; - GetMem(Result, PRow^.Actions * sizeof(Longint)); - PEntryArray := PSSYaccEntryArray(PChar(PRow) + sizeof(SSYaccPairTableRow)); - TheCount := PRow^.Actions; - for i := 0 to TheCount - 1 do - begin - PEntry := @PEntryArray^[ i]; - Result^[ i] := PEntry^.Token; - end; -end; - } constructor SSYaccLexemeCache.Create; begin inherited Create; @@ -1118,34 +793,3086 @@ constructor SSYaccLexemeCache.Create; function SSYaccLexemeCache.Dequeue: SSLexLexeme; begin - if (Count = 0) then + if Count = 0 then Result := nil else - begin - // Result := List^[ 0]; // marco + begin +{$WARN UNSAFE_CAST OFF} + Result := SSLexLexeme(List[0]); +{$WARN UNSAFE_CAST ON} Result.RefDec; Delete(0); Pack; - end; + end; end; procedure SSYaccLexemeCache.Enqueue(TheLexeme: SSLexLexeme); begin - Add(TheLexeme); +{$WARN UNSAFE_CAST OFF} + Add(Pointer(TheLexeme)); +{$WARN UNSAFE_CAST ON} TheLexeme.RefInc; end; -function SSYaccLexemeCache.Get(TheIndex: Longint): SSLexLexeme; +function SSYaccLexemeCache.Get(TheIndex: Integer): SSLexLexeme; begin - if ((Count = 0) or (TheIndex = MaxLongInt)) then + if (Count = 0) or (TheIndex = MaxLongint) then Result := nil else - Result := Items[ TheIndex]; +{$WARN UNSAFE_CAST OFF} + Result := SSLexLexeme(Items[TheIndex]); +{$WARN UNSAFE_CAST ON} end; -destructor SSYaccLexemeCache.Destroy; +destructor SSYaccLexemeCache.Destroy; begin inherited Destroy; end; + +procedure SSYaccTable.FullTab; +var + YaccProds: TYProds; + YaccRows: TYRows; + Row: TYRow; + N: Integer; + + procedure YP(S, L: Word); + begin + with YaccProds[N] do + begin + Size := S; + Leftside := L; + end; + Inc(N); + end; + + procedure R(F, G, A: Byte); + begin + with Row do + begin + Flags := F; + Gotos := G; + Actions := A; + SetLength(Entries, G + A); + N := 0; + end; + end; + + procedure RE(E, T: Longint); + begin + with Row.Entries[N] do + begin + Entry := E; + Token := T; + end; + Inc(N); + end; + +begin + + {$REGION 'Full YaccTable'} + + // === YaccProds === + + SetLength(YaccProds, 73); + N := 0; + YP(2, 0); + YP(1, 16386); + YP(1, 16385); + YP(3, 16385); + YP(3, 16385); + YP(3, 16385); + YP(3, 16385); + YP(3, 16385); + YP(3, 16385); + YP(3, 16385); + YP(3, 16385); + YP(3, 16385); + YP(3, 16385); + YP(3, 16385); + YP(3, 16385); + YP(3, 16385); + YP(3, 16385); + YP(3, 16385); + YP(3, 16385); + YP(2, 16385); + YP(2, 16385); + YP(7, 16388); + YP(1, 16387); + YP(5, 16387); + YP(6, 16387); + YP(5, 16387); + YP(6, 16387); + YP(1, 16389); + YP(1, 16389); + YP(3, 16389); + YP(1, 16389); + YP(3, 16389); + YP(4, 16389); + YP(3, 16393); + YP(5, 16393); + YP(7, 16393); + YP(3, 16395); + YP(2, 16395); + YP(1, 16395); + YP(1, 16395); + YP(1, 16395); + YP(1, 16395); + YP(2, 16395); + YP(0, 16397); + YP(1, 16397); + YP(1, 16397); + YP(4, 16394); + YP(1, 16402); + YP(1, 16403); + YP(3, 16403); + YP(3, 16402); + YP(4, 16400); + YP(2, 16404); + YP(4, 16404); + YP(0, 16392); + YP(3, 16392); + YP(1, 16399); + YP(1, 16405); + YP(3, 16405); + YP(1, 16390); + YP(3, 16390); + YP(1, 16398); + YP(1, 16398); + YP(2, 16391); + YP(0, 16391); + YP(0, 16396); + YP(1, 16396); + YP(1, 16406); + YP(3, 16406); + YP(1, 16401); + YP(1, 16401); + YP(1, 16401); + YP(1, 16401); + + // === YaccRows === + + SetLength(YaccRows, 134); + // [0] + R(0, 10, 16); + RE(1073741825, 47); + RE(1073741826, 42); + RE(1073741827, 41); + RE(1073741828, 40); + RE(1073741829, 39); + RE(1073741830, 34); + RE(1073741831, 29); + RE(1073741832, 22); + RE(1073741833, 11); + RE(1073741834, 8); + RE(1073741835, 7); + RE(1073741836, 6); + RE(1073741837, 5); + RE(1073741838, 4); + RE(1073741839, 3); + RE(1073741840, 2); + RE(17, 16401); + RE(18, 16398); + RE(19, 16395); + RE(20, 16394); + RE(21, 16390); + RE(22, 16389); + RE(23, 16388); + RE(24, 16387); + RE(25, 16385); + RE(26, 16386); + YaccRows[0] := Row; + // [1] + R(0, 9, 16); + RE(1073741825, 47); + RE(1073741826, 42); + RE(1073741827, 41); + RE(1073741828, 40); + RE(1073741829, 39); + RE(1073741830, 34); + RE(1073741831, 29); + RE(1073741832, 22); + RE(1073741833, 11); + RE(1073741834, 8); + RE(1073741835, 7); + RE(1073741836, 6); + RE(1073741837, 5); + RE(1073741838, 4); + RE(1073741839, 3); + RE(1073741840, 2); + RE(17, 16401); + RE(18, 16398); + RE(19, 16395); + RE(20, 16394); + RE(21, 16390); + RE(22, 16389); + RE(23, 16388); + RE(24, 16387); + RE(133, 16385); + YaccRows[1] := Row; + // [2] + R(0, 0, 1); + RE(536870984, 13); + YaccRows[2] := Row; + // [3] + R(0, 0, 1); + RE(536870983, 13); + YaccRows[3] := Row; + // [4] + R(0, 0, 1); + RE(536870981, 13); + YaccRows[4] := Row; + // [5] + R(0, 0, 1); + RE(536870982, 13); + YaccRows[5] := Row; + // [6] + R(0, 1, 2); + RE(1073741837, 5); + RE(1073741838, 4); + RE(132, 16398); + YaccRows[6] := Row; + // [7] + R(0, 9, 16); + RE(1073741825, 47); + RE(1073741826, 42); + RE(1073741827, 41); + RE(1073741828, 40); + RE(1073741829, 39); + RE(1073741830, 34); + RE(1073741831, 29); + RE(1073741832, 22); + RE(1073741833, 11); + RE(1073741834, 8); + RE(1073741835, 7); + RE(1073741836, 6); + RE(1073741837, 5); + RE(1073741838, 4); + RE(1073741839, 3); + RE(1073741840, 2); + RE(17, 16401); + RE(18, 16398); + RE(19, 16395); + RE(20, 16394); + RE(21, 16390); + RE(22, 16389); + RE(23, 16388); + RE(24, 16387); + RE(126, 16385); + YaccRows[7] := Row; + // [8] + R(0, 9, 16); + RE(1073741825, 47); + RE(1073741826, 42); + RE(1073741827, 41); + RE(1073741828, 40); + RE(1073741829, 39); + RE(1073741830, 34); + RE(1073741831, 29); + RE(1073741832, 22); + RE(1073741833, 11); + RE(1073741834, 8); + RE(1073741835, 7); + RE(1073741836, 6); + RE(1073741837, 5); + RE(1073741838, 4); + RE(1073741839, 3); + RE(1073741840, 2); + RE(17, 16401); + RE(18, 16398); + RE(19, 16395); + RE(20, 16394); + RE(21, 16390); + RE(22, 16389); + RE(23, 16388); + RE(24, 16387); + RE(125, 16385); + YaccRows[8] := Row; + // [9] + R(0, 9, 16); + RE(1073741825, 47); + RE(1073741826, 42); + RE(1073741827, 41); + RE(1073741828, 40); + RE(1073741829, 39); + RE(1073741830, 34); + RE(1073741831, 29); + RE(1073741832, 22); + RE(1073741833, 11); + RE(1073741834, 8); + RE(1073741835, 7); + RE(1073741836, 6); + RE(1073741837, 5); + RE(1073741838, 4); + RE(1073741839, 3); + RE(1073741840, 2); + RE(17, 16401); + RE(18, 16398); + RE(19, 16395); + RE(20, 16394); + RE(21, 16390); + RE(22, 16389); + RE(23, 16388); + RE(24, 16387); + RE(123, 16385); + YaccRows[9] := Row; + // [10] + R(0, 0, 2); + RE(1073741944, 51); + RE(1073741945, 50); + YaccRows[10] := Row; + // [11] + R(0, 0, 27); + RE(536870953, 10); + RE(536870953, 12); + RE(536870953, 14); + RE(536870953, 15); + RE(536870953, 16); + RE(536870953, 17); + RE(536870953, 18); + RE(536870953, 19); + RE(536870953, 20); + RE(536870953, 21); + RE(536870953, 22); + RE(536870953, 23); + RE(536870953, 24); + RE(536870953, 25); + RE(536870953, 26); + RE(536870953, 27); + RE(536870953, 30); + RE(536870953, 31); + RE(536870953, 32); + RE(536870953, 37); + RE(536870953, 43); + RE(536870953, 44); + RE(536870953, 45); + RE(536870953, 46); + RE(536870953, 48); + RE(536870953, 49); + RE(536870953, -1); + YaccRows[11] := Row; + // [12] + R(0, 0, 27); + RE(536870952, 10); + RE(536870952, 12); + RE(536870952, 14); + RE(536870952, 15); + RE(536870952, 16); + RE(536870952, 17); + RE(536870952, 18); + RE(536870952, 19); + RE(536870952, 20); + RE(536870952, 21); + RE(536870952, 22); + RE(536870952, 23); + RE(536870952, 24); + RE(536870952, 25); + RE(536870952, 26); + RE(536870952, 27); + RE(536870952, 30); + RE(536870952, 31); + RE(536870952, 32); + RE(536870952, 37); + RE(536870952, 43); + RE(536870952, 44); + RE(536870952, 45); + RE(536870952, 46); + RE(536870952, 48); + RE(536870952, 49); + RE(536870952, -1); + YaccRows[12] := Row; + // [13] + R(0, 0, 31); + RE(536870973, 9); + RE(536870973, 10); + RE(536870973, 11); + RE(536870973, 12); + RE(536870973, 14); + RE(536870973, 15); + RE(536870973, 16); + RE(536870973, 17); + RE(536870973, 18); + RE(536870973, 19); + RE(536870973, 20); + RE(536870973, 21); + RE(536870973, 22); + RE(536870973, 23); + RE(536870973, 24); + RE(536870973, 25); + RE(536870973, 26); + RE(536870973, 27); + RE(536870973, 28); + RE(536870973, 30); + RE(536870973, 31); + RE(536870973, 32); + RE(536870973, 36); + RE(536870973, 37); + RE(536870973, 43); + RE(536870973, 44); + RE(536870973, 45); + RE(536870973, 46); + RE(536870973, 48); + RE(536870973, 49); + RE(536870973, -1); + YaccRows[13] := Row; + // [14] + R(0, 0, 31); + RE(536870974, 9); + RE(536870974, 10); + RE(536870974, 11); + RE(536870974, 12); + RE(536870974, 14); + RE(536870974, 15); + RE(536870974, 16); + RE(536870974, 17); + RE(536870974, 18); + RE(536870974, 19); + RE(536870974, 20); + RE(536870974, 21); + RE(536870974, 22); + RE(536870974, 23); + RE(536870974, 24); + RE(536870974, 25); + RE(536870974, 26); + RE(536870974, 27); + RE(536870974, 28); + RE(536870974, 30); + RE(536870974, 31); + RE(536870974, 32); + RE(536870974, 36); + RE(536870974, 37); + RE(536870974, 43); + RE(536870974, 44); + RE(536870974, 45); + RE(536870974, 46); + RE(536870974, 48); + RE(536870974, 49); + RE(536870974, -1); + YaccRows[14] := Row; + // [15] + R(0, 0, 27); + RE(536870951, 10); + RE(536870951, 12); + RE(536870951, 14); + RE(536870951, 15); + RE(536870951, 16); + RE(536870951, 17); + RE(536870951, 18); + RE(536870951, 19); + RE(536870951, 20); + RE(536870951, 21); + RE(536870951, 22); + RE(536870951, 23); + RE(536870951, 24); + RE(536870951, 25); + RE(536870951, 26); + RE(536870951, 27); + RE(536870951, 30); + RE(536870951, 31); + RE(536870951, 32); + RE(536870951, 37); + RE(536870951, 43); + RE(536870951, 44); + RE(536870951, 45); + RE(536870951, 46); + RE(536870951, 48); + RE(536870951, 49); + RE(536870951, -1); + YaccRows[15] := Row; + // [16] + R(0, 0, 27); + RE(536870950, 10); + RE(536870950, 12); + RE(536870950, 14); + RE(536870950, 15); + RE(536870950, 16); + RE(536870950, 17); + RE(536870950, 18); + RE(536870950, 19); + RE(536870950, 20); + RE(536870950, 21); + RE(536870950, 22); + RE(536870950, 23); + RE(536870950, 24); + RE(536870950, 25); + RE(536870950, 26); + RE(536870950, 27); + RE(536870950, 30); + RE(536870950, 31); + RE(536870950, 32); + RE(536870950, 37); + RE(536870950, 43); + RE(536870950, 44); + RE(536870950, 45); + RE(536870950, 46); + RE(536870950, 48); + RE(536870950, 49); + RE(536870950, -1); + YaccRows[16] := Row; + // [17] + R(0, 0, 1); + RE(1073741934, 13); + YaccRows[17] := Row; + // [18] + R(0, 0, 31); + RE(536870971, 9); + RE(536870971, 10); + RE(536870971, 11); + RE(536870971, 12); + RE(536870971, 14); + RE(536870971, 15); + RE(536870971, 16); + RE(536870971, 17); + RE(536870971, 18); + RE(536870971, 19); + RE(536870971, 20); + RE(536870971, 21); + RE(536870971, 22); + RE(536870971, 23); + RE(536870971, 24); + RE(536870971, 25); + RE(536870971, 26); + RE(536870971, 27); + RE(536870971, 28); + RE(536870971, 30); + RE(536870971, 31); + RE(536870971, 32); + RE(536870971, 37); + RE(536870971, 43); + RE(536870971, 44); + RE(536870971, 45); + RE(536870971, 46); + RE(536870971, 48); + RE(536870971, 49); + RE(536870971, -1); + RE(1073741932, 36); + YaccRows[18] := Row; + // [19] + R(0, 0, 27); + RE(536870940, 10); + RE(536870940, 12); + RE(536870940, 14); + RE(536870940, 15); + RE(536870940, 16); + RE(536870940, 17); + RE(536870940, 18); + RE(536870940, 19); + RE(536870940, 20); + RE(536870940, 21); + RE(536870940, 22); + RE(536870940, 23); + RE(536870940, 24); + RE(536870940, 25); + RE(536870940, 26); + RE(536870940, 27); + RE(536870940, 30); + RE(536870940, 31); + RE(536870940, 32); + RE(536870940, 37); + RE(536870940, 43); + RE(536870940, 44); + RE(536870940, 45); + RE(536870940, 46); + RE(536870940, 48); + RE(536870940, 49); + RE(536870940, -1); + YaccRows[19] := Row; + // [20] + R(0, 0, 27); + RE(536870939, 10); + RE(536870939, 12); + RE(536870939, 14); + RE(536870939, 15); + RE(536870939, 16); + RE(536870939, 17); + RE(536870939, 18); + RE(536870939, 19); + RE(536870939, 20); + RE(536870939, 21); + RE(536870939, 22); + RE(536870939, 23); + RE(536870939, 24); + RE(536870939, 25); + RE(536870939, 26); + RE(536870939, 27); + RE(536870939, 30); + RE(536870939, 31); + RE(536870939, 32); + RE(536870939, 37); + RE(536870939, 43); + RE(536870939, 44); + RE(536870939, 45); + RE(536870939, 46); + RE(536870939, 48); + RE(536870939, 49); + RE(536870939, -1); + YaccRows[20] := Row; + // [21] + R(0, 1, 30); + RE(536870976, 9); + RE(536870976, 10); + RE(536870976, 11); + RE(536870976, 12); + RE(536870976, 14); + RE(536870976, 15); + RE(536870976, 16); + RE(536870976, 17); + RE(536870976, 18); + RE(536870976, 19); + RE(536870976, 20); + RE(536870976, 21); + RE(536870976, 22); + RE(536870976, 23); + RE(536870976, 24); + RE(536870976, 25); + RE(536870976, 26); + RE(536870976, 27); + RE(536870976, 30); + RE(536870976, 31); + RE(536870976, 32); + RE(536870976, 37); + RE(536870976, 43); + RE(536870976, 44); + RE(536870976, 45); + RE(536870976, 46); + RE(536870976, 48); + RE(536870976, 49); + RE(536870976, -1); + RE(1073741887, 28); + RE(105, 16391); + YaccRows[21] := Row; + // [22] + R(0, 0, 27); + RE(536870934, 10); + RE(536870934, 12); + RE(536870934, 14); + RE(536870934, 15); + RE(536870934, 16); + RE(536870934, 17); + RE(536870934, 18); + RE(536870934, 19); + RE(536870934, 20); + RE(536870934, 21); + RE(536870934, 22); + RE(536870934, 23); + RE(536870934, 24); + RE(536870934, 25); + RE(536870934, 26); + RE(536870934, 27); + RE(536870934, 30); + RE(536870934, 31); + RE(536870934, 32); + RE(536870934, 37); + RE(536870934, 43); + RE(536870934, 44); + RE(536870934, 45); + RE(536870934, 46); + RE(536870934, 48); + RE(536870934, 49); + RE(536870934, -1); + YaccRows[22] := Row; + // [23] + R(0, 0, 27); + RE(536870942, 10); + RE(536870942, 12); + RE(536870942, 14); + RE(536870942, 15); + RE(536870942, 16); + RE(536870942, 17); + RE(536870942, 18); + RE(536870942, 19); + RE(536870942, 20); + RE(536870942, 21); + RE(536870942, 22); + RE(536870942, 23); + RE(536870942, 24); + RE(536870942, 25); + RE(536870942, 26); + RE(536870942, 27); + RE(536870942, 30); + RE(536870942, 31); + RE(536870942, 32); + RE(536870942, 37); + RE(536870942, 43); + RE(536870942, 44); + RE(536870942, 45); + RE(536870942, 46); + RE(536870942, 48); + RE(536870942, 49); + RE(536870942, -1); + YaccRows[23] := Row; + // [24] + R(0, 0, 27); + RE(536870914, 10); + RE(536870914, 12); + RE(536870914, 14); + RE(536870914, 15); + RE(536870914, 16); + RE(536870914, 17); + RE(536870914, 18); + RE(536870914, 19); + RE(536870914, 20); + RE(536870914, 21); + RE(536870914, 22); + RE(536870914, 23); + RE(536870914, 24); + RE(536870914, 27); + RE(536870914, 30); + RE(536870914, 31); + RE(536870914, 32); + RE(536870914, 37); + RE(536870914, 43); + RE(536870914, 44); + RE(536870914, 45); + RE(536870914, 46); + RE(536870914, 48); + RE(536870914, 49); + RE(536870914, -1); + RE(1073741884, 26); + RE(1073741885, 25); + YaccRows[24] := Row; + // [25] + R(0, 0, 17); + RE(536870913, -1); + RE(1073741852, 49); + RE(1073741853, 48); + RE(1073741854, 46); + RE(1073741855, 45); + RE(1073741856, 44); + RE(1073741857, 43); + RE(1073741858, 24); + RE(1073741859, 23); + RE(1073741860, 22); + RE(1073741861, 21); + RE(1073741862, 20); + RE(1073741863, 19); + RE(1073741864, 18); + RE(1073741865, 17); + RE(1073741866, 16); + RE(1073741867, 15); + YaccRows[25] := Row; + // [26] + R(0, 0, 1); + RE(268435456, -1); + YaccRows[26] := Row; + // [27] + R(0, 0, 0); + YaccRows[27] := Row; + // [28] + R(0, 9, 16); + RE(1073741825, 47); + RE(1073741826, 42); + RE(1073741827, 41); + RE(1073741828, 40); + RE(1073741829, 39); + RE(1073741830, 34); + RE(1073741831, 29); + RE(1073741832, 22); + RE(1073741833, 11); + RE(1073741834, 8); + RE(1073741835, 7); + RE(1073741836, 6); + RE(1073741837, 5); + RE(1073741838, 4); + RE(1073741839, 3); + RE(1073741840, 2); + RE(17, 16401); + RE(18, 16398); + RE(19, 16395); + RE(20, 16394); + RE(21, 16390); + RE(22, 16389); + RE(23, 16388); + RE(24, 16387); + RE(59, 16385); + YaccRows[28] := Row; + // [29] + R(0, 9, 16); + RE(1073741825, 47); + RE(1073741826, 42); + RE(1073741827, 41); + RE(1073741828, 40); + RE(1073741829, 39); + RE(1073741830, 34); + RE(1073741831, 29); + RE(1073741832, 22); + RE(1073741833, 11); + RE(1073741834, 8); + RE(1073741835, 7); + RE(1073741836, 6); + RE(1073741837, 5); + RE(1073741838, 4); + RE(1073741839, 3); + RE(1073741840, 2); + RE(17, 16401); + RE(18, 16398); + RE(19, 16395); + RE(20, 16394); + RE(21, 16390); + RE(22, 16389); + RE(23, 16388); + RE(24, 16387); + RE(58, 16385); + YaccRows[29] := Row; + // [30] + R(0, 9, 16); + RE(1073741825, 47); + RE(1073741826, 42); + RE(1073741827, 41); + RE(1073741828, 40); + RE(1073741829, 39); + RE(1073741830, 34); + RE(1073741831, 29); + RE(1073741832, 22); + RE(1073741833, 11); + RE(1073741834, 8); + RE(1073741835, 7); + RE(1073741836, 6); + RE(1073741837, 5); + RE(1073741838, 4); + RE(1073741839, 3); + RE(1073741840, 2); + RE(17, 16401); + RE(18, 16398); + RE(19, 16395); + RE(20, 16394); + RE(21, 16390); + RE(22, 16389); + RE(23, 16388); + RE(24, 16387); + RE(57, 16385); + YaccRows[30] := Row; + // [31] + R(0, 9, 16); + RE(1073741825, 47); + RE(1073741826, 42); + RE(1073741827, 41); + RE(1073741828, 40); + RE(1073741829, 39); + RE(1073741830, 34); + RE(1073741831, 29); + RE(1073741832, 22); + RE(1073741833, 11); + RE(1073741834, 8); + RE(1073741835, 7); + RE(1073741836, 6); + RE(1073741837, 5); + RE(1073741838, 4); + RE(1073741839, 3); + RE(1073741840, 2); + RE(17, 16401); + RE(18, 16398); + RE(19, 16395); + RE(20, 16394); + RE(21, 16390); + RE(22, 16389); + RE(23, 16388); + RE(24, 16387); + RE(56, 16385); + YaccRows[31] := Row; + // [32] + R(0, 9, 16); + RE(1073741825, 47); + RE(1073741826, 42); + RE(1073741827, 41); + RE(1073741828, 40); + RE(1073741829, 39); + RE(1073741830, 34); + RE(1073741831, 29); + RE(1073741832, 22); + RE(1073741833, 11); + RE(1073741834, 8); + RE(1073741835, 7); + RE(1073741836, 6); + RE(1073741837, 5); + RE(1073741838, 4); + RE(1073741839, 3); + RE(1073741840, 2); + RE(17, 16401); + RE(18, 16398); + RE(19, 16395); + RE(20, 16394); + RE(21, 16390); + RE(22, 16389); + RE(23, 16388); + RE(24, 16387); + RE(55, 16385); + YaccRows[32] := Row; + // [33] + R(0, 9, 16); + RE(1073741825, 47); + RE(1073741826, 42); + RE(1073741827, 41); + RE(1073741828, 40); + RE(1073741829, 39); + RE(1073741830, 34); + RE(1073741831, 29); + RE(1073741832, 22); + RE(1073741833, 11); + RE(1073741834, 8); + RE(1073741835, 7); + RE(1073741836, 6); + RE(1073741837, 5); + RE(1073741838, 4); + RE(1073741839, 3); + RE(1073741840, 2); + RE(17, 16401); + RE(18, 16398); + RE(19, 16395); + RE(20, 16394); + RE(21, 16390); + RE(22, 16389); + RE(23, 16388); + RE(24, 16387); + RE(54, 16385); + YaccRows[33] := Row; + // [34] + R(0, 9, 16); + RE(1073741825, 47); + RE(1073741826, 42); + RE(1073741827, 41); + RE(1073741828, 40); + RE(1073741829, 39); + RE(1073741830, 34); + RE(1073741831, 29); + RE(1073741832, 22); + RE(1073741833, 11); + RE(1073741834, 8); + RE(1073741835, 7); + RE(1073741836, 6); + RE(1073741837, 5); + RE(1073741838, 4); + RE(1073741839, 3); + RE(1073741840, 2); + RE(17, 16401); + RE(18, 16398); + RE(19, 16395); + RE(20, 16394); + RE(21, 16390); + RE(22, 16389); + RE(23, 16388); + RE(24, 16387); + RE(53, 16385); + YaccRows[34] := Row; + // [35] + R(0, 9, 16); + RE(1073741825, 47); + RE(1073741826, 42); + RE(1073741827, 41); + RE(1073741828, 40); + RE(1073741829, 39); + RE(1073741830, 34); + RE(1073741831, 29); + RE(1073741832, 22); + RE(1073741833, 11); + RE(1073741834, 8); + RE(1073741835, 7); + RE(1073741836, 6); + RE(1073741837, 5); + RE(1073741838, 4); + RE(1073741839, 3); + RE(1073741840, 2); + RE(17, 16401); + RE(18, 16398); + RE(19, 16395); + RE(20, 16394); + RE(21, 16390); + RE(22, 16389); + RE(23, 16388); + RE(24, 16387); + RE(52, 16385); + YaccRows[35] := Row; + // [36] + R(0, 9, 16); + RE(1073741825, 47); + RE(1073741826, 42); + RE(1073741827, 41); + RE(1073741828, 40); + RE(1073741829, 39); + RE(1073741830, 34); + RE(1073741831, 29); + RE(1073741832, 22); + RE(1073741833, 11); + RE(1073741834, 8); + RE(1073741835, 7); + RE(1073741836, 6); + RE(1073741837, 5); + RE(1073741838, 4); + RE(1073741839, 3); + RE(1073741840, 2); + RE(17, 16401); + RE(18, 16398); + RE(19, 16395); + RE(20, 16394); + RE(21, 16390); + RE(22, 16389); + RE(23, 16388); + RE(24, 16387); + RE(51, 16385); + YaccRows[36] := Row; + // [37] + R(0, 9, 16); + RE(1073741825, 47); + RE(1073741826, 42); + RE(1073741827, 41); + RE(1073741828, 40); + RE(1073741829, 39); + RE(1073741830, 34); + RE(1073741831, 29); + RE(1073741832, 22); + RE(1073741833, 11); + RE(1073741834, 8); + RE(1073741835, 7); + RE(1073741836, 6); + RE(1073741837, 5); + RE(1073741838, 4); + RE(1073741839, 3); + RE(1073741840, 2); + RE(17, 16401); + RE(18, 16398); + RE(19, 16395); + RE(20, 16394); + RE(21, 16390); + RE(22, 16389); + RE(23, 16388); + RE(24, 16387); + RE(50, 16385); + YaccRows[37] := Row; + // [38] + R(0, 9, 16); + RE(1073741825, 47); + RE(1073741826, 42); + RE(1073741827, 41); + RE(1073741828, 40); + RE(1073741829, 39); + RE(1073741830, 34); + RE(1073741831, 29); + RE(1073741832, 22); + RE(1073741833, 11); + RE(1073741834, 8); + RE(1073741835, 7); + RE(1073741836, 6); + RE(1073741837, 5); + RE(1073741838, 4); + RE(1073741839, 3); + RE(1073741840, 2); + RE(17, 16401); + RE(18, 16398); + RE(19, 16395); + RE(20, 16394); + RE(21, 16390); + RE(22, 16389); + RE(23, 16388); + RE(24, 16387); + RE(49, 16385); + YaccRows[38] := Row; + // [39] + R(0, 9, 16); + RE(1073741825, 47); + RE(1073741826, 42); + RE(1073741827, 41); + RE(1073741828, 40); + RE(1073741829, 39); + RE(1073741830, 34); + RE(1073741831, 29); + RE(1073741832, 22); + RE(1073741833, 11); + RE(1073741834, 8); + RE(1073741835, 7); + RE(1073741836, 6); + RE(1073741837, 5); + RE(1073741838, 4); + RE(1073741839, 3); + RE(1073741840, 2); + RE(17, 16401); + RE(18, 16398); + RE(19, 16395); + RE(20, 16394); + RE(21, 16390); + RE(22, 16389); + RE(23, 16388); + RE(24, 16387); + RE(48, 16385); + YaccRows[39] := Row; + // [40] + R(0, 9, 16); + RE(1073741825, 47); + RE(1073741826, 42); + RE(1073741827, 41); + RE(1073741828, 40); + RE(1073741829, 39); + RE(1073741830, 34); + RE(1073741831, 29); + RE(1073741832, 22); + RE(1073741833, 11); + RE(1073741834, 8); + RE(1073741835, 7); + RE(1073741836, 6); + RE(1073741837, 5); + RE(1073741838, 4); + RE(1073741839, 3); + RE(1073741840, 2); + RE(17, 16401); + RE(18, 16398); + RE(19, 16395); + RE(20, 16394); + RE(21, 16390); + RE(22, 16389); + RE(23, 16388); + RE(24, 16387); + RE(47, 16385); + YaccRows[40] := Row; + // [41] + R(0, 9, 16); + RE(1073741825, 47); + RE(1073741826, 42); + RE(1073741827, 41); + RE(1073741828, 40); + RE(1073741829, 39); + RE(1073741830, 34); + RE(1073741831, 29); + RE(1073741832, 22); + RE(1073741833, 11); + RE(1073741834, 8); + RE(1073741835, 7); + RE(1073741836, 6); + RE(1073741837, 5); + RE(1073741838, 4); + RE(1073741839, 3); + RE(1073741840, 2); + RE(17, 16401); + RE(18, 16398); + RE(19, 16395); + RE(20, 16394); + RE(21, 16390); + RE(22, 16389); + RE(23, 16388); + RE(24, 16387); + RE(46, 16385); + YaccRows[41] := Row; + // [42] + R(0, 9, 16); + RE(1073741825, 47); + RE(1073741826, 42); + RE(1073741827, 41); + RE(1073741828, 40); + RE(1073741829, 39); + RE(1073741830, 34); + RE(1073741831, 29); + RE(1073741832, 22); + RE(1073741833, 11); + RE(1073741834, 8); + RE(1073741835, 7); + RE(1073741836, 6); + RE(1073741837, 5); + RE(1073741838, 4); + RE(1073741839, 3); + RE(1073741840, 2); + RE(17, 16401); + RE(18, 16398); + RE(19, 16395); + RE(20, 16394); + RE(21, 16390); + RE(22, 16389); + RE(23, 16388); + RE(24, 16387); + RE(45, 16385); + YaccRows[42] := Row; + // [43] + R(0, 9, 16); + RE(1073741825, 47); + RE(1073741826, 42); + RE(1073741827, 41); + RE(1073741828, 40); + RE(1073741829, 39); + RE(1073741830, 34); + RE(1073741831, 29); + RE(1073741832, 22); + RE(1073741833, 11); + RE(1073741834, 8); + RE(1073741835, 7); + RE(1073741836, 6); + RE(1073741837, 5); + RE(1073741838, 4); + RE(1073741839, 3); + RE(1073741840, 2); + RE(17, 16401); + RE(18, 16398); + RE(19, 16395); + RE(20, 16394); + RE(21, 16390); + RE(22, 16389); + RE(23, 16388); + RE(24, 16387); + RE(44, 16385); + YaccRows[43] := Row; + // [44] + R(0, 0, 25); + RE(536870921, 10); + RE(536870921, 12); + RE(536870921, 14); + RE(536870921, 15); + RE(536870921, 16); + RE(536870921, 17); + RE(536870921, 18); + RE(536870921, 19); + RE(536870921, 20); + RE(536870921, 27); + RE(536870921, 30); + RE(536870921, 31); + RE(536870921, 32); + RE(536870921, 37); + RE(536870921, -1); + RE(1073741852, 49); + RE(1073741853, 48); + RE(1073741854, 46); + RE(1073741855, 45); + RE(1073741856, 44); + RE(1073741857, 43); + RE(1073741858, 24); + RE(1073741859, 23); + RE(1073741860, 22); + RE(1073741861, 21); + YaccRows[44] := Row; + // [45] + R(0, 0, 25); + RE(536870920, 10); + RE(536870920, 12); + RE(536870920, 14); + RE(536870920, 15); + RE(536870920, 16); + RE(536870920, 17); + RE(536870920, 18); + RE(536870920, 19); + RE(536870920, 20); + RE(536870920, 27); + RE(536870920, 30); + RE(536870920, 31); + RE(536870920, 32); + RE(536870920, 37); + RE(536870920, -1); + RE(1073741852, 49); + RE(1073741853, 48); + RE(1073741854, 46); + RE(1073741855, 45); + RE(1073741856, 44); + RE(1073741857, 43); + RE(1073741858, 24); + RE(1073741859, 23); + RE(1073741860, 22); + RE(1073741861, 21); + YaccRows[45] := Row; + // [46] + R(0, 0, 25); + RE(536870919, 10); + RE(536870919, 12); + RE(536870919, 14); + RE(536870919, 15); + RE(536870919, 16); + RE(536870919, 17); + RE(536870919, 18); + RE(536870919, 19); + RE(536870919, 20); + RE(536870919, 27); + RE(536870919, 30); + RE(536870919, 31); + RE(536870919, 32); + RE(536870919, 37); + RE(536870919, -1); + RE(1073741852, 49); + RE(1073741853, 48); + RE(1073741854, 46); + RE(1073741855, 45); + RE(1073741856, 44); + RE(1073741857, 43); + RE(1073741858, 24); + RE(1073741859, 23); + RE(1073741860, 22); + RE(1073741861, 21); + YaccRows[46] := Row; + // [47] + R(0, 0, 25); + RE(536870923, 10); + RE(536870923, 12); + RE(536870923, 14); + RE(536870923, 15); + RE(536870923, 16); + RE(536870923, 17); + RE(536870923, 18); + RE(536870923, 19); + RE(536870923, 20); + RE(536870923, 27); + RE(536870923, 30); + RE(536870923, 31); + RE(536870923, 32); + RE(536870923, 37); + RE(536870923, -1); + RE(1073741852, 49); + RE(1073741853, 48); + RE(1073741854, 46); + RE(1073741855, 45); + RE(1073741856, 44); + RE(1073741857, 43); + RE(1073741858, 24); + RE(1073741859, 23); + RE(1073741860, 22); + RE(1073741861, 21); + YaccRows[47] := Row; + // [48] + R(0, 0, 25); + RE(536870922, 10); + RE(536870922, 12); + RE(536870922, 14); + RE(536870922, 15); + RE(536870922, 16); + RE(536870922, 17); + RE(536870922, 18); + RE(536870922, 19); + RE(536870922, 20); + RE(536870922, 27); + RE(536870922, 30); + RE(536870922, 31); + RE(536870922, 32); + RE(536870922, 37); + RE(536870922, -1); + RE(1073741852, 49); + RE(1073741853, 48); + RE(1073741854, 46); + RE(1073741855, 45); + RE(1073741856, 44); + RE(1073741857, 43); + RE(1073741858, 24); + RE(1073741859, 23); + RE(1073741860, 22); + RE(1073741861, 21); + YaccRows[48] := Row; + // [49] + R(0, 0, 25); + RE(536870924, 10); + RE(536870924, 12); + RE(536870924, 14); + RE(536870924, 15); + RE(536870924, 16); + RE(536870924, 17); + RE(536870924, 18); + RE(536870924, 19); + RE(536870924, 20); + RE(536870924, 27); + RE(536870924, 30); + RE(536870924, 31); + RE(536870924, 32); + RE(536870924, 37); + RE(536870924, -1); + RE(1073741852, 49); + RE(1073741853, 48); + RE(1073741854, 46); + RE(1073741855, 45); + RE(1073741856, 44); + RE(1073741857, 43); + RE(1073741858, 24); + RE(1073741859, 23); + RE(1073741860, 22); + RE(1073741861, 21); + YaccRows[49] := Row; + // [50] + R(0, 0, 25); + RE(536870925, 10); + RE(536870925, 12); + RE(536870925, 14); + RE(536870925, 15); + RE(536870925, 16); + RE(536870925, 17); + RE(536870925, 18); + RE(536870925, 19); + RE(536870925, 20); + RE(536870925, 21); + RE(536870925, 22); + RE(536870925, 27); + RE(536870925, 30); + RE(536870925, 31); + RE(536870925, 32); + RE(536870925, 37); + RE(536870925, 45); + RE(536870925, 46); + RE(536870925, 48); + RE(536870925, 49); + RE(536870925, -1); + RE(1073741856, 44); + RE(1073741857, 43); + RE(1073741858, 24); + RE(1073741859, 23); + YaccRows[50] := Row; + // [51] + R(0, 0, 25); + RE(536870926, 10); + RE(536870926, 12); + RE(536870926, 14); + RE(536870926, 15); + RE(536870926, 16); + RE(536870926, 17); + RE(536870926, 18); + RE(536870926, 19); + RE(536870926, 20); + RE(536870926, 21); + RE(536870926, 22); + RE(536870926, 27); + RE(536870926, 30); + RE(536870926, 31); + RE(536870926, 32); + RE(536870926, 37); + RE(536870926, 45); + RE(536870926, 46); + RE(536870926, 48); + RE(536870926, 49); + RE(536870926, -1); + RE(1073741856, 44); + RE(1073741857, 43); + RE(1073741858, 24); + RE(1073741859, 23); + YaccRows[51] := Row; + // [52] + R(0, 0, 25); + RE(536870928, 10); + RE(536870928, 12); + RE(536870928, 14); + RE(536870928, 15); + RE(536870928, 16); + RE(536870928, 17); + RE(536870928, 18); + RE(536870928, 19); + RE(536870928, 20); + RE(536870928, 21); + RE(536870928, 22); + RE(536870928, 23); + RE(536870928, 24); + RE(536870928, 27); + RE(536870928, 30); + RE(536870928, 31); + RE(536870928, 32); + RE(536870928, 37); + RE(536870928, 43); + RE(536870928, 44); + RE(536870928, 45); + RE(536870928, 46); + RE(536870928, 48); + RE(536870928, 49); + RE(536870928, -1); + YaccRows[52] := Row; + // [53] + R(0, 0, 25); + RE(536870927, 10); + RE(536870927, 12); + RE(536870927, 14); + RE(536870927, 15); + RE(536870927, 16); + RE(536870927, 17); + RE(536870927, 18); + RE(536870927, 19); + RE(536870927, 20); + RE(536870927, 21); + RE(536870927, 22); + RE(536870927, 23); + RE(536870927, 24); + RE(536870927, 27); + RE(536870927, 30); + RE(536870927, 31); + RE(536870927, 32); + RE(536870927, 37); + RE(536870927, 43); + RE(536870927, 44); + RE(536870927, 45); + RE(536870927, 46); + RE(536870927, 48); + RE(536870927, 49); + RE(536870927, -1); + YaccRows[53] := Row; + // [54] + R(0, 0, 25); + RE(536870929, 10); + RE(536870929, 12); + RE(536870929, 14); + RE(536870929, 15); + RE(536870929, 16); + RE(536870929, 17); + RE(536870929, 18); + RE(536870929, 19); + RE(536870929, 20); + RE(536870929, 21); + RE(536870929, 22); + RE(536870929, 23); + RE(536870929, 24); + RE(536870929, 27); + RE(536870929, 30); + RE(536870929, 31); + RE(536870929, 32); + RE(536870929, 37); + RE(536870929, 43); + RE(536870929, 44); + RE(536870929, 45); + RE(536870929, 46); + RE(536870929, 48); + RE(536870929, 49); + RE(536870929, -1); + YaccRows[54] := Row; + // [55] + R(0, 0, 25); + RE(536870930, 10); + RE(536870930, 12); + RE(536870930, 14); + RE(536870930, 15); + RE(536870930, 16); + RE(536870930, 17); + RE(536870930, 18); + RE(536870930, 19); + RE(536870930, 20); + RE(536870930, 21); + RE(536870930, 22); + RE(536870930, 23); + RE(536870930, 24); + RE(536870930, 27); + RE(536870930, 30); + RE(536870930, 31); + RE(536870930, 32); + RE(536870930, 37); + RE(536870930, 43); + RE(536870930, 44); + RE(536870930, 45); + RE(536870930, 46); + RE(536870930, 48); + RE(536870930, 49); + RE(536870930, -1); + YaccRows[55] := Row; + // [56] + R(0, 0, 25); + RE(536870915, 10); + RE(536870915, 12); + RE(536870915, 14); + RE(536870915, 15); + RE(536870915, 16); + RE(536870915, 17); + RE(536870915, 18); + RE(536870915, 19); + RE(536870915, 20); + RE(536870915, 27); + RE(536870915, 30); + RE(536870915, 31); + RE(536870915, 32); + RE(536870915, 37); + RE(536870915, 45); + RE(536870915, 46); + RE(536870915, 48); + RE(536870915, 49); + RE(536870915, -1); + RE(1073741856, 44); + RE(1073741857, 43); + RE(1073741858, 24); + RE(1073741859, 23); + RE(1073741860, 22); + RE(1073741861, 21); + YaccRows[56] := Row; + // [57] + R(0, 0, 25); + RE(536870916, 10); + RE(536870916, 12); + RE(536870916, 14); + RE(536870916, 15); + RE(536870916, 16); + RE(536870916, 17); + RE(536870916, 18); + RE(536870916, 19); + RE(536870916, 20); + RE(536870916, 27); + RE(536870916, 30); + RE(536870916, 31); + RE(536870916, 32); + RE(536870916, 37); + RE(536870916, 45); + RE(536870916, 46); + RE(536870916, 48); + RE(536870916, 49); + RE(536870916, -1); + RE(1073741856, 44); + RE(1073741857, 43); + RE(1073741858, 24); + RE(1073741859, 23); + RE(1073741860, 22); + RE(1073741861, 21); + YaccRows[57] := Row; + // [58] + R(0, 0, 25); + RE(536870917, 10); + RE(536870917, 12); + RE(536870917, 14); + RE(536870917, 15); + RE(536870917, 16); + RE(536870917, 17); + RE(536870917, 18); + RE(536870917, 19); + RE(536870917, 20); + RE(536870917, 27); + RE(536870917, 30); + RE(536870917, 31); + RE(536870917, 32); + RE(536870917, 37); + RE(536870917, 45); + RE(536870917, 46); + RE(536870917, 48); + RE(536870917, 49); + RE(536870917, -1); + RE(1073741856, 44); + RE(1073741857, 43); + RE(1073741858, 24); + RE(1073741859, 23); + RE(1073741860, 22); + RE(1073741861, 21); + YaccRows[58] := Row; + // [59] + R(0, 0, 25); + RE(536870918, 10); + RE(536870918, 12); + RE(536870918, 14); + RE(536870918, 15); + RE(536870918, 16); + RE(536870918, 17); + RE(536870918, 18); + RE(536870918, 19); + RE(536870918, 20); + RE(536870918, 27); + RE(536870918, 30); + RE(536870918, 31); + RE(536870918, 32); + RE(536870918, 37); + RE(536870918, 49); + RE(536870918, -1); + RE(1073741853, 48); + RE(1073741854, 46); + RE(1073741855, 45); + RE(1073741856, 44); + RE(1073741857, 43); + RE(1073741858, 24); + RE(1073741859, 23); + RE(1073741860, 22); + RE(1073741861, 21); + YaccRows[59] := Row; + // [60] + R(0, 2, 2); + RE(1073741837, 5); + RE(1073741838, 4); + RE(18, 16398); + RE(101, 16390); + YaccRows[60] := Row; + // [61] + R(0, 2, 2); + RE(1073741837, 5); + RE(1073741838, 4); + RE(18, 16398); + RE(62, 16390); + YaccRows[61] := Row; + // [62] + R(0, 1, 30); + RE(536870976, 9); + RE(536870976, 10); + RE(536870976, 11); + RE(536870976, 12); + RE(536870976, 14); + RE(536870976, 15); + RE(536870976, 16); + RE(536870976, 17); + RE(536870976, 18); + RE(536870976, 19); + RE(536870976, 20); + RE(536870976, 21); + RE(536870976, 22); + RE(536870976, 23); + RE(536870976, 24); + RE(536870976, 25); + RE(536870976, 26); + RE(536870976, 27); + RE(536870976, 30); + RE(536870976, 31); + RE(536870976, 32); + RE(536870976, 37); + RE(536870976, 43); + RE(536870976, 44); + RE(536870976, 45); + RE(536870976, 46); + RE(536870976, 48); + RE(536870976, 49); + RE(536870976, -1); + RE(1073741887, 28); + RE(64, 16391); + YaccRows[62] := Row; + // [63] + R(0, 1, 2); + RE(1073741837, 5); + RE(1073741838, 4); + RE(100, 16398); + YaccRows[63] := Row; + // [64] + R(0, 1, 29); + RE(536870966, 10); + RE(536870966, 11); + RE(536870966, 12); + RE(536870966, 14); + RE(536870966, 15); + RE(536870966, 16); + RE(536870966, 17); + RE(536870966, 18); + RE(536870966, 19); + RE(536870966, 20); + RE(536870966, 21); + RE(536870966, 22); + RE(536870966, 23); + RE(536870966, 24); + RE(536870966, 25); + RE(536870966, 26); + RE(536870966, 27); + RE(536870966, 30); + RE(536870966, 31); + RE(536870966, 32); + RE(536870966, 37); + RE(536870966, 43); + RE(536870966, 44); + RE(536870966, 45); + RE(536870966, 46); + RE(536870966, 48); + RE(536870966, 49); + RE(536870966, -1); + RE(1073741889, 9); + RE(66, 16392); + YaccRows[64] := Row; + // [65] + R(0, 11, 17); + RE(536870977, 10); + RE(1073741825, 47); + RE(1073741826, 42); + RE(1073741827, 41); + RE(1073741828, 40); + RE(1073741829, 39); + RE(1073741830, 34); + RE(1073741831, 29); + RE(1073741832, 22); + RE(1073741833, 11); + RE(1073741834, 8); + RE(1073741835, 7); + RE(1073741836, 6); + RE(1073741837, 5); + RE(1073741838, 4); + RE(1073741839, 3); + RE(1073741840, 2); + RE(70, 16406); + RE(17, 16401); + RE(18, 16398); + RE(98, 16396); + RE(19, 16395); + RE(20, 16394); + RE(21, 16390); + RE(22, 16389); + RE(23, 16388); + RE(24, 16387); + RE(72, 16385); + YaccRows[65] := Row; + // [66] + R(0, 1, 28); + RE(536870935, 10); + RE(536870935, 12); + RE(536870935, 14); + RE(536870935, 15); + RE(536870935, 16); + RE(536870935, 17); + RE(536870935, 18); + RE(536870935, 19); + RE(536870935, 20); + RE(536870935, 21); + RE(536870935, 22); + RE(536870935, 23); + RE(536870935, 24); + RE(536870935, 25); + RE(536870935, 26); + RE(536870935, 27); + RE(536870935, 30); + RE(536870935, 31); + RE(536870935, 32); + RE(536870935, 37); + RE(536870935, 43); + RE(536870935, 44); + RE(536870935, 45); + RE(536870935, 46); + RE(536870935, 48); + RE(536870935, 49); + RE(536870935, -1); + RE(1073741891, 11); + RE(68, 16393); + YaccRows[66] := Row; + // [67] + R(0, 11, 17); + RE(536870977, 12); + RE(1073741825, 47); + RE(1073741826, 42); + RE(1073741827, 41); + RE(1073741828, 40); + RE(1073741829, 39); + RE(1073741830, 34); + RE(1073741831, 29); + RE(1073741832, 22); + RE(1073741833, 11); + RE(1073741834, 8); + RE(1073741835, 7); + RE(1073741836, 6); + RE(1073741837, 5); + RE(1073741893, 4); + RE(1073741839, 3); + RE(1073741840, 2); + RE(70, 16406); + RE(17, 16401); + RE(18, 16398); + RE(71, 16396); + RE(19, 16395); + RE(20, 16394); + RE(21, 16390); + RE(22, 16389); + RE(23, 16388); + RE(24, 16387); + RE(72, 16385); + YaccRows[67] := Row; + // [68] + R(0, 0, 27); + RE(536870936, 10); + RE(536870936, 12); + RE(536870936, 14); + RE(536870936, 15); + RE(536870936, 16); + RE(536870936, 17); + RE(536870936, 18); + RE(536870936, 19); + RE(536870936, 20); + RE(536870936, 21); + RE(536870936, 22); + RE(536870936, 23); + RE(536870936, 24); + RE(536870936, 25); + RE(536870936, 26); + RE(536870936, 27); + RE(536870936, 30); + RE(536870936, 31); + RE(536870936, 32); + RE(536870936, 37); + RE(536870936, 43); + RE(536870936, 44); + RE(536870936, 45); + RE(536870936, 46); + RE(536870936, 48); + RE(536870936, 49); + RE(536870936, -1); + YaccRows[68] := Row; + // [69] + R(0, 0, 26); + RE(536870974, 9); + RE(536870974, 11); + RE(536870974, 12); + RE(536870974, 15); + RE(536870974, 16); + RE(536870974, 17); + RE(536870974, 18); + RE(536870974, 19); + RE(536870974, 20); + RE(536870974, 21); + RE(536870974, 22); + RE(536870974, 23); + RE(536870974, 24); + RE(536870974, 25); + RE(536870974, 26); + RE(536870974, 27); + RE(536870974, 28); + RE(536870974, 36); + RE(536870974, 43); + RE(536870974, 44); + RE(536870974, 45); + RE(536870974, 46); + RE(536870974, 48); + RE(536870974, 49); + RE(1073741900, 38); + RE(1073741901, 35); + YaccRows[69] := Row; + // [70] + R(0, 0, 2); + RE(536870978, 10); + RE(536870978, 12); + YaccRows[70] := Row; + // [71] + R(0, 0, 1); + RE(1073741899, 12); + YaccRows[71] := Row; + // [72] + R(0, 0, 19); + RE(536870979, 10); + RE(536870979, 12); + RE(1073741852, 49); + RE(1073741853, 48); + RE(1073741854, 46); + RE(1073741855, 45); + RE(1073741856, 44); + RE(1073741857, 43); + RE(1073741897, 27); + RE(1073741858, 24); + RE(1073741859, 23); + RE(1073741860, 22); + RE(1073741861, 21); + RE(1073741862, 20); + RE(1073741863, 19); + RE(1073741864, 18); + RE(1073741865, 17); + RE(1073741866, 16); + RE(1073741867, 15); + YaccRows[72] := Row; + // [73] + R(0, 10, 16); + RE(1073741825, 47); + RE(1073741826, 42); + RE(1073741827, 41); + RE(1073741828, 40); + RE(1073741829, 39); + RE(1073741830, 34); + RE(1073741831, 29); + RE(1073741832, 22); + RE(1073741833, 11); + RE(1073741834, 8); + RE(1073741835, 7); + RE(1073741836, 6); + RE(1073741837, 5); + RE(1073741838, 4); + RE(1073741839, 3); + RE(1073741840, 2); + RE(74, 16406); + RE(17, 16401); + RE(18, 16398); + RE(19, 16395); + RE(20, 16394); + RE(21, 16390); + RE(22, 16389); + RE(23, 16388); + RE(24, 16387); + RE(72, 16385); + YaccRows[73] := Row; + // [74] + R(0, 0, 2); + RE(536870980, 10); + RE(536870980, 12); + YaccRows[74] := Row; + // [75] + R(0, 0, 27); + RE(536870945, 10); + RE(536870945, 12); + RE(536870945, 14); + RE(536870945, 15); + RE(536870945, 16); + RE(536870945, 17); + RE(536870945, 18); + RE(536870945, 19); + RE(536870945, 20); + RE(536870945, 21); + RE(536870945, 22); + RE(536870945, 23); + RE(536870945, 24); + RE(536870945, 25); + RE(536870945, 26); + RE(536870945, 27); + RE(536870945, 30); + RE(536870945, 31); + RE(536870945, 32); + RE(536870945, 37); + RE(536870945, 43); + RE(536870945, 44); + RE(536870945, 45); + RE(536870945, 46); + RE(536870945, 48); + RE(536870945, 49); + RE(536870945, -1); + YaccRows[75] := Row; + // [76] + R(0, 4, 3); + RE(536870955, 35); + RE(1073741904, 33); + RE(1073741905, 5); + RE(82, 16405); + RE(83, 16400); + RE(84, 16399); + RE(85, 16397); + YaccRows[76] := Row; + // [77] + R(0, 11, 17); + RE(536870977, 12); + RE(1073741825, 47); + RE(1073741826, 42); + RE(1073741827, 41); + RE(1073741828, 40); + RE(1073741829, 39); + RE(1073741830, 34); + RE(1073741831, 29); + RE(1073741832, 22); + RE(1073741833, 11); + RE(1073741834, 8); + RE(1073741835, 7); + RE(1073741836, 6); + RE(1073741837, 5); + RE(1073741838, 4); + RE(1073741839, 3); + RE(1073741840, 2); + RE(70, 16406); + RE(17, 16401); + RE(18, 16398); + RE(78, 16396); + RE(19, 16395); + RE(20, 16394); + RE(21, 16390); + RE(22, 16389); + RE(23, 16388); + RE(24, 16387); + RE(72, 16385); + YaccRows[77] := Row; + // [78] + R(0, 0, 1); + RE(1073741903, 12); + YaccRows[78] := Row; + // [79] + R(0, 0, 27); + RE(536870946, 10); + RE(536870946, 12); + RE(536870946, 14); + RE(536870946, 15); + RE(536870946, 16); + RE(536870946, 17); + RE(536870946, 18); + RE(536870946, 19); + RE(536870946, 20); + RE(536870946, 21); + RE(536870946, 22); + RE(536870946, 23); + RE(536870946, 24); + RE(536870946, 25); + RE(536870946, 26); + RE(536870946, 27); + RE(536870946, 30); + RE(536870946, 31); + RE(536870946, 32); + RE(536870946, 37); + RE(536870946, 43); + RE(536870946, 44); + RE(536870946, 45); + RE(536870946, 46); + RE(536870946, 48); + RE(536870946, 49); + RE(536870946, -1); + YaccRows[79] := Row; + // [80] + R(0, 0, 1); + RE(1073741915, 13); + YaccRows[80] := Row; + // [81] + R(0, 0, 2); + RE(536870969, 35); + RE(1073741913, 36); + YaccRows[81] := Row; + // [82] + R(0, 0, 1); + RE(536870968, 35); + YaccRows[82] := Row; + // [83] + R(0, 0, 1); + RE(536870957, 35); + YaccRows[83] := Row; + // [84] + R(0, 0, 1); + RE(536870956, 35); + YaccRows[84] := Row; + // [85] + R(0, 0, 1); + RE(1073741910, 35); + YaccRows[85] := Row; + // [86] + R(0, 11, 17); + RE(536870977, 12); + RE(1073741825, 47); + RE(1073741826, 42); + RE(1073741827, 41); + RE(1073741828, 40); + RE(1073741829, 39); + RE(1073741830, 34); + RE(1073741831, 29); + RE(1073741832, 22); + RE(1073741833, 11); + RE(1073741834, 8); + RE(1073741835, 7); + RE(1073741836, 6); + RE(1073741837, 5); + RE(1073741838, 4); + RE(1073741839, 3); + RE(1073741840, 2); + RE(70, 16406); + RE(17, 16401); + RE(18, 16398); + RE(87, 16396); + RE(19, 16395); + RE(20, 16394); + RE(21, 16390); + RE(22, 16389); + RE(23, 16388); + RE(24, 16387); + RE(72, 16385); + YaccRows[86] := Row; + // [87] + R(0, 0, 1); + RE(1073741912, 12); + YaccRows[87] := Row; + // [88] + R(0, 0, 27); + RE(536870947, 10); + RE(536870947, 12); + RE(536870947, 14); + RE(536870947, 15); + RE(536870947, 16); + RE(536870947, 17); + RE(536870947, 18); + RE(536870947, 19); + RE(536870947, 20); + RE(536870947, 21); + RE(536870947, 22); + RE(536870947, 23); + RE(536870947, 24); + RE(536870947, 25); + RE(536870947, 26); + RE(536870947, 27); + RE(536870947, 30); + RE(536870947, 31); + RE(536870947, 32); + RE(536870947, 37); + RE(536870947, 43); + RE(536870947, 44); + RE(536870947, 45); + RE(536870947, 46); + RE(536870947, 48); + RE(536870947, 49); + RE(536870947, -1); + YaccRows[88] := Row; + // [89] + R(0, 1, 1); + RE(1073741905, 5); + RE(90, 16405); + YaccRows[89] := Row; + // [90] + R(0, 0, 1); + RE(536870970, 35); + YaccRows[90] := Row; + // [91] + R(0, 1, 1); + RE(1073741916, 34); + RE(93, 16404); + YaccRows[91] := Row; + // [92] + R(0, 1, 2); + RE(1073741837, 5); + RE(1073741838, 4); + RE(95, 16398); + YaccRows[92] := Row; + // [93] + R(0, 0, 1); + RE(1073741918, 14); + YaccRows[93] := Row; + // [94] + R(0, 0, 1); + RE(536870963, 35); + YaccRows[94] := Row; + // [95] + R(0, 0, 2); + RE(536870964, 14); + RE(1073741920, 27); + YaccRows[95] := Row; + // [96] + R(0, 1, 1); + RE(1073741916, 34); + RE(97, 16404); + YaccRows[96] := Row; + // [97] + R(0, 0, 1); + RE(536870965, 14); + YaccRows[97] := Row; + // [98] + R(0, 0, 1); + RE(1073741923, 10); + YaccRows[98] := Row; + // [99] + R(0, 0, 28); + RE(536870967, 10); + RE(536870967, 11); + RE(536870967, 12); + RE(536870967, 14); + RE(536870967, 15); + RE(536870967, 16); + RE(536870967, 17); + RE(536870967, 18); + RE(536870967, 19); + RE(536870967, 20); + RE(536870967, 21); + RE(536870967, 22); + RE(536870967, 23); + RE(536870967, 24); + RE(536870967, 25); + RE(536870967, 26); + RE(536870967, 27); + RE(536870967, 30); + RE(536870967, 31); + RE(536870967, 32); + RE(536870967, 37); + RE(536870967, 43); + RE(536870967, 44); + RE(536870967, 45); + RE(536870967, 46); + RE(536870967, 48); + RE(536870967, 49); + RE(536870967, -1); + YaccRows[99] := Row; + // [100] + R(0, 0, 29); + RE(536870975, 9); + RE(536870975, 10); + RE(536870975, 11); + RE(536870975, 12); + RE(536870975, 14); + RE(536870975, 15); + RE(536870975, 16); + RE(536870975, 17); + RE(536870975, 18); + RE(536870975, 19); + RE(536870975, 20); + RE(536870975, 21); + RE(536870975, 22); + RE(536870975, 23); + RE(536870975, 24); + RE(536870975, 25); + RE(536870975, 26); + RE(536870975, 27); + RE(536870975, 30); + RE(536870975, 31); + RE(536870975, 32); + RE(536870975, 37); + RE(536870975, 43); + RE(536870975, 44); + RE(536870975, 45); + RE(536870975, 46); + RE(536870975, 48); + RE(536870975, 49); + RE(536870975, -1); + YaccRows[100] := Row; + // [101] + R(0, 1, 30); + RE(536870976, 9); + RE(536870976, 10); + RE(536870976, 11); + RE(536870976, 12); + RE(536870976, 14); + RE(536870976, 15); + RE(536870976, 16); + RE(536870976, 17); + RE(536870976, 18); + RE(536870976, 19); + RE(536870976, 20); + RE(536870976, 21); + RE(536870976, 22); + RE(536870976, 23); + RE(536870976, 24); + RE(536870976, 25); + RE(536870976, 26); + RE(536870976, 27); + RE(536870976, 30); + RE(536870976, 31); + RE(536870976, 32); + RE(536870976, 37); + RE(536870976, 43); + RE(536870976, 44); + RE(536870976, 45); + RE(536870976, 46); + RE(536870976, 48); + RE(536870976, 49); + RE(536870976, -1); + RE(1073741887, 28); + RE(102, 16391); + YaccRows[101] := Row; + // [102] + R(0, 1, 29); + RE(536870966, 10); + RE(536870966, 11); + RE(536870966, 12); + RE(536870966, 14); + RE(536870966, 15); + RE(536870966, 16); + RE(536870966, 17); + RE(536870966, 18); + RE(536870966, 19); + RE(536870966, 20); + RE(536870966, 21); + RE(536870966, 22); + RE(536870966, 23); + RE(536870966, 24); + RE(536870966, 25); + RE(536870966, 26); + RE(536870966, 27); + RE(536870966, 30); + RE(536870966, 31); + RE(536870966, 32); + RE(536870966, 37); + RE(536870966, 43); + RE(536870966, 44); + RE(536870966, 45); + RE(536870966, 46); + RE(536870966, 48); + RE(536870966, 49); + RE(536870966, -1); + RE(1073741889, 9); + RE(103, 16392); + YaccRows[102] := Row; + // [103] + R(0, 1, 28); + RE(536870937, 10); + RE(536870937, 12); + RE(536870937, 14); + RE(536870937, 15); + RE(536870937, 16); + RE(536870937, 17); + RE(536870937, 18); + RE(536870937, 19); + RE(536870937, 20); + RE(536870937, 21); + RE(536870937, 22); + RE(536870937, 23); + RE(536870937, 24); + RE(536870937, 25); + RE(536870937, 26); + RE(536870937, 27); + RE(536870937, 30); + RE(536870937, 31); + RE(536870937, 32); + RE(536870937, 37); + RE(536870937, 43); + RE(536870937, 44); + RE(536870937, 45); + RE(536870937, 46); + RE(536870937, 48); + RE(536870937, 49); + RE(536870937, -1); + RE(1073741891, 11); + RE(104, 16393); + YaccRows[103] := Row; + // [104] + R(0, 0, 27); + RE(536870938, 10); + RE(536870938, 12); + RE(536870938, 14); + RE(536870938, 15); + RE(536870938, 16); + RE(536870938, 17); + RE(536870938, 18); + RE(536870938, 19); + RE(536870938, 20); + RE(536870938, 21); + RE(536870938, 22); + RE(536870938, 23); + RE(536870938, 24); + RE(536870938, 25); + RE(536870938, 26); + RE(536870938, 27); + RE(536870938, 30); + RE(536870938, 31); + RE(536870938, 32); + RE(536870938, 37); + RE(536870938, 43); + RE(536870938, 44); + RE(536870938, 45); + RE(536870938, 46); + RE(536870938, 48); + RE(536870938, 49); + RE(536870938, -1); + YaccRows[104] := Row; + // [105] + R(0, 1, 29); + RE(536870966, 10); + RE(536870966, 11); + RE(536870966, 12); + RE(536870966, 14); + RE(536870966, 15); + RE(536870966, 16); + RE(536870966, 17); + RE(536870966, 18); + RE(536870966, 19); + RE(536870966, 20); + RE(536870966, 21); + RE(536870966, 22); + RE(536870966, 23); + RE(536870966, 24); + RE(536870966, 25); + RE(536870966, 26); + RE(536870966, 27); + RE(536870966, 30); + RE(536870966, 31); + RE(536870966, 32); + RE(536870966, 37); + RE(536870966, 43); + RE(536870966, 44); + RE(536870966, 45); + RE(536870966, 46); + RE(536870966, 48); + RE(536870966, 49); + RE(536870966, -1); + RE(1073741889, 9); + RE(106, 16392); + YaccRows[105] := Row; + // [106] + R(0, 1, 28); + RE(536870943, 10); + RE(536870943, 12); + RE(536870943, 14); + RE(536870943, 15); + RE(536870943, 16); + RE(536870943, 17); + RE(536870943, 18); + RE(536870943, 19); + RE(536870943, 20); + RE(536870943, 21); + RE(536870943, 22); + RE(536870943, 23); + RE(536870943, 24); + RE(536870943, 25); + RE(536870943, 26); + RE(536870943, 27); + RE(536870943, 30); + RE(536870943, 31); + RE(536870943, 32); + RE(536870943, 37); + RE(536870943, 43); + RE(536870943, 44); + RE(536870943, 45); + RE(536870943, 46); + RE(536870943, 48); + RE(536870943, 49); + RE(536870943, -1); + RE(1073741891, 11); + RE(107, 16393); + YaccRows[106] := Row; + // [107] + R(0, 0, 27); + RE(536870944, 10); + RE(536870944, 12); + RE(536870944, 14); + RE(536870944, 15); + RE(536870944, 16); + RE(536870944, 17); + RE(536870944, 18); + RE(536870944, 19); + RE(536870944, 20); + RE(536870944, 21); + RE(536870944, 22); + RE(536870944, 23); + RE(536870944, 24); + RE(536870944, 25); + RE(536870944, 26); + RE(536870944, 27); + RE(536870944, 30); + RE(536870944, 31); + RE(536870944, 32); + RE(536870944, 37); + RE(536870944, 43); + RE(536870944, 44); + RE(536870944, 45); + RE(536870944, 46); + RE(536870944, 48); + RE(536870944, 49); + RE(536870944, -1); + YaccRows[107] := Row; + // [108] + R(0, 2, 2); + RE(1073741837, 5); + RE(1073741838, 4); + RE(18, 16398); + RE(109, 16390); + YaccRows[108] := Row; + // [109] + R(0, 0, 30); + RE(536870972, 9); + RE(536870972, 10); + RE(536870972, 11); + RE(536870972, 12); + RE(536870972, 14); + RE(536870972, 15); + RE(536870972, 16); + RE(536870972, 17); + RE(536870972, 18); + RE(536870972, 19); + RE(536870972, 20); + RE(536870972, 21); + RE(536870972, 22); + RE(536870972, 23); + RE(536870972, 24); + RE(536870972, 25); + RE(536870972, 26); + RE(536870972, 27); + RE(536870972, 28); + RE(536870972, 30); + RE(536870972, 31); + RE(536870972, 32); + RE(536870972, 37); + RE(536870972, 43); + RE(536870972, 44); + RE(536870972, 45); + RE(536870972, 46); + RE(536870972, 48); + RE(536870972, 49); + RE(536870972, -1); + YaccRows[109] := Row; + // [110] + R(0, 11, 16); + RE(1073741825, 47); + RE(1073741826, 42); + RE(1073741827, 41); + RE(1073741828, 40); + RE(1073741829, 39); + RE(1073741830, 34); + RE(1073741831, 29); + RE(1073741832, 22); + RE(1073741833, 11); + RE(1073741834, 8); + RE(1073741835, 7); + RE(1073741836, 6); + RE(1073741837, 5); + RE(1073741838, 4); + RE(1073741839, 3); + RE(1073741840, 2); + RE(111, 16403); + RE(112, 16402); + RE(17, 16401); + RE(18, 16398); + RE(19, 16395); + RE(20, 16394); + RE(21, 16390); + RE(22, 16389); + RE(23, 16388); + RE(24, 16387); + RE(113, 16385); + YaccRows[110] := Row; + // [111] + R(0, 0, 1); + RE(536870959, 14); + YaccRows[111] := Row; + // [112] + R(0, 0, 1); + RE(1073741943, 14); + YaccRows[112] := Row; + // [113] + R(0, 0, 19); + RE(536870960, 14); + RE(1073741852, 49); + RE(1073741853, 48); + RE(1073741854, 46); + RE(1073741855, 45); + RE(1073741856, 44); + RE(1073741857, 43); + RE(1073741938, 37); + RE(1073741939, 27); + RE(1073741858, 24); + RE(1073741859, 23); + RE(1073741860, 22); + RE(1073741861, 21); + RE(1073741862, 20); + RE(1073741863, 19); + RE(1073741864, 18); + RE(1073741865, 17); + RE(1073741866, 16); + RE(1073741867, 15); + YaccRows[113] := Row; + // [114] + R(0, 9, 16); + RE(1073741825, 47); + RE(1073741826, 42); + RE(1073741827, 41); + RE(1073741828, 40); + RE(1073741829, 39); + RE(1073741830, 34); + RE(1073741831, 29); + RE(1073741832, 22); + RE(1073741833, 11); + RE(1073741834, 8); + RE(1073741835, 7); + RE(1073741836, 6); + RE(1073741837, 5); + RE(1073741838, 4); + RE(1073741839, 3); + RE(1073741840, 2); + RE(17, 16401); + RE(18, 16398); + RE(19, 16395); + RE(20, 16394); + RE(21, 16390); + RE(22, 16389); + RE(23, 16388); + RE(24, 16387); + RE(118, 16385); + YaccRows[114] := Row; + // [115] + R(0, 10, 16); + RE(1073741825, 47); + RE(1073741826, 42); + RE(1073741827, 41); + RE(1073741828, 40); + RE(1073741829, 39); + RE(1073741830, 34); + RE(1073741831, 29); + RE(1073741832, 22); + RE(1073741833, 11); + RE(1073741834, 8); + RE(1073741835, 7); + RE(1073741836, 6); + RE(1073741837, 5); + RE(1073741838, 4); + RE(1073741839, 3); + RE(1073741840, 2); + RE(116, 16403); + RE(17, 16401); + RE(18, 16398); + RE(19, 16395); + RE(20, 16394); + RE(21, 16390); + RE(22, 16389); + RE(23, 16388); + RE(24, 16387); + RE(117, 16385); + YaccRows[115] := Row; + // [116] + R(0, 0, 1); + RE(536870961, 14); + YaccRows[116] := Row; + // [117] + R(0, 0, 18); + RE(536870960, 14); + RE(1073741852, 49); + RE(1073741853, 48); + RE(1073741854, 46); + RE(1073741855, 45); + RE(1073741856, 44); + RE(1073741857, 43); + RE(1073741939, 27); + RE(1073741858, 24); + RE(1073741859, 23); + RE(1073741860, 22); + RE(1073741861, 21); + RE(1073741862, 20); + RE(1073741863, 19); + RE(1073741864, 18); + RE(1073741865, 17); + RE(1073741866, 16); + RE(1073741867, 15); + YaccRows[117] := Row; + // [118] + R(0, 0, 17); + RE(536870962, 14); + RE(1073741852, 49); + RE(1073741853, 48); + RE(1073741854, 46); + RE(1073741855, 45); + RE(1073741856, 44); + RE(1073741857, 43); + RE(1073741858, 24); + RE(1073741859, 23); + RE(1073741860, 22); + RE(1073741861, 21); + RE(1073741862, 20); + RE(1073741863, 19); + RE(1073741864, 18); + RE(1073741865, 17); + RE(1073741866, 16); + RE(1073741867, 15); + YaccRows[118] := Row; + // [119] + R(0, 0, 27); + RE(536870958, 10); + RE(536870958, 12); + RE(536870958, 14); + RE(536870958, 15); + RE(536870958, 16); + RE(536870958, 17); + RE(536870958, 18); + RE(536870958, 19); + RE(536870958, 20); + RE(536870958, 21); + RE(536870958, 22); + RE(536870958, 23); + RE(536870958, 24); + RE(536870958, 25); + RE(536870958, 26); + RE(536870958, 27); + RE(536870958, 30); + RE(536870958, 31); + RE(536870958, 32); + RE(536870958, 37); + RE(536870958, 43); + RE(536870958, 44); + RE(536870958, 45); + RE(536870958, 46); + RE(536870958, 48); + RE(536870958, 49); + RE(536870958, -1); + YaccRows[119] := Row; + // [120] + R(0, 0, 27); + RE(536870949, 10); + RE(536870949, 12); + RE(536870949, 14); + RE(536870949, 15); + RE(536870949, 16); + RE(536870949, 17); + RE(536870949, 18); + RE(536870949, 19); + RE(536870949, 20); + RE(536870949, 21); + RE(536870949, 22); + RE(536870949, 23); + RE(536870949, 24); + RE(536870949, 25); + RE(536870949, 26); + RE(536870949, 27); + RE(536870949, 30); + RE(536870949, 31); + RE(536870949, 32); + RE(536870949, 37); + RE(536870949, 43); + RE(536870949, 44); + RE(536870949, 45); + RE(536870949, 46); + RE(536870949, 48); + RE(536870949, 49); + RE(536870949, -1); + YaccRows[120] := Row; + // [121] + R(0, 0, 1); + RE(1073741946, 51); + YaccRows[121] := Row; + // [122] + R(0, 0, 27); + RE(536870948, 10); + RE(536870948, 12); + RE(536870948, 14); + RE(536870948, 15); + RE(536870948, 16); + RE(536870948, 17); + RE(536870948, 18); + RE(536870948, 19); + RE(536870948, 20); + RE(536870948, 21); + RE(536870948, 22); + RE(536870948, 23); + RE(536870948, 24); + RE(536870948, 25); + RE(536870948, 26); + RE(536870948, 27); + RE(536870948, 30); + RE(536870948, 31); + RE(536870948, 32); + RE(536870948, 37); + RE(536870948, 43); + RE(536870948, 44); + RE(536870948, 45); + RE(536870948, 46); + RE(536870948, 48); + RE(536870948, 49); + RE(536870948, -1); + YaccRows[122] := Row; + // [123] + R(0, 0, 17); + RE(1073741852, 49); + RE(1073741853, 48); + RE(1073741854, 46); + RE(1073741855, 45); + RE(1073741856, 44); + RE(1073741857, 43); + RE(1073741858, 24); + RE(1073741859, 23); + RE(1073741860, 22); + RE(1073741861, 21); + RE(1073741862, 20); + RE(1073741863, 19); + RE(1073741864, 18); + RE(1073741865, 17); + RE(1073741866, 16); + RE(1073741867, 15); + RE(1073741948, 12); + YaccRows[123] := Row; + // [124] + R(0, 0, 27); + RE(536870941, 10); + RE(536870941, 12); + RE(536870941, 14); + RE(536870941, 15); + RE(536870941, 16); + RE(536870941, 17); + RE(536870941, 18); + RE(536870941, 19); + RE(536870941, 20); + RE(536870941, 21); + RE(536870941, 22); + RE(536870941, 23); + RE(536870941, 24); + RE(536870941, 25); + RE(536870941, 26); + RE(536870941, 27); + RE(536870941, 30); + RE(536870941, 31); + RE(536870941, 32); + RE(536870941, 37); + RE(536870941, 43); + RE(536870941, 44); + RE(536870941, 45); + RE(536870941, 46); + RE(536870941, 48); + RE(536870941, 49); + RE(536870941, -1); + YaccRows[124] := Row; + // [125] + R(0, 0, 25); + RE(536870931, 10); + RE(536870931, 12); + RE(536870931, 14); + RE(536870931, 15); + RE(536870931, 16); + RE(536870931, 17); + RE(536870931, 18); + RE(536870931, 19); + RE(536870931, 20); + RE(536870931, 21); + RE(536870931, 22); + RE(536870931, 27); + RE(536870931, 30); + RE(536870931, 31); + RE(536870931, 32); + RE(536870931, 37); + RE(536870931, 45); + RE(536870931, 46); + RE(536870931, 48); + RE(536870931, 49); + RE(536870931, -1); + RE(1073741856, 44); + RE(1073741857, 43); + RE(1073741858, 24); + RE(1073741859, 23); + YaccRows[125] := Row; + // [126] + R(0, 0, 17); + RE(1073741852, 49); + RE(1073741853, 48); + RE(1073741854, 46); + RE(1073741855, 45); + RE(1073741856, 44); + RE(1073741857, 43); + RE(1073741951, 30); + RE(1073741858, 24); + RE(1073741859, 23); + RE(1073741860, 22); + RE(1073741861, 21); + RE(1073741862, 20); + RE(1073741863, 19); + RE(1073741864, 18); + RE(1073741865, 17); + RE(1073741866, 16); + RE(1073741867, 15); + YaccRows[126] := Row; + // [127] + R(0, 9, 16); + RE(1073741825, 47); + RE(1073741826, 42); + RE(1073741827, 41); + RE(1073741828, 40); + RE(1073741829, 39); + RE(1073741830, 34); + RE(1073741831, 29); + RE(1073741832, 22); + RE(1073741833, 11); + RE(1073741834, 8); + RE(1073741835, 7); + RE(1073741836, 6); + RE(1073741837, 5); + RE(1073741838, 4); + RE(1073741839, 3); + RE(1073741840, 2); + RE(17, 16401); + RE(18, 16398); + RE(19, 16395); + RE(20, 16394); + RE(21, 16390); + RE(22, 16389); + RE(23, 16388); + RE(24, 16387); + RE(128, 16385); + YaccRows[127] := Row; + // [128] + R(0, 0, 17); + RE(1073741852, 49); + RE(1073741853, 48); + RE(1073741854, 46); + RE(1073741855, 45); + RE(1073741856, 44); + RE(1073741857, 43); + RE(1073741953, 31); + RE(1073741858, 24); + RE(1073741859, 23); + RE(1073741860, 22); + RE(1073741861, 21); + RE(1073741862, 20); + RE(1073741863, 19); + RE(1073741864, 18); + RE(1073741865, 17); + RE(1073741866, 16); + RE(1073741867, 15); + YaccRows[128] := Row; + // [129] + R(0, 9, 16); + RE(1073741825, 47); + RE(1073741826, 42); + RE(1073741827, 41); + RE(1073741828, 40); + RE(1073741829, 39); + RE(1073741830, 34); + RE(1073741831, 29); + RE(1073741832, 22); + RE(1073741833, 11); + RE(1073741834, 8); + RE(1073741835, 7); + RE(1073741836, 6); + RE(1073741837, 5); + RE(1073741838, 4); + RE(1073741839, 3); + RE(1073741840, 2); + RE(17, 16401); + RE(18, 16398); + RE(19, 16395); + RE(20, 16394); + RE(21, 16390); + RE(22, 16389); + RE(23, 16388); + RE(24, 16387); + RE(130, 16385); + YaccRows[129] := Row; + // [130] + R(0, 0, 17); + RE(1073741852, 49); + RE(1073741853, 48); + RE(1073741854, 46); + RE(1073741855, 45); + RE(1073741856, 44); + RE(1073741857, 43); + RE(1073741955, 32); + RE(1073741858, 24); + RE(1073741859, 23); + RE(1073741860, 22); + RE(1073741861, 21); + RE(1073741862, 20); + RE(1073741863, 19); + RE(1073741864, 18); + RE(1073741865, 17); + RE(1073741866, 16); + RE(1073741867, 15); + YaccRows[130] := Row; + // [131] + R(0, 0, 27); + RE(536870933, 10); + RE(536870933, 12); + RE(536870933, 14); + RE(536870933, 15); + RE(536870933, 16); + RE(536870933, 17); + RE(536870933, 18); + RE(536870933, 19); + RE(536870933, 20); + RE(536870933, 21); + RE(536870933, 22); + RE(536870933, 23); + RE(536870933, 24); + RE(536870933, 25); + RE(536870933, 26); + RE(536870933, 27); + RE(536870933, 30); + RE(536870933, 31); + RE(536870933, 32); + RE(536870933, 37); + RE(536870933, 43); + RE(536870933, 44); + RE(536870933, 45); + RE(536870933, 46); + RE(536870933, 48); + RE(536870933, 49); + RE(536870933, -1); + YaccRows[131] := Row; + // [132] + R(0, 0, 27); + RE(536870954, 10); + RE(536870954, 12); + RE(536870954, 14); + RE(536870954, 15); + RE(536870954, 16); + RE(536870954, 17); + RE(536870954, 18); + RE(536870954, 19); + RE(536870954, 20); + RE(536870954, 21); + RE(536870954, 22); + RE(536870954, 23); + RE(536870954, 24); + RE(536870954, 25); + RE(536870954, 26); + RE(536870954, 27); + RE(536870954, 30); + RE(536870954, 31); + RE(536870954, 32); + RE(536870954, 37); + RE(536870954, 43); + RE(536870954, 44); + RE(536870954, 45); + RE(536870954, 46); + RE(536870954, 48); + RE(536870954, 49); + RE(536870954, -1); + YaccRows[132] := Row; + // [133] + R(0, 0, 25); + RE(536870932, 10); + RE(536870932, 12); + RE(536870932, 14); + RE(536870932, 15); + RE(536870932, 16); + RE(536870932, 17); + RE(536870932, 18); + RE(536870932, 19); + RE(536870932, 20); + RE(536870932, 21); + RE(536870932, 22); + RE(536870932, 23); + RE(536870932, 24); + RE(536870932, 27); + RE(536870932, 30); + RE(536870932, 31); + RE(536870932, 32); + RE(536870932, 37); + RE(536870932, 43); + RE(536870932, 44); + RE(536870932, 45); + RE(536870932, 46); + RE(536870932, 48); + RE(536870932, 49); + RE(536870932, -1); + YaccRows[133] := Row; + + {$ENDREGION} + + RowArray := YaccRows; + ProdArray := YaccProds; +end; + + end. + diff --git a/Source/ObjectSpace/PessimisticLocking/BoldLockHandler.pas b/Source/ObjectSpace/PessimisticLocking/BoldLockHandler.pas index 923c2d3..486a2a5 100644 --- a/Source/ObjectSpace/PessimisticLocking/BoldLockHandler.pas +++ b/Source/ObjectSpace/PessimisticLocking/BoldLockHandler.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldLockHandler; interface @@ -14,8 +17,8 @@ interface BoldLockHolder; resourcestring - BOLD_GET_LOCKS_FAILED_ERROR = 'Failed to get locks'; - + BOLD_GET_LOCKS_FAILED_ERROR = '%s locked by %s'; + type TBoldFailureGetLocksFailed = class; @@ -59,7 +62,7 @@ TBoldEmptyLockHolder = class(TBoldAbstractLockHolder) function EnsureLocks: Boolean; override; procedure GetPropagationEvents(EventList: TStringList); override; end; - + {$IFNDEF BOLD_NO_QUERIES} TBoldPessimisticLockHandler = class(TBoldAbstractPessimisticLockHandler) private fRequiredShared: TBoldRegionList; @@ -70,7 +73,7 @@ TBoldPessimisticLockHandler = class(TBoldAbstractPessimisticLockHandler) fParentsChangedRegions: TBoldRegionList; fSubregionsChangedRegions: TBoldRegionList; fLockHolder: TBoldAbstractLockHolder; - fSubscriber: TBoldPassthroughSubscriber; + fSubscriber: TBoldExtendedPassthroughSubscriber; fOnActivityPropgress: TBoldLockManagerProgressEvent; fOnActivityStart: TNotifyEvent; fOnActivityEnd: TNotifyEvent; @@ -102,7 +105,7 @@ TBoldPessimisticLockHandler = class(TBoldAbstractPessimisticLockHandler) destructor Destroy; override; function LockElement(Element: TBoldDomainElement): Boolean; override; function EnsureLocks: Boolean; override; - procedure ReleaseUnneededRegions; override; + procedure ReleaseUnNeededRegions; override; property RequiredShared: TBoldRegionList read GetRequiredShared; property RequiredExclusive: TBoldRegionList read GetRequiredExclusive; property OnActivityStart: TNotifyEvent read fOnActivityStart write fOnActivityStart; @@ -110,6 +113,7 @@ TBoldPessimisticLockHandler = class(TBoldAbstractPessimisticLockHandler) property OnProgress: TBoldLockManagerProgressEvent read fOnActivityPropgress write fOnActivityPropgress; end; + {$ENDIF} implementation uses @@ -119,7 +123,6 @@ implementation BoldObjectSpaceExternalEvents, BoldDefaultID, BoldIndex, - HandlesConst, BoldElements; function NewRegionListFromStrings(Locks: TStrings; Factory: TBoldRegionFactory): TBoldRegionList; @@ -142,6 +145,7 @@ procedure RegionListToLockList(RegionList: TBoldRegionList; LockList: TBoldLockL { TBoldPessimisticLockHandler } +{$IFNDEF BOLD_NO_QUERIES} constructor TBoldPessimisticLockHandler.CreateWithLockHolder(System: TBoldSystem; LockHolder: TBoldAbstractLockHolder); begin inherited Create(System); @@ -154,13 +158,12 @@ constructor TBoldPessimisticLockHandler.CreateWithLockHolder(System: TBoldSystem fParentsChangedRegions := TBoldRegionList.Create; fSubregionsChangedRegions := TBoldRegionList.Create; - fSubscriber := TBoldPassthroughSubscriber.CreateWithReceiveAndAnswer(_ReceiveRolledBack, _AnswerMayCommit); + fSubscriber := TBoldExtendedPassthroughSubscriber.CreateWithReceiveAndAnswer(_ReceiveRolledBack, _AnswerMayCommit); System.AddSubscription(fSubscriber, bqMayCommit, bqMayCommit); System.AddSubscription(fSubscriber, beRolledBack, beRolledBack); System.PessimisticLockHandler := self; fLockHolder := LockHolder; - // this should be replaced with a subscription-mechanism Factory.OnRegionChanged := _RegionChanged; end; @@ -209,11 +212,9 @@ procedure TBoldPessimisticLockHandler.EnsureAllRequiredRegions; KnownRequiredOrHeldParentRegions.AddRegionLookup(fKnownRequiredParents); - // we know that the Explicit regions are ParentRegions... AddHeldLocksToRegionLookup(KnownRequiredOrHeldParentRegions, false); KnownRequiredOrHeldSubregions.AddRegionLookup(fKnownRequiredSubregions); - // we know that all held regions are atleast subregions... AddHeldLocksToRegionLookup(KnownRequiredOrHeldSubregions, true); Expander.ExpandParentRegions(RegionsToExpand, KnownRequiredOrHeldParentRegions, KnownRequiredOrHeldSubregions); @@ -252,12 +253,14 @@ function TBoldPessimisticLockHandler.GetRequiredLocks: Boolean; SharedLocks, ExclusiveLocks: TBoldLockList; HeldLocks, ClientsHoldingRequestedLocks: TStringList; ConflictingRegions: TBoldRegionList; + Clients: string; + Guard: IBoldGuard; begin + Guard := TBoldGuard.Create(SharedLocks, ExclusiveLocks, HeldLocks, ClientsHoldingRequestedLocks, ConflictingRegions); SharedLocks := TBoldLockList.Create; ExclusiveLocks := TBoldLockList.Create; HeldLocks := TStringList.Create; ClientsHoldingRequestedLocks := TStringList.Create; - try EnsureAllRequiredRegions; RegionListToLockList(fRequiredShared, SharedLocks); RegionListToLockList(fRequiredExclusive, ExclusiveLocks); @@ -279,14 +282,12 @@ function TBoldPessimisticLockHandler.GetRequiredLocks: Boolean; if not result then begin ConflictingRegions := NewRegionListFromStrings(HeldLocks, Factory); - SetBoldLastFailureReason(TBoldFailureGetLocksFailed.Create(BOLD_GET_LOCKS_FAILED_ERROR, nil, ConflictingRegions, ClientsHoldingRequestedLocks)); - ConflictingRegions.Free; - end; - finally - SharedLocks.Free; - ExclusiveLocks.Free; - FreeAndNil(HeldLocks); - FreeAndNil(ClientsHoldingRequestedLocks); + clients := ''; + if ClientsHoldingRequestedLocks.Count > 0 then + Clients := ClientsHoldingRequestedLocks.ValueFromIndex[0]; + SetBoldLastFailureReason(TBoldFailureGetLocksFailed.Create( + Format(BOLD_GET_LOCKS_FAILED_ERROR, [ConflictingRegions.AsString, clients]) + , nil, ConflictingRegions, ClientsHoldingRequestedLocks)); end; end; @@ -309,6 +310,7 @@ function TBoldPessimisticLockHandler.LockElement(Element: TBoldDomainElement): B for i := 0 to Regions.Count - 1 do RequireRegionExplicit(Regions[i]); +// REMOVED FOR TESTING if System.InTransaction then result := true else @@ -360,26 +362,28 @@ function TBoldPessimisticLockHandler.ArePropagationEventsInConflictWithRequiredR EventList: TStringList; i, j: integer; ClassName, MemberName, LockName: string; - ObjectID: TBoldDefaultID; + ObjectID, ExactId: TBoldDefaultID; EventType: TBoldObjectSpaceSubscriptionType; CurrObj: TBoldObject; CurrMember: TBoldMember; RegionList: TBoldRegionList; + Guard: IBoldGuard; begin + Guard := TBoldGuard.Create(EventList,ObjectId,ExactId,RegionList); Result := false; EventList := TStringList.Create; ObjectID:= TBoldDefaultID.CreateWithClassID(0, False); RegionList := TBoldRegionList.Create; - try fLockHolder.GetPropagationEvents(EventList); for i:= 0 to EventList.Count - 1 do begin EventType := TBoldObjectSpaceExternalEvent.DecodeExternalEvent(EventList[i], ClassName, MemberName, LockName, ObjectID); + ExactId := ObjectID.CloneWithClassId(System.BoldSystemTypeInfo.ClassTypeInfoByExpressionName[ClassName].TopSortedIndex, true) as TBoldDefaultID; case EventType of bsClassChanged:; bsEmbeddedStateOfObjectChanged: begin - CurrObj := System.EnsuredLocatorByID[ObjectID].EnsuredBoldObject; + CurrObj := System.EnsuredLocatorByID[ExactId].EnsuredBoldObject; for j:= 0 to CurrObj.BoldMemberCount - 1 do begin CurrMember := CurrObj.BoldMembers[j]; @@ -390,18 +394,13 @@ function TBoldPessimisticLockHandler.ArePropagationEventsInConflictWithRequiredR end; bsNonEmbeddedStateOfObjectChanged: begin - CurrObj := System.EnsuredLocatorByID[ObjectID].EnsuredBoldObject; + CurrObj := System.EnsuredLocatorByID[ExactId].EnsuredBoldObject; CurrMember := CurrObj.BoldMemberByExpressionName[MemberName]; result := IsElementInAnyRequiredRegion(CurrMember); end; end; if result then Break; end; - finally - FreeAndNil(EventList); - FreeAndNil(ObjectID); - FreeAndNil(RegionList); - end; end; function TBoldPessimisticLockHandler.IsElementInAnyRequiredRegion( @@ -432,16 +431,19 @@ procedure TBoldPessimisticLockHandler.ReleaseUnNeededRegions; UnRequiredLocks, RequiredExclusiveLocks, RequiredSharedLocks: TBoldLockList; LockName: string; TrueLockHolder: TBoldAbstractLockHolder; + Guard: IBoldGuard; begin - Elements := TList.Create; + Guard := TBoldGuard.Create(Elements, UnRequiredLocks, RequiredExclusiveLocks, RequiredSharedLocks, aTraverser); UnRequiredLocks := TBoldLockList.Create; RequiredSharedLocks := TBoldLockList.Create; RequiredExclusiveLocks := TBoldLockList.Create; TrueLockHolder := fLockHolder; try - aTraverser := fLockHolder.HeldExclusive.CreateTraverser; - try - while not aTraverser.EndOfList do + if fLockHolder.HeldExclusive.Count > 0 then + begin + Elements := TList.Create; + aTraverser := fLockHolder.HeldExclusive.CreateTraverser; + while aTraverser.MoveNext do begin LockName := (aTraverser.Item as TBoldLock).Name; if LockName <> BOLD_DBLOCK_NAME then @@ -452,16 +454,11 @@ procedure TBoldPessimisticLockHandler.ReleaseUnNeededRegions; if ElementListContainsDirtyElements(Elements) then RequireRegionExplicit(CurrentRegion); end; - aTraverser.Next; end; - finally - aTraverser.Free; end; - // since the regionExpander will cut the expansion tree with the held locks, we need to fake - // an empty lockholder for this excersise. The expansion will occur in the getmethod of RequiredExclusive and RequiredShared... fLockHolder := TBoldEmptyLockHolder.Create; - + RegionListToLockList(RequiredExclusive, RequiredExclusiveLocks); RegionListToLockList(RequiredShared, RequiredSharedLocks); @@ -475,11 +472,7 @@ procedure TBoldPessimisticLockHandler.ReleaseUnNeededRegions; fLockHolder.Release(UnRequiredLocks); finally - FreeAndNil(Elements); - FreeAndNil(UnRequiredLocks); - FreeAndNil(RequiredSharedLocks); - FreeAndNil(RequiredExclusiveLocks); - fLockHolder := TrueLockHolder; // Just in case + fLockHolder := TrueLockHolder; end; end; @@ -590,14 +583,12 @@ procedure TBoldPessimisticLockHandler.AddHeldLocksToRegionLookup(RegionLookup: T begin Guard := TBoldGuard.CReate(Traverser); Traverser := List.CreateTraverser; - while not Traverser.EndOfList do + while Traverser.MoveNext do begin RegionId := (Traverser.Item as TBoldLock).Name; - // Only check locks that are region-locks if (pos('.', RegionId) <> 0) then if not assigned(RegionLookup.FindByID(RegionId)) then RegionLookup.Add(Factory.GetRegionByName(RegionId)); - Traverser.Next; end; end; @@ -606,7 +597,7 @@ procedure TBoldPessimisticLockHandler.AddHeldLocksToRegionLookup(RegionLookup: T if AddSharedRegions then Add(fLockHolder.HeldShared); end; - + {$ENDIF} { TBoldFailureGetLocksFailed } @@ -656,7 +647,7 @@ destructor EBoldGetLocksFailed.Destroy; end; -{ TBoldEmptyLockHolder } + { BoldEmptyLockHolder } constructor TBoldEmptyLockHolder.Create; begin diff --git a/Source/ObjectSpace/PessimisticLocking/BoldLockHolder.pas b/Source/ObjectSpace/PessimisticLocking/BoldLockHolder.pas index 467edfb..fe589f4 100644 --- a/Source/ObjectSpace/PessimisticLocking/BoldLockHolder.pas +++ b/Source/ObjectSpace/PessimisticLocking/BoldLockHolder.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldLockHolder; interface @@ -17,13 +20,12 @@ interface TBoldLock = class; TBoldLockList = class; TBoldLockHolder = class; -// TBoldDatabaseLock = class; TBoldLock = class(TBoldMemoryManagedObject) private fName: string; public - constructor Create(Name: string); + constructor Create(const Name: string); property Name: string read fName; end; @@ -36,16 +38,16 @@ { TBoldDatabaseLock = class(TBoldLock) } TBoldLockList = class(TBoldStringHashIndex) protected - function ItemAsKeyString(Item: TObject): string; override; + function ItemASKeyString(Item: TObject): string; override; public destructor Destroy; override; procedure Add(Item: TObject); override; procedure AddList(List: TBoldLockList); - procedure AddLock(Name: string); + procedure AddLock(const Name: string); function AsOLEVariant: OleVariant; - function Includes(Name: string): Boolean; + function Includes(const Name: string): Boolean; procedure RemoveList(List: TBoldLockList); - procedure RemoveLock(Name: string); + procedure RemoveLock(const Name: string); end; TBoldAbstractLockHolder = class(TBoldMemoryManagedObject) @@ -72,7 +74,7 @@ TBoldLockHolder = class(TBoldAbstractLockHolder) fDequeuer: TBoldAbstractDequeuer; procedure WaitForWakeup; procedure WakeUp; - function _ListenerMessage(Msg: string): Boolean; + function _ListenerMessage(const Msg: string): Boolean; protected function GetHeldExclusive: TBoldLockList; override; function GetHeldShared: TBoldLockList; override; @@ -82,12 +84,13 @@ TBoldLockHolder = class(TBoldAbstractLockHolder) function Lock(Shared: TBoldLockList; Exclusive: TBoldLockList; HeldLocks, ClientsHoldingRequestedLocks: TStringList): Boolean; override; procedure Release(Locks: TBoldLockList); override; function EnsureLocks: Boolean; override; - function LockDatabase: Boolean; + function LockDatabase: Boolean; procedure GetPropagationEvents(EventList: TStringList); override; property TimeOut: Integer read fTimeOut write fTimeOut; property LockManager: IBoldLockManager read fLockManager write fLockManager; end; + implementation uses @@ -97,8 +100,8 @@ implementation BoldIndex, BoldLockingDefs, BoldObjectSpaceExternalEvents, - BoldDefaultID, - BoldCoreConsts; + BoldDefaultID + ; { TBoldLockHolder } @@ -144,7 +147,7 @@ function TBoldLockHolder.GetHeldShared: TBoldLockList; procedure TBoldLockHolder.GetPropagationEvents(EventList: TStringList); begin - fListener.Queue.AppendToStringList(EventList); + fListener.InQueue.AppendToStringList(EventList); end; function TBoldLockHolder.Lock(Shared: TBoldLockList; Exclusive: TBoldLockList; HeldLocks, ClientsHoldingRequestedLocks: TStringList): Boolean; @@ -166,7 +169,6 @@ function TBoldLockHolder.Lock(Shared: TBoldLockList; Exclusive: TBoldLockList; H WaitForWakeup; fHeldShared.AddList(Shared); fHeldExclusive.AddList(Exclusive); - // upgrade shared locks that we now aquired as exclusive fHeldShared.RemoveList(Exclusive); end else @@ -185,7 +187,7 @@ function TBoldLockHolder.LockDatabase: Boolean; ConflictingUsers: TStringList; begin if not assigned(fDequeuer) then - raise EBold.CreateFmt(sNoDequeuerAvailable, [classname]); + raise EBold.CreateFmt('%s.LockDatabase: there is no dequeuer available', [classname]); SharedLocks := TBoldLockList.Create; ExclusiveLocks := TBoldLockList.Create; Conflicts := TStringList.Create; @@ -217,7 +219,7 @@ procedure TBoldLockHolder.Release(Locks: TBoldLockList); procedure TBoldLockHolder.WaitForWakeup; begin if fWakeUpEvent.WaitFor(Timeout) <> wrSignaled then - raise EBold.CreateFmt(sOperationTimedOut, [ClassName]); + raise EBold.CreateFmt('%s.WaitForWakeUp: Operation timed out', [ClassName]); fWakeUpEvent.ResetEvent; end; @@ -226,7 +228,7 @@ procedure TBoldLockHolder.WakeUp; fWakeUpEvent.SetEvent; end; -function TBoldLockHolder._ListenerMessage(Msg: string): Boolean; +function TBoldLockHolder._ListenerMessage(const Msg: string): Boolean; var ClassName, MemberName, LockName: string; begin @@ -240,7 +242,7 @@ function TBoldLockHolder._ListenerMessage(Msg: string): Boolean; { TBoldLock } -constructor TBoldLock.Create(Name: string); +constructor TBoldLock.Create(const Name: string); begin fName := Name; end; @@ -250,7 +252,7 @@ constructor TBoldLock.Create(Name: string); procedure TBoldLockList.Add(Item: TObject); begin if not (Item is TBoldLock) then - raise EBold.CreateFmt(sWrongItemType, [classname, Item.classname]); + raise EBold.CreateFmt('%s.Add: Item should be TBoldLock, but is %s', [classname, Item.classname]); inherited; end; @@ -258,19 +260,18 @@ procedure TBoldLockList.AddList(List: TBoldLockList); var aTraverser: TBoldIndexTraverser; begin + if List.Count = 0 then + exit; aTraverser := List.CreateTraverser; try - while not aTraverser.EndOfList do - begin + while aTraverser.MoveNext do AddLock(TBoldLock(aTraverser.Item).Name); - aTraverser.Next; - end; finally aTraverser.Free; end; end; -procedure TBoldLockList.AddLock(Name: string); +procedure TBoldLockList.AddLock(const Name: string); begin if not Includes(Name) then Add(TBoldLock.Create(Name)); @@ -285,24 +286,23 @@ function TBoldLockList.AsOLEVariant: OleVariant; aTraverser := CreateTraverser; try i := 0; - while not aTraverser.EndOfList do + while aTraverser.MoveNext do begin result[i] := (aTraverser.Item as TBoldLock).Name; inc(i); - aTraverser.Next; end; finally aTraverser.Free; end; end; -destructor TBoldLockList.Destroy; +destructor TBoldLockList.destroy; begin Clear(True); inherited; end; -function TBoldLockList.Includes(Name: string): Boolean; +function TBoldLockList.Includes(const Name: string): Boolean; begin result := assigned(FindByString(Name)); end; @@ -317,30 +317,27 @@ procedure TBoldLockList.RemoveList(List: TBoldLockList); aTraverser: TBoldIndexTraverser; aLock: TBoldLock; begin + if (count = 0) or (List.Count = 0) then + exit; if List.Count > Count then begin aTraverser := CreateTraverser; - while not aTraverser.EndOfList do - begin - aLock := aTraverser.Item as TBoldLock; - aTraverser.Next; - if List.Includes(aLock.Name) then - RemoveLock(aLock.Name); - end; + while aTraverser.MoveNext do // double while loop is needed as removing from traversing list moves to next item automatically on remove + while Assigned(aTraverser.Item) and List.Includes((aTraverser.Item as TBoldLock).Name) do + RemoveLock((aTraverser.Item as TBoldLock).Name); aTraverser.Free; end else begin aTraverser := List.CreateTraverser; - while not aTraverser.EndOfList do + while aTraverser.MoveNext do begin RemoveLock((aTraverser.Item as TBoldLock).Name); - aTraverser.Next; end; aTraverser.Free; end; end; -procedure TBoldLockList.RemoveLock(Name: string); +procedure TBoldLockList.RemoveLock(const Name: string); var Item: TObject; begin @@ -365,4 +362,6 @@ constructor TBoldDatabaseLock.Create; inherited Create(TBoldObjectSpaceExternalEvent.EncodeExternalEvent(bsDBLock, '', '', '', nil)); end; } +initialization + end. diff --git a/Source/ObjectSpace/PessimisticLocking/BoldLockRegions.pas b/Source/ObjectSpace/PessimisticLocking/BoldLockRegions.pas index 16f0dd1..8ca8ca0 100644 --- a/Source/ObjectSpace/PessimisticLocking/BoldLockRegions.pas +++ b/Source/ObjectSpace/PessimisticLocking/BoldLockRegions.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldLockRegions; interface @@ -9,14 +12,11 @@ interface BoldSystemRT, BoldDefs, BoldBase, - BoldElements, - BoldGuard, BoldDomainElement, BoldRegionDefinitions, BoldLogHandler, BoldIndexableList; - const breNone = 0; breParentsChanged = 1; @@ -72,13 +72,26 @@ TBoldRegionFactory = class(TBoldAbstractRegionFactory) property OnRegionChanged: TBoldRegionEvent read fOnRegionChanged write fOnRegionChanged; end; + TBoldRegionLookupTraverser = class(TBoldIndexableListTraverser) + private + function GetRegion: TBoldRegion; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + public + property Region: TBoldRegion read GetRegion; + property Current: TBoldRegion read GetRegion; + end; + TBoldRegionLookup = class(TBoldUnOrderedIndexableList) private + class var IX_RegionId: integer; procedure ExpandOneLevelRegionsForNavigation(Regions: TBoldRegionLookup; Navigation: TBoldRoleRTInfo; CoreDef: TBoldRegionCoreDefinition; AlreadyExpandedRegions, AlreadyKnownRegions: TBoldregionLookup); procedure AddIfNotInLookup(Region: TBoldRegion); + protected + function TraverserClass: TBoldIndexableListTraverserClass; override; public constructor Create; - function FindByID(RegionId: string): TBoldRegion; + function CreateTraverser: TBoldRegionLookupTraverser; + function GetEnumerator: TBoldRegionLookupTraverser; + function FindByID(RegionId: string): TBoldRegion; {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure AddRegionLookup(Regions: TBoldRegionLookup); procedure AddRegionLookupWithFilter(Regions: TBoldRegionLookup; Filter: TBoldRegionLookup); procedure AddRegionList(Regions: TBoldRegionList); @@ -89,7 +102,8 @@ TBoldRegionLookup = class(TBoldUnOrderedIndexableList) TBoldOrderedRegionLookup = class(TBoldRegionLookup) private - function GetFirstRegion: TBoldRegion; + class var IX_RegionOrder: integer; + function GetFirstRegion: TBoldRegion; {$IFDEF BOLD_INLINE} inline; {$ENDIF} public constructor Create; property FirstRegion: TBoldRegion read GetFirstRegion; @@ -99,12 +113,13 @@ TBoldOrderedRegionLookup = class(TBoldRegionLookup) TBoldRegionList = class(TList) private function GetItems(i: Integer): TBoldRegion; + function GetAsString: string; public procedure AddList(List: TBoldRegionList); procedure AddRegionLookup(Regions: TBoldRegionLookup); procedure Assign(List: TBoldRegionList); -// procedure EnsureSubRegionObjects; property Items[i: Integer]: TBoldRegion read GetItems; default; + property AsString: string read GetAsString; end; { TBoldRegionState = @@ -128,10 +143,13 @@ TBoldRegionExpander = class(TBoldMemoryManagedObject) destructor Destroy; override; procedure ExpandParentRegions(RegionsToExpand: TBoldRegionLookup; KnownParentRegions, KnownSubregions: TBoldRegionLookup); procedure ExpandSubregions(RegionsToExpand: TBoldRegionLookup; KnownSubregions: TBoldregionLookup); + procedure ExpandRegionEnclosure(Regions: TBoldRegionLookup); + property NewParentRegions: TBoldRegionLookup read fNewParentRegions; property NewSubRegions: TBoldRegionLookup read fNewSubRegions; property OnProgress: TBoldLockManagerProgressEvent read fOnActivityProgress write fOnActivityProgress; + end; var @@ -141,24 +159,21 @@ implementation uses SysUtils, - BoldUtils, - BoldIndex, - BoldId, BoldDefaultId, + BoldElements, + BoldGuard, BoldHashIndexes, - BoldCoreConsts; - -var - IX_RegionId: integer = -1; - IX_RegionOrder: integer = -1; - + BoldId, + BoldIndex, + BoldRev; type TBoldRegionIndex = class(TBoldStringHashIndex) protected - function ItemAsKeyString(Item: TObject): string; override; + function ItemASKeyString(Item: TObject): string; override; end; + procedure NavigateAndSubscribe(Obj: TBoldObject; RoleRT: TBoldRoleRtInfo; ResultElement: TBoldIndirectElement; Subscriber: TBoldSubscriber; RequestedEvent: Integer); var aMember: TBoldMember; @@ -170,7 +185,7 @@ procedure NavigateAndSubscribe(Obj: TBoldObject; RoleRT: TBoldRoleRtInfo; Result if (aMember is TBoldObjectList) or (aMember is TBoldObjectReference) then AMember.GetAsList(ResultElement) else - raise EBoldInternal.CreateFmt(sTriedToNavigateNonAssociation, [Obj.BoldClassTypeInfo.ExpressionName, aMember.BoldMemberRTInfo.ExpressionName]); + raise EBoldInternal.CreateFmt('Tried to navigate %s.%s that is not an association', [Obj.BoldClassTypeInfo.ExpressionName, aMember.BoldMemberRTInfo.ExpressionName]); if assigned(Subscriber) then aMember.DefaultSubscribe(Subscriber, RequestedEvent); end @@ -192,6 +207,19 @@ procedure DoNavigationAndSubscribe(Obj: TBoldObject; Navigation: TBoldRoleRTInfo NavigateAndSubscribe(Obj, Navigation, ResultElement, Subscriber, RequestedEvent); end; +{ TBoldOrderedRegionLookup } + +constructor TBoldOrderedRegionLookup.Create; +begin + inherited; + SetIndexVariable(IX_RegionOrder, AddIndex(TBoldIntegerIndex.Create)); +end; + +function TBoldOrderedRegionLookup.GetFirstRegion: TBoldRegion; +begin + Result := (Indexes[IX_RegionOrder] as TBoldIntegerIndex).items[0] as TBoldRegion; +end; + { TBoldRegion } constructor TBoldRegion.Create(Definition: TBoldConcreteRegionDefinition; @@ -202,12 +230,10 @@ constructor TBoldRegion.Create(Definition: TBoldConcreteRegionDefinition; fFactory := Factory; fDefinition := Definition; PlaceRootSubscriptions; -// BoldLog.Log('RegConstr: '+AsString + ':' + RootLocator.BoldObject.ClassName + ':'+IntTOStr(Integer(Self))); end; destructor TBoldRegion.Destroy; begin -// BoldLog.Log('RegDestr: '+AsString + ':' + RootLocator.BoldObject.ClassName + ':'+IntTOStr(Integer(Self))); fRootLocator := nil; inherited; end; @@ -265,7 +291,7 @@ function TBoldRegion.GetAsString: string; if assigned(RootLocator) and assigned(RootLocator.BoldObjectID) then result := fFactory.RegionId(Definition.CoreDefinition, RootLocator) else - raise EBoldInternal.CreateFmt(sRegionMissingIDOrLocator, [ClassName]); + raise EBoldInternal.Create('TBoldRegion.GetAsString: Region is missing either a locator or an ID'); end; procedure TBoldRegion.GetElements(ResultList: TList); @@ -292,15 +318,13 @@ procedure TBoldRegion.Receive(Originator: TObject; OriginalEvent: TBoldEvent; Re if (Originator is TBoldObject) and not assigned(TBoldObject(Originator).BoldObjectLocator) and not assigned(RootLocator.BoldObject) then begin - // The object has been destroyed without getting a proper locator. - // We must be very careful. + fFactory.fLookup.ItemChanged(self); fFactory.fLookup.Remove(self); end else if (Originator = Root) then begin case OriginalEvent of - // removing the region form the factory lookup will destroy it automatically beDestroying: fFactory.fLookup.Remove(self); @@ -319,6 +343,21 @@ procedure TBoldRegion.Receive(Originator: TObject; OriginalEvent: TBoldEvent; Re end; end; +function TBoldRegionLookup.FindByID(RegionId: string): TBoldRegion; +begin + result := (Indexes[IX_RegionId] as TBoldStringHashIndex).FindByString(RegionId) as TBoldRegion; +end; + +function TBoldRegionLookup.GetEnumerator: TBoldRegionLookupTraverser; +begin + result := CreateTraverser as TBoldRegionLookupTraverser; +end; + +function TBoldRegionLookup.TraverserClass: TBoldIndexableListTraverserClass; +begin + result := TBoldRegionLookupTraverser; +end; + { TBoldRegionFactory } function TBoldRegionFactory.CoreDefintionFromRegionId( @@ -326,7 +365,7 @@ function TBoldRegionFactory.CoreDefintionFromRegionId( begin result := fDefinitions.CoreDefinition[Copy(RegionId, Pos('.', RegionId)+1, MaxInt)]; if not assigned(Result) then - raise EBoldInternal.CreateFmt(sBadRegionID, [classname, 'CoreDefintionFromRegionId', RegionId]); // do not localize + raise EBoldInternal.CreateFmt('%s.CoreDefinitionFromRegionId: Erroneous RegionId %s', [classname, RegionId]); end; constructor TBoldRegionFactory.Create(Definitions: TBoldRegionDefinitions); @@ -343,6 +382,7 @@ destructor TBoldRegionFactory.Destroy; inherited; end; + function TBoldRegionFactory.GetRegion( Definition: TBoldRegionCoreDefinition; RootLocator: TBoldObjectLocator): TBoldRegion; var @@ -353,7 +393,7 @@ function TBoldRegionFactory.GetRegion( begin ConcreteDef := Definition.ConcreteDefinitions.FindByRootClass(RootLocator.EnsuredBoldObject.BoldClassTypeInfo); if not assigned(ConcreteDef) then - raise EBold.CreateFmt(sBadRegionDefinition, [classname, Definition.Name, RootLocator.EnsuredBoldObject.BoldClassTypeInfo.ExpressionName]); + raise EBold.CreateFmt('%s.GetRegion: Erroneous region definitions. The region %s does not have %s as root class.', [classname, Definition.Name, RootLocator.EnsuredBoldObject.BoldClassTypeInfo.ExpressionName]); result := TBoldRegion.Create(ConcreteDef, RootLocator, Self); fLookup.Add(result); end; @@ -403,7 +443,7 @@ function TBoldRegionFactory.RegionId(Definition: TBoldRegionCoreDefinition; begin result := RootLocator.BoldObjectID.AsString + '.' + Definition.Name; if RootLocator.BoldObjectID is TBoldInternalObjectId then - result := 'i' + Result; + result := 'i' + Result; end; function TBoldRegionFactory.RootObjectLocatorFromRegionId(RegionId: string): TBoldObjectLocator; @@ -418,13 +458,13 @@ function TBoldRegionFactory.RootObjectLocatorFromRegionId(RegionId: string): TBo begin AsInt := StrToIntDef(Copy(RegionId, 2, Pos('.', RegionId)-1), -1); if AsInt = -1 then - raise EBoldInternal.CreateFmt(sBadRegionID, [classname, 'RootObjectFromRegionId', RegionId]); // do not localize + raise EBoldInternal.CreateFmt('%s.RootObjectFromRegionId: Erroneous RegionId %s', [classname, RegionId]); ObjId := TBoldInternalObjectId.CreateWithClassIDandInternalId(AsInt, 0, false); end else begin AsInt := StrToIntDef(Copy(RegionId, 1, Pos('.', RegionId)-1), -1); if AsInt = -1 then - raise EBoldInternal.CreateFmt(sBadRegionID, [classname, 'RootObjectFromRegionId', RegionId]); // do not localize + raise EBoldInternal.CreateFmt('%s.RootObjectFromRegionId: Erroneous RegionId %s', [classname, RegionId]); ObjId := TBoldDefaultID.CreateWithClassID(0, false); (ObjId as TBoldDefaultId).AsInteger := AsInt; end; @@ -443,20 +483,12 @@ function TBoldRegionIndex.ItemASKeyString(Item: TObject): string; { TBoldRegionLookup } -procedure TBoldRegionLookup.AddRegionLookup(Regions: TBoldregionLookup); +procedure TBoldRegionLookup.AddRegionLookup(Regions: TBoldRegionLookup); var - Traverser: TBoldIndexableListTraverser; + Region: TBoldRegion; begin - Traverser := Regions.CreateTraverser; - try - while not Traverser.EndOfList do - begin - AddIfNotInLookup(Traverser.Item as TBoldRegion); - Traverser.Next; - end; - finally - Traverser.Free; - end; + for Region in Regions do + AddIfNotInLookup(Region); end; constructor TBoldRegionLookup.Create; @@ -464,20 +496,18 @@ constructor TBoldRegionLookup.Create; SetIndexVariable(IX_RegionId, AddIndex(TBoldRegionIndex.Create)); end; +function TBoldRegionLookup.CreateTraverser: TBoldRegionLookupTraverser; +begin + result := TBoldRegionLookupTraverser(inherited CreateTraverser); + Assert(Result is TBoldRegionLookupTraverser); +end; + procedure TBoldRegionLookup.FillObjectList(ObjectList: TBoldObjectList); var - Traverser: TBoldIndexableListTraverser; + Region: TBoldRegion; begin - Traverser := CreateTraverser; - try - while not Traverser.EndOfList do - begin - ObjectList.AddLocator((Traverser.Item as TBoldRegion).RootLocator); - Traverser.Next; - end; - finally - Traverser.Free; - end; + for Region in self do + ObjectList.AddLocator(Region.RootLocator); end; procedure TBoldRegionLookup.FetchAndExpandOneLevelParentRegions(ParentRegions: TBoldRegionLookup; AlreadyExpandedRegions, AlreadyKnownRegions: TBoldRegionLookup); @@ -518,10 +548,11 @@ procedure TBoldRegionLookup.FetchAndExpandOneLevelParentRegions(ParentRegions: T assert(ReverseRole.RoleType = rtLinkRole); end; else - raise EBoldInternal.CreateFmt(sUnknownRoleType, [ClassName, Navigation.AsString]); + raise EBoldInternal.CreateFmt('%s.FetchAndExpandOneLevelParentRegions: unknown roletype of role %s', [ + ClassName, Navigation.AsString]); end; assert(ConcreteDef.RootClass.Conformsto(ReverseRole.ClassTypeInfo)); - assert(ObjectList[0].BOldClassTypeInfo.Conformsto(ReverseRole.ClassTypeInfo)); + assert(ObjectList[0].BoldClassTypeInfo.ConformsTo(ReverseRole.ClassTypeInfo)); ObjectList[0].BoldSystem.FetchLinksWithObjects(ObjectList, ReverseRole.ExpressionName); ExpandOneLevelRegionsForNavigation(ParentRegions, ReverseRole, SubRegionRef.ParentRegion.CoreDefinition, AlreadyExpandedRegions, AlreadyKnownRegions); @@ -529,6 +560,7 @@ procedure TBoldRegionLookup.FetchAndExpandOneLevelParentRegions(ParentRegions: T end; end; + procedure TBoldRegionLookup.FetchAndExpandOneLevelSubRegions(SubRegions: TBoldRegionLookup; AdditionalRegions: TBoldRegionLookup; AlreadyExpandedRegions, AlreadyKnownRegions: TBoldregionLookup); procedure MassiveFetch(System: TBoldSystem; ObjectList: TBoldObjectList; RoleRTInfo: TBoldRoleRTInfo ); var @@ -539,7 +571,6 @@ procedure TBoldRegionLookup.FetchAndExpandOneLevelSubRegions(SubRegions: TBoldRe FetchNeeded: Boolean; i: integer; begin - // first, check if we actually need to fetch anything right now TempObjectLIst := ObjectLIst.Clone as TBoldObjectList; try FetchNeeded := false; @@ -551,26 +582,23 @@ procedure TBoldRegionLookup.FetchAndExpandOneLevelSubRegions(SubRegions: TBoldRe if FetchNeeded then begin - // If we need to fetch any relations in the original set, then add all the unprocessed objects - // that have the same link. + DefiningClass := RoleRTINfo.ClassTypeInfo; while DefiningClass.FirstOwnMemberIndex > RoleRTInfo.index do DefiningClass := DefiningClass.SuperClassTypeInfo; Traverser := AdditionalRegions.CreateTraverser; try - while not Traverser.EndOfList do + while Traverser.MoveNext do begin aRegion := Traverser.Item as TBoldRegion; if aRegion.fDefinition.RootClass.ConformsTo(DefiningClass) then TempObjectList.AddLocator(aRegion.RootLocator); - Traverser.Next; end; finally Traverser.Free; end; end; - // even if the links are fetched, the objects might not be, so we better call FetchLinksWithObjects anyway. System.FetchLinksWithObjects(TempObjectList, RoleRTInfo.ExpressionName); finally TempObjectList.Free; @@ -601,11 +629,6 @@ procedure TBoldRegionLookup.FetchAndExpandOneLevelSubRegions(SubRegions: TBoldRe end; end; -function TBoldRegionLookup.FindByID(RegionId: string): TBoldRegion; -begin - result := (Indexes[IX_RegionId] as TBoldRegionIndex).FindByString(RegionId) as TBoldRegion; -end; - procedure TBoldRegionLookup.ExpandOneLevelRegionsForNavigation(Regions: TBoldRegionLookup; Navigation: TBoldRoleRTInfo; CoreDef: TBoldRegionCoreDefinition; AlreadyExpandedRegions, AlreadyKnownRegions: TBoldRegionLookup); procedure ExpandRegion(Region: TBoldRegion); @@ -630,7 +653,7 @@ procedure TBoldRegionLookup.ExpandOneLevelRegionsForNavigation(Regions: TBoldReg Regions.AddIfNotInLookup(NewRegion); end; if (Regions.Count > OldRegionsCount) and assigned(BoldRegionExpansionDebugLogHandler) then - BoldRegionExpansionDebugLogHandler.LogFmt(sLogAddedRegions, [ + BoldRegionExpansionDebugLogHandler.LogFmt('%s.%s Added Regions: %d', [ Region.Root.BoldClassTypeInfo.ExpressionName, Navigation.ExpressionName, Regions.Count - OldRegionsCount]); @@ -641,18 +664,10 @@ procedure TBoldRegionLookup.ExpandOneLevelRegionsForNavigation(Regions: TBoldReg end; var - Traverser: TBoldIndexableListTraverser; + Region: TBoldRegion; begin - Traverser := CreateTraverser; - try - while not Traverser.EndOfList do - begin - ExpandRegion(Traverser.Item as TBoldRegion); - Traverser.Next; - end; - finally - Traverser.Free; - end; + for Region in self do + ExpandRegion(Region); end; procedure TBoldRegionLookup.AddRegionList(Regions: TBoldRegionList); @@ -672,19 +687,11 @@ procedure TBoldRegionLookup.AddIfNotInLookup(Region: TBoldRegion); procedure TBoldRegionLookup.AddRegionLookupWithFilter(Regions, Filter: TBoldRegionLookup); var - Traverser: TBoldIndexableListTraverser; - Guard: IBoldGuard; Region: TBoldRegion; begin - Guard := TBoldGuard.Create(Traverser); - Traverser := Regions.CreateTraverser; - while not Traverser.EndOfList do - begin - Region := Traverser.Item as TBoldRegion; + for Region in Regions do if not assigned(Filter.FindById(Region.AsString)) then AddIfNotInLookup(Region); - Traverser.Next; - end; end; { TBoldRegionList } @@ -700,18 +707,10 @@ procedure TBoldRegionList.AddList(List: TBoldRegionList); procedure TBoldRegionList.AddRegionLookup(Regions: TBoldRegionLookup); var - Traverser: TBoldIndexableListTraverser; + Region: TBoldRegion; begin - Traverser := Regions.CreateTraverser; - try - while not Traverser.EndOfList do - begin - Add(Traverser.Item as TBoldRegion); - Traverser.Next; - end; - finally - Traverser.Free; - end; + for Region in Regions do + Add(Region); end; procedure TBoldRegionList.Assign(List: TBoldRegionList); @@ -762,6 +761,22 @@ procedure TBoldRegionList.Assign(List: TBoldRegionList); end; } +function TBoldRegionList.GetAsString: string; +var + sl: TStringList; + i: integer; +begin + result := ''; + sl := TStringList.Create; + try + for I := 0 to Count - 1 do + sl.Add(self[i].Root.DebugInfo); + finally + result := sl.CommaText; + sl.free; + end; +end; + function TBoldRegionList.GetItems(i: Integer): TBoldRegion; begin result := TObject(inherited Items[i]) as TBoldRegion; @@ -777,7 +792,7 @@ procedure TBoldRegionExpander.Clear; fToBeParentExpanded.Clear; end; -constructor TBoldRegionExpander.create; +constructor TBoldRegionExpander.Create; begin inherited; fNewParentRegions := TBoldRegionLookup.Create; @@ -787,7 +802,7 @@ constructor TBoldRegionExpander.create; fToBeParentExpanded := TBoldOrderedRegionLookup.Create; end; -destructor TBoldRegionExpander.destroy; +destructor TBoldRegionExpander.Destroy; begin FreeAndNil(fNewParentRegions); FreeAndNil(fNewSubregions); @@ -796,8 +811,6 @@ destructor TBoldRegionExpander.destroy; inherited; end; - - { procedure TBoldRegionExpander.ExpandSubAndParentRegions(ExplicitRegions: TBoldRegionList); begin @@ -813,21 +826,18 @@ procedure TBoldRegionExpander.ExpandSubAndParentRegions(ExplicitRegions: TBoldRe procedure TBoldRegionExpander.ExtractSimilarRegions(Regions: TBoldRegionLookup; Region: TBoldRegion; Result: TBoldRegionLookup); var - aRegion: TBoldRegion; - Traverser: TBoldIndexableListTraverser; + Traverser: TBoldRegionLookupTraverser; begin Result.Clear; Traverser := Regions.CreateTraverser; try - while not Traverser.EndOfList do + while Traverser.MoveNext do begin - aRegion := Traverser.Item as TBoldRegion; - if (aRegion.Definition = Region.Definition) and (aRegion.Root.BoldClassTypeINfo = Region.Root.BoldClassTypeInfo) then + while Assigned(Traverser.Region) and (Traverser.Region.Definition = Region.Definition) and (Traverser.Region.Root.BoldClassTypeINfo = Region.Root.BoldClassTypeInfo) do begin - Result.Add(aRegion); - Regions.Remove(aRegion); + Result.Add(Traverser.Region); + Regions.Remove(Traverser.Region); end; - Traverser.Next; end; finally Traverser.Free; @@ -844,7 +854,7 @@ procedure TBoldRegionExpander.ExpandParentRegions( if assigned(BoldRegionExpansionDebugLogHandler) then begin BoldRegionExpansionDebugLogHandler.Separator; - BoldRegionExpansionDebugLogHandler.Log(sLogExpandingParentRegions); + BoldRegionExpansionDebugLogHandler.Log('Expanding Parent regions'); end; Guard := TBoldGuard.Create(SimilarRegions, LocalNewParentRegions); fToBeParentExpanded.AddRegionLookup(RegionsToExpand); @@ -872,7 +882,7 @@ procedure TBoldRegionExpander.ExpandSubregions( if assigned(BoldRegionExpansionDebugLogHandler) then begin BoldRegionExpansionDebugLogHandler.Separator; - BoldRegionExpansionDebugLogHandler.Log(sLogExpandingSubRegions); + BoldRegionExpansionDebugLogHandler.Log('Expanding Subregions'); end; Guard := TBoldGuard.Create(SimilarRegions, LocalNewSubregions); fToBeSubExpanded.AddRegionLookup(RegionsToExpand); @@ -910,17 +920,15 @@ procedure TBoldRegionExpander.ExpandRegionEnclosure(Regions: TBoldRegionLookup); Regions.AddRegionLookup(NewSubRegions); end; -{ TBoldOrderedRegionLookup } - -constructor TBoldOrderedRegionLookup.Create; -begin - inherited; - SetIndexVariable(IX_RegionOrder, AddIndex(TBoldIntegerIndex.Create)); -end; +{ TBoldRegionLookupTraverser } -function TBoldOrderedRegionLookup.GetFirstRegion: TBoldRegion; +function TBoldRegionLookupTraverser.GetRegion: TBoldRegion; begin - Result := (Indexes[IX_RegionOrder] as TBoldIntegerIndex).items[0] as TBoldRegion; + result := inherited Item as TBoldRegion; end; +initialization + TBoldOrderedRegionLookup.IX_RegionOrder := -1; + TBoldRegionLookup.IX_RegionId := -1; end. + diff --git a/Source/ObjectSpace/PessimisticLocking/BoldRegionDefinitionParser.pas b/Source/ObjectSpace/PessimisticLocking/BoldRegionDefinitionParser.pas index 0d6b860..c5b5bd2 100644 --- a/Source/ObjectSpace/PessimisticLocking/BoldRegionDefinitionParser.pas +++ b/Source/ObjectSpace/PessimisticLocking/BoldRegionDefinitionParser.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldRegionDefinitionParser; interface @@ -46,26 +49,25 @@ TBoldRegionParser = class (TBoldMemoryManagedObject) procedure GenerateDefaultRegions; public constructor Create(RegionDefinitions: TBoldRegionDefinitions; SystemTypeInfo: TBoldSystemTypeInfo); - destructor Destroy; override; + destructor destroy; override; function Parse(RegionDefinitionList: TStrings): Boolean; property RegionDefinitions: TBoldRegionDefinitions read fRegionDefinitions; property SystemTypeInfo: TBoldSystemTypeInfo read fSystemTypeInfo; property Errors: TStringList read fErrors; end; - // Format - // RegionName\[ClassName\] : memberName (, memberName)* (| RegionName\[memberName\] (, RegionName\[memberName\]*)) - // examples: - // Region1[Person]: firstName, lastName | Region2[home] - // Region1[Building]: zipCode - // Region1[Residential_Building]: totalRent + + + + implementation uses - BoldCoreConsts, - BoldTaggedValueSupport; + BoldTaggedValueSupport, + BOldUtils, + BoldRev; const SPACE = #32; @@ -95,7 +97,7 @@ procedure TBoldRegionParser.Eat(s: string); OrgPosition := fPosition; for i := 1 to length(s) do if EOS or (NextToken <> s[i]) then - AddError(OrgPosition, sExpectedToken, [s], petSyntax) + AddError(OrgPosition, 'Expected ''%s''', [s], petSyntax) else inc(fPosition); Skip; @@ -122,7 +124,6 @@ procedure TBoldRegionParser.GenerateDefaultRegions; for ClassIx := 0 to SystemTypeInfo.TopSortedClasses.Count-1 do begin ClassTypeInfo := SystemTypeInfo.TopSortedClasses[ClassIx]; - // create the defaultEmptyRegion, it might be referenced by someone DefaultEmptyCore.EnsuredConcreteDefinition(ClassTypeInfo, existed); if ClassTypeInfo.GenerateDefaultRegion then @@ -178,17 +179,17 @@ function TBoldRegionParser.GetEOS: Boolean; function TBoldRegionParser.GetSymbol(Symboltype: TBoldRegionDefinitionSymbolType): String; begin fLastSymbolPosition := fPosition; - if EOS or not (NextToken in ['a'..'z','A'..'Z','_']) then + if EOS or not CharInSet(NextToken, ['a'..'z','A'..'Z','_']) then begin case SymbolType of - stClassName: AddError(fPosition, sClassNameExpected, [], petSyntax); - stMemberName: AddError(fPosition, sMemberNameExpected, [], petSyntax); - stRegionName: AddError(fPosition, sRegionNameExpected, [], petSyntax); + stClassName: AddError(fPosition, 'Class name expected', [], petSyntax); + stMemberName: AddError(fPosition, 'Member name expected', [], petSyntax); + stRegionName: AddError(fPosition, 'Region name expected', [], petSyntax); end; end; Result := NextToken; inc(fPosition); - while (not EOS) and (NextToken in ['a'..'z','A'..'Z','_', '0'..'9']) do + while (not EOS) and CharInSet(NextToken, ['a'..'z','A'..'Z','_', '0'..'9']) do begin Result := result + NextToken; inc(fPosition); @@ -210,7 +211,6 @@ function TBoldRegionParser.Parse(RegionDefinitionList: TStrings): Boolean; ParseCurrentExpression; except on e: EBoldLockExpressionSyntaxError do - // Eat SyntaxErrors; end; end; RegionDefinitions.ExpandDefinitions; @@ -231,7 +231,7 @@ procedure TBoldRegionParser.ParseMembers(ConcreteRegionDefinition: TBoldConcrete if assigned(MemberRTInfo) then TBoldRegionElementInclusion.Create(ConcreteRegionDefinition, MemberRTInfo) else - AddError(fLastSymbolPosition, sXIsNotAMember, [MemberName, ConcreteRegionDefinition.RootClass.ExpressionName], petSemantics); + AddError(fLastSymbolPosition, '%s is not a member of %s', [MemberName, ConcreteRegionDefinition.RootClass.ExpressionName], petSemantics); tryToEat(','); end; end; @@ -253,9 +253,9 @@ procedure TBoldRegionParser.ParseSubregions(ConcreteRegionDefinition: TBoldConcr IsDependent := not tryToEat('-'); MemberRTInfo := ConcreteRegionDefinition.RootClass.MemberRTInfoByExpressionName[MemberName]; if not assigned(MemberRTInfo) then - AddError(fLastSymbolPosition, sXIsNotAMember, [MemberName, ConcreteRegionDefinition.RootClass.ExPressionName], petSemantics) + AddError(fLastSymbolPosition, '%s is not a member of %s', [MemberName, ConcreteRegionDefinition.RootClass.ExPressionName], petSemantics) else if not (MemberRTInfo is TBoldRoleRTInfo) then - AddError(fLastSymbolPosition, sMemberIsNotARole, [ConcreteRegionDefinition.RootClass.ExPressionName, MemberName], petSemantics) + AddError(fLastSymbolPosition, 'Member %s.%s is not a role, unable to navigate', [ConcreteRegionDefinition.RootClass.ExPressionName, MemberName], petSemantics) else begin SubRegion := RegionDefinitions.EnsuredCoreDefinition(RegionName); @@ -273,7 +273,7 @@ procedure TBoldRegionParser.ParseMembersAndSubregions(CoreDefinition: TBoldRegio begin ConcreteRegionDefinition := CoreDefinition.EnsuredConcreteDefinition(ClassTypeInfo, AlreadyDefined); if AlreadyDefined then - AddError(1, sMultipleDefinitions, [CoreDefinition.Name ,classTypeInfo.ExpressionName], petSemantics) + AddError(1, 'Multiple definitions of %s[%s]', [CoreDefinition.Name ,classTypeInfo.ExpressionName], petSemantics) else begin ParseMembers(ConcreteRegionDefinition); @@ -284,7 +284,7 @@ procedure TBoldRegionParser.ParseMembersAndSubregions(CoreDefinition: TBoldRegio procedure TBoldRegionParser.Skip; begin - while not EOS and (NextToken in [SPACE, TAB]) do + while not EOS and CharInSet(NextToken, [SPACE, TAB]) do inc(fPosition); end; @@ -329,13 +329,13 @@ procedure TBoldRegionParser.ParseCurrentExpression; if Assigned(ClassTypeInfo) then ParseMembersAndSubregions(CoreDefinition, ClassTypeInfo) else - AddError(fLastSymbolPosition, sUnknownClassName, [ClassName], petSemantics); + AddError(fLastSymbolPosition, 'Unknown class name: ''%s''', [ClassName], petSemantics); end; -destructor TBoldRegionParser.Destroy; +destructor TBoldRegionParser.destroy; begin FreeAndNil(fErrors); - inherited; + inherited; end; procedure TBoldRegionParser.AddError(pos: integer; msg: String; args: array of const; ErrorType: TBoldRegionParserErrorType); @@ -344,7 +344,7 @@ procedure TBoldRegionParser.AddError(pos: integer; msg: String; args: array of c begin ErrorMsg := ''; if Pos <> -1 then - ErrorMsg := format('"%s" (%d): ', [fExpression, pos]); // do not localize + ErrorMsg := format('"%s" (%d): ', [fExpression, pos]); ErrorMsg := ErrorMsg + format(Msg, args); fErrors.Add(ErrorMsg); if ErrorType = petSyntax then @@ -361,12 +361,15 @@ procedure TBoldRegionParser.CheckRegionReferences; CoreDef := TBoldRegionCoreDefinition(fRegionDefinitions.CoreDefinitions[i]); if CoreDef.ConcreteDefinitions.Count = 0 then for j := 0 to CoreDef.UsedBy.Count-1 do - AddError(-1, sReferencedRegionNotDefined, [ + AddError(-1, 'Referenced region (%s) not defined. Used by %s[%s], role %s', [ CoreDef.Name, CoreDef.UsedBy[j].ParentRegion.CoreDefinition.Name, CoreDef.UsedBy[j].ParentRegion.RootClass.ExpressionName, CoreDef.UsedBy[j].SubregionRootNavigation.ExpressionName], petSemantics); end; + end; +initialization + end. diff --git a/Source/ObjectSpace/PessimisticLocking/BoldRegionDefinitions.pas b/Source/ObjectSpace/PessimisticLocking/BoldRegionDefinitions.pas index b2d634d..207fa0c 100644 --- a/Source/ObjectSpace/PessimisticLocking/BoldRegionDefinitions.pas +++ b/Source/ObjectSpace/PessimisticLocking/BoldRegionDefinitions.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldRegionDefinitions; interface @@ -112,23 +115,30 @@ TBoldRegionElementInclusion = class(TBoldMemoryManagedObject) TBoldConcreteRegionDefinitionList = class(TList) private function GetItem(i: Integer): TBoldConcreteRegionDefinition; + function GetAsCommaText: string; public function FindByRootClass(RootClass: TBoldClassTypeInfo): TBoldConcreteRegionDefinition; property Items[i: Integer]: TBoldConcreteRegionDefinition read GetItem; default; + public + property AsCommaText: string read GetAsCommaText; end; TBoldSubregionReferenceList = class(TList) private function GetItem(i: Integer): TBoldSubregionReference; + function GetAsCommaText: string; public property Items[i: Integer]: TBoldSubregionReference read GetItem; default; + property AsCommaText: string read GetAsCommaText; end; TBoldRegionElementInclusionList = class(TList) private function GetItem(i: Integer): TBoldRegionElementInclusion; + function GetAsCommaText: string; public property Items[i: Integer]: TBoldRegionElementInclusion read GetItem; default; + property AsCommaText: string read GetAsCommaText; end; const @@ -137,7 +147,8 @@ TBoldRegionElementInclusionList = class(TList) implementation uses - SysUtils; + SysUtils, + BoldRev; function GetEnsuredItem(List: TList; index: integer; theClass: TClass): TObject; var @@ -170,6 +181,21 @@ function TBoldConcreteRegionDefinitionList.FindByRootClass( end; end; +function TBoldConcreteRegionDefinitionList.GetAsCommaText: string; +var + sl: TStringList; + i: integer; +begin + sl := TStringList.Create; + try + for I := 0 to Count - 1 do + sl.Add(self[i].AsString); + finally + result := sl.CommaText; + sl.free; + end; +end; + function TBoldConcreteRegionDefinitionList.GetItem(i: Integer): TBoldConcreteRegionDefinition; begin result := TObject(inherited Items[i]) as TBoldConcreteRegionDefinition; @@ -292,6 +318,21 @@ function TBoldRegionDefinitions.GetRegionInclusionsByMember( { TBoldRegionElementInclusionList } +function TBoldRegionElementInclusionList.GetAsCommaText: string; +var + sl: TStringList; + i: integer; +begin + sl := TStringList.Create; + try + for I := 0 to Count - 1 do + sl.Add(self[i].Member.DisplayName); + finally + result := sl.CommaText; + sl.free; + end; +end; + function TBoldRegionElementInclusionList.GetItem( i: Integer): TBoldRegionElementInclusion; begin @@ -300,6 +341,21 @@ function TBoldRegionElementInclusionList.GetItem( { TBoldSubregionReferenceList } +function TBoldSubregionReferenceList.GetAsCommaText: string; +var + sl: TStringList; + i: integer; +begin + sl := TStringList.Create; + try + for I := 0 to Count - 1 do + sl.Add(self[i].ParentRegion.RootClass.DisplayName); + finally + result := sl.CommaText; + sl.free; + end; +end; + function TBoldSubregionReferenceList.GetItem( i: Integer): TBoldSubregionReference; begin @@ -382,7 +438,7 @@ procedure TBoldConcreteRegionDefinition.Clear; fElements.Clear; for i := 0 to fSubregions.Count-1 do fSubregions[i].Free; - fSubregions.Clear; + fSubregions.Clear; end; constructor TBoldConcreteRegionDefinition.Create(CoreDefinition: TBoldRegionCoreDefinition; Root: TBoldClassTypeInfo); @@ -463,4 +519,6 @@ constructor TBoldRegionElementInclusion.Create(Region: TBoldConcreteRegionDefini (Member as TBoldRoleRTInfo).RoleRTInfoOfOtherEnd.SetForceOtherEnd; end; + +initialization end. diff --git a/Source/ObjectSpace/RTModel/BoldGeneratedCodeDictionary.pas b/Source/ObjectSpace/RTModel/BoldGeneratedCodeDictionary.pas index 509e527..1c3c535 100644 --- a/Source/ObjectSpace/RTModel/BoldGeneratedCodeDictionary.pas +++ b/Source/ObjectSpace/RTModel/BoldGeneratedCodeDictionary.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldGeneratedCodeDictionary; interface @@ -18,12 +21,12 @@ TBoldGeneratedClassDescriptor = class; { TBoldGeneratedCodeList } TBoldGeneratedCodeList = class(TBoldIndexableList) private - function GetDescriptorByExpressionName(ExpressionName: string): TBoldGeneratedCodeDescriptor; + function GetDescriptorByExpressionName(const ExpressionName: string): TBoldGeneratedCodeDescriptor; function GetModelDescriptors(index: Integer): TBoldGeneratedCodeDescriptor; public constructor Create; - function AddGeneratedCodeDescriptorWithFunc(ExpressionName: string; InstBusiClasses: TInstallBusinessClasses; InstObjListClasses: TInstallObjectListClasses; CRC: string = ''):TBoldGeneratedCodeDescriptor; - property DescriptorByExpressionName[ExpressionName: string]: TBoldGeneratedCodeDescriptor read GetDescriptorByExpressionName; + function AddGeneratedCodeDescriptorWithFunc(const ExpressionName: string; InstBusiClasses: TInstallBusinessClasses; InstObjListClasses: TInstallObjectListClasses; CRC: string = ''):TBoldGeneratedCodeDescriptor; + property DescriptorByExpressionName[const ExpressionName: string]: TBoldGeneratedCodeDescriptor read GetDescriptorByExpressionName; property ModelEntries[index: Integer]: TBoldGeneratedCodeDescriptor read GetModelDescriptors; end; @@ -35,7 +38,7 @@ TBoldGeneratedCodeDescriptor = class fInstallBusinessClasses: TInstallBusinessClasses; fInstallObjectListClasses: TInstallObjectListClasses; public - constructor Create(ExpressionName: string; InstallBusinessClasses: TInstallBusinessClasses; InstallObjectListClasses: TInstallObjectListClasses; CRC: string); + constructor Create(const ExpressionName: string; InstallBusinessClasses: TInstallBusinessClasses; InstallObjectListClasses: TInstallObjectListClasses; CRC: string); property InstallBusinessClasses: TInstallBusinessClasses read fInstallBusinessClasses; property InstallObjectListClasses: TInstallObjectListClasses read fInstallObjectListClasses; property ExpressionName: string read fExpressionName; @@ -45,12 +48,12 @@ TBoldGeneratedCodeDescriptor = class { TBoldGeneratedClassList } TBoldGeneratedClassList = class(TBoldIndexableList) private - function GetDescriptorByExpressionName(ExpressionName: string): TBoldGeneratedClassDescriptor; + function GetDescriptorByExpressionName(const ExpressionName: string): TBoldGeneratedClassDescriptor; public constructor Create; procedure AddEntry(BoldObjectClassEntry: TBoldGeneratedClassDescriptor); - procedure AddObjectEntry(ExpressionName: string; AClass: TClass); - property EntryByExpressionName[ExpressionName: string]: TBoldGeneratedClassDescriptor read GetDescriptorByExpressionName; + procedure AddObjectEntry(const ExpressionName: string; AClass: TClass); + property EntryByExpressionName[const ExpressionName: string]: TBoldGeneratedClassDescriptor read GetDescriptorByExpressionName; end; { TBoldGeneratedClassDescriptor } @@ -64,7 +67,7 @@ TBoldGeneratedClassDescriptor = class property TheClass: TClass read fClass; end; -function GeneratedCodes: TBoldGeneratedCodeList; //Name space shortage!! +function GeneratedCodes: TBoldGeneratedCodeList; function BoldGeneratedCodesAssigned: Boolean; implementation @@ -78,14 +81,14 @@ implementation G_BoldGeneratedCodes: TBoldGeneratedCodeList = nil; IX_GeneratedClassExpressionName: integer = -1; IX_GeneratedCodeExpressionName: integer = -1; - + type { TGeneratedCodeExpressionNameIndex } TGeneratedCodeExpressionNameIndex = class(TBoldStringHashIndex) protected function ItemAsKeyString(Item: TObject): string; override; end; - + function TGeneratedCodeExpressionNameIndex.ItemAsKeyString(Item: TObject): string; begin Result := TBoldGeneratedCodeDescriptor(Item).ExpressionName; @@ -112,7 +115,7 @@ constructor TBoldGeneratedCodeList.Create; SetIndexVariable(IX_GeneratedCodeExpressionName, AddIndex(TGeneratedCodeExpressionNameIndex.Create)); end; -function TBoldGeneratedCodeList.GetDescriptorByExpressionName(ExpressionName: string): TBoldGeneratedCodeDescriptor; +function TBoldGeneratedCodeList.GetDescriptorByExpressionName(const ExpressionName: string): TBoldGeneratedCodeDescriptor; begin Result := TBoldGeneratedCodeDescriptor(TGeneratedCodeExpressionNameIndex(Indexes[IX_GeneratedCodeExpressionName]).FindByString(ExpressionName)) end; @@ -122,14 +125,14 @@ function TBoldGeneratedCodeList.GetModelDescriptors(index: Integer): TBoldGenera Result := TBoldGeneratedCodeDescriptor(Items[index]); end; -function TBoldGeneratedCodeList.AddGeneratedCodeDescriptorWithFunc(ExpressionName: string; InstBusiClasses: TInstallBusinessClasses; InstObjListClasses: TInstallObjectListClasses; CRC: string = ''): TBoldGeneratedCodeDescriptor; +function TBoldGeneratedCodeList.AddGeneratedCodeDescriptorWithFunc(const ExpressionName: string; InstBusiClasses: TInstallBusinessClasses; InstObjListClasses: TInstallObjectListClasses; CRC: string = ''): TBoldGeneratedCodeDescriptor; begin result := TBoldGeneratedCodeDescriptor.Create(ExpressionName, InstBusiClasses, InstObjListClasses, CRC); Add(result); end; { TBoldGeneratedCodeDescriptor } -constructor TBoldGeneratedCodeDescriptor.Create(ExpressionName: string; InstallBusinessClasses: TInstallBusinessClasses; InstallObjectListClasses: TInstallObjectListClasses; CRC: String); +constructor TBoldGeneratedCodeDescriptor.Create(const ExpressionName: string; InstallBusinessClasses: TInstallBusinessClasses; InstallObjectListClasses: TInstallObjectListClasses; CRC: String); begin fExpressionName := ExpressionName; fInstallBusinessClasses := InstallBusinessClasses; @@ -157,7 +160,8 @@ constructor TBoldGeneratedClassList.Create; SetIndexCapacity(1); SetIndexVariable(IX_GeneratedClassExpressionName, AddIndex(TGeneratedClassExpressionNameIndex.Create)); end; -function TBoldGeneratedClassList.GetDescriptorByExpressionName(ExpressionName: string): TBoldGeneratedClassDescriptor; + +function TBoldGeneratedClassList.GetDescriptorByExpressionName(const ExpressionName: string): TBoldGeneratedClassDescriptor; begin Result := TBoldGeneratedClassDescriptor(TGeneratedClassExpressionNameIndex(Indexes[IX_GeneratedClassExpressionName]).FindByString(ExpressionName)); end; @@ -167,7 +171,7 @@ procedure TBoldGeneratedClassList.AddEntry(BoldObjectClassEntry: TBoldGeneratedC Add(BoldObjectClassEntry); end; -procedure TBoldGeneratedClassList.AddObjectEntry(ExpressionName: string; AClass: TClass); +procedure TBoldGeneratedClassList.AddObjectEntry(const ExpressionName: string; AClass: TClass); begin AddEntry(TBoldGeneratedClassDescriptor.Create(ExpressionName, AClass)); end; diff --git a/Source/ObjectSpace/RTModel/BoldMemberTypeDictionary.pas b/Source/ObjectSpace/RTModel/BoldMemberTypeDictionary.pas index fa0d2db..5fdf224 100644 --- a/Source/ObjectSpace/RTModel/BoldMemberTypeDictionary.pas +++ b/Source/ObjectSpace/RTModel/BoldMemberTypeDictionary.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldMemberTypeDictionary; interface @@ -13,15 +16,17 @@ TBoldMemberTypeDescriptor = class; {---TBoldMemberTypeList---} TBoldMemberTypeList = class(TBoldIndexableList) private - function GetDescriptorByClass(BoldMemberClass: TClass): TBoldMemberTypeDescriptor; - function GetMemberTypeDescriptors(index: integer): TBoldMemberTypeDescriptor; - function GetDescriptorByDelphiName(DelphiName: string): TBoldMemberTypeDescriptor; + class var IX_MemberName: integer; + class var IX_MemberClass: integer; + function GetDescriptorByClass(BoldMemberClass: TClass): TBoldMemberTypeDescriptor; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetMemberTypeDescriptors(index: integer): TBoldMemberTypeDescriptor; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetDescriptorByDelphiName(const DelphiName: string): TBoldMemberTypeDescriptor; {$IFDEF BOLD_INLINE} inline; {$ENDIF} public constructor Create; procedure AddMemberTypeDescriptor(MemberClass: TClass; const AbstractionLevel: TBoldAbstractionLevel); procedure RemoveDescriptorByClass(BoldMemberClass: TClass); - property DescriptorByDelphiName[DelphiName: string]: TBoldMemberTypeDescriptor read GetDescriptorByDelphiName; + property DescriptorByDelphiName[const DelphiName: string]: TBoldMemberTypeDescriptor read GetDescriptorByDelphiName; property DescriptorByClass[BoldMemberClass: TClass]: TBoldMemberTypeDescriptor read GetDescriptorByClass; property Descriptors[Index: integer]: TBoldMemberTypeDescriptor read GetMemberTypeDescriptors; end; @@ -52,10 +57,6 @@ implementation var G_BoldMemberTypes: TBoldMemberTypeList; -var - IX_MemberName: integer = -1; - IX_MemberClass: integer = -1; - type {---TMemberNameIndex---} TMemberNameIndex = class(TBoldStringHashIndex) @@ -104,14 +105,14 @@ constructor TBoldMemberTypeList.Create; SetIndexVariable(IX_MemberClass, AddIndex(TMemberClassIndex.Create)); end; -function TBoldMemberTypeList.GetDescriptorByDelphiName(DelphiName: string): TBoldMemberTypeDescriptor; +function TBoldMemberTypeList.GetDescriptorByDelphiName(const DelphiName: string): TBoldMemberTypeDescriptor; begin - Result := TBoldMemberTypeDescriptor(TMemberNameIndex(Indexes[IX_MemberName]).FindByString(DelphiName)) + Result := TBoldMemberTypeDescriptor(TBoldStringHashIndex(Indexes[IX_MemberName]).FindByString(DelphiName)) end; function TBoldMemberTypeList.GetDescriptorByClass(BoldMemberClass: TClass): TBoldMemberTypeDescriptor; begin - Result := TBoldMemberTypeDescriptor(TMemberClassIndex(Indexes[IX_MemberClass]).FindByClass(BoldMemberClass)) + Result := TBoldMemberTypeDescriptor(TBoldClassHashIndex(Indexes[IX_MemberClass]).FindByClass(BoldMemberClass)) end; procedure TBoldMemberTypeList.AddMemberTypeDescriptor(MemberClass: TClass; @@ -139,6 +140,8 @@ constructor TBoldMemberTypeDescriptor.Create(MemberClass: TClass; end; initialization + TBoldMemberTypeList.IX_MemberName := -1; + TBoldMemberTypeList.IX_MemberClass := -1; finalization FreeAndNil(G_BoldMemberTypes); diff --git a/Source/ObjectSpace/RTModel/BoldSystemRT.pas b/Source/ObjectSpace/RTModel/BoldSystemRT.pas index 9b33c14..d2163b2 100644 --- a/Source/ObjectSpace/RTModel/BoldSystemRT.pas +++ b/Source/ObjectSpace/RTModel/BoldSystemRT.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldSystemRT; interface @@ -5,6 +8,7 @@ interface uses BoldDefs, BoldElements, + BoldIndexableList, BoldMetaElementList, BoldGeneratedCodeDictionary, BoldMeta, @@ -17,10 +21,22 @@ interface LITE_VERSION_CLASS_LIMIT = 15; CLASS_TYPE_INFO_MEM_SIZE = 24; +type + TBoldTypeInfoSearchOption = (soPartialMatch); + TBoldTypeInfoSearchOptions = set of TBoldTypeInfoSearchOption; + + TBoldSearchType = (stClass, stAttribute, stRole, stMethod, stType); + TBoldSearchTypes = set of TBoldSearchType; + +const cDefaultSearchTypes = [stClass, stAttribute, stRole, stMethod, stType]; +const cDefaultSearchTypeOptions = [soPartialMatch]; + type {forward declarations, classes in actual model} TBoldClassTypeInfoList = class; + TBoldAttributeTypeInfoList = class; TBoldMemberRTInfoList = class; + TBoldRoleRTInfoList = class; TBoldMethodRTInfoList = class; TBoldListTypeInfoList = class; @@ -34,7 +50,7 @@ TBoldNilTypeInfo = class; TBoldMemberRTInfo = class; TBoldRoleRTInfo = class; - TBoldListTypeInfo = class; +// TBoldListTypeInfo = class; // moved to BoldElements TBoldAttributeRTInfo = class; TBoldAttributeTypeInfo = class; TBoldMethodRTInfo = class; @@ -44,53 +60,130 @@ TBoldConstraintRTInfo = class; { TBoldRTEvaluator } TBoldRTEvaluator = class(TBoldEvaluator) public - function RTInfo(const Ocl: string; Context: TBoldElementTypeInfo; ReRaise: Boolean): TBoldMemberRTInfo; virtual; abstract; + function RTInfo(const Ocl: string; Context: TBoldElementTypeInfo; ReRaise: Boolean; const VariableList: TBoldExternalVariableList = nil): TBoldMemberRTInfo; virtual; abstract; + end; + + TBoldClassTypeInfoListTraverser = class(TBoldIndexableListTraverser) + public + function GetCurrent: TBoldClassTypeInfo; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + property Current: TBoldClassTypeInfo read GetCurrent; end; {---TBoldClassRTInfoList---} TBoldClassTypeInfoList = class(TBoldElementTypeInfoList) private - function GetItem(index: Integer): TBoldClassTypeInfo; - function GetItemByExpressionName(const ExpressionName: string): TBoldClassTypeInfo; - function GetItemByModelName(const ModelName: string): TBoldClassTypeInfo; - function GetItemByObjectClass(ObjectClass: TClass): TBoldClassTypeInfo; + class var IX_ObjectClass: integer; + function GetItem(index: Integer): TBoldClassTypeInfo; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetItemByExpressionName(const ExpressionName: string): TBoldClassTypeInfo; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetItemByModelName(const ModelName: string): TBoldClassTypeInfo; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetItemByObjectClass(ObjectClass: TClass): TBoldClassTypeInfo; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + protected + function TraverserClass: TBoldIndexableListTraverserClass; override; public constructor Create; + function GetEnumerator: TBoldClassTypeInfoListTraverser; property Items[index: Integer]: TBoldClassTypeInfo read GetItem; default; property ItemsByExpressionName[const ExpressionName: string]: TBoldClassTypeInfo read GetItemByExpressionName; property ItemsByModelName[const ModelName: string]: TBoldClassTypeInfo read GetItemByModelName; property ItemsByObjectClass[ObjectClass: TClass]: TBoldClassTypeInfo read GetItemByObjectClass; end; + TBoldMemberRTInfoListTraverser = class(TBoldIndexableListTraverser) + public + function GetCurrent: TBoldMemberRTInfo; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + property Current: TBoldMemberRTInfo read GetCurrent; + end; + {---TBoldMemberRTInfoList---} TBoldMemberRTInfoList = class(TBoldMetaElementList) private - function GetItem(index: Integer): TBoldMemberRTInfo; - function GetItemByExpressionName(const ExpressionName: string): TBoldMemberRTInfo; + function GetItem(index: Integer): TBoldMemberRTInfo; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetItemByExpressionName(const ExpressionName: string): TBoldMemberRTInfo; {$IFDEF BOLD_INLINE} inline; {$ENDIF} function GetItemByModelName(const ModelName: string): TBoldMemberRTInfo; + protected + function TraverserClass: TBoldIndexableListTraverserClass; override; public + function GetEnumerator: TBoldMemberRTInfoListTraverser; property Items[index: Integer]: TBoldMemberRTInfo read GetItem; default; property ItemsByExpressionName[const ExpressionName: string]: TBoldMemberRTInfo read GetItemByExpressionName; property ItemsByModelName[const ModelName: string]: TBoldMemberRTInfo read GetItemByModelName; end; + TBoldAttributeTypeInfoListTraverser = class(TBoldIndexableListTraverser) + public + function GetCurrent: TBoldAttributeTypeInfo; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + property Current: TBoldAttributeTypeInfo read GetCurrent; + end; + + TBoldAttributeTypeInfoList = class(TBoldMetaElementList) + private + function GetItem(index: Integer): TBoldAttributeTypeInfo; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetItemByExpressionName(const ExpressionName: string): TBoldAttributeTypeInfo; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetItemByModelName(const ModelName: string): TBoldAttributeTypeInfo; + protected + function TraverserClass: TBoldIndexableListTraverserClass; override; + public + function GetEnumerator: TBoldAttributeTypeInfoListTraverser; + property Items[index: Integer]: TBoldAttributeTypeInfo read GetItem; default; + property ItemsByExpressionName[const ExpressionName: string]: TBoldAttributeTypeInfo read GetItemByExpressionName; + property ItemsByModelName[const ModelName: string]: TBoldAttributeTypeInfo read GetItemByModelName; + end; + + TBoldRoleRTInfoListTraverser = class(TBoldIndexableListTraverser) + public + function GetCurrent: TBoldRoleRTInfo; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + property Current: TBoldRoleRTInfo read GetCurrent; + end; + + {---TBoldRoleRTInfoList---} + TBoldRoleRTInfoList = class(TBoldMetaElementList) + private + function GetItem(index: Integer): TBoldRoleRTInfo; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetItemByExpressionName(const ExpressionName: string): TBoldRoleRTInfo; + function GetItemByModelName(const ModelName: string): TBoldRoleRTInfo; + protected + function TraverserClass: TBoldIndexableListTraverserClass; override; + public + function GetEnumerator: TBoldRoleRTInfoListTraverser; + property Items[index: Integer]: TBoldRoleRTInfo read GetItem; default; + property ItemsByExpressionName[const ExpressionName: string]: TBoldRoleRTInfo read GetItemByExpressionName; + property ItemsByModelName[const ModelName: string]: TBoldRoleRTInfo read GetItemByModelName; + end; + + TBoldConstraintRTInfoListTraverser = class(TBoldIndexableListTraverser) + public + function GetCurrent: TBoldConstraintRTInfo; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + property Current: TBoldConstraintRTInfo read GetCurrent; + end; + TBoldConstraintRTInfoList = class(TBoldMetaElementList) private - function GetItem(index: Integer): TBoldConstraintRTInfo; - function GetItemByModelName(const ModelName: string): TBoldConstraintRTInfo; + function GetItem(index: Integer): TBoldConstraintRTInfo; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetItemByModelName(const ModelName: string): TBoldConstraintRTInfo; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + protected + function TraverserClass: TBoldIndexableListTraverserClass; override; public + function GetEnumerator: TBoldConstraintRTInfoListTraverser; property Items[index: Integer]: TBoldConstraintRTInfo read GetItem; default; property ItemsByModelName[const ModelName: string]: TBoldConstraintRTInfo read GetItemByModelName; end; + TBoldMethodRTInfoListTraverser = class(TBoldIndexableListTraverser) + public + function GetCurrent: TBoldMethodRTInfo; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + property Current: TBoldMethodRTInfo read GetCurrent; + end; {---TBoldMethodRTInfoList---} TBoldMethodRTInfoList = class(TBoldMetaElementList) private - function GetItem(index: Integer): TBoldMethodRTInfo; - function GetItemByModelName(const ModelName: string): TBoldMethodRTInfo; - function GetItemByExpressionName(const ExpressionName: string): TBoldMethodRTInfo; + function GetItem(index: Integer): TBoldMethodRTInfo; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetItemByModelName(const ModelName: string): TBoldMethodRTInfo; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetItemByExpressionName(const ExpressionName: string): TBoldMethodRTInfo; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + protected + function TraverserClass: TBoldIndexableListTraverserClass; override; public + function GetEnumerator: TBoldMethodRTInfoListTraverser; property Items[index: Integer]: TBoldMethodRTInfo read GetItem; default; property ItemsByModelName[const ModelName: string]: TBoldMethodRTInfo read GetItemByModelName; property ItemsByExpressionName[const ExpressionName: string]: TBoldMethodRTInfo read GetItemByExpressionName; @@ -99,10 +192,14 @@ TBoldMethodRTInfoList = class(TBoldMetaElementList) {---TBoldListTypeInfoList---} TBoldListTypeInfoList = class(TBoldElementTypeInfoList) private - function GetItemByElement(Element: TBoldElementTypeInfo): TBoldListTypeInfo; + class var IX_Element: integer; + class var IX_ListClass: integer; + function GetItemByElement(Element: TBoldElementTypeInfo): TBoldListTypeInfo; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetItemByListClass(ListClass: TClass): TBoldListTypeInfo; {$IFDEF BOLD_INLINE} inline; {$ENDIF} public constructor Create; property ItemByElement[Element: TBoldElementTypeInfo]: TBoldListTypeInfo read GetItemByElement; + property ItemByListClass[ObjectClass: TClass]: TBoldListTypeInfo read GetItemByListClass; end; {---TBoldTypeTypeInfo---} @@ -110,6 +207,7 @@ TBoldTypeTypeInfo = class(TBoldElementTypeInfo) protected constructor Create(const ModelName: string; const ExpressionName: string; const Delphiname: string; ModelTypeInfo: TBoldElementTypeInfo); function GetBoldType: TBoldElementTypeInfo; override; + function GetListTypeInfo: TBoldListTypeInfo; override; public function ConformsTo(CompareElement: TBoldElementTypeInfo): Boolean; override; end; @@ -118,12 +216,13 @@ TBoldElementTypeInfoWithConstraint = class(TBoldElementTypeInfo) private fConstraints: TBoldConstraintRTInfoList; fTaggedValues: TStrings; - function GetTaggedValues(const Tag: string): string; - function GetConstraints(const Name: String): TBoldConstraintRTInfo; - function GetConstraintCount: integer; - function GetTaggedvalueCount: integer; - function GetConstraintByIndex(Index: integer): TBoldConstraintRTInfo; - function GetTaggedValueByIndex(Index: integer): string; + function GetTaggedValues(const Tag: string): string; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetConstraints(const Name: String): TBoldConstraintRTInfo; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetConstraintCount: integer; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetTaggedvalueCount: integer; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetConstraintByIndex(Index: integer): TBoldConstraintRTInfo; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetTaggedValueByIndex(Index: integer): string; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetListTypeInfo: TBoldListTypeInfo; override; public constructor Create(MoldElement: TMoldElement; SystemTypeInfo: TBoldSystemTypeInfo); destructor Destroy; override; @@ -141,16 +240,16 @@ TBoldMetaElementWithConstraint = class(TBoldMetaElement) private fConstraints: TBoldConstraintRTInfoList; fTaggedValues: TStrings; - function GetTaggedValues(const Tag: string): string; - function GetConstraints(const Name: String): TBoldConstraintRTInfo; - function GetConstraintByIndex(Index: integer): TBoldConstraintRTInfo; - function GetConstraintCount: integer; - function GetTaggedValueByIndex(Index: integer): string; - function GetTaggedvalueCount: integer; + function GetTaggedValues(const Tag: string): string; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetConstraints(const Name: String): TBoldConstraintRTInfo; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetConstraintByIndex(Index: integer): TBoldConstraintRTInfo; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetConstraintCount: integer; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetTaggedValueByIndex(Index: integer): string; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetTaggedvalueCount: integer; {$IFDEF BOLD_INLINE} inline; {$ENDIF} public constructor Create(MoldElement: TMoldElement; const ModelName, ExpressionName, DelphiName: String; SystemTypeInfo: TBoldSystemTypeInfo); destructor Destroy; override; - procedure AddConstraint(Constraint: TBoldConstraintRTinfo); + procedure AddConstraint(Constraint: TBoldConstraintRTinfo); {$IFDEF BOLD_INLINE} inline; {$ENDIF} property Constraint[const Name: String]: TBoldConstraintRTInfo read GetConstraints; property ConstraintCount: integer read GetConstraintCount; property ConstraintByIndex[Index: integer]: TBoldConstraintRTInfo read GetConstraintByIndex; @@ -159,36 +258,44 @@ TBoldMetaElementWithConstraint = class(TBoldMetaElement) property TaggedValueByIndex[Index: integer]: string read GetTaggedValueByIndex; end; - {---TBoldSystemTypeInfo---} TBoldSystemTypeInfo = class(TBoldElementTypeInfoWithConstraint) private +{$IFDEF BOLD_LITE} + fClassTypeInfoMem: array[0..LITE_VERSION_CLASS_LIMIT*CLASS_TYPE_INFO_MEM_SIZE] of Integer; +{$ENDIF} fInitializationLog: TStringList; fOptimisticLocking: TBoldOptimisticLockingMode; - fAttributeTypes: TBoldElementTypeInfoList; + fAttributeTypes: TBoldAttributeTypeInfoList; fEvaluator: TBoldEvaluator; fListTypes: TBoldListTypeInfoList; fMethodsInstalled: Boolean; fNilTypeInfo: TBoldNilTypeInfo; - fTopSortedClasses: TBoldClassTypeInfoList; // Classes in topologically sorted order + fValueSetTypeInfo: TBoldElementTypeInfo; + fTopSortedClasses: TBoldClassTypeInfoList; + fValueSetTypeInfoList: TBoldElementTypeInfoList; fTypeTypeInfo: TBoldTypeTypeInfo; + fUntypedListTypeInfo: TBoldListTypeInfo; fUseGeneratedCode: Boolean; fGenerateMultiplicityConstraints: Boolean; fValueTypeNameList: TBoldElementTypeInfoList; fStereotype: string; - fUseClockLog: Boolean; + fUseClockLog: Boolean; function GetInitializationLog: TStringList; - function GetAttributeTypeInfoByDelphiName(const name: string): TBoldAttributeTypeInfo; - function GetAttributeTypeInfoByExpressionName(const name: string): TBoldAttributeTypeInfo; - function GetClassTypeInfoByExpressionName(const name: string): TBoldClassTypeInfo; - function GetClassTypeInfoByModelName(const name: string): TBoldClassTypeInfo; - function GetElementTypeInfoByDelphiName(const name: string): TBoldElementTypeInfo; - function GetElementTypeInfoByExpressionName(const name: string): TBoldElementTypeInfo; - function GetListTypeInfoByElement(Element: TBoldElementTypeInfo): TBoldListTypeInfo; - function GetRootClassTypeInfo: TBoldClassTypeInfo; + function GetAttributeTypeInfoByDelphiName(const name: string): TBoldAttributeTypeInfo; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetAttributeTypeInfoByExpressionName(const name: string): TBoldAttributeTypeInfo; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetClassTypeInfoByExpressionName(const name: string): TBoldClassTypeInfo; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetClassTypeInfoByModelName(const name: string): TBoldClassTypeInfo; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetElementTypeInfoByDelphiName(const name: string): TBoldElementTypeInfo; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetElementTypeInfoByExpressionName(const name: string): TBoldElementTypeInfo; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetListTypeInfoByElement(Element: TBoldElementTypeInfo): TBoldListTypeInfo; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetMemberTypeInfoByQualifiedName(const AClassName, AMemberName: string): TBoldMemberRtInfo; + function GetRootClassTypeInfo: TBoldClassTypeInfo; {$IFDEF BOLD_INLINE} inline; {$ENDIF} function GetValueTypeNameList: TBoldElementTypeInfoList; + function GetValueSetTypeInfoList: TBoldElementTypeInfoList; procedure InitializationError(const Message: String; args: array of const); procedure InstallAttributeType(TypeNameDictionary: TBoldTypeNameDictionary; pos: integer); + function GetClassTypeInfoByClass(ObjectClass: TClass): TBoldClassTypeInfo; protected function GetEvaluator: TBoldEvaluator; override; function GetBoldType: TBoldElementTypeInfo; override; @@ -198,18 +305,26 @@ TBoldSystemTypeInfo = class(TBoldElementTypeInfoWithConstraint) function ConformsTo(CompareElement: TBoldElementTypeInfo): Boolean; override; procedure GetValueTypeNames(S: TStrings; Classes, Types, System, metatype, lists: Boolean); procedure ReleaseEvaluator; + function FindElement(const AText: string; ASearchOptions: TBoldTypeInfoSearchOptions = cDefaultSearchTypeOptions; ASearchTypes: TBoldSearchTypes = cDefaultSearchTypes): TBoldMetaElement; + function FindValueSetAndTypeByName(const AName: string; out AElement: TBoldElement; out ATypeInfo: TBoldElementTypeInfo): boolean; + function FindValueSetByName(const AName: string): TBoldElement; property AttributeTypeInfoByDelphiName[const name: string]: TBoldAttributeTypeInfo read GetAttributeTypeInfoByDelphiName; property AttributeTypeInfoByExpressionName[const name: string]: TBoldAttributeTypeInfo read GetAttributeTypeInfoByExpressionName; - property AttributeTypes: TBoldElementTypeInfoList read fAttributeTypes; + property AttributeTypes: TBoldAttributeTypeInfoList read fAttributeTypes; property ClassTypeInfoByExpressionName[const name: string]: TBoldClassTypeInfo read GetClassTypeInfoByExpressionName; property ClassTypeInfoByModelName[const name: string]: TBoldClassTypeInfo read GetClassTypeInfoByModelName; + property ClassTypeInfoByClass[ObjectClass: TClass]: TBoldClassTypeInfo read GetClassTypeInfoByClass; + property MemberTypeInfoByQualifiedName[const AClassName, AMemberName: string]: TBoldMemberRtInfo read GetMemberTypeInfoByQualifiedName; property ListTypeInfoByElement[Element: TBoldElementTypeInfo]: TBoldListTypeInfo read GetListTypeInfoByElement; property ListTypes: TBoldListTypeInfoList read fListTypes; property NilTypeInfo: TBoldNilTypeInfo read fNilTypeInfo; + property ValueSetTypeInfo: TBoldElementTypeInfo read fValueSetTypeInfo; + property ValueSetTypeInfoList: TBoldElementTypeInfoList read GetValueSetTypeInfoList; property ElementTypeInfoByDelphiName[const name: string]: TBoldElementTypeInfo read GetElementTypeInfoByDelphiName; property ElementTypeInfoByExpressionName[const name: string]: TBoldElementTypeInfo read GetElementTypeInfoByExpressionName; property ValueTypeNameList: TBoldElementTypeInfoList read GetValueTypeNameList; property RootClassTypeInfo: TBoldClassTypeInfo read GetRootClassTypeInfo; + property UntypedListTypeInfo: TBoldListTypeInfo read fUntypedListTypeInfo; property TypeTypeInfo: TBoldTypeTypeInfo read fTypeTypeInfo; property MethodsInstalled: Boolean read fMethodsInstalled; property TopSortedClasses: TBoldClassTypeInfoList read FTopSortedClasses; @@ -230,21 +345,25 @@ TBoldClassTypeInfo = class(TBoldElementTypeInfoWithConstraint) private fOptimisticLocking: TBoldOptimisticLockingMode; FAllMembers: TBoldMemberRTInfoList; + fAllRoles: TBoldRoleRTInfoList; FFirstOwnMemberIndex: Integer; FMethods: TBoldMethodRTInfoList; - FObjectClass: TClass; // Really TBoldObjectClass The class with which it should be instansiated. + FObjectClass: TClass; fSuperClassTypeInfo: TBoldClassTypeInfo; fSystemTypeInfo: TBoldSystemTypeInfo; fTopSortedIndex: Integer; FStereotype: string; fDefaultStringRepresentation: string; fEmbeddedSingleLinkCount: integer; + fDerivedMemberCount: integer; fAllMembersCount: integer; + fAllRolesCount: Integer; fPackagename: string; - function GetListTypeInfo: TBoldListTypeInfo; - function GetMemberIndexByExpressionName(const name: string): Integer; - function GetMemberRTInfoByExpressionName(const Name: string): TBoldMemberRTInfo; - function GetMemberRTInfoByModelName(const Name: string): TBoldMemberRTInfo; + fSubClasssesBoldClassTypeInfoList: TBoldClassTypeInfoList; + fListTypeInfo: TBoldListTypeInfo; + function GetMemberIndexByExpressionName(const name: string): Integer; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetMemberRTInfoByExpressionName(const Name: string): TBoldMemberRTInfo; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetMemberRTInfoByModelName(const Name: string): TBoldMemberRTInfo; {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure InitializeMultiplicityConstraints; procedure Initialize(MoldClass: TMoldClass; TypeNameDictionary: TBoldTypeNameDictionary; BoldObjectClasses: TBoldGeneratedClassList; BoldObjectListClasses: TBoldGeneratedClassList; SkipMembers: Boolean); virtual; procedure SetObjectClass(BoldObjectClasses: TBoldGeneratedClassList); @@ -252,19 +371,29 @@ TBoldClassTypeInfo = class(TBoldElementTypeInfoWithConstraint) protected constructor Create(SystemTypeInfo: TBoldSystemTypeInfo; moldClass: TMoldClass; TypeNameDictionary: TBoldTypeNameDictionary; BoldObjectClasses: TBoldGeneratedClassList; BoldObjectListClasses: TBoldGeneratedClassList; SkipMembers: Boolean = false); function GetBoldType: TBoldElementTypeInfo; override; + function GetDisplayName: String; override; + function GetListTypeInfo: TBoldListTypeInfo; override; public +{$IFDEF BOLD_LITE} + class function NewInstance: TObject; override; + procedure FreeInstance; override; +{$ENDIF} destructor Destroy; override; function BoldIsA(C2: TBoldElementTypeInfo): Boolean; virtual; function ConformsTo(CompareElement: TBoldElementTypeInfo): Boolean; override; function LeastCommonSuperClass(OtherClassTypeInfo: TBoldClassTypeInfo): TBoldClassTypeInfo; + function ElementClass: TBoldElementClass; override; + function CreateElement: TBoldElement; override; property AllMembers: TBoldMemberRTInfoList read fAllMembers; + property AllRoles: TBoldRoleRTInfoList read fAllRoles; + property AllRolesCount: Integer read fAllRolesCount; + property DerivedMemberCount: integer read fDerivedMemberCount; property AllMembersCount: integer read fAllMembersCount; property FirstOwnMemberIndex: Integer read FFirstOwnMemberIndex; property HasSubclasses: Boolean index befHasSubclasses read GetElementFlag; property IsAbstract: Boolean index befIsAbstract read GetElementFlag; property IsImported: Boolean index befIsImported read GetElementFlag; property IsLinkClass: Boolean index befIsLinkClass read GetElementFlag; - property ListTypeInfo: TBoldListTypeInfo read GetListTypeInfo; property MemberIndexByExpressionName[const name: string]: Integer read GetMemberIndexByExpressionName; property MemberRTInfoByExpressionName[const Name: string]: TBoldMemberRTInfo read GetMemberRTInfoByExpressionName; property MemberRTInfoByModelName[const Name: string]: TBoldMemberRTInfo read GetMemberRTInfoByModelName; @@ -282,6 +411,7 @@ TBoldClassTypeInfo = class(TBoldElementTypeInfoWithConstraint) property GenerateDefaultRegion: Boolean index befGenerateDefaultRegion read GetElementFlag; property EmbeddedSingleLinkCount: integer read fEmbeddedSingleLinkCount; property QualifiedName: string read GetQualifiedName; + property SubClasssesBoldClassTypeInfoList: TBoldClassTypeInfoList read fSubClasssesBoldClassTypeInfoList; end; {---TBoldNilTypeInfo---} @@ -298,32 +428,37 @@ TBoldNilTypeInfo = class(TBoldClassTypeInfo) TBoldMemberRTInfo = class(TBoldMetaElementWithConstraint) private fDeriveExpression: string; + fDeriveMethod: Pointer; + fReverseDeriveMethod: Pointer; fStereotype: string; fDispId: integer; fBoldType: TBoldElementTypeInfo; fClassTypeInfo: TBoldClassTypeInfo; fIndex: Integer; - fEmbeddedLinkIndex: integer; // -1 if not an embedded link + fDeriverIndex: Integer; + fEmbeddedLinkIndex: integer; fVisibility: TVisibilityKind; fStreamName: string; protected constructor Create(ClassTypeInfo: TBoldClassTypeInfo; moldMember: TMoldMember; TypeNameDictionary: TBoldTypeNameDictionary); constructor CreateWithoutMoldMember(ClassTypeInfo: TBoldClassTypeInfo; const ModelName: string; const ExpressionName: string; const DelphiName: string; Persistent: Boolean ; TypeNameDictionary: TBoldTypeNameDictionary); + function GetDisplayName: String; override; function GetBoldType: TBoldElementTypeInfo; override; - function GetIsAttribute: Boolean; - function GetIsRole: Boolean; + function GetIsRole: Boolean; virtual; procedure SetBoldType(BoldType: TBoldElementTypeInfo); function GetMemberClass: TClass; virtual; abstract; function GetEncouragesOptimisticLockingOnDeletedOnly: Boolean; virtual; function GetCanHaveOldValue: Boolean; virtual; + function GetStoreInUndo: boolean; virtual; abstract; public destructor Destroy; override; - property IsDerived: Boolean index befIsDerived read GetElementFlag; // Always false for roles. + property IsDerived: Boolean index befIsDerived read GetElementFlag; property ClassTypeInfo: TBoldClassTypeInfo read fClassTypeInfo; property DelayedFetch: Boolean index befDelayedFetch read GetElementFlag; property index: Integer read FIndex; property EmbeddedLinkIndex: integer read fEmbeddedLinkIndex; - property IsAttribute: Boolean read GetIsAttribute; + property DeriverIndex: Integer read fDeriverIndex; + property IsAttribute: Boolean index befIsAttribute read GetElementFlag; property IsMultiRole: Boolean index befIsMultiRole read GetElementFlag; property IsRole: Boolean read GetIsRole; property IsSingleRole: Boolean index befIsSingleRole read GetElementFlag; @@ -340,18 +475,21 @@ TBoldMemberRTInfo = class(TBoldMetaElementWithConstraint) property CanHaveOldValue: Boolean read GetCanHaveOldValue; property ToBeRemoved: Boolean index befMemberToBeRemoved read GetElementFlag; property DispId: integer read fDispId; + property DeriveMethod: Pointer read fDeriveMethod write fDeriveMethod; // this is a bit unsafe since anyone can change it. + property ReverseDeriveMethod: Pointer read fReverseDeriveMethod write fReverseDeriveMethod; // this is a bit unsafe since anyone can change it. + property StoreInUndo: boolean read GetStoreInUndo; end; {---TBoldRoleRTInfo---} TBoldRoleRTInfo = class(TBoldMemberRTInfo) private fClassTypeInfoOfOtherEnd: TBoldClassTypeInfo; - fIndexOfOtherEnd: Integer; // Note, -1 if other end not maintained + fIndexOfOtherEnd: Integer; fLinkClassTypeInfo: TBoldClassTypeInfo; fOtherIndexInLinkClass: Integer; fOwnIndexInLinkClass: Integer; fQualifiers: TBoldMemberRTInfoList; - fRoleRTInfoOfOtherEnd: TBoldRoleRTInfo; // note, for an indirect this is the role in the link class + fRoleRTInfoOfOtherEnd: TBoldRoleRTInfo; fRoleType: TBoldRoleType; fMultiplicity: string; fChangeability: TChangeableKind; @@ -359,8 +497,8 @@ TBoldRoleRTInfo = class(TBoldMemberRTInfo) fDeleteAction: TDeleteAction; fAssociationStereotype: string; class procedure SetPass2InfoForAssociation(SystemTypeInfo: TBoldSystemTypeInfo; moldASsociation: TMoldAssociation); - function GetIndexOfLinkObjectRole: Integer; - function GetIndexOfMainRole: Integer; + function GetIndexOfLinkObjectRole: Integer; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetIndexOfMainRole: Integer; {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure InitQualifiers(Qualifiers: TMoldQualifierList); function GetDefaultRegionMode: TBoldAssociationEndDefaultRegionMode; protected @@ -373,14 +511,16 @@ TBoldRoleRTInfo = class(TBoldMemberRTInfo) function GetStringRepresentation(Representation: TBoldRepresentation): string; override; function GetEncouragesOptimisticLockingOnDeletedOnly: Boolean; override; function GetCanHaveOldValue: Boolean; override; + function GetIsRole: Boolean; override; + function GetStoreInUndo: boolean; override; public - destructor Destroy; override; + destructor destroy; override; procedure SetForceOtherEnd; property ClassTypeInfoOfOtherEnd: TBoldClassTypeInfo read FClassTypeInfoOfOtherEnd; property ForceOtherEnd: Boolean index befForceOtherEnd read GetElementFlag; property IndexOfLinkObjectRole: Integer read GetIndexOfLinkObjectRole; property IndexOfMainRole: Integer read GetIndexOfMainRole; - property IndexOfOtherEnd: Integer read FIndexOfOtherEnd; // index of the main role + property IndexOfOtherEnd: Integer read FIndexOfOtherEnd; property IsIndirect: Boolean index befIsIndirect read GetElementFlag; property IsNavigable: Boolean index befIsNavigable read GetElementFlag; property IsOrdered: Boolean index befIsOrdered read GetElementFlag; @@ -402,21 +542,6 @@ TBoldRoleRTInfo = class(TBoldMemberRTInfo) property AssociationStereotype: string read fAssociationStereotype; end; - {---TBoldListTypeInfo---} - TBoldListTypeInfo = class(TBoldElementTypeInfo) - private - fListClass: TClass; - fListElementTypeInfo: TBoldElementTypeInfo; - protected - constructor Create(ListElementTypeInfo: TBoldElementTypeInfo; SystemTypeInfo: TBoldSystemTypeInfo; ListClass: TClass); - function GetBoldType: TBoldElementTypeInfo; override; - function GetStringRepresentation(Representation: TBoldRepresentation): string; override; - public - function ConformsTo(CompareElement: TBoldElementTypeInfo): Boolean; override; - property ListClass: TClass read fListClass; - property ListElementTypeInfo: TBoldElementTypeInfo read fListElementTypeInfo; - end; - {---TBoldAttributeRTInfo---} TBoldAttributeRTInfo = class(TBoldMemberRTInfo) private @@ -426,6 +551,8 @@ TBoldAttributeRTInfo = class(TBoldMemberRTInfo) constructor Create(ClassTypeInfo: TBoldClassTypeInfo; MoldAttribute: TMoldAttribute; TypeNameDictionary: TBoldTypeNameDictionary); function GetMemberClass: TClass; override; function GetStringRepresentation(Representation: TBoldRepresentation): string; override; + function GetIsRole: Boolean; override; + function GetStoreInUndo: boolean; override; public property AllowNull: Boolean index befAllowNull read GetElementFlag; property Length: Integer read FLength; @@ -439,15 +566,20 @@ TBoldAttributeTypeInfo = class(TBoldElementTypeInfo) fAttributeClass: TClass; fIsAbstract: Boolean; fSuperAttributeTypeInfo: TBoldAttributeTypeInfo; + fListTypeInfo: TBoldListTypeInfo; protected constructor Create(const ModelName, ExpressionName: string; AttributeClass: TClass; SuperType: TBoldAttributeTypeInfo;const FallBackDelphiName: String; SystemTypeInfo: TBoldSystemTypeInfo; IsAbstract: Boolean); function GetBoldType: TBoldElementTypeInfo; override; + function GetListTypeInfo: TBoldListTypeInfo; override; public function BoldIsA(aType: TBoldElementTypeInfo): Boolean; function ConformsTo(CompareElement: TBoldElementTypeInfo): Boolean; override; + function ElementClass: TBoldElementClass; override; + function CreateElement: TBoldElement; override; property AttributeClass: TClass read fAttributeClass; property IsAbstract: Boolean read fIsAbstract; property SuperAttributeTypeInfo: TBoldAttributeTypeInfo read fSuperAttributeTypeInfo; + property ListTypeInfo: TBoldListTypeInfo read GetListTypeInfo; end; {---TBoldMethodRTInfo---} @@ -508,19 +640,21 @@ implementation SysUtils, BoldUtils, BoldGuard, - BoldIndexableList, BoldNameExpander, BoldHashIndexes, BoldMemberTypeDictionary, BoldOcl, BoldTypeList, BoldDefaultTaggedValues, - BoldCoreConsts, - BoldSystem; // FIXME move out last links here to dictionaries + BoldSystem, + BoldAttributes, + BoldDefaultStreamNames, + Windows; +{$IFDEF BOLD_LITE} var - IX_Element: integer = -1; - IX_ObjectClass: integer = -1; + G_TheSystemType: TBoldSystemTypeInfo; +{$ENDIF} type {---TObjectClassIndex---} @@ -535,6 +669,12 @@ TElementIndex = class(TBoldObjectHashIndex) function ItemAsKeyObject(Item: TObject): TObject; override; end; + {---TObjectClassIndex---} + TListClassIndex = class(TBoldClassHashIndex) + protected + function ItemAsKeyClass(Item: TObject): TClass; override; + end; + { TElementIndex } function TElementIndex.ItemASKeyObject(Item: TObject): TObject; begin @@ -548,7 +688,6 @@ function TObjectClassIndex.ItemAsKeyClass(Item: TObject): TClass; Result := TBoldClassTypeInfo(Item).ObjectClass; end; - {---TBoldClassTypeInfoList---} constructor TBoldClassTypeInfoList.Create; begin @@ -557,6 +696,11 @@ constructor TBoldClassTypeInfoList.Create; SetIndexvariable(IX_ObjectClass, AddIndex(TObjectClassIndex.Create)); end; +function TBoldClassTypeInfoList.GetEnumerator: TBoldClassTypeInfoListTraverser; +begin + result := CreateTraverser as TBoldClassTypeInfoListTraverser; +end; + function TBoldClassTypeInfoList.GetItem(index: Integer): TBoldClassTypeInfo; begin Result := TBoldClassTypeInfo(inherited Items[index]); @@ -574,10 +718,20 @@ function TBoldClassTypeInfoList.GetItemByExpressionName(const ExpressionName: st function TBoldClassTypeInfoList.GetItemByObjectClass(ObjectClass: TClass): TBoldClassTypeInfo; begin - Result := TBoldClassTypeInfo(TObjectClassIndex(Indexes[IX_ObjectClass]).FindByClass(ObjectClass)); + Result := TBoldClassTypeInfo(TBoldClassHashIndex(Indexes[IX_ObjectClass]).FindByClass(ObjectClass)); +end; + +function TBoldClassTypeInfoList.TraverserClass: TBoldIndexableListTraverserClass; +begin + result := TBoldClassTypeInfoListTraverser; end; {---TBoldMemberRTInfoList---} +function TBoldMemberRTInfoList.GetEnumerator: TBoldMemberRTInfoListTraverser; +begin + result := CreateTraverser as TBoldMemberRTInfoListTraverser; +end; + function TBoldMemberRTInfoList.GetItem(index: Integer): TBoldMemberRTInfo; begin Result := TBoldMemberRTInfo(inherited Items[index]); @@ -588,12 +742,22 @@ function TBoldMemberRTInfoList.GetItemByModelName(const ModelName: string): TBol Result := TBoldMemberRTInfo(inherited ItemsByModelName[ModelName]); end; +function TBoldMemberRTInfoList.TraverserClass: TBoldIndexableListTraverserClass; +begin + result := TBoldMemberRTInfoListTraverser; +end; + function TBoldMemberRTInfoList.GetItemByExpressionName(const ExpressionName: string): TBoldMemberRTInfo; begin Result := TBoldMemberRTInfo(inherited ItemsByExpressionName[ExpressionName]); end; {---TBoldMethodRTInfoList---} +function TBoldMethodRTInfoList.GetEnumerator: TBoldMethodRTInfoListTraverser; +begin + result := CreateTraverser as TBoldMethodRTInfoListTraverser; +end; + function TBoldMethodRTInfoList.GetItem(index: Integer): TBoldMethodRTInfo; begin Result := TBoldMethodRTInfo(inherited Items[index]); @@ -604,6 +768,11 @@ function TBoldMethodRTInfoList.GetItemByModelName(const ModelName: string): TBol Result := TBoldMethodRTInfo(inherited ItemsByModelName[ModelName]); end; +function TBoldMethodRTInfoList.TraverserClass: TBoldIndexableListTraverserClass; +begin + result := TBoldMethodRTInfoListTraverser; +end; + function TBoldMethodRTInfoList.GetItemByExpressionName(const ExpressionName: string): TBoldMethodRTInfo; begin Result := TBoldMethodRTInfo(inherited ItemsByExpressionName[ExpressionName]); @@ -612,14 +781,21 @@ function TBoldMethodRTInfoList.GetItemByExpressionName(const ExpressionName: str {---TBoldListTypeInfoList---} function TBoldListTypeInfoList.GetItemByElement(Element: TBoldElementTypeInfo): TBoldListTypeInfo; begin - Result := TBoldListTypeInfo(TElementIndex(Indexes[IX_Element]).FindByObject(Element)) + Result := TBoldListTypeInfo(TBoldObjectHashIndex(Indexes[IX_Element]).FindByObject(Element)) +end; + +function TBoldListTypeInfoList.GetItemByListClass( + ListClass: TClass): TBoldListTypeInfo; +begin + Result := TBoldListTypeInfo(TBoldClassHashIndex(Indexes[IX_ListClass]).FindByClass(ListClass)); end; constructor TBoldListTypeInfoList.Create; begin inherited; SetIndexCapacity(4); - SetIndexVariable(IX_Element, self.AddIndex(TElementIndex.Create)); + SetIndexVariable(IX_Element, AddIndex(TElementIndex.Create)); + SetIndexVariable(IX_ListClass, AddIndex(TListClassIndex.Create)); end; {---TBoldTypeTypeInfo---} @@ -639,11 +815,65 @@ function TBoldTypeTypeInfo.GetBoldType: TBoldElementTypeInfo; result := self; end; +function TBoldTypeTypeInfo.GetListTypeInfo: TBoldListTypeInfo; +begin + Result := TBoldSystemTypeInfo(SystemTypeInfo).ListTypes.ItemByElement[self]; +end; + +{ TBoldAttributeTypeInfoList } + +function TBoldAttributeTypeInfoList.GetEnumerator: TBoldAttributeTypeInfoListTraverser; +begin + result := CreateTraverser as TBoldAttributeTypeInfoListTraverser; +end; + +function TBoldAttributeTypeInfoList.GetItem( + index: Integer): TBoldAttributeTypeInfo; +begin + Result := TBoldAttributeTypeInfo(inherited Items[index]); +end; + +function TBoldAttributeTypeInfoList.GetItemByExpressionName( + const ExpressionName: string): TBoldAttributeTypeInfo; +begin + Result := TBoldAttributeTypeInfo(inherited ItemsByExpressionName[ExpressionName]); +end; + +function TBoldAttributeTypeInfoList.GetItemByModelName( + const ModelName: string): TBoldAttributeTypeInfo; +begin + Result := TBoldAttributeTypeInfo(inherited ItemsByModelName[ModelName]); +end; + +function TBoldAttributeTypeInfoList.TraverserClass: TBoldIndexableListTraverserClass; +begin + result := TBoldAttributeTypeInfoListTraverser; +end; + {---TBoldSystemTypeInfo---} function TBoldSystemTypeInfo.GetListTypeInfoByElement(Element: TBoldElementTypeInfo): TBoldListTypeInfo; begin - Result := fListTypes.ItemByElement[Element]; + if not Assigned(Element) then + Result := UntypedListTypeInfo + else + result := Element.ListTypeInfo; +end; + +function TBoldSystemTypeInfo.GetMemberTypeInfoByQualifiedName(const AClassName, AMemberName: string): TBoldMemberRtInfo; +var + vClassTypeInfo: TBoldClassTypeInfo; +begin + result := nil; + vClassTypeInfo := ClassTypeInfoByExpressionName[AClassName]; + if Assigned(vClassTypeInfo) then + result := vClassTypeInfo.MemberRTInfoByExpressionName[AMemberName]; +end; + +function TBoldSystemTypeInfo.GetClassTypeInfoByClass( + ObjectClass: TClass): TBoldClassTypeInfo; +begin + result := TopSortedClasses.ItemsByObjectClass[ObjectClass]; end; function TBoldSystemTypeInfo.GetClassTypeInfoByExpressionName(const name: string): TBoldClassTypeInfo; @@ -663,6 +893,7 @@ function TBoldSystemTypeInfo.GetAttributeTypeInfoByDelphiName(const name: string Assert(not Assigned(result) or (Result is TBoldAttributeTypeInfo)); end; + constructor TBoldSystemTypeInfo.Create(moldModel: TMoldModel; UseGeneratedCode, CheckCodeCheckSum: Boolean; TypeNameDictionary: TBoldTypeNameDictionary); var i: integer; @@ -670,6 +901,7 @@ constructor TBoldSystemTypeInfo.Create(moldModel: TMoldModel; UseGeneratedCode, BoldObjectListClasses: TBoldGeneratedClassList; Errors: TStringList; Guard: IBoldGuard; + BoldGeneratedCodeDescriptor: TBoldGeneratedCodeDescriptor; begin inherited Create(MoldModel, self); Guard := TBoldGuard.Create(BoldObjectListClasses, BoldObjectClasses, Errors); @@ -679,11 +911,16 @@ constructor TBoldSystemTypeInfo.Create(moldModel: TMoldModel; UseGeneratedCode, SetElementFlag(befSystemIsRunnable, true); fOptimisticLocking := MoldModel.OptimisticLocking; +{$IFDEF BOLD_LITE} + G_TheSystemType := self; +{$ENDIF} SetValueType(bvtSystem); - fTypeTypeInfo := TBoldTypeTypeInfo.Create('MetaType', 'MetaType', 'MetaType', self); // do not localize + fTypeTypeInfo := TBoldTypeTypeInfo.Create('MetaType', 'MetaType', 'MetaType', self); - fAttributeTypes := TBoldElementTypeInfoList.Create; + fAttributeTypes := TBoldAttributeTypeInfoList.Create; + AttributeTypes.Capacity := TypeNameDictionary.count; fListTypes := TBoldListTypeInfoList.Create; + ListTypes.Capacity := TypeNameDictionary.count + moldModel.Classes.Count + 1; ListTypes.Add(TBoldListTypeInfo.Create(fTypeTypeinfo, self, TBoldTypeList)); SetElementFlag(befSystemPersistent, true); SetElementFlag(befGenerateDefaultRegions, MoldModel.GenerateDefaultRegions); @@ -696,17 +933,29 @@ constructor TBoldSystemTypeInfo.Create(moldModel: TMoldModel; UseGeneratedCode, fUseGeneratedCode := UseGeneratedCode; if UseGeneratedCode then begin + BoldGeneratedCodeDescriptor := nil; for i := 0 to GeneratedCodes.Count - 1 do - if GeneratedCodes.ModelEntries[i].ExpressionName = MoldModel.ExpandedExpressionName then + if (GeneratedCodes.ModelEntries[i].ExpressionName = MoldModel.ExpandedExpressionName) then begin - if assigned(GeneratedCodes.ModelEntries[i].InstallBusinessClasses) then - GeneratedCodes.ModelEntries[i].InstallBusinessClasses(BoldObjectClasses); - if assigned(GeneratedCodes.ModelEntries[i].InstallObjectListClasses) then - GeneratedCodes.ModelEntries[i].InstallObjectListClasses(BoldObjectListClasses); - if CheckCodeCheckSum and (GeneratedCodes.ModelEntries[i].CRC <> '') and - (GeneratedCodes.ModelEntries[i].CRC <> MoldModel.CRC) then - InitializationError(sCRCDiffers, [MoldModel.CRC, GeneratedCodes.ModelEntries[i].CRC]); + BoldGeneratedCodeDescriptor := GeneratedCodes.ModelEntries[i]; + if (not CheckCodeCheckSum or (BoldGeneratedCodeDescriptor.CRC = '') or (BoldGeneratedCodeDescriptor.CRC = MoldModel.CRC)) then + begin + if assigned(BoldGeneratedCodeDescriptor.InstallBusinessClasses) then + begin + BoldObjectClasses.Capacity := moldModel.Classes.Count; + BoldGeneratedCodeDescriptor.InstallBusinessClasses(BoldObjectClasses); + end; + if assigned(BoldGeneratedCodeDescriptor.InstallObjectListClasses) then + begin + BoldObjectListClasses.Capacity := moldModel.Classes.Count; + BoldGeneratedCodeDescriptor.InstallObjectListClasses(BoldObjectListClasses); + end; + break; + end; end; + if CheckCodeCheckSum and (Assigned(BoldGeneratedCodeDescriptor) and (BoldGeneratedCodeDescriptor.CRC <> '') and (BoldGeneratedCodeDescriptor.CRC <> MoldModel.CRC) ) then + InitializationError('Generated CRC differs from Model CRC (expected %s, found %s). Please regenerate code.', + [MoldModel.CRC, BoldGeneratedCodeDescriptor.CRC]); end; for I := 0 to TypeNameDictionary.count - 1 do @@ -714,12 +963,8 @@ constructor TBoldSystemTypeInfo.Create(moldModel: TMoldModel; UseGeneratedCode, InstallAttributeType(TypeNameDictionary, i); end; - // The super-element-list that all other lists conform to (Used for OCL) - // Note: The elements does not need to (and should not) conform! - ListTypes.Add(TBoldListTypeInfo.Create(nil, self, TBoldObjectList)); - - // Superclasses must be constructed first. - // This also assures that FClasses will be topologicaly sorted + fUntypedListTypeInfo := TBoldListTypeInfo.Create(nil, self, TBoldObjectList); + ListTypes.Add(fUntypedListTypeInfo); moldModel.EnsureTopSorted; @@ -729,16 +974,15 @@ constructor TBoldSystemTypeInfo.Create(moldModel: TMoldModel; UseGeneratedCode, begin for i := 0 to Errors.Count - 1 do InitializationError(Errors[i], []); - // hopefully the root-class can be installed, it is required to get OCL running... TBoldClassTypeInfo.Create(self, moldModel.Classes[0], TypeNameDictionary, BoldObjectClasses, BoldObjectListClasses, true); exit; end; - + TopSortedClasses.Capacity := moldModel.Classes.Count; for I := 0 to moldModel.Classes.Count - 1 do TBoldClassTypeInfo.Create(self, moldModel.Classes[I], TypeNameDictionary, BoldObjectClasses, BoldObjectListClasses); - for I := 0 to moldModel.Associations.Count - 1 do // FIXME iterate on Classes instead + for I := 0 to moldModel.Associations.Count - 1 do TBoldRoleRTInfo.SetPass2InfoForAssociation(self, moldModel.Associations[I]); if GenerateMultiplicityConstraints then @@ -750,7 +994,7 @@ constructor TBoldSystemTypeInfo.Create(moldModel: TMoldModel; UseGeneratedCode, for i := 0 to TopSortedClasses.Count - 1 do if CompareText(TopSortedClasses[i].ObjectClass.ClassName, TopSortedClasses[i].DelphiName) <> 0 then begin - InitializationError(sGeneratedCodeNotRegistered, + InitializationError('Generated code for %s not registered with framework, ensure that it is included in project', [TopSortedClasses[i].ExpressionName]); end; end; @@ -758,6 +1002,7 @@ constructor TBoldSystemTypeInfo.Create(moldModel: TMoldModel; UseGeneratedCode, fMethodsInstalled := False; fNilTypeInfo := TBoldNilTypeInfo.Create(self, nil, nil, nil, nil); + fValueSetTypeInfo := AttributeTypeInfoByExpressionName['ValueSet']; end; function TBoldSystemTypeInfo.GetEvaluator: TBoldEvaluator; @@ -770,6 +1015,7 @@ function TBoldSystemTypeInfo.GetEvaluator: TBoldEvaluator; destructor TBoldSystemTypeInfo.Destroy; begin FreeAndNil(fListTypes); + FreeAndNil(fValueSetTypeInfoList); FreeAndNil(fAttributeTypes); FreeAndNil(fEvaluator); FreeAndNil(fTypeTypeInfo); @@ -780,6 +1026,97 @@ destructor TBoldSystemTypeInfo.Destroy; inherited; end; +function TBoldSystemTypeInfo.FindElement(const AText: string; + ASearchOptions: TBoldTypeInfoSearchOptions; + ASearchTypes: TBoldSearchTypes): TBoldMetaElement; + +var + s: string; + + function StringMatch(AElement: TBoldMetaElement): boolean; + begin + result :=((soPartialMatch in ASearchOptions) and (Pos(s, UpperCase(AElement.ExpressionName)) > 0)) + or SameText(UpperCase(AElement.ExpressionName), s); + end; + +var + ClassTypeInfo: TBoldClassTypeInfo; + MemberRTInfo: TBoldMemberRTInfo; + MethodRTInfo: TBoldMethodRTInfo; + AttributeTypeInfo: TBoldAttributeTypeInfo; +begin + result := nil; + s := UpperCase(AText); +// TBoldSearchType = stClass, stAttribute, stRole, stMethod, stType + for ClassTypeInfo in TopSortedClasses do + begin + if (stClass in ASearchTypes) and StringMatch(ClassTypeInfo) then + begin + result := ClassTypeInfo; + exit; + end; + if (stAttribute in ASearchTypes) or (stRole in ASearchTypes) then + for MemberRTInfo in ClassTypeInfo.AllMembers do + begin + if (((stRole in ASearchTypes) and MemberRTInfo.IsRole) + or ((stAttribute in ASearchTypes) and MemberRTInfo.IsAttribute) + and StringMatch(MemberRTInfo)) then + begin + result := MemberRTInfo; + exit; + end + end; + if (stMethod in ASearchTypes) then + for MethodRTInfo in ClassTypeInfo.Methods do + if StringMatch(MethodRTInfo) then + begin + result := MethodRTInfo; + exit; + end + end; + if (stType in ASearchTypes) then + for AttributeTypeInfo in AttributeTypes do + if StringMatch(AttributeTypeInfo) then + begin + result := AttributeTypeInfo; + exit; + end +end; + +function TBoldSystemTypeInfo.FindValueSetAndTypeByName( + const AName: string; out AElement: TBoldElement; out ATypeInfo: TBoldElementTypeInfo): boolean; +var + i: integer; + vValueSetClass: TBAValueSetClass; +begin + result := false; + if AName = '' then + exit; + for I := 0 to ValueSetTypeInfoList.Count - 1 do + begin + vValueSetClass := TBAValueSetClass(ValueSetTypeInfoList[i].ElementClass); + // TBABoolean descendants like TBAConstraint do not define new values, so they contain duplicated T/F therefore we skip them + if {(vValueSetClass = TBABoolean) or} {(not vValueSetClass.InheritsFrom(TBABoolean) and} (vValueSetClass.GetValues <> nil) then + begin + AElement := vValueSetClass.GetValues.FindByString(brDefault, AName); + if Assigned(AElement) then + begin + result := true; + ATypeInfo := ValueSetTypeInfoList[i]; + exit; + end; + end; + end; +end; + +function TBoldSystemTypeInfo.FindValueSetByName( + const AName: string): TBoldElement; +var + vTypeInfo: TBoldElementTypeInfo; +begin + FindValueSetAndTypeByName(AName, result, vTypeInfo); +end; + function TBoldSystemTypeInfo.ConformsTo(CompareElement: TBoldElementTypeInfo): Boolean; begin Result := CompareElement = self; @@ -793,37 +1130,55 @@ function TBoldSystemTypeInfo.GetValueTypeNameList: TBoldElementTypeInfoList; begin fValueTypeNameList := TBoldElementTypeInfoList.Create; fValueTypeNameList.OwnsEntries := false; - // System + fValueTypeNameList.Capacity := TopSortedClasses.Count + AttributeTypes.Count + ListTypes.Count + 2; fValueTypeNameList.Add(self); - // Classes for I := 0 to TopSortedClasses.Count - 1 do fValueTypeNameList.Add(TopSortedClasses[I]); - // Attributes for I := 0 to AttributeTypes.Count - 1 do fValueTypeNameList.Add(AttributeTypes[I]); - // MetaType fValueTypeNameList.Add(BoldType); - // ListTypes for I := 0 to ListTypes.Count - 1 do fValueTypeNameList.Add(ListTypes[I]); end; Result := fValueTypeNameList; end; +function TBoldSystemTypeInfo.GetValueSetTypeInfoList: TBoldElementTypeInfoList; +var + I: Integer; +begin + if not assigned(fValueSetTypeInfoList) then + begin + fValueSetTypeInfoList := TBoldElementTypeInfoList.Create; + fValueSetTypeInfoList.OwnsEntries := false; + fValueSetTypeInfoList.Capacity := AttributeTypes.Count; + for I := 0 to AttributeTypes.Count - 1 do + if AttributeTypes[I].ConformsTo(fValueSetTypeInfo) and not TBoldAttributeTypeInfo(AttributeTypes[I]).IsAbstract then + fValueSetTypeInfoList.Add(AttributeTypes[I]); + end; + result := fValueSetTypeInfoList; +end; + procedure TBoldSystemTypeInfo.GetValueTypeNames(S: TStrings; Classes, Types, System, metatype, lists: Boolean); var I: Integer; begin S.Clear; - for I := 0 to ValueTypeNameList.Count - 1 do - begin - case ValueTypeNameList[I].BoldValueType of - bvtList: if lists then S.Add(ValueTypeNameList[I].ExpressionName); - bvtClass: if Classes then S.Add(ValueTypeNameList[I].ExpressionName); - bvtAttr: if Types then S.Add(ValueTypeNameList[I].ExpressionName); - bvtSystem: if System then S.Add(ValueTypeNameList[I].ExpressionName); - bvtType: if metatype then S.Add(ValueTypeNameList[I].ExpressionName); + s.Capacity := ValueTypeNameList.Count; + s.BeginUpdate; + try + for I := 0 to ValueTypeNameList.Count - 1 do + begin + case ValueTypeNameList[I].BoldValueType of + bvtList: if lists then S.Add(ValueTypeNameList[I].ExpressionName); + bvtClass: if Classes then S.Add(ValueTypeNameList[I].ExpressionName); + bvtAttr: if Types then S.Add(ValueTypeNameList[I].ExpressionName); + bvtSystem: if System then S.Add(ValueTypeNameList[I].ExpressionName); + bvtType: if metatype then S.Add(ValueTypeNameList[I].ExpressionName); + end; end; + finally + s.EndUpdate; end; end; @@ -882,26 +1237,64 @@ constructor TBoldClassTypeInfo.Create(SystemTypeInfo: TBoldSystemTypeInfo; moldC fStereotype := MoldClass.Stereotype; end else - inherited Create(nil, SystemTypeInfo); // NilTypeInfo... + inherited Create(nil, SystemTypeInfo); SetValueType(bvtClass); fSystemTypeInfo := SystemTypeInfo; fAllMembers := TBoldMemberRTInfoList.Create; + FAllRoles := TBoldRoleRTInfoList.Create; + FAllRoles.OwnsEntries := false; fMethods := TBoldMethodRTInfoList.Create; - + fSubClasssesBoldClassTypeInfoList := TBoldClassTypeInfoList.Create; + fSubClasssesBoldClassTypeInfoList.OwnsEntries := false; Initialize(MoldClass, TypeNameDictionary, BoldObjectClasses, BoldObjectListClasses, SkipMembers); end; +function TBoldClassTypeInfo.ElementClass: TBoldElementClass; +begin + result := TBoldObjectReference +end; + +function TBoldClassTypeInfo.CreateElement: TBoldElement; +begin + result := TBoldObjectReference.CreateWithTypeInfo(self); +end; + function TBoldClassTypeInfo.BoldIsA(C2: TBoldElementTypeInfo): Boolean; +var + lBoldClassTypeInfo: TBoldClassTypeInfo; begin - result := false; - if (C2.ClassType = TBoldClassTypeInfo) or (C2 is TBoldClassTypeInfo) then // TBoldClassTypeInfo may have subclasses in future + if (c2.ClassType = TBoldClassTypeInfo) then begin - if c2 = self then - Result := True - else if Assigned(SuperClassTypeInfo) then - Result := SuperClassTypeInfo.BoldIsA(C2); - end; + if C2 = Self then + begin + Result := True; + end + else + begin + lBoldClassTypeInfo := TBoldClassTypeInfo(C2); + // if TopSortedIndex of this class is smaller than of the other class then it can't possibly descend from it + if TopSortedIndex < lBoldClassTypeInfo.TopSortedIndex then + Result := false + else + begin + if SystemTypeInfo.UseGeneratedCode then + Result := ObjectClass.InheritsFrom(lBoldClassTypeInfo.ObjectClass) + else + begin + Result := false; + lBoldClassTypeInfo := self; + while not result and Assigned(lBoldClassTypeInfo.SuperClassTypeInfo) do + begin + lBoldClassTypeInfo := lBoldClassTypeInfo.SuperClassTypeInfo; + Result := lBoldClassTypeInfo = C2; + end; + end; + end; + end; + end + else + Result := false; end; function TBoldClassTypeInfo.ConformsTo(CompareElement: TBoldElementTypeInfo): Boolean; @@ -926,7 +1319,7 @@ function TBoldNilTypeInfo.BoldIsA(C2: TBoldElementTypeInfo): Boolean; function TBoldNilTypeInfo.GetStringRepresentation(Representation: TBoldRepresentation): string; begin - result := 'nil'; // do not localize + result := 'nil'; end; {---TBoldMemberRTInfo---} @@ -948,13 +1341,16 @@ constructor TBoldMemberRTInfo.Create(ClassTypeInfo: TBoldClassTypeInfo; moldMemb SetElementFlag(befDelayedFetch, moldMember.EffectiveDelayedFetch); fIndex := ClassTypeInfo.AllMembers.Count; fEmbeddedLinkIndex := -1; + fDeriverIndex := -1; ClassTypeInfo.AllMembers.Add(self); + if IsRole then + ClassTypeInfo.AllRoles.Add(Self); if isDerived then begin + fDeriverIndex := ClassTypeInfo.fDerivedMemberCount; + inc(ClassTypeInfo.fDerivedMemberCount); fDeriveExpression := MoldMember.DerivationOCL; - // Check if we find an override expression in a subclass somewhere, - // start from superclass and move up in inheritance chain if DeriveExpression <> '' then begin MoldClass := MoldMember.Model.Classes[ClassTypeInfo.topSortedIndex]; @@ -962,7 +1358,6 @@ constructor TBoldMemberRTInfo.Create(ClassTypeInfo: TBoldClassTypeInfo; moldMemb while assigned(MoldClass) and (MoldClass <> MoldMember.MoldClass) do begin Expressions.Text := MoldClass.BoldTVByName[TAG_DERIVATIONEXPRESSIONS]; - // the following fixes a problem with the models in 2.0.20 that added extra spaces sometimes. for i := 0 to Expressions.Count - 1 do Expressions[i] := trim(Expressions[i]); @@ -982,7 +1377,6 @@ constructor TBoldMemberRTInfo.Create(ClassTypeInfo: TBoldClassTypeInfo; moldMemb constructor TBoldMemberRTInfo.CreateWithoutMoldMember(ClassTypeInfo: TBoldClassTypeInfo; const ModelName, ExpressionName, DelphiName: string; Persistent: Boolean; TypeNameDictionary: TBoldTypeNameDictionary); function EnsureLowerCaseLeadingCharacter(const ExpressionName: String): String; begin - // this is needed for the linkObject-roles since their name is made from the expressionname of the class... result := ExpressionName; if length(result) > 0 then result[1] := LowerCase(result[1])[1]; @@ -993,7 +1387,10 @@ constructor TBoldMemberRTInfo.CreateWithoutMoldMember(ClassTypeInfo: TBoldClassT fClassTypeInfo := ClassTypeInfo; FIndex := ClassTypeInfo.AllMembers.Count; fEmbeddedLinkIndex := -1; + fDeriverIndex := -1; ClassTypeInfo.AllMembers.Add(self); + if IsRole then + ClassTypeInfo.AllRoles.Add(Self); end; destructor TBoldMemberRTInfo.Destroy; @@ -1041,7 +1438,7 @@ function TBoldMethodRTInfo.GetSignature; destructor TBoldMethodRTInfo.Destroy; begin freeAndNil(fParameterList); - inherited; + inherited; end; function TBoldMethodRTInfo.GetStringRepresentation(Representation: TBoldRepresentation): string; @@ -1094,7 +1491,6 @@ procedure TBoldMethodRTInfo.EnsureParameterLIst(const Signature: string); pClass := ClassTypeInfo.SystemTypeInfo.ClassTypeInfoByModelName[pType]; if assigned(pClass) then pType := pClass.Delphiname; - // take care of commaseparated parameterlists while Pos(',', Parameter) <> 0 do begin pname := trim(copy(Parameter, 0, Pos(',', Parameter) - 1)); @@ -1116,8 +1512,7 @@ class procedure TBoldRoleRTInfo.SetPass2InfoForAssociation(SystemTypeInfo: TBold begin if assigned(aRole) then begin - // if the role of the other end is not navigable, it might not be there, - // but there is still a class on the other end... + aRole.fClassTypeInfoOfOtherEnd := ClassOfOtherEnd; aRole.fRoleRTInfoOfOtherEnd := RoleofOtherEnd; if assigned(RoleOfOtherEnd) then @@ -1201,16 +1596,15 @@ class procedure TBoldRoleRTInfo.SetPass2InfoForAssociation(SystemTypeInfo: TBold LinkObjectRole2 := nil; if not assigned(moldAssociation.Roles[0].moldClass) then begin - SystemTypeInfo.InitializationError(sInvalidAssociation, [MoldAssociation.Name , MoldAssociation.Roles[0].Name]); + SystemTypeInfo.InitializationError('Invalid association: %s.%s does not point to a class', [MoldAssociation.Name , MoldAssociation.Roles[0].Name]); exit; end; if not assigned(moldAssociation.Roles[1].moldClass) then begin - SystemTypeInfo.InitializationError(sInvalidAssociation, [MoldAssociation.Name , MoldAssociation.Roles[1].Name]); + SystemTypeInfo.InitializationError('Invalid association: %s.%s does not point to a class', [MoldAssociation.Name , MoldAssociation.Roles[1].Name]); exit; end; - // note, non-navigable association ends of derived associations will not exist in Mold. - + Class1 := SystemTypeInfo.ClassTypeInfoByModelName[moldAssociation.Roles[0].moldClass.name]; TempMember := Class1.MemberRTInfoByModelName[moldAssociation.Roles[0].name]; Assert(not assigned(TempMember) or (TempMember is TBoldRoleRTInfo)); @@ -1259,12 +1653,11 @@ class procedure TBoldRoleRTInfo.SetPass2InfoForAssociation(SystemTypeInfo: TBold PropagateOtherEnd(LinkObjectRole2, LinkClass, LinkClassRole1); end; end; - // derived associations can have qualifiers, but might only exist in one direction if assigned(Role1) then Role1.InitQualifiers(moldAssociation.Roles[0].Qualifiers); if assigned(Role2) then Role2.InitQualifiers(moldAssociation.Roles[1].Qualifiers); - + PropagateToSubClasses(Role1, LinkObjectRole1, moldAssociation.Roles[0].moldClass); PropagateToSubClasses(Role2, LinkObjectRole2, moldAssociation.Roles[1].moldClass); end; @@ -1297,7 +1690,7 @@ constructor TBoldRoleRTInfo.Create(ClassTypeInfo: TBoldClassTypeInfo; MoldRole: SetElementFlag(befIsSingleRole, not MoldRole.Multi); SetElementFlag(befQualifiedMulti, MoldRole.QualifiedMulti); if IsMultiRole then - SetElementFlag(befDelayedFetch, True); // FIXME: + SetElementFlag(befDelayedFetch, True); SetElementFlag(befMandatory, MoldRole.Mandatory); SetElementFlag(befIsStoredInObject, MoldRole.EffectiveEmbedded and (not MoldRole.Multi) and Persistent); @@ -1323,13 +1716,25 @@ constructor TBoldRoleRTInfo.Create(ClassTypeInfo: TBoldClassTypeInfo; MoldRole: fDeleteAction := MoldRole.EffectiveDeleteAction; fChangeability := MoldRole.Changeability; fAssociationStereotype := MoldRole.Association.Stereotype; + + if IsSingleRole then + begin + if IsIndirect then + fStreamName := BoldContentName_ObjectIdRefPair + else + fStreamName := BoldContentName_ObjectIdRef; + end + else + if IsIndirect then + fStreamName := BoldContentName_ObjectIdListRefPair + else + fStreamName := BoldContentName_ObjectIdListRef; end; constructor TBoldRoleRTInfo.CreateInnerLinkRole(ClassTypeInfo: TBoldClassTypeInfo; MoldRole: TMoldRole; Dummy: Smallint; TypeNameDictionary: TBoldTypeNameDictionary); begin inherited Create(ClassTypeInfo, MoldRole, TypeNameDictionary); fRoleType := rtInnerLInkRole; -// FIsInnerLinkRole := True; SetElementFlag(befIsMultiRole, False); SetElementFlag(befIsSingleRole, true); SetElementFlag(befIsStoredInObject, Persistent); @@ -1345,6 +1750,7 @@ constructor TBoldRoleRTInfo.CreateInnerLinkRole(ClassTypeInfo: TBoldClassTypeInf fAggregation := akNone; fDeleteAction := daAllow; fChangeability := ckFrozen; + fStreamName := BoldContentName_ObjectIdRef; end; constructor TBoldRoleRTInfo.CreateLinkObjectRole(ClassTypeInfo: TBoldClassTypeInfo; MainRole: TMoldRole; TypeNameDictionary: TBoldTypeNameDictionary; Dummy: smallint); @@ -1352,7 +1758,6 @@ constructor TBoldRoleRTInfo.CreateLinkObjectRole(ClassTypeInfo: TBoldClassTypeIn aLinkClass: TMoldClass; begin aLinkClass := MainRole.Association.LinkClass; - // when both link-roles will occur in a class, they must use another namingscheme if MainRole.MoldClass.ChildTo(MainRole.OtherEnd.MoldClass) or MainRole.OtherEnd.MoldClass.ChildTo(MainRole.MoldClass) then inherited CreateWithoutMoldMember(ClassTypeInfo, @@ -1370,7 +1775,7 @@ constructor TBoldRoleRTInfo.CreateLinkObjectRole(ClassTypeInfo: TBoldClassTypeIn SetElementFlag(befIsMultiRole, MainRole.Multi); SetElementFlag(befIsSingleRole, not MainRole.Multi); if IsMultiRole then - SetElementFlag(befDelayedFetch, True); // FIXME: + SetElementFlag(befDelayedFetch, True); SetElementFlag(befMandatory, MainRole.Mandatory); SetElementFlag(befIsStoredInObject, false); SetElementFlag(befIsOrdered, MainRole.EffectiveOrdered); @@ -1378,41 +1783,51 @@ constructor TBoldRoleRTInfo.CreateLinkObjectRole(ClassTypeInfo: TBoldClassTypeIn SetElementFlag(befIsIndirect, false); SetInternalState(BoldDefaultRegionModeMask, BoldDefaultRegionModeShift, integer(aedrmNone)); fRoleType := rtLinkRole; - - // CheckMe Are these correct fAggregation := akNone; fDeleteAction := daAllow; fChangeability := MainRole.Changeability; + if IsMultiRole then + fStreamName := BoldContentName_ObjectIdRef + else + fStreamName := BoldContentName_ObjectIdListRef; +end; + +function TBoldRoleRTInfo.GetStoreInUndo: boolean; +begin + result := not IsDerived and (((RoleType = rtRole) and (not (IsMultiRole or IsIndirect))) or (RoleType = rtInnerLinkRole)); end; function TBoldRoleRTInfo.GetStringRepresentation(Representation: TBoldRepresentation): string; begin Result := ClassTypeInfo.AsString + '.' + ExpressionName; end; + function TBoldRoleRTInfo.GetCanHaveOldValue: Boolean; begin - result := inherited GetCanHaveOldValue and (RoleType in [rtRole, rtInnerLinkRole]); + result := Persistent and (RoleType in [rtRole, rtInnerLinkRole]); end; procedure TBoldRoleRTInfo.SetForceOtherEnd; begin - // should only be called by the region defintions when a multi role is included in a region. SetElementFlag(befForceOtherEnd, true); end; function TBoldRoleRTInfo.GetEncouragesOptimisticLockingOnDeletedOnly: Boolean; begin - // non-embedded roles should validate that they have been - // unchanged in the db when their objects are deleted + result := not IsStoredInObject and Persistent and (RoleType = rtRole); end; - function TBoldRoleRTInfo.GetIsQualified: Boolean; begin result := assigned(Qualifiers) and (Qualifiers.Count > 0); end; +function TBoldRoleRTInfo.GetIsRole: Boolean; +begin + result := true; +end; + function TBoldRoleRTInfo.GetQualifiers: TBoldMemberRTInfoList; begin result := FQualifiers; @@ -1429,43 +1844,6 @@ function TBoldRoleRTInfo.GetMemberClass: TClass; result := TBoldObjectReference; end; -{---TBoldListTypeInfo---} -constructor TBoldListTypeInfo.Create(ListElementTypeInfo: TBoldElementTypeInfo; SystemTypeInfo: TBoldSystemTypeInfo; ListClass: TClass); -begin - if assigned(ListElementTypeInfo) then - inherited Create(ListElementTypeInfo.ModelName + 'List', // do not localize - 'Collection(' + ListElementTypeInfo.ExpressionName + ')', // do not localize - ListElementTypeInfo.Delphiname + 'List', SystemTypeInfo) // do not localize - else - inherited Create('Collection()', 'Collection()', 'Collection()', SystemTypeInfo); // do not localize - fListElementTypeInfo := ListElementTypeInfo; - SetValueType(bvtList); - fListClass := ListClass; -end; - -function TBoldListTypeInfo.ConformsTo(CompareElement: TBoldElementTypeInfo): Boolean; -var - CompareListTypeInfo: TBoldListTypeInfo; -begin - if CompareElement is TBoldListTypeInfo then - begin - CompareListTypeInfo := TBoldListTypeInfo(CompareElement); - Result := not assigned(CompareListTypeInfo.ListElementTypeInfo) or - (assigned(ListElementTypeInfo) and - ListElementTypeInfo.ConformsTo(CompareListTypeInfo.ListElementTypeInfo)); - end - else - Result := False; -end; - -function TBoldListTypeInfo.GetStringRepresentation(Representation: TBoldRepresentation): string; -begin - if assigned(ListElementTypeInfo) then - Result := 'Collection(' + ListElementTypeInfo.AsString + ')' // do not localize - else - Result := 'Collection()'; // do not localize -end; - {---TBoldAttributeRTInfo---} constructor TBoldAttributeRTInfo.Create(ClassTypeInfo: TBoldClassTypeInfo; MoldAttribute: TMoldAttribute; TypeNameDictionary: TBoldTypeNameDictionary); @@ -1473,6 +1851,7 @@ constructor TBoldAttributeRTInfo.Create(ClassTypeInfo: TBoldClassTypeInfo; MoldA Mapping: TBoldTypeNameMapping; begin inherited Create(ClassTypeInfo, MoldAttribute, TypeNameDictionary); + SetElementFlag(befIsAttribute, true); SetElementFlag(befIsStoredInObject, Persistent); SetElementFlag(befAllowNull, MoldAttribute.AllowNull); SetElementFlag(befHasInitalvalue, fInitialvalue <> ''); @@ -1483,7 +1862,7 @@ constructor TBoldAttributeRTInfo.Create(ClassTypeInfo: TBoldClassTypeInfo; MoldA SetElementFlag(befHasInitalvalue, true); Mapping := TypeNameDictionary.MappingForModelName[MoldAttribute.BoldType]; if not assigned(Mapping) then - ClassTypeInfo.SystemTypeInfo.InitializationError(sCannotFindAttributeMapping, + ClassTypeInfo.SystemTypeInfo.InitializationError('Unable to find Mapping for %s.%s: %s', [MoldAttribute.MoldClass.ExpandedExpressionname, MoldAttribute.ExpandedExpressionName, MoldAttribute.BoldType]) @@ -1492,14 +1871,14 @@ constructor TBoldAttributeRTInfo.Create(ClassTypeInfo: TBoldClassTypeInfo; MoldA fBoldType := ClassTypeInfo.SystemTypeInfo.AttributeTypeInfoByExpressionName[Mapping.expressionName]; fStreamName := Mapping.ExpandedContentsName; if not assigned(fBoldType) then - ClassTypeInfo.SystemTypeInfo.InitializationError(sUnableToFindBoldTypeForAttribute, + ClassTypeInfo.SystemTypeInfo.InitializationError('Unable to find BoldType for %s.%s (ExpressionType: %s)', [MoldAttribute.MoldClass.ExpandedExpressionname, MoldAttribute.ExpandedExpressionName, Mapping.ExpressionName]); if assigned(fBoldtype) and not assigned((fBoldType as TBoldAttributeTypeInfo).AttributeClass) then - ClassTypeInfo.SystemTypeInfo.InitializationError(sAttributeHasNoDelphiType, + ClassTypeInfo.SystemTypeInfo.InitializationError('Attribute %s.%s: %s has no registered DelphiType', [MoldAttribute.MoldClass.ExpandedExpressionname, MoldAttribute.ExpandedExpressionName, MoldAttribute.BoldType]); @@ -1507,11 +1886,21 @@ constructor TBoldAttributeRTInfo.Create(ClassTypeInfo: TBoldClassTypeInfo; MoldA end; +function TBoldAttributeRTInfo.GetStoreInUndo: boolean; +begin + result := not IsDerived; +end; + function TBoldAttributeRTInfo.GetStringRepresentation(Representation: TBoldRepresentation): string; begin Result := ClassTypeInfo.AsString + '.' + ExpressionName; end; +function TBoldAttributeRTInfo.GetIsRole: Boolean; +begin + result := false; +end; + function TBoldAttributeRTInfo.GetMemberClass: TClass; begin Assert(BoldType is TBoldAttributeTypeInfo); @@ -1532,33 +1921,45 @@ constructor TBoldAttributeTypeInfo.Create(const ModelName, ExpressionName: strin fSuperAttributeTypeInfo := SuperType; end; +function TBoldAttributeTypeInfo.ElementClass: TBoldElementClass; +begin + result := TBoldMemberClass(AttributeClass); +end; + +function TBoldAttributeTypeInfo.CreateElement: TBoldElement; +begin + result := TBoldMemberClass(AttributeClass).CreateWithTypeInfo(self); +end; + function TBoldAttributeTypeInfo.ConformsTo(CompareElement: TBoldElementTypeInfo): Boolean; begin - Result := False; - if CompareElement is TBoldAttributeTypeInfo then - Result := assigned(AttributeClass) and - AttributeClass.InheritsFrom(TBoldAttributeTypeInfo(CompareElement).AttributeClass) - else if CompareElement is TBoldListTypeInfo then - Result := not assigned(TBoldListTypeInfo(CompareElement).ListElementTypeInfo) or - ConformsTo(TBoldListTypeInfo(CompareElement).ListElementTypeInfo); - // integer conforms to float and currency - if not result and SameText(ExpressionName, 'integer') and // do not localize - (SameText(compareElement.ExpressionName, 'float') or // do not localize - SameText(compareElement.ExpressionName, 'currency')) then // do not localize - result := true + Result := CompareElement = self; + if not Result then + begin + if CompareElement is TBoldAttributeTypeInfo then + Result := assigned(AttributeClass) and AttributeClass.InheritsFrom(TBoldAttributeTypeInfo(CompareElement).AttributeClass) + else if CompareElement is TBoldListTypeInfo then + Result := not assigned(TBoldListTypeInfo(CompareElement).ListElementTypeInfo) or + ConformsTo(TBoldListTypeInfo(CompareElement).ListElementTypeInfo); + if not result and ((SameText(ExpressionName, 'integer') and + (SameText(compareElement.ExpressionName, 'float') or + SameText(compareElement.ExpressionName, 'currency'))) +{$IFDEF DateTimeConformsToDate} + or + (SameText(ExpressionName, 'date') and + SameText(compareElement.ExpressionName, 'datetime')) + or + (SameText(ExpressionName, 'datetime') and + SameText(compareElement.ExpressionName, 'date')) +{$ENDIF} + ) then + result := true + end; end; function TBoldAttributeTypeInfo.BoldIsA(aType: TBoldElementTypeInfo): Boolean; begin - Result := False; - if aType is TBoldAttributeTypeInfo then - begin - if aType = self then - Result := True - else if assigned(SuperAttributeTypeInfo) then - Result := SuperAttributeTypeInfo.BoldIsA(aType); - end else - Result := False; + result := (aType = Self ) or (aType is TBoldAttributeTypeInfo) and Assigned(SuperAttributeTypeInfo) and SuperAttributeTypeInfo.BoldIsA(aType); end; function TBoldRoleRTInfo.GetIndexOfLinkObjectRole: Integer; @@ -1577,16 +1978,34 @@ function TBoldRoleRTInfo.GetIndexOfMainRole: Integer; result := -1; end; +{$IFDEF BOLD_LITE} +class function TBoldClassTypeInfo.NewInstance: TObject; +begin + if G_TheSystemType.TopSortedClasses.Count >= LITE_VERSION_CLASS_LIMIT then + raise EBold.Create('Class limit exceeded'); + + result := InitInstance(addr(G_TheSystemType.fClassTypeInfoMem[G_TheSystemType.TopSortedClasses.Count * + CLASS_TYPE_INFO_MEM_SIZE])); +end; + +procedure TBoldClassTypeInfo.FreeInstance; +begin + CleanUpInstance; +end; +{$ENDIF} + procedure TBoldSystemTypeInfo.ReleaseEvaluator; begin FreeAndNil(fEvaluator); end; -destructor TBoldClassTypeInfo.Destroy; +destructor TBoldClassTypeInfo.destroy; begin assert(not assigned(SystemTypeInfo.TopSortedClasses)); FreeAndNil(fAllMembers); + FreeAndNil(FAllRoles); FreeAndNil(fMethods); + FreeAndNil(fSubClasssesBoldClassTypeInfoList); inherited; end; @@ -1626,10 +2045,10 @@ procedure TBoldClassTypeInfo.InitializeMultiplicityConstraints; Constr: TBoldConstraintRTinfo; begin Constr := TBoldConstraintRTInfo.Create(nil, - Role.ModelName + ' multiplicity constraint', '', '', // do not localize + Role.ModelName + ' multiplicity constraint', '', '', SystemTypeInfo, - format('%s->size %s %d', [role.ExpressionName, ExprFragment, limit]), // do not localize - format(sMultiplicityConstraintMessage,[role.ModelName, moreless, limit, role.ClassTypeInfoOfOtherEnd.ModelName])); + format('%s->size %s %d', [role.ExpressionName, ExprFragment, limit]), + format('Role %s must have %s %d %s',[role.ModelName, moreless, limit, role.ClassTypeInfoOfOtherEnd.ModelName])); AddConstraint(Constr); end; @@ -1645,9 +2064,9 @@ procedure TBoldClassTypeInfo.InitializeMultiplicityConstraints; lower := GetLowerLimitForMultiplicity(RoleRT.Multiplicity); if (upper > 1) and (upper < MaxInt) then - AddMultiplicityConstraint(RoleRT, '<=', sAtMost, upper); + AddMultiplicityConstraint(RoleRT, '<=', 'at most', upper); if (lower > 0) then - AddMultiplicityConstraint(RoleRT, '>=', sAtLeast, lower); + AddMultiplicityConstraint(RoleRT, '>=', 'at least', lower); end; end; end; @@ -1656,11 +2075,13 @@ procedure TBoldClassTypeInfo.InitializeMultiplicityConstraints; procedure TBoldClassTypeInfo.Initialize(MoldClass: TMoldClass; TypeNameDictionary: TBoldTypeNameDictionary; BoldObjectClasses: TBoldGeneratedClassList; BoldObjectListClasses: TBoldGeneratedClassList; SkipMembers: Boolean); var ListClass: TClass; - ListTypeInfo: TBoldListTypeInfo; ListClassDescriptor: TBoldGeneratedClassDescriptor; I: Integer; tempClass: TMoldClass; role: TMoldRole; + AttributeCount: integer; + RoleCount: integer; + MethodCount: integer; begin FTopSortedIndex := SystemTypeInfo.TopSortedClasses.Count; @@ -1677,6 +2098,7 @@ procedure TBoldClassTypeInfo.Initialize(MoldClass: TMoldClass; TypeNameDictionar begin fSuperClassTypeInfo := SystemTypeInfo.ClassTypeInfoByExpressionName[moldClass.SuperClass.ExpandedExpressionName]; fSuperClassTypeInfo.SetElementFlag(befHasSubclasses, True); + fSuperClassTypeInfo.SubClasssesBoldClassTypeInfoList.Add(Self); end; SetObjectClass(BoldObjectClasses); @@ -1691,14 +2113,26 @@ procedure TBoldClassTypeInfo.Initialize(MoldClass: TMoldClass; TypeNameDictionar else ListClass := TBoldObjectList; - ListTypeInfo := TBoldListTypeInfo.Create(Self, SystemTypeInfo, ListClass); + fListTypeInfo := TBoldListTypeInfo.Create(Self, SystemTypeInfo, ListClass); SystemTypeInfo.ListTypes.Add(ListTypeInfo); FFirstOwnMemberIndex := MoldClass.FirstOwnBoldMemberIndex; - if SkipMembers then // this is used if the MoldModel contains errors, and we still need to create a root-class, we want to make it as empty as possible to avoid problems. + if SkipMembers then exit; + RoleCount := 0; + AttributeCount := 0; + for i := 0 to MoldClass.AllBoldMembers.Count - 1 do + begin + if MoldClass.AllBoldMembers[i] is TMoldAttribute then + Inc(AttributeCount) + else + Inc(RoleCount); + end; + fAllRoles.Capacity := RoleCount; + FAllMembers.Capacity := MoldClass.AllBoldMembers.Count; + for i := 0 to MoldClass.AllBoldMembers.Count - 1 do begin if MoldClass.AllBoldMembers[i] is TMoldAttribute then @@ -1717,10 +2151,19 @@ procedure TBoldClassTypeInfo.Initialize(MoldClass: TMoldClass; TypeNameDictionar end; end; fAllMembersCount := FAllMembers.Count; + fAllRolesCount := FAllRoles.Count; fDefaultStringRepresentation := MoldClass.EffectiveDefaultStringRepresentation; - // Install methods backwards to get them in the same index in each class + + MethodCount := 0; + tempClass := moldClass; + repeat + MethodCount := MethodCount + tempClass.Methods.Count; + tempClass := tempClass.SuperClass; + until tempClass = nil; + if MethodCount > 0 then + FMethods.Capacity := MethodCount; for I := 0 to moldClass.Methods.Count - 1 do TBoldMethodRTInfo.Create(self, moldClass.Methods[I], - 1, TypeNameDictionary); @@ -1753,19 +2196,32 @@ function TBoldClassTypeInfo.GetBoldType: TBoldElementTypeInfo; result := SystemTypeInfo.TypeTypeInfo; end; +function TBoldClassTypeInfo.GetDisplayName: String; +begin + result := DelphiName; +end; + +function TBoldClassTypeInfo.GetListTypeInfo: TBoldListTypeInfo; +begin + result := fListTypeInfo; +end; + function TBoldMemberRTInfo.GetCanHaveOldValue: Boolean; begin result := Persistent; end; -function TBoldMemberRTInfo.GetEncouragesOptimisticLockingOnDeletedOnly: Boolean; +function TBoldMemberRTInfo.GetDisplayName: String; begin - result := false; + if Assigned(ClassTypeInfo) then + result := ClassTypeInfo.Displayname + '.' + ExpressionName + else + result := inherited GetDisplayName; end; -function TBoldMemberRTInfo.GetIsAttribute: Boolean; +function TBoldMemberRTInfo.GetEncouragesOptimisticLockingOnDeletedOnly: Boolean; begin - result := not IsSingleRole and not IsMultiRole; + result := false; end; function TBoldMemberRTInfo.GetIsRole: Boolean; @@ -1778,19 +2234,16 @@ procedure TBoldMemberRTInfo.SetBoldType(BoldType: TBoldElementTypeInfo); fBoldType := BoldType; end; -function TBoldListTypeInfo.GetBoldType: TBoldElementTypeInfo; -begin - result := SystemTypeInfo.BoldType; -end; - function TBoldAttributeTypeInfo.GetBoldType: TBoldElementTypeInfo; begin result := SystemTypeInfo.BoldType; end; -function TBoldClassTypeInfo.GetListTypeInfo: TBoldListTypeInfo; +function TBoldAttributeTypeInfo.GetListTypeInfo: TBoldListTypeInfo; begin - result := SystemTypeInfo.ListTypeInfoByElement[self]; + if not Assigned(fListTypeInfo) then + fListTypeInfo := TBoldSystemTypeInfo(SystemTypeInfo).ListTypes.ItemByElement[self]; + result := fListTypeInfo; end; procedure TBoldSystemTypeInfo.InstallAttributeType( @@ -1813,7 +2266,7 @@ procedure TBoldSystemTypeInfo.InstallAttributeType( begin if assigned(TempAttributeType.AttributeClass) and (AnsiCompareText(TempAttributeType.AttributeClass.ClassName, Mapping.ExpandedDelphiName) <> 0) then - InitializationError(sErrorInstallingAttribute, [TypeNameDictionary.Mapping[pos].ExpressionName, TempAttributeType.AttributeClass.ClassName]); + InitializationError('Error installing %s, already mapped to %s', [TypeNameDictionary.Mapping[pos].ExpressionName, TempAttributeType.AttributeClass.ClassName]); exit; end; @@ -1836,7 +2289,7 @@ procedure TBoldSystemTypeInfo.InstallAttributeType( begin SuperDescriptor := BoldMemberTypes.DescriptorByDelphiName[SuperClassName]; if not assigned(SuperDescriptor) then - InitializationError(sErrorInstallingAttribute_MissingSuperType, [TypeNameDictionary.Mapping[pos].ExpressionName, SuperClassName]) + InitializationError('Error installing %s, Super class (%s) not registered', [TypeNameDictionary.Mapping[pos].ExpressionName, SuperClassName]) else begin SuperMapping := TypeNameDictionary.AddMapping; @@ -1953,6 +2406,11 @@ function TBoldElementTypeInfoWithConstraint.GetConstraints(const Name: String): result := nil; end; +function TBoldElementTypeInfoWithConstraint.GetListTypeInfo: TBoldListTypeInfo; +begin + Result := TBoldSystemTypeInfo(SystemTypeInfo).ListTypes.ItemByElement[self]; +end; + function TBoldElementTypeInfoWithConstraint.GetTaggedValueByIndex(Index: integer): string; begin if assigned(fTaggedValues) then @@ -2018,7 +2476,7 @@ destructor TBoldMetaElementWithConstraint.Destroy; begin FreeAndNil(fTaggedValues); FreeAndNil(fConstraints); - inherited; + inherited; end; function TBoldMetaElementWithConstraint.GetConstraintByIndex(Index: integer): TBoldConstraintRTInfo; @@ -2071,6 +2529,11 @@ function TBoldMetaElementWithConstraint.GetTaggedValues(const Tag: string): stri { TBoldConstraintRTInfoList } +function TBoldConstraintRTInfoList.GetEnumerator: TBoldConstraintRTInfoListTraverser; +begin + result := CreateTraverser as TBoldConstraintRTInfoListTraverser; +end; + function TBoldConstraintRTInfoList.GetItem(index: Integer): TBoldConstraintRTInfo; begin result := TBoldConstraintRTInfo(inherited Items[index]); @@ -2081,6 +2544,11 @@ function TBoldConstraintRTInfoList.GetItemByModelName(const ModelName: string): result := TBoldConstraintRTInfo(inherited ItemsByModelName[ModelName]); end; +function TBoldConstraintRTInfoList.TraverserClass: TBoldIndexableListTraverserClass; +begin + result := TBoldConstraintRTInfoListTraverser; +end; + { TBoldConstraintRTInfo } constructor TBoldConstraintRTInfo.create(MoldElement: TMoldElement; const ModelName, ExpressionName, DelphiName: String; SystemTypeInfo: TBoldSystemTypeInfo; const Expression, Description: String); @@ -2088,6 +2556,8 @@ constructor TBoldConstraintRTInfo.create(MoldElement: TMoldElement; const ModelN inherited create(MoldElement, ModelName, ExpressionName, DelphiName, SystemTypeInfo); fExpression := Expression; fDescription := Description; + if Description = '' then + fDescription := ModelName; fBoldType := SystemTYpeInfo.TypeTypeInfo; end; @@ -2096,7 +2566,7 @@ function TBoldConstraintRTInfo.GetBoldType: TBoldElementTypeInfo; result := fBoldType; end; -destructor TBoldRoleRTInfo.Destroy; +destructor TBoldRoleRTInfo.destroy; begin FreeAndNil(FQualifiers); inherited; @@ -2105,7 +2575,7 @@ destructor TBoldRoleRTInfo.Destroy; function TBoldMethodRTInfo.GetBoldType: TBoldElementTypeInfo; begin result := ClassTypeInfo.SystemTypeInfo.ElementTypeInfoByExpressionName[ReturnType]; -end; +end; function TBoldClassTypeInfo.GetQualifiedName: string; begin @@ -2115,5 +2585,89 @@ function TBoldClassTypeInfo.GetQualifiedName: string; result := ModelName ; end; -end. +{---TBoldRoleRTInfoList---} +function TBoldRoleRTInfoList.GetEnumerator: TBoldRoleRTInfoListTraverser; +begin + result := CreateTraverser as TBoldRoleRTInfoListTraverser; +end; + +function TBoldRoleRTInfoList.GetItem(index: Integer): TBoldRoleRTInfo; +begin + Result := TBoldRoleRTInfo(inherited Items[index]); +end; + +function TBoldRoleRTInfoList.GetItemByModelName(const ModelName: string): TBoldRoleRTInfo; +begin + Result := TBoldRoleRTInfo(inherited ItemsByModelName[ModelName]); +end; + +function TBoldRoleRTInfoList.TraverserClass: TBoldIndexableListTraverserClass; +begin + result := TBoldRoleRTInfoListTraverser; +end; + +function TBoldRoleRTInfoList.GetItemByExpressionName(const ExpressionName: string): TBoldRoleRTInfo; +begin + Result := TBoldRoleRTInfo(inherited ItemsByExpressionName[ExpressionName]); +end; + +{ TListClassIndex } + +function TListClassIndex.ItemAsKeyClass(Item: TObject): TClass; +begin + Result := TBoldListTypeInfo(Item).ListClass; +end; + +{ TBoldMemberRTInfoListTraverser } + +function TBoldMemberRTInfoListTraverser.GetCurrent: TBoldMemberRTInfo; +begin + result := inherited GetItem as TBoldMemberRTInfo; +end; + +{ TBoldClassTypeInfoListTraverser } + +function TBoldClassTypeInfoListTraverser.GetCurrent: TBoldClassTypeInfo; +begin + result := inherited GetItem as TBoldClassTypeInfo; +end; + +{ TBoldAttributeTypeInfoListTraverser } + +function TBoldAttributeTypeInfoListTraverser.GetCurrent: TBoldAttributeTypeInfo; +begin + result := inherited GetItem as TBoldAttributeTypeInfo; +end; + +{ TBoldRoleRTInfoListTraverser } + +function TBoldRoleRTInfoListTraverser.GetCurrent: TBoldRoleRTInfo; +begin + result := inherited GetItem as TBoldRoleRTInfo; +end; + +{ TBoldConstraintRTInfoListTraverser } + +function TBoldConstraintRTInfoListTraverser.GetCurrent: TBoldConstraintRTInfo; +begin + result := inherited GetItem as TBoldConstraintRTInfo; +end; + +{ TBoldMethodRTInfoListTraverser } + +function TBoldMethodRTInfoListTraverser.GetCurrent: TBoldMethodRTInfo; +begin + result := inherited GetItem as TBoldMethodRTInfo; +end; + +initialization +{$IFDEF BOLD_LITE} + if CLASS_TYPE_INFO_MEM_SIZE <> TBoldClassTypeInfo.InstanceSize then + Raise EBold.Create('CLASS_TYPE_INFO_MEM_SIZE <> TBoldClassTypeInfo.InstanceSize'); +{$ENDIF} + TBoldClassTypeInfoList.IX_ObjectClass := -1; + TBoldListTypeInfoList.IX_Element := -1; + TBoldListTypeInfoList.IX_ListClass := -1; + +end. diff --git a/Source/ObjectSpace/Undo/BoldUndoHandler.pas b/Source/ObjectSpace/Undo/BoldUndoHandler.pas index 35e88e8..9cca03b 100644 --- a/Source/ObjectSpace/Undo/BoldUndoHandler.pas +++ b/Source/ObjectSpace/Undo/BoldUndoHandler.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldUndoHandler; interface @@ -13,6 +16,7 @@ interface BoldSystemRT, Classes; + type {forward declarations} TBoldUndoHandler = class; @@ -24,26 +28,27 @@ TBoldUndoBlock = class(TBoldNonRefCountedObject, IBoldUndoBlock) FName: string; FValueSpace: TBoldFreeStandingValueSpace; FContainsChanges: Boolean; -// procedure GetLinksToObject(const System: TBoldSystem; const ObjectId: TBoldObjectId; const OwnIndexInLinkClass: integer; -// const SingleLinkClassTypeInfo: TBoldClassTypeInfo; SingleLinkIds: TBoldObjectIdList); -// procedure AllIdsInClass(const System: TBoldSystem; const ClassTypeInfo: TBoldClassTypeInfo; IdList: TBoldObjectIdList); - function GetFSValueSpace: TBoldFreeStandingValueSpace; - procedure SetFSValueSpace(const Value: TBoldFreeStandingValueSpace); - function GetName: string; - function GetValueSpace: IBoldValueSpace; - function GetContainsChanges: Boolean; + procedure GetLinksToObject(const System: TBoldSystem; const ObjectId: TBoldObjectId; const OwnIndexInLinkClass: integer; + const SingleLinkClassTypeInfo: TBoldClassTypeInfo; SingleLinkIds: TBoldObjectIdList); + procedure AllIdsInClass(const System: TBoldSystem; const ClassTypeInfo: TBoldClassTypeInfo; IdList: TBoldObjectIdList); + function GetFSValueSpace: TBoldFreeStandingValueSpace; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure SetFSValueSpace(const Value: TBoldFreeStandingValueSpace); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetName: string; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetValueSpace: IBoldValueSpace; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetContainsChanges: Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} protected function HasObjectContentsForAnyObjectInList(const ObjectList: TBoldObjectList): Boolean; - function HandleMember(ObjectContents: IBoldObjectContents; MemberIndex: integer; MemberValue: IBoldValue): Boolean; - procedure HandleObject(Obj: IBoldObjectContents; RegardAsExisting: Boolean); + procedure HandleMember(const ObjectContents: IBoldObjectContents; MemberIndex: integer; const MemberValue: IBoldValue); + procedure HandleObject(const Obj: IBoldObjectContents; RegardAsExisting: Boolean); function IsDependantOn(Block: TBoldUndoBlock): Boolean; public constructor CreateNamedBlock(const BlockName: string; const FSVAlueSpace: TBoldFreeStandingValueSpace = nil); destructor Destroy; override; - procedure ApplytranslationList(IdTranslationList: TBoldIdTranslationList); + procedure ApplytranslationList(IdTranslationList: TBoldIdTranslationList); {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure Merge(Block: TBoldUndoBlock; const Overwrite: Boolean); function ValueExists(const ObjectID: TBoldObjectId; const MemberIndex: integer): Boolean; overload; function ValueExists(const ObjectID: TBoldObjectID; const MemberIndex: integer; out Value: IBoldValue): Boolean; overload; + procedure AddObjectsToList(const System: TBoldSystem; const AList: TBoldList); property BlockName: string read FName; property FSValueSpace: TBoldFreeStandingValueSpace read GetFSValueSpace write setFSVAlueSpace; property ValueSpace: IBoldValueSpace read GetValueSpace; @@ -53,41 +58,45 @@ TBoldUndoBlock = class(TBoldNonRefCountedObject, IBoldUndoBlock) TBoldUndoBlockList = class(TBoldNonRefCountedObject, IBoldUndoList) private FList: TStringList; - function GetBlocksByIndex(Index: integer): TBoldUndoBlock; - function GetBlocksByName(BlockName: string): TBoldUndoBlock; + function GetBlockByIndex(Index: integer): TBoldUndoBlock; + function GetBlockByName(const BlockName: string): TBoldUndoBlock; function GetCount: integer; function GetCurrentBlock: TBoldUndoBlock; - function GetAssertedBlocksByName(BlockName: string): TBoldUndoBlock; - function GetAssertedBlocksByIndex(Index: integer): TBoldUndoBlock; - function GetItems(Index: integer): IBoldUndoBlock; - function GetItemsByName(Name: string): IBoldUndoBlock; - function GetTopBlock: IBoldUndoBlock; + function GetAssertedBlockByName(const BlockName: string): TBoldUndoBlock; + function GetAssertedBlockByIndex(Index: integer): TBoldUndoBlock; + function GetItem(Index: integer): IBoldUndoBlock; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetItemByName(const Name: string): IBoldUndoBlock; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetTopBlock: IBoldUndoBlock; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetContainsChanges: Boolean; protected procedure Clear; - function AddBlock(BlockName: string; const FSVAlueSpace: TBoldFreeStandingValueSpace = nil): TBoldUndoBlock; - property AssertedBlocksByName[BlockName: string]: TBoldUndoBlock read GetAssertedBlocksByName; - property AssertedBlocksByIndex[Index: integer]: TBoldUndoBlock read GetAssertedBlocksByIndex; + function AddBlock(const BlockName: string; const FSVAlueSpace: TBoldFreeStandingValueSpace = nil): TBoldUndoBlock; + property AssertedBlockByName[const BlockName: string]: TBoldUndoBlock read GetAssertedBlockByName; + property AssertedBlockByIndex[Index: integer]: TBoldUndoBlock read GetAssertedBlockByIndex; function AssertedIndexOf(const BlockName: string): integer; - procedure InternalRemoveBlock(BlockName: string); // do not make const + procedure InternalRemoveBlock(const BlockName: string); overload; + procedure InternalRemoveBlock(Block: TBoldUndoBlock); overload; public procedure ApplytranslationList(IdTranslationList: TBoldIdTranslationList); constructor Create; destructor Destroy; override; procedure MoveBlock(CurIndex, NewIndex: integer); - function IndexOf(BlockName: string): integer; - function RemoveBlock(BlockName: string): Boolean; // do not make const - procedure RenameBlock(OldName, NewName: string); // do not make const - procedure MoveToTop(BlockName: string); - procedure MergeBlocks(DestinationBlockName, SourceBlockName: string); - property BlocksbyIndex[Index: integer]: TBoldUndoBlock read GetBlocksByIndex; - property BlocksByName[BlockName: string]: TBoldUndoBlock read GetBlocksByName; + function IndexOf(const BlockName: string): integer; overload; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function IndexOf(Block: TBoldUndoBlock): integer; overload; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function RemoveBlock(const BlockName: string): Boolean; + procedure RenameBlock(const OldName, NewName: string); + procedure MoveToTop(const BlockName: string); + procedure MergeBlocks(const DestinationBlockName, SourceBlockName: string); + property BlockByIndex[Index: integer]: TBoldUndoBlock read GetBlockByIndex; default; + property BlockByName[const BlockName: string]: TBoldUndoBlock read GetBlockByName; function CanMoveBlock(CurIndex, NewIndex: integer): Boolean; function CanMergeBlock(CurIndex, NewIndex: integer): Boolean; - function CanMoveToTop(CurIndex: integer): Boolean; + function CanMoveToTop(CurIndex: integer): Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure GetDependantBlocks(const BlockName: string; DependantBlocks: TList); procedure MergeAll; property Count: integer read GetCount; property CurrentBlock: TBoldUndoBlock read GetCurrentBlock; + property ContainsChanges: Boolean read GetContainsChanges; end; TBoldUndoHandler = class(TBoldAbstractUndoHandler, IBoldUndoHandler) @@ -96,46 +105,302 @@ TBoldUndoHandler = class(TBoldAbstractUndoHandler, IBoldUndoHandler) FRedoBlocks: TBoldUndoBlockList; fUndoState: TBoldUndoState; fEnabled: Boolean; +{ function GetFetchedValueOfIndirectMultiLink(const Member: TBoldMember; const OwningObjectId: TBoldObjectId; + const RoleRTInfo: TBoldRoleRTInfo): TBoldFreeStandingValue; + function GetFetchedValueOfDirectMultiLink (const Member: TBoldMember; const OwningObjectId: TBoldObjectId; + const RoleRTInfo: TBoldRoleRTInfo): TBoldFreeStandingValue; + } procedure DoUndo(UnDoValueSpace: TBoldFreeStandingValueSpace; RedoValueSpace: TBoldFreeStandingValueSpace); procedure DoUndoInTransaction(BlockName: string; FromList, ToList: TBoldUndoBlockList); // Don't make blockname const! - function GetUndoList: IBoldUndoList; - function GetRedoList: IBoldUndoList; - function CanUndoBlock(BlockName: string): Boolean; - function CanRedoBlock(BlockName: string):Boolean; - function GetEnabled: Boolean; - procedure SetEnabled(value: Boolean); + function GetUndoList: IBoldUndoList; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetRedoList: IBoldUndoList; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function CanUndoBlock(const BlockName: string): Boolean; + function CanRedoBlock(const BlockName: string):Boolean; + function GetEnabled: Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure SetEnabled(value: Boolean); public constructor Create(System: TBoldSystem); override; destructor Destroy; override; - function GetUniqueBlockName(SuggestedName: string): string; - procedure SetNamedCheckPoint(CheckPointName: string); + function GetUniqueBlockName(const SuggestedName: string): string; + procedure SetNamedCheckPoint(const CheckPointName: string); procedure SetCheckPoint; - procedure HandleMember(ObjectContents: IBoldObjectContents; MemberIndex: integer; MemberValue: IBoldValue); override; - procedure HandleObject(Obj: IBoldObjectContents; RegardAsExisting: Boolean); override; - procedure UndoBlock(BlockName: string); - procedure RedoBlock(BlockName: string); + procedure HandleMember(const ObjectContents: IBoldObjectContents; MemberIndex: integer; const MemberValue: IBoldValue); overload; override; + procedure HandleObject(const Obj: IBoldObjectContents; RegardAsExisting: Boolean); override; + procedure UndoBlock(const BlockName: string); + procedure RedoBlock(const BlockName: string); procedure UnDoLatest; - procedure Redolatest; + procedure RedoLatest; procedure ApplytranslationList(IdTranslationList: TBoldIdTranslationList); override; procedure PrepareUpdate(const ObjectList: TBoldObjectList); override; - procedure ClearAllUndoBlocks; + procedure ClearAllUndoBlocks; {$IFDEF BOLD_INLINE} inline; {$ENDIF} property UndoBlocks: TBoldUndoBlockList read fUndoBlocks; property RedoBlocks: TBoldUndoBlockList read fRedoBlocks; property UndoState: TBoldUndoState read fUndoState write fUndoState; + property Enabled: Boolean read GetEnabled write SetEnabled; end; implementation uses SysUtils, - BoldUtils, BoldDefs, BoldGuard, - BoldDomainElement, - BoldCoreConsts, - BoldSubscription; + BoldDomainElement; + +const + cUnNamedBlockName = 'UnNamed'; + +{ TBoldUndoBlock } + +constructor TBoldUndoBlock.CreateNamedBlock(const BlockName: string; const FSVAlueSpace: TBoldFreeStandingValueSpace); +begin + inherited Create; + FContainsChanges := false; + FName := BlockName; + FValueSpace := FSVAlueSpace; +end; + +function TBoldUndoBlock.GetFSValueSpace: TBoldFreeStandingValueSpace; +begin + if not Assigned(FValueSpace) then + FValueSpace := TBoldFreeStandingValueSpace.Create; + Result := FValueSpace; +end; + +function TBoldUndoBlock.IsDependantOn( + Block: TBoldUndoBlock): Boolean; +var + ObjectContents: TBoldFreeStandingObjectContents; + i, j: integer; + aValue: IBoldValue; + ObjectIds: TBoldObjectIdList; + G: IBoldGuard; +begin + G := TBoldGuard.Create(ObjectIds); + ObjectIds := TBoldObjectIdList.Create; + Result := false; + FSValueSpace.AllObjectIds(ObjectIds, True); + for i:= 0 to ObjectIds.Count - 1 do + begin + ObjectContents := FSValueSpace.GetFSObjectContentsByObjectId(ObjectIds[i]); + for j := 0 to ObjectContents.MemberCount - 1 do + begin + Result := Assigned(ObjectContents.ValueByIndex[j]) and Block.ValueExists(ObjectIds[i], j, aValue); + if Result then + Break; + end; + if Result then + Break; + end; +end; + +procedure TBoldUndoBlock.Merge(Block: TBoldUndoBlock; const Overwrite: Boolean); +var + OwnContents, ObjectContents: TBoldFreeStandingObjectContents; + ObjectId: TBoldObjectId; + i, j: integer; + ObjectIds: TBoldObjectIdList; + G: IBoldGuard; +begin + G := TBoldGuard.Create(ObjectIds); + ObjectIds := TBoldObjectIdList.Create; + Block.FSValueSpace.AllObjectIds(ObjectIds, True); + for i:= 0 to ObjectIds.Count - 1 do + begin + ObjectId := ObjectIds[i]; + ObjectContents := Block.FSValueSpace.GetFSObjectContentsByObjectId(ObjectId); + if not FSValueSpace.GetHasContentsForId(ObjectId) then begin + FSValueSpace.EnsureObjectContents(ObjectId); + OwnContents := FSValueSpace.GetFSObjectContentsByObjectId(ObjectId); + // When FSObjectContent is recreated for this block, + // then Existence/PersistenceState must be adopted from source block. + OwnContents.BoldExistenceState := ObjectContents.BoldExistenceState; + OwnContents.BoldPersistenceState := ObjectContents.BoldPersistenceState; + end else begin + OwnContents := FSValueSpace.GetFSObjectContentsByObjectId(ObjectId); + end; + for j:= 0 to ObjectContents.MemberCount - 1 do + if Assigned(ObjectContents.valueByIndex[j]) then + begin + if (OwnContents.MemberCount > j) and Assigned(OwnContents.ValueByIndex[j]) then + begin + if overwrite then + OwnContents.ValueByIndex[j].AssignContent(ObjectContents.ValueByIndex[j]); + end + else + begin + OwnContents.EnsureMemberAndGetValueByIndex(J, ObjectContents.ValueByIndex[j].ContentName).AssignContent(ObjectContents.ValueByIndex[j]); + end; + end; + end; +end; +function TBoldUndoBlock.ValueExists(const ObjectID: TBoldObjectID; + const MemberIndex: integer; out Value: IBoldValue): Boolean; +var + ObjectContents: TBoldFreeStandingObjectContents; +begin + Value := nil; + ObjectContents := FSValueSpace.GetFSObjectContentsByObjectId(ObjectID); + if Assigned(ObjectContents) and (MemberIndex < ObjectContents.memberCount) then + Value := ObjectContents.ValueByIndex[MemberIndex]; + Result := Assigned(Value); +end; + +function TBoldUndoBlock.ValueExists(const ObjectID: TBoldObjectId; + const MemberIndex: integer): Boolean; +var + Value: IBoldValue; +begin + result := ValueExists(ObjectId, MemberIndex, Value); +end; + +procedure TBoldUndoBlock.HandleMember(const ObjectContents: IBoldObjectContents; MemberIndex: integer; const MemberValue: IBoldValue); +var + ObjectId: TBoldObjectId; + FSObjectContents: TBoldFreeStandingObjectContents; +begin + ObjectId := ObjectContents.ObjectId; + FSObjectContents := FSValueSpace.GetFSObjectContentsByObjectId(ObjectId); + if not Assigned(FSObjectContents) or (MemberIndex >= FSObjectContents.memberCount) or not Assigned(FSObjectContents.ValueByIndex[MemberIndex]) then + begin + FContainsChanges := true; + if not Assigned(FSObjectContents) then + begin + FSObjectContents := FSValueSpace.GetEnsuredFSObjectContentsByObjectId(ObjectId); + FSObjectContents.ApplyObjectContents(ObjectContents, False, false); + end; + FSObjectContents.EnsureMemberAndGetValueByIndex(MemberIndex, MemberValue.ContentName).AssignContent(MemberValue); + end; +end; + +function TBoldUndoBlock.HasObjectContentsForAnyObjectInList( + const ObjectList: TBoldObjectList): Boolean; +var + i: integer; + ObjectId: TBoldObjectId; +begin + Result := false; + for i:= 0 to ObjectList.Count - 1 do + begin + ObjectId := ObjectList.BoldObjects[i].BoldObjectLocator.BoldObjectID; + Result := Assigned(FSValueSpace.GetFSObjectContentsByObjectId(ObjectId)); + if Result then + Break; + end; +end; + +procedure TBoldUndoBlock.GetLinksToObject(const System: TBoldSystem; const ObjectId: TBoldObjectId; const OwnIndexInLinkClass: integer; + const SingleLinkClassTypeInfo: TBoldClassTypeInfo; SingleLinkIds: TBoldObjectIdList); +var + ObjectIds: TBoldObjectIdList; + i: integer; + LinkValue: IBoldValue; +begin + ObjectIds := TBoldObjectIdList.Create; + try + AllIdsInClass(System, SingleLinkClassTypeInfo, ObjectIds); + for i:= 0 to ObjectIds.Count - 1 do + if ValueExists(ObjectIds[i], OwnIndexInLinkClass, LinkValue) and + Assigned((LinkValue as IBoldObjectIdRef).Id) and + ((LinkValue as IBoldObjectIdRef).Id.IsEqual[ObjectId]) then + SingleLinkIds.Add(ObjectIds[i].Clone); + except + FreeAndNil(ObjectIds); + end; +end; + +procedure TBoldUndoBlock.AddObjectsToList(const System: TBoldSystem; + const AList: TBoldList); +var + i: integer; + ObjectIds: TBoldObjectIdList; + G: IBoldGuard; +begin + G := TBoldGuard.Create(ObjectIds); + ObjectIds := TBoldObjectIdList.Create; + FSValueSpace.AllObjectIds(ObjectIds, false); + for i:= 0 to ObjectIds.Count - 1 do + AList.Add(System.Locators.ObjectByID[ObjectIds[i]]); +end; + +procedure TBoldUndoBlock.AllIdsInClass( const System: TBoldSystem; + const ClassTypeInfo: TBoldClassTypeInfo; IdList: TBoldObjectIdList); +var + i: integer; + ObjectIds: TBoldObjectIdList; + G: IBoldGuard; +begin + G := TBoldGuard.Create(ObjectIds); + ObjectIds := TBoldObjectIdList.Create; + FSValueSpace.AllObjectIds(ObjectIds, True); + for i:= 0 to ObjectIds.Count - 1 do + begin + if (System.Locators.ObjectByID[ObjectIds[i]].BoldClassTypeInfo = ClassTypeInfo) then + IdList.Add(ObjectIds[i]); + end; +end; + +procedure TBoldUndoBlock.HandleObject(const Obj: IBoldObjectContents; RegardAsExisting: Boolean); +var + ObjectId: TBoldObjectId; + ObjectContents: TBoldFreeStandingObjectContents; +begin + Assert(assigned(obj)); + ObjectId := Obj.ObjectID; + ObjectContents := FSValueSpace.GetFSObjectContentsByObjectId(ObjectId); + if not Assigned(ObjectContents) then + begin + FContainsChanges := True; + FSValueSpace.EnsureObjectContents(ObjectId); + ObjectContents := FSValueSpace.GetFSObjectContentsByObjectId(ObjectId); + ObjectContents.ApplyObjectContents(Obj, False, false); + if RegardAsExisting then + begin + ObjectContents.BoldPersistenceState := bvpsCurrent; + ObjectContents.BoldExistenceState := besExisting; + end; + end; +end; + +destructor TBoldUndoBlock.Destroy; +begin + FreeAndNil(FValueSpace); + inherited; +end; + +procedure TBoldUndoBlock.SetFSValueSpace( + const Value: TBoldFreeStandingValueSpace); +begin + if (FValueSpace <> Value) then + begin + FreeAndNil(FValueSpace); + FValueSpace := Value; + fContainsChanges := TRUE; + end; +end; + +function TBoldUndoBlock.GetName: string; +begin + Result := fName; +end; + +function TBoldUndoBlock.GetValueSpace: IBoldValueSpace; +begin + result := FSValueSpace as IBoldValueSpace; +end; + +function TBoldUndoBlock.GetContainsChanges: Boolean; +begin + result := fContainsChanges; +end; + +procedure TBoldUndoBlock.ApplytranslationList( + IdTranslationList: TBoldIdTranslationList); +begin + ValueSpace.ApplytranslationList(IdTranslationList); +end; { TBoldUndoHandler } @@ -145,6 +410,7 @@ constructor TBoldUndoHandler.Create(System: TBoldSystem); FUndoBlocks := TBoldUndoBlockList.Create; FRedoBlocks := TBoldUndoBlockList.Create; fUndoState := busNormal; + Enabled := false; end; destructor TBoldUndoHandler.Destroy; @@ -154,80 +420,92 @@ destructor TBoldUndoHandler.Destroy; inherited; end; -(* -function TBoldUndoHandler.GetFetchedValue(Member: TBoldMember): IBoldValue; +procedure TBoldUndoHandler.HandleMember(const ObjectContents: IBoldObjectContents; MemberIndex: integer; const MemberValue: IBoldValue); +begin + if Enabled and (UndoState = busNormal) then + begin + RedoBlocks.Clear; + UndoBlocks.CurrentBlock.HandleMember(ObjectContents, MemberIndex, MemberValue); + end; +end; + +function TBoldUndoBlockList.GetContainsChanges: Boolean; var i: integer; - RoleRTInfo: TBoldRoleRTInfo; - HasLinkObject: Boolean; - ObjectID: TBoldObjectID; begin - //TODO: finish implementation - Result := nil; - if Member.BoldMemberRTInfo.IsDerived then - Exit; - if Member.BoldMemberRTInfo.IsMultiRole then //if multilink - begin - ObjectID := Member.OwningObject.BoldObjectLocator.BoldObjectID; - RoleRTInfo := TBoldRoleRTInfo(Member.BoldMemberRTInfo); - HasLinkObject := Assigned(RoleRTInfo.LinkClassTypeInfo); - if HasLinkObject then - Result := (GetFetchedValueOfIndirectMultiLink(Member, ObjectId, RoleRTInfo) as IBoldValue) - else - // no links - Result := GetFetchedValueOfDirectMultiLink(Member, ObjectId, RoleRtInfo); - end + result := true; + for I := Count - 1 downto 0 do + if BlockByIndex[i].ContainsChanges then + exit; + result := false; +end; + +function TBoldUndoBlockList.GetCount: integer; +begin + Result := fList.Count; +end; + +function TBoldUndoBlockList.GetBlockByIndex( + Index: integer): TBoldUndoBlock; +begin + if (Index >= 0) and (Index < FList.Count) then + Result := FList.Objects[Index] as TBoldUndoBlock else - for i:= 0 to UndoBlocks.Count - 1 do - if UndoBlocks.BlocksbyIndex[i].ValueExists(Member.OwningObject.BoldObjectLocator.BoldObjectID, - Member.BoldMemberRTInfo.index, Result) then - Break; + Result := nil; end; -*) -procedure TBoldUndoHandler.HandleMember(ObjectContents: IBoldObjectContents; MemberIndex: integer; MemberValue: IBoldValue); +function TBoldUndoBlockList.GetBlockByName(const BlockName: string): TBoldUndoBlock; +var + Idx: integer; begin - if fEnabled and (UndoState = busNormal) then - begin - RedoBlocks.Clear; - UndoBlocks.CurrentBlock.HandleMember(ObjectContents, MemberIndex, MemberValue); - end; + Idx := FList.IndexOf(blockName); + if Idx <> - 1 then + Result := FList.Objects[Idx] as TBoldUndoBlock + else + Result := nil; end; + procedure TBoldUndoHandler.PrepareUpdate(const ObjectList: TBoldObjectList); var aBlock: TBoldUndoBlock; i: integer; begin + if not Enabled then + exit; RedoBlocks.Clear; i := 0; while i < UnDoBlocks.Count do begin - aBlock := UndoBlocks.BlocksbyIndex[i]; //UndoBlocks.CurrentBlock; + aBlock := UndoBlocks.BlockByIndex[i]; if aBlock.HasObjectContentsForAnyObjectInList(ObjectList) then begin - UnDoBlocks.InternalRemoveBlock(aBlock.BlockName) + UnDoBlocks.InternalRemoveBlock(aBlock) end else inc(i); end; +{$IFDEF MergeEmptyBlocks} UndoBlocks.MergeAll; +{$ENDIF} end; -procedure TBoldUndoHandler.SetNamedCheckPoint(CheckPointName: string); +procedure TBoldUndoHandler.SetNamedCheckPoint(const CheckPointName: string); begin - if Assigned(UndoBlocks.GetBlocksByName(CheckPointName)) or Assigned(RedoBlocks.GetBlocksByName(CheckPointName)) then - raise EBold.CreateFmt(sBlockNameInUse, [Classname, CheckPointName]) + if Assigned(UndoBlocks.GetBlockByName(CheckPointName)) or Assigned(RedoBlocks.GetBlockByName(CheckPointName)) then + raise EBold.CreateFmt('%s.SetCheckPoint: An Undo/Redo block named %s is already defined', [Classname, CheckPointName]) +{$IFDEF MergeEmptyBlocks} else if not (UndoBlocks.CurrentBlock.ContainsChanges) then UndoBlocks.RenameBlock(UndoBlocks.CurrentBlock.BlockName, CheckPointName) +{$ENDIF} else UndoBlocks.AddBlock(CheckPointName); end; -procedure TBoldUndoHandler.UndoBlock(BlockName: string); +procedure TBoldUndoHandler.UndoBlock(const BlockName: string); begin if System.InTransaction then - raise EBold.CreateFmt(sCannotUndoInTransaction, [ClassName]); + raise EBold.CreateFmt('%s.UndoBlock: the Undo-mechanism can only be invoked outside a transaction', [ClassName]); UndoState := busUndoing; try DoUndoInTransaction(BlockName, UndoBlocks, RedoBlocks); @@ -236,95 +514,11 @@ procedure TBoldUndoHandler.UndoBlock(BlockName: string); end; end; -(* -function TBoldUndoHandler.GetFetchedValueOfDirectMultiLink( - const Member: TBoldMember; const OwningObjectId: TBoldObjectId; - const RoleRTInfo: TBoldRoleRTInfo): TBoldFreeStandingValue; -var - CurrentValue: IBoldObjectIdListRef; - FetchedValue: TBFSObjectIdListRef; - ObjectIds, IdList: TBoldObjectIdList; - i: integer; - aValue: IBoldValue; - G: IBoldGuard; -begin - G := TBoldGuard.Create(ObjectIds, IdList); - //TODO: implement FetchedValues for LinkObjects?? - FetchedValue := TBFSObjectIdListRef.Create; - CurrentValue := Member.AsIBoldValue[bdepContents] as IBoldObjectIdListRef; - if Assigned(CurrentValue) then - begin - FetchedValue.AssignContent(CurrentValue); - ObjectIds := TBoldObjectIdList.Create; - IdList := TBoldObjectIdList.Create; - // non modified links - for i:= 0 to CurrentValue.Count - 1 do - if not NonUndoableBlock.ValueExists(CurrentValue.IdList[i], RoleRTInfo.IndexOfOtherEnd, aValue) then - IdList.Add(CurrentValue.IdList[i].Clone); - // deleted links - NonUndoableBlock.AllIdsInClass(System, RoleRTInfo.ClassTypeInfoOfOtherEnd, ObjectIds); - for i:= 0 to ObjectIds.Count - 1 do - begin - if NonUndoableBlock.ValueExists(Objectids[i], RoleRTInfo.IndexOfOtherEnd, aValue) and - Assigned((aValue as IBoldObjectIdRef).Id) and (aValue as IBoldObjectIdRef).Id.IsEqual[OwningObjectId] then - IdList.Add(ObjectIds[i]); - end; - FetchedValue.SetFromIdList(IdList); - end; - Result := FetchedValue; -end; - -function TBoldUndoHandler.GetFetchedValueOfIndirectMultiLink( - const Member: TBoldMember; const OwningObjectId: TBoldObjectId; - const RoleRTInfo: TBoldRoleRTInfo): TBoldFreeStandingValue; -var - CurrentValue: IBoldObjectIdListRefPair; - FetchedValue: TBFSObjectIdListrefPair; - i: integer; - ObjectIds, IdList1, IdList2: TBoldObjectIdList; // Idlist1 is the list of ids of the linkobjects - LinkObjectId : TBoldObjectId; - LinkValue: IBoldValue; -begin - //TODO: implement - CurrentValue := Member.AsIBoldValue[bdepContents] as IBoldObjectIdListRefPair; - FetchedValue := TBFSObjectIdListRefPair.Create; - FetchedValue.AssignContent(CurrentValue); - ObjectIds := TBoldObjectIdList.Create; - IdList1 := TBoldObjectIdList.Create; - IdList2 := TBoldObjectIdList.Create; - try - //non modified links - for i:= 0 to CurrentValue.Count - 1 do - begin - LinkObjectId := CurrentValue.IdList1[i]; //id1 is link object - if not Assigned(NonUndoableBlock.FSValueSpace.GetFSObjectContentsByObjectId(LinkObjectId)) then // link not modified - begin - IdList1.Add(CurrentValue.IdList1[i].Clone); - IdList2.Add(CurrentValue.IdList2[i].Clone); - end; - end; - //deleted links - NonUndoableBlock.GetLinksToObject(System, OwningObjectId, RoleRTInfo.OwnIndexInLinkClass, RoleRtInfo.LinkClassTypeInfo, ObjectIds); - for i:= 0 to ObjectIds.Count - 1 do - begin - IdList1.Add(ObjectIds[i].Clone); - NonUndoableBlock.ValueExists(ObjectIds[i],RoleRtInfo.OtherIndexInLinkClass, LinkValue); - IdList2.Add((LinkValue as IBoldObjectIdRef).Id.Clone); - end; - finally - FetchedValue.SetFromIdLists(IdList1, IdList2); - Result := FetchedValue; - FreeAndNil(ObjectIds); - FreeAndNil(IdList1); - FreeAndNil(IdList2); - end; -end; -*) -procedure TBoldUndoHandler.RedoBlock(BlockName: string); +procedure TBoldUndoHandler.RedoBlock(const BlockName: string); begin if System.InTransaction then - raise EBold.CreateFmt(sCannotUndoInTransaction, [ClassName]); + raise EBold.CreateFmt('%s.RedoBlock: the Undo-mechanism can only be invoked outside a transaction', [ClassName]); UndoState := busRedoing; try DoUndoInTransaction(BlockName, RedoBlocks, UndoBlocks); @@ -345,16 +539,14 @@ procedure TBoldUndoHandler.UndoLatest; UndoBlock(UndoBlocks.CurrentBlock.BlockName); end; -procedure TBoldUndoHandler.HandleObject(Obj: IBoldObjectContents; RegardAsExisting: Boolean); +procedure TBoldUndoHandler.HandleObject(const Obj: IBoldObjectContents; RegardAsExisting: Boolean); begin - if fEnabled and (UndoState = busNormal) then + if Enabled and (UndoState = busNormal) then begin RedoBlocks.Clear; UndoBlocks.CurrentBlock.HandleObject(Obj, RegardAsExisting); end; end; - -// Perform Undo, Fill in valuespace for Redoing procedure TBoldUndoHandler.DoUndo(UnDoValueSpace: TBoldFreeStandingValueSpace; RedoValueSpace: TBoldFreeStandingValueSpace); type @@ -365,19 +557,18 @@ procedure TBoldUndoHandler.DoUndo(UnDoValueSpace: TBoldFreeStandingValueSpace; procedure GetInnerLinkIndices(BoldObject: TBoldObject; var MemberIndex1, MemberIndex2: Integer); var i: integer; - MemberRTInfo: TBoldMemberRTInfo; + RoleRTInfo: TBoldRoleRTInfo; begin MemberIndex1 := -1; MemberIndex2 := -1; - for i:= 0 to BoldObject.BoldMemberCount - 1 do + for RoleRTInfo in BoldObject.BoldClassTypeInfo.AllRoles do begin - MemberRTInfo := BoldObject.BoldClassTypeInfo.AllMembers[i]; - if MemberRTInfo.IsRole and ((MemberRTInfo as TBoldRoleRTInfo).RoleType = rtInnerLinkRole) then + if RoleRTInfo.RoleType = rtInnerLinkRole then begin if (MemberIndex1 = -1) then - MemberIndex1 := i + MemberIndex1 := RoleRTInfo.index else if (MemberIndex2 = -1) then - MemberIndex2 := i + MemberIndex2 := RoleRTInfo.index else Break; end; @@ -406,9 +597,8 @@ procedure TBoldUndoHandler.DoUndo(UnDoValueSpace: TBoldFreeStandingValueSpace; Value1 := ObjectContents.valueByIndex[MemberIndex1] as IBoldObjectIdRef; if Assigned(Value0) and Assigned(Value1) then begin - // Very clumsy, but seems to work - // Problem is that when first assigment is done, other linkobject-link is not set yet, so - // otherend will be nil. This means that things will not be set upp properly. + + SavIdValue := TBFSObjectIdRef.Create; SavIdValue.AssignContent(Member1.AsIBoldValue[bdepContents]); Member1.AsIBoldValue[bdepContents].AssignContent(Value1); @@ -455,18 +645,20 @@ procedure TBoldUndoHandler.DoUndo(UnDoValueSpace: TBoldFreeStandingValueSpace; procedure UnDoLinks(BoldObject: TBoldObject; ObjectContents: IBoldObjectContents); var - i: Integer; aValue: IBoldValue; BoldMember: TBoldMember; + RoleRTInfo: TBoldRoleRTInfo; begin - for i := 0 to BoldObject.BoldMemberCount - 1 do + for RoleRTInfo in BoldObject.BoldClassTypeInfo.AllRoles do begin - aValue := ObjectContents.valueByIndex[i]; - if assigned(aValue) then + if RoleRTInfo.IsSingleRole and (RoleRTInfo.RoleType = rtRole) then begin - BoldMember := BoldObject.BoldMembers[i]; - if (BoldMember is TBoldObjectReference) and (TBoldObjectReference(BoldMember).BoldRoleRTInfo.RoleType = rtRole) then + aValue := ObjectContents.valueByIndex[RoleRTInfo.Index]; + if assigned(aValue) then + begin + BoldMember := BoldObject.BoldMembers[RoleRTInfo.Index]; BoldMember.AsIBoldValue[bDepUndo].AssignContent(aValue); + end; end; end; if BoldObject.BoldClassTypeInfo.IsLinkClass then @@ -477,12 +669,11 @@ procedure TBoldUndoHandler.DoUndo(UnDoValueSpace: TBoldFreeStandingValueSpace; var oid: TBoldObjectId; FSObjectContents: TBoldFreeStandingObjectContents; + FSRedoObjectContents: TBoldFreeStandingObjectContents; i, M: integer; + Value: IBoldValue; BoldObject: TBoldObject; - MemberId: TBoldMemberId; - G: IBoldGuard; begin - G := TBoldGuard.Create(MemberId); for i:= 0 to ObjectIds.Count - 1 do begin oid := ObjectIds[i]; @@ -491,22 +682,24 @@ procedure TBoldUndoHandler.DoUndo(UnDoValueSpace: TBoldFreeStandingValueSpace; FSObjectContents := UndoValueSpace.GetFSObjectContentsByObjectId(oid); if Assigned(BoldObject) then begin - if FSObjectContents.BoldExistenceState = besExisting then // just keep changed values + if FSObjectContents.BoldExistenceState = besExisting then begin RedoValueSpace.GetFSObjectContentsByObjectId(oid).ApplyObjectContents( FSObjectContents, true, false); RedoValueSpace.GetFSObjectContentsByObjectId(oid).UpdateObjectContentsFrom(BoldObject.AsIBoldObjectContents[bdepContents]) end - else // Object going away, keep all + else begin RedoValueSpace.GetFSObjectContentsByObjectId(oid).ApplyObjectContents(BoldObject.AsIBoldObjectContents[bdepContents], False, false); for M := 0 to BoldObject.BoldMemberCount -1 do if BoldObject.BoldMemberAssigned[M] and BoldObject.BoldMembers[M].StoreInUndo then begin - MemberId := TBoldMemberId.Create(M); - RedoValueSpace.GetFSObjectContentsByObjectId(oid).EnsureMember(MemberId, BoldObject.BoldMembers[M].AsIBoldValue[bdepContents].ContentName); - RedoValueSpace.GetFSObjectContentsByObjectId(oid).ValueByIndex[M].AssignContent(BoldObject.BoldMembers[M].AsIBoldValue[bdepContents]); - FreeAndNil(MemberId); + FSRedoObjectContents := RedoValueSpace.GetFSObjectContentsByObjectId(oid); + if FSRedoObjectContents is TBoldSystemFreeStandingObjectContents then + Value := TBoldSystemFreeStandingObjectContents(FSRedoObjectContents).EnsureMemberAndGetValueByIndex(BoldObject.BoldMembers[M]) + else + Value := FSRedoObjectContents.EnsureMemberAndGetValueByIndex(M, BoldObject.BoldMembers[M].AsIBoldValue[bdepContents].ContentName); + Value.AssignContent(BoldObject.BoldMembers[M].AsIBoldValue[bdepContents]); end; end; end @@ -520,7 +713,7 @@ procedure TBoldUndoHandler.DoUndo(UnDoValueSpace: TBoldFreeStandingValueSpace; function GetObjectAction( FSObjectContents: TBoldFreeStandingObjectContents; BoldObject: TBoldObject): TObjectAction; begin - result := oaUse; // stupid compiler + result := oaUse; if Assigned(BoldObject) then begin if FSObjectContents.BoldExistenceState = besExisting then @@ -540,14 +733,14 @@ procedure TBoldUndoHandler.DoUndo(UnDoValueSpace: TBoldFreeStandingValueSpace; bvpsTransient: Result := oaTransient; else - raise EBold.create(sInternalError); + raise EBold.create('Internal error?'); end; besNotCreated, besDeleted: case FSObjectContents.BoldPersistenceState of bvpsCurrent, bvpsModified, bvpsTransient: Result := oaDelete; else - raise EBold.create(sInternalError); + raise EBold.create('Internal error?'); end; end; end; @@ -566,7 +759,6 @@ procedure TBoldUndoHandler.DoUndo(UnDoValueSpace: TBoldFreeStandingValueSpace; ObjectIds := TBoldObjectIdList.Create; UndoValueSpace.AllObjectIds(ObjectIds, false); SaveOldValues; - // pass one, create all Objects, and set attributes for i:= 0 to ObjectIds.Count - 1 do begin oid := ObjectIds[i]; @@ -592,7 +784,6 @@ procedure TBoldUndoHandler.DoUndo(UnDoValueSpace: TBoldFreeStandingValueSpace; if ObjectAction <> oaDelete then UnDoObjectAndAttributes(BoldObject, UndoValueSpace.GetFSObjectContentsByObjectId(oid)); end; - // Pass 2, update links once all objects are in place for i:= 0 to ObjectIds.Count - 1 do begin oid := ObjectIds[i]; @@ -601,7 +792,6 @@ procedure TBoldUndoHandler.DoUndo(UnDoValueSpace: TBoldFreeStandingValueSpace; if Assigned(BoldObject) then UnDoLinks(BoldObject, UndoValueSpace.GetFSObjectContentsByObjectId(oid)); end; - // Pass 3, delete objects for i:= 0 to ObjectIds.Count - 1 do begin @@ -617,6 +807,16 @@ procedure TBoldUndoHandler.DoUndo(UnDoValueSpace: TBoldFreeStandingValueSpace; end; end; +function TBoldUndoBlockList.IndexOf(const BlockName: string): integer; +begin + Result := fList.IndexOf(BlockName); +end; + +function TBoldUndoBlockList.IndexOf(Block: TBoldUndoBlock): integer; +begin + Result := fList.IndexOfObject(Block); +end; + procedure TBoldUndoHandler.DoUndoInTransaction(BlockName: string; FromList, ToList: TBoldUndoBlockList); var @@ -625,34 +825,39 @@ procedure TBoldUndoHandler.DoUndoInTransaction(BlockName: string; G: IBoldGuard; begin G := TBoldGuard.Create(RedoValueSpace); - aBlock := FromList.BlocksByName[BlockName]; + aBlock := FromList.BlockByName[BlockName]; if Not Assigned(aBlock) then - raise EBold.CreateFmt(sInvalidBlockName, [BlockName]); + raise EBold.CreateFmt('%s is not a valid blockname for this operation', [BlockName]); if not FromList.CanMoveToTop(FromList.IndexOf(BlockName)) then - raise EBold.CreateFmt(sCannotMoveToTop, [BlockName]); + raise EBold.CreateFmt('%s Can''t be moved to top', [BlockName]); RedoValueSpace := TBoldFreeStandingValueSpace.Create; System.StartTransaction; try DoUndo(aBlock.FSValueSpace, RedoValueSpace); FromList.InternalRemoveBlock(BlockName); ToList.AddBlock(BlockName).FSValueSpace := RedoValueSpace; - RedoValueSpace := nil; // now owned by Redo-block + RedoValueSpace := nil; System.CommitTransaction; except System.RollbackTransaction; end; end; -function TBoldUndoHandler.CanRedoBlock(BlockName: string): Boolean; +function TBoldUndoHandler.CanRedoBlock(const BlockName: string): Boolean; begin Result := RedoBlocks.CanMoveToTop(RedoBlocks.AssertedIndexOf(BlockName)); end; -function TBoldUndoHandler.CanUndoBlock(BlockName: string): Boolean; +function TBoldUndoHandler.CanUndoBlock(const BlockName: string): Boolean; begin Result := UnDoBlocks.CanMoveToTop(UndoBlocks.AssertedIndexOf(BlockName)); end; +function TBoldUndoHandler.GetEnabled: Boolean; +begin + result := fEnabled; +end; + function TBoldUndoHandler.GetRedoList: IBoldUndoList; begin Result := FRedoBlocks; @@ -660,11 +865,10 @@ function TBoldUndoHandler.GetRedoList: IBoldUndoList; function TBoldUndoHandler.GetUndoList: IBoldUndoList; begin - Result := FUndoBlocks; + Result := FUndoBlocks; end; -function TBoldUndoHandler.GetUniqueBlockName( - SuggestedName: string): string; +function TBoldUndoHandler.GetUniqueBlockName(const SuggestedName: string): string; var i: integer; begin @@ -672,11 +876,18 @@ function TBoldUndoHandler.GetUniqueBlockName( Result := SuggestedName; while ((UndoBlocks.IndexOf(Result) <> -1) or (RedoBlocks.IndexOf(Result) <> -1)) do begin - Result := Format('%s %d', [SuggestedName, i]); // do not localize + Result := Format('%s %d', [SuggestedName, i]); inc(i); end; end; + +{function TBoldUndoHandler.GetNonUndoableBlock: IBoldUndoBlock; +begin + Result := FNonUndoableBlock; +end; +} + procedure TBoldUndoHandler.ApplytranslationList( IdTranslationList: TBoldIdTranslationList); begin @@ -686,7 +897,7 @@ procedure TBoldUndoHandler.ApplytranslationList( procedure TBoldUndoHandler.SetCheckPoint; begin - SetNamedCheckPoint(GetUniqueBlockName('')); + SetNamedCheckPoint(GetUniqueBlockName(cUnNamedBlockName)); end; procedure TBoldUndoHandler.ClearAllUndoBlocks; @@ -695,31 +906,29 @@ procedure TBoldUndoHandler.ClearAllUndoBlocks; FRedoBlocks.Clear; end; -function TBoldUndoHandler.GetEnabled: Boolean; -begin - result := fEnabled; -end; - procedure TBoldUndoHandler.SetEnabled(value: Boolean); begin - fEnabled := value; + if fEnabled <> value then + begin + fEnabled := value; + end; end; { TBoldUndoBlockList } -function TBoldUndoBlockList.AddBlock( - BlockName: string; const FSVAlueSpace: TBoldFreeStandingValueSpace): TBoldUndoBlock; +function TBoldUndoBlockList.AddBlock(const BlockName: string; + const FSVAlueSpace: TBoldFreeStandingValueSpace): TBoldUndoBlock; var Idx: integer; begin - if FList.IndexOfName(BlockName) = -1 then + if FList.IndexOf(BlockName) = -1 then begin Idx := FList.Add(BlockName); Result := TBoldUndoBlock.CreateNamedBlock(BlockName, FSVAlueSpace); FList.Objects[Idx] := Result; end else - raise EBold.CreateFmt(sBlockNameInUse, [ClassName, BlockName]); + raise EBold.CreateFmt('%s.AddBlock: a block named %s already exists', [ClassName, BlockName]); end; function TBoldUndoBlockList.CanMoveBlock(CurIndex, @@ -728,22 +937,22 @@ function TBoldUndoBlockList.CanMoveBlock(CurIndex, i: integer; CurBlock, NewBlock: TBoldUndoBlock; begin - CurBlock := AssertedBlocksByIndex[CurIndex]; - NewBlock := AssertedBlocksByIndex[NewIndex]; + CurBlock := AssertedBlockByIndex[CurIndex]; + NewBlock := AssertedBlockByIndex[NewIndex]; Result := (CurIndex = NewIndex) or not CurBlock.IsDependantOn(NewBlock); if Result then begin - if (CurIndex < NewIndex) then //moving up + if (CurIndex < NewIndex) then for i:= CurIndex + 1 to NewIndex do begin - Result := not CurBlock.IsDependantOn(BlocksByIndex[i]); + Result := not CurBlock.IsDependantOn(BlockByIndex[i]); if not Result then Break; end - else //moving down + else for i:= CurIndex - 1 downto NewIndex do begin - Result := not CurBlock.IsDependantOn(BlocksByIndex[i]); + Result := not CurBlock.IsDependantOn(BlockByIndex[i]); if not Result then Break; end; @@ -779,81 +988,55 @@ procedure TBoldUndoBlockList.MoveBlock(CurIndex, NewIndex: integer); begin if not CanMoveBlock(CurIndex, NewIndex) then - raise EBold.Create(sCannotMoveBlock); + raise EBold.Create('can''t move Block'); FList.Move(CurIndex, NewIndex); end; -function TBoldUndoBlockList.GetBlocksByIndex( - Index: integer): TBoldUndoBlock; +procedure TBoldUndoBlockList.MoveToTop(const BlockName: string); begin - if (Index >= 0) and (Index < FList.Count) then - Result := FList.Objects[Index] as TBoldUndoBlock - else - Result := nil; + MoveBlock(IndexOf(BlockName), FList.Count - 1); end; -function TBoldUndoBlockList.GetBlocksByName( - BlockName: string): TBoldUndoBlock; +procedure TBoldUndoBlockList.InternalRemoveBlock(Block: TBoldUndoBlock); var - Idx: integer; -begin - Idx := FList.IndexOf(blockName); - if Idx <> - 1 then - Result := FList.Objects[Idx] as TBoldUndoBlock - else - Result := nil; -end; - -function TBoldUndoBlockList.GetCount: integer; -begin - Result := fList.Count; -end; - -function TBoldUndoBlockList.IndexOf(BlockName: string): integer; -begin - Result := fList.IndexOf(BlockName); -end; - -procedure TBoldUndoBlockList.MoveToTop( - BlockName: string); + idx: integer; begin - MoveBlock(IndexOf(BlockName), FList.Count - 1); + idx := IndexOf(Block); + FList.Delete(idx); + FreeAndNil(Block); end; -procedure TBoldUndoBlockList.InternalRemoveBlock(BlockName: string); +procedure TBoldUndoBlockList.InternalRemoveBlock(const BlockName: string); var idx: integer; - obj: TObject; + Block: TBoldUndoBlock; begin idx := AssertedIndexOf(BlockName); - obj := FList.Objects[idx]; - FreeAndNil(obj); - FList.Delete(idx); + Block := FList.Objects[idx] as TBoldUndoBlock; + InternalRemoveBlock(Block); end; -procedure TBoldUndoBlockList.RenameBlock(OldName, - NewName: string); +procedure TBoldUndoBlockList.RenameBlock(const OldName, NewName: string); var aBlock: TBoldUndoBlock; begin - if Assigned(GetBlocksByName(NewName)) then - raise EBold.Create(sCannotRenameBlock); - aBlock := AssertedBlocksByName[OldName]; + if Assigned(GetBlockByName(NewName)) then + raise EBold.Create('Can''t rename block'); + aBlock := AssertedBlockByName[OldName]; FList.Strings[IndexOf(OldName)] := NewName; aBlock.FName := NewName; end; - procedure TBoldUndoBlockList.MergeBlocks(DestinationBlockName, - SourceBlockName: string); + procedure TBoldUndoBlockList.MergeBlocks(const DestinationBlockName, SourceBlockName: string); var DestinationBlock, SourceBlock: TBoldUndoBlock; begin - DestinationBlock := AssertedBlocksbyName[DestinationBlockName]; - SourceBlock := AssertedBlocksByName[SourceBlockName]; + DestinationBlock := AssertedBlockByName[DestinationBlockName]; + SourceBlock := AssertedBlockByName[SourceBlockName]; if not CanMergeBlock(IndexOf(SourceBlockName), IndexOf(DestinationBlockName)) then - raise EBold.Create(sCannotMergeBlocks); + raise EBold.Create('Can''t merge blocks'); DestinationBlock.Merge(SourceBlock, IndexOf(DestinationBlockName) > IndexOf(SourceBlockName)); - InternalRemoveBlock(SourceBlockName); + InternalRemoveBlock(SourceBlock); end; function TBoldUndoBlockList.CanMergeBlock(CurIndex, @@ -863,21 +1046,21 @@ function TBoldUndoBlockList.CanMergeBlock(CurIndex, CurBlock, NewBlock: TBoldUndoBlock; begin Result := true; - CurBlock := AssertedBlocksByIndex[CurIndex]; - NewBlock := AssertedBlocksByIndex[CurIndex]; - if CurIndex < NewIndex then //moving up + CurBlock := AssertedBlockByIndex[CurIndex]; + NewBlock := AssertedBlockByIndex[CurIndex]; + if CurIndex < NewIndex then begin for i:= CurIndex + 1 to NewIndex - 1 do begin - Result := not CurBlock.IsDependantOn(BlocksByIndex[i]); + Result := not CurBlock.IsDependantOn(BlockByIndex[i]); if not Result then Break; end end - else if CurIndex > NewIndex then //moving down + else if CurIndex > NewIndex then for i:= CurIndex - 1 downto NewIndex + 1 do begin - Result := not NewBlock.IsDependantOn(BlocksByIndex[i]); + Result := not NewBlock.IsDependantOn(BlockByIndex[i]); if not Result then Break; end; @@ -887,17 +1070,17 @@ function TBoldUndoBlockList.GetCurrentBlock: TBoldUndoBlock; begin Result := nil; if (Count = 0) then - Result := AddBlock('UnNamed') // do not localize + Result := AddBlock(cUnNamedBlockName) else if Count > 0 then Result := FList.Objects[Count - 1] as TBoldUndoBlock; end; -function TBoldUndoBlockList.GetAssertedBlocksByName( - BlockName: string): TBoldUndoBlock; +function TBoldUndoBlockList.GetAssertedBlockByName( + const BlockName: string): TBoldUndoBlock; begin - Result := BlocksByName[BlockName]; + Result := BlockByName[BlockName]; if not Assigned(Result) then - raise EBold.CreateFmt(sNoSuchBlock, [BlockName]); + raise EBold.CreateFmt('There is no block named %s', [BlockName]); end; function TBoldUndoBlockList.CanMoveToTop(CurIndex: integer): Boolean; @@ -910,18 +1093,17 @@ function TBoldUndoBlockList.AssertedIndexOf( begin Result := IndexOf(BlockName); if Result = -1 then - raise EBold.CreateFmt(sNoSuchBlock, [BlockName]); + raise EBold.CreateFmt('There is no block named %s', [BlockName]); end; -function TBoldUndoBlockList.GetItemsByName( - Name: string): IBoldUndoBlock; +function TBoldUndoBlockList.GetItemByName(const Name: string): IBoldUndoBlock; begin - result := BlocksByName[Name] as IBoldUndoBlock; + result := BlockByName[Name] as IBoldUndoBlock; end; -function TBoldUndoBlockList.GetItems(Index: integer): IBoldUndoBlock; +function TBoldUndoBlockList.GetItem(Index: integer): IBoldUndoBlock; begin - Result := BlocksbyIndex[Index] as IBoldUndoBlock ; + Result := BlockByIndex[Index] as IBoldUndoBlock ; end; function TBoldUndoBlockList.GetTopBlock: IBoldUndoBlock; @@ -935,7 +1117,7 @@ procedure TBoldUndoBlockList.ApplytranslationList( i: integer; begin for i := 0 to count-1 do - BlocksbyIndex[i].ApplytranslationList(IdTranslationList); + BlockByIndex[i].ApplytranslationList(IdTranslationList); end; procedure TBoldUndoBlockList.MergeAll; @@ -946,9 +1128,9 @@ procedure TBoldUndoBlockList.MergeAll; i:= Count - 1; while i > 0 do begin - aBlock := BlocksByIndex[i]; - BlocksByIndex[i - 1].Merge(aBlock, True); - InternalRemoveBlock(aBlock.BlockName); + aBlock := BlockByIndex[i]; + BlockByIndex[i - 1].Merge(aBlock, True); + InternalRemoveBlock(aBlock); dec(i); end; end; @@ -964,11 +1146,11 @@ procedure TBoldUndoBlockList.GetDependantBlocks(const BlockName: string; G: IBOldGuard; begin G := TBoldGuard.Create(ObjectIds); - aBlock := GetAssertedBlocksByName(BlockName); + aBlock := GetAssertedBlockByName(BlockName); if Assigned(aBlock) then begin if not Assigned(DependantBlocks) then - raise EBold.CreateFmt(sParameterNotDefined, [ClassName]); + raise EBold.CreateFmt('%s.GetDependantBlocks: parameter DependantBlocks not assigned', [ClassName]); ObjectIds := TBoldObjectIdList.Create; aBlock.FSValueSpace.AllObjectIds(ObjectIds, true); DependantBlocks.Clear; @@ -978,24 +1160,24 @@ procedure TBoldUndoBlockList.GetDependantBlocks(const BlockName: string; for j:= 0 to ObjectContents.MemberCount - 1 do for b := AssertedIndexOf(aBlock.BlockName)-1 downto 0 do begin - CurBlock := BlocksbyIndex[b]; + CurBlock := BlockByIndex[b]; if Assigned(ObjectContents.ValueByIndex[j]) and CurBlock.ValueExists(ObjectIds.ObjectIds[i], j, aValue) and (DependantBlocks.IndexOf(CurBlock) = - 1) then DependantBlocks.Add(CurBlock); - end;//for b - end;//for i + end; + end; end; end; -function TBoldUndoBlockList.GetAssertedBlocksByIndex( +function TBoldUndoBlockList.GetAssertedBlockByIndex( Index: integer): TBoldUndoBlock; begin - Result := BlocksByIndex[Index]; + Result := BlockByIndex[Index]; if not Assigned(Result) then - raise EBold.CreateFmt(sNoSuchBlockIndex, [Index]); + raise EBold.CreateFmt('There is no block with index %d', [Index]); end; -function TBoldUndoBlockList.RemoveBlock(BlockName: string): Boolean; +function TBoldUndoBlockList.RemoveBlock(const BlockName: string): Boolean; var idx: integer; begin @@ -1005,256 +1187,7 @@ function TBoldUndoBlockList.RemoveBlock(BlockName: string): Boolean; InternalRemoveBlock(BlockName); end; -{ TBoldUndoBlock } - -constructor TBoldUndoBlock.CreateNamedBlock(const BlockName: string; const FSVAlueSpace: TBoldFreeStandingValueSpace); -begin - inherited Create; - FContainsChanges := false; - FName := BlockName; - FValueSpace := FSVAlueSpace; -end; - - -function TBoldUndoBlock.IsDependantOn( - Block: TBoldUndoBlock): Boolean; -var - ObjectContents: TBoldFreeStandingObjectContents; - i, j: integer; - aValue: IBoldValue; - ObjectIds: TBoldObjectIdList; - G: IBoldGuard; -begin - G := TBoldGuard.Create(ObjectIds); - ObjectIds := TBoldObjectIdList.Create; - Result := false; - FSValueSpace.AllObjectIds(ObjectIds, True); - for i:= 0 to ObjectIds.Count - 1 do - begin - ObjectContents := FSValueSpace.GetFSObjectContentsByObjectId(ObjectIds[i]); - for j := 0 to ObjectContents.MemberCount - 1 do - begin - Result := Assigned(ObjectContents.ValueByIndex[j]) and Block.ValueExists(ObjectIds[i], j, aValue); - if Result then - Break; - end; - if Result then - Break; - end; -end; - -procedure TBoldUndoBlock.Merge(Block: TBoldUndoBlock; const Overwrite: Boolean); -var - OwnContents, ObjectContents: TBoldFreeStandingObjectContents; - ObjectId: TBoldObjectId; - MemberId: TBoldMemberId; - i, j: integer; - ObjectIds: TBoldObjectIdList; - G: IBoldGuard; -begin - G := TBoldGuard.Create(MemberId, ObjectIds); - // Todo: Same as ApplyValueSpace??? - ObjectIds := TBoldObjectIdList.Create; - Block.FSValueSpace.AllObjectIds(ObjectIds, True); - for i:= 0 to ObjectIds.Count - 1 do - begin - ObjectId := ObjectIds[i]; - ObjectContents := Block.FSValueSpace.GetFSObjectContentsByObjectId(ObjectId); - if not FSValueSpace.GetHasContentsForId(ObjectId) then - FSValueSpace.EnsureObjectContents(ObjectId); - OwnContents :=FSValueSpace.GetFSObjectContentsByObjectId(ObjectId); - for j:= 0 to ObjectContents.MemberCount - 1 do - if Assigned(ObjectContents.valueByIndex[j]) then - begin - MemberId := TBoldMemberId.Create(j); - if (OwnContents.MemberCount > j) and Assigned(OwnContents.ValueByIndex[j]) then // CHECKCME - begin - if overwrite then - OwnContents.ValueByIndex[j].AssignContent(ObjectContents.ValueByIndex[j]); - end - else - begin - OwnContents.EnsureMember(MemberId, ObjectContents.ValueByIndex[j].ContentName); - OwnContents.ValueByIndex[j].AssignContent(ObjectContents.ValueByIndex[j]); - end; - FreeAndNil(memberId); - end; - end; -end; - -function TBoldUndoBlock.ValueExists(const ObjectID: TBoldObjectID; - const MemberIndex: integer; out Value: IBoldValue): Boolean; -var - ObjectContents: TBoldFreeStandingObjectContents; -begin - Value := nil; - ObjectContents := FSValueSpace.GetFSObjectContentsByObjectId(ObjectID); - if Assigned(ObjectContents) and (MemberIndex < ObjectContents.memberCount) then - Value := ObjectContents.ValueByIndex[MemberIndex]; - Result := Assigned(Value); -end; - -function TBoldUndoBlock.ValueExists(const ObjectID: TBoldObjectId; - const MemberIndex: integer): Boolean; -var - OC: TBoldFreeStandingObjectContents; -begin - OC := FSValueSpace.GetFSobjectContentsByObjectId(ObjectID); - Result := Assigned(OC) and (MemberIndex < OC.memberCount) and - Assigned(OC.ValueByIndex[MemberIndex]); -end; - -function TBoldUndoBlock.HandleMember(ObjectContents: IBoldObjectContents; MemberIndex: integer; MemberValue: IBoldValue): Boolean; -var - MemberId: TBoldMemberId; - ObjectId: TBoldObjectId; - FSObjectContents: TBoldFreeStandingObjectContents; - G: IBoldGuard; -begin - G := TBoldGuard.Create(MemberId); - ObjectId := ObjectContents.ObjectId; - Result := not ValueExists(ObjectId, MemberIndex); - if Result then - begin - FContainsChanges := true; - MemberId := TBoldMemberId.Create(MemberIndex); - FSObjectContents := FSValueSpace.GetFSObjectContentsByObjectId(ObjectId); - if not Assigned(FSObjectContents) then - begin - FSValueSpace.EnsureObjectContents(ObjectId); - FSObjectContents := FSValueSpace.GetFSObjectContentsByObjectId(ObjectId); - FSObjectContents.ApplyObjectContents(ObjectContents, False, false); - end; - FSObjectContents.EnsureMember(MemberId, MemberValue.ContentName); - FSObjectContents.ValueByIndex[MemberIndex].AssignContent(MemberValue); - end; -end; - -function TBoldUndoBlock.HasObjectContentsForAnyObjectInList( - const ObjectList: TBoldObjectList): Boolean; -var - i: integer; - ObjectId: TBoldObjectId; -begin - Result := false; - for i:= 0 to ObjectList.Count - 1 do - begin - ObjectId := ObjectList.BoldObjects[i].BoldObjectLocator.BoldObjectID; - Result := Assigned(FSValueSpace.GetFSObjectContentsByObjectId(ObjectId)); - if Result then - Break; - end; -end; - -(* -procedure TBoldUndoBlock.GetLinksToObject(const System: TBoldSystem; const ObjectId: TBoldObjectId; const OwnIndexInLinkClass: integer; - const SingleLinkClassTypeInfo: TBoldClassTypeInfo; SingleLinkIds: TBoldObjectIdList); -var - ObjectIds: TBoldObjectIdList; - i: integer; - LinkValue: IBoldValue; -begin - // TODO: new implementation - ObjectIds := TBoldObjectIdList.Create; - try - AllIdsInClass(System, SingleLinkClassTypeInfo, ObjectIds); - for i:= 0 to ObjectIds.Count - 1 do - if ValueExists(ObjectIds[i], OwnIndexInLinkClass, LinkValue) and - Assigned((LinkValue as IBoldObjectIdRef).Id) and - ((LinkValue as IBoldObjectIdRef).Id.IsEqual[ObjectId]) then - SingleLinkIds.Add(ObjectIds[i].Clone); - except - FreeAndNil(ObjectIds); - end; -end; -*) - -(* -procedure TBoldUndoBlock.AllIdsInClass( const System: TBoldSystem; - const ClassTypeInfo: TBoldClassTypeInfo; IdList: TBoldObjectIdList); -var - i: integer; - ObjectIds: TBoldObjectIdList; - G: IBoldGuard; -begin -{ TODO : Won't work with really deleted objects } - G := TBoldGuard.Create(ObjectIds); - ObjectIds := TBoldObjectIdList.Create; - FSValueSpace.AllObjectIds(ObjectIds, True); - for i:= 0 to ObjectIds.Count - 1 do - begin - if (System.Locators.ObjectByID[ObjectIds[i]].BoldClassTypeInfo = ClassTypeInfo) then - IdList.Add(ObjectIds[i]); - end; -end; -*) - -procedure TBoldUndoBlock.HandleObject(Obj: IBoldObjectContents; RegardAsExisting: Boolean); -var - ObjectId: TBoldObjectId; - ObjectContents: TBoldFreeStandingObjectContents; -begin - Assert(assigned(obj)); - ObjectId := Obj.ObjectID; - ObjectContents := FSValueSpace.GetFSObjectContentsByObjectId(ObjectId); - if not Assigned(ObjectContents) then - begin - FContainsChanges := True; - FSValueSpace.EnsureObjectContents(ObjectId); - ObjectContents := FSValueSpace.GetFSObjectContentsByObjectId(ObjectId); - ObjectContents.ApplyObjectContents(Obj, False, false); - if RegardAsExisting then - begin - ObjectContents.BoldPersistenceState := bvpsCurrent; - ObjectContents.BoldExistenceState := besExisting; - end; - end; -end; - -function TBoldUndoBlock.GetFSValueSpace: TBoldFreeStandingValueSpace; -begin - if not Assigned(FValueSpace) then - FValueSpace := TBoldFreeStandingValueSpace.Create; - Result := FValueSpace; -end; - -destructor TBoldUndoBlock.Destroy; -begin - FreeAndNil(FValueSpace); - inherited; -end; - -procedure TBoldUndoBlock.SetFSValueSpace( - const Value: TBoldFreeStandingValueSpace); -begin - if (FValueSpace <> Value) then - begin - FreeAndNil(FValueSpace); - FValueSpace := Value; - fContainsChanges := TRUE; - end; -end; - -function TBoldUndoBlock.GetName: string; -begin - Result := fName; -end; - -function TBoldUndoBlock.GetValueSpace: IBoldValueSpace; -begin - result := FSValueSpace as IBoldValueSpace; -end; - -function TBoldUndoBlock.GetContainsChanges: Boolean; -begin - result := fContainsChanges; -end; - -procedure TBoldUndoBlock.ApplytranslationList( - IdTranslationList: TBoldIdTranslationList); -begin - ValueSpace.ApplytranslationList(IdTranslationList); -end; +initialization end. diff --git a/Source/ObjectSpace/Unloader/BoldUnloader.pas b/Source/ObjectSpace/Unloader/BoldUnloader.pas index 9be664a..dc1808b 100644 --- a/Source/ObjectSpace/Unloader/BoldUnloader.pas +++ b/Source/ObjectSpace/Unloader/BoldUnloader.pas @@ -1,3 +1,6 @@ +///////////////////////////////////////////////////////// + + unit BoldUnloader; interface @@ -13,6 +16,8 @@ interface { Forward declaration of classes } TBoldInvalidateMemberEvent = procedure(Member: TBoldMember; var Invalidate: Boolean) of object; TBoldUnloadObjectEvent = procedure(BoldObject: TBoldObject; var Unload: Boolean) of object; + TBoldReportUnloadEvent = procedure(const Scanned, UnloadedObjects, InvalidatedMembers: integer) of object; + TBoldMayUnloadStartEvent = procedure(var aStart: boolean) of object; TBoldUnLoader = class; @@ -24,11 +29,18 @@ TBoldUnLoader = class(TBoldMemoryManagedObject) fScanPerTick: integer; fActive: boolean; fWaitCount: integer; + fScanned: integer; + fInvalidatedMemberCount: integer; + fUnloadedObjectCount: integer; + fScanTime: TDateTime; fTraverser: TBoldLocatorListTraverser; fOnMayInvalidate: TBoldInvalidateMemberEvent; fOnMayUnload: TBoldUnloadObjectEvent; - procedure Scan; - procedure ScanObject(BoldObject: TBoldObject); + fOnMayStart: TBoldMayUnloadStartEvent; + fOnReportUnload: TBoldReportUnloadEvent; + FUnloadFromCurrentClassList: boolean; + function Scan: boolean; + function ScanObject(BoldObject: TBoldObject): boolean; procedure SetActive(const Value: boolean); procedure SetBoldSystem(const Value: TBoldSystem); procedure StartScan; @@ -36,13 +48,20 @@ TBoldUnLoader = class(TBoldMemoryManagedObject) public destructor Destroy; override; procedure Tick; + property InvalidatedMemberCount: integer read fInvalidatedMemberCount; + property UnloadedObjectCount: integer read fUnloadedObjectCount; + property Scanned: integer read fScanned; + property ScanTime: TDateTime read fScanTime; property BoldSystem: TBoldSystem read fBoldSystem write SetBoldSystem; - property ScanPerTick: integer read fScanPerTick write fScanPerTick; - property MinAgeForUnload: integer read fMinAgeForUnload write fMinAgeForUnload; + property ScanPerTick: integer read fScanPerTick write fScanPerTick; // milliseconds to spend in itterating on each tick + property MinAgeForUnload: integer read fMinAgeForUnload write fMinAgeForUnload; // unit for MinAgeForUnload is TickInterval property UnloadDelayedFetch: boolean read fUnloadDelayedFetch write fUnloadDelayedFetch; + property UnloadFromCurrentClassList: boolean read FUnloadFromCurrentClassList write FUnloadFromCurrentClassList; property Active: boolean read fActive write SetActive; property OnMayInvalidate: TBoldInvalidateMemberEvent read fOnMayInvalidate write fOnMayInvalidate; property OnMayUnload: TBoldUnloadObjectEvent read fOnMayUnload write fOnMayUnload; + property OnMayStart: TBoldMayUnloadStartEvent read fOnMayStart write fOnMayStart; + property OnReportUnload: TBoldReportUnloadEvent read fOnReportUnload write fOnReportUnload; end; @@ -50,8 +69,14 @@ implementation uses SysUtils, + Windows, + DateUtils, BoldUtils, - BoldCoreConsts; + BoldCoreConsts, + BoldSystemRT, + BoldIndex, + BoldElements, + BoldSubscription; { TBoldUnLoader } @@ -63,9 +88,9 @@ procedure TBoldUnLoader.SetActive(const Value: boolean); if Value then begin if Assigned(BoldSystem) then - StartScan + Tick else - raise EBold.CreateFmt(sNeedSystemToActivate, [ClassName]); + raise EBold.Create('TBoldUnLoader: Attempt to set Active without BoldSystem'); end else FreeAndNil(fTraverser); @@ -90,46 +115,64 @@ procedure TBoldUnLoader.StartWait; fWaitCount := 0; end; -procedure TBoldUnLoader.Scan; +function TBoldUnLoader.Scan: boolean; var Locator: TBoldObjectLocator; - Scanned: integer; + vScanned, vUnloadedObjectCount, vInvalidatedMemberCount: integer; + lStartTime: Int64; + lNow: Int64; + lTimeOut: boolean; begin - Scanned := 0; - while (not fTraverser.EndOfList) and (Scanned < ScanPerTick) do + lStartTime := GetTickCount; + lNow := lStartTime; + vScanned := Scanned; + vUnloadedObjectCount := UnloadedObjectCount; + vInvalidatedMemberCount := InvalidatedMemberCount; + lTimeOut := false; + while not lTimeOut and (fTraverser.MoveNext) do begin Locator := fTraverser.Locator; - if assigned(Locator.BoldObject) and (Locator.BoldObject.BoldExistenceState = besExisting) then + if assigned(Locator.BoldObject) and (Locator.BoldObject.BoldExistenceState = besExisting) and not Locator.BoldObject.BoldDirty then ScanObject(Locator.BoldObject); - fTraverser.Next; - inc(Scanned); + inc(fScanned); + lNow := GetTickCount; + lTimeOut := (lNow - lStartTime > scanPerTick) or (lNow < lStartTime); end; + IncMilliSecond(ScanTime, lNow-lStartTime); + if Assigned(fOnReportUnload) then + fOnReportUnload(Scanned - vScanned, UnloadedObjectCount - vUnloadedObjectCount, InvalidatedMemberCount - vInvalidatedMemberCount); + result := lTimeOut; end; -procedure TBoldUnLoader.ScanObject(BoldObject: TBoldObject); +function TBoldUnLoader.ScanObject(BoldObject: TBoldObject): boolean; procedure ScanMembers; var m: integer; Member: TBoldMember; - DoInvalidate: Boolean; + lDoInvalidate: Boolean; begin for m := 0 to BoldObject.BoldMemberCount-1 do - if BoldObject.BoldMemberAssigned[m] then begin - Member := BoldObject.BoldMembers[m]; - with BoldObject.BoldMembers[m] do + Member := BoldObject.BoldMemberIfAssigned[m]; + if Assigned(Member) then begin - if (not Touched) then + with Member do begin - if (Derived and (BoldPersistenceState = bvpsTransient)) or - (UnloadDelayedFetch and (BoldMemberRTInfo.DelayedFetch = True) and (BoldPersistenceState = bvpsCurrent)) then + if (not Touched) then begin - DoInvalidate := not MemberHasSubscribers; - if Assigned(OnMayInvalidate) then - OnMayInvalidate(Member, DoInvalidate); - if DoInvalidate then - Invalidate; + if (Derived and (BoldPersistenceState = bvpsTransient)) or + ((BoldPersistenceState = bvpsCurrent) and (not BoldMemberRTInfo.DelayedFetch or UnloadDelayedFetch)) then + begin + lDoInvalidate := not MemberHasSubscribers; + if Assigned(OnMayInvalidate) then + OnMayInvalidate(Member, lDoInvalidate); + if lDoInvalidate then + begin + inc(fInvalidatedMemberCount); + Invalidate; + end; + end; end; end; end; @@ -137,37 +180,56 @@ procedure TBoldUnLoader.ScanObject(BoldObject: TBoldObject); end; var - DoUnload: Boolean; - + vDoUnload: Boolean; begin + result := false; Scanmembers; - if BoldObject.Touched then - BoldObject.ClearTouched - else if BoldObject.BoldPersistent and not BoldObject.BoldDirty then + with BoldObject do begin - DoUnload := not BoldObject.ObjectHasSubscribers; - if Assigned(OnMayUnload) then - OnMayUnload(BoldObject, DoUnload); - if DoUnload then - BoldObject.BoldObjectLocator.UnloadBoldObject + if Touched then + ClearTouched + else if BoldPersistent and not BoldDirty and not ObjectHasSubscribers then + begin + vDoUnload:= UnloadFromCurrentClassList or (BoldSystem.Classes[BoldClassTypeInfo.TopSortedIndex].BoldPersistenceState <> bvpsCurrent); + if Assigned(OnMayUnload) then + OnMayUnload(BoldObject, vDoUnload); + if vDoUnload then + begin + BoldObjectLocator.UnloadBoldObject; + inc(fUnloadedObjectCount); + result := true; + end; + end; end; end; procedure TBoldUnLoader.Tick; +var + lStart: boolean; begin if Active then + begin + if BoldSystem.InTransaction or BoldSystem.IsProcessingTransactionOrUpdatingDatabase or BoldSystem.IsDerivingMembers then + exit; + if Assigned(fOnMayStart) then + begin + lStart := true; + fOnMayStart(lStart); + if not lStart then + exit; + end; if Assigned(fTraverser) then // in a Scan begin - Scan; - if fTraverser.EndOfList then + if not Scan then StartWait; end else // waiting begin INC(fWaitCount); - if fWaitCount > MinAgeForUnload then + if fWaitCount >= MinAgeForUnload then StartScan; end; + end; end; destructor TBoldUnLoader.Destroy; @@ -177,7 +239,3 @@ destructor TBoldUnLoader.Destroy; end; end. - - - - diff --git a/Source/ObjectSpace/UtilsGUI/BoldComponentValidator.pas b/Source/ObjectSpace/UtilsGUI/BoldComponentValidator.pas index ed0a7e3..8f4d8f5 100644 --- a/Source/ObjectSpace/UtilsGUI/BoldComponentValidator.pas +++ b/Source/ObjectSpace/UtilsGUI/BoldComponentValidator.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldComponentValidator; interface @@ -19,15 +22,18 @@ TBoldComponentValidator = class; { TBoldComponentValidator } TBoldComponentValidator = class + private + fValidateCount: integer; protected - function ValidateOCLComponent(Component: IBoldOCLComponent; Name: String): Boolean; function ValidateValidateableComponent(Component: IBoldValidateableComponent; NamePrefix: String): Boolean; procedure InitializeLog; procedure CompleteLog; public function ValidateComponent(Component: TPersistent; NamePrefix: String = ''; TraverseSubComponents: Boolean = false): Boolean; - function ValidateExpressionInContext(Expression: string; Context: TBoldElementTypeInfo; Name: String): Boolean; + function ValidateExpressionInContext(Expression: string; Context: TBoldElementTypeInfo; Name: String; const VariableList: TBoldExternalVariableList = nil): Boolean; procedure ValidateApplication; + function ValidateOCLComponent(Component: IBoldOCLComponent; Name: String): Boolean; + property ValidateCount: integer read fValidateCount write fValidateCount; end; implementation @@ -35,54 +41,68 @@ implementation uses SysUtils, BoldLogHandler, - BoldEnvironment, - BoldCoreConsts; + BoldDefs, + BoldEnvironment; { TBoldComponentValidator } + function TBoldComponentValidator.ValidateComponent(Component: TPersistent; NamePrefix: String = ''; TraverseSubComponents: Boolean = false): Boolean; var OCLComponent: IBoldOCLComponent; ValidateableComponent: IBoldValidateableComponent; i: integer; + vCounter: integer; + vIsFormOrDataModule: boolean; begin - if BoldEffectiveEnvironment.IsFormOrDataModule(Component) then - BoldLog.LogHeader := Format(sValidatingHeader, [(Component as TComponent).Name]); + vCounter := ValidateCount; + vIsFormOrDataModule := BoldEffectiveEnvironment.IsFormOrDataModule(Component); + if vIsFormOrDataModule then + BoldLog.LogFmt('Validating %s', [(Component as TComponent).Name], ltInfo); result := true; - if Component.GetInterface(IBoldOCLComponent, OCLComponent) then + if Supports(Component, IBoldValidateableComponent, ValidateableComponent) then + result := result and ValidateValidateableComponent(ValidateableComponent, NamePrefix + Component.GetNamePath) + else + if Supports(Component, IBoldOCLComponent, OCLComponent) then result := result and ValidateOCLComponent(OclComponent, NamePrefix + Component.GetNamePath); - if Component.GetInterface(IBoldValidateableComponent, ValidateableComponent) then - result := result and ValidateValidateableComponent(ValidateableComponent, NamePrefix); - if TraverseSubComponents and (Component is TComponent) then for i := 0 to (Component as TComponent).ComponentCount - 1 do result := result and ValidateComponent((Component as TComponent).Components[i], NamePrefix + Component.GetNamePath + '.', TraverseSubComponents); + if vIsFormOrDataModule then + begin + if result then + BoldLog.LogFmt('%s ok, checked %d expressions.', [(Component as TComponent).Name, ValidateCount - vCounter], ltInfo) + else + BoldLog.LogFmt('%s failed, checked %d expressions.', [(Component as TComponent).Name, ValidateCount - vCounter], ltWarning); + end; end; -function TBoldComponentValidator.ValidateExpressionInContext(Expression: string; Context: TBoldElementTypeInfo; Name: String): Boolean; + +function TBoldComponentValidator.ValidateExpressionInContext(Expression: string; Context: TBoldElementTypeInfo; Name: String; const VariableList: TBoldExternalVariableList = nil): Boolean; begin + inc(fValidateCount); result := true; if not assigned(Context) then begin result := false; - BoldLog.LogFmt(sNoContext, [Name]); + BoldLog.LogFmt('No context for %s', [Name], ltWarning); end else begin try - Context.Evaluator.ExpressionType(Expression, Context, true); + Context.Evaluator.ExpressionType(Expression, Context, true, VariableList); except on e: exception do begin result := false; - BoldLog.LogFmt(sValidationError, [Name, e.Message]); + BoldLog.LogFmt('Error in %s: %s', [Name, e.Message], ltError); end; end; + if not Result then + BoldLog.LogFmt('Expression: %s', [Expression], ltWarning); end; - if not Result then - BoldLog.LogFmt(sValidationExpression, [Expression]); end; procedure TBoldComponentValidator.ValidateApplication; @@ -98,9 +118,10 @@ procedure TBoldComponentValidator.ValidateApplication; function TBoldComponentValidator.ValidateOCLComponent(Component: IBoldOCLComponent; Name: String): Boolean; begin - result := ValidateExpressionInContext(Component.Expression, Component.ContextType, Name); + result := ValidateExpressionInContext(Component.Expression, Component.ContextType, Name, Component.VariableList); end; + function TBoldComponentValidator.ValidateValidateableComponent(Component: IBoldValidateableComponent; NamePrefix: String): Boolean; begin result := Component.ValidateComponent(self, NamePrefix); @@ -109,7 +130,7 @@ function TBoldComponentValidator.ValidateValidateableComponent(Component: IBoldV procedure TBoldComponentValidator.InitializeLog; begin BoldLog.Show; - BoldLog.StartLog(sComponentValidation); + BoldLog.StartLog('Component validation'); end; procedure TBoldComponentValidator.CompleteLog; @@ -119,4 +140,5 @@ procedure TBoldComponentValidator.CompleteLog; BoldLog.Show; end; +initialization end. diff --git a/Source/ObjectSpace/UtilsGUI/BoldOCLGraphicRTDebug.pas b/Source/ObjectSpace/UtilsGUI/BoldOCLGraphicRTDebug.pas index c2eb2b5..fef70c6 100644 --- a/Source/ObjectSpace/UtilsGUI/BoldOCLGraphicRTDebug.pas +++ b/Source/ObjectSpace/UtilsGUI/BoldOCLGraphicRTDebug.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldOCLGraphicRTDebug; interface @@ -37,8 +40,7 @@ implementation Controls, Dialogs, BoldOcl, - BoldOclPropEditor, - BoldCoreConsts; + BoldOclPropEditor; function CaseSensitiveIndexOf(Strings: TStrings; Str: String): integer; @@ -61,10 +63,13 @@ function TBoldOclGraphicRTDebugger.AddFixFor(const Ocl: String; Fixform := TBoldOclPropEditForm.Create(nil); fixform.Context := Context; FixForm.OclExpr := ocl; - FixForm.Caption := sIllegalExpressionEncountered; - FixForm.ExpressionPage.Caption := Format(sInComponent, [Componentpath]); -// BoldDeActivateDisplayQueue; - ShowMessage(format(sIncorrectMessage, [ocl, BOLDCRLF, Componentpath, BOLDCRLF, Message, BOLDCRLF, Context.AsString])); + FixForm.Caption := 'Runtime OCL Debugger: Illegal expression encountered, Please try to fix it'; + FixForm.ExpressionPage.Caption := 'In component: ' + Componentpath; + ShowMessage(format( + 'Incorrect OCL-expression: %s' + BOLDCRLF + + 'In Component: %s' + BOLDCRLF + + 'Message: %s' + BOLDCRLF + + 'Context: %s', [ocl, Componentpath, Message, Context.AsString])); if (FixForm.ShowModal = mrOK) and (ocl <> FixForm.OclExpr) then begin @@ -81,7 +86,6 @@ function TBoldOclGraphicRTDebugger.AddFixFor(const Ocl: String; else result := false; BoldOCLRTDebugger := self; -// BoldActivateDisplayQueue; end; function TBoldOclGraphicRTDebugger.GetFixFor(const Ocl: String; @@ -124,8 +128,8 @@ function TBoldOclGraphicRTDebugger.MatchString(Context: TBoldElementTypeInfo; if assigned(Context) then result := Context.AsString + '.' + Ocl else - result := '.' + Ocl; //do not localize + result := '.' + Ocl; end; +initialization end. - diff --git a/Source/ObjectSpace/UtilsGUI/BoldOclPropEditor.pas b/Source/ObjectSpace/UtilsGUI/BoldOclPropEditor.pas index 040e864..badde87 100644 --- a/Source/ObjectSpace/UtilsGUI/BoldOclPropEditor.pas +++ b/Source/ObjectSpace/UtilsGUI/BoldOclPropEditor.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldOclPropEditor; interface @@ -30,7 +33,7 @@ TBoldOclPropEditForm = class(TForm) TabControlPanel: TPanel; ExprEditPageControl: TPageControl; ExpressionPage: TTabSheet; - pnlLeftSide: TPanel; + pnlClient: TPanel; ExpParserPanel: TPanel; EditPanel: TPanel; EditMemo: TMemo; @@ -42,26 +45,35 @@ TBoldOclPropEditForm = class(TForm) PopupMenu1: TPopupMenu; Copymessagestoclipboard1: TMenuItem; ParserMessages: TMemo; - Splitter1: TSplitter; ParserMsg: TLabel; Splitter2: TSplitter; - pnlRightSide: TPanel; - SelectBox: TListBox; - pnlShowTypes: TPanel; - Typescb: TCheckBox; imgModelErrors: TImage; pnlOKCancel: TPanel; btnOK: TButton; btnCancel: TButton; btnShowInfo: TButton; + VariablesPageControl: TPageControl; + OclVariablesTabSheet: TTabSheet; + pnlOclVariables: TPanel; + VariablesListBox: TListBox; + ExpressionTypePageControl: TPageControl; + ExpressionTypeTabSheet: TTabSheet; + pnlRightSide: TPanel; + SelectBox: TListBox; + pnlFilterPersistence: TPanel; + Derivedcb: TCheckBox; + SplitterRight: TSplitter; + SplitterLeft: TSplitter; + filterCombo: TComboBox; + MRUPopupMenu: TPopupMenu; + Persistentcb: TCheckBox; + Transientcb: TCheckBox; procedure SelectBoxDblClick(Sender: TObject); procedure EditMemoEnter(Sender: TObject); procedure SelectBoxKeyPress(Sender: TObject; var Key: Char); procedure EditMemoChange(Sender: TObject); procedure ClearClick(Sender: TObject); procedure RemoveLastClick(Sender: TObject); - procedure SyntaxcbClick(Sender: TObject); - procedure TypescbClick(Sender: TObject); procedure EditMemoMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure EditMemoKeyPress(Sender: TObject; var Key: Char); @@ -76,30 +88,47 @@ TBoldOclPropEditForm = class(TForm) procedure Copymessagestoclipboard1Click(Sender: TObject); procedure imgModelErrorsClick(Sender: TObject); procedure InfoBrowserClick(Sender: TObject); + procedure SyntaxcbClick(Sender: TObject); + procedure FilterClick(Sender: TObject); + procedure filterComboChange(Sender: TObject); + procedure filterComboExit(Sender: TObject); + procedure VariableTypescbClick(Sender: TObject); + procedure FormCreate(Sender: TObject); + procedure FormDestroy(Sender: TObject); private { Private declarations } fContext: TBoldElementTypeInfo; fSystemTypeInfo: TBoldSystemTypeInfo; fOclEvaluator: TBoldOcl; fVariables: TBoldExternalVariableList; + fCompleteSelectList: TStrings; + fMRUExpressionList: TStringList; procedure SetOclExpr(Expr: String); function GetOclExpr: String; procedure SetContext(Context: TBoldElementTypeInfo); procedure SetSelection; procedure CleanParserMsg; procedure MemberHelp(Ocl: String); - Procedure OperationHelp(Ocl: String); + procedure OperationHelp(Ocl: String); + procedure ApplyFilter; + procedure UpdateVariables; function CheckOcl(Ocl: String): TBoldElementTypeInfo; - function GetOclEvaluator:TBoldOcl; + function GetOclEvaluator: TBoldOcl; procedure WMGetMinMaxInfo(Var Msg: TWMGetMinMaxINfo); message WM_GETMINMAXINFO; procedure SetVariables(const Value: TBoldExternalVariableList); + procedure AddExpressionToMRUList; + procedure FetchMRUExpressionList; + procedure MRUPopUpMenuClick(Sender: TObject); + function HasVariables: boolean; + procedure UpdateWidth; + procedure SetOclEvaluator(const Value: TBoldOCL); public { Public declarations } ShowSyntaxErrors: Boolean; - ShowTypes: Boolean; - Property OclEvaluator: TBoldOCL read GetOclEvaluator; + ShowDerived, ShowPersistent, ShowTransient: Boolean; constructor Create(AOwner: TComponent); override; destructor Destroy; override; + property OclEvaluator: TBoldOCL read GetOclEvaluator write SetOclEvaluator; property Context: TBoldElementTypeInfo read fContext write SetContext; property SystemTypeInfo: TBoldSystemTypeInfo read fSystemTypeInfo; property OclExpr: String read GetOclExpr write SetOclExpr; @@ -110,18 +139,22 @@ implementation uses SysUtils, + StrUtils, + BoldUtils, BoldDefs, BoldRegistry, BoldOclError, BoldSystem, - BoldCoreConsts, BoldOclClasses; {$R *.dfm} const - OCLInfoURL = 'http://info.borland.com/techpubs/delphi/boldfordelphi/?Mech_OclAndSubscription.htm'; + OCLInfoURL = 'http://www.boldsoft.com/go/oclinfo'; OCLInfoLocal = 'doc\oclinfo.html'; + cMRUExpressionRegKey = '\MRU'; + cMRUExpressionRegKeyName = 'OCL Expression'; + cHiddenOCLVariables: array[0..3] of string = ('Nil', 'True', 'False', 'TimeStampNow'); type ModeType = (Arrow, Dot, unKnown); @@ -131,51 +164,63 @@ procedure TBoldOclPropEditForm.CleanParserMsg; ParserMessages.lines.clear; end; +procedure TBoldOclPropEditForm.ClearClick(Sender: TObject); +begin + EditMemo.Lines.Clear; + EditMemoChange(Sender) +end; + constructor TBoldOclPropEditForm.Create(AOwner: TComponent); begin inherited; - ExpressionPAge.TabVisible := false; + fCompleteSelectList := TStringList.Create; + ShowDerived := true; + ShowPersistent := true; + ShowTransient := true; ExprEditPageControl.ActivePage := ExpressionPage; SetFocusedControl(EditMemo); - fOclEvaluator := nil; end; -destructor TBoldOclPropEditForm.Destroy; +destructor TBoldOclPropEditForm.destroy; begin - FreeAndNil(fOclEvaluator); + fCompleteSelectList.free; inherited; end; function TBoldOclPropEditForm.GetOclEvaluator; begin - if not assigned(fOclEvaluator) then - fOclEvaluator := TBoldOcl.Create(SystemTypeInfo, nil); result := fOclEvaluator; + if not Assigned(result) and Assigned(SystemTypeInfo) then + result := SystemTypeInfo.Evaluator as TBoldOcl +end; + +procedure TBoldOclPropEditForm.SetOclEvaluator(const Value: TBoldOCL); +begin + fOclEvaluator := Value; end; procedure TBoldOclPropEditForm.SetContext(Context: TBoldElementTypeInfo); -var - OldSystemTypeInfo: TBoldSystemTypeInfo; -// j, i: integer; begin - OldSystemTypeInfo := SystemTypeInfo; fContext := Context; -// ContextCombo.Items.Clear; if assigned(Context) then begin fSystemTypeInfo := Context.SystemTypeInfo as TBoldSystemTypeInfo; - Caption:= 'OCL expression editor - Context: ' + Context.AsString; // do not localize + Caption:= 'OCL expression editor - Context: ' + Context.AsString; end else begin - Caption:= 'OCL expression editor - Context: '; // do not localize + Caption:= 'OCL expression editor - Context: '; CleanParserMsg; - ParserMessages.lines.Add(sNoContextNoSupport); + ParserMessages.lines.Add('No Context, No design support'); end; if (not assigned(SystemTypeInfo)) and (TBoldSystem.DefaultSystem <> nil) then fSystemTypeInfo := TBoldSystem.DefaultSystem.BoldType as tBoldSystemTypeInfo; + filterCombo.ItemIndex := 0; + + UpdateWidth; + { if assigned( Model) then begin @@ -199,12 +244,6 @@ procedure TBoldOclPropEditForm.SetContext(Context: TBoldElementTypeInfo); ContextCombo.ItemIndex := i; } - if OldSystemTypeInfo <> fSystemTypeInfo then - begin - fOclEvaluator.Free; - fOclEvaluator := TBoldOcl.Create(SystemTypeInfo, nil); - end; - EditMemoChange(nil); imgModelErrors.visible := assigned(SystemTypeInfo) and (SystemTypeInfo.InitializationLog.count > 0); end; @@ -213,39 +252,103 @@ procedure TBoldOclPropEditForm.SetOclExpr(Expr: String); var i: integer; begin - while Expr <> '' do - begin - if pos(BOLDCR, Expr) = 0 then - begin - EditMemo.Lines.Add(Expr); - Expr := ''; - end - else - begin - EditMemo.Lines.Add(copy(Expr, 1, pos(BOLDCR, Expr))); - Delete(Expr, 1, pos(BOLDCR, Expr)); - end; - end; -// EditMemo.Text := EditMemo.Text + ' '; + EditMemo.Text := Expr; i := Length(EditMemo.Text); EditMemo.SelStart := i - 2; EditMemoChange(nil); end; function TBoldOclPropEditForm.GetOclExpr: String; +begin + result := EditMemo.Text; +end; + +function TBoldOclPropEditForm.HasVariables: boolean; +begin + result := (Assigned(fVariables) and (fVariables.count > 0)) or (Assigned(OclEvaluator) and (OclEvaluator.VariableCount > Length(cHiddenOCLVariables))); +end; + +procedure TBoldOclPropEditForm.AddExpressionToMRUList; +var + lRegistry: TBoldRegistry; +begin + if fMRUExpressionList.IndexOf(EditMemo.Text) = -1 then + begin + lRegistry := TBoldRegistry.Create; + try + fMRUExpressionList.insert(0, EditMemo.Text); + if fMRUExpressionList.Count > 10 then + begin + fMRUExpressionList.Delete(10); + end; + if lRegistry.OpenKey(cMRUExpressionRegKey) then + begin + lRegistry.WriteString(cMRUExpressionRegKeyName, fMRUExpressionList.CommaText); + lRegistry.CloseKey; + end; + finally + lRegistry.free; + end; + end; +end; + +type + TFilterType = (ftAll, ftAttribute, ftSingleLink, ftMultilink, ftOperation, ftType, ftText); + +procedure TBoldOclPropEditForm.ApplyFilter; + + function ExtractFilterType(const AString: string): TFilterType; + var + c: char; + begin + result := ftAll; + if (copy(AString, 3,1) = '|') and (Length(AString) > 4) then + begin + c := AString[1]; + case c of + '1': result := ftAttribute; + '2': result := ftSingleLink; + '3': result := ftMultiLink; + '4': result := ftType; + '5': result := ftOperation; + end; + end; + end; + var i: integer; + vElementType: TFilterType; + vFilterType: TFilterType; + vInclude: boolean; + vFilterText: string; begin - with EditMemo do + case filterCombo.ItemIndex of + -1: vFilterType := ftText; + Ord(ftAttribute)..Ord(ftType): vFilterType := TFilterType(filterCombo.ItemIndex); + else + vFilterType := ftAll; + end; + vFilterText := Trim(FilterCombo.Text); + + for I := 0 to fCompleteSelectList.Count - 1 do begin - result := ''; - For i := 0 to Lines.Count - 1 do - Result := Result + Lines[i] + BOLDCR; + vInclude := vFilterType = ftAll; + if vFilterType <> ftAll then + begin + vElementType := ExtractFilterType(fCompleteSelectList[i]); + case vFilterType of + ftAll: vInclude := true; + ftAttribute..ftOperation: vInclude := vElementType = vFilterType; + ftType: vInclude := true; + ftText: vInclude := (vFilterText = '') or AnsiContainsText(Copy(fCompleteSelectList[i], 5, MaxInt), vFilterText); + end; + end; + if vInclude then + SelectBox.Items.Add(fCompleteSelectList[i]); end; - Delete(result, length(result), 1); end; -function TBoldOClPropEditForm.CheckOcl(Ocl: String): TBoldElementTypeInfo; +function TBoldOclPropEditForm.CheckOcl(Ocl: String): TBoldElementTypeInfo; procedure ShowError(Ocl: String; ErrorPointer: String; message: string); var @@ -265,7 +368,7 @@ function TBoldOClPropEditForm.CheckOcl(Ocl: String): TBoldElementTypeInfo; insert('-------', errorPointer, length(ErrorPointer)); end else ErrorPointer := ErrorPointer + '-------'; - + ParserMessages.lines.Insert(i+1, ErrorPointer); end; @@ -275,7 +378,7 @@ function TBoldOClPropEditForm.CheckOcl(Ocl: String): TBoldElementTypeInfo; if Ocl = '' then begin Result := Context; - ParserMessages.lines.Add(sEmptyExpression); + ParserMessages.lines.Add('Empty Expression'); exit; end; @@ -286,12 +389,12 @@ function TBoldOClPropEditForm.CheckOcl(Ocl: String): TBoldElementTypeInfo; begin Result := nil; ParserMessages.lines.BeginUpdate; - if (Pos('SSYacc', e.Message) > 0) or (Pos('SSLex', e.Message) > 0) then // do not localize + if (Pos('SSYacc', e.Message) > 0) or (Pos('SSLex', e.Message) > 0) then begin if ShowSyntaxErrors then ShowError(e.Ocl, e.ErrorPointer, e.Message) else - ParserMessages.lines.add(sSyntaxError); + ParserMessages.lines.add('Unable to complete parse, syntax error'); end else ShowError(e.Ocl, e.ErrorPointer, e.Message); ParserMessages.lines.EndUpdate; @@ -300,7 +403,7 @@ function TBoldOClPropEditForm.CheckOcl(Ocl: String): TBoldElementTypeInfo; on e: EBoldOclInternalError do begin Result := nil; - e.Ocl := 'Internal Error: ' + e.ocl; // do not localize + e.Ocl := 'Internal Error: ' + e.ocl; ShowError(e.Ocl, e.ErrorPointer, e.Message); exit; end; @@ -318,12 +421,12 @@ function TBoldOClPropEditForm.CheckOcl(Ocl: String): TBoldElementTypeInfo; end; end; ParserMessages.lines.BeginUpdate; - ParserMessages.lines.Add(sSyntaxOK); + ParserMessages.lines.Add('Syntax is OK'); ParserMessages.lines.Add(''); if assigned(result) then - ParserMessages.lines.Add(Format(sCurrentTypeIsX, [Result.AsString])) + ParserMessages.lines.Add('Current type is: ' + Result.AsString) else - ParserMessages.lines.Add(sCurrentTypeIsUnknown); + ParserMessages.lines.Add('Current type is: unknown'); ParserMessages.SelStart := 0; ParserMessages.SelLength := 0; ParserMessages.lines.EndUpdate; @@ -353,10 +456,10 @@ procedure TBoldOclPropEditForm.OperationHelp(Ocl: String); if (not Assigned(Symbol.FormalArguments[0]) or ExpressionType.ConformsTo(Symbol.formalArguments[0]) or ((ExpressionType is TBoldListTypeInfo) and - assigned(TBoldListTypeInfo(ExpressionType).ListElementTypeInfo) and + assigned(TBoldListTypeInfo(ExpressionType).ListElementTypeInfo) and TBoldListTypeInfo(ExpressionType).ListElementTypeInfo.ConformsTo(Symbol.FormalArguments[0]))) and symbol.IsPostFix then begin - Addition := 'O | ' + prefix[Symbol.IsDotNotation] + Symbol.SymbolName; // do not localize + Addition := '5 | ' + prefix[Symbol.IsDotNotation] + Symbol.SymbolName; if Symbol.NumberofArgs > 1 then begin Addition := Addition + '('; @@ -367,24 +470,51 @@ procedure TBoldOclPropEditForm.OperationHelp(Ocl: String); begin ListExprType := Symbol.FormalArguments[j] as TBoldListTypeInfo; if Assigned(LIstExprType.ListElementTypeInfo) then - Addition := Addition + '«List<' + (Symbol.FormalArguments[j] as TBoldListTypeInfo).ListElementTypeInfo.ExpressionName + '>»,' // do not localize + Addition := Addition + '«List<' + (Symbol.FormalArguments[j] as TBoldListTypeInfo).ListElementTypeInfo.ExpressionName + '>»,' else - Addition := Addition + '«List»,' // do not localize // do not localize + Addition := Addition + '«List»,' end else Addition := Addition + '«' + Symbol.FormalArguments[j].ExpressionName + '»,' end else - Addition := Addition + '«AnyArg»,'; // do not localize + Addition := Addition + '«AnyArg»,'; Delete(Addition, Length(Addition), 1); Addition := Addition + ')'; end; - SelectBox.Items.AddObject(Addition + ' ', Symbol); + if Assigned(Symbol.ResultType) then + fCompleteSelectList.AddObject(Addition + ' : ' + Symbol.ResultType.ExpressionName , Symbol) + else + fCompleteSelectList.AddObject(Addition + ' ', Symbol); end; end; end; end; +procedure TBoldOclPropEditForm.RemoveLastClick(Sender: TObject); +var + line: string; +procedure RemovePrefix; +begin + if line = '' then + exit; + if line[length(line)] = '.' then + delete(line, length(line), 1) + else if Copy(line, Length(line) - 1, 2) = '->' then + delete(line, length(line) - 1, 2); +end; + +begin + Line := trim(EditMemo.Text); + if Line = '' then exit; + while (line <> '') and + (not CharInSet(line[length(line)], ['.', ' ']) and + (Copy(line, Length(line) - 1, 2) <> '->')) do + delete(line, length(line), 1); + RemovePrefix; + Editmemo.Text := trim(Line); +end; + procedure TBoldOclPropEditForm.MemberHelp(Ocl: String); const prefix: array[false..true] of string = ('', '.'); @@ -392,6 +522,7 @@ procedure TBoldOclPropEditForm.MemberHelp(Ocl: String); I: Integer; ClassInfo: TBoldClasstypeInfo; SystemInfo: TBoldSystemtypeInfo; + Member: TBoldMemberRTInfo; ExpressionType: TBoldElementTypeInfo; Attr: TBoldAttributeRTInfo; Role: TBoldRoleRTInfo; @@ -408,53 +539,64 @@ procedure TBoldOclPropEditForm.MemberHelp(Ocl: String); begin ClassInfo := ExpressionType as TBoldClasstypeInfo; for I := 0 to ClassInfo.AllMembers.Count - 1 do + begin + Member := ClassInfo.AllMembers[I]; + if not ShowDerived and Member.IsDerived then continue; + if not ShowPersistent and Member.Persistent then continue; + if not ShowTransient and not (Member.Persistent or Member.IsDerived) then continue; if ClassInfo.AllMembers[I] is TBoldAttributeRTInfo then begin Attr := ClassInfo.AllMembers[I] as TBoldAttributeRTInfo; - Exprname := 'M | ' + Prefix[ocl <> ''] + Attr.ExpressionName; // do not localize - if ShowTypes then - SelectBox.Items.Add(Exprname + ': ' + Attr.BoldType.ExpressionName) - else - SelectBox.Items.Add(Exprname + ' '); + Exprname := '1 | ' + Prefix[ocl <> ''] + Attr.ExpressionName; + fCompleteSelectList.Add(Exprname + ': ' + Attr.BoldType.ExpressionName) end else if ClassInfo.AllMembers[I] is TBoldRoleRTInfo then begin Role := ClassInfo.AllMembers[I] as TBoldRoleRTInfo; if role.IsNavigable then begin - Exprname := 'A | ' + Prefix[ocl <> ''] + Role.ExpressionName; // do not localize - if ShowTypes then - begin - if role.IsMultiRole then - SelectBox.Items.Add(ExprName + ': List<' + Role.ClassTypeInfoOfOtherEnd.Expressionname + '>') // do not localize // do not localize - else - SelectBox.Items.Add(ExprName + ': ' + Role.ClassTypeInfoOfOtherEnd.Expressionname) - end + if role.IsMultiRole then + Exprname := '3 | ' + Prefix[ocl <> ''] + Role.ExpressionName else - SelectBox.Items.Add(ExprName + ' '); + Exprname := '2 | ' + Prefix[ocl <> ''] + Role.ExpressionName; + if role.IsMultiRole then + fCompleteSelectList.Add(ExprName + ': List<' + Role.ClassTypeInfoOfOtherEnd.Expressionname + '>') + else + fCompleteSelectList.Add(ExprName + ': ' + Role.ClassTypeInfoOfOtherEnd.Expressionname) end; end; + end; end else if ExpressionType is TBoldSystemTypeInfo then begin SystemInfo := ExpressionType as TBoldSystemTypeInfo; for i := 0 to SystemInfo.TopSortedClasses.Count - 1 do with SystemInfo.TopSortedClasses[i] do - if ShowTypes then - SelectBox.Items.Add('C | ' + ExpressionName + ': ' + DelphiName) // do not localize - else - SelectBox.Items.Add('C | ' + ExpressionName + ' '); // do not localize + fCompleteSelectList.Add('4 | ' + ExpressionName + ': ' + DelphiName); end; end; +procedure TBoldOclPropEditForm.MRUPopUpMenuClick(Sender: TObject); +var + lMenuItem: TMenuItem; +begin + lMenuItem := (Sender as TMenuItem); + EditMemo.Text := fMRUExpressionList[lMenuItem.Parent.IndexOf(lMenuItem)]; +end; + procedure TBoldOclPropEditForm.SelectBoxDblClick(Sender: TObject); var Addition: String; + vListBox: TListBox; begin if not assigned(Context) then exit; - if SelectBox.ItemIndex = -1 then - SelectBox.ItemIndex := 0; - Addition := SelectBox.Items[SelectBox.ItemIndex]; + if not(Sender is TListBox) then + exit; + + vListBox := Sender as TListBox; + if vListBox.ItemIndex = -1 then + vListBox.ItemIndex := 0; + Addition := vListBox.Items[vListBox.ItemIndex]; if pos(' | ', Addition) <> 0 then Delete(Addition, 1, Pos(' | ', Addition) + 2); @@ -468,12 +610,14 @@ procedure TBoldOclPropEditForm.SelectBoxDblClick(Sender: TObject); EditMemo.Lines[EditMemo.Lines.Count - 1] + Addition; + if filterCombo.ItemIndex = -1 then + filterCombo.Clear; + EditMemoChange(Sender); end; procedure TBoldOclPropEditForm.EditMemoEnter(Sender: TObject); begin -// Context := DefaultBoldSystem.BoldSystemRtInfo; EditMemoChange(Sender); end; @@ -496,9 +640,21 @@ procedure TBoldOclPropEditForm.EditMemoChange(Sender: TObject); } Ocl := trim(EditMemo.Text); - SelectBox.Items.Clear; - MemberHelp(Ocl); - OperationHelp(Ocl); + VariablesListBox.Items.BeginUpdate; + SelectBox.Items.BeginUpdate; + fCompleteSelectList.BeginUpdate; + try + SelectBox.Clear; + fCompleteSelectList.Clear; + MemberHelp(Ocl); + OperationHelp(Ocl); + ApplyFilter; + UpdateVariables; + finally + VariablesListBox.Items.EndUpdate; + SelectBox.Items.EndUpdate; + fCompleteSelectList.EndUpdate; + end; { if Ocl = '' then begin @@ -517,55 +673,99 @@ procedure TBoldOclPropEditForm.EditMemoChange(Sender: TObject); } end; -procedure TBoldOclPropEditForm.ClearClick(Sender: TObject); +procedure TBoldOclPropEditForm.SyntaxcbClick(Sender: TObject); begin - EditMemo.Lines.Clear; - EditMemoChange(Sender) + ShowSyntaxErrors := syntaxcb.Checked; + EditMemoChange(Sender); end; -procedure TBoldOclPropEditForm.RemoveLastClick(Sender: TObject); +procedure TBoldOclPropEditForm.FilterClick(Sender: TObject); var - line: string; - -procedure RemovePrefix; + OldIndex: Integer; + OldTop: Integer; begin - if line = '' then - exit; - if line[length(line)] = '.' then - delete(line, length(line), 1) - else if Copy(line, Length(line) - 1, 2) = '->' then - delete(line, length(line) - 1, 2); + OldIndex := SelectBox.ItemIndex; + OldTop := SelectBox.TopIndex; + ShowDerived := Derivedcb.Checked; + ShowPersistent := Persistentcb.Checked; + ShowTransient := Transientcb.Checked; + EditMemoChange(Sender); + SelectBox.ItemIndex := OldIndex; + SelectBox.TopIndex := OldTop; end; +procedure TBoldOclPropEditForm.UpdateVariables; + + procedure AddVariable(const AName: string; AValueType: TBoldElementTypeInfo); + var + s: string; + begin + if not Assigned(AValueType) then + begin + VariablesListBox.Items.Add('5 | ' + AName + ': ' + 'Nil'); + exit; + end; + if AValueType is TBoldListTypeInfo then + s := '3 | ' + else + if AValueType is TBoldAttributeTypeInfo then + s := '1 | ' + else + if AValueType is TBoldClassTypeInfo then + s := '2 | ' + else + if AValueType is TBoldSystemTypeInfo then + s := '4 | ' + else + if AValueType is TBoldTypeTypeInfo then + s := '5 | ' + else + Assert(False, 'Unhandled ValueType: ' + AValueType.ClassName); + s := s + AName + ': ' + AValueType.ExpressionName; +// if VariablesListBox.Items.IndexOf(s) = -1 then + VariablesListBox.Items.Add(s); + end; + +var + i: integer; begin - // rewrite this entire procedure... - Line := trim(EditMemo.Text); - if Line = '' then exit; - while (line <> '') and - (not (line[length(line)] in ['.', ' ']) and - (Copy(line, Length(line) - 1, 2) <> '->')) do - delete(line, length(line), 1); - RemovePrefix; - Editmemo.Text := trim(Line); + VariablesPageControl.Visible := HasVariables; + VariablesListBox.Items.BeginUpdate; + VariablesListBox.Clear; + try + if Assigned(fVariables) then + for I := 0 to Variables.Count - 1 do + AddVariable(Variables[i].Name, Variables[i].ValueType); + for i := 0 to OclEvaluator.VariableCount - 1 do + with OclEvaluator.Variables[i] as TBoldOCLVariableBinding do + if AnsiIndexText(VariableName, cHiddenOCLVariables) = -1 then + AddVariable(VariableName, BoldType); + finally + VariablesListBox.Items.EndUpdate; + end; end; -procedure TBoldOclPropEditForm.SyntaxcbClick(Sender: TObject); +procedure TBoldOclPropEditForm.UpdateWidth; begin - ShowSyntaxErrors := syntaxcb.Checked; - EditMemoChange(Sender); + if not visible then + begin + if HasVariables then + Width := 900 + else + Width := 720; + end; end; -procedure TBoldOclPropEditForm.TypescbClick(Sender: TObject); +procedure TBoldOclPropEditForm.VariableTypescbClick(Sender: TObject); var OldIndex: Integer; OldTop: Integer; begin - OldIndex := SelectBox.ItemIndex; - OldTop := SelectBox.TopIndex; - ShowTypes := Typescb.checked; + OldIndex := VariablesListBox.ItemIndex; + OldTop := VariablesListBox.TopIndex; EditMemoChange(Sender); - SelectBox.ItemIndex := OldIndex; - SelectBox.TopIndex := OldTop; + VariablesListBox.ItemIndex := OldIndex; + VariablesListBox.TopIndex := OldTop; end; procedure TBoldOclPropEditForm.SetSelection; @@ -575,14 +775,14 @@ procedure TBoldOclPropEditForm.SetSelection; if EditMemo.SelLength = 0 then begin i := EditMemo.SelStart; - while (i > 0) and not (EditMemo.Text[i] in ['«', '»']) do + while (i > 0) and not CharInSet(EditMemo.Text[i], ['«', '»']) do dec(i); if (i = 0)or (EditMemo.Text[i] = '»') then exit; j := i + 1; - while (j <= Length(EditMemo.Text)) and not (EditMemo.Text[j] in ['«', '»']) do + while (j <= Length(EditMemo.Text)) and not CharInSet(EditMemo.Text[j], ['«', '»']) do Inc(j); if (j > Length(EditMemo.Text)) or (EditMemo.Text[j] = '«') then @@ -599,6 +799,56 @@ procedure TBoldOclPropEditForm.EditMemoMouseDown(Sender: TObject; SetSelection; end; +procedure TBoldOclPropEditForm.FetchMRUExpressionList; +var + lRegistry: TBoldRegistry; + lIndex: Integer; + lMenuItem: TMenuItem; +begin + lRegistry := TBoldRegistry.Create; + try + if lRegistry.OpenKey(cMRUExpressionRegKey) then + begin + fMRUExpressionList.CommaText := lRegistry.ReadString(cMRUExpressionRegKeyName, ''); + lRegistry.CloseKey; + end; + finally + lRegistry.free; + end; + for lIndex := 0 to fMRUExpressionList.Count - 1 do + begin + lMenuItem := TMenuItem.Create(Self); + lMenuItem.Caption := '&' + IntToStr(lIndex+1) + ': ' + fMRUExpressionList[lIndex]; + lMenuItem.OnClick := MRUPopUpMenuClick; + MRUPopupMenu.Items.Add(lMenuItem); + end; +end; + +procedure TBoldOclPropEditForm.filterComboChange(Sender: TObject); +begin + EditMemoChange(Sender); +end; + +procedure TBoldOclPropEditForm.filterComboExit(Sender: TObject); +begin + if (FilterCombo.ItemIndex = -1) and (FilterCombo.Text = '') then + begin + FilterCombo.ItemIndex := 0; + EditMemoChange(Sender); + end; +end; + +procedure TBoldOclPropEditForm.FormCreate(Sender: TObject); +begin + fMRUExpressionList := TStringList.Create; + FetchMRUExpressionList; +end; + +procedure TBoldOclPropEditForm.FormDestroy(Sender: TObject); +begin + fMRUExpressionList.free; +end; + procedure TBoldOclPropEditForm.EditMemoKeyPress(Sender: TObject; var Key: Char); begin SetSelection; @@ -609,6 +859,7 @@ procedure TBoldOclPropEditForm.EditMemoKeyPress(Sender: TObject; var Key: Char); procedure TBoldOclPropEditForm.OKClick(Sender: TObject); begin Modalresult := mrOK; + AddExpressionToMRUList; end; procedure TBoldOclPropEditForm.CancelClick(Sender: TObject); @@ -678,22 +929,59 @@ procedure TBoldOclPropEditForm.ContextComboChange(Sender: TObject); procedure TBoldOclPropEditForm.SelectBoxDrawItem(Control: TWinControl; Index: Integer; Rect: TRect; State: TOwnerDrawState); var StringfromSelect: String; + s: string; + r: TRect; + vXOffset: integer; begin with (Control as TListBox) do begin Canvas.FillRect(Rect); StringFromSelect := (Control as TListBox).items[Index]; case StringFromSelect[1] of - 'M': ImageList1.Draw(Canvas, Rect.Left + 2, Rect.Top, 0); //Member - 'C': ImageList1.Draw(Canvas, Rect.Left + 2, Rect.Top, 1); //Class - 'A': ImageList1.Draw(Canvas, Rect.Left + 2, Rect.Top, 2); //Assoc/role - 'E': ImageList1.Draw(Canvas, Rect.Left + 2, Rect.Top, 3); //Method - 'O': ImageList1.Draw(Canvas, Rect.Left + 2, Rect.Top, 4); //Operation (OCL) + '1': ImageList1.Draw(Canvas, Rect.Left + 2, Rect.Top, 0); + '2': ImageList1.Draw(Canvas, Rect.Left + 2, Rect.Top, 2); + '3': ImageList1.Draw(Canvas, Rect.Left + 2, Rect.Top, 3); + '4': ImageList1.Draw(Canvas, Rect.Left + 2, Rect.Top, 1); + '5': ImageList1.Draw(Canvas, Rect.Left + 2, Rect.Top, 4); end; if pos(' | ', StringFromSelect) <> 0 then Delete(StringFromSelect, 1, Pos(' | ', StringFromSelect) + 2); - Canvas.TextOut(ImageList1.Width + Rect.Left + 2, Rect.Top, StringfromSelect); + vXOffset := 2 + ImageList1.Width; + if not ((odFocused in State) or (odSelected in State)) then + begin + s := StringFromSelect; + + if pos(':', s) <> 0 then + Delete(s, Pos(':', s), MaxInt); + + if pos(' ', s) <> 0 then + Delete(s, Pos(' ', s), MaxInt); + + if pos('(', s) <> 0 then + Delete(s, Pos('(', s), MaxInt); + + r := Rect; + r.Left := r.Left + vXOffset; + Canvas.Font.Color := clBlack; + DrawText(Canvas.Handle, + PChar(S), + Length(S), + r, + DT_LEFT or DT_WORDBREAK or DT_CALCRECT); + + DrawText(Canvas.Handle, + PChar(S), + Length(S), + r, + DT_LEFT or DT_WORDBREAK); + + vXOffset := r.Right; + Canvas.Font.Color := $00A0A0A0;; + StringFromSelect := Copy(StringfromSelect, Length(s)+1, MaxInt); + end; + + Canvas.TextOut(Rect.Left + vXOffset, Rect.Top, StringFromSelect); end; end; @@ -728,6 +1016,7 @@ procedure TBoldOclPropEditForm.SetVariables(const Value: TBoldExternalVariableLi begin fVariables := Value; EditMemoChange(nil); + UpdateWidth; end; procedure TBoldOclPropEditForm.Copymessagestoclipboard1Click(Sender: TObject); @@ -735,19 +1024,20 @@ procedure TBoldOclPropEditForm.Copymessagestoclipboard1Click(Sender: TObject); s: string; begin if Assigned(Context) then - s := 'Context: ' + Context.ExpressionName + BOLDCRLF // do not localize + s := 'Context: ' + Context.ExpressionName + BOLDCRLF else s := ''; ClipBoard.AsText := s + - 'OCL Expression: ' + BOLDCRLF + // do not localize + 'OCL Expression: ' + BOLDCRLF + EditMemo.Text + BOLDCRLF + BOLDCRLF + - 'Parser messages: ' + BOLDCRLF + // do not localize + 'Parser messages: ' + BOLDCRLF + ParserMessages.lines.text; + end; procedure TBoldOclPropEditForm.imgModelErrorsClick(Sender: TObject); begin - Showmessage(Format(sModelContainsErrors, [BoldCRLF, BoldCRLF, SystemTypeInfo.InitializationLog.text])); + Showmessage('The model contains errors: ' + BoldCRLF + BoldCRLF+ SystemTypeInfo.InitializationLog.text); end; procedure TBoldOclPropEditForm.InfoBrowserClick(Sender: TObject); @@ -759,7 +1049,9 @@ procedure TBoldOclPropEditForm.InfoBrowserClick(Sender: TObject); else URL := OCLInfoURL; - ShellExecute(0, 'open', PChar(URL), '', '', SW_SHOWMAXIMIZED); // do not localize + ShellExecute(0, 'open', PChar(URL), '', '', SW_SHOWMAXIMIZED); end; +initialization + end. diff --git a/Source/ObjectSpace/UtilsGUI/BoldTypeNameSelector.dfm b/Source/ObjectSpace/UtilsGUI/BoldTypeNameSelector.dfm index d7a94e3..16482fb 100644 --- a/Source/ObjectSpace/UtilsGUI/BoldTypeNameSelector.dfm +++ b/Source/ObjectSpace/UtilsGUI/BoldTypeNameSelector.dfm @@ -56,8 +56,6 @@ object frmBoldTypeNameSelector: TfrmBoldTypeNameSelector TabOrder = 0 OnChange = tvMetaTypesChange OnDblClick = tvMetaTypesDblClick - ExplicitWidth = 344 - ExplicitHeight = 288 end object pnButtons: TPanel Left = 0 @@ -67,8 +65,6 @@ object frmBoldTypeNameSelector: TfrmBoldTypeNameSelector Align = alBottom BevelOuter = bvNone TabOrder = 1 - ExplicitTop = 288 - ExplicitWidth = 344 DesignSize = ( 336 40) @@ -100,7 +96,7 @@ object frmBoldTypeNameSelector: TfrmBoldTypeNameSelector Left = 228 Top = 164 Bitmap = { - 494C010101000400080010001000FFFFFFFFFF10FFFFFFFFFFFFFFFF424D3600 + 494C010101000400040010001000FFFFFFFFFF10FFFFFFFFFFFFFFFF424D3600 0000000000003600000028000000400000001000000001002000000000000010 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 diff --git a/Source/ObjectSpace/UtilsGUI/BoldTypeNameSelector.pas b/Source/ObjectSpace/UtilsGUI/BoldTypeNameSelector.pas index 988ad85..d1d7277 100644 --- a/Source/ObjectSpace/UtilsGUI/BoldTypeNameSelector.pas +++ b/Source/ObjectSpace/UtilsGUI/BoldTypeNameSelector.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldTypeNameSelector; interface @@ -12,7 +15,7 @@ interface StdCtrls, BoldSystemRT, BoldElements, - ImgList, Menus; + ImgList, Menus, System.ImageList; type TNodeType = (ntClass, ntClasses, ntAttributes, ntList, ntAttribute, ntClassList, @@ -48,7 +51,6 @@ implementation BoldUtils; {$R *.dfm} -{.$R BoldTypeNameSelector.res} { TfrmBoldTypeNameSelector } @@ -66,16 +68,16 @@ function TfrmBoldTypeNameSelector.Select(var StringValue: String; SystemTypeInfo procedure TfrmBoldTypeNameSelector.FormCreate(Sender: TObject); begin - ilImages.GetInstRes(HInstance, rtBitmap, 'SMALLUMLMODELROOTBITMAP', 16, [], clWhite); // do not localize - ilImages.GetInstRes(HInstance, rtBitmap, 'SMALLUMLCLASSBITMAP', 16, [], clWhite); // do not localize - ilImages.GetInstRes(HInstance, rtBitmap, 'SMALLUMLCLASSESBITMAP', 16, [], clWhite); // do not localize - ilImages.GetInstRes(HInstance, rtBitmap, 'SMALLUMLATTRIBUTEBITMAP', 16, [], clWhite); // do not localize - ilImages.GetInstRes(HInstance, rtBitmap, 'SMALLUMLATTRIBUTESBITMAP', 16, [], clWhite); // do not localize - ilImages.GetInstRes(HInstance, rtBitmap, 'SMALLLISTBITMAP', 16, [], clWhite); // do not localize - ilImages.GetInstRes(HInstance, rtBitmap, 'SMALLUMLCLASSLISTBITMAP', 16, [], clWhite); // do not localize - ilImages.GetInstRes(HInstance, rtBitmap, 'SMALLUMLATTRIBUTELISTBITMAP', 16, [], clWhite); // do not localize - ilImages.GetInstRes(HInstance, rtBitmap, 'SMALLSYSTEMBITMAP', 16, [], clWhite); // do not localize - ilImages.GetInstRes(HInstance, rtBitmap, 'SMALLTYPEBITMAP', 16, [], clWhite); // do not localize + ilImages.GetInstRes(HInstance, rtBitmap, 'SMALLUMLMODELROOTBITMAP', 16, [], clWhite); + ilImages.GetInstRes(HInstance, rtBitmap, 'SMALLUMLCLASSBITMAP', 16, [], clWhite); + ilImages.GetInstRes(HInstance, rtBitmap, 'SMALLUMLCLASSESBITMAP', 16, [], clWhite); + ilImages.GetInstRes(HInstance, rtBitmap, 'SMALLUMLATTRIBUTEBITMAP', 16, [], clWhite); + ilImages.GetInstRes(HInstance, rtBitmap, 'SMALLUMLATTRIBUTESBITMAP', 16, [], clWhite); + ilImages.GetInstRes(HInstance, rtBitmap, 'SMALLLISTBITMAP', 16, [], clWhite); + ilImages.GetInstRes(HInstance, rtBitmap, 'SMALLUMLCLASSLISTBITMAP', 16, [], clWhite); + ilImages.GetInstRes(HInstance, rtBitmap, 'SMALLUMLATTRIBUTELISTBITMAP', 16, [], clWhite); + ilImages.GetInstRes(HInstance, rtBitmap, 'SMALLSYSTEMBITMAP', 16, [], clWhite); + ilImages.GetInstRes(HInstance, rtBitmap, 'SMALLTYPEBITMAP', 16, [], clWhite); end; procedure TfrmBoldTypeNameSelector.GenerateNodes( @@ -85,96 +87,89 @@ procedure TfrmBoldTypeNameSelector.GenerateNodes( begin with tvMetaTypes do begin - // add the root node - Node := Items.AddObject(nil, 'Types in the system', nil); // do not localize - SetImageIndex(Node, ntRoot); + Items.BeginUpdate; + try + Node := Items.AddObject(nil, 'Types in the system', nil); + SetImageIndex(Node, ntRoot); - if bvtClass in ApprovedTypes then - begin - if SystemTypeInfo.TopSortedClasses.Count > 0 then + if bvtClass in ApprovedTypes then begin - // add the classes root node - Node2 := Items.AddChildObject(Node, 'Classes', nil); // do not localize - SetImageIndex(Node2, ntClasses); - // add the classes - for Index := 0 to SystemTypeInfo.TopSortedClasses.Count - 1 do + if SystemTypeInfo.TopSortedClasses.Count > 0 then begin - with SystemTypeInfo.TopSortedClasses[Index] do + Node2 := Items.AddChildObject(Node, 'Classes', nil); + SetImageIndex(Node2, ntClasses); + for Index := 0 to SystemTypeInfo.TopSortedClasses.Count - 1 do begin - Node := Items.AddChildObject(Node2, ExpressionName, Pointer(SystemTypeInfo.TopSortedClasses[Index])); - SetImageIndex(Node, ntClass); - SelectCurrentNode(CurrentStringValue, Node); + with SystemTypeInfo.TopSortedClasses[Index] do + begin + Node := Items.AddChildObject(Node2, ExpressionName, Pointer(SystemTypeInfo.TopSortedClasses[Index])); + SetImageIndex(Node, ntClass); + SelectCurrentNode(CurrentStringValue, Node); + end; end; + Node2.AlphaSort; end; - Node2.AlphaSort; end; - end; - - if bvtList in ApprovedTypes then - begin - // add the list root node - Node2 := Items.GetFirstNode; - ListRoot := Items.AddChildObject(Node2, 'Lists', nil); // do not localize - SetImageIndex(ListRoot, ntList); - // add the class list root node - Node2 := Items.AddChildObject(ListRoot, 'Class lists', nil); // do not localize - SetImageIndex(Node2, ntClassLists); - // add the class list nodes - for Index := 0 to SystemTypeInfo.TopSortedClasses.Count - 1 do + if bvtList in ApprovedTypes then begin - Node := Items.AddChildObject(Node2, SystemTypeInfo.ListTypeInfoByElement[SystemTypeInfo.TopSortedClasses[Index]].ExpressionName, Pointer(SystemTypeInfo.ListTypeInfoByElement[SystemTypeInfo.TopSortedClasses[Index]])); - SetImageIndex(Node, ntClassList); - SelectCurrentNode(CurrentStringValue, Node); - end; - Node2.AlphaSort; + Node2 := Items.GetFirstNode; + ListRoot := Items.AddChildObject(Node2, 'Lists', nil); + SetImageIndex(ListRoot, ntList); + Node2 := Items.AddChildObject(ListRoot, 'Class lists', nil); + SetImageIndex(Node2, ntClassLists); + for Index := 0 to SystemTypeInfo.TopSortedClasses.Count - 1 do + begin + Node := Items.AddChildObject(Node2, SystemTypeInfo.TopSortedClasses[Index].ListTypeInfo.ExpressionName, Pointer(SystemTypeInfo.TopSortedClasses[Index].ListTypeInfo)); + SetImageIndex(Node, ntClassList); + SelectCurrentNode(CurrentStringValue, Node); + end; + Node2.AlphaSort; + Node2 := Items.AddChildObject(ListRoot, 'Attribute lists', nil); + SetImageIndex(Node2, ntAttributeLists); + for Index := 0 to SystemTypeInfo.AttributeTypes.Count - 1 do + begin - // add the attribute list root node - Node2 := Items.AddChildObject(ListRoot, 'Attribute lists', nil); // do not localize - SetImageIndex(Node2, ntAttributeLists); + Node := Items.AddChildObject(Node2, SystemTypeInfo.AttributeTypes[Index].ListTypeInfo.ExpressionName, Pointer(SystemTypeInfo.AttributeTypes[Index].ListTypeInfo)); + SetImageIndex(Node, ntAttributeList); + SelectCurrentNode(CurrentStringValue, Node); + end; + Node2.AlphaSort; + end; - // add the attribute list nodes - for Index := 0 to SystemTypeInfo.AttributeTypes.Count - 1 do + if bvtAttr in ApprovedTypes then begin - Node := Items.AddChildObject(Node2, SystemTypeInfo.ListTypeInfoByElement[SystemTypeInfo.AttributeTypes[Index]].ExpressionName, Pointer(SystemTypeInfo.ListTypeInfoByElement[SystemTypeInfo.AttributeTypes[Index]])); - SetImageIndex(Node, ntAttributeList); - SelectCurrentNode(CurrentStringValue, Node); + Node := Items.GetFirstNode; + Node2 := Items.AddChildObject(Node, 'Attributes', nil); + SetImageIndex(Node2, ntAttributes); + for Index := 0 to SystemTypeInfo.AttributeTypes.Count - 1 do + begin + Node := Items.AddChildObject(Node2, SystemTypeInfo.AttributeTypes[Index].ExpressionName, Pointer(SystemTypeInfo.AttributeTypes[Index])); + SetImageIndex(Node, ntAttribute); + SelectCurrentNode(CurrentStringValue, Node); + end; + Node2.AlphaSort; end; - Node2.AlphaSort; - end; - if bvtAttr in ApprovedTypes then - begin - // add the attributes node - Node := Items.GetFirstNode; - Node2 := Items.AddChildObject(Node, 'Attributes', nil); // do not localize - SetImageIndex(Node2, ntAttributes); - for Index := 0 to SystemTypeInfo.AttributeTypes.Count - 1 do + if bvtSystem in ApprovedTypes then begin - // add the attribute nodes - Node := Items.AddChildObject(Node2, SystemTypeInfo.AttributeTypes[Index].ExpressionName, Pointer(SystemTypeInfo.AttributeTypes[Index])); - SetImageIndex(Node, ntAttribute); - SelectCurrentNode(CurrentStringValue, Node); + Node := Items.GetFirstNode; + Node2 := Items.AddChildObject(Node, SystemTypeInfo.ExpressionName , Pointer(SystemTypeInfo)); + SetImageIndex(Node2, ntSystem); + SelectCurrentNode(CurrentStringValue, Node2); end; - Node2.AlphaSort; - end; - - if bvtSystem in ApprovedTypes then - begin - Node := Items.GetFirstNode; - Node2 := Items.AddChildObject(Node, SystemTypeInfo.ExpressionName , Pointer(SystemTypeInfo)); - SetImageIndex(Node2, ntSystem); - SelectCurrentNode(CurrentStringValue, Node2); - end; - if bvtType in ApprovedTypes then - begin - Node := Items.GetFirstNode; - Node2 := Items.AddChildObject(Node, SystemTypeInfo.TypeTypeInfo.ExpressionName, Pointer(SystemTypeInfo.TypeTypeInfo)); - SetImageIndex(Node2, ntType); - SelectCurrentNode(CurrentStringValue, Node2); + if bvtType in ApprovedTypes then + begin + Node := Items.GetFirstNode; + Node2 := Items.AddChildObject(Node, SystemTypeInfo.TypeTypeInfo.ExpressionName, Pointer(SystemTypeInfo.TypeTypeInfo)); + SetImageIndex(Node2, ntType); + SelectCurrentNode(CurrentStringValue, Node2); + end; + Items.GetFirstNode.Expand(False); + finally + tvMetaTypes.Items.EndUpdate; end; - Items.GetFirstNode.Expand(False); end; end; diff --git a/Source/PMapper/Core/BoldAbstractObjectUpgrader.pas b/Source/PMapper/Core/BoldAbstractObjectUpgrader.pas index 4be98da..e0f5c44 100644 --- a/Source/PMapper/Core/BoldAbstractObjectUpgrader.pas +++ b/Source/PMapper/Core/BoldAbstractObjectUpgrader.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldAbstractObjectUpgrader; interface @@ -17,7 +20,7 @@ TBoldObjectUpgraderConfigItemClass = class of TBoldObjectUpgraderConfiguration TBoldObjectUpgraderConfigClass = class of TBoldObjectUpgraderConfiguration; TBoldObjectUpgraderConfigurationItem = class(TBoldUniquelyNamedCollectionItemWithNameStorage) - private + private FUpgradeOlderThanVersion: integer; procedure SetExpressionName(const Value: String); procedure SetUpgradeOlderThanVersion(const Value: integer); @@ -64,7 +67,6 @@ implementation uses SysUtils, BoldNameExpander, - BoldPMConsts, BoldTaggedValueSupport; { TBoldObjectUpgraderConfigurationItem } @@ -88,10 +90,11 @@ function TBoldObjectUpgraderConfigurationItem.GetDisplayName: string; if ExpressionName <> '' then result := ExpressionName else - result := sDisplayNameUnassigned; - result := Format(sUpgradeIfOlderThan, [Result, UpgradeOlderThanVersion]); + result := ''; + result := 'Upgrade ' + result + ' if older than ' + intToStr(UpgradeOlderThanVersion); end; + procedure TBoldObjectUpgraderConfigurationItem.SetExpressionName(const Value: String); begin UniqueName := BoldExpandName(Value, '', xtExpression, -1, nccDefault); @@ -145,4 +148,6 @@ function TBoldAbstractObjectUpgrader.NeedsManualUpdate(ExpressionName: string; V result := assigned(anItem) and (anItem.UpgradeOlderThanVersion > Version); end; +initialization + end. diff --git a/Source/PMapper/Core/BoldPMConsts.pas b/Source/PMapper/Core/BoldPMConsts.pas index d7f3b83..fbf42e3 100644 --- a/Source/PMapper/Core/BoldPMConsts.pas +++ b/Source/PMapper/Core/BoldPMConsts.pas @@ -212,3 +212,4 @@ interface implementation end. + diff --git a/Source/PMapper/Core/BoldPMapper.pas b/Source/PMapper/Core/BoldPMapper.pas index e7cb468..cffcc18 100644 --- a/Source/PMapper/Core/BoldPMapper.pas +++ b/Source/PMapper/Core/BoldPMapper.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldPMapper; interface @@ -17,10 +20,14 @@ TBoldPersistenceMapper = class(TBoldSubscribableObject) implementation +uses + BoldRev; + {---TBoldPersistenceMapper---} procedure TBoldPersistenceMapper.CreatePersistentStorage; begin end; -end. +initialization +end. diff --git a/Source/PMapper/Core/BoldPMapperLists.pas b/Source/PMapper/Core/BoldPMapperLists.pas index 341cd77..f06ef81 100644 --- a/Source/PMapper/Core/BoldPMapperLists.pas +++ b/Source/PMapper/Core/BoldPMapperLists.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldPMapperLists; interface @@ -32,13 +35,15 @@ TBoldPersistenceMapperDescriptor = class {---TBoldMemberPersistenceMapperList---} TBoldMemberPersistenceMapperDescriptorList = class(TBoldIndexableList) private - function GetDescriptorBydelphiName(name: string): TBoldMemberPersistenceMapperDescriptor; - function GetDescriptors(index: Integer): TBoldMemberPersistenceMapperDescriptor; + class var IX_MemberPMapperName: integer; + class var IX_MemberPMapperClass: integer; + function GetDescriptorBydelphiName(name: string): TBoldMemberPersistenceMapperDescriptor; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function GetDescriptors(index: Integer): TBoldMemberPersistenceMapperDescriptor; {$IFDEF BOLD_INLINE}inline;{$ENDIF} public constructor Create; procedure AddDescriptor(MemberPersistenceMapperClass: TBoldMemberPersistenceMapperClass; const AbstractionLevel: TBoldAbstractionLevel); - procedure RemoveDescriptorByClass(aClass: TBoldMemberPersistenceMapperClass); + procedure RemoveDescriptorByClass(aClass: TBoldMemberPersistenceMapperClass); {$IFDEF BOLD_INLINE}inline;{$ENDIF} function DescriptorForModelNameWithDefaultSupport(ModelName, DefaultMapperName: String; TypeNameDictionary: TBoldTypeNameDictionary): TBoldMemberPersistenceMapperDescriptor; property DescriptorByDelphiName[name: string]: TBoldMemberPersistenceMapperDescriptor read GetDescriptorByDelphiName; property Descriptors[index: integer]: TBoldMemberPersistenceMapperDescriptor read GetDescriptors; @@ -48,23 +53,24 @@ TBoldMemberPersistenceMapperDescriptorList = class(TBoldIndexableList) TBoldMemberPersistenceMapperDescriptor = class(TBoldPersistenceMapperDescriptor) private fAbstractionLevel: TBoldAbstractionLevel; - function GetMemberPersistenceMapperClass: TBoldMemberPersistenceMapperClass; + function GetMemberPersistenceMapperClass: TBoldMemberPersistenceMapperClass; {$IFDEF BOLD_INLINE}inline;{$ENDIF} public constructor Create(MemberPersistenceMapperClass: TBoldMemberPersistenceMapperClass; const AbstractionLevel: TBoldAbstractionLevel); property MemberPersistenceMapperClass: TBoldMemberPersistenceMapperClass read GetMemberPersistenceMapperClass; property AbstractionLevel: TBoldAbstractionLevel read fAbstractionLevel; - function CanStore(ContentName: string):Boolean; + function CanStore(const ContentName: string):Boolean; {$IFDEF BOLD_INLINE}inline;{$ENDIF} end; {---TBoldSystemPersistenceMapperList---} TBoldSystemPersistenceMapperDescriptorList = class(TBoldIndexableList) private - function GetDescriptorByName(name: string): TBoldSystemPersistenceMapperDescriptor; - function GetDescriptors(index: Integer): TBoldSystemPersistenceMapperDescriptor; + class var IX_SystemPMapperName: integer; + function GetDescriptorByName(name: string): TBoldSystemPersistenceMapperDescriptor; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function GetDescriptors(index: Integer): TBoldSystemPersistenceMapperDescriptor; {$IFDEF BOLD_INLINE}inline;{$ENDIF} public constructor Create; - procedure RemoveDescriptorByName(const Name: string); + procedure RemoveDescriptorByName(const Name: string); {$IFDEF BOLD_INLINE}inline;{$ENDIF} property DescriptorByName[name: string]: TBoldSystemPersistenceMapperDescriptor read GetDescriptorByName; property Descriptors[index: integer]: TBoldSystemPersistenceMapperDescriptor read GetDescriptors; end; @@ -72,7 +78,7 @@ TBoldSystemPersistenceMapperDescriptorList = class(TBoldIndexableList) {---TBoldSystemPersistenceMapperDescriptor---} TBoldSystemPersistenceMapperDescriptor = class(TBoldPersistenceMapperDescriptor) private - function GetSystemPersistenceMapperClass: TBoldSystemPersistenceMapperClass; + function GetSystemPersistenceMapperClass: TBoldSystemPersistenceMapperClass; {$IFDEF BOLD_INLINE}inline;{$ENDIF} public constructor Create(const name: string; BoldSystemPersistenceMapperClass: TBoldSystemPersistenceMapperClass); property SystemPersistenceMapperClass: TBoldSystemPersistenceMapperClass read GetSystemPersistenceMapperClass; @@ -81,11 +87,12 @@ TBoldSystemPersistenceMapperDescriptor = class(TBoldPersistenceMapperDescripto {---TBoldObjectPersistenceMapperList---} TBoldObjectPersistenceMapperDescriptorList = class(TBoldIndexableList) private - function GetDescriptorByName(name: string): TBoldObjectPersistenceMapperDescriptor; - function GetDescriptors(index: Integer): TBoldObjectPersistenceMapperDescriptor; + class var IX_ObjectPMapperName: integer; + function GetDescriptorByName(name: string): TBoldObjectPersistenceMapperDescriptor; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function GetDescriptors(index: Integer): TBoldObjectPersistenceMapperDescriptor; {$IFDEF BOLD_INLINE}inline;{$ENDIF} public constructor Create; - procedure RemoveDescriptorByName(const Name: string); + procedure RemoveDescriptorByName(const Name: string); {$IFDEF BOLD_INLINE}inline;{$ENDIF} property DescriptorByName[name: string]: TBoldObjectPersistenceMapperDescriptor read GetDescriptorByName; property Descriptors[index: integer]: TBoldObjectPersistenceMapperDescriptor read GetDescriptors; end; @@ -93,13 +100,12 @@ TBoldObjectPersistenceMapperDescriptorList = class(TBoldIndexableList) {---TBoldObjectPersistenceMapperDescriptor---} TBoldObjectPersistenceMapperDescriptor = class(TBoldPersistenceMapperDescriptor) private - function GetObjectPersistenceMapperClass: TBoldObjectPersistenceMapperClass; + function GetObjectPersistenceMapperClass: TBoldObjectPersistenceMapperClass; {$IFDEF BOLD_INLINE}inline;{$ENDIF} public constructor Create(const name: string; BoldObjectPersistenceMapperClass: TBoldObjectPersistenceMapperClass); property ObjectPersistenceMapper: TBoldObjectPersistenceMapperClass read GetObjectPersistenceMapperClass; end; - // Access points to PersistenceMapperDescriptor-lists objects function BoldMemberPersistenceMappers: TBoldMemberPersistenceMapperDescriptorList; function BoldMemberPersistenceMappersAssigned: Boolean; function BoldSystemPersistenceMappers: TBoldSystemPersistenceMapperDescriptorList; @@ -119,11 +125,6 @@ implementation G_BoldSystemPersistenceMappers: TBoldSystemPersistenceMapperDescriptorList = nil; G_BoldObjectPersistenceMappers: TBoldObjectPersistenceMapperDescriptorList = nil; - IX_SystemPMapperName: integer = -1; - IX_ObjectPMapperName: integer = -1; - IX_MemberPMapperName: integer = -1; - IX_MemberPMapperClass: integer = -1; - type {---TBoldMemberPMapperNameIndex---} TBoldMemberPMapperNameIndex = class(TBoldStringHashIndex) @@ -231,7 +232,7 @@ constructor TBoldMemberPersistenceMapperDescriptorList.Create; function TBoldMemberPersistenceMapperDescriptorList.GetDescriptorByDelphiName(name: string): TBoldMemberPersistenceMapperDescriptor; begin - Result := TBoldMemberPersistenceMapperDescriptor(TBoldMemberPMapperNameIndex(Indexes[IX_MemberPMapperName]).FindByString(Name)) + Result := TBoldMemberPersistenceMapperDescriptor(TBoldStringHashIndex(Indexes[IX_MemberPMapperName]).FindByString(Name)) end; function TBoldMemberPersistenceMapperDescriptorList.GetDescriptors(index: integer): TBoldMemberPersistenceMapperDescriptor; @@ -266,7 +267,7 @@ function TBoldMemberPersistenceMapperDescriptor.GetMemberPersistenceMapperClass: Result := TBoldMemberPersistenceMapperClass(PersistenceMapperClass); end; -function TBoldMemberPersistenceMapperDescriptor.CanStore(ContentName: String): Boolean; +function TBoldMemberPersistenceMapperDescriptor.CanStore(const ContentName: String): Boolean; begin Result := MemberPersistenceMapperClass.CanStore(ContentName); end; @@ -281,7 +282,7 @@ constructor TBoldSystemPersistenceMapperDescriptorList.Create; function TBoldSystemPersistenceMapperDescriptorList.GetDescriptorByName(name: string): TBoldSystemPersistenceMapperDescriptor; begin - Result := TBoldSystemPersistenceMapperDescriptor(TBoldSystemPMapperNameIndex(Indexes[IX_SystemPMapperName]).FindByString(Name)) + Result := TBoldSystemPersistenceMapperDescriptor(TBoldStringHashIndex(Indexes[IX_SystemPMapperName]).FindByString(Name)) end; function TBoldSystemPersistenceMapperDescriptorList.GetDescriptors(index: Integer): TBoldSystemPersistenceMapperDescriptor; @@ -316,7 +317,7 @@ constructor TBoldObjectPersistenceMapperDescriptorList.Create; function TBoldObjectPersistenceMapperDescriptorList.GetDescriptorByName(name: string): TBoldObjectPersistenceMapperDescriptor; begin - Result := TBoldObjectPersistenceMapperDescriptor(TBoldObjectPMapperNameIndex(Indexes[IX_ObjectPMapperName]).FindByString(Name)) + Result := TBoldObjectPersistenceMapperDescriptor(TBoldStringHashIndex(Indexes[IX_ObjectPMapperName]).FindByString(Name)) end; function TBoldObjectPersistenceMapperDescriptorList.GetDescriptors(index: Integer): TBoldObjectPersistenceMapperDescriptor; @@ -366,6 +367,10 @@ function TBoldMemberPersistenceMapperDescriptorList.DescriptorForModelNameWithDe end; initialization + TBoldMemberPersistenceMapperDescriptorList.IX_MemberPMapperName := -1; + TBoldMemberPersistenceMapperDescriptorList.IX_MemberPMapperClass := -1; + TBoldSystemPersistenceMapperDescriptorList.IX_SystemPMapperName := -1; + TBoldObjectPersistenceMapperDescriptorList.IX_ObjectPMapperName := -1; finalization FreeAndNil(G_BoldMemberPersistenceMappers); diff --git a/Source/PMapper/Core/BoldPMappers.pas b/Source/PMapper/Core/BoldPMappers.pas index 1106419..8f3cef1 100644 --- a/Source/PMapper/Core/BoldPMappers.pas +++ b/Source/PMapper/Core/BoldPMappers.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldPMappers; interface @@ -21,7 +24,7 @@ interface BoldValueSpaceInterfaces; type - {forward declarations} + {forward declarations} TBoldSystemPersistenceMapper = class; TBoldObjectPersistenceMapper = class; TBoldMemberPersistenceMapper = class; @@ -34,6 +37,7 @@ TBoldMemberPersistenceMapperList = class; TBoldPreparePSParams = procedure(PSParams: TBoldPSParams) of object; + { TBoldSystemPersistenceMapper } TBoldSystemPersistenceMapper = class(TBoldPersistenceMapper) private @@ -54,58 +58,64 @@ TBoldSystemPersistenceMapper = class(TBoldPersistenceMapper) fObjectUpgrader: TBoldAbstractObjectUpgrader; function GetPSSystemDescription: TBoldPSSystemDescription; procedure fPMCreate(ObjectIDList: TBoldObjectIdList; - ValueSpace: IBoldValueSpace; + const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList); procedure fPMDelete(ObjectIDList: TBoldObjectIdList; - ValueSpace: IBoldValueSpace; - Old_Values: IBoldValueSpace; + const ValueSpace: IBoldValueSpace; + const Old_Values: IBoldValueSpace; TranslationList: TBoldIdTranslationList); procedure fPMUpdate(ObjectIDList: TBoldObjectIdList; - ValueSpace: IBoldValueSpace; - Old_Values: IBoldValueSpace; + const ValueSpace: IBoldValueSpace; + const Old_Values: IBoldValueSpace; TranslationLIst: TBoldIdTranslationList); function GetSupportsObjectUpgrading: Boolean; protected FCurrentTimeStamp: TBoldTimeStampType; + fTimeOfTimeStamp: TDateTime; procedure InitializePSDescriptions; virtual; procedure FillPSParams(PSParams: TBoldPSParams); virtual; abstract; function CreatePSParams: TBoldPSParams; virtual; abstract; function CreatePSSystemDescription: TBoldPSSystemDescription; virtual; abstract; procedure ReserveID; virtual; abstract; - function NextExternalObjectId(ValueSpace: IBoldValueSpace; + function NextExternalObjectId(const ValueSpace: IBoldValueSpace; ObjectID: TBoldObjectId): TBoldObjectId; - procedure StartTransaction(ValueSpace: IBoldValueSpace); virtual; abstract; - procedure Commit(ValueSpace: IBoldValueSpace); virtual; abstract; - procedure RollBack(ValueSpace: IBoldValueSpace); virtual; abstract; + procedure StartTransaction(const ValueSpace: IBoldValueSpace); virtual; abstract; + procedure Commit(const ValueSpace: IBoldValueSpace); virtual; abstract; + procedure RollBack(const ValueSpace: IBoldValueSpace); virtual; abstract; + + procedure StartSQLBatch; virtual; abstract; + procedure EndSQLBatch; virtual; abstract; + procedure FailSQLBatch; virtual; abstract; procedure GetNewTimeStamp; virtual; abstract; function EnsurePrecondition(Precondition: TBoldUpdatePrecondition; TranslationList: TBoldIdTranslationList): Boolean; virtual; abstract; - procedure FetchDeletedObjects(ObjectIdList: TBoldObjectIdList; ValieSpace: IBoldValueSpace); virtual; abstract; + procedure FetchDeletedObjects(ObjectIdList: TBoldObjectIdList; const ValieSpace: IBoldValueSpace); virtual; abstract; procedure EnsurePSDescription; public - constructor CreateFromMold(MoldModel: TMoldModel; TypeNameDictionary: TBoldTypeNameDictionary); + constructor CreateFromMold(MoldModel: TMoldModel; TypeNameDictionary: TBoldTypeNameDictionary; DefaultObjectMapperName: string); destructor Destroy; override; procedure PMFetch(ObjectIDList: TBoldObjectIdList; - ValueSpace: IBoldValueSpace; + const ValueSpace: IBoldValueSpace; MemberIdList: TBoldMemberIdList; FetchMode: Integer; TranslationList: TBoldIdTranslationList); virtual; procedure PMFetchClassWithCondition(ObjectIDList: TBoldObjectIdList; - ValueSpace: IBoldValueSpace; + const ValueSpace: IBoldValueSpace; BoldCondition: TBoldCondition; FetchMode: Integer; TranslationList: TBoldIdTranslationList); virtual; procedure PMUpdate(ObjectIDList: TBoldObjectIdList; - ValueSpace: IBoldValueSpace; - Old_Values: IBoldValueSpace; + const ValueSpace: IBoldValueSpace; + const Old_Values: IBoldValueSpace; Precondition: TBoldUpdatePrecondition; TranslationList: TBoldIdTranslationList; - var TimeStamp: TBoldTimeStampType); + var TimeStamp: TBoldTimeStampType; + var TimeOfLatestUpdate: TDateTime); function CommonSuperClassObjectMapper(ObjectIdList: TBoldObjectIdList): TBoldObjectPersistenceMapper; procedure CreatePersistentStorage; override; function GetCorrectTime: TDateTime; procedure SubscribeToPersistenceEvents(Subscriber: TBoldSubscriber); - procedure ReserveNewIds(ValueSpace: IBoldValueSpace; ObjectIdList: TBoldObjectIdList; + procedure ReserveNewIds(const ValueSpace: IBoldValueSpace; ObjectIdList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList); property ObjectPersistenceMappers: TBoldObjectPersistenceMapperList @@ -115,6 +125,7 @@ TBoldSystemPersistenceMapper = class(TBoldPersistenceMapper) read fRootClassObjectPMapper; property OnPreparePSParams: TBoldPreparePSParams read fPreparePSParams write fPreparePSParams; property CurrentTimeStamp: TBoldTimeStampType read FCurrentTimeStamp; + property TimeOfTimeStamp: TDateTime read fTimeOfTimeStamp; procedure PMTranslateToGlobalIds(ObjectIdList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList); virtual; abstract; procedure PMTranslateToLocalIds(GlobalIdList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList); virtual; abstract; procedure PMSetReadonlyness(ReadOnlyList, WriteableList: TBoldObjectIdList); virtual; abstract; @@ -151,47 +162,47 @@ TBoldObjectPersistenceMapper = class(TBoldPersistenceMapper) fMemberMapperIndexByMemberIndex: array of integer; function GetLinkClassRole1: TBoldMemberPersistenceMapper; function GetLinkClassRole2: TBoldMemberPersistenceMapper; - procedure FillInMembers(MyMoldClass, CurrentMoldClass: TMoldClass; TypeNameDictionary: TBoldTypeNameDictionary); function LeastCommonSuperClassMapper(ObjectMapper: TBoldObjectPersistenceMapper): TBoldObjectPersistenceMapper; function GetMemberMapperIndexByMemberIndex(const MemberIndex: Integer): integer; protected fObjectIdClass: String; + procedure FillInMembers(MyMoldClass, CurrentMoldClass: TMoldClass; TypeNameDictionary: TBoldTypeNameDictionary); virtual; procedure PMFetchWithCondition(ObjectIDList: TBoldObjectIdList; - ValueSpace: IBoldValueSpace; + const ValueSpace: IBoldValueSpace; BoldCondition: TBoldCondition; FetchMode: Integer; TranslationList: TBoldIdTranslationList); virtual; abstract; - function NextExternalObjectId(ValueSpace: IBoldValueSpace; + function NextExternalObjectId(const ValueSpace: IBoldValueSpace; ObjectID: TBoldObjectId): TBoldObjectId; virtual; abstract; procedure InitializePSDescriptions; virtual; public constructor CreateFromMold(MoldClass: TMoldClass; Owner: TBoldSystemPersistenceMapper; TypeNameDictionary: TBoldTypeNameDictionary); virtual; destructor Destroy; override; procedure MakeIDsExact(ObjectIDList: TBoldObjectIdList; - TranslationList: TBoldIdTranslationList); virtual; abstract; + TranslationList: TBoldIdTranslationList; HandleNonExisting: Boolean); virtual; abstract; procedure EnsureIDsExact(ObjectIDList: TBoldObjectIdList; - TranslationList: TBoldIdTranslationList); virtual; + TranslationList: TBoldIdTranslationList; HandleNonExisting: Boolean); virtual; procedure PMFetchExactIDList(ObjectIDList: TBoldObjectIdList; - ValueSpace: IBoldValueSpace; + const ValueSpace: IBoldValueSpace; MemberIdList: TBoldMemberIdList; FetchMode: Integer; TranslationList:TBoldIdTranslationList; MissingList: TBoldObjectIdList); virtual; abstract; procedure PMFetchApproximateIDList(ObjectIDList: TBoldObjectIdList; - ValueSpace: IBoldValueSpace; + const ValueSpace: IBoldValueSpace; MemberIdList: TBoldMemberIdList; FetchMode: Integer; TranslationList: TBoldIdTranslationList); virtual; procedure PMCreate(ObjectIDList: TBoldObjectIdList; - ValueSpace: IBoldValueSpace; + const ValueSpace: IBoldValueSpace; TranslationList:TBoldIdTranslationList); virtual; abstract; procedure PMDelete(ObjectIDList: TBoldObjectIdList; - ValueSpace: IBoldValueSpace; - Old_Values: IBoldValueSpace; + const ValueSpace: IBoldValueSpace; + const Old_Values: IBoldValueSpace; TranslationList: TBoldIdTranslationList); virtual; abstract; procedure PMUpdate(ObjectIDList: TBoldObjectIdList; - ValueSpace: IBoldValueSpace; - Old_Values: IBoldValueSpace; + const ValueSpace: IBoldValueSpace; + const Old_Values: IBoldValueSpace; TranslationLIst: TBoldIdTranslationList); virtual; abstract; function BoldIsA(ObjectPMapper: TBoldObjectPersistenceMapper): Boolean; function LeastCommonSuperMapper(ObjectPMapper: TBoldObjectPersistenceMapper): TBoldObjectPersistenceMapper; @@ -240,18 +251,18 @@ TBoldMemberPersistenceMapper = class(TBoldPersistenceMapper) property MemberIndex: Integer read fMemberIndex; property ContentName: string read fContentName; property ExpressionName: string read fExpressionName; - function GetValue(ObjectContents: IBoldObjectContents): IBoldValue; - function GetEnsuredValue(ObjectContents: IBoldObjectContents): IBoldValue; - function IsDirty(ObjectContents: IBoldObjectContents): Boolean; virtual; - function ShouldFetch(ObjectContents: IBoldObjectContents): Boolean; virtual; - procedure PMCreate(ObjectIdList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; + function GetValue(const ObjectContents: IBoldObjectContents): IBoldValue; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetEnsuredValue(const ObjectContents: IBoldObjectContents): IBoldValue; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function IsDirty(const ObjectContents: IBoldObjectContents): Boolean; virtual; + function ShouldFetch(const ObjectContents: IBoldObjectContents): Boolean; virtual; + procedure PMCreate(ObjectIdList: TBoldObjectIdList; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList); virtual; - procedure PMUpdate(ObjectIdList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; + procedure PMUpdate(ObjectIdList: TBoldObjectIdList; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList); virtual; - procedure PMDelete(ObjectIdList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; + procedure PMDelete(ObjectIdList: TBoldObjectIdList; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList); virtual; procedure PMFetch(ObjectIdList: TBoldObjectIdList; - ValueSpace: IBoldValueSpace; + const ValueSpace: IBoldValueSpace; FetchMode: Integer; TranslationList: TBoldIdTranslationList; FailureList: TBoldObjectIdList); virtual; property SupportsPolymorphicFetch: Boolean read GetSupportsPolymorphicFetch; @@ -260,7 +271,7 @@ TBoldMemberPersistenceMapper = class(TBoldPersistenceMapper) { TBoldObjectPersistenceMapperList } TBoldObjectPersistenceMapperList = class(TBoldIndexableList) private - function GetItem(index: Integer): TBoldObjectPersistenceMapper; + function GetItem(index: Integer): TBoldObjectPersistenceMapper; {$IFDEF BOLD_INLINE} inline; {$ENDIF} public property Items[index: Integer]: TBoldObjectPersistenceMapper read GetItem; default; end; @@ -268,8 +279,9 @@ TBoldObjectPersistenceMapperList = class(TBoldIndexableList) { TBoldMemberPersistenceMapperList } TBoldMemberPersistenceMapperList = class(TBoldIndexableList) private - function GetItem(index: Integer): TBoldmemberPersistenceMapper; - function GetMemberMapperByExpressionName(ExpressionName: string): TBoldMemberPersistenceMapper; + class var IX_MemberMapper: integer; + function GetItem(index: Integer): TBoldmemberPersistenceMapper; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetMemberMapperByExpressionName(ExpressionName: string): TBoldMemberPersistenceMapper; {$IFDEF BOLD_INLINE} inline; {$ENDIF} public constructor Create; property Items[index: Integer]: TBoldMemberPersistenceMapper read GetItem; default; @@ -279,7 +291,7 @@ TBoldMemberPersistenceMapperList = class(TBoldIndexableList) { TBoldMemberMapperIndex } TBoldMemberMapperIndex = class(TBoldStringHashIndex) protected - function ItemAsKeyString(Item: TObject): string; override; + function ItemASKeyString(Item: TObject): string; override; end; procedure BoldPMLog(const s: string); @@ -298,26 +310,30 @@ implementation BoldDefaultStreamNames, BoldPMapperLists; -var - IX_MemberMapper: integer = -1; - procedure BoldPMLog(const s: string); begin if assigned(BoldPMLogHandler) then - BoldPMLogHandler.Log(formatDateTime('c: ', now) + trim(s)); // do not localize + BoldPMLogHandler.Log(formatDateTime('c: ', now)+trim(s)); end; procedure BoldPMLogFmt(const s: string; const Args: array of const); begin if assigned(BoldPMLogHandler) then - BoldPMLogHandler.LogFmt(formatDateTime('c: ', now) + trim(s), Args); // do not localize + BoldPMLogHandler.LogFmt(formatDateTime('c: ', now) +trim(s), Args); +end; + +{ TBoldObjectPersistenceMapperList } +function TBoldObjectPersistenceMapperList.GetItem(index: Integer): TBoldObjectPersistenceMapper; +begin + Result := TBoldObjectPersistenceMapper(inherited Items[index]); end; { TBoldSystemPersistenceMapper } -constructor TBoldSystemPersistenceMapper.CreateFromMold(MoldModel: TMoldModel; TypeNameDictionary: TBoldTypeNameDictionary); +constructor TBoldSystemPersistenceMapper.CreateFromMold(MoldModel: TMoldModel; TypeNameDictionary: TBoldTypeNameDictionary; DefaultObjectMapperName: string); var i: integer; ObjectPmapper: TBoldObjectPersistenceMapper; + ObjectMapperName: string; ObjectMapperDescriptor: TBoldObjectPersistenceMapperDescriptor; MoldClass: TMoldClass; begin @@ -333,14 +349,18 @@ constructor TBoldSystemPersistenceMapper.CreateFromMold(MoldModel: TMoldModel; T fUseClockLog := MoldModel.UseClockLog; fUpdateWholeObjects := MoldModel.UpdateWholeObjects; fObjectPersistenceMappers := TBoldObjectPersistenceMapperList.Create; + ObjectPersistenceMappers.Capacity := MoldModel.Classes.Count; for i := 0 to MoldModel.Classes.Count - 1 do begin if MoldModel.Classes[i].EffectivePersistent and (MoldModel.Classes[i].Storage in [bsInternal, bsPartiallyExternal]) then begin MoldClass := MoldModel.Classes[i]; - ObjectMapperDescriptor := BoldObjectPersistenceMappers.DescriptorByName[MoldClass.PMapperName]; + ObjectMapperName := MoldClass.PMapperName; + if BoldNamesEqual(ObjectMapperName, DEFAULTNAMELITERAL) and (DefaultObjectMapperName <> '') then + ObjectMapperName := DefaultObjectMapperName; + ObjectMapperDescriptor := BoldObjectPersistenceMappers.DescriptorByName[ObjectMapperName]; if not assigned(ObjectMapperDEscriptor) then - raise EBold.CreateFmt(sUnableToFindPMapperForClass, [MoldClass.PMapperName, MoldClass.Name]); + raise EBold.CreateFmt('Unable to find PersistenceMapper (%s) for class %s', [ObjectMapperName, MoldClass.Name]); ObjectPMapper := ObjectMapperDescriptor.ObjectPersistenceMapper.CreatefromMold(MoldClass, Self, TypeNameDictionary); end else @@ -358,7 +378,7 @@ destructor TBoldSystemPersistenceMapper.Destroy; end; procedure TBoldSystemPersistenceMapper.PMFetch(ObjectIDList: TBoldObjectIdList; - ValueSpace: IBoldValueSpace; + const ValueSpace: IBoldValueSpace; MemberIdList: TBoldMemberIdList; FetchMode: Integer; TranslationList: TBoldIdTranslationList); @@ -367,7 +387,7 @@ procedure TBoldSystemPersistenceMapper.PMFetch(ObjectIDList: TBoldObjectIdList; end; procedure TBoldSystemPersistenceMapper.PMFetchClassWithCondition(ObjectIDList: TBoldObjectIdList; - ValueSpace: IBoldValueSpace; + const ValueSpace: IBoldValueSpace; BoldCondition: TBoldCondition; FetchMode: Integer; TranslationList: TBoldIdTranslationList); @@ -376,16 +396,16 @@ procedure TBoldSystemPersistenceMapper.PMFetchClassWithCondition(ObjectIDList: T with ObjectPersistenceMappers[(BoldCondition as TBoldConditionWithClass).TopSortedIndex] do PMFetchWithCondition(ObjectIdList, ValueSpace, BoldCondition, FetchMode, TranslationList) else - raise EBold.CreateFmt(sConditionMustBeConditionWithClass , [ClassName, BoldCondition.Classname]); + raise EBold.CreateFmt('%s.PMFetchClassWithCondition: Condition must be a ConditionWithClass, not a %s', [ClassName, BoldCondition.Classname]); end; -function tBoldSystemPersistenceMapper.NextExternalObjectId(ValueSpace: IBoldValueSpace; ObjectID: TBoldObjectId): TBoldObjectId; +function tBoldSystemPersistenceMapper.NextExternalObjectId(const ValueSpace: IBoldValueSpace; ObjectID: TBoldObjectId): TBoldObjectId; begin result := ObjectPersistenceMappers[ObjectId.TopSortedIndex].NextExternalObjectID(ValueSpace, ObjectId); end; procedure TBoldSystemPersistenceMapper.fPMCreate(ObjectIDList: TBoldObjectIdList; - ValueSpace: IBoldValueSpace; + const ValueSpace: IBoldValueSpace; TranslationList:TBoldIdTranslationList); var TempList, @@ -394,32 +414,27 @@ procedure TBoldSystemPersistenceMapper.fPMCreate(ObjectIDList: TBoldObjectIdList i: integer; g: IBoldGuard; begin - g := TBoldGuard.Create(TempList); + g := TBoldGuard.Create(TempList, ActionList); tempList := Objectidlist.Clone; + ActionList := TBoldObjectIdList.Create; while TempList.Count > 0 do begin - ActionList := TBoldObjectIdList.Create; - try - CurrentPMapper := ObjectPersistenceMappers[TempList[0].TopSortedIndex]; - i := 0; - while i < TempList.Count do - if ObjectPersistenceMappers[TempList[i].TopSortedIndex] = CurrentPMapper then - begin - ActionList.Add(TempList[i]); - TempList.RemoveByIndex(i); - end - else - Inc(i); - CurrentPMapper.PMCreate(ActionList, ValueSpace, translationlist); - finally - ActionList.Free; - end; + i := TempList.Count -1; + CurrentPMapper := ObjectPersistenceMappers[TempList[i].TopSortedIndex]; + ActionList.Clear; + for i := i downto 0 do + if ObjectPersistenceMappers[TempList[i].TopSortedIndex] = CurrentPMapper then + begin + ActionList.Add(TempList[i]); + TempList.RemoveByIndex(i); + end; + CurrentPMapper.PMCreate(ActionList, ValueSpace, translationlist); end; end; procedure TBoldSystemPersistenceMapper.fPMDelete(ObjectIDList: TBoldObjectIdList; - ValueSpace: IBoldValueSpace; - Old_Values: IBoldValueSpace; + const ValueSpace: IBoldValueSpace; + const Old_Values: IBoldValueSpace; TranslationList: TBoldIdTranslationList); var TempList, @@ -428,32 +443,27 @@ procedure TBoldSystemPersistenceMapper.fPMDelete(ObjectIDList: TBoldObjectIdList i: integer; g: IBoldGuard; begin - g := TBoldGuard.Create(TempList); + g := TBoldGuard.Create(TempList, ActionList); tempList := ObjectidList.Clone; + ActionList := TBoldObjectIdList.Create; while TempList.Count > 0 do begin - ActionList := TBoldObjectIdList.Create; - try - CurrentPMapper := ObjectPersistenceMappers[TempList[0].topSortedIndex]; - i := 0; - while i < TempList.Count do - if ObjectPersistenceMappers[TempList[i].topSortedIndex] = CurrentPMapper then - begin - ActionList.Add(TempList[i]); - TempList.RemoveByIndex(i); - end - else - Inc(i); - CurrentPMapper.PMDelete(ActionList, ValueSpace, Old_Values, TranslationList); - finally - ActionList.Free; - end; + i := TempList.Count -1; + CurrentPMapper := ObjectPersistenceMappers[TempList[i].topSortedIndex]; + ActionList.clear; + for i := i downto 0 do + if ObjectPersistenceMappers[TempList[i].topSortedIndex] = CurrentPMapper then + begin + ActionList.Add(TempList[i]); + TempList.RemoveByIndex(i); + end; + CurrentPMapper.PMDelete(ActionList, ValueSpace, Old_Values, TranslationList); end; end; procedure TBoldSystemPersistenceMapper.fPMUpdate(ObjectIDList: TBoldObjectIdList; - ValueSpace: IBoldValueSpace; - Old_Values: IBoldValueSpace; + const ValueSpace: IBoldValueSpace; + const Old_Values: IBoldValueSpace; TranslationLIst: TBoldIdTranslationList); var TempList, @@ -462,26 +472,21 @@ procedure TBoldSystemPersistenceMapper.fPMUpdate(ObjectIDList: TBoldObjectIdList i: integer; g: IBoldGuard; begin - g := TBoldGuard.Create(TempList); + g := TBoldGuard.Create(TempList, ActionList); tempList := ObjectidList.Clone; + ActionList := TBoldObjectIdList.Create; while TempList.Count > 0 do begin - ActionList := TBoldObjectIdList.Create; - try - CurrentPMapper := ObjectPersistenceMappers[TempList[0].topSortedIndex]; - i := 0; - while i < TempList.Count do - if ObjectPersistenceMappers[TempList[i].topSortedIndex] = CurrentPMapper then - begin - ActionList.Add(TempList[i]); - TempList.RemoveByIndex(i); - end - else - Inc(i); - CurrentPMapper.PMUpdate(ActionList, ValueSpace, Old_Values, TranslationList); - finally - ActionList.Free; - end; + i := TempList.Count -1; + CurrentPMapper := ObjectPersistenceMappers[TempList[i].topSortedIndex]; + ActionList.Clear; + for i := i downto 0 do + if ObjectPersistenceMappers[TempList[i].topSortedIndex] = CurrentPMapper then + begin + ActionList.Add(TempList[i]); + TempList.RemoveByIndex(i); + end; + CurrentPMapper.PMUpdate(ActionList, ValueSpace, Old_Values, TranslationList); end; end; @@ -506,101 +511,94 @@ procedure TBoldSystemPersistenceMapper.CreatePersistentStorage; end; procedure TBoldSystemPersistenceMapper.PMUpdate(ObjectIDList: TBoldObjectIdList; - ValueSpace: IBoldValueSpace; - Old_Values: IBoldValueSpace; + const ValueSpace: IBoldValueSpace; + const Old_Values: IBoldValueSpace; Precondition: TBoldUpdatePrecondition; TranslationList: TBoldIdTranslationList; - var TimeStamp: TBoldTimeStampType); + var TimeStamp: TBoldTimeStampType; + var TimeOfLatestUpdate: TDateTime); var i: Integer; ModifiedObjectIDList, NewObjectIDList, DeletedObjectIDList: TBoldObjectIdList; ObjectContents: IBoldObjectContents; + Guard: IBoldGuard; begin if ObjectIDList.Count = 0 then Exit; + Guard := TBoldGuard.Create(ModifiedObjectIDList, NewObjectIDList, DeletedObjectIDList); + DeletedObjectIDList := TBoldObjectIdList.Create; + NewObjectIDList := TBoldObjectIdList.Create; + ModifiedObjectIDList := TBoldObjectIdList.Create; + + // downto order is important here - Daniel + for i := ObjectIDList.Count - 1 downto 0 do + begin + ObjectContents := ValueSpace.ObjectContentsByObjectId[ObjectIdList[i]]; + if ObjectContents.BoldPersistenceState = bvpsModified then + begin + if ObjectContents.BoldExistenceState = besDeleted then + DeletedObjectIDList.Add(ObjectIDList[i]) + else + NewObjectIDList.Add(ObjectIDList[i]); + end else + ModifiedObjectIDList.Add(ObjectIDList[i]); + end; ReserveNewIds(ValueSpace, ObjectIdList, TranslationList); + if UseTimestamp then + GetNewTimeStamp; StartTransaction(ValueSpace); try - if UseTimestamp then - GetNewTimeStamp; - except - RollBack(ValueSpace); - raise; - end; - Commit(valueSpace); + if assigned(Precondition) then + begin + if not EnsurePrecondition(Precondition, translationList) then + begin + Commit(valueSpace); + exit; + end; + end; - StartTransaction(ValueSpace); + StartSQLBatch; + if DeletedObjectIDList.Count > 0 then + fPMDelete(DeletedObjectIDList, ValueSpace, Old_Values, TranslationList); - try - if assigned(Precondition) and not EnsurePrecondition(Precondition, translationList) then - begin - RollBack(ValueSpace); - end - else + if NewObjectIDList.Count > 0 then + fPMCreate(NewObjectIDList, ValueSpace, translationList); + + if ModifiedObjectIDList.Count > 0 then + fPMUpdate(ModifiedObjectIDList, ValueSpace, Old_Values, TranslationList); + + if UseTimestamp then begin - DeletedObjectIDList := TBoldObjectIdList.Create; - NewObjectIDList := TBoldObjectIdList.Create; - ModifiedObjectIDList := TBoldObjectIdList.Create; - try - for i := ObjectIDList.Count - 1 downto 0 do - begin - ObjectContents := ValueSpace.ObjectContentsByObjectId[ObjectIdList[i]]; - if ObjectContents.BoldPersistenceState = bvpsModified then - begin - if ObjectContents.BoldExistenceState = besDeleted then - DeletedObjectIDList.Add(ObjectIDList[i]) - else - NewObjectIDList.Add(ObjectIDList[i]); - end else - ModifiedObjectIDList.Add(ObjectIDList[i]); - end; - - // the order below is important, delete must come before create - // due to a solution made for linkobjects in PMCreate to avoid duplicates - - if DeletedObjectIDList.Count > 0 then - fPMDelete(DeletedObjectIDList, ValueSpace, Old_Values, TranslationList); - - if NewObjectIDList.Count > 0 then - fPMCreate(NewObjectIDList, ValueSpace, translationList); - - if ModifiedObjectIDList.Count > 0 then - fPMUpdate(ModifiedObjectIDList, ValueSpace, Old_Values, TranslationList); - finally - ModifiedObjectIDList.Free; - NewObjectIDList.Free; - DeletedObjectIDList.Free; - end; - if UseTimestamp then - TimeStamp := CurrentTimeStamp; - Commit(valueSpace); - end; + TimeStamp := CurrentTimeStamp; + TimeOfLatestUpdate := fTimeOfTimeStamp; + end; + EndSQLBatch; + Commit(valueSpace); except RollBack(ValueSpace); + FailSQLBatch; raise; end; end; -procedure TBoldSystemPersistenceMapper.ReserveNewIds(ValueSpace: IBoldValueSpace; +procedure TBoldSystemPersistenceMapper.ReserveNewIds(const ValueSpace: IBoldValueSpace; ObjectIdList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList); var i: integer; newId: TBoldObjectID; begin - if ObjectIdList.Count = 0 then //FIXME: Rather unnecessary optimization I'd think? --jeho + if ObjectIdList.Count = 0 then Exit; with ObjectIdList do begin - // Reserve IDs for new objects for i := 0 to Count - 1 do if not ObjectIdList[i].IsStorable then ReserveId; - // Generate IDs for objects for i := 0 to Count - 1 do if not ObjectIDList[i].IsStorable then begin @@ -626,20 +624,18 @@ constructor TBoldObjectPersistenceMapper.CreateFromMold(MoldClass: TMoldClass; O fLinkRoleMapperIndex1 := -1; fLinkRoleMapperIndex2 := -1; if MoldClass.Versioned then - begin fVersioned := true; - end; if MoldClass.Versioned and assigned(MoldClass.SuperClass) and not MoldClass.SuperClass.Versioned then - raise EBold.CreateFmt(sSuperClassNotVersioned, [MoldClass.ExpandedExpressionName, MoldClass.SuperClass.ExpandedExpressionname]); + raise EBold.CreateFmt('Class %s is versioned, but not it''s superclass %s', [MoldClass.ExpandedExpressionName, MoldClass.SuperClass.ExpandedExpressionname]); if Assigned(MoldClass.SuperClass) then begin fSuperClass := SystemPersistenceMapper.ObjectPersistencemappers[MoldClass.SuperClass.TopSortedIndex]; if not Assigned(fSuperClass) then - raise EBold.CreateFmt(sSuperClassNotPersistent, [MoldClass.ExpandedExpressionName, MoldClass.SuperClass.ExpandedExpressionname]); + raise EBold.CreateFmt('Class %s has a nonpersistent superclass %s', [MoldClass.ExpandedExpressionName, MoldClass.SuperClass.ExpandedExpressionname]); SuperClass.fHasSubClasses := true; end; @@ -655,18 +651,18 @@ procedure TBoldObjectPersistenceMapper.CreatePersistentStorage; MemberPersistenceMappers[i].CreatePersistentStorage; end; -procedure TBoldObjectPersistenceMapper.PMFetchApproximateIDList(ObjectIDList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; MemberIdList: TBoldMemberIdList; FetchMode: Integer; TranslationList: TBoldIdTranslationList); +procedure TBoldObjectPersistenceMapper.PMFetchApproximateIDList(ObjectIDList: TBoldObjectIdList; const ValueSpace: IBoldValueSpace; MemberIdList: TBoldMemberIdList; FetchMode: Integer; TranslationList: TBoldIdTranslationList); var ActionList, - TempList, MissingList: TBoldObjectIdList; + TempList, NewTempList: array of TBoldObjectId; + NewTempCount: integer; MemberMapper: TBoldMemberPersistenceMapper; MemberMapperIndex: integer; TempMapper, CurrentPMapper: TBoldObjectPersistenceMapper; i: integer; - function ObjectMapperForNewID(OldID: TBoldObjectId): TBoldObjectPersistenceMapper; - // Only objects with inexact ClassIds can have changed their ClassID + function ObjectMapperForNewID(const OldID: TBoldObjectId; const TranslationList: TBoldIdTranslationList): TBoldObjectPersistenceMapper; var NewId: TBoldObjectId; begin @@ -674,84 +670,103 @@ procedure TBoldObjectPersistenceMapper.PMFetchApproximateIDList(ObjectIDList: TB NewId := OldID else NewId := TranslationList.TranslateToNewId[OldID]; - result := SystemPersistenceMapper.ObjectPersistenceMappers[NewID.topSortedIndex]; + Result := SystemPersistenceMapper.ObjectPersistenceMappers[NewID.topSortedIndex]; + end; + + procedure EnsureActionList; + begin + if not Assigned(ActionList) then + ActionList := TBoldObjectIdList.Create; end; begin - EnsureIDsExact(ObjectIDList, translationList); - tempList := ObjectidLIst.Clone; + EnsureIDsExact(ObjectIDList, translationList, false); + SetLength(TempList, ObjectIdList.Count); + SetLength(NewTempList, ObjectIdList.Count); + for i := 0 to ObjectidList.Count - 1 do + TempList[i] := ObjectIdList[i]; MissingList := TBoldObjectIdList.Create; + NewTempCount := 0; + ActionList := nil; try - while TempList.Count > 0 do + while Length(TempList) > 0 do begin - ActionList := TBoldObjectIdList.Create; + EnsureActionList; try - CurrentPMapper := ObjectMapperForNewID(TempList[0]); - if (TempList.Count > 1) and Assigned(MemberIdList) and (MemberIdList.Count = 1) then + CurrentPMapper := ObjectMapperForNewID(TempList[0], TranslationList); + if (Length(TempList) > 1) and Assigned(MemberIdList) and (MemberIdList.Count = 1) then begin - // Find the most Common ObjectMapper - for i := 1 to TempList.Count - 1 do + for i := 1 to Length(TempList) - 1 do begin - TempMapper := ObjectMapperForNewID(TempList[i]); + TempMapper := ObjectMapperForNewID(TempList[i], TranslationList); CurrentPMapper := CurrentPMapper.LeastCommonSuperMapper(TempMapper); end; - // mnake sure it has the member requested MemberMapperIndex := CurrentPMapper.MemberMapperIndexByMemberIndex[MemberIdList[0].MemberIndex]; if MemberMapperIndex <> -1 then begin MemberMapper := CurrentPMapper.MemberPersistenceMappers[MemberMapperIndex]; if MemberMapper.SupportsPolymorphicFetch then begin - ActionList.AddList(TempList); - TempList.Clear; + for i := 0 to Length(TempList) - 1 do + ActionList.Add(TempList[i]); + SetLength(TempList, 0); end; end; - // check if it was OK to fetch polymorphic, otherwise restore old PMapper. if ActionList.Count = 0 then - CurrentPMapper := ObjectMapperForNewID(TempList[0]); + CurrentPMapper := ObjectMapperForNewID(TempList[0], TranslationList); end; - i := 0; - while i < TempList.Count do - if ObjectMapperForNewID(TempList[i]) = CurrentPMapper then + for i := 0 to Length(TempList) - 1 do + if ObjectMapperForNewID(TempList[i], TranslationList) = CurrentPMapper then begin ActionList.Add(TempList[i]); - TempList.RemoveByIndex(i); end else - Inc(i); + begin + NewTempList[NewTempCount] := TempList[i]; + INC(NewTempCount); + end; CurrentPMapper.PMFetchExactIDList(ActionList, ValueSpace, MemberIdList, FetchMode, TranslationList, MissingList); finally - ActionList.Free; + ActionList.Clear; end; + SetLength(NewTempList, NewTempCount); + TempList:= NewTempList; + NewTempList := nil; + SetLength(NewTempList, NewTempCount); + NewTempCount := 0; end; if FetchMode = fmDistributable then if MissingList.Count > 0 then SystemPersistenceMapper.FetchDeletedObjects(MissingList, ValueSpace); finally - TempList.Free; + ActionList.free; MissingList.Free; end; end; -procedure TBoldObjectPersistenceMapper.EnsureIDsExact(ObjectIDList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList); +procedure TBoldObjectPersistenceMapper.EnsureIDsExact(ObjectIDList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList; HandleNonExisting: Boolean); var InexactIDList: TBoldObjectIdList; - ObjectID: TBoldObjectId; i: integer; g: IBoldGuard; begin g := TBoldGuard.Create(InexactIDList); - InexactIDList := TBoldObjectIdList.Create; - + InexactIDList := nil; for i := 0 to ObjectIDList.Count - 1 do begin - ObjectID := ObjectIDList[i]; - if not ObjectId.TopSortedIndexExact then - InexactIDList.Add(ObjectID); + if not ObjectIDList[i].TopSortedIndexExact then + begin + if not Assigned(InexactIDList) then + begin + InexactIDList := TBoldObjectIdList.Create; + InexactIDList.Capacity := ObjectIDList.Count-i; + end; + InexactIDList.Add(ObjectIDList[i]); + end; end; - if InExactIDList.Count > 0 then - MakeIDsExact(InexactIDList, TranslationList); + if Assigned(InexactIDList) and (InExactIDList.Count > 0) then + MakeIDsExact(InexactIDList, TranslationList, HandleNonExisting); end; procedure TBoldObjectPersistenceMapper.FillInMembers(MyMoldClass, CurrentMoldClass: TMoldClass; TypeNameDictionary: TBoldTypeNameDictionary); @@ -791,10 +806,10 @@ procedure TBoldObjectPersistenceMapper.FillInMembers(MyMoldClass, CurrentMoldCla MapperName := Mapping.ExpandedMapperName; end; - raise EBold.CreateFmt( sUnableToFindPMapperForX+ BOLDCRLF + - sUnableReason1 + BOLDCRLF + - sUnableReason2 + BOLDCRLF + - sUnableReason3, [ + raise EBold.CreateFmt('Unable to find persistence mapper for %s.%s (type: %s, mapper: %s). possible reasons: '+BOLDCRLF + + '* Typo'+BOLDCRLF+ + '* The mapper is not correctly installed in the initialization clause'+BOLDCRLF+ + '* The unit with the mapper is not included in the project', [ MoldAttribute.MoldClass.ExpandedExpressionName, MoldAttribute.ExpandedExpressionName, MoldAttribute.BoldType, @@ -816,34 +831,34 @@ procedure TBoldObjectPersistenceMapper.FillInMembers(MyMoldClass, CurrentMoldCla IsIndirect := assigned(MoldRole.Association.LinkClass); if MoldRole.Multi then if IsIndirect then - MemberDescriptor := BoldMemberPersistenceMappers.DescriptorByDelphiName['TBoldIndirectMultiLinkDefaultMapper'] // do not localize + MemberDescriptor := BoldMemberPersistenceMappers.DescriptorByDelphiName['TBoldIndirectMultiLinkDefaultMapper'] else - MemberDescriptor := BoldMemberPersistenceMappers.DescriptorByDelphiName['TBoldDirectMultiLinkDefaultMapper'] // do not localize + MemberDescriptor := BoldMemberPersistenceMappers.DescriptorByDelphiName['TBoldDirectMultiLinkDefaultMapper'] else if MoldRole.EffectiveEmbedded then - MemberDescriptor := BoldMemberPersistenceMappers.DescriptorByDelphiName['TBoldEmbeddedSingleLinkDefaultMapper'] // do not localize + MemberDescriptor := BoldMemberPersistenceMappers.DescriptorByDelphiName['TBoldEmbeddedSingleLinkDefaultMapper'] else if IsIndirect then - MemberDescriptor := BoldMemberPersistenceMappers.DescriptorByDelphiName['TBoldIndirectSingleLinkDefaultMapper'] // do not localize + MemberDescriptor := BoldMemberPersistenceMappers.DescriptorByDelphiName['TBoldIndirectSingleLinkDefaultMapper'] else - MemberDescriptor := BoldMemberPersistenceMappers.DescriptorByDelphiName['TBoldDirectSingleLinkDefaultMapper']; // do not localize + MemberDescriptor := BoldMemberPersistenceMappers.DescriptorByDelphiName['TBoldDirectSingleLinkDefaultMapper']; end else begin MemberDescriptor := BoldMemberPersistenceMappers.DescriptorByDelphiName[MoldRole.PMapperName]; if not assigned(MemberDescriptor) then - raise EBold.CreateFmt(sUnableToFindPMapperForXY, [MoldRole.MoldClass.ExpandedExpressionName, MoldRole.ExpandedExpressionName, MoldRole.PMappername]); + raise EBold.CreateFmt('Unable to find PersistenceMapper for %s.%s (mapper: %s)', [MoldRole.MoldClass.ExpandedExpressionName, MoldRole.ExpandedExpressionName, MoldRole.PMappername]); end; end; rtLinkRole: if MoldRole.MainRole.EffectivePersistent then begin if MoldRole.MainRole.Multi then - MemberDescriptor := BoldMemberPersistenceMappers.DescriptorByDelphiName['TBoldDirectMultiLinkDefaultMapper'] // do not localize + MemberDescriptor := BoldMemberPersistenceMappers.DescriptorByDelphiName['TBoldDirectMultiLinkDefaultMapper'] else - MemberDescriptor := BoldMemberPersistenceMappers.DescriptorByDelphiName['TBoldDirectSingleLinkDefaultMapper'] // do not localize + MemberDescriptor := BoldMemberPersistenceMappers.DescriptorByDelphiName['TBoldDirectSingleLinkDefaultMapper'] end; rtInnerLinkRole: begin if MoldRole.EffectivePersistent and CurrentMoldClass.EffectivePersistent then - MemberDescriptor := BoldMemberPersistenceMappers.DescriptorByDelphiName['TBoldEmbeddedSingleLinkDefaultMapper']; // do not localize + MemberDescriptor := BoldMemberPersistenceMappers.DescriptorByDelphiName['TBoldEmbeddedSingleLinkDefaultMapper']; if fLinkRoleMapperIndex1 = -1 then fLinkRoleMapperIndex1 := MemberPersistenceMappers.Count else @@ -877,6 +892,11 @@ function TBoldObjectPersistenceMapper.BoldIsA(ObjectPMapper: TBoldObjectPersiste result := fSuperClass.BoldIsA(ObjectPMapper); end; +function TBoldMemberPersistenceMapperList.GetMemberMapperByExpressionName(ExpressionName: string): TBoldMemberPersistenceMapper; +begin + result := (Indexes[IX_MemberMapper] as TBoldMemberMapperIndex).FindByString(ExpressionName) as TBoldMemberPersistenceMapper; +end; + { TBoldMemberPersistenceMapper } class function TBoldMemberPersistenceMapper.CanStore(const ContentName: string): Boolean; begin @@ -895,7 +915,7 @@ constructor TBoldMemberPersistenceMapper.CreateFromMold(Moldmember: TMoldmember; fExpressionName := MoldMember.ExpandedExpressionName; if assigned(Owner.MemberPersistenceMappers.MemberMapperByExpressionName[fExpressionName]) then - raise EBold.CreateFmt(sDuplicatePMappersForXInY, [fExpressionName, Owner.ExpressionName]); + raise EBold.CreateFmt('Duplicate memberMappers called "%s" in class %s', [fExpressionName, Owner.ExpressionName]); if MoldMember is TMoldAttribute then begin @@ -927,33 +947,28 @@ constructor TBoldMemberPersistenceMapper.CreateFromMold(Moldmember: TMoldmember; end; end; -procedure TBoldMemberPersistenceMapper.PMCreate(ObjectIdList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList); +procedure TBoldMemberPersistenceMapper.PMCreate(ObjectIdList: TBoldObjectIdList; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList); begin - raise EBold.CreateFmt(sCallToAbstractMethodOnCustomMapper, ['TBoldMemberPersistenceMapper', 'PMCreate', classname, 'PMCreate']); // do not localize + raise EBold.CreateFmt(sCallToAbstractMethodOnCustomMapper, ['TBoldMemberPersistenceMapper', 'PMCreate', classname, 'PMCreate']); end; -procedure TBoldMemberPersistenceMapper.PMUpdate(ObjectIdList: TBoldObjectIdList; ValueSpace: IBoldValueSpace;TranslationList: TBoldIdTranslationList); +procedure TBoldMemberPersistenceMapper.PMUpdate(ObjectIdList: TBoldObjectIdList; const ValueSpace: IBoldValueSpace;TranslationList: TBoldIdTranslationList); begin - raise EBold.CreateFmt(sCallToAbstractMethodOnCustomMapper, ['TBoldMemberPersistenceMapper', 'PMUpDate', classname, 'PMUpDate']); // do not localize + raise EBold.CreateFmt(sCallToAbstractMethodOnCustomMapper, ['TBoldMemberPersistenceMapper', 'PMUpDate', classname, 'PMUpDate']); end; -procedure TBoldMemberPersistenceMapper.PMDelete(ObjectIdList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList); +procedure TBoldMemberPersistenceMapper.PMDelete(ObjectIdList: TBoldObjectIdList; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList); begin - raise EBold.CreateFmt(sCallToAbstractMethodOnCustomMapper, ['TBoldMemberPersistenceMapper', 'PMDelete', classname, 'PMDelete']); // do not localize + raise EBold.CreateFmt(sCallToAbstractMethodOnCustomMapper, ['TBoldMemberPersistenceMapper', 'PMDelete', classname, 'PMDelete']); end; -procedure TBoldMemberPersistenceMapper.PMFetch(ObjectIdList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; FetchMode: Integer; TranslationList: TBoldIdTranslationList; FailureList: TBoldObjectIdList); +procedure TBoldMemberPersistenceMapper.PMFetch(ObjectIdList: TBoldObjectIdList; const ValueSpace: IBoldValueSpace; FetchMode: Integer; TranslationList: TBoldIdTranslationList; FailureList: TBoldObjectIdList); begin - raise EBold.CreateFmt(sCallToAbstractMethodOnCustomMapper, ['TBoldMemberPersistenceMapper', 'PMFetch', classname, 'PMFetch']); // do not localize -end; - -{ TBoldObjectPersistenceMapperList } -function TBoldObjectPersistenceMapperList.GetItem(index: Integer): TBoldObjectPersistenceMapper; -begin - Result := TBoldObjectPersistenceMapper(inherited Items[index]); + raise EBold.CreateFmt(sCallToAbstractMethodOnCustomMapper, ['TBoldMemberPersistenceMapper', 'PMFetch', classname, 'PMFetch']); end; { TBoldMemberPersistenceMapperList } + constructor TBoldMemberPersistenceMapperList.Create; begin inherited; @@ -994,16 +1009,25 @@ procedure TBoldObjectPersistenceMapper.BuildMemberFetchLists( end; var - i: integer; + i, MapperIndex: integer; begin assert(not assigned(DefaultFetchMemberList) or not DefaultFetchMemberList.OwnsEntries, 'Cannot put member mappers in a member mapper list that owns its entries.'); assert(not assigned(CustomFetchMemberList) or not CustomFetchMemberList.OwnsEntries, 'Cannot put member mappers in a member mapper list that owns its entries.'); if assigned(MemberIdList) then for i := 0 to MemberIdList.Count - 1 do - TestAdd(MemberPersistenceMappers[MemberMapperIndexByMemberIndex[MemberIdList[i].MemberIndex]]) + begin + MapperIndex := MemberMapperIndexByMemberIndex[MemberIdList[i].MemberIndex]; + if MapperIndex = -1 then + raise EBold.CreateFmt('%s.BuildMemberFetchLists: MemberMapperIndexByMemberIndex not found. Possibly TimeStamp tag not selected in the model', [classname]); + TestAdd(MemberPersistenceMappers[MapperIndex]); + end else + begin + if Assigned(DefaultFetchMemberList) then + DefaultFetchMemberList.Capacity := MemberPersistenceMappers.Count; for i := 0 to MemberPersistenceMappers.Count - 1 do TestAdd(MemberPersistenceMappers[i]); + end; end; function TBoldObjectPersistenceMapper.GetLinkClassRole1: TBoldMemberPersistenceMapper; @@ -1033,11 +1057,6 @@ procedure TBoldSystemPersistenceMapper.SubscribeToPersistenceEvents( AddSubscription(Subscriber, bpeFetchId, bpeFetchId); end; -function TBoldMemberPersistenceMapperList.GetMemberMapperByExpressionName(ExpressionName: string): TBoldMemberPersistenceMapper; -begin - result := (Indexes[IX_MemberMapper] as TBoldMemberMapperIndex).FindByString(ExpressionName) as TBoldMemberPersistenceMapper; -end; - { TBoldMemberMapperIndex } function TBoldMemberMapperIndex.ItemASKeyString(Item: TObject): string; @@ -1051,7 +1070,7 @@ function TBoldSystemPersistenceMapper.CommonSuperClassObjectMapper( i: Integer; begin if ObjectIdList.Count = 0 then - raise EBold.CreateFmt(sObjectIDListIsEmpty, [classname]); + raise EBold.CreateFmt('%s.CommonSuperClassObjectMapper: ObjectIdList is empty', [classname]); result := ObjectPersistenceMappers[ObjectIdList[0].TopSortedIndex]; for i := 1 to ObjectIdList.Count - 1 do @@ -1117,7 +1136,7 @@ procedure TBoldMemberPersistenceMapper.InitializePSDescriptions; end; function TBoldMemberPersistenceMapper.IsDirty( - ObjectContents: IBoldObjectContents): Boolean; + const ObjectContents: IBoldObjectContents): Boolean; var aValue: IBoldValue; begin @@ -1133,7 +1152,7 @@ function TBoldMemberPersistenceMapper.IsDirty( end; end; -function TBoldMemberPersistenceMapper.GetValue(ObjectContents: IBoldObjectContents): IBoldValue; +function TBoldMemberPersistenceMapper.GetValue(const ObjectContents: IBoldObjectContents): IBoldValue; begin if MemberIndex <> -1 then result := ObjectContents.ValueByIndex[MemberIndex] @@ -1141,21 +1160,15 @@ function TBoldMemberPersistenceMapper.GetValue(ObjectContents: IBoldObjectConten result := nil; end; -function TBoldMemberPersistenceMapper.GetEnsuredValue(ObjectContents: IBoldObjectContents): IBoldValue; -var - MemberId: TBoldMemberId; - g: IBoldGuard; +function TBoldMemberPersistenceMapper.GetEnsuredValue(const ObjectContents: IBoldObjectContents): IBoldValue; begin - g := TBoldGuard.Create(MemberId); if MemberIndex <> -1 then - begin - MemberId := TBoldMemberId.Create(MemberINdex); - ObjectContents.EnsureMember(MemberId, ContentName); - end; - result := GetValue(ObjectContents); + Result := ObjectContents.EnsureMemberAndGetValueByIndex(MemberIndex, ContentName) + else + Result := nil; end; -function TBoldMemberPersistenceMapper.ShouldFetch(ObjectContents: IBoldObjectContents): Boolean; +function TBoldMemberPersistenceMapper.ShouldFetch(const ObjectContents: IBoldObjectContents): Boolean; var aValue: IBoldValue; begin @@ -1175,11 +1188,6 @@ function TBoldObjectPersistenceMapper.GetMemberMapperIndexByMemberIndex(const Me else if MemberIndex < 0 then begin result := -1; - // the Timestamp-member has memberindex below 0 since it is a technical member... - // unfortunately it is also among the last members so this will be a bit slow. - // think of a better solution - // currently it is only called once per update-operation, and only on the rootclass - // mapper which does normally not have that many members, so the problem is more theoretical. for i := 0 to MemberPersistenceMappers.count - 1 do if MemberPersistenceMappers[i].MemberIndex = MemberIndex then begin @@ -1212,4 +1220,8 @@ function TBoldMemberPersistenceMapper.GetSupportsPolymorphicFetch: Boolean; result := false; end; +initialization + TBoldMemberPersistenceMapperList.IX_MemberMapper := -1; + end. + diff --git a/Source/PMapper/Core/BoldPSDescriptions.pas b/Source/PMapper/Core/BoldPSDescriptions.pas index 33d156f..97ffa4c 100644 --- a/Source/PMapper/Core/BoldPSDescriptions.pas +++ b/Source/PMapper/Core/BoldPSDescriptions.pas @@ -1,20 +1,24 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldPSDescriptions; interface uses + BoldBase, BoldPSParams; - + type TBoldPSDescriptionElement = class; TBoldPSSystemDescription = class; {---TBoldPSDescriptionElement---} - TBoldPSDescriptionElement = class + TBoldPSDescriptionElement = class(TBoldMemoryManagedObject) private fOwner: TBoldPSDescriptionElement; public - constructor Create(aOwner: TBoldPSDescriptionElement); + constructor Create(aOwner: TBoldPSDescriptionElement); property Owner: TBoldPSDescriptionElement read fOwner; end; @@ -26,10 +30,15 @@ TBoldPSSystemDescription = class(TBoldPSDescriptionElement) implementation +uses + BoldRev; + {---TBoldPSDescriptionElement---} constructor TBoldPSDescriptionElement.Create(aOwner: TBoldPSDescriptionElement); begin fOwner := aOwner; end; +initialization + end. diff --git a/Source/PMapper/Core/BoldPSParams.pas b/Source/PMapper/Core/BoldPSParams.pas index 3c7fdb5..c97ce52 100644 --- a/Source/PMapper/Core/BoldPSParams.pas +++ b/Source/PMapper/Core/BoldPSParams.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldPSParams; interface @@ -11,9 +14,14 @@ TBoldPSParams = class implementation +uses + BoldRev; + constructor TBoldPSParams.Create; begin inherited; end; +initialization + end. diff --git a/Source/PMapper/DbEvolutor/BoldDbEvolutor.pas b/Source/PMapper/DbEvolutor/BoldDbEvolutor.pas index 4cfa556..73e7323 100644 --- a/Source/PMapper/DbEvolutor/BoldDbEvolutor.pas +++ b/Source/PMapper/DbEvolutor/BoldDbEvolutor.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldDbEvolutor; interface @@ -52,16 +55,18 @@ TBoldDataBaseEvolutor = class procedure MoveDataAction(NewMemberMapping, OldMemberMapping: TBoldMemberMappingInfo; Param: TObject); procedure DetectTypeClashesAction(NewMemberMapping, OldMemberMapping: TBoldMemberMappingInfo; Param: TObject); procedure DetectMapperChange(NewMemberMapping, OldMemberMapping: TBoldMemberMappingInfo; Param: TObject); - procedure AddCommandToScript(Script: TStrings; s: string); + function DifferenceInColumns(const AColumns, BColumns: String): string; protected procedure InitializeTableData(TableList, ColumnList: TStringList; MappingInfo: TBoldSQLMappingInfo); procedure AddNewTables; procedure AddNewColumns; procedure AddNewInstances; + procedure AddNewIndexes; procedure MoveData; procedure DeleteOldInstances; procedure DropOldColumns; procedure DropOldTables; + procedure DropOldIndexes; procedure MergeOldDbTypes; procedure DetectTypeClashes; property OldMapping: TBoldSQLMappingInfo read fOldMapping; @@ -97,21 +102,22 @@ implementation BoldDbInterfaces, SysUtils, BoldUtils, - BoldPMConsts; + BoldGuard; { TBoldDataBaseEvolutor } procedure TBoldDataBaseEvolutor.AddNewColumns; var - i: integer; + i, dotIndex: integer; TableName, ColumnName: String; NewTable: TBoldSQLTableDescription; NewColumn: TBoldSQLColumnDescription; begin for i := 0 to NewColumns.Count - 1 do begin - TableName := Copy(NewColumns[i], 1, pos('.', NewColumns[i]) - 1); - ColumnName := Copy(NewColumns[i], pos('.', NewColumns[i]) + 1, maxint); + dotIndex := pos('.', NewColumns[i]); + TableName := Copy(NewColumns[i], 1, dotIndex - 1); + ColumnName := Copy(NewColumns[i], dotIndex + 1, maxint); if (OldColumns.IndexOf(NewColumns[i]) = -1) and (OldTables.IndexOf(TableName) <> -1) then begin NewTable := NewPSDescription.SQLTablesList.ItemsBySQLName[TableName]; @@ -122,48 +128,85 @@ procedure TBoldDataBaseEvolutor.AddNewColumns; end; end; +function ContainsIndex(IndexDefs: TBoldIndexDescriptionArray; Columns: WideString): Boolean; +var + i: Integer; +begin + for I := 0 to Length(IndexDefs) - 1 do + if BoldNamesEqual(IndexDefs[i].IndexedColumns, Columns) then + begin + Result := true; + Exit; + end; + Result := false; +end; + +procedure TBoldDataBaseEvolutor.AddNewIndexes; +var + Def, i: integer; + TableName: String; + BoldTable: TBoldSQLTableDescription; + AllTables: TStringList; + IndexDefs: TBoldIndexDescriptionArray; + g: IBoldGuard; +begin + g := TBoldGuard.Create(AllTables); + AllTables := TStringList.Create; + PersistenceHandle.DataBaseInterface.AllTableNames('', true, AllTables); + AllTables.CaseSensitive := false; + for i := 0 to AllTables.Count - 1 do + begin + TableName := UpperCase(AllTables[i]); + BoldTable := NewPSDescription.SQLTablesList.ItemsBySQLName[TableName]; + if not Assigned(BoldTable) then + Continue; + IndexDefs := PersistenceHandle.DataBaseInterface.GetIndexDescriptions(TableName); + for Def := 0 to BoldTable.IndexList.Count - 1 do + begin + if not ContainsIndex(IndexDefs, BoldTable.IndexList[Def].IndexedFields) then + Script.AddIndex(BoldTable.IndexList[Def]); + end; + end; +end; + procedure TBoldDataBaseEvolutor.AddNewInstances; var i, t: integer; NewTables: TStringList; OldExprName, ExprName: String; OldAllInstances: TBoldAllInstancesMappingArray; + g: IBoldGuard; begin - // in order not to add data more than once, we must loop over the PMapper, and not the mappinginfo + g := TBoldGuard.Create(NewTables); OldAllInstances := nil; NewTables := TStringList.Create; - try - for i := 0 to PMapper.ObjectPersistenceMappers.Count - 1 do + for i := 0 to PMapper.ObjectPersistenceMappers.Count - 1 do + begin + if assigned(PMapper.ObjectPersistenceMappers[i]) then begin - if assigned(PMapper.ObjectPersistenceMappers[i]) then + ExprName := PMapper.ObjectPersistenceMappers[i].ExpressionName; + OldExprName := TranslateClassExpressionName(ExprName, NewMapping, OldMapping); + if (OldExprName <> '') and HasOldInstances(OldExprName) then begin - ExprName := PMapper.ObjectPersistenceMappers[i].ExpressionName; - OldExprName := TranslateClassExpressionName(ExprName, NewMapping, OldMapping); - if (OldExprName <> '') and HasOldInstances(OldExprName) then + GetAllTablesForClass(ExprName, NewMapping, NewTables); + for t := 0 to NewTables.Count - 1 do begin - GetAllTablesForClass(ExprName, NewMapping, NewTables); - for t := 0 to NewTables.Count - 1 do + if not HasStorageMapping(OldExprName, NewTables[t], OldMapping) then begin - if not HasStorageMapping(OldExprName, NewTables[t], OldMapping) then - begin - OldAllInstances := OldMapping.GetAllInstancesMapping(OldExprName); - // what if more than 1 or = 0 - if Length(OldAllInstances) = 1 then - Script.CopyInstances( - ExprName, - OldAllInstances[0].TableName, - NewTables[t], - GetCommonPrimaryKeyColumns( - GetPrimaryIndexForExistingTable(OldAllInstances[0].TableName), - GetPrimaryIndexForNewTable(NewTables[t])), - OldMapping.GetDbTypeMapping(OldExprName)) - end; + OldAllInstances := OldMapping.GetAllInstancesMapping(OldExprName); + if Length(OldAllInstances) = 1 then + Script.CopyInstances( + ExprName, + OldAllInstances[0].TableName, + NewTables[t], + GetCommonPrimaryKeyColumns( + GetPrimaryIndexForExistingTable(OldAllInstances[0].TableName), + GetPrimaryIndexForNewTable(NewTables[t])), + OldMapping.GetDbTypeMapping(OldExprName)) end; end; end; end; - finally - NewTables.free; end; end; @@ -180,7 +223,7 @@ procedure TBoldDataBaseEvolutor.AddNewTables; Script.AddTable(NewTable); Script.AddSQLStatement( - format('INSERT INTO %s (%s) VALUES (''%s'')', [ // do not localize + format('INSERT INTO %s (%s) VALUES (''%s'')', [ BoldExpandPrefix(TABLETABLE_NAME, '', PersistenceHandle.SQLDataBaseConfig.SystemTablePrefix, NewPSDescription.SQLDatabaseConfig.MaxDBIdentifierLength, NewPSDescription.NationalCharConversion), TABLENAMECOLUMN_NAME, Newtable.SQLName])); @@ -221,7 +264,6 @@ procedure TBoldDataBaseEvolutor.DeleteOldInstances; OldExprName := OldMapping.ObjectStorageMappings[i].ClassExpressionName; OldTableName := OldMapping.ObjectStorageMappings[i].TableName; NewExprName := TranslateClassExpressionName(OldExprName, OldMapping, NewMapping); - // either the class does not exist anymore, or it is no longer stored in that table if HasOldInstances(OldExprName) and (Newtables.IndexOf(OldtableName) <> -1) and ((NewExprName = '') or not HasStorageMapping(NewExprName, OldTableName, NewMapping)) then @@ -248,42 +290,78 @@ destructor TBoldDataBaseEvolutor.destroy; procedure TBoldDataBaseEvolutor.DropOldColumns; var - Def, i: integer; - TableName, ColumnName: String; - Table: IBoldTable; + Def, i, index, dotIndex: integer; + s, TableName, ColumnName: String; IndexedColumns: TStringList; + AllTables: TStringList; + IndexDefs: TBoldIndexDescriptionArray; + t: Integer; + g: IBoldGuard; begin + g := TBoldGuard.Create(AllTables, IndexedColumns); IndexedColumns := TStringList.Create; IndexedColumns.Sorted := true; OldColumns.Sort; - Table := PersistenceHandle.DataBaseInterface.GetTable; - try - for i := 0 to OldColumns.Count - 1 do + AllTables := TStringList.Create; + PersistenceHandle.DataBaseInterface.AllTableNames('', true, AllTables); + AllTables.CaseSensitive := false; + for i := 0 to OldColumns.Count - 1 do + begin + dotIndex := pos('.', OldColumns[i]); + s := Copy(OldColumns[i], 1, dotIndex - 1); + if s <> TableName then begin - TableName := Copy(OldColumns[i], 1, pos('.', OldColumns[i]) - 1); - ColumnName := Copy(OldColumns[i], pos('.', OldColumns[i]) + 1, maxint); - if (NewColumns.IndexOf(OldColumns[i]) = -1) and (NewTables.IndexOf(TableName) <> -1) then + TableName := s; + index := AllTables.IndexOf(TableName); + if index < 0 then + continue; // raise Exception.Create(TableName + ' not found at index ' + IntToStr(i)); + IndexDefs := PersistenceHandle.DataBaseInterface.GetIndexDescriptions(TableName); + end; + ColumnName := Copy(OldColumns[i], dotIndex + 1, maxint); + if (NewColumns.IndexOf(OldColumns[i]) = -1) and (NewTables.IndexOf(TableName) <> -1) then + begin + for Def := 0 to Length(IndexDefs) - 1 do begin - // first time and every new table - if (i = 0) or (TableName <> Table.TableName) then - begin - // retrieve fresh indexdefs - Table.Tablename := TableName; - Table.IndexDefs.Update; - end; - // see if any indices needs to be dropped - for Def := 0 to Table.IndexDefs.Count - 1 do + IndexedColumns.CommaText := UpperCase(StringReplace(IndexDefs[Def].IndexedColumns, ';', ',', [rfReplaceAll])); + if IndexedColumns.IndexOf(UpperCase(ColumnName)) <> -1 then begin - IndexedColumns.CommaText := UpperCase(StringReplace(Table.IndexDefs[Def].Fields, ';', ',', [rfReplaceAll])); - if IndexedColumns.IndexOf(UpperCase(ColumnName)) <> -1 then - Script.DropIndex(Table.IndexDefs[Def].Name, Table.Tablename); + if not fPreScript.HasDropIndex(IndexDefs[Def].IndexName, Tablename) then + Script.DropIndex(IndexDefs[Def].IndexName, Tablename); end; - Script.DropColumn(TableName, ColumnName); end; + if not fPreScript.HasDropColumn(TableName, ColumnName) then + Script.DropColumn(TableName, ColumnName); + end; + end; +end; + +procedure TBoldDataBaseEvolutor.DropOldIndexes; +var + Def, i: integer; + TableName: String; + BoldTable: TBoldSQLTableDescription; + AllTables: TStringList; + IndexDefs: TBoldIndexDescriptionArray; + g: IBoldGuard; +begin + g := TBoldGuard.Create(AllTables); + AllTables := TStringList.Create; + PersistenceHandle.DataBaseInterface.AllTableNames('', true, AllTables); + AllTables.CaseSensitive := false; + for i := 0 to AllTables.Count - 1 do + begin + TableName := UpperCase(AllTables[i]); + BoldTable := NewPSDescription.SQLTablesList.ItemsBySQLName[TableName]; + if not Assigned(BoldTable) then + Continue; + IndexDefs := PersistenceHandle.DataBaseInterface.GetIndexDescriptions(TableName); + for Def := 0 to Length(IndexDefs) - 1 do + begin + if PersistenceHandle.SQLDataBaseConfig.EvolveDropsUnknownIndexes and + not Assigned(BoldTable.IndexList.ItemsByIndexFields[IndexDefs[Def].IndexedColumns]) and + not fPreScript.HasDropIndex(IndexDefs[Def].IndexName, Tablename) then + Script.DropIndex(IndexDefs[Def].IndexName, Tablename); end; - finally - IndexedColumns.Free; - PersistenceHandle.DataBaseInterface.releaseTable(Table); end; end; @@ -296,7 +374,7 @@ procedure TBoldDataBaseEvolutor.DropOldTables; begin Script.DropTable(OldTables[i]); Script.AddSQLStatement( - Format('DELETE FROM %s WHERE UPPER(%s)=''%s''', [ // do not localize + Format('DELETE FROM %s WHERE UPPER(%s)=''%s''', [ BoldExpandPrefix(TABLETABLE_NAME, '', PersistenceHandle.SQLDataBaseConfig.SystemTablePrefix, NewPSDescription.SQLDatabaseConfig.MaxDBIdentifierLength, NewPSDescription.NationalCharConversion), TABLENAMECOLUMN_NAME, uppercase(OldTables[i])])); @@ -306,9 +384,9 @@ procedure TBoldDataBaseEvolutor.DropOldTables; procedure TBoldDataBaseEvolutor.CalculateScript; begin if PersistenceHandle.Active then - raise EBold.CreateFmt(sPersistenceHandleActive, [classname, PersistenceHandle.Name]); + raise EBold.CreateFmt('%s.CalculateScript: PersistenceHandle %s is active. unable to execute', [classname, PersistenceHandle.Name]); - BoldLog.LogHeader := sInitializingScript; + BoldLog.LogHeader := 'Initializing Script'; BoldLog.ProgressMax := 10; try PMapper.OpenDatabase(false, false); @@ -317,7 +395,7 @@ procedure TBoldDataBaseEvolutor.CalculateScript; BoldLog.ProgressStep; fUnHandledMemberMappings.Clear; fUnhandledMemberMappings.FillFromList(OldMapping.MemberMappings); - + if not GenericScript then LoadExistingInstances; @@ -330,9 +408,13 @@ procedure TBoldDataBaseEvolutor.CalculateScript; AddNewTables; BoldLog.ProgressStep; AddNewColumns; BoldLog.ProgressStep; AddNewINstances; BoldLog.ProgressStep; + AddNewIndexes; BoldLog.ProgressStep; MoveData; BoldLog.ProgressStep; - DeleteOldInstances; BoldLog.ProgressStep; - DropOldColumns; BoldLog.ProgressStep; + DropOldIndexes; BoldLog.ProgressStep; + DeleteOldInstances; + BoldLog.ProgressStep; + DropOldColumns; + BoldLog.ProgressStep; DropOldTables; BoldLog.ProgressStep; Script.OptimizeScript; MergeOldDbTypes; @@ -385,23 +467,21 @@ function TBoldDataBaseEvolutor.HasOldInstances(const OldExpressionName: String): function TBoldDataBaseEvolutor.HasStorageMapping(const ExpressionName, TableName: String; Mapping: TBoldSQLMappingInfo): Boolean; var - tables: TStringList; + Tables: TStringList; i: integer; + g: IBoldGuard; begin + g := TBoldGuard.Create(Tables); result := false; Tables := TStringList.Create; - try - GetAllTablesForClass(ExpressionName, Mapping, Tables); - for i := 0 to Tables.Count - 1 do + GetAllTablesForClass(ExpressionName, Mapping, Tables); + for i := 0 to Tables.Count - 1 do + begin + if SameText(Tables[i], TableName) then begin - if SameText(Tables[i], TableName) then - begin - result := true; - break; - end; + result := true; + break; end; - finally - Tables.Free; end; end; @@ -414,23 +494,21 @@ procedure TBoldDataBaseEvolutor.InitializeTableData(TableList, ColumnList: TStri var i, j: integer; Columns: TStringList; + g: IBoldGuard; begin + g := TBoldGuard.Create(Columns); for i := 0 to MappingInfo.ObjectStorageMappings.Count - 1 do AddName(MappingInfo.ObjectStorageMappings[i].TableName, TableList); for i := 0 to MappingInfo.AllInstancesMappings.Count - 1 do AddName(MappingInfo.AllInstancesMappings[i].TableName, TableList); Columns := TStringList.Create; - try - for i := 0 to MappingInfo.MemberMappings.Count - 1 do - begin - AddName(MappingInfo.MemberMappings[i].TableName, TableList); - Columns.CommaText := MappingInfo.MemberMappings[i].Columns; - for j := 0 to Columns.Count - 1 do - AddName(MappingInfo.MemberMappings[i].TableName + '.' + Columns[j], ColumnList); - end; - finally - Columns.Free; - end + for i := 0 to MappingInfo.MemberMappings.Count - 1 do + begin + AddName(MappingInfo.MemberMappings[i].TableName, TableList); + Columns.CommaText := MappingInfo.MemberMappings[i].Columns; + for j := 0 to Columns.Count - 1 do + AddName(MappingInfo.MemberMappings[i].TableName+'.' + Columns[j], ColumnList); + end; end; procedure TBoldDataBaseEvolutor.LoadExistingInstances; @@ -439,7 +517,7 @@ procedure TBoldDataBaseEvolutor.LoadExistingInstances; begin query := PersistenceHandle.DataBaseInterface.GetQuery; try - query.AssignSQLText(format('SELECT DISTINCT BOLD_TYPE FROM %s', [OldRootTableName])); // do not localize + query.AssignSQLText(format('SELECT DISTINCT BOLD_TYPE FROM %s', [OldRootTableName])); Query.Open; while not QUery.Eof do begin @@ -459,7 +537,6 @@ procedure TBoldDataBaseEvolutor.ForEachMemberMappingPair(Action: TBoldMemberMapp OldMemberMappings: TBoldMemberMappingArray; NewMemberName, OldMemberName, NewExprName, OldExprName: String; begin - // in order not to move data more than once, we must loop over the PMapper, and not the mappinginfo OldMemberMappings := nil; NewMemberMappings := nil; for i := 0 to PMapper.ObjectPersistenceMappers.Count - 1 do @@ -476,7 +553,6 @@ procedure TBoldDataBaseEvolutor.ForEachMemberMappingPair(Action: TBoldMemberMapp begin NewMemberName := PMapper.ObjectPersistenceMappers[i].MemberPersistenceMappers[j].ExpressionName; NewMemberMappings := NewMapping.GetMemberMappings(NewExprName, NewMemberName); - // do we need to worry about lengths = 0, lengths > 1? if length(NewMemberMappings) = 1 then begin OldMemberName := TranslateMemberName(NewExprName, NewMemberName, OldExprName, NewMapping, OldMapping); @@ -514,26 +590,23 @@ procedure TBoldDataBaseEvolutor.MoveDataBetweenMappings(NewMemberMapping, OldMem var NewColumns, OldColumns: TStringList; i: integer; + g: IBoldGuard; begin + g := TBoldGuard.Create(NewColumns, OldColumns); NewColumns := TStringList.Create; OldColumns := TStringList.Create; - try - NewColumns.CommaText := NewMemberMapping.Columns; - OldColumns.CommaText := OldMemberMapping.Columns; - for i := 0 to MinIntValue([NewColumns.Count, OldColumns.Count]) - 1 do - begin - Script.MoveData(OldMemberMapping.TableName, - NewMemberMapping.TableName, - OldColumns[i], - NewColumns[i], - GetCommonPrimaryKeyColumns( - GetPrimaryIndexForExistingTable(OldMemberMapping.TableName), - GetPrimaryIndexForNewTable(NewMemberMapping.TableName)), - OldMapping.GetDbTypeMapping(OldMemberMapping.ClassExpressionName)); - end; - finally - NewColumns.Free; - OldColumns.Free; + NewColumns.CommaText := NewMemberMapping.Columns; + OldColumns.CommaText := OldMemberMapping.Columns; + for i := 0 to MinIntValue([NewColumns.Count, OldColumns.Count]) - 1 do + begin + Script.MoveData(OldMemberMapping.TableName, + NewMemberMapping.TableName, + OldColumns[i], + NewColumns[i], + GetCommonPrimaryKeyColumns( + GetPrimaryIndexForExistingTable(OldMemberMapping.TableName), + GetPrimaryIndexForNewTable(NewMemberMapping.TableName)), + OldMapping.GetDbTypeMapping(OldMemberMapping.ClassExpressionName)); end; end; @@ -543,13 +616,12 @@ function TBoldDataBaseEvolutor.OldRootTableName: String; tables: TStringList; TableName: String; begin - result := 'BOLD_OBJECT'; // do not localize + result := 'BOLD_OBJECT'; Tables := TStringList.create; try if (OldMapping.ObjectStorageMappings.Count = 0) and (OldMapping.AllInstancesMappings.Count = 1) then begin - // there is only the rootclass, it has no objectstorage, only AllInstances-mapping TableName := OldMapping.AllInstancesMappings[0].TableName; Tables.Values[TableName] := IntToStr(StrToIntDef(Tables.Values[TableName], 0) + 1); end; @@ -583,14 +655,13 @@ function TBoldDataBaseEvolutor.TranslateClassExpressionName(const ExpressionName begin dbType := SourceMapping.GetDbTypeMapping(ExpressionName); if dbType = NO_CLASS then - raise EBold.CreateFmt(sUnableToFindDBID, [classname, expressionName]); + raise EBold.CreateFmt('%s.TranslateClassExpressionName: Unable to find source dbid for %s', [classname, expressionName]); for i := 0 to SourceMapping.DbTypeMappings.Count - 1 do begin TestName := SourceMapping.DbTypeMappings[i].ClassExpressionName; if (SourceMapping.DbTypeMappings[i].DbType = dbType) and (DestMapping.GetDbTypeMapping(TestName) <> NO_CLASS) then begin - // oh, we found the testname in the destination mapping, then it is what we were looking for. result := TestName; break; end; @@ -619,7 +690,6 @@ function TBoldDataBaseEvolutor.TranslateMemberName( Mapping := SourceMemberMappings[0].TableName + '.' + SourceMemberMappings[0].Columns; for i := 0 to SourceMapping.MemberMappings.Count - 1 do begin - // if they have the same class name, and the same mapping, it is the same member if SameText(SourceMapping.MemberMappings[i].ClassExpressionName, SourceExprName) and SameText(SourceMapping.MemberMappings[i].TableName + '.' + SourceMapping.MemberMappings[i].Columns, Mapping) then begin @@ -646,7 +716,7 @@ procedure TBoldDataBaseEvolutor.ExecuteScript; fMergedMapping.WriteDataToDB(PersistenceHandle.DataBaseInterface); finally PersistenceHandle.DataBaseInterface.Close; - end; + end; end; procedure TBoldDataBaseEvolutor.MergeOldDbTypes; @@ -667,7 +737,6 @@ procedure TBoldDataBaseEvolutor.MergeOldDbTypes; DbType := OldMapping.GetDbTypeMapping(OldExprName); if DbType = NO_CLASS then begin - // try to locate a previously added type with the same dbtype in the new typemapping for j := 0 to i - 1 do begin if NewMapping.DbTypeMappings[i].DbType = NewMapping.DbTypeMappings[j].dbtype then @@ -698,9 +767,13 @@ procedure TBoldDataBaseEvolutor.GenerateScript(DbScript, MappingScript: TStrings dbScript.EndUpdate; MappingScript.BeginUpdate; - AddCommandToScript(MappingScript, PersistenceHandle.SQLDataBaseConfig.SqlScriptStartTransaction); - fMergedMapping.ScriptForWriteData(MappingScript, PersistenceHandle.SQLDataBaseConfig.SqlScriptSeparator, true, PersistenceHandle.SQLDataBaseConfig.SqlScriptTerminator); - AddCommandToScript(MappingScript, PersistenceHandle.SQLDataBaseConfig.SqlScriptCommitTransaction); + fMergedMapping.ScriptForWriteData( + PersistenceHandle.DatabaseInterface, + MappingScript, + True, + PersistenceHandle.SQLDataBaseConfig.SqlScriptSeparator, + PersistenceHandle.SQLDataBaseConfig.SqlScriptTerminator + ); MappingScript.EndUpdate; end; @@ -713,7 +786,6 @@ procedure TBoldDataBaseEvolutor.MarkMemberMappingHandled(UnhandledMemberMappings if OldDbType <> NO_CLASS then begin for i := UnhandledMemberMappings.Count - 1 downto 0 do - // if the dbtype, table and columns match then it is the same attribute... if (OldMapping.GetDbTypeMapping(UnhandledMemberMappings[i].ClassExpressionName) = OldDbType) and SameText(UnhandledMemberMappings[i].TableName, OldMemberMapping.TableName) and SameText(UnhandledMemberMappings[i].Columns, OldMemberMapping.Columns) then @@ -724,10 +796,9 @@ procedure TBoldDataBaseEvolutor.MarkMemberMappingHandled(UnhandledMemberMappings procedure TBoldDataBaseEvolutor.DetectMapperChange(NewMemberMapping, OldMemberMapping: TBoldMemberMappingInfo; Param: TObject); begin - if (NewMemberMapping.MapperName <> OldMemberMapping.MapperName) and (OldMemberMapping.MapperName <> '') then - begin + if (OldMemberMapping.MapperName <> '') and not NewMemberMapping.CompareMapping(OldMemberMapping) then (Param as TStrings).Add( - format(sMemberChangedMapper, [ + format('Member %s.%s changed mapper (%s->%s). Column[s] (%s) in table %s will be dropped and (%s) will be created in table %s, data loss!', [ NewMemberMapping.ClassExpressionName, NewMemberMapping.MemberName, OldMemberMapping.MapperName, @@ -737,7 +808,6 @@ procedure TBoldDataBaseEvolutor.DetectMapperChange(NewMemberMapping, OldMemberMa NewMemberMapping.Columns, NewMemberMapping.TableName])); end; -end; procedure TBoldDataBaseEvolutor.GenerateWarnings(Info: TStrings); var @@ -754,7 +824,6 @@ procedure TBoldDataBaseEvolutor.GenerateWarnings(Info: TStrings); if assigned(PMapper.ObjectPersistenceMappers[i]) and (length(NewMapping.GetObjectStorageMapping(PMapper.ObjectPersistenceMappers[i].ExpressionName)) = 0) then begin - // New class is persistent and abstract NewExprName := PMapper.ObjectPersistenceMappers[i].ExpressionName; oldExprName := TranslateClassExpressionName(NewExprName, NewMapping, OldMapping); if OldExprName <> '' then @@ -762,9 +831,9 @@ procedure TBoldDataBaseEvolutor.GenerateWarnings(Info: TStrings); if length(OldMapping.GetObjectStorageMapping(OldExprName)) > 0 then begin if GenericScript then - Info.Add(format(sClassBecameAbstract, [OldExprName, NewExprName])) + Info.Add(format('Class %s is concrete in old model, but %s is Abstract in new model', [OldExprName, NewExprName])) else if HasOldInstances(OldExprName) then - Info.Add(format(sUnableToHandleInstancesOfAbstract, [OldExprName, NewExprName])); + Info.Add(format('ERROR: There are instances of class %s, but %s is abstract in new model', [OldExprName, NewExprName])); end; end; end; @@ -777,7 +846,7 @@ procedure TBoldDataBaseEvolutor.GenerateWarnings(Info: TStrings); begin if HasOldInstances(UnhandledMemberMappings[0].ClassExpressionName) then begin - s := format(sDataStoredInXForYWillBeLost, [ + s := format('Data stored in column %s.%s for member %s.%s will be lost', [ UnhandledMemberMappings[0].TableName, UnhandledMemberMappings[0].columns, UnhandledMemberMappings[0].ClassExpressionName, @@ -786,9 +855,9 @@ procedure TBoldDataBaseEvolutor.GenerateWarnings(Info: TStrings); if newClassExpressionName <> UnhandledMemberMappings[0].ClassExpressionName then begin if NewClassExpressionname = '' then - s := s + sClassNoLongerExists + s := s + ' (class no longer exists)' else - s := s + format(sNewNameForClass, [NewClassExpressionName]); + s := s + format(' (class now called %s)', [NewClassExpressionName]); end; info.add(s); end; @@ -804,7 +873,6 @@ function TBoldDataBaseEvolutor.CanHaveOldInstances(const OldExpressionName: Stri dbTypeMapping: TBoldDbType; begin dbTypeMapping := OldMapping.GetDbTypeMapping(OldExpressionName); - // Abstract classes has no ObjectStorage mapping result := (dbTypeMapping <> NO_CLASS) and (length(OldMapping.GetObjectStorageMapping(OldExpressionName)) > 0); end; @@ -812,45 +880,38 @@ function TBoldDataBaseEvolutor.GetCommonPrimaryKeyColumns(const PrimaryKey1, Pri var i: integer; Fields1, Fields2: TStringList; + g: IBoldGuard; begin + g := TBoldGuard.Create(Fields1, Fields2); Fields1 := TStringList.Create; Fields2 := TStringList.Create; - result := ''; // perhaps should default to BOLD_ID... - try - Fields1.CommaText := PrimaryKey1; - Fields2.CommaText := UpperCase(PrimaryKey2); - Fields2.Sorted := true; - for i := Fields1.Count - 1 downto 0 do - if Fields2.IndexOf(UpperCase(Fields1[i])) = -1 then - Fields1.delete(i); - result := Fields1.CommaText; - finally - Fields1.Free; - Fields2.Free; - end; + result := ''; + Fields1.CommaText := PrimaryKey1; + Fields2.CommaText := UpperCase(PrimaryKey2); + Fields2.Sorted := true; + for i := Fields1.Count - 1 downto 0 do + if Fields2.IndexOf(UpperCase(Fields1[i])) = -1 then + Fields1.delete(i); + result := Fields1.CommaText; end; function TBoldDataBaseEvolutor.GetPrimaryIndexForExistingTable(const TableName: String): String; var - Table: IBoldTable; + IndexDefs: TBoldIndexDescriptionArray; i: integer; begin - Table := PersistenceHandle.DataBaseInterface.GetTable; - try - Table.Tablename := tableName; - result := ''; - Table.IndexDefs.Update; - for i := 0 to Table.IndexDefs.Count - 1 do + result := ''; + IndexDefs := PersistenceHandle.DataBaseInterface.GetIndexDescriptions(TableName); + for i := 0 to Length(IndexDefs)-1 do + begin + if IndexDefs[i].IsPrimary then begin - if ixPrimary in Table.IndexDefs[i].Options then - begin - result := StringReplace(Table.IndexDefs[i].Fields, ';', ',', [rfReplaceAll]); - exit; - end; + result := StringReplace(IndexDefs[i].IndexedColumns, ';', ',', [rfReplaceAll]); + exit; end; - finally - PersistenceHandle.DataBaseInterface.ReleaseTable(Table); end; + if result = '' then + raise EBold.CreateFmt('%s.GetPrimaryIndexForExistingTable: Table "%s" has no primary key.', [ClassName, TableName]); end; function TBoldDataBaseEvolutor.GetPrimaryIndexForNewTable(const TableName: String): String; @@ -858,13 +919,13 @@ function TBoldDataBaseEvolutor.GetPrimaryIndexForNewTable(const TableName: Strin TableDesc: TBoldSQLTableDescription; i: integer; begin - result := ''; + result := IDCOLUMN_NAME; // Fallback: see GetPrimaryIndexForExistingTable TableDesc := PMapper.PSSystemDescription.SQLTablesList.ItemsBySQLName[tableName]; if assigned(TableDesc) then for i := 0 to TableDesc.IndexList.Count - 1 do - if ixPrimary in TableDesc.IndexList[i].IndexOptions then + if BoldPSDescriptionsSQL.ixPrimary in TableDesc.IndexList[i].IndexOptions then begin - result := TableDesc.IndexList[i].IndexedFieldsForSQL; // this has commas instead of semicolons as separator + result := TableDesc.IndexList[i].IndexedFieldsForSQL; exit; end; end; @@ -877,24 +938,73 @@ procedure TBoldDataBaseEvolutor.DetectTypeClashes; procedure TBoldDataBaseEvolutor.DetectTypeClashesAction(NewMemberMapping, OldMemberMapping: TBoldMemberMappingInfo; Param: TObject); var i: integer; - columns: TStringList; + OldColumns: TStringList; + NewColumns: TStringList; ColumnDesc: TBoldSQlColumnDescription; TableDesc: TBoldSQLTableDescription; + SameTable: boolean; + SameTableAndMapper: boolean; + IsOrderedEvolve: boolean; + g: IBoldGuard; begin - if (NewMemberMapping.MapperName <> OldMemberMapping.MapperName) and (OldMemberMapping.MapperName <> '') then + if (OldMemberMapping.MapperName <> '') and (not NewMemberMapping.CompareMapping(OldMemberMapping)) then begin - Columns := TStringList.create; - Columns.CommaText := OldMemberMapping.Columns; - for i := 0 to Columns.Count - 1 do - fPreScript.DropColumn(OldMemberMapping.TableName, Columns[i]); + g := TBoldGuard.Create(NewColumns, OldColumns); + OldColumns := TStringList.create; + OldColumns.CommaText := OldMemberMapping.Columns; + NewColumns := TStringList.create; + NewColumns.CommaText := NewMemberMapping.Columns; + SameTable := (OldMemberMapping.TableName = NewMemberMapping.TableName); + SameTableAndMapper := SameTable and (OldMemberMapping.MapperName = NewMemberMapping.MapperName); + IsOrderedEvolve := SameTableAndMapper and (DifferenceInColumns(NewMemberMapping.Columns, OldMemberMapping.Columns) = NewColumns[0] + ORDERCOLUMN_SUFFIX); + if not IsOrderedEvolve and SameTable then + for i := 0 to OldColumns.Count - 1 do + fScript.DropColumn(OldMemberMapping.TableName, OldColumns[i]); TableDesc := NewPSDescription.SQLTablesList.ItemsBySQLName[NewMemberMapping.TableName]; - Columns.CommaText := NewMemberMapping.Columns; - for i := 0 to Columns.Count - 1 do + if SameTable then + for i := 0 to NewColumns.Count - 1 do + begin + if not IsOrderedEvolve or (i = ORDERCOLUMN_INDEX) then + begin + ColumnDesc := TableDesc.ColumnsList.ItemsBySQLName[NewColumns[i]] as TBoldSQLColumnDescription; + fScript.AddColumn(ColumnDesc); + end; + end; + end; +end; + +function TBoldDataBaseEvolutor.DifferenceInColumns(const AColumns, + BColumns: String): string; +var + i,j : integer; + a: TStringList; + b: TStringList; + c: TStringList; +begin + a := TStringList.Create; + b := TStringList.Create; + c := TStringList.Create; + try + a.CommaText := AColumns; + b.CommaText := BColumns; + for i := 0 to a.Count - 1 do + begin + j := b.IndexOf(a[i]); + if j = -1 then + c.Add(a[i]) + end; + for i := 0 to b.Count - 1 do begin - ColumnDesc := TableDesc.ColumnsList.ItemsBySQLName[Columns[i]] as TBoldSQLColumnDescription; - fScript.AddColumn(ColumnDesc); + j := a.IndexOf(b[i]); + if j = -1 then + c.Add(b[i]) end; + result := c.CommaText; + finally + a.free; + b.free; + c.free; end; end; @@ -905,11 +1015,6 @@ procedure TBoldDataBaseEvolutor.GenerateExecutedStatements(Info: TStrings); Info.AddStrings(Script.InternalLog); end; -procedure TBoldDataBaseEvolutor.AddCommandToScript(Script: TStrings; s: string); -begin - Script.Add(s+PersistenceHandle.SQLDataBaseConfig.SqlScriptTerminator); - if PersistenceHandle.SQLDataBaseConfig.SqlScriptSeparator <> '' then - Script.Add(PersistenceHandle.SQLDataBaseConfig.SqlScriptSeparator); -end; +initialization end. diff --git a/Source/PMapper/DbEvolutor/BoldDbEvolutorForm.pas b/Source/PMapper/DbEvolutor/BoldDbEvolutorForm.pas index 58a4a1e..33134a8 100644 --- a/Source/PMapper/DbEvolutor/BoldDbEvolutorForm.pas +++ b/Source/PMapper/DbEvolutor/BoldDbEvolutorForm.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldDbEvolutorForm; interface @@ -31,16 +34,17 @@ TfrmBoldDbEvolutor = class(TForm, IBoldLogReceiver) tsWarnings: TTabSheet; mmoWarnings: TMemo; ImageList1: TImageList; - Button1: TButton; - SaveDialog1: TSaveDialog; procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure FormClose(Sender: TObject; var Action: TCloseAction); - procedure Button1Click(Sender: TObject); private { Private declarations } + fSQLScript: TStringList; + fMappingInfoScript: TStringList; fWarnings: TStringList; fSessionName: String; + procedure SqlScriptChange(Sender: TObject); + procedure MappingInfoScriptChange(Sender: TObject); procedure SetProgress(const Value: integer); procedure SetLogHeader(const Value: string); procedure SetProgressMax(const Value: integer); @@ -58,12 +62,13 @@ TfrmBoldDbEvolutor = class(TForm, IBoldLogReceiver) function GetWarnings: TStrings; procedure UpdateWarningCount(Sender: TObject); public - constructor Create(Owner: TComponent); override; - destructor Destroy; override; + constructor create(Owner: TComponent); override; + destructor destroy; override; class procedure EvolveDB(PersistenceHandle: TBoldAbstractPersistenceHandleDB; GenerateGenericScript: Boolean); property SQLScript: TStrings read GetSQLScript; property MappingInfoScript: TStrings read GetMappingInfoScript; property Warnings: TStrings read GetWarnings; + { Public declarations } end; @@ -73,7 +78,6 @@ implementation SysUtils, BoldUtils, BoldDbEvolutor, - BoldPMConsts, BoldGuard; {$R *.DFM} @@ -82,12 +86,11 @@ implementation procedure TfrmBoldDbEvolutor.Clear; begin -// mmoActions.lines.Clear; end; procedure TfrmBoldDbEvolutor.EndLog; begin - Log(format(sDone, [formatDateTime('c', now), fSessionName])); // do not localize + Log(format('%s: Done %s', [formatDateTime('c', now), fSessionName])); end; procedure TfrmBoldDbEvolutor.Hide; @@ -115,7 +118,6 @@ procedure TfrmBoldDbEvolutor.SetProgress(const Value: integer); procedure TfrmBoldDbEvolutor.SetLogHeader(const Value: string); begin - // intentionally left empty end; procedure TfrmBoldDbEvolutor.SetProgressMax(const Value: integer); @@ -129,9 +131,19 @@ procedure TfrmBoldDbEvolutor.Show; inherited Show; end; +procedure TfrmBoldDbEvolutor.SqlScriptChange(Sender: TObject); +begin + mmoSQLScript.Lines.Assign(Sender as TStrings); +end; + +procedure TfrmBoldDbEvolutor.MappingInfoScriptChange(Sender: TObject); +begin + mmoMappingInfoScript.Lines.Assign(Sender as TStrings); +end; + procedure TfrmBoldDbEvolutor.StartLog(const SessionName: String); begin - Log(format(sStarting, [formatDateTime('c', now), sessionName])); // do not localize + Log(format('%s: Starting %s', [formatDateTime('c', now), sessionName])); fSessionName := SessionName; Show; end; @@ -143,6 +155,10 @@ procedure TfrmBoldDbEvolutor.FormCreate(Sender: TObject); GetInterface(IBoldLogReceiver, LogReceiver); BoldLog.RegisterLogReceiver(LogReceiver); PageControl1.ActivePage := tsActions; + fSQLScript := TStringList.Create; + fMappingInfoScript := TStringList.Create; + fSQLScript.OnChange := SqlScriptChange; + fMappingInfoScript.OnChange := MappingInfoScriptChange; end; procedure TfrmBoldDbEvolutor.FormDestroy(Sender: TObject); @@ -151,6 +167,8 @@ procedure TfrmBoldDbEvolutor.FormDestroy(Sender: TObject); begin GetInterface(IBoldLogReceiver, LogReceiver); BoldLog.UnRegisterLogReceiver(LogReceiver); + FreeAndNil(fSQLScript); + FreeAndNil(fMappingInfoScript); end; procedure TfrmBoldDbEvolutor.FormClose(Sender: TObject; var Action: TCloseAction); @@ -160,12 +178,12 @@ procedure TfrmBoldDbEvolutor.FormClose(Sender: TObject; var Action: TCloseAction function TfrmBoldDbEvolutor.GetMappingInfoScript: TStrings; begin - result := mmoMappingInfoScript.Lines; + result := fMappingInfoScript; //mmoMappingInfoScript.Lines; end; function TfrmBoldDbEvolutor.GetSQLScript: TStrings; begin - result := mmoSQLScript.Lines; + result := fSQLScript; //mmoSQLScript.Lines; end; function TfrmBoldDbEvolutor.GetWarnings: TStrings; @@ -183,7 +201,7 @@ constructor TfrmBoldDbEvolutor.create(Owner: TComponent); destructor TfrmBoldDbEvolutor.destroy; begin FreeAndNil(fWarnings); - inherited; + inherited; end; procedure TfrmBoldDbEvolutor.UpdateWarningCount(Sender: TObject); @@ -192,12 +210,11 @@ procedure TfrmBoldDbEvolutor.UpdateWarningCount(Sender: TObject); mmoWarnings.lines.Clear; mmoWarnings.lines.AddStrings(fWarnings); mmoWarnings.Lines.EndUpdate; - tsWarnings.Caption := format(sWarnings, [fWarnings.Count]); + tsWarnings.Caption := format('Warnings (%d)', [fWarnings.Count]); end; procedure TfrmBoldDbEvolutor.ProcessInterruption; begin - // intentionally left blank end; procedure TfrmBoldDbEvolutor.Sync; @@ -219,7 +236,7 @@ class procedure TfrmBoldDbEvolutor.EvolveDB(PersistenceHandle: TBoldAbstractPers EvolutorForm := TfrmBoldDbEvolutor.Create(nil); EvolutorForm.Show; try - BoldLog.StartLog(sDetectingChanges); + BoldLog.StartLog('Detecting changes'); Evolutor.GenericScript := GenerateGenericScript; try Evolutor.CalculateScript; @@ -230,7 +247,7 @@ class procedure TfrmBoldDbEvolutor.EvolveDB(PersistenceHandle: TBoldAbstractPers except on e: Exception do begin - showMessage(Format(sFailedToDetectChanges, [e.message])); + showMessage('Failed to detect changes: ' + e.message); exit; end; end; @@ -238,31 +255,35 @@ class procedure TfrmBoldDbEvolutor.EvolveDB(PersistenceHandle: TBoldAbstractPers BoldLog.EndLog; if EvolutorForm.SQLScript.Count = 0 then begin - ShowMessage(sNoUpdateNeeded); + ShowMessage('No update needed!'); EvolutorForm.Close; EvolutorForm := nil; end else begin - ShowMessage(Format(sInspectChanges, [BOLDCRLF, BOLDCRLF])); + ShowMessage( + 'Please inspect the planned actions and decide if you want to execute them' + BOLDCRLF + + BOLDCRLF + + 'Make sure you back up your critical data before upgrading the database!!!'); EvolutorForm.Hide; ModalResult := EvolutorForm.ShowModal; EvolutorForm := nil; if ModalResult = mrOK then begin try - BoldLog.StartLog(sUpdateDatabase); + BoldLog.StartLog('Update database'); Evolutor.ExecuteScript; BoldLog.EndLog; - ShowMessage(sUpdateSuccessful); + ShowMessage('Database successfully updated'); except on e: Exception do begin - showMessage(Format(sEvolveFailed, [e.Message, BOLDCRLF, BOLDCRLF])); + showMessage('Failed to Evolve database: ' + e.message + BOLDCRLF + BOLDCRLF + + 'See LogWindow for executed statements'); ExecutedStatements := TStringList.Create; BoldLog.Separator; - BoldLog.Log(sExecutedStatements); + BoldLog.Log('The following statements were executed before evolution failed: '); BoldLog.Separator; Evolutor.GenerateExecutedStatements(ExecutedStatements); for i := 0 to ExecutedStatements.Count - 1 do @@ -279,14 +300,5 @@ class procedure TfrmBoldDbEvolutor.EvolveDB(PersistenceHandle: TBoldAbstractPers end; end; -procedure TfrmBoldDbEvolutor.Button1Click(Sender: TObject); -begin - SaveDialog1.FileName := 'EvolutionScript.sql'; - if SaveDialog1.Execute then - mmoSQLScript.Lines.SaveToFile(SaveDialog1.FileName); - SaveDialog1.FileName := 'MappingInfoScript.sql'; - if SaveDialog1.Execute then - mmoMappingInfoScript.Lines.SaveToFile(SaveDialog1.FileName); -end; - +initialization end. diff --git a/Source/PMapper/DbEvolutor/BoldDbEvolutorScript.pas b/Source/PMapper/DbEvolutor/BoldDbEvolutorScript.pas index 4a9b0f2..2122de1 100644 --- a/Source/PMapper/DbEvolutor/BoldDbEvolutorScript.pas +++ b/Source/PMapper/DbEvolutor/BoldDbEvolutorScript.pas @@ -1,3 +1,5 @@ +{ Global compiler directives } +{$include bold.inc} unit BoldDbEvolutorScript; interface @@ -6,6 +8,7 @@ interface db, Classes, BoldDefs, + BoldBase, BoldLogHandler, BoldDBInterfaces, BoldPSDescriptionsSQL, @@ -26,7 +29,7 @@ TBoldTwoColumnOperation = class; TBoldMoveData = class; TBoldDataBaseEvolutorScript = class; - TBoldScriptOperation = class + TBoldScriptOperation = class(TBoldMemoryManagedObject) private fScript: TBoldDataBaseEvolutorScript; public @@ -37,6 +40,8 @@ TBoldScriptOperation = class TBoldTableOperation = class(TBoldScriptOperation) private fTableName: string; + protected + function GetDebugInfo: string; override; public constructor Create(Script: TBoldDataBaseEvolutorScript; const TableName: String); property TableName: string read fTableName; @@ -45,6 +50,8 @@ TBoldTableOperation = class(TBoldScriptOperation) TBoldAddTable = class(TBoldScriptOperation) private fTableDescr: TBoldSQLTableDescription; + protected + function GetDebugInfo: string; override; public constructor Create(Script: TBoldDataBaseEvolutorScript; TableDescr: TBoldSQLTableDescription); procedure Execute; @@ -60,6 +67,8 @@ TBoldDeleteInstances = class(TBoldTableOperation) private fExpressionName: String; fDbType: TBoldDbType; + protected + function GetDebugInfo: string; override; public constructor Create(Script: TBoldDataBaseEvolutorScript; const ExpressionName, TableName: String; DbType: TBoldDbType); procedure Execute; @@ -70,6 +79,8 @@ TBoldDeleteInstances = class(TBoldTableOperation) TBoldColumnOperation = class(TBoldTableOperation) private fColumnName: String; + protected + function GetDebugInfo: string; override; public constructor Create(Script: TBoldDataBaseEvolutorScript; const TableName, ColumnName: String); property ColumnName: String read fColumnName; @@ -78,6 +89,8 @@ TBoldColumnOperation = class(TBoldTableOperation) TBoldAddColumn = class(TBoldScriptOperation) private fColumnDesc: TBoldSQLColumnDescription; + protected + function GetDebugInfo: string; override; public constructor Create(Script: TBoldDataBaseEvolutorScript; ColumnDesc: TBoldSQLColumnDescription); procedure Execute; @@ -93,6 +106,8 @@ TBoldDropIndex = class(TBoldScriptOperation) private fIndexName: String; fTableName: String; + protected + function GetDebugInfo: string; override; public constructor Create(Script: TBoldDataBaseEvolutorScript; const IndexName: String; const TableName: String); procedure Execute; @@ -100,10 +115,23 @@ TBoldDropIndex = class(TBoldScriptOperation) property TableName: string read fTableName; end; + TBoldAddIndex = class(TBoldScriptOperation) + private + fIndexDescription: TBoldSQLIndexDescription; + protected + function GetDebugInfo: string; override; + public + constructor Create(Script: TBoldDataBaseEvolutorScript; IndexDescription: TBoldSQLIndexDescription); + procedure Execute; + property IndexDescription: TBoldSQLIndexDescription read fIndexDescription; + end; + TBoldTwoTableOperation = class(TBoldScriptOperation) private fSourceTable: String; fTargetTable: String; + protected + function GetDebugInfo: string; override; public constructor Create(Script: TBoldDataBaseEvolutorScript; const SourceTable, TargetTable: String); property SourceTable: String read fSourceTable; @@ -142,6 +170,8 @@ TBoldMoveData = class(TBoldTwoColumnOperation) fdbTypes: string; fAlsoMoveData: TBoldMoveData; function GetSignature: String; + protected +// function GetDebugInfo: string; override; public constructor Create(Script: TBoldDataBaseEvolutorScript; const SourceTable, TargetTable, SourceColumn, TargetColumn, IdColumns: String; dbType: TBoldDbType); destructor Destroy; override; @@ -162,6 +192,7 @@ TBoldDataBaseEvolutorScript = class fDroppedTables: TBoldObjectArray; fMovedData: TBoldObjectArray; fDroppedIndices: TBoldObjectArray; + fAddedIndices: TBoldObjectArray; fScript: TStrings; fDataBase: IBoldDataBase; fSQLDataBaseConfig: TBoldSQLDatabaseConfig; @@ -178,6 +209,7 @@ TBoldDataBaseEvolutorScript = class function GetMovedData(index: integer): TBoldMoveData; function GetDeletedInstances(index: integer): TBoldDeleteInstances; function GetDroppedIndices(index: integer): TBoldDropIndex; + function GetAddedIndices(index: integer): TBoldAddIndex; procedure ExtendSchema; procedure AdjustContents; procedure ReduceSchema; @@ -185,6 +217,8 @@ TBoldDataBaseEvolutorScript = class procedure StartTransaction; procedure CommitTransaction; procedure RollBackTransaction; + function CopyInstancesExists(const sExpressionName, sSourceTable, + sTargetTable, sidColumns: string; aSourceDbType: TBoldDbType): Boolean; protected procedure Execute; property AddedTables[index: integer]: TBoldAddTable read GetAddedTables; @@ -192,15 +226,21 @@ TBoldDataBaseEvolutorScript = class property DroppedTables[index: integer]: TBoldDropTable read GetDroppedTables; property DroppedColumns[index: integer]: TBoldDropColumn read GetDroppedColumns; property DroppedIndices[index: integer]: TBoldDropIndex read GetDroppedIndices; + property AddedIndices[index: integer]: TBoldAddIndex read GetAddedIndices; property CopiedInstances[index: integer]: TBoldCopyInstances read GetCopiedInstances; property MovedData[index: integer]: TBoldMoveData read GetMovedData; property DeletedInstances[index: integer]: TBoldDeleteInstances read GetDeletedInstances; public constructor Create; destructor Destroy; override; + function HasDropColumn(const TableName, ColumnName: String): boolean; + function HasDropIndex(const IndexName: String; const TableName: string): boolean; + function HasAddIndex(IndexDescription: TBoldSQLIndexDescription): boolean; + function HasAddColumn(ColumnDesc: TBoldSQLColumnDescription): boolean; procedure AddTable(TableDescr: TBoldSQLTableDescription); procedure AddColumn(ColumnDesc: TBoldSQLColumnDescription); procedure DropIndex(const IndexName: String; const TableName: string); + procedure AddIndex(IndexDescription: TBoldSQLIndexDescription); procedure DropColumn(const TableName, ColumnName: String); procedure DropTable(const TableName: String); procedure CopyInstances(const ExpressionName, SourceTable, TargetTable, IdColumns: String; SourceDbType: TBoldDbType); @@ -213,14 +253,13 @@ TBoldDataBaseEvolutorScript = class property InternalLog: TStringList read fInternalLog; end; - implementation uses SysUtils, BoldGuard, BoldUtils, - BoldPMConsts; + Boldrev; { TBoldAddTable } @@ -235,9 +274,9 @@ procedure TBoldAddTable.Execute; i: integer; index: TBoldSQLIndexDescription; begin - Script.Comment(sAddTable, [TableDescr.SQLName]); + Script.Comment('Add table %s', [TableDescr.SQLName]); Script.ExecuteSQL(TableDescr.SQLForCreateTable(Script.fDataBase), []); - for i := 0 to TableDescr.IndexList.Count - 1 do + for i := 0 to TableDescr.IndexList.Count-1 do begin index := TableDescr.IndexList[i] as TBoldSQLIndexDescription; if not (ixPrimary in Index.IndexOptions) then @@ -245,26 +284,56 @@ procedure TBoldAddTable.Execute; end; end; +function TBoldAddTable.GetDebugInfo: string; +begin + result := ClassName + ':' + TableDescr.SQLName; +end; + { TBoldDataBaseEvolutorScript } procedure TBoldDataBaseEvolutorScript.AddColumn(ColumnDesc: TBoldSQLColumnDescription); +begin + if not HasAddColumn(ColumnDesc) then + fAddedColumns.Add(TBoldAddColumn.Create(self, ColumnDesc)); +end; + +procedure TBoldDataBaseEvolutorScript.AddTable(TableDescr: TBoldSQLTableDescription); var i: integer; begin - for i := 0 to fAddedColumns.Count - 1 do - if AddedColumns[i].ColumnDesc = ColumnDesc then + for i := 0 to fAddedTables.Count - 1 do + if AddedTables[i].TableDescr = TableDescr then exit; - fAddedColumns.Add(TBoldAddColumn.Create(self, ColumnDesc)); + fAddedTables.Add(TBoldAddTable.Create(self, TableDescr)); end; -procedure TBoldDataBaseEvolutorScript.AddTable(TableDescr: TBoldSQLTableDescription); +function TBoldDataBaseEvolutorScript.CopyInstancesExists(const sExpressionName, + sSourceTable, sTargetTable, sidColumns: string; + aSourceDbType: TBoldDbType): Boolean; +var + i: Integer; + aCopyInstances: TBoldCopyInstances; begin - fAddedTables.Add(TBoldAddTable.Create(self, TableDescr)); + Result := False; + for i := 0 to (fCopiedInstances.Count - 1) do begin + aCopyInstances := GetCopiedInstances(i); + Result := (aCopyInstances.fExpressionName = sExpressionName) + and (aCopyInstances.fSourceTable = sSourceTable) + and (aCopyInstances.fTargetTable = sTargetTable) + and (aCopyInstances.fIdColumns = sidColumns) + and (aCopyInstances.fSourceDbType = aSourceDbType); + if Result then begin + Break; + end; + end; end; procedure TBoldDataBaseEvolutorScript.CopyInstances(const ExpressionName, SourceTable, TargetTable, IdColumns: String; SourceDbType: TBoldDbType); begin - fCopiedInstances.Add(TBoldCopyInstances.Create(self, ExpressionName, SourceTable, TargetTable, IdColumns, SourceDbType)); + // prevent, that 2 identical instances of TBoldCopyInstance are added here: + if not CopyInstancesExists(ExpressionName, SourceTable, TargetTable, idColumns, SourceDbType) then begin + fCopiedInstances.Add(TBoldCopyInstances.Create(self, ExpressionName, SourceTable, TargetTable, IdColumns, SourceDbType)); + end; end; constructor TBoldDataBaseEvolutorScript.Create; @@ -276,9 +345,9 @@ constructor TBoldDataBaseEvolutorScript.Create; fDeletedInstances := TBoldObjectArray.Create(10, [bcoDataOwner]); fDroppedColumns := TBoldObjectArray.Create(10, [bcoDataOwner]); fDroppedTables := TBoldObjectArray.Create(10, [bcoDataOwner]); - // the MoveData-list can not own its instances since they will be moved from there during OptimizeScript fMovedData := TBoldObjectArray.Create(10, []); fDroppedIndices := TBoldObjectArray.Create(10, [bcoDataOwner]); + fAddedIndices := TBoldObjectArray.Create(10, [bcoDataOwner]); fSQLStatements := TStringList.Create; fInternalLog := TStringList.Create; end; @@ -299,7 +368,8 @@ destructor TBoldDataBaseEvolutorScript.Destroy; FreeAndNil(fDroppedColumns); FreeAndNil(fDroppedTables); FreeAndNil(fDroppedIndices); - for i := 0 to fMovedData.Count - 1 do + FreeAndNil(fAddedIndices); + for i := 0 to fMovedData.Count-1 do fMovedData[i].Free; FreeAndNil(fMovedData); FreeAndNil(fSQLStatements); @@ -308,19 +378,18 @@ destructor TBoldDataBaseEvolutorScript.Destroy; end; procedure TBoldDataBaseEvolutorScript.DropColumn(const TableName, ColumnName: String); -var - i: integer; begin - for i := 0 to fDroppedColumns.Count - 1 do - if SameText(DroppedColumns[i].TableName, TableName) and - SameText(DroppedColumns[i].ColumnName, ColumnName) then - exit; - - fDroppedColumns.Add(TBoldDropColumn.Create(self, TableName, ColumnName)); + if not HasDropColumn(TableName, ColumnName) then + fDroppedColumns.Add(TBoldDropColumn.Create(self, TableName, ColumnName)); end; procedure TBoldDataBaseEvolutorScript.DropTable(const TableName: String); +var + i: integer; begin + for i := 0 to fDroppedTables.Count - 1 do + if DroppedTables[i].TableName = TableName then + exit; fDroppedTables.Add(TBoldDropTable.Create(self, TableName)); end; @@ -361,7 +430,7 @@ function TBoldDataBaseEvolutorScript.GetAddedTables(index: integer): TBoldAddTab procedure TBoldDataBaseEvolutorScript.MoveData(const SourceTable, TargetTable, SourceColumn, TargetColumn, IdColumns: String; dbType: TBoldDbType); begin - if not SameText(TargetTable + '.' + TargetColumn, SourceTable + '.' + SourceColumn) then + if not SameText(TargetTable+'.'+TargetColumn, SourceTable+'.'+SourceColumn) then fMovedData.Add(TBoldMoveData.Create(self, SourceTable, TargetTable, SourceColumn, TargetColumn, IdColumns, dbType)); end; @@ -410,6 +479,12 @@ function TBoldDataBaseEvolutorScript.GetAddedColumns(index: integer): TBoldAddCo result := TBoldAddColumn(fAddedColumns[index]); end; +function TBoldDataBaseEvolutorScript.GetAddedIndices( + index: integer): TBoldAddIndex; +begin + result := fAddedIndices[Index] as TBoldAddIndex; +end; + function TBoldDataBaseEvolutorScript.GetDroppedColumns(index: integer): TBoldDropColumn; begin result := TBoldDropColumn(fDroppedColumns[index]); @@ -431,6 +506,64 @@ function TBoldDataBaseEvolutorScript.GetMovedData( result := TBoldMoveData(fMovedData[index]); end; +function TBoldDataBaseEvolutorScript.HasAddColumn( + ColumnDesc: TBoldSQLColumnDescription): boolean; + var + i: integer; +begin + result := false; + for i := 0 to fAddedColumns.Count-1 do + if AddedColumns[i].ColumnDesc=ColumnDesc then + begin + result := true; + exit; + end; +end; + +function TBoldDataBaseEvolutorScript.HasAddIndex( + IndexDescription: TBoldSQLIndexDescription): boolean; +var + i: integer; +begin + result := false; + for i := 0 to fAddedIndices.Count - 1 do + if AddedIndices[i].IndexDescription=IndexDescription then + begin + result := true; + exit; + end; +end; + +function TBoldDataBaseEvolutorScript.HasDropColumn(const TableName, + ColumnName: String): boolean; +var + i: integer; +begin + result := false; + for i := 0 to fDroppedColumns.Count - 1 do + if AnsiSameText(DroppedColumns[i].TableName, TableName) and + AnsiSameText(DroppedColumns[i].ColumnName, ColumnName) then + begin + result := true; + exit; + end; +end; + +function TBoldDataBaseEvolutorScript.HasDropIndex(const IndexName, + TableName: string): boolean; +var + i: integer; +begin + result := false; + for I := 0 to fDroppedIndices.Count - 1 do + if AnsiSameText(DroppedIndices[i].IndexName, IndexName) + and AnsiSameText(DroppedIndices[i].TableName, TableName) then + begin + result := true; + exit; + end; +end; + function TBoldDataBaseEvolutorScript.GetDeletedInstances(index: integer): TBoldDeleteInstances; begin result := TBoldDeleteInstances(fDeletedInstances[index]); @@ -462,7 +595,7 @@ procedure TBoldDataBaseEvolutorScript.OptimizeScript; i := 0; while i < fMovedData.Count do begin - for j := fMovedData.Count - 1 downto i + 1 do + for j := fMovedData.Count-1 downto i+1 do begin if (MovedData[j].DbTypes = MovedData[i].DbTypes) and SameText(MovedData[j].SourceTable, MovedData[i].SourceTable) and @@ -478,26 +611,29 @@ procedure TBoldDataBaseEvolutorScript.OptimizeScript; MoveDataSignatures := TStringList.Create; try - for i := 0 to fMovedData.Count - 1 do + for i := 0 to fMovedData.Count-1 do MoveDataSignatures.AddObject(MovedData[i].Signature, MovedData[i]); MoveDataSignatures.Sort; - for i := 1 to MoveDataSignatures.Count - 1 do - if MoveDataSignatures[i - 1] = MoveDataSignatures[i] then + for i := 1 to MoveDataSignatures.Count-1 do + if MoveDataSignatures[i-1] = MoveDataSignatures[i] then begin - MoveData1 := TBoldMoveData(MoveDataSignatures.Objects[i - 1]); + MoveData1 := TBoldMoveData(MoveDataSignatures.Objects[i-1]); MoveData2 := TBoldMoveData(MoveDataSignatures.Objects[i]); - MoveData2.fdbTypes := MoveData2.dbTypes + ', ' + MoveData1.dbTypes; + MoveData2.fdbTypes := MoveData2.dbTypes + ', '+ MoveData1.dbTypes; fMovedData.Remove(MoveData1); - MoveData1.Free; + MoveData1.Free; end; finally MoveDataSignatures.free; end; + + end; procedure TBoldDataBaseEvolutorScript.DropIndex(const IndexName: String; const TableNAme: String); begin - fDroppedIndices.Add(TBoldDropIndex.Create(self, IndexName, TableName)); + if not HasDropIndex(IndexName, TableName) then + fDroppedIndices.Add(TBoldDropIndex.Create(self, IndexName, TableName)); end; function TBoldDataBaseEvolutorScript.GetDroppedIndices(index: integer): TBoldDropIndex; @@ -505,6 +641,12 @@ function TBoldDataBaseEvolutorScript.GetDroppedIndices(index: integer): TBoldDro result := fDroppedIndices[Index] as TBoldDropIndex; end; +procedure TBoldDataBaseEvolutorScript.AddIndex(IndexDescription: TBoldSQLIndexDescription); +begin + if not HasAddIndex(IndexDescription) then + fAddedIndices.Add(TBoldAddIndex.Create(self, IndexDescription )); +end; + procedure TBoldDataBaseEvolutorScript.AddSQLStatement(const sql: String); begin fSQLStatements.Add(sql); @@ -521,13 +663,13 @@ procedure TBoldDataBaseEvolutorScript.AdjustContents; // and Interbase does not make metadata changes visible inside the transaction StartTransaction; try - for i := 0 to fCopiedInstances.Count - 1 do + for i := 0 to fCopiedInstances.Count-1 do CopiedInstances[i].Execute; - for i := 0 to fMovedData.Count - 1 do + for i := 0 to fMovedData.Count-1 do MovedData[i].Execute; - for i := 0 to fDeletedInstances.Count - 1 do + for i := 0 to fDeletedInstances.Count-1 do DeletedInstances[i].Execute; CommitTransaction; @@ -541,25 +683,25 @@ procedure TBoldDataBaseEvolutorScript.ExtendSchema; var i: integer; begin - if fAddedTables.Count + fAddedColumns.Count = 0 then + if fAddedTables.Count + fAddedColumns.Count + fAddedIndices.Count = 0 then Exit; // wrap all non MetaData changes in a transaction. // Many databases do not allow them in a transaction, // and Interbase does not make metadata changes visible inside the transaction - if fSQLDataBaseConfig.AllowMetadataChangesInTransaction then - StartTransaction; + StartTransaction; try - for i := 0 to fAddedTables.Count - 1 do + for i := 0 to fAddedTables.Count-1 do AddedTables[i].Execute; - for i := 0 to fAddedColumns.Count - 1 do + for i := 0 to fAddedColumns.Count-1 do AddedColumns[i].Execute; - if fSQLDataBaseConfig.AllowMetadataChangesInTransaction then - CommitTransaction; + for i := 0 to fAddedIndices.Count-1 do + AddedIndices[i].Execute; + + CommitTransaction; except - if fSQLDataBaseConfig.AllowMetadataChangesInTransaction then - RollBackTransaction; + RollBackTransaction; raise; end; @@ -571,8 +713,7 @@ procedure TBoldDataBaseEvolutorScript.ReduceSchema; begin if fDroppedIndices.Count + fDroppedColumns.Count + fDroppedtables.Count = 0 then Exit; - if fSQLDataBaseConfig.AllowMetadataChangesInTransaction then - StartTransaction; + StartTransaction; try for i := 0 to fDroppedIndices.Count - 1 do DroppedIndices[i].Execute; @@ -583,11 +724,9 @@ procedure TBoldDataBaseEvolutorScript.ReduceSchema; for i := 0 to fDroppedTables.Count - 1 do DroppedTables[i].Execute; - if fSQLDataBaseConfig.AllowMetadataChangesInTransaction then - CommitTransaction; + CommitTransaction; except - if fSQLDataBaseConfig.AllowMetadataChangesInTransaction then - RollBackTransaction; + RollBackTransaction; raise; end; end; @@ -620,6 +759,8 @@ procedure TBoldDataBaseEvolutorScript.AddCommandToScript(s: string); procedure TBoldDataBaseEvolutorScript.StartTransaction; begin + if not fSQLDataBaseConfig.AllowMetadataChangesInTransaction then + exit; if assigned(fDataBase) then fDataBase.StartTransaction; if assigned(fScript) then @@ -627,7 +768,11 @@ procedure TBoldDataBaseEvolutorScript.StartTransaction; end; procedure TBoldDataBaseEvolutorScript.CommitTransaction; +const + sCommittingToDB = 'Committing changes to database'; begin + if not fSQLDataBaseConfig.AllowMetadataChangesInTransaction then + exit; if assigned(fDataBase) and fDatabase.InTransaction then begin BoldLog.Log(sCommittingToDB); @@ -635,17 +780,21 @@ procedure TBoldDataBaseEvolutorScript.CommitTransaction; end; if assigned(fScript) then AddCommandToScript(fSQLDataBaseConfig.SqlScriptCommitTransaction); - end; procedure TBoldDataBaseEvolutorScript.RollBackTransaction; +const + sRollingBackDB = 'Rolling back database changes'; begin + if not fSQLDataBaseConfig.AllowMetadataChangesInTransaction then + exit; if assigned(fDataBase) and fDatabase.InTransaction then begin BoldLog.Log(sRollingBackDB); fDataBase.RollBack; end; - AddCommandToScript(fSQLDataBaseConfig.SqlScriptRollBackTransaction); + if assigned(fScript) then + AddCommandToScript(fSQLDataBaseConfig.SqlScriptRollBackTransaction); end; { TBoldAddColumn } @@ -661,15 +810,14 @@ procedure TBoldAddColumn.Execute; i: integer; index: TBoldSQLIndexDescription; begin - Script.Comment(sAddColumn, [ColumnDesc.TableDescription.SQLName, ColumnDesc.SQLName]); - Script.ExecuteSQL( 'ALTER TABLE %s ADD %s', [ColumnDesc.TableDescription.SQLName, ColumnDesc.GetSQLForColumn(Script.fDataBase)]); // do not localize + Script.Comment('Add column %s.%s', [ColumnDesc.TableDescription.SQLName, ColumnDesc.SQLName]); + Script.ExecuteSQL( 'ALTER TABLE %s ADD %s', [ColumnDesc.TableDescription.SQLName, ColumnDesc.GetSQLForColumn(Script.fDataBase)]); + // There was code to also add index here, but we removed it as indexes are handled by separate AddIndex Operation +end; - for i := 0 to ColumnDesc.TableDescription.IndexList.Count - 1 do - begin - Index := ColumnDesc.TableDescription.IndexList[i] as TBoldSQLIndexDescription; - if SameText(Index.IndexedFields, ColumnDesc.SQLName) then - Script.ExecuteSQL(Index.SQLForSecondaryKey, []); - end; +function TBoldAddColumn.GetDebugInfo: string; +begin + result := ClassName + ':' + ColumnDesc.TableDescription.SQLName + '.' + ColumnDesc.SQLName; end; { TBoldCopyInstances } @@ -700,7 +848,7 @@ procedure TBoldCopyInstances.Execute; WhereConds: TStringList; SelectColumn: string; begin - Script.Comment(sAddInstanceOfClassToTable, [ExpressionName, TargetTable]); + Script.Comment('Add Instances of class %s to table %s', [ExpressionName, TargetTable]); SourceColumns := TStringList.Create; TargetColumns := TStringList.Create; IdColumnList := TStringList.Create; @@ -709,7 +857,7 @@ procedure TBoldCopyInstances.Execute; try SourceTables.Add(SourceTable); IdColumnList.Commatext := IdColumns; - for i := 0 to IdColumnLIst.Count - 1 do + for i := 0 to IdColumnLIst.Count-1 do begin SourceColumns.Add(SourceTable + '.' + IdColumnList[i]); TargetColumns.Add(IdColumnList[i]); @@ -717,28 +865,27 @@ procedure TBoldCopyInstances.Execute; LocalMoveData := MoveData; while assigned(LocalMoveData) do begin - Script.Comment(sMoveDataFromXtoY, [LocalMoveData.SourceTable, LocalMoveData.SourceColumn, LocalMoveData.TargetTable, LocalMoveData.TargetColumn, LocalMoveData.DbTypes]); + Script.Comment('Move data from %s.%s to %s.%s (dbtypes: %s)', [LocalMoveData.SourceTable, LocalMoveData.SourceColumn, LocalMoveData.TargetTable, LocalMoveData.TargetColumn, LocalMoveData.DbTypes]); if SourceTables.IndexOf(LocalMoveData.SourceTable) = -1 then SourceTables.Add(LocalMoveData.SourceTable); SelectColumn := LocalMoveData.SourceTable + '.' + LocalMoveData.SourceColumn; - // Renamed column needs alias if not SameText(LocalMoveData.SourceColumn, LocalMoveData.TargetColumn) then - SelectColumn := SelectColumn + ' AS ' + LocalMoveData.TargetColumn; // do not localize + SelectColumn := SelectColumn + ' AS ' + LocalMoveData.TargetColumn; SourceColumns.Add(SelectColumn); TargetColumns.Add(LocalMoveData.TargetColumn); LocalMoveData := LocalMoveData.AlsoMoveData; end; - sql := 'INSERT INTO %s (BOLD_TYPE, %s) SELECT %s.BOLD_TYPE, %s FROM %s%s'; // do not localize + sql := 'INSERT INTO %s (BOLD_TYPE, %s) SELECT %s.BOLD_TYPE, %s FROM %s%s'; - for i := 1 to SourceTables.Count - 1 do - for j := 0 to IdColumnList.Count - 1 do - WhereConds.Add(Format('%s.%s = %s.%s', [ // do not localize + for i := 1 to SourceTables.Count-1 do + for j := 0 to IdColumnList.Count-1 do + WhereConds.Add(Format('%s.%s = %s.%s', [ SourceTables[0], IdColumnList[j], SourceTables[i], IdColumnList[j]])); if SourceDbType <> NO_CLASS then - WhereConds.Add(Format('BOLD_TYPE = %d', [SourceDbType])); // do not localize + WhereConds.Add(Format('BOLD_TYPE = %d', [SourceDbType])); Script.ExecuteSQL(sql, [ TargetTable, @@ -746,7 +893,7 @@ procedure TBoldCopyInstances.Execute; SourceTable, BoldSeparateStringList(SourceColumns, ', ', '', ''), BoldSeparateStringList(SourceTables, ', ', '', ''), - BoldSeparateStringList(WhereConds, ' AND ', ' WHERE ', '')]); // do not localize + BoldSeparateStringList(WhereConds, ' AND ', ' WHERE ', '')]); finally SourceColumns.Free; SourceTables.Free; @@ -767,8 +914,13 @@ constructor TBoldDeleteInstances.Create(Script: TBoldDataBaseEvolutorScript; con procedure TBoldDeleteInstances.Execute; begin - Script.Comment(sDeleteInstancesOfClassFromTable, [ExpressionName, TableName]); - Script.ExecuteSQL('DELETE FROM %s WHERE BOLD_TYPE = %d', [TableName, DbType]); // do not localize + Script.Comment('Delete instances of %s from table %s', [ExpressionName, TableName]); + Script.ExecuteSQL('DELETE FROM %s WHERE BOLD_TYPE = %d', [TableName, DbType]); +end; + +function TBoldDeleteInstances.GetDebugInfo: string; +begin + result := ClassName + ':' + ExpressionName; end; { TBoldTableOperation } @@ -779,6 +931,11 @@ constructor TBoldTableOperation.Create(Script: TBoldDataBaseEvolutorScript; cons fTableName := TableName; end; +function TBoldTableOperation.GetDebugInfo: string; +begin + result := ClassName + ':' + TableName; +end; + { TBoldColumnOperation } constructor TBoldColumnOperation.Create(Script: TBoldDataBaseEvolutorScript; const TableName, ColumnName: String); @@ -787,6 +944,11 @@ constructor TBoldColumnOperation.Create(Script: TBoldDataBaseEvolutorScript; con fColumnName := ColumnName; end; +function TBoldColumnOperation.GetDebugInfo: string; +begin + result := ClassName + ':' + ColumnName; +end; + { TBoldTwoTableOperation } constructor TBoldTwoTableOperation.Create(Script: TBoldDataBaseEvolutorScript; const SourceTable, TargetTable: String); @@ -796,6 +958,11 @@ constructor TBoldTwoTableOperation.Create(Script: TBoldDataBaseEvolutorScript; c fTargetTable := TargetTable; end; +function TBoldTwoTableOperation.GetDebugInfo: string; +begin + result := ClassName + ':' + SourceTable + '->' + TargetTable; +end; + { TBoldTwoColumnOperation } constructor TBoldTwoColumnOperation.Create(Script: TBoldDataBaseEvolutorScript; const SourceTable, TargetTable, SourceColumn, TargetColumn: String); @@ -839,34 +1006,34 @@ procedure TBoldMoveData.Execute; SelectColumns := TStringList.Create; IdColumnList := TStringList.Create; IdColumnJoins := TStringList.Create; - + LocalMoveData := self; while assigned(LocalMoveData) do begin - Script.Comment(sMoveDataFromXtoY, [LocalMoveData.SourceTable, LocalMoveData.SourceColumn, LocalMoveData.TargetTable, LocalMoveData.TargetColumn, LocalMoveData.DbTypes]); + Script.Comment('Move data from %s.%s to %s.%s (dbtype: %s)', [LocalMoveData.SourceTable, LocalMoveData.SourceColumn, LocalMoveData.TargetTable, LocalMoveData.TargetColumn, LocalMoveData.DbTypes]); SourceColumns.Add(LocalMoveData.SourceColumn); TargetColumns.Add(LocalMoveData.TargetColumn); LocalMoveData := LocalMoveData.AlsoMoveData; end; if SameText(SourceTable, TargetTable) then begin - for i := 0 to SourceColumns.Count - 1 do - CopyStatements.Add(format('%s = %s', [TargetColumns[i], SourceColumns[i]])); // do not localize - Script.ExecuteSQL('UPDATE %s SET %s WHERE BOLD_TYPE IN (%s)', [TargetTable, BoldSeparateStringList(CopyStatements, ', ', '', ''), dbTypes]); // do not localize + for i := 0 to SourceColumns.Count-1 do + CopyStatements.Add(format('%s = %s', [TargetColumns[i], SourceColumns[i]])); + Script.ExecuteSQL('UPDATE %s SET %s WHERE BOLD_TYPE IN (%s)', [TargetTable, BoldSeparateStringList(CopyStatements, ', ', '', ''), dbTypes]); end else begin IdColumnList.CommaText := IdColumns; - for i := 0 to IdColumnList.Count - 1 do - IdColumnJoins.Add(format('Source.%s = Target.%s', [IdColumnList[i], IdColumnList[i]])); // do not localize + for i := 0 to IdColumnList.Count-1 do + IdColumnJoins.Add(format('Source.%s = Target.%s', [IdColumnList[i], IdColumnList[i]])); - for i := 0 to SourceColumns.Count - 1 do - SelectColumns.Add(format('%s = (SELECT %s FROM %s Source WHERE %s)', [ // do not localize + for i := 0 to SourceColumns.Count-1 do + SelectColumns.Add(format('%s = (SELECT %s FROM %s Source WHERE %s)', [ SourceColumns[i], TargetColumns[i], SourceTable, - BoldSeparateStringList(IdColumnJoins, ' AND ', '', '')])); // do not localize - Script.ExecuteSQL('UPDATE %s Target SET %s WHERE BOLD_TYPE IN (%s)', [TargetTable, BoldSeparateStringList(SelectColumns, ', ', '', ''), DbTypes]); // do not localize + BoldSeparateStringList(IdColumnJoins, ' AND ', '', '')])); + Script.ExecuteSQL('UPDATE %s Target SET %s WHERE BOLD_TYPE IN (%s)', [TargetTable, BoldSeparateStringList(SelectColumns, ', ', '', ''), DbTypes]); end; end; @@ -902,10 +1069,15 @@ constructor TBoldDropIndex.Create(Script: TBoldDataBaseEvolutorScript; const Ind procedure TBoldDropIndex.Execute; begin - Script.Comment(sDropIndex, [IndexName]); + Script.Comment('Drop index %s', [IndexName]); Script.ExecuteSQL(Script.fSqlDatabaseConfig.GetDropIndexQuery(TableName, IndexName), []); end; +function TBoldDropIndex.GetDebugInfo: string; +begin + result := ClassName + ':' + TableName + '.' + IndexName; +end; + { TBoldScriptOperation } constructor TBoldScriptOperation.Create(Script: TBoldDataBaseEvolutorScript); @@ -918,7 +1090,7 @@ constructor TBoldScriptOperation.Create(Script: TBoldDataBaseEvolutorScript); procedure TBoldDropColumn.Execute; begin - Script.Comment(sDropColumn, [TableName, ColumnName]); + Script.Comment('Drop column %s.%s', [TableName, ColumnName]); Script.ExecuteSQL(Script.fSqlDatabaseConfig.GetDropColumnQuery(TableName, ColumnName), []); end; @@ -926,10 +1098,28 @@ procedure TBoldDropColumn.Execute; procedure TBoldDropTable.Execute; begin - Script.Comment(sDropTable, [TableName]); + Script.Comment('Drop table %s', [TableName]); Script.ExecuteSQL(Script.fSqlDatabaseConfig.GetDropTableQuery(TableName), []); end; -end. +{ TBoldAddIndex } + +constructor TBoldAddIndex.Create(Script: TBoldDataBaseEvolutorScript; IndexDescription: TBoldSQLIndexDescription); +begin + inherited Create(Script); + fIndexDescription := IndexDescription; +end; +procedure TBoldAddIndex.Execute; +begin + Script.Comment('Create index %s %s:[%s] ', [IndexDescription.GeneratedName, IndexDescription.TableDescription.SQLNAme, IndexDescription.IndexedFields]); + Script.ExecuteSQL(IndexDescription.SQLForSecondaryKey, []); +end; +function TBoldAddIndex.GetDebugInfo: string; +begin + result := ClassName + ':' + IndexDescription.IndexedFields; +end; + +initialization +end. diff --git a/Source/PMapper/Default/BoldCustomBlobMapper.pas b/Source/PMapper/Default/BoldCustomBlobMapper.pas index 2eabd5c..52b8ec4 100644 --- a/Source/PMapper/Default/BoldCustomBlobMapper.pas +++ b/Source/PMapper/Default/BoldCustomBlobMapper.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldCustomBlobMapper; interface @@ -16,7 +19,7 @@ interface type TBoldPMBlobWithSeparateTable = class(TBoldMemberDefaultMapper) private - function GetBlobValue(Id: TBoldObjectId; ValueSpace: IBoldValueSpace): IBoldBlobContent; + function GetBlobValue(Id: TBoldObjectId; const ValueSpace: IBoldValueSpace): IBoldBlobContent; function IdListToString(IdList: TBoldObjectIdList): String; protected function GetColumnBDEFieldType(ColumnIndex: Integer): TFieldType; override; @@ -24,14 +27,14 @@ TBoldPMBlobWithSeparateTable = class(TBoldMemberDefaultMapper) function GetColumnCount: Integer; override; function GetColumnSize(ColumnIndex: Integer): Integer; override; function GetInitialColumnName(ColumnIndex: Integer): string; override; - function CompareField(ObjectContent: IBoldObjectContents; Field: IBoldField; ColumnIndex: integer; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList): Boolean; override; + function CompareField(const ObjectContent: IBoldObjectContents; const Field: IBoldField; ColumnIndex: integer; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList): Boolean; override; procedure InitializePSDescriptions; override; public constructor CreateFromMold(moldMember: TMoldMember; moldClass: TMoldClass; Owner: TBoldObjectPersistenceMapper; const MemberIndex: Integer; TypeNameDictionary: TBoldTypeNameDictionary); override; - procedure PMFetch(ObjectIdList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; FetchMode: Integer; TranslationList: TBoldIdTranslationList; FailureList: TBoldObjectIdList); override; - procedure PMCreate(ObjectIdList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList); override; - procedure PMUpdate(ObjectIdList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList); override; - procedure PMDelete(ObjectIdList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList); override; + procedure PMFetch(ObjectIdList: TBoldObjectIdList; const ValueSpace: IBoldValueSpace; FetchMode: Integer; TranslationList: TBoldIdTranslationList; FailureList: TBoldObjectIdList); override; + procedure PMCreate(ObjectIdList: TBoldObjectIdList; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList); override; + procedure PMUpdate(ObjectIdList: TBoldObjectIdList; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList); override; + procedure PMDelete(ObjectIdList: TBoldObjectIdList; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList); override; class function CanStore(const ContentName: String): Boolean; override; end; @@ -44,13 +47,12 @@ implementation BoldDefs, BoldPMapperLists, BoldMemberTypeDictionary, - BoldDefaultStreamNames, - BoldPMConsts; + BoldDefaultStreamNames; {const MemberNameColumn = 'MEMBERNAME'; } - + const BLOBDATA_TABLENAME = 'BLOBDATATABLE'; BLOBDATA_DATACOLUMNNAME = 'BLOBDATA'; @@ -78,8 +80,8 @@ function TBoldPMBlobWithSeparateTable.GetColumnTypeAsSQL(ColumnIndex: Integer): 0: result := SystemPersistenceMapper.SQLDataBaseConfig.ColumnTypeForInteger; 1: result := format(SystemPersistenceMapper.SQLDataBaseConfig.ColumnTypeForString, [ColumnSize[ColumnIndex]] ); 2: result := SystemPersistenceMapper.SQLDataBaseConfig.ColumnTypeForBlob; - else - raise EBold.CreateFmt(sIllegalColumnIndex, [classname, 'GetColumnTypeAsSQL', columnIndex] ); // do not localize + else + raise EBold.CreateFmt( '%s.GetColumnTypeAsSQL: unknown column (%d)', [classname, columnIndex] ); end; end; @@ -113,15 +115,15 @@ constructor TBoldPMBlobWithSeparateTable.CreateFromMold(moldMember: TMoldMember; begin inherited; if length(ExpressionName) > ColumnSize[1] then - raise EBold.CreateFmt(sMemberNameTooLong, [ClassName, ExpressionName, ColumnSize[1]] ); + raise EBold.CreateFmt( '%s.CreateFromMold: Too long MemberName (%s) - %d characters allowed', [ClassName, ExpressionName, ColumnSize[1]] ); fCustomCreateUpDate := true; fCustomFetch := true; if MoldClass.Versioned then - raise EBold.CreateFmt( sVersionedClassesNotSupported, [ClassName, MoldClass.ExpressionName]); + raise EBold.CreateFmt( '%s.CreateFromMold: Versioned classes (%s) currently not supported by this blobmapper', [ClassName, MoldClass.ExpressionName]); end; -procedure TBoldPMBlobWithSeparateTable.PMFetch(ObjectIdList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; FetchMode: Integer; TranslationList: TBoldIdTranslationList; FailureList: TBoldObjectIdList); +procedure TBoldPMBlobWithSeparateTable.PMFetch(ObjectIdList: TBoldObjectIdList; const ValueSpace: IBoldValueSpace; FetchMode: Integer; TranslationList: TBoldIdTranslationList; FailureList: TBoldObjectIdList); var q : IBoldQuery; Id: TBoldObjectId; @@ -135,7 +137,7 @@ procedure TBoldPMBlobWithSeparateTable.PMFetch(ObjectIdList: TBoldObjectIdList; try ActionList.AddList(ObjectIdlist); - sql := Format('SELECT %s, %s FROM %s WHERE %s IN (%s) AND UPPER(%s) = ''%s''', [ // do not localize + sql := Format('SELECT %s, %s FROM %s WHERE %s IN (%s) AND UPPER(%s) = ''%s''', [ IDCOLUMN_NAME, BLOBDATA_DATACOLUMNNAME, BLOBDATA_TABLENAME, IDCOLUMN_NAME, IdListToString(ActionList), BLOBDATA_MEMBERCOLUMNNAME, UpperCase(ExpressionName) ] ); @@ -144,7 +146,9 @@ procedure TBoldPMBlobWithSeparateTable.PMFetch(ObjectIdList: TBoldObjectIdList; q.Open; while not q.Eof do begin - Id := SystemPersistenceMapper.NewIdFromQuery(q, -1, 0, BOLDMAXTIMESTAMP); + // ClassId param -1 was added due to changes in signature of NewIdFromQuery, + // check if we can replace -1 with known ClassId if possible in order to get ExactId right away - Daniel + Id := SystemPersistenceMapper.NewIdFromQuery(q, -1, -1, 0, BOLDMAXTIMESTAMP); try value := GetBlobValue(Id, ValueSpace); Value.asBlob := q.Fields[1].AsBlob; @@ -165,29 +169,30 @@ procedure TBoldPMBlobWithSeparateTable.PMFetch(ObjectIdList: TBoldObjectIdList; end; end; -procedure TBoldPMBlobWithSeparateTable.PMCreate(ObjectIdList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList); +procedure TBoldPMBlobWithSeparateTable.PMCreate(ObjectIdList: TBoldObjectIdList; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList); var q: IBoldExecQuery; value: IBoldBlobContent; i: integer; - param: IBoldParameter; + IdParam, DataParam: IBoldParameter; begin Q := SystemPersistenceMapper.GetExecQuery; try - q.AssignSQLText(Format('INSERT INTO %s (%s, %s, %s) VALUES (:%s, :%s, :%s)', // do not localize + q.ParamCheck := true; + q.AssignSQLText(Format('INSERT INTO %s (%s, %s, %s) VALUES (:%s, :%s, :%s)', [BLOBDATA_TABLENAME, IDCOLUMN_NAME, BLOBDATA_MEMBERCOLUMNNAME, BLOBDATA_DATACOLUMNNAME, IDCOLUMN_NAME, BLOBDATA_MEMBERCOLUMNNAME, BLOBDATA_DATACOLUMNNAME])); q.ParamByName(BLOBDATA_MEMBERCOLUMNNAME).AsString := UpperCase(ExpressionName); + IdParam := q.ParamByName(IDCOLUMN_NAME); + DataParam := q.ParamByName(BLOBDATA_DATACOLUMNNAME); for i := 0 to ObjectIdList.Count-1 do begin - q.ParamByName(IDCOLUMN_NAME).AsInteger := StrToInt(TranslationList.TranslateToNewId[ObjectIdList[i]].AsString); + IdParam.AsInteger := StrToInt(TranslationList.TranslateToNewId[ObjectIdList[i]].AsString); Value := GetBlobValue(ObjectIdList[i], ValueSpace); - Param := q.ParamByName(BLOBDATA_DATACOLUMNNAME); - Param.DataType := SystemPersistenceMapper.SQLDataBaseConfig.FieldTypeForBlob; -//marco Param.AsBlob := Value.asBlob; + DataParam.AsBlob := Value.asBlob; q.ExecSQL; end; finally @@ -195,35 +200,35 @@ procedure TBoldPMBlobWithSeparateTable.PMCreate(ObjectIdList: TBoldObjectIdList; end; end; -procedure TBoldPMBlobWithSeparateTable.PMUpdate(ObjectIdList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList); +procedure TBoldPMBlobWithSeparateTable.PMUpdate(ObjectIdList: TBoldObjectIdList; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList); var q : IBoldExecQuery; i: integer; sql: string; value: IBoldBlobContent; - param: IBoldParameter; + IdParam, DataParam: IBoldParameter; begin Q := SystemPersistenceMapper.GetExecQuery; try - sql := Format('UPDATE %s SET %s = :%s WHERE %s = :%s AND UPPER(%s) = ''%s''', [ // do not localize + q.ParamCheck := true; + sql := Format('UPDATE %s SET %s = :%s WHERE %s = :%s AND UPPER(%s) = ''%s''', [ BLOBDATA_TABLENAME, BLOBDATA_DATACOLUMNNAME, BLOBDATA_DATACOLUMNNAME, IDCOLUMN_NAME, IDCOLUMN_NAME, BLOBDATA_MEMBERCOLUMNNAME, UpperCase(ExpressionName)]); q.AssignSQLText(sql); + IdParam := q.ParamByName(IDCOLUMN_NAME); + DataParam := q.ParamByName(BLOBDATA_DATACOLUMNNAME); for i := 0 to ObjectIdList.Count-1 do begin Value := GetBlobValue(ObjectIdList[i], ValueSpace); if Value.IsNull then - q.ParamByName(BLOBDATA_DATACOLUMNNAME).Clear + DataParam.Clear else - begin - Param := q.ParamByName(BLOBDATA_DATACOLUMNNAME); - Param.DataType := SystemPersistenceMapper.SQLDataBaseConfig.FieldTypeForBlob; -//marco Param.AsBlob := Value.asBlob; - end; - q.ParamByName(IDCOLUMN_NAME).AsInteger := StrToInt(ObjectIdList[i].AsString); + DataParam.AsBlob := Value.asBlob; + + IdParam.AsInteger := StrToInt(ObjectIdList[i].AsString); q.ExecSQL; end; finally @@ -231,13 +236,13 @@ procedure TBoldPMBlobWithSeparateTable.PMUpdate(ObjectIdList: TBoldObjectIdList; end; end; -procedure TBoldPMBlobWithSeparateTable.PMDelete(ObjectIdList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList); +procedure TBoldPMBlobWithSeparateTable.PMDelete(ObjectIdList: TBoldObjectIdList; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList); var q: IBoldExecQuery; begin Q := SystemPersistenceMapper.GetExecQuery; try - q.AssignSQLText(Format( 'DELETE FROM %s WHERE %s IN (%s) AND UPPER(%s) = ''%s''', [ // do not localize + q.AssignSQLText(Format( 'DELETE FROM %s WHERE %s IN (%s) AND UPPER(%s) = ''%s''', [ BLOBDATA_TABLENAME, IDColumn_NAME, IdListToString(ObjectIdList), BLOBDATA_MEMBERCOLUMNNAME, UpperCase(ExpressionName)])); @@ -252,7 +257,7 @@ class function TBoldPMBlobWithSeparateTable.CanStore(const ContentName: String): result := ContentName = BoldContentName_Blob; end; -function TBoldPMBlobWithSeparateTable.GetBlobValue(Id: TBoldObjectId; ValueSpace: IBoldValueSpace): IBoldBlobContent; +function TBoldPMBlobWithSeparateTable.GetBlobValue(Id: TBoldObjectId; const ValueSpace: IBoldValueSpace): IBoldBlobContent; var ObjectContents: IBoldObjectContents; value: IBoldValue; @@ -260,16 +265,16 @@ function TBoldPMBlobWithSeparateTable.GetBlobValue(Id: TBoldObjectId; ValueSpace begin Objectcontents := ValueSpace.ObjectContentsByObjectId[ID]; if not assigned(ObjectContents) then - raise Exception.CreateFmt(sObjectNotInValueSpace, [ClassName, ObjectpersistenceMapper.ExpressionName, ExpressionName, Id.AsString]); + raise Exception.CreateFmt('%s.GetBlobValue: Trying to get blob value for %s.%s, but the object (ID: %s) is not in the ValueSpace', [ClassName, ObjectpersistenceMapper.ExpressionName, ExpressionName, Id.AsString]); MemberID := TBoldMemberId.Create(MemberIndex); ObjectContents.EnsureMember(MemberID, ContentName); MemberID.Free; value := ObjectContents.ValueByIndex[MemberIndex]; if not assigned(value) then - raise Exception.CreateFmt(sValueNotInValueSpace, [ClassName, ObjectpersistenceMapper.ExpressionName, ExpressionName, Id.AsString]); + raise Exception.CreateFmt('%s.GetBlobValue: Trying to get blob value for %s.%s, but the value (ID: %s) is not in the ValueSpace', [ClassName, ObjectpersistenceMapper.ExpressionName, ExpressionName, Id.AsString]); if not value.QueryInterface(IBoldBlobContent, result) = S_OK then - raise Exception.CreateFmt(sValueNotBlob, [ClassName, ObjectpersistenceMapper.ExpressionName, ExpressionName]); + raise Exception.CreateFmt('%s.GetBlobValue: Trying to get blob value for %s.%s, but the value was not a blob...', [ClassName, ObjectpersistenceMapper.ExpressionName, ExpressionName]); end; function TBoldPMBlobWithSeparateTable.IdListToString(IdList: TBoldObjectIdList): String; @@ -286,11 +291,11 @@ function TBoldPMBlobWithSeparateTable.IdListToString(IdList: TBoldObjectIdList): end; function TBoldPMBlobWithSeparateTable.CompareField( - ObjectContent: IBoldObjectContents; Field: IBoldField; - ColumnIndex: integer; ValueSpace: IBoldValueSpace; + const ObjectContent: IBoldObjectContents; const Field: IBoldField; + ColumnIndex: integer; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList): Boolean; begin - raise Exception.CreateFmt(sCustomCompareRequired, [ClassName]); + raise Exception.CreateFmt('%s.CompareField: needs a custom Compare to do this', [ClassName]); end; procedure TBoldPMBlobWithSeparateTable.InitializePSDescriptions; @@ -305,10 +310,9 @@ procedure TBoldPMBlobWithSeparateTable.InitializePSDescriptions; BlobTable.SQLName := BLOBDATA_TABLENAME; BlobTable.AddColumn(InitialColumnName[0], ColumnTypeAsSQL[0], SystemPersistenceMapper.SQLDataBaseConfig.EffectiveSQLForNotNull, ColumnBDEFieldType[0], ColumnSize[0], false, ''); Blobtable.AddColumn(InitialColumnName[1], ColumnTypeAsSQL[1], SystemPersistenceMapper.SQLDataBaseConfig.EffectiveSQLForNotNull, ColumnBDEFieldType[1], ColumnSize[1], false, ''); - // the blob-column must allow null since it is reused for all blobs, and - // one of them might allow null + Blobtable.AddColumn(InitialColumnName[2], ColumnTypeAsSQL[2], '', ColumnBDEFieldType[2], ColumnSize[2], true, ''); - BlobTable.EnsureIndex(InitialColumnName[0] + ',' + InitialColumnName[1], true, true ); + BlobTable.EnsureIndex(InitialColumnName[0] + ',' + InitialColumnName[1], true, true, true ); end; end; @@ -318,5 +322,4 @@ initialization finalization if BoldMemberPersistenceMappersAssigned and BoldMemberTypesAssigned then BoldMemberPersistenceMappers.RemoveDescriptorByClass(TBoldPMBlobWithSeparateTable); - end. diff --git a/Source/PMapper/Default/BoldMappingInfo.pas b/Source/PMapper/Default/BoldMappingInfo.pas index 4df1977..987be91 100644 --- a/Source/PMapper/Default/BoldMappingInfo.pas +++ b/Source/PMapper/Default/BoldMappingInfo.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldMappingInfo; interface @@ -9,10 +12,10 @@ interface BoldDbInterfaces; type - { TBoldDefaultMappingInfo } + TBoldDefaultMappingInfo = class(TBoldSQLMappingInfo) private - procedure ScriptForClearData(Script: TStrings; separator: string; terminator: string); + procedure ScriptForClearData(Script: TStrings; Separator: string; Terminator: string); function AITableName: string; function MMTableName: string; function OSTableName: string; @@ -20,7 +23,8 @@ TBoldDefaultMappingInfo = class(TBoldSQLMappingInfo) function ExpandColumn(ColumnName: String): String; public procedure ReadDataFromDB(DataBase: IBoldDataBase; ReadDbTypeFromDB, ReadMappingFromDB: Boolean); override; - procedure ScriptForWriteData(Script: TStrings; Separator: string; ClearFirst: Boolean = true; terminator: string = ''); override; + procedure ScriptForWriteData(DataBase: IBoldDataBase; Script: TStrings; ClearFirst: Boolean; + Separator: String; Terminator: String); override; end; implementation @@ -30,27 +34,48 @@ implementation BoldUtils, BoldDefs; -{ TBoldDeafultMappingInfo } +{ TBoldDefaultMappingInfo } function TBoldDefaultMappingInfo.AITableName: string; begin result := BoldExpandPrefix(AllInstancesMappingTable_NAME, '', fSystemTablePrefix, MaxDBIdentifierLength, NationalCharConversion) end; -procedure TBoldDefaultMappingInfo.ScriptForClearData(Script: TStrings; separator: string; terminator: string); +procedure TBoldDefaultMappingInfo.ScriptForClearData(Script: TStrings; Separator: string; Terminator: string); procedure ClearTable(TableName: string); begin - script.add('DELETE FROM ' + TableName+terminator); // do not localize - if separator <> '' then + script.add('DELETE FROM ' + TableName+Terminator); // do not localize + if Separator <> '' then Script.Add(Separator); end; + procedure AddColumnIndexColumn; + var + sScript: string; + begin + if (FCurrentDatabase <> nil) and + (FCurrentDatabase.SQLDatabaseConfig <> nil) then + begin + sScript := Format('ALTER TABLE %s ADD %s '+FCurrentDatabase.SQLDatabaseConfig.ColumnTypeForInteger+' DEFAULT 0 '+FCurrentDatabase.SQLDatabaseConfig.SQLForNotNull, + [MMTableName, MMT_INDEX_COLUMN]); + sScript := FCurrentDatabase.SQLDatabaseConfig.GetIfColumnNotExistsQuery( + MMTableName, MMT_INDEX_COLUMN, sScript); + sScript := sScript + Terminator; + script.add(sScript); + if Separator <> '' then + Script.Add(Separator); + end; + end; + begin ClearTable(AITableName); ClearTable(MMTableName); ClearTable(OSTableName); ClearTable(DbTypeTableName); +{$IFDEF IndexColumn} + AddColumnIndexColumn; +{$ENDIF} end; @@ -79,17 +104,25 @@ procedure TBoldDefaultMappingInfo.ReadDataFromDB(DataBase: IBoldDataBase; ReadDb SELECTFROM = 'SELECT * FROM '; var q: IBoldQuery; -function GetMappernameFromQuery: String; -var - Field: IBoldField; -begin - Field := Q.FindField(ExpandColumn(MMT_MAPPERNAME_COLUMN)); - if assigned(Field) then - result := Field.AsString - else - result := ''; -end; + function GetMappernameFromQuery: String; + var + Field: IBoldField; + begin + Field := Q.FindField(ExpandColumn(MMT_MAPPERNAME_COLUMN)); + if assigned(Field) then + result := Field.AsString + else + result := ''; + end; +var + bColumnIndex: Boolean; + vClassNameField: IBoldField; + vTableNameField: IBoldField; + vMemberNameField: IBoldField; + vColumnsField: IBoldField; + vClassIdRequiredField: IBoldField; + vTypeColumnield: IBoldField; begin q := DataBase.GetQuery; try @@ -99,11 +132,14 @@ function GetMappernameFromQuery: String; q.AssignSQlText(SELECTFROM + AITableName); q.Open; + vClassNameField := q.FieldByName(ExpandColumn(AID_CLASSNAME_COLUMN)); + vTableNameField := q.FieldByName(ExpandColumn(AID_TABLENAME_COLUMN)); + vClassIdRequiredField := q.FieldByName(ExpandColumn(AID_CLASSIDREQUIRED_COLUMN)); while not Q.Eof do begin - AddAllInstancesMapping(q.FieldByName(ExpandColumn(AID_CLASSNAME_COLUMN)).AsString, - q.FieldByName(ExpandColumn(AID_TABLENAME_COLUMN)).AsString, - q.FieldByName(ExpandColumn(AID_CLASSIDREQUIRED_COLUMN)).AsInteger=1); + AddAllInstancesMapping(vClassNameField.AsString, + vTableNameField.AsString, + vClassIdRequiredField.AsInteger=1); q.Next; end; q.Close; @@ -111,13 +147,25 @@ function GetMappernameFromQuery: String; q.AssignSQLText(SELECTFROM + MMTableName); q.Open; + vClassNameField := q.FieldByName(ExpandColumn(MMT_CLASSNAME_COLUMN)); + vTableNameField := q.FieldByName(ExpandColumn(MMT_TABLENAME_COLUMN)); + vMemberNameField := q.FieldByName(ExpandColumn(MMT_MEMBERNAME_COLUMN)); + vColumnsField := q.FieldByName(ExpandColumn(MMT_COLUMNS_COLUMN)); while not Q.Eof do begin - AddMemberMapping(q.FieldByName(ExpandColumn(MMT_CLASSNAME_COLUMN)).AsString, - q.FieldByName(ExpandColumn(MMT_MEMBERNAME_COLUMN)).AsString, - q.FieldByName(ExpandColumn(MMT_TABLENAME_COLUMN)).AsString, - q.FieldByName(ExpandColumn(MMT_COLUMNS_COLUMN)).AsString, - GetMapperNameFromQuery); + //Fallback, if the old MemberMapping was used + if q.FindField(ExpandColumn(MMT_INDEX_COLUMN)) = nil then begin + bColumnIndex := False; + end else begin + bColumnIndex := q.FieldByName(ExpandColumn(MMT_INDEX_COLUMN)).AsInteger = 1; + end; + AddMemberMapping(vClassNameField.AsString, + vMemberNameField.AsString, + vTableNameField.AsString, + // Remove linebreaks, to make MappingInfo comparable in TBoldDataBaseEvolutor.MoveDataAction + StringReplace(vColumnsField.AsString, #13#10, '', [rfReplaceAll]), + GetMapperNameFromQuery, + bColumnIndex); q.Next; end; q.Close; @@ -125,10 +173,12 @@ function GetMappernameFromQuery: String; q.AssignSQLText(SELECTFROM + OSTableName); q.Open; + vClassNameField := q.FieldByName(ExpandColumn(ST_CLASSNAME_COLUMN)); + vTableNameField := q.FieldByName(ExpandColumn(ST_TABLENAME_COLUMN)); while not Q.Eof do begin - AddObjectStorageMapping(q.FieldByName(ExpandColumn(ST_CLASSNAME_COLUMN)).AsString, - q.FieldByName(ExpandColumn(ST_TABLENAME_COLUMN)).AsString); + AddObjectStorageMapping(vClassNameField.AsString, + vTableNameField.AsString); q.Next; end; q.Close; @@ -141,88 +191,175 @@ function GetMappernameFromQuery: String; q.AssignSQLText(SELECTFROM + DbTypeTableName); q.Open; + vClassNameField := q.FieldByName(ExpandColumn(CLASSNAMECOLUMN_NAME)); + vTypeColumnield := q.FieldByName(ExpandColumn(TYPECOLUMN_NAME)); while not Q.Eof do begin - AddTypeIdMapping(q.FieldByName(ExpandColumn(CLASSNAMECOLUMN_NAME)).AsString, - q.FieldByName(ExpandColumn(TYPECOLUMN_NAME)).AsInteger); + AddTypeIdMapping(vClassNameField.AsString, + vTypeColumnield.AsInteger); q.Next; end; q.Close; end; - finally DataBase.ReleaseQuery(q); end; end; -procedure TBoldDefaultMappingInfo.ScriptForWriteData(Script: TStrings; Separator: string; ClearFirst: Boolean = true; terminator: string = ''); +procedure TBoldDefaultMappingInfo.ScriptForWriteData(DataBase: IBoldDataBase; + Script: TStrings; ClearFirst: Boolean; Separator: String; Terminator: String); var - i: integer; + i,row,Limit: integer; + vInsertSql: string; + sl: TStringList; const Bool2Int: array[Boolean] of integer=(0, 1); begin - if ClearFirst then - ScriptForClearData(Script, Separator, terminator); - - for i := 0 to fAllInstancesMapping.Count - 1 do - begin - Script.Add(format('INSERT INTO %s (%s, %s, %s) VALUES (''%s'', ''%s'', %d)%s', [ // do not localize - AITableName, - ExpandColumn(AID_CLASSNAME_COLUMN), - ExpandColumn(AID_TABLENAME_COLUMN), - ExpandColumn(AID_CLASSIDREQUIRED_COLUMN), - AllInstancesMappingInfo[i].ClassExpressionName, - AllInstancesMappingInfo[i].TableName, - Bool2Int[AllInstancesMappingInfo[i].classIdrequired], - terminator])); - if separator <> '' then - Script.Add(Separator); - end; - - for i := 0 to fMemberMapping.Count - 1 do - begin - Script.Add(format('INSERT INTO %s (%s, %s, %s, %s, %s) VALUES (''%s'', ''%s'', ''%s'', ''%s'', ''%s'')%s', [ // do not localize - MMTableName, - ExpandColumn(MMT_CLASSNAME_COLUMN), - ExpandColumn(MMT_MEMBERNAME_COLUMN), - ExpandColumn(MMT_TABLENAME_COLUMN), - ExpandColumn(MMT_COLUMNS_COLUMN), - ExpandColumn(MMT_MAPPERNAME_COLUMN), - MemberMappingInfo[i].ClassExpressionName, - MemberMappingInfo[i].MemberName, - MemberMappingInfo[i].TableName, - MemberMappingInfo[i].Columns, - MemberMappingInfo[i].MapperName, - terminator])); - if separator <> '' then - Script.Add(Separator); + FCurrentDatabase := DataBase; + sl := TStringList.Create; + sl.LineBreak := ' '; + try + if ClearFirst then + ScriptForClearData(Script, Separator, Terminator); + Limit := FCurrentDatabase.SQLDatabaseConfig.MultiRowInsertLimit; + vInsertSql := format('INSERT INTO %s (%s, %s, %s) VALUES ', [ + AITableName, + ExpandColumn(AID_CLASSNAME_COLUMN), + ExpandColumn(AID_TABLENAME_COLUMN), + ExpandColumn(AID_CLASSIDREQUIRED_COLUMN) + ]); + row := 0; + for i := 0 to fAllInstancesMapping.Count - 1 do + begin + sl.Add(format('(''%s'', ''%s'', %d)%s', [ // do not localize + AllInstancesMappingInfo[i].ClassExpressionName, + AllInstancesMappingInfo[i].TableName, + Bool2Int[AllInstancesMappingInfo[i].classIdrequired], + Terminator])); + if row = 0 then + sl[sl.count-1] := vInsertSql + sl[sl.count-1] + else + sl[sl.count-1] := ',' + sl[sl.count-1]; + inc(row); + if (row = limit) or (i = fAllInstancesMapping.Count - 1) then + begin + Script.Add(sl.Text); + sl.clear; + if Separator <> '' then + Script.Add(Separator); + row := 0; + end; + end; + Assert(row = 0); + Assert(sl.count = 0); +{$IFDEF IndexColumn} + vInsertSql := format('INSERT INTO %s (%s, %s, %s, %s, %s, %s) VALUES ', +{$ELSE} + vInsertSql := format('INSERT INTO %s (%s, %s, %s, %s, %s) VALUES ', +{$ENDIF} + [MMTableName, + ExpandColumn(MMT_CLASSNAME_COLUMN), + ExpandColumn(MMT_MEMBERNAME_COLUMN), + ExpandColumn(MMT_TABLENAME_COLUMN), + ExpandColumn(MMT_COLUMNS_COLUMN), + ExpandColumn(MMT_MAPPERNAME_COLUMN) +{$IFDEF IndexColumn} + ,ExpandColumn(MMT_INDEX_COLUMN) +{$ENDIF} + ]); + for i := 0 to fMemberMapping.Count - 1 do + begin + sl.Add(Format( +{$IFDEF IndexColumn} + '(''%s'', ''%s'', ''%s'', ''%s'', ''%s'', %d)%s', [ // do not localize +{$ELSE} + '(''%s'', ''%s'', ''%s'', ''%s'', ''%s'')%s', [ // do not localize +{$ENDIF} + MemberMappingInfo[i].ClassExpressionName, + MemberMappingInfo[i].MemberName, + MemberMappingInfo[i].TableName, + MemberMappingInfo[i].Columns, + MemberMappingInfo[i].MapperName, +{$IFDEF IndexColumn} + Integer(MemberMappingInfo[i].ColumnIndex), +{$ENDIF} + terminator])); + if row = 0 then + sl[sl.count-1] := vInsertSql + sl[sl.count-1] + else + sl[sl.count-1] := ',' + sl[sl.count-1]; + inc(row); + if (row = limit) or (i = fMemberMapping.Count - 1) then + begin + Script.Add(sl.Text); + sl.clear; + if Separator <> '' then + Script.Add(Separator); + row := 0; + end; + end; + Assert(row = 0); + Assert(sl.count = 0); + vInsertSql := format('INSERT INTO %s (%s, %s) VALUES ', + [OSTableName, + ExpandColumn(ST_CLASSNAME_COLUMN), + ExpandColumn(ST_TABLENAME_COLUMN) + ]); + for i := 0 to fObjectStorageMapping.Count - 1 do + begin + sl.Add(format('(''%s'', ''%s'')%s', [ // do not localize + ObjectStorageMappingInfo[i].ClassExpressionName, + ObjectStorageMappingInfo[i].TableName, + Terminator])); + if row = 0 then + sl[sl.count-1] := vInsertSql + sl[sl.count-1] + else + sl[sl.count-1] := ',' + sl[sl.count-1]; + inc(row); + if (row = limit) or (i = fObjectStorageMapping.Count - 1) then + begin + Script.Add(sl.Text); + sl.clear; + if Separator <> '' then + Script.Add(Separator); + row := 0; + end; + end; + Assert(row = 0); + Assert(sl.count = 0); + vInsertSql := format('INSERT INTO %s (%s, %s) VALUES ', + [DbTypeTableName, + ExpandColumn(TYPECOLUMN_NAME), + ExpandColumn(CLASSNAMECOLUMN_NAME)]); + for i := 0 to fDbTypeMapping.Count - 1 do + begin + sl.Add(format('(%d, ''%s'')%s', [ // do not localize + DbTypeMapping[i].DbType, + DbTypeMapping[i].ClassExpressionName, + Terminator])); + if row = 0 then + sl[sl.count-1] := vInsertSql + sl[sl.count-1] + else + sl[sl.count-1] := ',' + sl[sl.count-1]; + inc(row); + if (row = limit) or (i = fDbTypeMapping.Count - 1) then + begin + Script.Add(sl.Text); + sl.clear; + if Separator <> '' then + Script.Add(Separator); + row := 0; + end; + end; + Assert(row = 0); + Assert(sl.count = 0); + finally + FCurrentDatabase := nil; + sl.free; end; +end; - for i := 0 to fObjectStorageMapping.Count - 1 do - begin - Script.Add(format('INSERT INTO %s (%s, %s) VALUES (''%s'', ''%s'')%s', [ // do not localize - OSTableName, - ExpandColumn(ST_CLASSNAME_COLUMN), - ExpandColumn(ST_TABLENAME_COLUMN), - ObjectStorageMappingInfo[i].ClassExpressionName, - ObjectStorageMappingInfo[i].TableName, - terminator])); - if separator <> '' then - Script.Add(Separator); - end; - for i := 0 to fDbTypeMapping.Count - 1 do - begin - Script.Add(format('INSERT INTO %s (%s, %s) VALUES (%d, ''%s'')%s', [ // do not localize - DbTypeTableName, - ExpandColumn(TYPECOLUMN_NAME), - ExpandColumn(CLASSNAMECOLUMN_NAME), - DbTypeMapping[i].DbType, - DbTypeMapping[i].ClassExpressionName, - terminator])); - if separator <> '' then - Script.Add(Separator); - end; -end; +initialization end. diff --git a/Source/PMapper/Default/BoldPMappersAttributeDefault.pas b/Source/PMapper/Default/BoldPMappersAttributeDefault.pas index d5eb4cc..b4ddb48 100644 --- a/Source/PMapper/Default/BoldPMappersAttributeDefault.pas +++ b/Source/PMapper/Default/BoldPMappersAttributeDefault.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldPMappersAttributeDefault; interface @@ -25,6 +28,7 @@ TBoldPMCurrency = class; TBoldPMDateTime = class; TBoldPMDate = class; TBoldPMTime = class; + TBoldPMGuid = class; {TBoldPMString} TBoldPMString = class(TBoldSingleColumnMember) @@ -34,32 +38,87 @@ TBoldPMString = class(TBoldSingleColumnMember) function GetColumnTypeAsSQL(ColumnIndex: Integer): string; override; function GetColumnBDEFieldType(ColumnIndex: Integer): TFieldType; override; function GetColumnSize(ColumnIndex: Integer): Integer; override; - function CompareField(ObjectContent: IBoldObjectContents; Field: IBoldField; ColumnIndex: integer; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList): Boolean; override; + function CompareField(const ObjectContent: IBoldObjectContents; const Field: IBoldField; ColumnIndex: integer; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList): Boolean; override; function DefaultDefaultDbValue: String; override; public constructor CreateFromMold(Moldmember: TMoldMember; MoldClass: TMoldClass; Owner: TBoldObjectPersistenceMapper; const MemberIndex: Integer; TypeNameDictionary: TBoldTypeNameDictionary); override; class function CanStore(const ContentName: string): Boolean; override; - procedure ValueFromField(OwningObjectId: TBoldObjectId; ObjectContent: IBoldObjectContents; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; Field: IBoldField; ColumnIndex: Integer); override; - procedure ValueToParam(ObjectContent: IBoldObjectContents; Param: IBoldParameter; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList); override; + procedure ValueFromField(OwningObjectId: TBoldObjectId; const ObjectContent: IBoldObjectContents; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; const Field: IBoldField; ColumnIndex: Integer); override; + procedure ValueToParam(const ObjectContent: IBoldObjectContents; const Param: IBoldParameter; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList); override; + function ValueAsVariant(const ObjectContent: IBoldObjectContents; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList): variant; override; + end; + + {TBoldPMAnsiString} + TBoldPMAnsiString = class(TBoldPMString) + protected + function CompareField(const ObjectContent: IBoldObjectContents; const Field: IBoldField; + ColumnIndex: integer; const ValueSpace: IBoldValueSpace; TranslationList: + TBoldIdTranslationList): Boolean; override; + public + procedure ValueFromField(OwningObjectId: TBoldObjectId; const ObjectContent: + IBoldObjectContents; const ValueSpace: IBoldValueSpace; TranslationList: + TBoldIdTranslationList; const Field: IBoldField; ColumnIndex: Integer); override; + procedure ValueToParam(const ObjectContent: IBoldObjectContents; const Param: + IBoldParameter; ColumnIndex: Integer; TranslationList: + TBoldIdTranslationList); override; + end; + + {TBoldPMUnicodeString} + TBoldPMUnicodeString = class(TBoldPMString) + protected + function CompareField(const ObjectContent: IBoldObjectContents; const Field: IBoldField; + ColumnIndex: integer; const ValueSpace: IBoldValueSpace; TranslationList: + TBoldIdTranslationList): Boolean; override; + function GetColumnTypeAsSQL(ColumnIndex: Integer): string; override; + function GetColumnBDEFieldType(ColumnIndex: Integer): TFieldType; override; + public + procedure ValueFromField(OwningObjectId: TBoldObjectId; const ObjectContent: + IBoldObjectContents; const ValueSpace: IBoldValueSpace; TranslationList: + TBoldIdTranslationList; const Field: IBoldField; ColumnIndex: Integer); override; + procedure ValueToParam(const ObjectContent: IBoldObjectContents; const Param: + IBoldParameter; ColumnIndex: Integer; TranslationList: + TBoldIdTranslationList); override; end; TBoldPMStringBDECodePageBug = class(TBoldPMString) public - procedure ValueToParam(ObjectContent: IBoldObjectContents; Param: IBoldParameter; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList); override; + procedure ValueToParam(const ObjectContent: IBoldObjectContents; const Param: IBoldParameter; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList); override; end; + {TBoldPMText} + TBoldPMText = class(TBoldSingleColumnMember) + private + protected + function GetColumnTypeAsSQL(ColumnIndex: Integer): string; override; + function GetColumnBDEFieldType(ColumnIndex: Integer): TFieldType; override; + function CompareField(const ObjectContent: IBoldObjectContents; const Field: IBoldField; ColumnIndex: integer; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList): Boolean; override; + function DefaultDefaultDbValue: String; override; + public + constructor CreateFromMold(Moldmember: TMoldMember; MoldClass: TMoldClass; Owner: TBoldObjectPersistenceMapper; const MemberIndex: Integer; TypeNameDictionary: TBoldTypeNameDictionary); override; + class function CanStore(const ContentName: string): Boolean; override; + procedure ValueFromField(OwningObjectId: TBoldObjectId; const ObjectContent: IBoldObjectContents; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; const Field: IBoldField; ColumnIndex: Integer); override; + procedure ValueToParam(const ObjectContent: IBoldObjectContents; const Param: IBoldParameter; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList); override; + end; + + {TBoldPMUnicodeText} + TBoldPMUnicodeText = class(TBoldPMText) + protected + function GetColumnTypeAsSQL(ColumnIndex: Integer): string; override; + function GetColumnBDEFieldType(ColumnIndex: Integer): TFieldType; override; + end; {TBoldPMInteger} TBoldPMInteger = class(TBoldSingleColumnMember) protected function GetColumnTypeAsSQL(ColumnIndex: Integer): string; override; function GetColumnBDEFieldType(ColumnIndex: Integer): TFieldType; override; - function CompareField(ObjectContent: IBoldObjectContents; Field: IBoldField; ColumnIndex: integer; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList): Boolean; override; + function CompareField(const ObjectContent: IBoldObjectContents; const Field: IBoldField; ColumnIndex: integer; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList): Boolean; override; function DefaultDefaultDbValue: String; override; public class function CanStore(const ContentName: string): Boolean; override; - procedure ValueFromField(OwningObjectId: TBoldObjectId; ObjectContent: IBoldObjectContents; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; Field: IBoldField; ColumnIndex: Integer); override; - procedure ValueToParam(ObjectContent: IBoldObjectContents; Param: IBoldParameter; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList); override; + procedure ValueFromField(OwningObjectId: TBoldObjectId; const ObjectContent: IBoldObjectContents; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; const Field: IBoldField; ColumnIndex: Integer); override; + procedure ValueToParam(const ObjectContent: IBoldObjectContents; const Param: IBoldParameter; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList); override; + function ValueAsVariant(const ObjectContent: IBoldObjectContents; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList): variant; override; end; {TBoldPMSmallInt} @@ -72,12 +131,12 @@ TBoldPMSmallInt = class(TBoldPMInteger) end; {TBoldPMByte} - TBoldPMByte = class(TBoldPMSmallInt) // No TFieldType value for byte + TBoldPMByte = class(TBoldPMSmallInt) class function CanStore(const ContentName: string): Boolean; override; end; {TBoldPMShortInt} - TBoldPMShortInt = class(TBoldPMSmallInt) // No TFieldType value for ShortInt + TBoldPMShortInt = class(TBoldPMSmallInt) class function CanStore(const ContentName: string): Boolean; override; end; @@ -94,11 +153,12 @@ TBoldPMLogic = class(TBoldSingleColumnMember) protected function GetColumnTypeAsSQL(ColumnIndex: Integer): string; override; function GetColumnBDEFieldType(ColumnIndex: Integer): TFieldType; override; - function CompareField(ObjectContent: IBoldObjectContents; Field: IBoldField; ColumnIndex: integer; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList): Boolean; override; + function CompareField(const ObjectContent: IBoldObjectContents; const Field: IBoldField; ColumnIndex: integer; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList): Boolean; override; public class function CanStore(const ContentName: string): Boolean; override; - procedure ValueFromField(OwningObjectId: TBoldObjectId; ObjectContent: IBoldObjectContents; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; Field: IBoldField; ColumnIndex: Integer); override; - procedure ValueToParam(ObjectContent: IBoldObjectContents; Param: IBoldParameter; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList); override; + procedure ValueFromField(OwningObjectId: TBoldObjectId; const ObjectContent: IBoldObjectContents; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; const Field: IBoldField; ColumnIndex: Integer); override; + procedure ValueToParam(const ObjectContent: IBoldObjectContents; const Param: IBoldParameter; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList); override; + function ValueAsVariant(const ObjectContent: IBoldObjectContents; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList): variant; override; end; {TBoldPMFloat} @@ -106,12 +166,13 @@ TBoldPMFloat = class(TBoldSingleColumnMember) protected function GetColumnTypeAsSQL(ColumnIndex: Integer): string; override; function GetColumnBDEFieldType(ColumnIndex: Integer): TFieldType; override; - function CompareField(ObjectContent: IBoldObjectContents; Field: IBoldField; ColumnIndex: integer; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList): Boolean; override; + function CompareField(const ObjectContent: IBoldObjectContents; const Field: IBoldField; ColumnIndex: integer; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList): Boolean; override; function DefaultDefaultDbValue: String; override; public class function CanStore(const ContentName: string): Boolean; override; - procedure ValueFromField(OwningObjectId: TBoldObjectId; ObjectContent: IBoldObjectContents; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; Field: IBoldField; ColumnIndex: Integer); override; - procedure ValueToParam(ObjectContent: IBoldObjectContents; Param: IBoldParameter; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList); override; + procedure ValueFromField(OwningObjectId: TBoldObjectId; const ObjectContent: IBoldObjectContents; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; const Field: IBoldField; ColumnIndex: Integer); override; + procedure ValueToParam(const ObjectContent: IBoldObjectContents; const Param: IBoldParameter; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList); override; + function ValueAsVariant(const ObjectContent: IBoldObjectContents; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList): variant; override; end; {TBoldPMCurrency} @@ -119,24 +180,28 @@ TBoldPMCurrency = class(TBoldSingleColumnMember) protected function GetColumnTypeAsSQL(ColumnIndex: Integer): string; override; function GetColumnBDEFieldType(ColumnIndex: Integer): TFieldType; override; - function CompareField(ObjectContent: IBoldObjectContents; Field: IBoldField; ColumnIndex: integer; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList): Boolean; override; + function CompareField(const ObjectContent: IBoldObjectContents; const Field: IBoldField; ColumnIndex: integer; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList): Boolean; override; function DefaultDefaultDbValue: String; override; public class function CanStore(const ContentName: string): Boolean; override; - procedure ValueFromField(OwningObjectId: TBoldObjectId; ObjectContent: IBoldObjectContents; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; Field: IBoldField; ColumnIndex: Integer); override; - procedure ValueToParam(ObjectContent: IBoldObjectContents; Param: IBoldParameter; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList); override; + procedure ValueFromField(OwningObjectId: TBoldObjectId; const ObjectContent: IBoldObjectContents; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; const Field: IBoldField; ColumnIndex: Integer); override; + procedure ValueToParam(const ObjectContent: IBoldObjectContents; const Param: IBoldParameter; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList); override; + function ValueAsVariant(const ObjectContent: IBoldObjectContents; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList): variant; override; end; {TBoldPMBlob} TBoldPMBlob = class(TBoldSingleColumnMember) + private + function StoreAsString(ColumnIndex: Integer): Boolean; protected function GetColumnBDEFieldType(ColumnIndex: Integer): TFieldType; override; function GetColumnTypeAsSQL(ColumnIndex: Integer): string; override; - function CompareField(ObjectContent: IBoldObjectContents; Field: IBoldField; ColumnIndex: integer; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList): Boolean; override; + function CompareField(const ObjectContent: IBoldObjectContents; const Field: IBoldField; ColumnIndex: integer; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList): Boolean; override; public class function CanStore(const ContentName: string): Boolean; override; - procedure ValueFromField(OwningObjectId: TBoldObjectId; ObjectContent: IBoldObjectContents; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; Field: IBoldField; ColumnIndex: Integer); override; - procedure ValueToParam(ObjectContent: IBoldObjectContents; Param: IBoldParameter; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList); override; + procedure ValueFromField(OwningObjectId: TBoldObjectId; const ObjectContent: IBoldObjectContents; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; const Field: IBoldField; ColumnIndex: Integer); override; + procedure ValueToParam(const ObjectContent: IBoldObjectContents; const Param: IBoldParameter; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList); override; + function ValueAsVariant(const ObjectContent: IBoldObjectContents; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList): variant; override; end; {TBoldPMBlob} @@ -147,10 +212,10 @@ TBoldPMMemoBlob = class(TBoldPMBlob) TBoldPMNonEmptyBlob = class(TBoldPMBlob) protected - function CompareField(ObjectContent: IBoldObjectContents; Field: IBoldField; ColumnIndex: integer; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList): Boolean; override; + function CompareField(const ObjectContent: IBoldObjectContents; const Field: IBoldField; ColumnIndex: integer; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList): Boolean; override; public - procedure ValueFromField(OwningObjectId: TBoldObjectId; ObjectContent: IBoldObjectContents; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; Field: IBoldField; ColumnIndex: Integer); override; - procedure ValueToParam(ObjectContent: IBoldObjectContents; Param: IBoldParameter; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList); override; + procedure ValueFromField(OwningObjectId: TBoldObjectId; const ObjectContent: IBoldObjectContents; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; const Field: IBoldField; ColumnIndex: Integer); override; + procedure ValueToParam(const ObjectContent: IBoldObjectContents; const Param: IBoldParameter; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList); override; end; TBoldPMLiveBlob = class(TBoldPMBlob) @@ -167,11 +232,12 @@ TBoldPMTypedBlob = class(TBoldPMBlob) function GetColumnCount: Integer; override; function GetColumnSize(ColumnIndex: Integer): Integer; override; function GetInitialColumnName(ColumnIndex: Integer): string; override; - function CompareField(ObjectContent: IBoldObjectContents; Field: IBoldField; ColumnIndex: integer; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList): Boolean; override; + function CompareField(const ObjectContent: IBoldObjectContents; const Field: IBoldField; ColumnIndex: integer; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList): Boolean; override; public class function CanStore(const ContentName: string): Boolean; override; - procedure ValueFromField(OwningObjectId: TBoldObjectId; ObjectContent: IBoldObjectContents; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; Field: IBoldField; ColumnIndex: Integer); override; - procedure ValueToParam(ObjectContent: IBoldObjectContents; Param: IBoldParameter; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList); override; + procedure ValueFromField(OwningObjectId: TBoldObjectId; const ObjectContent: IBoldObjectContents; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; const Field: IBoldField; ColumnIndex: Integer); override; + procedure ValueToParam(const ObjectContent: IBoldObjectContents; const Param: IBoldParameter; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList); override; + function ValueAsVariant(const ObjectContent: IBoldObjectContents; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList): variant; override; end; TBoldPMLiveTypedBlob = class(TBoldPMTypedBlob) @@ -187,35 +253,45 @@ TBoldPMDateTime = class(TBoldSingleColumnMember) protected function GetColumnBDEFieldType(ColumnIndex: Integer): TFieldType; override; function GetColumnTypeAsSQL(ColumnIndex: Integer): string; override; - function CompareField(ObjectContent: IBoldObjectContents; Field: IBoldField; ColumnIndex: integer; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList): Boolean; override; + function CompareField(const ObjectContent: IBoldObjectContents; const Field: IBoldField; ColumnIndex: integer; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList): Boolean; override; + function DefaultDefaultDbValue: String; override; public class function CanStore(const ContentName: string): Boolean; override; - procedure ValueFromField(OwningObjectId: TBoldObjectId; ObjectContent: IBoldObjectContents; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; Field: IBoldField; ColumnIndex: Integer); override; - procedure ValueToParam(ObjectContent: IBoldObjectContents; Param: IBoldParameter; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList); override; + procedure ValueFromField(OwningObjectId: TBoldObjectId; const ObjectContent: IBoldObjectContents; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; const Field: IBoldField; ColumnIndex: Integer); override; + procedure ValueToParam(const ObjectContent: IBoldObjectContents; const Param: IBoldParameter; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList); override; + function ValueAsVariant(const ObjectContent: IBoldObjectContents; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList): variant; override; end; {TBoldPMDate} TBoldPMDate = class(TBoldPMDateTime) protected function GetColumnBDEFieldType(ColumnIndex: Integer): TFieldType; override; - function CompareField(ObjectContent: IBoldObjectContents; Field: IBoldField; ColumnIndex: integer; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList): Boolean; override; + function CompareField(const ObjectContent: IBoldObjectContents; const Field: IBoldField; ColumnIndex: integer; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList): Boolean; override; function GetColumnTypeAsSQL(ColumnIndex: Integer): string; override; public class function CanStore(const ContentName: string): Boolean; override; - procedure ValueFromField(OwningObjectId: TBoldObjectId; ObjectContent: IBoldObjectContents; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; Field: IBoldField; ColumnIndex: Integer); override; - procedure ValueToParam(ObjectContent: IBoldObjectContents; Param: IBoldParameter; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList); override; + procedure ValueFromField(OwningObjectId: TBoldObjectId; const ObjectContent: IBoldObjectContents; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; const Field: IBoldField; ColumnIndex: Integer); override; + procedure ValueToParam(const ObjectContent: IBoldObjectContents; const Param: IBoldParameter; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList); override; + function ValueAsVariant(const ObjectContent: IBoldObjectContents; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList): variant; override; end; {TBoldPMTime} TBoldPMTime = class(TBoldPMDateTime) protected function GetColumnBDEFieldType(ColumnIndex: Integer): TFieldType; override; - function CompareField(ObjectContent: IBoldObjectContents; Field: IBoldField; ColumnIndex: integer; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList): Boolean; override; + function CompareField(const ObjectContent: IBoldObjectContents; const Field: IBoldField; ColumnIndex: integer; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList): Boolean; override; function GetColumnTypeAsSQL(ColumnIndex: Integer): string; override; public class function CanStore(const ContentName: string): Boolean; override; - procedure ValueFromField(OwningObjectId: TBoldObjectId; ObjectContent: IBoldObjectContents; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; Field: IBoldField; ColumnIndex: Integer); override; - procedure ValueToParam(ObjectContent: IBoldObjectContents; Param: IBoldParameter; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList); override; + procedure ValueFromField(OwningObjectId: TBoldObjectId; const ObjectContent: IBoldObjectContents; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; const Field: IBoldField; ColumnIndex: Integer); override; + procedure ValueToParam(const ObjectContent: IBoldObjectContents; const Param: IBoldParameter; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList); override; + function ValueAsVariant(const ObjectContent: IBoldObjectContents; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList): variant; override; + end; + + TBoldPMGuid = class(TBoldPMString) + protected + function GetColumnTypeAsSQL(ColumnIndex: Integer): string; override; + function GetColumnBDEFieldType(ColumnIndex: Integer): TFieldType; override; end; implementation @@ -223,14 +299,14 @@ implementation uses SysUtils, BoldDefs, + BoldUtils, BoldValueInterfaces, BoldPMapperLists, BoldDefaultStreamNames, - BoldPMappersSQL, - BoldPMConsts; + Variants; var - TwoSeconds: TDateTime; // initialized in initizlization-section + TwoSeconds: TDateTime; {---TBoldPMString---} @@ -245,7 +321,7 @@ constructor TBoldPMString.CreateFromMold(Moldmember: TMoldMember; MoldClass: TMo if SystemPersistenceMapper.SQLDataBaseConfig.StoreEmptyStringsAsNULL then begin if (MoldMember as TMoldAttribute).AllowNull then - raise EBold.CreateFmt(sAttributeMustNotAllowNullIfEmptyStringsStoreAsNull, [ + raise EBold.CreateFmt('String attribute must not allow NULL in the model if persistencemapper stores empty strings as NULL (%s.%s)', [ MoldClass.Name, MoldMember.Name]); fAllowNull := True; end; @@ -253,7 +329,7 @@ constructor TBoldPMString.CreateFromMold(Moldmember: TMoldMember; MoldClass: TMo function TBoldPMString.GetColumnTypeAsSQL(ColumnIndex: Integer): string; begin - Result := Format(SystemPersistenceMapper.SQLDataBaseConfig.ColumnTypeForString, [GetColumnSize(ColumnIndex)]); + Result := SystemPersistenceMapper.SQLDataBaseConfig.GetColumnTypeForString(GetColumnSize(ColumnIndex)); end; class function TBoldPMString.CanStore(const ContentName: string): Boolean; @@ -263,7 +339,7 @@ class function TBoldPMString.CanStore(const ContentName: string): Boolean; function TBoldPMString.GetColumnBDEFieldType(ColumnIndex: Integer): TFieldType; begin - Result := ftString; + Result := ftMemo; // Changed from ftString to ftMemo as MSSQL truncates string params to 8000 end; function TBoldPMString.GetColumnSize(ColumnIndex: Integer): Integer; @@ -271,7 +347,22 @@ function TBoldPMString.GetColumnSize(ColumnIndex: Integer): Integer; Result := fColumnSize; end; -procedure TBoldPMString.ValueFromField(OwningObjectId: TBoldObjectId; ObjectContent: IBoldObjectContents; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; Field: IBoldField; ColumnIndex: Integer); +function TBoldPMString.ValueAsVariant(const ObjectContent: IBoldObjectContents; + ColumnIndex: Integer; TranslationList: TBoldIdTranslationList): variant; +var + aString: IBoldStringContent; +begin + EnsureFirstColumn(ColumnIndex); + aString := GetEnsuredValue(ObjectContent) as IBoldStringContent; + if aString.IsNull then + result := null + else + begin + result := aString.AsString; + end; +end; + +procedure TBoldPMString.ValueFromField(OwningObjectId: TBoldObjectId; const ObjectContent: IBoldObjectContents; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; const Field: IBoldField; ColumnIndex: Integer); var aString: IBoldStringContent; begin @@ -288,7 +379,7 @@ procedure TBoldPMString.ValueFromField(OwningObjectId: TBoldObjectId; ObjectCont aString.AsString := Field.AsString end; -function TBoldPMString.CompareField(ObjectContent: IBoldObjectContents; Field: IBoldField; ColumnIndex: integer; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList): Boolean; +function TBoldPMString.CompareField(const ObjectContent: IBoldObjectContents; const Field: IBoldField; ColumnIndex: integer; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList): Boolean; var aString: IBoldStringContent; begin @@ -306,7 +397,7 @@ function TBoldPMString.CompareField(ObjectContent: IBoldObjectContents; Field: I end; -procedure TBoldPMString.ValueToParam(ObjectContent: IBoldObjectContents; Param: IBoldParameter; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList); +procedure TBoldPMString.ValueToParam(const ObjectContent: IBoldObjectContents; const Param: IBoldParameter; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList); var aString: IBoldStringContent; begin @@ -315,7 +406,12 @@ procedure TBoldPMString.ValueToParam(ObjectContent: IBoldObjectContents; Param: if aString.IsNull then SetParamToNullWithDataType(Param, GetColumnBDEFieldType(0)) else - Param.AsString := aString.AsString + begin + // the setting of Param DataType is a workaround for UniDAC MSSQL param trim to 8000 bug. + if Length(aString.AsString) >= 8000 then + Param.DataType := GetColumnBDEFieldType(0); + Param.AsString := aString.AsString; + end; end; {---TBoldPMInteger---} @@ -335,7 +431,7 @@ function TBoldPMInteger.GetColumnBDEFieldType(ColumnIndex: Integer): TFieldType; Result := ftInteger; end; -function TBoldPMInteger.CompareField(ObjectContent: IBoldObjectContents; Field: IBoldField; ColumnIndex: integer; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList): Boolean; +function TBoldPMInteger.CompareField(const ObjectContent: IBoldObjectContents; const Field: IBoldField; ColumnIndex: integer; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList): Boolean; var anInteger: IBoldIntegerContent; begin @@ -345,7 +441,20 @@ function TBoldPMInteger.CompareField(ObjectContent: IBoldObjectContents; Field: result := Field.AsInteger = anInteger.AsInteger; end; -procedure TBoldPMInteger.ValueFromField(OwningObjectId: TBoldObjectId; ObjectContent: IBoldObjectContents; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; Field: IBoldField; ColumnIndex: Integer); +function TBoldPMInteger.ValueAsVariant(const ObjectContent: IBoldObjectContents; + ColumnIndex: Integer; TranslationList: TBoldIdTranslationList): variant; +var + anInteger: IBoldIntegerContent; +begin + EnsureFirstColumn(ColumnIndex); + anInteger := GetEnsuredValue(ObjectContent) as IBoldIntegerContent; + if anInteger.IsNull then + result := null + else + Result := anInteger.AsInteger; +end; + +procedure TBoldPMInteger.ValueFromField(OwningObjectId: TBoldObjectId; const ObjectContent: IBoldObjectContents; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; const Field: IBoldField; ColumnIndex: Integer); var anInteger: IBoldIntegerContent; begin @@ -357,7 +466,7 @@ procedure TBoldPMInteger.ValueFromField(OwningObjectId: TBoldObjectId; ObjectCon anInteger.AsInteger := Field.AsInteger; end; -procedure TBoldPMInteger.ValueToParam(ObjectContent: IBoldObjectContents; Param: IBoldParameter; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList); +procedure TBoldPMInteger.ValueToParam(const ObjectContent: IBoldObjectContents; const Param: IBoldParameter; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList); var anInteger: IBoldIntegerContent; begin @@ -411,7 +520,7 @@ function TBoldPMWord.GetColumnBDEFieldType(ColumnIndex: Integer): TFieldType; {---TBoldPMLogic---} function TBoldPMLogic.GetColumnTypeAsSQL(ColumnIndex: Integer): string; begin - Result := 'VARCHAR(1)'; // do not localize + Result := 'VARCHAR(1)'; end; class function TBoldPMLogic.CanStore(const ContentName: string): Boolean; @@ -424,8 +533,8 @@ function TBoldPMLogic.GetColumnBDEFieldType(ColumnIndex: Integer): TFieldType; Result := ftBoolean; end; -function TBoldPMLogic.CompareField(ObjectContent: IBoldObjectContents; Field: IBoldField; - ColumnIndex: integer; ValueSpace: IBoldValueSpace; +function TBoldPMLogic.CompareField(const ObjectContent: IBoldObjectContents; const Field: IBoldField; + ColumnIndex: integer; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList): Boolean; var aBoolean: IBoldBooleanContent; @@ -436,7 +545,20 @@ function TBoldPMLogic.CompareField(ObjectContent: IBoldObjectContents; Field: IB result := Field.AsBoolean = aBoolean.AsBoolean; end; -procedure TBoldPMLogic.ValueFromField(OwningObjectId: TBoldObjectId; ObjectContent: IBoldObjectContents; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; Field: IBoldField; ColumnIndex: Integer); +function TBoldPMLogic.ValueAsVariant(const ObjectContent: IBoldObjectContents; + ColumnIndex: Integer; TranslationList: TBoldIdTranslationList): variant; +var + aBoolean: IBoldBooleanContent; +begin + EnsureFirstColumn(ColumnIndex); + aBoolean := GetEnsuredValue(ObjectContent) as IBoldBooleanContent; + if aBoolean.IsNull then + result := Null + else + result := aBoolean.asBoolean; +end; + +procedure TBoldPMLogic.ValueFromField(OwningObjectId: TBoldObjectId; const ObjectContent: IBoldObjectContents; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; const Field: IBoldField; ColumnIndex: Integer); var aBoolean: IBoldBooleanContent; begin @@ -448,7 +570,7 @@ procedure TBoldPMLogic.ValueFromField(OwningObjectId: TBoldObjectId; ObjectConte aBoolean.AsBoolean := Field.AsBoolean; end; -procedure TBoldPMLogic.ValueToParam(ObjectContent: IBoldObjectContents; Param: IBoldParameter; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList); +procedure TBoldPMLogic.ValueToParam(const ObjectContent: IBoldObjectContents; const Param: IBoldParameter; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList); var aBoolean: IBoldBooleanContent; begin @@ -476,8 +598,8 @@ function TBoldPMFloat.GetColumnBDEFieldType(ColumnIndex: Integer): TFieldType; Result := ftFloat; end; -function TBoldPMFloat.CompareField(ObjectContent: IBoldObjectContents; Field: IBoldField; - ColumnIndex: integer; ValueSpace: IBoldValueSpace; +function TBoldPMFloat.CompareField(const ObjectContent: IBoldObjectContents; const Field: IBoldField; + ColumnIndex: integer; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList): Boolean; var aFloat: IBoldFloatContent; @@ -488,7 +610,20 @@ function TBoldPMFloat.CompareField(ObjectContent: IBoldObjectContents; Field: IB result := Field.AsFloat = aFloat.AsFloat; end; -procedure TBoldPMFloat.ValueFromField(OwningObjectId: TBoldObjectId; ObjectContent: IBoldObjectContents; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; Field: IBoldField; ColumnIndex: Integer); +function TBoldPMFloat.ValueAsVariant(const ObjectContent: IBoldObjectContents; + ColumnIndex: Integer; TranslationList: TBoldIdTranslationList): variant; +var + aFloat: IBoldFloatContent; +begin + EnsureFirstColumn(ColumnIndex); + aFloat := GetEnsuredValue(ObjectContent) as IBoldFloatContent; + if aFloat.IsNull then + result := Null + else + result := aFloat.AsFloat; +end; + +procedure TBoldPMFloat.ValueFromField(OwningObjectId: TBoldObjectId; const ObjectContent: IBoldObjectContents; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; const Field: IBoldField; ColumnIndex: Integer); var aFloat: IBoldFloatContent; begin @@ -500,7 +635,7 @@ procedure TBoldPMFloat.ValueFromField(OwningObjectId: TBoldObjectId; ObjectConte aFloat.AsFloat := Field.AsFloat; end; -procedure TBoldPMFloat.ValueToParam(ObjectContent: IBoldObjectContents; Param: IBoldParameter; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList); +procedure TBoldPMFloat.ValueToParam(const ObjectContent: IBoldObjectContents; const Param: IBoldParameter; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList); var aFloat: IBoldFloatContent; begin @@ -523,7 +658,7 @@ function TBoldPMCurrency.GetColumnBDEFieldType(ColumnIndex: Integer): TFieldType Result := ftCurrency; end; -function TBoldPMCurrency.CompareField(ObjectContent: IBoldObjectContents; Field: IBoldField; ColumnIndex: integer; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList): Boolean; +function TBoldPMCurrency.CompareField(const ObjectContent: IBoldObjectContents; const Field: IBoldField; ColumnIndex: integer; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList): Boolean; var aCurrency: IBoldCurrencyContent; begin @@ -534,7 +669,20 @@ function TBoldPMCurrency.CompareField(ObjectContent: IBoldObjectContents; Field: end; -procedure TBoldPMCurrency.ValueFromField(OwningObjectId: TBoldObjectId; ObjectContent: IBoldObjectContents; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; Field: IBoldField; ColumnIndex: Integer); +function TBoldPMCurrency.ValueAsVariant(const ObjectContent: IBoldObjectContents; + ColumnIndex: Integer; TranslationList: TBoldIdTranslationList): variant; +var + aCurrency: IBoldCurrencyContent; +begin + EnsureFirstColumn(ColumnIndex); + aCurrency := GetEnsuredValue(ObjectContent) as IBoldCurrencyContent; + if aCurrency.IsNull then + result := null + else + result := aCurrency.AsCurrency; +end; + +procedure TBoldPMCurrency.ValueFromField(OwningObjectId: TBoldObjectId; const ObjectContent: IBoldObjectContents; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; const Field: IBoldField; ColumnIndex: Integer); var aCurrency: IBoldCurrencyContent; begin @@ -546,7 +694,7 @@ procedure TBoldPMCurrency.ValueFromField(OwningObjectId: TBoldObjectId; ObjectCo aCurrency.AsCurrency := Field.AsCurrency; end; -procedure TBoldPMCurrency.ValueToParam(ObjectContent: IBoldObjectContents; Param: IBoldParameter; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList); +procedure TBoldPMCurrency.ValueToParam(const ObjectContent: IBoldObjectContents; const Param: IBoldParameter; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList); var aCurrency: IBoldCurrencyContent; begin @@ -564,6 +712,11 @@ function TBoldPMBlob.GetColumnTypeAsSQL(ColumnIndex: Integer): string; Result := SystemPersistenceMapper.SQLDataBaseConfig.ColumnTypeForBlob; end; +function TBoldPMBlob.StoreAsString(ColumnIndex: Integer): Boolean; +begin + Result := GetColumnBDEFieldType(ColumnIndex) = ftstring; +end; + class function TBoldPMBlob.CanStore(const ContentName: string): Boolean; begin Result := AnsiCompareText(ContentName, BoldContentName_Blob) = 0; @@ -574,8 +727,8 @@ function TBoldPMBlob.GetColumnBDEFieldType(ColumnIndex: Integer): TFieldType; Result := SystemPersistenceMapper.SQLDataBaseConfig.FieldTypeForBlob; end; -function TBoldPMBlob.CompareField(ObjectContent: IBoldObjectContents; Field: IBoldField; - ColumnIndex: integer; ValueSpace: IBoldValueSpace; +function TBoldPMBlob.CompareField(const ObjectContent: IBoldObjectContents; const Field: IBoldField; + ColumnIndex: integer; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList): Boolean; var aBlob: IBoldBlobContent; @@ -583,22 +736,39 @@ function TBoldPMBlob.CompareField(ObjectContent: IBoldObjectContents; Field: IBo EnsureFirstColumn(ColumnIndex); aBlob := GetValue(ObjectContent) as IBoldBlobContent; if not CheckEitherNull(field, aBlob, result) then - result := Field.AsBlob = aBlob.AsBlob; + begin + if StoreAsString(ColumnIndex) then + result := aBlob.AsString = Field.AsString + else + result := aBlob.AsBlob = Field.AsBlob; + end; end; -procedure TBoldPMBlob.ValueFromField(OwningObjectId: TBoldObjectId; ObjectContent: IBoldObjectContents; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; Field: IBoldField; ColumnIndex: Integer); +procedure TBoldPMBlob.ValueFromField(OwningObjectId: TBoldObjectId; const ObjectContent: IBoldObjectContents; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; const Field: IBoldField; ColumnIndex: Integer); var aBlob: IBoldBlobContent; + aBlobStreamContent: IBoldBlobStreamContent; begin EnsureFirstColumn(ColumnIndex); aBlob := GetEnsuredValue(ObjectContent) as IBoldBlobContent; - if Field.IsNull then - aBlob.SetContentToNull - else - aBlob.AsBlob := Field.AsBlob; + aBlobStreamContent := aBlob as IBoldBlobStreamContent; + aBlobStreamContent.BeginSupressEvents; + try + if Field.IsNull then + aBlob.SetContentToNull + else + begin + if StoreAsString(ColumnIndex) then + aBlob.AsBlob := Field.AsAnsiString + else + aBlob.AsBlob := Field.AsBlob; + end; + finally + aBlobStreamContent.EndSupressEvents; + end; end; -procedure TBoldPMBlob.ValueToParam(ObjectContent: IBoldObjectContents; Param: IBoldParameter; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList); +procedure TBoldPMBlob.ValueToParam(const ObjectContent: IBoldObjectContents; const Param: IBoldParameter; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList); var aBlob: IBoldBlobContent; begin @@ -608,8 +778,25 @@ procedure TBoldPMBlob.ValueToParam(ObjectContent: IBoldObjectContents; Param: IB SetParamToNullWithDataType(Param, GetColumnBDEFieldType(0)) else begin - Param.DataType := ColumnBDEFieldType[ColumnIndex]; -//marco Param.AsBlob := aBlob.AsBlob; + if StoreAsString(ColumnIndex) then + Param.asString := aBlob.asString + else + Param.AsBlob := aBlob.asBlob; + end; +end; + +function TBoldPMBlob.ValueAsVariant(const ObjectContent: IBoldObjectContents; + ColumnIndex: Integer; TranslationList: TBoldIdTranslationList): variant; +var + aBlob: IBoldBlobContent; +begin + EnsureFirstColumn(ColumnIndex); + aBlob := GetEnsuredValue(ObjectContent) as IBoldBlobContent; + if aBlob.IsNull then + result := Null + else + begin + result := aBlob.asBlob; end; end; @@ -645,7 +832,7 @@ function TBoldPMTypedBlob.GetColumnSize(ColumnIndex: Integer): Integer; function TBoldPMTypedBlob.GetInitialColumnName(ColumnIndex: Integer): string; begin if ColumnIndex = 1 then - Result := InitialColumnRootName + '_Content' // do not localize + Result := InitialColumnRootName + '_Content' else Result := inherited GetInitialColumnName(ColumnIndex); end; @@ -655,7 +842,7 @@ class function TBoldPMTypedBlob.CanStore(const ContentName: string): Boolean; Result := AnsiCompareText(ContentName, BoldContentName_TypedBlob) = 0; end; -function TBoldPMTypedBlob.CompareField(ObjectContent: IBoldObjectContents; Field: IBoldField; ColumnIndex: integer; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList): Boolean; +function TBoldPMTypedBlob.CompareField(const ObjectContent: IBoldObjectContents; const Field: IBoldField; ColumnIndex: integer; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList): Boolean; var aTypedBlob: IBoldTypedBlob; begin @@ -669,7 +856,24 @@ function TBoldPMTypedBlob.CompareField(ObjectContent: IBoldObjectContents; Field result := inherited CompareField(ObjectContent, Field, ColumnIndex, ValueSpace, TranslationList); end; -procedure TBoldPMTypedBlob.ValueFromField(OwningObjectId: TBoldObjectId; ObjectContent: IBoldObjectContents; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; Field: IBoldField; ColumnIndex: Integer); +function TBoldPMTypedBlob.ValueAsVariant(const ObjectContent: IBoldObjectContents; + ColumnIndex: Integer; TranslationList: TBoldIdTranslationList): variant; +var + aTypedBlob: IBoldTypedBlob; +begin + if ColumnIndex = 1 then + begin + aTypedBlob := GetEnsuredValue(ObjectContent) as IBoldTypedBlob; + if aTypedBlob.IsNull then + result := null + else + result := aTypedBlob.ContentTypeContent; + end + else + result := Inherited ValueAsVariant(ObjectContent, ColumnIndex, TranslationList); +end; + +procedure TBoldPMTypedBlob.ValueFromField(OwningObjectId: TBoldObjectId; const ObjectContent: IBoldObjectContents; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; const Field: IBoldField; ColumnIndex: Integer); var aTypedBlob: IBoldTypedBlob; begin @@ -685,7 +889,7 @@ procedure TBoldPMTypedBlob.ValueFromField(OwningObjectId: TBoldObjectId; ObjectC Inherited; end; -procedure TBoldPMTypedBlob.ValueToParam(ObjectContent: IBoldObjectContents; Param: IBoldParameter; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList); +procedure TBoldPMTypedBlob.ValueToParam(const ObjectContent: IBoldObjectContents; const Param: IBoldParameter; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList); var aTypedBlob: IBoldTypedBlob; begin @@ -714,32 +918,60 @@ class function TBoldPMDateTime.CanStore(const ContentName: string): Boolean; function TBoldPMDateTime.GetColumnBDEFieldType(ColumnIndex: Integer): TFieldType; begin - Result := ftDateTime; + Result := ftDateTime; // workaround for DBX is to use ftDate, DBX does not properly support DateTime end; -function TBoldPMDateTime.CompareField(ObjectContent: IBoldObjectContents; Field: IBoldField; ColumnIndex: integer; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList): Boolean; +function TBoldPMDateTime.CompareField(const ObjectContent: IBoldObjectContents; const Field: IBoldField; ColumnIndex: integer; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList): Boolean; var aDateTime: IBoldDateTimeContent; begin EnsureFirstColumn(ColumnIndex); aDateTime := GetValue(ObjectContent) as IBoldDateTimeContent; - if not CheckEitherNull(field, aDateTime, result) then + if Field.IsNull {$IFDEF ConvertZeroDateToDateNil} or (Field.AsDateTime = 0) or (abs(Field.AsDateTime) < TwoSeconds) {$ENDIF} then + result := (aDateTime as IBoldNullableValue).isNull + else if (aDateTime as IBoldNullableValue).IsNull then + result := false + else result := abs(Field.AsDateTime - aDateTime.AsDateTime) < TwoSeconds; end; -procedure TBoldPMDateTime.ValueFromField(OwningObjectId: TBoldObjectId; ObjectContent: IBoldObjectContents; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; Field: IBoldField; ColumnIndex: Integer); +function TBoldPMDateTime.DefaultDefaultDbValue: String; +begin + Result := SystemPersistenceMapper.SQLDataBaseConfig.DefaultValueForDateTime; +end; + +function TBoldPMDateTime.ValueAsVariant(const ObjectContent: IBoldObjectContents; + ColumnIndex: Integer; TranslationList: TBoldIdTranslationList): variant; var aDateTime: IBoldDateTimeContent; begin EnsureFirstColumn(ColumnIndex); aDateTime := GetEnsuredValue(ObjectContent) as IBoldDateTimeContent; - if Field.IsNull then + if aDateTime.IsNull then + result := null + else + result := aDateTime.AsDateTime; +end; + +procedure TBoldPMDateTime.ValueFromField(OwningObjectId: TBoldObjectId; const ObjectContent: IBoldObjectContents; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; const Field: IBoldField; ColumnIndex: Integer); +var + aDateTime: IBoldDateTimeContent; +begin + EnsureFirstColumn(ColumnIndex); + aDateTime := GetEnsuredValue(ObjectContent) as IBoldDateTimeContent; + if Field.IsNull {$IFDEF ConvertZeroDateToDateNil} or (Field.AsDateTime = 0) or (abs(Field.AsDateTime) < TwoSeconds) {$ENDIF} then aDateTime.SetContentToNull else + begin +{$IFDEF NoNegativeDates} + if (Field.Value < 0) then + raise EBold.Create(Format('Negative date in Object %s column %s', [OwningObjectId.AsString, Field.FieldName])); +{$ENDIF} aDateTime.AsDateTime := Field.Value; + end; end; -procedure TBoldPMDateTime.ValueToParam(ObjectContent: IBoldObjectContents; Param: IBoldParameter; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList); +procedure TBoldPMDateTime.ValueToParam(const ObjectContent: IBoldObjectContents; const Param: IBoldParameter; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList); var aDateTime: IBoldDateTimeContent; begin @@ -762,7 +994,7 @@ function TBoldPMDate.GetColumnBDEFieldType(ColumnIndex: Integer): TFieldType; Result := ftDate; end; -function TBoldPMDate.CompareField(ObjectContent: IBoldObjectContents; Field: IBoldField; ColumnIndex: integer; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList): Boolean; +function TBoldPMDate.CompareField(const ObjectContent: IBoldObjectContents; const Field: IBoldField; ColumnIndex: integer; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList): Boolean; var aDate: IBoldDateContent; begin @@ -777,7 +1009,20 @@ function TBoldPMDate.GetColumnTypeAsSQL(ColumnIndex: Integer): string; Result := SystemPersistenceMapper.SQLDataBaseConfig.ColumnTypeForDate; end; -procedure TBoldPMDate.ValueFromField(OwningObjectId: TBoldObjectId; ObjectContent: IBoldObjectContents; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; Field: IBoldField; ColumnIndex: Integer); +function TBoldPMDate.ValueAsVariant(const ObjectContent: IBoldObjectContents; + ColumnIndex: Integer; TranslationList: TBoldIdTranslationList): variant; +var + aDate: IBoldDateContent; +begin + EnsureFirstColumn(ColumnIndex); + aDate := GetEnsuredValue(ObjectContent) as IBoldDateContent; + if aDate.IsNull then + result := null + else + result := aDate.AsDate; +end; + +procedure TBoldPMDate.ValueFromField(OwningObjectId: TBoldObjectId; const ObjectContent: IBoldObjectContents; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; const Field: IBoldField; ColumnIndex: Integer); var aDate: IBoldDateContent; begin @@ -789,7 +1034,7 @@ procedure TBoldPMDate.ValueFromField(OwningObjectId: TBoldObjectId; ObjectConten aDate.AsDate := Field.Value; end; -procedure TBoldPMDate.ValueToParam(ObjectContent: IBoldObjectContents; Param: IBoldParameter; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList); +procedure TBoldPMDate.ValueToParam(const ObjectContent: IBoldObjectContents; const Param: IBoldParameter; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList); var aDate: IBoldDateContent; begin @@ -812,7 +1057,7 @@ function TBoldPMTime.GetColumnBDEFieldType(ColumnIndex: Integer): TFieldType; Result := ftTime; end; -function TBoldPMTime.CompareField(ObjectContent: IBoldObjectContents; Field: IBoldField; ColumnIndex: integer; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList): Boolean; +function TBoldPMTime.CompareField(const ObjectContent: IBoldObjectContents; const Field: IBoldField; ColumnIndex: integer; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList): Boolean; var aTime: IBoldTimeContent; begin @@ -828,8 +1073,20 @@ function TBoldPMTime.GetColumnTypeAsSQL(ColumnIndex: Integer): string; Result := SystemPersistenceMapper.SQLDataBaseConfig.ColumnTypeForTime; end; +function TBoldPMTime.ValueAsVariant(const ObjectContent: IBoldObjectContents; + ColumnIndex: Integer; TranslationList: TBoldIdTranslationList): variant; +var + aTime: IBoldTimeContent; +begin + EnsureFirstColumn(ColumnIndex); + aTime := GetEnsuredValue(ObjectContent) as IBoldTimeContent; + if aTime.IsNull then + result := null + else + result := aTime.AsTime; +end; -procedure TBoldPMTime.ValueFromField(OwningObjectId: TBoldObjectId; ObjectContent: IBoldObjectContents; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; Field: IBoldField; ColumnIndex: Integer); +procedure TBoldPMTime.ValueFromField(OwningObjectId: TBoldObjectId; const ObjectContent: IBoldObjectContents; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; const Field: IBoldField; ColumnIndex: Integer); var aTime: IBoldTimeContent; begin @@ -841,7 +1098,7 @@ procedure TBoldPMTime.ValueFromField(OwningObjectId: TBoldObjectId; ObjectConten aTime.AsTime := Field.Value; end; -procedure TBoldPMTime.ValueToParam(ObjectContent: IBoldObjectContents; Param: IBoldParameter; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList); +procedure TBoldPMTime.ValueToParam(const ObjectContent: IBoldObjectContents; const Param: IBoldParameter; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList); var aTime: IBoldTimeContent; begin @@ -865,8 +1122,8 @@ function TBoldPMMemoBlob.GetColumnBDEFieldType(ColumnIndex: Integer): TFieldType const InternalEmptyString = '<## Internal Empty ##>'; -function TBoldPMNonEmptyBlob.CompareField(ObjectContent: IBoldObjectContents; Field: IBoldField; - ColumnIndex: integer; ValueSpace: IBoldValueSpace; +function TBoldPMNonEmptyBlob.CompareField(const ObjectContent: IBoldObjectContents; const Field: IBoldField; + ColumnIndex: integer; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList): Boolean; var aBlobContent: IBoldBlobContent; @@ -877,9 +1134,9 @@ function TBoldPMNonEmptyBlob.CompareField(ObjectContent: IBoldObjectContents; Fi result := Field.Value = aBlobContent.AsBlob; end; -procedure TBoldPMNonEmptyBlob.ValueFromField(OwningObjectId: TBoldObjectId; ObjectContent: IBoldObjectContents; - ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; - Field: IBoldField; ColumnIndex: Integer); +procedure TBoldPMNonEmptyBlob.ValueFromField(OwningObjectId: TBoldObjectId; const ObjectContent: IBoldObjectContents; + const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; + const Field: IBoldField; ColumnIndex: Integer); var aBlobContent: IBoldBlobContent; begin @@ -889,8 +1146,8 @@ procedure TBoldPMNonEmptyBlob.ValueFromField(OwningObjectId: TBoldObjectId; Obje aBlobContent.AsBlob := ''; end; -procedure TBoldPMNonEmptyBlob.ValueToParam(ObjectContent: IBoldObjectContents; - Param: IBoldParameter; ColumnIndex: Integer; +procedure TBoldPMNonEmptyBlob.ValueToParam(const ObjectContent: IBoldObjectContents; + const Param: IBoldParameter; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList); var EmptyBlobHandled: Boolean; @@ -940,27 +1197,36 @@ function TBoldPMLiveTypedBlob.GetRequiresLiveQuery: Boolean; result := true; end; + function TBoldPMString.DefaultDefaultDbValue: String; begin - if SystemPersistenceMapper.SQLDataBaseConfig.SupportsStringDefaultValues then - result := '''''' - else - result := ''; + result:=''; + if not AllowNull and (SystemPersistenceMapper.SQLDataBaseConfig.SupportsStringDefaultValues) then + result := ''''''; end; function TBoldPMInteger.DefaultDefaultDbValue: String; begin - result := SystemPersistenceMapper.SQLDataBaseConfig.CorrectlyQuotedDefaultValue('0'); + if AllowNull then + result := '' + else + result := SystemPersistenceMapper.SQLDataBaseConfig.CorrectlyQuotedDefaultValue('0'); end; function TBoldPMFloat.DefaultDefaultDbValue: String; begin - result := SystemPersistenceMapper.SQLDataBaseConfig.CorrectlyQuotedDefaultValue('0'); + if AllowNull then + result := '' + else + result := SystemPersistenceMapper.SQLDataBaseConfig.CorrectlyQuotedDefaultValue('0'); end; function TBoldPMCurrency.DefaultDefaultDbValue: String; begin - result := SystemPersistenceMapper.SQLDataBaseConfig.CorrectlyQuotedDefaultValue('0'); + if AllowNull then + result := '' + else + result := SystemPersistenceMapper.SQLDataBaseConfig.CorrectlyQuotedDefaultValue('0'); end; function TBoldPMCurrency.GetColumnTypeAsSQL(ColumnIndex: Integer): string; @@ -968,10 +1234,131 @@ function TBoldPMCurrency.GetColumnTypeAsSQL(ColumnIndex: Integer): string; Result := SystemPersistenceMapper.SQLDataBaseConfig.ColumnTypeForCurrency; end; +{ TBoldPMAnsiString } + +function TBoldPMAnsiString.CompareField(const ObjectContent: IBoldObjectContents; + const Field: IBoldField; ColumnIndex: integer; const ValueSpace: IBoldValueSpace; + TranslationList: TBoldIdTranslationList): Boolean; +var + aString: IBoldAnsiStringContent; +begin + EnsureFirstColumn(ColumnIndex); + aString := GetValue(ObjectContent) as IBoldAnsiStringContent; + result := + SystemPersistenceMapper.SQLDataBaseConfig.StoreEmptyStringsAsNULL and + Field.IsNull and (aString.asAnsiString = ''); + + if not result then + begin + if not CheckEitherNull(field, aString, result) then + result := Field.AsAnsiString = aString.asAnsiString; + end; +end; + +procedure TBoldPMAnsiString.ValueFromField(OwningObjectId: TBoldObjectId; + const ObjectContent: IBoldObjectContents; const ValueSpace: IBoldValueSpace; + TranslationList: TBoldIdTranslationList; const Field: IBoldField; ColumnIndex: + Integer); +var + aString: IBoldAnsiStringContent; +begin + EnsureFirstColumn(ColumnIndex); + aString := GetEnsuredValue(ObjectContent) as IBoldAnsiStringContent; + if Field.IsNull then + begin + if SystemPersistenceMapper.SQLDataBaseConfig.StoreEmptyStringsAsNULL then + aString.AsString := '' + else + aString.SetContentToNull + end + else + aString.asAnsiString := Field.AsAnsiString +end; + +procedure TBoldPMAnsiString.ValueToParam(const ObjectContent: IBoldObjectContents; + const Param: IBoldParameter; ColumnIndex: Integer; TranslationList: + TBoldIdTranslationList); +var + aString: IBoldAnsiStringContent; +begin + EnsureFirstColumn(ColumnIndex); + aString := GetEnsuredValue(ObjectContent) as IBoldAnsiStringContent; + if aString.IsNull then + SetParamToNullWithDataType(Param, GetColumnBDEFieldType(0)) + else + Param.AsAnsiString := aString.asAnsiString +end; + +{ TBoldPMUnicodeString } + +function TBoldPMUnicodeString.CompareField(const ObjectContent: IBoldObjectContents; + const Field: IBoldField; ColumnIndex: integer; const ValueSpace: IBoldValueSpace; + TranslationList: TBoldIdTranslationList): Boolean; +var + aString: IBoldUnicodeStringContent; +begin + EnsureFirstColumn(ColumnIndex); + aString := GetValue(ObjectContent) as IBoldUnicodeStringContent; + result := + SystemPersistenceMapper.SQLDataBaseConfig.StoreEmptyStringsAsNULL and + Field.IsNull and (aString.asUnicodeString = ''); + + if not result then + begin + if not CheckEitherNull(field, aString, result) then + result := Field.AsWideString = aString.asUnicodeString; + end; +end; + +function TBoldPMUnicodeString.GetColumnBDEFieldType(ColumnIndex: Integer): + TFieldType; +begin + Result := ftWideString; +end; + +function TBoldPMUnicodeString.GetColumnTypeAsSQL(ColumnIndex: Integer): string; +begin + Result := SystemPersistenceMapper.SQLDataBaseConfig.GetColumnTypeForUnicodeString(GetColumnSize(ColumnIndex)); +end; + +procedure TBoldPMUnicodeString.ValueFromField(OwningObjectId: TBoldObjectId; + const ObjectContent: IBoldObjectContents; const ValueSpace: IBoldValueSpace; + TranslationList: TBoldIdTranslationList; const Field: IBoldField; ColumnIndex: + Integer); +var + aString: IBoldUnicodeStringContent; +begin + EnsureFirstColumn(ColumnIndex); + aString := GetEnsuredValue(ObjectContent) as IBoldUnicodeStringContent; + if Field.IsNull then + begin + if SystemPersistenceMapper.SQLDataBaseConfig.StoreEmptyStringsAsNULL then + aString.AsString := '' + else + aString.SetContentToNull + end + else + aString.asUnicodeString := Field.AsWideString +end; + +procedure TBoldPMUnicodeString.ValueToParam(const ObjectContent: IBoldObjectContents; + const Param: IBoldParameter; ColumnIndex: Integer; TranslationList: + TBoldIdTranslationList); +var + aString: IBoldUnicodeStringContent; +begin + EnsureFirstColumn(ColumnIndex); + aString := GetEnsuredValue(ObjectContent) as IBoldUnicodeStringContent; + if aString.IsNull then + SetParamToNullWithDataType(Param, GetColumnBDEFieldType(0)) + else + Param.AsWideString := aString.asUnicodeString +end; + { TBoldPMStringBDECodePageBug } procedure TBoldPMStringBDECodePageBug.ValueToParam( - ObjectContent: IBoldObjectContents; Param: IBoldParameter; + const ObjectContent: IBoldObjectContents; const Param: IBoldParameter; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList); var aString: IBoldStringContent; @@ -982,21 +1369,133 @@ procedure TBoldPMStringBDECodePageBug.ValueToParam( SetParamToNullWithDataType(Param, GetColumnBDEFieldType(0)) else begin - // make a copy of the string so that the param can - // mess with it alone + Param.AsString := copy(aString.AsString, 1, maxint); end; end; -initialization +{---TBoldPMText---} +constructor TBoldPMText.CreateFromMold(Moldmember: TMoldMember; MoldClass: TMoldClass; Owner: TBoldObjectPersistenceMapper; const MemberIndex: Integer; TypeNameDictionary: TBoldTypeNameDictionary); +begin + inherited; + if (DefaultDbValue <> '') and + (DefaultDbValue[1] <> '''') and + (DefaultDbValue[1] <> '"') then + DefaultDbValue := '''' + DefaultDbValue + ''''; + if SystemPersistenceMapper.SQLDataBaseConfig.StoreEmptyStringsAsNULL then + begin + if (MoldMember as TMoldAttribute).AllowNull then + raise EBold.CreateFmt('String attribute must not allow NULL in the model if persistencemapper stores empty strings as NULL (%s.%s)', [ + MoldClass.Name, MoldMember.Name]); + fAllowNull := True; + end; +end; - TwoSeconds := EncodeTime(0, 0, 2, 0); +function TBoldPMText.DefaultDefaultDbValue: String; +begin + if SystemPersistenceMapper.SQLDataBaseConfig.SupportsStringDefaultValues then + result := '''''' + else + result := ''; +end; + +function TBoldPMText.GetColumnTypeAsSQL(ColumnIndex: Integer): string; +begin + Result := SystemPersistenceMapper.SQLDataBaseConfig.ColumnTypeForText; +end; + +class function TBoldPMText.CanStore(const ContentName: string): Boolean; +begin + Result := AnsiCompareText(ContentName, BoldContentName_String) = 0; +end; + +function TBoldPMText.GetColumnBDEFieldType(ColumnIndex: Integer): TFieldType; +begin + Result := ftMemo; +end; +procedure TBoldPMText.ValueFromField(OwningObjectId: TBoldObjectId; const ObjectContent: IBoldObjectContents; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; const Field: IBoldField; ColumnIndex: Integer); +var + aString: IBoldStringContent; +begin + EnsureFirstColumn(ColumnIndex); + aString := GetEnsuredValue(ObjectContent) as IBoldStringContent; + if Field.IsNull then + begin + if SystemPersistenceMapper.SQLDataBaseConfig.StoreEmptyStringsAsNULL then + aString.AsString := '' + else + aString.SetContentToNull + end + else + aString.AsString := Field.AsString +end; + +function TBoldPMText.CompareField(const ObjectContent: IBoldObjectContents; const Field: IBoldField; ColumnIndex: integer; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList): Boolean; +var + aString: IBoldStringContent; +begin + EnsureFirstColumn(ColumnIndex); + aString := GetValue(ObjectContent) as IBoldStringContent; + result := + SystemPersistenceMapper.SQLDataBaseConfig.StoreEmptyStringsAsNULL and + Field.IsNull and (aString.AsString = ''); + + if not result then + begin + if not CheckEitherNull(field, aString, result) then + result := Field.AsString = aString.AsString; + end; +end; + +procedure TBoldPMText.ValueToParam(const ObjectContent: IBoldObjectContents; const Param: IBoldParameter; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList); +var + aString: IBoldStringContent; +begin + EnsureFirstColumn(ColumnIndex); + aString := GetEnsuredValue(ObjectContent) as IBoldStringContent; + if aString.IsNull then + SetParamToNullWithDataType(Param, GetColumnBDEFieldType(0)) + else + Param.AsString := aString.AsString +end; + +{ TBoldPMUnicodeText } + +function TBoldPMUnicodeText.GetColumnBDEFieldType(ColumnIndex: Integer): + TFieldType; +begin + Result := ftWideMemo; +end; + +function TBoldPMUnicodeText.GetColumnTypeAsSQL(ColumnIndex: Integer): string; +begin + Result := SystemPersistenceMapper.SQLDataBaseConfig.ColumnTypeForUnicodeText; +end; + +{ TBoldPMGuid } + +function TBoldPMGuid.GetColumnBDEFieldType(ColumnIndex: Integer): TFieldType; +begin + result := ftGuid; +end; + +function TBoldPMGuid.GetColumnTypeAsSQL(ColumnIndex: Integer): string; +begin + Result := SystemPersistenceMapper.SQLDataBaseConfig.ColumnTypeForGUID; +end; + +initialization + TwoSeconds := EncodeTime(0, 0, 2, 0); with BoldMemberPersistenceMappers do begin AddDescriptor(TBoldSingleColumnMember, alAbstract); AddDescriptor(TBoldPMString, alConcrete); + AddDescriptor(TBoldPMAnsiString, alConcrete); + AddDescriptor(TBoldPMUnicodeString, alConcrete); AddDescriptor(TBoldPMStringBDECodePageBug, alConcrete); + AddDescriptor(TBoldPMText, alConcrete); + AddDescriptor(TBoldPMUnicodeText, alConcrete); AddDescriptor(TBoldPMInteger, alConcrete); AddDescriptor(TBoldPMSmallInt, alConcrete); AddDescriptor(TBoldPMByte, alConcrete); @@ -1014,6 +1513,7 @@ initialization AddDescriptor(TBoldPMDate, alConcrete); AddDescriptor(TBoldPMTime, alConcrete); AddDescriptor(TBoldPMLogic, alConcrete); + AddDescriptor(TBoldPMGuid, alConcrete); end; {end - initialization} @@ -1023,7 +1523,11 @@ finalization begin RemoveDescriptorByClass(TBoldSingleColumnMember); RemoveDescriptorByClass(TBoldPMString); + RemoveDescriptorByClass(TBoldPMAnsiString); + RemoveDescriptorByClass(TBoldPMUnicodeString); RemoveDescriptorByClass(TBoldPMStringBDECodePageBug); + RemoveDescriptorByClass(TBoldPMText); + RemoveDescriptorByClass(TBoldPMUnicodeText); RemoveDescriptorByClass(TBoldPMInteger); RemoveDescriptorByClass(TBoldPMSmallInt); RemoveDescriptorByClass(TBoldPMByte); @@ -1041,8 +1545,8 @@ finalization RemoveDescriptorByClass(TBoldPMDate); RemoveDescriptorByClass(TBoldPMTime); RemoveDescriptorByClass(TBoldPMLogic); + RemoveDescriptorByClass(TBoldPMGuid); end; {END finalization} end. - diff --git a/Source/PMapper/Default/BoldPMappersDefault.pas b/Source/PMapper/Default/BoldPMappersDefault.pas index a6676bd..a406401 100644 --- a/Source/PMapper/Default/BoldPMappersDefault.pas +++ b/Source/PMapper/Default/BoldPMappersDefault.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldPMappersDefault; interface @@ -20,10 +23,13 @@ interface BoldPSParams, BoldPSDescriptions, BoldPSDescriptionsSQL, + BoldIndexCollection, BoldPSDescriptionsDefault, BoldSQLMappingInfo, BoldPMappers, - BoldPMappersSQL; + BoldPMappersSQL, + BoldElements; + const MEMBERIDCOLUMN_NAME = 'MEMBER_ID'; @@ -37,6 +43,8 @@ TBoldMemberDefaultMapper = class; TBoldModelVersionMember = class; EBoldCantGetID = class(EBold); + TGetNewTimeStampEvent = procedure(out aCurrentTimeStamp: integer; out aLastClockTimestamp: integer; out aLastClock: TDateTime; out aTheNowValue: TDateTime; aClockLogGranularity: TDateTime) of object; + TIDIncrementEvent = function(aNumberOfIdsToReserve: integer): integer of object; { TBoldSystemDefaultMapper } TBoldSystemDefaultMapper = class(TBoldSystemSQLMapper) @@ -44,6 +52,7 @@ TBoldSystemDefaultMapper = class(TBoldSystemSQLMapper) fNextDBID: Longint; fLastReservedDBID: Longint; fReservedCount: Longint; + fCustomIndexes: TBoldIndexCollection; fXFilesTimeStampColumn: TBoldSQLColumnDescription; fXFilesGlobalIdColumn: TBoldSQLColumnDescription; fTimeStampTableTimeStampColumn: TBoldSQLColumnDescription; @@ -53,8 +62,8 @@ TBoldSystemDefaultMapper = class(TBoldSystemSQLMapper) fClockLogTableThisTimeStampColumn: TBoldSQLColumnDescription; fClockLogTableThisClockColumn: TBoldSQLColumnDescription; fClockLogTableLastClockColumn: TBoldSQLColumnDescription; - function GetPSSystemDescription: TBoldDefaultSystemDescription; - function GetRootClassObjectPersistenceMapper: TBoldObjectDefaultMapper; + function GetPSSystemDescription: TBoldDefaultSystemDescription; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetRootClassObjectPersistenceMapper: TBoldObjectDefaultMapper; {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure GetChangePointsQuery(Query: IBoldQuery; IdList: TBoldObjectIdList; StartTime: TBoldTimestampType; EndTime: TBoldTimestampType; NameSpace: TBoldSqlnameSpace); protected function CreatePSParams: TBoldPSParams; override; @@ -65,29 +74,32 @@ TBoldSystemDefaultMapper = class(TBoldSystemSQLMapper) property ReservedCount: Longint read fReservedCount write fReservedCount; function NewGlobalIdFromQuery(aQuery: IBoldQuery; BoldDbTypeColumn: Integer): TBoldObjectId; procedure GetNewTimeStamp; override; - procedure FetchDeletedObjects(ObjectIdList: TBoldObjectIdList; ValueSpace: IBoldValueSpace); override; + procedure FetchDeletedObjects(ObjectIdList: TBoldObjectIdList; const ValueSpace: IBoldValueSpace); override; procedure InitializeBoldDbType; override; function CreateMappingInfo: TBoldSQLMappingInfo; override; procedure InitializePSDescriptions; override; function EnsurePrecondition(Precondition: TBoldUpdatePrecondition; TranslationList: TBoldIdTranslationList): Boolean; override; function EnsureOptimisticLocking(Precondition: TBoldOptimisticLockingPrecondition; TranslationList: TBoldIdTranslationList): Boolean; public - constructor CreateFromMold(moldModel: TMoldModel; TypeNameDictionary: TBoldTypeNameDictionary; SQlDatabaseConfig: TBoldSQLDatabaseConfig; GetDatabaseFunc: TBoldGetDatabaseEvent); + constructor CreateFromMold(moldModel: TMoldModel; TypeNameDictionary: TBoldTypeNameDictionary; + CustomIndexes: TBoldIndexCollection; SQlDatabaseConfig: TBoldSQLDatabaseConfig; GetDatabaseFunc: TBoldGetDatabaseEvent); procedure PMFetchClassWithCondition(ObjectIDList: TBoldObjectIdList; - ValueSpace: IBoldValueSpace; + const ValueSpace: IBoldValueSpace; BoldCondition: TBoldCondition; FetchMode: Integer; TranslationList: TBoldIdTranslationList); override; - function GetListUsingQuery(ObjectIDList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; aQuery: IBoldQuery; FetchMode: Integer; TranslationList: TBoldIdTranslationList; TimeStamp: TBoldTimeStampType; MaxAnswers: integer = -1; Offset: integer = -1): integer; + function GetListUsingQuery(ObjectIDList: TBoldObjectIdList; const ValueSpace: IBoldValueSpace; const aQuery: IBoldQuery; ClassId, BoldDbTypeColumn, ObjectIdColumn: integer; FetchMode: Integer; TranslationList: TBoldIdTranslationList; TimeStamp: TBoldTimeStampType; MaxAnswers: integer = -1; Offset: integer = -1): integer; function EnsureTable(const TableName: string; TableVersioned: Boolean): TBoldSQLTableDescription; override; function EnsureColumn(const TableName, ColumnName, SQLType, SQLAllowNull: string; const BDEType: TFieldType; Length: Integer; const AllowNull, InVersionedTable: Boolean; const DefaultDBValue: String): TBoldSQLColumnDescription; - procedure EnsureIndex(const TableName, Fields: string; const PrimaryIndex, Unique, InVersionedTable: Boolean); + procedure EnsureIndex(const TableName, Fields: string; const PrimaryIndex, + Unique, NonClustered, InVersionedTable: Boolean); procedure PMTranslateToGlobalIds(ObjectIdList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList); override; procedure PMTranslateToLocalIds(GlobalIdList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList); override; procedure PMSetReadonlyness(ReadOnlyList, WriteableList: TBoldObjectIdList); override; procedure PMTimestampForTime(ClockTime: TDateTime; var Timestamp: TBoldTimestampType); override; procedure PMTimeForTimestamp(Timestamp: TBoldTimestampType; var ClockTime: TDateTime); override; - function NewIdFromQuery(aQuery: IBoldQuery; BoldDbTypeColumn, ObjectIdColumn: integer; Timestamp: TBoldTimeStampType): TBoldObjectId; + function NewIdFromQuery(const aQuery: IBoldQuery; ClassId, BoldDbTypeColumn, ObjectIdColumn: integer; Timestamp: TBoldTimeStampType): TBoldObjectId; + function CanEvaluateInPS(sOCL: string; aSystem: TBoldElement; aContext: TBoldElementTypeInfo = nil; const aVariableList: TBoldExternalVariableList = nil): Boolean; override; property PSSystemDescription: TBoldDefaultSystemDescription read GetPSSystemDescription; property RootClassObjectPersistenceMapper: TBoldObjectDefaultMapper read GetRootClassObjectPersistenceMapper; property XFilesTimeStampColumn: TBoldSQLColumnDescription read fXFilesTimeStampColumn; @@ -101,51 +113,73 @@ TBoldSystemDefaultMapper = class(TBoldSystemSQLMapper) property TimeStampTableTimeStampColumn: TBoldSQLColumnDescription read fTimeStampTableTimeStampColumn; end; + TQueryCacheEntry = record + MemberList: TBoldMemberIdList; + SqlStrings: TStringList; + FetchMode: Integer; + MemberPMList: TBoldMemberPersistenceMapperList; + CustomMembers: TBoldMemberPersistenceMapperList; + end; + + TPMCreateCacheEntry = record + SqlStrings: TStringList; + MemberPMList: TBoldMemberPersistenceMapperList; + end; + + TQueryCache = array of TQueryCacheEntry; + TPMCreateCache = array of TPMCreateCacheEntry; + { TBoldObjectDefaultMapper } TBoldObjectDefaultMapper = class(TBoldObjectSQLMapper) private fSubClassesID: string; fModelVersionMember: TBoldModelVersionMember; fOptimisticLockingMode: TBoldOptimisticLockingMode; - function GetSystemPersistenceMapper: TBoldSystemDefaultMapper; + fQueryCache: TQueryCache; + fPMCreateCache: TPMCreateCache; + fSingleLinkList: TBoldMemberIdList; + function GetSystemPersistenceMapper: TBoldSystemDefaultMapper; {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure PMUpdateStopTime(ObjectIDList: TBoldObjectIdList); procedure GetChangePoints(ObjectIDList: TBoldObjectIdList; Condition: TBoldChangePointCondition; NameSpace: TBoldSqlnameSpace); - procedure PMMultiPurposeRetrieveExactIdList(ObjectsToFetch: TBoldObjectIdList; ValueSpace: IBoldValueSpace; MemberIdList: TBoldMemberIdList; FetchMode: Integer; TranslationList: TBoldIdTranslationList; MissingList: TBoldObjectIdList; FailureList: TBoldObjectIdList; TimeStamp: TBoldTimeStampType); - - procedure HandleCompareData(FetchedId: TBoldObjectId; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; Query: IBoldQuery; MemberPMList: TBoldMemberPersistenceMapperList; FetchMode: integer; FailureList: TBoldObjectIdList); - function CompareFieldsToMembers(ObjectID: TBoldObjectId; ValueSpace: IBoldValueSpace; DataSet: IBoldDataSet; memberList: TBoldMemberPersistenceMapperList; TranslationList: TBoldIdTranslationList): Boolean; - procedure DetectLinkClassDuplicates(ObjectIdList: TBoldObjectidList; ValueSpace: IBoldvalueSpace; TranslationList: TBoldIdTranslationList; DuplicateList: TBoldObjectIdList); + procedure PMMultiPurposeRetrieveExactIdList(ObjectsToFetch: TBoldObjectIdList; const ValueSpace: IBoldValueSpace; MemberIdList: TBoldMemberIdList; FetchMode: Integer; TranslationList: TBoldIdTranslationList; MissingList: TBoldObjectIdList; FailureList: TBoldObjectIdList; TimeStamp: TBoldTimeStampType); + function FindInCache(MemberIdList: TBoldMemberIdList; FetchMode: integer; var MemberPMList, CustomMembers: TBoldMemberPersistenceMapperList; var ASql: TStringList): boolean; + procedure HandleCompareData(FetchedId: TBoldObjectId; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; const Query: IBoldQuery; MemberPMList: TBoldMemberPersistenceMapperList; FetchMode: integer; FailureList: TBoldObjectIdList); + function CompareFieldsToMembers(ObjectID: TBoldObjectId; const ValueSpace: IBoldValueSpace; const DataSet: IBoldDataSet; memberList: TBoldMemberPersistenceMapperList; TranslationList: TBoldIdTranslationList): Boolean; + procedure DetectLinkClassDuplicates(ObjectIdList: TBoldObjectidList; const ValueSpace: IBoldvalueSpace; TranslationList: TBoldIdTranslationList; DuplicateList: TBoldObjectIdList); procedure GenerateMappingInfo(ExpressionName: String; MoldClass: TMoldClass); - procedure PMTemporalUpdate(ObjectIdList: TBoldObjectIdList; ValueSpace: IBoldvalueSpace; TranslationList: TBoldIdTranslationList); - procedure FetchPreviousSingleLinkValues(ObjectIdList: TBoldObjectIdLIst; Old_Values: IBoldvalueSpace); - procedure MakeIDsExactUsingTable(ObjectIDList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList; Table: TBoldSQLTableDescription); - function InternalIdListSegmentToWhereFragment(IdList: TBoldObjectIdList; Start, Stop: integer; Parameterized: IBoldParameterized): String; - procedure InternalMakeIDsExact(ObjectIDList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList); + procedure PMTemporalUpdate(ObjectIdList: TBoldObjectIdList; const ValueSpace: IBoldvalueSpace; TranslationList: TBoldIdTranslationList); + procedure FetchPreviousSingleLinkValues(ObjectIdList: TBoldObjectIdLIst; const Old_Values: IBoldvalueSpace); + procedure MakeIDsExactUsingTable(ObjectIDList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList; Table: TBoldSQLTableDescription; EnsureAll: Boolean; HandleNonExisting: Boolean); + function InternalIdListSegmentToWhereFragment(IdList: TBoldObjectIdList; Start, Stop: Integer; AllowParms: Boolean; const Parameterized: IBoldParameterized): String; + procedure InternalMakeIDsExact(ObjectIDList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList; EnsureAll: Boolean; HandleNonExisting: Boolean); + procedure FetchRawSqlCondition(ObjectIDList: TBoldObjectIdList; const ValueSpace: IBoldValueSpace; RawCondition: TBoldRawSqlCondition; FetchMode: Integer; TranslationList: TBoldIdTranslationList); protected procedure JoinSQLTableByKey(SQL: TStringList; MainTable, JoinTable: TBoldSQLTableDescription); override; procedure SQLForID(Table: TBoldSQLTableDescription; SQL: TStrings; UseAlias: Boolean); override; procedure SQLForDistributed(SQL: TStrings; const SQLStyle: TBoldSQLStyle); override; procedure PMFetchWithCondition(ObjectIDList: TBoldObjectIdList; - ValueSpace: IBoldValueSpace; BoldCondition: TBoldCondition; FetchMode: Integer; TranslationList: TBoldIdTranslationList); override; - function NextExternalObjectId(ValueSpace: IBoldValueSpace; ObjectId: TBoldObjectId): TBoldObjectId; override; + const ValueSpace: IBoldValueSpace; BoldCondition: TBoldCondition; FetchMode: Integer; TranslationList: TBoldIdTranslationList); override; + function NextExternalObjectId(const ValueSpace: IBoldValueSpace; ObjectId: TBoldObjectId): TBoldObjectId; override; function DistributableTable: TBoldSQLTableDescription; override; - procedure PMCompareExactIDList(ObjectIDList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; MemberIdList: TBoldMemberIdList; TranslationList: TBoldIdTranslationList; FailureList: TBoldObjectIdList); + procedure PMCompareExactIDList(ObjectIDList: TBoldObjectIdList; const ValueSpace: IBoldValueSpace; MemberIdList: TBoldMemberIdList; TranslationList: TBoldIdTranslationList; FailureList: TBoldObjectIdList); procedure InitializePSDescriptions; override; + procedure FillInMembers(MyMoldClass, CurrentMoldClass: TMoldClass; TypeNameDictionary: TBoldTypeNameDictionary); override; public constructor CreateFromMold(moldClass: TMoldClass; Owner: TBoldSystemPersistenceMapper; TypeNameDictionary: TBoldTypeNameDictionary); override; + destructor Destroy; override; procedure SQLForKey(Table: TBoldSQLTableDescription; SQL: TStrings; const SQLStyle: TBoldSQLStyle; useAlias: Boolean); override; function UpdatesMembersInTable(aTable: TBoldSQLTableDescription): Boolean; override; - function IdListSegmentToWhereFragment(IdList: TBoldObjectIdList; Start, Stop: integer; Query: IBoldExecQuery): String; overload; - function IdListSegmentToWhereFragment(IdList: TBoldObjectIdList; Start, Stop: integer; Query: IBoldQuery): String; overload; - procedure MakeIDsExact(ObjectIDList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList); override; - procedure PMFetchExactIDList(ObjectIDList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; MemberIdList: TBoldMemberIdList; FetchMode: Integer; TranslationList: TBoldIdTranslationList; MissingList: TBoldObjectIdList); override; - procedure PMDelete(ObjectIDList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; Old_Values: IBoldValueSpace; TranslationList: TBoldIdTranslationList); override; - procedure PMCreate(ObjectIDList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList); override; - procedure PMUpdate(ObjectIDList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; Old_Values: IBoldValueSpace; TranslationList: TBoldIdTranslationList); override; - procedure DistributableInfoFromQuery(ObjectID: TBoldObjectId; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; DataSet: IBoldDataSet); - procedure HandleFetchData(FetchedId: TBoldObjectId; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; Query: IBoldQuery; MemberPMList: TBoldMemberPersistenceMapperList; FetchMode: integer; FailureList: TBoldObjectIdList); - procedure PortObject(ObjectId: TBoldObjectId; Query: IBoldQuery); - function IsOldVersion(Query: IBoldQuery): Boolean; + function IdListSegmentToWhereFragment(IdList: TBoldObjectIdList; Start, Stop: Integer; AllowParms: Boolean; const Query: IBoldExecQuery): String; overload; + function IdListSegmentToWhereFragment(IdList: TBoldObjectIdList; Start, Stop: Integer; AllowParms: Boolean; const Query: IBoldQuery): String; overload; + procedure MakeIDsExact(ObjectIDList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList; HandleNonExisting: Boolean); override; + procedure PMFetchExactIDList(ObjectIDList: TBoldObjectIdList; const ValueSpace: IBoldValueSpace; MemberIdList: TBoldMemberIdList; FetchMode: Integer; TranslationList: TBoldIdTranslationList; MissingList: TBoldObjectIdList); override; + procedure PMDelete(ObjectIDList: TBoldObjectIdList; const ValueSpace: IBoldValueSpace; const Old_Values: IBoldValueSpace; TranslationList: TBoldIdTranslationList); override; + procedure PMCreate(ObjectIDList: TBoldObjectIdList; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList); override; + procedure PMUpdate(ObjectIDList: TBoldObjectIdList; const ValueSpace: IBoldValueSpace; const Old_Values: IBoldValueSpace; TranslationList: TBoldIdTranslationList); override; + procedure DistributableInfoFromQuery(ObjectID: TBoldObjectId; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; const DataSet: IBoldDataSet); + procedure HandleFetchData(FetchedId: TBoldObjectId; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; const Query: IBoldQuery; MemberPMList: TBoldMemberPersistenceMapperList; FetchMode: integer; FailureList: TBoldObjectIdList); + procedure PortObject(ObjectId: TBoldObjectId; const Query: IBoldQuery); + function IsOldVersion(const Query: IBoldQuery): Boolean; property SubClassesID: string read fSubClassesID write fSubClassesId; property SystemPersistenceMapper: TBoldSystemDefaultMapper read GetSystemPersistenceMapper; property ModelVersionMember: TBoldModelVersionMember read fModelVersionMember; @@ -155,14 +189,15 @@ TBoldObjectDefaultMapper = class(TBoldObjectSQLMapper) TBoldMemberDefaultMapper = class(TBoldMemberSQLMapper) private procedure GenerateMappingInfo(MoldClass: TMoldClass; MoldMember: TMoldMember); - function GetSystemPersistenceMapper: TBoldSystemDefaultMapper; - function GetObjectPersistenceMapper: TBoldObjectDefaultMapper; + function GetSystemPersistenceMapper: TBoldSystemDefaultMapper; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetObjectPersistenceMapper: TBoldObjectDefaultMapper; {$IFDEF BOLD_INLINE} inline; {$ENDIF} protected - function CheckEitherNull(field: IBoldField; Value: IBoldValue; var Equal: Boolean): Boolean; + FColumnIndex: Boolean; + function CheckEitherNull(const field: IBoldField; const Value: IBoldValue; var Equal: Boolean): Boolean; function GetAllowNullAsSQL: string; override; procedure GetChangePoints(ObjectIDList: TBoldObjectIdList; Condition: TBoldChangePointCondition; NameSpace: TBoldSqlnameSpace); virtual; - function CompareFields(ObjectContent: IBoldObjectContents; DataSet: IBoldDataSet; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList): Boolean; - function CompareField(ObjectContent: IBoldObjectContents; Field: IBoldField; ColumnIndex: integer; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList): Boolean; virtual; abstract; + function CompareFields(const ObjectContent: IBoldObjectContents; const DataSet: IBoldDataSet; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList): Boolean; + function CompareField(const ObjectContent: IBoldObjectContents; const Field: IBoldField; ColumnIndex: integer; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList): Boolean; virtual; abstract; procedure InitializePSDescriptions; override; function RequiresMemberMapping: Boolean; virtual; function FindDefiningTable(LocalMoldClass: TMoldClass; MoldMember: TMoldMember): string; virtual; @@ -170,7 +205,7 @@ TBoldMemberDefaultMapper = class(TBoldMemberSQLMapper) public constructor CreateFromMold(moldMember: TMoldMember; moldClass: TMoldClass; Owner: TBoldObjectPersistenceMapper; const MemberIndex: Integer; TypeNameDictionary: TBoldTypeNameDictionary); override; procedure PMFetch(ObjectIdList: TBoldObjectIdList; - ValueSpace: IBoldValueSpace; + const ValueSpace: IBoldValueSpace; FetchMode: Integer; TranslationList: TBoldIdTranslationList; FailureList: TBoldObjectIdList); override; property ObjectPersistenceMapper: TBoldObjectDefaultMapper read GetObjectPersistenceMapper; @@ -193,15 +228,16 @@ TBoldModelVersionMember = class(TBoldSingleColumnMember) protected function GetColumnTypeAsSQL(ColumnIndex: Integer): string; override; function GetColumnBDEFieldType(ColumnIndex: Integer): TFieldType; override; - function CompareField(ObjectContent: IBoldObjectContents; Field: IBoldField; ColumnIndex: integer; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList): Boolean; override; + function CompareField(const ObjectContent: IBoldObjectContents; const Field: IBoldField; ColumnIndex: integer;const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList): Boolean; override; function FindDefiningTable(LocalMoldClass: TMoldClass; MoldMember: TMoldMember): string; override; public constructor CreateFromMold(moldMember: TMoldMember; moldClass: TMoldClass; Owner: TBoldObjectPersistenceMapper; const MemberIndex: Integer; TypeNameDictionary: TBoldTypeNameDictionary); override; - function IsDirty(ObjectContents: IBoldObjectContents): Boolean; override; - function ShouldFetch(ObjectContents: IBoldObjectContents): Boolean; override; - procedure ValueToParam(ObjectContent: IBoldObjectContents; Param: IBoldParameter; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList); override; - procedure ValueFromField(OwningObjectId: TBoldObjectId; ObjectContent: IBoldObjectContents; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; Field: IBoldField; ColumnIndex: Integer); override; - function VersionFromQuery(Query: IBoldQuery): Integer; + function IsDirty(const ObjectContents: IBoldObjectContents): Boolean; override; + function ShouldFetch(const ObjectContents: IBoldObjectContents): Boolean; override; + procedure ValueToParam(const ObjectContent: IBoldObjectContents; const Param: IBoldParameter; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList); override; + procedure ValueFromField(OwningObjectId: TBoldObjectId; const ObjectContent: IBoldObjectContents; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; const Field: IBoldField; ColumnIndex: Integer); override; + function ValueAsVariant(const ObjectContent: IBoldObjectContents; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList): variant; override; + function VersionFromQuery(const Query: IBoldQuery): Integer; property VersionNumber: Integer read fVersionNumber write fVersionNumber; end; @@ -210,14 +246,32 @@ TBoldReadOnlynessMember = class(TBoldSingleColumnMember) protected function GetColumnTypeAsSQL(ColumnIndex: Integer): string; override; function GetColumnBDEFieldType(ColumnIndex: Integer): TFieldType; override; - function CompareField(ObjectContent: IBoldObjectContents; Field: IBoldField; ColumnIndex: integer; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList): Boolean; override; + function CompareField(const ObjectContent: IBoldObjectContents; const Field: IBoldField; ColumnIndex: integer;const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList): Boolean; override; function FindDefiningTable(LocalMoldClass: TMoldClass; MoldMember: TMoldMember): string; override; public constructor CreateFromMold(moldMember: TMoldMember; moldClass: TMoldClass; Owner: TBoldObjectPersistenceMapper; const MemberIndex: Integer; TypeNameDictionary: TBoldTypeNameDictionary); override; - function IsDirty(ObjectContents: IBoldObjectContents): Boolean; override; - function ShouldFetch(ObjectContents: IBoldObjectContents): Boolean; override; - procedure ValueToParam(ObjectContent: IBoldObjectContents; Param: IBoldParameter; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList); override; - procedure ValueFromField(OwningObjectId: TBoldObjectId; ObjectContent: IBoldObjectContents; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; Field: IBoldField; ColumnIndex: Integer); override; + function IsDirty(const ObjectContents: IBoldObjectContents): Boolean; override; + function ShouldFetch(const ObjectContents: IBoldObjectContents): Boolean; override; + procedure ValueToParam(const ObjectContent: IBoldObjectContents; const Param: IBoldParameter; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList); override; + procedure ValueFromField(OwningObjectId: TBoldObjectId; const ObjectContent: IBoldObjectContents; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; const Field: IBoldField; ColumnIndex: Integer); override; + function ValueAsVariant(const ObjectContent: IBoldObjectContents; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList): variant; override; + end; + + { TBoldNonXFileTimeStampMember } + TBoldNonXFileTimeStampMember = class(TBoldSingleColumnMember) + protected + function GetColumnTypeAsSQL(ColumnIndex: Integer): string; override; + function GetColumnBDEFieldType(ColumnIndex: Integer): TFieldType; override; + function CompareField(const ObjectContent: IBoldObjectContents; const Field: IBoldField; ColumnIndex: integer;const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList): Boolean; override; + function FindDefiningTable(LocalMoldClass: TMoldClass; MoldMember: TMoldMember): string; override; + function SupportsComparingWithoutValue: Boolean; override; + public + constructor CreateFromMold(moldMember: TMoldMember; moldClass: TMoldClass; Owner: TBoldObjectPersistenceMapper; const MemberIndex: Integer; TypeNameDictionary: TBoldTypeNameDictionary); override; + function IsDirty(const ObjectContents: IBoldObjectContents): Boolean; override; + function ShouldFetch(const ObjectContents: IBoldObjectContents): Boolean; override; + procedure ValueToParam(const ObjectContent: IBoldObjectContents; const Param: IBoldParameter; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList); override; + procedure ValueFromField(OwningObjectId: TBoldObjectId; const ObjectContent: IBoldObjectContents; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; const Field: IBoldField; ColumnIndex: Integer); override; + function ValueAsVariant(const ObjectContent: IBoldObjectContents; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList): variant; override; end; TBoldXFilesMembers = class(TBoldSingleColumnMember) @@ -231,15 +285,16 @@ TBoldTimeStampMember = class(TBoldXFilesMembers) protected function GetColumnTypeAsSQL(ColumnIndex: Integer): string; override; function GetColumnBDEFieldType(ColumnIndex: Integer): TFieldType; override; - function CompareField(ObjectContent: IBoldObjectContents; Field: IBoldField; ColumnIndex: integer; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList): Boolean; override; + function CompareField(const ObjectContent: IBoldObjectContents; const Field: IBoldField; ColumnIndex: integer;const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList): Boolean; override; function FindDefiningTable(LocalMoldClass: TMoldClass; MoldMember: TMoldMember): string; override; function SupportsComparingWithoutValue: Boolean; override; public constructor CreateFromMold(moldMember: TMoldMember; moldClass: TMoldClass; Owner: TBoldObjectPersistenceMapper; const MemberIndex: Integer; TypeNameDictionary: TBoldTypeNameDictionary); override; - function IsDirty(ObjectContents: IBoldObjectContents): Boolean; override; - function ShouldFetch(ObjectContents: IBoldObjectContents): Boolean; override; - procedure ValueToParam(ObjectContent: IBoldObjectContents; Param: IBoldParameter; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList); override; - procedure ValueFromField(OwningObjectId: TBoldObjectId; ObjectContent: IBoldObjectContents; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; Field: IBoldField; ColumnIndex: Integer); override; + function IsDirty(const ObjectContents: IBoldObjectContents): Boolean; override; + function ShouldFetch(const ObjectContents: IBoldObjectContents): Boolean; override; + procedure ValueToParam(const ObjectContent: IBoldObjectContents; const Param: IBoldParameter; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList); override; + procedure ValueFromField(OwningObjectId: TBoldObjectId; const ObjectContent: IBoldObjectContents; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; const Field: IBoldField; ColumnIndex: Integer); override; + function ValueAsVariant(const ObjectContent: IBoldObjectContents; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList): variant; override; end; { TBoldTimeStampMember } @@ -247,16 +302,18 @@ TBoldGlobalIdMember = class(TBoldXFilesMembers) protected function GetColumnTypeAsSQL(ColumnIndex: Integer): string; override; function GetColumnBDEFieldType(ColumnIndex: Integer): TFieldType; override; - function CompareField(ObjectContent: IBoldObjectContents; Field: IBoldField; ColumnIndex: integer; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList): Boolean; override; + function CompareField(const ObjectContent: IBoldObjectContents; const Field: IBoldField; ColumnIndex: integer;const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList): Boolean; override; function FindDefiningTable(LocalMoldClass: TMoldClass; MoldMember: TMoldMember): string; override; public constructor CreateFromMold(moldMember: TMoldMember; moldClass: TMoldClass; Owner: TBoldObjectPersistenceMapper; const MemberIndex: Integer; TypeNameDictionary: TBoldTypeNameDictionary); override; - function IsDirty(ObjectContents: IBoldObjectContents): Boolean; override; - function ShouldFetch(ObjectContents: IBoldObjectContents): Boolean; override; - procedure ValueToParam(ObjectContent: IBoldObjectContents; Param: IBoldParameter; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList); override; - procedure ValueFromField(OwningObjectId: TBoldObjectId; ObjectContent: IBoldObjectContents; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; Field: IBoldField; ColumnIndex: Integer); override; + function IsDirty(const ObjectContents: IBoldObjectContents): Boolean; override; + function ShouldFetch(const ObjectContents: IBoldObjectContents): Boolean; override; + procedure ValueToParam(const ObjectContent: IBoldObjectContents; const Param: IBoldParameter; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList); override; + procedure ValueFromField(OwningObjectId: TBoldObjectId; const ObjectContent: IBoldObjectContents; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; const Field: IBoldField; ColumnIndex: Integer); override; + function ValueAsVariant(const ObjectContent: IBoldObjectContents; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList): variant; override; end; + TExternalIdGenerator = function: string; EBoldOptimisticLockingFailed = class(EBoldOperationFailedForIdList) @@ -266,6 +323,9 @@ EBoldOptimisticLockingFailed = class(EBoldOperationFailedForIdList) var ExternalIDGenerator: TExternalIdGenerator; + NewTimeStampEvent: TGetNewTimeStampEvent; + IDIncrementEvent: TIDIncrementEvent; + CompatibilityMode: boolean; implementation @@ -289,23 +349,208 @@ implementation BoldSqlQueryGenerator, BoldGUIDUtils, BoldGuard, + {$IFDEF RIL} + {$IFNDEF BOLD_UNICODE} + StringBuilder, + {$ENDIF} + {$ENDIF} BoldDefaultStreamNames, - BoldPMConsts; + BoldPMConsts, + BoldOCL, + BoldOclLightWeightNodeMaker, + BoldOCLClasses, + BoldSystem, + BoldSystemRT, + BoldContainers, + BoldIndex, + BoldIndexableList; const TIMESTAMPMEMBERINDEX = -2; {--Supporting functions/procedures---} +function TBoldSystemDefaultMapper.GetPSSystemDescription: TBoldDefaultSystemDescription; +begin + result := (inherited PSSystemDescription) as TBoldDefaultSystemDescription; +end; + +function TBoldObjectDefaultMapper.GetSystemPersistenceMapper: TBoldSystemDefaultMapper; +begin + result := (inherited SystemPersistenceMapper) as TBoldSystemDefaultMapper; +end; + +function TBoldSystemDefaultMapper.GetRootClassObjectPersistenceMapper: TBoldObjectDefaultMapper; +begin + result := (inherited RootClassObjectPersistenceMapper) as TBoldObjectDefaultMapper; +end; + +function TBoldMemberDefaultMapper.GetSystemPersistenceMapper: TBoldSystemDefaultMapper; +begin + result := inherited SystemPersistenceMapper as TBoldSystemDefaultMapper; +end; + +function TBoldMemberDefaultMapper.GetObjectPersistenceMapper: TBoldObjectDefaultMapper; +begin + result := (inherited ObjectPersistenceMapper) as TBoldObjectDefaultMapper; +end; + { TBoldSystemDefaultMapper } -constructor TBoldSystemDefaultMapper.CreateFromMold(moldModel: TMoldModel; TypeNameDictionary: TBoldTypeNameDictionary; SQlDatabaseConfig: TBoldSQLDatabaseConfig; GetDatabaseFunc: TBoldGetDatabaseEvent); + +function TBoldSystemDefaultMapper.CanEvaluateInPS(sOCL: string; + aSystem: TBoldElement; aContext: TBoldElementTypeInfo; + const aVariableList: TBoldExternalVariableList): Boolean; +var + i: Integer; + aResultEntry: TBoldOclEntry; + aEnv: TBoldOclEnvironment; + aOLWNodeMaker: TBoldOLWNodeMaker; + aOCLCondition: TBoldOCLCondition; + aSQLNodeResolver: TBoldSqlNodeResolver; + aSQLNodeMaker: TBoldSQLNodeMaker; + aBoldSystem: TBoldSystem; + aBoldOCL: TBoldOCL; + aResultType: TBoldElementTypeInfo; + aClassTypeInfo: TBoldClassTypeInfo; + aGlobalNameSpace: TBoldSqlNameSpace; + aSQlGenerator: TBoldSQLQueryGenerator; + aVariableIDLists: TBoldObjectArray; + + procedure FixQueriesForEnv(VarBinding: TBoldSQLVariableBinding; Context: TBoldObjectIdList; NameSpace: TBoldSqlNameSpace); + var + MainTableRef: TBoldSqlTableReference; + BoldID: TBoldDefaultID; + begin + if CompareText(VarBinding.VariableName, 'SELF') = 0 then // do not localize + begin + VarBinding.NewQuery(NameSpace); + + MainTableRef := VarBinding.TableReferenceForTable(VarBinding.ObjectMapper.MainTable, VarBinding.Query, true); + VarBinding.Context := aOclCondition.Context; + VarBinding.Query.AddWCF(TBoldSQLWCFBinaryInfix.CreateWCFForIdList(MainTableRef.GetColumnReference(IDCOLUMN_NAME), aOclCondition.Context)); + end else if VarBinding.IsExternal and (VarBinding.TopSortedIndex > -1) then + begin + VarBinding.NewQuery(NameSpace); + + MainTableRef := VarBinding.TableReferenceForTable(VarBinding.ObjectMapper.MainTable, VarBinding.Query, true); + VarBinding.Context := TBoldObjectIdList.Create; + aVariableIDLists.Add(VarBinding.Context); + BoldID := TBoldDefaultID.CreateWithClassID(VarBinding.ObjectMapper.TopSortedIndex, True); + BoldID.AsInteger := VarBinding.ExternalVarvalue; + VarBinding.Context.Add(BoldID); + VarBinding.Query.AddWCF(TBoldSQLWCFBinaryInfix.CreateWCFForIdList(MainTableRef.GetColumnReference(IDCOLUMN_NAME), VarBinding.Context)); + end; + end; + +begin + Result := False; + // Let all objects point to nil, so there are no problems on free + aResultEntry := nil; + aEnv := nil; + aOLWNodeMaker := nil; + aOCLCondition := nil; + aSQlNodeResolver := nil; + aSQLNodeMaker := nil; + aSQLGenerator := nil; + aGlobalNameSpace := nil; + + // On empty OCL a PS evaluation is unnecessary (objects are loaded already). + // System parameter must be type of TBoldSystem (see TBoldPersistenceController). + // Also OCL evaluator must be type of TBoldOCL, otherwise validation is not possible. + if (sOCL = '') or not ((aSystem is TBoldSystem) and + (TBoldSystem(aSystem).Evaluator is TBoldOCL)) then + begin + Exit; + end; + + // Validation does not work with collection as context, though evaluation + // would be possible. Therefore always use ListElementTypeInfo. + if Assigned(aContext) and (aContext is TBoldListTypeInfo) then begin + aContext := TBoldListTypeInfo(aContext).ListElementTypeInfo; + end; + + aBoldSystem := TBoldSystem(aSystem); + aBoldOCL := TBoldOcl(aBoldSystem.Evaluator); + aVariableIDLists := TBoldObjectArray.Create(0, [bcoDataOwner]); + Result := True; + try + try + aEnv := TBoldOclEnvironment.Create(aBoldOCL.GlobalEnv); + // OCL semantic check + aResultEntry := aBoldOCL.SemanticCheck(sOCL, aContext, aVariableList, true, aEnv); + aOLWNodeMaker := TBoldOLWNodeMaker.Create(aResultEntry.Ocl, aBoldSystem.BoldSystemTypeInfo, aBoldSystem, aEnv); + aResultEntry.Ocl.AcceptVisitor(aOLWNodeMaker); + // Can OCL be evaluated in PS in general? + if not aOLWNodeMaker.Failed then begin + aOCLCondition := TBoldOclCondition.Create; + aOCLCondition.OclExpr := sOCL; + + for i := 0 to aOLWNodeMaker.ExternalVarBindings.Count - 1 do + aOCLCondition.Env.Add(TBoldOLWVariableBinding(aOLWNodeMaker.ExternalVarBindings[i])); + aOLWNodeMaker.ExternalVarBindings.Clear; + + aOCLCondition.RootNode := aOLWNodeMaker.RootNode; + + aResultType := aResultEntry.Ocl.BoldType; + if aResultType is TBoldListTypeInfo then begin + aClassTypeInfo := TBoldListTypeInfo(aResultType).ListElementTypeInfo as TBoldClassTypeInfo; + end else begin + aClassTypeInfo := aResultType as TBoldClassTypeInfo; + end; + aOCLCondition.TopSortedIndex := aClassTypeInfo.TopSortedIndex; + + // Can all parts of OCLs be translated to SQL symbols? + aSQLNodeMaker := TBoldSQLNodeMaker.Create(aOCLCondition); + aSQLNodeMaker.Execute; + + aSQLNodeResolver := TBoldSqlNodeResolver.Create(Self, aSQLNodeMaker.RootNode, aSQLNodeMaker.SQLVarBindings); + aSQLNodeResolver.Execute; + // Finally the real check, which checks every symbol (AcceptVisitor). + aGlobalNameSpace := TBoldSqlnameSpace.Create; + + aSQlGenerator := TBoldSqlQueryGenerator.Create(aGlobalNameSpace); + for i := 0 to aSQLNodeMaker.SQLVarBindings.Count - 1 do begin + aSQLNodeMaker.SQLVarBindings[i].AcceptVisitor(aSQlGenerator); + FixQueriesForEnv(aSQLNodeMaker.SQLVarBindings[i] as TBoldSqlVariableBinding, aOclCondition.Context, aGlobalNameSpace); + end; + + aSQLNodeMaker.RootNode.AcceptVisitor(aSQlGenerator); + end else begin + Result := False; + end; + except + Result := False; + end; + finally + if Assigned(aResultEntry) then begin + if aResultEntry.OwnedByDictionary then begin + aResultEntry.UsedByOtherEvaluation := false + end else begin + aResultEntry.Free; + end; + end; + aEnv.Free; + aOLWNodeMaker.Free; + aOCLCondition.Free; + aSQLGenerator.Free; + aSQlNodeResolver.Free; + aGlobalNameSpace.Free; + aSQLNodeMaker.Free; + aVariableIDLists.Free; + end; +end; + +constructor TBoldSystemDefaultMapper.CreateFromMold(moldModel: TMoldModel; TypeNameDictionary: TBoldTypeNameDictionary; + CustomIndexes: TBoldIndexCollection; SQlDatabaseConfig: TBoldSQLDatabaseConfig; GetDatabaseFunc: TBoldGetDatabaseEvent); begin inherited; NextDBID := -1; LastReservedDBID := -2; ReservedCount := 0; + fCustomIndexes := CustomIndexes; end; + procedure TBoldSystemDefaultMapper.ReserveID; begin Inc(fReservedCount); @@ -355,15 +600,15 @@ function TBoldSystemDefaultMapper.EnsureTable(const TableName: string; TableVers if TableVersioned then begin AddColumn(TIMESTAMPSTARTCOLUMNNAME, SQLDataBaseConfig.ColumnTypeForInteger, SQLDataBaseConfig.EffectiveSQLforNotNull, BOLDTIMESTAMPFIELDTYPE, 0, false, SQLDataBaseConfig.CorrectlyQuotedDefaultValue('0')); - EnsureIndex(IDCOLUMN_NAME + ';' + TIMESTAMPSTARTCOLUMNNAME, True, True); + EnsureIndex(IDCOLUMN_NAME + ';' + TIMESTAMPSTARTCOLUMNNAME, True, True, False); // the following two indices improves performance alot in Interbase, and seems to have no negative impact in SQLServer. - EnsureIndex(TIMESTAMPSTARTCOLUMNNAME, false, false); - EnsureIndex(IDCOLUMN_NAME, false, false); + EnsureIndex(TIMESTAMPSTARTCOLUMNNAME, false, false, false); + EnsureIndex(IDCOLUMN_NAME, false, false, false); end else - EnsureIndex(IDCOLUMN_NAME, True, True); + EnsureIndex(IDCOLUMN_NAME, True, True, false); - EnsureIndex(TYPECOLUMN_NAME, False, False); + EnsureIndex(TYPECOLUMN_NAME, False, False, false); end; Result := Result; end; @@ -392,62 +637,77 @@ function TBoldSystemDefaultMapper.EnsureColumn(const TableName, ColumnName, SQLT end; end; -procedure TBoldSystemDefaultMapper.EnsureIndex(const TableName, Fields: string; const PrimaryIndex, Unique, InVersionedTable: Boolean); +procedure TBoldSystemDefaultMapper.EnsureIndex(const TableName, Fields: string; + const PrimaryIndex, Unique, NonClustered, InVersionedTable: Boolean); var Table: TBoldSQLTableDescription; begin EnsureTable(TableName, InVersionedTable); Table := PSSystemDescription.SQLTablesList.ItemsBySQLName[TableName]; - Table.EnsureIndex(Fields, PrimaryIndex, Unique); + Table.EnsureIndex(Fields, PrimaryIndex, Unique, NonClustered); end; -function TBoldSystemDefaultMapper.NewIdFromQuery(aQuery: IBoldQuery; BoldDbTypeColumn, ObjectIdColumn: integer; Timestamp: TBoldTimeStampType): TBoldObjectId; +function TBoldSystemDefaultMapper.NewIdFromQuery(const aQuery: IBoldQuery; ClassId, BoldDbTypeColumn, ObjectIdColumn: integer; Timestamp: TBoldTimeStampType): TBoldObjectId; var ObjectId: TBoldDefaultId; TopSortedIndex: integer; begin if BoldDbTypeColumn = -1 then - TopSortedIndex := NO_CLASS + TopSortedIndex := ClassId else TopSortedIndex := topSortedIndexForBoldDbType(aQuery.Fields[BoldDbTypeColumn].AsInteger); if TimeStamp <> BoldMaxTimeStamp then - ObjectId := TBoldTimestampedDefaultId.createWithTimeAndClassId(TimeStamp, TopSortedIndex, true) + ObjectId := TBoldTimestampedDefaultId.createWithTimeAndClassId(TimeStamp, TopSortedIndex, BoldDbTypeColumn <> -1) else - ObjectId := TBoldDefaultId.CreateWithClassId(TopSortedIndex, true); + ObjectId := TBoldDefaultId.CreateWithClassId(TopSortedIndex, BoldDbTypeColumn <> -1); ObjectId.AsInteger := aQuery.Fields[ObjectIdColumn].AsInteger; result := ObjectId; end; -function TBoldSystemDefaultMapper.GetListUsingQuery(ObjectIDList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; aQuery: IBoldQuery; FetchMode: Integer; TranslationList: TBoldIdTranslationList; TimeStamp: TBoldTimeStampType; MaxAnswers: integer = -1; Offset: integer = -1): integer; +function TBoldSystemDefaultMapper.GetListUsingQuery(ObjectIDList: TBoldObjectIdList; const ValueSpace: IBoldValueSpace; const aQuery: IBoldQuery; ClassId, BoldDbTypeColumn, ObjectIdColumn: integer; FetchMode: Integer; TranslationList: TBoldIdTranslationList; TimeStamp: TBoldTimeStampType; MaxAnswers: integer = -1; Offset: integer = -1): integer; var ObjectId: TBoldObjectId; Counter: integer; + RecordsToProcess: integer; begin + Result := 0; aQuery.Open; if offset <> -1 then - aQuery.MoveBy(Offset); - // when MaxAnswer = -1 the while-test will never occur and we will get all the answers + begin + RecordsToProcess := aQuery.RecordCount - Offset {- aQuery.RecNo}; + if Offset <> 0 then + aQuery.MoveBy(Offset); + end + else + RecordsToProcess := aQuery.RecordCount {- aQuery.RecNo}; +// when MaxAnswer = -1 the while-test will never occur and we will get all the answers Counter := MaxAnswers; + + if (MaxAnswers <> -1) and (MaxAnswers < RecordsToProcess) then + RecordsToProcess := MaxAnswers; + ObjectIDList.Capacity := ObjectIDList.Count + RecordsToProcess; + TranslationList.Capacity := TranslationList.Count + RecordsToProcess; + while not aQuery.EOF and (Counter <> 0) do begin if TimeStamp = BOLDINVALIDTIMESTAMP then - ObjectId := NewIdFromQuery(aQuery, 1, 0, aQuery.FieldByName(TIMESTAMPSTARTCOLUMNNAME).AsInteger) + ObjectId := NewIdFromQuery(aQuery, ClassId, BoldDbTypeColumn, ObjectIdColumn, aQuery.FieldByUpperCaseName(TIMESTAMPSTARTCOLUMNNAMEUPPER).AsInteger) else - ObjectId := NewIdFromQuery(aQuery, 1, 0, TimeStamp); + ObjectId := NewIdFromQuery(aQuery, ClassId, BoldDbTypeColumn, ObjectIdColumn, TimeStamp); ValueSpace.EnsureObjectId(TranslationList.TranslateToNewId[ObjectId]); ObjectIDList.Add(ObjectId); - TranslationList.AddTranslation(nil, ObjectId); + INC(Result); + TranslationList.AddTranslationAdoptNew(nil, ObjectId); SendExtendedEvent(bpeFetchId, [ObjectId]); - ObjectId.Free; aQuery.Next; dec(Counter); end; - if (MaxAnswers < 0) or (Counter > 0) then +{ if (MaxAnswers < 0) or (Counter > 0) then result := MaxAnswers - Counter else - result := aQuery.RecordCount; + result := aQuery.RecordCount;} end; function TBoldSystemDefaultMapper.EnsurePrecondition(Precondition: TBoldUpdatePrecondition; TranslationList: TBoldIdTranslationList): Boolean; @@ -473,10 +733,25 @@ procedure MergeFailures(MasterList, NewList: TBoldObjectIdList); Precondition.AddFailedObject(Newlist[i]); end; +function ContainsMemberId(MemberIdList: TBoldMemberIdList; MemberIndex: integer): boolean; +var + i: integer; +begin + result := false; + for I := 0 to MemberIdList.Count - 1 do + begin + if MemberIdList[i].MemberIndex = MemberIndex then + begin + result := true; + exit; + end; + end; +end; + var OldMemberIdList: TBoldMemberIdList; - SingleObjectList: TBoldObjectIdList; - TimeStampedObjects: TBoldObjectIdList; + SingleClassList: TBoldObjectIdList; + XFileTimeStampedObjects: TBoldObjectIdList; ObjectContents: IBoldObjectContents; Value: IBoldValue; ObjectIdList: TBoldObjectIdList; @@ -484,59 +759,134 @@ procedure MergeFailures(MasterList, NewList: TBoldObjectIdList); ObjectMapper: TBoldObjectDefaultmapper; FailureList: TBoldObjectIdList; BoldGuard: IBoldGuard; + TopSortedIndex: integer; + MemberCount: integer; + FetchBlockSize: integer; begin - BoldGuard := TBoldGuard.Create(TimeStampedObjects, ObjectIdList, FailureList, - SingleObjectlist, OldMemberIdList); + BoldGuard := TBoldGuard.Create(XFileTimeStampedObjects, ObjectIdList, FailureList, + SingleClassList, OldMemberIdList); OldMemberIdList := TBoldMemberIdList.Create; - SingleObjectList := TBoldObjectIdList.Create; - TimeStampedObjects := TBoldObjectIdList.Create; + SingleClassList := TBoldObjectIdList.Create; + XFileTimeStampedObjects := TBoldObjectIdList.Create; ObjectIdList := TBoldObjectIdList.Create; FailureList := TBoldObjectIdList.Create; + FetchBlockSize := SQLDataBaseConfig.FetchBlockSize; Precondition.valueSpace.AllObjectIds(ObjectidList, true); - for i := 0 to ObjectIdList.Count - 1 do + + for i := ObjectIdList.Count - 1 downto 0 do begin ObjectContents := Precondition.ValueSpace.ObjectContentsByObjectId[ObjectIdList[i]]; - if assigned(ObjectContents) then - begin - OldMemberIdList.Clear; - - if ObjectContents.TimeStamp <> -1 then - TimeStampedObjects.Add(ObjectIdList[i]); + // remove objects with no ObjectContents + if not assigned(ObjectContents) then + ObjectIdList.RemoveByIndex(i); + end; - for MemberIx := 0 to ObjectContents.MemberCount - 1 do + while ObjectIdList.count > 0 do + begin + TopSortedIndex := ObjectIdList[ObjectIdList.count-1].TopSortedIndex; + SingleClassList.Clear; + SingleClassList.Add(ObjectIdList[ObjectIdList.count-1]); + ObjectIdList.RemoveByIndex(ObjectIdList.count-1); + for I := ObjectIdList.Count - 1 downto 0 do + begin + // collect objects of same class in SingleClassList + if TopSortedIndex = ObjectIdList[i].TopSortedIndex then begin - Value := ObjectContents.ValueByIndex[MemberIx]; - if assigned(Value) then - OldMemberIdList.Add(TBoldmemberId.Create(MemberIx)); + SingleClassList.Add(ObjectIdList[i]); + ObjectIdList.RemoveByIndex(i); + if SingleClassList.count = FetchBlockSize then + break; end; + end; + OldMemberIdList.Clear; - // we must compare the object even if it has no dirty members - // since it might be a delete and the object in the db might - // be deleted already. if it is timestamped however, we will - // detect it more cheap that way - if (OldMemberIdList.Count > 0) or (ObjectContents.TimeStamp = -1) then + // process one object + ObjectContents := Precondition.ValueSpace.ObjectContentsByObjectId[SingleClassList[SingleClassList.count-1]]; + if ObjectContents.TimeStamp <> -1 then + if UseXFiles then + XFileTimeStampedObjects.AddIfNotInList(SingleClassList[SingleClassList.count-1]) + else + OldMemberIdList.Add(TBoldMemberId.Create(TIMESTAMPMEMBERINDEX)); + + for MemberIx := 0 to ObjectContents.MemberCount - 1 do + begin + Value := ObjectContents.ValueByIndex[MemberIx]; + if assigned(Value) then begin - SingleObjectList.Clear; - SingleObjectList.Add(ObjectIdList[i]); - failureList.Clear; - ObjectMapper := ObjectPersistenceMappers[ObjectIdList[i].TopSortedIndex] as TBoldObjectDefaultMapper; - Objectmapper.PMCompareExactIDList(SingleObjectList, Precondition.ValueSpace, OldMemberIdList, translationList, FailureList); - MergeFailures(precondition.FailureList, FailureList); + OldMemberIdList.Add(TBoldMemberId.Create(MemberIx)); end; end; + // loop and compare other objects, if they need exact same members as first object + // then keep them in SingleClassList and fetch them together + // otherwise return the object to ObjectIdList to be processed in the next pass + for i := SingleClassList.count - 2 downto 0 do // -2 is on purpose to skip the object we processed above + begin + ObjectContents := Precondition.ValueSpace.ObjectContentsByObjectId[SingleClassList[i]]; + MemberCount := 0; + begin + if ObjectContents.TimeStamp <> -1 then + begin + if UseXFiles then + XFileTimeStampedObjects.AddIfNotInList(SingleClassList[i]) + else + begin + if not ContainsMemberId(OldMemberIdList, TIMESTAMPMEMBERINDEX) then + begin // put the object back in the ObjectIdList + ObjectIdList.Add(SingleClassList[i]); + SingleClassList.RemoveByIndex(i); + continue; + end + else + Inc(MemberCount); + end; + end; + for MemberIx := 0 to ObjectContents.MemberCount - 1 do + begin + Value := ObjectContents.ValueByIndex[MemberIx]; + if assigned(Value) then + begin + if not ContainsMemberId(OldMemberIdList, MemberIx) then + begin // set MemberCount to number we're sure won't match so it will be removed + MemberCount := MaxInt; + break; + end + else + Inc(MemberCount); + end; + end; + // now also make sure the OldMemberIdList doesn't contain more members + if MemberCount <> OldMemberIdList.Count then + begin // put the object back in the ObjectIdList + ObjectIdList.Add(SingleClassList[i]); + SingleClassList.RemoveByIndex(i); + end + end + end; + + // we must compare the object even if it has no dirty members + // since it might be a delete and the object in the db might + // be deleted already. if it is timestamped however, we will + // detect it more cheap that way + if (OldMemberIdList.Count > 0) or (ObjectContents.TimeStamp = -1) then + begin + failureList.Clear; + ObjectMapper := ObjectPersistenceMappers[TopSortedIndex] as TBoldObjectDefaultMapper; + Objectmapper.PMCompareExactIDList(SingleClassList, Precondition.ValueSpace, OldMemberIdList, translationList, FailureList); + MergeFailures(precondition.FailureList, FailureList); + end; end; - if TimeStampedObjects.Count > 0 then + if XFileTimeStampedObjects.Count > 0 then begin OldMemberIdList.clear; FailureList.Clear; OldMemberIdList.Add(TBoldMemberId.Create(TIMESTAMPMEMBERINDEX)); - RootClassObjectPersistenceMapper.PMCompareExactIDList(TimeStampedObjects, Precondition.ValueSpace, OldMemberIdList, translationlist, FailureList); + RootClassObjectPersistenceMapper.PMCompareExactIDList(XFileTimeStampedObjects, Precondition.ValueSpace, OldMemberIdList, translationlist, FailureList); if FailureList.Count > 0 then begin - BoldLog.Log(sOptimisticLockingFailedOnTimeStamp); + BoldLog.Log('Optimistic Locking failed on timestamp for the following Objects'); for i := 0 to FailureList.Count - 1 do - BoldLog.LogFmt(sOptimisticLockFailedLog, + BoldLog.LogFmt('%s: Id %s', [ ObjectPersistenceMappers[FailureList[i].TopSortedIndex].ExpressionName, FailureList[i].AsString @@ -611,31 +961,9 @@ procedure TBoldObjectDefaultMapper.GenerateMappingInfo(ExpressionName: String; M end; constructor TBoldObjectDefaultMapper.CreateFromMold(moldClass: TMoldClass; Owner: TBoldSystemPersistenceMapper; TypeNameDictionary: TBoldTypeNameDictionary); -var - i: integer; begin inherited; fOptimisticLockingMode := MoldClass.EffectiveOptimisticLocking; - if SystemPersistenceMapper.UseModelVersion then - begin - fModelVersionMember := TBoldModelVersionMember.CreateFromMold(nil, MoldClass, self, -1, TypeNameDictionary); - MemberPersistenceMappers.Add(fModelVersionMember); - end; - if SystemPersistenceMapper.UseReadOnly then - MemberPersistenceMappers.Add(TBoldReadOnlynessMember.CreateFromMold(nil, MoldClass, self, -1, TypeNameDictionary)); - - - if SystemPersistenceMapper.UseXFiles then - begin - if SystemPersistenceMapper.UseTimestamp then - MemberPersistenceMappers.Add(TBoldTimeStampMember.CreateFromMold(nil, MoldClass, self, -1, TypeNameDictionary)); - if SystemPersistenceMapper.UseGlobalId then - MemberPersistenceMappers.Add(TBoldGlobalIdMember.CreateFromMold(nil, MoldClass, self, -1, TypeNameDictionary)); - end; - - fObjectIdClass := BOLDDEFAULTIDNAME; - for i := 0 to MoldClass.AllPossibleNames.Count - 1 do - GenerateMappingInfo(MoldClass.AllPossibleNames[i], MoldClass); end; type @@ -644,44 +972,41 @@ TLittleClass = class dbType: TBoldDbType; end; - - -procedure TBoldObjectDefaultMapper.InternalMakeIDsExact(ObjectIDList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList); +procedure TBoldObjectDefaultMapper.InternalMakeIDsExact(ObjectIDList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList; EnsureAll: Boolean; HandleNonExisting: Boolean); var i: integer; ObjectMapper: TBoldObjectDefaultMapper; begin if assigned(MainTable) then - MakeIDsExactUsingTable(ObjectIDList, TranslationList, MainTable) + MakeIDsExactUsingTable(ObjectIDList, TranslationList, MainTable, not SystemPersistenceMapper.UseXFiles, HandleNonExisting) else begin for i := 0 to SystemPersistenceMapper.ObjectPersistenceMappers.Count-1 do begin ObjectMapper := SystemPersistenceMapper.ObjectPersistenceMappers[i] as TBoldObjectDefaultMapper; if assigned(ObjectMapper) and (ObjectMapper.SuperClass = self) then - ObjectMapper.InternalMakeIDsExact(objectidlist, TranslationList); + ObjectMapper.InternalMakeIDsExact(objectidlist, TranslationList, not SystemPersistenceMapper.UseXFiles, HandleNonExisting); end; end; end; - -procedure TBoldObjectDefaultMapper.MakeIDsExact(ObjectIDList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList); +procedure TBoldObjectDefaultMapper.MakeIDsExact(ObjectIDList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList; HandleNonExisting: Boolean); var i: Integer; MissingIds: TBoldObjectIdList; begin if ObjectIDList.Count = 0 then exit; - InternalMakeIDsExact(ObjectIDList, TranslationList); MissingIds := TBoldObjectIdList.Create; try + MakeIDsExactUsingTable(ObjectIDList, TranslationList, MainTable, not SystemPersistenceMapper.UseXFiles, HandleNonExisting); if SystemPersistenceMapper.UseXFiles then begin for i := 0 to ObjectIDList.Count-1 do if TranslationList.TranslateToNewId[ObjectIdList[i]] = ObjectIdList[i] then MissingIds.Add(ObjectIdList[i]); if MissingIds.Count > 0 then - MakeIDsExactUsingTable(MissingIds, TranslationList, SystemPersistenceMapper.PSSystemDescription.XFilestable); + MakeIDsExactUsingTable(MissingIds, TranslationList, SystemPersistenceMapper.PSSystemDescription.XFilestable, true, HandleNonExisting); end; finally MissingIds.Free; @@ -690,34 +1015,64 @@ procedure TBoldObjectDefaultMapper.MakeIDsExact(ObjectIDList: TBoldObjectIdList; procedure TBoldObjectDefaultMapper.SQLForID(Table: TBoldSQLTableDescription; SQL: TStrings; useAlias: Boolean); begin - SQL.Append(Format('%s.%s', [Tablealias(Table, useAlias), IDCOLUMN_NAME])); // do not localize + SQL.Append(Format('%s.%s', [Tablealias(Table, useAlias), IDCOLUMN_NAME])) end; procedure TBoldObjectDefaultMapper.SQLForKey(Table: TBoldSQLTableDescription; SQL: TStrings; const SQLStyle: TBoldSQLStyle; useAlias: Boolean); var - tableQualifier, ColumnString: string; + tableQualifier, + ColumnString: string; begin tableQualifier := ''; if (Table = MainTable) and useAlias then tableQualifier := TableAlias(Table, useALias) + '.'; case SQLStyle of - ssColumns: ColumnString := tableQualifier + '%s'; - ssParameters: ColumnString := ':' + tableQualifier + '%s'; + ssColumns : ColumnString := tableQualifier; + ssParameters: ColumnString := ':' + tableQualifier; end; - SQL.Append(Format(ColumnString, [Table.ColumnsList[0].SQLName])); - SQL.Append(Format(ColumnString, [Table.ColumnsList[1].SQLName])); + SQL.Append(ColumnString+Table.ColumnsList[0].SQLName); + SQL.Append(ColumnString+Table.ColumnsList[1].SQLName); end; procedure TBoldObjectDefaultMapper.JoinSQLTableByKey(SQL: TStringList; MainTable, JoinTable: TBoldSQLTableDescription); -const - SQLEQUALITY = '%s.%s = %s.%s'; +{$IFDEF RIL} +var + SB: TStringBuilder; begin - SQL.Append(Format(SQLEQUALITY, [TableAlias(JoinTable, True), IDCOLUMN_NAME, TableAlias(MainTable, True), IDCOLUMN_NAME])); + SB := TStringBuilder.Create(); + //SQL.Append(Format('%s.%s = %s.%s', [TableAlias(JoinTable, True), IDCOLUMN_NAME, TableAlias(MainTable, True), IDCOLUMN_NAME])); + SB.Append(TableAlias(JoinTable, True)); + SB.Append('.'); + SB.Append(IDCOLUMN_NAME); + SB.Append(' = '); + SB.Append(TableAlias(MainTable, True)); + SB.Append('.'); + SB.Append(IDCOLUMN_NAME); + SQL.Append(SB.Tostring); if Versioned then - SQL.Append(Format(SQLEQUALITY, [TableAlias(JoinTable, True), TIMESTAMPSTARTCOLUMNNAME, TableAlias(MainTable, True), TIMESTAMPSTARTCOLUMNNAME])); + begin + // SQL.Append(Format('%s.%s = %s.%s', [TableAlias(JoinTable, True), TIMESTAMPSTARTCOLUMNNAME, TableAlias(MainTable, True), TIMESTAMPSTARTCOLUMNNAME])); + SB.Clear; + SB.Append(TableAlias(JoinTable, True)); + SB.Append('.'); + SB.Append(TIMESTAMPSTARTCOLUMNNAME); + SB.Append(' = '); + SB.Append(TableAlias(MainTable, True)); + SB.Append('.'); + SB.Append(TIMESTAMPSTARTCOLUMNNAME); + SQL.Append(SB.Tostring); + end; + FreeAndNil(SB); end; +{$ELSE} +begin + SQL.Append(Format('%s.%s = %s.%s', [TableAlias(JoinTable, True), IDCOLUMN_NAME, TableAlias(MainTable, True), IDCOLUMN_NAME])); + if Versioned then + SQL.Append(Format('%s.%s = %s.%s', [TableAlias(JoinTable, True), TIMESTAMPSTARTCOLUMNNAME, TableAlias(MainTable, True), TIMESTAMPSTARTCOLUMNNAME])); +end; +{$ENDIF} procedure TBoldObjectDefaultMapper.PMUpdateStopTime(ObjectIDList: TBoldObjectIdList); var @@ -731,7 +1086,7 @@ procedure TBoldObjectDefaultMapper.PMUpdateStopTime(ObjectIDList: TBoldObjectIdL for i := 0 to ObjectIdList.Count - 1 do IdStringList.Add(ObjectIdList[i].AsString); - UpdateQuery.AssignSQLText(format('UPDATE %s SET %s = %d WHERE %s in (%s) AND (%s = %d)', // do not localize + UpdateQuery.AssignSQLText(format('UPDATE %s SET %s = %d WHERE %s in (%s) AND (%s = %d)', [SystemPersistenceMapper.RootClassObjectPersistenceMapper.MainTable.SQLName, TIMESTAMPSTOPCOLUMNNAME, SystemPersistenceMapper.CurrentTimeStamp - 1, @@ -748,27 +1103,55 @@ procedure TBoldObjectDefaultMapper.PMUpdateStopTime(ObjectIDList: TBoldObjectIdL end; end; -procedure TBoldObjectDefaultMapper.PMCreate(ObjectIDList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList); +procedure TBoldObjectDefaultMapper.PMCreate(ObjectIDList: TBoldObjectIdList; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList); + var - I, T, A: Integer; - TickCounter: integer; aQuery: IBoldExecQuery; - sql, TempList: TStringList; + Row: Integer; + SQL: TStringList; + procedure ExecuteQuery; + var + i: integer; + begin + aQuery.Params.EndUpdate; + aQuery.SQLStrings.EndUpdate; +// aQuery.ParamCheck := true; + aQuery.ExecSQL; + aQuery.Params.BeginUpdate; + aQuery.SQLStrings.BeginUpdate; +// aQuery.ParamCheck := false; + aQuery.Params.Clear; + aQuery.AssignSQL(SQL); + Row := 0; + end; +var +{$IFDEF RIL} + SB: TStringBuilder; +{$ENDIF} + I, T, A: Integer; + TickCounter: integer; + TempList: TStringList; MemberPMList: TBoldMemberPersistenceMapperList; MemberPMapper: TBoldMemberDefaultMapper; NewID: TBoldObjectId; DuplicateList: TBoldObjectIdList; + IdColumnParam: IBoldParameter; + TypeColumnParam: IBoldParameter; BoldGuard: IBoldGuard; + FoundInCache: boolean; + StoreInCache: boolean; + UseParams: boolean; + Limit: integer; + ObjectCount: Integer; begin - BoldGuard := TBoldGuard.Create(MemberPMList); - MemberPMList := TBoldMemberPersistenceMapperList.Create; - MemberPMList.OwnsEntries := False; + BoldGuard := TBoldGuard.Create({MemberPMList}{$IFDEF RIL}SB{$ENDIF},TempList); + {$IFDEF RIL} + SB := TStringBuilder.Create; + {$ENDIF} Tickcounter := 0; if IsLinkClass and (not Versioned) then begin - // this will update link-objects rather than create new if they are already in the database - // this happens only if two applications link the same two objects at the same time DuplicateList := TBoldObjectidList.Create; try DetectLinkClassDuplicates(ObjectIdList, ValueSpace, TranslationList, DuplicateList); @@ -784,95 +1167,173 @@ procedure TBoldObjectDefaultMapper.PMCreate(ObjectIDList: TBoldObjectIdList; Val if ObjectIdList.Count = 0 then exit; end; - + Limit := SystemPersistenceMapper.SQLDataBaseConfig.MultiRowInsertLimit; + UseParams := SystemPersistenceMapper.SQLDataBaseConfig.UseParamsForInteger; aQuery := SystemPersistenceMapper.GetExecQuery; - sql := TStringList.Create; + aQuery.ParamCheck := true; + TempList := TStringList.Create; + aQuery.SQLStrings.BeginUpdate; + aQuery.Params.BeginUpdate; + aQuery.Params.clear; + FoundInCache := useParams and (Limit = 1) and (Length(fPMCreateCache) > 0); try for T := 0 to AllTables.Count - 1 do begin - // Clear the memberlist, as we reuse it. - while MemberPMList.Count > 0 do - MemberPMList.RemoveByIndex(0); - // Fill it with members to use. - // FIXME: This will probably not work for members with several tables... /JoHo - for A := 0 to MemberPersistenceMappers.Count - 1 do + StoreInCache := false; + if not FoundInCache then begin - MemberPMapper := MemberPersistenceMappers[A] as TBoldMemberDefaultMapper; - if assigned(MemberPMapper) and - MemberPMapper.IsStoredInObject and not MemberPMapper.CustomCreateUpDate and - ((MemberPMapper.ColumnDescriptions[0] as TBoldSQLColumnDescription).TableDescription = AllTables[T]) then - MemberPMList.Add(MemberPMapper); - end; - - // Create insert query. - sql.Clear; - aQuery.ClearParams; - TempList := TStringList.Create; - SQLForMembers(AllTables[T], TempLIst, MemberPMList, ssColumns, True, False, False); + MemberPMList := TBoldMemberPersistenceMapperList.Create; + MemberPMList.OwnsEntries := False; + aQuery.ClearParams; + for A := 0 to MemberPersistenceMappers.Count - 1 do + begin + MemberPMapper := MemberPersistenceMappers[A] as TBoldMemberDefaultMapper; + if assigned(MemberPMapper) and + MemberPMapper.IsStoredInObject and not MemberPMapper.CustomCreateUpDate and + ((MemberPMapper.ColumnDescriptions[0] as TBoldSQLColumnDescription).TableDescription = AllTables[T]) then + MemberPMList.Add(MemberPMapper); + end; + SQL := TStringList.Create; + TempList.clear; + SQLForMembers(AllTables[T], TempList, MemberPMList, ssColumns, True, False, False); - if Alltables[T].Versioned then - begin - TempList.Add(TIMESTAMPSTARTCOLUMNNAME); - if allTables[T].ContainsStopTimeStamp then - TempList.Add(TIMESTAMPSTOPCOLUMNNAME); - end; + if Alltables[T].Versioned then + begin + TempList.Add(TIMESTAMPSTARTCOLUMNNAME); + if allTables[T].ContainsStopTimeStamp then + TempList.Add(TIMESTAMPSTOPCOLUMNNAME); + end; - BoldAppendToStrings(SQL, Format('INSERT INTO %s (%s) ', [AllTables[T].SQLName, // do not localize - BoldSeparateStringList(TempLIst, ', ', '', '')]), True); + {$IFDEF RIL} + //BoldAppendToStrings(SQL, Format('INSERT INTO %s (%s) ', [AllTables[T].SQLName, BoldSeparateStringList(TempLIst, ', ', '', '')]), True); + SB.Clear; + SB.Append('INSERT INTO '); + SB.Append(AllTables[T].SQLName); + SB.Append(' ('); + SB.Append(BoldSeparateStringList(TempLIst, ', ', '', '')); + SB.Append(') '); + BoldAppendToStrings(SQL, SB.ToString, True); + {$ELSE} + BoldAppendToStrings(SQL, Format('INSERT INTO %s (%s) ', [AllTables[T].SQLName, + BoldSeparateStringList(TempList, ', ', '', '')]), True); + {$ENDIF} + + if UseParams then + begin + TempList.Clear; + SQLForMembers(AllTables[T], TempList, MemberPMList, ssParameters, True, False, False); + end; - TempList.Clear; - SQLForMembers(AllTables[T], TempList, MemberPMList, ssParameters, True, False, False); + if Alltables[T].Versioned then + begin + TempList.Add(':' + TIMESTAMPSTARTCOLUMNNAME); + if allTables[T].ContainsStopTimeStamp then + TempList.Add(':' + TIMESTAMPSTOPCOLUMNNAME); + end; - if Alltables[T].Versioned then + {$IFDEF RIL} + SB.Clear; + SB.Append('VALUES '); + if UseParams then + begin + SB.Append('('); + SB.Append(BoldSeparateStringList(TempLIst, ', ', '', '')); + SB.Append(') '); + end; + BoldAppendToStrings(SQL, SB.ToString, True); + + {$ELSE} + BoldAppendToStrings(SQL, Format('VALUES (%s) ', [BoldSeparateStringList(TempLIst, ', ', '', '')]), True); + {$ENDIF} + // store in cache + StoreInCache := UseParams and (Limit = 1); + if StoreInCache then + begin + i := Length(fPMCreateCache); + SetLength(fPMCreateCache, i+1); + fPMCreateCache[i].SqlStrings := Sql; + fPMCreateCache[i].MemberPMList := MemberPMList; + end; + end + else begin - TempList.Add(':' + TIMESTAMPSTARTCOLUMNNAME); - if allTables[T].ContainsStopTimeStamp then - TempList.Add(':' + TIMESTAMPSTOPCOLUMNNAME); + SQL := fPMCreateCache[T].SqlStrings; + MemberPMList := fPMCreateCache[T].MemberPMList; end; - - BoldAppendToStrings(SQL, Format('VALUES (%s) ', [BoldSeparateStringList(TempLIst, ', ', '', '')]), True); // do not localize - TempLIst.Free; - + aQuery.ClearParams; aQuery.AssignSQL(SQL); - aQuery.StartSQLBatch; - try - for I := 0 to ObjectIDList.Count - 1 do + Row := 0; + SB.Clear; + for I := 0 to ObjectIDList.Count-1 do + begin + NewID := TranslationList.TranslateToNewID[ObjectIDList[I]]; + if UseParams then begin - // All tables have id and type as column 0 and 1 respectively - NewID := TranslationList.TranslateToNewID[ObjectIDList[I]]; - aQuery.ParamByName(IDCOLUMN_NAME).AsInteger := (NewId as TBoldDefaultId).AsInteger; - aQuery.ParamByName(TYPECOLUMN_NAME).AsSmallInt := SystemPersistenceMapper.BoldDbTypeForTopSortedIndex(NewId.topSortedIndex); - - ValuesToParamsByMemberList(ObjectIDList[I], ValueSpace, aQuery, MemberPMList, TranslationList, dsmCreate); - - if Alltables[T].Versioned then + IdColumnParam := aQuery.CreateParam(ftInteger, IDCOLUMN_NAME); + TypeColumnParam := aQuery.CreateParam(ftSmallInt, TYPECOLUMN_NAME); + IdColumnParam.AsInteger := (NewId as TBoldDefaultId).AsInteger; + TypeColumnParam.AsSmallInt := SystemPersistenceMapper.BoldDbTypeForTopSortedIndex(NewId.topSortedIndex) + end + else + begin + SB.Append( Format('(%s,%d', [NewId.AsString, SystemPersistenceMapper.BoldDbTypeForTopSortedIndex(NewId.topSortedIndex)]) ); + end; + TempList.Clear; + ValuesToQueryByMemberList(ObjectIDList[I], ValueSpace, aQuery, TempList, MemberPMList, TranslationList, dsmCreate); + SB.Append(TempList.text); + SB.Replace(#13#10, ''); + if Alltables[T].Versioned then + begin + if versioned then begin - if versioned then - aQuery.ParamByName(TIMESTAMPSTARTCOLUMNNAME).AsInteger := SystemPersistenceMapper.CurrentTimeStamp - else - aQuery.ParamByName(TIMESTAMPSTARTCOLUMNNAME).AsInteger := 0; - - if allTables[T].ContainsStopTimeStamp then - aQuery.ParamByName(TIMESTAMPSTOPCOLUMNNAME).AsInteger := BOLDMAXTIMESTAMP; + aQuery.EnsureParamByName(TIMESTAMPSTARTCOLUMNNAME).AsInteger := SystemPersistenceMapper.CurrentTimeStamp; + SB.Append(',:'+TIMESTAMPSTARTCOLUMNNAME); + end + else + begin + aQuery.EnsureParamByName(TIMESTAMPSTARTCOLUMNNAME).AsInteger := 0; + SB.Append(',:'+TIMESTAMPSTARTCOLUMNNAME); end; - Inc(TickCounter); - if (TickCounter MOD AllTables.Count) = 0 then + if allTables[T].ContainsStopTimeStamp then begin - SystemPersistenceMapper.SendExtendedEvent(bpeCreateObject, [ObjectIdList[i], ValueSpace]); - TickCounter := 0; + aQuery.EnsureParamByName(TIMESTAMPSTOPCOLUMNNAME).AsInteger := BOLDMAXTIMESTAMP; + SB.Append(',:'+TIMESTAMPSTOPCOLUMNNAME); end; - aQuery.ExecSQL; end; - aQuery.EndSQLBatch; - except - aQuery.FailSQLBatch; - raise; + Inc(TickCounter); + if (TickCounter MOD AllTables.Count) = 0 then + begin + SystemPersistenceMapper.SendExtendedEvent(bpeCreateObject, [ObjectIdList[i], ValueSpace]); + TickCounter := 0; + end; + inc(Row); + if UseParams or (i = ObjectIDList.Count-1) or (Row = Limit) or (aQuery.ParamCount + aQuery.BatchQueryParamCount >= SystemPersistenceMapper.SQLDataBaseConfig.MaxBatchQueryParams) then + begin + if not UseParams then + SB.Append(')'); + aQuery.SQLStrings.Add(SB.ToString); + SB.Clear; + ExecuteQuery; + end + else + if not UseParams then + begin + SB.Append('),'); + end; + end; + if not StoreInCache then + begin + MemberPMList.free; + SQl.free; end; end; finally + aQuery.SQLStrings.Clear; + aQuery.SQLStrings.EndUpdate; + aQuery.Params.Clear; + aQuery.Params.EndUpdate; SystemPersistenceMapper.ReleaseExecQuery(aQuery); - sql.Free; end; for A := 0 to MemberPersistenceMappers.Count - 1 do begin @@ -884,7 +1345,7 @@ procedure TBoldObjectDefaultMapper.PMCreate(ObjectIDList: TBoldObjectIdList; Val end; end; -procedure TBoldObjectDefaultMapper.PMTemporalUpdate(ObjectIdList: TBoldObjectIdList; ValueSpace: IBoldvalueSpace; TranslationList: TBoldIdTranslationList); +procedure TBoldObjectDefaultMapper.PMTemporalUpdate(ObjectIdList: TBoldObjectIdList; const ValueSpace: IBoldvalueSpace; TranslationList: TBoldIdTranslationList); var aQuery: IBoldExecQuery; OldDataQuery: IBoldQuery; @@ -909,10 +1370,8 @@ procedure TBoldObjectDefaultMapper.PMTemporalUpdate(ObjectIdList: TBoldObjectIdL begin if Alltables[T] <> SystemPersistenceMapper.PSSystemDescription.XFilestable then begin - // Clear the memberlist, as we reuse it. MemberPMList.Clear; - // Fill it with members to use. - // FIXME: This will probably not work for members with several tables... /JoHo + for A := 0 to MemberPersistenceMappers.Count - 1 do begin MemberPMapper := MemberPersistenceMappers[A] as TBoldMemberDefaultMapper; @@ -922,8 +1381,6 @@ procedure TBoldObjectDefaultMapper.PMTemporalUpdate(ObjectIdList: TBoldObjectIdL MemberPMList.Add(MemberPMapper); end; - // Create insert query. - SQL.Clear; TempList.Clear; @@ -931,18 +1388,18 @@ procedure TBoldObjectDefaultMapper.PMTemporalUpdate(ObjectIdList: TBoldObjectIdL TempList.Add(ObjectIdLIst[i].AsString); if AllTables[T].ContainsStopTimeStamp then - OldDataQuery.AssignSQLText(format('SELECT * FROM %s WHERE (%s in %s) AND (%s = %d)', [ // do not localize + OldDataQuery.AssignSQLText(format('SELECT * FROM %s WHERE (%s in %s) AND (%s = %d)', [ Alltables[T].SQlname, IDCOLUMN_NAME, BoldSeparateStringlist(TempList, ', ', '(', ')'), TIMESTAMPSTOPCOLUMNNAME, SystemPersistenceMapper.CurrentTimeStamp - 1])) else OldDataQuery.AssignSQLText(format( - 'SELECT DataTable.* FROM %0:s DataTable, %1:s RootTable ' + // do not localize - 'WHERE (DataTable.%2:s in %3:s) AND ' + // do not localize - '(DataTable.%2:s = RootTable.%2:s) AND ' + // do not localize - '(DataTable.%4:s = RootTable.%4:s) AND ' + // do not localize - '(RootTable.%5:s = %6:d)', [ // do not localize + 'SELECT DataTable.* FROM %0:s DataTable, %1:s RootTable '+ + 'WHERE (DataTable.%2:s in %3:s) AND '+ + '(DataTable.%2:s = RootTable.%2:s) AND '+ + '(DataTable.%4:s = RootTable.%4:s) AND '+ + '(RootTable.%5:s = %6:d)', [ Alltables[T].SQlname, SystemPersistenceMapper.RootClassObjectPersistenceMapper.MainTable.SQLName, IDCOLUMN_NAME, @@ -957,7 +1414,7 @@ procedure TBoldObjectDefaultMapper.PMTemporalUpdate(ObjectIdList: TBoldObjectIdL for i := 0 to OldDataQuery.FieldCount - 1 do TempList.Add(OldDataQuery.Fields[i].FieldName); - BoldAppendToStrings(SQL, Format('INSERT INTO %s (%s) ', [AllTables[T].SQLName, // do not localize + BoldAppendToStrings(SQL, Format('INSERT INTO %s (%s) ', [AllTables[T].SQLName, BoldSeparateStringList(TempLIst, ', ', '', '')]), True); TempList.Clear; @@ -972,25 +1429,20 @@ procedure TBoldObjectDefaultMapper.PMTemporalUpdate(ObjectIdList: TBoldObjectIdL TypeColumnIndex := i; end; - BoldAppendToStrings(SQL, Format('VALUES (%s) ', [BoldSeparateStringList(TempLIst, ', ', '', '')]), True); // do not localize + BoldAppendToStrings(SQL, Format('VALUES (%s) ', [BoldSeparateStringList(TempLIst, ', ', '', '')]), True); if (IdColumnIndex = -1) or (TypeColumnIndex = -1) then - raise EBoldInternal.CreateFmt(sTypeAndIDColumnMissing, [classname, aQuery.SQLText]); + raise EBoldInternal.CreateFmt('%s.PMTemporalUpdate: Unable to find either type or ID column in SQL-statement (%s)', [classname, aQuery.SQLText]); aQuery.AssignSQL(SQL); while not OldDataQuery.Eof do begin - NewId := SystemPersistenceMapper.NewIdFromQuery(OldDataQuery, TypeColumnIndex, IdColumnIndex, BOLDMAXTIMESTAMP); + NewId := SystemPersistenceMapper.NewIdFromQuery(OldDataQuery, NO_CLASS, TypeColumnIndex, IdColumnIndex, BOLDMAXTIMESTAMP); try - // copy all old data for i := 0 to OldDataQuery.FieldCount - 1 do aQuery.ParamByName(OldDataQuery.Fields[i].FieldName).AssignFieldValue(OldDataQuery.Fields[i]); - - // fill with known new data. ValuesToParamsByMemberList(NewId, ValueSpace, aQuery, MemberPMList, TranslationList, dsmUpdate); - - // set the timestamps aQuery.ParamByName(TIMESTAMPSTARTCOLUMNNAME).AsInteger := SystemPersistenceMapper.CurrentTimeStamp; if allTables[T].ContainsStopTimeStamp then aQuery.ParamByName(TIMESTAMPSTOPCOLUMNNAME).AsInteger := BOLDMAXTIMESTAMP; @@ -1026,9 +1478,9 @@ procedure TBoldObjectDefaultMapper.PMTemporalUpdate(ObjectIdList: TBoldObjectIdL SystemPersistenceMapper.ReleaseQuery(OldDataQuery); SQL.Free; end; -end; +end; -procedure TBoldObjectDefaultMapper.PMUpdate(ObjectIDList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; Old_Values: IBoldValueSpace; TranslationList: TBoldIdTranslationList); +procedure TBoldObjectDefaultMapper.PMUpdate(ObjectIDList: TBoldObjectIdList; const ValueSpace: IBoldValueSpace; const Old_Values: IBoldValueSpace; TranslationList: TBoldIdTranslationList); var aQuery: IBoldExecQuery; I, T, A: Integer; @@ -1037,9 +1489,10 @@ procedure TBoldObjectDefaultMapper.PMUpdate(ObjectIDList: TBoldObjectIdList; Val MemberPMapper: TBoldMemberDefaultMapper; ObjectContents: IBoldObjectContents; sql: TStringList; + UseParams: boolean; BoldGuard: IBoldGuard; begin - BoldGuard := TBoldGuard.Create(MemberPMList, SQL); + BoldGuard := TBoldGuard.Create(MemberPMList, SQL, TempList); if Versioned then begin PMTemporalUpdate(ObjectIdList, ValueSpace, TranslationList); @@ -1051,66 +1504,72 @@ procedure TBoldObjectDefaultMapper.PMUpdate(ObjectIDList: TBoldObjectIdList; Val if Assigned(Old_Values) then FetchPreviousSingleLinkValues(ObjectIdList, Old_Values); + UseParams := SystemPersistenceMapper.SQLDataBaseConfig.UseParamsForInteger; aQuery := SystemPersistenceMapper.GetExecQuery; + aQuery.ParamCheck := false; + aQuery.SQLStrings.BeginUpdate; sql := TStringList.Create; + TempList := TStringList.Create; try - aQuery.StartSQLBatch; - try - for T := 0 to AllTables.Count - 1 do + for T := 0 to AllTables.Count - 1 do + begin + if UpdatesMembersInTable(AllTables[T]) then begin - if UpdatesMembersInTable(AllTables[T]) then + for I := 0 to ObjectIDList.Count - 1 do begin - for I := 0 to ObjectIDList.Count - 1 do + ObjectContents := ValueSpace.ObjectContentsByObjectId[ObjectIDList[I]]; + MemberPMList.Clear; + for A := 0 to MemberPersistenceMappers.Count - 1 do begin - ObjectContents := ValueSpace.ObjectContentsByObjectId[ObjectIDList[I]]; - - // Clear the memberlist, as we reuse it. - while MemberPMList.Count > 0 do - MemberPMList.RemoveByIndex(0); + MemberPMapper := MemberPersistenceMappers[A] as TBoldMemberDefaultMapper; + if assigned(MemberPMapper) and + MemberPMapper.IsStoredInObject and not MemberPMapper.CustomCreateUpDate and + MemberPMapper.IsDirty(ObjectContents) and + ((MemberPMapper.ColumnDescriptions[0] as TBoldSQLColumnDescription).TableDescription = AllTables[T]) then + MemberPMList.Add(MemberPMapper); + end; - // Fill it with members to use. - for A := 0 to MemberPersistenceMappers.Count - 1 do + if MemberPMLIst.Count > 0 then + begin + SQL.Clear; + BoldAppendToStrings(SQL, Format('UPDATE %s SET ', [AllTables[T].SQLName]), True); + if UseParams then begin - MemberPMapper := MemberPersistenceMappers[A] as TBoldMemberDefaultMapper; - if assigned(MemberPMapper) and - MemberPMapper.IsStoredInObject and not MemberPMapper.CustomCreateUpDate and - MemberPMapper.IsDirty(ObjectContents) and - ((MemberPMapper.ColumnDescriptions[0] as TBoldSQLColumnDescription).TableDescription = AllTables[T]) then - MemberPMList.Add(MemberPMapper); + TempList.Clear; + SQLForMembers(AllTables[T], TempList, MemberPMList, ssValues, False, False, False); + BoldAppendToStrings(SQL, BoldSeparateStringList(TempLIst, ', ', '', ''), True); end; + aQuery.ClearParams; + aQuery.AssignSQL(sql); - if MemberPMLIst.Count > 0 then + TempList.Clear; + ValuesToQueryByMemberList(ObjectIDList[I], ValueSpace, aQuery, TempList, MemberPMList, TranslationList, dsmUpdate); + aQuery.SQLStrings.Add(TempList.Text); + if UseParams then begin - TempList := TStringList.Create; - SQLForMembers(AllTables[T], TempList, MemberPMList, ssValues, False, False, False); - - SQL.Clear; - BoldAppendToStrings(SQL, Format('UPDATE %s', [AllTables[T].SQLName]), True); // do not localize - BoldAppendToStrings(SQL, Format('SET %s', [BoldSeparateStringList(TempLIst, ', ', '', '')]), True); // do not localize - BoldAppendToStrings(SQL, Format('WHERE %s = :%0:s', [IDCOLUMN_NAME]), True); // do not localize - - TempList.Free; - - aQuery.ClearParams; - aQuery.AssignSQL(sql); + aQuery.CreateParam(ftInteger, IDCOLUMN_NAME).AsInteger := (TranslationList.TranslateToNewID[ObjectIDList[I]] as TBoldDefaultId).asInteger; + BoldAppendToStrings(aQuery.SQLStrings, Format(' WHERE %s = :%0:s', [IDCOLUMN_NAME]), True); + end + else + BoldAppendToStrings(aQuery.SQLStrings, Format(' WHERE %s = %s', [IDCOLUMN_NAME, ObjectIDList[I].AsString]), True); - aQuery.ParamByName(IDCOLUMN_NAME).AsInteger := (TranslationList.TranslateToNewID[ObjectIDList[I]] as TBoldDefaultId).asInteger; - ValuesToParamsByMemberList(ObjectIDList[I], ValueSpace, aQuery, MemberPMList, TranslationList, dsmUpdate); - SystemPersistenceMapper.SendExtendedEvent(bpeUpdateObject, [ObjectIDList[I], ValueSpace, aQuery]); - aQuery.ExecSQL; - end; + SystemPersistenceMapper.SendExtendedEvent(bpeUpdateObject, [ObjectIDList[I], ValueSpace, aQuery]); + aQuery.SQLStrings.EndUpdate; + aQuery.ParamCheck := true; + aQuery.ExecSQL; + aQuery.ParamCheck := false; + aQuery.SQLStrings.BeginUpdate; end; end; end; - aQuery.EndSQLBatch; - except - aQuery.FailSQLBatch; - raise; end; finally + aQuery.SQLStrings.Clear; + aQuery.ClearParams; + aQuery.SQLStrings.EndUpdate; SystemPersistenceMapper.ReleaseExecQuery(aQuery); end; - + for A := 0 to MemberPersistenceMappers.Count - 1 do begin with MemberPersistenceMappers[A] do @@ -1121,8 +1580,8 @@ procedure TBoldObjectDefaultMapper.PMUpdate(ObjectIDList: TBoldObjectIdList; Val end; end; -procedure TBoldObjectDefaultMapper.PMDelete(ObjectIDList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; - Old_Values: IBoldValueSpace; TranslationList: TBoldIdTranslationList); +procedure TBoldObjectDefaultMapper.PMDelete(ObjectIDList: TBoldObjectIdList; const ValueSpace: IBoldValueSpace; + const Old_Values: IBoldValueSpace; TranslationList: TBoldIdTranslationList); var I, T: Integer; aQuery: IBoldExecQuery; @@ -1155,6 +1614,8 @@ procedure TBoldObjectDefaultMapper.PMDelete(ObjectIDList: TBoldObjectIdList; Val lst := TStringList.Create; FetchBlockSize := SystemPersistenceMapper.SQLDataBaseConfig.FetchBlockSize; aQuery := SystemPersistenceMapper.GetExecQuery; + aQuery.ParamCheck := false; + aQuery.ClearParams; try ObjectCount := ObjectIDList.Count - 1; for Block := 0 to (ObjectCount div FetchBlockSize) do @@ -1165,14 +1626,10 @@ procedure TBoldObjectDefaultMapper.PMDelete(ObjectIDList: TBoldObjectIdList; Val for i := start to stop do SystemPersistenceMapper.SendExtendedEvent(bpeDeleteObject, [ObjectIDList[I], ValueSpace]); + BoldAppendToStrings(lst, 'DELETE FROM %s ', false); + IdListString := IdListSegmentToWhereFragment(ObjectIdList, start, stop, false, aQuery); - // Construct the delete statement with a placeholder for table-name - BoldAppendToStrings(lst, 'DELETE FROM %s', True); // do not localize - IdListString := IdListSegmentToWhereFragment(ObjectIdList, start, stop, aQuery); - - BoldAppendToStrings(lst, Format('WHERE %%s %s', [IdListString]), True); // do not localize - - //Execute SQLStatement on all tables except the xfiles table + BoldAppendToStrings(lst, Format(' WHERE %%s %s', [IdListString]), false); for T := 0 to AllTables.Count - 1 do begin if AllTables[t] <> SystemPersistenceMapper.PSSystemDescription.XFilestable then @@ -1183,14 +1640,13 @@ procedure TBoldObjectDefaultMapper.PMDelete(ObjectIDList: TBoldObjectIdList; Val begin if AllTables[t].ColumnsList.IndexOf(SystemPersistenceMapper.XFilesTimeStampColumn)<> -1 then begin - aQuery.AssignSQLText(Format('UPDATE %s SET %s = %d WHERE %s %s', // do not localize + aQuery.AssignSQLText(Format('UPDATE %s SET %s = %d WHERE %s %s', [AllTables[T].SQLName, SystemPersistenceMapper.XFilesTimeStampColumn.SQLName, SystemPersistenceMapper.CurrentTimeStamp, IDCOLUMN_NAME, IdListString])); aQuery.ExecSQL; end; end; end; - end; for I := 0 to ObjectIDList.Count - 1 do @@ -1203,13 +1659,47 @@ procedure TBoldObjectDefaultMapper.PMDelete(ObjectIDList: TBoldObjectIdList; Val end; end; -procedure TBoldObjectDefaultMapper.PMMultiPurposeRetrieveExactIdList(ObjectsToFetch: TBoldObjectIdList; ValueSpace: IBoldValueSpace; MemberIdList: TBoldMemberIdList; FetchMode: Integer; TranslationList: TBoldIdTranslationList; MissingList: TBoldObjectIdList; FailureList: TBoldObjectIdList; TimeStamp: TBoldTimeStampType); +procedure LogLateFetch(SQLHits: integer; ExpressionName: String); +begin + BoldPMLogFmt('Fetched %d objects of class %s', [SQLHits, ExpressionName]); + (* + if SQLHits = 1 then + try + raise Exception.CreateFmt('Fetched %d objects of class %s', [SQLHits, ExpressionName]); + except + on E: Exception do + TATErrorManager.LogLastException(E,'Fetch trace', 20); + end; + *) +end; + +function TBoldObjectDefaultMapper.FindInCache(MemberIdList: TBoldMemberIdList; + FetchMode: integer; var MemberPMList, CustomMembers: TBoldMemberPersistenceMapperList; + var ASql: TStringList): boolean; +var + i: integer; +begin + result := false; + for I := Length(fQueryCache) - 1 downto 0 do + if (fQueryCache[i].fetchMode = FetchMode) and + ((not Assigned(MemberIdList) and not Assigned(fQueryCache[i].MemberList)) + or (Assigned(MemberIdList) and (MemberIdList.IsEqual(fQueryCache[i].MemberList)))) then + begin + result := true; + MemberPMList := fQueryCache[i].MemberPMList; + CustomMembers := fQueryCache[i].CustomMembers; + ASQL := fQueryCache[i].SqlStrings; + exit; + end; +end; + +procedure TBoldObjectDefaultMapper.PMMultiPurposeRetrieveExactIdList(ObjectsToFetch: TBoldObjectIdList; const ValueSpace: IBoldValueSpace; MemberIdList: TBoldMemberIdList; FetchMode: Integer; TranslationList: TBoldIdTranslationList; MissingList: TBoldObjectIdList; FailureList: TBoldObjectIdList; TimeStamp: TBoldTimeStampType); var Start, Stop: integer; CustomMembers, MemberPMList: TBoldMemberPersistenceMapperList; aQuery: IBoldQuery; - TempLIst: TStringList; + TempList: TStringList; Block, ObjectCount: Longint; i: Integer; @@ -1219,76 +1709,85 @@ procedure TBoldObjectDefaultMapper.PMMultiPurposeRetrieveExactIdList(ObjectsToFe sql: TStringList; FetchBlockSize: integer; RefetchIdList: TBoldObjectIdList; + Guard: IBoldGuard; + FoundInCache: boolean; begin - MemberPMList := TBoldMemberPersistenceMapperList.Create; - MemberPMList.OwnsEntries := False; - CustomMembers := TBoldMemberPersistenceMapperList.Create; - CustomMembers.OwnsEntries := False; - aQuery := SystemPersistenceMapper.GetQuery; - TempLIst := TStringList.Create; - sql := TStringList.Create; + Guard := TBoldGuard.Create(TempList, RefetchIdList); + FoundInCache := FindInCache(MemberIdList, FetchMode, MemberPMList, CustomMembers, sql); + if not FoundInCache then + begin + sql := TStringList.Create; + MemberPMList := TBoldMemberPersistenceMapperList.Create; + MemberPMList.OwnsEntries := False; + CustomMembers := TBoldMemberPersistenceMapperList.Create; + CustomMembers.OwnsEntries := False; + BuildMemberFetchLists(MemberIdList, MemberPMLIst, CustomMembers, FetchMode); + end; + TempList := TStringList.Create; RefetchIdList := TBoldObjectIdList.Create; FetchBlockSize := SystemPersistenceMapper.SQLDataBaseConfig.FetchBlockSize; - + aQuery := SystemPersistenceMapper.GetQuery; try - BuildMemberFetchLists(MemberIdList, MemberPMLIst, CustomMembers, FetchMode); - try if SystemPersistenceMapper.SupportsObjectUpgrading then SystemPersistenceMapper.ObjectUpgrader.StartTransaction; - // if the memberidlist is empty, then we must fetch the objects to make sure they still exist in the database - // this ensures optimistic locking on deleted objects. - // The below test will skip fetching the object if we are fetching only "custom members" + if (MemberPMList.Count > 0) or not assigned(MemberIdList) or (MemberIdList.Count = 0) then begin +{ if assigned(MissingList) then MissingList.AddList(ObjectsToFetch); - - // We do not want to retrieve more than FetchBlockSize objects at a time - +} ObjectCount := ObjectsToFetch.Count - 1; - for Block := 0 to (ObjectCount div FetchBlockSize) do + if assigned(MissingList) then begin - sql.clear; - RetrieveSelectStatement(SQL, MemberPMList, FetchMode, Versioned); + MissingList.Capacity := ObjectCount+1; + for I := ObjectsToFetch.Count - 1 downto 0 do + MissingList.Add(ObjectsToFetch[i]); + end; + if not FoundInCache then + RetrieveSelectStatement(SQL, MemberPMList, FetchMode, Versioned); + for Block := 0 to (ObjectCount div FetchBlockSize) do + begin Start := Block * FetchBlockSize; Stop := MinIntValue([Pred(Succ(Block) * FetchBlockSize), ObjectCount]); if Stop >= Start then begin aQuery.ClearParams; - BoldAppendToStrings(SQL, IdListSegmentToWhereFragment(ObjectsToFetch, Start, Stop, aQuery), False); + TempList.Assign(SQL); + BoldAppendToStrings(TempList, IdListSegmentToWhereFragment(ObjectsToFetch, Start, Stop, true, aQuery), False); if versioned then - RetrieveTimeStampCondition(SQL, TimeStamp, true, 'AND', false); // do not localize + RetrieveTimeStampCondition(TempList, TimeStamp, true, 'AND', false); + aQuery.SQLText := TempList.Text; SQLHits := 0; - aQuery.AssignSQL(SQL); aQuery.Open; while not aQuery.EOF do begin Inc(SQLHits); - tempId := (SystemPersistenceMapper as TBoldSystemDefaultMapper).NewIdFromQuery(aQuery, 1, 0, timeStamp); + tempId := (SystemPersistenceMapper as TBoldSystemDefaultMapper).NewIdFromQuery(aQuery, NO_CLASS, 1, 0, timeStamp); NewId := ObjectsToFetch.IDByID[TempId]; TempId.Free; if not assigned(NewId) then - raise EBoldInternal.CreateFmt(sUninvitedObjectReturnedFromDB, [classname, aQuery.Fields[0].AsInteger]); + raise EBoldInternal.CreateFmt('%s.PMMultiPurposeRetrieveExactIdList: Database returned object we didn''t ask for (ID: %d)', [classname, aQuery.Fields[0].AsInteger]); if assigned(MissingList) then begin i := MissingList.IndexByID[NewId]; if i <> -1 then - MissingList.RemoveByIndex(i) + MissingList.RemoveByIndex(i); end; if not NewId.TopSortedIndexExact then NewId := TranslationList.TranslateToNewID[NewId]; if not NewId.TopSortedIndexExact then - raise EBoldInternal.CreateFmt(sIDExactnessFailure, [classname]); + raise EBoldInternal.CreateFmt('%s.PMMultiPurposeRetrieveExactIdList: Got an Id with no or only approx class!', [classname]); if (TimeStamp = BOLDMAXTIMESTAMP) and not assigned(MemberIdList) and SystemPersistenceMapper.SupportsObjectUpgrading and IsOldVersion(aQuery) then begin @@ -1312,21 +1811,29 @@ procedure TBoldObjectDefaultMapper.PMMultiPurposeRetrieveExactIdList(ObjectsToFe aQuery.Next; end; + aQuery.ClearParams; aQuery.Close; - BoldPMLogFmt(sLogFetchedXobjectsOfY, [SQLHits, ExpressionName]); + if BoldPMLogHandler<>nil then + LogLateFetch(SQLHits, ExpressionName); end; end; if assigned(MissingList) and (FetchMode <> fmDistributable) and (MissingList.Count > 0) then begin - BoldPMLogFmt(sLogXObjectsOfYMissing, [MissingList.Count, ExpressionName]); - - for i := 0 to MissingList.Count - 1 do - begin - ObjectContents := ValueSpace.EnsuredObjectContentsByObjectId[MissingList[i]]; - ObjectContents.BoldExistenceState := besDeleted; - ObjectContents.IsReadOnly := true; - end; + if BoldPMLogHandler<>nil then + BoldPMLogFmt('%d objects of type %s were missing', [MissingList.Count, ExpressionName]); +// if not SystemPersistenceMapper.SQLDataBaseConfig.IgnoreMissingObjects then + for i := 0 to MissingList.Count-1 do + begin + if SystemPersistenceMapper.SQLDataBaseConfig.IgnoreMissingObjects then + TranslationList.AddTranslationAdoptNew(MissingList[i], TBoldNonExistingObjectId.CreateWithClassID(MissingList[i].TopSortedIndex, MissingList[i].TopSortedIndexExact)) + else + begin + ObjectContents := ValueSpace.EnsuredObjectContentsByObjectId[MissingList[i]]; + ObjectContents.BoldExistenceState := besDeleted; + ObjectContents.IsReadOnly := true; + end; + end; end; end; @@ -1345,16 +1852,23 @@ procedure TBoldObjectDefaultMapper.PMMultiPurposeRetrieveExactIdList(ObjectsToFe for i := 0 to CustomMembers.Count - 1 do CustomMembers[i].PMFetch(ObjectsToFetch, ValueSpace, FetchMode, TranslationList, failureList); finally - sql.Free; - MemberPMList.Free; - CustomMembers.Free; SystemPersistenceMapper.ReleaseQuery(aQuery); - TempLIst.Free; - RefetchIdList.Free; + if not FoundInCache then + begin + // store in cache + i := Length(fQueryCache); + SetLength(fQueryCache, i+1); + if Assigned(MemberIdList) then + fQueryCache[i].MemberList := MemberIdList.Clone; + fQueryCache[i].SqlStrings := Sql; + fQueryCache[i].FetchMode := FetchMode; + fQueryCache[i].MemberPMList := MemberPMList; + fQueryCache[i].CustomMembers := CustomMembers; + end; end; end; -function TBoldObjectDefaultMapper.CompareFieldsToMembers(ObjectID: TBoldObjectId; ValueSpace: IBoldValueSpace; DataSet: IBoldDataSet; memberList: TBoldMemberPersistenceMapperList; TranslationList: TBoldIdTranslationList): Boolean; +function TBoldObjectDefaultMapper.CompareFieldsToMembers(ObjectID: TBoldObjectId; const ValueSpace: IBoldValueSpace; const DataSet: IBoldDataSet; memberList: TBoldMemberPersistenceMapperList; TranslationList: TBoldIdTranslationList): Boolean; var i: integer; ObjectContents: IBoldObjectContents; @@ -1366,14 +1880,14 @@ function TBoldObjectDefaultMapper.CompareFieldsToMembers(ObjectID: TBoldObjectId result := result and TBoldMemberDefaultMapper(Memberlist[i]).CompareFields(ObjectContents, DataSet, ValueSpace, Translationlist); end; -procedure TBoldObjectDefaultMapper.HandleCompareData(FetchedId: TBoldObjectId; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; Query: IBoldQuery; MemberPMList: TBoldMemberPersistenceMapperList; FetchMode: integer; FailureList: TBoldObjectIdList); +procedure TBoldObjectDefaultMapper.HandleCompareData(FetchedId: TBoldObjectId; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; const Query: IBoldQuery; MemberPMList: TBoldMemberPersistenceMapperList; FetchMode: integer; FailureList: TBoldObjectIdList); begin if not CompareFieldsToMembers(FetchedId, ValueSpace, Query, MemberPMList, TranslationList) and not FailureList.IdInList[FetchedId] then FailureList.Add(FetchedId); end; -procedure TBoldObjectDefaultMapper.PMCompareExactIDList(ObjectIDList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; MemberIdList: TBoldMemberIdList; TranslationList: TBoldIdTranslationList; FailureList: TBoldObjectIdList); +procedure TBoldObjectDefaultMapper.PMCompareExactIDList(ObjectIDList: TBoldObjectIdList; const ValueSpace: IBoldValueSpace; MemberIdList: TBoldMemberIdList; TranslationList: TBoldIdTranslationList; FailureList: TBoldObjectIdList); var MissingList: TBoldObjectIdList; i: integer; @@ -1385,28 +1899,26 @@ procedure TBoldObjectDefaultMapper.PMCompareExactIDList(ObjectIDList: TBoldObjec PMMultiPurposeRetrieveExactIdList(ObjectIdList, ValueSpace, MemberIdList, fmCompare, translationList, MissingList, FailureList, BoldMaxTimeStamp); if MissingList.Count > 0 then begin - BoldLog.LogFmt(sOptimisticLockingFailedForNonExisting, [expressionName]); + BoldLog.LogFmt('Optimistic Locking failed for the following objects of type %s because they did not exist in the database:', [expressionName]); for i := 0 to MissingList.Count - 1 do - BoldLog.LogFmt(sLogIdAsString, [MissingList[i].AsString]); + BoldLog.Log('Id: ' + MissingList[i].AsString); FailureList.AddList(MissingList); end; end; -procedure TBoldObjectDefaultMapper.HandleFetchData(FetchedId: TBoldObjectId; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; Query: IBoldQuery; MemberPMList: TBoldMemberPersistenceMapperList; FetchMode: integer; FailureList: TBoldObjectIdList); +procedure TBoldObjectDefaultMapper.HandleFetchData(FetchedId: TBoldObjectId; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; const Query: IBoldQuery; MemberPMList: TBoldMemberPersistenceMapperList; FetchMode: integer; FailureList: TBoldObjectIdList); begin ValuesFromFieldsByMemberList(FetchedId, ValueSpace, TranslationList, Query, MemberPMList); if FetchMode = fmDistributable then DistributableInfoFromQuery(FetchedId, ValueSpace, TranslationList, Query); end; -procedure TBoldObjectDefaultMapper.PMFetchExactIDList(ObjectIDList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; MemberIdList: TBoldMemberIdList; FetchMode: Integer; TranslationList: TBoldIdTranslationList; MissingList: TBoldObjectIdList); +procedure TBoldObjectDefaultMapper.PMFetchExactIDList(ObjectIDList: TBoldObjectIdList; const ValueSpace: IBoldValueSpace; MemberIdList: TBoldMemberIdList; FetchMode: Integer; TranslationList: TBoldIdTranslationList; MissingList: TBoldObjectIdList); var i: integer; TimeStamp: TBoldTimeStampType; ListOfOtherTimeStamps, ObjectsToFetch: TBoldObjectIdList; begin - // Note, when the list gets here it contains only object of one class, from one - // Bold, that are not previously present in the Bold (or possibly a forced fetch) if objectIdList.Count = 0 then exit; @@ -1445,23 +1957,78 @@ procedure TBoldObjectDefaultMapper.PMFetchExactIDList(ObjectIDList: TBoldObjectI end; end; -procedure TBoldObjectDefaultMapper.PMFetchWithCondition(ObjectIDList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; BoldCondition: TBoldCondition; FetchMode: Integer; TranslationList: TBoldIdTranslationList); +procedure TBoldObjectDefaultMapper.FetchRawSqlCondition(ObjectIDList: TBoldObjectIdList; const ValueSpace: IBoldValueSpace; RawCondition: TBoldRawSqlCondition; FetchMode: Integer; TranslationList: TBoldIdTranslationList); var aQuery: IBoldQuery; - WhereToken: string; - fromLine: String; - JoinLine: String; - RootTableName: string; - JoinCondition: string; +begin + aQuery := SystemPersistenceMapper.GetQuery; + try + aQuery.AssignSQLText(RawCondition.SQL); + aQuery.AssignParams(RawCondition.Params); + RawCondition.AvailableAnswers := (SystemPersistenceMapper as TBoldSystemDefaultMapper).GetListUsingQuery(ObjectIDList, ValueSpace, aQuery, RawCondition.TopSortedIndex, -1, 0, FetchMode, TranslationList, RawCondition.Time, RawCondition.MaxAnswers, RawCondition.Offset); + finally + SystemPersistenceMapper.ReleaseQuery(aQuery); + end; +end; + +procedure TBoldObjectDefaultMapper.FillInMembers(MyMoldClass, + CurrentMoldClass: TMoldClass; TypeNameDictionary: TBoldTypeNameDictionary); +var + i: integer; +begin + fOptimisticLockingMode := MyMoldClass.EffectiveOptimisticLocking; + if SystemPersistenceMapper.UseModelVersion then + begin + fModelVersionMember := TBoldModelVersionMember.CreateFromMold(nil, MyMoldClass, self, -1, TypeNameDictionary); + MemberPersistenceMappers.Add(fModelVersionMember); + end; + if SystemPersistenceMapper.UseReadOnly then + MemberPersistenceMappers.Add(TBoldReadOnlynessMember.CreateFromMold(nil, MyMoldClass, self, -1, TypeNameDictionary)); + + + if SystemPersistenceMapper.UseXFiles then + begin + if SystemPersistenceMapper.UseTimestamp then + MemberPersistenceMappers.Add(TBoldTimeStampMember.CreateFromMold(nil, MyMoldClass, self, -1, TypeNameDictionary)); + if SystemPersistenceMapper.UseGlobalId then + MemberPersistenceMappers.Add(TBoldGlobalIdMember.CreateFromMold(nil, MyMoldClass, self, -1, TypeNameDictionary)); + end + else + begin + if SystemPersistenceMapper.UseTimestamp and (not MyMoldClass.IsRootClass )then + MemberPersistenceMappers.Add(TBoldNonXFileTimeStampMember.CreateFromMold(nil, MyMoldClass, self, -1, TypeNameDictionary)); + end; + + fObjectIdClass := BOLDDEFAULTIDNAME; + for i := 0 to MyMoldClass.AllPossibleNames.Count - 1 do + GenerateMappingInfo(MyMoldClass.AllPossibleNames[i], MyMoldClass); + inherited; +end; + +procedure TBoldObjectDefaultMapper.PMFetchWithCondition(ObjectIDList: TBoldObjectIdList; const ValueSpace: IBoldValueSpace; BoldCondition: TBoldCondition; FetchMode: Integer; TranslationList: TBoldIdTranslationList); +var + aQuery: IBoldQuery; + WhereToken, + fromLine, JoinLine, + RootTableName, JoinCondition, + sCurrentMappingInfo: string; i, j: Integer; timeStamp: TBoldTimeStampType; MappingInfo: TBoldAllInstancesMappingArray; SQL: TStringList; SQLCondition: TBoldSQLCondition; +{$IFDEF RIL} + SB: TStringBuilder; +{$ENDIF} begin if not assigned(BoldCondition) or (BoldCondition is TBoldConditionWithClass) then begin - if BoldCondition is TBoldSQLCondition then + if BoldCondition is TBoldRawSqlCondition then + begin + FetchRawSqlCondition(ObjectIDList, ValueSpace, TBoldRawSqlCondition(BoldCondition), FetchMode, TranslationList); + Exit; + end + else if BoldCondition is TBoldSQLCondition then SQLCondition := BoldCondition as TBoldSQLCondition else SQLCondition := nil; @@ -1469,11 +2036,16 @@ procedure TBoldObjectDefaultMapper.PMFetchWithCondition(ObjectIDList: TBoldObjec MappingInfo := SystemPersistenceMapper.MappingInfo.GetAllInstancesMapping(ExpressionName); aQuery := SystemPersistenceMapper.GetQuery; sql := TStringList.Create; + {$IFDEF RIL} + SB := TStringBuilder.Create; + {$ENDIF} try for i := 0 to length(MappingInfo) - 1 do begin + sCurrentMappingInfo := MappingInfo[i].TableName; + sql.Clear; - WhereToken := 'WHERE'; // Do not localize + WhereToken := 'WHERE'; if assigned(BoldCondition) then timeStamp := (BoldCondition as TBoldConditionWithClass).Time @@ -1482,19 +2054,33 @@ procedure TBoldObjectDefaultMapper.PMFetchWithCondition(ObjectIDList: TBoldObjec if (BoldCondition is TBoldTimestampCondition) then begin - SQL.Add(format('SELECT %s, %s', [IDCOLUMN_NAME, TYPECOLUMN_NAME])); // Do not localize - SQL.Add(format('FROM %s', [(SystemPersistenceMapper.PSSystemDescription as TBoldDefaultSystemDescription).XFilestable.SQLName])); // Do not localize - SQL.Add(format('WHERE %s > %d', [SystemPersistenceMapper.XFilesTimeStampColumn.SQLname, (BoldCondition as TBoldTimestampCondition).Timestamp])); // Do not localize + SQL.Add(format('SELECT %s, %s', [IDCOLUMN_NAME, TYPECOLUMN_NAME])); + SQL.Add(format('FROM %s', [(SystemPersistenceMapper.PSSystemDescription as TBoldDefaultSystemDescription).XFilestable.SQLName])); + SQL.Add(format('WHERE %s > %d', [SystemPersistenceMapper.XFilesTimeStampColumn.SQLname, (BoldCondition as TBoldTimestampCondition).Timestamp])); aQuery.AssignSQL(SQL); end else begin - SQL.Append(Format('SELECT %s.%s, %s.%s', [MappingInfo[i].TableName, IDCOLUMN_NAME, MappingInfo[i].TableName, TYPECOLUMN_NAME])); // do not localize - FromLine := Format('FROM %s', [MappingInfo[i].TableName]); // do not localize + {$IFDEF RIL} + SB.Clear; + SB.Append('SELECT '); + SB.Append(sCurrentMappingInfo); + SB.Append('.'); + SB.Append(IDCOLUMN_NAME); + SB.Append(', '); + SB.Append(sCurrentMappingInfo); + SB.Append('.'); + SB.Append(TYPECOLUMN_NAME); + SQL.Append(SB.ToString); + + FromLine := 'FROM '+sCurrentMappingInfo; + {$ELSE} + SQL.Append(Format('SELECT %s.%s, %s.%s', [MappingInfo[i].TableName, IDCOLUMN_NAME, MappingInfo[i].TableName, TYPECOLUMN_NAME])); + FromLine := Format('FROM %s', [MappingInfo[i].TableName]); + {$ENDIF} + JoinLine := ''; RootTableName := SystemPersistenceMapper.RootClassObjectPersistenceMapper.MainTable.SQLName; - - // add the rest of the tables if assigned(SQLCondition) and SQLCondition.JoinInheritedTables and ((SQLCondition.whereFragment <> '') or @@ -1502,35 +2088,35 @@ procedure TBoldObjectDefaultMapper.PMFetchWithCondition(ObjectIDList: TBoldObjec begin for j := 0 to AllTables.count - 1 do - if not SameText(Alltables[j].SQLName, MappingInfo[i].TableName) and + if not SameText(Alltables[j].SQLName, sCurrentMappingInfo) and (AllTables[j] <> SystemPersistenceMapper.PSSystemDescription.XFilestable) then begin - JoinCondition := format('(%s.%s = %s.%s)', // do not localize - [MappingInfo[i].TableName, IDCOLUMN_NAME, AllTables[j].SQLName, IDCOLUMN_NAME]); + JoinCondition := format('(%s.%s = %s.%s)', + [sCurrentMappingInfo, IDCOLUMN_NAME, AllTables[j].SQLName, IDCOLUMN_NAME]); if SystemPersistenceMapper.SQLDataBaseConfig.UseSQL92Joins then - fromLine := fromLine + format(' left join %s on %s ', [AllTables[j].SQLName, JoinCondition]) // do not localize + fromLine := fromLine + format(' left join %s on %s ', [AllTables[j].SQLName, JoinCondition]) else begin - fromLine := fromLine + format(', %s', [AllTables[j].SQLName]); // do not localize - JoinLine := JoinLine + format('%s %s ', [WhereToken, joinCondition]); // do not localize - WhereToken := 'AND'; // do not localize + fromLine := fromLine + format(', %s', [AllTables[j].SQLName]); + JoinLine := JoinLine + format('%s %s ', [WhereToken, joinCondition]); + WhereToken := 'AND'; end end; end else if Versioned and - not SameText(MappingInfo[i].TableName, RootTableName) then + not SameText(sCurrentMappingInfo, RootTableName) then begin - joinCondition := format('(%s.%s = %s.%s) ', // do not localize - [MappingInfo[i].TableName, IDCOLUMN_NAME, RootTableName, IDCOLUMN_NAME]); + joinCondition := format('(%s.%s = %s.%s) ', + [sCurrentMappingInfo, IDCOLUMN_NAME, RootTableName, IDCOLUMN_NAME]); if SystemPersistenceMapper.SQLDataBaseConfig.UseSQL92Joins then - fromLine := fromLine + format(' left join %s on %s ', [RootTableName, JoinCondition]) // do not localize + fromLine := fromLine + format(' left join %s on %s ', [RootTableName, JoinCondition]) else begin - fromLine := FromLine + ', ' + RootTableName; // do not localize - JoinLine := JoinLine + format(' %s %s ', [WhereToken, joincondition]); // do not localize - WhereToken := 'AND'; // do not localize + fromLine := FromLine + ', ' + RootTableName; + JoinLine := JoinLine + format(' %s %s ', [WhereToken, joincondition]); + WhereToken := 'AND'; end; end; SQL.Add(fromLine); @@ -1540,21 +2126,21 @@ procedure TBoldObjectDefaultMapper.PMFetchWithCondition(ObjectIDList: TBoldObjec if Versioned then begin RetrieveTimeStampCondition(sql, TimeStamp, false, WhereToken, false); - WhereToken := 'AND'; // do not localize + WhereToken := 'AND'; end; if MappingInfo[i].ClassIdRequired then begin - SQL.Add(Format('%s %s.%s in (%s)', [WhereToken, MappingInfo[i].TableName, TYPECOLUMN_NAME, SubClassesID])); // do not localize - WhereToken := 'AND'; // do not localize + SQL.Add(Format('%s %s.%s in (%s)', [WhereToken, sCurrentMappingInfo, TYPECOLUMN_NAME, SubClassesID])); + WhereToken := 'AND'; end; if assigned(SQLCondition) then begin - if SQLCondition.whereFragment <> '' then // do not localize - SQL.Append(Format('%s (%s)', [WhereToken, SQLCondition.whereFragment])); // do not localize - if SQLCondition.orderBy <> '' then // do not localize - SQL.Append(Format('ORDER BY %s', [SQLCondition.orderBy])); // do not localize + if SQLCondition.whereFragment <> '' then + SQL.Append(Format('%s (%s)', [WhereToken, SQLCondition.whereFragment])); + if SQLCondition.orderBy <> '' then + SQL.Append(Format('ORDER BY %s', [SQLCondition.orderBy])); end; aQuery.AssignSQL(SQL); @@ -1562,88 +2148,244 @@ procedure TBoldObjectDefaultMapper.PMFetchWithCondition(ObjectIDList: TBoldObjec if assigned(SQLCondition) then aQuery.AssignParams(SQLCondition.Params); + if assigned(SQLCondition) and Assigned(SystemPersistenceMapper.OnPsEvaluate) then + SystemPersistenceMapper.OnPsEvaluate(aQuery); end; - BoldCondition.AvailableAnswers := (SystemPersistenceMapper as TBoldSystemDefaultMapper).GetListUsingQuery(ObjectIDList, ValueSpace, aQuery, FetchMode, TranslationList, TimeStamp, BoldCondition.MaxAnswers, BoldCondition.Offset); - BoldPMLogFmt(sLogFetchedXObjectsOfYFromTableZ, [ObjectIdList.Count, ExpressionName, MappingInfo[i].tableName]); + BoldCondition.AvailableAnswers := (SystemPersistenceMapper as TBoldSystemDefaultMapper).GetListUsingQuery(ObjectIDList, ValueSpace, aQuery, NO_CLASS ,1, 0, FetchMode, TranslationList, TimeStamp, BoldCondition.MaxAnswers, BoldCondition.Offset); + {$IFDEF RIL} + //BoldPMLogFmt('Fetched %d IDs in class %s from table %s', [ObjectIdList.Count, ExpressionName, MappingInfo[i].tableName]); + if BoldPMLogHandler<>nil then { skip formating if the string is not used anyway... //ril } + begin + SB.Clear; + SB.Append('Fetched '); + SB.Append(IntToStr(ObjectIdList.Count)); + SB.Append(' IDs in class '); + SB.Append(ExpressionName); + SB.Append(' from table '); + SB.Append(sCurrentMappingInfo); + BoldPMLogFmt(SB.ToSTring, []); + end; + {$ELSE} + BoldPMLogFmt('Fetched %d IDs in class %s from table %s', [ObjectIdList.Count, ExpressionName, MappingInfo[i].tableName]); + {$ENDIF} end; finally SystemPersistenceMapper.ReleaseQuery(aQuery); sql.Free; + {$IFDEF RIL} + FreeAndNil(SB); + {$ENDIF} end; end else - raise EBold.CreateFmt(sUnknownConditionType, [BoldCondition.ClassName]); + raise EBold.CreateFmt('Unknown type of condition (%s)', [BoldCondition.ClassName]); end; -function TBoldObjectDefaultMapper.NextExternalObjectId(ValueSpace: IBoldValueSpace; ObjectId: TBoldObjectId): TBoldObjectId; +function TBoldObjectDefaultMapper.NextExternalObjectId(const ValueSpace: IBoldValueSpace; ObjectId: TBoldObjectId): TBoldObjectId; var aQuery: IBoldQuery; aExecQuery: IBoldExecQuery; NewID: Longint; SystemDefaultMapper: TBoldSystemDefaultMapper; begin + NewId := -1; SystemDefaultMapper := SystemPersistenceMapper as TBoldSystemDefaultMapper; if SystemDefaultMapper.NextDBID > SystemDefaultMapper.LastReservedDBID then begin - SystemDefaultMapper.StartTransaction(ValueSpace); - aQuery := SystemDefaultMapper.GetQuery; - aExecQuery := SystemDefaultMapper.GetExecQuery; - try + // plugin ID increment here + if Assigned(IDIncrementEvent) then + begin + NewID := IDIncrementEvent(SystemDefaultMapper.ReservedCount); + if CompatibilityMode then + begin + aExecQuery := SystemDefaultMapper.GetExecQuery; + try + try + aExecQuery.AssignSQLText(Format('UPDATE %s SET %s = %s + %d', [// do not localize + SystemDefaultMapper.PSSystemDescription.IdTable.SQLName, + IDCOLUMN_NAME, + IDCOLUMN_NAME, + SystemDefaultMapper.ReservedCount])); + aExecQuery.ExecSQL; + except + on E: EDatabaseError do + begin + raise EBoldCantGetID.CreateFmt('Can''t get ID (%s: %s)!', [e.ClassName, e.message]); + end; + end; + finally + SystemDefaultMapper.ReleaseExecQuery(aExecQuery); + end; + end; + end + else + begin + SystemDefaultMapper.StartTransaction(ValueSpace); + aQuery := SystemDefaultMapper.GetQuery; + aExecQuery := SystemDefaultMapper.GetExecQuery; try - aExecQuery.AssignSQLText(Format('UPDATE %s SET %s = %s + %d', [ // do not localize - SystemDefaultMapper.PSSystemDescription.IdTable.SQLName, - IDCOLUMN_NAME, - IDCOLUMN_NAME, - SystemDefaultMapper.ReservedCount])); - aExecQuery.ExecSQL; - aQuery.AssignSQLText(Format('SELECT %s FROM %s', [ // do not localize - IDCOLUMN_NAME, - SystemDefaultMapper.PSSystemDescription.IdTable.SQLName])); - aQuery.Open; - NewID := aQuery.Fields[0].AsInteger; - aQuery.Close; - SystemDefaultMapper.Commit(ValueSpace); - SystemDefaultMapper.NextDBID := NewID - SystemDefaultMapper.ReservedCount; - SystemDefaultMapper.LastReservedDBID := SystemDefaultMapper.NextDBID + SystemDefaultMapper.ReservedCount - 1; - except - on e: EDatabaseError do + try + aExecQuery.AssignSQLText(Format('UPDATE %s SET %s = %s + %d', [ + SystemDefaultMapper.PSSystemDescription.IdTable.SQLName, + IDCOLUMN_NAME, + IDCOLUMN_NAME, + SystemDefaultMapper.ReservedCount])); + aExecQuery.ExecSQL; + aQuery.AssignSQLText(Format('SELECT %s FROM %s', [ + IDCOLUMN_NAME, + SystemDefaultMapper.PSSystemDescription.IdTable.SQLName])); + aQuery.Open; + NewID := aQuery.Fields[0].AsInteger; + aQuery.Close; + SystemDefaultMapper.Commit(ValueSpace); + except + on e: EDatabaseError do + begin + SystemDefaultMapper.RollBack(ValueSpace); + raise EBoldCantGetID.CreateFmt('Can''t get ID (%s: %s)!', [e.ClassName, e.message]); + end; + end; + finally + SystemDefaultMapper.ReleaseQuery(aQuery); + SystemDefaultMapper.ReleaseExecQuery(aExecQuery); + end; + end; + SystemDefaultMapper.NextDBID := NewID - SystemDefaultMapper.ReservedCount; + SystemDefaultMapper.LastReservedDBID := SystemDefaultMapper.NextDBID + SystemDefaultMapper.ReservedCount - 1; + end; + SystemDefaultMapper.ReservedCount := 0; + + Result := TBoldDefaultId.CreateWithClassID(ObjectId.TopSortedIndex, true); + (result as TBoldDefaultId).AsInteger := SystemDefaultMapper.NextDBID; + + SystemDefaultMapper.NextDBID := SystemDefaultMapper.NextDBID + 1; +end; + +procedure TBoldObjectDefaultMapper.FetchPreviousSingleLinkValues(ObjectIdList: TBoldObjectIdLIst; const Old_Values: IBoldvalueSpace); +var + i: integer; +begin + if not Assigned(fSingleLinkList) then + begin + fSingleLinkList := TBoldMemberIdList.Create; + for i := 0 to MemberPersistenceMappers.Count - 1 do + if MemberPersistenceMappers[i] is TBoldEmbeddedSingleLinkDefaultMapper then + fSingleLinkList.Add(TBoldmemberId.Create(MemberPersistenceMappers[i].MemberIndex)); + end; + if fSingleLinkList.Count > 0 then + PMFetchExactIDList(ObjectIdList, Old_Values, fSingleLInkList, fmNormal, nil, nil); +end; + +procedure TBoldObjectDefaultMapper.MakeIDsExactUsingTable( + ObjectIDList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList; + Table: TBoldSQLTableDescription; EnsureAll: Boolean; + HandleNonExisting: Boolean); +{$IFDEF RIL} +var + Block, + ObjectCount: Longint; + topSortedIndex, I, j: Integer; + tempId: TBoldObjectId; + aQuery: IBoldQuery; + lst: TStringList; + Start, Stop: integer; + WhereFragment: string; + LittleObject: TLittleClass; + Ids: TList; + FetchBlockSize: integer; + sTestCompare: string; + Found: boolean; + SB: TStringBuilder; +begin + if ObjectIDList.Count = 0 then + exit; + lst := TStringList.Create; + SB := TStringBuilder.Create; + Ids := TList.Create; + aQuery := SystemPersistenceMapper.GetQuery; + FetchBlockSize := SystemPersistenceMapper.SQLDataBaseConfig.FetchBlockSize; + try + ObjectCount := ObjectIDList.Count - 1; + for Block := 0 to (ObjectCount div FetchBlockSize) do + begin + lst.Clear; + aQuery.ClearParams; + Table.RetrieveSelectIdAndTypeStatement(lst); + Start := Block * FetchBlockSize; + Stop := MinIntValue([Pred(Succ(Block) * FetchBlockSize), ObjectCount]); + + WhereFragment := IdListSegmentToWhereFragment(ObjectIDList, start, stop, true, aquery); + {<*>} + //BoldAppendToStrings(lst, Format(' WHERE %s %s', [IDCOLUMN_NAME, WhereFragment]), True); + { + sTestCompare := Format(' WHERE %s %s', [IDCOLUMN_NAME, WhereFragment]); + } + SB.Clear; + SB.Append(' WHERE '); + SB.Append(IDCOLUMN_NAME); + SB.Append(' '); + SB.Append(WhereFragment); + { + if S<>sTestCompare then + raise Exception.CreateFmt('Optimize error in TBoldObjectDefaultMapper.MakeIDsExactUsingTable %s<>%s', [S, sTestCompare]); + } + BoldAppendToStrings(lst, SB.ToString, True); + {} + + aQuery.AssignSQL(lst); + aQuery.Open; + Ids.Count := 0; + // commented out as Query.RecordCount can be slow +// if aQuery.RecordCount > Ids.Capacity then +// Ids.Capacity := aQuery.RecordCount; + TranslationList.Capacity := aQuery.RecordCount; + try + while not aQuery.EOF do + begin + LittleObject := TLittleClass.Create; + LittleObject.Id := aQuery.Fields[0].AsInteger; + LittleObject.DbType := aQuery.Fields[1].AsInteger; + Ids.Add(LittleObject); + aQuery.next; + end; + for i := Start to Stop do begin - SystemDefaultMapper.RollBack(ValueSpace); - raise EBoldCantGetID.CreateFmt(sCannotGetID, [e.ClassName, e.message]); + Found := false; + for j := 0 to Ids.Count - 1 do + begin + if TBoldDefaultId(ObjectIdList[i]).AsInteger = TLittleClass(Ids[j]).Id then + begin + Found := true; + TopSortedIndex := SystemPersistenceMapper.topSortedIndexForBoldDbType(TLittleClass(Ids[j]).dbType); + tempId := ObjectIdList[i].CloneWithClassId(TopSortedIndex, true); + TranslationList.AddTranslationAdoptNew(ObjectIdList[i], tempId); + Break; + end; + end; + if not Found and not SystemPersistenceMapper.SQLDataBaseConfig.IgnoreMissingObjects then + begin + if HandleNonExisting then + begin + tempId := TBoldNonExistingObjectId.Create; + TranslationList.AddTranslationAdoptNew(ObjectIdList[i], tempId); + end + else if EnsureAll then + Raise EBoldObjectNotInPs.CreateFmt('Id %d not found in table %s', [TBoldDefaultId(ObjectIdList[i]).AsInteger, Table.SQLName]); + end; end; + finally + aQuery.close; + for j := 0 to Ids.Count - 1 do + tObject(Ids[j]).Free; end; - finally - SystemDefaultMapper.ReleaseQuery(aQuery); - SystemDefaultMapper.ReleaseExecQuery(aExecQuery); end; + finally + SystemPersistenceMapper.ReleaseQuery(aQuery); + lst.Free; + FreeAndNil(SB); + Ids.free; end; - SystemDefaultMapper.ReservedCount := 0; - - Result := TBoldDefaultId.CreateWithClassID(ObjectId.TopSortedIndex, true); - (result as TBoldDefaultId).AsInteger := SystemDefaultMapper.NextDBID; - - SystemDefaultMapper.NextDBID := SystemDefaultMapper.NextDBID + 1; -end; - -procedure TBoldObjectDefaultMapper.FetchPreviousSingleLinkValues(ObjectIdList: TBoldObjectIdLIst; Old_Values: IBoldvalueSpace); -var - i: integer; - SingleLinkList: TBoldMemberIdList; - BoldGuard: IBoldGuard; -begin - BoldGuard := TBoldGuard.Create(SingleLinkList); - SingleLinkList := TBoldMemberIdList.Create; - - for i := 0 to MemberPersistenceMappers.Count - 1 do - if MemberPersistenceMappers[i] is TBoldEmbeddedSingleLinkDefaultMapper then - SingleLinkList.Add(TBoldmemberId.Create(MemberPersistenceMappers[i].MemberIndex)); - if SingleLinkList.Count > 0 then - PMFetchExactIDList(ObjectIdList, Old_Values, SingleLInkList, fmNormal, nil, nil); -end; - -procedure TBoldObjectDefaultMapper.MakeIDsExactUsingTable( - ObjectIDList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList; - Table: TBoldSQLTableDescription); +{$ELSE} var Block, ObjectCount: Longint; @@ -1659,11 +2401,11 @@ procedure TBoldObjectDefaultMapper.MakeIDsExactUsingTable( begin if ObjectIDList.Count = 0 then exit; - lst := TStringList.Create; aQuery := SystemPersistenceMapper.GetQuery; FetchBlockSize := SystemPersistenceMapper.SQLDataBaseConfig.FetchBlockSize; + Ids := TList.Create; + lst := TStringList.Create; try - // We do not want to retrieve more than BLOCKSIZE objects at a time ObjectCount := ObjectIDList.Count - 1; for Block := 0 to (ObjectCount div FetchBlockSize) do begin @@ -1672,11 +2414,13 @@ procedure TBoldObjectDefaultMapper.MakeIDsExactUsingTable( Start := Block * FetchBlockSize; Stop := MinIntValue([Pred(Succ(Block) * FetchBlockSize), ObjectCount]); - WhereFragment := IdListSegmentToWhereFragment(ObjectIDList, start, stop, aquery); - BoldAppendToStrings(lst, Format(' WHERE %s %s', [IDCOLUMN_NAME, WhereFragment]), True); // do not localize + WhereFragment := IdListSegmentToWhereFragment(ObjectIDList, start, stop, true, aquery); + BoldAppendToStrings(lst, Format(' WHERE %s %s', [IDCOLUMN_NAME, WhereFragment]), True); aQuery.AssignSQL(lst); aQuery.Open; - Ids := TList.Create; + Ids.Count := 0; + if Stop - Start >= Ids.Capacity then + Ids.Capacity := Stop - Start +1; try while not aQuery.EOF do begin @@ -1688,7 +2432,6 @@ procedure TBoldObjectDefaultMapper.MakeIDsExactUsingTable( end; for i := 0 to ObjectIdList.Count - 1 do begin - // fixme: Square for j := 0 to Ids.Count - 1 do begin if TBoldDefaultId(ObjectIdList[i]).AsInteger = TLittleClass(Ids[j]).Id then @@ -1704,29 +2447,69 @@ procedure TBoldObjectDefaultMapper.MakeIDsExactUsingTable( aQuery.close; for j := 0 to Ids.Count - 1 do tObject(Ids[j]).Free; - Ids.Free; end; end; finally SystemPersistenceMapper.ReleaseQuery(aQuery); lst.Free; + Ids.Free; end; +{$ENDIF} end; function TBoldObjectDefaultMapper.InternalIdListSegmentToWhereFragment( - IdList: TBoldObjectIdList; Start, Stop: integer; - Parameterized: IBoldParameterized): String; + IdList: TBoldObjectIdList; Start, Stop: Integer; AllowParms: Boolean; + const Parameterized: IBoldParameterized): String; function GetParamStr(IdIndex, ParamIndex: integer; UseParams: Boolean): String; begin if UseParams then begin - result := ':ID' + IntToStr(ParamIndex); // do not localize - Parameterized.CreateParam(ftInteger, 'ID' + IntToStr(ParamIndex), ptInput, SizeOf(Integer)).AsInteger := (IdList[IdIndex] as TBoldDefaultId).AsInteger; // do not localize + result := ':ID'+IntToStr(ParamIndex); + Assert(IdList[IdIndex] is TBoldDefaultId, IdList[IdIndex].ClassName); + Parameterized.CreateParam(ftInteger, 'ID'+IntToStr(ParamIndex)).AsInteger := (IdList[IdIndex] as TBoldDefaultId).AsInteger; end else result := IdList[Idindex].asString end; +{$IFDEF RIL} +var + i,j: integer; + TempList: TStringList; + ParamCount: integer; + UseParams: Boolean; + SB: TStringBuilder; +begin + + ParamCount := stop-start + 1; + UseParams := AllowParms and (ParamCount <= SystemPersistenceMapper.SQLDataBaseConfig.MaxParamsInIdList); + if ParamCount = 1 then + begin + Result := ' = ' + GetParamStr(start, 1, UseParams); + end + else + try + if UseParams then + i := ParamCount * 12 + else + i := ParamCount * 8; + SB := TStringBuilder.Create(i+5); + j := i+5; + SB.Append('in ('); + for i := start to stop do + begin + if i > start then + SB.Append(', '); + SB.Append(GetParamStr(i, i-start+1, Useparams)); + end; + SB.Append(')'); + {} + Result := SB.ToString; + finally + i := sb.Length; + FreeAndNil(SB); + end; +{$ELSE} var TempList: TStringList; i: integer; @@ -1744,25 +2527,27 @@ function TBoldObjectDefaultMapper.InternalIdListSegmentToWhereFragment( TempList := TStringList.Create; for i := start to stop do TempList.Add(GetParamStr(i, i-start+1, Useparams)); - result := BoldSeparateStringList(TempLIst, ', ', 'in (', ')'); // do not localize + result := BoldSeparateStringList(TempLIst, ', ', 'in (', ')'); end; +{$ENDIF} end; function TBoldObjectDefaultMapper.IdListSegmentToWhereFragment( - IdList: TBoldObjectIdList; Start, Stop: integer; - Query: IBoldExecQuery): String; + IdList: TBoldObjectIdList; Start, Stop: Integer; AllowParms: Boolean; + const Query: IBoldExecQuery): String; begin - result := InternalIdListSegmentToWhereFragment(IdList, Start, Stop, Query as IBoldParameterized); + result := InternalIdListSegmentToWhereFragment(IdList, Start, Stop, AllowParms, Query as IBoldParameterized); end; function TBoldObjectDefaultMapper.IdListSegmentToWhereFragment( - IdList: TBoldObjectIdList; Start, Stop: integer; - Query: IBoldQuery): String; + IdList: TBoldObjectIdList; Start, Stop: Integer; AllowParms: Boolean; + const Query: IBoldQuery): String; begin - result := InternalIdListSegmentToWhereFragment(IdList, Start, Stop, Query as IBoldParameterized); + result := InternalIdListSegmentToWhereFragment(IdList, Start, Stop, AllowParms, Query as IBoldParameterized); end; { TBoldMemberDefaultMapper } + function TBoldMemberDefaultMapper.GetAllowNullAsSQL: string; begin if AllowNull then @@ -1772,6 +2557,68 @@ function TBoldMemberDefaultMapper.GetAllowNullAsSQL: string; end; procedure TBoldMemberDefaultMapper.GenerateMappingInfo(MoldClass: TMoldClass; MoldMember: TMoldMember); +{$IFDEF RIL} + procedure GenerateLocal(const ClassExpressionName, MemberExpressionName: String; var ColumnNames: String; const LocalMoldClass: TMoldClass); + var + i: integer; + SubClass: TMoldClass; + begin + if LocalMoldClass.TableMapping in [tmOwn, tmParent] then + begin + TBoldSystemDefaultMapper(SystemPersistenceMapper).MappingInfo.AddMemberMapping( + ClassExpressionName, MemberExpressionName, + FindDefiningTable(LocalMoldClass, MoldMember), + ColumnNames, ClassName, FColumnIndex); + end; + if LocalMoldClass.TableMapping = tmChildren then + begin + for i := 0 to LocalMoldClass.SubClasses.Count-1 do + begin + SubClass := LocalMoldClass.SubClasses[i]; + if SubClass.EffectivePersistent then + GenerateLocal(ClassExpressionName, MemberExpressionName, ColumnNames, SubClass); + end; + end; + end; + + procedure GenerateForClassName(const ClassExpressionName: String; var ColumnNames: String); + var + i: integer; + s: TStringList; + BoldGuard: IBoldGuard; + begin + GenerateLocal(ClassExpressionName, ExpressionName, ColumnNames, moldclass); + if assigned(MoldMember) then + begin + BoldGuard := TBoldGuard.Create(s); + s := TStringlist.Create; + s.CommaText := MoldMember.FormerNames; + for i := 0 to s.count - 1 do + GenerateLocal(ClassExpressionName, s[i], ColumnNames, moldclass); + end; + end; + +var + i: integer; + ColumnNames: String; + SB: TStringBuilder; +begin + if requiresMemberMapping then + begin + SB := TStringBuilder.Create; + ColumnNames := ''; + for i := 0 to ColumnCount - 1 do + begin + if SB.Length > 0 then + SB.Append(', '); + SB.Append(BoldExpandName(InitialColumnName[i], '', xtSQL, SystemPersistenceMapper.SQLDataBaseConfig.MaxDBIdentifierLength, SystemPersistenceMapper.NationalCharConversion)); + end; + ColumnNames := SB.ToString; + for i := 0 to MoldClass.AllPossibleNames.count - 1 do + GenerateForClassName(MoldClass.AllPossibleNames[i], ColumnNames); + FreeAndNil(SB); + end; +{$ELSE} var ColumnNames: String; @@ -1785,7 +2632,8 @@ procedure TBoldMemberDefaultMapper.GenerateMappingInfo(MoldClass: TMoldClass; Mo MemberExpressionName, FindDefiningTable(LocalMoldClass, MoldMember), ColumnNames, - ClassName); + ClassName, + FColumnIndex); if LocalMoldClass.TableMapping = tmChildren then for i := 0 to LocalMoldClass.SubClasses.Count - 1 do if LocalMoldClass.SubClasses[i].EffectivePersistent then @@ -1819,14 +2667,12 @@ procedure TBoldMemberDefaultMapper.GenerateMappingInfo(MoldClass: TMoldClass; Mo begin if ColumnNames <> '' then ColumnNames := ColumnNames + ', '; - // expansion below is to truncate the names to the right length again... ColumnNames := ColumnNames + BoldExpandName(InitialColumnName[i], '', xtSQL, SystemPersistenceMapper.SQLDataBaseConfig.MaxDBIdentifierLength, SystemPersistenceMapper.NationalCharConversion); end; - - // this will loop over the name, all former names, and the names of the association for i := 0 to MoldClass.AllPossibleNames.count - 1 do GenerateForClassName(MoldClass.AllPossibleNames[i]); end; +{$ENDIF} end; constructor TBoldMemberDefaultMapper.CreateFromMold(moldMember: TMoldMember; moldClass: TMoldClass; Owner: TBoldObjectPersistenceMapper; const MemberIndex: Integer; TypeNameDictionary: TBoldTypeNameDictionary); @@ -1842,66 +2688,121 @@ procedure TBoldSystemDefaultMapper.GetNewTimeStamp; aExecQuery: IBoldExecQuery; LastClockTimestamp: TBoldTimestampType; LastClock: TDateTime; - TheNowValue: TDateTime; begin - aQuery := GetQuery; - aExecQuery := GetExecQuery; - try - aExecQuery.AssignSQLText( - Format('UPDATE %s SET %s = %s + 1', [ // do not localize - PSSystemDescription.TimeStampTable.SQLName, - TimeStampTableTimeStampColumn.SQLname, - TimeStampTableTimeStampColumn.SQLname])); - aExecQuery.ExecSQL; + if Assigned(NewTimeStampEvent) then + begin + NewTimeStampEvent(FCurrentTimeStamp, LastClockTimestamp, LastClock, fTimeOfTimeStamp, ClockLogGranularity); + if CompatibilityMode or UseClockLog then + begin + aExecQuery := GetExecQuery; + try + if CompatibilityMode then + begin + aExecQuery.AssignSQLText( + Format('UPDATE %s SET %s = %d', [// do not localize + PSSystemDescription.TimeStampTable.SQLName, + TimeStampTableTimeStampColumn.SQLName, + FCurrentTimeStamp])); + aExecQuery.ExecSQL; + end; + if UseClockLog then + begin + if LastClockTimeStamp <> -1 then + begin + aExecQuery.ParamCheck := true; + if CompatibilityMode then + begin + aExecQuery.AssignSQLText( + Format('UPDATE %s SET %s = :newTimestamp, %s = :newClock', [// do not localize + PSSystemDescription.LastClockTable.SQLName, + LastClockTableLastTimeStampColumn.SQLName, + LastClockTableLastClockColumn.SQLName])); + aExecQuery.ParamByName('newTimestamp').AsInteger := FCurrentTimeStamp; // do not localize + aExecQuery.ParamByName('newClock').AsDateTime := fTimeOfTimeStamp; // do not localize + aExecQuery.ExecSQL; + end; - aQuery.AssignSQLText( - Format('SELECT %s FROM %s', [ // do not localize - TimeStampTableTimeStampColumn.SQLname, - PSSystemDescription.TimeStampTable.SQLName])); - aQuery.Open; - FCurrentTimeStamp := aQuery.Fields[0].AsInteger; - aQuery.Close; + aExecQuery.AssignSQLText(Format('INSERT INTO %s (%s, %s, %s, %s) VALUES (:lastTimeStamp, :thisTimeStamp, :lastClock, :thisClock)', // do not localize + [PSSystemDescription.ClockLogTable.SQLName, + ClockLogTableLastTimeStampColumn.SQLName, + ClockLogTableThisTimeStampColumn.SQLName, + ClockLogTableLastClockColumn.SQLName, + ClockLogTableThisClockColumn.SQLName])); + aExecQuery.ParamByName('lastTimeStamp').AsInteger := LastClockTimestamp; // do not localize + aExecQuery.ParamByName('thisTimeStamp').AsInteger := FCurrentTimeStamp; // do not localize + aExecQuery.ParamByName('lastClock').AsDateTime := LastClock; // do not localize + aExecQuery.ParamByName('thisClock').AsDateTime := fTimeOfTimeStamp; // do not localize + aExecQuery.ExecSQL; + end; + end; + finally + ReleaseExecQuery(aExecQuery); + end; + end; + end + else + begin + aQuery := GetQuery; + aExecQuery := GetExecQuery; + aExecQuery.ParamCheck := false; + try + aExecQuery.AssignSQLText( + Format('UPDATE %s SET %s = %s + 1', [ + PSSystemDescription.TimeStampTable.SQLName, + TimeStampTableTimeStampColumn.SQLname, + TimeStampTableTimeStampColumn.SQLname])); + aExecQuery.ExecSQL; - if UseClockLog then - begin aQuery.AssignSQLText( - Format('SELECT %s, %s FROM %s', [ // do not localize - LastClockTableLastTimeStampColumn.SqlName, - LastClockTableLastClockColumn.SQLName, - PSSystemDescription.LastClockTable.SQLName])); + Format('SELECT %s FROM %s', [ + TimeStampTableTimeStampColumn.SQLname, + PSSystemDescription.TimeStampTable.SQLName])); aQuery.Open; - LastClockTimestamp := aQuery.Fields[0].AsInteger; - LastClock := aQuery.Fields[1].AsDateTime; + FCurrentTimeStamp := aQuery.Fields[0].AsInteger; aQuery.Close; - TheNowValue := GetCorrectTime; - if (TheNowValue - LastClock) > ClockLogGranularity then + if UseClockLog then begin - aExecQuery.AssignSQLText( - Format('UPDATE %s SET %s = :newTimestamp, %s = :newClock', [ // do not localize - PSSystemDescription.LastClockTable.SQLName, - LastClockTableLastTimeStampColumn.SQLName, - LastClockTableLastClockColumn.SQLName])); - aExecQuery.ParamByName('newTimestamp').AsInteger := FCurrentTimeStamp; // do not localize - aExecQuery.ParamByName('newClock').AsDateTime := TheNowValue; // do not localize - aExecQuery.ExecSQL; - - aExecQuery.AssignSQLText(Format('INSERT INTO %s (%s, %s, %s, %s) VALUES (:lastTimeStamp, :thisTimeStamp, :lastClock, :thisClock)', // do not localize - [PSSystemDescription.ClockLogTable.SQLName, - ClockLogTableLastTimeStampColumn.SQLName, - ClockLogTableThisTimeStampColumn.SQLName, - ClockLogTableLastClockColumn.SQLName, - ClockLogTableThisClockColumn.SQLName])); - aExecQuery.ParamByName('lastTimeStamp').AsInteger := LastClockTimestamp; // do not localize - aExecQuery.ParamByName('thisTimeStamp').AsInteger := FCurrentTimeStamp; // do not localize - aExecQuery.ParamByName('lastClock').AsDateTime := LastClock; // do not localize - aExecQuery.ParamByName('thisClock').AsDateTime := TheNowValue; // do not localize - aExecQuery.ExecSQL; + aQuery.AssignSQLText( + Format('SELECT %s, %s FROM %s', [ + LastClockTableLastTimeStampColumn.SqlName, + LastClockTableLastClockColumn.SQLName, + PSSystemDescription.LastClockTable.SQLName])); + aQuery.Open; + LastClockTimestamp := aQuery.Fields[0].AsInteger; + LastClock := aQuery.Fields[1].AsDateTime; + aQuery.Close; + +// fTimeOfTimeStamp := GetCorrectTime; // TimeOfTimeStamp is already set in NewTimeStampEvent + if (fTimeOfTimeStamp - LastClock) > ClockLogGranularity then + begin + aExecQuery.ParamCheck := true; + aExecQuery.AssignSQLText( + Format('UPDATE %s SET %s = %d, %s = :newClock', [ + PSSystemDescription.LastClockTable.SQLName, + LastClockTableLastTimeStampColumn.SQLName, + Integer(FCurrentTimeStamp), + LastClockTableLastClockColumn.SQLName])); + aExecQuery.ParamByName('newClock').AsDateTime := fTimeOfTimeStamp; // do not localize + aExecQuery.ExecSQL; + + aExecQuery.AssignSQLText(Format('INSERT INTO %s (%s, %s, %s, %s) VALUES (%d, %d, :lastClock, :thisClock)', + [PSSystemDescription.ClockLogTable.SQLName, + ClockLogTableLastTimeStampColumn.SQLName, + ClockLogTableThisTimeStampColumn.SQLName, + ClockLogTableLastClockColumn.SQLName, + ClockLogTableThisClockColumn.SQLName, + Integer(LastClockTimestamp), + Integer(FCurrentTimeStamp)])); + aExecQuery.ParamByName('lastClock').AsDateTime := LastClock; // do not localize + aExecQuery.ParamByName('thisClock').AsDateTime := fTimeOfTimeStamp; // do not localize + aExecQuery.ExecSQL; + end; end; + finally + ReleaseQuery(aQuery); + ReleaseExecQuery(aExecQuery); end; - finally - ReleaseQuery(aQuery); - ReleaseExecQuery(aExecQuery); end; end; @@ -1915,7 +2816,7 @@ function TBoldObjectDefaultMapper.UpdatesMembersInTable( if atable.Versioned then begin Inc(limit); - if atable.ContainsStopTimeStamp then + if aTable.ContainsStopTimeStamp then Inc(limit); end; result := (aTable.ColumnsList.Count > limit); @@ -1948,13 +2849,13 @@ procedure TBoldObjectDefaultMapper.SQLForDistributed(SQL: TStrings; end; procedure TBoldObjectDefaultMapper.DistributableInfoFromQuery( - ObjectID: TBoldObjectId; ValueSpace: IBoldValueSpace; - TranslationList: TBoldIdTranslationList; DataSet: IBoldDataSet); + ObjectID: TBoldObjectId; const ValueSpace: IBoldValueSpace; + TranslationList: TBoldIdTranslationList; const DataSet: IBoldDataSet); begin if SystemPersistenceMapper.UseTimestamp then - ValueSpace.EnsuredObjectContentsByObjectId[ObjectID].TimeStamp := DataSet.FieldByName(SystemPersistenceMapper.XFilesTimeStampColumn.SQLname).AsInteger; + ValueSpace.EnsuredObjectContentsByObjectId[ObjectID].TimeStamp := DataSet.FieldByUpperCaseName(SystemPersistenceMapper.XFilesTimeStampColumn.SQLNameUpper).AsInteger; if SystemPersistenceMapper.UseGlobalId then - ValueSpace.EnsuredObjectContentsByObjectId[ObjectID].GlobalId := DataSet.FieldByName(SystemPersistenceMapper.XFilesGlobalIdColumn.SQLName).AsString; + ValueSpace.EnsuredObjectContentsByObjectId[ObjectID].GlobalId := DataSet.FieldByUpperCaseName(SystemPersistenceMapper.XFilesGlobalIdColumn.SQLNameUpper).AsString; end; procedure TBoldSystemDefaultMapper.PMTranslateToGlobalIds( @@ -1984,7 +2885,7 @@ procedure TBoldSystemDefaultMapper.PMTranslateToGlobalIds( IdList.Add(ObjectIdList[I].AsString); aQuery.AssignSQLText( - Format('SELECT %s, %s, %s FROM %s WHERE %0:s IN (%4:s)', [ // do not localize + Format('SELECT %s, %s, %s FROM %s WHERE %0:s IN (%4:s)', [ IDCOLUMN_NAME, TYPECOLUMN_NAME, XFilesGlobalIdColumn.SQLName, @@ -1993,16 +2894,13 @@ procedure TBoldSystemDefaultMapper.PMTranslateToGlobalIds( aQuery.Open; + TranslationList.Capacity := TranslationList.Count + aQuery.RecordCount; while not aQuery.EOF do begin - anObjectId := NewIdFromQuery(aQuery, 1, 0, BOLDMAXTIMESTAMP); + anObjectId := NewIdFromQuery(aQuery, NO_CLASS, 1, 0, BOLDMAXTIMESTAMP); aGlobalId := NewGlobalIdFromQuery(aQuery, 1); - TranslationList.AddTranslation(anObjectId, aGlobalId); - - anObjectId.Free; - - aGlobalId.Free; + TranslationList.AddTranslationAdoptBoth(anObjectId, aGlobalId); aQuery.Next; end; @@ -2042,7 +2940,7 @@ procedure TBoldSystemDefaultMapper.PMTranslateToLocalIds( IdList.Add(GlobalIdList[I].AsString); aQuery.AssignSQLText( - Format('SELECT %s, %s, %s FROM %s WHERE %0:s IN (%4:s)', [ // do not localize + Format('SELECT %s, %s, %s FROM %s WHERE %0:s IN (%4:s)', [ XFilesGlobalIdColumn.SQLName, IDCOLUMN_NAME, TYPECOLUMN_NAME, @@ -2051,15 +2949,13 @@ procedure TBoldSystemDefaultMapper.PMTranslateToLocalIds( aQuery.Open; + TranslationList.Capacity := TranslationList.Count + aQuery.RecordCount; while not aQuery.EOF do begin aGlobalId := NewGlobalIdFromQuery(aQuery, 2); - anObjectId := NewIdFromQuery(aQuery, 2, 1, BoldMaxTimeStamp); + anObjectId := NewIdFromQuery(aQuery,NO_CLASS, 2, 1, BoldMaxTimeStamp); - TranslationList.AddTranslation(aGlobalId, anObjectId); - - freeandnil(anObjectId); - freeAndNil(aGlobalId); + TranslationList.AddTranslationAdoptBoth(aGlobalId, anObjectId); aQuery.Next; end; @@ -2074,7 +2970,7 @@ procedure TBoldSystemDefaultMapper.PMTranslateToLocalIds( end; procedure TBoldSystemDefaultMapper.FetchDeletedObjects( - ObjectIdList: TBoldObjectIdList; ValueSpace: IBoldValueSpace); + ObjectIdList: TBoldObjectIdList; const ValueSpace: IBoldValueSpace); var aQuery: IBoldQuery; IdList: TStringList; @@ -2100,7 +2996,7 @@ procedure TBoldSystemDefaultMapper.FetchDeletedObjects( IdList.Add(ObjectIdList[I].AsString); aQuery.AssignSQLText( - Format('SELECT %s, %s, %s FROM %s WHERE %0:s IN (%4:s)', [ // do not localize + Format('SELECT %s, %s, %s FROM %s WHERE %0:s IN (%4:s)', [ IDCOLUMN_NAME, TYPECOLUMN_NAME, XFilesTimeStampColumn.SQLname, @@ -2148,7 +3044,7 @@ procedure TBoldSystemDefaultMapper.InitializeBoldDbType; begin BoldDbType := MappingInfo.GetDbTypeMapping(ObjectPersistenceMapper.ExpressionName); if BoldDbType = NO_CLASS then - MissingIds.Add(format(sUnableToFindDBIDForX, [ObjectPersistenceMapper.ExpressionName])) + MissingIds.Add(format('Unable to find databaseId for %s', [ObjectPersistenceMapper.ExpressionName])) else ObjectPersistenceMapper.BoldDbType := BoldDbType; @@ -2160,8 +3056,8 @@ procedure TBoldSystemDefaultMapper.InitializeBoldDbType; end; end; end; - if MissingIds.COunt > 0 then - raise EBold.Create(MissingIds.Text); + if MissingIds.Count > 0 then + raise EBoldMissingID.Create(MissingIds.Text); end; procedure TBoldSystemDefaultMapper.PMSetReadonlyness(ReadOnlyList, WriteableList: TBoldObjectIdList); @@ -2195,7 +3091,7 @@ procedure TBoldSystemDefaultMapper.PMSetReadonlyness(ReadOnlyList, WriteableList IdList.Add(ObjectIDList[I].AsString); aQuery.AssignSQLText( - Format('UPDATE %s SET %s = %d WHERE %s IN (%s)', [ // do not localize + Format('UPDATE %s SET %s = %d WHERE %s IN (%s)', [ RootClassObjectPersistenceMapper.MainTable.SQLName, READONLYCOLUMN_NAME, ReadOnlyValue, @@ -2221,14 +3117,14 @@ function TBoldSystemDefaultMapper.NewGlobalIdFromQuery(aQuery: IBoldQuery; BoldD begin TopSortedIndex := topSortedIndexForBoldDbType(aQuery.Fields[BoldDbTypeColumn].AsInteger); Result := TBoldGlobalId.CreateWithInfo( - aQuery.FieldByName(XFilesGlobalIdColumn.SQLName).AsString, + aQuery.FieldByUpperCaseName(XFilesGlobalIdColumn.SQLNameUpper).AsString, TopSortedIndex, true, ObjectPersistenceMappers[TopSortedIndex].ExpressionName); end; procedure TBoldMemberDefaultMapper.PMFetch(ObjectIdList: TBoldObjectIdList; - ValueSpace: IBoldValueSpace; FetchMode: Integer; + const ValueSpace: IBoldValueSpace; FetchMode: Integer; TranslationList: TBoldIdTranslationList; FailureList: TBoldObjectIdList); var Block, @@ -2241,10 +3137,8 @@ procedure TBoldMemberDefaultMapper.PMFetch(ObjectIdList: TBoldObjectIdList; MemberPMList: TBoldMemberPersistenceMapperList; Table: TBoldSQLTableDescription; begin - // Note, when the list gets here it contains only object of one class, from one - // Bold, that are not previously present in the Bold (or possibly a forced fetch) - // all objectids are the same timestamp, this has been taken care of by PMFetchExactId + if (ObjectIdList.Count > 1) and RequiresLiveQuery then BlockSize := 1 else @@ -2268,30 +3162,30 @@ procedure TBoldMemberDefaultMapper.PMFetch(ObjectIdList: TBoldObjectIdList; Table := (ColumnDescriptions[0] as TBoldSQLColumnDescription).TableDescription; TempLIst.Clear; TBoldObjectDefaultMapper(ObjectPersistenceMapper).SQLForMembers(Table, TempList, MemberPMList, ssColumns, true, true, False); - SQL.Text := format('SELECT %s FROM %s WHERE %s ', [BoldSeparateStringList(TempLIst, ', ', '', ''), Table.SQLName, IDCOLUMN_NAME]); // do not localize + SQL.Text := format('SELECT %s FROM %s WHERE %s ', [BoldSeparateStringList(TempLIst, ', ', '', ''), Table.SQLName, IDCOLUMN_NAME]); Start := Block * BlockSize; Stop := MinIntValue([Pred(Succ(Block) * BlockSize), ObjectCount]); if Start <= stop then begin - BoldAppendToStrings(SQL, ObjectPersistenceMapper.IdListSegmentToWhereFragment(ObjectIdList, start, stop, aQuery), False); + BoldAppendToStrings(SQL, ObjectPersistenceMapper.IdListSegmentToWhereFragment(ObjectIdList, start, stop, true, aQuery), False); aQuery.AssignSQL(sql); aQuery.Open; while not aQuery.EOF do begin - tempId := SystemPersistenceMapper.NewIdFromQuery(aQuery, 1, 0, ObjectIDList[0].TimeStamp); + tempId := SystemPersistenceMapper.NewIdFromQuery(aQuery, NO_CLASS, 1, 0, ObjectIDList[0].TimeStamp); NewId := ObjectIDList.IDByID[TempId]; TempId.Free; if not assigned(NewId) then - raise EBoldInternal.CreateFmt('%s.PMFetch: Database returned object we didn''t ask for (ID: %d)', [ClassName, aQuery.Fields[0].AsInteger]); // do not localize + raise EBoldInternal.CreateFmt('%s.PMFetch: Database returned object we didn''t ask for (ID: %d)', [ClassName, aQuery.Fields[0].AsInteger]); if not NewId.TopSortedIndexExact then NewId := TranslationList.TranslateToNewID[NewId]; if not NewId.TopSortedIndexExact then - raise EBoldInternal.CreateFmt('%s.PMFetch: Got an Id with no or only approx class!', [Classname]); // do not localize + raise EBoldInternal.CreateFmt('%s.PMFetch: Got an Id with no or only approx class!', [Classname]); ObjectPersistenceMapper.ValuesFromFieldsByMemberList(NewId, ValueSpace, TranslationList, aQuery, MemberPMList); @@ -2309,23 +3203,8 @@ procedure TBoldMemberDefaultMapper.PMFetch(ObjectIdList: TBoldObjectIdList; end; end; -function TBoldSystemDefaultMapper.GetPSSystemDescription: TBoldDefaultSystemDescription; -begin - result := (inherited PSSystemDescription) as TBoldDefaultSystemDescription; -end; - -function TBoldObjectDefaultMapper.GetSystemPersistenceMapper: TBoldSystemDefaultMapper; -begin - result := (inherited SystemPersistenceMapper) as TBoldSystemDefaultMapper; -end; - -function TBoldSystemDefaultMapper.GetRootClassObjectPersistenceMapper: TBoldObjectDefaultMapper; -begin - result := (inherited RootClassObjectPersistenceMapper) as TBoldObjectDefaultMapper; -end; - procedure TBoldSystemDefaultMapper.PMFetchClassWithCondition( - ObjectIDList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; + ObjectIDList: TBoldObjectIdList; const ValueSpace: IBoldValueSpace; BoldCondition: TBoldCondition; FetchMode: Integer; TranslationList: TBoldIdTranslationList); var @@ -2338,19 +3217,33 @@ procedure TBoldSystemDefaultMapper.PMFetchClassWithCondition( SQlGenerator: TBoldSQLQueryGenerator; aCPCond: TBoldChangePointCondition; GlobalNameSpace: TBoldSqlNameSpace; + aVariableIDLists: TBoldObjectArray; + vBoldParameterized: IBoldParameterized; procedure FixQueriesForEnv(VarBinding: TBoldSQLVariableBinding; Context: TBoldObjectIdList; NameSpace: TBoldSqlNameSpace); var MainTableRef: TBoldSqlTableReference; + BoldID: TBoldDefaultID; begin - if VarBinding.VariableName = 'SELF' then // do not localize + if CompareText(VarBinding.VariableName, 'SELF') = 0 then // do not localize begin VarBinding.NewQuery(NameSpace); MainTableRef := VarBinding.TableReferenceForTable(VarBinding.ObjectMapper.MainTable, VarBinding.Query, true); VarBinding.Context := OclCondition.Context; VarBinding.Query.AddWCF(TBoldSQLWCFBinaryInfix.CreateWCFForIdList(MainTableRef.GetColumnReference(IDCOLUMN_NAME), OclCondition.Context)); - end; + end else if VarBinding.IsExternal and (VarBinding.TopSortedIndex > -1) then + begin + VarBinding.NewQuery(NameSpace); + + MainTableRef := VarBinding.TableReferenceForTable(VarBinding.ObjectMapper.MainTable, VarBinding.Query, true); + VarBinding.Context := TBoldObjectIdList.Create; + aVariableIDLists.Add(VarBinding.Context); + BoldID := TBoldDefaultID.CreateWithClassID(VarBinding.ObjectMapper.TopSortedIndex, True); + BoldID.AsInteger := VarBinding.ExternalVarvalue; + VarBinding.Context.AddAndAdopt(BoldID); + VarBinding.Query.AddWCF(TBoldSQLWCFBinaryInfix.CreateWCFForIdList(MainTableRef.GetColumnReference(IDCOLUMN_NAME), VarBinding.Context)); + end; end; begin @@ -2361,8 +3254,14 @@ procedure TBoldSystemDefaultMapper.PMFetchClassWithCondition( GlobalNameSpace := nil; SQLNodeMaker := nil; q2 := GetQuery; + if q2.QueryInterface(IBoldParameterized, vBoldParameterized) = S_OK then + begin + vBoldParameterized.ParamCheck := false; + vBoldParameterized := nil; + end; sql := TStringList.Create; OclCondition := BoldCondition as TBoldOclCondition; + aVariableIDLists := TBoldObjectArray.Create(0, [bcoDataOwner]); try SQLNodeMaker := TBoldSQlNodeMaker.Create(OclCondition); SQLNodeMaker.Execute; @@ -2385,7 +3284,10 @@ procedure TBoldSystemDefaultMapper.PMFetchClassWithCondition( Q2.AssignSQL(sql); Q2.AssignParams(SQLNodeMaker.RootNode.Query.Params); - BoldCondition.AvailableAnswers := GetListUsingQuery(ObjectIdList, ValueSpace, Q2, FetchMode, TranslationList, BOLDMAXTIMESTAMP, BoldCondition.MaxAnswers, BoldCondition.Offset); + if Assigned(OnPsEvaluate) then + OnPsEvaluate(Q2); + + BoldCondition.AvailableAnswers := GetListUsingQuery(ObjectIdList, ValueSpace, Q2, NO_CLASS, 1, 0, FetchMode, TranslationList, BOLDMAXTIMESTAMP, BoldCondition.MaxAnswers, BoldCondition.Offset); finally ReleaseQuery(q2); sql.Free; @@ -2393,6 +3295,7 @@ procedure TBoldSystemDefaultMapper.PMFetchClassWithCondition( SQlNodeResolver.free; GlobalNameSpace.Free; SQLNodeMaker.Free; + aVariableIDLists.Free; end; end else if BoldCondition is TBoldChangePointCondition then @@ -2409,7 +3312,7 @@ procedure TBoldSystemDefaultMapper.PMFetchClassWithCondition( q2 := GetQuery; try GetChangePointsQuery(q2, aCPCond.IdList, aCPCond.StartTime, aCPCond.EndTime, GlobalNameSpace); - BoldCondition.AvailableAnswers := GetListUsingQuery(ObjectIdList, ValueSpace, Q2, FetchMode, TranslationList, BOLDINVALIDTIMESTAMP, BoldCondition.MaxAnswers, BoldCondition.Offset); + BoldCondition.AvailableAnswers := GetListUsingQuery(ObjectIdList, ValueSpace, Q2, NO_CLASS, 1, 0, FetchMode, TranslationList, BOLDINVALIDTIMESTAMP, BoldCondition.MaxAnswers, BoldCondition.Offset); (CommonSuperClassObjectMapper(aCPCond.IdList) as TBoldObjectDefaultMapper).GetChangePoints(ObjectIdList, aCPCond, GlobalNameSpace); finally ReleaseQuery(q2); @@ -2466,7 +3369,7 @@ procedure TBoldObjectDefaultMapper.GetChangePoints( (MemberPersistenceMappers[MemberMapperIndexByMemberIndex[Condition.MemberIdList[i].MemberIndex]] as TBoldMemberDefaultMapper).GetChangePoints(ObjectIdList, Condition, NameSpace); end; -function TBoldMemberDefaultMapper.CompareFields(ObjectContent: IBoldObjectContents; DataSet: IBoldDataSet; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList): Boolean; +function TBoldMemberDefaultMapper.CompareFields(const ObjectContent: IBoldObjectContents; const DataSet: IBoldDataSet; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList): Boolean; var aField : IBoldField; ColumnIndex: Integer; @@ -2476,22 +3379,25 @@ function TBoldMemberDefaultMapper.CompareFields(ObjectContent: IBoldObjectConten begin for ColumnIndex := 0 to ColumnCount - 1 do begin - aField := DataSet.FieldByName(ColumnDescriptions[ColumnIndex].SQLName); + aField := DataSet.FieldByUpperCaseName(ColumnDescriptions[ColumnIndex].SQLNameUpper); if Assigned(aField) then begin if not CompareField(ObjectContent, aField, ColumnIndex, ValueSpace, TranslationList) then begin - BoldLog.LogFmt(sOptimisticLockingFailed, + BoldLog.LogFmt('Optimistic Locking Failed for %s.%s (ID: %s) Column %d [%s] ValueInDb:%s InMemTimestamp: %d', [ObjectPersistenceMapper.ExpressionName, ExpressionName, ObjectContent.ObjectId.AsString, ColumnIndex, - ColumnDescriptions[ColumnIndex].SQLName]); + ColumnDescriptions[ColumnIndex].SQLName, + aField.AsString, + ObjectContent.Timestamp] + ); result := false; end; end else - raise EBoldInternal.CreateFmt(sSomeColumnsNotInTable, [classname, 'CompareFields', ColumnIndex, ColumnDescriptions[ColumnIndex].SQLName]); // do not localize + raise EBoldInternal.CreateFmt('%s.CompareFields: Some columns not found in table (%d:%s)', [classname, ColumnIndex, ColumnDescriptions[ColumnIndex].SQLName]); end; end; end; @@ -2499,7 +3405,7 @@ function TBoldMemberDefaultMapper.CompareFields(ObjectContent: IBoldObjectConten procedure TBoldMemberDefaultMapper.GetChangePoints( ObjectIDList: TBoldObjectIdList; Condition: TBoldChangePointCondition; NameSpace: TBoldSqlnameSpace); begin - raise EBold.CreateFmt(sNotSupportedOnMember, [classname]); + raise EBold.CreateFmt('%s.GetChangePoints: not supported on this member', [classname]); end; procedure TBoldSystemDefaultMapper.PMTimeForTimestamp( @@ -2510,13 +3416,13 @@ procedure TBoldSystemDefaultMapper.PMTimeForTimestamp( aQuery := GetQuery; try aQuery.AssignSQLText( - format('SELECT %s FROM %s WHERE :time1 >= %s and :time2 < %s', [ // do not localize + format('SELECT %s FROM %s WHERE :time1 >= %s and :time2 < %s', [ ClockLogTableLastClockColumn.SQLname, PSSystemDescription.ClockLogTable.SQLName, ClockLogTableLastTimeStampColumn.SQLName, ClockLogTableThisTimeStampColumn.SQLName])); - aQuery.ParamByName('time1').AsInteger := Timestamp; // do not localize - aQuery.ParamByName('time2').AsInteger := Timestamp; // do not localize + aQuery.ParamByName('time1').AsInteger := Timestamp; + aQuery.ParamByName('time2').AsInteger := Timestamp; aQuery.Open; if not aQuery.EOF then ClockTime := aQuery.Fields[0].AsDateTime @@ -2536,13 +3442,13 @@ procedure TBoldSystemDefaultMapper.PMTimestampForTime(ClockTime: TDateTime; aQuery := GetQuery; try aQuery.AssignSQLText( - Format('SELECT %s FROM %s WHERE :time1 > %s and :time2 <= %s', [ // do not localize + Format('SELECT %s FROM %s WHERE :time1 > %s and :time2 <= %s', [ ClockLogTableThisTimeStampColumn.SQLName, PSSystemDescription.ClockLogTable.SQLName, ClockLogTableLastClockColumn.SQLname, ClockLogTableThisClockColumn.SQLname])); - aQuery.ParamByName('time1').AsDateTime := ClockTime; // do not localize - aQuery.ParamByName('time2').AsDateTime := ClockTime; // do not localize + aQuery.ParamByName('time1').AsDateTime := ClockTime; + aQuery.ParamByName('time2').AsDateTime := ClockTime; aQuery.Open; if not aQuery.EOF then Timestamp := aQuery.Fields[0].AsInteger @@ -2559,11 +3465,6 @@ function TBoldMemberDefaultMapper.SupportsComparingWithoutValue: Boolean; result := false; end; -function TBoldMemberDefaultMapper.GetObjectPersistenceMapper: TBoldObjectDefaultMapper; -begin - result := (inherited ObjectPersistenceMapper) as TBoldObjectDefaultMapper; -end; - { EBoldOptimisticLockingFailed } constructor EBoldOptimisticLockingFailed.Create(msg: string; args: array of const; FailedObjects: TBoldObjectIdList); @@ -2571,8 +3472,28 @@ constructor EBoldOptimisticLockingFailed.Create(msg: string; args: array of cons inherited Create(Msg, Args, FailedObjects); end; +destructor TBoldObjectDefaultMapper.Destroy; +var + i: integer; +begin + for I := 0 to Length(fQueryCache) - 1 do + begin + fQueryCache[i].SqlStrings.Free; + fQueryCache[i].MemberList.Free; + fQueryCache[i].MemberPMList.Free; + fQueryCache[i].CustomMembers.Free; + end; + for I := 0 to Length(fPMCreateCache) - 1 do + begin + fPMCreateCache[i].SqlStrings.Free; + fPMCreateCache[i].MemberPMList.Free; + end; + fSingleLinkList.free; + inherited; +end; + procedure TBoldObjectDefaultMapper.DetectLinkClassDuplicates( - ObjectIdList: TBoldObjectidList; ValueSpace: IBoldvalueSpace; + ObjectIdList: TBoldObjectidList; const ValueSpace: IBoldvalueSpace; TranslationList: TBoldIdTranslationList; DuplicateList: TBoldObjectIdList); var @@ -2598,10 +3519,8 @@ procedure TBoldObjectDefaultMapper.DetectLinkClassDuplicates( LinkMapper1 := (LinkClassRole1 as TBoldEmbeddedSingleLinkDefaultMapper); LinkMapper2 := (LinkClassRole2 as TBoldEmbeddedSingleLinkDefaultMapper); - // if we find a linkobject that links the same two objects as one of the new, - // translate the new object to the old object. - QueryText := format('SELECT %s, %s FROM %s WHERE (%s = %%s) AND (%s = %%s)', [ // do not localize + QueryText := format('SELECT %s, %s FROM %s WHERE (%s = %%s) AND (%s = %%s)', [ IDCOLUMN_NAME, TYPECOLUMN_NAME, MainTable.SQLName, LinkMapper1.MainColumnName, LinkMapper2.MainColumnName]); @@ -2612,8 +3531,6 @@ procedure TBoldObjectDefaultMapper.DetectLinkClassDuplicates( LinkObject := ValueSpace.EnsuredObjectContentsByObjectId[ObjectIdList[i]]; Id1 := (LinkMapper1.GetValue(LinkObject) as IBoldObjectIdRef).Id; Id2 := (LinkMapper2.GetValue(LinkObject) as IBoldObjectIdRef).Id; - - // if either object is new, then this can not be a dupe if not (ObjectisNew(Id1) or ObjectIsNew(Id2)) then begin if assigned(Id1) then @@ -2621,8 +3538,6 @@ procedure TBoldObjectDefaultMapper.DetectLinkClassDuplicates( if assigned(Id2) then Id2 := TranslationList.TranslateToNewId[Id2]; - // if the linkobject is broken (doesn't have 2 IDs) or is pointing to objects that are deleted, - // then we will get an inconsistent database later, but lets not get an AV here... if assigned(Id1) and assigned(Id2) then begin @@ -2630,15 +3545,9 @@ procedure TBoldObjectDefaultMapper.DetectLinkClassDuplicates( Query.open; if not query.Eof then begin - OldLinkObjectId := SystemPersistenceMapper.NewIdFromQuery(Query, 1, 0, BOLDMAXTIMESTAMP); - try - // the new linkobject has already received a translation to its persistent ID - // we need to add a translation from that ID to the existing link objectid - TranslationList.addTranslation(TranslationList.TranslateToNewId[ObjectIdList[i]], OldLinkObjectId); - DuplicateList.Add(ObjectIdList[i]); - finally - OldLinkObjectId.Free; - end; + OldLinkObjectId := SystemPersistenceMapper.NewIdFromQuery(Query, NO_CLASS, 1, 0, BOLDMAXTIMESTAMP); + TranslationList.addTranslationAdoptNew(TranslationList.TranslateToNewId[ObjectIdList[i]], OldLinkObjectId); + DuplicateList.Add(ObjectIdList[i]); end; Query.Close; end; @@ -2650,8 +3559,8 @@ procedure TBoldObjectDefaultMapper.DetectLinkClassDuplicates( end; end; -function TBoldMemberDefaultMapper.CheckEitherNull(field: IBoldField; - Value: IBoldValue; var Equal: Boolean): Boolean; +function TBoldMemberDefaultMapper.CheckEitherNull(const field: IBoldField; + const Value: IBoldValue; var Equal: Boolean): Boolean; begin Equal := false; result := false; @@ -2686,7 +3595,8 @@ procedure TBoldMemberDefaultMapper.InitializePSDescriptions; Columns := TStringList.Create; Columns.CommaText := MemberMappings[0].Columns; if Columns.Count <> ColumnCount then - raise EBold.CreateFmt(sUnsupportedMappingChange, [ObjectPersistenceMapper.ExpressionName, ExpressionName]); + raise EBold.CreateFmt('Database Mapping has changed in an unsupported way for %s.%s. Number of columns has changed', [ObjectPersistenceMapper.ExpressionName, ExpressionName]); + ColumnDescriptions.Capacity := ObjectPersistenceMapper.MemberPersistenceMappers.Count; for i := 0 to Columns.Count - 1 do ColumnDescriptions.Add( SystemPersistenceMapper.EnsureColumn(MemberMappings[0].TableName, @@ -2696,17 +3606,23 @@ procedure TBoldMemberDefaultMapper.InitializePSDescriptions; ColumnBDEFieldType[i], ColumnSize[i], AllowNull, - ObjectPersistenceMapper.Versioned, // ??? is this really right? is it not supposed to be the mapper of the class that defines the attribute? - Yes, in theory. In practice it makes no difference. + ObjectPersistenceMapper.Versioned, DefaultDbValue)); +{$IFDEF IndexColumn} + if MemberMappings[0].ColumnIndex then begin + for i := 0 to Columns.Count - 1 do + SystemPersistenceMapper.EnsureIndex(MemberMappings[0].TableName, + Columns[i], False, False, True, False); + end; +{$ENDIF} end else if (length(memberMappings) = 0) and RequiresMemberMapping then - raise EBold.CreateFmt(sUnableToFindMappingForX, [ObjectPersistenceMapper.ExpressionName, ExpressionName]); + raise EBoldMissingID.CreateFmt('Unable to find database mapping for %s.%s', [ObjectPersistenceMapper.ExpressionName, ExpressionName]); end; procedure TBoldObjectDefaultMapper.InitializePSDescriptions; begin - // it is important that the x-files table come before the other tables - // (and in general that the tables for a superclass comes before the tables of a subclass) + if SystemPersistenceMapper.UseXFiles then AllTables.Add(SystemPersistenceMapper.PSSystemDescription.XFilestable); @@ -2715,13 +3631,10 @@ procedure TBoldObjectDefaultMapper.InitializePSDescriptions; if not assigned(SuperClass) then SystemPersistenceMapper.PSSystemDescription.RootTable := MainTable; - // the starttimestamp column is added in EnsureTable - // root class needs to have a stopcolumn as well... if Versioned and (self = SystemPersistenceMapper.RootClassObjectPersistenceMapper) then begin SystemPersistenceMapper.EnsureColumn(MainTable.SQLName, TIMESTAMPSTOPCOLUMNNAME, SystemPersistenceMapper.SQLDataBaseConfig.ColumnTypeForInteger, SystemPersistenceMapper.SQLDataBaseConfig.EffectiveSQLforNotNull, BOLDTIMESTAMPFIELDTYPE, 0, true, true, SystemPersistenceMapper.SQLDataBaseConfig.CorrectlyQuotedDefaultValue(intTostr(BOLDMAXTIMESTAMP))); - // the following index improves performance alot in Interbase, and seems to have no negative impact in SQLServer. - MainTable.EnsureIndex(TIMESTAMPSTOPCOLUMNNAME, false, false); + MainTable.EnsureIndex(TIMESTAMPSTOPCOLUMNNAME, false, false, false); MainTable.ContainsStopTimeStamp := true; end; end; @@ -2733,26 +3646,21 @@ procedure TBoldSystemDefaultMapper.InitializePSDescriptions; DefaultStringLength: integer; begin DefaultStringLength := SQLDataBaseConfig.DefaultStringLength; - // inherited is called at the end to ensure that systemtables are available to other parts of initialization - - // Create BOLD_ID + PSSystemDescription.SQLTablesList.Capacity := ObjectPersistenceMappers.Count + 10; PSSystemDescription.IdTable := TBoldSQLTableDescription.Create(PSSystemDescription, false); PSSystemDescription.IdTable.SQLName := IDTABLE_NAME; PSSystemDescription.IdTable.AddColumn(IDCOLUMN_NAME, SQLDataBaseConfig.ColumnTypeForInteger, SQLDataBaseConfig.EffectiveSQLforNotNull, IDCOLUMN_TYPE, 0, False, ''); - - // Create BOLD_TYPES PSSystemDescription.TypeTable := TBoldSQLTableDescription.Create(PSSystemDescription, false); PSSystemDescription.TypeTable.SQLName := TYPETABLE_NAME; PSSystemDescription.TypeTable.AddColumn(TYPECOLUMN_NAME, SQLDataBaseConfig.ColumnTypeForSmallInt, SQLDataBaseConfig.EffectiveSQLforNotNull, TYPECOLUMN_TYPE, 0, False, ''); PSSystemDescription.TypeTable.AddColumn(CLASSNAMECOLUMN_NAME, format(SQLDataBaseConfig.ColumnTypeForString, [DefaultStringLength]), SQLDataBaseConfig.EffectiveSQLforNotNull, ftString, DefaultStringLength, False, ''); - if UseXFiles then begin PSSystemDescription.XFilesTable := TBoldSQLTableDescription.Create(PSSystemDescription, false); - PSSystemDescription.XFilesTable.SQLName := TABLEPREFIXTAG + '_XFILES'; // do not localize + PSSystemDescription.XFilesTable.SQLName := TABLEPREFIXTAG + '_XFILES'; PSSystemDescription.XFilesTable.AddColumn(IDCOLUMN_NAME, SQLDataBaseConfig.ColumnTypeForInteger, SQLDataBaseConfig.EffectiveSQLforNotNull, IDCOLUMN_TYPE, 0, False, ''); PSSystemDescription.XFilesTable.AddColumn(TYPECOLUMN_NAME, SQLDataBaseConfig.ColumnTypeForSmallInt, SQLDataBaseConfig.EffectiveSQLforNotNull, TYPECOLUMN_TYPE, 0, False, ''); - PSSystemDescription.XFilesTable.EnsureIndex(IDCOLUMN_NAME, true, true); + PSSystemDescription.XFilesTable.EnsureIndex(IDCOLUMN_NAME, true, true, false); if UseGlobalId then fXFilesGlobalIdColumn := PSSystemDescription.XFilesTable.AddColumn(GLOBALIDCOLUMN_NAME, format(SQLDataBaseConfig.ColumnTypeForString, [DefaultStringLength]), SQLDataBaseConfig.EffectiveSQLforNotNull, ftString, DefaultStringLength, False, ''); if UseTimestamp then @@ -2792,7 +3700,9 @@ procedure TBoldSystemDefaultMapper.InitializePSDescriptions; PSSystemDescription.MemberMappingTable.AddColumn(MMT_TABLENAME_COLUMN, format(SQLDataBaseConfig.ColumnTypeForString, [MappingStringLength]), SQLDataBaseConfig.EffectiveSQLforNotNull, ftString, MappingStringLength, False, ''); PSSystemDescription.MemberMappingTable.AddColumn(MMT_COLUMNS_COLUMN, format(SQLDataBaseConfig.ColumnTypeForString, [MappingStringLength]), SQLDataBaseConfig.EffectiveSQLforNotNull, ftString, MappingStringLength, False, ''); PSSystemDescription.MemberMappingTable.AddColumn(MMT_MAPPERNAME_COLUMN, format(SQLDataBaseConfig.ColumnTypeForString, [MappingStringLength]), SQLDataBaseConfig.EffectiveSQLforNotNull, ftString, MappingStringLength, False, ''); - +{$IFDEF IndexColumn} + PSSystemDescription.MemberMappingTable.AddColumn(MMT_INDEX_COLUMN, SQLDataBaseConfig.ColumnTypeForInteger, SQLDataBaseConfig.EffectiveSQLforNotNull, ftBoolean, 0, False, ''); +{$ENDIF} PSSystemDescription.AllInstancesMappingTable := TBoldSQLTableDescription.Create(PSSystemDescription, false); PSSystemDescription.AllInstancesMappingTable.SQLName := AllInstancesMappingTable_NAME; PSSystemDescription.AllInstancesMappingTable.AddColumn(AID_CLASSNAME_COLUMN, format(SQLDataBaseConfig.ColumnTypeForString, [MappingStringLength]), SQLDataBaseConfig.EffectiveSQLforNotNull, ftString, MappingStringLength, False, ''); @@ -2806,11 +3716,6 @@ procedure TBoldSystemDefaultMapper.InitializePSDescriptions; inherited; end; -function TBoldMemberDefaultMapper.GetSystemPersistenceMapper: TBoldSystemDefaultMapper; -begin - result := inherited SystemPersistenceMapper as TBoldSystemDefaultMapper; -end; - function TBoldMemberDefaultMapper.RequiresMemberMapping: Boolean; begin result := ColumnCount > 0; @@ -2842,17 +3747,16 @@ function TBoldSingleColumnMember.GetColumnSize(ColumnIndex: Integer): Integer; class procedure TBoldSingleColumnMember.EnsureFirstColumn(ColumnIndex: Integer); begin if ColumnIndex <> 0 then - raise EBoldBadColumnIndex.CreateFmt(sIllegalColumnIndex, [ClassName, 'EnsureFirstColumn', ColumnIndex]); // do not localize + raise EBoldBadColumnIndex.CreateFmt('%s: Illegal Column Index (%d)', [ClassName, ColumnIndex]); end; { TBoldModelVersionMember } function TBoldModelVersionMember.CompareField( - ObjectContent: IBoldObjectContents; Field: IBoldField; ColumnIndex: integer; - ValueSpace: IBoldValueSpace; + const ObjectContent: IBoldObjectContents; const Field: IBoldField; ColumnIndex: integer; + const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList): Boolean; begin -// actually this method is irrelevant result := true; end; @@ -2892,50 +3796,55 @@ function TBoldModelVersionMember.GetColumnTypeAsSQL(ColumnIndex: Integer): strin end; function TBoldModelVersionMember.IsDirty( - ObjectContents: IBoldObjectContents): Boolean; + const ObjectContents: IBoldObjectContents): Boolean; begin result := true; end; function TBoldModelVersionMember.ShouldFetch( - ObjectContents: IBoldObjectContents): Boolean; + const ObjectContents: IBoldObjectContents): Boolean; begin - // in an environment that uses ModelVersion, - // it must always be fetched so that an automatic update can be performed + result := true; end; +function TBoldModelVersionMember.ValueAsVariant( + const ObjectContent: IBoldObjectContents; ColumnIndex: Integer; + TranslationList: TBoldIdTranslationList): variant; +begin + result := VersionNumber; +end; + procedure TBoldModelVersionMember.ValueFromField( - OwningObjectId: TBoldObjectId; ObjectContent: IBoldObjectContents; - ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; - Field: IBoldField; ColumnIndex: Integer); + OwningObjectId: TBoldObjectId; const ObjectContent: IBoldObjectContents; + const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; + const Field: IBoldField; ColumnIndex: Integer); begin -// do nothing end; procedure TBoldModelVersionMember.ValueToParam( - ObjectContent: IBoldObjectContents; Param: IBoldParameter; + const ObjectContent: IBoldObjectContents; const Param: IBoldParameter; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList); begin Param.AsInteger := VersionNumber; end; -function TBoldModelVersionMember.VersionFromQuery(Query: IBoldQuery): Integer; +function TBoldModelVersionMember.VersionFromQuery(const Query: IBoldQuery): Integer; var aField: IBoldField; begin - aField := Query.FieldByName(ColumnDescriptions[0].SQLName); + aField := Query.FieldByUpperCaseName(ColumnDescriptions[0].SQLNameUpper); if assigned(aField) then result := aField.AsInteger else - raise EBoldInternal.CreateFmt(sColumnNotFoundInTable, [classname, ColumnDescriptions[0].SQLName]); + raise EBoldInternal.CreateFmt('%s.VersionFromQuery: Column not found in table (%s)', [classname, ColumnDescriptions[0].SQLName]); end; { TBoldReadOnlynessMember } function TBoldReadOnlynessMember.CompareField( - ObjectContent: IBoldObjectContents; Field: IBoldField; ColumnIndex: integer; - ValueSpace: IBoldValueSpace; + const ObjectContent: IBoldObjectContents; const Field: IBoldField; ColumnIndex: integer; + const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList): Boolean; begin result := true; @@ -2977,35 +3886,40 @@ function TBoldReadOnlynessMember.GetColumnTypeAsSQL( end; function TBoldReadOnlynessMember.IsDirty( - ObjectContents: IBoldObjectContents): Boolean; + const ObjectContents: IBoldObjectContents): Boolean; begin result := false; end; function TBoldReadOnlynessMember.ShouldFetch( - ObjectContents: IBoldObjectContents): Boolean; + const ObjectContents: IBoldObjectContents): Boolean; begin result := true; end; +function TBoldReadOnlynessMember.ValueAsVariant( + const ObjectContent: IBoldObjectContents; ColumnIndex: Integer; + TranslationList: TBoldIdTranslationList): variant; +begin + result := 0; +end; + procedure TBoldReadOnlynessMember.ValueFromField( - OwningObjectId: TBoldObjectId; ObjectContent: IBoldObjectContents; - ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; - Field: IBoldField; ColumnIndex: Integer); + OwningObjectId: TBoldObjectId; const ObjectContent: IBoldObjectContents; + const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; + const Field: IBoldField; ColumnIndex: Integer); begin ObjectContent.SetIsReadOnly(field.AsInteger = 1); end; procedure TBoldReadOnlynessMember.ValueToParam( - ObjectContent: IBoldObjectContents; Param: IBoldParameter; + const ObjectContent: IBoldObjectContents; const Param: IBoldParameter; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList); begin - // since IsDirty is false, this will only happen on Create or - // when using UpdateWholeObjects (which is a bad thing...) Param.AsInteger := 0; end; -function TBoldObjectDefaultMapper.IsOldVersion(Query: IBoldQuery): Boolean; +function TBoldObjectDefaultMapper.IsOldVersion(const Query: IBoldQuery): Boolean; var CurrentObjectVersion: integer; begin @@ -3014,7 +3928,7 @@ function TBoldObjectDefaultMapper.IsOldVersion(Query: IBoldQuery): Boolean; SystemPersistenceMapper.ObjectUpgrader.NeedsManualUpdate(ExpressionName, CurrentObjectVersion); end; -procedure TBoldObjectDefaultMapper.PortObject(ObjectId: TBoldObjectId; Query: IBoldQuery); +procedure TBoldObjectDefaultMapper.PortObject(ObjectId: TBoldObjectId; const Query: IBoldQuery); begin if assigned(SystemPersistenceMapper.ObjectUpgrader) then SystemPersistenceMapper.ObjectUpgrader.UpgradeObjectById(ObjectId, Query); @@ -3024,14 +3938,14 @@ procedure TBoldObjectDefaultMapper.PortObject(ObjectId: TBoldObjectId; Query: IB { TBoldTimeStampMember } function TBoldTimeStampMember.CompareField( - ObjectContent: IBoldObjectContents; Field: IBoldField; - ColumnIndex: integer; ValueSpace: IBoldValueSpace; + const ObjectContent: IBoldObjectContents; const Field: IBoldField; + ColumnIndex: integer; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList): Boolean; begin if ColumnIndex = 0 then result := Field.AsInteger = ObjectContent.TimeStamp else - raise EBold.CreateFmt(sIllegalColumnIndex, [classname, 'CompareField', ColumnIndex]); // do not localize + raise EBold.CreateFmt('%s.CompareField: invalid columnIndex (%d)', [classname, ColumnIndex]); end; constructor TBoldTimeStampMember.CreateFromMold(moldMember: TMoldMember; @@ -3050,10 +3964,9 @@ constructor TBoldTimeStampMember.CreateFromMold(moldMember: TMoldMember; function TBoldTimeStampMember.FindDefiningTable(LocalMoldClass: TMoldClass; MoldMember: TMoldMember): string; begin - // unfortunately, it is too early to call the - // SystemPersistenceMapper.XFilesTable.SQLName since it would create the - // PSDescriptions before all the Mappers are in place. - result := BoldExpandPrefix(TABLEPREFIXTAG + '_XFILES', '', SystemPersistenceMapper.SQLDatabaseConfig.SystemTablePrefix, SystemPersistenceMapper.SQLDataBaseConfig.MaxDBIdentifierLength, SystemPersistenceMapper.NationalCharConversion); // do not localize + + + result := BoldExpandPrefix(TABLEPREFIXTAG + '_XFILES', '', SystemPersistenceMapper.SQLDatabaseConfig.SystemTablePrefix, SystemPersistenceMapper.SQLDataBaseConfig.MaxDBIdentifierLength, SystemPersistenceMapper.NationalCharConversion); end; function TBoldTimeStampMember.GetColumnBDEFieldType(ColumnIndex: Integer): TFieldType; @@ -3067,14 +3980,13 @@ function TBoldTimeStampMember.GetColumnTypeAsSQL(ColumnIndex: Integer): string; end; -function TBoldTimeStampMember.IsDirty(ObjectContents: IBoldObjectContents): Boolean; +function TBoldTimeStampMember.IsDirty(const ObjectContents: IBoldObjectContents): Boolean; begin result := true; end; -function TBoldTimeStampMember.ShouldFetch(ObjectContents: IBoldObjectContents): Boolean; +function TBoldTimeStampMember.ShouldFetch(const ObjectContents: IBoldObjectContents): Boolean; begin - // the timestamp should only be loaded if the object uses timestamp-mode for optimistic locking result := ObjectPersistenceMapper.fOptimisticLockingMode = bolmTimeStamp; end; @@ -3083,16 +3995,22 @@ function TBoldTimeStampMember.SupportsComparingWithoutValue: Boolean; result := true; end; +function TBoldTimeStampMember.ValueAsVariant(const ObjectContent: IBoldObjectContents; + ColumnIndex: Integer; TranslationList: TBoldIdTranslationList): variant; +begin + result := SystemPersistenceMapper.CurrentTimeStamp;; +end; + procedure TBoldTimeStampMember.ValueFromField( - OwningObjectId: TBoldObjectId; ObjectContent: IBoldObjectContents; - ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; - Field: IBoldField; ColumnIndex: Integer); + OwningObjectId: TBoldObjectId; const ObjectContent: IBoldObjectContents; + const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; + const Field: IBoldField; ColumnIndex: Integer); begin ObjectContent.TimeStamp := Field.AsInteger; end; procedure TBoldTimeStampMember.ValueToParam( - ObjectContent: IBoldObjectContents; Param: IBoldParameter; + const ObjectContent: IBoldObjectContents; const Param: IBoldParameter; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList); begin Param.AsInteger := SystemPersistenceMapper.CurrentTimeStamp; @@ -3101,8 +4019,8 @@ procedure TBoldTimeStampMember.ValueToParam( { TBoldGlobalIdMember } function TBoldGlobalIdMember.CompareField( - ObjectContent: IBoldObjectContents; Field: IBoldField; - ColumnIndex: integer; ValueSpace: IBoldValueSpace; + const ObjectContent: IBoldObjectContents; const Field: IBoldField; + ColumnIndex: integer; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList): Boolean; begin result := true; @@ -3117,7 +4035,7 @@ constructor TBoldGlobalIdMember.CreateFromMold(moldMember: TMoldMember; fDefaultDbValue := ''; fAllowNull := false; fDelayedFetch := true; - fContentName := 'String'; // do not localize + fContentName := 'String'; fIsStoredInObject := true; fInitialColumnRootName := GLOBALIDCOLUMN_NAME; inherited; @@ -3125,10 +4043,9 @@ constructor TBoldGlobalIdMember.CreateFromMold(moldMember: TMoldMember; function TBoldGlobalIdMember.FindDefiningTable(LocalMoldClass: TMoldClass; MoldMember: TMoldMember): string; begin - // unfortunately, it is too early to call the - // SystemPersistenceMapper.XFilesTable.SQLName since it would create the - // PSDescriptions before all the Mappers are in place. - result := BoldExpandPrefix(TABLEPREFIXTAG + '_XFILES', '', SystemPersistenceMapper.SQLDatabaseConfig.SystemTablePrefix, SystemPersistenceMapper.SQLDataBaseConfig.MaxDBIdentifierLength, SystemPersistenceMapper.NationalCharConversion); // do not localize + + + result := BoldExpandPrefix(TABLEPREFIXTAG + '_XFILES', '', SystemPersistenceMapper.SQLDatabaseConfig.SystemTablePrefix, SystemPersistenceMapper.SQLDataBaseConfig.MaxDBIdentifierLength, SystemPersistenceMapper.NationalCharConversion); end; function TBoldGlobalIdMember.GetColumnBDEFieldType(ColumnIndex: Integer): TFieldType; @@ -3138,32 +4055,39 @@ function TBoldGlobalIdMember.GetColumnBDEFieldType(ColumnIndex: Integer): TField function TBoldGlobalIdMember.GetColumnTypeAsSQL(ColumnIndex: Integer): string; begin - // {F4252AB4-8FFA-460F-BDBD-1BB57D588D14} result := format(SystemPersistenceMapper.SQLDataBaseConfig.ColumnTypeForString, [39]); end; function TBoldGlobalIdMember.IsDirty( - ObjectContents: IBoldObjectContents): Boolean; + const ObjectContents: IBoldObjectContents): Boolean; begin result := false; end; -function TBoldGlobalIdMember.ShouldFetch(ObjectContents: IBoldObjectContents): Boolean; +function TBoldGlobalIdMember.ShouldFetch(const ObjectContents: IBoldObjectContents): Boolean; begin result := false; end; +function TBoldGlobalIdMember.ValueAsVariant(const ObjectContent: IBoldObjectContents; + ColumnIndex: Integer; TranslationList: TBoldIdTranslationList): variant; +begin + result := ObjectContent.GlobalId; + if result = '' then + result := ExternalIdGenerator; +end; + procedure TBoldGlobalIdMember.ValueFromField(OwningObjectId: TBoldObjectId; - ObjectContent: IBoldObjectContents; ValueSpace: IBoldValueSpace; - TranslationList: TBoldIdTranslationList; Field: IBoldField; + const ObjectContent: IBoldObjectContents; const ValueSpace: IBoldValueSpace; + TranslationList: TBoldIdTranslationList; const Field: IBoldField; ColumnIndex: Integer); begin ObjectContent.GlobalId := Field.AsString; end; procedure TBoldGlobalIdMember.ValueToParam( - ObjectContent: IBoldObjectContents; Param: IBoldParameter; + const ObjectContent: IBoldObjectContents; const Param: IBoldParameter; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList); var GlobalId: String; @@ -3182,7 +4106,6 @@ procedure TBoldXFilesMembers.InitializePSDescriptions; i: integer; begin inherited; - // since these members do not require membermappings... they have to build their PSDesc manually if ColumnDescriptions.Count = 0 then begin for i := 0 to ColumnCount - 1 do @@ -3199,6 +4122,105 @@ function TBoldXFilesMembers.RequiresMemberMapping: Boolean; result := false; end; +{ TBoldNonXFileTimeStampMember } + +function TBoldNonXFileTimeStampMember.CompareField( + const ObjectContent: IBoldObjectContents; const Field: IBoldField; ColumnIndex: integer; + const ValueSpace: IBoldValueSpace; + TranslationList: TBoldIdTranslationList): Boolean; +begin + if ColumnIndex = 0 then + result := Field.AsInteger = ObjectContent.TimeStamp + else + raise EBold.CreateFmt('%s.CompareField: invalid columnIndex (%d)', [classname, ColumnIndex]); + +end; + +constructor TBoldNonXFileTimeStampMember.CreateFromMold(moldMember: TMoldMember; + moldClass: TMoldClass; Owner: TBoldObjectPersistenceMapper; + const MemberIndex: Integer; TypeNameDictionary: TBoldTypeNameDictionary); +begin + fExpressionname := '_' + TIMESTAMPCOLUMN_NAME; + fDefaultDbValue := ''; + fAllowNull := false; + fDelayedFetch := MoldClass.EffectiveOptimisticLocking <> bolmTimeStamp; + fContentName := ''; + fIsStoredInObject := true; + fInitialColumnRootName := TIMESTAMPCOLUMN_NAME; + inherited CreateFromMold(MoldMember, MoldClass, Owner, TIMESTAMPMEMBERINDEX, TypeNameDictionary); +end; + +function TBoldNonXFileTimeStampMember.FindDefiningTable( + LocalMoldClass: TMoldClass; MoldMember: TMoldMember): string; +var + TopClassWithOwnTable, RootClass, C: TMoldClass; +begin + TopClassWithOwnTable := nil; + RootClass := LocalMoldClass.Model.RootClass; + C := LocalMoldClass; + while C <> RootClass do + begin + if C.TableMapping = tmOwn then + TopClassWithOwnTable := C; + Assert(Assigned(C.SuperClass), C.name); + C := C.SuperClass; + end; + if not Assigned(TopClassWithOwnTable) then + raise Exception.Create('No table found for timestamp for class: ' + LocalMoldClass.name); + result := BoldExpandPrefix(TopClassWithOwnTable.TableName, TopClassWithOwnTable.Name, SystemPersistenceMapper.SQLDatabaseConfig.SystemTablePrefix, SystemPersistenceMapper.SQLDataBaseConfig.MaxDbIdentifierLength, RootClass.Model.NationalCharConversion); +end; + +function TBoldNonXFileTimeStampMember.GetColumnBDEFieldType( + ColumnIndex: Integer): TFieldType; +begin + result := BOLDTIMESTAMPFIELDTYPE; +end; + +function TBoldNonXFileTimeStampMember.GetColumnTypeAsSQL( + ColumnIndex: Integer): string; +begin + result := SystemPersistenceMapper.SQLDataBaseConfig.ColumnTypeForInteger; +end; + +function TBoldNonXFileTimeStampMember.IsDirty( + const ObjectContents: IBoldObjectContents): Boolean; +begin + result := true; +end; + +function TBoldNonXFileTimeStampMember.ShouldFetch( + const ObjectContents: IBoldObjectContents): Boolean; +begin + result := ObjectPersistenceMapper.fOptimisticLockingMode = bolmTimeStamp; +end; + +function TBoldNonXFileTimeStampMember.SupportsComparingWithoutValue: Boolean; +begin + result := true; +end; + +function TBoldNonXFileTimeStampMember.ValueAsVariant( + const ObjectContent: IBoldObjectContents; ColumnIndex: Integer; + TranslationList: TBoldIdTranslationList): variant; +begin + result := SystemPersistenceMapper.CurrentTimeStamp; +end; + +procedure TBoldNonXFileTimeStampMember.ValueFromField( + OwningObjectId: TBoldObjectId; const ObjectContent: IBoldObjectContents; + const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; + const Field: IBoldField; ColumnIndex: Integer); +begin + ObjectContent.TimeStamp := Field.AsInteger; +end; + +procedure TBoldNonXFileTimeStampMember.ValueToParam( + const ObjectContent: IBoldObjectContents; const Param: IBoldParameter; + ColumnIndex: Integer; TranslationList: TBoldIdTranslationList); +begin + Param.AsInteger := SystemPersistenceMapper.CurrentTimeStamp; +end; + initialization ExternalIDGenerator := BoldCreateGUIDWithBracketsAsString; @@ -3217,4 +4239,3 @@ finalization end. - diff --git a/Source/PMapper/Default/BoldPMappersLinkDefault.pas b/Source/PMapper/Default/BoldPMappersLinkDefault.pas index e7a7022..77402c5 100644 --- a/Source/PMapper/Default/BoldPMappersLinkDefault.pas +++ b/Source/PMapper/Default/BoldPMappersLinkDefault.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldPMappersLinkDefault; interface @@ -59,14 +62,15 @@ TBoldEmbeddedSingleLinkDefaultMapper = class(TBoldLinkDefaultMapper) function GetColumnBDEFieldType(ColumnIndex: Integer): TFieldType; override; function GetColumnSize(ColumnIndex: Integer): Integer; override; function GetInitialColumnName(ColumnIndex: Integer): string; override; - function CompareField(ObjectContent: IBoldObjectContents; Field: IBoldField; ColumnIndex: integer; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList): Boolean; override; + function CompareField(const ObjectContent: IBoldObjectContents; const Field: IBoldField; ColumnIndex: integer; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList): Boolean; override; procedure InitializePSDescriptions; override; function GetOtherEndObjectMapper: TBoldObjectDefaultMapper; override; function DefaultDefaultDbValue: String; override; public class function CanStore(const ContentName: string): Boolean; override; - procedure ValueToParam(ObjectContent: IBoldObjectContents; Param: IBoldParameter; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList); override; - procedure ValueFromField(OwningObjectId: TBoldObjectId; ObjectContent: IBoldObjectContents; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; Field: IBoldField; ColumnIndex: Integer); override; + procedure ValueToParam(const ObjectContent: IBoldObjectContents; const Param: IBoldParameter; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList); override; + procedure ValueFromField(OwningObjectId: TBoldObjectId; const ObjectContent: IBoldObjectContents; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; const Field: IBoldField; ColumnIndex: Integer); override; + function ValueAsVariant(const ObjectContent: IBoldObjectContents; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList): variant; override; constructor CreateFromMold(moldMember: TMoldMember; moldClass: TMoldClass; Owner: TBoldObjectPersistenceMapper; const MemberIndex: Integer; TypeNameDictionary: TBoldTypeNameDictionary); override; property OtherEndObjectPMIndex: Integer read fOtherEndObjectPMIndex; property OtherEndMemberPMIndex: Integer read GetOtherEndMemberPMIndex; @@ -86,8 +90,8 @@ TBoldNonEmbeddedLinkDefaultMapper = class (TBoldLinkDefaultMapper) fRemoteInnerLinkMemberIndex: integer; fIsIndirect: Boolean; fRemoteOtherEndObjectMapperIndex: Integer; - procedure ProcessSQL(Query: IBoldQuery; WhereFragment: String; resultList: TList; TimeStamp: TBoldTimeStampType); - procedure ProcessResult(ResultList: TList; ValueSpace: IBoldValueSpace; ObjectIdList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList; timeStamp: TBoldTimeStampType; FetchMode: integer; FailureList: TBoldObjectIdList); + procedure ProcessSQL(const Query: IBoldQuery; WhereFragment: String; resultList: TList; TimeStamp: TBoldTimeStampType); + procedure ProcessResult(ResultList: TList; const ValueSpace: IBoldValueSpace; ObjectIdList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList; timeStamp: TBoldTimeStampType; FetchMode: integer; FailureList: TBoldObjectIdList); function GetLinkClassTableName: string; function GetLinkClassObjectMapper: TBoldObjectDefaultMapper; virtual; abstract; function GetClosestColumnName: string; @@ -100,9 +104,9 @@ TBoldNonEmbeddedLinkDefaultMapper = class (TBoldLinkDefaultMapper) function GetIsOrdered: Boolean; virtual; abstract; procedure GetChangePoints(ObjectIDList: TBoldObjectIdList; Condition: TBoldChangePointCondition; NameSpace: TBoldSqlnameSpace); override; function GetColumnCount: Integer; override; - procedure CompareValuesToLists(OwningId: TBoldObjectId; MemberInterface: IBoldValue; ListOfClosestEnd: TBoldObjectIdlist; ListOfRemoteEnd: TBoldObjectIdlist; FailureList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList); virtual; abstract; - procedure StuffValuesFromLists(MemberInterface: IBoldValue; ListOfClosestEnd: TBoldObjectIdlist; ListOfRemoteEnd: TBoldObjectIdlist); virtual; abstract; - function CompareField(ObjectContent: IBoldObjectContents; Field: IBoldField; ColumnIndex: integer; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList): Boolean; override; + procedure CompareValuesToLists(OwningId: TBoldObjectId; const MemberInterface: IBoldValue; ListOfClosestEnd: TBoldObjectIdlist; ListOfRemoteEnd: TBoldObjectIdlist; FailureList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList); virtual; abstract; + procedure StuffValuesFromLists(const MemberInterface: IBoldValue; ListOfClosestEnd: TBoldObjectIdlist; ListOfRemoteEnd: TBoldObjectIdlist); virtual; abstract; + function CompareField(const ObjectContent: IBoldObjectContents; const Field: IBoldField; ColumnIndex: integer; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList): Boolean; override; function EmbeddingMapper: TBoldEmbeddedSingleLinkDefaultMapper; function GetOtherEndObjectMapper: TBoldObjectDefaultMapper; override; function GetSupportsPolymorphicFetch: Boolean; override; @@ -114,7 +118,7 @@ TBoldNonEmbeddedLinkDefaultMapper = class (TBoldLinkDefaultMapper) property LinkClassTablename: string read GetLinkClassTableName; property LinkClassObjectMapper: TBoldObjectDefaultMapper read GetLinkClassObjectMapper; property Ordered: Boolean read GetIsOrdered; - procedure PMFetch(ObjectIDList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; FetchMode: Integer; TranslationList: TBoldIdTranslationList; FailureList: TBoldObjectIdList); override; + procedure PMFetch(ObjectIDList: TBoldObjectIdList; const ValueSpace: IBoldValueSpace; FetchMode: Integer; TranslationList: TBoldIdTranslationList; FailureList: TBoldObjectIdList); override; constructor CreateFromMold(moldMember: TMoldMember; moldClass: TMoldClass; Owner: TBoldObjectPersistenceMapper; const MemberIndex: Integer; TypeNameDictionary: TBoldTypeNameDictionary); override; end; @@ -128,8 +132,8 @@ TBoldSingleLinkDefaultMapper = class(TBoldNonEmbeddedLinkDefaultMapper) { TBoldDirectSingleLinkDefaultmapper } TBoldDirectSingleLinkDefaultmapper = class(TBoldSingleLinkDefaultMapper) protected - procedure StuffValuesFromLists(MemberInterface: IBoldValue; ListOfClosestEnd: TBoldObjectIdlist; ListOfRemoteEnd: TBoldObjectIdlist); override; - procedure CompareValuesToLists(OwningId: TBoldObjectId; MemberInterface: IBoldValue; ListOfClosestEnd: TBoldObjectIdlist; ListOfRemoteEnd: TBoldObjectIdlist; FailureList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList); override; + procedure StuffValuesFromLists(const MemberInterface: IBoldValue; ListOfClosestEnd: TBoldObjectIdlist; ListOfRemoteEnd: TBoldObjectIdlist); override; + procedure CompareValuesToLists(OwningId: TBoldObjectId; const MemberInterface: IBoldValue; ListOfClosestEnd: TBoldObjectIdlist; ListOfRemoteEnd: TBoldObjectIdlist; FailureList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList); override; function GetLinkClassObjectMapper: TBoldObjectDefaultMapper; override; public constructor CreateFromMold(moldMember: TMoldMember; moldClass: TMoldClass; Owner: TBoldObjectPersistenceMapper; const MemberIndex: Integer; TypeNameDictionary: TBoldTypeNameDictionary); override; @@ -139,8 +143,8 @@ TBoldDirectSingleLinkDefaultmapper = class(TBoldSingleLinkDefaultMapper) { TBoldIndirectSingleLinkDefaultmapper } TBoldIndirectSingleLinkDefaultmapper = class(TBoldSingleLinkDefaultMapper) protected - procedure StuffValuesFromLists(MemberInterface: IBoldValue; ListOfClosestEnd: TBoldObjectIdlist; ListOfRemoteEnd: TBoldObjectIdlist); override; - procedure CompareValuesToLists(OwningId: TBoldObjectId; MemberInterface: IBoldValue; ListOfClosestEnd: TBoldObjectIdlist; ListOfRemoteEnd: TBoldObjectIdlist; FailureList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList); override; + procedure StuffValuesFromLists(const MemberInterface: IBoldValue; ListOfClosestEnd: TBoldObjectIdlist; ListOfRemoteEnd: TBoldObjectIdlist); override; + procedure CompareValuesToLists(OwningId: TBoldObjectId; const MemberInterface: IBoldValue; ListOfClosestEnd: TBoldObjectIdlist; ListOfRemoteEnd: TBoldObjectIdlist; FailureList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList); override; function GetLinkClassObjectMapper: TBoldObjectDefaultMapper; override; public constructor CreateFromMold(moldMember: TMoldMember; moldClass: TMoldClass; Owner: TBoldObjectPersistenceMapper; const MemberIndex: Integer; TypeNameDictionary: TBoldTypeNameDictionary); override; @@ -160,8 +164,8 @@ TBoldMultiLinkDefaultMapper = class(TBoldNonEmbeddedLinkDefaultMapper) { TBoldDirectMultiLinkDefaultmapper } TBoldDirectMultiLinkDefaultmapper = class(TBoldMultiLinkDefaultMapper) protected - procedure StuffValuesFromLists(MemberInterface: IBoldValue; ListOfClosestEnd: TBoldObjectIdlist; ListOfRemoteEnd: TBoldObjectIdlist); override; - procedure CompareValuesToLists(OwningId: TBoldObjectId; MemberInterface: IBoldValue; ListOfClosestEnd: TBoldObjectIdlist; ListOfRemoteEnd: TBoldObjectIdlist; FailureList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList); override; + procedure StuffValuesFromLists(const MemberInterface: IBoldValue; ListOfClosestEnd: TBoldObjectIdlist; ListOfRemoteEnd: TBoldObjectIdlist); override; + procedure CompareValuesToLists(OwningId: TBoldObjectId; const MemberInterface: IBoldValue; ListOfClosestEnd: TBoldObjectIdlist; ListOfRemoteEnd: TBoldObjectIdlist; FailureList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList); override; function GetLinkClassObjectMapper: TBoldObjectDefaultMapper; override; public constructor CreateFromMold(moldMember: TMoldMember; moldClass: TMoldClass; Owner: TBoldObjectPersistenceMapper; const MemberIndex: Integer; TypeNameDictionary: TBoldTypeNameDictionary); override; @@ -171,14 +175,17 @@ TBoldDirectMultiLinkDefaultmapper = class(TBoldMultiLinkDefaultMapper) { TBoldIndirectMultiLinkDefaultmapper } TBoldIndirectMultiLinkDefaultmapper = class(TBoldMultiLinkDefaultMapper) protected - procedure StuffValuesFromLists(MemberInterface: IBoldValue; ListOfClosestEnd: TBoldObjectIdlist; ListOfRemoteEnd: TBoldObjectIdlist); override; - procedure CompareValuesToLists(OwningId: TBoldObjectId; MemberInterface: IBoldValue; ListOfClosestEnd: TBoldObjectIdlist; ListOfRemoteEnd: TBoldObjectIdlist; FailureList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList); override; + procedure StuffValuesFromLists(const MemberInterface: IBoldValue; ListOfClosestEnd: TBoldObjectIdlist; ListOfRemoteEnd: TBoldObjectIdlist); override; + procedure CompareValuesToLists(OwningId: TBoldObjectId; const MemberInterface: IBoldValue; ListOfClosestEnd: TBoldObjectIdlist; ListOfRemoteEnd: TBoldObjectIdlist; FailureList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList); override; function GetLinkClassObjectMapper: TBoldObjectDefaultMapper; override; public constructor CreateFromMold(moldMember: TMoldMember; moldClass: TMoldClass; Owner: TBoldObjectPersistenceMapper; const MemberIndex: Integer; TypeNameDictionary: TBoldTypeNameDictionary); override; class function CanStore(const ContentName: string): Boolean; override; end; + const + MaxUnion = 30; + implementation uses @@ -194,13 +201,17 @@ implementation BoldTaggedValueSupport, BoldPMapperLists, BoldGuard, - BoldDefaultStreamNames, - BoldPMConsts; + {$IFDEF RIL} + {$IFNDEF BOLD_UNICODE} + StringBuilder, + {$ENDIF} + {$ENDIF} + BoldDefaultStreamNames; { Supporting functions/procedures } {Returns new ObjectId with owned ClassId, both must be freed} -function CreateAndEnsureId(ObjectId: Integer; ClassId: Integer; Exact: Boolean; TransLationlist: TBoldIdTranslationList; ValueSpace: IBoldValueSpace; TimeStamp: TBoldTimeStampType): TBoldDefaultId; +function CreateAndEnsureId(ObjectId: Integer; ClassId: Integer; Exact: Boolean; TransLationlist: TBoldIdTranslationList; const ValueSpace: IBoldValueSpace; TimeStamp: TBoldTimeStampType): TBoldDefaultId; begin Assert (ClassID <> -1); if TimeStamp = BOLDMAXTIMESTAMP then @@ -210,7 +221,7 @@ function CreateAndEnsureId(ObjectId: Integer; ClassId: Integer; Exact: Boolean; Result.AsInteger := ObjectId; if assigned(TranslationList) then - TranslationList.AddTranslation(nil, Result); // needed? + TranslationList.AddTranslation(nil, Result); ValueSpace.EnsureObjectId(Result); end; @@ -242,14 +253,18 @@ TTempLinkValues = class(TObject) end; function SortLinkValues(Item1, Item2: Pointer): integer; +var + Tl1, Tl2: TTempLinkValues; begin - result := TTempLinkValues(Item1).Objectid - TTempLinkValues(Item2).Objectid; + Tl1 := TTempLinkValues(Item1); + Tl2 := TTempLinkValues(Item2); + result := Tl1.Objectid - Tl2.Objectid; if result = 0 then - result := TTempLinkValues(Item1).OrderValue - TTempLinkValues(Item2).OrderValue; + result := Tl1.OrderValue - Tl2.OrderValue; if result = 0 then - result := TTempLinkValues(Item1).RemoteId - TTempLinkValues(Item2).RemoteId; + result := Tl1.RemoteId - Tl2.RemoteId; if result = 0 then - result := TTempLinkValues(Item1).ClosestId - TTempLinkValues(Item2).ClosestId; + result := Tl1.ClosestId - Tl2.ClosestId; end; constructor TBoldNonEmbeddedLinkDefaultMapper.CreateFromMold( @@ -262,9 +277,9 @@ constructor TBoldNonEmbeddedLinkDefaultMapper.CreateFromMold( fIsStoredInObject := IsStoredInObject and ((MoldMember as TMoldRole).RoleType in [rtRole, rtInnerLinkRole]); end; -function TBoldNonEmbeddedLinkDefaultMapper.CompareField(ObjectContent: IBoldObjectContents; Field: IBoldField; ColumnIndex: integer; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList): Boolean; +function TBoldNonEmbeddedLinkDefaultMapper.CompareField(const ObjectContent: IBoldObjectContents; const Field: IBoldField; ColumnIndex: integer; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList): Boolean; begin - raise EBold.CreateFmt(sCannotCallOnTransientClass, [classname]); + raise EBold.CreateFmt('%s.CompareField: Can not be called for this class, it is not stored', [classname]); end; function TBoldNonEmbeddedLinkDefaultMapper.GetColumnCount: Integer; @@ -272,7 +287,268 @@ function TBoldNonEmbeddedLinkDefaultMapper.GetColumnCount: Integer; Result := 0; end; -procedure TBoldNonEmbeddedLinkDefaultMapper.ProcessSQL(Query: IBoldQuery; WhereFragment: String; resultList: TList; TimeStamp: TBoldTimeStampType); +procedure TBoldNonEmbeddedLinkDefaultMapper.ProcessSQL(const Query: IBoldQuery; WhereFragment: String; resultList: TList; TimeStamp: TBoldTimeStampType); +{$IFDEF RIL} +var + Cnt: integer; + + i, j: integer; + ClassIdRequired: Boolean; + NextColumnIndex: integer; + LinkData: TTempLinkValues; + MappingInfo: TBoldMemberMappingArray; + AIMappingInfo: TBoldAllInstancesMappingArray; // of TBoldAllInstancesMappingInfo + EmbeddingColumnName, + EmbeddingOrderColumnName: String; + WhereClause, + SelectClause: String; + Selectlist: TStringList; + SQL: TStringList; + OperatingOnRootTable: Boolean; + RootTableJoin, + sMappingInfoTableName: string; + First: Boolean; +const + LinkTableAlias: String = 'LinkTable_Alias'; + LinkTableAlias_Dot: String = 'LinkTable_Alias.'; + RootTableAlias: String = 'RootTable_Alias'; + procedure ExecQuery; + var + tmpQuery: IBoldQuery; + begin + tmpQuery := Query; + tmpQuery.AssignSQL(SQL); + SQL.Clear; + tmpQuery.Open; + if tmpQuery.RecordCount > resultList.Capacity then + resultList.Capacity := tmpQuery.RecordCount; + while not tmpQuery.Eof do + begin + LinkData := TTempLinkValues.Create; + LinkData.ClosestId := tmpQuery.Fields[0].AsInteger; + LinkData.ClosestClassid := tmpQuery.Fields[1].AsInteger; + LinkData.ObjectId := tmpQuery.Fields[2].AsInteger; + NextColumnIndex := 3; + if ordered then + begin + LinkData.Ordervalue := tmpQuery.Fields[NextColumnIndex].AsInteger; + INC(NextColumnIndex); + end + else + LinkData.OrderValue := 0; + + if isIndirect then + LinkData.RemoteId := tmpQuery.Fields[NextColumnIndex].AsInteger; + ResultList.Add(LinkData); + tmpQuery.Next; + end; + tmpQuery.Close; + end; +var + SB: TStringBuilder; + + +begin + AIMappingInfo := nil; + SelectList := TStringList.Create; + sql := TStringList.Create; + SB := TStringBuilder.Create; + first := true; + MappingInfo := SystemPersistenceMapper.MappingInfo.GetMemberMappings(ClosestOtherEndObjectMapper.ExpressionName, EmbeddingMapper.ExpressionName); + try + if length(MappingInfo)>1 then + BoldPMLogFmt('Fetching accross %4d tables for %s', [length(MappingInfo), EmbeddingMapper.ExpressionName]); + for i := 0 to length(MappingInfo) - 1 do + begin + if not first then + SQL.Append(' UNION '); + sMappingInfoTableName := MappingInfo[i].TableName; + + EmbeddingColumnName := MappingInfo[i].ColumnByIndex[0]; + if Ordered then + begin + if ORDERCOLUMN_INDEX >= MappingInfo[i].ColumnCount then + raise EBoldBadColumnIndex.CreateFmt('%s.: Order column not found for association %s', [ClassName, EmbeddingColumnName]); + EmbeddingOrderColumnName := MappingInfo[i].ColumnByIndex[ORDERCOLUMN_INDEX]; + end + else + EmbeddingOrderColumnName := ''; + + SelectList.Clear; + {ID, TYPE, ClosstId, [OderColumn], [RemoteColumn]} + + //SelectList.Add(LinkTableAlias + '.' + IDCOLUMN_NAME); + SB.Clear; + SB.Append(LinkTableAlias_Dot); + SB.Append(IDCOLUMN_NAME); + SelectList.Append(SB.ToString); + //SelectList.Add(LinkTableAlias + '.' + TYPECOLUMN_NAME); + SB.Clear; + SB.Append(LinkTableAlias_Dot); + SB.Append(TYPECOLUMN_NAME); + SelectList.Append(SB.ToString); + //SelectList.Append(LinkTableAlias + '.' + EmbeddingColumnName); + SB.Clear; + SB.Append(LinkTableAlias_Dot); + SB.Append(EmbeddingColumnName); + SelectList.Append(SB.ToString); + + if ordered then + SelectList.Append(EmbeddingOrderColumnName); + if IsIndirect then + SelectList.Append(RemoteInnerLinkMapper.MainColumnName); + + //SelectClause := Format('SELECT %s', [BoldSeparateStringList(SelectList, ', ', '', '')]); + SelectClause := 'SELECT ' + BoldSeparateStringList(SelectList,', ','',''); + + //WhereClause := Format('WHERE (%s.%s) %s', [LinkTableAlias, EmbeddingColumnName, WhereFragment]); + SB.Clear; + SB.Append('WHERE ('); + SB.Append(LinkTableAlias_Dot); + SB.Append(EmbeddingColumnName); + SB.Append(') '); + SB.Append(WhereFragment); + WhereClause := SB.ToString; + + SQL.Append(SelectClause); + //SQL.Add('FROM '+ MappingInfo[i].TableName + ' ' + LinkTableAlias); + SB.Clear; + SB.Append('FROM '); + SB.Append(sMappingInfoTableName); + SB.Append(' '); + SB.Append(LinkTableAlias); + SQL.Append(SB.ToString); + + RootTableJoin := ''; { build this string conditionally, only if needed !! //ril } + { + RootTableJoin := format('((%s.%s = %s.%s) and (%s.%s = %s.%s))', [ + LinkTableAlias, TIMESTAMPSTARTCOLUMNNAME, + RootTableAlias, TIMESTAMPSTARTCOLUMNNAME, + LinkTableAlias, IDCOLUMN_NAME, + RootTableAlias, IDCOLUMN_NAME]); + } + + if ClosestOtherEndObjectMapper.Versioned and + not SameText(sMappingInfoTableName, SystemPersistenceMapper.RootClassObjectPersistenceMapper.Maintable.SQLName) {=OperatingOnRootTable} then + begin + if SystemPersistenceMapper.SQLDataBaseConfig.UseSQL92Joins then + begin + SB.Clear; + SB.Append('(('); + SB.Append(LinkTableAlias_Dot); + SB.Append(TIMESTAMPSTARTCOLUMNNAME); + SB.Append(' = '); + SB.Append(RootTableAlias); + SB.Append('.'); + SB.Append(TIMESTAMPSTARTCOLUMNNAME); + SB.Append(') and ('); + SB.Append(LinkTableAlias_Dot); + SB.Append(IDCOLUMN_NAME); + SB.Append(' = '); + SB.Append(RootTableAlias); + SB.Append('.'); + SB.Append(IDCOLUMN_NAME); + SB.Append('))'); + RootTableJoin := SB.ToString; + { + SQL.append(format(' left join %s %s on %s', [ + SystemPersistenceMapper.RootClassObjectPersistenceMapper.MainTable.SQLName, RootTableAlias, RootTableJoin] )) + } + + SB.Clear; + SB.Append(' left join '); + SB.Append(SystemPersistenceMapper.RootClassObjectPersistenceMapper.MainTable.SQLName); + SB.Append(' '); + SB.Append(RootTableAlias); + SB.Append(' on '); + SB.Append(RootTableJoin); + SQL.Append(SB.ToString); + end + else + begin + {SQL.Append(format(', %s %s', [SystemPersistenceMapper.RootClassObjectPersistenceMapper.MainTable.SQLName, RootTableAlias] )); } + SQL.Append(', '+SystemPersistenceMapper.RootClassObjectPersistenceMapper.MainTable.SQLName+' '+RootTableAlias); + end; + end; + + SQL.Append(WhereClause); + + ClassIDRequired := true; + AIMappingInfo := SystemPersistenceMapper.MappingInfo.GetAllInstancesMapping(ClosestOtherEndObjectMapper.ExpressionName); + { 1. Cheapest check first. + 2. Break when false as this won't change anymore... } + Cnt := Length(AIMappingInfo); + for j := 0 to Cnt-1 do + begin + if not AIMappingInfo[j].ClassIdRequired and + SameText(AIMappingInfo[j].TableName, sMappingInfoTableName) then + begin + ClassIdRequired := False; + Break; + end; + end; + + if ClassIdRequired then + begin + {ril}//SQL.Add(format('AND (%s in (%s))', [TYPECOLUMN_NAME, ClosestOtherEndObjectMapper.SubClassesID])); + //SQL.Append('AND ('+TYPECOLUMN_NAME+' in ('+ClosestOtherEndObjectMapper.SubClassesID+'))'); + SB.Clear; + SB.Append('AND ('); + SB.Append(TYPECOLUMN_NAME); + SB.Append(' in ('); + SB.Append(ClosestOtherEndObjectMapper.SubClassesID); + SB.Append('))'); + SQL.Append(SB.ToString); + end; + + if ClosestOtherEndObjectMapper.Versioned then + begin + OperatingOnRootTable := SameText(sMappingInfoTableName, SystemPersistenceMapper.RootClassObjectPersistenceMapper.Maintable.SQLName); + if OperatingOnRootTable then + ClosestOtherEndObjectMapper.RetrieveTimeStampCondition(SQL, TimeStamp, false, 'AND', True, LinkTableAlias, LinkTableAlias) + else + ClosestOtherEndObjectMapper.RetrieveTimeStampCondition(SQL, TimeStamp, false, 'AND', True, LinkTableAlias, RootTableAlias); + if not OperatingOnRootTable and not SystemPersistenceMapper.SQLDataBaseConfig.UseSQL92Joins then + begin + if RootTableJoin='' then { not prepared yet } + begin + SB.Clear; + SB.Append('(('); + SB.Append(LinkTableAlias_Dot); + SB.Append(TIMESTAMPSTARTCOLUMNNAME); + SB.Append(' = '); + SB.Append(RootTableAlias); + SB.Append('.'); + SB.Append(TIMESTAMPSTARTCOLUMNNAME); + SB.Append(') and ('); + SB.Append(LinkTableAlias_Dot); + SB.Append(IDCOLUMN_NAME); + SB.Append(' = '); + SB.Append(RootTableAlias); + SB.Append('.'); + SB.Append(IDCOLUMN_NAME); + SB.Append('))'); + RootTableJoin := SB.ToString; + end; + SQL.Append('and '+RootTableJoin); + end; + end; + if ((i+1) mod MaxUnion) = 0 then + begin + ExecQuery; + first := true; + end + else + first := false; + end; + if Sql.Count > 0 then + ExecQuery; + finally + SelectList.Free; + SQL.free; + SB.Free; + end; +{$ELSE} var i, j: integer; ClassIdRequired: Boolean; @@ -299,47 +575,44 @@ procedure TBoldNonEmbeddedLinkDefaultMapper.ProcessSQL(Query: IBoldQuery; WhereF begin EmbeddingColumnName := MappingInfo[i].ColumnByIndex[0]; if Ordered then - EmbeddingOrderColumnName := MappingInfo[i].ColumnByIndex[1] + EmbeddingOrderColumnName := MappingInfo[i].ColumnByIndex[ORDERCOLUMN_INDEX] else EmbeddingOrderColumnName := ''; SelectList.Clear; {ID, TYPE, ClosstId, [OderColumn], [RemoteColumn]} SelectList.Add(LinkTableAlias + '.' + IDCOLUMN_NAME); - SelectList.Add(LinkTableAlias + '.' + TYPECOLUMN_NAME); // FIXME hardwired + SelectList.Add(LinkTableAlias + '.' + TYPECOLUMN_NAME); SelectList.Append(LinkTableAlias + '.' + EmbeddingColumnName); - // there is no need to add an OrderBy clause since the list will be ordered in memory prior to processing if ordered then SelectList.Append(EmbeddingOrderColumnName); if IsIndirect then SelectList.Append(Format('%s', [RemoteInnerLinkMapper.MainColumnName])); - SelectClause := Format('SELECT %s', [BoldSeparateStringList(SelectList, ', ', '', '')]); // do not localize + SelectClause := Format('SELECT %s', [BoldSeparateStringList(SelectList, ', ', '', '')]); - WhereClause := Format('WHERE (%s.%s) %s', [LinkTableAlias, EmbeddingColumnName, WhereFragment]); // do not localize + WhereClause := Format('WHERE (%s.%s) %s', [LinkTableAlias, EmbeddingColumnName, WhereFragment]); SQL.Clear; SQL.Add(SelectClause); - SQL.Add('FROM '+ MappingInfo[i].TableName + ' ' + LinkTableAlias); // do not localize + SQL.Add('FROM '+ MappingInfo[i].TableName + ' ' + LinkTableAlias); OperatingOnRootTable := SameText(MappingInfo[i].TableName, SystemPersistenceMapper.RootClassObjectPersistenceMapper.Maintable.SQLName); - RootTableJoin := format('((%s.%s = %s.%s) and (%s.%s = %s.%s))', [ // do not localize + RootTableJoin := format('((%s.%s = %s.%s) and (%s.%s = %s.%s))', [ LinkTableAlias, TIMESTAMPSTARTCOLUMNNAME, RootTableAlias, TIMESTAMPSTARTCOLUMNNAME, LinkTableAlias, IDCOLUMN_NAME, RootTableAlias, IDCOLUMN_NAME]); - // Add the root table if it is needed and not already there - if ClosestOtherEndObjectMapper.Versioned and not OperatingOnRootTable then begin if SystemPersistenceMapper.SQLDataBaseConfig.UseSQL92Joins then - SQL.append(format(' left join %s %s on %s', [ // do not localize + SQL.append(format(' left join %s %s on %s', [ SystemPersistenceMapper.RootClassObjectPersistenceMapper.MainTable.SQLName, RootTableAlias, RootTableJoin] )) else - SQL.Append(format(', %s %s', [ // do not localize + SQL.Append(format(', %s %s', [ SystemPersistenceMapper.RootClassObjectPersistenceMapper.MainTable.SQLName, RootTableAlias] )); end; @@ -354,17 +627,15 @@ procedure TBoldNonEmbeddedLinkDefaultMapper.ProcessSQL(Query: IBoldQuery; WhereF ClassIdRequired := false; if ClassIdRequired then - SQL.Add(format('AND (%s in (%s))', [TYPECOLUMN_NAME, ClosestOtherEndObjectMapper.SubClassesID])); // do not localize - - // add timestamp conditions and nessesary joins + SQL.Add(format('AND (%s in (%s))', [TYPECOLUMN_NAME, ClosestOtherEndObjectMapper.SubClassesID])); if ClosestOtherEndObjectMapper.Versioned then begin if OperatingOnRootTable then - ClosestOtherEndObjectMapper.RetrieveTimeStampCondition(SQL, TimeStamp, false, 'AND', True, LinkTableAlias, LinkTableAlias) // do not localize + ClosestOtherEndObjectMapper.RetrieveTimeStampCondition(SQL, TimeStamp, false, 'AND', True, LinkTableAlias, LinkTableAlias) else - ClosestOtherEndObjectMapper.RetrieveTimeStampCondition(SQL, TimeStamp, false, 'AND', True, LinkTableAlias, RootTableAlias); // do not localize + ClosestOtherEndObjectMapper.RetrieveTimeStampCondition(SQL, TimeStamp, false, 'AND', True, LinkTableAlias, RootTableAlias); if not OperatingOnRootTable and not SystemPersistenceMapper.SQLDataBaseConfig.UseSQL92Joins then - SQL.Append(format('and %s', [RootTableJoin])); // do not localize + SQL.Append(format('and %s', [RootTableJoin])); end; Query.AssignSQL(SQL); @@ -394,9 +665,11 @@ procedure TBoldNonEmbeddedLinkDefaultMapper.ProcessSQL(Query: IBoldQuery; WhereF SelectList.Free; sql.free; end; -end; +{$ENDIF} +end; { TBoldNonEmbeddedLinkDefaultMapper.ProcessSQL } -procedure TBoldNonEmbeddedLinkDefaultMapper.ProcessResult(ResultList: TList; ValueSpace: IBoldValueSpace; ObjectIdList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList; TimeStamp: TBoldTimeStampType; FetchMode: integer; FailureList: TBoldObjectIdList); + +procedure TBoldNonEmbeddedLinkDefaultMapper.ProcessResult(ResultList: TList; const ValueSpace: IBoldValueSpace; ObjectIdList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList; TimeStamp: TBoldTimeStampType; FetchMode: integer; FailureList: TBoldObjectIdList); var UnprocessedObjects: TBoldObjectidList; ListOfClosestEnd: TBoldObjectIdlist; @@ -410,19 +683,18 @@ procedure TBoldNonEmbeddedLinkDefaultMapper.ProcessResult(ResultList: TList; Val i, OldfailureCount: integer; begin ObjectContents := ValueSpace.EnsuredObjectContentsByObjectId[CurrentobjectId]; - ObjectContents.EnsureMember(MemberId, ContentName); - MemberInterface := ObjectContents.ValueByMemberId[MemberID]; + MemberInterface := ObjectContents.EnsureMemberAndGetValueByIndex(MemberId.MemberIndex, ContentName); if FetchMode = fmCompare then begin OldFailureCount := failureLIst.Count; CompareValuestoLists(CurrentObjectId, MemberInterface, ListOfClosestEnd, ListOfRemoteEnd, FailureList, TranslationList); if FailureList.Count > OldFailureCount then begin - BoldLog.LogFmt(sOptimisticLockingFailedForTheFollowing, [ + BoldLog.LogFmt('Optimistic Locking failed for %s.%s for the following objects', [ ObjectPersistenceMapper.ExpressionName, ExpressionName]); for i := OldFailureCount to FailureList.Count - 1 do - BoldLog.LogFmt(sLogIdAsString, [FailureList[i].AsString]); + BoldLog.Log('Id: '+ FailureList[i].AsString); end; end else if MemberInterface.BoldPersistenceState = bvpsInvalid then @@ -435,16 +707,14 @@ procedure TBoldNonEmbeddedLinkDefaultMapper.ProcessResult(ResultList: TList; Val procedure EnsureAndAddToList(List: TBoldObjectIdList; ClassId: integer; Exact: Boolean; IdAsInteger: integer); var BoldId: TBoldDefaultId; - BoldGuard: IBoldGuard; begin - BoldGuard := TBoldGuard.Create(BoldID); BoldId := CreateAndEnsureId(IdAsInteger, ClassId, Exact, TranslationList, ValueSpace, TimeStamp); - List.Add(BoldId); + List.AddAndAdopt(BoldId); end; function FindInListByIdAsInteger(List: TBoldObjectIdList; IdAsInteger: integer): TBoldObjectId; @@ -465,6 +735,7 @@ procedure TBoldNonEmbeddedLinkDefaultMapper.ProcessResult(ResultList: TList; Val Currentresult: TTempLinkValues; RemoteOtherEndExact: Boolean; TranslatedClassId: integer; + BoldObjectId: TBoldObjectId; BoldGuard: IBoldGuard; begin BoldGuard := TBoldGuard.Create(ListOfRemoteEnd, ListOfClosestEnd, UnprocessedObjects, MemberID); @@ -472,12 +743,13 @@ procedure TBoldNonEmbeddedLinkDefaultMapper.ProcessResult(ResultList: TList; Val (not ObjectPersistenceMappers[RemoteOtherEndObjectMapperIndex].HasSubClasses); UnprocessedObjects := ObjectIDList.Clone; + MemberID := TBoldMemberId.Create(MemberIndex); ListOfClosestEnd := TBoldObjectIdlist.Create; ListOfRemoteEnd := TBoldObjectIdlist.Create; - MemberID := TBoldMemberId.Create(MemberIndex); - + CurrentId := -1; if resultList.Count > 0 then - begin + try + ListOfClosestEnd.Capacity := resultList.Count; CurrentId := TTempLinkValues(ResultList[0]).ObjectId; for i := 0 to ResultList.Count - 1 do begin @@ -496,10 +768,18 @@ procedure TBoldNonEmbeddedLinkDefaultMapper.ProcessResult(ResultList: TList; Val CurrentResult.RemoteId); end; - ProcessResultForOneObject(FindInListByIdAsInteger(UnprocessedObjects, CurrentId)); - end; + BoldObjectId := FindInListByIdAsInteger(UnprocessedObjects, CurrentId); + ProcessResultForOneObject(BoldObjectId); + except + on e:EBoldDuplicateSingleLinkValueInDb do + begin + e.Message := 'BoldId: ' + IntToStr(CurrentId) + ' ' + e.Message; - // clear links for objects that had no related objects in the database + raise; + end + else + raise; + end; while UnprocessedObjects.Count > 0 do ProcessResultForOneObject(UnprocessedObjects[0] as TBoldDefaultId); {Lists empty at this point} @@ -527,12 +807,12 @@ function TBoldNonEmbeddedLinkDefaultMapper.CreateSelectClause: string; end; *) -procedure TBoldNonEmbeddedLinkDefaultMapper.PMFetch(ObjectIDList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; FetchMode: Integer; TranslationList: TBoldIdTranslationList; FailureList: TBoldObjectIdList); +procedure TBoldNonEmbeddedLinkDefaultMapper.PMFetch(ObjectIDList: TBoldObjectIdList; const ValueSpace: IBoldValueSpace; FetchMode: Integer; TranslationList: TBoldIdTranslationList; FailureList: TBoldObjectIdList); var TimeStamp: TBoldTimeStampType; ResultList: TList; start, stop: integer; - Block, ObjectCount, I: Integer; + Block, ObjectCount, I, FetchBlockSize, unions: Integer; WhereFragment: String; TopSortedIndex: Integer; aQuery: IBoldQuery; @@ -542,8 +822,6 @@ procedure TBoldNonEmbeddedLinkDefaultMapper.PMFetch(ObjectIDList: TBoldObjectIdL TopSortedIndex := ObjectPersistenceMapper.TopSortedIndex; - // splitting on timestamps is performed by the objectpersistencemapper already - TimeStamp := ObjectIdList[0].TimeStamp; for I := 0 to ObjectIDList.Count - 1 do @@ -567,19 +845,24 @@ procedure TBoldNonEmbeddedLinkDefaultMapper.PMFetch(ObjectIDList: TBoldObjectIdL try ObjectCount := ObjectIDList.Count - 1; - // only do the fetching in blocks, the actual processing must be done in one go - // since ProcessResult will clear all objects with empty links - // besides, the point of blockfetching is mainly to reduce the size of the SQL-statement - for Block := 0 to (ObjectCount div SystemPersistenceMapper.SQLDataBaseConfig.FetchBlockSize) do + Unions := MinIntValue([MaxUnion, length(SystemPersistenceMapper.MappingInfo.GetMemberMappings(ClosestOtherEndObjectMapper.ExpressionName, EmbeddingMapper.ExpressionName))]); + FetchBlockSize := 1; + if Unions > 0 then + FetchBlockSize := SystemPersistenceMapper.SQLDataBaseConfig.FetchBlockSize div Unions; + if FetchBlockSize = 0 then + FetchBlockSize := 1; + for Block := 0 to (ObjectCount div FetchBlockSize) do begin aQuery.ClearParams; - Start := Block * SystemPersistenceMapper.SQLDataBaseConfig.FetchBlockSize; - Stop := MinIntValue([Pred(Succ(Block) * SystemPersistenceMapper.SQLDataBaseConfig.FetchBlockSize), ObjectCount]); - WhereFragment := ObjectPersistenceMapper.IdListSegmentToWhereFragment(ObjectIdList, Start, Stop, aQuery); + Start := Block * FetchBlockSize; + Stop := MinIntValue([Pred(Succ(Block) * FetchBlockSize), ObjectCount]); + WhereFragment := ObjectPersistenceMapper.IdListSegmentToWhereFragment(ObjectIdList, Start, Stop, false, aQuery); ProcessSQL(aQuery, WhereFragment, resultList, TimeStamp); end; - ResultList.Sort(SortLinkValues); - BoldPMLogFmt(sLogFetchIDs, [ResultLIst.Count, ObjectIdList.Count, ObjectPersistenceMapper.ExpressionName, ExpressionName]); + if ResultList.Count > 1 then + ResultList.Sort(SortLinkValues); + if BoldPMLogHandler<>nil then + BoldPMLogFmt('Fetched %4d ids for %4d nonembedded links %s.%s', [ResultLIst.Count, ObjectIdList.Count, ObjectPersistenceMapper.ExpressionName, ExpressionName]); ProcessResult(ResultList, ValueSpace, ObjectIdList, TranslationList, timeStamp, FetchMode, FailureList); finally @@ -602,7 +885,7 @@ function TBoldEmbeddedSingleLinkDefaultMapper.GetColumnTypeAsSQL(ColumnIndex: In case ColumnIndex of 0, 1: Result := SystemPersistenceMapper.SQLDataBaseConfig.ColumnTypeForInteger; else - raise EBoldBadColumnIndex.CreateFmt(sIllegalColumnIndex, [ClassName, 'GetColumnTypeAsSQL', ColumnIndex]); // do not localize + raise EBoldBadColumnIndex.CreateFmt('%s.GetColumnTypeAsSQL: Bad column index', [ClassName]); end; end; @@ -616,7 +899,7 @@ function TBoldEmbeddedSingleLinkDefaultMapper.GetColumnBDEFieldType(ColumnIndex: case ColumnIndex of 0, 1: Result := ftInteger; else - raise EBoldBadColumnIndex.CreateFmt(sIllegalColumnIndex, [ClassName, 'GetColumnBDEFieldType', ColumnIndex]); // do not localize + raise EBoldBadColumnIndex.CreateFmt('%s.GetColumnBDEFieldType: Bad column index', [ClassName]); end; end; @@ -625,7 +908,7 @@ function TBoldEmbeddedSingleLinkDefaultMapper.GetColumnSize(ColumnIndex: Integer Result := 0; end; -function TBoldEmbeddedSingleLinkDefaultMapper.CompareField(ObjectContent: IBoldObjectContents; Field: IBoldField; ColumnIndex: integer; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList): Boolean; +function TBoldEmbeddedSingleLinkDefaultMapper.CompareField(const ObjectContent: IBoldObjectContents; const Field: IBoldField; ColumnIndex: integer; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList): Boolean; var anIdRef: IBoldObjectIdRef; begin @@ -650,37 +933,72 @@ function TBoldEmbeddedSingleLinkDefaultMapper.CompareField(ObjectContent: IBoldO result := Field.AsInteger = anIdRef.OrderNo; end; end; + end; function TBoldEmbeddedSingleLinkDefaultMapper.GetInitialColumnName(ColumnIndex: Integer): string; begin case ColumnIndex of 0: Result := InitialColumnRootName; - 1: Result := InitialColumnRootName + '_O'; + 1: Result := InitialColumnRootName + ORDERCOLUMN_SUFFIX; else - raise EBoldBadColumnIndex.CreateFmt(sIllegalColumnIndex, [classname, 'GetInitialColumnName', ColumnIndex]); // do not localize + raise EBoldBadColumnIndex.CreateFmt('%s.GetInitialColumnName: Bad column index', [classname]); end; end; -procedure TBoldEmbeddedSingleLinkDefaultMapper.ValueToParam(ObjectContent: IBoldObjectContents; Param: IBoldParameter; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList); +procedure TBoldEmbeddedSingleLinkDefaultMapper.ValueToParam(const ObjectContent: IBoldObjectContents; const Param: IBoldParameter; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList); var SingleLink: IBoldObjectIdRef; + aBoldObjectID: TBoldObjectID; begin SingleLink := GetEnsuredValue(ObjectContent) as IBoldObjectIdRef; case ColumnIndex of 0: if assigned(SingleLink.Id) then - Param.AsInteger := (TranslationList.TranslateToNewID[SingleLink.Id] as TBoldDefaultId).asInteger + begin + aBoldObjectID := TranslationList.TranslateToNewID[SingleLink.Id]; + if aBoldObjectID is TBoldDefaultId then + Param.AsInteger := TBoldDefaultId(aBoldObjectID).asInteger + else + Param.AsInteger := INTERNALNULLKEY; + end else Param.AsInteger := INTERNALNULLKEY; 1: Param.AsInteger := SingleLink.OrderNo; else - raise EBoldBadColumnIndex.CreateFmt(sIllegalColumnIndex, [ClassName, 'ValueToParam', ColumnIndex]); // do not localize + raise EBoldBadColumnIndex.CreateFmt('%s.ValueToParam: Bad column index (%d)', [ClassName, ColumnIndex]); end; end; -procedure TBoldEmbeddedSingleLinkDefaultMapper.ValueFromField(OwningObjectId: TBoldObjectId; ObjectContent: IBoldObjectContents; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; Field: IBoldField; ColumnIndex: Integer); +function TBoldEmbeddedSingleLinkDefaultMapper.ValueAsVariant( + const ObjectContent: IBoldObjectContents; ColumnIndex: Integer; + TranslationList: TBoldIdTranslationList): variant; +var + SingleLink: IBoldObjectIdRef; + aBoldObjectID: TBoldObjectID; +begin + SingleLink := GetEnsuredValue(ObjectContent) as IBoldObjectIdRef; + case ColumnIndex of + 0: + if assigned(SingleLink.Id) then + begin + aBoldObjectID := TranslationList.TranslateToNewID[SingleLink.Id]; + if aBoldObjectID is TBoldDefaultId then + result := TBoldDefaultId(aBoldObjectID).asInteger + else + result := INTERNALNULLKEY; + end + else + result := INTERNALNULLKEY; + 1: + result := SingleLink.OrderNo; + else + raise EBoldBadColumnIndex.CreateFmt('%s.ValueAsVariant: Bad column index (%d)', [ClassName, ColumnIndex]); + end; +end; + +procedure TBoldEmbeddedSingleLinkDefaultMapper.ValueFromField(OwningObjectId: TBoldObjectId; const ObjectContent: IBoldObjectContents; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; const Field: IBoldField; ColumnIndex: Integer); var ObjectId: TBoldObjectId; anIdRef: IBoldObjectIdRef; @@ -691,15 +1009,14 @@ procedure TBoldEmbeddedSingleLinkDefaultMapper.ValueFromField(OwningObjectId: TB if not Field.IsNull and (Field.AsInteger <> INTERNALNULLKEY) then begin ObjectId := CreateAndEnsureId(Field.AsInteger, OtherEndObjectPMIndex, OtherEndExact, TranslationList, ValueSpace, OwningObjectId.TimeStamp); - anIdRef.SetFromId(ObjectId); - ObjectID.Free; + anIdRef.SetFromId(ObjectId, true); end else - anIdRef.SetFromId(nil); + anIdRef.SetFromId(nil, false); 1: anIdRef.Orderno := Field.AsInteger; else - raise EBoldBadColumnIndex.CreateFmt(sIllegalColumnIndex, [ClassName, 'ValueFromField', ColumnIndex]); // do not localize + raise EBoldBadColumnIndex.CreateFmt('%s.ValueFromField: Bad column index', [ClassName]); end; end; @@ -794,7 +1111,7 @@ function TBoldDirectSingleLinkDefaultmapper.GetLinkClassObjectMapper: TBoldObjec result := nil; end; -procedure TBoldDirectSingleLinkDefaultmapper.CompareValuesToLists(OwningId: TBoldObjectId; MemberInterface: IBoldValue; ListOfClosestEnd: TBoldObjectIdlist; ListOfRemoteEnd: TBoldObjectIdlist; FailureList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList); +procedure TBoldDirectSingleLinkDefaultmapper.CompareValuesToLists(OwningId: TBoldObjectId; const MemberInterface: IBoldValue; ListOfClosestEnd: TBoldObjectIdlist; ListOfRemoteEnd: TBoldObjectIdlist; FailureList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList); var IdRef: IBoldObjectIdRef; begin @@ -812,10 +1129,10 @@ procedure TBoldDirectSingleLinkDefaultmapper.CompareValuesToLists(OwningId: TBol end; procedure TBoldDirectSingleLinkDefaultmapper.StuffValuesFromLists( - MemberInterface: IBoldValue; ListOfClosestEnd, + const MemberInterface: IBoldValue; ListOfClosestEnd, ListOfRemoteEnd: TBoldObjectIdlist); begin - (MemberInterface as IBoldObjectIdRef).SetFromId(FirstIdInList(ListOfClosestEnd)); + (MemberInterface as IBoldObjectIdRef).SetFromId(FirstIdInList(ListOfClosestEnd), false); end; { TBoldIndirectSingleLinkDefaultmapper } @@ -838,7 +1155,7 @@ constructor TBoldIndirectSingleLinkDefaultmapper.CreateFromMold( fRemoteInnerLinkMemberIndex := LinkClass.AllBoldMembers.IndexOf(Role.OtherEnd.LinkRole.OtherEnd); if (LinkClass.TableMapping = tmChildren) then - raise EBoldFeatureNotImplementedYet.CreateFmt(sChildMappedLinkClassesNotSupported, + raise EBoldFeatureNotImplementedYet.CreateFmt('%s.%s: ChildMapped LinkObjects (%s) are not supported!', [MoldClass.name, Role.Name, LinkClass.Name]); end; @@ -847,7 +1164,7 @@ function TBoldIndirectSingleLinkDefaultmapper.GetLinkClassObjectMapper: TBoldObj result := ObjectPersistenceMappers[ClosestOtherEndObjectMapperIndex]; end; -procedure TBoldIndirectSingleLinkDefaultmapper.CompareValuesToLists(OwningId: TBoldObjectId; MemberInterface: IBoldValue; ListOfClosestEnd: TBoldObjectIdlist; ListOfRemoteEnd: TBoldObjectIdlist; FailureList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList); +procedure TBoldIndirectSingleLinkDefaultmapper.CompareValuesToLists(OwningId: TBoldObjectId; const MemberInterface: IBoldValue; ListOfClosestEnd: TBoldObjectIdlist; ListOfRemoteEnd: TBoldObjectIdlist; FailureList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList); var IdRefPair: IBoldObjectIdRefPair; begin @@ -867,7 +1184,7 @@ procedure TBoldIndirectSingleLinkDefaultmapper.CompareValuesToLists(OwningId: TB end; procedure TBoldIndirectSingleLinkDefaultmapper.StuffValuesFromLists( - MemberInterface: IBoldValue; ListOfClosestEnd, + const MemberInterface: IBoldValue; ListOfClosestEnd, ListOfRemoteEnd: TBoldObjectIdlist); begin (MemberInterface as IBoldObjectIdRefPair).SetFromIds(FirstIdInList(ListOfClosestEnd), FirstIdInList(ListOfRemoteEnd)); @@ -876,7 +1193,7 @@ procedure TBoldIndirectSingleLinkDefaultmapper.StuffValuesFromLists( { TBoldDirectMultiLinkDefaultmapper } procedure TBoldDirectMultiLinkDefaultmapper.CompareValuesToLists( - OwningId: TBoldObjectId; MemberInterface: IBoldValue; ListOfClosestEnd, + OwningId: TBoldObjectId; const MemberInterface: IBoldValue; ListOfClosestEnd, ListOfRemoteEnd, FailureList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList); var IdList: IBoldObjectIdListRef; @@ -921,7 +1238,7 @@ function TBoldDirectMultiLinkDefaultmapper.GetLinkClassObjectMapper: TBoldObject end; procedure TBoldDirectMultiLinkDefaultmapper.StuffValuesFromLists( - MemberInterface: IBoldValue; ListOfClosestEnd, + const MemberInterface: IBoldValue; ListOfClosestEnd, ListOfRemoteEnd: TBoldObjectIdlist); begin (MemberInterface as IBoldObjectIdListRef).SetFromIdList(ListOfClosestEnd); @@ -930,7 +1247,7 @@ procedure TBoldDirectMultiLinkDefaultmapper.StuffValuesFromLists( { TBoldIndirectMultiLinkDefaultmapper } procedure TBoldIndirectMultiLinkDefaultmapper.CompareValuesToLists( - OwningId: TBoldObjectId; MemberInterface: IBoldValue; ListOfClosestEnd, + OwningId: TBoldObjectId; const MemberInterface: IBoldValue; ListOfClosestEnd, ListOfRemoteEnd, FailureList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList); var IdLists: IBoldObjectIdListRefPair; @@ -973,7 +1290,7 @@ constructor TBoldIndirectMultiLinkDefaultmapper.CreateFromMold( fRemoteInnerLinkMemberIndex := LinkClass.AllBoldMembers.IndexOf(Role.OtherEnd.LinkRole.OtherEnd); if (LinkClass.TableMapping = tmChildren) then - raise EBoldFeatureNotImplementedYet.CreateFmt(sChildMappedLinkClassesNotSupported, + raise EBoldFeatureNotImplementedYet.CreateFmt('%s.%s: ChildMapped LinkObjects (%s) are not supported!', [MoldClass.name, Role.Name, LinkClass.Name]); end; @@ -983,7 +1300,7 @@ function TBoldIndirectMultiLinkDefaultmapper.GetLinkClassObjectMapper: TBoldObje end; procedure TBoldIndirectMultiLinkDefaultmapper.StuffValuesFromLists( - MemberInterface: IBoldValue; ListOfClosestEnd, + const MemberInterface: IBoldValue; ListOfClosestEnd, ListOfRemoteEnd: TBoldObjectIdlist); begin (MemberInterface as IBoldObjectIdListRefPair).SetFromIdLists(ListOfClosestEnd, ListOfRemoteEnd); @@ -993,7 +1310,8 @@ procedure TBoldIndirectMultiLinkDefaultmapper.StuffValuesFromLists( function TBoldSingleLinkDefaultMapper.FirstIdInList(List: TBoldObjectIdList): TBoldObjectId; begin - Assert(List.Count <= 1); + if List.Count > 1 then + raise EBoldDuplicateSingleLinkValueInDb.Create(ObjectPersistenceMapper.ExpressionName + '.' + ExpressionName + ';List count is ' + IntToStr(List.Count) + ', expected <= 1, possible reason: duplicate values in DB for a single link'); if List.Count = 0 then Result := nil else @@ -1064,7 +1382,7 @@ procedure TBoldEmbeddedSingleLinkDefaultMapper.GetNonEmbeddedChangePoints( result.AddJoin(NewTableRef.GetColumnReference(MemberMapping.ColumnByIndex[0]), JoinTableRef.GetColumnReference(MemberMapping.ColumnByIndex[0])); result.AddJoin(NewTableRef.GetColumnReference(IDCOLUMN_NAME), JoinTableRef.GetColumnReference(IDCOLUMN_NAME)); Query.AddWCF(TBoldSQLWCFUnaryPrefix.Create(TBoldSQLWCFExists.Create(result, NewTableRef), - 'not')); // do not localize + 'not')); end; function JoinRootTableInto(Query: TBoldSQLQuery; TableRef: TBoldSQLTableReference): TBoldSQLTableReference; @@ -1141,6 +1459,7 @@ procedure TBoldEmbeddedSingleLinkDefaultMapper.InitializePSDescriptions; i, j: Integer; MemberMappings: TBoldMemberMappingArray; Columns: TStringList; + CatenatedColumns: string; BoldGuard: IBoldGuard; begin inherited; @@ -1150,14 +1469,29 @@ procedure TBoldEmbeddedSingleLinkDefaultMapper.InitializePSDescriptions; if not IsInherited then begin - Columns := TStringList.create; MemberMappings := SystemPersistenceMapper.MappingInfo.GetMemberMappings(ObjectPersistenceMapper.ExpressionName, ExpressionName); - for i := 0 to length(MemberMappings) - 1 do + Columns := TStringList.create; + if SystemPersistenceMapper.SQLDataBaseConfig.SingleIndexOrderedLinks then begin - Columns.CommaText := MemberMappings[i].Columns; - for j := 0 to Columns.Count - 1 do + for i := 0 to length(MemberMappings) - 1 do + begin + Columns.CommaText := MemberMappings[i].Columns; + CatenatedColumns := Columns[0]; + for j := 1 to Columns.Count - 1 do + CatenatedColumns := CatenatedColumns + ';' + Columns[j]; SystemPersistenceMapper.EnsureIndex(MemberMappings[i].TableName, - Columns[j], False, False, ObjectPersistenceMapper.Versioned); + CatenatedColumns, False, False, False, ObjectPersistenceMapper.Versioned); + end; + end + else + begin + for i := 0 to length(MemberMappings) - 1 do + begin + Columns.CommaText := MemberMappings[i].Columns; + for j := 0 to Columns.Count - 1 do + SystemPersistenceMapper.EnsureIndex(MemberMappings[i].TableName, + Columns[j], False, False, False, ObjectPersistenceMapper.Versioned); + end; end; end; end; @@ -1182,7 +1516,7 @@ function TBoldEmbeddedSingleLinkDefaultMapper.GetMainColumnName: String; function TBoldEmbeddedSingleLinkDefaultMapper.GetOrderColumnName: String; begin - result := ColumnDescriptions[1].SQLName; + result := ColumnDescriptions[ORDERCOLUMN_INDEX].SQLName; end; function TBoldNonEmbeddedLinkDefaultMapper.GetLinkClassTableName: string; @@ -1252,6 +1586,7 @@ function TBoldNonEmbeddedLinkDefaultMapper.GetSupportsPolymorphicFetch: Boolean; end; initialization + with BoldMemberPersistenceMappers do begin AddDescriptor(TBoldNonEmbeddedLinkDefaultMapper, alAbstract); @@ -1280,4 +1615,3 @@ finalization end. - diff --git a/Source/PMapper/Default/BoldPSDescriptionsDefault.pas b/Source/PMapper/Default/BoldPSDescriptionsDefault.pas index aafb9fd..0901142 100644 --- a/Source/PMapper/Default/BoldPSDescriptionsDefault.pas +++ b/Source/PMapper/Default/BoldPSDescriptionsDefault.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldPSDescriptionsDefault; interface @@ -7,12 +10,14 @@ interface BoldPSDescriptionsSQL, BoldPSParams, BoldPSParamsSQL, - BoldPSParamsDefault; + BoldPSParamsDefault, + BoldDBInterfaces; type {---TBoldDefaultSystemDescription---} TBoldDefaultSystemDescription = class(TBoldSQLSystemDescription) private + Query: IBoldExecQuery; FIdTable: TBoldSQLTableDescription; FTimeStamptable: TBoldSQLTableDescription; FTypeTable: TBoldSQLTableDescription; @@ -36,16 +41,15 @@ TBoldDefaultSystemDescription = class(TBoldSQLSystemDescription) procedure AddFirstClock(PSParams: TBoldPSDefaultParams); procedure AddTableNames(PSParams: TBoldPSDefaultParams); - procedure GenerateScriptForFirstID(Script: TStrings; Separator: String); - procedure GenerateScriptForFirstTimeStamp(Script: TStrings; Separator: String); - procedure GenerateScriptForFirstClock(Script: TStrings; Separator: String); - procedure GenerateScriptForTableNames(Script: TStrings; Separator: String); + procedure GenerateScriptForFirstID(Script: TStrings); + procedure GenerateScriptForFirstTimeStamp(Script: TStrings); + procedure GenerateScriptForFirstClock(Script: TStrings); + procedure GenerateScriptForTableNames(Script: TStrings); protected - procedure InitializeKnownSystemtables(KnownTables: TStrings; PSParams: TBoldPSSQLParams); override; public procedure CreatePersistentStorage(PSParams: TBoldPSParams); override; - procedure GenerateDatabaseScript(Script: TStrings; Separator: string); override; + procedure GenerateDatabaseScript(Script: TStrings); override; property IdTable: TBoldSQLTableDescription read FIdTable write SetIdTable; property RootTable: TBoldSQLTableDescription read fRootTable write SetRootTable; property TypeTable: TBoldSQLTableDescription read FTypeTable write SetTypeTable; @@ -63,11 +67,15 @@ implementation uses SysUtils, - BoldDBInterfaces, + {$IFNDEF BOLD_UNICODE} + StringBuilder, + {$ENDIF} + DB, BoldDefs, BoldLogHandler, BoldNameExpander, - BoldPMConsts; + BoldMath, + BoldRev; {---TBoldDefaultSystemDescription---} @@ -92,28 +100,23 @@ procedure TBoldDefaultSystemDescription.AddFirstClock(PSParams: TBoldPSDefaultPa end; procedure AddFirstClockUsingQuery; - var - Q: IBoldExecQuery; begin - q := PSParams.DataBase.GetExecQuery; - try - q.AssignSQLText(format( - 'INSERT INTO %s (%s, %s) VALUES (0, :FirstClock)', // do not localize - [LastClockTable.SQLName, LASTTIMESTAMPCOLUMN_NAME, LASTCLOCKCOLUMN_NAME] )); - q.ParamByName('FirstClock').AsDateTime := 0; // do not localize - q.ExecSQL; - finally - PSParams.DataBase.ReleaseExecQuery(q); - end; + Query.AssignSQLText(format( + 'INSERT INTO %s (%s, %s) VALUES (0, :FirstClock)', + [LastClockTable.SQLName, LASTTIMESTAMPCOLUMN_NAME, LASTCLOCKCOLUMN_NAME] )); + Query.CreateParam(ftDateTime, 'FirstClock').AsDateTime := 0; + Query.ParamCheck := true; + Query.ExecSQL; + Query.ParamCheck := false; end; - + begin - BoldLog.Log(sLogWritingFirstClock); + BoldLog.Log('Writing First Clock'); case EffectiveGenerationMode(PSParams) of dbgTable: AddFirstClockUsingTable; dbgQuery: AddFirstClockUsingQuery; - else raise EBold.CreateFmt(sUnknownGenerationMode, [ClassName, 'AddFirstClock']); // do not localize + else raise EBold.CreateFmt('%s.AddFirstClock: unknown database generation mode', [ClassName]); end; end; @@ -138,26 +141,19 @@ procedure TBoldDefaultSystemDescription.AddFirstID(PSParams: TBoldPSDefaultParam end; procedure AddFirstIdUsingQuery; - var - Q: IBoldExecQuery; begin - q := PSParams.DataBase.GetExecQuery; - try - q.AssignSQLText(format( - 'INSERT INTO %s (%s) VALUES (1)', // do not localize + Query.AssignSQLText(format( + 'INSERT INTO %s (%s) VALUES (1)', [IDTable.SQLName, IDCOLUMN_NAME] )); - q.ExecSQL; - finally - PSParams.DataBase.ReleaseExecQuery(q); - end; + Query.ExecSQL; end; begin - BoldLog.Log(sLogWritingFirstID); + BoldLog.Log('Writing First ID'); case EffectiveGenerationMode(PSParams) of dbgTable: AddFirstIDUsingTable; dbgQuery: AddFirstIDUsingQuery; - else raise EBold.CreateFmt(sUnknownGenerationMode, [ClassName, 'AddFirstID']); // do not localize + else raise EBold.CreateFmt('%s.AddFirstID: unknown database generation mode', [ClassName]); end; end; @@ -166,7 +162,7 @@ procedure TBoldDefaultSystemDescription.AddFirstTimeStamp(PSParams: TBoldPSDefau var Table: IBoldTable; begin - BoldLog.Log(sLogWritingFirstTimeStamp); + BoldLog.Log('Writing First TimeStamp'); Table := PSParams.DataBase.GetTable; with Table do try @@ -181,26 +177,19 @@ procedure TBoldDefaultSystemDescription.AddFirstTimeStamp(PSParams: TBoldPSDefau end; end; procedure AddFirstTimeStampUsingQuery; - var - Q: IBoldExecQuery; begin - q := PSParams.DataBase.GetExecQuery; - try - q.AssignSQLText(format( - 'INSERT INTO %s (%s) VALUES (0)', // do not localize - [TimeStampTable.SQLName, BoldExpandName(TIMESTAMPCOLUMN_NAME, '', xtSQL, SQLDatabaseConfig.MaxDbIdentifierLength, NationalCharConversion)] )); - q.ExecSQL; - finally - PSParams.DataBase.ReleaseExecQuery(q); - end; + Query.AssignSQLText(format( + 'INSERT INTO %s (%s) VALUES (0)', + [TimeStampTable.SQLName, BoldExpandName(TIMESTAMPCOLUMN_NAME, '', xtSQL, SQLDatabaseConfig.MaxDbIdentifierLength, NationalCharConversion)] )); + Query.ExecSQL; end; begin - BoldLog.Log(sLogWritingFirstTimeStamp); + BoldLog.Log('Writing First TimeStamp'); case EffectiveGenerationMode(PSParams) of dbgTable: AddFirstTimeStampUsingTable; dbgQuery: AddFirstTimeStampUsingQuery; - else raise EBold.CreateFmt(sUnknownGenerationMode, [ClassName, 'AddFirstTimeStamp']); // do not localize + else raise EBold.CreateFmt('%s.AddFirstTimeStamp: unknown database generation mode', [ClassName]); end; end; @@ -220,7 +209,7 @@ procedure TBoldDefaultSystemDescription.AddTableNames(PSParams: TBoldPSDefaultPa for i := 0 to SQLTablesList.Count - 1 do begin Append; - FieldValues['TABLENAME'] := SQLTablesList[i].SQLName; // do not localize + FieldValues['TABLENAME'] := SQLTablesList[i].SQLName; Post; end; Close; @@ -231,45 +220,58 @@ procedure TBoldDefaultSystemDescription.AddTableNames(PSParams: TBoldPSDefaultPa procedure AddTableNamesUsingQuery; var - Q: IBoldExecQuery; i: integer; + row, limit: integer; + sb: TStringBuilder; + TableCount: integer; + sInsert: string; begin - q := PSParams.DataBase.GetExecQuery; + sb := TStringBuilder.Create; try - q.AssignSQLText(format( - 'INSERT INTO %s (TABLENAME) VALUES (:TABLENAME)', // do not localize - [TableTable.SQLName] )); - for i := 0 to SQLTablesList.Count - 1 do + sInsert := format('INSERT INTO %s (TABLENAME) VALUES ', [TableTable.SQLName]); + limit := SQLDatabaseConfig.MultiRowInsertLimit; + row := 0; + for i := 0 to SQLTablesList.Count-1 do begin - q.ParamByName('TABLENAME').AsString := SQLTablesList[i].SQLName; // do not localize - q.ExecSQL; + if row = 0 then + sb.append(sInsert); + sb.Append(Format('(''%s'')', [SQLTablesList[i].SQLName])); + inc(row); + if (row = limit) or (i = SQLTablesList.Count - 1) then + begin + Query.AssignSQLText(sb.ToString); + Query.ExecSQL; + row := 0; + sb.clear; + end + else + sb.Append(','); end; finally - PSParams.DataBase.ReleaseExecQuery(q); + sb.free; end; end; begin - BoldLog.Log(sLogWritingTableNames); + BoldLog.Log('Writing TableNames'); case EffectiveGenerationMode(PSParams) of dbgTable: AddTableNamesUsingTable; dbgQuery: AddTableNamesUsingQuery; - else raise EBold.CreateFmt(sUnknownGenerationMode, [ClassName, 'AddTableNames']); // do not localize + else raise EBold.CreateFmt('%s.AddTableNames: unknown database generation mode', [ClassName]); end; end; procedure TBoldDefaultSystemDescription.CreatePersistentStorage(PSParams: TBoldPSParams); var PSParamsDefault: TBoldPSDefaultParams; -begin - inherited; - if BoldLog.ProcessInterruption then - exit; - BoldLog.LogHeader := sLogInitializingDefaultPS; - PSParamsDefault := PSParams as TBoldPSDefaultParams; - if EffectiveUseTransactions(PSParamsDefault) then - PSParamsDefault.Database.StartTransaction; - try + + procedure InternalExecute; + begin + Query := PSParamsDefault.Database.GetExecQuery; + Query.ParamCheck := false; + Query.StartSQLBatch; + if EffectiveUseTransactions(PSParamsDefault) then + PSParamsDefault.Database.StartTransaction; AddFirstID(PSParamsDefault); if assigned(TimeStampTable) then AddFirstTimeStamp(PSParamsDefault); @@ -277,60 +279,78 @@ procedure TBoldDefaultSystemDescription.CreatePersistentStorage(PSParams: TBoldP AddFirstClock(PSParamsDefault); AddTableNames(PSParamsDefault); BoldLog.Separator; + Query.EndSQLBatch; + end; + +begin + inherited; + if BoldLog.ProcessInterruption then + exit; + BoldLog.LogHeader := 'Initializing Default Persistent Storage'; + PSParamsDefault := PSParams as TBoldPSDefaultParams; + try + InternalExecute; finally + PSParamsDefault.Database.ReleaseExecQuery(Query); if EffectiveUseTransactions(PSParamsDefault) then begin BoldLog.Separator; - BoldLog.Log(sCommittingInitialData); + BoldLog.Log('Committing changes to initial data'); PSParamsDefault.Database.Commit; end; end; end; -procedure TBoldDefaultSystemDescription.GenerateDatabaseScript( - Script: TStrings; Separator: string); +procedure TBoldDefaultSystemDescription.GenerateDatabaseScript(Script: TStrings); begin inherited; - GenerateScriptForFirstID(Script, Separator); + GenerateScriptForFirstID(Script); if assigned(TimeStampTable) then - GenerateScriptForFirstTimeStamp(Script, Separator); + GenerateScriptForFirstTimeStamp(Script); if assigned(LastClockTable) then - GenerateScriptForFirstClock(Script, Separator); - GenerateScriptForTableNames(Script, Separator); + GenerateScriptForFirstClock(Script); + GenerateScriptForTableNames(Script); end; -procedure TBoldDefaultSystemDescription.GenerateScriptForFirstClock(Script: TStrings; Separator: String); +procedure TBoldDefaultSystemDescription.GenerateScriptForFirstClock(Script: TStrings); begin - Script.Add(Separator); Script.Add(format( - 'INSERT INTO %s (%s, %s) VALUES (0, %s)', // do not localize - [LastClockTable.SQLName, LASTTIMESTAMPCOLUMN_NAME, LASTCLOCKCOLUMN_NAME, DateToStr(0)] )); + 'INSERT INTO %s (%s, %s) VALUES (0, %s)%s', + [LastClockTable.SQLName, LASTTIMESTAMPCOLUMN_NAME, LASTCLOCKCOLUMN_NAME, QuotedStr(DateToStr(0)), + SQLDatabaseConfig.SqlScriptTerminator] )); + if SQLDatabaseConfig.SqlScriptSeparator<>'' then + Script.Add(SQLDatabaseConfig.SqlScriptSeparator); end; -procedure TBoldDefaultSystemDescription.GenerateScriptForFirstID(Script: TStrings; Separator: String); +procedure TBoldDefaultSystemDescription.GenerateScriptForFirstID(Script: TStrings); begin - Script.Add(Separator); - Script.Add(format('INSERT INTO %s (%s) VALUES (1)', [IDTable.SQLName, IDCOLUMN_NAME] )); // do not localize + Script.Add(format('INSERT INTO %s (%s) VALUES (1)%s', [IDTable.SQLName, IDCOLUMN_NAME, SQLDatabaseConfig.SqlScriptTerminator] )); + if SQLDatabaseConfig.SqlScriptSeparator<>'' then + Script.Add(SQLDatabaseConfig.SqlScriptSeparator); end; -procedure TBoldDefaultSystemDescription.GenerateScriptForFirstTimeStamp(Script: TStrings; Separator: String); +procedure TBoldDefaultSystemDescription.GenerateScriptForFirstTimeStamp(Script: TStrings); begin - Script.Add(Separator); Script.Add(format( - 'INSERT INTO %s (%s) VALUES (0)', // do not localize - [TimeStampTable.SQLName, BoldExpandName(TIMESTAMPCOLUMN_NAME, '', xtSQL, SQLDatabaseConfig.MaxDbIdentifierLength, NationalCharConversion)] )); + 'INSERT INTO %s (%s) VALUES (0)%s', + [TimeStampTable.SQLName, + BoldExpandName(TIMESTAMPCOLUMN_NAME, '', xtSQL, SQLDatabaseConfig.MaxDbIdentifierLength, NationalCharConversion), + SQLDatabaseConfig.SqlScriptTerminator] )); + if SQLDatabaseConfig.SqlScriptSeparator<>'' then + Script.Add(SQLDatabaseConfig.SqlScriptSeparator); end; -procedure TBoldDefaultSystemDescription.GenerateScriptForTableNames(Script: TStrings; Separator: String); +procedure TBoldDefaultSystemDescription.GenerateScriptForTableNames(Script: TStrings); var i: integer; begin for i := 0 to SQLTablesList.Count - 1 do begin - Script.Add(Separator); Script.Add(format( - 'INSERT INTO %s (TABLENAME) VALUES (''%s'')', // do not localize - [TableTable.SQLName, SQLTablesList[i].SQLName])); + 'INSERT INTO %s (TABLENAME) VALUES (''%s'')%s', + [TableTable.SQLName, SQLTablesList[i].SQLName, SQLDatabaseConfig.SqlScriptTerminator])); + if SQLDatabaseConfig.SqlScriptSeparator<>'' then + Script.Add(SQLDatabaseConfig.SqlScriptSeparator); end; end; @@ -339,15 +359,12 @@ procedure TBoldDefaultSystemDescription.InitializeKnownSystemtables( var Query: IBoldQuery; begin - // Reset The Query-pointer to avoid AVs at the end of method Query := nil; - // try to determine if the TablesTable exists... if PSParams.DataBase.TableExists(TableTable.SQLName) then begin - // Load the data from the table Query := PSParams.DataBase.GetQuery; try - Query.AssignSQLText(format('SELECT %s FROM %s', [TABLENAMECOLUMN_NAME, TableTable.SQLName])); // do not localize // do not localize + Query.AssignSQLText(format('SELECT %s FROM %s', [TABLENAMECOLUMN_NAME, TableTable.SQLName])); try Query.Open; while not Query.Eof do @@ -357,8 +374,7 @@ procedure TBoldDefaultSystemDescription.InitializeKnownSystemtables( end; Query.Close; except - // silence any exceptions (this happens if the table does not exist in the database, - // and the databaseinterfaces does not support IBoldTable + end; finally PSParams.DataBase.ReleaseQuery(Query); @@ -366,34 +382,42 @@ procedure TBoldDefaultSystemDescription.InitializeKnownSystemtables( end; end; -procedure TBoldDefaultSystemDescription.SetIdTable(const Value: TBoldSQLTableDescription); +procedure TBoldDefaultSystemDescription.SetIdTable( + const Value: TBoldSQLTableDescription); begin FIdTable := Value; end; -procedure TBoldDefaultSystemDescription.SetRootTable(const Value: TBoldSQLTableDescription); +procedure TBoldDefaultSystemDescription.SetRootTable( + const Value: TBoldSQLTableDescription); begin fRootTable := Value; end; -procedure TBoldDefaultSystemDescription.SetTabletable(const Value: TBoldSQLTableDescription); +procedure TBoldDefaultSystemDescription.SetTabletable( + const Value: TBoldSQLTableDescription); begin FTabletable := Value; end; -procedure TBoldDefaultSystemDescription.SetTimeStamptable(const Value: TBoldSQLTableDescription); +procedure TBoldDefaultSystemDescription.SetTimeStamptable( + const Value: TBoldSQLTableDescription); begin FTimeStamptable := Value; end; -procedure TBoldDefaultSystemDescription.SetTypeTable(const Value: TBoldSQLTableDescription); +procedure TBoldDefaultSystemDescription.SetTypeTable( + const Value: TBoldSQLTableDescription); begin FTypeTable := Value; end; -procedure TBoldDefaultSystemDescription.SetXFilestable(const Value: TBoldSQLTableDescription); +procedure TBoldDefaultSystemDescription.SetXFilestable( + const Value: TBoldSQLTableDescription); begin FXFilestable := Value; end; +initialization + end. diff --git a/Source/PMapper/Default/BoldPSParamsDefault.pas b/Source/PMapper/Default/BoldPSParamsDefault.pas index bc820df..1999cdf 100644 --- a/Source/PMapper/Default/BoldPSParamsDefault.pas +++ b/Source/PMapper/Default/BoldPSParamsDefault.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldPSParamsDefault; interface @@ -12,4 +15,10 @@ TBoldPSDefaultParams = class(TBoldPSSQLParams) implementation +uses + BoldRev; + + +initialization + end. diff --git a/Source/PMapper/SQL/BoldPMappersSQL.pas b/Source/PMapper/SQL/BoldPMappersSQL.pas index b054858..00043df 100644 --- a/Source/PMapper/SQL/BoldPMappersSQL.pas +++ b/Source/PMapper/SQL/BoldPMappersSQL.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldPMappersSQL; interface @@ -13,10 +16,12 @@ interface BoldId, BoldSQLMappingInfo, BoldSQLDatabaseConfig, + BoldIndexCollection, BoldValueSpaceInterfaces, BoldTypeNameDictionary, BoldPSDescriptionsSQL, - BoldTaggedValueSupport; + BoldTaggedValueSupport, + BoldElements; type { forward declarations } @@ -24,12 +29,15 @@ TBoldSystemSQLMapper = class; TBoldObjectSQLMapper = class; TBoldMemberSQLMapper = class; TBoldPreInitializeBoldDbType = procedure(SystemSQLMapper: TBoldSystemSQLMapper) of Object; + TBoldOnPsEvaluate = procedure(const ABoldQuery: IBoldQuery) of Object; EBoldDbTypeMissing = class(EBold); {---Enumerations---} TBoldDBStorageMode = (dsmUpdate, dsmCreate); + + {---TBoldSystemSQLMapper---} TBoldSystemSQLMapper = class(TBoldSystemPersistenceMapper) private @@ -38,42 +46,59 @@ TBoldSystemSQLMapper = class(TBoldSystemPersistenceMapper) fMappingInfo: TBoldSQLMappingInfo; fNationalCharConversion: TBoldNationalCharConversion; fSQLDataBaseConfig: TBoldSQLDataBaseConfig; + fCustomIndexes: TBoldIndexCollection; fOnGetDatabase: TBoldGetDatabaseEvent; + fMaxDbType: integer; + fExecQuery: IBoldExecQuery; + fOnPsEvaluate: TBoldOnPsEvaluate; + fTopSortedIndexForBoldDbType: array of integer; // JNo, optimization function GetIBoldDataBase: IBoldDataBase; function GetAllTables: TBoldSQLTableDescriptionList; function GetPSSystemDescription: TBoldSQLSystemDescription; - function GetRootClassObjectPersistenceMapper: TBoldObjectSQLMapper; - function GetMappingInfo: TBoldSQLMappingInfo; + function GetRootClassObjectPersistenceMapper: TBoldObjectSQLMapper; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetMappingInfo: TBoldSQLMappingInfo; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure InitializeTopSortedIndexForBoldDbType; protected procedure InitializeBoldDbType; virtual; abstract; procedure FillPSParams(PSParams: TBoldPSParams); override; function CreatePSParams: TBoldPSParams; override; - procedure StartTransaction(ValueSpace: IBoldValueSpace); override; - procedure Commit(ValueSpace: IBoldValueSpace); override; - procedure RollBack(ValueSpace: IBoldValueSpace); override; + procedure StartTransaction(const ValueSpace: IBoldValueSpace); override; + procedure Commit(const ValueSpace: IBoldValueSpace); override; + procedure RollBack(const ValueSpace: IBoldValueSpace); override; function CreateMappingInfo: TBoldSQLMappingInfo; virtual; abstract; + procedure AddCustomIndexes; public - constructor CreateFromMold(MoldModel: TMoldModel; TypeNameDictionary: TBoldTypeNameDictionary; SQLDatabaseConfig: TBoldSQLDatabaseConfig; GetDatabaseFunc: TBoldGetDatabaseEvent); + constructor CreateFromMold(MoldModel: TMoldModel; TypeNameDictionary: TBoldTypeNameDictionary; + CustomIndexes: TBoldIndexCollection; SQLDatabaseConfig: TBoldSQLDatabaseConfig; GetDatabaseFunc: TBoldGetDatabaseEvent); destructor Destroy; override; procedure PMFetch(ObjectIDList: TBoldObjectIdList; - ValueSpace: IBoldValueSpace; + const ValueSpace: IBoldValueSpace; MemberIdList: TBoldMemberIdList; FetchMode: Integer; TranslationList: TBoldIdTranslationList); override; function BoldDbTypeForTopSortedIndex(TopSortedIndex: Integer): TBoldDbType; procedure CloseDataBase; procedure CreatePersistentStorage; override; - procedure GenerateDatabaseScript(Script: TStrings; Separator: string); virtual; + procedure GenerateDatabaseScript(Script: TStrings); virtual; function EnsureTable(const TableName: string; TableVersioned: Boolean): TBoldSQLTableDescription; virtual; abstract; + function EnsureColumn(const TableName, ColumnName, SQLType, + SQLAllowNull: string; const BDEType: TFieldType; Length: Integer; + const AllowNull, InVersionedTable: Boolean; + const DefaultDBValue: String): TBoldSQLColumnDescription; + procedure EnsureIndex(const TableName, Fields: string; const PrimaryIndex, + Unique, InVersionedTable: Boolean); function GetQuery: IBoldQuery; function GetExecQuery: IBoldExecQuery; + procedure StartSQLBatch; override; + procedure EndSQLBatch; override; + procedure FailSQLBatch; override; procedure InvokeMemberMappersInitializeSystem; virtual; procedure OpenDatabase(ReadDbTypeFromDB: Boolean; ReadMappingFromDB: Boolean); procedure ReleaseQuery(var aQuery: IBoldQuery); procedure ReleaseExecQuery(var aQuery: IBoldExecQuery); function TopSortedIndexForBoldDbType(BoldDbType: TBoldDbType): Integer; + function CanEvaluateInPS(sOCL: string; aSystem: TBoldElement; aContext: TBoldElementTypeInfo = nil; const aVariableList: TBoldExternalVariableList = nil): Boolean; virtual; abstract; property AllTables: TBoldSQLTableDescriptionList read GetAllTables; -// property Connected: Boolean read GetConnected; property Database: IBoldDataBase read GetIBoldDataBase; property OnPreInitializeBoldDbType: TBoldPreInitializeBoldDbType read fOnPreInitializeBoldDbType write fOnPreInitializeBoldDbType; property PSSystemDescription: TBoldSQLSystemDescription read GetPSSystemDescription; @@ -81,12 +106,13 @@ TBoldSystemSQLMapper = class(TBoldSystemPersistenceMapper) property MappingInfo: TBoldSQLMappingInfo read GetMappingInfo; property NationalCharConversion: TBoldNationalCharConversion read fNationalCharConversion; property SQLDataBaseConfig: TBoldSQLDataBaseConfig read fSQLDataBaseConfig; + property OnPsEvaluate: TBoldOnPsEvaluate read fOnPsEvaluate write fOnPsEvaluate; end; {---TBoldObjectSQLMapper---} TBoldObjectSQLMapper = class(TBoldObjectPersistenceMapper) private - fBoldDbType: TBoldDbType; // FIXME move down + fBoldDbType: TBoldDbType; fAllTables: TBoldSQLTableDescriptionList; fMainTable: TBoldSQLTableDescription; function GetSystemPersistenceMapper: TBoldSystemSQLMapper; @@ -104,15 +130,16 @@ TBoldObjectSQLMapper = class(TBoldObjectPersistenceMapper) public constructor CreateFromMold(MoldClass: TMoldClass; Owner: TBoldSystemPersistenceMapper; TypeNameDictionary: TBoldTypeNameDictionary); override; destructor Destroy; override; - procedure GenerateDatabaseScript(Script: TStrings; Separator: string); virtual; + procedure GenerateDatabaseScript(Script: TStrings); virtual; function UpdatesMembersInTable(aTable: TBoldSQLTableDescription): Boolean; virtual; abstract; property AllTables: TBoldSQLtableDescriptionList read GetAllTables; property MainTable: TBoldSQLTableDescription read fmainTable; procedure RetrieveSelectStatement(s: TStrings; MemberMapperList: TBoldMemberPersistenceMapperList; FetchMode: Integer; ForceRootTable: Boolean); virtual; procedure RetrieveTimeStampCondition(SQL: TStrings; TimeStamp: TBoldTimeStampType; UseAlias: Boolean; WhereToken: string; UseOwnTableForStartTime: Boolean; SuggestedStartTimeAlias: string = ''; SuggestedEndTimeAlias: string = ''); property BoldDbType: TBoldDbType read fBoldDbType write fBoldDbType; - procedure ValuesFromFieldsByMemberList(ObjectId: TBoldObjectId; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; DataSet: IBoldDataSet; MemberList: TBoldMemberPersistenceMapperList); - procedure ValuesToParamsByMemberList(ObjectId: TBoldObjectId; ValueSpace: IBoldValueSpace; Query: IBoldExecQuery; memberList: TBoldMemberPersistenceMapperList; TranslationList: TBoldIdTranslationList; DBStorageMode: TBoldDBStorageMode); + procedure ValuesFromFieldsByMemberList(ObjectId: TBoldObjectId; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; const DataSet: IBoldDataSet; MemberList: TBoldMemberPersistenceMapperList); + procedure ValuesToParamsByMemberList(ObjectId: TBoldObjectId; const ValueSpace: IBoldValueSpace; const Query: IBoldExecQuery; memberList: TBoldMemberPersistenceMapperList; TranslationList: TBoldIdTranslationList; DBStorageMode: TBoldDBStorageMode); + procedure ValuesToQueryByMemberList(ObjectId: TBoldObjectId; const ValueSpace: IBoldValueSpace; const Query: IBoldExecQuery; SQL: TStrings; memberList: TBoldMemberPersistenceMapperList; TranslationList: TBoldIdTranslationList; DBStorageMode: TBoldDBStorageMode); property SystemPersistenceMapper: TBoldSystemSQLMapper read GetSystemPersistenceMapper; end; @@ -135,25 +162,25 @@ TBoldMemberSQLMapper = class(TBoldMemberPersistenceMapper) function DefaultDefaultDbValue: String; virtual; property InitialColumnRootName: string read fInitialColumnRootName; function GetRequiresLiveQuery: Boolean; virtual; - procedure SetParamToNullWithDataType(aParam: IBoldParameter; FieldType: TFieldType); + procedure SetParamToNullWithDataType(const aParam: IBoldParameter; FieldType: TFieldType); function GetColumnBDEFieldType(ColumnIndex: Integer): TFieldType; virtual; property InitialColumnName[Columnindex: integer]: string read GetInitialColumnName; public constructor CreateFromMold(Moldmember: TMoldMember; MoldClass: TMoldClass; Owner: TBoldObjectPersistenceMapper; const MemberIndex: Integer; TypeNameDictionary: TBoldTypeNameDictionary); override; destructor Destroy; override; - procedure GenerateDatabaseScript(Script: TStrings; Separator: string); virtual; + procedure GenerateDatabaseScript(Script: TStrings); virtual; property ColumnDescriptions: TBoldSQLDescriptionList read GetColumnDescriptions; property AllowNullAsSQL: string read GetAllowNullAsSQL; property ColumnCount: integer read GetColumnCount; property ColumnTypeAsSQL[Columnindex: integer]: string read GetColumnTypeAsSQL; property ColumnSize[Columnindex: integer]: integer read GetColumnSize; property AllowNull: Boolean read fAllowNull; -// procedure ValueToParam(Value: IBoldValue; Param: IBoldParameter; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList); virtual; - procedure ValueToParam(ObjectContent: IBoldObjectContents; Param: IBoldParameter; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList); virtual; - procedure ValueFromField(OwningObjectId: TBoldObjectId; ObjectContent: IBoldObjectContents; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; Field: IBoldField; ColumnIndex: Integer); virtual; - procedure ValueToQuery(ObjectContent: IBoldObjectContents; ValueSpace: IBoldValueSpace; Query: IBoldExecQuery; TranslationList: TBoldIdtranslationlist; DBStorageMode: TBoldDBStorageMode); - procedure ValueFromQuery(OwningObjectId: TBoldObjectId; ObjectContent: IBoldObjectContents; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; DataSet: IBoldDataSet); virtual; - procedure InitializeSystem(theDatabase: IBoldDataBase); virtual; + function ValueAsVariant(const ObjectContent: IBoldObjectContents; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList): variant; virtual; + procedure ValueToParam(const ObjectContent: IBoldObjectContents; const Param: IBoldParameter; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList); virtual; + procedure ValueFromField(OwningObjectId: TBoldObjectId; const ObjectContent: IBoldObjectContents; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; const Field: IBoldField; ColumnIndex: Integer); virtual; + procedure ValueToQuery(const ObjectContent: IBoldObjectContents; const ValueSpace: IBoldValueSpace; const Query: IBoldExecQuery; TranslationList: TBoldIdtranslationlist; DBStorageMode: TBoldDBStorageMode); + procedure ValueFromQuery(OwningObjectId: TBoldObjectId; const ObjectContent: IBoldObjectContents; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; const DataSet: IBoldDataSet); + procedure InitializeSystem(const theDatabase: IBoldDataBase); virtual; property ColumnBDEFieldType[Columnindex: integer]: TFieldType read GetColumnBDEFieldType; property RequiresLiveQuery: Boolean read GetRequiresLiveQuery; property SystemPersistenceMapper: TBoldSystemSQLMapper read GetSystemPersistenceMapper; @@ -167,9 +194,17 @@ implementation BoldUtils, BoldPSParamsSQL, BoldNameExpander, + BoldValueInterfaces, + BoldDefaultStreamNames, + Variants, SysUtils, - BoldPMConsts; - + {$IFDEF RIL} + {$IFNDEF BOLD_UNICODE} + StringBuilder, + {$ENDIF} + {$ENDIF} + BoldRev; + {---TBoldSystemSQLMapper---} function TBoldSystemSQLMapper.GetAllTables: TBoldSQLTableDescriptionList; begin @@ -181,13 +216,18 @@ function TBoldSystemSQLMapper.GetPSSystemDescription: TBoldSQLSystemDescription; result := (inherited PSSystemDescription) as TBoldSQLSystemDescription; end; -constructor TBoldSystemSQLMapper.CreateFromMold(MoldModel: TMoldModel; TypeNameDictionary: TBoldTypeNameDictionary; SQlDatabaseConfig: TBoldSQLDatabaseConfig; GetDatabaseFunc: TBoldGetDatabaseEvent); +constructor TBoldSystemSQLMapper.CreateFromMold(MoldModel: TMoldModel; TypeNameDictionary: TBoldTypeNameDictionary; + CustomIndexes: TBoldIndexCollection; SQlDatabaseConfig: TBoldSQLDatabaseConfig; GetDatabaseFunc: TBoldGetDatabaseEvent); begin fNationalCharConversion := MoldModel.NationalCharConversion; - fSQLDataBaseConfig := TBoldSQLDataBaseConfig.Create; - fSQLDataBaseConfig.AssignConfig(SQLDatabaseConfig); + fSQLDataBaseConfig := SQlDatabaseConfig; + fCustomIndexes := TBoldIndexCollection.Create(nil); + if Assigned(CustomIndexes) then + fCustomIndexes.Assign(CustomIndexes); fOnGetDatabase := GetDatabaseFunc; - inherited createFromMold(MoldModel, TypeNameDictionary); + fMaxDbType := -1; + inherited CreateFromMold(MoldModel, TypeNameDictionary, SQlDatabaseConfig.DefaultObjectMapper); + AddCustomIndexes; end; procedure TBoldSystemSQLMapper.FillPSParams(PSParams: TBoldPSParams); @@ -211,17 +251,51 @@ procedure TBoldSystemSQLMapper.ReleaseQuery(var aQuery: IBoldQuery); Database.ReleaseQuery(aQuery); end; +function TBoldSystemSQLMapper.GetExecQuery: IBoldExecQuery; +begin + if not Assigned(fExecQuery) then + begin + fExecQuery := Database.GetExecQuery; + end; + result := fExecQuery; +end; + +procedure TBoldSystemSQLMapper.ReleaseExecQuery(var aQuery: IBoldExecQuery); +begin + if fExecQuery <> aQuery then + Database.ReleaseExecQuery(aQuery); +end; + function TBoldSystemSQLMapper.GetIBoldDataBase: IBoldDataBase; begin if not assigned(fOnGetDatabase) then raise EBoldInternal.CreateFmt('%s: No event that provides an IBoldDatabase', [classname]); result := fOnGetDatabase; if not assigned(result) then - raise EBold.CreateFmt(sNoDatabase, [classname]); + raise EBold.CreateFmt('%s: No database', [classname]); end; -procedure TBoldSystemSQLMapper.StartTransaction(ValueSpace: IBoldValueSpace); +procedure TBoldSystemSQLMapper.StartSQLBatch; begin + GetExecQuery.StartSQLBatch; +end; + +procedure TBoldSystemSQLMapper.EndSQLBatch; +begin + GetExecQuery.EndSQLBatch; +end; + +procedure TBoldSystemSQLMapper.FailSQLBatch; +begin + GetExecQuery.FailSQLBatch; +end; + +procedure TBoldSystemSQLMapper.StartTransaction(const ValueSpace: IBoldValueSpace); +begin +{$IFDEF BOLD_LITE} + if Database.InTransaction then + raise EBold.Create('Transactions not supported in Bold Lite'); +{$ELSE} with Database do if IsSqlBased and (not InTransaction) then begin @@ -230,36 +304,83 @@ procedure TBoldSystemSQLMapper.StartTransaction(ValueSpace: IBoldValueSpace); end else fTransactionStartedByMe := false; +{$ENDIF} end; -procedure TBoldSystemSQLMapper.Commit(ValueSpace: IBoldValueSpace); +procedure TBoldSystemSQLMapper.Commit(const ValueSpace: IBoldValueSpace); begin +{$IFDEF BOLD_LITE} + if Database.InTransaction then + raise EBold.Create('Transactions not supported in Bold Lite'); +{$ELSE} if fTransactionStartedByMe then with Database do if IsSqlBased and InTransaction then Commit; fTransactionStartedByMe := false; +{$ENDIF} end; -procedure TBoldSystemSQLMapper.RollBack(ValueSpace: IBoldValueSpace); +procedure TBoldSystemSQLMapper.RollBack(const ValueSpace: IBoldValueSpace); begin +{$IFDEF BOLD_LITE} + if Database.InTransaction then + raise EBold.Create('Transactions not supported in Bold Lite'); +{$ELSE} if fTransactionStartedByMe then with Database do if IsSqlBased and InTransaction then RollBack; fTransactionStartedByMe := false; +{$ENDIF} +end; + +function TBoldSystemSQLMapper.EnsureColumn(const TableName, ColumnName, SQLType, SQLAllowNull: string; + const BDEType: TFieldType; Length: Integer; + const AllowNull, InVersionedTable: Boolean; + const DefaultDBValue: String): TBoldSQLColumnDescription; +var + Table: TBoldSQLTableDescription; +begin + EnsureTable(TableName, InversionedTable); + Table := PSSystemDescription.SQLTablesList.ItemsBySQLName[TableName]; + Result := Table.ColumnsList.ItemsBySQLName[ColumnName] as TBoldSQLColumnDescription; + if not assigned(Result) then + Result := Table.AddColumn(ColumnName, SQLType, SQLAllowNull, BDEType, Length, AllowNull, DefaultDbValue) + else + begin + Result.Size := Length; + Result.Mandatory := not AllowNull; + Result.SQLType := SQLType; + Result.FieldType := BDEType; + Result.SQLAllowNull := SQLAllowNull; + result.DefaultDBValue := DefaultDBValue; + end; +end; + +procedure TBoldSystemSQLMapper.EnsureIndex(const TableName, Fields: string; const PrimaryIndex, Unique, InVersionedTable: Boolean); +var + Table: TBoldSQLTableDescription; +begin + EnsureTable(TableName, InVersionedTable); + Table := PSSystemDescription.SQLTablesList.ItemsBySQLName[TableName]; + Table.EnsureIndex(Fields, PrimaryIndex, Unique, false); end; procedure TBoldSystemSQLMapper.OpenDatabase(ReadDbTypeFromDB: Boolean; ReadMappingFromDB: Boolean); begin try Database.OPEN; + if not Database.Connected then + raise EBold.CreateFmt('%s.OpenDatabase: Failed to connect to database', [classname]); + MappingInfo.ReadDataFromDB(DataBase, ReadDbTypeFromDB, ReadMappingFromDB); if assigned(OnPreInitializeBoldDbType) then OnPreInitializeBoldDbType(self); // used for DBStructureValidator InitializeBoldDbType; + InitializeTopSortedIndexForBoldDbType; EnsurePSDescription; except DataBase.Close; @@ -333,7 +454,7 @@ function TBoldObjectSQLMapper.TableAlias(Table: TBoldSQLTableDescription; useAli if useAlias then begin if Table = DistributableTable then - result := 'X_FILES' // do not localize + result := 'X_FILES' else begin i := AllTables.Indexof(Table) + 1; @@ -349,6 +470,85 @@ function TBoldObjectSQLMapper.TableAlias(Table: TBoldSQLTableDescription; useAli end; procedure TBoldObjectSQLMapper.SQLForMembers(Table: TBoldSQLTableDescription; SQL: TStrings; const MemberList: TBoldMemberPersistenceMapperList; const SQLStyle: TBoldSQLStyle; const IncludeKey: Boolean; const StoredInObjectOnly, UseAlias: Boolean); +{$IFDEF RIL} +var + SB: TStringBuilder; + c, m: integer; + Column: TBoldSQLColumnDescription; + MemberMapper: TBoldMemberSQLMapper; +begin + if IncludeKey and (SQLStyle in [ssColumns, ssParameters]) then + begin + if assigned(Table) then + SQLForKey(Table, SQL, SQLStyle, UseAlias) + else + SQLForKey(MainTable, SQL, SQLStyle, UseAlias) + end; + +{ + if ScanRF(sMembersSQL,#13#10,0)= SLen-1 then //has ctrlf at end of str + SLen := SLen-2; //=removes ctrlf +} + if MemberList.Count = 0 then + exit; + SB := TStringBuilder.Create(SQL.Text); + try + for m := 0 to MemberList.Count - 1 do + begin + MemberMapper := MemberList[m] as TBoldMemberSQLMapper; + if Assigned(MemberMapper) and + (not StoredInObjectOnly or MemberMapper.IsStoredInObject) then + begin + for c := 0 to MemberMapper.ColumnDescriptions.Count - 1 do + begin + Column := MemberMapper.ColumnDescriptions[c] as TBoldSQLColumnDescription; + if not Assigned(Table) or (Column.TableDescription = table) then + begin + if Assigned(Table) then + begin + if SB.Length>0 then + SB.Append(#13#10); {= "append"} + case SQLStyle of + ssColumns : begin + SB.Append(Column.SQLName); + end; + ssParameters: begin + SB.Append(':'); + SB.Append(Column.SQLName); + end; + ssValues : begin + SB.Append(Format('%s = :%0:s', [Column.SQLName])); + end; + else + raise EBold.Create('unimplememnted'); + end + end + else + begin + if SB.Length>0 then + SB.Append(#13#10); {= "append"} + case SQLStyle of + ssColumns: begin + // SQL.Append(Format('%s.%s', [TableAlias(Column.TableDescription, useAlias), Column.SQLName])) + SB.Append(TableAlias(Column.TableDescription, useAlias)); + SB.Append('.'); + SB.Append(Column.SQLName); + end; + else + raise EBold.Create('unimplememnted'); + end; + end; + end; + end; + end; + end; + finally + SB.Replace(#13#10#13#10, #13#10); + SQL.Text := SB.ToString; + FreeAndNil(SB); + end; +end; +{$ELSE} var c, m: integer; @@ -373,22 +573,24 @@ procedure TBoldObjectSQLMapper.SQLForMembers(Table: TBoldSQLTableDescription; SQ if assigned(Table) then case SQLStyle of ssColumns: SQL.Append(Column.SQLName); - ssParameters: SQL.Append(Format(':%s', [Column.SQLName])); // do not localize - ssValues: SQL.Append(Format('%s = :%0:s', [Column.SQLName])); // do not localize + ssParameters: SQL.Append(Format(':%s', [Column.SQLName])); + ssValues: SQL.Append(Format('%s = :%0:s', [Column.SQLName])); else - raise EBold.Create(sUnimplemented); + raise EBold.Create('unimplememnted'); end else case SQLStyle of - ssColumns: SQL.Append(Format('%s.%s', [TableAlias(Column.TableDescription, useAlias), Column.SQLName])) // do not localize + ssColumns: SQL.Append(Format('%s.%s', [TableAlias(Column.TableDescription, useAlias), Column.SQLName])) else - raise EBold.Create(sUnimplemented); + raise EBold.Create('unimplememnted'); end; end; end; end; +{$ENDIF} procedure TBoldObjectSQLMapper.RetrieveSelectStatement(s: TStrings; MemberMapperList: TBoldMemberPersistenceMapperList; FetchMode: Integer; ForceRootTable: Boolean); +{$IFDEF RIL} var T: Integer; SelectList: TStringList; @@ -400,15 +602,136 @@ procedure TBoldObjectSQLMapper.RetrieveSelectStatement(s: TStrings; MemberMapper TableList: TBoldSQLtableDescriptionList; Table: TBoldSQLtableDescription; Mapper: TBoldMemberSQLMapper; + SB: TStringBuilder; begin SelectList := TStringList.Create; FromList := TStringList.Create; WhereList := TStringList.Create; - JoinLIst := TStringList.Create; + JoinList := TStringList.Create; TableList := TBoldSQLtableDescriptionList.Create(SystemPersistenceMapper.PSSystemDescription); tableList.OwnsEntries := false; + SB := TStringBuilder.Create; + try + + if ForceRootTable then + TableList.Add(SystemPersistenceMapper.RootClassObjectPersistenceMapper.MainTable); + + for MapperIx := 0 to MemberMapperList.count - 1 do + begin + Mapper := MemberMapperList[MapperIx] as TBoldMemberSQLMapper; + for ColumnIx := 0 to Mapper.ColumnDescriptions.Count - 1 do + begin + Table := (Mapper.ColumnDescriptions[ColumnIx] as TBoldSQLColumnDescription).TableDescription; + if TableList.IndexOf(Table) = -1 then + TableList.Add(Table); + end; + end; + + SQLForMembers(nil, SelectList, MemberMapperList, ssColumns, true, false, true); + //FromList.Append(Format('%s %s', [MainTable.SQLName, TableAlias(MainTable, true)])); + SB.Clear; + SB.Append(MainTable.SQLName); + SB.Append(' '); + SB.Append(TableAlias(MainTable, true)); + FromList.Append(SB.ToString); + + if (FetchMode = fmNormal) and SystemPersistenceMapper.SQLDataBaseConfig.UseSQL92Joins then + begin + { cheapest check first } + for T := 0 to TableList.COunt-1 do + if (TableList[T]<>MainTable) and (TableList[T].ColumnsList.Count>2) then + begin + //Join := format('left join %s %s on ', [TableList[T].SQLName, TableAlias(TableList[T], true)]); + SB.Clear; + SB.Append('left join '); + SB.Append(TableList[T].SQLName); + SB.Append(' '); + SB.Append(TableAlias(TableList[T], true)); + SB.Append(' on '); + + JoinList.Clear; + JoinSQLTableByKey(JoinList, MainTable, TableList[T]); + + //Join := Join + BoldSeparateStringList(JoinList, ' and ', '(', ')'); + SB.Append(BoldSeparateStringList(JoinList, ' and ', '(', ')')); + Join := SB.ToString; + FromList.Append(Join); + end; + end + else + begin + for T := 0 to TableList.Count - 1 do + if (TableList[T] <> MainTable) and (TableList[T].ColumnsList.Count > 2) then + begin + //FromList.Append(Format('%s %s',[TableList[T].SQLName, TableAlias(TableList[t], true)])); + SB.Clear; + SB.Append(TableList[T].SQLName); + SB.Append(' '); + SB.Append(TableAlias(TableList[t], true)); + FromList.Append(SB.ToString); + end; + + for T := 0 to TableList.Count-1 do + begin + {ril} // cheapest check first + if (TableList[T]<>MainTable) and (TableList[T].ColumnsList.Count > 2) then + JoinSQLTableByKey(WhereList, MainTable, TableList[T]); + end; + +{ if FetchMode = fmDistributable then + begin + SQLForDistributed(SelectList, ssColumns); + FromList.Append(Format('%s %s', [DistributableTable.SQLName, + TableAlias(DistributableTable, true)])); + JoinSQLTableByKey(WhereList, MainTable, DistributableTable); + end;} + end; + + SQLForID(Maintable, WhereList, True); + + {ril} {'SELECT %s ':} + BoldAppendToStrings(S, 'SELECT '+BoldSeparateStringList(SelectList, ', ', '', '')+' ', true); + if SystemPersistenceMapper.SQLDataBaseConfig.UseSQL92Joins and (FetchMode = fmNormal) then + {ril} {'FROM %s ':} + BoldAppendToStrings(S, 'FROM '+BoldSeparateStringList(FromList, ' ', '', '')+' ', true) + else + {ril} {'FROM %s ':} + BoldAppendToStrings(S, 'FROM '+BoldSeparateStringList(FromList, ', ', '', '')+' ', true); + + {ril} {'WHERE %s ':} + BoldAppendToStrings(S, 'WHERE '+BoldSeparateStringList(WhereList, ' AND ', '', '')+' ', true); + finally + SelectList.Free; + FromList.Free; + WhereList.Free; + JoinList.Free; + TableList.Free; + FreeAndNil(SB); + end; +end; +{$ELSE} +var + T: Integer; + SelectList: TStringList; + FromList: TStringList; + WhereList: TStringList; + JoinList: TStringList; + Join: String; + MapperIx, ColumnIx: integer; + TableList: TBoldSQLtableDescriptionList; + Table: TBoldSQLtableDescription; + Mapper: TBoldMemberSQLMapper; + +begin + SelectList := TStringList.Create; + FromList := TStringList.Create; + WhereList := TStringList.Create; + JoinLIst := TStringList.Create; + TableList := TBoldSQLtableDescriptionList.Create(SystemPersistenceMapper.PSSystemDescription); + tableList.OwnsEntries := false; try + if ForceRootTable then TableList.Add(SystemPersistenceMapper.RootClassObjectPersistenceMapper.MainTable); @@ -425,17 +748,16 @@ procedure TBoldObjectSQLMapper.RetrieveSelectStatement(s: TStrings; MemberMapper SQLForMembers(nil, SelectList, MemberMapperList, ssColumns, true, false, true); - FromList.Append(Format('%s %s', [MainTable.SQLName, TableAlias(MainTable, true)])); // do not localize + FromList.Append(Format('%s %s', [MainTable.SQLName, TableAlias(MainTable, true)])); if SystemPersistenceMapper.SQLDataBaseConfig.UseSQL92Joins and (FetchMode = fmNormal) then begin - // left join rateable x on Song.Bold_ID=rateable.Bold_id for T := 0 to TableList.COunt - 1 do if (TableList[T].ColumnsList.Count > 2) and (TableList[T] <> MainTable) then begin - Join := format('left join %s %s on ', [TableList[T].SQLName, TableAlias(TableList[T], true)]); // do not localize + Join := format('left join %s %s on ', [TableList[T].SQLName, TableAlias(TableList[T], true)]); JoinList.Clear; JoinSQLTableByKey(JoinList, MainTable, TableList[T]); - Join := Join + BoldSeparateStringList(JoinList, ' and ', '(', ')'); // do not localize + Join := Join + BoldSeparateStringList(JoinList, ' and ', '(', ')'); FromList.Add(Join); end; end @@ -443,7 +765,7 @@ procedure TBoldObjectSQLMapper.RetrieveSelectStatement(s: TStrings; MemberMapper begin for T := 0 to TableList.Count - 1 do if (TableList[T].ColumnsList.Count > 2) and (TableList[T] <> MainTable) then - FromList.Append(Format('%s %s',[TableList[T].SQLName, TableAlias(TableList[t], true)])); // do not localize + FromList.Append(Format('%s %s',[TableList[T].SQLName, TableAlias(TableList[t], true)])); for T := 0 to TableList.Count - 1 do begin @@ -462,14 +784,14 @@ procedure TBoldObjectSQLMapper.RetrieveSelectStatement(s: TStrings; MemberMapper SQLForID(Maintable, WhereList, True); - BoldAppendToStrings(S, Format('SELECT %s ', [BoldSeparateStringList(SelectList, ', ', '', '')]), true); // do not localize + BoldAppendToStrings(S, Format('SELECT %s ', [BoldSeparateStringList(SelectList, ', ', '', '')]), true); if SystemPersistenceMapper.SQLDataBaseConfig.UseSQL92Joins and (FetchMode = fmNormal) then - BoldAppendToStrings(S, Format('FROM %s ', [BoldSeparateStringList(FromList, ' ', '', '')]), true) // do not localize + BoldAppendToStrings(S, Format('FROM %s ', [BoldSeparateStringList(FromList, ' ', '', '')]), true) else - BoldAppendToStrings(S, Format('FROM %s ', [BoldSeparateStringList(FromList, ', ', '', '')]), true); // do not localize + BoldAppendToStrings(S, Format('FROM %s ', [BoldSeparateStringList(FromList, ', ', '', '')]), true); - BoldAppendToStrings(S, Format('WHERE %s ', [BoldSeparateStringList(WhereList, ' AND ', '', '')]), true); // do not localize + BoldAppendToStrings(S, Format('WHERE %s ', [BoldSeparateStringList(WhereList, ' AND ', '', '')]), true); finally SelectList.Free; FromList.Free; @@ -478,23 +800,110 @@ procedure TBoldObjectSQLMapper.RetrieveSelectStatement(s: TStrings; MemberMapper TableList.Free; end; end; +{$ENDIF} + -procedure TBoldObjectSQLMapper.ValuesFromFieldsByMemberList(ObjectID: TBoldObjectId; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; DataSet: IBoldDataSet; memberList: TBoldMemberPersistenceMapperList); +procedure TBoldObjectSQLMapper.ValuesFromFieldsByMemberList(ObjectID: TBoldObjectId; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; const DataSet: IBoldDataSet; memberList: TBoldMemberPersistenceMapperList); var - i: integer; + i,FieldIndex: integer; + aField : IBoldField; ObjectContents: IBoldObjectContents; + MemberMapper: TBoldMemberSQLMapper; + ColumnIndex: Integer; begin ObjectContents := ValueSpace.EnsuredObjectContentsByObjectId[ObjectID]; + FieldIndex := 2; // skip id and type for i:= 0 to memberlist.count - 1 do - TBoldMemberSQLMapper(Memberlist[i]).ValueFromQuery(ObjectId, ObjectContents, ValueSpace, TranslationList, DataSet); + begin + MemberMapper := TBoldMemberSQLMapper(Memberlist[i]); + if MemberMapper.ShouldFetch(ObjectContents) then + for ColumnIndex := 0 to MemberMapper.ColumnCount - 1 do + begin + aField := nil; + if FieldIndex < DataSet.FieldCount then + begin + aField := DataSet.Fields[FieldIndex]; + if not SameText(aField.FieldName, MemberMapper.ColumnDescriptions[ColumnIndex].SQLName) then + aField := nil; + end; + if not Assigned(aField) then + begin + aField := DataSet.FieldByUpperCaseName(MemberMapper.ColumnDescriptions[ColumnIndex].SQLNameUpper); + FieldIndex := aField.Field.Index; + end; + MemberMapper.ValueFromField(ObjectId, ObjectContents, ValueSpace, TranslationList, aField, ColumnIndex); + inc(FieldIndex); + end; + end; end; -procedure TBoldObjectSQLMapper.ValuesToParamsByMemberList(ObjectID: TBoldObjectId; ValueSpace: IBoldValueSpace; Query: IBoldExecQuery; memberList: TBoldMemberPersistenceMapperList; TranslationList: TBoldIdTranslationList; DBStorageMode: TBoldDBStorageMode); +procedure TBoldObjectSQLMapper.ValuesToParamsByMemberList(ObjectId: TBoldObjectId; const ValueSpace: IBoldValueSpace; const Query: IBoldExecQuery; memberList: TBoldMemberPersistenceMapperList; TranslationList: TBoldIdTranslationList; DBStorageMode: TBoldDBStorageMode); var i: integer; + ObjectContents: IBoldObjectContents; begin + ObjectContents := ValueSpace.EnsuredObjectContentsByObjectId[ObjectID]; for i := 0 to memberlist.count - 1 do - TBoldMemberSQLMapper(Memberlist[i]).ValueToQuery(ValueSpace.ObjectContentsByObjectId[ObjectID], ValueSpace, Query, translationList, DBStorageMode); + TBoldMemberSQLMapper(Memberlist[i]).ValueToQuery(ObjectContents, ValueSpace, Query, translationList, DBStorageMode); +end; + +procedure TBoldObjectSQLMapper.ValuesToQueryByMemberList( + ObjectId: TBoldObjectId; const ValueSpace: IBoldValueSpace; const Query: IBoldExecQuery; + SQL: TStrings; memberList: TBoldMemberPersistenceMapperList; + TranslationList: TBoldIdTranslationList; DBStorageMode: TBoldDBStorageMode); +var + i: integer; + ColumnIndex: Integer; + MemberMapper: TBoldMemberSQLMapper; + ObjectContents: IBoldObjectContents; + Members: TStringList; + Value: Variant; + Param: IBoldParameter; + ParamName: string; +begin + if SystemPersistenceMapper.SQLDataBaseConfig.UseParamsForInteger then + ValuesToParamsByMemberList(ObjectID,ValueSpace,Query,MemberList,TranslationList,DbStorageMode) + else + begin + ObjectContents := ValueSpace.EnsuredObjectContentsByObjectId[ObjectID]; + Members := TStringList.Create; + for i := 0 to MemberList.count - 1 do + begin + MemberMapper := Memberlist[i] as TBoldMemberSQLMapper; + if (DBStorageMode = dsmCreate) or MemberMapper.IsDirty(ObjectContents) then + begin + for ColumnIndex := 0 to MemberMapper.ColumnCount - 1 do + begin + Value := MemberMapper.ValueAsVariant(ObjectContents, ColumnIndex, TranslationList); + if not SystemPersistenceMapper.SQLDataBaseConfig.UseParamsForEmptyString and SameText(MemberMapper.ContentName, BoldContentName_String) and (Value = '') then + Members.Add(QuotedStr('')) // handle blank strings + else // handle nulls + if VarIsNull(Value) then + Members.Add(SystemPersistenceMapper.SQLDataBaseConfig.SQLforNull) + else // handle integers + if (MemberMapper.ColumnTypeAsSQL[ColumnIndex] = SystemPersistenceMapper.SQLDataBaseConfig.ColumnTypeForInteger) then + Members.Add(Value) + else + begin + ParamName := 'p'+IntToStr(Query.ParamCount); + Param := Query.CreateParam(ftUnknown, ParamName); + MemberMapper.ValueToParam(ObjectContents, Param, ColumnIndex, translationList); + Members.Add(':'+ParamName); + end; + if DBStorageMode = dsmUpdate then + Members[Members.Count-1] := Format('%s=%s', [MemberMapper.ColumnDescriptions[ColumnIndex].SQLName, Members[Members.Count-1]]); + end; + end; + end; + if (Members.Count > 0) then + begin + if (DBStorageMode = dsmCreate) then + SQL.Add(','+Members.CommaText) + else + SQL.Add(Members.CommaText); + end; + Members.free; + end; end; {---TBoldMemberSQLMapper---} @@ -506,16 +915,16 @@ constructor TBoldMemberSQLMapper.CreateFromMold(Moldmember: TMoldMember; MoldCla fInitialColumnRootName := BoldExpandName(MoldMember.ColumnName, MoldMember.name, xtSQL, SystemPersistenceMapper.SQLDataBaseConfig.MaxDBIdentifierLength, MoldClass.Model.NationalCharConversion); - if MoldMember is TMoldAttribute then - fDefaultDbValue := (MoldMember as TMoldAttribute).DefaultDBValue; - - if fDefaultDbValue = '' then - fDefaultDbValue := DefaultDefaultDbValue; - if MoldMember is TMoldAttribute then fAllowNull := (MoldMember as TMoldAttribute).AllowNull else fAllowNull := true; + + if MoldMember is TMoldAttribute then + fDefaultDbValue := (MoldMember as TMoldAttribute).DefaultDBValue; + + if fDefaultDbValue = '' then + fDefaultDbValue := DefaultDefaultDbValue; end; destructor TBoldMemberSQLMapper.destroy; @@ -527,14 +936,47 @@ destructor TBoldMemberSQLMapper.destroy; function TBoldMemberSQLMapper.GetColumnSize(ColumnIndex: Integer): Integer; begin - raise EBold.CreateFmt(sIllegalColumnIndex, [ClassName, 'GetColumnSize', ColumnIndex]); // do not localize + raise EBold.CreateFmt('%s.GetColumnSize: illegal index', [ClassName]); end; function TBoldMemberSQLMapper.GetInitialColumnName(ColumnIndex: Integer): string; begin Result := InitialColumnRootName; if ColumnIndex > 0 then - Result := Format('%s_%d', [Result, ColumnIndex]); // do not localize + Result := Format('%s_%d', [Result, ColumnIndex]); +end; + + +procedure TBoldSystemSQLMapper.AddCustomIndexes; +var + I: Integer; + Table: TBoldSQLTableDescription; + CustomIndex: TBoldIndexDefintion; + AnIndex: TBoldSQLIndexDescription; +begin + for I := 0 to fCustomIndexes.Count - 1 do + begin + CustomIndex := fCustomIndexes.IndexDefinition[I]; + Table := PSSystemDescription.SQLTablesList.ItemsBySQLName[CustomIndex.TableName]; + if CustomIndex.Remove then + begin + AnIndex := nil; + if Assigned(Table) then + AnIndex := Table.IndexList.ItemsByIndexFields[CustomIndex.Columns]; + if Assigned(AnIndex) then + begin + Table.IndexList.Remove(AnIndex); + end + else + raise EBold.Create('Can''t Remove nonexistent index: ' + CustomIndex.TableName + ': [' + CustomIndex.Columns+ ']'); + end + else + begin + if (Table = nil) then + raise EBold.Create('Can''t create index on nonexistant table ' + CustomIndex.TableName); + Table.EnsureIndex(CustomIndex.Columns, False, CustomIndex.Unique, false); + end; + end; end; function TBoldSystemSQLMapper.BoldDbTypeForTopSortedIndex( @@ -543,22 +985,17 @@ function TBoldSystemSQLMapper.BoldDbTypeForTopSortedIndex( result := (ObjectPersistenceMappers[TopSortedIndex] as TBoldObjectSQLMapper).BoldDbType; end; -function TBoldSystemSQLMapper.TopSortedIndexForBoldDbType( - BoldDbType: TBoldDbType): Integer; -var - i: integer; +function TBoldSystemSQLMapper.TopSortedIndexForBoldDbType(BoldDbType: TBoldDbType): Integer; begin - result := -1; - for i := 0 to ObjectPersistenceMappers.Count - 1 do - if (ObjectPersistenceMappers[i] is TBoldObjectSQLMapper) and // tests for nil - ((ObjectPersistenceMappers[i] as TBoldObjectSQLMapper).BoldDbType = BoldDbType) then - begin - result := i; - break; - end; + if fMaxDbType = -1 then + raise Exception.Create('fTopSortedIndexForBoldDbType not initialized'); + if BoldDbType > fMaxDbType then + Result := -1 + else + Result := fTopSortedIndexForBoldDbType[BoldDbType]; end; -procedure TBoldMemberSQLMapper.SetParamToNullWithDataType(aParam: IBoldParameter; FieldType: TFieldType); +procedure TBoldMemberSQLMapper.SetParamToNullWithDataType(const aParam: IBoldParameter; FieldType: TFieldType); begin with aParam do begin @@ -568,17 +1005,23 @@ procedure TBoldMemberSQLMapper.SetParamToNullWithDataType(aParam: IBoldParameter end; end; -procedure TBoldMemberSQLMapper.ValueToParam(ObjectContent: IBoldObjectContents; Param: IBoldParameter; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList); +procedure TBoldMemberSQLMapper.ValueToParam(const ObjectContent: IBoldObjectContents; const Param: IBoldParameter; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList); +begin + raise EBold.CreateFmt('%s.ValueToParam: illegal call', [classname]); +end; + +function TBoldMemberSQLMapper.ValueAsVariant(const ObjectContent: IBoldObjectContents; + ColumnIndex: Integer; TranslationList: TBoldIdTranslationList): variant; begin - raise EBold.CreateFmt(sIllegalCall, [classname, 'ValueToParam']); // do not localize + raise EBold.CreateFmt('%s.ValueAsVariant: Illegal call', [classname]); end; -procedure TBoldMemberSQLMapper.ValueFromField(OwningObjectId: TBoldObjectId; ObjectContent: IBoldObjectContents; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; Field: IBoldField; ColumnIndex: Integer); +procedure TBoldMemberSQLMapper.ValueFromField(OwningObjectId: TBoldObjectId; const ObjectContent: IBoldObjectContents; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; const Field: IBoldField; ColumnIndex: Integer); begin - raise EBold.CreateFmt(sIllegalCall, [classname, 'ValueFromField']); // do not localize + raise EBold.CreateFmt('%s.ValueFromField: Illegal call', [classname]); end; -procedure TBoldMemberSQLMapper.ValueToQuery(ObjectContent: IBoldObjectContents; ValueSpace: IBoldValueSpace; Query: IBoldExecQuery; TranslationList: TBoldIdTranslationList; DBStorageMode: TBoldDBStorageMode); +procedure TBoldMemberSQLMapper.ValueToQuery(const ObjectContent: IBoldObjectContents; const ValueSpace: IBoldValueSpace; const Query: IBoldExecQuery; TranslationList: TBoldIdTranslationList; DBStorageMode: TBoldDBStorageMode); var aParam : IBoldParameter; ColumnIndex: Integer; @@ -587,44 +1030,52 @@ procedure TBoldMemberSQLMapper.ValueToQuery(ObjectContent: IBoldObjectContents; begin for ColumnIndex := 0 to ColumnCount - 1 do begin - aParam := Query.ParamByName(ColumnDescriptions[ColumnIndex].SQLName); + if Query.ParamCheck then + aParam := Query.EnsureParamByName(ColumnDescriptions[ColumnIndex].SQLName) + else + aParam := Query.CreateParam(ftUnknown, 'p'+IntToStr(Query.ParamCount)); if Assigned(aParam) then ValueToParam(ObjectContent, aParam, ColumnIndex, translationList) else - raise EBoldInternal.CreateFmt(sSomeColumnsNotInTable, [classname, 'ValueToQuery', ColumnIndex, ColumnDescriptions[ColumnIndex].SQLName]); // do not localize + raise EBoldInternal.CreateFmt('%s.ValueToQuery: Some columns not found in table (%d:%s)', [classname, ColumnIndex, ColumnDescriptions[ColumnIndex].SQLName]); end; end; end; -procedure TBoldMemberSQLMapper.ValueFromQuery(OwningObjectId: TBoldObjectId; ObjectContent: IBoldObjectContents; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; DataSet: IBoldDataSet); +procedure TBoldMemberSQLMapper.ValueFromQuery(OwningObjectId: TBoldObjectId; const ObjectContent: IBoldObjectContents; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; const DataSet: IBoldDataSet); var aField : IBoldField; ColumnIndex: Integer; + ErrorMsg : String; begin if ShouldFetch(ObjectContent) then begin for ColumnIndex := 0 to ColumnCount - 1 do begin - aField := DataSet.FieldByName(ColumnDescriptions[ColumnIndex].SQLName); + aField := DataSet.FieldByUpperCaseName(ColumnDescriptions[ColumnIndex].SQLNameUpper); + if not Assigned(aField) and (Length(ColumnDescriptions[ColumnIndex].SQLName) = 31) then // Could be DBX problem + aField := DataSet.FieldByUpperCaseName(Copy(ColumnDescriptions[ColumnIndex].SQLNameUpper,1,30)); if Assigned(aField) then ValueFromField(OwningObjectId, ObjectContent, ValueSpace, TranslationList, aField, ColumnIndex) else - raise EBoldInternal.CreateFmt(sSomeColumnsNotInTable, [classname, 'ValueFromQuery', ColumnIndex, ColumnDescriptions[ColumnIndex].SQLName]); // do not localize + raise EBoldInternal.CreateFmt('%s.ValueFromQuery: Some columns not found in table (%d:%s).' + ErrorMsg, [classname, ColumnIndex, ColumnDescriptions[ColumnIndex].SQLName]); end; end; end; -procedure TBoldMemberSQLMapper.InitializeSystem(theDatabase: IBoldDataBase); +procedure TBoldMemberSQLMapper.InitializeSystem(const theDatabase: IBoldDataBase); begin end; function TBoldMemberSQLMapper.GetColumnBDEFieldType(ColumnIndex: Integer): TFieldType; begin - raise EBold.CreateFmt(sIllegalColumnIndex, [ClassName, 'GetColumnBDEFieldType', ColumnIndex]); // do not localize + raise EBold.CreateFmt('%s.GetColumnBDEFieldType: illegal index', [ClassName]); end; procedure TBoldSystemSQLMapper.CloseDataBase; begin + if assigned(fExecQuery) then + Database.ReleaseExecQuery(fExecQuery); Database.Close; end; @@ -684,10 +1135,10 @@ procedure TBoldObjectSQLMapper.RetrieveTimeStampCondition(SQL: TStrings; TimeSta end; if TimeStamp = BOLDMAXTIMESTAMP then - SQL.Append(Format('%s (%s.%s = %d)', [WhereToken, // do not localize + SQL.Append(Format('%s (%s.%s = %d)', [WhereToken, EndTimeTableAlias, TIMESTAMPSTOPCOLUMNNAME, TimeStamp])) else - SQL.Append(Format('%s ((%s.%s <= %d) and (%s.%s >= %d))', [WhereToken, // do not localize + SQL.Append(Format('%s ((%s.%s <= %d) and (%s.%s >= %d))', [WhereToken, StartTimeTableAlias, TIMESTAMPSTARTCOLUMNNAME, TimeStamp, EndTimeTableAlias, TIMESTAMPSTOPCOLUMNNAME, TimeStamp])); end; @@ -707,7 +1158,7 @@ function TBoldSystemSQLMapper.GetMappingInfo: TBoldSQLMappingInfo; destructor TBoldSystemSQLMapper.Destroy; begin FreeAndNil(fMappingInfo); - FreeAndNil(fSQLDataBaseConfig); + FreeAndNil(fCustomIndexes); inherited; end; @@ -751,27 +1202,27 @@ function TBoldMemberSQLMapper.DefaultDefaultDbValue: String; result := ''; end; -procedure TBoldSystemSQLMapper.GenerateDatabaseScript(Script: TStrings; Separator: string); +procedure TBoldSystemSQLMapper.GenerateDatabaseScript(Script: TStrings); var i: integer; begin - PSSystemDescription.GenerateDatabaseScript(Script, Separator); + PSSystemDescription.GenerateDatabaseScript(Script); for i := 0 to ObjectPersistenceMappers.Count - 1 do if assigned(ObjectPersistenceMappers[i]) then - (ObjectPersistenceMappers[i] as TBoldObjectSQLMapper).GenerateDatabaseScript(script, separator); - MappingInfo.ScriptForWriteData(Script, Separator, false); + (ObjectPersistenceMappers[i] as TBoldObjectSQLMapper).GenerateDatabaseScript(script); + MappingInfo.ScriptForWriteData(Database, Script, False, SQLDatabaseConfig.SqlScriptSeparator, SQLDatabaseConfig.SqlScriptTerminator); end; -procedure TBoldObjectSQLMapper.GenerateDatabaseScript(Script: TStrings; Separator: string); +procedure TBoldObjectSQLMapper.GenerateDatabaseScript(Script: TStrings); var i: integer; begin for i := 0 to MemberPersistenceMappers.Count - 1 do if assigned(MemberPersistenceMappers[i]) then - (MemberPersistenceMappers[i] as TBoldMemberSQLMapper).GenerateDatabaseScript(script, separator); + (MemberPersistenceMappers[i] as TBoldMemberSQLMapper).GenerateDatabaseScript(script); end; -procedure TBoldMemberSQLMapper.GenerateDatabaseScript(Script: TStrings; Separator: string); +procedure TBoldMemberSQLMapper.GenerateDatabaseScript(Script: TStrings); begin // intentionally left blank end; @@ -796,18 +1247,8 @@ function TBoldMemberSQLMapper.GetColumnDescriptions: TBoldSQLDescriptionList; result := fColumnDescriptions; end; -function TBoldSystemSQLMapper.GetExecQuery: IBoldExecQuery; -begin - result := Database.GetExecQuery; -end; - -procedure TBoldSystemSQLMapper.ReleaseExecQuery(var aQuery: IBoldExecQuery); -begin - Database.ReleaseExecQuery(aQuery); -end; - procedure TBoldSystemSQLMapper.PMFetch(ObjectIDList: TBoldObjectIdList; - ValueSpace: IBoldValueSpace; MemberIdList: TBoldMemberIdList; + const ValueSpace: IBoldValueSpace; MemberIdList: TBoldMemberIdList; FetchMode: Integer; TranslationList: TBoldIdTranslationList); var WasInTransaction: Boolean; @@ -821,4 +1262,34 @@ procedure TBoldSystemSQLMapper.PMFetch(ObjectIDList: TBoldObjectIdList; end; end; +procedure TBoldSystemSQLMapper.InitializeTopSortedIndexForBoldDbType; +var + i: integer; + DbType: integer; +begin + fMaxDbType := -1; + for i := 0 to ObjectPersistenceMappers.Count - 1 do + if ObjectPersistenceMappers[i] is TBoldObjectSQLMapper then + begin + DbType := TBoldObjectSQLMapper(ObjectPersistenceMappers[i]).BoldDbType; + if DbType > fMaxDbType then + fMaxDbType := DbType; + end; + if fMaxDbType > 50000 then + raise Exception.Create(Format('DbType: %d, too big', [fMaxDbType])); + SetLength(fTopSortedIndexForBoldDbType, fMaxDbType+1); + for i := 0 to fMaxDbType do + fTopSortedIndexForBoldDbType[i] := -1; + for i := 0 to ObjectPersistenceMappers.Count - 1 do + if (ObjectPersistenceMappers[i] is TBoldObjectSQLMapper) then + begin + DbType := TBoldObjectSQLMapper(ObjectPersistenceMappers[i]).BoldDbType; + if fTopSortedIndexForBoldDbType[DbType] <> -1 then + raise Exception.Create(Format('Duplicate DbType: %d', [i])); + fTopSortedIndexForBoldDbType[DbType] := i; + end; +end; + +initialization + end. diff --git a/Source/PMapper/SQL/BoldPSDescriptionsSQL.pas b/Source/PMapper/SQL/BoldPSDescriptionsSQL.pas index e977acb..32bd600 100644 --- a/Source/PMapper/SQL/BoldPSDescriptionsSQL.pas +++ b/Source/PMapper/SQL/BoldPSDescriptionsSQL.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldPSDescriptionsSQL; interface @@ -19,6 +22,11 @@ interface TYPECOLUMN_TYPE = ftSmallint; type + //Copied from Data.DB + TIndexOptionExt = (ixPrimary, ixUnique, ixDescending, ixCaseInsensitive, + ixExpression, ixNonMaintained, ixNonClustered {ext}); + TIndexOptionsExt = set of TIndexOptionExt; + TBoldSQLSystemDescription = class; TBoldSQLDescriptionElement = class; TBoldSQLTableDescription = class; @@ -32,6 +40,7 @@ TBoldSQLIndexDescriptionList = class; {---TBoldSQLSystemDescription---} TBoldSQLSystemDescription = class(TBoldPSSystemDescription) private + Query: IBoldExecQuery; fTables: TBoldSQLTableDescriptionList; fSQLDatabaseConfig: TBoldSQLDatabaseConfig; fNationalCharConversion: TBoldNationalCharConversion; @@ -48,7 +57,7 @@ TBoldSQLSystemDescription = class(TBoldPSSystemDescription) destructor Destroy; override; procedure CleanPersistentStorage(PSParams: TBoldPSSQLParams); procedure CreatePersistentStorage(PSParams: TBoldPSParams); override; - procedure GenerateDatabaseScript(Script: TStrings; Separator: string); virtual; + procedure GenerateDatabaseScript(Script: TStrings); virtual; property SQLDatabaseConfig: TBoldSQLDatabaseConfig read fSQLDatabaseConfig; property SQLTablesList: TBoldSQLTableDescriptionList read fTables; property NationalCharConversion: TBoldNationalCharConversion read fNationalCharConversion; @@ -58,12 +67,15 @@ TBoldSQLSystemDescription = class(TBoldPSSystemDescription) TBoldSQLDescriptionElement = class(TBoldPSDescriptionElement) private fSQLName: string; + fSQLNameUpper: string; protected - procedure SetSQLName(v: string); virtual; - function MappedSQLName(value: String): String; + function GetDebugInfo: string; override; + procedure SetSQLName(const v: string); virtual; function OwningSystem: TBoldSQLSystemdescription; public property SQLName: string read fSQLName write SetSQLName; + property SQLNameUpper: string read fSQLNameUpper; + function MappedSQLName(const value: String): String; end; {---TBoldSQLTableDescription---} @@ -76,20 +88,20 @@ TBoldSQLTableDescription = class(TBoldSQLDescriptionElement) fContainsStopTimeStamp: Boolean; function GetSystemDescription: TBoldSQLSystemDescription; protected - procedure SetSQLName(v: string); override; + procedure SetSQLName(const v: string); override; function TableExists(PSParams: TBoldPSSQLParams): boolean; procedure CreateTableBDE(PSParams: TBoldPSSQLParams); procedure CreateTableSQL(PSParams: TBoldPSSQLParams); public constructor Create(aOwner: TBoldPSDescriptionElement; Versioned: Boolean); destructor Destroy; override; - function AddColumn(const ColName: string; SQLColType, AllowNullAsSQL: String; ColType: TFieldType; ColSize: Integer; AllowNull: Boolean; DefaultDBValue: string): TBoldSQLColumnDescription; - procedure EnsureIndex(const Fields: string; Primary, Unique: boolean); + function AddColumn(const ColName: string; SQLColType, AllowNullAsSQL: String; ColType: TFieldType; ColSize: Integer; AllowNull: Boolean; const DefaultDBValue: string): TBoldSQLColumnDescription; + procedure EnsureIndex(const Fields: string; Primary, Unique, NonClustered: boolean); procedure CreateTable(PSParams: TBoldPSSQLParams); procedure DeleteTable(PSParams: TBoldPSSQLParams); procedure RetrieveSelectIdAndTypeStatement(S: TStrings); - procedure GenerateDatabaseScript(Script: TStrings; Separator: string); - function SQLForCreateTable(DataBase: IBoldDatabase): string; + procedure GenerateDatabaseScript(Script: TStrings); + function SQLForCreateTable(const DataBase: IBoldDatabase): string; function SQLForDropTable: string; property ColumnsList: TBoldSQLDescriptionList read fColumns; property IndexList: TBoldSQLIndexDescriptionList read fIndexes; @@ -108,13 +120,14 @@ TBoldSQLColumnDescription = class(TBoldSQLDescriptionElement) fSQLAllowNull: string; fFieldType: TFieldType; fDefaultDBValue: String; - function GetTableDescription: TBoldSQLTableDescription; + function GetTableDescription: TBoldSQLTableDescription; {$IFDEF BOLD_INLINE} inline; {$ENDIF} protected - procedure SetSQLName(v: string); override; + function GetDebugInfo: string; override; + procedure SetSQLName(const v: string); override; public procedure CreateBDEColumn(FieldDefs: TFieldDefs); constructor Create(aOwner: TBoldPSDescriptionElement); - function GetSQLForColumn(DataBase: IBoldDatabase): string; + function GetSQLForColumn(const DataBase: IBoldDatabase): string; property TableDescription: TBoldSQLTableDescription read GetTableDescription; property Size: integer read fSize write fSize; property Mandatory: Boolean read fMandatory write fMandatory; @@ -127,56 +140,58 @@ TBoldSQLColumnDescription = class(TBoldSQLDescriptionElement) {---TBoldSQLIndexDescription---} TBoldSQLIndexDescription = class(TBoldPSDescriptionElement) private - fIndexOptions: TIndexOptions; + fIndexOptions: TIndexOptionsExt; fIndexedFields: string; function GetTableDescription: TBoldSQLTableDescription; function GetIndexedFieldsForSQL: String; - protected - property TableDescription: TBoldSQLTableDescription read GetTableDescription; - function GeneratedName: String; public + property TableDescription: TBoldSQLTableDescription read GetTableDescription; constructor Create(aOwner: TBoldPSDescriptionElement; const Fields: String); + class function NormalizeFields(const IndexedFields: string): string; function SQLForPrimaryKey: string; function SQLForSecondaryKey: string; + function GeneratedName: String; property IndexedFields: string read fIndexedFields write fIndexedFields; property IndexedFieldsForSQL: String read GetIndexedFieldsForSQL; procedure CreateBDEIndex(PSParams: TBoldPSSQLParams; IndexDefs: TIndexDefs); - property IndexOptions: TIndexOptions read fIndexOptions write fIndexOptions; + property IndexOptions: TIndexOptionsExt read fIndexOptions write fIndexOptions; end; {---TBoldSQLDescriptionList---} TBoldSQLDescriptionList = class(TBoldIndexableList) private fSystemDescription: TBoldSQLSystemDescription; - function GetItem(index: Integer): TBoldSQLDescriptionElement; - function GetItemBySQLName(SQLName: string): TBoldSQLDescriptionElement; + function GetItem(index: Integer): TBoldSQLDescriptionElement; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetItemBySQLName(const SQLName: string): TBoldSQLDescriptionElement; public constructor Create(SystemDescription: TBoldSQLSystemDescription); - procedure ToStrings(S: TStrings); //Does not feel necessary.. + procedure ToStrings(S: TStrings); property Items[index: Integer]: TBoldSQLDescriptionElement read GetItem; default; - property ItemsBySQLName[SQLName: string]: TBoldSQLDescriptionElement read GetItemBySQLName; + property ItemsBySQLName[const SQLName: string]: TBoldSQLDescriptionElement read GetItemBySQLName; end; {---TBoldSQLTableDescriptionList---} TBoldSQLTableDescriptionList = class(TBoldSQLDescriptionList) private - function GetItem(index: Integer): TBoldSQLTableDescription; - function GetItemBySQLName(SQLName: string): TBoldSQLTableDescription; + function GetItem(index: Integer): TBoldSQLTableDescription; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetItemBySQLName(const SQLName: string): TBoldSQLTableDescription; public property Items[index: Integer]: TBoldSQLTableDescription read GetItem; default; - property ItemsBySQLName[SQLName: string]: TBoldSQLtableDescription read GetItemBySQLName; + property ItemsBySQLName[const SQLName: string]: TBoldSQLtableDescription read GetItemBySQLName; end; TBoldSQLIndexDescriptionList = class(TBoldIndexableList) private - function GetItem(index: integer): TBoldSQLIndexDescription; - function GetItemsByIndexFields(const IndexFields: string): TBoldSQLIndexDescription; + class var IX_SQLIndexFields: integer; + function GetItem(index: integer): TBoldSQLIndexDescription; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetItemsByIndexFields(const IndexFields: string): TBoldSQLIndexDescription; {$IFDEF BOLD_INLINE} inline; {$ENDIF} public constructor Create; property items[index: integer]: TBoldSQLIndexDescription read GetItem; default; property ItemsByIndexFields[const IndexFields: string]: TBoldSQLIndexDescription read GetItemsByIndexFields; end; + var BoldCleanDatabaseForced: Boolean = false; @@ -188,15 +203,19 @@ implementation BoldLogHandler, BoldQueryUserDlg, SysUtils, - BoldPMConsts, TypInfo, + {$IFDEF MSWINDOWS} Controls, Dialogs, + {$ENDIF} + {$IFDEF LINUX} + QControls, + QDialogs, + {$ENDIF} BoldHashIndexes; var IX_SQLDescriptionSQLName: integer = -1; - IX_SQLIndexFields: integer = -1; type {---TSQLDescriptorSQLNameIndex---} @@ -216,60 +235,80 @@ function TSQLDescriptorSQLNameIndex.ItemAsKeyString(Item: TObject): string; Result := TBoldSQLDescriptionElement(Item).SQLName; end; +function TBoldSQLIndexDescriptionList.GetItem(index: integer): TBoldSQLIndexDescription; +begin + result := (inherited items[index]) as TBoldSQLIndexDescription; +end; + +function TBoldSQLIndexDescriptionList.GetItemsByIndexFields(const IndexFields: string): TBoldSQLIndexDescription; +begin + Result := TBoldSQLIndexDescription(TBoldStringHashIndex(Indexes[IX_SQLIndexFields]).FindByString(TBoldSQLIndexDescription.NormalizeFields(IndexFields))); +end; + {---TBoldSQLSystemDescription---} constructor TBoldSQLSystemDescription.Create(aOwner: TBoldPSDescriptionElement; SQLDatabaseConfig: TBoldSQLDataBaseConfig; NationalCharConversion: TBoldNationalCharConversion); begin - inherited create(aOwner); + inherited Create(aOwner); fTables := TBoldSQLTableDescriptionList.Create(self); - fSQLDatabaseConfig := TBoldSQLDataBaseConfig.Create; - fSQLDatabaseConfig.AssignConfig(SQLDatabaseConfig); + fSQLDatabaseConfig := SQLDatabaseConfig; fNationalCharConversion := NationalCharConversion; end; destructor TBoldSQLSystemDescription.Destroy; begin FreeAndNil(fTables); - FreeAndNil(fSQLDatabaseConfig); inherited; end; procedure TBoldSQLSystemDescription.InitializeKnownSystemtables( KnownTables: TStrings; PSParams: TBoldPSSQLParams); begin - // do nothing; end; procedure TBoldSQLSystemDescription.CreatePersistentStorage(PSParams: TBoldPSParams); var - i: integer; PsParamsSQL: TBoldPSSQLParams; + + procedure CreateTables; + var + i: integer; + begin + Query := PSParamsSQL.Database.GetExecQuery; + Query.ParamCheck := false; + Query.StartSQLBatch; + try + if BoldLog.ProcessInterruption then + exit; + BoldLog.LogHeader := 'Creating tables'; + BoldLog.ProgressMax := SQLTablesList.Count-1; + for i := 0 to SQLTablesList.Count - 1 do + begin + BoldLog.Progress := i; + SQLTablesList[i].CreateTable(PsParamsSQL); + BoldLog.Sync; + if BoldLog.ProcessInterruption then + exit; + end; + Query.EndSQLBatch; + CommitMetaDataTransaction(PSParamsSQL); + except + RollBackMetaDataTransaction(PSParamsSQL); + Query.FailSQLBatch; + raise; + end; + end; + begin if not (PSParams is TBoldPSSQLParams) then - raise EBold.CreateFmt(sUnknownPSParamsType, [classname, PSParams.Classname]); + raise EBold.CreateFmt('%s.CreatePersistentStorage: Unknown type of PSParams: %s', [classname, PSParams.Classname]); PSParamsSQL := PSParams as TBoldPSSQLParams; - CleanPersistentStorage(PSParamsSQL); - StartMetaDataTransaction(PSParamsSQL); try - if BoldLog.ProcessInterruption then - exit; - - BoldLog.LogHeader := sCreatingTables; - BoldLog.ProgressMax := SQLTablesList.Count-1; - for i := 0 to SQLTablesList.Count - 1 do - begin - BoldLog.Progress := i; - SQLTablesList[i].CreateTable(PsParamsSQL); - BoldLog.Sync; - if BoldLog.ProcessInterruption then - exit; - end; - CommitMetaDataTransaction(PSParamsSQL); - except - RollBackMetaDataTransaction(PSParamsSQL); - raise; + CreateTables; + finally + PSParamsSQL.Database.ReleaseExecQuery(Query); end; end; @@ -279,7 +318,9 @@ function TBoldSQLSystemDescription.ContinueClearPS(TableNameList: TStrings): boo if TableNameList.IndexOf(BoldExpandPrefix(IDTABLE_NAME, '', SQLDatabaseConfig.SystemTablePrefix, SQLDatabaseConfig.MaxDBIdentifierLength, NationalCharConversion)) > -1 then Result := BoldCleanDatabaseForced or - (MessageDlg(sContinueDeleteBoldTables, mtWarning, [mbYes, mbNo], 0) = mrYes); + (MessageDlg('Persistent Storage Seems to Contain a Bold Database. ' + + 'Continuing Will Permanently Destroy Data. Continue?', + mtWarning, [mbYes, mbNo], 0) = mrYes); end; procedure TBoldSQLSystemDescription.CleanPersistentStorage(PSParams: TBoldPSSQLParams); @@ -311,18 +352,10 @@ function DeleteTableBDE: boolean; end; function DeleteTableSQL: boolean; -var - Query: IBoldExecQuery; begin result := true; - - Query := PSParams.DataBase.GetExecQuery; - try - Query.AssignSQLText('DROP TABLE ' + Tablenamelist[i]); // do not localize - Query.ExecSQL; - finally - PSParams.dataBase.ReleaseExecQuery(Query); - end; + self.Query.AssignSQLText('DROP TABLE '+Tablenamelist[i]); + self.Query.ExecSQL; end; function DeleteTable: Boolean; @@ -331,11 +364,12 @@ function DeleteTable: Boolean; IsBoldTable: boolean; begin + Result:=False; IsBoldTable := Knowntables.IndexOf(TableNameList[i]) <> -1 ; if not IsBoldTable and (not PSParams.IgnoreUnknownTables) and not (Query in [qrYesAll, qrNoAll]) then - Query := QueryUser(sDeleteTable, Format(sDeleteNonBoldTable, [TableNameList[i]])); + Query := QueryUser('Delete Table', Format('Table %s does not seem to be a Bold table. Do you want to delete it.', [TableNameList[i]])); MayDelete := (Query in [qrYes, qrYesAll]) and (not PSParams.IgnoreUnknownTables); @@ -350,7 +384,7 @@ function DeleteTable: Boolean; begin Guard := TBoldGuard.Create(Knowntables, TableNameList); - BoldLog.LogHeader := sCleaningPS; + BoldLog.LogHeader := 'Cleaning Persistent Storage'; Query := qrYes; TableNameList := TStringList.Create; @@ -358,15 +392,13 @@ function DeleteTable: Boolean; InitializeKnownSystemtables(KnownTables, PSParams); - - // this is needed in ADO since the cached table seems to keep the BOLD_TABLEs table open even though it has been closed... PSParams.Database.ReleaseCachedObjects; StartMetaDataTransaction(PSParams); try PSParams.Database.AllTableNames('*', False, TableNameList); if not ContinueClearPS(TableNameList) then - raise EBold.Create(sCleaningPSAborted); + raise EBold.Create('Cleaning of Persistent Storage Aborted'); BoldLog.ProgressMax := TableNameList.Count-1; for i := 0 to TableNameList.Count - 1 do @@ -375,13 +407,13 @@ function DeleteTable: Boolean; try if DeleteTable then begin - BoldLog.LogFmt(sDeletingTableX, [TableNameList[i]]); + BoldLog.LogFmt('Deleting Table: %s', [TableNameList[i]]); end else - BoldLog.LogFmt(sKeepingTableX, [TableNameList[i]]); + BoldLog.LogFmt('Keeping Table: %s', [TableNameList[i]]); except on e:Exception do - BoldLog.LogFmt(sErrorDeletingTable, [TableNameList[i], E.Message], ltError); + BoldLog.LogFmt('Error Deleting Table %s: %s', [TableNameList[i], E.Message], ltError); end; BoldLog.Sync; if BoldLog.ProcessInterruption then @@ -396,7 +428,12 @@ function DeleteTable: Boolean; end; {---TBoldSQLDescriptionElement---} -function TBoldSQLDescriptionElement.MappedSQLName(value: String): String; +function TBoldSQLDescriptionElement.GetDebugInfo: string; +begin + result := ClassName + ':' + SqlName; +end; + +function TBoldSQLDescriptionElement.MappedSQLName(const value: String): String; var System: TBoldSQLSystemDescription; begin @@ -417,9 +454,10 @@ function TBoldSQLDescriptionElement.OwningSystem: TBoldSQLSystemdescription; result := nil; end; -procedure TBoldSQLDescriptionElement.SetSQLName(v: string); +procedure TBoldSQLDescriptionElement.SetSQLName(const v: string); begin fSQLName := MappedSQlName(v); + fSQLNameUpper := AnsiUpperCase(v); end; {---TBoldSQLTableDescription---} @@ -439,35 +477,35 @@ destructor TBoldSQLTableDescription.Destroy; inherited; end; -function TBoldSQLTableDescription.SQLForCreateTable(DataBase: IBoldDatabase): string; +function TBoldSQLTableDescription.SQLForCreateTable(const DataBase: IBoldDatabase): string; var i: integer; s: string; begin - Result := Format('CREATE TABLE %s (', [SQLName]); // do not localize + Result := Format('CREATE TABLE %s (', [SQLName]); for i := 0 to ColumnsList.Count - 1 do begin if i > 0 then Result := Result + ', ' + BOLDCRLF; s := (ColumnsList[i] as TBoldSQLColumnDescription).GetSQLForColumn(DataBase); Result := Result + ' ' + s; - BoldLog.Log(Format(sAddingColumn, [s]), ltDetail); + BoldLog.Log('Adding column: '+s, ltDetail); end; if SystemDescription.SQLDatabaseConfig.SupportsConstraintsInCreateTable and Assigned(PrimaryIndex) then begin Result := Result + ', ' + BOLDCRLF + ' ' + PrimaryIndex.SQLForPrimaryKey; - BoldLog.Log(Format(sAddingPrimaryIndex, [PrimaryIndex.SQLForPrimaryKey]), ltDetail); + BoldLog.Log('Adding Primary index: '+PrimaryIndex.SQLForPrimaryKey, ltDetail); end; Result := Result + ')'; end; function TBoldSQLTableDescription.SQLForDropTable: string; begin - result := format('DROP TABLE %s', [SQLName]); // do not localize + result := format('DROP TABLE %s', [SQLName]); end; -procedure TBoldSQLTableDescription.SetSQLName(v: string); +procedure TBoldSQLTableDescription.SetSQLName(const v: string); begin if SQLName <> MappedSQLName(v) then begin @@ -495,12 +533,9 @@ procedure TBoldSQLTableDescription.CreateTableBDE(PSParams: TBoldPSSQLParams); try TableName := SQLName; Exclusive := True; - - // Create columns FieldDefs.Clear; for i := 0 to ColumnsList.Count - 1 do (ColumnsList[i] as TBoldSQLColumnDescription).CreateBDEColumn(FieldDefs); - // Create Indexes if IndexList.Count > MAXIMUMINDEXCOUNT then MaxIndex := MAXIMUMINDEXCOUNT else @@ -520,26 +555,22 @@ procedure TBoldSQLTableDescription.CreateTableSQL(PSParams: TBoldPSSQLParams); i: integer; Query: IBoldExecQuery; begin - Query := PSParams.Database.GetExecQuery; - try - Query.AssignSQLText(SQLForCreateTable(PSParams.Database)); - Query.ExecSQL; - for i := 0 to IndexList.count-1 do - if (not SystemDescription.SQLDatabaseConfig.SupportsConstraintsInCreateTable) or - (IndexList[i] <> PrimaryIndex) then - begin - Query.AssignSQLText((IndexList[i] as TBoldSQLIndexDescription).SQLForSecondaryKey); - Query.ExecSQL; - end; - finally - PSParams.Database.ReleaseExecQuery(Query); - end; + Query := SystemDescription.Query; + Query.AssignSQLText(SQLForCreateTable(PSParams.Database)); + Query.ExecSQL; + for i := 0 to IndexList.count-1 do + if (not SystemDescription.SQLDatabaseConfig.SupportsConstraintsInCreateTable) or + (IndexList[i] <> PrimaryIndex) then + begin + Query.AssignSQLText((IndexList[i] as TBoldSQLIndexDescription).SQLForSecondaryKey); + Query.ExecSQL; + end; end; procedure TBoldSQLTableDescription.CreateTable(PSParams: TBoldPSSQLParams); begin - BoldLog.LogFmtIndent(sCreatingTableX, [SQLName]); + BoldLog.LogFmtIndent('Creating Table: %s', [SQLName]); case SystemDescription.EffectiveGenerationMode(PSParams) of dbgTable: CreateTableBDE(PSParams); dbgQuery: CreateTableSQL(PSParams); @@ -564,10 +595,10 @@ procedure TBoldSQLTableDescription.DeleteTable(PSParams: TBoldPSSQLParams); var Table: IBoldTable; begin - BoldLog.LogFmt(sLocatingTableX, [SQLName]); + BoldLog.LogFmt('Locating Table: %s', [SQLName]); if TableExists(PSParams) then begin - BoldLog.LogFmt(sDeletingTableX, [SQLName]); + BoldLog.LogFmt('Deleting Table: %s', [SQLName]); Table := PSParams.Database.GetTable; with table do try @@ -580,10 +611,10 @@ procedure TBoldSQLTableDescription.DeleteTable(PSParams: TBoldPSSQLParams); end; end else - BoldLog.LogFmt(sTableXNotPresent, [SQLName]); + BoldLog.LogFmt('Table %s not Present', [SQLName]); end; -function TBoldSQLTableDescription.AddColumn(const ColName: string; SQLColType, AllowNullAsSQL: String; ColType: TFieldType; ColSize: Integer; AllowNull: Boolean; DefaultDBValue: String): TBoldSQLColumnDescription; +function TBoldSQLTableDescription.AddColumn(const ColName: string; SQLColType, AllowNullAsSQL: String; ColType: TFieldType; ColSize: Integer; AllowNull: Boolean; const DefaultDBValue: String): TBoldSQLColumnDescription; begin Result := TBoldSQLColumnDescription.Create(Self); Result.SQLName := ColName; @@ -595,7 +626,7 @@ function TBoldSQLTableDescription.AddColumn(const ColName: string; SQLColType, A Result.DefaultDBValue := DefaultDBValue; end; -procedure TBoldSQLTableDescription.EnsureIndex(const Fields: string; Primary, Unique: boolean); +procedure TBoldSQLTableDescription.EnsureIndex(const Fields: string; Primary, Unique, NonClustered: boolean); var BoldSQLIndexDescription: TBoldSQLIndexDescription; begin @@ -610,14 +641,16 @@ procedure TBoldSQLTableDescription.EnsureIndex(const Fields: string; Primary, Un end; if Unique then BoldSQLIndexDescription.IndexOptions := BoldSQLIndexDescription.IndexOptions + [ixUnique]; + if NonClustered then + BoldSQLIndexDescription.IndexOptions := BoldSQLIndexDescription.IndexOptions + [ixNonClustered]; end; procedure TBoldSQLTableDescription.RetrieveSelectIdAndTypeStatement(S: TStrings); begin with S do begin - Append(Format('SELECT %s.%s, %s.%s',[SQLName, IDCOLUMN_NAME, SQLName, TYPECOLUMN_NAME])); // do not localize - Append(Format('FROM %s',[SQLName])); // do not localize + Append(Format('SELECT %s.%s, %s.%s',[SQLName, IDCOLUMN_NAME, SQLName, TYPECOLUMN_NAME])); + Append(Format('FROM %s',[SQLName])); end; end; @@ -633,7 +666,7 @@ procedure TBoldSQLColumnDescription.CreateBDEColumn(FieldDefs: TFieldDefs); var FieldDef: TFieldDef; begin - BoldLog.LogFmt(sAddingColumnInfo, + BoldLog.LogFmt('Adding column: %s [%s, %d]', [SQLName, GetEnumName(TypeInfo(TFieldType), Ord(FieldType)), Size], ltDetail); FieldDef := FieldDefs.AddFieldDef; @@ -644,8 +677,8 @@ procedure TBoldSQLColumnDescription.CreateBDEColumn(FieldDefs: TFieldDefs); if DefaultDBValue <> '' then begin BoldLog.Separator; - BoldLog.LogFmt(sColumnHasDefaultDBValue, [SQLName, DefaultDBValue], ltWarning); - BoldLog.Log(sUnsupportedInTableCreationMode); + BoldLog.LogFmt('Column %s has a default db value (%s)', [SQLName, DefaultDBValue], ltWarning); + BoldLog.Log('This is not supported when generating the database using TTable, please use TQuery-method instead if this default value is required'); BoldLog.Separator; end; end; @@ -655,7 +688,7 @@ function TBoldSQLColumnDescription.GetTableDescription: TBoldSQLTableDescription Result := Owner as TBoldSQLTableDescription; end; -procedure TBoldSQLColumnDescription.SetSQLName(v: string); +procedure TBoldSQLColumnDescription.SetSQLName(const v: string); begin if SQLName <> v then begin @@ -664,16 +697,21 @@ procedure TBoldSQLColumnDescription.SetSQLName(v: string); end; end; -function TBoldSQLColumnDescription.GetSQLForColumn(DataBase: IBoldDatabase): string; +function TBoldSQLColumnDescription.GetDebugInfo: string; +begin + result := TableDescription.SqlName + '.' + SqlName; +end; + +function TBoldSQLColumnDescription.GetSQLForColumn(const DataBase: IBoldDatabase): string; var DefaultValue: String; begin if (not assigned(DataBase) or Database.SupportsDefaultColumnValues) and (DefaultDbValue <> '') then - DefaultValue := 'DEFAULT ' + DefaultDbValue // do not localize + DefaultValue := 'DEFAULT '+DefaultDbValue else DefaultValue := ''; - Result := Format('%s %s %s %s', [SQLName, SQLType, DefaultValue, SQLAllowNull]); // do not localize + Result := Format('%s %s %s %s', [SQLName, SQLType, DefaultValue, SQLAllowNull]); end; {---TBoldSQLIndexDescription---} @@ -688,18 +726,20 @@ constructor TBoldSQLIndexDescription.Create(aOwner: TBoldPSDescriptionElement; c function TBoldSQLIndexDescription.SQLForPrimaryKey: string; begin - Result := Format('CONSTRAINT %s PRIMARY KEY (%s)', [generatedName, IndexedFieldsForSQL]); // do not localize + Result := Format('CONSTRAINT %s PRIMARY KEY (%s)', [generatedName, IndexedFieldsForSQL]); end; function TBoldSQLIndexDescription.SQLForSecondaryKey: string; var - Unique: string; + sType: string; begin if ixUnique in IndexOptions then - Unique := 'UNIQUE' // do not localize + sType := 'UNIQUE' // do not localize + else if ixNonClustered in IndexOptions then + sType := 'NONCLUSTERED' // do not localize else - Unique := ''; - Result := Format('CREATE %s INDEX %s ON %s (%s)', [Unique, GeneratedName, TableDescription.SQLName, IndexedFieldsForSQL]); // do not localize + sType := ''; + Result := Format('CREATE %s INDEX %s ON %s (%s)', [sType, GeneratedName, TableDescription.SQLName, IndexedFieldsForSQL]); // do not localize end; @@ -708,6 +748,27 @@ function TBoldSQLIndexDescription.GetTableDescription: TBoldSQLTableDescription; Result := Owner as TBoldSQLTableDescription; end; +class function TBoldSQLIndexDescription.NormalizeFields( + const IndexedFields: string): string; +var + sl: TStringList; +begin + result := StringReplace(IndexedFields, ';', ',', [rfReplaceAll]); + result := StringReplace(result, ' ', '', [rfReplaceAll]); + if pos(',', result) > 1 then + begin + sl := TStringList.Create; + try + sl.CommaText := result; + sl.Sorted := true; + Result := sl.CommaText; + finally + sl.free; + end; + end; + result := StringReplace(Result, ',', ';', [rfReplaceAll]); +end; + procedure TBoldSQLIndexDescription.CreateBDEIndex(PSParams: TBoldPSSQLParams; IndexDefs: TIndexDefs); var ActualOptions: TIndexOptions; @@ -715,16 +776,33 @@ procedure TBoldSQLIndexDescription.CreateBDEIndex(PSParams: TBoldPSSQLParams; In SQLName: string; begin SQLName := GeneratedName; - BoldLog.LogFmt(sAddingIndex, [SQLName, IndexedFields], ltDetail); - ActualOptions := IndexOptions; + BoldLog.LogFmt('Adding Index: %s on %s', [SQLName, IndexedFields], ltDetail); + //Conversion of TIndexOptionsEx to TIndexOptions + if ixPrimary in IndexOptions then begin + ActualOptions := ActualOptions + [db.ixPrimary]; + end; + if ixUnique in IndexOptions then begin + ActualOptions := ActualOptions + [db.ixUnique]; + end; + if ixDescending in IndexOptions then begin + ActualOptions := ActualOptions + [db.ixDescending]; + end; + if ixCaseInsensitive in IndexOptions then begin + ActualOptions := ActualOptions + [db.ixCaseInsensitive]; + end; + if ixExpression in IndexOptions then begin + ActualOptions := ActualOptions + [db.ixExpression]; + end; + if ixNonMaintained in IndexOptions then begin + ActualOptions := ActualOptions + [db.ixNonMaintained]; + end; ActualName := SQLName; - // Paradox complains if IndexOptions are empty. if not PSParams.Database.IsSQLBased then begin if ActualOptions = [] then - ActualOptions := [ixCaseInsensitive]; + ActualOptions := [db.ixCaseInsensitive]; - if ixPrimary in ActualOptions then + if db.ixPrimary in ActualOptions then ActualName := ''; end; IndexDefs.Add(ActualName, IndexedFields, ActualOptions); @@ -745,7 +823,7 @@ function TBoldSQLDescriptionList.GetItem(index: Integer): TBoldSQLDescriptionEle Result := TBoldSQLDescriptionElement(inherited Items[index]); end; -function TBoldSQLDescriptionList.GetItemBySQLName(SQLName: string): TBoldSQLDescriptionElement; +function TBoldSQLDescriptionList.GetItemBySQLName(const SQLName: string): TBoldSQLDescriptionElement; begin Result := TBoldSQLDescriptionElement(TSQLDescriptorSQLNameIndex(Indexes[IX_SQLDescriptionSQLName]).FindByString( BoldExpandName(SQLName, '', xtSQL, @@ -769,7 +847,7 @@ function TBoldSQLTableDescriptionList.GetItem(index: Integer): TBoldSQLTableDesc Result := TBoldSQLTableDescription(inherited Items[index]); end; -function TBoldSQLTableDescriptionList.GetItemBySQLName(SQLName: string): TBoldSQLTableDescription; +function TBoldSQLTableDescriptionList.GetItemBySQLName(const SQLName: string): TBoldSQLTableDescription; begin Result := TBoldSQLTableDescription(TSQLDescriptorSQLNameIndex(Indexes[IX_SQLDescriptionSQLName]).FindByString( BoldExpandName(SQLName, '', xtSQL, @@ -789,7 +867,7 @@ function TBoldSQLIndexDescription.GeneratedName: String; IndexNameLength := TableDescription.SystemDescription.SQLDatabaseConfig.MaxDBIdentifierLength; if IndexNameLength = -1 then IndexNameLength := TableDescription.SystemDescription.SQLDatabaseConfig.MaxIndexNameLength; - result := BoldExpandName('IX_'+TableDescription.SQLName+'_'+IndexedFields, // do not localize + result := BoldExpandName('IX_'+TableDescription.SQLName+'_'+StringReplace(IndexedFields, ';', '_', [rfReplaceAll]), '', xtSQL, IndexNameLength, @@ -803,35 +881,26 @@ constructor TBoldSQLIndexDescriptionList.Create; begin inherited Create; SetIndexCapacity(1); + IX_SQLIndexFields := -1; SetIndexVariable(IX_SQLIndexFields, AddIndex(TSQLIndexFieldsIndex.Create)); end; -function TBoldSQLIndexDescriptionList.GetItem(index: integer): TBoldSQLIndexDescription; -begin - result := (inherited items[index]) as TBoldSQLIndexDescription; -end; - -function TBoldSQLIndexDescriptionList.GetItemsByIndexFields(const IndexFields: string): TBoldSQLIndexDescription; -begin - Result := TBoldSQLIndexDescription(TSQLIndexFieldsIndex(Indexes[IX_SQLIndexFields]).FindByString(IndexFields)); -end; - { TSQLIndexFieldsIndex } function TSQLIndexFieldsIndex.ItemAsKeyString(Item: TObject): string; begin - Result := TBoldSQLIndexDescription(Item).IndexedFields; + Result := TBoldSQLIndexDescription.NormalizeFields(TBoldSQLIndexDescription(Item).IndexedFields); end; -procedure TBoldSQLSystemDescription.GenerateDatabaseScript(Script: TStrings; Separator: string); +procedure TBoldSQLSystemDescription.GenerateDatabaseScript(Script: TStrings); var i: integer; begin for i := 0 to SQLTablesList.Count - 1 do - SQLTablesList[i].GenerateDatabaseScript(Script, Separator); + SQLTablesList[i].GenerateDatabaseScript(Script); end; -procedure TBoldSQLTableDescription.GenerateDatabaseScript(Script: TStrings; Separator: string); +procedure TBoldSQLTableDescription.GenerateDatabaseScript(Script: TStrings); var SQL: TStringList; Guard: IBoldGuard; @@ -839,16 +908,18 @@ procedure TBoldSQLTableDescription.GenerateDatabaseScript(Script: TStrings; Sepa begin Guard := TBoldGuard.create(SQL); SQL := TStringList.Create; - sql.Text := SQLForCreateTable(nil); - Script.Add(Separator); + sql.Text := SQLForCreateTable(nil) + SystemDescription.SQLDatabaseConfig.SqlScriptTerminator; Script.AddStrings(Sql); + if SystemDescription.SQLDatabaseConfig.SqlScriptSeparator<>'' then + Script.Add(SystemDescription.SQLDatabaseConfig.SqlScriptSeparator); for i := 0 to IndexList.count-1 do if IndexList[i] <> PrimaryIndex then begin - sql.Text := (IndexList[i] as TBoldSQLIndexDescription).SQLForSecondaryKey; - Script.Add(Separator); + sql.Text := (IndexList[i] as TBoldSQLIndexDescription).SQLForSecondaryKey + SystemDescription.SQLDatabaseConfig.SqlScriptTerminator; Script.AddStrings(Sql); + if SystemDescription.SQLDatabaseConfig.SqlScriptSeparator<>'' then + Script.Add(SystemDescription.SQLDatabaseConfig.SqlScriptSeparator); end; end; @@ -868,7 +939,7 @@ procedure TBoldSQLSystemDescription.CommitMetaDataTransaction(PSParams: TBoldPSS begin if PsParams.Database.InTransaction then begin - BoldLog.Log(sCommittingToDB); + BoldLog.Log('Committing changes to metadata'); PsParams.Database.Commit; end; end; @@ -877,7 +948,7 @@ procedure TBoldSQLSystemDescription.RollBackMetaDataTransaction(PSParams: TBoldP begin if PsParams.Database.InTransaction then begin - BoldLog.Log(sRollingBackDB); + BoldLog.Log('Rolling back changes to metadata'); PsParams.Database.RollBack; end; end; @@ -888,4 +959,5 @@ procedure TBoldSQLSystemDescription.StartMetaDataTransaction(PSParams: TBoldPSSQ PsParams.Database.StartTransaction; end; +initialization end. diff --git a/Source/PMapper/SQL/BoldPSParamsSQL.pas b/Source/PMapper/SQL/BoldPSParamsSQL.pas index 3acdbe6..7c79aab 100644 --- a/Source/PMapper/SQL/BoldPSParamsSQL.pas +++ b/Source/PMapper/SQL/BoldPSParamsSQL.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldPSParamsSQL; interface @@ -20,4 +23,12 @@ TBoldPSSQLParams = class(TBoldPSParams) implementation +uses + BoldRev; + +{ TBoldPSSQLParams } + +initialization + + end. diff --git a/Source/PMapper/SQL/BoldSQLDatabaseConfig.pas b/Source/PMapper/SQL/BoldSQLDatabaseConfig.pas index 9524330..e3683f3 100644 --- a/Source/PMapper/SQL/BoldSQLDatabaseConfig.pas +++ b/Source/PMapper/SQL/BoldSQLDatabaseConfig.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldSQLDatabaseConfig; interface @@ -13,32 +16,57 @@ interface dbeInterbaseSQLDialect1, dbeInterbaseSQLDialect3, dbeGenericANSISQL92, dbeSQLServer, + dbePostgres, dbeDBISAM, dbeOracle, dbeAdvantage, dbeParadox, dbeInformix); +const + cMaxBatchQueryLength = 65536 * 64; + cMaxBatchQueryParams = 1000; + +type TBoldSQLDataBaseConfig = class; TBoldSQLDataBaseConfig = class(TPersistent) private + FIfTemplate: string; + FColumnExistsTemplate: string; + FTableExistsTemplate: string; + FIndexExistsTemplate: string; + FIndexColumnExistsTemplate: string; FColumnTypeForBlob: string; FColumnTypeForDateTime: string; FColumnTypeForDate: string; FColumnTypeForTime: string; FColumnTypeForFloat: string; + fColumnTypeForInt64: string; + fDefaultValueForDateTime: string; + FDefaultSystemMapper: string; + FDefaultObjectMapper: string; fOnChange: TNotifyEvent; fUseSQL92Joins: boolean; + fSingleIndexOrderedLinks: Boolean; fFetchBlockSize: integer; + fMultiRowInsertLimit: integer; + fUseParamsForInteger: boolean; + fUseParamsForEmptyString: boolean; fDefaultStringLength: integer; FColumnTypeForString: string; + FColumnTypeForUnicodeString: string; + FColumnTypeForText: string; + FColumnTypeForUnicodeText: string; + FLongStringLimit: integer; fDropColumnTemplate: string; fDropIndexTemplate: string; fDropTableTemplate: string; + fIndexInfoTemplate: string; fSQLforNotNull: string; FColumnTypeForInteger: string; fColumnTypeForSmallInt: string; + FColumnTypeForGUID: string; fSupportsConstraintsInCreateTable: Boolean; fQuoteNonStringDefaultValues: Boolean; fSupportsStringDefaultValues: Boolean; @@ -61,24 +89,52 @@ TBoldSQLDataBaseConfig = class(TPersistent) FSqlScriptSeparator: string; FSqlScriptRollBackTransaction: string; FSqlScriptCommitTransaction: string; + FDatabaseCaseSensitiveTemplate: string; + fQuoteLeftBracketInLike: Boolean; + fIgnoreMissingObjects: boolean; + fMaxBatchQueryLength: integer; + fMaxBatchQueryParams: integer; + fBatchQueryBegin: string; + fBatchQueryEnd: string; + fBatchQuerySeparator: string; + fUseBatchQueries: boolean; + fUseMultiRowInserts: boolean; + fSQLforNull: string; + fEvolveDropsUnknownIndexes: boolean; + procedure SetIfTemplate(const Value: string); + procedure SetColumnExistsTemplate(const Value: string); + procedure SetTableExistsTemplate(const Value: string); + procedure SetIndexExistsTemplate(const Value: string); + procedure SetIndexColumnExistsTemplate(const Value: string); procedure SetColumnTypeForBlob(const Value: string); procedure SetColumnTypeForDate(const Value: string); procedure SetColumnTypeForDateTime(const Value: string); procedure SetColumnTypeForTime(const Value: string); + procedure SetDefaultValueForDateTime(const Value: string); + procedure SetDefaultObjectMapper(const Value: string); + procedure SetDefaultSystemMapper(const Value: string); procedure Change; procedure SetUseSQL92Joins(const Value: boolean); + procedure SetSingleIndexOrderedLinks(const Value: boolean); procedure SetColumnTypeForFloat(const Value: string); procedure SetDefaultStringLength(const Value: integer); procedure SetFetchBlockSize(const Value: integer); procedure SetColumnTypeForString(const Value: string); + procedure SetColumnTypeForUnicodeString(const Value: string); + procedure SetColumnTypeForText(const Value: string); + procedure SetColumnTypeForUnicodeText(const Value: string); + procedure SetLongStringLimit(Value: integer); procedure SetDropColumnTemplate(const Value: string); procedure SetDropIndexTemplate(const Value: string); procedure SetDropTableTemplate(const Value: string); + procedure SetIndexInfoTemplate(const Value: string); procedure SetInitialValues; procedure SetSQLforNotNull(const Value: string); procedure SetColumnTypeForInteger(const Value: string); function GetEffectiveSQLForNotNull: string; procedure SetColumnTypeForSmallInt(const Value: string); + procedure SetColumnTypeForInt64(const Value: string); + procedure SetColumnTypeForGUID(const Value: string); procedure SetSupportsConstraintsInCreateTable(const Value: Boolean); procedure SetQuoteNonStringDefaultValues(const Value: Boolean); procedure SetSupportsStringDefaultValues(const Value: Boolean); @@ -90,10 +146,12 @@ TBoldSQLDataBaseConfig = class(TPersistent) procedure SetDBGenerationMode(const Value: TBoldDatabaseGenerationMode); procedure setAllowMetadataChangesInTransaction(const Value: Boolean); procedure ReadUseTransactionsDuringDBCreate(Reader: TReader); + procedure SetDatabaseCaseSensitiveTemplate(const Value: string); procedure SetFieldTypeForBlob(const Value: TFieldType); procedure SetEmptyStringMarker(const Value: String); procedure SetStoreEmptyStringsAsNULL(const Value: Boolean); procedure SetSystemTablePrefix(const Value: String); + procedure SetQuoteLeftBracketInLike(const Value: Boolean); procedure SetSqlScriptCommentStart(const Value: string); procedure SetSqlScriptCommentStop(const Value: string); procedure SetSqlScriptSeparator(const Value: string); @@ -101,51 +159,103 @@ TBoldSQLDataBaseConfig = class(TPersistent) procedure SetSqlScriptTerminator(const Value: string); procedure SetSqlScriptCommitTransaction(const Value: string); procedure SetSqlScriptRollBackTransaction(const Value: string); + procedure SetIgnoreMissingObjects(const Value: boolean); + procedure SetMaxBatchQueryLength(const Value: integer); + procedure SetMaxBatchQueryParams(const Value: integer); + procedure SetBatchQueryBegin(const Value: string); + procedure SetBatchQueryEnd(const Value: string); + procedure SetBatchQuerySeparator(const Value: string); + procedure SetUseBatchQueries(const Value: boolean); + procedure SetMultiRowInsertLimit(const Value: integer); + procedure SetUseParamsForInteger(const Value: boolean); + procedure SetUseParamsForEmptyString(const Value: boolean); + procedure SetSQLforNull(const Value: string); + procedure SetEvolveDropsUnknownIndexes(const Value: boolean); protected procedure DefineProperties(Filer: TFiler); override; public - constructor create; + constructor Create; destructor Destroy; override; procedure Assign(Source: TPersistent); override; procedure AssignConfig(Source: TBoldSQLDataBaseConfig); function GetDropColumnQuery(const TableName, columnName: String): String; function GetDropIndexQuery(const TableName, IndexName: String): String; function GetDropTableQuery(const TableName: String): String; + function GetIndexInfoQuery(const TableName: String): String; + function GetColumnTypeForString(Size: Integer): string; + function GetColumnTypeForUnicodeString(Size: Integer): string; procedure InitializeDbEngineSettings(Engine: TBoldDatabaseEngine); function CorrectlyQuotedDefaultValue(value: string): String; + function GetColumnExistsQuery(const TableName, ColumnName: string): string; + function GetIfColumnNotExistsQuery(const TableName, ColumnName, SQLStatement: + string): string; + function GetIndexColumnExistsQuery(const TableName, IndexColumnName: string): + string; + function GetIndexExistsQuery(const TableName, IndexName: string): string; + function GetTableExistsQuery(const TableName: string): string; property EffectiveSQLForNotNull: string read GetEffectiveSQLForNotNull; property OnChange: TNotifyEvent read fOnChange write fOnChange; property Engine: TBoldDatabaseEngine read fEngine write fEngine; published + property DefaultSystemMapper: string read FDefaultSystemMapper write SetDefaultSystemMapper; + property DefaultObjectMapper: string read FDefaultObjectMapper write SetDefaultObjectMapper; + property IfTemplate: string read FIfTemplate write SetIfTemplate; + property ColumnExistsTemplate: string read FColumnExistsTemplate write SetColumnExistsTemplate; + property TableExistsTemplate: string read FTableExistsTemplate write SetTableExistsTemplate; + property IndexExistsTemplate: string read FIndexExistsTemplate write SetIndexExistsTemplate; + property IndexColumnExistsTemplate: string read FIndexColumnExistsTemplate write SetIndexColumnExistsTemplate; property ColumnTypeForDate: string read FColumnTypeForDate write SetColumnTypeForDate; property ColumnTypeForTime: string read FColumnTypeForTime write SetColumnTypeForTime; property ColumnTypeForDateTime: string read FColumnTypeForDateTime write SetColumnTypeForDateTime; + property DefaultValueForDateTime: string read FDefaultValueForDateTime write SetDefaultValueForDateTime; property ColumnTypeForBlob: string read FColumnTypeForBlob write SetColumnTypeForBlob; property ColumnTypeForFloat: string read FColumnTypeForFloat write SetColumnTypeForFloat; property ColumnTypeForCurrency: string read FColumnTypeForCurrency write SetColumnTypeForCurrency; property ColumnTypeForString: string read FColumnTypeForString write SetColumnTypeForString; + property ColumnTypeForUnicodeString: string read FColumnTypeForUnicodeString write SetColumnTypeForUnicodeString; + property ColumnTypeForText: string read FColumnTypeForText write SetColumnTypeForText; + property ColumnTypeForUnicodeText: string read FColumnTypeForUnicodeText write SetColumnTypeForUnicodeText; + property LongStringLimit: integer read FLongStringLimit write SetLongStringLimit default -1; property ColumnTypeForInteger: string read FColumnTypeForInteger write SetColumnTypeForInteger; property ColumnTypeForSmallInt: string read fColumnTypeForSmallInt write SetColumnTypeForSmallInt; + property ColumnTypeForInt64: string read fColumnTypeForInt64 write SetColumnTypeForInt64; + property ColumnTypeForGUID: string read fColumnTypeForGUID write SetColumnTypeForGUID; property FieldTypeForBlob: TFieldType read fFieldTypeForBlob write SetFieldTypeForBlob default ftBlob; property FetchBlockSize: integer read fFetchBlockSize write SetFetchBlockSize default 250; property MaxParamsInIdList: integer read fMaxParamsInIdList write SetMaxParamsInIdList default 20; property DefaultStringLength: integer read fDefaultStringLength write SetDefaultStringLength default 255; property UseSQL92Joins: boolean read fUseSQL92Joins write SetUseSQL92Joins default false; + property SingleIndexOrderedLinks: boolean read fSingleIndexOrderedLinks write SetSingleIndexOrderedLinks default false; + property IgnoreMissingObjects: boolean read fIgnoreMissingObjects write SetIgnoreMissingObjects default false; property DropColumnTemplate: string read fDropColumnTemplate write SetDropColumnTemplate; property DropTableTemplate: string read fDropTableTemplate write SetDropTableTemplate; + property IndexInfoTemplate: string read fIndexInfoTemplate write SetIndexInfoTemplate; property DropIndexTemplate: string read fDropIndexTemplate write SetDropIndexTemplate; + property EvolveDropsUnknownIndexes: boolean read fEvolveDropsUnknownIndexes write SetEvolveDropsUnknownIndexes; property MaxDbIdentifierLength: integer read fMaxDbIdentifierLength write SetMaxDbIdentifierLength default -1; property MaxIndexNameLength: integer read fMaxIndexNameLength write SetMaxIndexNameLenght default 18; + property MaxBatchQueryLength: integer read fMaxBatchQueryLength write SetMaxBatchQueryLength default cMaxBatchQueryLength; + property MaxBatchQueryParams: integer read fMaxBatchQueryParams write SetMaxBatchQueryParams default cMaxBatchQueryParams; + property BatchQueryBegin: string read fBatchQueryBegin write SetBatchQueryBegin; + property BatchQueryEnd: string read fBatchQueryEnd write SetBatchQueryEnd; + property BatchQuerySeparator: string read fBatchQuerySeparator write SetBatchQuerySeparator; + property UseBatchQueries: boolean read fUseBatchQueries write SetUseBatchQueries default false; + property UseParamsForInteger: boolean read fUseParamsForInteger write SetUseParamsForInteger default false; + property UseParamsForEmptyString: boolean read fUseParamsForEmptyString write SetUseParamsForEmptyString default false; + property MultiRowInsertLimit: integer read fMultiRowInsertLimit write SetMultiRowInsertLimit default 1; + property SQLforNull: string read fSQLforNull write SetSQLforNull; property SQLforNotNull: string read fSQLforNotNull write SetSQLforNotNull; property QuoteNonStringDefaultValues: Boolean read fQuoteNonStringDefaultValues write SetQuoteNonStringDefaultValues; property SupportsConstraintsInCreateTable: Boolean read fSupportsConstraintsInCreateTable write SetSupportsConstraintsInCreateTable; property SupportsStringDefaultValues: Boolean read fSupportsStringDefaultValues write SetSupportsStringDefaultValues; property DBGenerationMode: TBoldDatabaseGenerationMode read fDBGenerationMode write SetDBGenerationMode; property AllowMetadataChangesInTransaction: Boolean read fAllowMetadataChangesInTransaction write setAllowMetadataChangesInTransaction default True; + property DatabaseCaseSensitiveTemplate: string read FDatabaseCaseSensitiveTemplate write SetDatabaseCaseSensitiveTemplate; property ReservedWords: TStringList read fReservedWords write SetReservedWords; property EmptyStringMarker: String read fEmptyStringMarker write SetEmptyStringMarker; property StoreEmptyStringsAsNULL: Boolean read fStoreEmptyStringsAsNULL write SetStoreEmptyStringsAsNULL; property SystemTablePrefix: String read fSystemTablePrefix write SetSystemTablePrefix; + property QuoteLeftBracketInLike: Boolean read fQuoteLeftBracketInLike write SetQuoteLeftBracketInLike; property SqlScriptSeparator: string read FSqlScriptSeparator write SetSqlScriptSeparator; property SqlScriptTerminator: string read FSqlScriptTerminator write SetSqlScriptTerminator; property SqlScriptCommentStart: string read FSqlScriptCommentStart write SetSqlScriptCommentStart; @@ -158,13 +268,17 @@ TBoldSQLDataBaseConfig = class(TPersistent) implementation uses - SysUtils; + SysUtils, + BoldRev; const EmptyMarker = ''; TableNameMarker = ''; ColumnNameMarker = ''; IndexNameMarker = ''; + ConditionMarker = ''; + SQLStatementMarker = ''; + IndexColumnNameMarker = ''; { TBoldSQLDataBaseConfig } @@ -180,18 +294,39 @@ procedure TBoldSQLDataBaseConfig.AssignConfig(Source: TBoldSQLDataBaseConfig); begin fColumnTypeForBlob := Source.ColumnTypeForBlob; fColumnTypeForDateTime := Source.ColumnTypeForDateTime; + fDefaultValueForDateTime := Source.DefaultValueForDateTime; fColumnTypeForDate := Source.ColumnTypeForDate; fColumnTypeForTime := Source.ColumnTypeForTime; fColumnTypeForFloat := Source.ColumnTypeForFloat; FColumnTypeForCurrency := Source.ColumnTypeForCurrency; fColumnTypeForString := Source.ColumnTypeForString; + fColumnTypeForUnicodeString := Source.ColumnTypeForUnicodeString; + fColumnTypeForText := Source.ColumnTypeForText; + fColumnTypeForUnicodeText := Source.ColumnTypeForUnicodeText; + FLongStringLimit := Source.LongStringLimit; FColumnTypeForInteger := Source.ColumnTypeForInteger; fColumnTypeForSmallInt := Source.ColumnTypeForSmallInt; + fColumnTypeForInt64 := Source.ColumnTypeForInt64; + fColumnTypeForGUID := Source.ColumnTypeForGUID; + FDefaultSystemMapper := Source.FDefaultSystemMapper; + FDefaultObjectMapper := Source.FDefaultObjectMapper; fUseSQL92Joins := Source.UseSQL92Joins; + fMultiRowInsertLimit := Source.MultiRowInsertLimit; + fUseParamsForInteger := Source.UseParamsForInteger; + fUseParamsForEmptyString := Source.UseParamsForEmptyString; + fSingleIndexOrderedLinks := Source.SingleIndexOrderedLinks; fFetchBlockSize := Source.FetchBlockSize; + fIndexInfoTemplate := Source.IndexInfoTemplate; fMaxParamsInIdList := Source.MaxParamsInIdList; fMaxIndexNameLength := Source.MaxIndexNameLength; fMaxDbIdentifierLength := Source.MaxDbIdentifierLength; + fMaxIndexNameLength := Source.MaxIndexNameLength; + fMaxBatchQueryLength := Source.MaxBatchQueryLength; + fMaxBatchQueryParams := Source.MaxBatchQueryParams; + fBatchQueryBegin := Source.BatchQueryBegin; + fBatchQueryEnd := Source.BatchQueryEnd; + fBatchQuerySeparator := Source.BatchQuerySeparator; + fUseBatchQueries := Source.UseBatchQueries; fFieldTypeForBlob := Source.FieldTypeForBlob; fStoreEmptyStringsAsNULL := Source.StoreEmptyStringsAsNULL; fSystemTablePrefix := Source.SystemTablePrefix; @@ -202,6 +337,8 @@ procedure TBoldSQLDataBaseConfig.AssignConfig(Source: TBoldSQLDataBaseConfig); fDropColumnTemplate := Source.DropColumnTemplate; fDropTableTemplate := Source.DropTableTemplate; fDropIndexTemplate := Source.DropIndexTemplate; + fEvolveDropsUnknownIndexes := Source.EvolveDropsUnknownIndexes; + fSQLforNull := Source.SQLforNull; fSQLforNotNull := Source.SQLforNotNull; fSupportsConstraintsInCreateTable := Source.SupportsConstraintsInCreateTable; fQuoteNonStringDefaultValues := Source.QuoteNonStringDefaultValues; @@ -214,6 +351,13 @@ procedure TBoldSQLDataBaseConfig.AssignConfig(Source: TBoldSQLDataBaseConfig); FSqlScriptStartTransaction := Source.SqlScriptStartTransaction; FSqlScriptCommitTransaction := Source.SqlScriptCommitTransaction; FSqlScriptRollBackTransaction := Source.SqlScriptRollBackTransaction; + FIfTemplate := Source.IfTemplate; + FColumnExistsTemplate := Source.ColumnExistsTemplate; + FTableExistsTemplate := Source.TableExistsTemplate; + FIndexExistsTemplate := Source.IndexExistsTemplate; + FIndexColumnExistsTemplate := Source.IndexColumnExistsTemplate; + FDatabaseCaseSensitiveTemplate := Source.DatabaseCaseSensitiveTemplate; + FIgnoreMissingObjects := Source.IgnoreMissingObjects; Change; end; @@ -227,6 +371,8 @@ constructor TBoldSQLDataBaseConfig.create; begin inherited; fReservedWords := TStringList.Create; + FDefaultSystemMapper := DEFAULTNAME; + FDefaultObjectMapper := DEFAULTNAME; // Since SetInitialValues is called when the persistencehandle sets the "dbengine" property // and the fetchblocksize has not been tested with all databases, it should not be restored when // setting the initial values, instead it is initialized once in the constructor @@ -234,6 +380,42 @@ constructor TBoldSQLDataBaseConfig.create; SetInitialValues; end; +procedure TBoldSQLDataBaseConfig.SetBatchQueryBegin(const Value: string); +begin + if fBatchQueryBegin <> Value then + begin + fBatchQueryBegin := Value; + Change; + end; +end; + +procedure TBoldSQLDataBaseConfig.SetBatchQueryEnd(const Value: string); +begin + if fBatchQueryEnd <> Value then + begin + fBatchQueryEnd := Value; + Change; + end; +end; + +procedure TBoldSQLDataBaseConfig.SetBatchQuerySeparator(const Value: string); +begin + if fBatchQuerySeparator <> Value then + begin + fBatchQuerySeparator := Value; + Change; + end; +end; + +procedure TBoldSQLDataBaseConfig.SetColumnExistsTemplate(const Value: string); +begin + if FColumnExistsTemplate <> Value then + begin + FColumnExistsTemplate := Value; + Change; + end; +end; + procedure TBoldSQLDataBaseConfig.SetColumnTypeForBlob(const Value: string); begin if fColumnTypeForBlob <> Value then @@ -271,6 +453,15 @@ procedure TBoldSQLDataBaseConfig.SetColumnTypeForFloat(const Value: string); end; end; +procedure TBoldSQLDataBaseConfig.SetColumnTypeForGUID(const Value: string); +begin + if FColumnTypeForGUID <> Value then + begin + FColumnTypeForGUID := Value; + Change; + end; +end; + procedure TBoldSQLDataBaseConfig.SetColumnTypeForString(const Value: string); begin if FColumnTypeForString <> Value then @@ -280,6 +471,33 @@ procedure TBoldSQLDataBaseConfig.SetColumnTypeForString(const Value: string); end; end; +procedure TBoldSQLDataBaseConfig.SetColumnTypeForUnicodeString(const Value: string); +begin + if FColumnTypeForUnicodeString <> Value then + begin + FColumnTypeForUnicodeString := Value; + Change; + end; +end; + +procedure TBoldSQLDataBaseConfig.SetColumnTypeForText(const Value: string); +begin + if FColumnTypeForText <> Value then + begin + FColumnTypeForText := Value; + Change; + end; +end; + +procedure TBoldSQLDataBaseConfig.SetColumnTypeForUnicodeText(const Value: string); +begin + if FColumnTypeForUnicodeText <> Value then + begin + FColumnTypeForUnicodeText := Value; + Change; + end; +end; + procedure TBoldSQLDataBaseConfig.SetColumnTypeForTime(const Value: string); begin if fColumnTypeForTime <> Value then @@ -289,6 +507,15 @@ procedure TBoldSQLDataBaseConfig.SetColumnTypeForTime(const Value: string); end; end; +procedure TBoldSQLDataBaseConfig.SetDefaultObjectMapper(const Value: string); +begin + if fDefaultObjectMapper <> Value then + begin + fDefaultObjectMapper := Value; + Change; + end; +end; + procedure TBoldSQLDataBaseConfig.SetDefaultStringLength(const Value: integer); begin if fDefaultStringLength <> Value then @@ -298,6 +525,25 @@ procedure TBoldSQLDataBaseConfig.SetDefaultStringLength(const Value: integer); end; end; +procedure TBoldSQLDataBaseConfig.SetDefaultSystemMapper(const Value: string); +begin + if fDefaultSystemMapper <> Value then + begin + fDefaultSystemMapper := Value; + Change; + end; +end; + +procedure TBoldSQLDataBaseConfig.SetDefaultValueForDateTime( + const Value: string); +begin + if fDefaultValueForDateTime <> Value then + begin + fDefaultValueForDateTime := Value; + Change; + end; +end; + procedure TBoldSQLDataBaseConfig.SetDropColumnTemplate(const Value: string); begin if fDropColumnTemplate <> Value then @@ -334,52 +580,162 @@ procedure TBoldSQLDataBaseConfig.SetFetchBlockSize(const Value: integer); end; end; +function TBoldSQLDataBaseConfig.GetColumnTypeForString(Size: Integer): string; +begin + if ( LongStringLimit = -1) or (Size <= LongStringLimit) then + Result := Format(ColumnTypeForString, [Size]) + else + Result := Format(ColumnTypeForText, [Size]); +end; + +function TBoldSQLDataBaseConfig.GetColumnTypeForUnicodeString( + Size: Integer): string; +begin + if ( LongStringLimit = -1) or (Size <= LongStringLimit) then + Result := Format(ColumnTypeForUnicodeString, [Size]) + else + Result := Format(ColumnTypeForUnicodeText, [Size]); +end; + function TBoldSQLDataBaseConfig.GetDropColumnQuery(const TableName: string; const columnName: String): String; begin - result := DropColumnTemplate; - result := StringReplace(result, TableNameMarker, TableName, [rfIgnoreCase, rfReplaceAll]); - result := StringReplace(result, ColumnNameMarker, ColumnName, [rfIgnoreCase, rfReplaceAll]); + Result := ''; + if DropColumnTemplate <> '' then begin + Result := DropColumnTemplate; + Result := StringReplace(result, TableNameMarker, TableName, [rfIgnoreCase, + rfReplaceAll]); + Result := StringReplace(result, ColumnNameMarker, ColumnName, [rfIgnoreCase, + rfReplaceAll]); + end else begin + raise EBold.Create('Please set the template in the SQLDatabaseConfig ' + + 'for DropColumnTemplate.'); + end; end; function TBoldSQLDataBaseConfig.GetDropIndexQuery(const TableName: string; const IndexName: String): String; begin - result := DropIndexTemplate; - result := StringReplace(result, TableNameMarker, TableName, [rfIgnoreCase, rfReplaceAll]); - result := StringReplace(result, IndexNameMarker, IndexName, [rfIgnoreCase, rfReplaceAll]); + Result := ''; + if DropIndexTemplate <> '' then begin + Result := DropIndexTemplate; + Result := StringReplace(result, TableNameMarker, TableName, [rfIgnoreCase, + rfReplaceAll]); + Result := StringReplace(result, IndexNameMarker, IndexName, [rfIgnoreCase, + rfReplaceAll]); + end else begin + raise EBold.Create('Please set the template in the SQLDatabaseConfig ' + + 'for DropIndexTemplate.'); + end; end; function TBoldSQLDataBaseConfig.GetDropTableQuery(const TableName: String): String; begin - result := DropTableTemplate; - result := StringReplace(result, TableNameMarker, TableName, [rfIgnoreCase, rfReplaceAll]); + Result := ''; + if DropTableTemplate <> '' then begin + Result := DropTableTemplate; + Result := StringReplace(result, TableNameMarker, TableName, [rfIgnoreCase, + rfReplaceAll]); + end else begin + raise EBold.Create('Please set the template in the SQLDatabaseConfig ' + + 'for DropTableTemplate.'); + end; end; +procedure TBoldSQLDataBaseConfig.SetIndexInfoTemplate(const Value: string); +begin + if fIndexInfoTemplate <> Value then + begin + fIndexInfoTemplate := Value; + Change; + end; +end; + +procedure TBoldSQLDataBaseConfig.SetIfTemplate(const Value: string); +begin + if FIfTemplate <> Value then + begin + FIfTemplate := Value; + Change; + end; +end; + +procedure TBoldSQLDataBaseConfig.SetIgnoreMissingObjects(const Value: boolean); +begin + if fIgnoreMissingObjects <> Value then + begin + fIgnoreMissingObjects := Value; + Change; + end; +end; + +procedure TBoldSQLDataBaseConfig.SetIndexColumnExistsTemplate( + const Value: string); +begin + if FIndexColumnExistsTemplate <> Value then + begin + FIndexColumnExistsTemplate := Value; + Change; + end; +end; + +procedure TBoldSQLDataBaseConfig.SetIndexExistsTemplate(const Value: string); +begin + if FIndexExistsTemplate <> Value then + begin + FIndexExistsTemplate := Value; + Change; + end; +end; + procedure TBoldSQLDataBaseConfig.SetInitialValues; begin - FColumnTypeForBlob := 'BLOB'; // do not localize - FColumnTypeForDateTime := 'DATE'; // do not localize - FColumnTypeForDate := 'DATE'; // do not localize - FColumnTypeForTime := 'DATE'; // do not localize - FColumnTypeForFloat := 'DOUBLE PRECISION'; // do not localize - FColumnTypeForCurrency := 'DOUBLE PRECISION'; // do not localize - fColumnTypeForString := 'VARCHAR(%d)'; // do not localize - FColumnTypeForInteger := 'INTEGER'; // do not localize - fColumnTypeForSmallInt := 'SMALLINT'; // do not localize + FDatabaseCaseSensitiveTemplate := ''; // is database specific + FIfTemplate := ''; // is database specific + FColumnExistsTemplate := ''; // is database specific + FTableExistsTemplate := ''; // is database specific + FIndexExistsTemplate := ''; // is database specific + FIndexColumnExistsTemplate := ''; // is database specific + FColumnTypeForBlob := 'BLOB'; + FColumnTypeForDateTime := 'DATE'; + FColumnTypeForDate := 'DATE'; + FColumnTypeForTime := 'DATE'; + fDefaultValueForDateTime := ''; + FColumnTypeForFloat := 'DOUBLE PRECISION'; + FColumnTypeForCurrency := 'DOUBLE PRECISION'; + fColumnTypeForString := 'VARCHAR(%d)'; + fColumnTypeForUnicodeString := 'NVARCHAR(%d)'; // do not localize + fColumnTypeForText := 'VARCHAR(MAX)'; // do not localize + fColumnTypeForUnicodeText := 'NVARCHAR(MAX)'; // do not localize + fLongStringLimit := -1; + FColumnTypeForInteger := 'INTEGER'; + fColumnTypeForSmallInt := 'SMALLINT'; + fColumnTypeForInt64 := 'BIGINT'; // do not localize fDefaultStringLength := 255; fMaxParamsInIdList := 20; fMaxIndexNameLength := 18; fMaxDbIdentifierLength := -1; + fMaxBatchQueryLength := cMaxBatchQueryLength; + fMaxBatchQueryParams := cMaxBatchQueryParams; + fBatchQueryBegin := ''; + fBatchQueryEnd := ''; + fBatchQuerySeparator := ';'; + fUseBatchQueries := false; fFieldTypeForBlob := ftBlob; fStoreEmptyStringsAsNULL := false; - fSystemTablePrefix := 'BOLD'; // do not localize + fSystemTablePrefix := 'BOLD'; fEmptyStringMarker := ''; + fMultiRowInsertLimit := 1; + UseParamsForInteger := false; + UseParamsForEmptyString := false; + fIgnoreMissingObjects := false; fAllowMetadataChangesInTransaction := true; fDBGenerationMode := dbgQuery; - fDropColumnTemplate := 'ALTER TABLE DROP '; // do not localize - fDropTableTemplate := 'DROP TABLE '; // do not localize - fDropIndexTemplate := 'DROP INDEX '; // do not localize - fSQLforNotNull := 'NOT NULL'; // do not localize + fDropColumnTemplate := 'ALTER TABLE DROP '; + fDropTableTemplate := 'DROP TABLE '; + fDropIndexTemplate := 'DROP INDEX '; + fEvolveDropsUnknownIndexes := true; + fSQLforNull := 'NULL'; + fSQLforNotNull := 'NOT NULL'; fSupportsConstraintsInCreateTable := true; FQuoteNonStringDefaultValues := false; fSupportsStringDefaultValues := true; @@ -387,35 +743,90 @@ procedure TBoldSQLDataBaseConfig.SetInitialValues; FSqlScriptStartTransaction := 'START TRANSACTION'; FSqlScriptTerminator := ';'; FSqlScriptCommentStop := ' */'; - FSqlScriptSeparator := '---'; + FSqlScriptSeparator := ''; FSqlScriptRollBackTransaction := 'ROLLBACK'; FSqlScriptCommitTransaction := 'COMMIT'; - fReservedWords.Text := 'ACTIVE, ADD, ALL, AFTER, ALTER'#10'AND, ANY, AS, ASC, ASCENDING,'#10 + // do not localize - 'AT, AUTO, AUTOINC, AVG, BASE_NAME'#10'BEFORE, BEGIN, BETWEEN, BLOB, BOOLEAN,'#10 + // do not localize - 'BOTH, BY, BYTES, CACHE, CAST, CHAR'#10'CHARACTER, CHECK, CHECK_POINT_LENGTH, COLLATE,'#10 + // do not localize - 'COLUMN, COMMIT, COMMITTED, COMPUTED'#10'CONDITIONAL, CONSTRAINT, CONTAINING, COUNT, CREATE, CSTRING,'#10 + // do not localize - 'CURRENT, CURSOR, DATABASE, DATE, DAY'#10'DEBUG, DEC, DECIMAL, DECLARE, DEFAULT,'#10 + // do not localize - 'DELETE, DESC, DESCENDING, DISTINCT, DO'#10'DOMAIN, DOUBLE, DROP, ELSE, END,'#10 + // do not localize - 'ENTRY_POINT, ESCAPE, EXCEPTION, EXECUTE'#10'EXISTS, EXIT, EXTERNAL, EXTRACT, FILE, FILTER,'#10 + // do not localize - 'FLOAT, FOR, FOREIGN, FROM, FULL, FUNCTION'#10'GDSCODE, GENERATOR, GEN_ID, GRANT,'#10 + // do not localize - 'GROUP, GROUP_COMMIT_WAIT_TIME, HAVING'#10'HOUR, IF, IN, INT, INACTIVE, INDEX, INNER,'#10 + // do not localize - 'INPUT_TYPE, INSERT, INTEGER, INTO'#10'IS, ISOLATION, JOIN, KEY, LONG, LENGTH,'#10 + // do not localize - 'LOGFILE, LOWER, LEADING, LEFT, LEVEL'#10'LIKE, LOG_BUFFER_SIZE, MANUAL, MAX, MAXIMUM_SEGMENT,'#10 + // do not localize - 'MERGE, MESSAGE, MIN, MINUTE, MODULE_NAME'#10'MONEY, MONTH, NAMES, NATIONAL, NATURAL,'#10 + // do not localize - 'NCHAR, NO, NOT, NULL, NUM_LOG_BUFFERS'#10'NUMERIC, OF, ON, ONLY, OPTION,'#10 + // do not localize - 'OR, ORDER, OUTER, OUTPUT_TYPE, OVERFLOW'#10'PAGE_SIZE, PAGE, PAGES, PARAMETER, PASSWORD,'#10 + // do not localize - 'PLAN, POSITION, POST_EVENT, PRECISION'#10'PROCEDURE, PROTECTED, PRIMARY, PRIVILEGES, RAW_PARTITIONS, RDB$DB_KEY,'#10 + // do not localize - 'READ, REAL, RECORD_VERSION, REFERENCES'#10'RESERV, RESERVING, RETAIN, RETURNING_VALUES, RETURNS, REVOKE,'#10 + // do not localize - 'RIGHT, ROLE, ROLLBACK, SECOND, SEGMENT'#10'SELECT, SET, SHARED, SHADOW, SCHEMA, SINGULAR,'#10 + // do not localize - 'SIZE, SMALLINT, SNAPSHOT, SOME, SORT'#10'SQLCODE, STABILITY, STARTING, STARTS, STATISTICS,'#10 + // do not localize - 'SUB_TYPE, SUBSTRING, SUM, SUSPEND, TABLE'#10'THEN, TIME, TIMESTAMP, TIMEZONE_HOUR, TIMEZONE_MINUTE,'#10 + // do not localize - 'TO, TRAILING, TRANSACTION, TRIGGER, TRIM'#10'UNCOMMITTED, UNION, UNIQUE, UPDATE, UPPER,'#10 + // do not localize - 'USER, VALUE, VALUES, VARCHAR, VARIABLE'#10'VARYING, VIEW, WAIT, WHEN, WHERE,'#10 + // do not localize - 'WHILE, WITH, WORK, WRITE, YEAR'; // do not localize + fReservedWords.Text := 'ACTIVE, ADD, ALL, AFTER, ALTER'#10'AND, ANY, AS, ASC, ASCENDING,'#10 + + 'AT, AUTO, AUTOINC, AVG, BASE_NAME'#10'BEFORE, BEGIN, BETWEEN, BLOB, BOOLEAN,'#10 + + 'BOTH, BY, BYTES, CACHE, CAST, CHAR'#10'CHARACTER, CHECK, CHECK_POINT_LENGTH, COLLATE,'#10 + + 'COLUMN, COMMIT, COMMITTED, COMPUTED'#10'CONDITIONAL, CONSTRAINT, CONTAINING, COUNT, CREATE, CSTRING,'#10 + + 'CURRENT, CURSOR, DATABASE, DATE, DAY'#10'DEBUG, DEC, DECIMAL, DECLARE, DEFAULT,'#10 + + 'DELETE, DESC, DESCENDING, DISTINCT, DO'#10'DOMAIN, DOUBLE, DROP, ELSE, END,'#10 + + 'ENTRY_POINT, ESCAPE, EXCEPTION, EXECUTE'#10'EXISTS, EXIT, EXTERNAL, EXTRACT, FILE, FILTER,'#10 + + 'FLOAT, FOR, FOREIGN, FROM, FULL, FUNCTION'#10'GDSCODE, GENERATOR, GEN_ID, GRANT,'#10 + + 'GROUP, GROUP_COMMIT_WAIT_TIME, HAVING'#10'HOUR, IF, IN, INT, INACTIVE, INDEX, INNER,'#10 + + 'INPUT_TYPE, INSERT, INTEGER, INTO'#10'IS, ISOLATION, JOIN, KEY, LONG, LENGTH,'#10 + + 'LOGFILE, LOWER, LEADING, LEFT, LEVEL'#10'LIKE, LOG_BUFFER_SIZE, MANUAL, MAX, MAXIMUM_SEGMENT,'#10 + + 'MERGE, MESSAGE, MIN, MINUTE, MODULE_NAME'#10'MONEY, MONTH, NAMES, NATIONAL, NATURAL,'#10 + + 'NCHAR, NO, NOT, NULL, NUM_LOG_BUFFERS'#10'NUMERIC, OF, ON, ONLY, OPTION,'#10 + + 'OR, ORDER, OUTER, OUTPUT_TYPE, OVERFLOW'#10'PAGE_SIZE, PAGE, PAGES, PARAMETER, PASSWORD,'#10 + + 'PLAN, POSITION, POST_EVENT, PRECISION'#10'PROCEDURE, PROTECTED, PRIMARY, PRIVILEGES, RAW_PARTITIONS, RDB$DB_KEY,'#10 + + 'READ, REAL, RECORD_VERSION, REFERENCES'#10'RESERV, RESERVING, RETAIN, RETURNING_VALUES, RETURNS, REVOKE,'#10 + + 'RIGHT, ROLE, ROLLBACK, SECOND, SEGMENT'#10'SELECT, SET, SHARED, SHADOW, SCHEMA, SINGULAR,'#10 + + 'SIZE, SMALLINT, SNAPSHOT, SOME, SORT'#10'SQLCODE, STABILITY, STARTING, STARTS, STATISTICS,'#10 + + 'SUB_TYPE, SUBSTRING, SUM, SUSPEND, TABLE'#10'THEN, TIME, TIMESTAMP, TIMEZONE_HOUR, TIMEZONE_MINUTE,'#10 + + 'TO, TRAILING, TRANSACTION, TRIGGER, TRIM'#10'UNCOMMITTED, UNION, UNIQUE, UPDATE, UPPER,'#10 + + 'USER, VALUE, VALUES, VARCHAR, VARIABLE'#10'VARYING, VIEW, WAIT, WHEN, WHERE,'#10 + + 'WHILE, WITH, WORK, WRITE, YEAR'; Change; end; +procedure TBoldSQLDataBaseConfig.SetLongStringLimit(Value: integer); +begin + if FLongStringLimit <> Value then + begin + FLongStringLimit := Value; + Change; + end; +end; + +procedure TBoldSQLDataBaseConfig.SetSingleIndexOrderedLinks(const Value: boolean); +begin + if fSingleIndexOrderedLinks <> Value then + begin + fSingleIndexOrderedLinks := Value; + Change; + end; +end; + +procedure TBoldSQLDataBaseConfig.SetUseBatchQueries(const Value: boolean); +begin + if fUseBatchQueries <> Value then + begin + fUseBatchQueries := Value; + Change; + end; +end; + +procedure TBoldSQLDataBaseConfig.SetUseParamsForEmptyString( + const Value: boolean); +begin + if fUseParamsForEmptyString <> Value then + begin + fUseParamsForEmptyString := Value; + Change; + end; +end; + +procedure TBoldSQLDataBaseConfig.SetUseParamsForInteger(const Value: boolean); +begin + if fUseParamsForInteger <> Value then + begin + fUseParamsForInteger := Value; + Change; + end; +end; + +procedure TBoldSQLDataBaseConfig.SetMultiRowInsertLimit(const Value: integer); +begin + if fMultiRowInsertLimit <> Value then + begin + fMultiRowInsertLimit := Value; + Change; + end; +end; + procedure TBoldSQLDataBaseConfig.SetUseSQL92Joins(const Value: boolean); begin if fUseSQL92Joins <> Value then @@ -432,76 +843,223 @@ procedure TBoldSQLDataBaseConfig.InitializeDbEngineSettings(Engine: TBoldDatabas ReservedWords.Add(name) end; begin - // if the engine is unknown, we do not alter any settings. if Engine <> dbeUnknown then SetInitialValues; case Engine of + dbePostgres: + begin + fColumnTypeForBlob := 'BYTEA'; // do not localize + fColumnTypeForCurrency := 'NUMERIC'; // do not localize + fColumnTypeForDateTime := 'TIMESTAMP'; // do not localize + fColumnTypeForFloat := 'NUMERIC'; // do not localize + FColumnTypeForTime := 'TIME'; // do not localize + fColumnTypeForGuid := 'UUID'; + fMaxIndexNameLength := 63; + fMaxDbIdentifierLength := 63; + fMultiRowInsertLimit := 1000; +// IndexInfoTemplate := 'select indexname from pg_indexes where tablename = '''''; // this is not complete IndexName, IsPrimary, IsUnique, ColumnName + fReservedWords.Text := 'ALL, ANALYSE, AND, ANY, ARRAY, AS, ASC, ASYMMETRIC, AUTHORIZATION,'#10 + // do not localize + 'BETWEEN, BINARY, BOOLEAN, BOTH, CASE, CAST, CHAR, CHARACTER, CHECK,'#10 + // do not localize + 'CMIN, COALESCE, COLLATE, COLUMN, CONSTRAINT, CONVERT, CREATE, CROSS,'#10 + // do not localize + 'CURRENT_DATE, CURRENT_ROLE, CURRENT_TIME, CURRENT_TIMESTAMP,'#10 + // do not localize + 'CURRENT_USER, DEC, DECIMAL, DEFAULT, DEFERRABLE, SEC, ELSE, END,'#10 + // do not localize + 'EXCEPT, EXISTS, EXTRACT, FALSE, FLOAT, FOR, FOREIGN, FREEZE, FROM,'#10 + // do not localize + 'FULL, GRANT, GREATEST, GROUP, HAVING, ILIKE, IN, INITIALLY, INNER,'#10 + // do not localize + 'INOUT, INT, INTEGER, INTERSECT, INTERVAL, INTO, IS, ISNULL, JOIN,'#10 + // do not localize + 'LEADING, LEAST, LEFT, LIKE, LIMIT, LOCALTIME, LOCALTIMESTAMP,'#10 + // do not localize + 'NATIONAL, NATURAL, NCHAR, NEW, NONE, NOT, NOTNULL, NULL, NULLIF,'#10 + // do not localize + 'NUMERIC, OFF, OFFSET, OLD, ON, ONLY, OR, ORDER, OUT, OUTER, OVERLAPS,'#10 + // do not localize + 'OVERLAY, PLI, POSITION, PRECISION, PRIMARY, REAL, REFERENCES,'#10 + // do not localize + 'RETURNING, RIGHT, ROW, SELECT, SESSION_USER, SETOF, SIMILAR,'#10 + // do not localize + 'SMALLINT, SOME, SUBSTRING, SYMMETRIC, TABLE, THEN, TIME, TIMESTAMP,'#10 + // do not localize + 'TOP_LEVEL_COUNT, TRAILING, TREAT, TRIM, TRUE, UNION, UNIQUE, USER,'#10 + // do not localize + 'USING, VALUES, VARCHAR, VERBOSE, WHEN, WHERE'; // do not localize + + + end; dbeSQLServer: begin - fColumnTypeForDate := 'DATETIME'; // do not localize - fColumnTypeForTime := 'DATETIME'; // do not localize - fColumnTypeForDateTime := 'DATETIME'; // do not localize - fColumnTypeForFloat := 'DECIMAL (28,10)'; // do not localize - fColumnTypeForCurrency := 'DECIMAL (28,10)'; // do not localize - fDropColumnTemplate := 'ALTER TABLE DROP COLUMN '; // do not localize - fDropIndexTemplate := 'DROP INDEX .'; // do not localize + FDatabaseCaseSensitiveTemplate := 'EXECUTE sp_helpsort'; // do not localize + FIfTemplate := 'IF BEGIN END'; // do not localize + FColumnExistsTemplate := 'SELECT * FROM SYS.COLUMNS WHERE UPPER(NAME) = UPPER(N'''') AND OBJECT_ID = OBJECT_ID(UPPER(N''''))'; // do not localize + FTableExistsTemplate := 'SELECT * FROM SYS.TABLES WHERE UPPER(NAME)=UPPER('''')'; // do not localize + FIndexExistsTemplate := 'SELECT NAME FROM SYS.INDEXES WHERE UPPER(NAME)=UPPER('''') AND OBJECT_ID = OBJECT_ID(UPPER(N''''))'; // do not localize + FIndexColumnExistsTemplate := + 'SELECT IND.NAME FROM SYS.INDEXES IND INNER' // do not localize + +' JOIN SYS.INDEX_COLUMNS IC ON IND.OBJECT_ID = IC.OBJECT_ID AND' // do not localize + +' IND.INDEX_ID = IC.INDEX_ID INNER JOIN SYS.COLUMNS COL ON' // do not localize + +' IC.OBJECT_ID = COL.OBJECT_ID AND IC.COLUMN_ID = COL.COLUMN_ID' // do not localize + +' WHERE IND.OBJECT_ID = OBJECT_ID(UPPER(N'''')) AND UPPER(COL.NAME) = UPPER('''')'; // do not localize + fColumnTypeForDate := 'DATETIME'; // do not localize + fColumnTypeForTime := 'DATETIME'; // do not localize + fColumnTypeForDateTime := 'DATETIME'; // do not localize + fColumnTypeForFloat := 'DECIMAL (28,10)'; // do not localize + fColumnTypeForCurrency := 'DECIMAL (28,10)'; // do not localize + fColumnTypeForText := 'VARCHAR(MAX)'; // do not localize + fColumnTypeForUnicodeText := 'NVARCHAR(MAX)'; // do not localize + FColumnTypeForBlob := 'VARBINARY(MAX)'; // do not localize + fColumnTypeForInt64 := 'BIGINT'; // do not localize + fColumnTypeForGuid := 'UNIQUEIDENTIFIER'; // do not localize + fLongStringLimit := 4000; + fMaxBatchQueryLength := 65536 * 1024; // Length of a string containing SQL statements (batch size) 65,536 * Network packet size Default packet size is 4096 bytes + fMaxBatchQueryParams := 2000; + fMultiRowInsertLimit := 1000; + fDropColumnTemplate := + 'DECLARE @CONSTRAINTNAME NVARCHAR(200)' // do not localize + +' SELECT @CONSTRAINTNAME=OD.NAME' // do not localize + +' FROM SYSOBJECTS OT, SYSCOLUMNS C, SYSOBJECTS OD' // do not localize + +' WHERE UPPER(OT.NAME) = UPPER('''')' // do not localize + +' AND OT.ID = C.ID' // do not localize + +' AND UPPER(C.NAME) = UPPER('''')' // do not localize + +' AND C.CDEFAULT = OD.ID' // do not localize + +' IF @CONSTRAINTNAME IS NOT NULL' // do not localize + +' EXEC(''ALTER TABLE DROP CONSTRAINT '' + @CONSTRAINTNAME)' // do not localize + +' IF EXISTS (SELECT * FROM SYSCOLUMNS WHERE ID=OBJECT_ID('''') AND UPPER(NAME)=UPPER(''''))' // do not localize + +' EXEC(''ALTER TABLE DROP COLUMN '')'; // do not localize + fDropIndexTemplate := 'DROP INDEX .'; // do not localize + fIndexInfoTemplate:= + 'SELECT IND.NAME INDEXNAME, IND.IS_PRIMARY_KEY ISPRIMARY, IND.IS_UNIQUE ISUNIQUE, COL.NAME COLUMNNAME FROM' // do not localize + +' SYS.INDEXES IND INNER JOIN SYS.INDEX_COLUMNS IC ON IND.OBJECT_ID = IC.OBJECT_ID AND IND.INDEX_ID = IC.INDEX_ID' // do not localize + +' INNER JOIN SYS.COLUMNS COL ON IC.OBJECT_ID = COL.OBJECT_ID AND IC.COLUMN_ID = COL.COLUMN_ID' // do not localize + +' WHERE UPPER(OBJECT_NAME(IND.OBJECT_ID))=UPPER('''')' // do not localize + +' ORDER BY INDEXNAME, INDEX_COLUMN_ID'; // do not localize end; dbeGenericANSISQL92: begin - fColumnTypeForDate := 'DATE'; // do not localize - fColumnTypeForTime := 'TIME'; // do not localize - fColumnTypeForDateTime := 'TIMESTAMP'; // do not localize + fColumnTypeForDate := 'DATE'; + fColumnTypeForTime := 'TIME'; + fColumnTypeForDateTime := 'TIMESTAMP'; end; dbeInterbaseSQLDialect3: begin - fColumnTypeForDate := 'TIMESTAMP'; // do not localize - fColumnTypeForTime := 'TIMESTAMP'; // do not localize - fColumnTypeForDateTime := 'TIMESTAMP'; // do not localize + fColumnTypeForDate := 'TIMESTAMP'; // do not localize + fColumnTypeForTime := 'TIMESTAMP'; // do not localize + fColumnTypeForDateTime := 'TIMESTAMP'; // do not localize fMaxIndexNameLength := 31; fMaxDbIdentifierLength := 31; fAllowMetadataChangesInTransaction := true; + fColumnTypeForInt64:='INT64'; // do not localize + fColumnTypeForText:='VARCHAR(32765)'; // do not localize + fColumnTypeForUnicodeString:='VARCHAR(%d) CHARACTER SET UNICODE'; // do not localize + fColumnTypeForUnicodeText:='VARCHAR(4000) CHARACTER SET UNICODE'; // do not localize + fIfTemplate:='EXECUTE BLOCK AS BEGIN IF () THEN EXECUTE STATEMENT ''''; END'; // do not localize + fIndexColumnExistsTemplate:= + 'SELECT IX.RDB$INDEX_NAME AS Name FROM RDB$INDICES IX, RDB$INDEX_SEGMENTS SG WHERE IX.RDB$INDEX_NAME = SG.RDB$INDEX_NAME AND ' // do not localize + +' UPPER(SG.RDB$FIELD_NAME)=UPPER('''') AND UPPER(IX.RDB$RELATION_NAME)=UPPER('''')'; // do not localize + fIndexExistsTemplate:= + 'SELECT * FROM RDB$INDICES WHERE UPPER(RDB$INDEX_NAME) = UPPER('''')'; // do not localize + fTableExistsTemplate:= + 'SELECT * FROM RDB$RELATIONS WHERE UPPER(RDB$RELATION_NAME) = UPPER('''')'; // do not localize + fColumnExistsTemplate:= + 'SELECT * FROM RDB$RELATION_FIELDS WHERE UPPER(RDB$RELATION_NAME)=' // do not localize + +'UPPER('''') AND UPPER(RDB$FIELD_NAME)=UPPER('''')'; // do not localize + fIndexInfoTemplate := 'select ix.rdb$index_name INDEXNAME, sg.rdb$field_name COLUMNNAME,' + // do not localize + 'case (ix.rdb$unique_flag) when 1 then ''T'' else ''F'' end isunique,' + + 'case(rc.rdb$constraint_type) when ''PRIMARY KEY'' then ''T'' else ''F'' end isprimary ' + + 'from rdb$indices ix ' + + 'left join rdb$relation_constraints rc on rc.rdb$index_name = ix.rdb$index_name ' + + 'left join rdb$index_segments sg on ix.rdb$index_name = sg.rdb$index_name where Upper(ix.rdb$relation_name)=Upper('''') '+ + 'order by ix.rdb$index_name, sg.rdb$field_position'; + ; + end; dbeInterbaseSQLDialect1: begin fMaxIndexNameLength := 31; fMaxDbIdentifierLength := 31; fAllowMetadataChangesInTransaction := true; + fColumnTypeForInt64:='INT64'; // do not localize + fColumnTypeForText:='VARCHAR(32765)'; // do not localize + fColumnTypeForUnicodeString:='VARCHAR(%d) CHARACTER SET UNICODE'; // do not localize + fColumnTypeForUnicodeText:='VARCHAR(4000) CHARACTER SET UNICODE'; // do not localize + fIfTemplate:='EXECUTE BLOCK AS BEGIN IF () THEN EXECUTE STATEMENT ''''; END'; // do not localize + fIndexColumnExistsTemplate:= + 'SELECT IX.RDB$INDEX_NAME AS Name FROM RDB$INDICES IX, RDB$INDEX_SEGMENTS SG WHERE IX.RDB$INDEX_NAME = SG.RDB$INDEX_NAME AND ' // do not localize + +' UPPER(SG.RDB$FIELD_NAME)=UPPER('''') AND UPPER(IX.RDB$RELATION_NAME)=UPPER('''')'; // do not localize + fIndexExistsTemplate:= + 'SELECT * FROM RDB$INDICES WHERE UPPER(RDB$INDEX_NAME) = UPPER('''')'; // do not localize + fTableExistsTemplate:= + 'SELECT * FROM RDB$RELATIONS WHERE UPPER(RDB$RELATION_NAME) = UPPER('''')'; // do not localize + fColumnExistsTemplate:= + 'SELECT * FROM RDB$RELATION_FIELDS WHERE UPPER(RDB$RELATION_NAME)=' // do not localize + +'UPPER('''') AND UPPER(RDB$FIELD_NAME)=UPPER('''')'; // do not localize + fIndexInfoTemplate := 'select ix.rdb$index_name INDEXNAME, sg.rdb$field_name COLUMNNAME,' + // do not localize + 'case (ix.rdb$unique_flag) when 1 then ''T'' else ''F'' end isunique,' + + 'case(rc.rdb$constraint_type) when ''PRIMARY KEY'' then ''T'' else ''F'' end isprimary ' + + 'from rdb$indices ix ' + + 'left join rdb$relation_constraints rc on rc.rdb$index_name = ix.rdb$index_name ' + + 'left join rdb$index_segments sg on ix.rdb$index_name = sg.rdb$index_name where Upper(ix.rdb$relation_name)=Upper('''') '+ + 'order by ix.rdb$index_name, sg.rdb$field_position'; end; dbeDBISAM: begin - fColumnTypeForDate := 'DATE'; // do not localize - fColumnTypeForTime := 'TIME'; // do not localize - fColumnTypeForDateTime := 'TIMESTAMP'; // do not localize - fColumnTypeForFloat := 'FLOAT'; // do not localize - fColumnTypeForCurrency := 'FLOAT'; // do not localize + fColumnTypeForDate := 'DATE'; + fColumnTypeForTime := 'TIME'; + fColumnTypeForDateTime := 'TIMESTAMP'; + fColumnTypeForFloat := 'FLOAT'; + fColumnTypeForCurrency := 'FLOAT'; fDefaultStringLength := 250; - AddReservedWord('Description'); // do not localize + AddReservedWord('Description'); end; dbeAdvantage: begin - fSQLforNotNull := 'CONSTRAINT NOT NULL'; // do not localize - fColumnTypeForSmallInt := 'SHORT'; // do not localize - fColumnTypeForFloat := 'NUMERIC'; // do not localize - fColumnTypeForCurrency := 'NUMERIC'; // do not localize + fSQLforNotNull := 'CONSTRAINT NOT NULL'; + fColumnTypeForSmallInt := 'SHORT'; + fColumnTypeForFloat := 'NUMERIC'; + fColumnTypeForCurrency := 'NUMERIC'; fSupportsConstraintsInCreateTable := false; fQuoteNonStringDefaultValues := true; fSupportsStringDefaultValues := false; - fColumnTypeForDate := 'DATE'; // do not localize - fColumnTypeForTime := 'TIME'; // do not localize - fColumnTypeForDateTime := 'TIMESTAMP'; // do not localize - fColumnTypeForString := 'CHAR(%d)'; // do not localize + fColumnTypeForDate := 'DATE'; + fColumnTypeForTime := 'TIME'; + fColumnTypeForDateTime := 'TIMESTAMP'; + fColumnTypeForString := 'CHAR(%d)'; fStoreEmptyStringsAsNULL := True; end; dbeOracle: begin - FColumnTypeForString := 'VARCHAR2(%d)'; // do not localize - FColumnTypeForFloat := 'NUMBER'; // do not localize - FColumnTypeForCurrency := 'NUMBER'; // do not localize - FColumnTypeForInteger := 'NUMBER(10,0)'; // do not localize - fColumnTypeForSmallInt := 'NUMBER(5,0)'; // do not localize - fDropColumnTemplate := 'ALTER TABLE DROP COLUMN '; // do not localize + FColumnTypeForString := 'VARCHAR2(%d)'; // do not localize + FColumnTypeForFloat := 'NUMBER'; // do not localize + FColumnTypeForCurrency := 'NUMBER(10,2)'; // do not localize + fColumnTypeForText:='CLOB'; // do not localize + fColumnTypeForUnicodeString:='NVARCHAR2(%d)'; // do not localize + fColumnTypeForUnicodeText:='CLOB'; // do not localize fMaxIndexNameLength := 30; fMaxDbIdentifierLength := 30; + fSupportsStringDefaultValues:=False; + fIfTemplate:= + 'DECLARE V_COUNT INTEGER; BEGIN SELECT CASE WHEN () THEN 1 ELSE 0 END CASE1 INTO V_COUNT FROM DUAL;' // do not localize + +' IF (V_COUNT=1) THEN EXECUTE IMMEDIATE ''''; END IF;END;'; // do not localize + fIndexColumnExistsTemplate:= + 'SELECT INDEX_NAME AS NAME FROM USER_IND_COLUMNS WHERE UPPER(COLUMN_NAME)=UPPER('''')' // do not localize + +' AND UPPER(TABLE_NAME)=UPPER('''')'; // do not localize + fIndexExistsTemplate:= + 'SELECT * FROM USER_INDEXES WHERE UPPER(INDEX_NAME) = UPPER('''') AND GENERATED = ''N'''; // do not localize + fTableExistsTemplate:= + 'SELECT * FROM USER_TABLES WHERE UPPER(TABLE_NAME) = UPPER('''')'; // do not localize + fColumnExistsTemplate:= + 'SELECT * FROM USER_TAB_COLUMNS WHERE UPPER(TABLE_NAME) = UPPER('''')' // do not localize + +' AND UPPER(COLUMN_NAME) = UPPER('''')'; // do not localize + fIndexInfoTemplate:= + 'SELECT AIC.INDEX_NAME AS IndexName,' // do not localize + +' CASE ALC.CONSTRAINT_TYPE' // do not localize + +' WHEN ''P'' THEN ''T''' // do not localize + +' ELSE ''F''' // do not localize + +' END AS IsPrimary,' // do not localize + +' CASE ALC.CONSTRAINT_TYPE' // do not localize + +' WHEN ''U'' THEN ''T''' // do not localize + +' WHEN ''P'' THEN ''T''' // do not localize + +' ELSE ''F''' // do not localize + +' END AS IsUnique,' // do not localize + +' AIC.COLUMN_NAME AS ColumnName' // do not localize + +' FROM USER_IND_COLUMNS AIC' // do not localize + +' LEFT JOIN USER_CONSTRAINTS ALC ON AIC.INDEX_NAME = ALC.CONSTRAINT_NAME' // do not localize + +' AND AIC.TABLE_NAME = ALC.TABLE_NAME' // do not localize + +' WHERE UPPER(AIC.TABLE_NAME) = UPPER('''')' // do not localize + +' ORDER BY IndexName, Column_Position'; // do not localize + fDropColumnTemplate := 'ALTER TABLE DROP COLUMN '; // do not localize + fBatchQueryBegin := 'BEGIN'; + fBatchQueryEnd := 'END;'; end; dbeParadox: begin @@ -511,11 +1069,11 @@ procedure TBoldSQLDataBaseConfig.InitializeDbEngineSettings(Engine: TBoldDatabas begin fMaxIndexNameLength := 18; fMaxDbIdentifierLength := 18; - fColumnTypeForCurrency := 'MONEY'; // do not localize - fColumnTypeForFloat := 'NUMERIC'; // do not localize - fColumnTypeForDate := 'DATETIME YEAR TO DAY'; // do not localize - fColumnTypeForTime := 'DATETIME HOUR TO FRACTION'; // do not localize - fColumnTypeForDateTime := 'DATETIME YEAR TO FRACTION'; // do not localize + fColumnTypeForCurrency := 'MONEY'; + fColumnTypeForFloat := 'NUMERIC'; + fColumnTypeForDate := 'DATETIME YEAR TO DAY'; + fColumnTypeForTime := 'DATETIME HOUR TO FRACTION'; + fColumnTypeForDateTime := 'DATETIME YEAR TO FRACTION'; end; end; Change; @@ -536,6 +1094,15 @@ procedure TBoldSQLDataBaseConfig.SetSQLforNotNull(const Value: string); end; end; +procedure TBoldSQLDataBaseConfig.SetSQLforNull(const Value: string); +begin + if FColumnTypeForInteger <> Value then + begin + fSQLforNull := Value; + Change; + end; +end; + procedure TBoldSQLDataBaseConfig.SetColumnTypeForInteger(const Value: string); begin if FColumnTypeForInteger <> Value then @@ -553,6 +1120,14 @@ function TBoldSQLDataBaseConfig.GetEffectiveSQLForNotNull: string; result := SQLforNotNull; end; + +function TBoldSQLDataBaseConfig.GetIndexInfoQuery( + const TableName: String): String; +begin + result := IndexInfoTemplate; + result := StringReplace(result, '', TableName, [rfIgnoreCase, rfReplaceAll]); +end; + procedure TBoldSQLDataBaseConfig.SetColumnTypeForSmallInt(const Value: string); begin if FColumnTypeForSmallInt <> Value then @@ -562,6 +1137,14 @@ procedure TBoldSQLDataBaseConfig.SetColumnTypeForSmallInt(const Value: string); end; end; +procedure TBoldSQLDataBaseConfig.SetColumnTypeForInt64(const Value: string); +begin + if fColumnTypeForInt64 <> Value then begin + fColumnTypeForInt64 := Value; + Change; + end; +end; + procedure TBoldSQLDataBaseConfig.SetSupportsConstraintsInCreateTable(const Value: Boolean); begin if fSupportsConstraintsInCreateTable <> Value then @@ -571,6 +1154,16 @@ procedure TBoldSQLDataBaseConfig.SetSupportsConstraintsInCreateTable(const Value end; end; +procedure TBoldSQLDataBaseConfig.SetQuoteLeftBracketInLike( + const Value: Boolean); +begin + if fQuoteLeftBracketInLike <> Value then + begin + fQuoteLeftBracketInLike := Value; + Change; + end; +end; + procedure TBoldSQLDataBaseConfig.SetQuoteNonStringDefaultValues(const Value: Boolean); begin if fQuoteNonStringDefaultValues <> Value then @@ -635,6 +1228,24 @@ procedure TBoldSQLDataBaseConfig.SetMaxIndexNameLenght(const Value: integer); end; end; +procedure TBoldSQLDataBaseConfig.SetMaxBatchQueryLength(const Value: integer); +begin + if fMaxBatchQueryLength <> Value then + begin + fMaxBatchQueryLength := Value; + Change; + end; +end; + +procedure TBoldSQLDataBaseConfig.SetMaxBatchQueryParams(const Value: integer); +begin + if fMaxBatchQueryParams <> Value then + begin + fMaxBatchQueryParams := Value; + Change; + end; +end; + procedure TBoldSQLDataBaseConfig.SetMaxDbIdentifierLength(const Value: integer); begin if fMaxDbIdentifierLength <> Value then @@ -665,7 +1276,89 @@ procedure TBoldSQLDataBaseConfig.setAllowMetadataChangesInTransaction(const Valu procedure TBoldSQLDataBaseConfig.DefineProperties(Filer: TFiler); begin inherited DefineProperties(Filer); - Filer.DefineProperty('UseTransactionsDuringDBCreate', ReadUseTransactionsDuringDBCreate, nil, True); // do not localize + Filer.DefineProperty('UseTransactionsDuringDBCreate', ReadUseTransactionsDuringDBCreate, nil, True); +end; + +function TBoldSQLDataBaseConfig.GetColumnExistsQuery(const TableName, + ColumnName: string): string; +begin + Result := ''; + if ColumnExistsTemplate <> '' then begin + Result := ColumnExistsTemplate; + Result := StringReplace(Result, TableNameMarker, TableName, [rfIgnoreCase, + rfReplaceAll]); + Result := StringReplace(Result, ColumnNameMarker, ColumnName, [rfIgnoreCase, + rfReplaceAll]); + end else begin + raise EBold.Create('Please set the template in the SQLDatabaseConfig ' + + 'for ColumnExistsTemplate.'); + end; +end; + +function TBoldSQLDataBaseConfig.GetIfColumnNotExistsQuery(const TableName, + ColumnName, SQLStatement: string): string; +var + sCondition: string; +begin + Result := ''; + if (ColumnExistsTemplate <> '') and (IfTemplate <> '') then begin + sCondition := GetColumnExistsQuery(TableName, ColumnName); + sCondition := Format('NOT EXISTS(%s)', [sCondition]); + Result := IfTemplate; + Result := StringReplace(Result, ConditionMarker, sCondition, [rfReplaceAll, + rfIgnoreCase]); + Result := StringReplace(Result, SQLStatementMarker, SQLStatement, + [rfReplaceAll, rfIgnoreCase]); + end else begin + raise EBold.Create('Please set the templates in the SQLDatabaseConfig ' + + 'for IfTemplate and ColumnExistsTemplate.'); + end; +end; + +function TBoldSQLDataBaseConfig.GetIndexColumnExistsQuery(const TableName, + IndexColumnName: string): string; +begin + Result := ''; + if IndexColumnExistsTemplate <> '' then begin + Result := IndexColumnExistsTemplate; + Result := StringReplace(Result, TableNameMarker, TableName, [rfIgnoreCase, + rfReplaceAll]); + Result := StringReplace(Result, IndexColumnNameMarker, IndexColumnName, + [rfIgnoreCase, rfReplaceAll]); + end else begin + raise EBold.Create('Please set the template in the SQLDatabaseConfig ' + + 'for IndexColumnExistsTemplate.'); + end; +end; + +function TBoldSQLDataBaseConfig.GetIndexExistsQuery(const TableName, IndexName: + string): string; +begin + Result := ''; + if IndexExistsTemplate <> '' then begin + Result := IndexExistsTemplate; + Result := StringReplace(Result, TableNameMarker, TableName, [rfIgnoreCase, + rfReplaceAll]); + Result := StringReplace(Result, IndexNameMarker, IndexName, [rfIgnoreCase, + rfReplaceAll]); + end else begin + raise EBold.Create('Please set the template in the SQLDatabaseConfig ' + + 'for IndexExistsTemplate.'); + end; +end; + +function TBoldSQLDataBaseConfig.GetTableExistsQuery(const TableName: string): + string; +begin + Result := ''; + if TableExistsTemplate <> '' then begin + Result := TableExistsTemplate; + Result := StringReplace(Result, TableNameMarker, TableName, [rfIgnoreCase, + rfReplaceAll]); + end else begin + raise EBold.Create('Please set the template in the SQLDatabaseConfig ' + + 'for TableExistsTemplate.'); + end; end; procedure TBoldSQLDataBaseConfig.ReadUseTransactionsDuringDBCreate(Reader: TReader); @@ -673,6 +1366,15 @@ procedure TBoldSQLDataBaseConfig.ReadUseTransactionsDuringDBCreate(Reader: TRead AllowMetadataChangesInTransaction := Reader.ReadBoolean; end; +procedure TBoldSQLDataBaseConfig.SetDatabaseCaseSensitiveTemplate(const Value: + string); +begin + if FDatabaseCaseSensitiveTemplate <> Value then begin + FDatabaseCaseSensitiveTemplate := Value; + Change; + end; +end; + procedure TBoldSQLDataBaseConfig.SetFieldTypeForBlob(const Value: TFieldType); begin if fFieldTypeForBlob <> Value then @@ -691,6 +1393,15 @@ procedure TBoldSQLDataBaseConfig.SetEmptyStringMarker(const Value: String); end; end; +procedure TBoldSQLDataBaseConfig.SetEvolveDropsUnknownIndexes(const Value: boolean); +begin + if fEvolveDropsUnknownIndexes <> Value then + begin + fEvolveDropsUnknownIndexes := Value; + Change; + end; +end; + procedure TBoldSQLDataBaseConfig.SetStoreEmptyStringsAsNULL(const Value: Boolean); begin if fStoreEmptyStringsAsNULL <> Value then @@ -700,12 +1411,13 @@ procedure TBoldSQLDataBaseConfig.SetStoreEmptyStringsAsNULL(const Value: Boolean end; end; + procedure TBoldSQLDataBaseConfig.SetSystemTablePrefix(const Value: String); var Temp: String; begin if Value = '' then - temp := 'BOLD' // do not localize + temp := 'BOLD' else temp := Value; if fSystemTablePrefix <> temp then @@ -715,6 +1427,15 @@ procedure TBoldSQLDataBaseConfig.SetSystemTablePrefix(const Value: String); end; end; +procedure TBoldSQLDataBaseConfig.SetTableExistsTemplate(const Value: string); +begin + if FTableExistsTemplate <> Value then + begin + FTableExistsTemplate := Value; + Change; + end; +end; + procedure TBoldSQLDataBaseConfig.SetSqlScriptCommentStart( const Value: string); begin @@ -764,4 +1485,5 @@ procedure TBoldSQLDataBaseConfig.SetSqlScriptRollBackTransaction( Change; end; +initialization end. diff --git a/Source/PMapper/SQL/BoldSQLMappingInfo.pas b/Source/PMapper/SQL/BoldSQLMappingInfo.pas index 0b3e230..9b0699c 100644 --- a/Source/PMapper/SQL/BoldSQLMappingInfo.pas +++ b/Source/PMapper/SQL/BoldSQLMappingInfo.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldSQLMappingInfo; interface @@ -24,19 +27,25 @@ TBoldClassMappingInfo = class(TBoldMemoryManagedObject) TBoldMemberMappingInfo = class(TBoldClassMappingInfo) private + FColumnIndex: Boolean; fMemberName: String; fTableName: string; fColumns: string; fMapperName: string; function GetColumnByIndex(Index: integer): string; + function GetColumnCount: integer; public - constructor create(const ClassExpressionName, MemberName, TableName, Columns, MapperName: string); + constructor create(const ClassExpressionName, MemberName, TableName, Columns, + MapperName: string; const ColumnIndex: Boolean); function CompareMapping(Mapping: TBoldMemberMappingInfo): Boolean; + function CompareType(Mapping: TBoldMemberMappingInfo): Boolean; property MemberName: String read fMemberName; property TableName: string read fTableName; property MapperName: string read fMapperName; property Columns: string read fColumns; property ColumnByIndex[Index: integer]: string read GetColumnByIndex; + property ColumnIndex: Boolean read FColumnIndex; + property ColumnCount: integer read GetColumnCount; end; TBoldDbTypeMappingInfo = class(TBoldClassMappingInfo) @@ -75,7 +84,7 @@ TBoldObjectStorageMappingInfo = class(TBoldClassMappingInfo) TBoldMemberMappingList = class(TBoldIndexableList) private function GetMappingsByExpressionNames(const ClassExpressionName, MemberName: string): TBoldMemberMappingArray; - function GetItems(index: integer): TBoldMemberMappingInfo; + function GetItems(index: integer): TBoldMemberMappingInfo; {$IFDEF BOLD_INLINE}inline;{$ENDIF} public constructor Create; procedure FillFromList(SourceList: TBoldMemberMappingList); @@ -88,27 +97,27 @@ TBoldClassMappingList = class(TBoldIndexableList) function GetMappingsForClassName(const ClassExpressionName: string): TBoldClassMappingArray; public constructor Create; - procedure AddMapping(Mapping: TBoldClassMappingInfo); + procedure AddMapping(Mapping: TBoldClassMappingInfo); {$IFDEF BOLD_INLINE}inline;{$ENDIF} property MappingsForClassName[const ClassExpressionName: string]: TBoldClassMappingArray read GetMappingsForClassName; end; TBoldAllInstancesMappingList = class(TBoldClassMappingList) private - function GetItems(index: integer): TBoldAllInstancesMappingInfo; + function GetItems(index: integer): TBoldAllInstancesMappingInfo; {$IFDEF BOLD_INLINE}inline;{$ENDIF} public property items[index: integer]: TBoldAllInstancesMappingInfo read GetItems; default; end; TBoldObjectStorageMappingList = class(TBoldClassMappingList) private - function GetItems(index: integer): TBoldObjectStorageMappingInfo; + function GetItems(index: integer): TBoldObjectStorageMappingInfo; {$IFDEF BOLD_INLINE}inline;{$ENDIF} public property items[index: integer]: TBoldObjectStorageMappingInfo read GetItems; default; end; TBoldDbTypeMappingList = class(TBoldClassMappingList) private - function GetItems(index: integer): TBoldDbTypeMappingInfo; + function GetItems(index: integer): TBoldDbTypeMappingInfo; {$IFDEF BOLD_INLINE}inline;{$ENDIF} public property items[index: integer]: TBoldDbTypeMappingInfo read GetItems; default; end; @@ -129,6 +138,7 @@ TBoldSQLMappingInfo = class fAllInstancesMapping: TBoldAllInstancesMappingList; fObjectStorageMapping: TBoldObjectStorageMappingList; fDbTypeMapping: TBoldDbTypeMappingList; + FCurrentDatabase: IBoldDataBase; property MemberMappingInfo[index: integer]: TBoldMemberMappingInfo read GetMemberMappingInfo; property AllInstancesMappingInfo[index: integer]: TBoldAllInstancesMappingInfo read GetAllInstancesMappingInfo; property ObjectStorageMappingInfo[index: integer]: TBoldObjectStorageMappingInfo read GetObjectStorageMappingInfo; @@ -140,9 +150,11 @@ TBoldSQLMappingInfo = class destructor Destroy; override; procedure ReadDataFromDB(DataBase: IBoldDataBase; ReadDbTypeFromDB, ReadMappingFromDB: Boolean); virtual; abstract; procedure WriteDataToDB(DataBase: IBoldDataBase); - procedure ScriptForWriteData(Script: TStrings; Separator: string = ''; ClearFirst: Boolean = true; terminator: string = ''); virtual; abstract; + procedure ScriptForWriteData(DataBase: IBoldDataBase; Script: TStrings; ClearFirst: Boolean; + Separator: String; Terminator: String); virtual; abstract; function CloneWithoutDbType: TBoldSQLMappingInfo; - procedure AddMemberMapping(const ClassExpressionName, MemberName, TableName, ColumnNames, MapperName: String); + procedure AddMemberMapping(const ClassExpressionName, MemberName, TableName, + ColumnNames, MapperName: String; const ColumnIndex: Boolean); procedure AddAllInstancesMapping(const ClassExpressionName, TableName: String; ClassIdRequired: Boolean); procedure AddObjectStorageMapping(const ClassExpressionName, TableName: String); Procedure AddTypeIdMapping(const ClassExpressionName: String; DbType: TBoldDbType); @@ -165,27 +177,52 @@ implementation uses BoldIndex, BoldLogHandler, + StrUtils, SysUtils, BoldUtils, - BoldPMConsts, - BoldHashIndexes; + BoldHashIndexes, + BoldPMapperLists, + Boldrev; type + TBoldClassMappingIndex = class(TBoldStringHashIndex) protected - function ItemAsKeyString(Item: TObject): string; override; + function ItemASKeyString(Item: TObject): string; override; end; TBoldMemberMappingIndex = class(TBoldStringHashIndex) protected - function ItemAsKeyString(Item: TObject): string; override; - function KeyStringForExpressionNames(const ClassExpressionName, MemberName: string): string; + function ItemASKeyString(Item: TObject): string; override; + function KeyStringForExpressionNames(const ClassExpressionName, MemberName: string): string; {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure FindAllByExpressionNames(const ClassExpressionName, MemberName: string; aList: TList); end; var IX_ClassExpressionNameIndex: integer = -1; IX_ClassAndMemberExpressionNameIndex: integer = -1; + +{ TBoldAllInstancesMappingList } + +function TBoldAllInstancesMappingList.GetItems(index: integer): TBoldAllInstancesMappingInfo; +begin + result := (inherited items[index]) as TBoldAllInstancesMappingInfo; +end; + +{ TBoldObjectStorageMappingList } + +function TBoldObjectStorageMappingList.GetItems(index: integer): TBoldObjectStorageMappingInfo; +begin + result := (inherited items[index]) as TBoldObjectStorageMappingInfo; +end; + +{ TBoldDbTypeMappingList } + +function TBoldDbTypeMappingList.GetItems(index: integer): TBoldDbTypeMappingInfo; +begin + result := (inherited items[index]) as TBoldDbTypeMappingInfo; +end; + { TBoldDBMappingInfo } procedure TBoldSQLMappingInfo.AddAllInstancesMapping(const ClassExpressionName, TableName: String; ClassIdRequired: Boolean); @@ -203,7 +240,9 @@ procedure TBoldSQLMappingInfo.AddAllInstancesMapping(const ClassExpressionName, fAllInstancesMapping.Add(TBoldAllInstancesMappingInfo.Create(ClassExpressionName, TableName, ClassIdRequired)); end; -procedure TBoldSQLMappingInfo.AddMemberMapping(const ClassExpressionName, MemberName, TableName, ColumnNames, MapperName: String); +procedure TBoldSQLMappingInfo.AddMemberMapping(const ClassExpressionName, + MemberName, TableName, ColumnNames, MapperName: String; const ColumnIndex: + Boolean); var OldMappings: TBoldMemberMappingArray; i: integer; @@ -215,7 +254,8 @@ procedure TBoldSQLMappingInfo.AddMemberMapping(const ClassExpressionName, Member begin exit; end; - fMemberMapping.Add(TBoldMemberMappingInfo.Create(ClassExpressionName, MemberName, TableName, ColumnNames, MapperName)); + fMemberMapping.Add(TBoldMemberMappingInfo.Create(ClassExpressionName, + MemberName, TableName, ColumnNames, MapperName, ColumnIndex)); end; procedure TBoldSQLMappingInfo.AddObjectStorageMapping(const ClassExpressionName, TableName: String); @@ -303,18 +343,44 @@ function TBoldSQLMappingInfo.GetObjectStorageMappingInfo( function TBoldMemberMappingInfo.CompareMapping(Mapping: TBoldMemberMappingInfo): Boolean; begin - result := - SameText(TableName, Mapping.TableName) and - SameText(Columns, Mapping.Columns); + Result := (SameText(TableName, Mapping.TableName) and SameText(Columns, Mapping.Columns)) and CompareType(Mapping); +end; + +function TBoldMemberMappingInfo.CompareType( + Mapping: TBoldMemberMappingInfo): Boolean; +const + CompatibleDateTypes: array [0..2] of string = ('TBoldPMDateTime', 'TBoldPMDate', 'TBoldPMTime'); + CompatibleStringTypes: array [0..1] of string = ('TBoldPMString', 'TBoldPMAnsiString'); +begin + Result := (MapperName = Mapping.MapperName); + if not Result then begin + // This is hardcoded case that should consider Date and DateTime as compatible. + // The generic way to do this properly would be to compare the actual ColumnTypes that are specified in TBoldSQLDataBaseConfig + // But the sql config is hard to reach from here... + Result := ((AnsiIndexText(MapperName, CompatibleDateTypes) <> -1) and + (AnsiIndexText(Mapping.MapperName, CompatibleDateTypes) <> -1)); + end; + if not Result then begin + // Same for String/AnsiString + Result := ((AnsiIndexText(MapperName, CompatibleStringTypes) <> -1) and + (AnsiIndexText(Mapping.MapperName, CompatibleStringTypes) <> -1)); + end; + if not Result then +// If new mapper inherits from old mapper we assume they are compatible + Result := BoldMemberPersistenceMappers.DescriptorByDelphiName[MapperName].MemberPersistenceMapperClass.InheritsFrom( + BoldMemberPersistenceMappers.DescriptorByDelphiName[Mapping.MapperName].MemberPersistenceMapperClass); end; -constructor TBoldMemberMappingInfo.create(const ClassExpressionName, MemberName, TableName, Columns, MapperName: string); +constructor TBoldMemberMappingInfo.create(const ClassExpressionName, + MemberName, TableName, Columns, MapperName: string; const ColumnIndex: + Boolean); begin inherited create(ClassExpressionName); fMemberName := MemberName; fTableName := TableName; fColumns := Columns; fMapperName := MapperName; + FColumnIndex := ColumnIndex; end; function TBoldMemberMappingInfo.GetColumnByIndex(Index: integer): string; @@ -330,6 +396,19 @@ function TBoldMemberMappingInfo.GetColumnByIndex(Index: integer): string; end; end; +function TBoldMemberMappingInfo.GetColumnCount: integer; +var + s: TStringList; +begin + s := TStringList.Create; + try + s.CommaText := Columns; + result := s.Count; + finally + s.free; + end; +end; + { TBoldAllInstancesMappingInfo } function TBoldAllInstancesMappingInfo.CompareMapping(Mapping: TBoldAllInstancesMappingInfo): Boolean; @@ -410,7 +489,8 @@ procedure TBoldMemberMappingList.FillFromList( SourceList[i].MemberName, SourceList[i].TableName, SourceList[i].Columns, - Sourcelist[i].MapperName)); + Sourcelist[i].MapperName, + SourceList[i].ColumnIndex)); end; function TBoldMemberMappingList.GetItems(index: integer): TBoldMemberMappingInfo; @@ -489,7 +569,7 @@ procedure TBoldSQLMappingInfo.AddTypeIdMapping(const ClassExpressionName: String raise EBoldInternal.CreateFmt('%s.AddTypeIdMapping: ClassExpressionName is empty (dbtype: %d)', [ClassName, dbType]); OldMapping := GetDbTypeMapping(ClassExpressionName); if (OldMapping <> -1) and (OldMapping <> dbtype) then - raise EBold.CreateFmt(sMultipleDBTypes, [classname, ClassExpressionName, dbtype, oldMapping]); + raise EBold.CreateFmt('%s.AddTypeIdMapping: The class %s has multiple db types (%d and %d)', [classname, ClassExpressionName, dbtype, oldMapping]); if OldMapping = -1 then begin fDbTypeMapping.AddMapping(TBoldDbTypeMappingInfo.create(ClassExpressionName, DbType)); @@ -515,27 +595,6 @@ function TBoldSQLMappingInfo.GetDbTypeMappingInfo(Index: integer): TBoldDbTypeMa end; -{ TBoldAllInstancesMappingList } - -function TBoldAllInstancesMappingList.GetItems(index: integer): TBoldAllInstancesMappingInfo; -begin - result := (inherited items[index]) as TBoldAllInstancesMappingInfo; -end; - -{ TBoldObjectStorageMappingList } - -function TBoldObjectStorageMappingList.GetItems(index: integer): TBoldObjectStorageMappingInfo; -begin - result := (inherited items[index]) as TBoldObjectStorageMappingInfo; -end; - -{ TBoldDbTypeMappingList } - -function TBoldDbTypeMappingList.GetItems(index: integer): TBoldDbTypeMappingInfo; -begin - result := (inherited items[index]) as TBoldDbTypeMappingInfo; -end; - procedure TBoldSQLMappingInfo.WriteDataToDB(DataBase: IBoldDataBase); var i: integer; @@ -544,22 +603,38 @@ procedure TBoldSQLMappingInfo.WriteDataToDB(DataBase: IBoldDataBase); begin if BoldLog.ProcessInterruption then exit; - - BoldLog.Log(sLogWritingMappingToDB); - Script := TStringList.create; - q := DataBase.GetExecQuery; + BoldLog.Log('Writing mapping information to database'); + if not Database.Connected then + Database.Open; + Database.StartTransaction; try - ScriptForWriteData(Script); - BoldLog.ProgressMax := Script.Count; - for i := 0 to Script.Count-1 do - begin - q.AssignSQLText(Script[i]); - q.ExecSQL; - BoldLog.Progress := i; + q := DataBase.GetExecQuery; + Script := TStringList.create; + try + q.ParamCheck := false; + ScriptForWriteData(DataBase, Script, True, '', ''); + BoldLog.ProgressMax := Script.Count; + q.StartSQLBatch; + try + for i := 0 to Script.Count-1 do + begin + q.AssignSQLText(Script[i]); + q.ExecSQL; + BoldLog.Progress := i; + end; + q.EndSQLBatch; + except + q.FailSQLBatch; + raise; + end; + finally + Script.Free; + DataBase.ReleaseExecQuery(q); end; finally - Script.Free; - DataBase.ReleaseExecQuery(q); + BoldLog.Separator; + BoldLog.Log('Committing changes to mapping information'); + Database.Commit; end; end; @@ -574,7 +649,8 @@ function TBoldSQLMappingInfo.CloneWithoutDbType: TBoldSQLMappingInfo; MemberMappingInfo[i].MemberName, MemberMappingInfo[i].TableName, MemberMappingInfo[i].Columns, - MemberMappingInfo[i].MapperName); + MemberMappingInfo[i].MapperName, + MemberMappingInfo[i].ColumnIndex); for i := 0 to fAllInstancesMapping.Count-1 do result.AddAllInstancesMapping(AllInstancesMappingInfo[i].ClassExpressionName, AllInstancesMappingInfo[i].TableName, AllInstancesMappingInfo[i].ClassIdRequired); @@ -583,4 +659,5 @@ function TBoldSQLMappingInfo.CloneWithoutDbType: TBoldSQLMappingInfo; result.AddObjectStorageMapping(ObjectStorageMappingInfo[i].ClassExpressionName, ObjectStorageMappingInfo[i].TableName); end; +initialization end. diff --git a/Source/PMapper/SQL/BoldSQLQuery.pas b/Source/PMapper/SQL/BoldSQLQuery.pas index f2cb252..89cace6 100644 --- a/Source/PMapper/SQL/BoldSQLQuery.pas +++ b/Source/PMapper/SQL/BoldSQLQuery.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldSQLQuery; interface @@ -5,6 +8,7 @@ interface uses Db, Classes, + BoldBase, BoldSQLDataBaseConfig, BoldId, BoldContainers, @@ -43,7 +47,7 @@ TBoldSqlTableReferenceList = class; TBoldSQLQueryMode = (qmSelect, qmInsert, qmUpdate, qmDelete); { TBoldSQLJoin } - TBoldSQLJoin = class + TBoldSQLJoin = class(TBoldMemoryManagedObject) private fColumnRef1: TBoldSQLColumnReference; fColumnRef2: TBoldSQLColumnReference; @@ -56,26 +60,26 @@ TBoldSQLJoin = class end; { TBoldSQLTableReference } - TBoldSQLTableReference = class + TBoldSQLTableReference = class(TBoldMemoryManagedObject) private fTableDescription: TBoldSQLTableDescription; fColumnReferences: TBoldObjectArray; fQuery: TBoldSQLQuery; fAliasName: String; - function GetAliasName: String; - function GetTableAliasDeclaration: String; - procedure EnsureColumnExists(ColumnName, Operation: String); + function GetAliasName: String; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetTableAliasDeclaration: String; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure EnsureColumnExists(const ColumnName, Operation: String); public constructor Create(Query: TBoldSQLQuery); destructor Destroy; override; - function GetColumnReference(ColumnName: String): TBoldSQLColumnReference; + function GetColumnReference(const ColumnName: String): TBoldSQLColumnReference; property TableDescription: TBoldSQLTableDescription read fTableDescription; property AliasName: String read GetAliasName; property TableAliasDeclaration: String read GetTableAliasDeclaration; end; { TBoldSQLColumnReference } - TBoldSQLColumnReference = class + TBoldSQLColumnReference = class(TBoldMemoryManagedObject) private fColumnDescription: TBoldSQLColumnDescription; fTableReference: TBoldSQLTableReference; @@ -87,8 +91,19 @@ TBoldSQLColumnReference = class property PrefixedColumnName: String read GetPrefixedColumnName; end; + { TBoldSQLOrderByInfo } + TBoldSQLOrderByInfo = class(TBoldMemoryManagedObject) + private + FColumn: TBoldSQLColumnReference; + FDescending: Boolean; + public + constructor Create(Column: TBoldSQLColumnReference; const Descending: Boolean); + property Column: TBoldSQLColumnReference read FColumn; + property Descending: Boolean read FDescending; + end; + { TBoldSqlWCF } - TBoldSqlWCF = class + TBoldSqlWCF = class(TBoldMemoryManagedObject) public function GetAsString(Query: TBoldSQlQuery): String; virtual; abstract; end; @@ -100,7 +115,7 @@ TBoldSQLWCFBinary = class(TBoldSqlWCF) fArg2: TBoldSqlWCF; fSymbol: string; public - constructor Create(arg1, arg2: TBoldSqlWCF; Symbol: String); + constructor Create(arg1, arg2: TBoldSqlWCF; const Symbol: String); destructor Destroy; override; end; @@ -117,6 +132,16 @@ TBoldSQLWCFBinaryPrefix = class(TBoldSqlWCFBinary) function GetAsString(Query: TBoldSQlQuery): String; override; end; + { TBoldSQLWCFXOR } + TBoldSQLWCFXOR = class(TBoldSqlWCF) + private + fArg1: TBoldSqlWCF; + fArg2: TBoldSqlWCF; + public + constructor Create(arg1, arg2: TBoldSqlWCF); + function GetAsString(Query: TBoldSQlQuery): String; override; + end; + { TBoldSQLWCFUnary } TBoldSQLWCFUnary = class(TBoldSqlWCF) private @@ -133,6 +158,12 @@ TBoldSQLWCFUnaryPrefix = class(TBoldSqlWCFUnary) function GetAsString(Query: TBoldSQlQuery): String; override; end; + { TBoldSQLWCFUnaryTransforLikeString } + TBoldSQLWCFUnaryTransformLikeString = class(TBoldSqlWCFUnary) + public + function GetAsString(Query: TBoldSQlQuery): String; override; + end; + { TBoldSQLWCFUnaryPostfix } TBoldSQLWCFUnaryPostfix = class(TBoldSqlWCFUnary) public @@ -144,7 +175,7 @@ TBoldSQLWCFString = class(TBoldSqlWCF) private fStr: String; public - constructor Create(Value: String); + constructor Create(const Value: String); function GetAsString(Query: TBoldSQlQuery): String; override; end; @@ -161,7 +192,7 @@ TBoldSQLWCFInteger = class(TBoldSqlWCF) TBoldSQLWCFFloat = class(TBoldSqlWCF) private fFloat: Double; - fParam:TParam; //<- Add param variable to avoid multiple create (HK) + fParam:TParam; public constructor Create(Value: Double); function GetAsString(Query: TBoldSQlQuery): String; override; @@ -171,7 +202,7 @@ TBoldSQLWCFFloat = class(TBoldSqlWCF) TBoldSQLWCFDate = class(TBoldSqlWCF) private fDate: TDateTime; - fParam:TParam; //<- Add param variable to avoid multiple create (HK) + fParam:TParam; public constructor Create(Value: TDateTime); function GetAsString(Query: TBoldSQlQuery): String; override; @@ -181,7 +212,7 @@ TBoldSQLWCFDate = class(TBoldSqlWCF) TBoldSQLWCFTime = class(TBoldSqlWCF) private fTime: TDateTime; - fParam:TParam; //<- Add param variable to avoid multiple create (HK) + fParam:TParam; public constructor Create(Value: TDateTime); function GetAsString(Query: TBoldSQlQuery): String; override; @@ -215,8 +246,7 @@ TBoldSQLWCFWithQuery = class(TBoldSqlWCF) fQuery: TBoldSQLQuery; protected function QueryAsString: String; - procedure CopyParams(Query: TBoldSQlQuery);//<- Provide a way to copy parameters (HK) - + procedure CopyParams(Query: TBoldSQlQuery); public constructor Create(query: TBoldSQLQuery); destructor Destroy; override; @@ -268,25 +298,25 @@ TBoldSQLWCFGenericExpression = class(TBoldSqlWCF) private fExpr: String; public - constructor Create(Expr: String); + constructor Create(const Expr: String); function GetAsString(Query: TBoldSQlQuery): String; override; end; { TBoldSQLNameSpace } - TBoldSQLNameSpace = class + TBoldSQLNameSpace = class(TBoldMemoryManagedObject) private fUsedNames: TStringList; fUsedParams: integer; public constructor Create; destructor Destroy; override; - function GetUnusedParamNumber: integer; + function GetUnusedParamNumber: integer; {$IFDEF BOLD_INLINE} inline; {$ENDIF} - function GetUniqueAlias(TableName: String): String; + function GetUniqueAlias(const TableName: String): String; end; { TBoldSQLQuery } - TBoldSQLQuery = class + TBoldSQLQuery = class(TBoldMemoryManagedObject) private fMode: TBoldSQLQueryMode; fJoins: TBoldObjectArray; @@ -294,6 +324,9 @@ TBoldSQLQuery = class fSystemDescription: TBoldSQLSystemDescription; fColumnsToRetrieve: TBoldObjectArray; fColumnsToOrderBy: TBoldObjectArray; + fDistinct: Boolean; + fLimit: Integer; + fLimitTop: Boolean; fWhereClauseFragments: TBoldObjectArray; fParams: TParams; fRetrieveCountStar: Boolean; @@ -302,15 +335,14 @@ TBoldSQLQuery = class fMainTable: TBoldSqlTableReference; fIgnoreHistoricObjects: Boolean; fSQLDatabaseConfig: TBoldSQLDatabaseConfig; - function GetColumnToRetrieve(Index: Integer): TBoldSQLColumnReference; - function GetJoin(index: integer): TBoldSQLJoin; - function GetUniqueAlias(TableName: String): String; - function GetWCF(index: integer): TBoldSqlWCF; + function GetColumnToRetrieve(Index: Integer): TBoldSQLColumnReference; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetJoin(index: integer): TBoldSQLJoin; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetUniqueAlias(const TableName: String): String; + function GetWCF(index: integer): TBoldSqlWCF; {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure GenerateSelect(Strings: TStrings); procedure EnsureTableExists(tableName, Operation: String); function GetAsString: string; protected - property TableReferences: TBoldSQLTableReferenceList read fTableReferences; property ColumnToRetrieve[Index: Integer]: TBoldSQLColumnReference read GetColumnToRetrieve; property Join[Index: integer]: TBoldSQLJoin read GetJoin; property WCF[index: integer]: TBoldSqlWCF read GetWCF; @@ -318,32 +350,36 @@ TBoldSQLQuery = class constructor Create(Mode: TBoldSQLQueryMode; SystemDescription: TBoldSQLSystemDescription; SQLDatabaseConfig: TBoldSQLDatabaseConfig; NameSpace: TBoldSqlNameSpace); destructor Destroy; override; function AddJoin(ColumnRef1, ColumnRef2: TBoldSQLColumnReference): TBoldSQLJoin; - function AddTableReference(TableName: String): TBoldSQLTableReference; + function AddTableReference(const TableName: String): TBoldSQLTableReference; procedure AddColumnToRetrieve(ColumnReference: TBoldSQLColumnReference); - procedure AddColumnToOrderBy(Columnreference: TBoldSQlColumnReference); + procedure AddColumnToOrderBy(Columnreference: TBoldSQlColumnReference; const + Descending: Boolean); procedure GenerateSQL(Strings: TStrings); - function AddParam(name: string=''): TParam; + function AddParam(const name: string=''): TParam; function HastableReferenceInList(TableReference: TBoldSQLTablereference): boolean; - procedure RetrieveCountStar; - procedure AddWCF(WCF: TBoldSqlWCF); - procedure ClearColumnsToRetrieve; + procedure RetrieveCountStar; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure AddWCF(WCF: TBoldSqlWCF); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure ClearColumnsToRetrieve; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure SetLimit(const Top: Boolean = True; const Limit: Integer = 1); property Mode: TBoldSQLQueryMode read fMode; property SystemDescription: TBoldSQLSystemDescription read fSystemDescription; property MainTable: TBoldSQLTableReference read fMaintable; property AsString: string read GetAsString; + property Distinct: Boolean read fDistinct write fDistinct; property SQLDatabaseConfig: TBoldSQLDatabaseConfig read fSQLDatabaseConfig; - property Params: TParams read fParams; //<- Expose params so we may Copy them to real Query (HK) + property Params: TParams read fParams; property IgnoreHistoricObjects: Boolean read fIgnoreHistoricObjects write fIgnoreHistoricObjects; + property TableReferences: TBoldSQLTableReferenceList read fTableReferences; end; { TBoldSqlTableReferenceList } TBoldSqlTableReferenceList = class(TBoldObjectArray) private - function Get(Index: Integer): TBoldSqlTableReference; - procedure Put(Index: Integer; const Value: TBoldSqlTableReference); + function Get(Index: Integer): TBoldSqlTableReference; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure Put(Index: Integer; const Value: TBoldSqlTableReference); {$IFDEF BOLD_INLINE} inline; {$ENDIF} public - function Add(Item: TBoldSqlTableReference): Integer; - procedure Insert(Index: Integer; Item: TBoldSqlTableReference); + function Add(Item: TBoldSqlTableReference): Integer; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure Insert(Index: Integer; Item: TBoldSqlTableReference); {$IFDEF BOLD_INLINE} inline; {$ENDIF} property Items[Index: Integer]: TBoldSqlTableReference read Get write Put; default; end; @@ -353,13 +389,18 @@ implementation BoldDefs, BoldPSDescriptionsDefault, SysUtils, - BoldUtils; + BoldIndex, +{$IFNDEF BOLD_UNICODE} + StringBuilder, +{$ENDIF} + BoldUtils, + BoldIndexableList; { TBoldSQLQuery } -function TBoldSQLQuery.AddTableReference(TableName: String): TBoldSQLTableReference; +function TBoldSQLQuery.AddTableReference(const TableName: String): TBoldSQLTableReference; var RootTable: TBoldSQLTableDescription; RootTableRef: TBoldSQLTableReference; @@ -368,7 +409,7 @@ function TBoldSQLQuery.AddTableReference(TableName: String): TBoldSQLTableRefere MyIdCol, RootIdCol, MyStartCol, RootStartCol: TBoldSQLColumnReference; begin - EnsureTableExists(TableName, 'AddTableReference'); // do not localize + EnsureTableExists(TableName, 'AddTableReference'); result := TBoldSQLTableReference.Create(self); Result.fTableDescription := SystemDescription.SQLTablesList.ItemsBySQLName[TableName]; @@ -404,13 +445,16 @@ constructor TBoldSQLQuery.Create(Mode: TBoldSQLQueryMode; SystemDescription: TBo fJoins := TBoldObjectArray.Create(0, [bcoDataOwner]); fTableReferences := TBoldSqlTableReferenceList.Create(0, [bcoDataOwner]); fColumnsToRetrieve := TBoldObjectArray.Create(0, []); - fColumnsToOrderBy := TBoldObjectArray.Create(0, []); + fColumnsToOrderBy := TBoldObjectArray.Create(0, [bcoDataOwner]); fSQLDatabaseConfig := SQLDatabaseConfig; fWhereClauseFragments := TBoldObjectArray.Create(0, [bcoDataOwner]); fSystemDescription := SystemDescription; fParams := TParams.Create; fNameSpace := nameSpace; fIgnoreHistoricObjects := true; + fDistinct := False; + fLimit := 0; + fLimitTop := True; end; destructor TBoldSQLQuery.Destroy; @@ -438,9 +482,49 @@ procedure TBoldSQLQuery.GenerateSQL(Strings: TStrings); {$HINTS ON} procedure TBoldSQLQuery.GenerateSelect(Strings: TStrings); + + procedure AddOrderByClause(const LimitTop: Boolean); + var + temp: string; + i: Integer; + OrderByInfo: TBoldSQLOrderByInfo; + begin + temp := ''; + if (fColumnsToOrderBy.Count = 0) and (fLimit > 0) then begin + // Use default sort on BOLD_ID column for limit, when no sort was spezified + if Assigned(MainTable) then begin + temp := MainTable.GetColumnReference(IDCOLUMN_NAME).PrefixedColumnName; + end else begin + temp := TableReferences[TableReferences.Count - 1].GetColumnReference(IDCOLUMN_NAME).PrefixedColumnName; + end; + if not LimitTop then begin + temp := temp + ' DESC'; // do not localize + end; + end; + + if (fColumnsToOrderBy.Count > 0) then begin + for i := 0 to fColumnsToOrderBy.Count - 1 do + begin + OrderByInfo := TBoldSQLOrderByInfo(fColumnsToOrderBy[i]); + if temp <> '' then + temp := temp + ', '; + temp := temp + OrderByInfo.Column.PrefixedColumnName; + // If last records are fetched (not LimitTop) then sorting must be reversed. + if not (OrderByInfo.Descending xor LimitTop) then begin + temp := temp + ' DESC'; // do not localize + end; + end; + end; + + if temp <> '' then begin + Strings.Add('ORDER BY ' + temp); // do not localize + end; + end; + + var - i, j: integer; temp: String; + i, j: integer; TempStringList: TStringList; PrefixOfNextWCF: string; PrevTable: String; @@ -453,9 +537,24 @@ procedure TBoldSQLQuery.GenerateSelect(Strings: TStrings); TempStringlist.Add(ColumnToRetrieve[i].PrefixedColumnName); if fGroupOperation <> '' then TempStringList[0] := fGroupOperation + '(' + TempStringList[0] + ')'; - if fRetrieveCountStar then - TempStringList.Add('COUNT(*)'); // do not localize - Strings.Add('SELECT ' + BoldSeparateStringList(tempStringList, ', ', '', '')); // do not localize + if fRetrieveCountStar then begin + if fDistinct and (TableReferences.Count > 0) then begin + // Use ID column of last added table als distinct column. + TempStringList.Add('COUNT(DISTINCT ' + + TableReferences[TableReferences.Count - 1].GetColumnReference( + IDCOLUMN_NAME).PrefixedColumnName + ')'); // do not localize + end else begin + TempStringList.Add('COUNT(*)'); // do not localize + end; + end; + temp := 'SELECT '; // do not localize + if fDistinct and (not fRetrieveCountStar) then begin + temp := temp + 'DISTINCT '; // do not localize + end; + if fLimit > 0 then begin + temp := temp + 'TOP ' + IntToStr(fLimit) + ' '; // do not localize + end; + Strings.Add(temp + BoldSeparateStringList(tempStringList, ', ', '', '')); PrefixOfNextWCF := 'WHERE'; // do not localize @@ -497,7 +596,7 @@ procedure TBoldSQLQuery.GenerateSelect(Strings: TStrings); end else temp := temp + format(' JOIN %s ON (%s)', [TableReferences[i].TableAliasDeclaration, cond]); // do not localize - end; + end; Strings.Add(temp); for i := 0 to UnprocessedJoins.Count - 1 do begin @@ -524,17 +623,22 @@ procedure TBoldSQLQuery.GenerateSelect(Strings: TStrings); Strings.Add(PrefixOfNextWCF + ' ' + TBoldSqlWCF(fWhereClauseFragments[i]).GetAsString(self)); PrefixOfNextWCF := ' AND'; // do not localize end; - temp := ''; - if fColumnsToOrderBy.Count > 0 then - begin - for i := 0 to fColumnsToOrderBy.Count - 1 do - begin - if temp <> '' then - temp := temp + ', '; - temp := temp + TBoldSQlColumnReference(fColumnsToOrderBy[i]).PrefixedColumnName; - end; - Strings.Add('ORDER BY ' + temp); // do not localize + + AddOrderByClause(fLimitTop); + + // The following must be done last! + // Special case, when multiple last records are to be selected: + // Through the reversed sort the result set has the wanted records, + // but in reverse order. (Theoretcal problem, because Limit is 1 on ->first/last) + // Therefore original order must be restored: + if (not fLimitTop) and (fLimit > 1) then begin + Strings.Insert(0, 'SELECT * FROM ('); + // SubSelect must be provided with Alias, + // otherwise its not possible to resort the outer select. + Strings.Add(') AS ReverseOrderSelect'); + AddOrderByClause(True); end; + TempStringList.Free; end; @@ -554,7 +658,7 @@ function TBoldSQLQuery.GetColumnToRetrieve(Index: Integer): TBoldSQLColumnRefere result := TBoldSQLColumnReference(fColumnsToRetrieve[index]); end; -function TBoldSQLQuery.GetUniqueAlias(TableName: String): String; +function TBoldSQLQuery.GetUniqueAlias(const TableName: String): String; var i, Counter: Integer; OK: Boolean; @@ -613,7 +717,7 @@ function TBoldSQLQuery.GetWCF(index: integer): TBoldSqlWCF; result := TBoldSqlWCF(fWhereClauseFragments[index]); end; -function TBoldSQLQuery.AddParam(name: string=''): TParam; +function TBoldSQLQuery.AddParam(const name: string=''): TParam; begin result := fParams.Add as tParam; if Name = '' then @@ -650,9 +754,16 @@ function TBoldSQLQuery.HastableReferenceInList( result := fTableReferences.IndexOf(TableReference) <> -1; end; +procedure TBoldSQLQuery.SetLimit(const Top: Boolean = True; const Limit: + Integer = 1); +begin + fLimit := Limit; + fLimitTop := Top; +end; + { TBoldSQLTableReference } -function TBoldSQLTableReference.GetColumnReference(ColumnName: String): TBoldSQLColumnReference; +function TBoldSQLTableReference.GetColumnReference(const ColumnName: String): TBoldSQLColumnReference; var i: integer; begin @@ -680,7 +791,7 @@ destructor TBoldSQLTableReference.Destroy; inherited; end; -procedure TBoldSQLTableReference.EnsureColumnExists(ColumnName, +procedure TBoldSQLTableReference.EnsureColumnExists(const ColumnName, Operation: String); begin if not assigned(TableDescription.ColumnsList.ItemsBySQLName[ColumnName]) then @@ -713,6 +824,15 @@ function TBoldSQLColumnReference.GetPrefixedColumnName: String; result := format('%s.%s', [TableReference.AliasName, ColumnDescription.SQLName]) // do not localize end; +{ TBoldSQLOrderByInfo } + +constructor TBoldSQLOrderByInfo.Create(Column: TBoldSQLColumnReference; + const Descending: Boolean); +begin + FColumn := Column; + FDescending := Descending; +end; + { TBoldSQLJoin } constructor TBoldSQLJoin.Create(ColumnRef1, ColumnRef2: TBoldSqlColumnReference); @@ -772,7 +892,7 @@ procedure TBoldSqlTableReferenceList.Put(Index: Integer; { TBoldSQLWCFBinary } -constructor TBoldSQLWCFBinary.Create(arg1, arg2: TBoldSqlWCF; Symbol: String); +constructor TBoldSQLWCFBinary.Create(arg1, arg2: TBoldSqlWCF; const Symbol: String); begin inherited Create; fArg1 := Arg1; @@ -791,7 +911,21 @@ destructor TBoldSQLWCFBinary.destroy; function TBoldSQLWCFBinaryInfix.GetAsString(Query: TBoldSQlQuery): String; begin - result := '(' + fArg1.GetAsString(Query) + ' ' + fSymbol + ' ' + fArg2.GetAsString(Query) + ')'; + Result := '('; + if Assigned(fArg1) then begin + Result := Result + fArg1.GetAsString(Query) + ' '; + end; + if Assigned(fArg1) and Assigned(fArg2) then begin + Result := Result + fSymbol; + end; + if Assigned(fArg2) then begin + Result := Result + ' ' + fArg2.GetAsString(Query); + end; + // Add the escape character to use % and _ ( and [ ) within a search. + if SameStr(fSymbol, 'LIKE') then begin + Result := Result + ' ESCAPE ''\'''; + end; + Result := Result + ')'; end; class function TBoldSQLWCFBinaryInfix.CreateWCFForIdList( @@ -825,9 +959,31 @@ function TBoldSQLWCFBinaryPrefix.GetAsString(Query: TBoldSQlQuery): String; result := '(' + fSymbol + '(' + fArg1.GetAsString(Query) + ', ' + fArg2.GetAsString(Query) + '))'; end; +{ TBoldSQLWCFXOR } + +constructor TBoldSQLWCFXOR.Create(arg1, arg2: TBoldSqlWCF); +begin + inherited Create; + fArg1 := Arg1; + fArg2 := Arg2; +end; + +function TBoldSQLWCFXOR.GetAsString(Query: TBoldSQlQuery): String; +begin + Result := '('; + if Assigned(fArg1) and Assigned(fArg2) then begin + Result := Result + Format('(%s AND NOT %s) or (%1:s AND NOT %0:s)', + [fArg1.GetAsString(Query), + fArg2.GetAsString(Query)]); + end else begin + Result := Result + 'FALSE'; // This case does not exist + end; + Result := Result + ')'; +end; + { TBoldSQLWCFString } -constructor TBoldSQLWCFString.Create(Value: String); +constructor TBoldSQLWCFString.Create(const Value: String); begin fStr := Value; end; @@ -962,8 +1118,11 @@ constructor TBoldSQLWCFInQuery.create(Arg1: TBoldSqlWCF; destructor TBoldSQLWCFInQuery.destroy; begin // a workaround, the In-condition does not really own its query - fQuery := nil; + // -> No, not a workaroung, but a memory leak! + // -> TBoldSQLWCFInQuery is used only in 2 places, and there the query is not freed. +// fQuery := nil; + freeAndNil(fArg1); inherited; freeAndNil(fArg1); end; @@ -976,7 +1135,7 @@ function TBoldSQLWCFInQuery.GetAsString(Query: TBoldSQlQuery): String; { TBoldSQLWCFGenericExpression } -constructor TBoldSQLWCFGenericExpression.Create(Expr: String); +constructor TBoldSQLWCFGenericExpression.Create(const Expr: String); begin fExpr := Expr; end; @@ -1085,7 +1244,7 @@ destructor TBoldSQLNameSpace.destroy; inherited; end; -function TBoldSQLNameSpace.GetUniqueAlias(TableName: String): String; +function TBoldSQLNameSpace.GetUniqueAlias(const TableName: String): String; var i: integer; begin @@ -1097,9 +1256,10 @@ function TBoldSQLNameSpace.GetUniqueAlias(TableName: String): String; fUsedNames.Add(result); end; -procedure TBoldSQLQuery.AddColumnToOrderBy(Columnreference: TBoldSQlColumnReference); +procedure TBoldSQLQuery.AddColumnToOrderBy(Columnreference: + TBoldSQlColumnReference; const Descending: Boolean); begin - fColumnsToOrderBy.Add(ColumnReference); + fColumnsToOrderBy.Add(TBoldSQLOrderByInfo.Create(ColumnReference, Descending)); end; function TBoldSQLNameSpace.GetUnusedParamNumber: integer; @@ -1140,5 +1300,33 @@ function TBoldSQLWCFTime.GetAsString(Query: TBoldSQlQuery): String; result := ':' + fParam.Name; end; -end. + +{ TBoldSQLWCFUnaryTransforLikeString } + +function TBoldSQLWCFUnaryTransformLikeString.GetAsString( + Query: TBoldSQlQuery): String; +var + SB: TStringBuilder; + Ch: Char; +begin + Result := fArg1.GetAsString(Query); + if true or Query.SQLDatabaseConfig.QuoteLeftBracketInLike then + begin + Sb := TStringBuilder.Create(Length(Result)+10); + try + for Ch in Result do + if Ch = '[' then + SB.Append('[[]') + else + SB.Append(Ch); + Result := SB.ToString; + finally + sb.free; + end; + end; +end; + +initialization + +end. diff --git a/Source/PMapper/SQL/BoldSqlNodeMaker.pas b/Source/PMapper/SQL/BoldSqlNodeMaker.pas index b700fef..b671b50 100644 --- a/Source/PMapper/SQL/BoldSqlNodeMaker.pas +++ b/Source/PMapper/SQL/BoldSqlNodeMaker.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldSqlNodeMaker; interface @@ -43,7 +46,8 @@ implementation uses Classes, - SysUtils; + SysUtils, + BoldRev; { TBoldSqlNodeMaker } @@ -59,20 +63,18 @@ destructor TBoldSqlNodeMaker.destroy; var i: integer; begin - // simply let go of all the OLWVarBindings, they will be owned by the condition. for i := fOLWVarBindings.Count-1 downto 0 do fOLWVarBindings[i] := nil; FreeAndNil(fOLWVarBindings); for i := fSQLVarBindings.Count-1 downto 0 do begin - // external variables should be freed, internal should just be removed, they will be freed by the rootnode. if TBoldSqlVariableBinding(fSQLVarBindings[i]).IsExternal then TBoldSqlVariableBinding(fSQLVarBindings[i]).Free; fSQLVarBindings[i] := nil; end; FreeAndNil(fSqlVarbindings); - + FreeAndNil(fRootNode); inherited; end; @@ -85,7 +87,7 @@ function TBoldSqlNodeMaker.SQLBindingForVarBinding( begin result := nil; for i := 0 to fOLWVarBindings.Count-1 do - if (fOLWVarBindings[i] as TBoldOLWVariableBinding).variablename = VarBinding.VariableName then + if CompareText((fOLWVarBindings[i] as TBoldOLWVariableBinding).variablename, VarBinding.VariableName) = 0 then begin result := TBoldSQLVariableBinding(fSqlVarBindings[i]); break; @@ -95,7 +97,7 @@ function TBoldSqlNodeMaker.SQLBindingForVarBinding( procedure TBoldSqlNodeMaker.VisitTBoldOLWEnumLiteral(N: TBoldOLWEnumLiteral); begin - fRootNode := TBoldSqlEnumLiteral.create(n.Position, n.name); + fRootNode := TBoldSqlEnumLiteral.create(n.Position, n.Intvalue, n.name); end; procedure TBoldSqlNodeMaker.VisitTBoldOLWIntLiteral(N: TBoldOLWIntLiteral); @@ -126,7 +128,6 @@ procedure TBoldSqlNodeMaker.VisitTBoldOLWListCoercion(N: TBoldOLWListCoercion); procedure TBoldSqlNodeMaker.VisitTBoldOLWLiteral(N: TBoldOLWLiteral); begin - // Abstract class end; procedure TBoldSqlNodeMaker.VisitTBoldOLWMember(N: TBoldOLWMember); @@ -151,7 +152,6 @@ procedure TBoldSqlNodeMaker.VisitTBoldOLWMember(N: TBoldOLWMember); procedure TBoldSqlNodeMaker.VisitTBoldOLWNode(N: TBoldOLWNode); begin - // abstract class end; procedure TBoldSqlNodeMaker.VisitTBoldOLWFloatLiteral(N: TBoldOLWFloatLiteral); @@ -196,7 +196,7 @@ procedure TBoldSqlNodeMaker.VisitTBoldOLWVariableBinding(N: TBoldOLWVariableBind begin varBind := nil; for i := 0 to SQLVarBindings.Count-1 do - if ((SQLVarBindings[i] as TBoldSqlVariableBinding).VariableName = n.variableName) then + if CompareText((SQLVarBindings[i] as TBoldSqlVariableBinding).VariableName, n.variableName) = 0 then VarBind := SQLVarBindings[i] as TBoldSqlVariableBinding; if not assigned(VarBind) then @@ -260,4 +260,5 @@ procedure TBoldSqlNodeMaker.VisitTBoldOLWTimeLiteral( fRootNode := TBoldSqlTimeLiteral.Create(n.Position, n.TimeValue); end; +initialization end. diff --git a/Source/PMapper/SQL/BoldSqlNodes.pas b/Source/PMapper/SQL/BoldSqlNodes.pas index a81431e..3def7b2 100644 --- a/Source/PMapper/SQL/BoldSqlNodes.pas +++ b/Source/PMapper/SQL/BoldSqlNodes.pas @@ -1,9 +1,14 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldSqlNodes; interface + uses DB, Classes, + BoldBase, BoldPSDescriptionsSQL, BoldPMappersSQL, BoldSqlQuery, @@ -51,27 +56,27 @@ TBoldSqlNodeVisitor = class(TObject) TBoldSqlNodeList = class(TList) private - function GetItem(index: Integer): TBoldSqlNode; - procedure PutItem(index: Integer; Value: TBoldSqlNode); + function GetItem(index: Integer): TBoldSqlNode; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure PutItem(index: Integer; Value: TBoldSqlNode); {$IFDEF BOLD_INLINE} inline; {$ENDIF} public destructor Destroy; override; - function Add(Item: TBoldSqlNode): Integer; + function Add(Item: TBoldSqlNode): Integer; {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure TraverseList(V: TBoldSqlNodeVisitor); virtual; property Items[index: Integer]: TBoldSqlNode read GetItem write PutItem; default; end; - TBoldSqlNode = class(TObject) + TBoldSqlNode = class(TBoldMemoryManagedObject) private fPosition: integer; fObjectMapper: TBoldObjectSQLMapper; fTableReferences: TBoldSqlTableReferenceList; fWCF: TBoldSqlWCF; fQuery: TBoldSqlQuery; - function GetHasObjectMapper: Boolean; - function GetHasQuery: boolean; + function GetHasObjectMapper: Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} function GetTableReferences: TBoldSqlTableReferenceList; virtual; protected + function GetHasQuery: boolean; virtual; function GetQuery: TBoldSqlQuery; virtual; function GetObjectMapper: TBoldObjectSQLMapper; virtual; procedure SetObjectMapper(const Value: TBoldObjectSQLMapper); virtual; @@ -152,7 +157,7 @@ TBoldSqlMember = class(TBoldSqlNode) fMemberMapper: TBoldMemberSQLMapper; fIsBoolean: Boolean; public - constructor Create(Position: integer; memberName: String; MemberIndex: Integer; MemberOf: TBoldSqlNode; IsBoolean: Boolean); + constructor Create(Position: integer; const memberName: String; MemberIndex: Integer; MemberOf: TBoldSqlNode; IsBoolean: Boolean); destructor Destroy; override; function TableReferenceForTable(Table: TBoldSqlTableDescription; Query: TBoldSqlQuery; ForceOwnTable: Boolean): TBoldSqlTableReference; override; procedure AcceptVisitor(V: TBoldSqlNodeVisitor); override; @@ -191,6 +196,7 @@ TBoldSqlVariableReference = class(TBoldSqlNode) fVariableBinding: TBoldSqlVariableBinding; function GetTableReferences: TBoldSqlTableReferenceList; override; protected + function GetHasQuery: boolean; override; function GetQuery: TBoldSqlQuery; override; function GetObjectMapper: TBoldObjectSQLMapper; override; procedure SetObjectMapper(const Value: TBoldObjectSQLMapper); override; @@ -277,13 +283,13 @@ TBoldSqlEnumLiteral = class(TBoldSqlLiteral) protected function GetAsString: String; override; public - constructor Create(Position: integer; Name: String); + constructor Create(Position, IntValue: integer; Name: String); property Name: string read fName; property Intvalue: integer read fIntValue write fIntvalue; procedure AcceptVisitor(V: TBoldSqlNodeVisitor); override; end; - TBoldSqlSymbol = class + TBoldSqlSymbol = class(TBoldMemoryManagedObject) protected function GetName: String; virtual; abstract; function GetSQLName: String; virtual; @@ -294,7 +300,7 @@ TBoldSqlSymbol = class property SQLName: String read GetSQLName; end; - TBoldSQLWCFVariable = class(TBoldSqlWCF) //<- New WCFclass to handle variables (HK) + TBoldSQLWCFVariable = class(TBoldSqlWCF) private fParam:TParam; fVariableBinding:TBoldSqlVariableBinding; @@ -302,7 +308,7 @@ TBoldSQLWCFVariable = class(TBoldSqlWCF) //<- New WCFclass to handle constructor Create(VariableBinding: TBoldSqlVariableBinding); function GetAsString(Query: TBoldSQlQuery): String; override; destructor Destroy;override; - end; //<- End (HK) + end; implementation @@ -310,7 +316,6 @@ implementation uses SysUtils, BoldDefs, - BoldPMConsts, BoldSQLMappingInfo, BoldPMappersDefault; @@ -340,10 +345,9 @@ constructor TBoldSqlOperation.create(Position: integer; OperationName: String); destructor TBoldSqlOperation.Destroy; begin FreeAndNil(fArgs); - inherited; + inherited; end; - { TBoldSqlNode } procedure TBoldSqlNode.AcceptVisitor(V: TBoldSqlNodeVisitor); @@ -360,10 +364,10 @@ constructor TBoldSqlNode.Create(Position: integer); destructor TBoldSqlNode.destroy; begin - inherited; FreeAndNil(fTableReferences); FreeAndNil(fWCF); FreeAndNil(fQuery); + inherited; end; function TBoldSqlNode.GetHasObjectMapper: Boolean; @@ -418,11 +422,12 @@ procedure TBoldSqlNode.CopyTableReferences(node: TBoldSqlNode); fTableReferences.Add(Node.GetTableReferences[i]); end; + procedure TBoldSqlNode.SetObjectMapper(const Value: TBoldObjectSQLMapper); begin fObjectmapper := Value; if HasObjectMapper and (length(ObjectMapper.SystemPersistenceMapper.MappingInfo.GetAllInstancesMapping(ObjectMapper.ExpressionName)) > 1) then - raise EBold.CreateFmt(sChildMappedClassesNotSupported, [ObjectMapper.ExpressionName]); + raise EBold.Create('ChildMapped classes not supported: '+ObjectMapper.ExpressionName); end; procedure TBoldSqlNode.SetQuery(const Value: TBoldSqlQuery); @@ -430,6 +435,7 @@ procedure TBoldSqlNode.SetQuery(const Value: TBoldSqlQuery); fQuery := Value; end; + function TBoldSqlNode.TableReferenceForTable(Table: TBoldSQLTableDescription; Query: TBoldSqlQuery; ForceOwntable: Boolean): TBoldSqlTableReference; var i: integer; @@ -448,8 +454,6 @@ function TBoldSqlNode.TableReferenceForTable(Table: TBoldSQLTableDescription; Qu if assigned(ObjectMapper) and (ObjectMapper.AllTables.IndexOf(Table) = -1) then raise EBoldInternal.createFmt('Table %s does not belong to class %s', [Table.SQLName, ObjectMapper.ExpressionName]); - // if the table reference has been used before, by the same query, then reuse it. - for i := 0 to fTableReferences.Count-1 do if (fTablereferences[i].TableDescription = Table) and Query.HastableReferenceInList(fTablereferences[i]) then @@ -475,8 +479,8 @@ function TBoldSqlNode.TableReferenceForTable(Table: TBoldSQLTableDescription; Qu TypeIDWCF := TBoldSQLWCFGenericExpression.Create('('+(ObjectMapper as TBoldObjectDefaultMapper).SubClassesID+')'); TypeColRef := Result.GetColumnReference(TYPECOLUMN_NAME); TypeColRefWCF := TBoldSQLWCFColumnRef.Create(TypeColRef); - TypeWCF := TBoldSQLWCFBinaryInfix.Create(TypeColRefWCF, TypeIDWCF, 'IN'); // do not localize - Query.AddWCF(TypeWCF); // ensures the maintable as first table; + TypeWCF := TBoldSQLWCFBinaryInfix.Create(TypeColRefWCF, TypeIDWCF, 'IN'); + Query.AddWCF(TypeWCF); end; end; end; @@ -550,8 +554,8 @@ constructor TBoldSqlIteration.Create(Position: integer; OperationName: String; L destructor TBoldSqlIteration.Destroy; begin - inherited; FreeandNil(fLoopVar); + inherited; end; function TBoldSqlIteration.TableReferenceForTable( @@ -570,7 +574,7 @@ procedure TBoldSqlMember.AcceptVisitor(V: TBoldSqlNodeVisitor); v.VisitTBoldSqlMember(self); end; -constructor TBoldSqlMember.Create(Position: integer; memberName: String; MemberIndex: Integer; MemberOf: TBoldSqlNode; IsBoolean: Boolean); +constructor TBoldSqlMember.Create(Position: integer; const memberName: String; MemberIndex: Integer; MemberOf: TBoldSqlNode; IsBoolean: Boolean); begin inherited Create(Position); fMemberName := memberName; @@ -588,7 +592,6 @@ destructor TBoldSqlMember.Destroy; end; function TBoldSqlMember.QueryOfMemberOfIsEnclosing: Boolean; -// Checks if the query of the memberOf-node will enclose this node, or if we can steal it. begin result := (MemberOf is TBoldSQLVariableReference) and (MemberOf as TBoldSQLVariableReference).VariableBinding.IsLoopVar; @@ -646,13 +649,15 @@ procedure TBoldSqlVariableBinding.AcceptVisitor(V: TBoldSqlNodeVisitor); v.VisitTBoldSqlVariableBinding(self); end; + procedure TBoldSqlVariableBinding.AddRef; begin inc(fRefCount); if (fRefCount > 1) and not fIsLoopVar then - raise EBold.Create(sExternalVarsCanOnlyBereferencedOnce); + raise EBold.Create('external variables (and self) can currently only be referenced once'); end; + constructor TBoldSqlVariableBinding.Create(Position: integer; VariableName: String; TopSortedIndex: integer); begin inherited Create(Position); @@ -660,6 +665,7 @@ constructor TBoldSqlVariableBinding.Create(Position: integer; VariableName: Stri fTopSortedIndex := TopSortedIndex; end; + { TBoldSqlStrLiteral } procedure TBoldSqlStrLiteral.AcceptVisitor(V: TBoldSqlNodeVisitor); @@ -667,6 +673,7 @@ procedure TBoldSqlStrLiteral.AcceptVisitor(V: TBoldSqlNodeVisitor); v.VisitTBoldSqlStrLiteral(self); end; + constructor TBoldSqlStrLiteral.Create(Position: integer; StrValue: String); begin inherited Create(Position); @@ -771,6 +778,15 @@ constructor TBoldSqlVariableReference.Create(Position: integer; VariableBinding: fVariableBinding := VariableBinding; end; +function TBoldSqlVariableReference.GetHasQuery: boolean; +begin + if VariableBinding.IsLoopVar then begin + Result := inherited GetHasQuery; + end else begin + Result := VariableBinding.HasQuery; + end; +end; + function TBoldSqlVariableReference.GetObjectMapper: TBoldObjectSQLMapper; begin result := VariableBinding.ObjectMapper; @@ -783,7 +799,7 @@ function TBoldSqlVariableReference.GetQuery: TBoldSqlQuery; function TBoldSqlVariableReference.RelinquishWCF: TBoldSqlWCF; begin - result := TBoldSQLWCFVariable.Create(VariableBinding); //<- Use new WCF class for variables (HK) + result := TBoldSQLWCFVariable.Create(VariableBinding); end; function TBoldSqlVariableReference.RelinquishQuery: TBoldSqlQuery; @@ -841,9 +857,11 @@ destructor TBoldSqlListCoercion.destroy; inherited; end; -constructor TBoldSqlEnumLiteral.Create(Position: integer; Name: String); +constructor TBoldSqlEnumLiteral.Create(Position, IntValue: integer; Name: + String); begin inherited Create(Position); + fIntValue := IntValue; fName := Name; end; @@ -917,9 +935,6 @@ function TBoldSqlSymbol.ResolveObjectMapper(OperationNode: TBoldSqlOperation): T end; { TBoldSQLWCFVariable } - - -//<- Implement new WCFclass for variables (HK) constructor TBoldSQLWCFVariable.Create( VariableBinding: TBoldSqlVariableBinding); begin @@ -940,7 +955,6 @@ function TBoldSQLWCFVariable.GetAsString(Query: TBoldSQlQuery): String; fParam.Value:=fVariableBinding.ExternalVarValue; result := ':'+fParam.Name; end; -//<- END (HK) { TBoldSqlDateLiteral } @@ -983,4 +997,5 @@ function TBoldSqlTimeLiteral.GetAsString: String; result := TimeToStr(TimeValue); end; +initialization end. diff --git a/Source/PMapper/SQL/BoldSqlNodesResolver.pas b/Source/PMapper/SQL/BoldSqlNodesResolver.pas index 3a901cb..77292a6 100644 --- a/Source/PMapper/SQL/BoldSqlNodesResolver.pas +++ b/Source/PMapper/SQL/BoldSqlNodesResolver.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldSqlNodesResolver; interface @@ -19,6 +22,7 @@ TBoldSqlNodeResolver = class(TBoldSqlNodeVisitor) fRootNode: TBoldSQLNode; fExternalVariables: TBoldSQLNodeList; protected + function FindSymbolByName(const Name: string): TBSS_Symbol; procedure VisitTBoldSqlNode(N: TBoldSqlNode); override; procedure VisitTBoldSqlListCoercion(N: TBoldSqlListCoercion); override; procedure VisitTBoldSqlOperation(N: TBoldSqlOperation); override; @@ -44,7 +48,10 @@ implementation uses SysUtils, BoldUtils, - BoldPMappersLinkDefault; + BoldPMappersLinkDefault, + BoldPMappers, + BoldIndex, + BoldIndexableList; { TBoldSqlNodeResolver } @@ -67,6 +74,11 @@ procedure TBoldSqlNodeResolver.Execute; fRootNode.AcceptVisitor(self); end; +function TBoldSqlNodeResolver.FindSymbolByName(const Name: string): TBSS_Symbol; +begin + result := SqlSymbolDictionary.SymbolByName[Name]; +end; + procedure TBoldSqlNodeResolver.VisitTBoldSqlDateLiteral( N: TBoldSqlDateLiteral); begin @@ -114,8 +126,17 @@ procedure TBoldSqlNodeResolver.VisitTBoldSqlLiteral(N: TBoldSqlLiteral); procedure TBoldSqlNodeResolver.VisitTBoldSqlMember(N: TBoldSqlMember); begin n.MemberOf.AcceptVisitor(self); - - n.MemberMapper := n.MemberOf.ObjectMapper.MemberPersistenceMappers[n.MemberOf.ObjectMapper.MemberMapperIndexByMemberIndex[n.MemberIndex]] as TBoldMemberSQLMapper; + try + n.MemberMapper := n.MemberOf.ObjectMapper.MemberPersistenceMappers[n.MemberOf.ObjectMapper.MemberMapperIndexByMemberIndex[n.MemberIndex]] as TBoldMemberSQLMapper; + except + on EAssertionFailed do + begin + if not n.MemberOf.HasObjectMapper then + raise EBold.CreateFmt('ObjectMapper not found for member ''%s'', possibly due to unsupported combination of child/parent mapping.', [n.MemberName]) + else + raise; + end; + end; if n.MemberMapper is TBoldLinkDefaultMapper then n.ObjectMapper := (n.MemberMapper as TBoldLinkDefaultMapper).OtherEndObjectMapper; @@ -130,8 +151,12 @@ procedure TBoldSqlNodeResolver.VisitTBoldSqlOperation(N: TBoldSqlOperation); if n.ClassType = TBoldSQLOperation then begin n.Symbol := FindSymbolByName(n.OperationName); + if not Assigned(n.Symbol) then + raise EBold.CreateFmt('InPs SQLSymbol ''%s'' not found, possibly not available for InPs evaluation.', [n.OperationName]); n.Args.TraverseList(self); n.ObjectMapper := n.Symbol.ResolveObjectMapper(n); + if not n.HasObjectMapper then + n.ObjectMapper := n.Symbol.ResolveObjectMapper(n); end; end; @@ -159,4 +184,5 @@ procedure TBoldSqlNodeResolver.VisitTBoldSqlVariableReference(N: TBoldSqlVariabl n.VariableBinding.AddRef; end; +initialization end. diff --git a/Source/PMapper/SQL/BoldSqlQueryGenerator.pas b/Source/PMapper/SQL/BoldSqlQueryGenerator.pas index c5a708b..b14bc9c 100644 --- a/Source/PMapper/SQL/BoldSqlQueryGenerator.pas +++ b/Source/PMapper/SQL/BoldSqlQueryGenerator.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldSqlQueryGenerator; interface @@ -44,7 +47,8 @@ implementation BoldPMappersSQL, BoldPmappersDefault, BoldPMappersLinkDefault, - BoldPMappersAttributeDefault; + BoldPMappersAttributeDefault, + BoldRev; { TBoldSqlQueryGenerator } @@ -120,7 +124,6 @@ procedure TBoldSqlQueryGenerator.HandleRelation(N: TBoldSqlMember); if (n.MemberMapper is TBoldEmbeddedSingleLinkDefaultMapper) then begin - // embedded Singlelinks LastJoinLeftColumn := n.MemberMapper.ColumnDescriptions[0] as TBoldSQLColumnDescription; TableForLastJoinLeft := n.MemberOf.TableReferenceForTable(LastJoinLeftColumn.TableDescription, n.Query, true); n.Query.AddJoin(n.MainTableRef.GetColumnReference(IDCOLUMN_NAME), TableForLastJoinLeft.GetColumnReference(LastJoinLeftColumn.SQLName)); @@ -130,7 +133,6 @@ procedure TBoldSqlQueryGenerator.HandleRelation(N: TBoldSqlMember); LinkMapper := n.MemberMapper as TBoldNonEmbeddedLinkDefaultMapper; if LinkMapper.IsIndirect then begin - // Nonembedded Indirect links TableRefForLink := n.Query.AddTableReference(LinkMapper.LinkClassTableName); n.Query.AddJoin(TablerefForlink.GetColumnReference(LInkMapper.ClosestColumnName), @@ -141,7 +143,6 @@ procedure TBoldSqlQueryGenerator.HandleRelation(N: TBoldSqlMember); end else begin - // Nonembedded Direct links n.Query.AddJoin( n.MainTableRef.GetColumnReference(LinkMapper.ClosestColumnName), n.MemberOf.MainTableRef(n.Query).GetColumnReference(IDCOLUMN_NAME)); @@ -162,11 +163,10 @@ procedure TBoldSqlQueryGenerator.HandleAttribute(N: TBoldSqlMember); ColumnRef := TableRef.GetColumnReference(MainColumn.SQlName); if n.isBoolean and (n.MemberMapper is TBoldPMInteger) then begin - // "boolattr = 1" WCF := TBoldSQLWCFBinaryInfix.Create( TBoldSQLWCFColumnRef.Create(ColumnRef), TBoldSQLWCFInteger.Create(1), '='); - + if not n.QueryOfMemberOfIsEnclosing then begin Query := n.MemberOf.RelinquishQuery; @@ -239,6 +239,6 @@ procedure TBoldSqlQueryGenerator.VisitTBoldSqlTimeLiteral( n.WCF := TBoldSQLWCFTime.Create(n.TimeValue); end; -end. - +initialization +end. diff --git a/Source/PMapper/SQL/BoldSqlSymbols.pas b/Source/PMapper/SQL/BoldSqlSymbols.pas index a213f75..f4fcbc6 100644 --- a/Source/PMapper/SQL/BoldSqlSymbols.pas +++ b/Source/PMapper/SQL/BoldSqlSymbols.pas @@ -1,10 +1,12 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldSqlSymbols; interface uses - BoldPMappersSql, - BoldSQLQuery, + BoldIndexableList, BoldSqlNodes; type @@ -13,6 +15,80 @@ TBSS_Symbol = class(TBoldSqlSymbol) function GetName: String; override; end; + {---TBoldSymbolDictionary---} + TBoldSqlSymbolDictionary = class(TBoldIndexableList) + private + function GetSymbol(const Name: string): TBSS_Symbol; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetSymbolByIndex(index: Integer): TBSS_Symbol; + class var IX_SymbolName: integer; + public + constructor Create(); + property SymbolByName[const name: string]: TBSS_Symbol read GetSymbol; + property Symbols[i: Integer]: TBSS_Symbol read GetSymbolByIndex; default; + end; + +function SqlSymbolDictionary: TBoldSqlSymbolDictionary; + +implementation + +uses + BoldPMappersSql, + BoldSQLQuery, + BoldHashIndexes, + BoldPMappersDefault, + SysUtils, + BoldDefs, + BoldContainers, + BoldPSDescriptionsSQL, BoldPMappersLinkDefault; + +var + SqlSymbols: TBoldSqlSymbolDictionary; + +type + {---TSymbolNameIndex---} + TSymbolNameIndex = class(TBoldStringHashIndex) + protected + function ItemAsKeyString(Item: TObject): string; override; + end; + +function SqlSymbolDictionary: TBoldSqlSymbolDictionary; +begin + result := SqlSymbols; +end; + + {---TSymbolNameIndex---} +function TSymbolNameIndex.ItemAsKeyString(Item: TObject): string; +begin + Result := TBSS_Symbol(Item).Name; +end; + +{ TBSS_Symbol } + +function TBSS_Symbol.GetName: String; +begin + result := copy(ClassName, 6, maxint); +end; + +{ TBoldSqlSymbolDictionary } + +constructor TBoldSqlSymbolDictionary.Create(); +begin + inherited create; + SetIndexCapacity(1); + SetIndexVariable(IX_SymbolName, AddIndex(TSymbolNameIndex.Create)); +end; + +function TBoldSqlSymbolDictionary.GetSymbol(const Name: string): TBSS_Symbol; +begin + Result := TBSS_Symbol(TBoldStringHashIndex(indexes[IX_SymbolName]).FindByString(Name)); +end; + +function TBoldSqlSymbolDictionary.GetSymbolByIndex(index: Integer): TBSS_Symbol; +begin + Result := TBSS_Symbol(Items[index]); +end; + +type TBSS_BinarySymbol = class(TBSS_Symbol) protected procedure ConvertQueryToWCF(SourceNode, DestNode: TBoldSqlNode); @@ -51,12 +127,14 @@ TBSS_LessEQ = class(TBSS_BinaryBooleanSymbol) end; TBSS_GreaterEQ = class(TBSS_BinaryBooleanSymbol) - protected function GetName: String; override; + protected + function GetName: String; override; end; TBSS_SQLLike = class(TBSS_BinarySymbol) protected function GetSQLName: String; override; + procedure BuildWCFOrQuery(OperationNode: TBoldSQLOperation; NameSpace: TBoldSqlNameSpace); override; end; TBSS_SQLLikeCaseInsensitive = class(TBSS_SQLLike) @@ -126,14 +204,14 @@ TBSS_Floor = class(TBSS_UnarySymbol) TBSS_Round = class(TBSS_UnarySymbol) end; - TBSS_ToUpper = class(TBSS_Symbol) + TBSS_ToUpper = class(TBSS_UnarySymbol) protected function GetSQLName: String; override; public procedure BuildWCFOrQuery(OperationNode: TBoldSQLOperation; NameSpace: TBoldSqlNameSpace); override; end; - TBSS_toLower = class(TBSS_Symbol) + TBSS_toLower = class(TBSS_UnarySymbol) protected function GetSQLName: String; override; public @@ -235,6 +313,8 @@ TBSS_includes = class(TBSS_Symbol) end; TBSS_Length = class(TBSS_UnarySymbol) + protected + function GetSQLName: String; override; end; TBSS_ListOperations = class(TBSS_Symbol) @@ -280,12 +360,52 @@ TBSS_OclAsType = class(TBSS_Symbol) procedure BuildWCFOrQuery(OperationNode: TBoldSQLOperation; NameSpace: TBoldSqlNameSpace); override; end; + TBSS_SafeCast = class(TBSS_OclAsType); + TBSS_FilterOnType = class(TBSS_Symbol) public function ResolveObjectMapper(OperationNode: TBoldSqlOperation): TBoldObjectSqlMapper; override; procedure BuildWCFOrQuery(OperationNode: TBoldSQLOperation; NameSpace: TBoldSqlNameSpace); override; end; + TBSS_AsSet = class(TBSS_Symbol) + public + procedure BuildWCFOrQuery(OperationNode: TBoldSQLOperation; NameSpace: + TBoldSqlNameSpace); override; + function ResolveObjectMapper(OperationNode: TBoldSqlOperation): + TBoldObjectSqlMapper; override; + end; + + TBSS_First = class(TBSS_Symbol) + protected + function IsTopLimit: Boolean; virtual; + public + procedure BuildWCFOrQuery(OperationNode: TBoldSQLOperation; NameSpace: + TBoldSqlNameSpace); override; + end; + + TBSS_Last = class(TBSS_First) + protected + function IsTopLimit: Boolean; override; + end; + + TBSS_BoldId = class(TBSS_Symbol) + public + procedure BuildWCFOrQuery(OperationNode: TBoldSQLOperation; NameSpace: TBoldSqlNameSpace); override; + end; + +type + TBSS_BoldIDIs = class(TBSS_BinarySymbol) + public + procedure BuildWCFOrQuery(OperationNode: TBoldSQLOperation; NameSpace: TBoldSqlNameSpace); override; + end; + +type + TBSS_BoldIDIn = class(TBSS_BinarySymbol) + public + procedure BuildWCFOrQuery(OperationNode: TBoldSQLOperation; NameSpace: TBoldSqlNameSpace); override; + end; + { These operations are available in OCL, but have not yet been implemented in ocl2sql @@ -377,43 +497,6 @@ TBSS_Existing = class(TBSS_Symbol) end; } -function FindSymbolByName(Name: String): TBSS_Symbol; - -implementation - -uses - BoldPMappersDefault, - SysUtils, - BoldDefs, - BoldContainers, - BoldPSDescriptionsSQL, - BoldPMConsts; - -var - SqlSymbols: TBoldObjectArray; - -function FindSymbolByName(Name: String): TBSS_Symbol; -var - i: integer; -begin - for i := 0 to sqlSymbols.Count-1 do - begin - if CompareText(TBSS_Symbol(sqlSymbols[i]).name, Name) = 0 then - begin - result := TBSS_Symbol(sqlSymbols[i]); - exit; - end; - end; - raise EBold.CreateFmt(sUnableToFindSymbolForX, [Name]); -end; - -{ TBSS_Symbol } - -function TBSS_Symbol.GetName: String; -begin - result := copy(ClassName, 6, maxint); -end; - { TBSS_Select } procedure TBSS_Select.BuildWCFOrQuery(OperationNode: TBoldSQLOperation; NameSpace: TBoldSqlNameSpace); @@ -548,7 +631,7 @@ procedure TBSS_BinarySymbol.ConvertQueryToWCF(SourceNode, DestNode: TBoldSqlNode function TBSS_UnaryMinus.GetName: String; begin - result := 'unary-'; // do not localize + result := 'unary-'; end; function TBSS_UnaryMinus.GetSQLName: String; @@ -556,13 +639,27 @@ function TBSS_UnaryMinus.GetSQLName: String; result := '-'; end; +{ TBSS_Length } + +function TBSS_Length.GetSQLName: String; +begin + result := 'LEN'; // do not localize +end; + { TBSS_UnarySymbol } procedure TBSS_UnarySymbol.BuildWCFOrQuery( OperationNode: TBoldSQlOperation; NameSpace: TBoldSqlNameSpace); +var + WCF: TBoldSQLWCF; begin - OperationNode.WCF := TBoldSQLWCFUnaryPrefix.Create( - OperationNode.Args[0].RelinquishWCF, sqlName); + WCF := TBoldSQLWCFUnaryPrefix.Create( + OperationNode.Args[0].RelinquishWCF, SQLName); + + if OperationNode.Args[0].HasQuery then + OperationNode.Query := OperationNode.Args[0].RelinquishQuery; + + OperationNode.WCF := WCF; end; { TBSS_Size } @@ -574,9 +671,19 @@ procedure TBSS_Size.BuildWCFOrQuery(OperationNode: TBoldSQLOperation; NameSpace: { TBSS_SQLLike } +procedure TBSS_SQLLike.BuildWCFOrQuery(OperationNode: TBoldSQLOperation; + NameSpace: TBoldSqlNameSpace); +begin + OperationNode.WCF := TBoldSQLWCFBinaryInfix.Create( + OperationNode.Args[0].RelinquishWCF, + TBoldSQLWCFUnaryTransformLikeString.Create(OperationNode.Args[1].RelinquishWCF, ''), SQLname); + + CollectArgWCFs(OperationNode); +end; + function TBSS_SQLLike.GetSQLName: String; begin - result := 'LIKE'; // do not localize + result := 'LIKE'; end; { TBSS_SQLLikeCaseInsensitive } @@ -619,7 +726,7 @@ procedure TBSS_ToUpper.BuildWCFOrQuery(OperationNode: TBoldSQLOperation; function TBSS_ToUpper.GetSQLName: String; begin - result := 'UPPER'; // do not localize + result := 'UPPER'; end; { TBSS_toLower } @@ -633,7 +740,7 @@ procedure TBSS_toLower.BuildWCFOrQuery(OperationNode: TBoldSQLOperation; function TBSS_toLower.GetSQLName: String; begin - result := 'LOWER'; // do not localize + result := 'LOWER'; end; { TBSS_reject } @@ -644,7 +751,7 @@ procedure TBSS_reject.BuildWCFOrQuery(OperationNode: TBoldSQLOperation; NameSpac begin Sel := OperationNode as TBoldSQLIteration; Sel.Query := Sel.LoopVar.RelinquishQuery; - Sel.Query.AddWCF(TBoldSQLWCFUnaryPrefix.Create(OperationNode.Args[1].RelinquishWCF, 'NOT')); // do not localize + Sel.Query.AddWCF(TBoldSQLWCFUnaryPrefix.Create(OperationNode.Args[1].RelinquishWCF, 'NOT')); end; { TBSS_isNull } @@ -654,7 +761,7 @@ procedure TBSS_isNull.BuildWCFOrQuery(OperationNode: TBoldSQLOperation; NameSpac WCF: TBoldSQLWCF; Query: TBoldSQLQuery; begin - WCF := TBoldSQLWCFUnaryPostfix.Create(OperationNode.Args[0].RelinquishWCF, 'IS NULL'); // do not localize + WCF := TBoldSQLWCFUnaryPostfix.Create(OperationNode.Args[0].RelinquishWCF, 'IS NULL'); if OperationNode.args[0].HasQuery then begin @@ -681,11 +788,11 @@ procedure TBSS_GroupFunctions.BuildWCFOrQuery(OperationNode: TBoldSQLOperation; (WCF as TBoldSQLWCFColumnRef).Columnref, SQLName); end else - raise EBoldInternal.CreateFmt('Argument to %s has has no ColumnRef WCF', [Name]) // do not localize + raise EBoldInternal.CreateFmt('Argument to %s has has no ColumnRef WCF', [Name]) end else - raise EBoldInternal.CreateFmt('Argument to %s has no Query', [Name]) // do not localize + raise EBoldInternal.CreateFmt('Argument to %s has no Query', [Name]) end; { TBSS_includes } @@ -698,7 +805,7 @@ procedure TBSS_includes.BuildWCFOrQuery(OperationNode: TBoldSQLOperation; NameSp VarReference: TBoldSQlVariableReference; begin if not OperationNode.args[0].HasQuery then - raise EBoldInternal.Create('Arg 0 for Includes has no Query'); // do not localize + raise EBoldInternal.Create('Arg 0 for Includes has no Query'); Q1IdColumnRef := OperationNode.Args[0].MainTableRef.GetColumnReference(IDCOLUMN_NAME); @@ -708,14 +815,12 @@ procedure TBSS_includes.BuildWCFOrQuery(OperationNode: TBoldSQLOperation; NameSp if VarReference.IsExternalVariable then WCF := TBoldSQLWCFBinaryInfix.CreateWCFForIdList(Q1IDColumnRef, VarReference.VariableBinding.Context) else - // BoldId = VariabelReference.BoldId WCF := TBoldSQLWCFBinaryInfix.create( TBoldSQLWCFColumnRef.Create(Q1IDColumnRef), TBoldSQLWCFColumnRef.Create(OperationNode.Args[1].MainTableRef.GetColumnReference(IDCOLUMN_NAME)) ,'=') end else begin - // BoldID in (Arg1.Query) Query := OperationNode.Args[1].RelinquishQuery; WCF := TBoldSQLWCFInQuery.Create(TBoldSQLWCFColumnRef.Create(Q1IdColumnRef), Query, OperationNode.Args[1].MainTableRef(Query)); end; @@ -729,21 +834,21 @@ procedure TBSS_includes.BuildWCFOrQuery(OperationNode: TBoldSQLOperation; NameSp function TBSS_Average.GetSQLName: String; begin - result := 'AVG'; // do not localize + result := 'AVG'; end; { TBSS_MinValue } function TBSS_MinValue.GetSQLName: String; begin - result := 'MIN'; // do not localize + result := 'MIN'; end; { TBSS_Maxvalue } function TBSS_Maxvalue.GetSQLName: String; begin - result := 'MAX'; // do not localize + result := 'MAX'; end; { TBSS_Exists } @@ -763,13 +868,12 @@ procedure TBSS_ForAll.BuildWCFOrQuery(OperationNode: TBoldSQLOperation; NameSpac var Query: TBoldSqlQuery; TempWCF: TBoldSqlWCF; - // ForAll(x) -> not Exists(not x) begin Query := (OperationNode as TBoldSqlIteration).LoopVar.RelinquishQuery; - tempWcf := TBoldSQLWCFUnaryPrefix.Create(OperationNode.Args[1].RelinquishWCF, 'NOT'); // do not localize + tempWcf := TBoldSQLWCFUnaryPrefix.Create(OperationNode.Args[1].RelinquishWCF, 'NOT'); Query.AddWCF(TempWcf); TempWCF := TBoldSQLWCFExists.Create(Query, OperationNode.Args[0].MaintableRef(Query)); - OperationNode.WCF := TBoldSQLWCFUnaryPrefix.Create(TempWCF, 'NOT') // do not localize + OperationNode.WCF := TBoldSQLWCFUnaryPrefix.Create(TempWCF, 'NOT') end; { TBSS_orderby } @@ -785,12 +889,12 @@ procedure TBSS_orderby.BuildWCFOrQuery(OperationNode: TBoldSQLOperation; NameSpa Loopvar: TBoldSqlVariableBinding; begin if not (OperationNode.args[1] is TBoldSqlMember) then - raise EBold.Create(sArgToOrderByMustBeMember); + raise EBold.Create('Argument to OrderBy must be a Member'); OrderByMember := OperationNode.args[1] as TBoldSqlMember; if OrderByMember.MemberMapper.ColumnCount <> 1 then - raise EBold.Create(sArgToOrderByMustHaveExactlyOneColumn); + raise EBold.Create('Argument to OrderBy must have exactly 1 column'); Loopvar := (OperationNode as TBoldSQlIteration).Loopvar; @@ -802,7 +906,7 @@ procedure TBSS_orderby.BuildWCFOrQuery(OperationNode: TBoldSQLOperation; NameSpa OrderByColumnName := OrderByMember.MemberMapper.ColumnDescriptions[0].SQLName; ColRef := TableRef.GetColumnReference(OrderByColumnName); - Query.AddColumnToOrderBy(ColRef); + Query.AddColumnToOrderBy(ColRef, False); OperationNode.WCF := Loopvar.RelinquishWCF; @@ -812,8 +916,41 @@ procedure TBSS_orderby.BuildWCFOrQuery(OperationNode: TBoldSQLOperation; NameSpa { TBSS_orderDescending } procedure TBSS_orderDescending.BuildWCFOrQuery(OperationNode: TBoldSQLOperation; NameSpace: TBoldSqlNameSpace); +var + Query: TBoldSqlQuery; + OrderByMember: TBoldSqlMember; + OrderByColumnName: String; + tableDescription: TBoldSQLTableDescription; + TableRef: TBoldSQlTableReference; + ColRef: TBoldSqlColumnReference; + Loopvar: TBoldSqlVariableBinding; +const + sArgToOrderByMustBeMember = 'Argument to OrderBy must be a Member'; + sArgToOrderByMustHaveExactlyOneColumn = 'Argument to OrderBy must have exactly 1 column'; begin - Raise EBold.Create(sOrderByDescendingNotImplemented); + if not (OperationNode.args[1] is TBoldSqlMember) then + raise EBold.Create(sArgToOrderByMustBeMember); + + OrderByMember := OperationNode.args[1] as TBoldSqlMember; + + if OrderByMember.MemberMapper.ColumnCount <> 1 then + raise EBold.Create(sArgToOrderByMustHaveExactlyOneColumn); + + Loopvar := (OperationNode as TBoldSQlIteration).Loopvar; + + Query := Loopvar.RelinquishQuery; + + TableDescription := (OrderByMember.MemberMapper.ColumnDescriptions[0].Owner as TBoldSQLTableDescription); + TableRef := OperationNode.TableReferenceForTable(TableDescription, Query, false); + + OrderByColumnName := OrderByMember.MemberMapper.ColumnDescriptions[0].SQLName; + ColRef := TableRef.GetColumnReference(OrderByColumnName); + + Query.AddColumnToOrderBy(ColRef, True); + + OperationNode.WCF := Loopvar.RelinquishWCF; + + OperationNode.Query := Query; end; { TBSS_isEmpty } @@ -873,13 +1010,39 @@ procedure TBSS_Intersection.BuildWCFOrQuery( procedure TBSS_SymmetricDifference.BuildWCFOrQuery( OperationNode: TBoldSQLOperation; NameSpace: TBoldSqlNameSpace); // a->symmetricDifference(b) >> ((id in a) xor (id in b)) +// SQL does not support XOR, so we have to use inline version: +// a->symmetricDifference(b) >> (id in a) and (not (id in b)) or +// (id in b) and (not (id in a)) begin OperationNode.NewQuery(nameSpace); +// OperationNode.Query.AddWCF( +// TBoldSQLWCFBinaryInfix.Create( +// CreateBoldIdMatchWCF(OperationNode, OperationNode.args[0]), +// CreateBoldIdMatchWCF(OperationNode, OperationNode.args[1]), +// 'XOR')); // do not localize + +{ Doesnt work, because queries of the args are relinquished for the first part OperationNode.Query.AddWCF( TBoldSQLWCFBinaryInfix.Create( + TBoldSQLWCFBinaryInfix.Create( + CreateBoldIdMatchWCF(OperationNode, OperationNode.args[0]), + TBoldSQLWCFUnaryPrefix.Create( + CreateBoldIdMatchWCF(OperationNode, OperationNode.args[1]), + 'NOT'), // do not localize + 'AND'), // do not localize + TBoldSQLWCFBinaryInfix.Create( + CreateBoldIdMatchWCF(OperationNode, OperationNode.args[1]), + TBoldSQLWCFUnaryPrefix.Create( + CreateBoldIdMatchWCF(OperationNode, OperationNode.args[0]), + 'NOT'), // do not localize + 'AND'), // do not localize + 'OR')); // do not localize +} + // Solution: custom WCF for XOR + OperationNode.Query.AddWCF( + TBoldSQLWCFXOR.Create( CreateBoldIdMatchWCF(OperationNode, OperationNode.args[0]), - CreateBoldIdMatchWCF(OperationNode, OperationNode.args[1]), - 'XOR')); // do not localize + CreateBoldIdMatchWCF(OperationNode, OperationNode.args[1]))); end; { TBSS_Difference } @@ -997,7 +1160,10 @@ procedure TBSS_OclAsType.BuildWCFOrQuery(OperationNode: TBoldSQLOperation; OperationNode.Args[0].MainTableRef.GetColumnReference(IDCOLUMN_NAME)); end else + begin OperationNode.Query := OperationNode.Args[0].RelinquishQuery; + OperationNode.CopyTableReferences(OperationNode.Args[0]); + end; end; function TBSS_OclAsType.ResolveObjectMapper( @@ -1018,8 +1184,8 @@ procedure TBSS_FilterOnType.BuildWCFOrQuery( begin ObjectMapper := OperationNode.Args[1].ObjectMapper as TBoldObjectDefaultMapper; TypeColRef := TBoldSQLWCFColumnRef.Create(OperationNode.Args[0].MainTableRef.GetColumnReference(TYPECOLUMN_NAME)); - TypeValue := TBoldSQLWCFGenericExpression.Create('(' + ObjectMapper.SubClassesID + ')'); - WCF := TBoldSQLWCFBinaryInfix.Create(TypeColRef, TypeValue, 'IN'); // do not localize + TypeValue := TBoldSQLWCFGenericExpression.Create('('+ObjectMapper.SubClassesID+')'); + WCF := TBoldSQLWCFBinaryInfix.Create(TypeColRef, TypeValue, 'IN'); if OperationNode.Args[0].HasQuery then OperationNode.Query := OperationNode.Args[0].RelinquishQuery; @@ -1029,7 +1195,7 @@ procedure TBSS_FilterOnType.BuildWCFOrQuery( else begin if assigned(OperationNode.Args[0].WCF) then - WCF := TBoldSQLWCFBinaryInfix.Create(WCF, OperationNode.Args[0].RelinquishWCF, 'AND'); // do not localize + WCF := TBoldSQLWCFBinaryInfix.Create(WCF, OperationNode.Args[0].RelinquishWCF, 'AND'); OperationNode.WCF := WCF; end; @@ -1042,8 +1208,137 @@ function TBSS_FilterOnType.ResolveObjectMapper( result := OperationNode.Args[1].ObjectMapper; end; +{ TBSS_AsSet } + +procedure TBSS_AsSet.BuildWCFOrQuery(OperationNode: TBoldSQLOperation; + NameSpace: TBoldSqlNameSpace); +var + Query: TBoldSqlQuery; +begin + Query := OperationNode.Args[0].RelinquishQuery; + + // Distinct is usually not necessary because inPS evaluation returns no + // duplicate objects. But if asSet is used in a (Sub-)Select, this is indeed needed. + Query.Distinct := True; + + // Further simply pass Result without doing anything more + OperationNode.WCF := operationNode.Args[0].RelinquishWCF; + OperationNode.Query := Query; +end; + +function TBSS_AsSet.ResolveObjectMapper(OperationNode: TBoldSqlOperation): + TBoldObjectSqlMapper; +begin + result := OperationNode.Args[0].ObjectMapper; +end; + +{ TBSS_First } + +procedure TBSS_First.BuildWCFOrQuery(OperationNode: TBoldSQLOperation; + NameSpace: TBoldSqlNameSpace); +var + Query: TBoldSqlQuery; +begin + Query := OperationNode.Args[0].RelinquishQuery; + + // Limit in Query einstellen + Query.SetLimit(IsTopLimit); + + // Ansonsten simple Weitergabe des Ergebnisses ohne etwas zu machen + OperationNode.WCF := operationNode.Args[0].RelinquishWCF; + OperationNode.Query := Query; +end; + +function TBSS_First.IsTopLimit: Boolean; +begin + Result := True; +end; + +{ TBSS_Last } + +function TBSS_Last.IsTopLimit: Boolean; +begin + Result := False; +end; + +{ TBSS_BoldIDIs } + +procedure TBSS_BoldIDIs.BuildWCFOrQuery( + OperationNode: TBoldSQLOperation; NameSpace: TBoldSqlNameSpace); +var + TypeColRef: TBoldSQLWCFColumnRef; +begin + TypeColRef := TBoldSQLWCFColumnRef.Create(OperationNode.Args[0].MainTableRef.GetColumnReference(IDCOLUMN_NAME)); + OperationNode.WCF := TBoldSQLWCFBinaryInfix.Create(TypeColRef, OperationNode.Args[1].RelinquishWCF, '='); + CollectArgWCFs(OperationNode); +end; + +{ TBSS_BoldIDIn } + +procedure TBSS_BoldIDIn.BuildWCFOrQuery( + OperationNode: TBoldSQLOperation; NameSpace: TBoldSqlNameSpace); +var + TypeColRef: TBoldSQLWCFColumnRef; + TypeValue: TBoldSQLWCFGenericExpression; + aWCF: TBoldSqlWCF; + sIDs: string; +begin + TypeColRef := TBoldSQLWCFColumnRef.Create(OperationNode.Args[0].MainTableRef.GetColumnReference(IDCOLUMN_NAME)); + aWCF := OperationNode.Args[1].RelinquishWCF; + sIDs := aWCF.GetAsString(OperationNode.Args[0].Query); + aWCF.Free; + // Übergebenen String in ID-Liste umwandeln -> "" entfernen + // Außer es ist Paramter (:Param) + if (Length(sIDs) > 0) then begin + if (sIDs[1] = '''') then begin + sIDs := Copy(sIDs, 2, Length(sIDs) - 2); + end else if (sIDs[1] = ':') then begin + sIDs := OperationNode.Args[0].Query.Params.ParamValues[Copy(sIDs, 2, MaxInt)]; + end; + end; + TypeValue := TBoldSQLWCFGenericExpression.Create('(' + sIDs + ')'); + OperationNode.WCF := TBoldSQLWCFBinaryInfix.Create(TypeColRef, TypeValue, 'in'); // do not localize + CollectArgWCFs(OperationNode); +end; + +{ TBSS_BoldId } + +procedure TBSS_BoldId.BuildWCFOrQuery(OperationNode: TBoldSQLOperation; + NameSpace: TBoldSqlNameSpace); +var + SQLNode: TBoldSQLNode; + Query: TBoldSqlQuery; + SqlMember: TBoldSqlMember; + TableRefs: TBoldSQLTableReferenceList; + ColumnName: string; +begin + Query := nil; + SQLNode := OperationNode.Args[0]; + if SQLNode is TBoldSqlVariableReference then + begin + Query := TBoldSqlVariableReference(SQLNode).Query; + ColumnName := IDCOLUMN_NAME; + end + else + if (SQLNode is TBoldSqlMember) then + begin + SqlMember := TBoldSqlMember(SQLNode); + if SqlMember.MemberMapper.IsStoredInObject and + (SqlMember.memberOf is TBoldSqlVariableReference) then + begin + ColumnName := SqlMember.MemberMapper.ColumnDescriptions[0].sqlName; + Query := TBoldSqlVariableReference(SqlMember.memberOf).VariableBinding.Query; + end; + end; + if not Assigned(Query) then + raise EBoldInternal.Create(className + ': No Query found.'); + TableRefs := Query.TableReferences; + OperationNode.WCF := TBoldSQLWCFColumnRef.Create(TableRefs[TableRefs.Count-1].GetColumnReference(ColumnName)); +end; + initialization - sqlSymbols := TBoldObjectArray.Create(0, [bcoDataOwner]); + TBoldSqlSymbolDictionary.IX_SymbolName := -1; + sqlSymbols := TBoldSqlSymbolDictionary.Create; sqlSymbols.Add(TBSS_Add.Create); sqlSymbols.Add(TBSS_Equal.Create); sqlSymbols.Add(TBSS_NotEqual.Create); @@ -1064,6 +1359,9 @@ initialization sqlSymbols.Add(TBSS_not.Create); sqlSymbols.Add(TBSS_UnaryMinus.Create); sqlSymbols.Add(TBSS_isNull.Create); + sqlSymbols.Add(TBSS_Abs.Create); + sqlSymbols.Add(TBSS_Floor.Create); + sqlSymbols.Add(TBSS_Round.Create); sqlSymbols.Add(TBSS_Size.Create); sqlSymbols.Add(TBSS_Select.Create); sqlSymbols.Add(TBSS_Reject.Create); @@ -1086,14 +1384,19 @@ initialization sqlSymbols.Add(TBSS_ToLower.Create); sqlSymbols.Add(TBSS_Union.Create); sqlSymbols.Add(TBSS_Intersection.Create); + sqlSymbols.Add(TBSS_SymmetricDifference.Create); sqlSymbols.Add(TBSS_Difference.Create); sqlSymbols.Add(TBSS_oclIsTypeOf.Create); sqlSymbols.Add(TBSS_oclIsKindOf.Create); sqlSymbols.Add(TBSS_oclAsType.Create); + sqlSymbols.Add(TBSS_SafeCast.Create); sqlSymbols.Add(TBSS_FilterOnType.Create); - - // SymmetricDiffernece is not supported since SQL does not support XOR -// sqlSymbols.Add(TBSS_SymmetricDifference.Create); + sqlSymbols.Add(TBSS_AsSet.Create); + sqlSymbols.Add(TBSS_First.Create); + sqlSymbols.Add(TBSS_Last.Create); + sqlSymbols.Add(TBSS_BoldId.Create); + sqlSymbols.Add(TBSS_BoldIDIs.Create); + sqlSymbols.Add(TBSS_BoldIDIn.Create); finalization FreeAndNil(sqlSymbols); diff --git a/Source/PMapper/Validator/BoldDbDataValidator.pas b/Source/PMapper/Validator/BoldDbDataValidator.pas index 7e73b22..c0c6b8d 100644 --- a/Source/PMapper/Validator/BoldDbDataValidator.pas +++ b/Source/PMapper/Validator/BoldDbDataValidator.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldDbDataValidator; interface @@ -21,6 +24,7 @@ TBoldDbDataValidator = class(TBoldDbValidator) fTypeTestedTables: TStringList; fQuery: IBoldQuery; fExistenceInParentTestedTables: TStringList; + FPauseBetweenQueries: integer; function GetQuery: IBoldQuery; procedure SuggesttableInsert(table: TBoldSQLTableDescription; IdList, TypeList: TStrings); @@ -29,18 +33,22 @@ TBoldDbDataValidator = class(TBoldDbValidator) function Prepare2TableTest(SQLTemplate: String; CheckList: TStringList; args: array of const; table1, table2: String; IdList: TStrings; TypeList: TStrings = nil): Boolean; procedure AddRemedyForDeleteObjects(Mapper: TBoldObjectSQLMapper; IdList: TStringList); procedure DeActivate; override; + procedure OpenQuery; property Query: IBoldQuery read GetQuery; property TypeTestedTables: TStringList read fTypeTestedTables; property ExistenceInParentTestedTables: TStringList read fExistenceInParentTestedTables; public - constructor Create(owner: Tcomponent); override; - destructor Destroy; override; + constructor Create(owner: TComponent); override; + destructor destroy; override; procedure ValidateExistence(ObjectSQLMapper: TBoldObjectSQLMapper); procedure ValidateStrayObjects(ObjectDefaultMapper: TBoldObjectDefaultMapper); procedure ValidateRelations(ObjectSQLMapper: TBoldObjectSQLMapper); + procedure ValidateNotNullColumns(ObjectSQLMapper: TBoldObjectSQLMapper); + procedure ValidateNotNullForColumn(BoldSQLColumnDescription: TBoldSQLColumnDescription); procedure ValidateLinkObjectDupes(ObjectSQLMapper: TBoldObjectSQLMapper); procedure ValidateLinkObjects(ObjectSQLMapper: TBoldObjectSQLMapper); procedure Validate; override; + property PauseBetweenQueries: integer read FPauseBetweenQueries write FPauseBetweenQueries; end; implementation @@ -54,10 +62,9 @@ implementation BoldDefs, SysUtils, BoldUtils, - BoldPMConsts; + BoldMath; const - Field_BOLD_ID = 'BOLD_ID'; ExistenceInParentTest: String = 'SELECT OWN.BOLD_ID, OWN.BOLD_TYPE ' + BOLDCRLF + 'FROM %s OWN ' + BOLDCRLF + @@ -65,7 +72,6 @@ implementation ' SELECT PARENT.BOLD_ID ' + BOLDCRLF + ' FROM %s PARENT ' + BOLDCRLF + ' WHERE PARENT.BOLD_ID = OWN.BOLD_ID)'; - // [Own, Parent] ExistenceInChildTest: string = 'SELECT PARENT.BOLD_ID, PARENT.BOLD_TYPE ' + BOLDCRLF + @@ -75,16 +81,13 @@ implementation ' SELECT BOLD_ID' + BOLDCRLF + ' FROM %s OWN ' + BOLDCRLF + ' WHERE OWN.BOLD_ID = PARENT.BOLD_ID)'; - // [parent, types, Own] TypeTest: String = 'SELECT PARENT.BOLD_ID, PARENT.BOLD_TYPE, OWN.BOLD_TYPE' + BOLDCRLF + 'FROM %s PARENT, %s OWN' + BOLDCRLF + 'WHERE (PARENT.BOLD_ID = OWN.BOLD_ID) AND' + BOLDCRLF + ' (PARENT.BOLD_TYPE <> OWN.BOLD_TYPE)'; - // [Parent, Own] - // find all objects that are related, but the other end does not exist. RelationTest: String = 'SELECT OWN.%s, OWN.BOLD_ID' + BOLDCRLF + @@ -93,7 +96,13 @@ implementation ' SELECT RELATED.BOLD_ID' + BOLDCRLF + ' FROM %2:s RELATED' + BOLDCRLF + ' WHERE RELATED.BOLD_ID = OWN.%0:s)'; - // [Link, OwnTable, RelatedTable] + + DuplicateSingleLinkTest: String = + 'SELECT %0:s' + BOLDCRLF + + 'FROM %s' + BOLDCRLF + + 'WHERE %0:s <> -1 ' + BOLDCRLF + + 'GROUP BY %0:s' + BOLDCRLF + + 'HAVING COUNT(*) > 1'; LinkObjectDupesTest: String = 'SELECT LINKTABLE.BOLD_ID, LINKTABLE.%s, LINKTABLE.%s, COUNT(*)' + BOLDCRLF + @@ -101,20 +110,15 @@ implementation 'GROUP BY LINKTABLE.%0:s, LINKTABLE.%1:s' + BOLDCRLF + 'HAVING COUNT(*) >= 2' + BOLDCRLF + 'ORDER BY %0:s, %1:s'; - // [Link1, link2, linktable] - // linkobjects with empty ends LinkObjectTest: String = 'SELECT BOLD_ID' + BOLDCRLF + 'FROM %s' + BOLDCRLF + 'WHERE %s = -1 or %s = -1'; - - // Linkobjects pointing to nonexisting objects LinkObjectTest2: String = 'SELECT LT.BOLD_ID' + BOLDCRLF + 'FROM %s LT' + BOLDCRLF + 'WHERE NOT EXISTS (SELECT T.BOLD_ID FROM %s T WHERE LT.%s = T.BOLD_ID)'; - //[LinkTable, OtherTable, LinkColumn] StrayObjectsTest: string = @@ -126,7 +130,6 @@ implementation 'SELECT T1.BOLD_ID, T1.BOLD_TYPE ' + BOLDCRLF + 'FROM %s T1, %s T2 ' + BOLDCRLF + 'WHERE (T1.%s = T2.BOLD_ID) and (T2.%s <> T1.BOLD_ID)'; - // [Table1, table2, link1, link2Own, Parent] { TBoldDbDataValidator } @@ -147,7 +150,16 @@ function TBoldDbDataValidator.MemberIsInherited( result := MemberMapper.MemberIndex < MemberMapper.ObjectPersistenceMapper.SuperClass.MemberPersistenceMappers.count; end; +procedure TBoldDbDataValidator.OpenQuery; +begin + Sleep(1000*PauseBetweenQueries); + Query.Open; +end; + function TBoldDbDataValidator.Prepare2TableTest(SQLTemplate: String; CheckList: TStringList; args: array of const; table1, table2: String; IdList: TStrings; TypeList: TStrings = nil): Boolean; +var + BoldIdField: IBoldField; + BoldTypeField: IBoldField; begin if not assigned(CheckList) or ((CheckList.IndexOf(Table1 + ':' + Table2) = -1) and @@ -156,13 +168,16 @@ function TBoldDbDataValidator.Prepare2TableTest(SQLTemplate: String; CheckList: IdList.Clear; if assigned(typelist) then typeList.Clear; + Query.Close; Query.AssignSQLText(format(SQLTemplate, args)); - Query.Open; + OpenQuery; + BoldIdField := Query.FieldByName('BOLD_ID'); + BoldTypeField := Query.FieldByName('BOLD_TYPE'); while not query.eof do begin - IdList.Add(Query.FieldByName(Field_BOLD_ID).AsString); + IdList.Add(BoldIdField.AsString); if assigned(Typelist) then - TypeList.Add(Query.FieldByName('BOLD_TYPE').AsString); // do not localize + TypeList.Add(BoldTypeField.AsString); Query.Next; end; Query.Close; @@ -179,30 +194,27 @@ procedure TBoldDbDataValidator.Validate; i: integer; ObjectPMapper: TBoldObjectSQLMapper; begin +(* if not PersistenceHandle.DatabaseInterface.Connected then begin - Remedy.Add(sDBNotOpened); - BoldLog.Log(sDBMustBeOpened); + BoldLog.Log('Database must be opened before Structurevalidation is performed!'); exit; end; - +*) BoldLog.ProgressMax := SystemSQLMapper.ObjectPersistenceMappers.count - 1; for i := 0 to SystemSQLMapper.ObjectPersistenceMappers.count - 1 do begin ObjectPMapper := SystemSQLMapper.ObjectPersistenceMappers[i] as TBoldObjectSQLMapper; if assigned(ObjectPMapper) then begin - BoldLog.LogHeader := Format(sProcessingClass, [ObjectPMapper.ExpressionName]); + BoldLog.LogHeader := Format('Processing class %d %s', [i, ObjectPMapper.ExpressionName]); ValidateExistence(ObjectPMapper); ValidateRelations(ObjectPMapper); +// ValidateNotNullColumns(ObjectPMapper); if ObjectPmapper is TBoldObjectDefaultMapper then ValidateStrayObjects(ObjectPMapper as TBoldObjectDefaultMapper); - if ObjectPMapper.IsLinkClass then begin - // The SQL for this is broken... why? - // - // ValidateLinkObjectDupes(ObjectPMapper); ValidateLinkObjects(ObjectPmapper); end; end; @@ -224,7 +236,6 @@ procedure TBoldDbDataValidator.SuggesttableInsert(table: TBoldSQLTableDescriptio UnsupportedColumns := ''; Skip := false; - // check all columns except BodlID/BoldType for j := 2 to Table.ColumnsList.Count - 1 do begin Column := Table.ColumnsList[j] as TBoldSQLColumnDescription; @@ -236,18 +247,17 @@ procedure TBoldDbDataValidator.SuggesttableInsert(table: TBoldSQLTableDescriptio NotNullValues := NotNullvalues + ', '''''; ftLargeint, ftBCD, ftCurrency, ftFloat, ftSmallint, ftInteger, ftWord : NotNullvalues := NotNullvalues + ', 0'; - ftBoolean: NotNullValues := NotNullValues + ', false'; // do not localize + ftBoolean: NotNullValues := NotNullValues + ', false'; ftDate: NotNullValues := NotNullValues + ', ' + DateToStr(0.0); ftTime: NotNullValues := NotNullValues + ', ' + TimeToStr(0.0); ftDateTime: NotNullValues := NotNullValues + ', ' + DateTimeToStr(0.0); else begin - // ftBytes, ftVarBytes, ftAutoInc, ftGraphic, ftFmtMemo, - // ftParadoxOle, ftDBaseOle, ftTypedBinary, ftCursor, - // ftADT, ftArray, ftReference, ftDataSet, ftOraBlob, ftOraClob, - // ftVariant, ftInterface, ftIDispatch, ftGuid + + + skip := true; - NotNullValues := NotNullValues + ', '; // do not localize + NotNullValues := NotNullValues + ', '; if UnsupportedColumns <> '' then UnsupportedColumns := UnsupportedColumns + ', '; @@ -257,14 +267,14 @@ procedure TBoldDbDataValidator.SuggesttableInsert(table: TBoldSQLTableDescriptio end; end; - remedySQL := 'INSERT INTO %s (BOLD_ID, BOLD_TYPE%s) VALUES (%s, %s%s)'; // do not localize + remedySQL := 'INSERT INTO %s (BOLD_ID, BOLD_TYPE%s) VALUES (%s, %s%s)'; if skip then begin - Remedy.add(format(sColumnsHaveUnsupportedType, [UnsupportedColumns])); - remedySQL := '// ' + remedySQL; + Remedy.add(format('-- Required column(s) %s has unsupported type(s)', [UnsupportedColumns])); + remedySQL := '-- '+ remedySQL; end else - remedy.Add(Format(sAddMissingEntries, [Table.SQLName])); + remedy.Add(Format('-- add missing entries into %s', [Table.SQLName])); for j := 0 to idlist.count - 1 do Remedy.Add(format(remedySQL, [Table.SQLName, NotNullColumns, IdList[j], TypeList[j], NotNullValues])); @@ -292,26 +302,36 @@ procedure TBoldDbDataValidator.ValidateExistence(ObjectSQLMapper: TBoldObjectSQL tempMapper := ObjectSQLMapper; while assigned(TempMapper) do begin - if assigned(tempMapper.Maintable) and (Tables.IndexOf(tempMapper.Maintable) = -1) then + if (tempMapper.Maintable<>nil) and (Tables.IndexOf(tempMapper.Maintable) = -1) then Tables.Add(tempMapper.Maintable); TempMapper := TempMapper.Superclass as TBoldObjectSQLMapper; end; - for i := 0 to Tables.count - 2 do + for i := 0 to Tables.count-2 do begin + if Tables[i]=nil then + begin + BoldLog.LogFmt('TBoldDbDataValidator.ValidateExistence: %s Tables[%d]=nil', [ObjectSQLMapper.ExpressionName, I]); + Continue; + end; + if Tables[i+1]=nil then + begin + BoldLog.LogFmt('TBoldDbDataValidator.ValidateExistence: %s Tables[%d+1]=nil', [ObjectSQLMapper.ExpressionName, I]); + Continue; + end; SubTable := Tables[i].SQLName; - SuperTable := Tables[i + 1].SQLName; + SuperTable := Tables[i+1].SQLName; if Prepare2TableTest(ExistenceInParentTest, ExistenceInParentTestedTables, [SubTable, SuperTable], SubTable, SuperTable, IdList, TypeList) then begin - BoldLog.LogFmt(sLogObjectsMissingInParentTable, [SubTable, SuperTable]); - Boldlog.Log(IdList.CommaText); + BoldLog.LogFmt('The following objects exists in %s, but not in parent table %s', [SubTable, SuperTable], ltWarning); + Boldlog.Log(IdList.CommaText, ltDetail); SuggestTableInsert(Tables[i+1], IdList, TypeList); end; if Prepare2TableTest(TypeTest, TypeTestedTables, [SuperTable, SubTable], SuperTable, SubTable, IdList) then begin - BoldLog.LogFmt(sLogObjectsHaveDifferentType, [SuperTable, SubTable]); - Boldlog.Log(IdList.CommaText); + BoldLog.LogFmt('The following objects have different type in table %s and %s', [SuperTable, SubTable], ltWarning); + Boldlog.Log(IdList.CommaText, ltDetail); end; end; @@ -330,8 +350,8 @@ procedure TBoldDbDataValidator.ValidateExistence(ObjectSQLMapper: TBoldObjectSQL (ObjectSQLMapper as TBoldObjectDefaultMapper).SubClassesID, SubTable], SubTable, SuperTable, IdList, TypeList) then begin - BoldLog.LogFmt(sLogObjectsMissingInChildtable, [SuperTable, SubTable]); - Boldlog.Log(IdList.CommaText); + BoldLog.LogFmt('The following objects exists in %s, but not in child table %s', [SuperTable, SubTable], ltWarning); + Boldlog.Log(IdList.CommaText, ltDetail); SuggesttableInsert(ObjectSQLMapper.MainTable, IdList, TypeList); end; end; @@ -350,23 +370,29 @@ procedure TBoldDbDataValidator.ValidateLinkObjectDupes( LinkTable, LinkColumn1, LinkColumn2: String; IdList: TStringList; + Link1Field: IBoldField; + Link2Field: IBoldField; + BoldIdField: IBoldField; begin IdList := TStringList.create; LinkColumn1 := (ObjectSQLMapper.LinkClassRole1 as TBoldEmbeddedSingleLinkDefaultMapper).MainColumnName; LinkColumn2 := (ObjectSQLMapper.LinkClassRole2 as TBoldEmbeddedSingleLinkDefaultMapper).MainColumnName; LinkTable := ObjectSQLMapper.MainTable.SQLName; - + Query.Close; Query.AssignSQLText(format(LinkObjectDupesTest, [LInkColumn1, LinkColumn2, LInkTable])); - Query.Open; + OpenQuery; LastLink1 := -Maxint; LastLInk2 := -MaxInt; + Link1Field := Query.FieldByName(LinkColumn1); + Link2Field := Query.FieldByName(LinkColumn2); + BoldIdField := Query.FieldByName('BOLD_ID'); while not query.eof do begin - link1 := Query.FieldByName(LinkColumn1).AsInteger; - link2 := Query.FieldByName(LinkColumn2).AsInteger; + link1 := Link1Field.AsInteger; + link2 := Link2Field.AsInteger; if (Link1 = LastLink1) and (link2 = lastlink2) then - IdList.Add(Query.FieldByName(Field_BOLD_ID).AsString) + IdList.Add(BoldIdField.AsString) else begin LastLInk1 := link1; @@ -375,8 +401,8 @@ procedure TBoldDbDataValidator.ValidateLinkObjectDupes( end; if IdList.Count > 0 then begin - BoldLog.Log(sLogLinkObjectsAreDupes); - BoldLog.Log(IdList.CommaText); + BoldLog.Log('The following Linkobjects are duplicates:', ltWarning); + BoldLog.Log(IdList.CommaText, ltDetail); end; IdList.Free; end; @@ -387,48 +413,82 @@ procedure TBoldDbDataValidator.ValidateLinkObjects(ObjectSQLMapper: TBoldObjectS LinkColumn1, LinkColumn2: String; IdList: TStringList; -procedure CheckSpacePointers(LinkMApper: TBoldEmbeddedSingleLInkDefaultMapper); -begin - Query.AssignSQLText(format(LinkObjectTest2, [ - LinkTable, - LInkMapper.OtherEndObjectMapper.Maintable.SQLName, - LinkMapper.MainColumnName])); - Query.Open; - - while not query.eof do + procedure CheckSpacePointers(LinkMApper: TBoldEmbeddedSingleLInkDefaultMapper); + var + MainTableName: string; + TempIdList: TStringList; + s: string; + BoldIdField: IBoldField; begin - IdList.Add(Query.FieldByName(Field_BOLD_ID).AsString); - Query.Next; - end; - - if IdList.Count > 0 then - begin - BoldLog.LogFmt(sLogLinkObjectsLinkUnexistingObjects, [ObjectSQLmapper.ExpressionName]); - BoldLog.Log(IdList.CommaText); - Remedy.Add(Format(sCommentRemoveSpaceLinkObjects, [ObjectSQLmapper.ExpressionName])); - AddRemedyForDeleteObjects(ObjectSQLMapper, IDList); + if LinkMapper=nil then + begin + BoldLog.LogFmt('TBoldDbDataValidator.ValidateLinkObjects->CheckSpacePointers: %s: LinkMapper=nil', [ObjectSQLMapper.ExpressionName]); + Exit; + end; + Assert(PersistenceHandle.BoldModel.MoldModel.GetClassByName(LinkMapper.OtherEndObjectMapper.ExpressionName) <> nil, 'Class ' + LinkMapper.ObjectPersistenceMapper.ExpressionName + ' not found.'); + if LInkMapper.OtherEndObjectMapper=nil then + begin + BoldLog.LogFmt('TBoldDbDataValidator.ValidateLinkObjects->CheckSpacePointers: %s: LinkMapper.OtherEndObjectMapper=nil', [ObjectSQLMapper.ExpressionName]); + Exit; + end; + if LInkMapper.OtherEndObjectMapper.Maintable<>nil then + MainTableName := LinkMapper.OtherEndObjectMapper.Maintable.SQLName + else + begin + MainTableName := 'Bold_Object'; // it would be more efficient to find first concrete superclass so that we search more concrete table instead of all in Bold_Object + if not PersistenceHandle.BoldModel.MoldModel.GetClassByName(LinkMapper.OtherEndObjectMapper.ExpressionName).IsAbstract or not LinkMapper.OtherEndObjectMapper.HasSubClasses then + BoldLog.LogFmt('TBoldDbDataValidator.ValidateLinkObjects->CheckSpacePointers: %s: Link: %s LinkMapper.OtherEndObjectMapper.Maintable=nil, substituting bold_object', [ObjectSQLMapper.ExpressionName, LinkMapper.MainColumnName]); + end; + Query.Close; + Query.AssignSQLText(format(LinkObjectTest2, [ + LinkTable, + MainTableName, + LinkMapper.MainColumnName])); + OpenQuery; + BoldIdField := Query.FieldByName('BOLD_ID'); + TempIdList := TStringList.Create; + try + while not query.eof do + begin + s := BoldIdField.AsString; + if IdList.IndexOf(s) = -1 then + begin + TempIdList.Add(s); + IdList.Add(s); + end; + Query.Next; + end; + if TempIdList.Count > 0 then begin + BoldLog.LogFmt('The following Linkobjects (class %s) have links to nonexisting objects:', [ObjectSQLmapper.ExpressionName], ltWarning); + BoldLog.Log(TempIdList.CommaText, ltDetail); + Remedy.Add(Format('-- Clean Linkobjects (%s) with space pointers', [ObjectSQLmapper.ExpressionName])); + AddRemedyForDeleteObjects(ObjectSQLMapper, IDList); + end; + finally + TempIdList.free; + end; end; -end; +var + BoldIdField: IBoldField; begin IdList := TStringList.create; LinkColumn1 := (ObjectSQLMapper.LinkClassRole1 as TBoldEmbeddedSingleLinkDefaultMapper).MainColumnName; LinkColumn2 := (ObjectSQLMapper.LinkClassRole2 as TBoldEmbeddedSingleLinkDefaultMapper).MainColumnName; LinkTable := ObjectSQLMapper.MainTable.SQLName; - + Query.Close; Query.AssignSQLText(format(LinkObjectTest, [LinkTable, LinkColumn1, LinkColumn2])); - Query.Open; + OpenQuery; + BoldIdField := Query.FieldByName('BOLD_ID'); while not query.eof do begin - IdList.Add(Query.FieldByName(Field_BOLD_ID).AsString); + IdList.Add(BoldIdField.AsString); Query.Next; end; - - if IdList.Count > 0 then - begin - BoldLog.LogFmt(sLogBrokenLinkObjects, [ObjectSQLmapper.ExpressionName]); - BoldLog.Log(IdList.CommaText); - Remedy.Add(Format(sCommentRemoveBrokenLinkObjects, [ObjectSQLmapper.ExpressionName])); + if IdList.Count > 0 then begin + BoldLog.LogFmt('The following Linkobjects (class %s) have empty links in one direction:', [ObjectSQLmapper.ExpressionName], ltWarning); + BoldLog.Log(IdList.CommaText, ltDetail); + Remedy.Add(Format('-- Clean Linkobjects (%s) with broken links', [ObjectSQLmapper.ExpressionName])); AddRemedyForDeleteObjects(ObjectSQLMapper, IdLIst); end; @@ -438,9 +498,60 @@ procedure CheckSpacePointers(LinkMApper: TBoldEmbeddedSingleLInkDefaultMapper); IdList.Free; end; +procedure TBoldDbDataValidator.ValidateNotNullForColumn( + BoldSQLColumnDescription: TBoldSQLColumnDescription); +var + FieldNames: TStrings; + TableName: String; + ColumnName: String; + NullCount: integer; +begin + FieldNames := TStringList.Create; + query.Close; + TableName := BoldSQLColumnDescription.tableDescription.SQLName; + ColumnName := BoldSQLColumnDescription.SQLName; + try + Query.AssignSQLText(Format('SELECT count(*) FROM %s WHERE %s.%s IS NULL', + [TableName, + TableName, + ColumnName])); + OpenQuery; + nullcount := Query.Fields[0].AsInteger; + Query.Close; + if NullCount <> 0 then + begin + BoldLog.LogFmtIndent('%d Null-values found in Table %s, Column %s: ', + [NullCount, tableName, ColumnName], ltWarning); + Remedy.Add(Format('UPDATE %s SET %s = WHERE %1:s IS NULL;', + [TableName, ColumnName])); + end; + finally + FieldNames.Free; + end; +end; + +procedure TBoldDbDataValidator.ValidateNotNullColumns( + ObjectSQLMapper: TBoldObjectSQLMapper); +var + i, j: integer; + BoldSQLTableDescription: TBoldSQLTableDescription; + BoldSQLColumnDescription: TBoldSQLColumnDescription; +begin + for j := 0 to ObjectSQLMapper.AllTables.Count-1 do + begin + BoldSQLTableDescription := ObjectSQLMapper.AllTables[j]; + for i := 0 to BoldSQLTableDescription.ColumnsList.count - 1 do + begin + BoldSQLColumnDescription := BoldSQLTableDescription.ColumnsList[i] as TBoldSQlColumnDescription; + if BoldSQLColumnDescription.Mandatory then + ValidateNotNullForColumn(BoldSQLColumnDescription); + end; + end; +end; + procedure TBoldDbDataValidator.ValidateRelations(ObjectSQLMapper: TBoldObjectSQLMapper); var - i: integer; + i,j: integer; IdList: TStringList; SingleLink: TBoldEmbeddedSingleLinkDefaultMapper; RelatedTable, @@ -449,6 +560,10 @@ procedure TBoldDbDataValidator.ValidateRelations(ObjectSQLMapper: TBoldObjectSQL MemberOfOtherEnd: TBoldMemberSQLMapper; SingleRoleOfOtherEnd: TBoldEmbeddedSingleLInkDefaultMapper; MemberMappings: TBoldMemberMappingArray; + BoldIdField: IBoldField; + FetchBlockSize: integer; + Block, Start,Stop: integer; + s: string; begin IdList := TStringList.create; LinkTable := ObjectSQLMapper.MainTable; @@ -461,60 +576,152 @@ procedure TBoldDbDataValidator.ValidateRelations(ObjectSQLMapper: TBoldObjectSQL begin SingleLink := ObjectSQLMapper.MemberPersistenceMappers[i] as TBoldEmbeddedSingleLinkDefaultMapper; MemberMappings := ObjectSQLMapper.SystemPersistenceMapper.MappingInfo.GetMemberMappings(ObjectSQLMapper.ExpressionName, SingleLink.ExpressionName); - // check if the member is stored in our table. if (length(MemberMappings) = 1) and SameText(MemberMappings[0].TableName, LinkTable.SQLName) then begin - RelatedTable := (SystemSQLMapper.ObjectPersistenceMappers[SingleLink.OtherEndObjectPMIndex] as TBoldObjectSQLMapper).MainTable; + ClassOfOtherEnd := SystemSQLMapper.ObjectPersistenceMappers[SingleLink.OtherEndObjectPMIndex] as TBoldObjectSQlMapper; + MemberOfOtherEnd := ClassOfOtherEnd.MemberPersistenceMappers[SingleLink.OtherEndMemberPMIndex] as TBoldMemberSQLMapper; + RelatedTable := ClassOfOtherEnd.MainTable; + if RelatedTable = nil then //childmapped abstract class + RelatedTable := ObjectSQLMapper.SystemPersistenceMapper.RootClassObjectPersistenceMapper.MainTable; + if SingleLink=nil then + begin + BoldLog.LogFmt('TBoldDbDataValidator.ValidateRelations: %s:%d SingleLink=nil', [ObjectSQLMapper.ExpressionName, I]); + Continue; + end; + if LinkTable=nil then + begin + BoldLog.LogFmt('TBoldDbDataValidator.ValidateRelations: %s:%d LinkTable=nil', [ObjectSQLMapper.ExpressionName, I]); + Continue; + end; + if RelatedTable=nil then + begin + BoldLog.LogFmt('TBoldDbDataValidator.ValidateRelations: %s:%d RelatedTable=nil', [ObjectSQLMapper.ExpressionName, I]); + Continue; + end; + Query.Close; Query.AssignSQLText(format(RelationTest, [SingleLink.MainColumnName, LInkTable.SQLName, relatedtable.SQLName])); - Query.Open; + OpenQuery; + BoldIdField := Query.FieldByName('BOLD_ID'); IdList.Clear; while not query.eof do begin - IdList.Add(Query.FieldByName(Field_BOLD_ID).AsString); + IdList.Add(BoldIdField.AsString); Query.Next; end; Query.Close; if IdList.Count > 0 then begin - BoldLog.LogFmt(sLogObjectsWithBrokenLinks, [ObjectSQlMapper.ExpressionName, SingleLink.ExpressionName]); - BoldLog.Log(IdList.CommaText); - Remedy.Add(Format(sCommentCleanRelation, [ObjectSQlMapper.ExpressionName, SingleLink.ExpressionName])); - - remedy.Add(format('UPDATE %s SET %s = -1 WHERE BOLD_ID IN (%s);', // do not localize - [LinkTable.SQLName, SingleLink.MainColumnName, IdList.CommaText])); + BoldLog.LogFmt('The following (%d) objects of class %s have invalid links in %s:', [IdList.Count, ObjectSQlMapper.ExpressionName, SingleLink.ExpressionName], ltWarning); + FetchBlockSize := SystemSQLMapper.SQLDataBaseConfig.FetchBlockSize; + for Block := 0 to (IdList.Count div FetchBlockSize) do + begin + s := ''; + Start := Block * FetchBlockSize; + Stop := MinIntValue([Pred(Succ(Block) * FetchBlockSize), IdList.Count-1]); + for j := Start to Stop do + begin + s := s + IdList[j]; + if j < stop then + s := s + ','; + end; + BoldLog.Log(s, ltDetail); + Remedy.Add(Format('-- Clean relation (%s.%s) ', [ObjectSQlMapper.ExpressionName, SingleLink.ExpressionName])); + Remedy.Add(format('UPDATE %s SET %s = -1 WHERE BOLD_ID IN (%s);', + [LinkTable.SQLName, SingleLink.MainColumnName, s])); + end; end; - // find inconsistent single-single embedded links - ClassOfOtherEnd := ObjectSQLMapper.SystemPersistenceMapper.ObjectPersistencemappers[SingleLInk.OtherEndObjectPMIndex] as TBoldObjectSQlMapper; if assigned(ClassOfOtherEnd) then begin MemberOfOtherEnd := ClassOfOtherEnd.MemberPersistenceMappers[SingleLink.OtherEndMemberPMIndex] as TBoldMemberSQLMapper; + if (MemberofOtherEnd is TBoldSingleLinkDefaultMapper) and (not ObjectSQlMapper.IsLinkClass) then + begin + BoldLog.LogFmt('Validating 1-1 singlelinks for duplicate values: %s.%s',[ObjectSQlMapper.MainTable.SQlName, SingleLink.MainColumnName]); + Query.Close; + Query.AssignSQLText(format(DuplicateSingleLinkTest, [ + SingleLink.MainColumnName, ObjectSQlMapper.MainTable.SQlName, SingleLink.MainColumnName, + SingleLink.MainColumnName])); + OpenQuery; + BoldIdField := Query.FieldByName(SingleLink.MainColumnName); + IdList.Clear; + while not query.eof do + begin + IdList.Add(BoldIdField.AsString); + Query.Next; + end; + Query.Close; + while not query.eof do + begin + IdList.Add(BoldIdField.AsString); + Query.Next; + end; + Query.Close; + if IdList.Count > 0 then + begin + BoldLog.LogFmt('The following %d objects of class %s have duplicate values in singlelinks (%s) :', + [IdList.Count, ObjectSQlMapper.ExpressionName, SingleLink.ExpressionName]); + FetchBlockSize := SystemSQLMapper.SQLDataBaseConfig.FetchBlockSize; + for Block := 0 to (IdList.Count div FetchBlockSize) do + begin + s := ''; + Start := Block * FetchBlockSize; + Stop := MinIntValue([Pred(Succ(Block) * FetchBlockSize), IdList.Count-1]); + for j := Start to Stop do + begin + s := s + IdList[j]; + if j < stop then + s := s + ','; + end; + BoldLog.Log(s); + Remedy.Add(Format('-- Unlink relation (%s.%s) ', [ObjectSQlMapper.ExpressionName, SingleLink.ExpressionName])); + Remedy.Add(format('UPDATE %s SET %s = -1 WHERE %s IN (%s);', + [ObjectSQlMapper.MainTable.SQlName, SingleLink.MainColumnName, SingleLink.MainColumnName, s])); + end; + end; + end; if MemberofOtherEnd is TBoldEmbeddedSingleLinkDefaultMapper then + if ClassOfOtherEnd.MainTable = nil then + BoldLog.LogFmt('Can''t validate 1-1 : %s.%s',[ClassOfOtherEnd.ExpressionName, MemberOfOtherEnd.ExpressionName], ltError) + else begin + BoldLog.LogFmt('Validating 1-1 : %s.%s',[ClassOfOtherEnd.ExpressionName, MemberOfOtherEnd.ExpressionName]); SingleRoleOfOtherEnd := MemberOfOtherEnd as TBoldEmbeddedSingleLinkDefaultMapper; + Query.Close; Query.AssignSQLText(format(SingleSingleEmbeddInconsistencyTest, [ ObjectSQlMapper.MainTable.SQlName, ClassOfOtherEnd.MainTable.sqlName, SingleLink.MainColumnName, SingleRoleOfOtherEnd.MainColumnName])); - Query.Open; + OpenQuery; + BoldIdField := Query.FieldByName('BOLD_ID'); IdList.Clear; while not query.eof do begin - IdList.Add(Query.FieldByName(Field_BOLD_ID).AsString); + IdList.Add(BoldIdField.AsString); Query.Next; end; Query.Close; if IdList.Count > 0 then begin - BoldLog.LogFmt(sLogObjectsWithWrongLinks, [ObjectSQlMapper.ExpressionName, SingleLink.ExpressionName]); - BoldLog.Log(IdList.CommaText); - Remedy.Add(Format(sCommentCleanRelation, [ObjectSQlMapper.ExpressionName, SingleLink.ExpressionName])); - - remedy.Add(format('UPDATE %s SET %s = -1 WHERE BOLD_ID IN (%s);', // do not localize - [ObjectSQlMapper.MainTable.SQlName, SingleLink.MainColumnName, IdList.CommaText])); + BoldLog.LogFmt('The following %d objects of class %s have singlelinks (%s) pointing to objects that don''t point back (they might point elsewhere):', [IdList.Count, ObjectSQlMapper.ExpressionName, SingleLink.ExpressionName]); + FetchBlockSize := SystemSQLMapper.SQLDataBaseConfig.FetchBlockSize; + for Block := 0 to (IdList.Count div FetchBlockSize) do + begin + s := ''; + Start := Block * FetchBlockSize; + Stop := MinIntValue([Pred(Succ(Block) * FetchBlockSize), IdList.Count-1]); + for j := Start to Stop do + begin + s := s + IdList[j]; + if j < stop then + s := s + ','; + end; + BoldLog.Log(s, ltDetail); + Remedy.Add(Format('-- Clean relation (%s.%s) ', [ObjectSQlMapper.ExpressionName, SingleLink.ExpressionName])); + Remedy.Add(format('UPDATE %s SET %s = -1 WHERE BOLD_ID IN (%s);', + [ObjectSQlMapper.MainTable.SQlName, SingleLink.MainColumnName, s])); + end; end; - end; end; end; @@ -525,33 +732,64 @@ procedure TBoldDbDataValidator.ValidateRelations(ObjectSQLMapper: TBoldObjectSQL procedure TBoldDbDataValidator.ValidateStrayObjects(ObjectDefaultMapper: TBoldObjectDefaultMapper); var + i: integer; IdList: TStringList; + TypeList: TStringList; + TypeId: string; OwnMapping: TBoldAllInstancesMappingArray; + FetchBlockSize: integer; + Block, Start,Stop: integer; + s: string; + BoldIdField: IBoldField; + BoldTypeField: IBoldField; begin OwnMapping := SystemSQLMapper.MappingInfo.GetAllInstancesMapping(ObjectdefaultMapper.ExpressionName); if (length(OwnMapping)=1) and not OwnMapping[0].ClassIdRequired then begin IdList := TStringList.Create; + TypeList := TStringList.Create; try + Query.Close; Query.AssignSQLText(format(StrayObjectsTest, [ObjectDefaultMapper.MainTable.SQLName, ObjectDefaultMapper.SubClassesID])); - Query.Open; + OpenQuery; + BoldIdField := Query.FieldByName('BOLD_ID'); + BoldTypeField := Query.FieldByName('BOLD_TYPE'); while not query.eof do begin - IdList.Add(Query.FieldByName(Field_BOLD_ID).AsString); + IdList.Add(BoldIdField.AsString); + TypeId := BoldTypeField.AsString; + if not TypeList.Indexof(TypeId) > -1 then + TypeList.Add(TypeId); Query.Next; end; Query.Close; if IdList.Count > 0 then begin - BoldLog.LogFmt(sLogObjectsWithIllegalType, [ObjectDefaultMapper.MainTable.SQLName]); - BoldLog.Log(IdList.CommaText); - Remedy.Add(format(sCommentRemoveObjectsWithIllegaltype, [ObjectDefaultMapper.MainTable.SQLName])); - Remedy.Add(format('DELETE FROM %s WHERE BOLD_ID IN (%s);', [ObjectDefaultMapper.MainTable.SQLName, IdList.CommaText])); // do not localize - Query.AssignSQLText(Format('SELECT * FROM %s WHERE BOLD_ID IN (%s)', [ObjectDefaultMapper.MainTable.SQLName, IdList.CommaText])); // do not localize + BoldLog.Log('The following invalid types occur in the objects listed below:', ltWarning); + BoldLog.Log(TypeList.CommaText, ltDetail); + FetchBlockSize := SystemSQLMapper.SQLDataBaseConfig.FetchBlockSize; + for Block := 0 to (IdList.Count div FetchBlockSize) do + begin + s := ''; + Start := Block * FetchBlockSize; + Stop := MinIntValue([Pred(Succ(Block) * FetchBlockSize), IdList.Count-1]); + for i := Start to Stop do + begin + s := s + IdList[i]; + if i < stop then + s := s + ','; + end; + BoldLog.Log(s, ltDetail); + end; + BoldLog.LogFmt('The following %d objects are in table %s, but with an illegal type:', [IdList.Count, ObjectDefaultMapper.MainTable.SQLName], ltWarning); + Remedy.Add(format('-- Remove objects with illegal type in table %s', [ObjectDefaultMapper.MainTable.SQLName])); + Remedy.Add(format('DELETE FROM %s WHERE BOLD_ID IN (%s);', [ObjectDefaultMapper.MainTable.SQLName, s])); + Query.AssignSQLText(Format('SELECT * FROM %s WHERE BOLD_ID IN (%s)', [ObjectDefaultMapper.MainTable.SQLName, s])); end; finally FreeAndNil(IdList); + FreeAndNil(TypeList); end; end; end; @@ -579,12 +817,31 @@ procedure TBoldDbDataValidator.DeActivate; procedure TBoldDbDataValidator.AddRemedyForDeleteObjects(Mapper: TBoldObjectSQLMapper; IdList: TStringList); var - i: integer; + i,j: integer; + FetchBlockSize: integer; + Block, Start,Stop: integer; + s: string; begin + FetchBlockSize := SystemSQLMapper.SQLDataBaseConfig.FetchBlockSize; for i := 0 to Mapper.AllTables.Count - 1 do if Mapper.Alltables[i] <> (Mapper.SystemPersistenceMapper.PSSystemDescription as TBoldDefaultSystemDescription).XFilestable then - Remedy.Add(format('DELETE FROM %s WHERE BOLD_ID IN (%s);', [Mapper.AllTables[i].SQLName, IdList.CommaText])); // do not localize + begin + for Block := 0 to (IdList.Count div FetchBlockSize) do + begin + s := ''; + Start := Block * FetchBlockSize; + Stop := MinIntValue([Pred(Succ(Block) * FetchBlockSize), IdList.Count-1]); + for j := Start to Stop do + begin + s := s + IdList[j]; + if j < stop then + s := s + ','; + end; + Remedy.Add(format('DELETE FROM %s WHERE BOLD_ID IN (%s);', [Mapper.AllTables[i].SQLName, s])); + end; + end; end; -end. +initialization +end. diff --git a/Source/PMapper/Validator/BoldDbStructureValidator.pas b/Source/PMapper/Validator/BoldDbStructureValidator.pas index 6aadcb0..6fffe77 100644 --- a/Source/PMapper/Validator/BoldDbStructureValidator.pas +++ b/Source/PMapper/Validator/BoldDbStructureValidator.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldDbStructureValidator; interface @@ -17,10 +20,10 @@ TBoldDbStructureValidator = class(TBoldDbValidator) fCurrentTable: IBoldTable; function GetCurrentTable: IBoldTable; protected - procedure ValidateNotNullForColumn(BoldSQLColumnDescription: TBoldSQLColumnDescription); procedure ValidateColumn(BoldSQLColumnDescription: TBoldSQLColumnDescription); procedure ValidateColumnsForTable(BoldSQLTableDescription: TBoldSQLTableDescription); procedure ValidateIndicesForTable(BoldSQLTableDescription: TBoldSQLTableDescription); + procedure FindExtraIndiciesForTable(BoldSQLTableDescription: TBoldSQLTableDescription); procedure ValidateIndex(BoldSQLIndexDescription: TBoldSQLIndexDescription); procedure ValidateTable(BoldSQLTableDescription: TBoldSQLTableDescription); procedure DeActivate; override; @@ -42,8 +45,8 @@ implementation BoldPMappersDefault, BoldPMappersSQL, BoldPMappers, - BoldPMConsts, - SysUtils; + SysUtils, + BoldRev; { TBoldDbStructureValidator } procedure TBoldDbStructureValidator.Validate; @@ -67,32 +70,35 @@ procedure TBoldDbStructureValidator.Validate; for i := 0 to PMapper.ObjectPersistenceMappers.Count - 1 do begin ObjectMapper := PMapper.ObjectPersistenceMappers[i]; - if MappingInfo.GetDbTypeMapping(ObjectMapper.ExpressionName) = NO_CLASS then + if Assigned(ObjectMapper) then begin - if QueryRes <> qrYesAll then - QueryRes := QueryUser(sMissingID, format(sAnIDWasMissing, [ObjectMapper.ExpressionName])); - if QueryRes in [qrYesAll, qrYes] then + if MappingInfo.GetDbTypeMapping(ObjectMapper.ExpressionName) = NO_CLASS then begin - MappingInfo.AddTypeIdMapping(ObjectMapper.ExpressionName, MappingInfo.HighestUsedDbType+1); - MappingsAdded := true; - end - else - exit; - end; + if QueryRes <> qrYesAll then + QueryRes := QueryUser('Missing ID', format('A databaseId was missing for %s. Do you want to add an unused ID?', [ObjectMapper.ExpressionName])); + if QueryRes in [qrYesAll, qrYes] then + begin + MappingInfo.AddTypeIdMapping(ObjectMapper.ExpressionName, MappingInfo.HighestUsedDbType+1); + MappingsAdded := true; + end + else + exit; + end; + end; // PMapper.ObjectPersistenceMappers[i] = nil ??? /FRHA end; if MappingsAdded then MappingInfo.WriteDataToDB(PersistenceHandle.DataBaseInterface); finally PersistenceHandle.DataBaseInterface.Close; end; - + PersistenceHandle.Active := false; PersistenceHandle.Active := true; try BoldLog.ProgressMax := SystemSQLMapper.AllTables.count - 1; for i := 0 to SystemSQLMapper.AllTables.count - 1 do begin ValidateTable(SystemSQLMapper.AllTables[i]); - BoldLog.LogHeader := Format(sCheckingTable, [SystemSQLMapper.AllTables[i].SQLName]); + BoldLog.LogHeader := 'Checking table ' + SystemSQLMapper.AllTables[i].SQLName; BoldLog.Progress := i; end; finally @@ -111,35 +117,139 @@ procedure TBoldDbStructureValidator.ValidateColumnsForTable(BoldSQLTableDescript procedure TBoldDbStructureValidator.ValidateColumn( BoldSQLColumnDescription: TBoldSQLColumnDescription); var + aQuery: IBoldQuery; + bColumnExists: Boolean; TableName: String; ColumnName: String; + FieldDef: TFieldDef; +const + sColumnMissing = 'Column missing: %s.%s (SQLType: %s)'; + sColumnSizeMismatch = 'Column %s in table %s has wrong size %d, should be %d'; + sColumnAllowsNull = 'Column %s in table %s allows null but the model does not'; + sColumnNotAllows = 'Column %s in table %s does not allow null but the model does'; + BlobFieldTypes = [{$IFDEF BOLD_DELPHI15_OR_LATER}ftStream,{$ENDIF} ftBlob..ftTypedBinary, ftOraBlob, ftOraClob]; begin TableName := BoldSQLColumnDescription.tableDescription.SQLName; ColumnName := BoldSQLColumnDescription.SQLName; - if not assigned(Currenttable.FindField(ColumnName)) then - begin + aQuery := SystemSQLMapper.GetQuery; + try + aQuery.AssignSQLText(SystemSQLMapper.SQLDataBaseConfig.GetColumnExistsQuery(TableName, ColumnName)); + aQuery.Open; + bColumnExists := aQuery.RecordCount = 1; + aQuery.Close; + if bColumnExists then + begin + FieldDef := CurrentTable.FieldDefs.Find(ColumnName); + if not (FieldDef.DataType in BlobFieldTypes) then + begin + if FieldDef.Size <> BoldSQLColumnDescription.Size then + BoldLog.LogFmt(sColumnSizeMismatch, + [ColumnName, Tablename, FieldDef.Size, BoldSQLColumnDescription.Size ], ltWarning); + end; + if FieldDef.Required <> BoldSQLColumnDescription.Mandatory then + begin + if FieldDef.Required then + BoldLog.LogFmt(sColumnNotAllows, + [ColumnName, Tablename], ltWarning) + else + BoldLog.LogFmt(sColumnAllowsNull, + [ColumnName, Tablename], ltWarning) + end; + end; + finally + SystemSQLMapper.ReleaseQuery(aQuery); + end; + + if not bColumnExists then begin BoldLog.LogFmt(sColumnMissing, - [Tablename, ColumnName, BoldSQLColumnDescription.SQLType]); - Remedy.add(format('alter table %s add %s %s %s;', [TableName, ColumnName, BoldSQLColumnDescription.SQLType, BoldSQLColumnDescription.SQLAllowNull])); // do not localize - end - else - if BoldSQLColumnDescription.Mandatory then - ValidateNotNullForColumn(BoldSQLColumnDescription); + [Tablename, ColumnName, BoldSQLColumnDescription.SQLType], ltWarning); + Remedy.add(format('alter table %s add %s %s %s;', [TableName, ColumnName, + BoldSQLColumnDescription.SQLType, BoldSQLColumnDescription.SQLAllowNull])); // do not localize + end else if BoldSQLColumnDescription.Mandatory then begin + // Moved to BoldDbDataValidator +// ValidateNotNullForColumn(BoldSQLColumnDescription); + end; end; procedure TBoldDbStructureValidator.ValidateIndex( BoldSQLIndexDescription: TBoldSQLIndexDescription); var - Index: TIndexDef; - IndexFields: String; + i,j: Integer; + sTableName: string; + sIndexFields: string; + aIndexFields: TStringList; + aQuery: IBoldQuery; + bIndexExists: Boolean; + MatchList, TempList: TStringList; + sIndexName: string; + isMultiIndex: boolean; + NameField: IBoldField; +const + sIndexMissing = 'Index missing: %s.(%s)'; + cIndexNameColumn = 'name'; // mssql specific, should it be a setting in sqlconfig ? begin - IndexFields := BoldSQLIndexDescription.IndexedFields; - Index := CurrentTable.IndexDefs.GetIndexForFields(IndexFields, false); - if not assigned(Index) then + MatchList := TStringList.Create; + TempList := TStringList.Create; + bIndexExists := False; + sTableName := TBoldSQLTableDescription(BoldSQLIndexDescription.Owner).SQLName; + sIndexFields := BoldSQLIndexDescription.IndexedFields; + aQuery := DataBase.GetQuery; + aIndexFields := TStringList.Create; + try + if pos(',', sIndexFields) > 1 then + aIndexFields.Delimiter := ',' + else + aIndexFields.Delimiter := ';'; + aIndexFields.DelimitedText := sIndexFields; + //At this time only indices exists with one index-field + //but maybe more in future + isMultiIndex := aIndexFields.Count > 1; + for i := 0 to aIndexFields.Count - 1 do + begin + aQuery.AssignSQLText(SystemSQLMapper.SQLDataBaseConfig + .GetIndexColumnExistsQuery(sTableName, Trim(aIndexFields[i]))); + aQuery.Open; + NameField := aQuery.FieldByName(cIndexNameColumn); + bIndexExists := aQuery.RecordCount > 0; + if isMultiIndex then + begin // for multi field indexes we have to determine if at least one index exists for all IndexFields + TempList.Clear; + while not aQuery.Eof do + begin + sIndexName := NameField.asString; + if i = 0 then // for first column we add all index names to list + MatchList.Add(sIndexName) + else // for all other columns we check if index exists + TempList.Add(sIndexName); + aQuery.next; + end; + if i > 0 then + begin + for j := MatchList.Count - 1 downto 0 do + if TempList.IndexOf(MatchList[j]) = -1 then + MatchList.Delete(j); + bIndexExists := MatchList.Count > 0; + end; + end; + aQuery.Close; + if not bIndexExists then begin + Break; + end; + end; + finally + if isMultiIndex then + bIndexExists := MatchList.count > 0; + aIndexFields.Free; + DataBase.ReleaseQuery(aQuery); + TempList.free; + MatchList.free; + end; + if not bIndexExists then begin - BoldLog.LogFmt(sIndexMissing, [CurrentTable.TableName, IndexFields]); - if ixPrimary in BoldSQLIndexDescription.IndexOptions then - Remedy.Add(Format('alter table %s add %s', [CurrentTable.TableName, BoldSQLIndexDescription.SQLForPrimaryKey])) // do not localize + BoldLog.LogFmt(sIndexMissing, [sTableName, sIndexFields], ltWarning); + if BoldPSDescriptionsSQL.ixPrimary in BoldSQLIndexDescription.IndexOptions then + Remedy.Add(Format('alter table %s add %s', [sTableName, + BoldSQLIndexDescription.SQLForPrimaryKey])) // do not localize else Remedy.Add(BoldSQLIndexDescription.SQLForSecondaryKey); end; @@ -151,56 +261,28 @@ procedure TBoldDbStructureValidator.ValidateIndicesForTable( i: integer; begin for i := 0 to BoldSQLTableDescription.IndexList.count - 1 do + begin ValidateIndex(BoldSQLTableDescription.IndexList[i] as TBoldSQLIndexDescription); -end; - -procedure TBoldDbStructureValidator.ValidateNotNullForColumn( - BoldSQLColumnDescription: TBoldSQLColumnDescription); -var - query: IBoldQuery; - FieldNames: TStrings; - TableName: String; - ColumnName: String; - NullCount: integer; -begin - FieldNames := TStringList.Create; - query := SystemSQLMapper.GetQuery; - TableName := BoldSQLColumnDescription.tableDescription.SQLName; - ColumnName := BoldSQLColumnDescription.SQLName; - try - Query.AssignSQLText(Format('SELECT count(*) FROM %s WHERE %s IS NULL', // do not localize - [TableName, - ColumnName])); - Query.Open; - nullcount := Query.Fields[0].AsInteger; - Query.Close; - if NullCount <> 0 then - begin - BoldLog.LogFmtIndent(sNullValuesFound, - [NullCount, tableName, ColumnName]); - Remedy.Add(Format('UPDATE %s SET %s = WHERE %1:s IS NULL;', // do not localize - [TableName, ColumnName])); - end; - finally - FieldNames.Free; - SystemSQLMapper.ReleaseQuery(query); end; end; procedure TBoldDbStructureValidator.ValidateTable( BoldSQLTableDescription: TBoldSQLTableDescription); +var + TableName: string; begin - CurrentTable.TableName := BoldSQLTableDescription.SQLName; + TableName := BoldSQLTableDescription.MappedSQLName(BoldSQLTableDescription.SQLNameUpper); + CurrentTable.TableName := TableName; if CurrentTable.Exists then begin - currentTable.Open; + CurrentTable.FieldDefs.Update; ValidateColumnsForTable(BoldSQLTableDescription); ValidateIndicesForTable(BoldSQLTableDescription); - CurrentTable.Close; + FindExtraIndiciesForTable(BoldSQLTableDescription); end else begin - BoldLog.LogFmt(sTableDoesNotExist, [BoldSQLTableDescription.SQLName]); + BoldLog.LogFmt('Table %s does not exist', [BoldSQLTableDescription.MappedSQLName(BoldSQLTableDescription.SQLNameUpper)], ltWarning); remedy.Add(BoldSQLTableDescription.sqlforCreateTable(DataBase)); end; end; @@ -212,6 +294,48 @@ destructor TBoldDbStructureValidator.destroy; inherited; end; +procedure TBoldDbStructureValidator.FindExtraIndiciesForTable( + BoldSQLTableDescription: TBoldSQLTableDescription); + + function SameFields(const s1, s2: String): boolean; + begin + result := SameText(TBoldSQLIndexDescription.NormalizeFields(s1), TBoldSQLIndexDescription.NormalizeFields(s2)); + end; + + function DefinedInModel(IndexDef: TBoldIndexDescription): Boolean; + var + j: Integer; + begin + Result := false; + for j := 0 to BoldSQLTableDescription.IndexList.count - 1 do + if SameText(IndexDef.IndexName, BoldSQLTableDescription.IndexList[j].GeneratedName) and + SameFields(IndexDef.IndexedColumns, BoldSQLTableDescription.IndexList[j].IndexedFields) then + begin + result := True; + Exit; + end; + for j := 0 to PersistenceHandle.CustomIndexes.Count - 1 do + begin + if SameText(IndexDef.IndexName, PersistenceHandle.CustomIndexes.IndexDefinition[j].TableName) and + SameFields(IndexDef.IndexedColumns, PersistenceHandle.CustomIndexes.IndexDefinition[j].Columns) and + (IndexDef.IsUnique = PersistenceHandle.CustomIndexes.IndexDefinition[j].Unique) then + begin + result := True; + Exit; + end; + end; + end; + +var + i: Integer; + IndexDefs: TBoldIndexDescriptionArray; +begin + IndexDefs := DataBase.GetIndexDescriptions(BoldSQLTableDescription.SQlName); + for I := 0 to length(IndexDefs) - 1 do + if not DefinedInModel(IndexDefs[i]) then + BoldLog.LogFmt('Extra Index: %s(%s)', [BoldSQLTableDescription.SQLName, IndexDefs[i].IndexedColumns], ltWarning); +end; + function TBoldDbStructureValidator.GetCurrentTable: IBoldTable; begin if not assigned(fCurrentTable) then @@ -223,10 +347,10 @@ procedure TBoldDbStructureValidator.DeActivate; begin if assigned(fCurrentTable) then DataBase.ReleaseTable(fCurrentTable); + inherited; end; -end. - - +initialization +end. diff --git a/Source/PMapper/Validator/BoldDbValidator.pas b/Source/PMapper/Validator/BoldDbValidator.pas index 69798fd..9319dd1 100644 --- a/Source/PMapper/Validator/BoldDbValidator.pas +++ b/Source/PMapper/Validator/BoldDbValidator.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldDbValidator; interface @@ -6,7 +9,8 @@ interface Classes, BoldDbInterfaces, BoldAbstractPersistenceHandleDB, - BoldPMappersSQL; + BoldPMappersSQL, + BoldSubscription; type { forward declarations } @@ -19,10 +23,12 @@ TBoldDbValidator = class(TComponent) fRemedy: TStringList; fPersistenceHandle: TBoldAbstractPersistenceHandleDB; FEnabled: Boolean; + fSubscriber: TBoldPassThroughSubscriber; function GetSystemSQLMapper: TBoldSystemSQLMApper; procedure SetEnabled(const Value: Boolean); procedure CheckTypeTableConsistency(SystemSQLMapper: TBoldSystemSQLMapper); function GetDataBase: IBoldDataBase; + procedure Receive(Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent); protected procedure DeActivate; virtual; procedure SetPersistenceHandle(const Value: TBoldAbstractPersistenceHandleDB); virtual; @@ -35,7 +41,7 @@ TBoldDbValidator = class(TComponent) procedure Activate; procedure Validate; virtual; abstract; function Execute: Boolean; - property remedy: TStringList read fRemedy; + property Remedy: TStringList read fRemedy; published property PersistenceHandle: TBoldAbstractPersistenceHandleDB read fPersistenceHandle write SetPersistenceHandle; property Enabled: Boolean read FEnabled write SetEnabled; @@ -49,7 +55,6 @@ implementation BoldNameExpander, BoldDefs, SysUtils, - BoldPMConsts, Dialogs, Controls; @@ -63,20 +68,35 @@ procedure TBoldDbValidator.SetEnabled(const Value: Boolean); destructor TBoldDbValidator.destroy; begin FreeAndNil(fRemedy); + FreeAndNil(fSubscriber); inherited; end; function TBoldDbValidator.GetSystemSQLMapper: TBoldSystemSQLMApper; begin if not assigned(fSystemMapper) then + begin fSystemMapper := PersistenceHandle.PersistenceControllerDefault.PersistenceMapper as TBoldSystemSQLMapper; + fSystemMapper.AddSmallSubscription(fSubscriber, [beDestroying], beDestroying); + end; result := fSystemMapper; end; -constructor TBoldDbValidator.create(owner: TComponent); +procedure TBoldDbValidator.Receive(Originator: TObject; + OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent); +begin + if RequestedEvent = beDestroying then + begin + fSystemMapper := nil; + fSubscriber.CancelAllSubscriptions; + end; +end; + +constructor TBoldDbValidator.Create(owner: TComponent); begin inherited; fRemedy := TStringList.Create; + fSubscriber := TBoldPassThroughSubscriber.Create(Receive); end; procedure TBoldDbValidator.SetPersistenceHandle(const Value: TBoldAbstractPersistenceHandleDB); @@ -94,21 +114,26 @@ procedure TBoldDbValidator.CheckTypeTableConsistency(SystemSQLMapper: TBoldSyste Found: Boolean; MissingClasses: Boolean; ObjectPMapper: TBoldObjectSQLMapper; + TypeParam, ClassParam: IBoldParameter; + BoldDBTypeField: IBoldField; + ClassNameField: IBoldField; begin query := SystemSQLMapper.GetQuery; ExecQuery := SystemSQLMapper.GetExecQuery; - query.AssignSQLText(format('SELECT * FROM %s', [TypeTableName])); // do not localize + query.AssignSQLText(format('SELECT * FROM %s', [TypeTableName])); HighestBoldDbType := -1; Query.Open; + BoldDBTypeField := Query.FieldByName('BOLD_TYPE'); + ClassNameField := Query.FieldByName('CLASSNAME'); while not query.eof do begin - BoldDbType := Query.FieldByName('BOLD_TYPE').AsInteger; // do not localize + BoldDbType := BoldDBTypeField.AsInteger; if BoldDbType > HighestBoldDbType then HighestBoldDbType := BoldDbType; - Name := Query.FieldByName('CLASSNAME').AsString; // do not localize + Name := ClassNameField.AsString; Found := false; for i := 0 to SystemSQLMapper.ObjectPersistenceMappers.count - 1 do @@ -123,7 +148,7 @@ procedure TBoldDbValidator.CheckTypeTableConsistency(SystemSQLMapper: TBoldSyste end; end; if not found then - BoldLog.LogFmt(sClassInDBNotInModel, [Name, BoldDbType]); + BoldLog.LogFmt('Database contains a class %s with BoldType %d that is not in the model...', [Name, BoldDbType]); Query.Next; end; Query.Close; @@ -136,24 +161,27 @@ procedure TBoldDbValidator.CheckTypeTableConsistency(SystemSQLMapper: TBoldSyste begin if not MissingClasses then BoldLog.Separator; - BoldLog.LogFmt(sClassWithoutDBID, [ObjectPMapper.ExpressionName]); + BoldLog.LogFmt('Model contains a class %s that does not have a database id', [ObjectPMapper.ExpressionName]); MissingClasses := true; end; end; if MissingClasses and - (MessageDlg(sCorrectClassesWithNoID, + (MessageDlg('There are classes with no database ID. Do you want to correct this now?', mtConfirmation, [mbYes, mbNo], 0) = mrYes) then begin BoldLog.Separator; Execquery.AssignSQLText( - format('INSERT INTO %s (%s, %s) VALUES (:%s, :%s)', [ // do not localize + format('INSERT INTO %s (%s, %s) VALUES (:%s, :%s)', [ TypeTablename, TYPECOLUMN_NAME, CLASSNAMECOLUMN_NAME, TYPECOLUMN_NAME, CLASSNAMECOLUMN_NAME])); + ExecQuery.ParamCheck := true; + TypeParam := ExecQuery.ParamByName(TYPECOLUMN_NAME); + ClassParam := ExecQuery.ParamByName(CLASSNAMECOLUMN_NAME); for i := 0 to SystemSQLMapper.ObjectPersistenceMappers.count - 1 do begin ObjectPMapper := SystemSQLMapper.ObjectPersistenceMappers[i] as TBoldObjectSQLMapper; @@ -161,9 +189,9 @@ procedure TBoldDbValidator.CheckTypeTableConsistency(SystemSQLMapper: TBoldSyste begin Inc(HighestBoldDbType); ObjectPMapper.BoldDbType := HighestBoldDbType; - BoldLog.LogFmt(sAddingBoldDBType, [ObjectPMapper.BoldDbType, ObjectPMapper.expressionName]); - ExecQuery.ParamByName(TYPECOLUMN_NAME).AsInteger := HighestBoldDbType; - ExecQuery.ParamByName(CLASSNAMECOLUMN_NAME).AsString := ObjectPMapper.ExpressionName; + BoldLog.LogFmt('Adding BoldDbType %d for %s', [ObjectPMapper.BoldDbType, ObjectPMapper.expressionName]); + TypeParam.AsInteger := HighestBoldDbType; + ClassParam.AsString := ObjectPMapper.ExpressionName; ExecQuery.ExecSQL; end; end; @@ -193,7 +221,7 @@ function TBoldDbValidator.Execute: Boolean; var i: integer; begin - BoldLog.StartLog(sDatabaseValidation); + BoldLog.StartLog('Database validation'); result := false; if assigned(PersistenceHandle) then begin @@ -204,24 +232,25 @@ function TBoldDbValidator.Execute: Boolean; if remedy.Count <> 0 then begin BoldLog.Separator; - BoldLog.Log(sInconsistenciesFound, ltWarning); + BoldLog.Log('Inconsistencies found', ltWarning); for i := 0 to remedy.Count - 1 do - BoldLog.Log(remedy[i]); + BoldLog.Log(remedy[i], ltDetail); BoldLog.Separator; end; result := Remedy.Count = 0; finally + BoldLog.Log('Database validation finished', ltInfo); DeActivate; end; except on e: Exception do begin - BoldLog.LogFmt(sDBValidationFailed, [e.message], ltError); + BoldLog.LogFmt('Database validation failed: %s', [e.message], ltError); end; end; end else - BoldLog.Log(sCannotValidateWithoutPHandle, ltError); + BoldLog.Log('Unable to perform validation, missing a PersistenceHandle', ltError); BoldLog.EndLog; end; @@ -235,4 +264,5 @@ function TBoldDbValidator.TypeTableName: String; result := BoldExpandPrefix(TYPETABLE_NAME, '', PersistenceHandle.SQLDataBaseConfig.SystemTablePrefix, SystemSQLMapper.SQLDatabaseConfig.MaxDBIdentifierLength, SystemSQLMapper.NationalCharConversion); end; +initialization end. diff --git a/Source/Persistence/ADO/ADOConsts.pas b/Source/Persistence/ADO/ADOConsts.pas index 5248c6e..8a70c3a 100644 --- a/Source/Persistence/ADO/ADOConsts.pas +++ b/Source/Persistence/ADO/ADOConsts.pas @@ -15,4 +15,4 @@ interface implementation -end. \ No newline at end of file +end. diff --git a/Source/Persistence/ADO/BoldADOInterfaces.pas b/Source/Persistence/ADO/BoldADOInterfaces.pas index 3c0ee6b..d2b4be0 100644 --- a/Source/Persistence/ADO/BoldADOInterfaces.pas +++ b/Source/Persistence/ADO/BoldADOInterfaces.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldADOInterfaces; interface @@ -6,6 +9,7 @@ interface Classes, Db, ADODB, + BoldDefs, BoldSQLDatabaseConfig, BoldDBInterfaces; @@ -13,7 +17,8 @@ interface { forward declarations } TBoldADOParameter = class; TBoldADOQuery = class; - TBoldADOTable = class; TBoldADOConnection = class; + TBoldADOTable = class; + TBoldADOConnection = class; TBoldADOQueryClass = class of TBoldADOQuery; { TBoldADOParameter } @@ -27,6 +32,7 @@ TBoldADOParameter = class(TBoldParameterWrapper, IBoldParameter) function GetDataType: TFieldType; procedure SetDataType(Value: TFieldType); function GetAsBCD: Currency; + function GetAsblob: TBoldBlobData; function GetAsBoolean: Boolean; function GetAsDateTime: TDateTime; function GetAsCurrency: Currency; @@ -34,9 +40,10 @@ TBoldADOParameter = class(TBoldParameterWrapper, IBoldParameter) function GetAsInteger: Longint; function GetAsMemo: string; function GetAsString: string; + function GetAsInt64: Int64; function GetIsNull: Boolean; procedure SetAsBCD(const Value: Currency); - procedure SetAsBlob(const Value: TBlobData); + procedure SetAsBlob(const Value: TBoldBlobData); procedure SetAsBoolean(Value: Boolean); procedure SetAsCurrency(const Value: Currency); procedure SetAsDate(const Value: TDateTime); @@ -48,9 +55,14 @@ TBoldADOParameter = class(TBoldParameterWrapper, IBoldParameter) procedure SetAsSmallInt(Value: LongInt); procedure SetAsTime(const Value: TDateTime); procedure SetAsWord(Value: LongInt); + procedure SetAsInt64(const Value: Int64); procedure SetText(const Value: string); function GetParameter: TParameter; procedure AssignFieldValue(source: IBoldField); + function GetAsAnsiString: TBoldAnsiString; + function GetAsWideString: WideString; + procedure SetAsAnsiString(const Value: TBoldAnsiString); + procedure SetAsWideString(const Value: Widestring); property Parameter: TParameter read GetParameter; public constructor create(AdoParameter: TParameter; DatasetWrapper: TBoldDatasetWrapper); @@ -70,9 +82,13 @@ TBoldADOQuery = class(TBoldDataSetWrapper, IBoldQuery, IBoldExecQuery, IBoldPa procedure SetRequestLiveQuery(NewValue: Boolean); function GetSQLText: String; procedure AssignSQL(SQL: TStrings); virtual; - procedure AssignSQLText(SQL: String); + procedure AssignSQLText(const SQL: String); function GetRowsAffected: integer; function GetRecordCount: integer; + function GetParamCheck: Boolean; + procedure SetParamCheck(value: Boolean); + function GetUseReadTransactions: boolean; + procedure SetUseReadTransactions(value: boolean); protected procedure StartSQLBatch; virtual; procedure EndSQLBatch; virtual; @@ -96,7 +112,7 @@ TBoldADOTable = class(TBoldDataSetWrapper, IBoldTable) procedure CreateTable; procedure DeleteTable; function GetIndexDefs: TIndexDefs; - procedure SetTableName(NewName: String); + procedure SetTableName(const NewName: String); function GetTableName: String; procedure SetExclusive(NewValue: Boolean); function GetExclusive: Boolean; @@ -126,18 +142,20 @@ TBoldADOConnection = class(TBoldDatabaseWrapper, IBoldDataBase) procedure RollBack; procedure Open; procedure Close; + procedure Reconnect; - function GetTable: IBoldTable; - procedure ReleaseTable(var Table: IBoldTable); + function GetIsExecutingQuery: Boolean; function SupportsTableCreation: Boolean; procedure ReleaseCachedObjects; protected procedure AllTableNames(Pattern: String; ShowSystemTables: Boolean; TableNameList: TStrings); override; function GetQuery: IBoldQuery; override; procedure ReleaseQuery(var Query: IBoldQuery); override; + function GetTable: IBoldTable; override; + procedure ReleaseTable(var Table: IBoldTable); override; public - constructor Create(DataBase: TADOConnection; SQLDataBaseConfig: TBoldSQLDatabaseConfig); - destructor Destroy; override; + constructor create(DataBase: TADOConnection; SQLDataBaseConfig: TBoldSQLDatabaseConfig); + destructor destroy; override; end; var @@ -146,13 +164,11 @@ TBoldADOConnection = class(TBoldDatabaseWrapper, IBoldDataBase) implementation uses - BoldDefs, BoldUtils, SysUtils, Variants, Masks, - BoldGuard, - BoldCoreConsts; + BoldGuard; { TBoldADOQuery } @@ -175,7 +191,6 @@ procedure TBoldADOQuery.AssignSQL(SQL: TStrings); Guard: IBoldGuard; begin Guard := TBoldGuard.Create(BackupQuery); - // ADO sometimes tries to bind the params at this point, unless we disconnect the connection first OldConnection := Query.Connection; if Query.Parameters.count > 0 then begin @@ -183,7 +198,6 @@ procedure TBoldADOQuery.AssignSQL(SQL: TStrings); BackupQuery.Parameters.Assign(Query.Parameters); end; - Query.Close; // safe operation even if the query is closed. Open queries will cause "invalid operation" on next line Query.Connection := nil; Query.SQL.BeginUpdate; Query.SQL.Assign(SQL); @@ -194,15 +208,16 @@ procedure TBoldADOQuery.AssignSQL(SQL: TStrings); Query.Connection := OldConnection; end; -procedure TBoldADOQuery.AssignSQLText(SQL: String); -var - StringList: TStringList; - Guard: IBoldguard; +procedure TBoldADOQuery.AssignSQLText(const SQL: String); begin - Guard := tBoldGuard.Create(StringList); - StringList := TStringList.create; - BoldAppendToStrings(StringList, SQL, true); - AssignSQL(StringList); + Query.SQL.BeginUpdate; + Query.SQL.Clear; +{$IFDEF BOLD_DELPHI10_OR_LATER} + Query.SQL.Append(SQL); // FIXME, this gives one long line. +{$ELSE} + BoldAppendToStrings(Query.SQL, SQL, true); +{$ENDIF} + Query.SQL.EndUpdate; end; procedure TBoldADOQuery.ClearParams; @@ -214,6 +229,7 @@ constructor TBoldADOQuery.Create(Query: TADOQuery; DatabaseWrapper: TBoldDatabas begin inherited create(DatabaseWrapper); fQuery := Query; + SetParamCheck(true); end; function TBoldADOQuery.Createparam(FldType: TFieldType; const ParamName: string; ParamType: TParamType; Size: integer): IBoldParameter; @@ -225,18 +241,21 @@ function TBoldADOQuery.Createparam(FldType: TFieldType; const ParamName: string; procedure TBoldADOQuery.EndSQLBatch; begin - // intentionally left blank end; procedure TBoldADOQuery.ExecSQL; begin +{$IFDEF BOLD_DELPHI10_OR_LATER} + BoldLogSQLWide(Query.SQL, self); +{$ELSE} BoldLogSQL(Query.SQL); +{$ENDIF} try Query.ExecSQL; except on e: Exception do begin - e.Message := e.Message + BOLDCRLF + 'SQL: ' + Query.SQL.text; // do not localize + e.Message := e.Message + BOLDCRLF + 'SQL: ' + Query.SQL.text; raise; end; end; @@ -244,7 +263,6 @@ procedure TBoldADOQuery.ExecSQL; procedure TBoldADOQuery.FailSQLBatch; begin - // intentionally left blank end; function TBoldADOQuery.GetDataSet: TDataSet; @@ -252,6 +270,11 @@ function TBoldADOQuery.GetDataSet: TDataSet; result := Query; end; +function TBoldADOQuery.GetParamCheck: Boolean; +begin + Result := Query.ParamCheck; +end; + function TBoldADOQuery.GetParamCount: integer; begin result := Query.Parameters.count; @@ -287,18 +310,24 @@ function TBoldADOQuery.GetSQLText: String; result := Query.SQL.Text; end; +function TBoldADOQuery.GetUseReadTransactions: boolean; +begin + result := false; +end; + procedure TBoldADOQuery.Open; begin +{$IFDEF BOLD_DELPHI10_OR_LATER} + BoldLogSQLWide(Query.SQL, self); +{$ELSE} BoldLogSQL(Query.SQL); +{$ENDIF} try - Query.CacheSize := 10000; - Query.CursorType := ctOpenForwardOnly; - Query.LockType := ltReadOnly; inherited; except on e: Exception do begin - e.Message := e.Message + BOLDCRLF + 'SQL: ' + Query.SQL.text; // do not localize + e.Message := e.Message + BOLDCRLF + 'SQL: ' + Query.SQL.text; raise; end; end; @@ -315,14 +344,22 @@ function TBoldADOQuery.ParamByName(const Value: string): IBoldParameter; result := nil; end; +procedure TBoldADOQuery.SetParamCheck(value: Boolean); +begin + Query.ParamCheck := Value; +end; + procedure TBoldADOQuery.SetRequestLiveQuery(NewValue: Boolean); begin - // ignore +end; + +procedure TBoldADOQuery.SetUseReadTransactions(value: boolean); +begin + end; procedure TBoldADOQuery.StartSQLBatch; begin - // intentionally left blank end; { TBoldADOTable } @@ -330,7 +367,7 @@ procedure TBoldADOQuery.StartSQLBatch; procedure TBoldADOTable.AddIndex(const Name, Fields: string; Options: TIndexOptions; const DescFields: string); begin - raise EBold.CreateFmt(sMethodNotImplemented, [ClassName, 'AddIndex']); // do not localize + raise EBold.CreateFmt('%s.AddIndex: not implemented', [ClassName]); end; constructor TBoldADOTable.Create(Table: TADOTable; DatabaseWrapper: TBoldDatabaseWrapper); @@ -341,12 +378,12 @@ constructor TBoldADOTable.Create(Table: TADOTable; DatabaseWrapper: TBoldDatabas procedure TBoldADOTable.CreateTable; begin - raise EBold.CreateFmt(sMethodNotImplemented, [ClassName, 'CreateTable']); // do not localize + raise EBold.CreateFmt('%s.CreateTable: not implemented', [ClassName]); end; procedure TBoldADOTable.DeleteTable; begin - raise EBold.CreateFmt(sMethodNotImplemented, [ClassName, 'DeleteTable']); // do not localize + raise EBold.CreateFmt('%s.DeleteTable: not implemented', [ClassName]); end; function TBoldADOTable.GetDataSet: TDataSet; @@ -366,11 +403,8 @@ function TBoldADOTable.GetExists: Boolean; begin Guard := TBoldGuard.Create(AllTables); Result := False; - - // First we make sure we have a table component and that it is connected to a database if Assigned(Table) and Assigned(Table.Connection) then begin - // We now create a list that will hold all the table names in the database Alltables := TStringList.Create; Table.Connection.GetTableNames(AllTables); Result := AllTables.IndexOf(GetTableName) <> -1; @@ -400,14 +434,12 @@ procedure TBoldADOTable.SetExclusive(NewValue: Boolean); Table.LockType := ltOptimistic; end; -procedure TBoldADOTable.SetTableName(NewName: String); +procedure TBoldADOTable.SetTableName(const NewName: String); begin Table.TableName := NewName; end; { TBoldADOConnection } - -// Populate the "TableNameList" with tablenames from the database that maches "pattern" procedure TBoldADOConnection.AllTableNames(Pattern: String; ShowSystemTables: Boolean; TableNameList: TStrings); var TempList: TStringList; @@ -422,19 +454,17 @@ procedure TBoldADOConnection.AllTableNames(Pattern: String; ShowSystemTables: Bo else TempPattern := Pattern; - // Retrieve the list of table names - // Note: This does not include views or procedures, there is a specific - // method in TADOConnection for that + GetDataBase.GetTableNames(TempList, ShowSystemTables); - // MatchesMask is used to compare filenames with wildcards, suits us here - // but there should be some care taken, when using tablenames with period - // signes, as that might be interpreted as filename extensions + for i := 0 to TempList.Count-1 do if MatchesMask(TempList[i], tempPattern) then TableNameList.Add(TempList[i]); end; + + procedure TBoldADOConnection.Commit; begin DataBase.CommitTrans; @@ -445,6 +475,11 @@ function TBoldADOConnection.GetInTransaction: Boolean; result := DataBase.InTransaction; end; +function TBoldADOConnection.GetIsExecutingQuery: Boolean; +begin + result := false; // TODO: implement +end; + function TBoldADOConnection.GetIsSQLBased: Boolean; begin result := true; @@ -452,7 +487,6 @@ function TBoldADOConnection.GetIsSQLBased: Boolean; function TBoldADOConnection.GetKeepConnection: Boolean; begin - //CheckMe; result := true; end; @@ -468,7 +502,6 @@ procedure TBoldADOConnection.RollBack; procedure TBoldADOConnection.SetKeepConnection(NewValue: Boolean); begin - //CheckMe; end; procedure TBoldADOConnection.SetlogInPrompt(NewValue: Boolean); @@ -481,9 +514,8 @@ procedure TBoldADOConnection.StartTransaction; DataBase.BeginTrans; end; -destructor TBoldADOConnection.Destroy; +destructor TBoldADOConnection.destroy; begin -// FreeAndNil(fParameters); FreeAndNil(fCachedQuery); FreeAndNil(fCachedTable); inherited; @@ -493,7 +525,7 @@ constructor TBoldADOConnection.create(DataBase: TADOConnection; SQLDataBaseConfi begin inherited create(SQLDataBaseConfig); fDatabase := DataBase; -end; +end; procedure TBoldADOConnection.Close; begin @@ -597,7 +629,6 @@ function TBoldADOConnection.SupportsTableCreation: Boolean; procedure TBoldADOParameter.Clear; begin - // FIXME end; constructor TBoldADOParameter.create(AdoParameter: TParameter; DatasetWrapper: TBoldDatasetWrapper); @@ -606,11 +637,23 @@ constructor TBoldADOParameter.create(AdoParameter: TParameter; DatasetWrapper: T fParameter := AdoParameter; end; +function TBoldADOParameter.GetAsAnsiString: TBoldAnsiString; +begin + result := TBoldAnsiString(Parameter.Value); + if string(result) = DatasetWrapper.DatabaseWrapper.SQLDatabaseConfig.EmptyStringMarker then + result := ''; +end; + function TBoldADOParameter.GetAsBCD: Currency; begin result := parameter.Value; end; +function TBoldADOParameter.GetAsblob: TBoldBlobData; +begin + result := TBoldAnsiString(parameter.Value); +end; + function TBoldADOParameter.GetAsBoolean: Boolean; begin result := parameter.Value; @@ -631,6 +674,11 @@ function TBoldADOParameter.GetAsFloat: Double; result := parameter.Value; end; +function TBoldADOParameter.GetAsInt64: Int64; +begin + result := parameter.Value; +end; + function TBoldADOParameter.GetAsInteger: Longint; begin result := parameter.Value; @@ -645,7 +693,7 @@ function TBoldADOParameter.GetAsString: string; begin result := parameter.Value; if result = DatasetWrapper.DatabaseWrapper.SQLDatabaseConfig.EmptyStringMarker then - result := ''; + result := ''; end; function TBoldADOParameter.GetAsVariant: Variant; @@ -653,6 +701,13 @@ function TBoldADOParameter.GetAsVariant: Variant; result := parameter.Value; end; +function TBoldADOParameter.GetAsWideString: WideString; +begin + result := Parameter.Value; + if string(result) = DatasetWrapper.DatabaseWrapper.SQLDatabaseConfig.EmptyStringMarker then + result := ''; +end; + function TBoldADOParameter.GetDataType: TFieldType; begin result := parameter.DataType; @@ -673,6 +728,14 @@ function TBoldADOParameter.GetParameter: TParameter; result := fParameter; end; +procedure TBoldADOParameter.SetAsAnsiString(const Value: TBoldAnsiString); +begin + if value = '' then + Parameter.Value := DatasetWrapper.DatabaseWrapper.SQLDatabaseConfig.EmptyStringMarker + else + Parameter.Value := Value +end; + procedure TBoldADOParameter.SetAsBCD(const Value: Currency); begin Parameter.Value := Value; @@ -713,6 +776,11 @@ procedure TBoldADOParameter.SetAsFloat(const Value: Double); Parameter.Value := Value; end; +procedure TBoldADOParameter.SetAsInt64(const Value: Int64); +begin + Parameter.Value := Value; +end; + procedure TBoldADOParameter.SetAsInteger(Value: Integer); begin Parameter.Value := Value; @@ -746,6 +814,14 @@ procedure TBoldADOParameter.SetAsVariant(const NewValue: Variant); Parameter.Value := NewValue; end; +procedure TBoldADOParameter.SetAsWideString(const Value: Widestring); +begin + if value = '' then + Parameter.Value := DatasetWrapper.DatabaseWrapper.SQLDatabaseConfig.EmptyStringMarker + else + Parameter.Value := Value +end; + procedure TBoldADOParameter.SetAsWord(Value: Integer); begin Parameter.Value := Value; @@ -766,14 +842,21 @@ procedure TBoldADOParameter.AssignFieldValue(source: IBoldField); Parameter.Assign(Source.Field); end; +procedure TBoldADOConnection.Reconnect; +begin + if Assigned(fDataBase) then begin + fDataBase.Connected := False; + fDataBase.Connected := True; + end; +end; + procedure TBoldADOConnection.ReleaseCachedObjects; begin FreeAndNil(fCachedTable); FreeAndNil(fCachedQuery); end; -end. - - +initialization +end. diff --git a/Source/Persistence/ADO/BoldDatabaseAdapterADO.pas b/Source/Persistence/ADO/BoldDatabaseAdapterADO.pas index 55fcafc..deb699d 100644 --- a/Source/Persistence/ADO/BoldDatabaseAdapterADO.pas +++ b/Source/Persistence/ADO/BoldDatabaseAdapterADO.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldDatabaseAdapterADO; interface @@ -22,7 +25,7 @@ TBoldDatabaseAdapterADO = class(TBoldAbstractDatabaseAdapter) procedure ReleaseBoldDatabase; override; function GetDataBaseInterface: IBoldDatabase; override; public - destructor Destroy; override; + destructor destroy; override; published property Connection: TADOConnection read GetDataBase write SetDataBase; {$IFNDEF T2H} @@ -35,11 +38,11 @@ implementation uses SysUtils, BoldDefs, - ADOConsts; + BoldRev; { TBoldDatabaseAdapterADO } -destructor TBoldDatabaseAdapterADO.Destroy; +destructor TBoldDatabaseAdapterADO.destroy; begin Changed; FreePublisher; @@ -55,7 +58,7 @@ function TBoldDatabaseAdapterADO.GetDataBase: TADOConnection; function TBoldDatabaseAdapterADO.GetDataBaseInterface: IBoldDatabase; begin if not assigned(Connection) then - raise EBold.CreateFmt(sAdapterNotConnected, [classname]); + raise EBold.CreateFmt('%s.GetDatabaseInterface: The adapter is not connected to an ADO connection', [classname]); if not assigned(fBoldDatabase) then fBoldDatabase := TBoldADOConnection.create(Connection, SQLDataBaseConfig); result := fBoldDatabase; @@ -71,4 +74,6 @@ procedure TBoldDatabaseAdapterADO.SetDataBase(const Value: TADOConnection); InternalDatabase := value; end; +initialization + end. diff --git a/Source/Persistence/ADO/BoldPersistenceHandleADO.pas b/Source/Persistence/ADO/BoldPersistenceHandleADO.pas index b7a7c18..776f731 100644 --- a/Source/Persistence/ADO/BoldPersistenceHandleADO.pas +++ b/Source/Persistence/ADO/BoldPersistenceHandleADO.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldPersistenceHandleADO; interface @@ -47,8 +50,8 @@ TBoldPersistenceHandleADO = class(TBoldDBPersistenceHandle) procedure InternalTransferproperties(const target: TBoldPersistenceHandleDB); override; {$ENDIF} public - constructor Create(owner: tComponent); override; - destructor Destroy; override; + constructor create(owner: tComponent); override; + destructor destroy; override; function GetDataBaseInterface: IBoldDatabase; override; procedure Assign(Source: TPersistent); override; published @@ -74,8 +77,7 @@ implementation SysUtils, BoldDefs, BoldDatabaseAdapterAdo, - BoldUtils, - ADOConsts; + BoldUtils; function BoldStringToNetworkProtocol(s: String): TBoldNetworkProtocol; var @@ -87,7 +89,7 @@ function BoldStringToNetworkProtocol(s: String): TBoldNetworkProtocol; result := i; exit; end; - + result := bnwpLocal; end; @@ -97,13 +99,13 @@ procedure TBoldPersistenceHandleADO.AddExtendedProperties( Result: TStrings); begin if trim(DataSource) <> '' then - result.Add('DSN='+trim(DataSource)); // do not localize + result.Add('DSN='+trim(DataSource)); if trim(HostName) <> '' then - Result.Add('Hostname='+trim(HostName)); // do not localize + Result.Add('Hostname='+trim(HostName)); if trim(InitialCatalog) <> '' then - Result.Add('Initial Catalog='+trim(InitialCatalog)); // do not localize + Result.Add('Initial Catalog='+trim(InitialCatalog)); - result.Add('NetworkProt='+BoldNetWorkProtocolStringRep[NetWorkProtocol]); // do not localize + result.Add('NetworkProt='+BoldNetWorkProtocolStringRep[NetWorkProtocol]); Result.AddStrings(ExtendedProperties); end; @@ -127,7 +129,7 @@ procedure TBoldPersistenceHandleADO.UpdateInternalConnectionString; LExtendedProperties := TStringList.Create; AddExtendedProperties(LExtendedProperties); - ConnectionString := format('Provider=%s;Persist Security Info=%s;Data Source=%s;Extended Properties=%s', // do not localize + ConnectionString := format('Provider=%s;Persist Security Info=%s;Data Source=%s;Extended Properties=%s', [Provider, BoolToStr[PersistSecurityInfo], DataSource, @@ -140,11 +142,12 @@ procedure TBoldPersistenceHandleADO.UpdateInternalConnectionString; constructor TBoldPersistenceHandleADO.create(owner: tComponent); begin inherited; - FHostName := ''; // do not localize + FHostName := ''; fExtendedProperties := TStringList.Create; end; -destructor TBoldPersistenceHandleADO.Destroy; + +destructor TBoldPersistenceHandleADO.destroy; begin Active := false; FreeAndNil(fOwnConnection); @@ -152,12 +155,13 @@ destructor TBoldPersistenceHandleADO.Destroy; inherited; end; + procedure TBoldPersistenceHandleADO.SetADOConnection( const Value: TADOConnection); begin if fADOConnection <> Value then begin - CheckInactive('SetDataBase'); // do not localize + CheckInactive('SetDataBase'); if assigned(fOwnConnection) then begin FreeAndNil(fOwnConnection); @@ -186,7 +190,7 @@ procedure TBoldPersistenceHandleADO.SetHostName(const Value: String); begin FHostName := Value; if trim(fHostName) = '' then - FHostName := ''; // do not localize + FHostName := ''; UpdateInternalConnectionString; end; @@ -243,7 +247,7 @@ function TBoldPersistenceHandleADO.getEffectiveConnection: TADOConnection; UpdateInternalConnectionString; end; result := fOwnConnection; - end; + end; end; procedure TBoldPersistenceHandleADO.SetPassword(const Value: string); @@ -280,14 +284,14 @@ procedure TBoldPersistenceHandleADO.InternalTransferproperties( if not assigned(Target.DatabaseAdapter) then begin Target.DatabaseAdapter := TBoldDatabaseAdapterADO.Create(Target.Owner); - Target.DatabaseAdapter.Name := GetNewComponentName(Target.DatabaseAdapter, 'BoldDatabaseAdapterADO'); // do not localize - LongRec(DesInfo).Lo := LongRec(DesInfo).lo+16; //set Left - LongRec(DesInfo).Hi := LongRec(DesInfo).hi+16; //Set Top; + Target.DatabaseAdapter.Name := GetNewComponentName(Target.DatabaseAdapter, 'BoldDatabaseAdapterADO'); + LongRec(DesInfo).Lo := LongRec(DesInfo).lo+16; + LongRec(DesInfo).Hi := LongRec(DesInfo).hi+16; Target.DatabaseAdapter.DesignInfo := DesInfo; - showmessage(sCreatedNewAdapter); + showmessage('Created a new DatabaseAdapterADO'); end else if not (target.DatabaseAdapter is TBoldDatabaseAdapterADO) then - raise Exception.CreateFmt(sCanOnlyTransferToADOAdapter, [target.DatabaseAdapter.ClassName] ); + raise Exception.CreateFmt('The persistencehandle is connected to a %s, properties can only be transfered to a TBoldDatabaseAdapterADO', [target.DatabaseAdapter.ClassName] ); Adapter := target.DatabaseAdapter as tBoldDatabaseAdapterADO; if assigned(fADOConnection) then @@ -296,17 +300,17 @@ procedure TBoldPersistenceHandleADO.InternalTransferproperties( if not assigned(Adapter.Connection) then begin Adapter.Connection := TADOConnection.Create(Target.owner); - Adapter.Connection.Name := GetNewComponentName(Adapter.Connection, 'ADODatabase'); // do not localize - showmessage(sCreatedNewDB); - LongRec(DesInfo).Lo := LongRec(DesInfo).lo+16; //set Left - LongRec(DesInfo).Hi := LongRec(DesInfo).hi+16; //Set Top; + Adapter.Connection.Name := GetNewComponentName(Adapter.Connection, 'ADODatabase'); + showmessage('Created a new ADODatabase'); + LongRec(DesInfo).Lo := LongRec(DesInfo).lo+16; + LongRec(DesInfo).Hi := LongRec(DesInfo).hi+16; Adapter.Connection.DesignInfo := DesInfo; try LExtendedProperties := TStringList.Create; AddExtendedProperties(LExtendedProperties); - ConnectionString := format('Provider=%s;Persist Security Info=%s;Data Source=%s;Extended Properties=%s', // do not localize + ConnectionString := format('Provider=%s;Persist Security Info=%s;Data Source=%s;Extended Properties=%s', [Provider, BoolToStr[PersistSecurityInfo], DataSource, @@ -316,9 +320,9 @@ procedure TBoldPersistenceHandleADO.InternalTransferproperties( except on e: exception do begin - showmessage(sCouldNotTransferConnectionString+BOLDCRLF+BOLDCRLF+ + showmessage('Connection string settings could not be transferred to the new ADO connection: '+BOLDCRLF+BOLDCRLF+ e.message + BOLDCRLF+BOLDCRLF + - sTransferManually); + 'Please transfer these manually!'); Adapter.Connection.ConnectionString := ''; end; @@ -326,7 +330,6 @@ procedure TBoldPersistenceHandleADO.InternalTransferproperties( end; end; +initialization end. - - diff --git a/Source/Persistence/ADO/BoldPersistenceHandleADOReg.pas b/Source/Persistence/ADO/BoldPersistenceHandleADOReg.pas index a5be726..3a25a19 100644 --- a/Source/Persistence/ADO/BoldPersistenceHandleADOReg.pas +++ b/Source/Persistence/ADO/BoldPersistenceHandleADOReg.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldPersistenceHandleADOReg; interface @@ -17,9 +20,7 @@ implementation procedure Register; begin - {$WARNINGS OFF} - RegisterComponents(BOLDPAGENAME_DEPRECATED, [TBoldPersistenceHandleADO]); - {$WARNINGS ON} + RegisterComponents(BOLDPAGENAME_DEPRECATED, [TBoldPersistenceHandleADO]); RegisterComponents(BOLDPAGENAME_PERSISTENCE, [TBoldDatabaseAdapterADO]); end; diff --git a/Source/Persistence/Advantage/BoldAdvantageInterfaces.pas b/Source/Persistence/Advantage/BoldAdvantageInterfaces.pas index 6eb4c4a..edebc9d 100644 --- a/Source/Persistence/Advantage/BoldAdvantageInterfaces.pas +++ b/Source/Persistence/Advantage/BoldAdvantageInterfaces.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldAdvantageInterfaces; interface @@ -10,7 +13,7 @@ interface adstable, BoldSQLDatabaseConfig, BoldDBInterfaces; - + type { forward declarations } TBoldAdvantageDatabase = class; @@ -33,7 +36,9 @@ TBoldAdvantageQuery = class(TBoldDataSetWrapper, IBoldQuery, IBoldExecQuery, I procedure AssignParams(Sourceparams: TParams); procedure ClearParams; procedure AssignSQL(SQL: TStrings); - procedure AssignSQLText(SQL: String); + procedure AssignSQLText(const SQL: String); + function GetParamCheck: Boolean; + procedure SetParamCheck(value: Boolean); procedure SetRequestLiveQuery(NewValue: Boolean); function Createparam(FldType: TFieldType; const ParamName: string; ParamType: TParamType; Size: integer): IBoldParameter; protected @@ -57,7 +62,7 @@ TBoldAdvantageTable = class(TBoldDataSetWrapper, IBoldTable) procedure DeleteTable; function GetTable: TADSTable; function GetIndexDefs: TIndexDefs; - procedure SetTableName(NewName: String); + procedure SetTableName(const NewName: String); function GetTableName: String; procedure SetExclusive(NewValue: Boolean); function GetExclusive: Boolean; @@ -82,12 +87,10 @@ TBoldAdvantageDatabase = class(TBolddatabaseWrapper, IBoldDataBase) function GetIsSQLBased: Boolean; function GetKeepConnection: Boolean; function GetLogInPrompt: Boolean; - function GetTable: IBoldTable; function SupportsTableCreation: boolean; procedure Close; procedure Commit; procedure Open; - procedure ReleaseTable(var Table: IBoldTable); procedure Rollback; procedure SetKeepConnection(NewValue: Boolean); procedure SetlogInPrompt(NewValue: Boolean); @@ -98,9 +101,11 @@ TBoldAdvantageDatabase = class(TBolddatabaseWrapper, IBoldDataBase) procedure AllTableNames(Pattern: String; ShowSystemTables: Boolean; TableNameList: TStrings); override; function GetQuery: IBoldQuery; override; procedure ReleaseQuery(var Query: IBoldQuery); override; + function GetTable: IBoldTable; override; + procedure ReleaseTable(var Table: IBoldTable); override; public - constructor Create(Database: TADSConnection; SQLDataBaseConfig: TBoldSQLDatabaseConfig); - destructor Destroy; override; + constructor create(Database: TADSConnection; SQLDataBaseConfig: TBoldSQLDatabaseConfig); + destructor destroy; override; end; var @@ -141,7 +146,7 @@ procedure TBoldAdvantageQuery.AssignSQL(SQL: TStrings); Query.SQL.EndUpdate; end; -procedure TBoldAdvantageQuery.AssignSQLText(SQL: String); +procedure TBoldAdvantageQuery.AssignSQLText(const SQL: String); begin Query.SQL.BeginUpdate; Query.SQL.Clear; @@ -158,6 +163,7 @@ constructor TBoldAdvantageQuery.Create(Query: TADSQuery; DatabaseWrapper: TBoldD begin inherited create(DatabaseWrapper); FQuery := Query; + SetParamCheck(true); end; function TBoldAdvantageQuery.Createparam(FldType: TFieldType; @@ -191,6 +197,11 @@ function TBoldAdvantageQuery.GetDataSet: TDataSet; result := Query; end; +function TBoldAdvantageQuery.GetParamCheck: Boolean; +begin + Result := Query.ParamCheck; +end; + function TBoldAdvantageQuery.GetParamCount: integer; begin result := Query.Params.count; @@ -244,6 +255,11 @@ function TBoldAdvantageQuery.ParamByName(const Value: string): IBoldParameter; end; +procedure TBoldAdvantageQuery.SetParamCheck(value: Boolean); +begin + Query.ParamCheck := Value; +end; + procedure TBoldAdvantageQuery.SetRequestLiveQuery(NewValue: Boolean); begin end; @@ -313,19 +329,16 @@ procedure TBoldAdvantageTable.SetExclusive(NewValue: Boolean); Table.Exclusive := NewValue; end; -procedure TBoldAdvantageTable.SetTableName(NewName: String); +procedure TBoldAdvantageTable.SetTableName(const NewName: String); begin Table.TableName := NewName; end; - - { TBoldSDDataBase } procedure TBoldAdvantageDatabase.AllTableNames(Pattern: String; ShowSystemTables: Boolean; TableNameList: TStrings); begin -// if (Pattern <> '') and (Pattern <> '*') then -// raise Exception.CreateFmt('%s.AlltableNames: This call does not allow patterns ("%s")', [ClassName, Pattern]); + Database.GetTableNames(TableNameList, Pattern {ShowSystemTables}); end; @@ -345,7 +358,7 @@ constructor TBoldAdvantageDatabase.create(DataBase: TADSConnection; SQLDataBaseC FDataBase := DataBase; end; -destructor TBoldAdvantageDatabase.Destroy; +destructor TBoldAdvantageDatabase.destroy; begin inherited; FDatabase := nil; @@ -487,4 +500,5 @@ function TBoldAdvantageDatabase.SupportsTableCreation: boolean; result := true; end; +initialization end. diff --git a/Source/Persistence/Advantage/BoldDatabaseAdapterAdvantage.pas b/Source/Persistence/Advantage/BoldDatabaseAdapterAdvantage.pas index 3cf8fd3..428729c 100644 --- a/Source/Persistence/Advantage/BoldDatabaseAdapterAdvantage.pas +++ b/Source/Persistence/Advantage/BoldDatabaseAdapterAdvantage.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldDatabaseAdapterAdvantage; interface @@ -22,7 +25,7 @@ TBoldDatabaseAdapterAdvantage = class(TBoldAbstractDatabaseAdapter) procedure ReleaseBoldDatabase; override; function GetDataBaseInterface: IBoldDatabase; override; public - destructor Destroy; override; + destructor destroy; override; published property DataBase: TADSConnection read GetDataBase write SetDataBase; {$IFNDEF T2H} @@ -34,16 +37,17 @@ implementation uses SysUtils, - BoldDefs; + BoldDefs, + BoldRev; -{ TBoldDatabaseAdapterAdvantage } +{ TBoldDatabaseAdapterAdvantage } -destructor TBoldDatabaseAdapterAdvantage.Destroy; +destructor TBoldDatabaseAdapterAdvantage.destroy; begin Changed; FreePublisher; FreeAndNil(fBoldDatabase); - inherited; + inherited; end; function TBoldDatabaseAdapterAdvantage.GetDataBase: TADSConnection; @@ -54,7 +58,7 @@ function TBoldDatabaseAdapterAdvantage.GetDataBase: TADSConnection; function TBoldDatabaseAdapterAdvantage.GetDataBaseInterface: IBoldDatabase; begin if not assigned(Database) then - raise EBold.CreateFmt('%s.GetDatabaseInterface: The adapter is not connected to a database', [classname]); + raise EBold.CreateFmt('%s.GetDatabaseInterface: The adapter is not connected to a database', [classname]); if not assigned(fBoldDatabase) then fBoldDatabase := TBoldAdvantageDataBase.create(Database, SQLDataBaseConfig); result := fBoldDatabase; @@ -70,4 +74,6 @@ procedure TBoldDatabaseAdapterAdvantage.SetDataBase(const Value: TADSConnection) InternalDatabase := value; end; +initialization + end. diff --git a/Source/Persistence/Advantage/BoldPersistenceHandleAdvantage.pas b/Source/Persistence/Advantage/BoldPersistenceHandleAdvantage.pas index 17618b4..579c1b1 100644 --- a/Source/Persistence/Advantage/BoldPersistenceHandleAdvantage.pas +++ b/Source/Persistence/Advantage/BoldPersistenceHandleAdvantage.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldPersistenceHandleAdvantage; interface @@ -21,7 +24,7 @@ TBoldPersistenceHandleAdvantage = class(TBoldDBPersistenceHandle) property DatabaseAdapter: TBoldAdvantageDatabase read FDatabaseAdapter; property EffectiveDatabase: TAdsConnection read GetEffectiveDatabase; public - destructor Destroy; override; + destructor destroy; override; function GetDataBaseInterface: IBoldDatabase; override; published property AdsConnection: TAdsConnection read FAdsConnection write SetDatabase; @@ -30,11 +33,12 @@ TBoldPersistenceHandleAdvantage = class(TBoldDBPersistenceHandle) implementation uses - SysUtils; + SysUtils, + BoldRev; { TBoldPersistenceHandleAdvantage } -destructor TBoldPersistenceHandleAdvantage.Destroy; +destructor TBoldPersistenceHandleAdvantage.destroy; begin Active := false; FreeAndNil(FEffectiveDatabase); @@ -84,4 +88,6 @@ procedure TBoldPersistenceHandleAdvantage.SetDataBase(const Value: TAdsConnectio end; end; +initialization + end. diff --git a/Source/Persistence/Advantage/BoldPersistenceHandleAdvantageReg.pas b/Source/Persistence/Advantage/BoldPersistenceHandleAdvantageReg.pas index 72dafce..4de7925 100644 --- a/Source/Persistence/Advantage/BoldPersistenceHandleAdvantageReg.pas +++ b/Source/Persistence/Advantage/BoldPersistenceHandleAdvantageReg.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldPersistenceHandleAdvantageReg; interface @@ -13,15 +16,21 @@ implementation Classes, registry, BoldIDESupport, + BoldVersionInfo, BoldDatabaseAdapterAdvantage, BoldPersistenceHandleAdvantage, BoldIDEConsts; procedure Register; begin - RemovePackageFromDisabledPackagesRegistry(format('BoldAdvantage%s', [LIBSUFFIX])); // do not localize + RemovePackageFromDisabledPackagesRegistry(format('Bold%d%d%sAdvantage', [ + BoldBuildVersionNumberMajor, + BoldBuildVersionNumberMinor, + BoldBuildTarget])); RegisterComponents(BOLDPAGENAME_DEPRECATED, [TBoldPersistenceHandleAdvantage]); RegisterComponents(BOLDPAGENAME_PERSISTENCE, [TBoldDatabaseAdapterAdvantage]); end; +initialization + end. diff --git a/Source/Persistence/BDE/BDEConsts.pas b/Source/Persistence/BDE/BDEConsts.pas index 09abc16..0487eba 100644 --- a/Source/Persistence/BDE/BDEConsts.pas +++ b/Source/Persistence/BDE/BDEConsts.pas @@ -20,4 +20,4 @@ interface implementation -end. \ No newline at end of file +end. diff --git a/Source/Persistence/BDE/BoldBDEBatchInterfaces.pas b/Source/Persistence/BDE/BoldBDEBatchInterfaces.pas index 22d7cd6..7e8d1e3 100644 --- a/Source/Persistence/BDE/BoldBDEBatchInterfaces.pas +++ b/Source/Persistence/BDE/BoldBDEBatchInterfaces.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldBDEBatchInterfaces; interface @@ -30,10 +33,11 @@ TBoldBDEBatchQuery = class(TBoldBDEQuery) property InBatch: Boolean read FInBatch write fInBatch; property HasCachedStatements: boolean read GetHasCachedStatements; public - destructor Destroy; override; + destructor destroy; override; class procedure InstallBatchQueries; end; + var BOLDBATCHQUERYMAXSIZE: integer = 30000; BOLDBATCHQUERYSEPARATOR: string = ';'; @@ -43,8 +47,7 @@ implementation uses SysUtils, dbTables, - BoldDefs, - BDEConsts; + BoldDefs; function ReplaceParamMarkers(const sql: String; Counter: integer; SourceParams, DestParams: TParams): String; const @@ -98,7 +101,7 @@ function ReplaceParamMarkers(const sql: String; Counter: integer; SourceParams, NewParam := DestParams.CreateParam(OldParam.DataType, prefix+OldParam.Name, OldParam.ParamType); NewParam.Assign(OldParam); - NewParam.Name:=prefix+OldParam.Name; // HK Assign also transfers name + NewParam.Name:=prefix+OldParam.Name; if OldParam.IsNull then NewParam.Clear else @@ -109,7 +112,7 @@ function ReplaceParamMarkers(const sql: String; Counter: integer; SourceParams, CurPos := StartPos; end else - if IsLiteral then + if IsLiteral then Literal := not Literal; Inc(CurPos); until CurPos > Length(TempResult); @@ -138,7 +141,7 @@ procedure TBoldBDEBatchQuery.BatchExecSQL; ExecuteBatch; end; -destructor TBoldBDEBatchQuery.Destroy; +destructor TBoldBDEBatchQuery.destroy; begin FreeAndNil(fAccumulatedParams); FreeAndNil(fAccumulatedSQL); @@ -189,10 +192,12 @@ procedure TBoldBDEBatchQuery.ExecuteBatch; if assigned(BatchQuery.DBSession) then begin Driver := Query.DBSession.GetAliasDriverName(query.DatabaseName); - if pos('INFORMIX', UpperCase(Driver)) = 0 then // do not localize - DriverMsg := Format(sOnlyTestedWithInformix, [BOLDCRLF]); + if pos('INFORMIX', UpperCase(Driver)) = 0 then + DriverMsg := 'Batch operations has only been tested with Informix' + BOLDCRLF; end; - e.Message := Format(sBatchFailure, [DriverMsg, e.Message, BOLDCRLF, BatchQuery.SQL.Text]); + e.Message := DriverMsg+ + 'Batch operation failed: ' + e.MEssage + BOLDCRLF + + 'SQL: '+BatchQuery.SQL.Text; raise; end; end; @@ -246,5 +251,5 @@ procedure TBoldBDEBatchQuery.StartSQLBatch; InBatch := true; end; +initialization end. - diff --git a/Source/Persistence/BDE/BoldBDEInterfaces.pas b/Source/Persistence/BDE/BoldBDEInterfaces.pas index 24837d7..f6520aa 100644 --- a/Source/Persistence/BDE/BoldBDEInterfaces.pas +++ b/Source/Persistence/BDE/BoldBDEInterfaces.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldBDEInterfaces; interface @@ -24,16 +27,25 @@ TBoldBDEQuery = class(TBoldDataSetWrapper, IBoldQuery, IBoldExecQuery, IBoldPa function GetQuery: TQuery; procedure AssignParams(SourceParams: TParams); function GetParamCount: integer; - function GetParams(i: integer): IBoldParameter; + function GetParams: TParams; + function GetParam(i: integer): IBoldParameter; function GetRequestLiveQuery: Boolean; function ParamByName(const Value: string): IBoldParameter; procedure SetRequestLiveQuery(NewValue: Boolean); function GetSQLText: String; + function GetSQLStrings: TStrings; procedure AssignSQL(SQL: TStrings); - procedure AssignSQLText(SQL: String); + procedure AssignSQLText(const SQL: String); + function GetParamCheck: Boolean; + procedure SetParamCheck(value: Boolean); function GetRowsAffected: integer; function GetRecordCount: integer; - function Createparam(FldType: TFieldType; const ParamName: string; ParamType: TParamType; Size: integer): IBoldParameter; + function Createparam(FldType: TFieldType; const ParamName: string; ParamType: TParamType; Size: integer): IBoldParameter; override; + function GetUseReadTransactions: boolean; + procedure SetUseReadTransactions(value: boolean); + procedure BeginExecuteQuery; + procedure EndExecuteQuery; + function GetBatchQueryParamCount: integer; protected function GetDataSet: TDataSet; override; procedure StartSQLBatch; virtual; @@ -56,7 +68,7 @@ TBoldBDETable = class(TBoldDataSetWrapper, IBoldTable) procedure DeleteTable; function GetTable: TTable; function GetIndexDefs: TIndexDefs; - procedure SetTableName(NewName: String); + procedure SetTableName(const NewName: String); function GetTableName: String; procedure SetExclusive(NewValue: Boolean); function GetExclusive: Boolean; @@ -74,6 +86,7 @@ TBoldBDEDataBase = class(TBoldDatabaseWrapper, IBoldDataBase) fDataBase: TDataBase; fCachedTable: TTable; fCachedQuery: TQuery; + fExecuteQueryCount: integer; function GetConnected: Boolean; function GetInTransaction: Boolean; function GetIsSQLBased: Boolean; @@ -86,17 +99,22 @@ TBoldBDEDataBase = class(TBoldDatabaseWrapper, IBoldDataBase) procedure RollBack; procedure Open; procedure Close; + procedure Reconnect; function GetTable: IBoldTable; procedure ReleaseTable(var Table: IBoldTable); function SupportsTableCreation: Boolean; procedure ReleaseCachedObjects; + function GetIsExecutingQuery: Boolean; + procedure BeginExecuteQuery; + procedure EndExecuteQuery; protected procedure AllTableNames(Pattern: String; ShowSystemTables: Boolean; TableNameList: TStrings); override; function GetQuery: IBoldQuery; override; procedure ReleaseQuery(var Query: IBoldQuery); override; public - constructor Create(DataBase: TDataBase; SQLDataBaseConfig: TBoldSQLDatabaseConfig); - destructor Destroy; override; + constructor create(DataBase: TDataBase; SQLDataBaseConfig: TBoldSQLDatabaseConfig); + destructor destroy; override; + procedure CreateDatabase; end; var @@ -107,8 +125,7 @@ implementation uses SysUtils, BoldDefs, - BoldUtils, - BDEConsts; + BoldUtils; { TBoldBDEQuery } @@ -127,12 +144,22 @@ function TBoldBDEQuery.GetQuery: TQuery; result := fQuery; end; +function TBoldBDEQuery.GetParamCheck: Boolean; +begin + Result := Query.ParamCheck; +end; + function TBoldBDEQuery.GetParamCount: integer; begin result := Query.params.count; end; -function TBoldBDEQuery.GetParams(I: integer): IBoldParameter; +function TBoldBDEQuery.GetParams: TParams; +begin + result := Query.Params; +end; + +function TBoldBDEQuery.GetParam(I: integer): IBoldParameter; begin result := TBoldDbParameter.Create(Query.Params[i], self); end; @@ -153,11 +180,26 @@ function TBoldBDEQuery.ParamByName(const Value: string): IBoldParameter; result := nil; end; +procedure TBoldBDEQuery.SetParamCheck(value: Boolean); +begin + Query.ParamCheck := Value; +end; + procedure TBoldBDEQuery.SetRequestLiveQuery(NewValue: Boolean); begin Query.RequestLive := NewValue; end; +procedure TBoldBDEQuery.SetUseReadTransactions(value: boolean); +begin + +end; + +function TBoldBDEQuery.GetBatchQueryParamCount: integer; +begin + result := 0 +end; + function TBoldBDEQuery.GetDataSet: TDataSet; begin result := Query; @@ -165,60 +207,72 @@ function TBoldBDEQuery.GetDataSet: TDataSet; procedure TBoldBDEQuery.ExecSQL; begin + BeginExecuteQuery; + try BoldLogSQL(Query.SQL); try Query.ExecSQL; except on e: Exception do begin - e.Message := Format(sSQLFailure, [e.Message, BOLDCRLF, Query.SQL.text]); + e.Message := e.Message + BOLDCRLF + 'SQL: ' + Query.SQL.text; raise; end; end + finally + EndExecuteQuery; + end; end; constructor TBoldBDEQuery.Create(Query: TQuery; DatabaseWrapper: TBoldDatabaseWrapper); begin inherited Create(DatabaseWrapper); fQuery := Query; + SetParamCheck(true); +end; + +procedure TBoldBDEQuery.EndExecuteQuery; +begin + (DatabaseWrapper as TBoldBDEDataBase).EndExecuteQuery; end; procedure TBoldBDEQuery.EndSQLBatch; begin - // intentionally left blank end; procedure TBoldBDEQuery.StartSQLBatch; begin - // intentionally left blank end; procedure TBoldBDEQuery.FailSQLBatch; begin - // intentionally left blank end; procedure TBoldBDEQuery.Open; begin + BeginExecuteQuery; + try BoldLogSQL(Query.SQL); try inherited; except on e: Exception do begin - e.Message := Format(sSQLFailure, [e.Message, BOLDCRLF, Query.SQL.text]); + e.Message := e.Message + BOLDCRLF + 'SQL: ' + Query.SQL.text; raise; end; end + finally + EndExecuteQuery; + end; end; procedure TBoldBDEQuery.AssignSQL(SQL: TStrings); begin - // Assign already calls BeginUpdate and EndUpdate before and after doing the actual assign Query.SQL.Assign(SQL); end; -procedure TBoldBDEQuery.AssignSQLText(SQL: String); +procedure TBoldBDEQuery.AssignSQLText(const SQL: String); begin Query.SQL.BeginUpdate; Query.SQL.Clear; @@ -226,11 +280,26 @@ procedure TBoldBDEQuery.AssignSQLText(SQL: String); Query.SQL.EndUpdate; end; +procedure TBoldBDEQuery.BeginExecuteQuery; +begin + (DatabaseWrapper as TBoldBDEDataBase).EndExecuteQuery; +end; + +function TBoldBDEQuery.GetSQLStrings: TStrings; +begin + result := Query.SQL; +end; + function TBoldBDEQuery.GetSQLText: String; begin result := Query.SQL.text; end; +function TBoldBDEQuery.GetUseReadTransactions: boolean; +begin + result := false; +end; + function TBoldBDEQuery.GetRowsAffected: integer; begin result := Query.RowsAffected; @@ -312,7 +381,7 @@ procedure TBoldBDETable.SetExclusive(NewValue: Boolean); Table.Exclusive := NewValue; end; -procedure TBoldBDETable.SetTableName(NewName: String); +procedure TBoldBDETable.SetTableName(const NewName: String); begin Table.TableName := NewName; end; @@ -331,6 +400,11 @@ function TBoldBDEDataBase.GetInTransaction: Boolean; result := fDataBase.InTransaction; end; +function TBoldBDEDataBase.GetIsExecutingQuery: Boolean; +begin + Result := fExecuteQueryCount > 0; +end; + function TBoldBDEDataBase.GetIsSQLBased: Boolean; begin result := fDataBase.IsSQLBased; @@ -362,6 +436,11 @@ constructor TBoldBDEDataBase.create(DataBase: TDataBase; SQLDataBaseConfig: TBol fDataBase := DataBase; end; +procedure TBoldBDEDataBase.CreateDatabase; +begin + Assert(false, 'Not implemented.'); +end; + function TBoldBDEDataBase.GetConnected: Boolean; begin result := fDataBase.Connected; @@ -387,12 +466,22 @@ procedure TBoldBDEDataBase.Open; fDataBase.Open; end; +procedure TBoldBDEDataBase.BeginExecuteQuery; +begin + inc(fExecuteQueryCount); +end; + +procedure TBoldBDEDataBase.EndExecuteQuery; +begin + dec(fExecuteQueryCount); +end; + procedure TBoldBDEDataBase.Close; begin fDataBase.Close; end; -destructor TBoldBDEDataBase.Destroy; +destructor TBoldBDEDataBase.destroy; begin inherited; fDatabase := nil; @@ -478,13 +567,19 @@ function TBoldBDEDataBase.SupportsTableCreation: Boolean; result := true; end; +procedure TBoldBDEDataBase.Reconnect; +begin + if Assigned(FDataBase) then begin + FDataBase.Connected := False; + FDataBase.Connected := True; + end; +end; + procedure TBoldBDEDataBase.ReleaseCachedObjects; begin FreeAndNil(fCachedTable); FreeAndNil(fCachedQuery); end; +initialization end. - - - diff --git a/Source/Persistence/BDE/BoldDatabaseAdapterBDE.pas b/Source/Persistence/BDE/BoldDatabaseAdapterBDE.pas index 4a8bb88..2656a9a 100644 --- a/Source/Persistence/BDE/BoldDatabaseAdapterBDE.pas +++ b/Source/Persistence/BDE/BoldDatabaseAdapterBDE.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldDatabaseAdapterBDE; interface @@ -22,7 +25,7 @@ TBoldDatabaseAdapterBDE = class(TBoldAbstractDatabaseAdapter) procedure ReleaseBoldDatabase; override; function GetDataBaseInterface: IBoldDatabase; override; public - destructor Destroy; override; + destructor destroy; override; published property DataBase: TDataBase read GetDataBase write SetDataBase; {$IFNDEF T2H} @@ -35,16 +38,16 @@ implementation uses SysUtils, BoldDefs, - BDEConsts; + BoldRev; -{ TBoldDatabaseAdapterBDE } +{ TBoldDatabaseAdapterBDE } -destructor TBoldDatabaseAdapterBDE.Destroy; +destructor TBoldDatabaseAdapterBDE.destroy; begin Changed; FreePublisher; FreeAndNil(fBoldDatabase); - inherited; + inherited; end; function TBoldDatabaseAdapterBDE.GetDataBase: TDataBase; @@ -55,7 +58,7 @@ function TBoldDatabaseAdapterBDE.GetDataBase: TDataBase; function TBoldDatabaseAdapterBDE.GetDataBaseInterface: IBoldDatabase; begin if not assigned(Database) then - raise EBold.CreateFmt(sAdapterNotConnected, [classname]); + raise EBold.CreateFmt('%s.GetDatabaseInterface: The adapter is not connected to a database', [classname]); if not assigned(fBoldDatabase) then fBoldDatabase := TBoldBDEDataBase.create(Database, SQLDataBaseConfig); result := fBoldDatabase; @@ -71,4 +74,6 @@ procedure TBoldDatabaseAdapterBDE.SetDataBase(const Value: TDataBase); InternalDatabase := value; end; +initialization + end. diff --git a/Source/Persistence/BDE/BoldPersistenceHandleBDE.pas b/Source/Persistence/BDE/BoldPersistenceHandleBDE.pas index 319a964..4007ffb 100644 --- a/Source/Persistence/BDE/BoldPersistenceHandleBDE.pas +++ b/Source/Persistence/BDE/BoldPersistenceHandleBDE.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldPersistenceHandleBDE; interface @@ -39,7 +42,7 @@ TBoldPersistenceHandleBDE = class(TBoldDBPersistenceHandle) procedure InternalTransferproperties(const target: TBoldPersistenceHandleDB); override; {$ENDIF} public - destructor Destroy; override; + destructor destroy; override; function GetDataBaseInterface: IBoldDatabase; override; published property DatabaseName: string read GetDataBasename write SetDataBaseName; @@ -51,16 +54,11 @@ implementation uses SysUtils, - BoldDatabaseAdapterBDE, - BDEConsts; - -const - USERNAME = 'USER NAME'; - PASSWORD = 'PASSWORD'; + BoldDatabaseAdapterBDE; { TBoldPersistenceHandleBDE } -destructor TBoldPersistenceHandleBDE.Destroy; +destructor TBoldPersistenceHandleBDE.destroy; begin Active := false; FreeAndNil(fOwnDataBase); @@ -111,10 +109,10 @@ function TBoldPersistenceHandleBDE.getEffectiveDataBase: TDataBase; if not fExistingDatabase.Connected then begin if UserName <> '' then - fExistingDataBase.Params.Values[USERNAME] := Username; + fExistingDataBase.Params.Values['USER NAME'] := Username; if Password <> '' then begin - fExistingDataBase.Params.Values[PASSWORD] := Password; + fExistingDataBase.Params.Values['PASSWORD'] := Password; fExistingDataBase.LoginPrompt := false; end; end; @@ -124,14 +122,12 @@ function TBoldPersistenceHandleBDE.getEffectiveDataBase: TDataBase; end; end; - // we had no database, and were not able to find any database... - fOwnDataBase := TDataBase.Create(nil); - fOwnDataBase.name := name+'_DataBase'; // do not localize + fOwnDataBase.name := name+'_DataBase'; fOwnDataBase.DatabaseName := DatabaseName; fOwnDataBase.SessionName := SessionName; - fOwnDataBase.Params.Values[USERNAME] := Username; - fOwnDataBase.Params.Values[PASSWORD] := Password; + fOwnDataBase.Params.Values['USER NAME'] := Username; + fOwnDataBase.Params.Values['PASSWORD'] := Password; if PassWord <> '' then fOwnDataBase.LoginPrompt := false; result := fOwnDataBase; @@ -148,14 +144,14 @@ procedure TBoldPersistenceHandleBDE.InternalTransferproperties( if not assigned(Target.DatabaseAdapter) then begin Target.DatabaseAdapter := TBoldDatabaseAdapterBDE.Create(Target.Owner); - Target.DatabaseAdapter.Name := GetNewComponentName(Target.DatabaseAdapter, 'BoldDatabaseAdapterBDE'); // do not localize - LongRec(DesInfo).Lo := LongRec(DesInfo).lo+16; //set Left - LongRec(DesInfo).Hi := LongRec(DesInfo).hi+16; //Set Top; + Target.DatabaseAdapter.Name := GetNewComponentName(Target.DatabaseAdapter, 'BoldDatabaseAdapterBDE'); + LongRec(DesInfo).Lo := LongRec(DesInfo).lo+16; + LongRec(DesInfo).Hi := LongRec(DesInfo).hi+16; Target.DatabaseAdapter.DesignInfo := DesInfo; - showmessage(sCreatedNewAdapter); + showmessage('Created a new DatabaseAdapterBDE'); end else if not (target.DatabaseAdapter is tBoldDatabaseAdapterBDE) then - raise Exception.CreateFmt(sPropertiesCannotBeTransferred, [target.DatabaseAdapter.ClassName] ); + raise Exception.CreateFmt('The persistencehandle is connected to a %s, properties can only be transfered to a TBoldDatabaseAdapterBDE', [target.DatabaseAdapter.ClassName] ); Adapter := target.DatabaseAdapter as tBoldDatabaseAdapterBDE; if assigned(fDatabase) then @@ -164,15 +160,15 @@ procedure TBoldPersistenceHandleBDE.InternalTransferproperties( if not assigned(Adapter.Database) then begin Adapter.DataBase := TDatabase.Create(Target.owner); - Adapter.DataBase.Name := GetNewComponentName(Adapter.DataBase, 'Database'); // do not localize - showmessage(sCreatedNewDB); - LongRec(DesInfo).Lo := LongRec(DesInfo).lo+16; //set Left - LongRec(DesInfo).Hi := LongRec(DesInfo).hi+16; //Set Top; + Adapter.DataBase.Name := GetNewComponentName(Adapter.DataBase, 'Database'); + showmessage('Created a new Database'); + LongRec(DesInfo).Lo := LongRec(DesInfo).lo+16; + LongRec(DesInfo).Hi := LongRec(DesInfo).hi+16; Adapter.DataBase.DesignInfo := DesInfo; end; - Adapter.Database.Params.Values[PASSWORD] := Password; - Adapter.Database.Params.Values[USERNAME] := Username; - if Adapter.Database.Params.Values[PASSWORD] <> '' then + Adapter.Database.Params.Values['PASSWORD'] := Password; + Adapter.Database.Params.Values['USER NAME'] := Username; + if Adapter.Database.Params.Values['PASSWORD'] <> '' then Adapter.Database.LoginPrompt := false; if not assigned(Database) then Adapter.DataBase.DatabaseName := DatabaseName; @@ -204,7 +200,7 @@ procedure TBoldPersistenceHandleBDE.SetDataBase(const Value: TDataBase); begin if fDataBase <> Value then begin - CheckInactive('SetDataBase'); // do not localize + CheckInactive('SetDataBase'); if assigned(fOwnDataBase) then begin FreeAndNil(FOwnDataBase); @@ -225,7 +221,7 @@ procedure TBoldPersistenceHandleBDE.SetDatabaseName(const Value: string); begin if FDatabaseName <> Value then begin - CheckInactive('SetDataBaseName'); // do not localize + CheckInactive('SetDataBaseName'); if assigned(fOwnDataBase) then fOwnDataBase.DatabaseName := DatabaseName; FDatabaseName := Value; @@ -238,18 +234,18 @@ procedure TBoldPersistenceHandleBDE.SetPassword(const Value: string); if Value <> PassWord then begin if assigned(fOwnDataBase) then - fOwnDataBase.Params.Values[PASSWORD] := value; + fOwnDataBase.Params.Values['PASSWORD'] := value; if assigned(fExistingDataBase) then - fExistingDataBase.Params.Values[PASSWORD] := Value; + fExistingDataBase.Params.Values['PASSWORD'] := Value; end; - inherited; + inherited; end; procedure TBoldPersistenceHandleBDE.SetSessionName(const Value: String); begin if FSessionName <> Value then begin - CheckInactive('SetSessionName'); // do not localize + CheckInactive('SetSessionName'); FSessionName := Value; if assigned(fOwnDataBase) then fOwnDataBase.SessionName := SessionName; @@ -262,11 +258,13 @@ procedure TBoldPersistenceHandleBDE.SetUserName(const Value: string); if value <> Username then begin if assigned(fOwnDataBase) then - fOwnDataBase.Params.Values[USERNAME] := UserName; + fOwnDataBase.Params.Values['USER NAME'] := UserName; if assigned(fExistingDataBase) then - fExistingDataBase.Params.Values[USERNAME] := UserName; + fExistingDataBase.Params.Values['USER NAME'] := UserName; end; inherited; end; +initialization + end. diff --git a/Source/Persistence/BDE/BoldPersistenceHandleBDEPropertyEditors.pas b/Source/Persistence/BDE/BoldPersistenceHandleBDEPropertyEditors.pas index 1e0a45f..06907a8 100644 --- a/Source/Persistence/BDE/BoldPersistenceHandleBDEPropertyEditors.pas +++ b/Source/Persistence/BDE/BoldPersistenceHandleBDEPropertyEditors.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldPersistenceHandleBDEPropertyEditors; interface @@ -7,7 +10,7 @@ interface BoldPropertyEditors; type - { forward declarations } + { forward declarations } TBoldDatabaseNameProperty = class; TBoldSessionNameProperty = class; @@ -23,10 +26,11 @@ TBoldSessionNameProperty = class(TBoldStringSelectionProperty) procedure GetValueList(List: TStrings); override; end; -implementation +implementation uses - DBTables; + DBTables, + BoldRev; { TBoldDatabaseNameProperty } @@ -43,4 +47,6 @@ procedure TBoldSessionNameProperty.GetValueList(List: TStrings); Sessions.GetSessionNames(List); end; +initialization + end. diff --git a/Source/Persistence/BDE/BoldPersistenceHandleBdeReg.pas b/Source/Persistence/BDE/BoldPersistenceHandleBdeReg.pas index 60c280a..8907b91 100644 --- a/Source/Persistence/BDE/BoldPersistenceHandleBdeReg.pas +++ b/Source/Persistence/BDE/BoldPersistenceHandleBdeReg.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldPersistenceHandleBDEReg; interface @@ -20,11 +23,9 @@ implementation procedure Register; begin RegisterComponents(BOLDPAGENAME_PERSISTENCE, [TBoldDatabaseAdapterBDE]); - {$WARNINGS OFF} RegisterComponents(BOLDPAGENAME_DEPRECATED, [TBoldPersistenceHandleBDE]); - RegisterPropertyEditor(TypeInfo(string), TBoldPersistenceHandleBDE, 'DatabaseName', TBoldDatabaseNameProperty); // do not localize - RegisterPropertyEditor(TypeInfo(string), TBoldPersistenceHandleBDE, 'SessionName', TBoldSessionNameProperty); // do not localize - {$WARNINGS ON} + RegisterPropertyEditor(TypeInfo(string), TBoldPersistenceHandleBDE, 'DatabaseName', TBoldDatabaseNameProperty); + RegisterPropertyEditor(TypeInfo(string), TBoldPersistenceHandleBDE, 'SessionName', TBoldSessionNameProperty); end; end. diff --git a/Source/Persistence/COM/BoldAbstractComClientPersistenceHandles.pas b/Source/Persistence/COM/BoldAbstractComClientPersistenceHandles.pas index 466c57c..83966d2 100644 --- a/Source/Persistence/COM/BoldAbstractComClientPersistenceHandles.pas +++ b/Source/Persistence/COM/BoldAbstractComClientPersistenceHandles.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldAbstractComClientPersistenceHandles; interface @@ -139,5 +142,7 @@ procedure TBoldAbstractComClientPersistenceHandle.SetObjectName(const Value: str end; end; -end. +initialization + +end. diff --git a/Source/Persistence/COM/BoldAbstractComPersistenceControllerProxy.pas b/Source/Persistence/COM/BoldAbstractComPersistenceControllerProxy.pas index 1f0dbae..6a19922 100644 --- a/Source/Persistence/COM/BoldAbstractComPersistenceControllerProxy.pas +++ b/Source/Persistence/COM/BoldAbstractComPersistenceControllerProxy.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldAbstractComPersistenceControllerProxy; interface @@ -29,6 +32,9 @@ TBoldAbstractComPersistenceControllerProxy = class(TBoldPersistenceController) implementation +uses + BoldRev; + { TBoldAbstractComPersistenceControllerProxy } destructor TBoldAbstractComPersistenceControllerProxy.Destroy; @@ -48,7 +54,7 @@ procedure TBoldAbstractComPersistenceControllerProxy.ExactifyIds( begin TranslationList := TBoldIDTranslationList.Create; try - PMExactifyIds(ObjectIdList, TranslationList); + PMExactifyIds(ObjectIdList, TranslationList, false); ValueSpace.ExactifyIds(TranslationList); ObjectIdList.ExactifyIds(TranslationList); finally @@ -62,5 +68,6 @@ procedure TBoldAbstractComPersistenceControllerProxy.SubscribeToPeristenceEvents inherited; end; -end. +initialization +end. diff --git a/Source/Persistence/Core/BoldAbstractSnooper.pas b/Source/Persistence/Core/BoldAbstractSnooper.pas index 9ec0b6d..e589ced 100644 --- a/Source/Persistence/Core/BoldAbstractSnooper.pas +++ b/Source/Persistence/Core/BoldAbstractSnooper.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldAbstractSnooper; interface @@ -15,39 +18,58 @@ interface {forward declarations} TBoldAbstractSnooper = class; + TBooleanArray = array of boolean; + TBoldAbstractSnooper = class(TBoldPersistenceControllerPassthrough) private fMoldModel: TMoldModel; fEvents: TStringList; + fEventsLength: integer; + fEventClassFlags: TBooleanArray; fSubscriptions: TStringList; fCancelledSubscriptions: TStringList; fModelSorted: Boolean; FOnPropagatorFailure: TBoldNotifyEventWithErrorMessage; + fClassesToIgnore: string; + fArrayOfClassesToIgnore: TBooleanArray; + fUseSubscriptions: boolean; + fUseClassEvents: boolean; + fUseMemberLevelOSS: boolean; + fEventTimeStamp: TDateTime; + procedure SetClassesToIgnore(const Value: string); protected - procedure GenerateNonEmbeddedStateChangedEvent(OldID, NewID: TBoldObjectId; const NonEmbeddedLinkName: string); + procedure GenerateNonEmbeddedStateChangedEvent(OldID, NewID: TBoldObjectId; MoldClass: TMoldClass; const NonEmbeddedLinkName: string); procedure SubscribeToNonEmbeddedStateChangedEvent(Id: TBoldObjectId; const NonEmbeddedLinkName: string); function ObjectIdByMemberIndex(Object_Content: IBoldObjectContents; MemberIndex: integer): TBoldObjectID; - function MemberIsEmbeddedSingleLink(MoldMember: TMoldMember; var NonEmbeddedLinkName: string): Boolean; + function MemberIsEmbeddedSingleLink(MoldMember: TMoldMember; var NonEmbeddedLink: TMoldRole): Boolean; function MemberIsNonEmbeddedLink(MoldMember: TMoldMember; var MemberName: string): Boolean; function ClassNameFromClassID(const TopSortedIndex: integer): string; - procedure NonEmbeddedStateOfObjectChanged(Object_Content, NewObject_Content: IBoldObjectContents; MoldClass: TMoldClass); + procedure NonEmbeddedStateOfObjectChanged(const Object_Content, NewObject_Content: IBoldObjectContents; MoldClass: TMoldClass); procedure ClearEvents; procedure EnsureDataBaseLock(const ClientID: TBoldClientID); virtual; procedure ReleaseDataBaseLock(const ClientID: TBoldClientID); virtual; procedure DoPropagatorFailure(Sender: TObject; const ErrorMessage: string); procedure AddClassEvents(TopsortedIndex: integer); + procedure AddEvent(const AEvent: string); + procedure AddSubscription(const AEvent: string); + procedure CancelSubscription(const AEvent: string); + function EventLimitReached: boolean; public - constructor Create(MoldModel: TMoldModel); + constructor Create(MoldModel: TMoldModel); virtual; destructor Destroy; override; procedure PMFetch(ObjectIdList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; MemberIdList: TBoldMemberIdList; FetchMode: Integer; BoldClientID: TBoldClientID); override; procedure PMFetchIDListWithCondition(ObjectIdList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; FetchMode: Integer; Condition: TBoldCondition; BoldClientID: TBoldClientID); override; - procedure PMUpdate(ObjectIdList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; Old_Values: IBoldValueSpace; Precondition: TBoldUpdatePrecondition; TranslationList: TBoldIdTranslationList; var TimeStamp: TBoldTimeStampType; BoldClientID: TBoldClientID); override; + procedure PMUpdate(ObjectIdList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; Old_Values: IBoldValueSpace; Precondition: TBoldUpdatePrecondition; TranslationList: TBoldIdTranslationList; var TimeStamp: TBoldTimeStampType; var TimeOfLatestUpdate: TDateTime; BoldClientID: TBoldClientID); override; procedure TransmitEvents(const ClientID: TBoldClientID); virtual; abstract; property MoldModel: TMoldModel read fMoldModel; property Events: TStringList read fEvents; + property UseClassEvents: boolean read fUseClassEvents write fUseClassEvents; + property UseMemberLevelOSS: boolean read fUseMemberLevelOSS write fUseMemberLevelOSS; + property UseSubscriptions: boolean read fUseSubscriptions write fUseSubscriptions; property Subscriptions: TStringList read fSubscriptions; property CancelledSubscriptions: TStringList read fCancelledSubscriptions; property OnPropagatorFailure: TBoldNotifyEventWithErrorMessage read FOnPropagatorFailure write FOnPropagatorFailure; + property ClassesToIgnore: string read fClassesToIgnore write SetClassesToIgnore; end; implementation @@ -68,6 +90,12 @@ constructor TBoldAbstractSnooper.Create(MoldModel: TMoldModel); fEvents.Duplicates := dupIgnore; fSubscriptions := TStringList.Create; fCancelledSubscriptions := TStringList.Create; + SetLength(fEventClassFlags, MoldModel.Classes.Count); + SetLength(fArrayOfClassesToIgnore, MoldModel.Classes.Count); + + UseClassEvents := False; // Bold original behaviour = true + UseMemberLevelOSS := True; // Bold original behaviour = false + UseSubscriptions := False; // // Bold original behaviour = true end; destructor TBoldAbstractSnooper.Destroy; @@ -89,7 +117,7 @@ procedure TBoldAbstractSnooper.PMFetch(ObjectIdList: TBoldObjectIdList; ValueSpa Object_Content: IBoldObjectContents; begin inherited; - if (BoldClientID = NOTVALIDCLIENTID) or not Assigned(MoldModel) then + if {(BoldClientID = NOTVALIDCLIENTID) or} not Assigned(MoldModel) or not UseSubscriptions then Exit; if not fModelSorted then begin @@ -97,13 +125,11 @@ procedure TBoldAbstractSnooper.PMFetch(ObjectIdList: TBoldObjectIdList; ValueSpa fModelSorted := true; end; try - // SubscribeToEmbeddedStateOfObject for i:= 0 to ObjectIdList.Count - 1 do begin LoadingEmbedded := false; Object_Content := ValueSpace.ObjectContentsbyObjectId[ObjectIdList[i]]; - // SubscribeToNonEmbeddedStateOfObject - // explicit MemberIdList + if Assigned(MemberIdList) then begin @@ -122,19 +148,18 @@ procedure TBoldAbstractSnooper.PMFetch(ObjectIdList: TBoldObjectIdList; ValueSpa end else begin - if Assigned(Object_Content) then // get not delayed members + if Assigned(Object_Content) then begin LoadingEmbedded := true; MoldClass := MoldModel.Classes[ObjectIdList[i].TopSortedIndex]; for j:= 0 to Object_Content.MemberCount - 1 do - //if member is not delayed if not (MoldClass.AllBoldMembers[j].EffectiveDelayedFetch) and MemberIsNonEmbeddedLink(MoldClass.AllBoldMembers[j], MemberName) then SubscribeToNonEmbeddedStateChangedEvent(ObjectIdList[i], MemberName); end; end; - if LoadingEmbedded then - Subscriptions.Add(TBoldObjectSpaceExternalEvent.EncodeExternalEvent(bsEmbeddedStateOfObjectChanged, '', '', '', ObjectIdList[i])); + if UseSubscriptions and LoadingEmbedded then + AddSubscription(TBoldObjectSpaceExternalEvent.EncodeExternalEvent(bsEmbeddedStateOfObjectChanged, '', '', '', ObjectIdList[i])); end; TransmitEvents(BoldClientID); finally @@ -148,22 +173,21 @@ procedure TBoldAbstractSnooper.PMFetchIDListWithCondition(ObjectIdList: TBoldObj TopSortedIndex: integer; begin inherited; - if (BoldClientID = NOTVALIDCLIENTID) then - Exit; - // SubscribeToClassChanged +// if (BoldClientID = NOTVALIDCLIENTID) then +// Exit; if (Condition.ClassType = TBoldConditionWithClass) then begin TopSortedIndex := (Condition as TBoldConditionWithClass).TopSortedIndex; - Subscriptions.Add(TBoldObjectSpaceExternalEvent.EncodeExternalEvent(bsClassChanged, ClassNameFromClassId(TopSortedIndex), - '', '', nil)); + if UseSubscriptions then + AddSubscription(TBoldObjectSpaceExternalEvent.EncodeExternalEvent(bsClassChanged, ClassNameFromClassId(TopSortedIndex), '', '', nil)); end; TransmitEvents(BoldClientID); end; procedure TBoldAbstractSnooper.PMUpdate(ObjectIdList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; Old_Values: IBoldValueSpace; - Precondition: TBoldUpdatePrecondition; - TranslationList: TBoldIdTranslationList; var TimeStamp: TBoldTimeStampType; + Precondition: TBoldUpdatePrecondition; + TranslationList: TBoldIdTranslationList; var TimeStamp: TBoldTimeStampType; var TimeOfLatestUpdate: TDateTime; BoldClientID: TBoldClientID); var i, j: integer; @@ -174,12 +198,12 @@ procedure TBoldAbstractSnooper.PMUpdate(ObjectIdList: TBoldObjectIdList; ValueSp ObjectId: TBoldObjectID; MoldClass: TMoldClass; MemberName: string; + MemberValue: IBoldValue; + sl: TStringList; begin - //make a copy of objectIDList assert(assigned(MoldModel), 'Snooper has no Model'); LocalObjectIdList := ObjectIdList.Clone; try - //get old values LocalOld_Values := nil; LocalTranslationList := nil; if not Assigned(Old_Values) then @@ -197,45 +221,84 @@ procedure TBoldAbstractSnooper.PMUpdate(ObjectIdList: TBoldObjectIdList; ValueSp ValueSpace.ApplytranslationList(TranslationList); LocalObjectIdList.ApplyTranslationList(TranslationList); - if (BoldClientID <> NOTVALIDCLIENTID) then - for i := 0 to LocalObjectIDList.Count - 1 do - begin - Object_Content := ValueSpace.ObjectContentsByObjectId[LocalObjectIdList[i]]; - Assert(Assigned(Object_Content), 'Object does not exist'); - if Object_Content.BoldPersistenceState = bvpsModified then - case Object_Content.BoldExistenceState of - besExisting: - begin + EnsureDataBaseLock(BoldClientID); + try + inherited PMUpdate(LocalObjectIdList, ValueSpace, Old_Values, Precondition, nil, TimeStamp, TimeOfLatestUpdate, BoldClientID); + finally + ReleaseDataBaseLock(BoldClientID); + end; + if (assigned(Precondition) and (Precondition.failed)) {or (BoldClientID = NOTVALIDCLIENTID)} then + exit; + +// if (BoldClientID <> NOTVALIDCLIENTID) then + for i := 0 to LocalObjectIDList.Count - 1 do + begin + MoldClass := MoldModel.Classes[LocalObjectIdList[i].TopSortedIndex]; + Object_Content := ValueSpace.ObjectContentsByObjectId[LocalObjectIdList[i]]; + Assert(Assigned(Object_Content), Format('Object [%s] of type [%s] does not exist', + [LocalObjectIdList[i].AsString, + MoldClass.ExpandedExpressionName])); + if Object_Content.BoldPersistenceState = bvpsModified then + case Object_Content.BoldExistenceState of + besExisting: + begin + if UseClassEvents and not fArrayOfClassesToIgnore[LocalObjectIdList[i].TopSortedIndex] then AddClassEvents(LocalObjectIdList[i].TopSortedIndex); - Subscriptions.Add(TBoldObjectSpaceExternalEvent.EncodeExternalEvent(bsEmbeddedStateOfObjectChanged, '', '', '', TranslationList.TranslateToNewId[LocalObjectIdList[i]])); + if UseSubscriptions then + AddSubscription(TBoldObjectSpaceExternalEvent.EncodeExternalEvent(bsEmbeddedStateOfObjectChanged, '', '', '', TranslationList.TranslateToNewId[LocalObjectIdList[i]])); + if not fArrayOfClassesToIgnore[MoldClass.TopSortedIndex] then + AddEvent(TBoldObjectSpaceExternalEvent.EncodeExternalEvent(bsObjectCreated, MoldClass.ExpandedExpressionName, '', '', LocalObjectIdList[i])); + end; + besDeleted: + begin + if not fArrayOfClassesToIgnore[LocalObjectIdList[i].TopSortedIndex] then + begin + if UseClassEvents then + AddClassEvents(LocalObjectIdList[i].TopSortedIndex); + Events.Add(TBoldObjectSpaceExternalEvent.EncodeExternalEvent(bsObjectDeleted, MoldClass.ExpandedExpressionName, '', '', LocalObjectIdList[i])); end; - besDeleted: + if UseSubscriptions then + CancelSubscription(TBoldObjectSpaceExternalEvent.EncodeExternalEvent(bsEmbeddedStateOfObjectChanged, '', '', '', LocalObjectIdList[i])) ; + for j:= 0 to MoldClass.AllBoldMembers.Count - 1 do begin - AddClassEvents(LocalObjectIdList[i].TopSortedIndex); - Events.Add(TBoldObjectSpaceExternalEvent.EncodeExternalEvent(bsObjectDeleted, '', '', '', LocalObjectIdList[i])) ; - CancelledSubscriptions.Add(TBoldObjectSpaceExternalEvent.EncodeExternalEvent(bsEmbeddedStateOfObjectChanged, '', '', '', LocalObjectIdList[i])) ; - //Cancel subscriptions to NonEmbeddedStateOfObjectChanged events - MoldClass := MoldModel.Classes[ObjectIDList[i].TopSortedIndex]; - for j:= 0 to MoldClass.AllBoldMembers.Count - 1 do + MemberName := MoldClass.AllBoldMembers.Items[j].ExpandedExpressionName; + if UseSubscriptions and MemberIsNonEmbeddedLink(MoldClass.AllBoldMembers[j], MemberName) then + CancelSubscription(TBoldObjectSpaceExternalEvent.EncodeExternalEvent(bsNonEmbeddedStateOfObjectChanged, '', MemberName, '', LocalObjectIdList[i])); + end; + end; + end + else + begin + if not fArrayOfClassesToIgnore[LocalObjectIdList[i].TopSortedIndex] then + begin + if UseMemberLevelOss then + begin + sl:= TStringList.Create; + try + for j := 0 to Object_Content.MemberCount -1 do + begin + MemberValue := Object_Content.ValueByIndex[j]; + if Assigned(MemberValue) and (MemberValue.BoldPersistenceState = bvpsModified) then begin - MemberName := MoldClass.AllBoldMembers.Items[j].ExpandedExpressionName; - if MemberIsNonEmbeddedLink(MoldClass.AllBoldMembers[j], MemberName) then - CancelledSubscriptions.Add(TBoldObjectSpaceExternalEvent.EncodeExternalEvent(bsNonEmbeddedStateOfObjectChanged, '', MemberName, '', LocalObjectIdList[i])); + if MoldClass.AllBoldMembers[j] is TMoldAttribute then + sl.Add(MoldClass.AllBoldMembers[j].ExpandedExpressionName) + else + if MoldClass.AllBoldMembers[j] is TMoldRole and TMoldRole(MoldClass.AllBoldMembers[j]).EffectiveEmbedded then + sl.Add(MoldClass.AllBoldMembers[j].ExpandedExpressionName) end; end; - end //case - else - Events.Add(TBoldObjectSpaceExternalEvent.EncodeExternalEvent(bsEmbeddedStateOfObjectChanged, '', '', '', LocalObjectIdList[i])); - end; //for - - EnsureDataBaseLock(BoldClientID); - try - inherited PMUpdate(LocalObjectIdList, ValueSpace, Old_Values, Precondition, nil, TimeStamp, BoldClientID); - finally - ReleaseDataBaseLock(BoldClientID); + if sl.Count > 0 then + begin + AddEvent(TBoldObjectSpaceExternalEvent.EncodeExternalEvent(bsMemberChanged, MoldClass.ExpandedExpressionName, sl.CommaText, '', LocalObjectIdList[i])); + end; + finally + sl.free; + end; + end; + AddEvent(TBoldObjectSpaceExternalEvent.EncodeExternalEvent(bsEmbeddedStateOfObjectChanged, MoldClass.ExpandedExpressionName, '', '', LocalObjectIdList[i])); + end; + end; end; - if (not assigned(Precondition) or (not Precondition.failed)) and - (BoldClientID <> NOTVALIDCLIENTID) then begin for i:= LocalObjectIdList.Count - 1 downto 0 do @@ -246,18 +309,17 @@ procedure TBoldAbstractSnooper.PMUpdate(ObjectIdList: TBoldObjectIdList; ValueSp NewObject_Content := ValueSpace.ObjectContentsByObjectId[ObjectId] else NewObject_Content := nil; - NonEmbeddedStateOfObjectChanged(Object_Content, NewObject_Content, + if not fArrayOfClassesToIgnore[LocalObjectIdList[i].TopSortedIndex] then + NonEmbeddedStateOfObjectChanged(Object_Content, NewObject_Content, MoldModel.Classes[LocalObjectIdList[i].TopSortedIndex]); end; TransmitEvents(BoldClientID); end; finally - // release the interfaces Object_Content := nil; NewObject_Content := nil; if assigned(LocalOld_Values) then begin - // must release the interface before removing the underlying object Old_Values := nil; FreeAndNil(LocalOld_Values); end; @@ -266,55 +328,87 @@ procedure TBoldAbstractSnooper.PMUpdate(ObjectIdList: TBoldObjectIdList; ValueSp end; end; -procedure TBoldAbstractSnooper.GenerateNonEmbeddedStateChangedEvent(OldID, NewID: TBoldObjectId; const NonEmbeddedLinkName: string); +procedure TBoldAbstractSnooper.GenerateNonEmbeddedStateChangedEvent(OldID, NewID: TBoldObjectId; MoldClass: TMoldClass; const NonEmbeddedLinkName: string); begin if (Assigned(OldID) and Assigned(NewID) and not(OldID.IsEqual[NewID])) then begin - Events.Add(TBoldObjectSpaceExternalEvent.EncodeExternalEvent(bsNonEmbeddedStateOfObjectChanged, '', NonEmbeddedLinkName, '', OldID)); - Events.Add(TBoldObjectSpaceExternalEvent.EncodeExternalEvent(bsNonEmbeddedStateOfObjectChanged, '', NonEmbeddedLinkName, '', NewID)); + AddEvent(TBoldObjectSpaceExternalEvent.EncodeExternalEvent(bsNonEmbeddedStateOfObjectChanged, MoldClass.ExpandedExpressionName, NonEmbeddedLinkName, '', OldID)); + AddEvent(TBoldObjectSpaceExternalEvent.EncodeExternalEvent(bsNonEmbeddedStateOfObjectChanged, MoldClass.ExpandedExpressionName, NonEmbeddedLinkName, '', NewID)); end else if (Assigned(OldID) and not Assigned(NewID)) then - Events.Add(TBoldObjectSpaceExternalEvent.EncodeExternalEvent(bsNonEmbeddedStateOfObjectChanged, '', NonEmbeddedLinkName, '', OldID)) + AddEvent(TBoldObjectSpaceExternalEvent.EncodeExternalEvent(bsNonEmbeddedStateOfObjectChanged, MoldClass.ExpandedExpressionName, NonEmbeddedLinkName, '', OldID)) else if (Assigned(NewID) and not Assigned(OldID)) then - Events.Add(TBoldObjectSpaceExternalEvent.EncodeExternalEvent(bsNonEmbeddedStateOfObjectChanged, '', NonEmbeddedLinkName, '', NewID)); + AddEvent(TBoldObjectSpaceExternalEvent.EncodeExternalEvent(bsNonEmbeddedStateOfObjectChanged, MoldClass.ExpandedExpressionName, NonEmbeddedLinkName, '', NewID)); +end; + +procedure TBoldAbstractSnooper.SetClassesToIgnore(const Value: string); +var + sl: TStringList; + MoldClass: TMoldClass; + i: integer; +begin + if fClassesToIgnore = Value then + exit; + for i := 0 to high(fArrayOfClassesToIgnore) do + fArrayOfClassesToIgnore[i] := false; + sl := TStringList.Create; + try + Sl.CommaText := Value; + for i := 0 to sl.count -1 do + begin + MoldClass := MoldModel.Classes.ItemsByName[sl[i]]; + if not Assigned(MoldClass) then + raise Exception.CreateFmt('Invalid class name %s', [sl[i]]); + fArrayOfClassesToIgnore[MoldClass.TopSortedIndex] := true; + end; + fClassesToIgnore := Value; + finally + sl.free; + end; end; procedure TBoldAbstractSnooper.SubscribeToNonEmbeddedStateChangedEvent(Id: TBoldObjectId; const NonEmbeddedLinkName: string); begin - if Assigned(Id) then - Subscriptions.Add(TBoldObjectSpaceExternalEvent.EncodeExternalEvent(bsNonEmbeddedStateOfObjectChanged, '', NonEmbeddedLinkName, '', Id)) + if Assigned(Id) and UseSubscriptions then + AddSubscription(TBoldObjectSpaceExternalEvent.EncodeExternalEvent(bsNonEmbeddedStateOfObjectChanged, '', NonEmbeddedLinkName, '', Id)) end; function TBoldAbstractSnooper.ObjectIdByMemberIndex(Object_Content: IBoldObjectContents; MemberIndex: integer): TBoldObjectID; var Value: IBoldValue; IDRef: IBoldObjectIDRef; + IDRefPair: IBoldObjectIdrefPair; begin Result := nil; if Assigned(Object_Content) then begin Value := Object_Content.ValueByIndex[MemberIndex]; - if Assigned(Value) and (Value.QueryInterface(IBoldObjectIDRef, IDRef) = S_OK) then - Result := IDRef.Id; + if Assigned(Value) then + begin + if (Value.QueryInterface(IBoldObjectIDRef, IDRef) = S_OK) then + Result := IDRef.Id + else + if (Value.QueryInterface(IBoldObjectIdrefPair, IDRefPair) = S_OK) then + Result := IDRefPair.Id1; // or ID2 ? + end; end; end; -function TBoldAbstractSnooper.MemberIsEmbeddedSingleLink(MoldMember: TMoldMember; var NonEmbeddedLinkName: string): Boolean; +function TBoldAbstractSnooper.MemberIsEmbeddedSingleLink(MoldMember: TMoldMember; var NonEmbeddedLink: TMoldRole): Boolean; var MoldRole: TMoldRole; - NonEmbeddedLink: TMoldRole; begin Result := false; + NonEmbeddedLink := nil; if (MoldMember is TMoldRole) then begin MoldRole := MoldMember as TMoldRole; - Result := MoldRole.EffectiveEmbedded; + Result := MoldRole.EffectiveEmbedded and MoldRole.EffectivePersistent; if Result then begin NonEmbeddedLink := MoldRole.OtherEnd ; if (NonEmbeddedLink.RoleType = rtLinkRole) then NonEmbeddedLink := NonEmbeddedLink.MainRole; - NonEmbeddedLinkName := NonEmbeddedLink.ExpandedExpressionName; end; end; end; @@ -333,13 +427,14 @@ function TBoldAbstractSnooper.MemberIsNonEmbeddedLink(MoldMember: TMoldMember; v end; end; -procedure TBoldAbstractSnooper.NonEmbeddedStateOfObjectChanged(Object_Content, NewObject_Content: IBoldObjectContents; MoldClass: TMoldClass); +procedure TBoldAbstractSnooper.NonEmbeddedStateOfObjectChanged(const Object_Content, NewObject_Content: IBoldObjectContents; MoldClass: TMoldClass); var j: integer; MemberCount: integer; Id: TBoldObjectID; NewId: TBoldObjectID; NonEmbeddedLinkName: string; + NonEmbeddedLink: TMoldRole; begin MemberCount := 0; if Assigned(Object_Content) then @@ -347,24 +442,52 @@ procedure TBoldAbstractSnooper.NonEmbeddedStateOfObjectChanged(Object_Content, N else if Assigned(NewObject_Content) then MemberCount := NewObject_Content.MemberCount; for j:= 0 to MemberCount - 1 do - if MemberIsEmbeddedSingleLink(MoldClass.AllBoldMembers[j], NonEmbeddedLinkName) then - begin + if MemberIsEmbeddedSingleLink(MoldClass.AllBoldMembers[j], NonEmbeddedLink) then + begin; Id := ObjectIdByMemberIndex(Object_Content, j); NewId := ObjectIdByMemberIndex(NewObject_Content, j); - GenerateNonEmbeddedStateChangedEvent(Id, NewId,NonEmbeddedLinkName); + NonEmbeddedLinkName := NonEmbeddedLink.ExpandedExpressionName; + GenerateNonEmbeddedStateChangedEvent(Id, NewId, NonEmbeddedLink.MoldClass, NonEmbeddedLinkName); end; end; +procedure TBoldAbstractSnooper.AddEvent(const AEvent: string); +begin + if Events.Count = 0 then + begin + fEventTimeStamp := now; + fEventsLength := 0; + end; + Events.Add(AEvent); + Inc(fEventsLength, Length(AEvent)); + if EventLimitReached then + TransmitEvents(NOTVALIDCLIENTID); +end; + +procedure TBoldAbstractSnooper.AddSubscription(const AEvent: string); +begin + Subscriptions.Add(AEvent); +end; + +procedure TBoldAbstractSnooper.CancelSubscription(const AEvent: string); +begin + CancelledSubscriptions.Add(AEvent); +end; + function TBoldAbstractSnooper.ClassNameFromClassId(const TopSortedIndex: integer): string; begin Result := MoldModel.Classes[TopSortedIndex].ExpandedExpressionName; end; procedure TBoldAbstractSnooper.ClearEvents; +var + i: integer; begin Events.Clear; Subscriptions.Clear; CancelledSubscriptions.Clear; + for i := 0 to length(fEventClassFlags)-1 do + fEventClassFlags[i] := false; end; procedure TBoldAbstractSnooper.DoPropagatorFailure(Sender: TObject; const ErrorMessage: string); @@ -377,22 +500,36 @@ procedure TBoldAbstractSnooper.AddClassEvents(TopsortedIndex: integer); var MoldClass: TMoldClass; begin + if fEventClassFlags[TopSortedIndex] then + exit; MoldClass := MoldModel.Classes[TopSortedIndex]; + if not fEventClassFlags[MoldClass.TopSortedIndex] then + AddEvent(TBoldObjectSpaceExternalEvent.EncodeExternalEvent(bsClassChanged, MoldClass.ExpandedExpressionName, '', '', nil)); while assigned(MoldClass) do begin - Events.Add(TBoldObjectSpaceExternalEvent.EncodeExternalEvent(bsClassChanged, MoldClass.ExpandedExpressionName, '', '', nil)); + if not fEventClassFlags[MoldClass.TopSortedIndex] then + fEventClassFlags[MoldClass.TopSortedIndex] := true; MoldClass := MoldClass.SuperClass; end; end; procedure TBoldAbstractSnooper.EnsureDataBaseLock(const ClientID: TBoldClientID); begin - // intentionally left blank +end; + +function TBoldAbstractSnooper.EventLimitReached: boolean; +const + c1millisecond = 1 / 86400000; + cAgeLimit = c1millisecond * 200; // half a second; + cMessageLengthLimit = 1200; +begin + result := (fEventsLength > cMessageLengthLimit) + or (fEventTimeStamp>0) and (now - fEventTimeStamp > cAgeLimit); end; procedure TBoldAbstractSnooper.ReleaseDataBaseLock(const ClientID: TBoldClientID); begin - // intentionally left blank end; +initialization end. diff --git a/Source/Persistence/Core/BoldPersistenceController.pas b/Source/Persistence/Core/BoldPersistenceController.pas index ac97999..3b839ab 100644 --- a/Source/Persistence/Core/BoldPersistenceController.pas +++ b/Source/Persistence/Core/BoldPersistenceController.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldPersistenceController; interface @@ -8,7 +11,9 @@ interface BoldId, BoldUpdatePrecondition, BoldValueSpaceInterfaces, - BoldDefs; + BoldDefs, + BoldElements, + BoldDBInterfaces; type { forward declarations } @@ -17,20 +22,26 @@ TBoldPersistenceController = class; {-- TBoldPersistenceController --} TBoldPersistenceController = class(TBoldSubscribableObject) public - procedure PMExactifyIds(ObjectIdList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList); virtual; abstract; + procedure PMExactifyIds(ObjectIdList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList; HandleNonExisting: Boolean); virtual; abstract; procedure PMFetch(ObjectIdList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; MemberIdList: TBoldMemberIdList; FetchMode: Integer; BoldClientID: TBoldClientID); virtual; abstract; procedure PMFetchIDListWithCondition(ObjectIdList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; FetchMode: Integer; Condition: TBoldCondition; BoldClientID: TBoldClientID); virtual; abstract; - procedure PMUpdate(ObjectIdList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; Old_Values: IBoldValueSpace; Precondition: TBoldUpdatePrecondition; TranslationList: TBoldIdTranslationList; var TimeStamp: TBoldTimeStampType; BoldClientID: TBoldClientID); virtual; abstract; + procedure PMUpdate(ObjectIdList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; Old_Values: IBoldValueSpace; Precondition: TBoldUpdatePrecondition; TranslationList: TBoldIdTranslationList; var TimeStamp: TBoldTimeStampType; var TimeOfLatestUpdate: TDateTime; BoldClientID: TBoldClientID); virtual; abstract; procedure PMTranslateToGlobalIds(ObjectIdList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList); virtual; abstract; procedure PMTranslateToLocalIds(GlobalIdList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList); virtual; abstract; procedure PMSetReadOnlyness(ReadOnlyList, WriteableList: TBoldObjectIdList); virtual; abstract; procedure SubscribeToPeristenceEvents(Subscriber: TBoldSubscriber); virtual; - // this info should be stored in separate Mapping model function MultilinksAreStoredInObject: Boolean; virtual; procedure ReserveNewIds(ValueSpace: IBoldValueSpace; ObjectIdList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList); virtual; abstract; procedure PMTimestampForTime(ClockTime: TDateTime; var Timestamp: TBoldTimestampType); virtual; procedure PMTimeForTimestamp(Timestamp: TBoldTimestampType; var ClockTime: TDateTime); virtual; + // The BoldSystem is passed as TBoldElement, + // because include of BoldSystem.pas would cause recursive dependency. + function CanEvaluateInPS(sOCL: string; aSystem: TBoldElement; aContext: TBoldElementTypeInfo = nil; const aVariableList: TBoldExternalVariableList = nil): Boolean; virtual; abstract; + procedure StartTransaction; virtual; + procedure CommitTransaction; virtual; + procedure RollbackTransaction; virtual; + function DatabaseInterface: IBoldDatabase; virtual; end; const @@ -41,10 +52,31 @@ implementation uses SysUtils, - PersistenceConsts; + BoldRev; { TBoldPersistenceController } +procedure TBoldPersistenceController.StartTransaction; +begin + // Can be overriden but not mandatory +end; + +procedure TBoldPersistenceController.CommitTransaction; +begin + // Can be overriden but not mandatory +end; + +procedure TBoldPersistenceController.RollbackTransaction; +begin + // If Rollback is ever called, then it has to be overriden so we raise an exception + raise EBoldFeatureNotImplementedYet.CreateFmt('RollbackTransaction not supported by %s', [classname]); +end; + +function TBoldPersistenceController.DatabaseInterface: IBoldDatabase; +begin + result := nil; +end; + function TBoldPersistenceController.MultilinksAreStoredInObject: Boolean; begin result := false; @@ -53,13 +85,13 @@ function TBoldPersistenceController.MultilinksAreStoredInObject: Boolean; procedure TBoldPersistenceController.PMTimeForTimestamp( Timestamp: TBoldTimestampType; var ClockTime: TDateTime); begin - raise EBoldFeatureNotImplementedYet.CreateFmt(sPMTimeForTimeStampNotSupported, [classname]); + raise EBoldFeatureNotImplementedYet.CreateFmt('PMTimeForTimestamp not supported by %s', [classname]); end; procedure TBoldPersistenceController.PMTimestampForTime( ClockTime: TDateTime; var Timestamp: TBoldTimestampType); begin - raise EBoldFeatureNotImplementedYet.CreateFmt(sPMTimeStampForTimeNotSupported, [classname]); + raise EBoldFeatureNotImplementedYet.CreateFmt('PMTimestampForTime not supported by %s', [classname]); end; procedure TBoldPersistenceController.SubscribeToPeristenceEvents( @@ -75,6 +107,5 @@ procedure TBoldPersistenceController.SubscribeToPeristenceEvents( AddSubscription(Subscriber, bpeEndFetchId, bpeEndFetchId); end; +initialization end. - - diff --git a/Source/Persistence/Core/BoldPersistenceHandle.pas b/Source/Persistence/Core/BoldPersistenceHandle.pas index b0071a1..cd95526 100644 --- a/Source/Persistence/Core/BoldPersistenceHandle.pas +++ b/Source/Persistence/Core/BoldPersistenceHandle.pas @@ -1,30 +1,37 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldPersistenceHandle; interface uses Classes, - BoldDefs, BoldHandle, BoldSubscription, BoldPersistenceController; type + TBoldPersistenceHandle = class; + TBoldPersistenceHandleClass = class of TBoldHandle; + TBoldPersistenceHandle = class(TBoldHandle) private fActive: Boolean; fPersistenceController: TBoldPersistenceController; - fPersistenceSubscriber: TBoldPassThroughSubscriber; - function GetActive: Boolean; + fPersistenceSubscriber: TBoldExtendedPassthroughSubscriber; function GetPersistenceController: TBoldPersistenceController; function GetHasPersistenceController: Boolean; + function GetPersistenceSubscriber: TBoldExtendedPassthroughSubscriber; protected - procedure CheckInactive(Action: String); + procedure CheckInactive(const Action: String); function CreatePersistenceController: TBoldPersistenceController; virtual; abstract; function GetHandledObject: TObject; override; procedure ReceiveExtendedEvent(Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent; const Args: array of const); + function GetActive: boolean; virtual; procedure SetActive(Value: Boolean); virtual; property HasPersistenceController: Boolean read GetHasPersistenceController; + property PersistenceSubscriber: TBoldExtendedPassthroughSubscriber read GetPersistenceSubscriber; public constructor Create(Owner: TComponent); override; destructor Destroy; override; @@ -38,7 +45,8 @@ implementation uses SysUtils, - PersistenceConsts; + BoldDefs, + BoldRev; function TBoldPersistenceHandle.GetHandledObject: TObject; begin @@ -52,15 +60,21 @@ function TBoldPersistenceHandle.GetActive: Boolean; procedure TBoldPersistenceHandle.SetActive(Value: Boolean); begin - fActive := Value; - if not Active then - SendEvent(self, beDeactivating); + if fActive <> Value then + begin + fActive := Value; + if not Value then + begin + SendEvent(self, beDeactivating); + ReleasePersistenceController; + end; + end; end; -procedure TBoldPersistenceHandle.CheckInactive(Action: String); +procedure TBoldPersistenceHandle.CheckInactive(const Action: String); begin - if active then - raise EBold.CreateFmt(sNotAllowedOnActiveHandle, [Action]); + if Active then + raise EBold.CreateFmt('%s Not allowed on active PersistenceHandle', [Action]); end; constructor TBoldPersistenceHandle.create(Owner: TComponent); @@ -72,15 +86,25 @@ constructor TBoldPersistenceHandle.create(Owner: TComponent); function TBoldPersistenceHandle.GetPersistenceController: TBoldPersistenceController; begin if not assigned(fPersistenceController) then + begin fPersistenceController := CreatePersistenceController; + fPersistenceController.AddSmallSubscription(PersistenceSubscriber, [beDestroying], beDestroying); + end; result := fPersistenceController; end; +function TBoldPersistenceHandle.GetPersistenceSubscriber: TBoldExtendedPassthroughSubscriber; +begin + if not Assigned(fPersistenceSubscriber) then + fPersistenceSubscriber := TBoldExtendedPassthroughSubscriber.CreateWithExtendedReceive(ReceiveExtendedEvent); + result := fPersistenceSubscriber; +end; + destructor TBoldPersistenceHandle.Destroy; begin FreePublisher; - FreeAndNil(fPersistenceController); FreeAndNil(fPersistenceSubscriber); + FreeAndNil(fPersistenceController); inherited; end; @@ -88,31 +112,44 @@ procedure TBoldPersistenceHandle.ReceiveExtendedEvent( Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent; const Args: array of const); begin - SendExtendedEvent(Originator, OriginalEvent, Args); + if (Originator = fPersistenceController) and (OriginalEvent = beDestroying) then + begin + fPersistenceController := nil; + end + else + SendExtendedEvent(Originator, OriginalEvent, Args); end; procedure TBoldPersistenceHandle.AddPersistenceSubscription(Subscriber: TBoldSubscriber); begin - fPersistenceSubscriber := TBoldPassThroughSubscriber.CreateWithExtendedReceive(ReceiveExtendedEvent); + PersistenceSubscriber.CancelAllSubscriptions; + PersistenceController.AddSmallSubscription(fPersistenceSubscriber, [beDestroying], beDestroying); PersistenceController.SubscribeToPeristenceEvents(fPersistenceSubscriber); - AddSubscription(Subscriber, bpeEndFetch, bpeEndFetch); - AddSubscription(Subscriber, bpeEndUpdate, bpeEndUpdate); - AddSubscription(Subscriber, bpeEndFetchId, bpeEndUpdate); + AddSubscription(Subscriber, bpeFetchId, bpeFetchId); AddSubscription(Subscriber, bpeFetchObject, bpeFetchObject); AddSubscription(Subscriber, bpeFetchMember, bpeFetchMember); - AddSubscription(Subscriber, bpeUpdateObject, bpeUpdateObject); AddSubscription(Subscriber, bpeCreateObject, bpeCreateObject); + AddSubscription(Subscriber, bpeUpdateObject, bpeUpdateObject); AddSubscription(Subscriber, bpeDeleteObject, bpeDeleteObject); - AddSubscription(Subscriber, bpeFetchId, bpeFetchId); + AddSubscription(Subscriber, bpeStartFetchId, bpeStartFetchId); AddSubscription(Subscriber, bpeStartFetch, bpeStartFetch); AddSubscription(Subscriber, bpeStartUpdate, bpeStartUpdate); - AddSubscription(Subscriber, bpeStartFetchId, bpeStartUpdate); + AddSubscription(Subscriber, bpeEndFetchId, bpeEndFetchId); + AddSubscription(Subscriber, bpeEndFetch, bpeEndFetch); + AddSubscription(Subscriber, bpeEndUpdate, bpeEndUpdate); + + AddSubscription(Subscriber, bpeStartFetchMember, bpeStartFetchMember); + AddSubscription(Subscriber, bpeEndFetchMember, bpeEndFetchMember); + AddSubscription(Subscriber, bpeStartFetchObjectById, bpeStartFetchObjectById); + AddSubscription(Subscriber, bpeEndFetchObjectById, bpeEndFetchObjectById); + AddSubscription(Subscriber, bpeStartFetchClass, bpeStartFetchClass); + AddSubscription(Subscriber, bpeEndFetchClass, bpeEndFetchClass); end; procedure TBoldPersistenceHandle.ReleasePersistenceController; begin - if active then - Active := false; + Active := false; + FreeAndNil(fPersistenceSubscriber); FreeAndNil(fPersistenceController); end; @@ -121,4 +158,6 @@ function TBoldPersistenceHandle.GetHasPersistenceController: Boolean; result := assigned(fPersistenceController); end; +initialization + end. diff --git a/Source/Persistence/Core/BoldPersistenceHandlePTWithModel.pas b/Source/Persistence/Core/BoldPersistenceHandlePTWithModel.pas index de4f162..91ef9cc 100644 --- a/Source/Persistence/Core/BoldPersistenceHandlePTWithModel.pas +++ b/Source/Persistence/Core/BoldPersistenceHandlePTWithModel.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldPersistenceHandlePTWithModel; interface @@ -27,7 +30,8 @@ TBoldPersistenceHandlePassthroughWithModel = class(TBoldPersistenceHandlePasst implementation uses - SysUtils; + SysUtils, + BoldRev; const breModelDestroyed = 42; @@ -57,7 +61,7 @@ procedure TBoldPersistenceHandlePassthroughWithModel.SetBoldModel(Value: TBoldAb procedure TBoldPersistenceHandlePassthroughWithModel.ModelChanged; begin ReleasePersistenceController; - SendEvent(self, beValueIdentityChanged); // type change regarded as idenitychange + SendEvent(self, beValueIdentityChanged); end; destructor TBoldPersistenceHandlePassthroughWithModel.Destroy; @@ -77,4 +81,5 @@ procedure TBoldPersistenceHandlePassthroughWithModel._Receive(Originator: TObjec end; end; +initialization end. diff --git a/Source/Persistence/Core/BoldPersistenceHandlePassthrough.pas b/Source/Persistence/Core/BoldPersistenceHandlePassthrough.pas index 3ee6359..bb16be7 100644 --- a/Source/Persistence/Core/BoldPersistenceHandlePassthrough.pas +++ b/Source/Persistence/Core/BoldPersistenceHandlePassthrough.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldPersistenceHandlePassthrough; interface @@ -15,13 +18,15 @@ TBoldPersistenceHandlePassthrough = class(TBoldPersistenceHandle) fNextPHandleSubscriber: TBoldPassthroughSubscriber; procedure SetNextPersistenceHandle(NextPHandle: TBoldPersistenceHandle); procedure NextPHandleDeleted(Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent); + function GetLastPersistenceHandle: TBoldPersistenceHandle; protected procedure ChainPersistenceController(PersistenceController: TBoldPersistenceControllerPassThrough); procedure SetActive(Value: Boolean); override; - procedure InitNextPHandle(NextPHandle: TBoldPersistenceHandle); virtual; + procedure InitNextPHandle(NextPHandle: TBoldPersistenceHandle); virtual; public constructor Create(Owner: TComponent); override; destructor Destroy; override; + property LastPersistenceHandle: TBoldPersistenceHandle read GetLastPersistenceHandle; property NextPersistenceHandle: TBoldPersistenceHandle read fNextPersistenceHandle write {fNextPersistenceHandle}SetNextPersistenceHandle; end; @@ -29,15 +34,17 @@ TBoldPersistenceHandlePassthrough = class(TBoldPersistenceHandle) implementation uses - SysUtils; + SysUtils, + BoldRev; { TBoldPersistenceControllerPassthroughHandle } + procedure TBoldPersistenceHandlePassthrough.SetActive(Value: Boolean); begin - inherited; if Assigned(NextPersistenceHandle) then NextPersistenceHandle.Active := Value; + inherited; end; procedure TBoldPersistenceHandlePassthrough.SetNextPersistenceHandle( @@ -49,7 +56,7 @@ procedure TBoldPersistenceHandlePassthrough.SetNextPersistenceHandle( fNextPersistenceHandle := NextPHandle; if Assigned(fNextPersistenceHandle) then fNextPersistenceHandle.AddSmallSubscription(fNextPHandleSubscriber, [beDestroying], beDestroying); - InitNextPHandle(NextPHandle); + InitNextPHandle(NextPHandle); end; end; @@ -71,13 +78,19 @@ destructor TBoldPersistenceHandlePassthrough.Destroy; FreePublisher; FreeAndNil(fNextPHandleSubscriber); fNextPersistenceHandle := nil; - inherited; + inherited; +end; + +function TBoldPersistenceHandlePassthrough.GetLastPersistenceHandle: TBoldPersistenceHandle; +begin + result := NextPersistenceHandle; + while result is TBoldPersistenceHandlePassthrough do + result := TBoldPersistenceHandlePassthrough(result).NextPersistenceHandle; end; procedure TBoldPersistenceHandlePassthrough.InitNextPHandle( NextPHandle: TBoldPersistenceHandle); begin - //DoNothing end; procedure TBoldPersistenceHandlePassthrough.ChainPersistenceController(PersistenceController: TBoldPersistenceControllerPassThrough); @@ -86,4 +99,6 @@ procedure TBoldPersistenceHandlePassthrough.ChainPersistenceController(Persisten PersistenceController.NextPersistenceController := NextPersistenceHandle.PersistenceController; end; +initialization + end. diff --git a/Source/Persistence/Core/BoldPersistenceNotifier.pas b/Source/Persistence/Core/BoldPersistenceNotifier.pas index 94e576d..527b48d 100644 --- a/Source/Persistence/Core/BoldPersistenceNotifier.pas +++ b/Source/Persistence/Core/BoldPersistenceNotifier.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldPersistenceNotifier; interface @@ -26,9 +29,9 @@ TBoldAbstractPersistenceNotifier = class(TComponent) private fEvents: array[bpeMinReserved..bpeMaxReserved] of TBoldExtendedEventHandler; FPersistenceHandle: TBoldPersistenceHandle; - fSubscriber: TBoldSubscriber; + fSubscriber: TBoldExtendedPassthroughSubscriber; fFetchLog: TBoldIntegerArray; - fOnAlertExcessiveFetch: TBoldAlertExcessiveFetchEvent; + fOnAlertExcessiveFetch: TBoldAlertExcessiveFetchEvent; procedure SetPersistenceHandle(const Value: TBoldPersistenceHandle); function GetEvent(index: integer): TBoldExtendedEventHandler; procedure SetEvent(const index: integer; EventHandler: TBoldExtendedEventHandler); @@ -68,7 +71,7 @@ TBoldAbstractPersistenceNotifier = class(TComponent) property OnFetchID: TBoldExtendedEventHandler index bpeFetchID read GetEvent write SetEvent; property OnProgressStart: TBoldExtendedEventHandler index bpeProgressStart read GetEvent write SetEvent; property OnProgressEnd: TBoldExtendedEventHandler index bpeProgressEnd read GetEvent write SetEvent; - property OnAlertExcessiveFetch: TBoldAlertExcessiveFetchEvent read fOnAlertExcessiveFetch write fOnAlertExcessiveFetch; + property OnAlertExcessiveFetch: TBoldAlertExcessiveFetchEvent read fOnAlertExcessiveFetch write fOnAlertExcessiveFetch; property PersistenceHandle: TBoldPersistenceHandle read FPersistenceHandle write SetPersistenceHandle; property FetchLog: TBoldIntegerArray read GetFetchLog; public @@ -101,6 +104,7 @@ TBoldPersistenceNotifier = class(TBoldAbstractPersistenceNotifier) TBoldPersistenceProgressNotifier = class(TBoldAbstractPersistenceNotifier) private { Private declarations } + fLastUpdate: TDateTime; FAnimation: TAnimate; fAnimationTimer: TTimer; FWinControl: TWinControl; @@ -116,6 +120,7 @@ TBoldPersistenceProgressNotifier = class(TBoldAbstractPersistenceNotifier) procedure SetMsgLabel(const Value: TLabel); function GetAnimationInterval: integer; procedure SetAnimationInterval(const Value: integer); + function GetAnimationTimer: TTimer; protected { Protected declarations } procedure EndEvent; @@ -123,6 +128,7 @@ TBoldPersistenceProgressNotifier = class(TBoldAbstractPersistenceNotifier) procedure StepProgress; procedure StepAnimation; procedure SetMessage(const s: String); + procedure UpdateProgressBar; procedure EndFetch(Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent; const Args: array of const); override; procedure EndUpdate(Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent; const Args: array of const); override; procedure EndFetchID(Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent; const Args: array of const); override; @@ -136,6 +142,7 @@ TBoldPersistenceProgressNotifier = class(TBoldAbstractPersistenceNotifier) procedure StartFetchID(Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent; const Args: array of const); override; procedure FetchID(Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent; const Args: array of const); override; procedure Notification(AComponent: TComponent; Operation: TOperation); override; + property AnimationTimer: TTimer read GetAnimationTimer; public { Public declarations } constructor Create(Owner: TComponent); override; @@ -159,11 +166,14 @@ implementation uses SysUtils, - PersistenceConsts; + BoldRev; const brePersistenceHandleDestroying = 100; +const + c100ms = 1/24/60/60/10; + { TBoldAbstractPersistenceNotifier } procedure TBoldAbstractPersistenceNotifier.CallIfAssigned(EventID: integer; @@ -177,7 +187,7 @@ procedure TBoldAbstractPersistenceNotifier.CallIfAssigned(EventID: integer; constructor TBoldAbstractPersistenceNotifier.create(owner: TComponent); begin inherited; - fSubscriber := TBoldPassThroughSubscriber.CreateWithExtendedReceive(ReceiveExtendedEvent); + fSubscriber := TBoldExtendedPassthroughSubscriber.CreateWithExtendedReceive(ReceiveExtendedEvent); end; procedure TBoldAbstractPersistenceNotifier.CreateObject( @@ -320,7 +330,7 @@ procedure TBoldAbstractPersistenceNotifier.ReceiveExtendedEvent( if (OriginalEvent = bpeEndFetch) or (OriginalEvent = bpeEndUpdate) or (OriginalEvent = bpeEndFetchId) then ProgressEnd(Originator, OriginalEvent, RequestedEvent, args); - + if (OriginalEvent = beDestroying) and (RequestedEvent = brePersistenceHandleDestroying) then begin PersistenceHandle := nil; @@ -341,7 +351,6 @@ procedure TBoldAbstractPersistenceNotifier.SetPersistenceHandle(const Value: TBo fSubscriber.CancelAllSubscriptions; if Assigned(Value) then begin - // delay the adding of persistence-subscriptions until "loaded". ignore in designtime if not (csDesigning in ComponentState) and not (csLoading in ComponentState) then Value.AddPersistenceSubscription(fSubscriber); @@ -393,7 +402,7 @@ procedure TBoldAbstractPersistenceNotifier.AlertExcessiveFetch(ObjectId: TBoldOb procedure TBoldAbstractPersistenceNotifier.Loaded; begin inherited; - if assigned(fPersistenceHandle) then + if assigned(fPersistenceHandle) and not (csDesigning in ComponentState) then FPersistenceHandle.AddPersistenceSubscription(fSubscriber); end; @@ -402,19 +411,18 @@ procedure TBoldAbstractPersistenceNotifier.Loaded; procedure TBoldPersistenceProgressNotifier.AnimationTurnOff(Sender: TObject); begin if assigned(Animation) then + begin Animation.Stop; - fAnimationTimer.Enabled := false; + AnimationTimer.Enabled := false; + end; end; constructor TBoldPersistenceProgressNotifier.create(owner: TComponent); begin inherited; - fAnimationTimer := TTimer.Create(self); - fAnimationTimer.OnTimer := AnimationTurnOff; - fAnimationTimer.Interval := 100; - fMsgFetchObjects := sFetchingObjects; - fMsgRetrieveIds := sRetrievingIDs; - fMsgUpdateDatabase := sUpdatingDB; + fMsgFetchObjects := 'Fetching objects'; + fMsgRetrieveIds := 'Retrieving object IDs'; + fMsgUpdateDatabase := 'Updating database'; end; procedure TBoldPersistenceProgressNotifier.CreateObject( @@ -439,11 +447,11 @@ procedure TBoldPersistenceProgressNotifier.EndEvent; begin ProgressBar.Visible := false; ProgressBar.Max := 0; - ProgressBar.Refresh; + UpdateProgressBar; end; if assigned(Animation) then begin - fAnimationTimer.Enabled := true; + AnimationTimer.Enabled := true; Animation.Refresh; end; SetMessage(''); @@ -499,10 +507,21 @@ procedure TBoldPersistenceProgressNotifier.FetchObject(Originator: TObject; type TExposedWinControl = class(TWinControl); -{ Handle removing of non-bold components } +{ Handle removing of non-bold components } function TBoldPersistenceProgressNotifier.GetAnimationInterval: integer; begin - result := fAnimationTimer.Interval; + result := AnimationTimer.Interval; +end; + +function TBoldPersistenceProgressNotifier.GetAnimationTimer: TTimer; +begin + if not Assigned(fAnimationTimer) then + begin + fAnimationTimer := TTimer.Create(self); + fAnimationTimer.OnTimer := AnimationTurnOff; + fAnimationTimer.Interval := 100; + end; + result := fAnimationTimer; end; procedure TBoldPersistenceProgressNotifier.Notification( @@ -533,7 +552,7 @@ procedure TBoldPersistenceProgressNotifier.SetAnimation( procedure TBoldPersistenceProgressNotifier.SetAnimationInterval( const Value: integer); begin - fAnimationTimer.Interval := Value; + AnimationTimer.Interval := Value; end; procedure TBoldPersistenceProgressNotifier.SetMessage(const s: String); @@ -584,11 +603,11 @@ procedure TBoldPersistenceProgressNotifier.StartEvent(Count: integer); ProgressBar.Visible := true; ProgressBar.Position := 0; ProgressBar.Max := Count; - ProgressBar.Refresh; + UpdateProgressBar; end; if Assigned(Animation) then begin - fAnimationTimer.Enabled := False; + AnimationTimer.Enabled := False; if not Animation.Active and (Animation.FrameCount > 0) then Animation.Play(0, Animation.FrameCount - 1, 0); @@ -627,7 +646,7 @@ procedure TBoldPersistenceProgressNotifier.StepAnimation; begin if assigned(Animation) then begin - fAnimationTimer.Enabled := false; + AnimationTimer.Enabled := false; if (Animation.FrameCount > 0) then Animation.Play(0, Animation.FrameCount - 1, 0); Animation.Refresh; @@ -639,7 +658,7 @@ procedure TBoldPersistenceProgressNotifier.StepProgress; if assigned(ProgressBar) then begin ProgressBar.StepIt; - ProgressBar.Refresh; + UpdateProgressBar; end; end; @@ -651,4 +670,15 @@ procedure TBoldPersistenceProgressNotifier.UpdateObject( StepProgress; end; +procedure TBoldPersistenceProgressNotifier.UpdateProgressBar; +begin + if now - fLastUpdate > c100ms then + begin + ProgressBar.Refresh; + fLastUpdate := now; + end; +end; + +initialization + end. diff --git a/Source/Persistence/Core/BoldUpdatePrecondition.pas b/Source/Persistence/Core/BoldUpdatePrecondition.pas index f939007..8e9d106 100644 --- a/Source/Persistence/Core/BoldUpdatePrecondition.pas +++ b/Source/Persistence/Core/BoldUpdatePrecondition.pas @@ -1,10 +1,12 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldUpdatePrecondition; interface uses BoldFreeStandingValues, - BoldDefs, BoldId, BoldBase, BoldStreams, @@ -12,7 +14,6 @@ interface type TBoldUpdatePrecondition = class(TBoldNonRefCountedObject, IBoldStreamable) - protected function GetStreamName: string; virtual; abstract; function GetFailureReason: string; virtual; @@ -28,10 +29,10 @@ TBoldOptimisticLockingPrecondition = class(TBoldUpdatePrecondition) private fFreeStandingValueSpace: TBoldFreeStandingValueSpace; fFailureList: TBoldObjectIdList; - function GetValueSpace: IBoldValueSpace; - function GetFreeStandingValueSpace: TBoldFreeStandingValueSpace; - function GetFailureList: TBoldObjectIdList; - function GetHasOptimisticLocks: Boolean; + function GetValueSpace: IBoldValueSpace; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetFreeStandingValueSpace: TBoldFreeStandingValueSpace; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetFailureList: TBoldObjectIdList; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetHasOptimisticLocks: Boolean; // do not inline it causes problems in D2007 at least protected function GetStreamName: string; override; function GetFailureReason: string; override; @@ -52,10 +53,10 @@ implementation uses SysUtils, - BoldXMLStreaming, BoldDefaultStreamNames, BoldDefaultXMLStreaming, - PersistenceConsts; + BoldDefs, + BoldXMLStreaming; const OptimisticLockingPreConditionStreamName = 'OptimisticLockingPreCondition'; @@ -83,7 +84,6 @@ TBoldXMLOptimisticLockingPreConditionStreamer = class(TBoldXMLPreConditionStre constructor TBoldUpdatePrecondition.create; begin - // do nothing end; function TBoldUpdatePrecondition.GetFailed: Boolean; @@ -116,7 +116,7 @@ procedure TBoldOptimisticLockingPrecondition.ClearValueSpace; FreeAndNil(fFreeStandingValueSpace); end; -destructor TBoldOptimisticLockingPrecondition.destroy; +destructor TBoldOptimisticLockingPrecondition.Destroy; begin FreeAndNil(fFreeStandingValueSpace); FreeAndNil(fFailureList); @@ -136,8 +136,16 @@ function TBoldOptimisticLockingPrecondition.GetFailureList: TBoldObjectIdList; end; function TBoldOptimisticLockingPrecondition.GetFailureReason: string; +var + I: Integer; begin - result := format(sOptimisticLockingFailedForNObjects, [FailureList.Count]); + result := format('Optimistic locking failed for the following %d objects:', [FailureList.Count]); + for i := 0 to FailureList.Count - 1 do + begin + if i > 0 then + Result := Result + ', '; + result := Result + ('Id: '+ FailureList[i].AsString); + end; end; function TBoldOptimisticLockingPrecondition.GetFreeStandingValueSpace: TBoldFreeStandingValueSpace; @@ -147,27 +155,19 @@ function TBoldOptimisticLockingPrecondition.GetFreeStandingValueSpace: TBoldFree result := fFreeStandingValueSpace; end; -function TBoldOptimisticLockingPrecondition.GetHasOptimisticLocks: Boolean; -var - Ids: TBoldObjectIdList; +function TBoldOptimisticLockingPrecondition.GetValueSpace: IBoldValueSpace; begin - Ids := TBoldObjectIdList.create; - try - ValueSpace.AllObjectIds(Ids, true); - result := Ids.Count <> 0; - finally - Ids.Free; - end; + result := FreeStandingValueSpace; end; -function TBoldOptimisticLockingPrecondition.GetStreamName: string; +function TBoldOptimisticLockingPrecondition.GetHasOptimisticLocks: Boolean; begin - result := OptimisticLockingPreConditionStreamName; + result := not ValueSpace.IsEmpty; end; -function TBoldOptimisticLockingPrecondition.GetValueSpace: IBoldValueSpace; +function TBoldOptimisticLockingPrecondition.GetStreamName: string; begin - result := FreeStandingValueSpace; + result := OptimisticLockingPreConditionStreamName; end; { TBoldXMLPreConditionStreamer } @@ -176,17 +176,14 @@ procedure TBoldXMLPreConditionStreamer.ReadObject(Obj: TObject; Node: TBoldXMLNode); begin inherited; - // do nothing yet end; procedure TBoldXMLPreConditionStreamer.WriteObject( Obj: TBoldInterfacedObject; Node: TBoldXMLNode); begin inherited; - // do nothing yet end; - { TBoldXMLOptimisticLockingPreConditionStreamer } function TBoldXMLOptimisticLockingPreConditionStreamer.CreateObject: TObject; @@ -211,12 +208,12 @@ procedure TBoldXMLOptimisticLockingPreConditionStreamer.ReadObject(Obj: TObject; if Node.Manager is TBoldDefaultXMLStreamManager then begin Manager := Node.Manager as TBoldDefaultXMLStreamManager; - SubNode := Node.GetSubNode('ValueSpace'); // do not localize + SubNode := Node.GetSubNode('ValueSpace'); Manager.ReadValueSpace(Condition.ValueSpace, SubNode); SubNode.Free; end; - IdList := Node.ReadSubNodeObject('FailureList', BOLDOBJECTIDLISTNAME) as TBoldObjectIdList; // do not localize + IdList := Node.ReadSubNodeObject('FailureList', BOLDOBJECTIDLISTNAME) as TBoldObjectIdList; Condition.FailureList.Clear; Condition.FailureList.AddList(IdList); IdList.Free; @@ -243,7 +240,7 @@ procedure TBoldXMLOptimisticLockingPreConditionStreamer.WriteObject(Obj: TBoldIn Manager.PersistenceStatesToBeStreamed := [bvpsCurrent]; - SubNode := Node.NewSubNode('ValueSpace'); // do not localize + SubNode := Node.NewSubNode('ValueSpace'); Manager.WriteValueSpace(Condition.ValueSpace, IdLIst, nil, SubNode); SubNode.Free; @@ -252,7 +249,7 @@ procedure TBoldXMLOptimisticLockingPreConditionStreamer.WriteObject(Obj: TBoldIn FreeAndNil(IdList); end; end; - Node.WriteSubNodeObject('FailureList', BOLDOBJECTIDLISTNAME, Condition.FailureList); // do not localize + Node.WriteSubNodeObject('FailureList', BOLDOBJECTIDLISTNAME, Condition.FailureList); end; initialization diff --git a/Source/Persistence/Core/PersistenceConsts.pas b/Source/Persistence/Core/PersistenceConsts.pas index 580f44d..1d94b8e 100644 --- a/Source/Persistence/Core/PersistenceConsts.pas +++ b/Source/Persistence/Core/PersistenceConsts.pas @@ -71,4 +71,4 @@ interface implementation -end. \ No newline at end of file +end. diff --git a/Source/Persistence/DB/BoldAbstractDatabaseAdapter.pas b/Source/Persistence/DB/BoldAbstractDatabaseAdapter.pas index 369d643..dd314e8 100644 --- a/Source/Persistence/DB/BoldAbstractDatabaseAdapter.pas +++ b/Source/Persistence/DB/BoldAbstractDatabaseAdapter.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldAbstractDatabaseAdapter; interface @@ -6,7 +9,8 @@ interface Classes, BoldDBInterfaces, BoldSQLDatabaseConfig, - BoldSubscription; + BoldSubscription, + BoldIndexCollection; const beDatabaseAdapterChanged = 100; @@ -19,9 +23,11 @@ TBoldAbstractDatabaseAdapter = class; TBoldAbstractDatabaseAdapter = class(TBoldSubscribableComponent) private FSQLDatabaseConfig: TBoldSQLDatabaseConfig; + fCustomIndexes: TBoldIndexCollection; fDatabaseEngine: TBoldDataBaseEngine; fInternalDatabase: TComponent; procedure SetSQLDatabaseConfig(const Value: TBoldSQLDatabaseConfig); + procedure SetCustomIndexes(const Value: TBoldIndexCollection); procedure SetInternalDatabase(const Value: TComponent); protected procedure ReleaseBoldDatabase; virtual; abstract; @@ -32,17 +38,20 @@ TBoldAbstractDatabaseAdapter = class(TBoldSubscribableComponent) property InternalDatabase: TComponent read fInternalDatabase write SetInternalDatabase; function GetDataBaseInterface: IBoldDatabase; virtual; abstract; public - constructor Create(aOwner: TComponent); override; - destructor Destroy; override; + constructor create(aOwner: TComponent); override; + destructor destroy; override; + procedure CreateDatabase; virtual; abstract; property DatabaseInterface: IBoldDatabase read GetDatabaseInterface; published property SQLDatabaseConfig: TBoldSQLDatabaseConfig read FSQLDatabaseConfig write SetSQLDatabaseConfig; + property CustomIndexes: TBoldIndexCollection read fCustomIndexes write SetCustomIndexes; end; implementation uses - SysUtils; + SysUtils, + BoldRev; { TBoldAbstractDatabaseAdapter } @@ -55,11 +64,13 @@ constructor TBoldAbstractDatabaseAdapter.create(aOwner: TComponent); begin inherited; fSQLDatabaseConfig := TBoldSQLDatabaseConfig.Create; + fCustomIndexes := TBoldIndexCollection.Create(Self); end; destructor TBoldAbstractDatabaseAdapter.destroy; begin FreeAndNil(fSQLDatabaseConfig); + FreeAndNil(fCustomIndexes); inherited; end; @@ -87,6 +98,12 @@ procedure TBoldAbstractDatabaseAdapter.SetInternalDatabase(const Value: TCompone end; end; +procedure TBoldAbstractDatabaseAdapter.SetCustomIndexes( + const Value: TBoldIndexCollection); +begin + fCustomIndexes.Assign(value); +end; + procedure TBoldAbstractDatabaseAdapter.SetDataBaseEngine(const Value: TBoldDataBaseEngine); begin if value <> fDatabaseEngine then @@ -103,4 +120,6 @@ procedure TBoldAbstractDatabaseAdapter.SetSQLDatabaseConfig(const Value: TBoldSQ FSQLDatabaseConfig.AssignConfig(value); end; +initialization + end. diff --git a/Source/Persistence/DB/BoldAbstractPersistenceHandleDB.pas b/Source/Persistence/DB/BoldAbstractPersistenceHandleDB.pas index 2b9a6f1..9ef9831 100644 --- a/Source/Persistence/DB/BoldAbstractPersistenceHandleDB.pas +++ b/Source/Persistence/DB/BoldAbstractPersistenceHandleDB.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldAbstractPersistenceHandleDB; interface @@ -13,7 +16,7 @@ interface BoldSQLDatabaseConfig, BoldPersistenceControllerDefault, BoldDbInterfaces, - BoldPSParams; + BoldPSParams, BoldIndexCollection; type { forward declarations } @@ -42,16 +45,19 @@ TBoldAbstractPersistenceHandleDB = class(TBoldPersistenceHandle) function CreatePersistenceController: TBoldPersistenceController; override; procedure SetActive(Value: Boolean); override; function GetSQLDatabaseConfig: TBoldSQLDatabaseConfig; virtual; abstract; + function GetCustomIndexes: TBoldIndexCollection; virtual; abstract; function GetDataBaseInterface: IBoldDatabase; virtual; abstract; procedure AssertSQLDatabaseconfig(Context: String); virtual; public - constructor Create(Owner: TComponent); override; - destructor Destroy; override; + constructor create(Owner: TComponent); override; + destructor destroy; override; property PersistenceControllerDefault: TBoldPersistenceControllerDefault read GetPersistenceControllerDefault; procedure CreateDataBaseSchema(IgnoreUnknownTables: Boolean = false); + procedure CreateDataBase; procedure AddModelEvolutionInfoToDatabase; property DatabaseInterface: IBoldDatabase read GetDatabaseInterface; property SQLDatabaseConfig: TBoldSQLDatabaseConfig read GetSQLDatabaseConfig; + property CustomIndexes: TBoldIndexCOllection read GetCustomIndexes; published property BoldModel: TBoldAbstractModel read FBoldModel write SetBoldModel; property OnGetCurrentTime: TBoldGetTimeEvent read fOnGetCurrentTime write fOnGetCurrentTime; @@ -68,7 +74,7 @@ implementation BoldLogHandler, BoldPSDescriptionsSQL, BoldPMappersDefault, - PersistenceConsts; + BoldPersistenceControllerPassthrough; const breModelChanged = 100; @@ -150,6 +156,11 @@ constructor TBoldAbstractPersistenceHandleDB.create(Owner: TComponent); fComponentSubscriber := TBoldPassthroughSubscriber.Create(_ReceiveComponentEvents); end; +procedure TBoldAbstractPersistenceHandleDB.CreateDataBase; +begin + DatabaseInterface.CreateDatabase; +end; + procedure TBoldAbstractPersistenceHandleDB.CreateDataBaseSchema( IgnoreUnknownTables: Boolean); var @@ -157,16 +168,17 @@ procedure TBoldAbstractPersistenceHandleDB.CreateDataBaseSchema( begin fIgnoreUnknownTables := IgnoreUnknownTables; if Active then - raise EBold.Create(sCannotGenerateWhenHandleIsActive); + raise EBold.Create('Can not generate database schema when the PersistenceHandle is Active'); if not assigned(BoldModel) then - raise EBold.CreateFmt(sModelComponentMissing, [ClassName, Name]); - AssertSQLDatabaseconfig(sCreateSchema); + raise EBold.CreateFmt('%s.CreateDataBaseSchema: Can not create database schema for %s without a Model-component', [ClassName, Name]); + AssertSQLDatabaseconfig('Create DatabaseSchema'); - PMapper := TBoldSystemDefaultMapper.CreateFromMold(BoldModel.RawMoldModel, BoldModel.TypeNameDictionary, SQLDataBaseConfig, GetDataBaseInterface); + PMapper := TBoldSystemDefaultMapper.CreateFromMold(BoldModel.RawMoldModel, BoldModel.TypeNameDictionary, + CustomIndexes, SQLDataBaseConfig, GetDataBaseInterface); try try - BoldLog.StartLog(sGenerateSchema); + BoldLog.StartLog('Generate Database Schema'); PMapper.OpenDatabase(false, false); PMapper.OnPreparePSParams := PreparePSParams; PMapper.CreatePersistentStorage; @@ -174,7 +186,7 @@ procedure TBoldAbstractPersistenceHandleDB.CreateDataBaseSchema( except on e: Exception do begin - BoldLog.LogFmt(sSchemaGenerationAborted,[e.message], ltError); + BoldLog.LogFmt('Generation of Database Schema Aborted (%s)',[e.message], ltError); raise; end; end; @@ -189,8 +201,11 @@ function TBoldAbstractPersistenceHandleDB.CreatePersistenceController: TBoldPers PController: TBoldPersistenceControllerDefault; begin if not assigned(BoldModel) then - raise EBold.createFmt(sCannotGetPControllerWithoutModel, [ClassName]); - PController := TBoldPersistenceControllerDefault.CreateFromMold(BoldModel.MoldModel, BoldModel.TypeNameDictionary, SQLDataBaseConfig, GetDataBaseInterface); + raise EBold.createFmt('%s.CreatePersistenceController: Can not get a PersistenceController without a Model', [ClassName]); + if not assigned(SQLDataBaseConfig) then + raise EBold.createFmt('%s.CreatePersistenceController: Can not get a PersistenceController without SQLDataBaseConfig', [ClassName]); + PController := TBoldPersistenceControllerDefault.CreateFromMold(BoldModel.MoldModel, BoldModel.TypeNameDictionary, + CustomIndexes, SQLDataBaseConfig, GetDataBaseInterface); PController.PersistenceMapper.OnGetCurrentTime := fOnGetCurrentTime; PController.PersistenceMapper.ClockLogGranularity := fClockLogGranularity; @@ -210,12 +225,17 @@ function TBoldAbstractPersistenceHandleDB.GetClockLogGranularity: string; hrs, mins, secs, msecs: Word; begin DecodeTime(fClockLogGranularity, hrs, mins, secs, msecs); - result := Format('%d:%d:%d.%d', [hrs, mins, secs, msecs]); // do not localize + result := Format('%d:%d:%d.%d', [hrs, mins, secs, msecs]); end; function TBoldAbstractPersistenceHandleDB.GetPersistenceControllerDefault: TBoldPersistenceControllerDefault; +var + vPersistenceController: TBoldPersistenceController; begin - result := PersistenceController as TBoldPersistenceControllerDefault; + vPersistenceController := PersistenceController; + while not (vPersistenceController is TBoldPersistenceControllerDefault) and (vPersistenceController is TBoldPersistenceControllerPassthrough) do + vPersistenceController := (vPersistenceController as TBoldPersistenceControllerPassthrough).NextPersistenceController; + result := vPersistenceController as TBoldPersistenceControllerDefault; end; procedure TBoldAbstractPersistenceHandleDB.PlaceComponentSubscriptions; @@ -239,10 +259,11 @@ procedure TBoldAbstractPersistenceHandleDB.SetActive(Value: Boolean); begin if value <> Active then begin + Assert(Assigned(PersistenceControllerDefault)); if value then begin if assigned(UpgraderHandle) and not BoldModel.MoldModel.UseModelVersion then - raise EBold.CreateFmt(sCannotActivate_UpgraderMismatch, [classname]); + raise EBold.CreateFmt('%s.SetActive: Cannot activate, there is an UpgraderHandle but the Model does not have UseModelVersion true', [classname]); PersistenceControllerDefault.OpenDatabase(EvolutionSupport); end else @@ -267,11 +288,11 @@ procedure TBoldAbstractPersistenceHandleDB.SetClockLogGranularity(const Value: s input: string; function GetNext(Delimiter: string): Integer; + const + ErrorMessage = '%s.SetClockLogGranularity: string is not properly formatted. Should be ::.'; var - ErrorMessage: string; p: Integer; begin - ErrorMessage := sClockStringFormatError; if Delimiter <> '' then begin p := pos(Delimiter, input); @@ -304,7 +325,7 @@ procedure TBoldAbstractPersistenceHandleDB.SetEvolutionSupport(const Value: Bool if Value <> FEvolutionSupport then begin if Active then - raise EBold.CreateFmt(sCannotSetWhenHandleIsActive, [classname, 'SetEvolutionSupport', name]); // do not localize + raise EBold.CreateFmt('%s.SetEvolutionSupport: Cannot set this property when the handle (%s) is active', [classname, name]); FEvolutionSupport := Value; end; end; @@ -330,7 +351,9 @@ procedure TBoldAbstractPersistenceHandleDB.AssertSQLDatabaseconfig( Context: String); begin if not assigned(SQLDatabaseConfig) then - raise EBold.CreateFmt(sSQLDatabaseConfigMissing, [classname, Context]); + raise EBold.CreateFmt('%s: Unable to %s. There is no SQLDatabaseConfig available', [classname, Context]); end; +initialization + end. diff --git a/Source/Persistence/DB/BoldDBActions.pas b/Source/Persistence/DB/BoldDBActions.pas index 6f4d07d..9145b0a 100644 --- a/Source/Persistence/DB/BoldDBActions.pas +++ b/Source/Persistence/DB/BoldDBActions.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldDBActions; interface @@ -33,8 +36,7 @@ implementation BoldDefs, SysUtils, BoldActionDefs, - BoldUtils, - PersistenceConsts; + BoldUtils; { TBoldGenerateSchemaAction } @@ -42,7 +44,7 @@ implementation constructor TBoldGenerateSchemaAction.Create(AOwner: TComponent); begin inherited; - Caption := sGenerateSchema; + Caption := 'Generate Schema'; end; procedure TBoldGenerateSchemaAction.ExecuteTarget(Target: TObject); @@ -74,4 +76,6 @@ procedure TBoldGenerateSchemaAction.SetBoldPersistenceHandleDB(const Value: TBol fBoldPersistenceHandleDB.FreeNotification(Self); end; +initialization + end. diff --git a/Source/Persistence/DB/BoldDBInterfaces.pas b/Source/Persistence/DB/BoldDBInterfaces.pas index d575e29..c5b92e7 100644 --- a/Source/Persistence/DB/BoldDBInterfaces.pas +++ b/Source/Persistence/DB/BoldDBInterfaces.pas @@ -1,28 +1,55 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldDBInterfaces; interface uses + {$IFNDEF BOLD_UNICODE} + StringBuilder, + {$ENDIF} Classes, Db, + SysUtils, BoldBase, BoldSQLDatabaseConfig, - BoldLogHandler; + WideStrings, + BoldLogHandler, + BoldDefs; +const + cInitialBatchBufferSize = 1024*64; // 64 kb type IBoldQuery = interface; IBoldDataBase = interface; IBoldTable = interface; IBoldField = interface; IBoldParameter = interface; + IBoldParameterized = interface; TBoldDataSetWrapper = class; TBoldDatabaseWrapper = class; TBoldFieldWrapper = class; + TBoldAbstractQueryWrapper = class; TBoldFieldWrapperClass = class of TBoldFieldWrapper; TBoldGetDatabaseEvent = function: IBoldDatabase of object; + {$IFDEF BOLD_UNICODE} + TBoldBlobData = AnsiString; + {$ELSE} + TBoldBlobData = TBlobData; + {$ENDIF} + + TBoldIndexDescription = record + IndexName: String; + IndexedColumns: String; // separated by ; + IsPrimary: Boolean; + IsUnique: Boolean; + end; + + TBoldIndexDescriptionArray = array of TBoldIndexDescription; IBoldField = interface ['{F4126F4C-F1B2-472B-B53F-2ECEC8EE9253}'] @@ -31,7 +58,11 @@ TBoldFieldWrapperClass = class of TBoldFieldWrapper; function GetAsVariant: Variant; procedure SetAsVariant(const Value: Variant); function GetAsString: String; - procedure SetAsString(const Value: String); + procedure SetAsString(const Value: string); + function GetAsAnsiString: TBoldAnsiString; + procedure SetAsAnsiString(const Value: TBoldAnsiString); + function GetAsWideString: TBoldUnicodeString; + procedure SetAsWideString(const Value: TBoldUnicodeString); function GetAsInteger: Integer; procedure SetAsInteger(const Value: Integer); function GetAsBoolean: Boolean; @@ -47,13 +78,17 @@ TBoldFieldWrapperClass = class of TBoldFieldWrapper; function GetAsTime: TDateTime; procedure SetAsTime(const Value: TDateTime); procedure SetAsDate(const Value: TDateTime); - procedure SetAsBlob(const Value: string); - function GetAsBlob: string; + procedure SetAsBlob(const Value: TBoldAnsiString); + function GetAsBlob: TBoldAnsiString; + function GetAsInt64: Int64; + procedure SetAsInt64(const Value: Int64); property Field: TField read GetField; property AsVariant: Variant read GetAsVariant write SetAsVariant; property Value: Variant read GetAsVariant write SetAsVariant; property AsString: String read GetAsString write SetAsString; + property AsAnsiString: TBoldAnsiString read GetAsAnsiString write SetAsAnsiString; + property AsWideString: TBoldUnicodeString read GetAsWideString write SetAsWideString; property AsInteger: Integer read GetAsInteger write SetAsInteger; property AsBoolean: Boolean read GetAsBoolean write SetAsBoolean; property AsCurrency: Currency read GetAsCurrency write SetAsCurrency; @@ -61,11 +96,18 @@ TBoldFieldWrapperClass = class of TBoldFieldWrapper; property AsFloat: Double read GetAsFloat write SetAsFloat; property AsDate: TDateTime read GetAsDate write SetAsDate; property AsTime: TDateTime read GetAsTime write SetAsTime; - property AsBlob: String read GetAsBlob write SetAsBlob; + property AsBlob: TBoldAnsiString read GetAsBlob write SetAsBlob; + property AsInt64: Int64 read GetAsInt64 write SetAsInt64; property IsNull: Boolean read GetIsNull; property FieldName: String read GetFieldName; end; + IBoldDBParam = interface + ['{FB3D383D-2F7E-49DC-9834-40ABDCAA3445}'] + // some libraries use non TParam descendant implementations, for those that use TParam, this interface can be implemented + function GetParameter: TParam; + property Parameter: TParam read GetParameter; + end; IBoldParameter = interface ['{FFAD2670-423A-11D3-89F6-006008F62CFF}'] @@ -76,6 +118,7 @@ TBoldFieldWrapperClass = class of TBoldFieldWrapper; function GetDataType: TFieldType; procedure SetDataType(Value: TFieldType); function GetAsBCD: Currency; + function GetAsBlob: TBoldBlobData; function GetAsBoolean: Boolean; function GetAsDateTime: TDateTime; function GetAsCurrency: Currency; @@ -83,10 +126,12 @@ TBoldFieldWrapperClass = class of TBoldFieldWrapper; function GetAsInteger: Longint; function GetAsMemo: string; function GetAsString: string; -// function GetAsWideString: WideString; + function GetAsAnsiString: TBoldAnsiString; + function GetAsInt64: Int64; + function GetAsWideString: WideString; function GetIsNull: Boolean; procedure SetAsBCD(const Value: Currency); - procedure SetAsBlob(const Value: TBlobData); + procedure SetAsBlob(const Value: TBoldBlobData); procedure SetAsBoolean(Value: Boolean); procedure SetAsCurrency(const Value: Currency); procedure SetAsDate(const Value: TDateTime); @@ -95,29 +140,34 @@ TBoldFieldWrapperClass = class of TBoldFieldWrapper; procedure SetAsInteger(Value: Longint); procedure SetAsMemo(const Value: string); procedure SetAsString(const Value: string); -// procedure SetAsWideString(const Value: Widestring); + procedure SetAsAnsiString(const Value: TBoldAnsiString); + procedure SetAsWideString(const Value: Widestring); procedure SetAsSmallInt(Value: LongInt); procedure SetAsTime(const Value: TDateTime); procedure SetAsWord(Value: LongInt); + procedure SetAsInt64(const Value: Int64); procedure SetText(const Value: string); - procedure AssignFieldValue(source: IBoldField); - property asVariant: Variant read GetAsVariant write SetAsVariant; + procedure AssignFieldValue(const source: IBoldField); + procedure Assign(const source: IBoldParameter); + property AsVariant: Variant read GetAsVariant write SetAsVariant; property Name: String read GetName; property DataType: TFieldType read GetDataType write SetDataType; property AsBCD: Currency read GetAsBCD write SetAsBCD; -//marco property AsBlob: TBlobData read GetAsString write SetAsBlob; + property AsBlob: TBoldBlobData read GetAsBlob write SetAsBlob; property AsBoolean: Boolean read GetAsBoolean write SetAsBoolean; property AsCurrency: Currency read GetAsCurrency write SetAsCurrency; property AsDate: TDateTime read GetAsDateTime write SetAsDate; property AsDateTime: TDateTime read GetAsDateTime write SetAsDateTime; property AsFloat: Double read GetAsFloat write SetAsFloat; property AsInteger: LongInt read GetAsInteger write SetAsInteger; + property AsInt64: Int64 read GetAsInt64 write SetAsInt64; property AsSmallInt: LongInt read GetAsInteger write SetAsSmallInt; property AsMemo: string read GetAsMemo write SetAsMemo; property AsString: string read GetAsString write SetAsString; + property AsAnsiString: TBoldAnsiString read GetAsAnsiString write SetAsAnsiString; property AsTime: TDateTime read GetAsDateTime write SetAsTime; property AsWord: LongInt read GetAsInteger write SetAsWord; -// property AsWideString: WideString read GetAsWideString write SetAsWideString; + property AsWideString: WideString read GetAsWideString write SetAsWideString; property IsNull: Boolean read GetIsNull; property Text: string read GetAsString write SetText; end; @@ -126,7 +176,8 @@ TBoldFieldWrapperClass = class of TBoldFieldWrapper; ['{D00CA0A0-41CE-11D3-89F5-006008F62CFF}'] procedure Append; procedure Close; - function FieldByName(const FieldName: string): IBoldField; + function FieldByUpperCaseName(const FieldName: string): IBoldField; + function FieldByName(const FieldName: string): IBoldField; function FindField(const FieldName: string): IBoldField; procedure First; function GetDataSet: TDataSet; @@ -156,7 +207,27 @@ TBoldFieldWrapperClass = class of TBoldFieldWrapper; property State: TDataSetState read GetState; end; - IBoldExecQuery = interface + IBoldParameterized = interface + ['{B9020CF8-0300-4476-9453-4A3760E13225}'] + function GetParamCheck: Boolean; + procedure SetParamCheck(value: Boolean); + procedure ClearParams; + procedure AssignParams(Params: TParams); + function ParamByName(const Value: string): IBoldParameter; + function FindParam(const Value: string): IBoldParameter; + function EnsureParamByName(const Value: string): IBoldParameter; + function GetParamCount: integer; + function GetParam(i:integer): IBoldParameter; + function CreateParam(FldType: TFieldType; const ParamName: string): IBoldParameter; overload; + function Createparam(FldType: TFieldType; const ParamName: string; ParamType: TParamType; Size: integer): IBoldParameter; overload; + function GetParams: TParams; + property Param[i: integer]: IBoldParameter read GetParam; + property ParamCount: integer read GetParamCount; + property ParamCheck: Boolean read GetParamCheck write SetParamCheck; + property Params: TParams read GetParams; + end; + + IBoldExecQuery = interface(IBoldParameterized) ['{219D1FF1-F509-42A3-96E9-D7F62C28C1EA}'] function GetSQLText: String; procedure StartSQLBatch; @@ -164,26 +235,19 @@ TBoldFieldWrapperClass = class of TBoldFieldWrapper; procedure FailSQLBatch; procedure ExecSQL; procedure AssignSQL(SQL: TStrings); - procedure AssignSQLText(SQL: String); - procedure ClearParams; - function ParamByName(const Value: string): IBoldParameter; + procedure AssignSQLText(const SQL: String); function GetRowsAffected: integer; function GetImplementor: TObject; + function GetUseReadTransactions: boolean; + procedure SetUseReadTransactions(value: boolean); + function GetSQLStrings: TStrings; + function GetBatchQueryParamCount: integer; property RowsAffected: integer read GetRowsAffected; property Implementor: TObject read GetImplementor; property SQLText: String read GetSQLText; - end; - - IBoldParameterized = interface - ['{B9020CF8-0300-4476-9453-4A3760E13225}'] - procedure ClearParams; - procedure AssignParams(Params: TParams); - function ParamByName(const Value: string): IBoldParameter; - function GetParamCount: integer; - function GetParams(i:integer): IBoldParameter; - function Createparam(FldType: TFieldType; const ParamName: string; ParamType: TParamType; Size: integer): IBoldParameter; - property Params[i: integer]: IBoldParameter read GetParams; - property ParamCount: integer read GetParamCount; + property SQLStrings: TStrings read GetSQLStrings; + property UseReadTransactions: boolean read GetUseReadTransactions write SetUseReadTransactions; + property BatchQueryParamCount: integer read GetBatchQueryParamCount; end; IBoldQuery = interface(IBoldDataSet) @@ -192,21 +256,27 @@ TBoldFieldWrapperClass = class of TBoldFieldWrapper; function GetRequestLiveQuery: Boolean; procedure SetRequestLiveQuery(NewValue: Boolean); function GetRecordCount: integer; - procedure AssignSQLText(SQL: String); + procedure AssignSQLText(const SQL: String); procedure AssignSQL(SQL: TStrings); procedure ClearParams; procedure AssignParams(Params: TParams); function ParamByName(const Value: string): IBoldParameter; + function FindParam(const Value: string): IBoldParameter; + function GetUseReadTransactions: boolean; + procedure SetUseReadTransactions(value: boolean); + function GetRecNo: integer; property RequestLiveQuery: Boolean read GetRequestLiveQuery write SetRequestLiveQuery; property RecordCount: integer read GetRecordCount; - property SQLText: String read GetSQLText; + property SQLText: String read GetSQLText write AssignSQLText; + property UseReadTransactions: boolean read GetUseReadTransactions write SetUseReadTransactions; + property RecNo: integer read GetRecNo; end; IBoldTable = interface(IBoldDataSet) ['{D6698E80-41CE-11D3-89F5-006008F62CFF}'] procedure AddIndex(const Name, Fields: string; Options: TIndexOptions; const DescFields: string = ''); function GetIndexDefs: TIndexDefs; - procedure SetTableName(NewName: String); + procedure SetTableName(const NewName: String); function GetTableName: String; procedure SetExclusive(NewValue: Boolean); function GetExclusive: Boolean; @@ -227,6 +297,7 @@ TBoldFieldWrapperClass = class of TBoldFieldWrapper; procedure RollBack; procedure Open; procedure Close; + procedure Reconnect; function GetInTransaction: Boolean; function GetIsSQLBased: Boolean; procedure AllTableNames(Pattern: String; SystemTables: Boolean; TableNameList: TStrings); @@ -250,51 +321,62 @@ TBoldFieldWrapperClass = class of TBoldFieldWrapper; function SupportsTableCreation: Boolean; procedure ReleaseCachedObjects; function TableExists(const TableName: String): Boolean; + function GetIndexDescriptions(const TableName: String): TBoldIndexDescriptionArray; function GetSQLDatabaseConfig: TBoldSQLDatabaseConfig; property SQLDatabaseConfig: TBoldSQLDatabaseConfig read GetSQLDatabaseConfig; + function GetIsExecutingQuery: Boolean; + property IsExecutingQuery: Boolean read GetIsExecutingQuery; + procedure CreateDatabase; end; TBoldParameterWrapper = class(TBoldRefCountedObject) private - fDatasetWrapper: TBolddatasetWrapper; + fDatasetWrapper: TBoldAbstractQueryWrapper; protected - property DatasetWrapper: TBoldDatasetWrapper read fDatasetWrapper; + property DatasetWrapper: TBoldAbstractQueryWrapper read fDatasetWrapper; public - constructor create(DatasetWrapper: TBoldDatasetWrapper); + constructor Create(DatasetWrapper: TBoldAbstractQueryWrapper); end; TBoldDbParameter = class(TBoldParameterWrapper, IBoldParameter) private - fParameter: TParam; - function GetAsVariant: Variant; - procedure SetAsVariant(const NewValue: Variant); - function GetName: String; - procedure Clear; - function GetDataType: TFieldType; - procedure SetDataType(Value: TFieldType); - function GetAsBCD: Currency; - function GetAsBoolean: Boolean; - function GetAsCurrency: Currency; - function GetAsFloat: Double; - function GetAsInteger: Longint; - function GetAsMemo: string; + FParameter: TParam; + function GetAsVariant: Variant; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + procedure SetAsVariant(const NewValue: Variant); {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function GetName: String; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + procedure Clear; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function GetDataType: TFieldType; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + procedure SetDataType(Value: TFieldType); {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function GetAsBCD: Currency; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function GetAsBlob: TBoldBlobData; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function GetAsBoolean: Boolean; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function GetAsCurrency: Currency; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function GetAsFloat: Double; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function GetAsInteger: Longint; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function GetAsMemo: string; {$IFDEF BOLD_INLINE}inline;{$ENDIF} function GetAsString: string; - function GetIsNull: Boolean; - procedure SetAsBCD(const Value: Currency); - procedure SetAsBlob(const Value: TBlobData); - procedure SetAsBoolean(Value: Boolean); - procedure SetAsCurrency(const Value: Currency); - procedure SetAsDate(const Value: TDateTime); - procedure SetAsFloat(const Value: Double); - procedure SetAsInteger(Value: Longint); - procedure SetAsMemo(const Value: string); + function GetAsAnsiString: TBoldAnsiString; + function GetAsWideString: WideString; + function GetAsInt64: Int64; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function GetIsNull: Boolean; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + procedure SetAsBCD(const Value: Currency); {$IFDEF BOLD_INLINE}inline;{$ENDIF} + procedure SetAsBlob(const Value: TBoldBlobData); {$IFDEF BOLD_INLINE}inline;{$ENDIF} + procedure SetAsBoolean(Value: Boolean); {$IFDEF BOLD_INLINE}inline;{$ENDIF} + procedure SetAsCurrency(const Value: Currency); {$IFDEF BOLD_INLINE}inline;{$ENDIF} + procedure SetAsDate(const Value: TDateTime); {$IFDEF BOLD_INLINE}inline;{$ENDIF} + procedure SetAsFloat(const Value: Double); {$IFDEF BOLD_INLINE}inline;{$ENDIF} + procedure SetAsInteger(Value: Longint); {$IFDEF BOLD_INLINE}inline;{$ENDIF} + procedure SetAsMemo(const Value: string); {$IFDEF BOLD_INLINE}inline;{$ENDIF} procedure SetAsString(const Value: string); - procedure SetAsSmallInt(Value: LongInt); - procedure SetAsTime(const Value: TDateTime); -// procedure SetAsWideString(const Value: Widestring); - procedure SetAsWord(Value: LongInt); - procedure SetText(const Value: string); - procedure AssignFieldValue(source: IBoldField); + procedure SetAsAnsiString(const Value: TBoldAnsiString); + procedure SetAsWideString(const Value: Widestring); + procedure SetAsSmallInt(Value: LongInt); {$IFDEF BOLD_INLINE}inline;{$ENDIF} + procedure SetAsTime(const Value: TDateTime); {$IFDEF BOLD_INLINE}inline;{$ENDIF} + procedure SetAsInt64(const Value: Int64); {$IFDEF BOLD_INLINE}inline;{$ENDIF} + procedure SetAsWord(Value: LongInt); {$IFDEF BOLD_INLINE}inline;{$ENDIF} + procedure SetText(const Value: string); {$IFDEF BOLD_INLINE}inline;{$ENDIF} + procedure AssignFieldValue(const source: IBoldField); {$IFDEF BOLD_INLINE}inline;{$ENDIF} + procedure Assign(const source: IBoldParameter); {$IFDEF BOLD_INLINE}inline;{$ENDIF} function GetParameter: TParam; protected property Parameter: TParam read GetParameter; @@ -305,55 +387,130 @@ TBoldDbParameter = class(TBoldParameterWrapper, IBoldParameter) destructor Destroy; override; end; - TBoldDataSetWrapper = class(TBoldNonRefCountedObject) + TBoldAbstractQueryWrapper = class(TBoldNonRefCountedObject) private - fLastKnowFieldIndex: integer; fDatabaseWrapper: TBoldDatabaseWrapper; + protected + function GetImplementor: TObject; + public + constructor Create(DatabaseWrapper: TBoldDatabaseWrapper); virtual; + procedure Clear; virtual; + property DatabaseWrapper: TBoldDatabaseWrapper read fDatabaseWrapper; + end; + + TBoldDataSetWrapper = class(TBoldAbstractQueryWrapper) + private + fLastUsedFieldIndex: integer; + // Names in uppercase. May differ from what is + // in the dataset. + fFieldNames: array of string; + fNamesInited: Boolean; + fWrapper1: TBoldFieldWrapper; + fWrapper1AsInterface: IBoldField; + fWrapper2: TBoldFieldWrapper; + fWrapper2AsInterface: IBoldField; + private function GetWrappedField(Field: TField): IBoldField; protected function GetFieldWrapperClass: TBoldFieldWrapperClass; virtual; function GetDataSet: TDataSet; virtual; abstract; - function GetEof: Boolean; + function GetEof: Boolean; {$IFDEF BOLD_INLINE}inline;{$ENDIF} function GetFields(Index: integer): IBoldField; - function GetFieldCount: integer; - function GetFieldValue(const FieldName: string): Variant; - procedure SetFieldValue(const FieldName: string; const Value: Variant); - function GetFieldDefs: TFieldDefs; - procedure Append; - function Createparam(FldType: TFieldType; const ParamName: string; ParamType: TParamType; Size: integer): IBoldParameter; + function GetFieldCount: integer; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function GetFieldValue(const FieldName: string): Variant; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + procedure SetFieldValue(const FieldName: string; const Value: Variant); {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function GetFieldDefs: TFieldDefs; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + procedure Append; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function ParamByName(const Value: string): IBoldParameter; virtual; abstract; + function FindParam(const Value: string): IBoldParameter; virtual; abstract; + function Createparam(FldType: TFieldType; const ParamName: string): IBoldParameter; overload; virtual; + function Createparam(FldType: TFieldType; const ParamName: string; ParamType: TParamType; Size: integer): IBoldParameter; overload; virtual; + function EnsureParamByName(const Value: string): IBoldParameter; virtual; procedure Close; virtual; - function FieldByName(const FieldName: string): IBoldField; + function FieldByName(const FieldName: string): IBoldField; virtual; + function FieldByUpperCaseName(const FieldNameUpper: string): IBoldField; function FindField(const FieldName: string): IBoldField; - procedure First; - procedure Delete; - procedure Next; + procedure First; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + procedure Delete; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + procedure Next; {$IFDEF BOLD_INLINE}inline;{$ENDIF} procedure Open; virtual; procedure Edit; function MoveBy(Distance: integer): integer; function Locate(const KeyFields: string; const KeyValues: Variant; Options: TLocateOptions): Boolean; procedure Post; - function GetImplementor: TObject; function GetState: TDataSetState; + function GetRecNo: integer; virtual; + procedure Reconnect; public - constructor Create(DatabaseWrapper: TBoldDatabaseWrapper); - property DatabaseWrapper: TBoldDatabaseWrapper read fDatabaseWrapper; property DataSet: TDataSet read GetDataSet; end; - TBoldDatabaseWrapper = class(TBoldNonRefCountedObject) + TBoldBatchDataSetWrapper = class(TBoldDataSetWrapper) private + fBatchQuery: IBoldExecQuery; + FInBatch: Boolean; + fAccumulatedSQLLength: integer; + fParamsInBeginUpdate: Boolean; + {$IFDEF UseSynCommons} + SB: SynCommons.TTextWriter; + {$ELSE} + SB: TStringBuilder; + {$ENDIF} + function GetAccumulatedSQL: TStrings; + function GetHasCachedStatements: boolean; + procedure ReplaceParamMarkers(sql: TStrings; const Source, Dest: IBoldExecQuery); + procedure SetInBatch(const Value: Boolean); + protected + procedure StartSQLBatch; virtual; + procedure EndSQLBatch; virtual; + procedure FailSQLBatch; virtual; + procedure ExecSQL; virtual; abstract; + function GetParams: TParams; virtual; abstract; + function GetSqlText: string; virtual; abstract; + procedure AssignSQLText(const SQL: string); virtual; abstract; + function GetSQLStrings: TStrings; virtual; abstract; + function GetSqlLength: integer; + function ParamsContainBlob: Boolean; + function GetBatchQueryParamCount: integer; + procedure BatchExecSQL; + procedure ExecuteBatch; + property AccumulatedSQL: TStrings read GetAccumulatedSQL; + property InBatch: Boolean read FInBatch write SetInBatch; + property HasCachedStatements: boolean read GetHasCachedStatements; + property BatchQuery: IBoldExecQuery read fBatchQuery; + public + constructor Create(DatabaseWrapper: TBoldDatabaseWrapper); override; + destructor Destroy; override; + property SqlText: string read GetSqlText write AssignSQLText; + property SQLStrings: TStrings read GetSQLStrings; + property Params: TParams read GetParams; + end; + + TBoldDatabaseWrapper = class(TBoldNonRefCountedObject) + strict private fSQLDataBaseConfig: TBoldSQLDatabaseConfig; + fAllTableNames: TStringList; + function GetWindowsLoginName: string; + function GetIndexDescriptionsViaTable( const TableName: String): TBoldIndexDescriptionArray; + function GetIndexDescriptionsViaQuery( const TableName: String): TBoldIndexDescriptionArray; protected function SupportsDefaultColumnValues: Boolean; virtual; procedure AllTableNames(Pattern: String; SystemTables: Boolean; TableNameList: TStrings); virtual; abstract; + function GetIndexDescriptions(const TableName: String): TBoldIndexDescriptionArray; virtual; + function GetTable: IBoldTable; virtual; abstract; + procedure ReleaseTable(var Table: IBoldTable); virtual; abstract; function TableExists(const TableName: String): Boolean; function GetQuery: IBoldQuery; virtual; abstract; procedure ReleaseQuery(var Query: IBoldQuery); virtual; abstract; function GetExecQuery: IBoldExecQuery; virtual; procedure ReleaseExecQuery(var Query: IBoldExecQuery); virtual; - function GetSQLDatabaseConfig: TBoldSQLDatabaseConfig; + function GetSQLDatabaseConfig: TBoldSQLDatabaseConfig; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function InternalGetDatabaseError(const aErrorType: TBoldDatabaseErrorType; + const E: Exception; sSQL, sServer, sDatabase, sUserName: string; + bUseWindowsAuth: Boolean): EBoldDatabaseError; public constructor Create(SQLDataBaseConfig: TBoldSQLDatabaseConfig); destructor Destroy; override; + procedure CreateDatabase; virtual; abstract; property SQLDatabaseConfig: TBoldSQLDatabaseConfig read GetSQLDatabaseConfig; end; @@ -362,52 +519,65 @@ TBoldFieldWrapper = class(TBoldRefcountedObject, IBoldField) fSavedValue: Variant; fField: TField; fDatasetWrapper: TBoldDataSetWrapper; - function GetField: TField; - function GetAsVariant: Variant; + function GetField: TField; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function GetAsVariant: Variant; {$IFDEF BOLD_INLINE}inline;{$ENDIF} procedure SetAsVariant(const Value: Variant); procedure SetAsString(const Value: String); - function GetAsInteger: Integer; - procedure SetAsInteger(const Value: Integer); - function GetAsBoolean: Boolean; - function GetAsCurrency: Currency; - function GetAsDateTime: TDateTime; - function GetAsFloat: Double; - function GetIsNull: Boolean; - procedure SetAsBoolean(const Value: Boolean); - procedure SetAsCurrency(const Value: Currency); - procedure SetAsDateTime(const Value: TDateTime); - procedure SetAsFloat(const Value: Double); - function GetFieldName: String; - function GetAsDate: TDateTime; - function GetAsTime: TDateTime; - procedure SetAsTime(const Value: TDateTime); - procedure SetAsDate(const Value: TDateTime); - procedure SetAsBlob(const Value: string); - function GetAsBlob: string; + function GetAsAnsiString: TBoldAnsiString; + procedure SetAsAnsiString(const Value: TBoldAnsiString); + function GetAsWideString: TBoldUnicodeString; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + procedure SetAsWideString(const Value: TBoldUnicodeString); {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function GetAsInteger: Integer; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + procedure SetAsInteger(const Value: Integer); {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function GetAsBoolean: Boolean; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function GetAsCurrency: Currency; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function GetAsDateTime: TDateTime; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function GetAsFloat: Double; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function GetIsNull: Boolean; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + procedure SetAsBoolean(const Value: Boolean); {$IFDEF BOLD_INLINE}inline;{$ENDIF} + procedure SetAsCurrency(const Value: Currency); {$IFDEF BOLD_INLINE}inline;{$ENDIF} + procedure SetAsDateTime(const Value: TDateTime); {$IFDEF BOLD_INLINE}inline;{$ENDIF} + procedure SetAsFloat(const Value: Double); {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function GetFieldName: String; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function GetAsDate: TDateTime; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function GetAsTime: TDateTime; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + procedure SetAsTime(const Value: TDateTime); {$IFDEF BOLD_INLINE}inline;{$ENDIF} + procedure SetAsDate(const Value: TDateTime); {$IFDEF BOLD_INLINE}inline;{$ENDIF} + procedure SetAsBlob(const Value: TBoldAnsiString); {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function GetAsBlob: TBoldAnsiString; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function GetAsInt64: Int64; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + procedure SetAsInt64(const Value: Int64); {$IFDEF BOLD_INLINE}inline;{$ENDIF} protected function GetAsString: String; virtual; property DataSetWrapper: TBoldDatasetWrapper read fDatasetWrapper; public - constructor create(Field: TField; DatasetWrapper: TBoldDatasetWrapper); + constructor Create(Field: TField; DatasetWrapper: TBoldDatasetWrapper); + procedure ReTarget(Field: TField); {$IFDEF BOLD_INLINE} inline; {$ENDIF} property Field: TField read GetField; property FieldName: String read GetFieldName; end; procedure BoldLogSQL(const sql: TStrings); +procedure BoldLogSQLWide(const sql: TWideStrings; const Params: IBoldParameterized); +procedure BoldLogSQLWithParams(const sql: TStrings; const Params: IBoldParameterized); +function BoldQueryAsString(const sql: TStrings; const Params: IBoldParameterized): string; +procedure kiCLogSQL(const s: String); +procedure kiCLogSQLException(const s: String); var BoldSQLLogHandler: TBoldLogHandler = nil; BoldSQLLogCount: integer = 0; + BoldSQLMessage: string = ''; + kiCSQLLogHandler: TBoldLogHandler = nil; + kiCSQLExceptionLogHandler: TBoldLogHandler = nil; implementation uses - Bolddefs, - BoldSharedStrings, Variants, - SysUtils, - BoldUtils, - BoldPMConsts; + Windows, + BoldSharedStrings, + BoldUtils; procedure BoldLogSQL(const sql: TStrings); var @@ -416,21 +586,118 @@ procedure BoldLogSQL(const sql: TStrings); Inc(BoldSQLLogCount); if assigned(BoldSQLLogHandler) then begin + if BoldSQLMessage <> '' then + BoldSQLLogHandler.Log(BoldSQLMessage); + BoldSQLLogHandler.Log( + formatDateTime('c: ', now) + + format('SQL %3d- %s', [BoldSQLLogCount, trim(SQL[0])])); + for i := 1 to SQL.Count - 1 do + begin + if trim(SQL[i]) <> '' then + BoldSQLLogHandler.Log(' ' + + Trim(SQL[i])); + end; + end; +end; + +procedure BoldLogSQLWide(const sql: TWideStrings; const Params: IBoldParameterized); +var + i: integer; +begin + Inc(BoldSQLLogCount); + if assigned(BoldSQLLogHandler) then + begin + if BoldSQLMessage <> '' then + BoldSQLLogHandler.Log(BoldSQLMessage); + BoldSQLLogHandler.Log( + formatDateTime('c: ', now) + + format('SQL %3d- %s', [BoldSQLLogCount, trim(SQL[0])])); + for i := 1 to SQL.Count - 1 do + begin + if trim(SQL[i]) <> '' then + BoldSQLLogHandler.Log(' ' + + Trim(SQL[i])); + end; + if Params <> nil then + for I := 0 to Params.ParamCount - 1 do + begin + BoldSQLLogHandler.Log( + ' ' + + Format(' [%s]:%s', [Params.Param[i].Name, Params.Param[i].AsString]) + ); + end; + end; +end; + +function BoldQueryAsString(const sql: TStrings; const Params: IBoldParameterized): string; +var + i: integer; +begin + result := ''; + for i := 0 to SQL.Count - 1 do + begin + if trim(SQL[i]) <> '' then + result := result + Trim(SQL[i]); + end; + if Params <> nil then + for I := 0 to Params.ParamCount - 1 do + begin + result := result + Format(' [%s]:%s', [Params.Param[i].Name, Params.Param[i].AsString]); + end; +end; + +procedure BoldLogSQLWithParams(const sql: TStrings; const Params: IBoldParameterized); +var + i: integer; +begin + Inc(BoldSQLLogCount); + if assigned(BoldSQLLogHandler) then + begin + if BoldSQLMessage <> '' then + BoldSQLLogHandler.Log(BoldSQLMessage); BoldSQLLogHandler.Log( - formatDateTime('c: ', now) + // do not localize - format('SQL %3d- %s', [BoldSQLLogCount, trim(SQL[0])])); // do not localize + formatDateTime('c: ', now) + + format('SQL %3d- %s', [BoldSQLLogCount, trim(SQL[0])])); for i := 1 to SQL.Count - 1 do begin if trim(SQL[i]) <> '' then BoldSQLLogHandler.Log(' ' + Trim(SQL[i])); end; + if Params <> nil then + for I := 0 to Params.ParamCount - 1 do + begin + BoldSQLLogHandler.Log( + ' ' + + Format(' [%s]:%s', [Params.Param[i].Name, Params.Param[i].AsString]) + ); + end; + end; +end; + +procedure kiCLogSQL(const s: String); +begin + if assigned(kiCSQLLogHandler) then begin + kiCSQLLogHandler.Log(s); + end; +end; + +procedure kiCLogSQLException(const s: String); +begin + if assigned(kiCSQLExceptionLogHandler) then + begin + kiCSQLExceptionLogHandler.Log(s); end; end; { TBoldDbParameter } -procedure TBoldDbParameter.AssignFieldValue(source: IBoldField); +procedure TBoldDbParameter.Assign(const source: IBoldParameter); +begin + Parameter.Value := Source.AsVariant; +end; + +procedure TBoldDbParameter.AssignFieldValue(const source: IBoldField); begin Parameter.AssignFieldValue(Source.Field, Source.AsVariant); end; @@ -440,13 +707,13 @@ procedure TBoldDbParameter.Clear; Parameter.Clear; end; -constructor TBoldDbParameter.create(DbParameter: TParam; DatasetWrapper: TBoldDatasetWrapper); +constructor TBoldDbParameter.Create(DbParameter: TParam; DatasetWrapper: TBoldDatasetWrapper); begin inherited Create(DatasetWrapper); fParameter := DbParameter; end; -destructor TBoldDbParameter.destroy; +destructor TBoldDbParameter.Destroy; begin inherited; end; @@ -456,6 +723,11 @@ function TBoldDbParameter.GetAsBCD: Currency; result := Parameter.AsBCD; end; +function TBoldDbParameter.GetAsBlob: TBoldBlobData; +begin + result := TBoldBlobData(Parameter.AsBlob); +end; + function TBoldDbParameter.GetAsBoolean: Boolean; begin result := Parameter.AsBoolean @@ -481,6 +753,15 @@ function TBoldDbParameter.GetAsInteger: Longint; result := Parameter.AsInteger end; +function TBoldDBParameter.GetAsInt64: Int64; +begin +{$IFDEF BOLD_DELPHI15_OR_LATER} + result := parameter.AsLargeInt; +{$ELSE} + result := parameter.AsInteger; +{$ENDIF} +end; + function TBoldDbParameter.GetAsMemo: string; begin result := Parameter.AsMemo; @@ -493,6 +774,24 @@ function TBoldDbParameter.GetAsString: string; result := ''; end; +function TBoldDbParameter.GetAsAnsiString: TBoldAnsiString; +begin + {$IFDEF BOLD_UNICODE} + result := Parameter.AsAnsiString; + {$ELSE} + result := Parameter.AsString; + {$ENDIF} + if string(result) = DatasetWrapper.DatabaseWrapper.SQLDatabaseConfig.EmptyStringMarker then + result := ''; +end; + +function TBoldDbParameter.GetAsWideString: WideString; +begin + result := Parameter.AsWideString; + if string(result) = DatasetWrapper.DatabaseWrapper.SQLDatabaseConfig.EmptyStringMarker then + result := ''; +end; + function TBoldDbParameter.GetAsVariant: Variant; begin result := Parameter.Value; @@ -523,9 +822,9 @@ procedure TBoldDbParameter.SetAsBCD(const Value: Currency); Parameter.AsBCD := Value; end; -procedure TBoldDbParameter.SetAsBlob(const Value: TBlobData); +procedure TBoldDbParameter.SetAsBlob(const Value: TBoldBlobData); begin - Parameter.AsBlob := Value; + Parameter.AsBlob := TBlobData(Value); end; procedure TBoldDbParameter.SetAsBoolean(Value: Boolean); @@ -558,6 +857,16 @@ procedure TBoldDbParameter.SetAsInteger(Value: Integer); Parameter.AsInteger := Value; end; +procedure TBoldDBParameter.SetAsInt64(const Value: Int64); +begin +{$IFDEF BOLD_DELPHI15_OR_LATER} + Parameter.AsLargeInt := Value; +{$ELSE} + Parameter.AsInteger:= Value; +{$ENDIF} +end; + + procedure TBoldDbParameter.SetAsMemo(const Value: string); begin Parameter.AsMemo := Value; @@ -576,6 +885,26 @@ procedure TBoldDbParameter.SetAsString(const Value: string); Parameter.Value := Value end; +procedure TBoldDbParameter.SetAsAnsiString(const Value: TBoldAnsiString); +begin + if value = '' then + Parameter.Value := DatasetWrapper.DatabaseWrapper.SQLDatabaseConfig.EmptyStringMarker + else + {$IFDEF BOLD_UNICODE} + Parameter.AsAnsiString := Value + {$ELSE} + Parameter.AsString := Value + {$ENDIF} +end; + +procedure TBoldDbParameter.SetAsWideString(const Value: Widestring); +begin + if value = '' then + Parameter.Value := DatasetWrapper.DatabaseWrapper.SQLDatabaseConfig.EmptyStringMarker + else + Parameter.AsWideString := Value +end; + procedure TBoldDbParameter.SetAsTime(const Value: TDateTime); begin Parameter.AsTime := Value; @@ -586,11 +915,6 @@ procedure TBoldDbParameter.SetAsVariant(const NewValue: Variant); Parameter.Value := NewValue; end; -//procedure TBoldDbParameter.SetAsWideString(const Value: Widestring); -//begin -// Parameter.AsWi TParam -//end; - procedure TBoldDbParameter.SetAsWord(Value: Integer); begin Parameter.AsWord := Value; @@ -615,18 +939,20 @@ procedure TBoldDataSetWrapper.Append; procedure TBoldDataSetWrapper.Close; begin - DataSet.Close; + if Assigned(DataSet) then // some subclasses perform tricks here + DataSet.Close; end; -constructor TBoldDataSetWrapper.Create(DatabaseWrapper: TBoldDatabaseWrapper); +function TBoldDataSetWrapper.Createparam(FldType: TFieldType; + const ParamName: string; ParamType: TParamType; + Size: integer): IBoldParameter; begin - inherited Create; - fDatabaseWrapper := DatabaseWrapper; + raise EBold.CreateFmt('%s.Createparam: Not supported yet... override in this subclass needed', [classname]); end; -function TBoldDataSetWrapper.Createparam(FldType: TFieldType; const ParamName: string; ParamType: TParamType; Size: integer): IBoldParameter; +function TBoldDataSetWrapper.Createparam(FldType: TFieldType; const ParamName: string): IBoldParameter; begin - raise EBold.CreateFmt(sCreateParamNotImplemented, [classname]); + result := Createparam(FldType, Paramname, ptUnknown, 0); end; procedure TBoldDataSetWrapper.Delete; @@ -639,40 +965,86 @@ procedure TBoldDataSetWrapper.Edit; DataSet.Edit; end; +function TBoldDataSetWrapper.EnsureParamByName( + const Value: string): IBoldParameter; +begin + result := FindParam(Value); + if not Assigned(result) then + result := CreateParam(db.ftUnknown, Value); +end; + function TBoldDataSetWrapper.FieldByName(const FieldName: string): IBoldField; -var - Wrapper: TBoldFieldWrapper; begin - Dataset.FieldList.Update; - if (fLastKnowFieldIndex + 1 >= 0) and - (fLastKnowFieldIndex + 1 <= DataSet.FieldCount - 1) and - (DataSet.FieldList.strings[fLastKnowFieldIndex + 1] = FieldName) then + Result := FieldByUpperCaseName(AnsiUpperCase(FieldName)); +end; + +function TBoldDataSetWrapper.FieldByUpperCaseName(const FieldNameUpper: string): IBoldField; +var + DataSetFieldList :TFieldList; + + procedure FoundIndex(Index: Integer); begin - inc(fLastKnowFieldIndex); - end - else - if (fLastKnowFieldIndex < 0) or - (fLastKnowFieldIndex > DataSet.FieldCount - 1) or - (DataSet.FieldList.Strings[fLastKnowFieldIndex] <> FieldName) then - begin - fLastKnowFieldIndex := DataSet.FieldList.FieldByName(FieldName).FieldNo - 1; - end; + fLastUsedFieldIndex := Index; + fFieldNames[Index] := FieldNameUpper; + end; + + function TryIndex(Index: Integer): Boolean; + begin + Result := + (Index >= 0) and + (Index < Length(fFieldNames)) and + (FieldNameUpper = fFieldNames[Index]); + if Result then + FoundIndex(Index); + end; + + function SearchIndex: Boolean; + var + I: Integer; + begin + result := false; + for I := 0 to DataSet.FieldCount - 1 do + if FieldNameUpper = fFieldNames[I] then + begin + FoundIndex(I); + Result := true; + break; + end; + end; - Wrapper := GetFieldWrapperClass.Create(DataSet.FieldList.Fields[fLastKnowFieldIndex], self); - Wrapper.GetInterface(IBoldField, result); + procedure InitNames; + var + F: integer; + begin + DataSetFieldList.Update; + SetLength(fFieldNames, DataSet.FieldCount); + for F := 0 to DataSet.FieldCount - 1 do + fFieldNames[F] := AnsiUpperCase(DataSetFieldList.Fields[F].FieldName); + fNamesInited := true; + end; + +begin + DataSetFieldList := DataSet.FieldList; + if not fNamesInited then + InitNames; + if not TryIndex(fLastUsedFieldIndex+1) then + if not TryIndex(fLastUsedFieldIndex-1) then + if not TryIndex(fLastUsedFieldIndex) then + if not SearchIndex then + fLastUsedFieldIndex := -1; + if fLastUsedFieldIndex = -1 then + Result := nil + else + Result := GetWrappedField(DataSetFieldList.Fields[fLastUsedFieldIndex]); end; function TBoldDataSetWrapper.FindField(const FieldName: string): IBoldField; var - Wrapper: TBoldFieldWrapper; Field: TField; begin Field := DataSet.FindField(FieldName); if assigned(field) then - begin - Wrapper := GetFieldWrapperClass.Create(Field, self); - Wrapper.GetInterface(IBoldField, result); - end + Result := GetWrappedField(Field) else result := nil; end; @@ -698,11 +1070,8 @@ function TBoldDataSetWrapper.GetFieldDefs: TFieldDefs; end; function TBoldDataSetWrapper.GetFields(Index: integer): IBoldField; -var - Wrapper: TBoldFieldWrapper; begin - Wrapper := GetFieldWrapperClass.Create(DataSet.Fields[Index], self); - Wrapper.GetInterface(IBoldField, Result); + Result := GetWrappedField(DataSet.Fields[Index]); end; function TBoldDataSetWrapper.GetFieldValue(const FieldName: string): Variant; @@ -715,9 +1084,9 @@ function TBoldDataSetWrapper.GetFieldWrapperClass: TBoldFieldWrapperClass; result := TBoldFieldWrapper; end; -function TBoldDataSetWrapper.GetImplementor: TObject; +function TBoldDataSetWrapper.GetRecNo: integer; begin - result := self; + result := Dataset.RecNo; end; function TBoldDataSetWrapper.GetState: TDataSetState; @@ -725,6 +1094,33 @@ function TBoldDataSetWrapper.GetState: TDataSetState; result := DataSet.State; end; +function TBoldDataSetWrapper.GetWrappedField(Field: TField): IBoldField; +begin + // Reuse wrapper if we hold only reference + if Assigned(fWrapper1) and (fWrapper1.RefCount =1) then + begin + fWrapper1.Retarget(Field); + Result := fWrapper1AsInterface; + end + else if Assigned(fWrapper2) and (fWrapper2.RefCount =1) then + begin + fWrapper2.Retarget(Field); + Result := fWrapper2AsInterface; + end + else if not Assigned(fWrapper1) then + begin + fWrapper1 := GetFieldWrapperClass.Create(Field, self); + fWrapper1.GetInterface(IBoldField, fWrapper1AsInterface); + Result := fWrapper1AsInterface; + end + else + begin + fWrapper2 := GetFieldWrapperClass.Create(Field, self); + fWrapper2.GetInterface(IBoldField, fWrapper2AsInterface); + Result := fWrapper2AsInterface; + end; +end; + function TBoldDataSetWrapper.Locate(const KeyFields: string; const KeyValues: Variant; Options: TLocateOptions): Boolean; begin @@ -744,7 +1140,8 @@ procedure TBoldDataSetWrapper.Next; procedure TBoldDataSetWrapper.Open; begin Dataset.Open; - fLastKnowFieldIndex := -1; + fLastUsedFieldIndex := -1; + fNamesInited := false; end; procedure TBoldDataSetWrapper.Post; @@ -752,6 +1149,13 @@ procedure TBoldDataSetWrapper.Post; DataSet.Post; end; +procedure TBoldDataSetWrapper.Reconnect; +begin + if DatabaseWrapper.SupportsInterface(IBoldDataBase) then begin + (DatabaseWrapper as IBoldDataBase).Reconnect; + end; +end; + procedure TBoldDataSetWrapper.SetFieldValue(const FieldName: string; const Value: Variant); begin @@ -760,22 +1164,26 @@ procedure TBoldDataSetWrapper.SetFieldValue(const FieldName: string; { TBoldFieldWrapper } -procedure TBoldFieldWrapper.SetAsBlob(const Value: string); +procedure TBoldFieldWrapper.SetAsBlob(const Value: TBoldAnsiString); begin Field.AsVariant := Value; end; -constructor TBoldFieldWrapper.create(Field: TField; DatasetWrapper: TBoldDatasetWrapper); +constructor TBoldFieldWrapper.Create(Field: TField; DatasetWrapper: TBoldDatasetWrapper); begin inherited create; fField := Field; - fSavedValue := Field.Value; + fSavedValue := Field.Value; fDatasetWrapper := DatasetWrapper; end; -function TBoldFieldWrapper.GetAsBlob: string; +function TBoldFieldWrapper.GetAsBlob: TBoldAnsiString; begin - result := Field.AsVariant; + {$IFDEF BOLD_UNICODE} + Result := Field.AsAnsiString; + {$ELSE} + Result := Field.AsString; + {$ENDIF} end; function TBoldFieldWrapper.GetAsBoolean: Boolean; @@ -815,11 +1223,42 @@ function TBoldFieldWrapper.GetAsString: String; result := ''; end; +function TBoldFieldWrapper.GetAsAnsiString: TBoldAnsiString; +begin + {$IFDEF BOLD_UNICODE} + result := BoldSharedStringManager.GetSharedAnsiString(Field.AsAnsiString); + if String(result) = DatasetWrapper.DatabaseWrapper.SQLDatabaseConfig.EmptyStringMarker then + result := ''; + {$ELSE} + Result := GetAsString; + {$ENDIF} +end; + +function TBoldFieldWrapper.GetAsWideString: TBoldUnicodeString; +begin + {$IFDEF BOLD_UNICODE} + result := GetAsString; + {$ELSE} + result := Field.AsWideString; + if result = DatasetWrapper.DatabaseWrapper.SQLDatabaseConfig.EmptyStringMarker then + result := ''; + {$ENDIF} +end; + function TBoldFieldWrapper.GetAsTime: TDateTime; begin result := frac(Field.AsDateTime); end; +function TBoldFieldWrapper.GetAsInt64; +begin +{$IFDEF BOLD_DELPHI15_OR_LATER} + Result := fField.AsLargeInt; +{$ELSE} + Result := fField.AsInteger; +{$ENDIF} +end; + function TBoldFieldWrapper.GetAsVariant: Variant; begin result := fSavedValue; @@ -840,6 +1279,21 @@ function TBoldFieldWrapper.GetIsNull: Boolean; result := VarType(fSavedValue) = varNull; end; +procedure TBoldFieldWrapper.ReTarget(Field: TField); +begin + fField := Field; + fSavedValue := Field.Value; +end; + +procedure TBoldFieldWrapper.SetAsInt64(const Value: Int64); +begin +{$IFDEF BOLD_DELPHI15_OR_LATER} + Field.AsLargeInt := Value; +{$ELSE} + Field.AsInteger:= Value; +{$ENDIF} +end; + procedure TBoldFieldWrapper.SetAsBoolean(const Value: Boolean); begin Field.AsBoolean := Value; @@ -873,10 +1327,35 @@ procedure TBoldFieldWrapper.SetAsString(const Value: String); Field.AsString := Value; end; +procedure TBoldFieldWrapper.SetAsAnsiString(const Value: TBoldAnsiString); +begin + {$IFDEF BOLD_UNICODE} + if value = '' then + Field.AsAnsiString := TBoldAnsiString( + DataSetWrapper.DatabaseWrapper.SQLDatabaseConfig.EmptyStringMarker) + else + Field.AsAnsiString := Value; + {$ELSE} + SetAsString(Value); + {$ENDIF} +end; + +procedure TBoldFieldWrapper.SetAsWideString(const Value: TBoldUnicodeString); +begin + {$IFDEF BOLD_UNICODE} + SetAsString(Value); + {$ELSE} + if value = '' then + Field.AsWideString := TBoldUnicodeString(DataSetWrapper.DatabaseWrapper.SQLDatabaseConfig.EmptyStringMarker) + else + Field.AsWideString := Value; + {$ENDIF} +end; + procedure TBoldFieldWrapper.SetAsVariant(const Value: Variant); begin Field.AsVariant := value; - fSavedValue := Value; + fSavedValue := Value; end; procedure TBoldFieldWrapper.SetAsDate(const Value: TDateTime); @@ -891,17 +1370,16 @@ procedure TBoldFieldWrapper.SetAsTime(const Value: TDateTime); { TBoldDatabaseWrapper } -constructor TBoldDatabaseWrapper.create(SQLDatabaseConfig: TBoldSQLDatabaseConfig); +constructor TBoldDatabaseWrapper.Create(SQLDatabaseConfig: TBoldSQLDatabaseConfig); begin inherited Create; - fSQLDatabaseConfig := TBoldSQLDataBaseConfig.Create; - fSQlDatabaseConfig.AssignConfig(SQLDatabaseConfig); + fSQLDatabaseConfig := SQLDatabaseConfig; end; destructor TBoldDatabaseWrapper.destroy; begin - FreeAndNil(fSQLDatabaseConfig); - inherited; + FreeAndNil(fAllTableNames); + inherited; end; function TBoldDatabaseWrapper.GetExecQuery: IBoldExecQuery; @@ -918,11 +1396,177 @@ function TBoldDatabaseWrapper.GetExecQuery: IBoldExecQuery; end; end; +function TBoldDatabaseWrapper.GetIndexDescriptions( + const TableName: String): TBoldIndexDescriptionArray; +begin + if SQLDatabaseConfig.IndexInfoTemplate = '' then + Result := GetIndexDescriptionsViaTable(TableName) + else + Result := GetIndexDescriptionsViaQuery(TableName); +end; + +function TBoldDatabaseWrapper.GetIndexDescriptionsViaQuery( + const TableName: String): TBoldIndexDescriptionArray; +var + DbQuery: IBoldQuery; + CurrentIndex: integer; + LastIndexName: string; + SQL: string; + vIndexField: IBoldField; + vColumnField: IBoldField; + vIsPrimaryField: IBoldField; + vIsUniqueField: IBoldField; +const + cIndexName = 'indexName'; + cColumnName = 'columnName'; + cIsPrimary = 'isPrimary'; + cisUnique = 'isUnique'; + cFieldNotFoundMessage = 'Field %s not found in IndexInfoQuery result set.'; +begin + SetLength(result, 0); + DbQuery := GetQuery; + lastIndexName := ''; + try + SQL := SQLDatabaseConfig.GetIndexInfoQuery(TableName); + DbQuery.AssignSQLText(SQL); + DbQuery.Open; + Assert(Assigned(DbQuery.FindField(cIndexName)), Format(cFieldNotFoundMessage, [cIndexName])); + Assert(Assigned(DbQuery.FindField(cColumnName)), Format(cFieldNotFoundMessage, [cColumnName])); + Assert(Assigned(DbQuery.FindField(cIsPrimary)), Format(cFieldNotFoundMessage, [cIsPrimary])); + Assert(Assigned(DbQuery.FindField(cIsUnique)), Format(cFieldNotFoundMessage, [cIsUnique])); + vIndexField := DbQuery.FieldByName(cIndexName); + vColumnField := DbQuery.FieldByName(cColumnName); + vIsPrimaryField := DbQuery.FieldByName(cIsPrimary); + vIsUniqueField := DbQuery.FieldByName(cIsUnique); + CurrentIndex := -1; + // IndexName, IsPrimary, IsUnique, ColumnName + while not DbQuery.Eof do + begin + if vIndexField.AsString <> LastIndexName then // new Index + begin + INC(CurrentIndex); + SetLength(Result, CurrentIndex+1); + LastIndexName := vIndexField.AsString; + Result[CurrentIndex].IndexName := LastIndexName; + Result[CurrentIndex].IsPrimary := vIsPrimaryField.AsBoolean; + Result[CurrentIndex].IsUnique := vIsUniqueField.AsBoolean; + end; + if Result[CurrentIndex].IndexedColumns = '' then + Result[CurrentIndex].IndexedColumns := vColumnField.AsString + else + Result[CurrentIndex].IndexedColumns := Result[CurrentIndex].IndexedColumns + ';' + vColumnField.AsString; + DbQuery.Next; + end; + finally + DbQuery.Close; + releaseQuery(DbQuery); + end; +end; + +function TBoldDatabaseWrapper.GetIndexDescriptionsViaTable( + const TableName: String): TBoldIndexDescriptionArray; +var + DbTable: IBoldTable; + I: integer; + IndexDef: TIndexDef; +begin + SetLength(result, 0); + DbTable := GetTable; + try + DbTable.Tablename := TableName; + DbTable.Open; + SetLength(Result, DbTable.IndexDefs.Count); + for I := 0 to DbTable.IndexDefs.Count - 1 do + begin + IndexDef := DbTable.IndexDefs[i]; + result[i].IndexName := IndexDef.Name; + Result[i].IndexedColumns := IndexDef.Fields; + result[i].IsPrimary := ixPrimary in IndexDef.Options; + result[i].IsUnique := ixUnique in IndexDef.Options; + end; + finally + DbTable.Close; + releaseTable(DbTable); + end; + +end; + function TBoldDatabaseWrapper.GetSQLDatabaseConfig: TBoldSQLDatabaseConfig; begin result := fSQLDataBaseConfig; end; +function TBoldDatabaseWrapper.GetWindowsLoginName: string; +var + User: PChar; + Size: DWord; +begin + Result := ''; + Size := 256; + User := StrAlloc(Size); + try + try + if WNetGetUser(PChar(0), User, Size) = 0 then begin + Result := string(User); + end else begin + RaiseLastOSError; + end; + except + if GetUserName(User, Size) then begin + Result := string(User); + end else begin + RaiseLastOSError; + end; + end; + finally + StrDispose(User); + end; +end; + + +function TBoldDatabaseWrapper.InternalGetDatabaseError(const aErrorType: + TBoldDatabaseErrorType; const E: Exception; sSQL, sServer, sDatabase, + sUserName: string; bUseWindowsAuth: Boolean): EBoldDatabaseError; +var + sMsg, + sWindowsAuth: string; +begin + case aErrorType of + bdetConnection: begin + sMsg := Format(BOLD_DATABASE_ERROR_CONNECTION, [sServer]); + Result := EBoldDatabaseConnectionError.Create(sMsg); + end; + bdetSQL: begin + sMsg := Format(BOLD_DATABASE_ERROR_SQL, [sSQL, E.Message]); + Result := EBoldDatabaseSQLError.Create(sMsg); + end; + bdetUpdate: begin + Result := EBoldDatabaseSQLError.Create(BOLD_DATABASE_ERROR_UPDATE); + end; + bdetDeadlock: begin + sMsg := Format(BOLD_DATABASE_ERROR_DEADLOCK, [E.Message]); + Result := EBoldDatabaseDeadlockError.Create(sMsg); + end; + bdetLogin: begin + if bUseWindowsAuth then begin + sWindowsAuth := BOLD_DATABASE_ERROR_LOGIN_WINDOWS_AUTH; + sUserName := GetWindowsLoginName; + end else begin + sWindowsAuth := ''; + end; + sMsg := Format(BOLD_DATABASE_ERROR_LOGIN, [sUserName, sDatabase, sServer]); + Result := EBoldDatabaseLoginError.Create(sMsg); + end; +// bdetError: begin + else begin + sMsg := Format(BOLD_DATABASE_ERROR_UNKNOWN, [E.Message]); + Result := EBoldDatabaseError.Create(sMsg); + end; + end; + result.OriginalExceptionClass := E.ClassName; + result.OriginalExceptionMessage := E.Message; +end; + procedure TBoldDatabaseWrapper.ReleaseExecQuery(var Query: IBoldExecQuery); var Query2: IBoldQuery; @@ -940,29 +1584,337 @@ function TBoldDatabaseWrapper.SupportsDefaultColumnValues: Boolean; result := true; end; -function TBoldDatabaseWrapper.TableExists( - const TableName: String): Boolean; -var - TableNames: TStringList; - i: integer; +function TBoldDatabaseWrapper.TableExists(const TableName: String): Boolean; begin - TableNames := TStringList.Create; - result := false; - AllTableNames('*', true, TableNames); - for i := 0 to Tablenames.Count-1 do + if not Assigned(fAllTableNames) then begin - if SameText(TableNames[i], TableName) then - result := true; + fAllTableNames := TStringList.Create; + fAllTableNames.Sorted := true; + AllTableNames('*', true, fAllTableNames); end; - TableNames.Free; + result := fAllTableNames.IndexOf(TableName) <> -1; end; { TBoldParameterWrapper } -constructor TBoldParameterWrapper.create(DatasetWrapper: TBoldDatasetWrapper); +constructor TBoldParameterWrapper.Create(DatasetWrapper: TBoldAbstractQueryWrapper); begin inherited create; fDatasetWrapper := DatasetWrapper; end; +{ TBoldAbstractQueryWrapper } + +procedure TBoldAbstractQueryWrapper.Clear; +begin +// to be override +end; + +constructor TBoldAbstractQueryWrapper.Create( + DatabaseWrapper: TBoldDatabaseWrapper); +begin + inherited Create; + fDatabaseWrapper := DatabaseWrapper; +end; + +function TBoldAbstractQueryWrapper.GetImplementor: TObject; +begin + result := self; +end; + +{ TBoldBatchDataSetWrapper } + +function TBoldBatchDataSetWrapper.ParamsContainBlob: Boolean; +var + i: integer; +const + BlobFieldTypes = [{$IFDEF BOLD_DELPHI15_OR_LATER}db.ftStream,{$ENDIF} db.ftBlob, db.ftGraphic..db.ftTypedBinary, db.ftOraBlob, db.ftOraClob]; +begin + result := false; + for i := 0 to self.Params.Count-1 do + if (Params[i].DataType in BlobFieldTypes) then + begin + result := true; + exit; + end; +end; + +procedure TBoldBatchDataSetWrapper.ReplaceParamMarkers(sql: TStrings; + const Source, Dest: IBoldExecQuery); +const + Literals = ['''', '"', '`']; +var + SourceParams, DestParams: TParams; + Name: String; + Prefix: String; + NewParamName: String; + CurPos, StartPos: integer; + PrevPos: integer; + i: integer; + ParamIndex, FirstParam: integer; + Line: String; + oldParam, NewParam: TParam; + Literal: Boolean; + + function NameDelimiter: Boolean; + begin + Result := CharInSet(line[CurPos], [' ', ',', ';', ')', #13, #10]); + end; + + function IsLiteral: Boolean; + begin + Result := CharInSet(line[CurPos], Literals); + end; + + function CurrentChar: Char; + begin + result := line[CurPos]; + end; + + procedure AddLine(const s: string); + begin + {$IFDEF UseSynCommons} + SB.AddString(SynCommons.StringReplaceAll(RawUTF8(s), BOLDCRLF, ' ')); + {$ELSE} + sb.Append(StringReplace(s, BOLDCRLF, ' ', [rfReplaceAll])); + {$ENDIF} + end; + +begin + SourceParams := Source.Params; + DestParams := Dest.Params; + if Source.ParamCount = 0 then + begin + for i := 0 to Sql.Count - 1 do + begin + Line := sql[i]; + AddLine(Line); + end; + end + else + begin + if Dest.ParamCount = 0 then + begin + Dest.Params.Assign(Source.Params); + for i := 0 to Sql.Count - 1 do + begin + Line := sql[i]; + AddLine(Line); + end; + end + else + begin + FirstParam := Dest.ParamCount; + ParamIndex := Dest.ParamCount; + Dest.ParamCheck := false; + for i := 0 to Sql.Count - 1 do + begin + Line := Sql[i]; + if line = '' then + continue; + CurPos := 1; + PrevPos := CurPos; + Literal := False; + repeat + while CharInSet(CurrentChar, LeadBytes) do Inc(CurPos, 2); + if (CurrentChar = ':') and not Literal and (Line[CurPos+1] <> ':') then + begin + StartPos := CurPos; + while (CurrentChar <> #0) and (Literal or not NameDelimiter) do + begin + Inc(CurPos); + if Curpos > Length(Line) then + break; + while CharInSet(CurrentChar, LeadBytes) do Inc(CurPos, 2); + if IsLiteral then + begin + Literal := not Literal; + end; + end; + Name := copy(Line, StartPos+1, CurPos-(StartPos+1)); + OldParam := SourceParams[ParamIndex-FirstParam]; + Assert(OldParam.Name = Name); + Prefix := 'P'+IntToStr(ParamIndex); + NewParamName := prefix {+ Name}; + NewParam := DestParams.CreateParam(OldParam.DataType, NewParamName, ptUnknown); + NewParam.Assign(OldParam); + NewParam.Name := NewParamName; + AddLine(Copy(Line, PrevPos, StartPos-PrevPos+1)); + PrevPos := CurPos; + {$IFDEF UseSynCommons} + SB.AddString(RawUTF8(NewParamName)); + {$ELSE} + SB.Append(NewParamName); + {$ENDIF} + inc(ParamIndex); + end + else + if IsLiteral then + Literal := not Literal; + Inc(CurPos); + until CurPos > Length(Line); + if PrevPos <= Length(Line) then + AddLine(Copy(Line, PrevPos, MaxInt)); + end; + end; + end; + {$IFDEF UseSynCommons} + SB.AddString(RawUTF8(DatabaseWrapper.SQLDatabaseConfig.BatchQuerySeparator)); + Inc(fAccumulatedSQLLength, Integer(sb.TextLength) + Length(Dest.SQLStrings.LineBreak)); + Dest.SQLStrings.Add(String(sb.text)); + sb.CancelAll; + {$ELSE} + SB.Append(DatabaseWrapper.SQLDatabaseConfig.BatchQuerySeparator); + Dest.SQLStrings.Add(sb.ToString); + Inc(fAccumulatedSQLLength, SB.Length + Length(Dest.SQLStrings.LineBreak)); + SB.Clear; + {$ENDIF} +end; + +function TBoldBatchDataSetWrapper.GetHasCachedStatements: boolean; +begin + result := fAccumulatedSQLLength > 0; +end; + +function TBoldBatchDataSetWrapper.GetSqlLength: integer; +var + i: Integer; + LB: string; +begin + result := 0; + LB := SQLStrings.LineBreak; + for I := 0 to SQLStrings.Count - 1 do + Inc(result, Length(SQLStrings[I]) + Length(LB)); +end; + +function TBoldBatchDataSetWrapper.GetAccumulatedSQL: TStrings; +begin + result := BatchQuery.SQLStrings; +end; + +function TBoldBatchDataSetWrapper.GetBatchQueryParamCount: integer; +begin + result := 0; + if Assigned(BatchQuery) then + result := BatchQuery.ParamCount; +end; + +procedure TBoldBatchDataSetWrapper.SetInBatch(const Value: Boolean); +begin + if not DatabaseWrapper.SQLDatabaseConfig.UseBatchQueries then + exit; + if FInBatch <> Value then + begin + FInBatch := Value; + if Value then + begin + fBatchQuery := DatabaseWrapper.GetExecQuery; + fBatchQuery.SQLStrings.BeginUpdate; + fBatchQuery.Params.BeginUpdate; + fParamsInBeginUpdate := true; + if Supports(fBatchQuery, IBoldParameterized) then + (fBatchQuery as IBoldParameterized).ParamCheck := false; + end + else + begin + if fParamsInBeginUpdate then + begin + fBatchQuery.SQLStrings.EndUpdate; + fBatchQuery.Params.EndUpdate; + end; + DatabaseWrapper.ReleaseExecQuery(fBatchQuery); + end; + end; +end; + +procedure TBoldBatchDataSetWrapper.StartSQLBatch; +begin + InBatch := DatabaseWrapper.SQLDatabaseConfig.UseBatchQueries; +end; + +procedure TBoldBatchDataSetWrapper.BatchExecSQL; +var + SQLDatabaseConfig: TBoldSQLDatabaseConfig; +begin + if inBatch then + begin + SQLDatabaseConfig := DatabaseWrapper.SQLDatabaseConfig; + if ParamsContainBlob + or (fAccumulatedSQLLength + GetSqlLength + + Length(SQLDatabaseConfig.BatchQueryBegin) + Length(SQLDatabaseConfig.BatchQueryEnd) + >= SQLDatabaseConfig.MaxBatchQueryLength) + or (BatchQuery.ParamCount + ParamCount >= SQLDatabaseConfig.MaxBatchQueryParams) then + ExecuteBatch; + ReplaceParamMarkers(SQLStrings, self as IBoldExecQuery, BatchQuery); + end; +end; + +constructor TBoldBatchDataSetWrapper.Create( + DatabaseWrapper: TBoldDatabaseWrapper); +begin + inherited Create(DatabaseWrapper); + {$IFDEF UseSynCommons} + SB := SynCommons.TTextWriter.CreateOwnedStream(cInitialBatchBufferSize); + {$ELSE} + SB := TStringBuilder.Create(cInitialBatchBufferSize); + {$ENDIF} +end; + +destructor TBoldBatchDataSetWrapper.Destroy; +begin + if Assigned(DatabaseWrapper) and Assigned(fBatchQuery) then + DatabaseWrapper.ReleaseExecQuery(fBatchQuery); + FreeAndNil(SB); + inherited; +end; + +procedure TBoldBatchDataSetWrapper.EndSQLBatch; +begin + if InBatch and HasCachedStatements then + ExecuteBatch; + InBatch := false; +end; + +procedure TBoldBatchDataSetWrapper.FailSQLBatch; +begin + if InBatch then + begin + AccumulatedSQL.Clear; + fAccumulatedSQLLength := 0; + end; +end; + +procedure TBoldBatchDataSetWrapper.ExecuteBatch; +begin + if HasCachedStatements then + begin + fInBatch := false; + try + if fParamsInBeginUpdate then + begin + if DatabaseWrapper.SQLDatabaseConfig.BatchQueryBegin <> '' then + fBatchQuery.SQLStrings.Insert(0, DatabaseWrapper.SQLDatabaseConfig.BatchQueryBegin); + if DatabaseWrapper.SQLDatabaseConfig.BatchQueryEnd <> '' then + fBatchQuery.SQLStrings.Append(DatabaseWrapper.SQLDatabaseConfig.BatchQueryEnd); + fBatchQuery.SQLStrings.EndUpdate; + fBatchQuery.Params.EndUpdate; + fParamsInBeginUpdate:=false; + fBatchQuery.ParamCheck := true; + end; + fBatchQuery.ExecSql; + finally + fInBatch := true; + AccumulatedSQL.Clear; + fAccumulatedSQLLength := 0; + fBatchQuery.SQLStrings.BeginUpdate; + fBatchQuery.Params.BeginUpdate; + fBatchQuery.Params.Clear; + fParamsInBeginUpdate:=true; + fBatchQuery.ParamCheck := false; + end; + end; +end; + +initialization + end. diff --git a/Source/Persistence/DB/BoldPersistenceControllerDefault.pas b/Source/Persistence/DB/BoldPersistenceControllerDefault.pas index 9f43dd1..1ef634c 100644 --- a/Source/Persistence/DB/BoldPersistenceControllerDefault.pas +++ b/Source/Persistence/DB/BoldPersistenceControllerDefault.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldPersistenceControllerDefault; interface @@ -14,7 +17,9 @@ interface BoldPersistenceController, BoldSQLDatabaseConfig, BoldTypeNameDictionary, - BoldDefs; + BoldDefs, + BoldIndexCollection, + BoldElements; type { forward declarations } @@ -28,31 +33,34 @@ TBoldPersistenceControllerDefault = class(TBoldPersistenceController) fMoldModel: TMoldModel; fTypeNameDictionary: TBoldTypeNameDictionary; fSQLDataBaseConfig: TBoldSQLDataBaseConfig; + fCustomIndexes: TBoldIndexCollection; fOnGetDatabase: TBoldGetDatabaseEvent; - procedure EnsureActive(Action: String); + procedure EnsureActive(Action: String); function GetPersistenceMapper: TBoldSystemDefaultMapper; - procedure SQLDatabaseConfigChanged(Sender: TObject); public - constructor CreateFromMold(MoldModel: TMoldModel; TypeNameDictionary: TBoldTypeNameDictionary; SQLDataBaseConfig: TBoldSQLDataBaseConfig; GetDatabaseFunc: TBoldGetDatabaseEvent); + constructor CreateFromMold(MoldModel: TMoldModel; TypeNameDictionary: TBoldTypeNameDictionary; + CustomIndexes: TBoldIndexCollection; SQLDataBaseConfig: TBoldSQLDataBaseConfig; GetDatabaseFunc: TBoldGetDatabaseEvent); destructor Destroy; override; - procedure PMExactifyIds(ObjectIdList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList); override; + procedure PMExactifyIds(ObjectIdList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList; HandleNonExisting: Boolean); override; procedure PMFetch(ObjectIdList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; MemberIdList: TBoldMemberIdList; FetchMode: integer; BoldClientID: TBoldClientID); override; procedure PMFetchIDListWithCondition(ObjectIdList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; FetchMode: Integer; Condition: TBoldCondition; BoldClientID: TBoldClientID); override; - procedure PMUpdate(ObjectIdList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; Old_Values: IBoldValueSpace; Precondition: TBoldUpdatePrecondition; TranslationList: TBoldIdTranslationList; var TimeStamp: TBoldTimeStampType; BoldClientID: TBoldClientID); override; + procedure PMUpdate(ObjectIdList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; Old_Values: IBoldValueSpace; Precondition: TBoldUpdatePrecondition; TranslationList: TBoldIdTranslationList; var TimeStamp: TBoldTimeStampType; var TimeOfLatestUpdate: TDateTime; BoldClientID: TBoldClientID); override; procedure OpenDatabase(ReadMappingFromDb: Boolean); procedure CloseDataBase; procedure PMTranslateToGlobalIds(ObjectIdList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList); override; procedure PMTranslateToLocalIds(GlobalIdList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList); override; - procedure PMSetReadOnlyness(ReadOnlyList, WriteableList: TBoldObjectIdList); override; + procedure PMSetReadonlyness(ReadOnlyList, WriteableList: TBoldObjectIdList); override; procedure SubscribeToPeristenceEvents(Subscriber: TBoldSubscriber); override; procedure ReserveNewIds(ValueSpace: IBoldValueSpace; ObjectIdList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList); override; property PersistenceMapper: TBoldSystemDefaultMapper read GetPersistenceMapper; procedure PMTimestampForTime(ClockTime: TDateTime; var Timestamp: TBoldTimestampType); override; procedure PMTimeForTimestamp(Timestamp: TBoldTimestampType; var ClockTime: TDateTime); override; - procedure StartTransaction; - procedure CommitTransaction; - procedure RollbackTransaction; + procedure StartTransaction; override; + procedure CommitTransaction; override; + procedure RollbackTransaction; override; + function DatabaseInterface: IBoldDatabase; override; function InTransaction: Boolean; + function CanEvaluateInPS(sOCL: string; aSystem: TBoldElement; aContext: TBoldElementTypeInfo = nil; const aVariableList: TBoldExternalVariableList = nil): Boolean; override; property Active: Boolean read fActive; property SQLDataBaseConfig: TBoldSQLDataBaseConfig read fSQLDataBaseConfig; end; @@ -61,37 +69,40 @@ implementation uses SysUtils, + BoldUtils, BoldPMappers, BoldGuard, + BoldPMapperLists, //PATCH BoldPMappersSQL, - PersistenceConsts, - BoldPMappersAttributeDefault, // Not used, just to pull them in - BoldPMappersLinkDefault; // Not used, just to pull them in + BoldPMappersAttributeDefault, + BoldPMappersLinkDefault; {---TBoldPersistenceControllerDefault---} -constructor TBoldPersistenceControllerDefault.CreateFromMold(MoldModel: TMoldModel; TypeNameDictionary: TBoldTypeNameDictionary; SQLDataBaseConfig: TBoldSQLDataBaseConfig; GetDatabaseFunc: TBoldGetDatabaseEvent); +constructor TBoldPersistenceControllerDefault.CreateFromMold(MoldModel: TMoldModel; TypeNameDictionary: TBoldTypeNameDictionary; + CustomIndexes: TBoldIndexCollection; SQLDataBaseConfig: TBoldSQLDataBaseConfig; GetDatabaseFunc: TBoldGetDatabaseEvent); begin + inherited Create; fMoldModel := MoldModel; fTypeNameDictionary := TypeNameDictionary; fActive := false; - fSQLDataBaseConfig := TBoldSQLDataBaseConfig.Create; - fSQLDataBaseConfig.AssignConfig(SQLDataBaseConfig); - fSQLDataBaseConfig.OnChange := SQLDataBaseConfigChanged; + fSQLDataBaseConfig := SQLDataBaseConfig; + fCustomIndexes := TBoldIndexCollection.Create(nil); + fCustomIndexes.Assign(CustomIndexes); fOnGetDatabase := GetDatabaseFunc; end; -procedure TBoldPersistenceControllerDefault.PMExactifyIds(ObjectIdList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList); +procedure TBoldPersistenceControllerDefault.PMExactifyIds(ObjectIdList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList; HandleNonExisting: Boolean); begin - EnsureActive('PMExactifyIDs'); // do not localize - PersistenceMapper.RootClassObjectPersistenceMapper.EnsureIDsExact(ObjectIdlist, TranslationList); + EnsureActive('PMExactifyIDs'); + PersistenceMapper.RootClassObjectPersistenceMapper.EnsureIDsExact(ObjectIdlist, TranslationList, HandleNonExisting); end; -procedure TBoldPersistenceControllerDefault.PMUpdate(ObjectIdList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; Old_Values: IBoldValueSpace; Precondition: TBoldUpdatePrecondition; TranslationList: TBoldIdTranslationList; var TimeStamp: TBoldTimeStampType; BoldClientID: TBoldClientID); +procedure TBoldPersistenceControllerDefault.PMUpdate(ObjectIdList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; Old_Values: IBoldValueSpace; Precondition: TBoldUpdatePrecondition; TranslationList: TBoldIdTranslationList; var TimeStamp: TBoldTimeStampType; var TimeOfLatestUpdate: TDateTime; BoldClientID: TBoldClientID); var aTranslationList: TBoldIdTranslationList; NewTimeStamp: TBoldTimeStampType; begin - EnsureActive('PMUpdate'); // do not localize + EnsureActive('PMUpdate'); SendExtendedEvent(bpeStartUpdate, [ObjectIdList, valueSpace]); if assigned(TranslationList) then aTranslationList := TranslationList @@ -99,7 +110,7 @@ procedure TBoldPersistenceControllerDefault.PMUpdate(ObjectIdList: TBoldObjectId aTranslationList := TBoldIdTranslationList.Create; try - PersistenceMapper.PMUpdate(ObjectIdList, ValueSpace, Old_Values, Precondition, aTranslationList, NewTimeStamp); + PersistenceMapper.PMUpdate(ObjectIdList, ValueSpace, Old_Values, Precondition, aTranslationList, NewTimeStamp, TimeOfLatestUpdate); if not assigned(Precondition) or not Precondition.failed then begin TimeStamp := NewTimeStamp; @@ -112,39 +123,53 @@ procedure TBoldPersistenceControllerDefault.PMUpdate(ObjectIdList: TBoldObjectId end; end; -procedure TBoldPersistenceControllerDefault.PMFetch(ObjectIDList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; MemberIdList: TBoldMemberIdList; FetchMode: Integer; BoldClientID: TBoldClientID); +procedure TBoldPersistenceControllerDefault.PMFetch(ObjectIDList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; MemberIdList: TBoldMemberIdList; FetchMode: Integer; BoldClientID: TBoldClientID); var TranslationList: TBoldIdTranslationList; ExactifyTranslationList: TBoldIdTranslationList; DefaultMemberList: TBoldMemberPersistenceMapperList; FetchIdList: TBoldObjectIdList; WasInTransaction: Boolean; + NeedsExacitfy: boolean; + Guard: IBoldGuard; begin - EnsureActive('PMFetch'); // do not localize + Guard := TBoldguard.Create(TranslationLIst, ExactifyTranslationLIst, DefaultMemberList, FetchIdList); + EnsureActive('PMFetch'); SendExtendedEvent(bpeStartFetch, [ObjectIdList, MemberIdList]); - - TranslationList := TBoldIdTranslationList.Create; - ExactifyTranslationList := TBoldIdTranslationList.Create; - DefaultMemberList := TBoldMemberPersistenceMapperList.Create; - DefaultMemberList.OwnsEntries := false; - FetchIdList := ObjectIdList.Clone; - try WasInTransaction := PersistenceMapper.Database.InTransaction; - PMExactifyIDs(FetchIdList, ExactifyTranslationList); - ValueSpace.ExactifyIDs(ExactifyTranslationList); - ObjectIdList.ExactifyIds(ExactifyTranslationList); - FetchIdList.ExactifyIds(ExactifyTranslationList); - PersistenceMapper.PMFetch(FetchIDList, ValueSpace, MemberIdList, FetchMode, TranslationList); + NeedsExacitfy := ObjectIdList.HasInexactIds; + DefaultMemberList := TBoldMemberPersistenceMapperList.Create; + DefaultMemberList.OwnsEntries := false; + TranslationList := TBoldIdTranslationList.Create; + if NeedsExacitfy then + begin + ExactifyTranslationList := TBoldIdTranslationList.Create; + FetchIdList := ObjectIdList.Clone; + PMExactifyIDs(FetchIdList, ExactifyTranslationList, false); + ValueSpace.ExactifyIDs(ExactifyTranslationList); + ObjectIdList.ExactifyIds(ExactifyTranslationList); + FetchIdList.ExactifyIds(ExactifyTranslationList); + if FetchIdList.HasNonExistingIds then + FetchIdList.RemoveNonExistingIds; + PersistenceMapper.PMFetch(FetchIDList, ValueSpace, MemberIdList, FetchMode, TranslationList) + end + else + begin + if ObjectIdList.HasNonExistingIds then + begin + FetchIdList := ObjectIdList.Clone; + FetchIdList.RemoveNonExistingIds; + PersistenceMapper.PMFetch(FetchIdList, ValueSpace, MemberIdList, FetchMode, TranslationList); + end + else + PersistenceMapper.PMFetch(ObjectIdList, ValueSpace, MemberIdList, FetchMode, TranslationList); + end; ValueSpace.ApplyTranslationList(TranslationList); if not WasInTransaction and PersistenceMapper.Database.InTransaction then PersistenceMapper.Database.Commit; finally - TranslationLIst.Free; - ExactifyTranslationLIst.Free; - DefaultMemberList.Free; - FetchIdList.Free; - SendEvent(bpeEndFetch); + SendExtendedEvent(bpeEndFetch, [ObjectIdList, MemberIdList]); end; end; @@ -155,15 +180,18 @@ procedure TBoldPersistenceControllerDefault.PMFetchIDListWithCondition(ObjectIDL WasInTransaction: Boolean; begin Guard := TBoldguard.Create(TranslationList); - EnsureActive('PMFetchIdListWithCondition'); // do not localize + EnsureActive('PMFetchIdListWithCondition'); SendExtendedEvent(bpeStartFetchId, [Condition]); - TranslationList := TBoldIdTranslationList.Create; - WasInTransaction := PersistenceMapper.Database.InTransaction; - PersistenceMapper.PMFetchClassWithCondition(ObjectIdList, ValueSpace, Condition, FetchMode, TranslationList); - ValueSpace.ApplyTranslationList(TranslationList); - if not WasInTransaction and PersistenceMapper.Database.InTransaction then - PersistenceMapper.Database.Commit; - SendEvent(bpeEndFetchId); + try + TranslationList := TBoldIdTranslationList.Create; + WasInTransaction := PersistenceMapper.Database.InTransaction; + PersistenceMapper.PMFetchClassWithCondition(ObjectIdList, ValueSpace, Condition, FetchMode, TranslationList); + ValueSpace.ApplyTranslationList(TranslationList); + if not WasInTransaction and PersistenceMapper.Database.InTransaction then + PersistenceMapper.Database.Commit; + finally + SendExtendedEvent(bpeEndFetchId, [ObjectIdList]); + end; end; procedure TBoldPersistenceControllerDefault.OpenDatabase(ReadMappingFromDb: Boolean); @@ -177,6 +205,13 @@ procedure TBoldPersistenceControllerDefault.OpenDatabase(ReadMappingFromDb: Bool fActive := true; end; +function TBoldPersistenceControllerDefault.CanEvaluateInPS(sOCL: string; + aSystem: TBoldElement; aContext: TBoldElementTypeInfo; + const aVariableList: TBoldExternalVariableList): Boolean; +begin + Result := PersistenceMapper.CanEvaluateInPS(sOCL, aSystem, aContext, aVariableList); +end; + procedure TBoldPersistenceControllerDefault.CloseDataBase; begin PersistenceMapper.CloseDatabase; @@ -186,7 +221,7 @@ procedure TBoldPersistenceControllerDefault.CloseDataBase; destructor TBoldPersistenceControllerDefault.Destroy; begin FreeAndNil(fPersistenceMapper); - FreeAndNil(fSQLDataBaseConfig); + FreeAndNil(fCustomIndexes); inherited; end; @@ -194,7 +229,7 @@ procedure TBoldPersistenceControllerDefault.PMTranslateToGlobalIds( ObjectIdList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList); begin - EnsureActive('PMTranslateToGlobalIds'); // do not localize + EnsureActive('PMTranslateToGlobalIds'); PersistenceMapper.PMTranslateToGlobalIds(ObjectIdList, TranslationList); end; @@ -202,14 +237,14 @@ procedure TBoldPersistenceControllerDefault.PMTranslateToLocalIds( GlobalIdList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList); begin - EnsureActive('PMTranslateToLocalIds'); // do not localize + EnsureActive('PMTranslateToLocalIds'); PersistenceMapper.PMTranslateToLocalIds(GlobalIdList, TranslationList); end; procedure TBoldPersistenceControllerDefault.PMSetReadonlyness(ReadOnlyList, WriteableList: TBoldObjectIdList); begin - EnsureActive('PMSetReadonlyness'); // do not localize + EnsureActive('PMSetReadonlyness'); PersistenceMapper.PMSetReadonlyness(ReadOnlyList, WriteableList); end; @@ -223,44 +258,65 @@ procedure TBoldPersistenceControllerDefault.SubscribeToPeristenceEvents( procedure TBoldPersistenceControllerDefault.ReserveNewIds(ValueSpace: IBoldValueSpace; ObjectIdList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList); begin - EnsureActive('ReserveNewIds'); // do not localize + EnsureActive('ReserveNewIds'); PersistenceMapper.ReserveNewIds(ValueSpace, ObjectIdList, TranslationList); end; procedure TBoldPersistenceControllerDefault.PMTimeForTimestamp( Timestamp: TBoldTimestampType; var ClockTime: TDateTime); begin - EnsureActive('PMTimeForTimeStamp'); // do not localize + EnsureActive('PMTimeForTimeStamp'); PersistenceMapper.PMTimeForTimestamp(Timestamp, ClockTime); end; procedure TBoldPersistenceControllerDefault.PMTimestampForTime( ClockTime: TDateTime; var Timestamp: TBoldTimestampType); begin - EnsureActive('PMTimestampForTime'); // do not localize + EnsureActive('PMTimestampForTime'); PersistenceMapper.PMTimestampForTime(ClockTime, Timestamp); end; procedure TBoldPersistenceControllerDefault.EnsureActive(Action: String); begin if not fActive then - raise EBold.CreateFmt(sNotActive, [ClassName, Action]); + raise EBold.CreateFmt('%s.%s: Not Active', [ClassName, Action]); +end; + +function TBoldPersistenceControllerDefault.DatabaseInterface: IBoldDatabase; +begin + if Assigned(PersistenceMapper) then + result := PersistenceMapper.Database + else + result := nil; end; function TBoldPersistenceControllerDefault.GetPersistenceMapper: TBoldSystemDefaultMapper; +type + TTBoldSystemDefaultMapperClass = class of TBoldSystemDefaultMapper; +var + SystemMapperDescriptor: TBoldSystemPersistenceMapperDescriptor; + SystemPMapperName: string; + SysPMapperClass: TTBoldSystemDefaultMapperClass; begin if not assigned(fPersistenceMapper) then - fPersistenceMapper := TBoldSystemDefaultMapper.CreateFromMold(fMoldModel, fTypeNameDictionary, SQLDataBaseConfig, fOnGetDatabase); + begin + SystemPMapperName := fMoldModel.PMapperName; + if BoldNamesEqual(SystemPMapperName, DEFAULTNAME) and (SQLDataBaseConfig.DefaultSystemMapper <> '') then + SystemPMapperName := SQLDataBaseConfig.DefaultSystemMapper; + + SystemMapperDescriptor := BoldSystemPersistenceMappers.DescriptorByName[SystemPMapperName]; //PATCH + if not assigned(SystemMapperDescriptor) then //PATCH + raise EBold.CreateFmt('Unable to find SystemPersistenceMapper (%s)', [SystemPMapperName]); //PATCH + + SysPMapperClass := TTBoldSystemDefaultMapperClass(SystemMapperDescriptor.SystemPersistenceMapperClass); //PATCH - This ugly code is needed to call the correct static constructor!!! + + fPersistenceMapper := SysPMapperClass.CreateFromMold(fMoldModel, fTypeNameDictionary, fCustomIndexes,SQLDataBaseConfig, fOnGetDatabase); //PATCH +// fPersistenceMapper := TBoldSystemDefaultMapper.CreateFromMold(fMoldModel, fTypeNameDictionary, SQLDataBaseConfig, fOnGetDatabase); //PATCH - Original is Hardcoded! + end; result := fPersistenceMapper; end; -procedure TBoldPersistenceControllerDefault.SQLDatabaseConfigChanged(Sender: TObject); -begin - if assigned(fPersistencemapper) then - PersistenceMapper.SQLDataBaseConfig.AssignConfig(SQLDataBaseConfig); -end; - procedure TBoldPersistenceControllerDefault.CommitTransaction; begin PersistenceMapper.Database.Commit; @@ -281,4 +337,8 @@ function TBoldPersistenceControllerDefault.InTransaction: Boolean; Result := PersistenceMapper.Database.InTransaction; end; +initialization + + + end. diff --git a/Source/Persistence/DB/BoldPersistenceHandleDB.pas b/Source/Persistence/DB/BoldPersistenceHandleDB.pas index 35eb88e..ce97e2a 100644 --- a/Source/Persistence/DB/BoldPersistenceHandleDB.pas +++ b/Source/Persistence/DB/BoldPersistenceHandleDB.pas @@ -1,17 +1,19 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldPersistenceHandleDB; interface - uses Classes, BoldSubscription, BoldDbInterfaces, BoldAbstractPersistenceHandleDB, BoldSQLDatabaseConfig, + BoldIndexCollection, BoldAbstractDataBaseAdapter; type - { TBoldPersistenceHandleDB } TBoldPersistenceHandleDB = class(TBoldAbstractPersistenceHandleDB) private fDatabaseAdapter: TBoldAbstractDatabaseAdapter; @@ -21,6 +23,7 @@ TBoldPersistenceHandleDB = class(TBoldAbstractPersistenceHandleDB) procedure PlaceComponentSubscriptions; protected function GetSQLDatabaseConfig: TBoldSQLDatabaseConfig; override; + function GetCustomIndexes: TBoldIndexCollection; override; function GetDataBaseInterface: IBoldDatabase; override; procedure SetActive(Value: Boolean); override; procedure AssertSQLDatabaseconfig(Context: String); override; @@ -28,8 +31,8 @@ TBoldPersistenceHandleDB = class(TBoldAbstractPersistenceHandleDB) function GetNewComponentName(Comp: Tcomponent; BaseName: string): String; {$ENDIF} public - constructor Create(aOwner: TComponent); override; - destructor Destroy; override; + constructor create(aOwner: TComponent); override; + destructor destroy; override; published property DatabaseAdapter: TBoldAbstractDatabaseAdapter read fDatabaseAdapter write SetDatabaseAdapter; end; @@ -39,7 +42,7 @@ implementation uses BoldDefs, SysUtils, - PersistenceConsts; + BoldRev; const breDatabaseAdapterDestroying = 100; @@ -56,14 +59,22 @@ constructor TBoldPersistenceHandleDB.create(aOwner: Tcomponent); destructor TBoldPersistenceHandleDB.destroy; begin FreeAndNil(fComponentSubscriber); - inherited; + inherited; end; procedure TBoldPersistenceHandleDB.AssertSQLDatabaseconfig( Context: String); begin if not assigned(DatabaseAdapter) then - raise EBold.CreateFmt(sNoDatabaseAdapterAvailable, [classname, Context]); + raise EBold.CreateFmt('%s: Unable to %s. There is no DatabaseAdapter available', [classname, Context]); +end; + +function TBoldPersistenceHandleDB.GetCustomIndexes: TBoldIndexCollection; +begin + if assigned(fDatabaseAdapter) then + result := fDatabaseAdapter.CustomIndexes + else + result := nil; end; function TBoldPersistenceHandleDB.GetDataBaseInterface: IBoldDatabase; @@ -106,7 +117,7 @@ procedure TBoldPersistenceHandleDB.PlaceComponentSubscriptions; procedure TBoldPersistenceHandleDB.SetActive(Value: Boolean); begin if value and not assigned(DatabaseAdapter) then - raise EBold.CreateFmt(sCannotActivateWithoutDBAdapter, [classname]); + raise EBold.CreateFmt('%s.SetActive: Can not set persistence handle to active since it is not connected to a database adapter', [classname]); inherited; end; @@ -129,7 +140,6 @@ procedure TBoldPersistenceHandleDB._ReceiveComponentEvents( begin if active and not (csDestroying in ComponentState) then begin - // what to do? end; fDatabaseAdapter := nil; end; @@ -137,10 +147,10 @@ procedure TBoldPersistenceHandleDB._ReceiveComponentEvents( begin if active and not (csDestroying in ComponentState) then begin - // what to do? end; end; end; end; +initialization end. diff --git a/Source/Persistence/DB/BoldPersistenceHandleDB_deprecated.pas b/Source/Persistence/DB/BoldPersistenceHandleDB_deprecated.pas index 93ababf..194b8b5 100644 --- a/Source/Persistence/DB/BoldPersistenceHandleDB_deprecated.pas +++ b/Source/Persistence/DB/BoldPersistenceHandleDB_deprecated.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldPersistenceHandleDB_deprecated; interface @@ -8,7 +11,7 @@ interface Controls, BoldPersistenceHandleDb, BoldSQLDatabaseConfig, - BoldAbstractPersistenceHandleDB; + BoldAbstractPersistenceHandleDB, BoldIndexCollection; type @@ -21,6 +24,7 @@ TBoldDBPersistenceHandle = class(TBoldAbstractPersistenceHandleDB) fUserName: String; fPassword: String; fSQLDataBaseConfig: TBoldSQLDataBaseConfig; + fCustomIndexes: TBoldIndexCollection; fDatabaseEngine: TBoldDataBaseEngine; procedure SQLDatabaseConfigChanged(Sender: TObject); procedure SetSQLDataBaseConfig(const Value: TBoldSQLDataBaseConfig); @@ -32,18 +36,19 @@ TBoldDBPersistenceHandle = class(TBoldAbstractPersistenceHandleDB) procedure SetDataBaseEngine(const Value: TBoldDataBaseEngine); virtual; procedure SetPassword(const Value: string); virtual; procedure SetUserName(const Value: string); virtual; - function GetSQLDatabaseConfig: TBoldSQLDataBaseConfig; override; - {$IFDEF T2H} // properties is removed, but should still be in doc - property EmptyStringMarker; // String - property SystemTablesPrefix; // String + function GetSQLDataBaseConfig: TBoldSQLDataBaseConfig; override; + function GetCustomIndexes: TBoldIndexCollection; override; + {$IFDEF T2H} + property EmptyStringMarker; + property SystemTablesPrefix; {$ELSE} procedure InternalTransferproperties(const target: TBoldPersistenceHandleDB); virtual; function GetNewComponentName(Comp: Tcomponent; BaseName: string): String; {$ENDIF} procedure DefineProperties(Filer: TFiler); override; public - constructor Create(Owner: TComponent); override; - destructor Destroy; override; + constructor create(Owner: TComponent); override; + destructor destroy; override; published property Username: string read fusername write SetUserName; property Password: string read fPassword write SetPassword; @@ -118,7 +123,6 @@ function TBoldDBPersistenceHandle.GetSQLDataBaseConfig: TBoldSQLDataBaseConfig; procedure TBoldDBPersistenceHandle.DefineProperties(Filer: TFiler); begin inherited DefineProperties(Filer); - // EmptyStringMarker and SystemtablePrefix moved to SQLDatabaseConfig in v 4.0 Filer.DefineProperty('EmptyStringMarker', ReadEmptyStringMarker, nil, True); Filer.DefineProperty('SystemTablesPrefix', ReadSystemTablePrefix, nil, True); end; @@ -158,7 +162,15 @@ procedure TBoldDBPersistenceHandle.TransferPropertiesToNewPersistenceHandle( procedure TBoldDBPersistenceHandle.InternalTransferproperties(const target: TBoldPersistenceHandleDB); begin - // do nothing +end; + +function TBoldDBPersistenceHandle.GetCustomIndexes: TBoldIndexCollection; +begin + if not assigned(fCustomIndexes) then + begin + fCustomIndexes := TBoldIndexCollection.Create(self); + end; + result := fCustomIndexes; end; function TBoldDBPersistenceHandle.GetNewComponentName(Comp: Tcomponent; @@ -172,4 +184,6 @@ function TBoldDBPersistenceHandle.GetNewComponentName(Comp: Tcomponent; result := BaseName + inttostr(i); end; +initialization + end. diff --git a/Source/Persistence/DB/BoldPersistenceHandleDBreg.pas b/Source/Persistence/DB/BoldPersistenceHandleDBreg.pas index 63a297c..14dc3d3 100644 --- a/Source/Persistence/DB/BoldPersistenceHandleDBreg.pas +++ b/Source/Persistence/DB/BoldPersistenceHandleDBreg.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldPersistenceHandleDBreg; interface @@ -6,8 +9,6 @@ procedure Register; implementation -{.$R BoldPersistenceHandleDB.res} - uses Classes, Dialogs, @@ -15,11 +16,14 @@ implementation BoldDbActions, DesignEditors, DesignIntf, - actnlist, +{$IFDEF BOLD_DELPHI17_OR_LATER} + Actions, +{$ELSE} + ActnList, +{$ENDIF} SysUtils, BoldPersistenceHandleDB, - BoldIDEConsts, - BoldPMConsts; + BoldIDEConsts; type { TBoldPersistenceHandleDBEditor } @@ -36,8 +40,8 @@ TBoldPersistenceHandleDBEditor = class(TComponentEditor) procedure Register; begin RegisterComponents(BOLDPAGENAME_PERSISTENCE, [TBoldPersistenceHandleDB]); -// RegisterActions(BOLDACTIONGROUPNAME, -// [TBoldGenerateSchemaAction], nil); + RegisterActions(BOLDACTIONGROUPNAME, + [TBoldGenerateSchemaAction], nil); RegisterComponentEditor(TBoldPersistenceHandleDB, TBoldPersistenceHandleDBEditor); end; @@ -56,11 +60,11 @@ procedure TBoldPersistenceHandleDBEditor.GenerateSchema; begin try TBoldPersistenceHandleDB(Component).CreateDataBaseSchema; - showmessage(sSchemaGenerated); + showmessage('Database schema generated'); except on e: Exception do begin - Showmessage(Format(sSchemaGenerationFailed, [BOLDCRLF, BOLDCRLF, e.message])); + Showmessage('Database schema generation failed: '+BOLDCRLF+BOLDCRLF+e.message); end; end; end; @@ -69,7 +73,7 @@ procedure TBoldPersistenceHandleDBEditor.GenerateSchema; function TBoldPersistenceHandleDBEditor.GetVerb(Index: Integer): string; begin case Index of - 0: Result := sGenerateSchema; + 0: Result := 'Generate Database Schema...'; end; end; diff --git a/Source/Persistence/DBExpress/BoldDBXInterfaces.pas b/Source/Persistence/DBExpress/BoldDBXInterfaces.pas index 2afe59c..e0bdc43 100644 --- a/Source/Persistence/DBExpress/BoldDBXInterfaces.pas +++ b/Source/Persistence/DBExpress/BoldDBXInterfaces.pas @@ -1,3 +1,5 @@ +{ Global compiler directives } +{$include bold.inc} unit BoldDBXInterfaces; interface @@ -6,7 +8,7 @@ interface Classes, Db, SQlExpr, - DBXpress, + DBXCommon, BoldSQLDataBaseConfig, BoldDBInterfaces; @@ -17,7 +19,6 @@ TBoldDBXQuery = class; TBoldDBXTable = class; TBoldDBXQueryClass = class of TBoldDBXQuery; - { TBoldDBXParameter } TBoldDBXParameter = class(TBoldDbParameter) protected @@ -29,29 +30,43 @@ TBoldDBXParameter = class(TBoldDbParameter) TBoldDBXQuery = class(TBoldDataSetWrapper, IBoldQuery, IBoldExecQuery, IBoldParameterized) private fQuery: TSQLQuery; + fSQLStrings: TStringList; + fReadTransactionStarted: Boolean; + fUseReadTransactions: boolean; procedure AssignParams(SourceParams: TParams); + function GetParams: TParams; function GetParamCount: integer; - function GetParams(i: integer): IBoldParameter; + function GetParam(i: integer): IBoldParameter; function GetRequestLiveQuery: Boolean; function ParamByName(const Value: string): IBoldParameter; procedure SetRequestLiveQuery(NewValue: Boolean); function GetSQLText: String; procedure ClearParams; procedure AssignSQL(SQL: TStrings); - procedure AssignSQLText(SQL: String); + procedure AssignSQLText(const SQL: String); + function GetParamCheck: Boolean; + procedure SetParamCheck(value: Boolean); function GetRowsAffected: integer; function GetRecordCount: integer; - function Createparam(FldType: TFieldType; const ParamName: string; ParamType: TParamType; Size: integer): IBoldParameter; + function Createparam(FldType: TFieldType; const ParamName: string; ParamType: TParamType; Size: integer): IBoldParameter; override; + function GetUseReadTransactions: boolean; + procedure SetUseReadTransactions(value: boolean); + procedure BeginExecuteQuery; + procedure EndExecuteQuery; + function GetBatchQueryParamCount: integer; protected function GetDataSet: TDataSet; override; + function GetSQLStrings: TStrings; procedure StartSQLBatch; virtual; procedure EndSQLBatch; virtual; procedure FailSQLBatch; virtual; procedure ExecSQL; virtual; property Query: TSQLQuery read fQuery; procedure Open; override; + procedure Close; override; public constructor Create(Query: TSQLQuery; DatabaseWrapper: TBoldDatabaseWrapper); virtual; + destructor Destroy; override; end; { TBoldDBXTable } @@ -63,7 +78,7 @@ TBoldDBXTable = class(TBoldDataSetWrapper, IBoldTable) procedure DeleteTable; function GetTable: TSQLTable; function GetIndexDefs: TIndexDefs; - procedure SetTableName(NewName: String); + procedure SetTableName(const NewName: String); function GetTableName: String; procedure SetExclusive(NewValue: Boolean); function GetExclusive: Boolean; @@ -79,9 +94,10 @@ TBoldDBXTable = class(TBoldDataSetWrapper, IBoldTable) TBoldDBXDataBase = class(TBoldDatabaseWrapper, IBoldDataBase) private fDataBase: TSQLConnection; + fTransaction: TDBXTransaction; fCachedTable: TSQLTable; fCachedQuery: TSQLQuery; - fTransactionDesc: TTransactionDesc; + fExecuteQueryCount: integer; function GetConnected: Boolean; function GetInTransaction: Boolean; function GetIsSQLBased: Boolean; @@ -90,21 +106,26 @@ TBoldDBXDataBase = class(TBoldDatabaseWrapper, IBoldDataBase) procedure SetKeepConnection(NewValue: Boolean); function GetKeepConnection: Boolean; procedure StartTransaction; + procedure StartReadTransaction; procedure Commit; procedure RollBack; procedure Open; procedure Close; - function GetTable: IBoldTable; - procedure ReleaseTable(var Table: IBoldTable); + procedure Reconnect; function SupportsTableCreation: Boolean; procedure ReleaseCachedObjects; + function GetIsExecutingQuery: Boolean; + procedure BeginExecuteQuery; + procedure EndExecuteQuery; protected procedure AllTableNames(Pattern: String; ShowSystemTables: Boolean; TableNameList: TStrings); override; function GetQuery: IBoldQuery; override; procedure ReleaseQuery(var Query: IBoldQuery); override; + function GetTable: IBoldTable; override; + procedure ReleaseTable(var Table: IBoldTable); override; public constructor create(DataBase: TSQLConnection; SQLDataBaseConfig: TBoldSQLDataBaseConfig); - destructor Destroy; override; + destructor destroy; override; end; var @@ -119,17 +140,28 @@ implementation SqlTimSt, BoldDefs, SysUtils, - BoldUtils, - BoldCoreConsts; + BoldUtils; { TBoldDBXQuery } procedure TBoldDBXQuery.AssignParams(Sourceparams: tparams); +var + i: integer; begin if assigned(Sourceparams) then Query.Params.Assign(SourceParams) else Query.Params.Clear; + for i := 0 to Query.Params.Count - 1 do + if Query.Params[i].DataType = ftDateTime then + Query.Params[i].DataType := ftDate; // Patch since DBX does not support datetime in this version. + + +end; + +function TBoldDBXQuery.GetParamCheck: Boolean; +begin + Result := Query.ParamCheck; end; function TBoldDBXQuery.GetParamCount: integer; @@ -137,14 +169,18 @@ function TBoldDBXQuery.GetParamCount: integer; result := Query.params.count; end; -function TBoldDBXQuery.GetParams(I: integer): IBoldParameter; +function TBoldDBXQuery.GetParams: TParams; +begin + result := Query.Params; +end; + +function TBoldDBXQuery.GetParam(I: integer): IBoldParameter; begin result := TBoldDBXParameter.Create(Query.Params[i], self); end; function TBoldDBXQuery.GetREquestLiveQuery: Boolean; begin - // FIXME result := Query.RequestLive; result := false; end; @@ -159,10 +195,24 @@ function TBoldDBXQuery.ParamByName(const Value: string): IBoldParameter; result := nil; end; +procedure TBoldDBXQuery.SetParamCheck(value: Boolean); +begin + Query.ParamCheck := Value; +end; + procedure TBoldDBXQuery.SetRequestLiveQuery(NewValue: Boolean); begin - // FIXME -// Query.RequestLive := NewValue; + +end; + +procedure TBoldDBXQuery.SetUseReadTransactions(value: boolean); +begin + fUseReadTransactions := value; +end; + +function TBoldDBXQuery.GetBatchQueryParamCount: integer; +begin + result := 0; end; function TBoldDBXQuery.GetDataSet: TDataSet; @@ -171,52 +221,136 @@ function TBoldDBXQuery.GetDataSet: TDataSet; end; procedure TBoldDBXQuery.ExecSQL; +var + Retries: Integer; + Done: Boolean; begin - BoldLogSQL(Query.SQL); + BeginExecuteQuery; try - Query.ExecSQL; - except - on e: Exception do - begin - e.Message := e.Message + BOLDCRLF + 'SQL: ' + Query.SQL.text; // do not localize - raise; + +{$IFDEF BOLD_DELPHI10_OR_LATER} + {$IFDEF BOLD_UNICODE} + BoldLogSQL(Query.SQL); + {$ELSE} + BoldLogSQLWide(Query.SQL, self); + {$ENDIF} +{$ELSE} + BoldLogSQL(Query.SQL); +{$ENDIF} + + Retries := 0; + Done := false; + while not Done do + begin + try + if Query.SQLConnection.InTransaction then + fReadTransactionStarted := false + else + begin + (DatabaseWrapper as TBoldDBXDataBase).StartReadTransaction; + fReadTransactionStarted := true; + end; + + Query.ExecSQL; + if fReadTransactionStarted and (DatabaseWrapper as TBoldDBXDataBase).GetInTransaction then + begin + (DatabaseWrapper as TBoldDBXDataBase).Commit; + fReadTransactionStarted := false; + end; + Done := true; + except + on e: Exception do + begin + e.Message := e.Message + BOLDCRLF + 'SQL: ' + Query.SQL.text; + if (not fReadTransactionStarted) or (Retries > 4) then + raise; + if (DatabaseWrapper as TBoldDBXDataBase).GetInTransaction then + (DatabaseWrapper as TBoldDBXDataBase).Rollback; + fReadTransactionStarted := false; + INC(Retries); + sleep(Retries*200); + end; + end; - end + end; + finally + EndExecuteQuery; + end; end; constructor TBoldDBXQuery.Create(Query: TSQLQuery; DatabaseWrapper: TBoldDatabaseWrapper); begin inherited Create(DatabaseWrapper); fQuery := Query; + SetParamCheck(true); + fUseReadTransactions := true; + fSQLStrings := TStringList.Create; +end; + +procedure TBoldDBXQuery.BeginExecuteQuery; +begin + (DatabaseWrapper as TBoldDBXDataBase).BeginExecuteQuery; +end; + +procedure TBoldDBXQuery.EndExecuteQuery; +begin + (DatabaseWrapper as TBoldDBXDataBase).EndExecuteQuery; end; procedure TBoldDBXQuery.EndSQLBatch; begin - // intentionally left blank end; procedure TBoldDBXQuery.StartSQLBatch; begin - // intentionally left blank end; procedure TBoldDBXQuery.FailSQLBatch; begin - // intentionally left blank end; procedure TBoldDBXQuery.Open; +var + Retries: Integer; + Done: Boolean; begin +{$IFDEF BOLD_DELPHI10_OR_LATER} + {$IFDEF BOLD_UNICODE} BoldLogSQL(Query.SQL); - try - inherited; - except - on e: Exception do - begin - e.Message := e.Message + BOLDCRLF + 'SQL: ' + Query.SQL.text; // do not localize - raise; + {$ELSE} + BoldLogSQLWide(Query.SQL, self); + {$ENDIF} +{$ELSE} + BoldLogSQL(Query.SQL); +{$ENDIF} + Retries := 0; + Done := false; + while not Done do + begin + try + if (DatabaseWrapper as TBoldDBXDataBase).GetInTransaction then + fReadTransactionStarted := false + else + begin + (DatabaseWrapper as TBoldDBXDataBase).StartReadTransaction; + fReadTransactionStarted := true; + end; + inherited; + Done := true; + except + on e: Exception do + begin + e.Message := e.Message + BOLDCRLF + 'SQL: ' + Query.SQL.text; + if (not fReadTransactionStarted) or (Retries > 4) then + raise; + if (DatabaseWrapper as TBoldDBXDataBase).GetInTransaction then + (DatabaseWrapper as TBoldDBXDataBase).Rollback; + fReadTransactionStarted := false; + INC(Retries); + sleep(Retries*200); + end; end; - end + end; end; procedure TBoldDBXQuery.AssignSQL(SQL: TStrings); @@ -226,19 +360,36 @@ procedure TBoldDBXQuery.AssignSQL(SQL: TStrings); Query.SQL.EndUpdate; end; -procedure TBoldDBXQuery.AssignSQLText(SQL: String); +procedure TBoldDBXQuery.AssignSQLText(const SQL: String); begin Query.SQL.BeginUpdate; Query.SQL.Clear; +{$IFDEF BOLD_DELPHI10_OR_LATER} + Query.SQL.Append(SQL); // FIXME, this gives one long line. +{$ELSE} BoldAppendToStrings(Query.SQL, SQL, true); +{$ENDIF} + Query.SQL.EndUpdate; end; +function TBoldDBXQuery.GetSQLStrings: TStrings; +begin + result := fSQLStrings; + result.clear; + result.Add(Query.SQL.Text); +end; + function TBoldDBXQuery.GetSQLText: String; begin result := Query.SQL.text; end; +function TBoldDBXQuery.GetUseReadTransactions: boolean; +begin + result := fUseReadTransactions; +end; + function TBoldDBXQuery.GetRowsAffected: integer; begin result := Query.RowsAffected; @@ -254,6 +405,14 @@ procedure TBoldDBXQuery.ClearParams; query.params.Clear; end; +procedure TBoldDBXQuery.Close; +begin + inherited; + if (fReadTransactionStarted) and (DatabaseWrapper as TBoldDBXDataBase).GetInTransaction then + (DatabaseWrapper as TBoldDBXDataBase).Commit; + fReadTransactionStarted := false; +end; + function TBoldDBXQuery.Createparam(FldType: TFieldType; const ParamName: string; ParamType: TParamType; Size: integer): IBoldParameter; @@ -261,13 +420,20 @@ function TBoldDBXQuery.Createparam(FldType: TFieldType; result := TBoldDbParameter.Create(Query.params.CreateParam(fldType, ParamName, ParamType), self); end; +destructor TBoldDBXQuery.Destroy; +begin + if (fReadTransactionStarted) then + Close; + FreeAndNil(fSQLStrings); + inherited; +end; + { TBoldDBXTable } procedure TBoldDBXTable.AddIndex(const Name, Fields: string; Options: TIndexOptions; const DescFields: string); begin - // FIXME -// Table.AddIndex(Name, Fields, Options, DescFields); + end; constructor TBoldDBXTable.Create(Table: TSQLTable; DatabaseWrapper: TBoldDatabaseWrapper); @@ -278,12 +444,11 @@ constructor TBoldDBXTable.Create(Table: TSQLTable; DatabaseWrapper: TBoldDatabas procedure TBoldDBXTable.CreateTable; begin - raise EBold.CreateFmt(sMethodNotImplemented, [classname, 'CreateTable']); // do not localize + raise EBold.CreateFmt('%s.CreateTable: Not supported', [classname]); end; procedure TBoldDBXTable.DeleteTable; begin -// FIXME Table.DeleteTable; end; function TBoldDBXTable.GetDataSet: TDataSet; @@ -293,14 +458,23 @@ function TBoldDBXTable.GetDataSet: TDataSet; function TBoldDBXTable.GetExclusive: Boolean; begin -// FIXME result := Table.Exclusive; result := false; end; function TBoldDBXTable.GetExists: Boolean; +var + DB: IBoldDataBase; + NameList: TStringList; begin -// FIXME result := Table.Exists; - result := false; + NameList := TStringList.Create; + NameList.CaseSensitive := false; + try + DB:= DatabaseWrapper as IBoldDataBase; + DB.AllTableNames('', false, NameList); + Result := NameList.IndexOf(fTable.TableName) > -1; + finally + FreeANdNil(NameList); + end; end; function TBoldDBXTable.GetIndexDefs: TIndexDefs; @@ -322,19 +496,53 @@ function TBoldDBXTable.GetTableName: String; procedure TBoldDBXTable.SetExclusive(NewValue: Boolean); begin -// FIXME Table.Exclusive := NewValue; end; -procedure TBoldDBXTable.SetTableName(NewName: String); -begin - Table.TableName := NewName; +procedure TBoldDBXTable.SetTableName(const NewName: String); +var + DB: IBoldDataBase; + NameList: TStringList; + NameIndex: Integer; + s: string; +begin + s := NewName; + NameList := TStringList.Create; + NameList.CaseSensitive := false; + try + DB:= DatabaseWrapper as IBoldDataBase; + DB.AllTableNames('', false, NameList); + NameIndex := NameList.IndexOf(s); + if NameIndex > -1 then + s := NameList[NameIndex]; + finally + FreeANdNil(NameList); + end; + Table.TableName := s; end; { TBoldDBXDataBase } procedure TBoldDBXDataBase.AllTableNames(Pattern: String; ShowSystemTables: Boolean; TableNameList: TStrings); +var + SystemTableNames: TStringList; + TableName: string; begin - fDataBase.GetTableNames(TableNameList, ShowSystemTables); + if (Pattern <> '') and (Pattern <> '*') then + raise Exception.CreateFmt('%s.AlltableNames: This call does not allow patterns ("%s")', [ClassName, Pattern]); + fDataBase.GetTableNames(TableNameList, false); + if ShowSystemTables then + begin + SystemTableNames := TStringList.Create; + try + fDataBase.GetTableNames(SystemTableNames, true); + for TableName in SystemTableNames do + if TableNameList.IndexOf(TableName) = -1 then + TableNameList.Add(TableName); + finally + FreeAndNil(SystemTableNames); + end; + end; + end; function TBoldDBXDataBase.GetInTransaction: Boolean; @@ -342,6 +550,11 @@ function TBoldDBXDataBase.GetInTransaction: Boolean; result := fDataBase.InTransaction; end; +function TBoldDBXDataBase.GetIsExecutingQuery: Boolean; +begin + Result := fExecuteQueryCount > 0; +end; + function TBoldDBXDataBase.GetIsSQLBased: Boolean; begin result := true; @@ -378,21 +591,24 @@ function TBoldDBXDataBase.GetConnected: Boolean; result := fDataBase.Connected; end; +procedure TBoldDBXDataBase.StartReadTransaction; +begin + fTransaction := fDataBase.BeginTransaction(TDBXIsolations.ReadCommitted); +end; + procedure TBoldDBXDataBase.StartTransaction; begin -// fTransactionDesc.IsolationLevel := xilREADCOMMITTED; - fTransactionDesc.TransactionID := BOLD_DEFAULT_DBX_TRANSACTION_ID; - fDataBase.StartTransaction(fTransactionDesc); + fTransaction := fDataBase.BeginTransaction(TDBXIsolations.RepeatableRead); end; procedure TBoldDBXDataBase.Commit; begin - fDatabase.Commit(fTransactionDesc); + fDatabase.CommitFreeAndNil(fTransaction); end; procedure TBoldDBXDataBase.RollBack; begin - fDataBase.Rollback(fTransactionDesc); + fDataBase.RollbackFreeAndNil(fTransaction); end; procedure TBoldDBXDataBase.Open; @@ -400,6 +616,11 @@ procedure TBoldDBXDataBase.Open; fDataBase.Open; end; +procedure TBoldDBXDataBase.BeginExecuteQuery; +begin + inc(fExecuteQueryCount); +end; + procedure TBoldDBXDataBase.Close; begin fDataBase.Close; @@ -413,6 +634,11 @@ destructor TBoldDBXDataBase.destroy; FreeAndNil(fCachedQuery); end; +procedure TBoldDBXDataBase.EndExecuteQuery; +begin + dec(fExecuteQueryCount); +end; + function TBoldDBXDataBase.GetQuery: IBoldQuery; var Query: TSQLQuery; @@ -461,9 +687,11 @@ procedure TBoldDBXDataBase.ReleaseQuery(var Query: IBoldQuery); if fCachedQuery.Active then fCachedQuery.Close; fCachedQuery.SQL.Clear; + fCachedQuery.Params.Clear; end else DBXQuery.fQuery.free; + DBXQuery.fQuery := nil; DBXQuery.Free; end; end; @@ -489,6 +717,14 @@ function TBoldDBXDataBase.SupportsTableCreation: Boolean; result := false; end; +procedure TBoldDBXDataBase.Reconnect; +begin + if Assigned(fDataBase) then begin + fDataBase.Connected := False; + fDataBase.Connected := True; + end; +end; + procedure TBoldDBXDataBase.ReleaseCachedObjects; begin FreeAndNil(fCachedTable); @@ -499,16 +735,14 @@ procedure TBoldDBXDataBase.ReleaseCachedObjects; function TBoldDBXParameter.GetAsDateTime: TDateTime; begin - // dbexpress does not handle AsDateTime, only AsSQLTimeStamp result := SQLTimeStampToDateTime(Parameter.AsSQLTimeStamp); end; procedure TBoldDBXParameter.SetAsDateTime(const Value: TDateTime); begin - // dbexpress does not handle AsDateTime, only AsSQLTimeStamp -// Parameter.AsDateTime := value; + Parameter.AsSQLTimeStamp := DateTimetoSQLTimeStamp(value); end; +initialization end. - diff --git a/Source/Persistence/DBExpress/BoldDatabaseAdapterDBX.pas b/Source/Persistence/DBExpress/BoldDatabaseAdapterDBX.pas index 7ef867f..e28cef4 100644 --- a/Source/Persistence/DBExpress/BoldDatabaseAdapterDBX.pas +++ b/Source/Persistence/DBExpress/BoldDatabaseAdapterDBX.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldDatabaseAdapterDBX; interface @@ -5,7 +8,6 @@ interface uses BoldAbstractDataBaseAdapter, BoldDBInterfaces, - DBXpress, SQLExpr, BoldDBXInterfaces; @@ -35,7 +37,8 @@ implementation uses SysUtils, - BoldDefs; + BoldDefs, + BoldRev; { TBoldDatabaseAdapterDBX } @@ -71,4 +74,6 @@ procedure TBoldDatabaseAdapterDBX.SetDataBase(const Value: TSQLConnection); InternalDatabase := value; end; +initialization + end. diff --git a/Source/Persistence/DBExpress/BoldPersistenceHandleDBX.pas b/Source/Persistence/DBExpress/BoldPersistenceHandleDBX.pas index fe336a3..8174f47 100644 --- a/Source/Persistence/DBExpress/BoldPersistenceHandleDBX.pas +++ b/Source/Persistence/DBExpress/BoldPersistenceHandleDBX.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldPersistenceHandleDBX; interface @@ -24,7 +27,7 @@ TBoldPersistenceHandleDBX = class(TBoldDBPersistenceHandle) procedure SetPassword(const Value: string); override; procedure SetUserName(const Value: string); override; public - destructor Destroy; override; + destructor destroy; override; function GetDataBaseInterface: IBoldDatabase; override; published property SQLConnection: TSQLConnection read fSQLConnection write SetSQLConnection; @@ -33,7 +36,8 @@ TBoldPersistenceHandleDBX = class(TBoldDBPersistenceHandle) implementation uses - SysUtils; + SysUtils, + BoldRev; { TBoldPersistenceHandleDBX } @@ -75,11 +79,13 @@ procedure TBoldPersistenceHandleDBX.SetSQLConnection(const Value: TSQLConnection procedure TBoldPersistenceHandleDBX.SetPassword(const Value: string); begin raise Exception.Create('Can not set password directly on PersistenceHandleDBX, set it on the SQLConnection'); -end; +end; procedure TBoldPersistenceHandleDBX.SetUserName(const Value: string); begin raise Exception.Create('Can not set username directly on PersistenceHandleDBX, set it on the SQLConnection'); end; +initialization + end. diff --git a/Source/Persistence/DBExpress/BoldPersistenceHandleDBXReg.pas b/Source/Persistence/DBExpress/BoldPersistenceHandleDBXReg.pas index 8c692a2..e762a28 100644 --- a/Source/Persistence/DBExpress/BoldPersistenceHandleDBXReg.pas +++ b/Source/Persistence/DBExpress/BoldPersistenceHandleDBXReg.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldPersistenceHandleDBXReg; interface @@ -6,16 +9,21 @@ procedure Register; implementation -{$R BoldPersistenceHandleDBX.res} - uses Classes, BoldPersistenceHandleDBX, + BoldAbstractDatabaseAdapter, + BoldIndexCollection, BoldDatabaseAdapterDBX, - BoldIDEConsts; + BoldIDEConsts, ColnEdit, DesignIntf; +type + + TBoldIndexCollectionProperty = class(TCollectionProperty) + end; procedure Register; begin + RegisterPropertyEditor(TypeInfo(TBoldIndexCollection), TBoldAbstractDatabaseAdapter, 'CustomIndexes', TBoldIndexCollectionProperty); // Should really be registered in own unit RegisterComponents(BOLDPAGENAME_DEPRECATED, [TBoldPersistenceHandleDBX]); RegisterComponents(BOLDPAGENAME_PERSISTENCE, [TBoldDatabaseAdapterDBX]); end; diff --git a/Source/Persistence/DBISAM/BoldDBISAMInterfaces.pas b/Source/Persistence/DBISAM/BoldDBISAMInterfaces.pas index fea94fb..abe4d76 100644 --- a/Source/Persistence/DBISAM/BoldDBISAMInterfaces.pas +++ b/Source/Persistence/DBISAM/BoldDBISAMInterfaces.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldDBISAMInterfaces; interface @@ -23,7 +26,7 @@ TBoldDBISAMQuery = class(TBoldDataSetWrapper, IBoldQuery, IBoldExecQuery, IBol fQuery: TDBISAMQuery; function GetQuery: TDBISAMQuery; procedure AssignParams(SourceParams: TParams); - procedure ClearParams; + procedure ClearParams; function GetParamCount: integer; function GetParams(i: integer): IBoldParameter; function GetRequestLiveQuery: Boolean; @@ -32,6 +35,8 @@ TBoldDBISAMQuery = class(TBoldDataSetWrapper, IBoldQuery, IBoldExecQuery, IBol function GetSQLText: String; procedure AssignSQL(SQL: TStrings); procedure AssignSQLText(SQL: String); + function GetParamCheck: Boolean; + procedure SetParamCheck(value: Boolean); function GetRowsAffected: integer; function GetRecordCount: integer; function Createparam(FldType: TFieldType; const ParamName: string; ParamType: TParamType; Size: integer): IBoldParameter; @@ -86,8 +91,6 @@ TBoldDBISAMDataBase = class(TBoldDatabaseWrapper, IBoldDataBase) procedure RollBack; procedure Open; procedure Close; - function GetTable: IBoldTable; - procedure ReleaseTable(var Table: IBoldTable); function SupportsTableCreation: Boolean; procedure ReleaseCachedObjects; protected @@ -95,9 +98,11 @@ TBoldDBISAMDataBase = class(TBoldDatabaseWrapper, IBoldDataBase) procedure AllTableNames(Pattern: String; ShowSystemTables: Boolean; TableNameList: TStrings); override; function GetQuery: IBoldQuery; override; procedure ReleaseQuery(var Query: IBoldQuery); override; + function GetTable: IBoldTable; override; + procedure ReleaseTable(var Table: IBoldTable); override; public - constructor Create(DataBase: TDBISAMDataBase; SQLDataBaseConfig: TBoldSQLDatabaseConfig); - destructor Destroy; override; + constructor create(DataBase: TDBISAMDataBase; SQLDataBaseConfig: TBoldSQLDatabaseConfig); + destructor destroy; override; end; var @@ -107,7 +112,8 @@ implementation uses SysUtils, - BoldDefs; + BoldDefs, + BoldRev; { TBoldDBISAMQuery } @@ -126,6 +132,11 @@ function TBoldDBISAMQuery.GetQuery: TDBISAMQuery; result := fQuery; end; +function TBoldDBISAMQuery.GetParamCheck: Boolean; +begin + Result := Query.ParamCheck; +end; + function TBoldDBISAMQuery.GetParamCount: integer; begin result := Query.params.count; @@ -152,6 +163,11 @@ function TBoldDBISAMQuery.ParamByName(const Value: string): IBoldParameter; result := nil; end; +procedure TBoldDBISAMQuery.SetParamCheck(value: Boolean); +begin + Query.ParamCheck := Value; +end; + procedure TBoldDBISAMQuery.SetRequestLiveQuery(NewValue: Boolean); begin Query.RequestLive := NewValue; @@ -170,7 +186,7 @@ procedure TBoldDBISAMQuery.ExecSQL; except on e: Exception do begin - e.Message := e.Message + BOLDCRLF + 'SQL: ' + Query.SQL.text; // do not localize + e.Message := e.Message + BOLDCRLF + 'SQL: ' + Query.SQL.text; raise; end; end @@ -180,21 +196,19 @@ constructor TBoldDBISAMQuery.Create(Query: TDBISAMQuery; DatabaseWrapper: TBoldD begin inherited Create(DatabaseWrapper); fQuery := Query; + SetParamCheck(true); end; procedure TBoldDBISAMQuery.EndSQLBatch; begin - // intentionally left blank end; procedure TBoldDBISAMQuery.StartSQLBatch; begin - // intentionally left blank end; procedure TBoldDBISAMQuery.FailSQLBatch; begin - // intentionally left blank end; procedure TBoldDBISAMQuery.Open; @@ -205,7 +219,7 @@ procedure TBoldDBISAMQuery.Open; except on e: Exception do begin - e.Message := e.Message + BOLDCRLF + 'SQL: ' + Query.SQL.text; // do not localize + e.Message := e.Message + BOLDCRLF + 'SQL: ' + Query.SQL.text; raise; end; end @@ -333,7 +347,7 @@ function TBoldDBISAMDataBase.GetInTransaction: Boolean; function TBoldDBISAMDataBase.GetIsSQLBased: Boolean; begin - result := true; // CHECKME: fDataBase.IsSQLBased; + result := true; end; function TBoldDBISAMDataBase.GetKeepConnection: Boolean; @@ -343,7 +357,7 @@ function TBoldDBISAMDataBase.GetKeepConnection: Boolean; function TBoldDBISAMDataBase.GetLogInPrompt: Boolean; begin - result := false; // CHECKME: fDataBase.LoginPrompt; + result := false; end; procedure TBoldDBISAMDataBase.SetKeepConnection(NewValue: Boolean); @@ -353,7 +367,6 @@ procedure TBoldDBISAMDataBase.SetKeepConnection(NewValue: Boolean); procedure TBoldDBISAMDataBase.SetlogInPrompt(NewValue: Boolean); begin - // DO NOTHING; // CHECKME: fDataBase.LoginPrompt := NewValue; end; constructor TBoldDBISAMDataBase.create(DataBase: TDBISAMDataBase; SQLDataBaseConfig: TBoldSQLDatabaseConfig); @@ -489,7 +502,5 @@ function TBoldDBISAMDataBase.SupportsDefaultColumnValues: Boolean; result := false; end; +initialization end. - - - diff --git a/Source/Persistence/DBISAM/BoldDatabaseAdapterDBIsam.pas b/Source/Persistence/DBISAM/BoldDatabaseAdapterDBIsam.pas index 5a51b7d..8ed0326 100644 --- a/Source/Persistence/DBISAM/BoldDatabaseAdapterDBIsam.pas +++ b/Source/Persistence/DBISAM/BoldDatabaseAdapterDBIsam.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldDatabaseAdapterDBISAM; interface @@ -24,8 +27,8 @@ TBoldDatabaseAdapterDBISAM = class(TBoldAbstractDatabaseAdapter) procedure ReleaseBoldDatabase; override; function GetDataBaseInterface: IBoldDatabase; override; public - constructor Create(aOwner: TComponent); override; - destructor Destroy; override; + constructor create(aOwner: TComponent); override; + destructor destroy; override; published property DataBase: TDBISAMDataBase read GetDataBase write SetDataBase; {$IFNDEF T2H} @@ -38,9 +41,9 @@ implementation uses SysUtils, BoldDefs, - DBISAMConsts; + BoldRev; -{ TBoldDatabaseAdapterDBISAM } +{ TBoldDatabaseAdapterDBISAM } constructor TBoldDatabaseAdapterDBISAM.create(aOwner: TComponent); begin @@ -53,7 +56,7 @@ destructor TBoldDatabaseAdapterDBISAM.destroy; Changed; FreePublisher; FreeAndNil(fBoldDatabase); - inherited; + inherited; end; function TBoldDatabaseAdapterDBISAM.GetDataBase: TDBISAMDataBase; @@ -64,7 +67,7 @@ function TBoldDatabaseAdapterDBISAM.GetDataBase: TDBISAMDataBase; function TBoldDatabaseAdapterDBISAM.GetDataBaseInterface: IBoldDatabase; begin if not assigned(Database) then - raise EBold.CreateFmt(sAdapterNotConnected, [classname]); + raise EBold.CreateFmt('%s.GetDatabaseInterface: The adapter is not connected to a database', [classname]); if not assigned(fBoldDatabase) then fBoldDatabase := TBoldDBISAMDataBase.create(Database, SQLDataBaseConfig); result := fBoldDatabase; @@ -80,4 +83,6 @@ procedure TBoldDatabaseAdapterDBISAM.SetDataBase(const Value: TDBISAMDataBase); InternalDatabase := value; end; +initialization + end. diff --git a/Source/Persistence/DBISAM/BoldPersistenceHandleDBISAM.pas b/Source/Persistence/DBISAM/BoldPersistenceHandleDBISAM.pas index 1c55b11..c26c30c 100644 --- a/Source/Persistence/DBISAM/BoldPersistenceHandleDBISAM.pas +++ b/Source/Persistence/DBISAM/BoldPersistenceHandleDBISAM.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldPersistenceHandleDBISAM; interface @@ -28,8 +31,8 @@ TBoldPersistenceHandleDBISAM = class(TBoldDBPersistenceHandle) procedure InternalTransferproperties(const target: TBoldPersistenceHandleDB); override; {$ENDIF} public - constructor Create(Owner: TComponent); override; - destructor Destroy; override; + constructor create(Owner: TComponent); override; + destructor destroy; override; function GetDataBaseInterface: IBoldDatabase; override; published property DataBase: TDBISAMDatabase read fDataBase write SetDataBase; @@ -79,7 +82,7 @@ procedure TBoldPersistenceHandleDBISAM.SetDataBase(const Value: TDBISAMDatabase) begin if fDataBase <> Value then begin - CheckInactive('SetDataBase'); // do not localize + CheckInactive('SetDataBase'); fDataBase := Value; if assigned(fDataBase) then fDataBase.FreeNotification(self); @@ -97,14 +100,14 @@ procedure TBoldPersistenceHandleDBISAM.InternalTransferproperties( if not assigned(Target.DatabaseAdapter) then begin Target.DatabaseAdapter := TBoldDatabaseAdapterDBISAM.Create(Target.Owner); - Target.DatabaseAdapter.Name := GetNewComponentName(Target.DatabaseAdapter, 'BoldDatabaseAdapterDBISAM'); // do not localize - LongRec(DesInfo).Lo := LongRec(DesInfo).lo+16; //set Left - LongRec(DesInfo).Hi := LongRec(DesInfo).hi+16; //Set Top; + Target.DatabaseAdapter.Name := GetNewComponentName(Target.DatabaseAdapter, 'BoldDatabaseAdapterDBISAM'); + LongRec(DesInfo).Lo := LongRec(DesInfo).lo+16; + LongRec(DesInfo).Hi := LongRec(DesInfo).hi+16; Target.DatabaseAdapter.DesignInfo := DesInfo; - showmessage(sCreatedNewAdapter); + showmessage('Created a new DatabaseAdapterDBISAM'); end else if not (target.DatabaseAdapter is tBoldDatabaseAdapterDBISAM) then - raise Exception.CreateFmt(sCannotTransferProperties, [target.DatabaseAdapter.ClassName] ); + raise Exception.CreateFmt('The persistencehandle is connected to a %s, properties can only be transfered to a TBoldDatabaseAdapterDBISAM', [target.DatabaseAdapter.ClassName] ); Adapter := target.DatabaseAdapter as tBoldDatabaseAdapterDBISAM; if assigned(fDatabase) then @@ -113,14 +116,14 @@ procedure TBoldPersistenceHandleDBISAM.InternalTransferproperties( if not assigned(Adapter.Database) then begin Adapter.DataBase := TDBISAMDatabase.Create(Target.owner); - Adapter.DataBase.Name := GetNewComponentName(Adapter.DataBase, 'Database'); // do not localize - showmessage(sCreatedDB); - LongRec(DesInfo).Lo := LongRec(DesInfo).lo+16; //set Left - LongRec(DesInfo).Hi := LongRec(DesInfo).hi+16; //Set Top; + Adapter.DataBase.Name := GetNewComponentName(Adapter.DataBase, 'Database'); + showmessage('Created a new Database'); + LongRec(DesInfo).Lo := LongRec(DesInfo).lo+16; + LongRec(DesInfo).Hi := LongRec(DesInfo).hi+16; Adapter.DataBase.DesignInfo := DesInfo; end; end; -end. - +initialization +end. diff --git a/Source/Persistence/DBISAM/BoldPersistenceHandleDBISAMReg.pas b/Source/Persistence/DBISAM/BoldPersistenceHandleDBISAMReg.pas index 603ce8d..3584806 100644 --- a/Source/Persistence/DBISAM/BoldPersistenceHandleDBISAMReg.pas +++ b/Source/Persistence/DBISAM/BoldPersistenceHandleDBISAMReg.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldPersistenceHandleDBISAMReg; interface @@ -11,16 +14,22 @@ implementation uses SysUtils, Classes, + BoldIDESupport, + BoldVersionInfo, BoldDatabaseAdapterDBIsam, BoldPersistenceHandleDBISAM, - BoldIDESupport, - BoldIDEConsts; + BoldIDEConsts; procedure Register; begin - RemovePackageFromDisabledPackagesRegistry(format('BoldDBISAM%s', [LIBSUFFIX])); // do not localize + RemovePackageFromDisabledPackagesRegistry(format('Bold%d%d%sDOA', [ + BoldBuildVersionNumberMajor, + BoldBuildVersionNumberMinor, + BoldBuildTarget])); RegisterComponents(BOLDPAGENAME_DEPRECATED, [TBoldPersistenceHandleDBISAM]); RegisterComponents(BOLDPAGENAME_PERSISTENCE, [TBoldDatabaseAdapterDBISAM]); end; +initialization + end. diff --git a/Source/Persistence/DBISAM/DBISAMConsts.pas b/Source/Persistence/DBISAM/DBISAMConsts.pas index c94a822..c60b145 100644 --- a/Source/Persistence/DBISAM/DBISAMConsts.pas +++ b/Source/Persistence/DBISAM/DBISAMConsts.pas @@ -12,4 +12,4 @@ interface implementation -end. \ No newline at end of file +end. diff --git a/Source/Persistence/DOA/BoldDOAInterfaces.pas b/Source/Persistence/DOA/BoldDOAInterfaces.pas index cd3931f..78348ec 100644 --- a/Source/Persistence/DOA/BoldDOAInterfaces.pas +++ b/Source/Persistence/DOA/BoldDOAInterfaces.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldDOAInterfaces; interface @@ -5,7 +8,6 @@ interface uses Classes, Db, - Contnrs, Oracle, OracleTypes, OracleData, @@ -17,22 +19,12 @@ interface { forward declarations } TBoldDOADataBase = class; TBoldDOAQuery = class; - TLobValues = class - private - FLOB:TLoblocator; - FValue:TBlobData; - public - constructor Create(aLOB:TLOBLocator;const aValue:TBlobData); - destructor Destroy; override; - end; -// TBoldDOATable = class; { TBoldDOAQuery } TBoldDOAQuery = class(TBoldDataSetWrapper, IBoldQuery, IBoldParameterized) private fQuery: TOracleDataSet; - fLOBList:TObjectList; function GetQuery: TOracleDataSet; procedure AssignParams(SourceParams: TParams); function GetParamCount: integer; @@ -42,7 +34,9 @@ TBoldDOAQuery = class(TBoldDataSetWrapper, IBoldQuery, IBoldParameterized) procedure SetRequestLiveQuery(NewValue: Boolean); function GetSQLText: String; procedure AssignSQL(SQL: TStrings); - procedure AssignSQLText(SQL: String); + procedure AssignSQLText(const SQL: String); + function GetParamCheck: Boolean; + procedure SetParamCheck(value: Boolean); function GetRecordCount: integer; function Createparam(FldType: TFieldType; const ParamName: string; ParamType: TParamType; Size: integer): IBoldParameter; protected @@ -50,26 +44,24 @@ TBoldDOAQuery = class(TBoldDataSetWrapper, IBoldQuery, IBoldParameterized) procedure ClearParams; property Query: TOracleDataSet read GetQuery; procedure Open; override; - procedure BuildVariables; - procedure Clear; public constructor Create(Query: TOracleDataSet; DatabaseWrapper: TBoldDatabaseWrapper); virtual; - destructor Destroy; override; end; TBoldDOAExecQuery = class(TBoldNonRefCountedObject, IBoldExecQuery, IBoldParameterized) private fQuery: TOracleQuery; fDatabase: TBoldDOADatabase; - fLOBList:TObjectList; procedure ClearParams; procedure AssignParams(SourceParams: TParams); function ParamByName(const Value: string): IBoldParameter; function GetParamCount: integer; function GetSQLText: String; function GetParams(i:integer): IBoldParameter; - procedure AssignSQL(SQL: TStrings); + procedure AssignSQL(const SQL: TStrings); procedure AssignSQLText(SQL: String); + function GetParamCheck: Boolean; + procedure SetParamCheck(value: Boolean); procedure StartSQLBatch; procedure EndSQLBatch; procedure FailSQLBatch; @@ -78,12 +70,8 @@ TBoldDOAExecQuery = class(TBoldNonRefCountedObject, IBoldExecQuery, IBoldParam function GetRowsAffected: integer; function GetImplementor: TObject; property Query: TOracleQuery read fQuery; - protected - procedure BuildVariables; - procedure Clear; public constructor Create(Query: TOracleQuery; Database: TBoldDOADatabase); - destructor Destroy; override; end; { TBoldADOParameter } @@ -129,6 +117,8 @@ TBoldDOAParameter = class(TBoldRefCountedObject, IBoldParameter) constructor create(Query: TBoldDOAQuery; ExecQuery: TBoldDOAExecQuery; ParamIndex: integer; ParamName: String); end; + + { TBoldDOADataBase } TBoldDOADataBase = class(TBoldDatabaseWrapper, IBoldDataBase) private @@ -147,8 +137,6 @@ TBoldDOADataBase = class(TBoldDatabaseWrapper, IBoldDataBase) procedure RollBack; procedure Open; procedure Close; - function GetTable: IBoldTable; - procedure ReleaseTable(var Table: IBoldTable); function SupportsTableCreation: Boolean; procedure ReleaseCachedObjects; protected @@ -157,9 +145,11 @@ TBoldDOADataBase = class(TBoldDatabaseWrapper, IBoldDataBase) procedure ReleaseQuery(var Query: IBoldQuery); override; function GetExecQuery: IBoldExecQuery; override; procedure ReleaseExecQuery(var Query: IBoldExecQuery); override; + function GetTable: IBoldTable; override; + procedure ReleaseTable(var Table: IBoldTable); override; public - constructor Create(DataBase: TOracleSession; SQLDataBaseConfig: TBoldSQLDatabaseConfig); - destructor Destroy; override; + constructor create(DataBase: TOracleSession; SQLDataBaseConfig: TBoldSQLDatabaseConfig); + destructor destroy; override; end; implementation @@ -168,9 +158,7 @@ implementation Variants, BoldDefs, SysUtils, - OracleCI, - BoldUtils, - DOAConsts; + BoldUtils; function FieldTypeToOracleType(FieldType: TFieldType): integer; begin @@ -234,6 +222,9 @@ function OracleTypeToFieldType(OracleType: Integer): TFieldType; end; end; + + + { TBoldDOAQuery } procedure TBoldDOAQuery.AssignParams(Sourceparams: tparams); @@ -251,6 +242,11 @@ function TBoldDOAQuery.GetQuery: TOracleDataSet; result := fQuery; end; +function TBoldDOAQuery.GetParamCheck: Boolean; +begin + Result := Query.ParamCheck; +end; + function TBoldDOAQuery.GetParamCount: integer; begin result := Query.Variables.count; @@ -263,7 +259,6 @@ function TBoldDOAQuery.GetParams(I: integer): IBoldParameter; function TBoldDOAQuery.GetREquestLiveQuery: Boolean; begin - // FIXME: Query.RequestLive; result := true; end; @@ -272,17 +267,16 @@ function TBoldDOAQuery.ParamByName(const Value: string): IBoldParameter; i: integer; begin i := Query.VariableIndex(value); - if i = -1 then - begin - BuildVariables; - i := Query.VariableIndex(value); - end; result := TBoldDOAParameter.Create(self, nil, i, value) end; +procedure TBoldDOAQuery.SetParamCheck(value: Boolean); +begin + Query.ParamCheck := Value; +end; + procedure TBoldDOAQuery.SetRequestLiveQuery(NewValue: Boolean); begin - //FIXME: Query.RequestLive := NewValue; ; end; @@ -295,6 +289,7 @@ constructor TBoldDOAQuery.Create(Query: TOracleDataSet; DatabaseWrapper: TBoldDa begin inherited Create(DatabaseWrapper); fQuery := Query; + SetParamCheck(true); end; procedure TBoldDOAQuery.Open; @@ -305,7 +300,7 @@ procedure TBoldDOAQuery.Open; except on e: Exception do begin - e.Message := e.Message + BOLDCRLF + 'SQL: ' + Query.SQL.text; // do not localize + e.Message := e.Message + BOLDCRLF + 'SQL: ' + Query.SQL.text; raise; end; end @@ -318,7 +313,7 @@ procedure TBoldDOAQuery.AssignSQL(SQL: TStrings); Query.SQL.EndUpdate; end; -procedure TBoldDOAQuery.AssignSQLText(SQL: String); +procedure TBoldDOAQuery.AssignSQLText(const SQL: String); begin Query.SQL.BeginUpdate; Query.SQL.Clear; @@ -347,25 +342,6 @@ procedure TBoldDOAQuery.ClearParams; query.DeleteVariables; end; -procedure TBoldDOAQuery.BuildVariables; -var - VarList: TStringList; - i : integer; -begin - VarList := Oracle.FindVariables(Query.SQL.Text, False); - for i := 0 to VarList.Count - 1 do Query.DeclareVariable(VarList[i], otString); -end; - -procedure TBoldDOAQuery.Clear; -begin - Query.DeleteVariables; - FLoblist.Clear; -end; -destructor TBoldDOAQuery.Destroy; -begin - FLobList.Free; - inherited; -end; { TBoldDOADataBase } procedure TBoldDOADataBase.AllTableNames(Pattern: String; ShowSystemTables: Boolean; TableNameList: TStrings); @@ -376,14 +352,14 @@ procedure TBoldDOADataBase.AllTableNames(Pattern: String; ShowSystemTables: Bool aQuery := TOracleDataset.Create(nil); aQuery.Session := fDataBase; SQL := - 'select owner, table_name, tablespace_name '+ // do not localize - 'from all_tables '; // do not localize + 'select owner, table_name, tablespace_name '+ + 'from all_tables '; if not ShowSystemTables then SQL := SQL + - 'where owner <> ''SYSTEM'' and owner <> ''DBSNMP'' and owner <> ''ORDSYS'' and '+ // do not localize - 'owner <> ''OUTLN'' and owner <> ''SYS'' and owner <> ''MDSYS'' and owner <> ''MTSSYS'' '; // do not localize - SQL := SQL + 'order by owner, table_name, tablespace_name'; // do not localize + 'where owner <> ''SYSTEM'' and owner <> ''DBSNMP'' and owner <> ''ORDSYS'' and '+ + 'owner <> ''OUTLN'' and owner <> ''SYS'' and owner <> ''MDSYS'' and owner <> ''MTSSYS'' '; + SQL := SQL + 'order by owner, table_name, tablespace_name'; aQuery.SQL.Text := SQL; aQuery.Open; while not aQuery.Eof do @@ -407,24 +383,20 @@ function TBoldDOADataBase.GetIsSQLBased: Boolean; function TBoldDOADataBase.GetKeepConnection: Boolean; begin - // FIXME: result := fDataBase.KeepConnection; result := true end; function TBoldDOADataBase.GetLogInPrompt: Boolean; begin - //FIXME: result := fDataBase.LoginPrompt; result := true; end; procedure TBoldDOADataBase.SetKeepConnection(NewValue: Boolean); begin - // FIXME: fDataBase.KeepConnection := NewValue; end; procedure TBoldDOADataBase.SetlogInPrompt(NewValue: Boolean); begin - // FIXME: fDataBase.LoginPrompt := NewValue; end; constructor TBoldDOADataBase.create(DataBase: TOracleSession; SQLDataBaseConfig: TBoldSQLDatabaseConfig); @@ -477,7 +449,6 @@ destructor TBoldDOADataBase.destroy; begin inherited; fDatabase := nil; -// FreeAndNil(fCachedTable); FreeAndNil(fCachedQuery); FreeAndNil(fCachedExecQuery); end; @@ -501,7 +472,7 @@ function TBoldDOADataBase.GetQuery: IBoldQuery; function TBoldDOADataBase.GetTable: IBoldTable; begin - raise EBold.CreateFmt(sIBoldTablesNotSupported, [classname, 'GetTable']); // do not localize + raise EBold.CreateFmt('%s.GetTable: DOA-Implementation does not support IBoldTables', [classname]); end; { var @@ -545,7 +516,7 @@ procedure TBoldDOADataBase.ReleaseQuery(var Query: IBoldQuery); procedure TBoldDOADataBase.ReleaseTable(var Table: IBoldTable); begin - raise EBold.CreateFmt(sIBoldTablesNotSupported, [classname, 'ReleaseTable']); // do not localize + raise EBold.CreateFmt('%s.ReleaseTable: DOA-Implementation does not support IBoldTables', [classname]); end; { var @@ -571,7 +542,6 @@ function TBoldDOADataBase.SupportsTableCreation: Boolean; procedure TBoldDOADataBase.ReleaseCachedObjects; begin -// FreeAndNil(fCachedTable); FreeAndNil(fCachedQuery); FreeAndNil(fCachedExecQuery); end; @@ -610,8 +580,10 @@ procedure TBoldDOADataBase.ReleaseExecQuery(var Query: IBoldExecQuery); DOAExecQuery.fQuery.free; DOAExecQuery.Free; end; + end; + { TBoldDOAParameter } procedure TBoldDOAParameter.AssignFieldValue(source: IBoldField); @@ -637,17 +609,15 @@ constructor TBoldDOAParameter.create(Query: TBoldDOAQuery; ExecQuery: TBoldDOAEx procedure TBoldDOAParameter.EnsureParameter(fieldType: TFieldType); begin - if fieldType <> ftUnknown then + if fParamIndex = -1 then begin if assigned(fQuery) then begin - FQuery.Query.DeleteVariable(fParamName); fQuery.Query.DeclareVariable(fParamName, FieldTypeToOracleType(FieldType)); fParamIndex := fQuery.Query.VariableIndex(fParamName); end else begin - fExecQuery.Query.DeleteVariable(fParamName); fExecQuery.Query.DeclareVariable(fParamName, FieldTypeToOracleType(FieldType)); fParamIndex := fExecQuery.Query.VariableIndex(fParamName); end; @@ -744,22 +714,12 @@ procedure TBoldDOAParameter.SetAsBCD(const Value: Currency); end; procedure TBoldDOAParameter.SetAsBlob(const Value: TBlobData); -var - LOB:TLOBLocator; begin EnsureParameter(ftBlob); - if assigned(fQuery) then - begin - LOB := TLOBLocator.Create(fQuery.Query.Session,otBlob); - FQuery.Query.SetComplexVariable(fQuery.Query.VariableName(fParamIndex),LOB); - end + if value = '' then + SetAsVariant(GetDatabaseWrapper.SQLDatabaseConfig.EmptyStringMarker) else - begin - LOB := TLOBLocator.CreateTemporary(fExecQuery.Query.Session,otBlob,True); - LOB.Write(Value[1],Length(Value)); - fExecQuery.Query.SetComplexVariable(fExecQuery.Query.VariableName(fParamIndex),LOB); - FExecQuery.fLOBList.Add(TLobValues.Create(LOB,value)) - end; + SetAsVariant(Value); end; procedure TBoldDOAParameter.SetAsBoolean(Value: Boolean); @@ -777,18 +737,13 @@ procedure TBoldDOAParameter.SetAsCurrency(const Value: Currency); procedure TBoldDOAParameter.SetAsDate(const Value: TDateTime); begin EnsureParameter(ftDate); - SetAsDateTime(Value); + SetAsVariant(Value); end; procedure TBoldDOAParameter.SetAsDateTime(const Value: TDateTime); begin EnsureParameter(ftDateTime); - if assigned(fQuery) then - fQuery.Query.SetVariable(fParamIndex, Value) - else - fExecQuery.Query.SetVariable(fParamIndex, Value) - -// SetAsVariant(Value); + SetAsVariant(Value); end; procedure TBoldDOAParameter.SetAsFloat(const Value: Double); @@ -827,7 +782,7 @@ procedure TBoldDOAParameter.SetAsString(const Value: string); procedure TBoldDOAParameter.SetAsTime(const Value: TDateTime); begin EnsureParameter(ftTime); - SetAsDateTime(Value); + SetAsVariant(Value); end; procedure TBoldDOAParameter.SetAsVariant(const NewValue: Variant); @@ -862,7 +817,7 @@ procedure TBoldDOAParameter.SetText(const Value: string); { TBoldDOAExecQuery } -procedure TBoldDOAExecQuery.AssignSQL(SQL: TStrings); +procedure TBoldDOAExecQuery.AssignSQL(const SQL: TStrings); begin Query.SQL.Assign(SQL); end; @@ -875,14 +830,13 @@ procedure TBoldDOAExecQuery.AssignSQLText(SQL: String); procedure TBoldDOAExecQuery.ClearParams; begin query.DeleteVariables; - FLobList.Clear; end; constructor TBoldDOAExecQuery.Create(Query: TOracleQuery; Database: TBoldDOADatabase); begin fQuery := Query; fDatabase := Database; - FLobList := TObjectList.Create; + SetParamCheck(true); end; function TBoldDOAExecQuery.Createparam(FldType: TFieldType; @@ -895,12 +849,10 @@ function TBoldDOAExecQuery.Createparam(FldType: TFieldType; procedure TBoldDOAExecQuery.EndSQLBatch; begin - // Do nothing end; procedure TBoldDOAExecQuery.FailSQLBatch; begin - // Do nothing end; function TBoldDOAExecQuery.GetImplementor: TObject; @@ -908,6 +860,11 @@ function TBoldDOAExecQuery.GetImplementor: TObject; result := Query; end; +function TBoldDOAExecQuery.GetParamCheck: Boolean; +begin + Query.ParamCheck := Value; +end; + function TBoldDOAExecQuery.GetParamCount: integer; begin result := Query.VariableCount; @@ -934,11 +891,6 @@ function TBoldDOAExecQuery.ParamByName( i: integer; begin i := Query.VariableIndex(value); - if i = -1 then - begin - BuildVariables; - i := Query.VariableIndex(value); - end; result := TBoldDOAParameter.Create(nil, self, i, Value) end; @@ -947,19 +899,22 @@ procedure TBoldDOAExecQuery.ExecSQL; BoldLogSQL(fQuery.SQL); try fQuery.Execute; - fQuery.Close; except on e: Exception do begin - e.Message := e.Message + BOLDCRLF + 'SQL: ' + fQuery.SQL.text; // do not localize + e.Message := e.Message + BOLDCRLF + 'SQL: ' + fQuery.SQL.text; raise; end; end end; +procedure TBoldDOAExecQuery.SetParamCheck(value: Boolean); +begin + Query.ParamCheck := Value; +end; + procedure TBoldDOAExecQuery.StartSQLBatch; begin - // do nothing end; procedure TBoldDOAExecQuery.AssignParams(SourceParams: TParams); @@ -970,41 +925,5 @@ procedure TBoldDOAExecQuery.AssignParams(SourceParams: TParams); Query.Variables.list.Clear; end; -procedure TBoldDOAExecQuery.BuildVariables; -var - VarList: TStringList; - i : integer; -begin - VarList := Oracle.FindVariables(Query.SQL.Text, False); - for i := 0 to VarList.Count - 1 do Query.DeclareVariable(VarList[i], otString); -end; - -procedure TBoldDOAExecQuery.Clear; -begin - Query.DeleteVariables; - FLoblist.Clear; -end; - -destructor TBoldDOAExecQuery.Destroy; -begin - FLobList.Free; - inherited; -end; - -{ TLobValues } - -constructor TLobValues.Create(aLOB: TLOBLocator;const aValue: TBlobData); -begin - inherited Create; - FLOB := aLOB; - FValue := aValue; -end; - -destructor TLobValues.Destroy; -begin - FLOB.Free; - inherited Destroy; -end; - initialization end. diff --git a/Source/Persistence/DOA/BoldDatabaseAdapterDOA.pas b/Source/Persistence/DOA/BoldDatabaseAdapterDOA.pas index 3b23dc6..7d3b674 100644 --- a/Source/Persistence/DOA/BoldDatabaseAdapterDOA.pas +++ b/Source/Persistence/DOA/BoldDatabaseAdapterDOA.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldDatabaseAdapterDOA; interface @@ -22,7 +25,7 @@ TBoldDatabaseAdapterDOA = class(TBoldAbstractDatabaseAdapter) procedure ReleaseBoldDatabase; override; function GetDataBaseInterface: IBoldDatabase; override; public - destructor Destroy; override; + destructor destroy; override; published property DataBase: TOracleSession read GetDataBase write SetDataBase; {$IFNDEF T2H} @@ -35,16 +38,16 @@ implementation uses SysUtils, BoldDefs, - DOAConsts; + BoldRev; -{ TBoldDatabaseAdapterDOA } +{ TBoldDatabaseAdapterDOA } destructor TBoldDatabaseAdapterDOA.destroy; begin Changed; FreePublisher; FreeAndNil(fBoldDatabase); - inherited; + inherited; end; function TBoldDatabaseAdapterDOA.GetDataBase: TOracleSession; @@ -55,7 +58,7 @@ function TBoldDatabaseAdapterDOA.GetDataBase: TOracleSession; function TBoldDatabaseAdapterDOA.GetDataBaseInterface: IBoldDatabase; begin if not assigned(Database) then - raise EBold.CreateFmt(sAdapterNotConnected, [classname]); + raise EBold.CreateFmt('%s.GetDatabaseInterface: The adapter is not connected to an OracleSession', [classname]); if not assigned(fBoldDatabase) then fBoldDatabase := TBoldDOADataBase.create(Database, SQLDataBaseConfig); result := fBoldDatabase; @@ -71,4 +74,6 @@ procedure TBoldDatabaseAdapterDOA.SetDataBase(const Value: TOracleSession); InternalDatabase := value; end; +initialization + end. diff --git a/Source/Persistence/DOA/BoldPersistenceHandleDOA.pas b/Source/Persistence/DOA/BoldPersistenceHandleDOA.pas index f3fbfef..fef9518 100644 --- a/Source/Persistence/DOA/BoldPersistenceHandleDOA.pas +++ b/Source/Persistence/DOA/BoldPersistenceHandleDOA.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldPersistenceHandleDOA; interface @@ -24,7 +27,7 @@ TBoldPersistenceHandleDOA = class(TBoldDBPersistenceHandle) procedure SetPassword(const Value: string); override; procedure SetUserName(const Value: string); override; public - destructor Destroy; override; + destructor destroy; override; function GetDataBaseInterface: IBoldDatabase; override; published property OracleSession: TOracleSession read fOracleSession write SetOracleSession; @@ -33,7 +36,8 @@ TBoldPersistenceHandleDOA = class(TBoldDBPersistenceHandle) implementation uses - SysUtils; + SysUtils, + BoldRev; { TBoldPersistenceHandleDOA } @@ -49,12 +53,13 @@ function TBoldPersistenceHandleDOA.GetDataBaseInterface: IBoldDatabase; if not assigned(fDataBaseAdapter) then begin if not assigned(fOracleSession) then - raise Exception.CreateFmt(sNoOracleSession, [classname]); + raise Exception.CreateFmt('%s.GetDatabaseInterface: There is no OracleSession, can''t create a database interface', [classname]); fDataBaseAdapter := TBoldDOADataBase.create(fOracleSession, SQLDataBaseConfig); end; result := fDataBaseAdapter; end; + procedure TBoldPersistenceHandleDOA.Notification(AComponent: TComponent; Operation: TOperation); begin @@ -71,7 +76,7 @@ procedure TBoldPersistenceHandleDOA.SetOracleSession(const NewValue: TOracleSess begin if fOracleSession <> NewValue then begin - CheckInactive('SetDataBase'); // do not localize + CheckInactive('SetDataBase'); fOracleSession := NewValue; if assigned(fOracleSession) then fOracleSession.FreeNotification(self); @@ -80,12 +85,14 @@ procedure TBoldPersistenceHandleDOA.SetOracleSession(const NewValue: TOracleSess procedure TBoldPersistenceHandleDOA.SetPassword(const Value: string); begin - raise Exception.CreateFmt(sSetOnOracleSession, [classname, 'SetPassword']); // do not localize + raise Exception.CreateFmt('%s.SetPassword: Not supported, set the password directly on your OracleSession-object', [classname]); end; procedure TBoldPersistenceHandleDOA.SetUserName(const Value: string); begin - raise Exception.CreateFmt(sSetOnOracleSession, [classname, 'SetUserName']); // do not localize + raise Exception.CreateFmt('%s.SetUserName: Not supported, set the Username directly on your OracleSession-object', [classname]); end; +initialization + end. diff --git a/Source/Persistence/DOA/BoldPersistenceHandleDOAReg.pas b/Source/Persistence/DOA/BoldPersistenceHandleDOAReg.pas index 32c855c..3911447 100644 --- a/Source/Persistence/DOA/BoldPersistenceHandleDOAReg.pas +++ b/Source/Persistence/DOA/BoldPersistenceHandleDOAReg.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldPersistenceHandleDOAReg; interface @@ -11,16 +14,22 @@ implementation uses Classes, SysUtils, - BoldDatabaseAdapterDOA, BoldPersistenceHandleDOA, BoldIDESupport, + BoldVersionInfo, + BoldDatabaseAdapterDOA, BoldIDEConsts; procedure Register; begin - RemovePackageFromDisabledPackagesRegistry(format('BoldDOA%s', [LIBSUFFIX])); // do not localize + RemovePackageFromDisabledPackagesRegistry(format('Bold%d%d%sDOA', [ + BoldBuildVersionNumberMajor, + BoldBuildVersionNumberMinor, + BoldBuildTarget])); RegisterComponents(BOLDPAGENAME_DEPRECATED, [TBoldPersistenceHandleDOA]); RegisterComponents(BOLDPAGENAME_PERSISTENCE, [TBoldDatabaseAdapterDOA]); end; +initialization + end. diff --git a/Source/Persistence/DOA/DOAConsts.pas b/Source/Persistence/DOA/DOAConsts.pas index 7e3e449..3a6216e 100644 --- a/Source/Persistence/DOA/DOAConsts.pas +++ b/Source/Persistence/DOA/DOAConsts.pas @@ -17,4 +17,4 @@ interface implementation -end. \ No newline at end of file +end. diff --git a/Source/Persistence/ExternalPersistence/BoldAbstractExternalPersistenceController.pas b/Source/Persistence/ExternalPersistence/BoldAbstractExternalPersistenceController.pas index c7c5f21..ad5eacf 100644 --- a/Source/Persistence/ExternalPersistence/BoldAbstractExternalPersistenceController.pas +++ b/Source/Persistence/ExternalPersistence/BoldAbstractExternalPersistenceController.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldAbstractExternalPersistenceController; interface @@ -21,7 +24,7 @@ TBoldAbstractExternalPersistenceController = class(TBoldPersistenceControllerP FOnStartUpdates: TNotifyEvent; FOnEndUpdates: TNotifyEvent; fOnFailUpdates: TNotifyEvent; - + fUpdateBoldDatabaseFirst: boolean; procedure SplitObjects(ObjectIdList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; ObjectsToPassAlong, ObjectsToHandle: TBoldObjectIdList; var CommonClass: TMoldClass); protected procedure PrepareFetch(ObjectIdList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; MoldClass: TMoldClass; MemberIdList: TBoldMemberIdList; var FetchContext: TObject); virtual; @@ -45,14 +48,14 @@ TBoldAbstractExternalPersistenceController = class(TBoldPersistenceControllerP property MaxFetchBlockSize: integer read GetMaxFetchBlockSize; public - constructor Create(MoldModel: TMoldModel; TypeNameDictionary: TBoldTypeNameDictionary; OnStartUpdates, OnEndUpdates, OnFailUpdates: TNotifyEvent); - procedure PMExactifyIds(ObjectIdList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList); override; + constructor Create(MoldModel: TMoldModel; TypeNameDictionary: TBoldTypeNameDictionary; OnStartUpdates, OnEndUpdates, OnFailUpdates: TNotifyEvent; AUpdateBoldDatabaseFirst: boolean); + procedure PMExactifyIds(ObjectIdList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList; HandleNonExisting: Boolean); override; procedure PMFetch(ObjectIdList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; MemberIdList: TBoldMemberIdList; FetchMode: Integer; BoldClientID: TBoldClientID); override; procedure PMFetchIDListWithCondition(ObjectIdList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; FetchMode: Integer; Condition: TBoldCondition; BoldClientID: TBoldClientID); override; - procedure PMUpdate(ObjectIdList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; Old_Values: IBoldValueSpace; Precondition: TBoldUpdatePrecondition; TranslationList: TBoldIdTranslationList; var TimeStamp: TBoldTimeStampType; BoldClientID: TBoldClientID); override; + procedure PMUpdate(ObjectIdList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; Old_Values: IBoldValueSpace; Precondition: TBoldUpdatePrecondition; TranslationList: TBoldIdTranslationList; var TimeStamp: TBoldTimeStampType; var TimeOfLatestUpdate: TDateTime; BoldClientID: TBoldClientID); override; function KeyForObject(ObjectContents: IBoldObjectContents): IBoldValue; function ValueForObject(ObjectContents: IBoldObjectContents; MemberExpressionName: string): IBoldValue; - + property UpdateBoldDatabaseFirst: boolean read fUpdateBoldDatabaseFirst; end; @@ -66,7 +69,7 @@ implementation { TBoldAbstractExternalPersistenceController } -constructor TBoldAbstractExternalPersistenceController.Create(MoldModel: TMoldModel; TypeNameDictionary: TBoldTypeNameDictionary; OnStartUpdates, OnEndUpdates, OnFailUpdates: TNotifyEvent); +constructor TBoldAbstractExternalPersistenceController.Create(MoldModel: TMoldModel; TypeNameDictionary: TBoldTypeNameDictionary; OnStartUpdates, OnEndUpdates, OnFailUpdates: TNotifyEvent; AUpdateBoldDatabaseFirst: boolean); begin inherited Create; fMoldModel := MoldModel; @@ -75,11 +78,12 @@ constructor TBoldAbstractExternalPersistenceController.Create(MoldModel: TMoldMo FOnStartUpdates := OnStartUpdates; fOnFailUpdates := OnFailUpdates; FOnEndUpdates := OnEndUpdates; + FUpdateBoldDatabaseFirst := AUpdateBoldDatabaseFirst; end; procedure TBoldAbstractExternalPersistenceController.PMExactifyIds( ObjectIdList: TBoldObjectIdList; - TranslationList: TBoldIdTranslationList); + TranslationList: TBoldIdTranslationList; HandleNonExisting: Boolean); begin inherited; end; @@ -117,12 +121,13 @@ procedure TBoldAbstractExternalPersistenceController.PMFetch( if MembersToHandle.Count = 0 then ObjectsToHandle.Clear; end; - - // only call inherited fetch if there is anything to fetch from the internal database if (ObjectsToPassAlong.Count > 0) and (not assigned(MembersToPAssAlong) or (MembersToPassAlong.Count > 0)) then inherited PMFetch(ObjectsToPassAlong, Valuespace, MembersToPassAlong, FetchMode, BoldClientId); - EnsureObjectsforFetch(ObjectsToHandle, ValueSpace, MembersToHandle); - FetchObjects(ObjectsToHandle, ValueSpace, MembersToHandle); + if ObjectsToHandle.count > 0 then + begin + EnsureObjectsforFetch(ObjectsToHandle, ValueSpace, MembersToHandle); + FetchObjects(ObjectsToHandle, ValueSpace, MembersToHandle); + end; end; procedure TBoldAbstractExternalPersistenceController.PMFetchIDListWithCondition( @@ -148,7 +153,7 @@ procedure TBoldAbstractExternalPersistenceController.PMUpdate( ObjectIdList: TBoldObjectIdList; ValueSpace, Old_Values: IBoldValueSpace; Precondition: TBoldUpdatePrecondition; TranslationList: TBoldIdTranslationList; - var TimeStamp: TBoldTimeStampType; BoldClientID: TBoldClientID); + var TimeStamp: TBoldTimeStampType; var TimeOfLatestUpdate: TDateTime; BoldClientID: TBoldClientID); var i: integer; ObjectsToHandle, @@ -157,7 +162,7 @@ procedure TBoldAbstractExternalPersistenceController.PMUpdate( SuperClass: TMoldClass; ObjectsToCreate, ObjectsToDelete, ObjectsToUpdate: TBoldObjectidList; ObjectContents: IBoldObjectContents; - + lNeedsExternalTransaction: boolean; begin Guard := TBoldGuard.Create( ObjectsToHandle, ObjectsToPassAlong, @@ -183,16 +188,38 @@ procedure TBoldAbstractExternalPersistenceController.PMUpdate( end else ObjectsToUpdate.Add(ObjectsTohandle[i]); end; - StartUpdates; + lNeedsExternalTransaction := ((ObjectsToCreate.Count + ObjectsToDelete.count + ObjectsToUpdate.count) > 0); + if lNeedsExternalTransaction then + begin + StartUpdates; + StartTransaction; + end; try + if UpdateBoldDatabaseFirst then + begin + inherited PMUpdate(ObjectsToPassAlong, ValueSpace, Old_Values, Precondition, TranslationList, TimeStamp, TimeOfLatestUpdate, BoldClientId); + ObjectsToCreate.ApplyTranslationList(TranslationList); + end; CreateObjects(ObjectsToCreate, ValueSpace); DeleteObjects(ObjectsToDelete, ValueSpace); UpdateObjects(ObjectsToUpdate, ValueSpace); - - inherited PMUpdate(ObjectsToPassAlong, ValueSpace, Old_Values, Precondition, TranslationList, TimeStamp, BoldClientId); - EndUpdates; + if not UpdateBoldDatabaseFirst then + begin + inherited PMUpdate(ObjectsToPassAlong, ValueSpace, Old_Values, Precondition, TranslationList, TimeStamp, TimeOfLatestUpdate, BoldClientId); + end; + if lNeedsExternalTransaction then + begin + EndUpdates; + CommitTransaction; + end; except - FailUpdates; + if lNeedsExternalTransaction then + try + FailUpdates; + finally + RollbackTransaction; + end; + raise; end; end; @@ -352,7 +379,7 @@ procedure TBoldAbstractExternalPersistenceController.FetchObjects( ActionList: TBoldObjectIdList; FetchContext: TObject; MoldClass: TMoldClass; - + procedure AddToActionList(index: integer); begin ActionList.Add(IdList[index]); @@ -363,7 +390,7 @@ procedure TBoldAbstractExternalPersistenceController.FetchObjects( ActionList := TBoldObjectIdList.Create; TranslationList := TBoldIdTranslationList.Create; - PMExactifyIds(ObjectIdList, TranslationList); + PMExactifyIds(ObjectIdList, TranslationList, false); IdList := ObjectIdList.Clone; IdList.ApplyTranslationList(TranslationList); @@ -392,12 +419,10 @@ procedure TBoldAbstractExternalPersistenceController.FetchObjects( procedure TBoldAbstractExternalPersistenceController.PostFetch( FetchContext: TObject; MoldClass: TMoldClass); begin - // intentionally left blank end; procedure TBoldAbstractExternalPersistenceController.PrepareFetch(ObjectIdList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; MoldClass: TMoldClass; MemberIdList: TBoldMemberIdList; var FetchContext: TObject); begin - // intentionally left blank end; function TBoldAbstractExternalPersistenceController.GetMaxFetchBlockSize: integer; @@ -411,4 +436,6 @@ procedure TBoldAbstractExternalPersistenceController.FailUpdates; fOnFailUpdates(self); end; +initialization + end. diff --git a/Source/Persistence/ExternalPersistence/BoldAbstractExternalPersistenceHandle.pas b/Source/Persistence/ExternalPersistence/BoldAbstractExternalPersistenceHandle.pas index 5f602b0..80945dc 100644 --- a/Source/Persistence/ExternalPersistence/BoldAbstractExternalPersistenceHandle.pas +++ b/Source/Persistence/ExternalPersistence/BoldAbstractExternalPersistenceHandle.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldAbstractExternalPersistenceHandle; interface @@ -9,6 +12,7 @@ interface BoldPersistenceHandlePTWithModel, BoldAbstractExternalPersistenceController; + type TBoldAbstractExternalPersistenceHandle = class(TBoldPersistenceHandlePassthroughWithModel) private @@ -17,6 +21,7 @@ TBoldAbstractExternalPersistenceHandle = class(TBoldPersistenceHandlePassthrou fOnFailUpdates: TNotifyEvent; FOnActivate: TNotifyEvent; FOnDeActivate: TNotifyEvent; + FUpdateBoldDatabaseFirst: boolean; function GetPersistenceController: TBoldAbstractExternalPersistenceController; protected procedure SetActive(Value: Boolean); override; @@ -36,13 +41,16 @@ TBoldAbstractExternalPersistenceHandle = class(TBoldPersistenceHandlePassthrou function IntValueForObject(ObjectContents: IBoldObjectContents; MemberExpressionName: string): Integer; function GetReferredObject(ObjectContents: IBoldObjectContents; MemberExpressionName: string; ValueSpace: IBoldValueSpace): IBoldObjectContents; property PersistenceController: TBoldAbstractExternalPersistenceController read GetPersistenceController; + property UpdateBoldDatabaseFirst: boolean read FUpdateBoldDatabaseFirst write FUpdateBoldDatabaseFirst default false; end; + + implementation uses - BoldDefs, - ExPeConsts; + BoldDefs; + { TBoldAbstractExternalPersistenceHandle } @@ -57,7 +65,7 @@ function TBoldAbstractExternalPersistenceHandle.CurrencyValueForObject( if Value.QueryInterface(IBoldCurrencyContent, Currvalue) = S_OK then result := Currvalue.asCurrency else - raise EBold.createFmt(sValueNotCurrency, [classname, MemberExpressionName]); + raise EBold.createFmt('%s.CurrencyValueForObject: The value (%s) is not a currency', [classname, MemberExpressionName]); end; function TBoldAbstractExternalPersistenceHandle.DateValueForObject( @@ -71,7 +79,7 @@ function TBoldAbstractExternalPersistenceHandle.DateValueForObject( if Value.QueryInterface(IBoldDateContent, Datevalue) = S_OK then result := Datevalue.asDate else - raise EBold.createFmt(sValueNotDate, [classname, MemberExpressionName]); + raise EBold.createFmt('%s.DateValueForObject: The value (%s) is not a date', [classname, MemberExpressionName]); end; function TBoldAbstractExternalPersistenceHandle.GetPersistenceController: TBoldAbstractExternalPersistenceController; @@ -107,7 +115,7 @@ function TBoldAbstractExternalPersistenceHandle.IntValueForObject( if Value.QueryInterface(IBoldIntegerContent, Intvalue) = S_OK then result := Intvalue.asInteger else - raise EBold.createFmt(sValueNotInteger, [classname, MemberExpressionName]); + raise EBold.createFmt('%s.IntValueForObject: The value (%s) is not an integer', [classname, MemberExpressionName]); end; function TBoldAbstractExternalPersistenceHandle.KeyForObject(ObjectContents: IBoldObjectContents): IBoldValue; @@ -125,7 +133,7 @@ function TBoldAbstractExternalPersistenceHandle.KeyIntForObject( if Value.QueryInterface(IBoldIntegerContent, Intvalue) = S_OK then result := Intvalue.asInteger else - raise EBold.createFmt(sKeyNotInteger, [classname]); + raise EBold.createFmt('%s.KeyIntForObject: The key is not an integer', [classname]); end; function TBoldAbstractExternalPersistenceHandle.KeyStringForObject( @@ -138,7 +146,7 @@ function TBoldAbstractExternalPersistenceHandle.KeyStringForObject( if Value.QueryInterface(IBoldStringContent, Strvalue) = S_OK then result := (Value as IBoldStringContent).asString else - raise EBold.createFmt(sKeyNotString, [classname]); + raise EBold.createFmt('%s.KeyStringForObject: The key is not a string', [classname]); end; function TBoldAbstractExternalPersistenceHandle.StringValueForObject( @@ -153,7 +161,7 @@ function TBoldAbstractExternalPersistenceHandle.StringValueForObject( if Value.QueryInterface(IBoldStringContent, StrValue) = S_OK then result := StrValue.asString else - raise EBold.createFmt(sValueNotString, [classname, MemberExpressionName]); + raise EBold.createFmt('%s.StringValueForObject: The value (%s) is not is not a string', [classname, MemberExpressionName]); end; function TBoldAbstractExternalPersistenceHandle.ValueForObject( @@ -179,4 +187,7 @@ procedure TBoldAbstractExternalPersistenceHandle.SetActive(Value: Boolean); end; end; + +initialization + end. diff --git a/Source/Persistence/ExternalPersistence/BoldAbstractPartiallyExternalPC.pas b/Source/Persistence/ExternalPersistence/BoldAbstractPartiallyExternalPC.pas index 0b416ae..e19c699 100644 --- a/Source/Persistence/ExternalPersistence/BoldAbstractPartiallyExternalPC.pas +++ b/Source/Persistence/ExternalPersistence/BoldAbstractPartiallyExternalPC.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldAbstractPartiallyExternalPC; interface @@ -18,6 +21,7 @@ TBoldAbstractPartiallyExternalPC = class(TBoldAbstractExternalPersistenceContr fDeletedExternalObjects: TBoldObjectIdList; fNewExternalObjects: TBoldObjectIdList; protected + function FetchAllMembersWhenFetchingKey(MoldClass: TMoldClass): boolean; virtual; function ExternalKeyExistsInExternalStorage(MoldClass: TMoldClass; ExternalKey: TBoldObjectId): Boolean; virtual; procedure PrepareFetchExternal(ExternalKeys: TBoldObjectIdList; ValueSpace: IBoldValueSpace; MoldClass: TMoldClass; MemberIdList: TBoldMemberIdList; var FetchContext: TObject); virtual; procedure PrepareFetch(ObjectIdList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; MoldClass: TMoldClass; MemberIdList: TBoldMemberIdList; var FetchContext: TObject); override; @@ -30,10 +34,11 @@ TBoldAbstractPartiallyExternalPC = class(TBoldAbstractExternalPersistenceContr procedure TranslateInternalIdsToExternal(InternalIds, ExternalKeys: TBoldObjectIdList; ValueSpace: IBoldValueSpace); function ExternalKeysToInternalSQL(MoldClass: TMoldClass; ExternalKeys: TBoldObjectIdList): String; virtual; procedure CreateInternalObject(MoldClass: TMoldClass; ExternalKey: TBoldObjectid; ValueSpace: IBoldValueSpace; Ids: TBoldObjectidList); + procedure CreateInternalObjects(MoldClass: TMoldClass; ExternalIDlist: TBoldObjectIdList; const ValueSpace: IBoldValueSpace; Ids: TBoldObjectidList); procedure FindMoldRoleByName(ObjectContents: IBoldObjectContents; ExpressionName: String; var MoldRole: TMoldRole; var Index: integer); public - constructor Create(MoldModel: TMoldModel; TypeNameDictionary: TBoldTypeNameDictionary; OnStartUpdates, OnEndUpdates, OnFailUpdates: TNotifyEvent); - destructor Destroy; override; + constructor Create(MoldModel: TMoldModel; TypeNameDictionary: TBoldTypeNameDictionary; OnStartUpdates, OnEndUpdates, OnFailUpdates: TNotifyEvent; AUpdateBoldDatabaseFirst: boolean); + destructor destroy; override; procedure SetMultiLink(MultiLink: IBoldObjectIdListref; ExternalKeys: TBoldObjectIdList; MoldClassOfOtherEnd: TMoldClass); procedure SetSingleLink(SingleLink: IBoldObjectIdRef; ExternalKey: TBoldObjectId; MoldClassOfOtherEnd: TMoldClass); procedure TranslateExternalKeysToInternalIds(MoldClass: TMoldClass; ExternalKeys, InternalIds: TBoldObjectIdList); @@ -42,7 +47,6 @@ TBoldAbstractPartiallyExternalPC = class(TBoldAbstractExternalPersistenceContr end; implementation - uses BoldGuard, SysUtils, @@ -51,12 +55,11 @@ implementation BoldDefs, BoldTaggedValueSupport, BoldFreeStandingValues, - BoldUtils, - ExPeConsts; - + BoldUtils; + { TBoldAbstractPartiallyExternalPC } -constructor TBoldAbstractPartiallyExternalPC.Create(MoldModel: TMoldModel; TypeNameDictionary: TBoldTypeNameDictionary; OnStartUpdates, OnEndUpdates, OnFailUpdates: TNotifyEvent); +constructor TBoldAbstractPartiallyExternalPC.Create(MoldModel: TMoldModel; TypeNameDictionary: TBoldTypeNameDictionary; OnStartUpdates, OnEndUpdates, OnFailUpdates: TNotifyEvent; AUpdateBoldDatabaseFirst: boolean); begin inherited; fDeletedExternalObjects := TBoldObjectIdList.Create; @@ -76,14 +79,13 @@ procedure TBoldAbstractPartiallyExternalPC.CreateInternalObject( Guard: IBoldGuard; UpdateIdList: TBoldObjectIdList; TimeStamp: Integer; + TimeOfTimeStamp: TDateTime; begin Guard := TBoldguard.Create(TranslationList, NewId, UpdateIdlist); TranslationList := TBoldIDTranslationList.Create; UpdateIdList := TBoldObjectIdList.Create; TopSortedIndex := MoldClass.TopSortedIndex; - - // FIXME: how can we be sure that the object is actually of the type MoldClass? NewId := TBoldInternalObjectId.CreateWithClassID(TopSortedIndex, MoldClass.SubClasses.Count = 0); NewObject := ValueSpace.GetEnsuredObjectContentsByObjectId(NewId); @@ -97,22 +99,66 @@ procedure TBoldAbstractPartiallyExternalPC.CreateInternalObject( end; NewObject.BoldPersistenceState := bvpsModified; NewObject.BoldExistenceState := besExisting; - - // insert the external key to the new object so that it can be saved to the internal database AssignKeyToObject(MoldClass, NewObject, ExternalKey, ValueSpace); NewObject := nil; UpdateIdList.Add(NewId); - NextPersistenceController.PMUpdate(UpdateIdList, ValueSpace, nil, nil, TranslationList, TimeStamp, -1); - - // return the translated ID! + NextPersistenceController.PMUpdate(UpdateIdList, ValueSpace, nil, nil, TranslationList, TimeStamp, TimeOfTimeStamp, -1); Id := TranslationList.TranslateToNewId[NewId].Clone; Ids.Add(Id); - - // indicate that this is a newly created object if anyone wants to initialize any internal-attributes. NewExternalObjects.Add(Id); end; +procedure TBoldAbstractPartiallyExternalPC.CreateInternalObjects( + MoldClass: TMoldClass; ExternalIDlist: TBoldObjectIdList; + const ValueSpace: IBoldValueSpace; Ids: TBoldObjectidList); +var + i: integer; + j: integer; + TopSortedIndex: integer; + NewId: TBoldObjectId; + TranslationList: TBoldIDTranslationList; + NewObject: IBoldObjectContents; + Id: TBoldObjectId; + Guard: IBoldGuard; + UpdateIdList: TBoldObjectIdList; + TimeStamp: Integer; + TimeOfTimeStamp: TDateTime; +begin + Guard := TBoldguard.Create(TranslationList, NewId, UpdateIdlist); + TranslationList := TBoldIDTranslationList.Create; + UpdateIdList := TBoldObjectIdList.Create; + + TopSortedIndex := MoldClass.TopSortedIndex; + for i := 0 to ExternalIDlist.Count - 1 do + begin + NewId := TBoldInternalObjectId.CreateWithClassID(TopSortedIndex, MoldClass.SubClasses.Count = 0); + NewObject := ValueSpace.GetEnsuredObjectContentsByObjectId(NewId); + for j := 0 to MoldClass.AllBoldMembers.Count-1 do + begin + if MoldClass.AllBoldMembers[j].Storage in [bsInternal, bsExternalKey] then + begin + EnsureMember(NewObject, MoldClass.AllBoldMembers[j], j); + NewObject.ValueByIndex[j].BoldPersistenceState := bvpsModified; + end; + end; + NewObject.BoldPersistenceState := bvpsModified; + NewObject.BoldExistenceState := besExisting; + AssignKeyToObject(MoldClass, NewObject, ExternalIDlist[i], ValueSpace); + NewObject := nil; + UpdateIdList.Add(NewId); + end; + + NextPersistenceController.PMUpdate(UpdateIdList, ValueSpace, nil, nil, TranslationList, TimeStamp, TimeOfTimeStamp, -1); + + for i := 0 to ExternalIDlist.Count - 1 do + begin + Id := TranslationList.TranslateToNewId[NewId].Clone; + Ids.Add(Id); + NewExternalObjects.Add(Id); + end; +end; + destructor TBoldAbstractPartiallyExternalPC.destroy; begin FreeAndNil(fDeletedExternalObjects); @@ -133,14 +179,14 @@ function TBoldAbstractPartiallyExternalPC.ExternalKeysToInternalSQL( if (MoldClass.AllBoldMembers[i] is TMoldAttribute) and (MoldClass.AllBoldMembers[i].Storage = bsExternalKey) then begin if assigned(ExternalKey) then - raise EBold.CreateFmt(sNotSupportedWithMultipleKeys, [classname, MoldClass.ExpandedExpressionName]) + raise EBold.CreateFmt('%s.ExternalKeysToInternalSQL: Automatic SQL-generation only supported for classes with 1 (one) external key (class %s has multiple)', [classname, MoldClass.ExpandedExpressionName]) else ExternalKey := MoldClass.AllBoldMembers[i] as TMoldAttribute; end; if not assigned(ExternalKey) then - raise EBold.CreateFmt(sNotSupportedWithNoKeys, [classname, MoldClass.ExpandedExpressionName]); + raise EBold.CreateFmt('%s.ExternalKeysToInternalSQL: Automatic SQL-generation only supported for classes with 1 (one) external key (class %s has none!)', [classname, MoldClass.ExpandedExpressionName]); - result := format('%s.%s in (', [ // do not localize + result := format('%s.%s in (', [ BoldExpandName(ExternalKey.MoldClass.Tablename, ExternalKey.MoldClass.Name, xtSQL, -1, nccFalse), BoldExpandName(ExternalKey.ColumnName, ExternalKey.name, xtSQL, -1, nccFalse)]); Mapping := TypeNameDictionary.MappingForModelName[ExternalKey.BoldType]; @@ -157,6 +203,11 @@ function TBoldAbstractPartiallyExternalPC.ExternalKeysToInternalSQL( result := result + ')'; end; +function TBoldAbstractPartiallyExternalPC.FetchAllMembersWhenFetchingKey(MoldClass: TMoldClass): boolean; +begin + result := false; +end; + procedure TBoldAbstractPartiallyExternalPC.FetchExternalKeysForIDs( InternalObjectIdList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; MoldClass: TMoldClass); @@ -166,11 +217,19 @@ procedure TBoldAbstractPartiallyExternalPC.FetchExternalKeysForIDs( guard: IBoldGuard; begin Guard := TBoldGuard.Create(MemberIdList); - MemberIdList := tBoldMemberIdList.Create; - for i := 0 to MoldClass.AllBoldMembers.count-1 do - if MoldClass.AllBoldMembers[i].Storage = bsExternalKey then - MemberIdList.Add(TBoldMemberId.Create(i)); - NextPersistenceController.PMFetch(InternalObjectIdList, ValueSpace, MemberIdList, fmNormal, -1); + if FetchAllMembersWhenFetchingKey(MoldClass) then + begin + NextPersistenceController.PMFetch(InternalObjectIdList, ValueSpace, nil, fmNormal, -1); + end + else + begin + MemberIdList := TBoldMemberIdList.Create; + for i := 0 to MoldClass.AllBoldMembers.count-1 do + if MoldClass.AllBoldMembers[i].Storage = bsExternalKey then + MemberIdList.Add(TBoldMemberId.Create(i)); + if MemberIdList.count > 0 then + NextPersistenceController.PMFetch(InternalObjectIdList, ValueSpace, MemberIdList, fmNormal, -1); + end; end; procedure TBoldAbstractPartiallyExternalPC.FindMoldRoleByName(ObjectContents: IBoldObjectContents; @@ -191,7 +250,7 @@ procedure TBoldAbstractPartiallyExternalPC.FindMoldRoleByName(ObjectContents: IB end; end; if index = -1 then - raise EBold.CreateFmt(sNoSuchRole, [ClassNAme, ExpressionName, MoldClass.ExpandedExpressionName]); + raise EBold.CreateFmt('%s.FindMoldRoleByName: There is no role called %s in class %s', [ClassNAme, ExpressionName, MoldClass.ExpandedExpressionName]); end; procedure TBoldAbstractPartiallyExternalPC.HandleAllInstances( @@ -209,13 +268,8 @@ procedure TBoldAbstractPartiallyExternalPC.HandleAllInstances( TempvalueSpace := TBoldFreeStandingvalueSpace.Create; InternalObjectIdList := TBoldObjectidList.create; ExternalKeys := TBoldObjectIdList.create; - - // send the condition query to the internal database and fetch the objects to a local valuespace NextPersistenceController.PMFetchIDListWithCondition(InternalObjectIdList, TempValueSpace, fmNormal, Condition, -1); - // Get the external keys GetExternalKeys(MoldClass, ExternalKeys); - - // match the external keys and the internal objects. MatchObjectsByKeys(MoldClass, TempValueSpace, InternalObjectIdList, ExternalKeys, ObjectIdList); end; @@ -227,19 +281,18 @@ procedure TBoldAbstractPartiallyExternalPC.MatchObjectsByKeys(MoldClass: TMoldCl TranslationList: TBoldIdTranslationList; ObjectContents: IBoldObjectContents; Guard: IBoldGuard; + lNotFoundObjects: TBoldObjectIdList; begin - // The Internal ids and External keys should be expected to contain references to the same objects. - - Guard := TBoldguard.Create(TranslationList); + Guard := TBoldguard.Create(TranslationList, lNotFoundObjects); + lNotFoundObjects:= TBoldObjectIdList.Create; FetchExternalKeysForIDs(InternalIds, ValueSpace, MoldClass); TranslationList := TBoldIdTranslationList.Create; for i := 0 to InternalIds.Count-1 do begin - ObjectContents := ValueSpace.ObjectContentsByObjectId[InternalIds[i]]; + ObjectContents := ValueSpace.EnsuredObjectContentsByObjectId[InternalIds[i]]; ExternalKey := GetExternalKeyFromObject(ObjectContents, ValueSpace); TranslationList.AddTranslation(ExternalKey, InternalIds[i]); - // Objects that have been deleted in external database are just logged... if not ExternalKeys.IdInList[ExternalKey] then DeletedExternalObjects.Add(InternalIds[i]); ExternalKey.Free; @@ -250,15 +303,15 @@ procedure TBoldAbstractPartiallyExternalPC.MatchObjectsByKeys(MoldClass: TMoldCl InternalId := TranslationList.TranslateToNewId[ExternalKeys[i]]; if assigned(InternalId) and (ExternalKeys[i] <> InternalId) then begin - // the objects that already exist in the internal database can be returned directly FoundObjects.Add(InternalId) end else begin - // the missing objects has to be created in the internal database - CreateInternalObject(MoldClass, ExternalKeys[i], ValueSpace, FoundObjects) + lNotFoundObjects.Add(ExternalKeys[i]); end; end; + if lNotFoundObjects.count > 0 then + CreateInternalObjects(MoldClass, lNotFoundObjects, ValueSpace, FoundObjects) end; function TBoldAbstractPartiallyExternalPC.ExternalKeyExistsInExternalStorage(MoldClass: TMoldClass; ExternalKey: TBoldObjectId): Boolean; @@ -281,12 +334,12 @@ procedure TBoldAbstractPartiallyExternalPC.PrepareFetch(ObjectIdList: TBoldObjec begin ObjectContents := ValueSpace.ObjectContentsByObjectId[ObjectIdList[i]]; ExternalKey := GetExternalKeyFromObject(ObjectContents, ValueSpace); - // only perform the existencetest if this is the default-fetch of an object - // when fetching custommembers we assume this test has already been performed + if not assigned(MemberIdList) or ExternalKeyExistsInExternalStorage(MoldClass, ExternalKey) then ExternalKeys.Add(ExternalKey) else DeletedExternalObjects.Add(ObjectIdList[i]); + ExternalKey.free; end; PrepareFetchExternal(ExternalKeys, ValueSpace, MoldClass, MemberIdList, FetchContext); end; @@ -296,7 +349,6 @@ procedure TBoldAbstractPartiallyExternalPC.PrepareFetchExternal( MoldClass: TMoldClass; MemberIdList: TBoldMemberIdList; var FetchContext: TObject); begin - // intentionally left blank end; procedure TBoldAbstractPartiallyExternalPC.SetMultiLink( @@ -316,7 +368,6 @@ procedure TBoldAbstractPartiallyExternalPC.SetSingleLink( ExternalKeys: TBoldObjectIdList; InternalIds: TBoldObjectIdList; begin - // set the member to point to the ID if assigned(ExternalKey) then begin ExternalKeys := TBoldObjectIdList.Create; @@ -324,12 +375,12 @@ procedure TBoldAbstractPartiallyExternalPC.SetSingleLink( InternalIds := TBoldObjectidList.Create; TranslateExternalKeysToInternalIds(MoldClassOfOtherEnd, ExternalKeys, InternalIds); if InternalIds.Count = 1 then - SingleLink.SetFromId(InternalIds[0]); + SingleLink.SetFromId(InternalIds[0], false); InternalIds.Free; ExternalKeys.Free; end else - SingleLink.SetFromId(nil); + SingleLink.SetFromId(nil, false); end; procedure TBoldAbstractPartiallyExternalPC.TranslateExternalKeysToInternalIds( @@ -385,5 +436,5 @@ procedure TBoldAbstractPartiallyExternalPC.TranslateInternalIdsToExternal( end; end; +initialization end. - diff --git a/Source/Persistence/ExternalPersistence/BoldAbstractPartiallyExternalPH.pas b/Source/Persistence/ExternalPersistence/BoldAbstractPartiallyExternalPH.pas index 931240f..fb10cc1 100644 --- a/Source/Persistence/ExternalPersistence/BoldAbstractPartiallyExternalPH.pas +++ b/Source/Persistence/ExternalPersistence/BoldAbstractPartiallyExternalPH.pas @@ -1,7 +1,9 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldAbstractPartiallyExternalPH; interface - uses BoldId, BoldMeta, @@ -37,8 +39,6 @@ implementation BoldDefaultId, BoldDefs, BoldGuard, - BoldPersistenceHandlePTWithModel, - ExPeConsts; { TBoldAbstractpartiallyExternalPH } @@ -78,7 +78,7 @@ function TBoldAbstractpartiallyExternalPH.GetObjectIdByExternalKey( Guard := TBoldGuard.Create(ExternalKeys, InternalIds); MoldClass := BoldModel.MoldModel.Classes.ItemsByExpressionName[ExpressionName]; if not assigned(MoldClass) then - raise EBold.CreateFmt(sInvalidClassName, [classname, expressionname]); + raise EBold.CreateFmt('%s.GetObjectIdByExternalKey: Invalid class name (%s)', [classname, expressionname]); ExternalKeys := TBoldObjectIdLIst.Create; InternalIds := TBoldObjectIdLIst.Create; ExternalKeys.Add(ExternalKey); @@ -127,4 +127,5 @@ procedure TBoldAbstractpartiallyExternalPH.SetSingleLink(SingleLink: IBoldObject PersistenceController.SetSingleLink(SingleLink, ExternalKey, MoldClassOfOtherEnd); end; +initialization end. diff --git a/Source/Persistence/ExternalPersistence/BoldExternalPersistenceConfigItemDataSet.pas b/Source/Persistence/ExternalPersistence/BoldExternalPersistenceConfigItemDataSet.pas index e36704c..6f7ed50 100644 --- a/Source/Persistence/ExternalPersistence/BoldExternalPersistenceConfigItemDataSet.pas +++ b/Source/Persistence/ExternalPersistence/BoldExternalPersistenceConfigItemDataSet.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldExternalPersistenceConfigItemDataSet; interface @@ -37,6 +40,10 @@ TBoldExternalPersistenceConfigDataSetItems = class(TBoldCollectionWithUniquely implementation +uses + BoldRev; + + constructor TBoldExternalPersistenceConfigDataSetItem.Create(AOwner: TCollection); begin inherited Create(AOwner); @@ -87,4 +94,6 @@ function TBoldExternalPersistenceConfigDataSetItems.GetItem( result := inherited GetItem(Index) as TBoldExternalPersistenceConfigDataSetItem; end; +initialization + end. diff --git a/Source/Persistence/ExternalPersistence/BoldExternalPersistenceControllerConfig.pas b/Source/Persistence/ExternalPersistence/BoldExternalPersistenceControllerConfig.pas index 284b8d2..b13dea1 100644 --- a/Source/Persistence/ExternalPersistence/BoldExternalPersistenceControllerConfig.pas +++ b/Source/Persistence/ExternalPersistence/BoldExternalPersistenceControllerConfig.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldExternalPersistenceControllerConfig; interface @@ -32,6 +35,7 @@ TBoldExternalPersistenceConfigItems = class; TBoldExternalPersistenceConfigItem = class(TBoldUniquelyNamedCollectionItemWithNameStorage) private + FFetchAllMembersWhenFetchingKey: boolean; FOnCreateObject: TBoldExternalPersistenceCreateEvent; FOnReadObject: TBoldExternalPersistenceFetchEvent; FOnUpdateObject: TBoldExternalPersistenceUpdateEvent; @@ -51,6 +55,7 @@ TBoldExternalPersistenceConfigItem = class(TBoldUniquelyNamedCollectionItemWit public published property ExpressionName: String read GetExpressionName write SetExpressionName; + property FetchAllMembersWhenFetchingKey: boolean read FFetchAllMembersWhenFetchingKey write FFetchAllMembersWhenFetchingKey default false; property OnCreateObject: TBoldExternalPersistenceCreateEvent read FOnCreateObject write FOnCreateObject; property OnReadObject: TBoldExternalPersistenceFetchEvent read FOnReadObject write FOnReadObject; property OnUpdateObject: TBoldExternalPersistenceUpdateEvent read FOnUpdateObject write FOnUpdateObject; @@ -78,6 +83,9 @@ TBoldExternalPersistenceConfigItems = class(TBoldCollectionWithUniquelyNamedIt implementation +uses + Boldrev; + { TBoldExternalPersistenceConfigItem } procedure TBoldExternalPersistenceConfigItem.SetExpressionName(const Value: String); @@ -117,4 +125,5 @@ function TBoldExternalPersistenceConfigItems.GetItem(Index: Integer): TBoldExter Result := inherited GetItem(Index) as TBoldExternalPersistenceConfigItem; end; +initialization end. diff --git a/Source/Persistence/ExternalPersistence/BoldExternalPersistenceControllerDataSet.pas b/Source/Persistence/ExternalPersistence/BoldExternalPersistenceControllerDataSet.pas index 176d485..9a3d000 100644 --- a/Source/Persistence/ExternalPersistence/BoldExternalPersistenceControllerDataSet.pas +++ b/Source/Persistence/ExternalPersistence/BoldExternalPersistenceControllerDataSet.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldExternalPersistenceControllerDataSet; interface @@ -20,6 +23,10 @@ TBoldExternalPersistenceControllerDataSet = class(TBoldAbstractPartiallyExtern fMaxFetchBlockSize: integer; protected function LocateInDB(MoldClass: TMoldClass; ObjectContents: IBoldObjectContents): TDataSet; + procedure PrepareFetchExternal(ExternalKeys: TBoldObjectIdList; + ValueSpace: IBoldValueSpace; MoldClass: TMoldClass; + MemberIdList: TBoldMemberIdList; var FetchContext: TObject); override; + procedure PostFetch(FetchContext: TObject; MoldClass: TMoldClass); override; function ConfigItemByObjectContents(ObjectContents: IBoldObjectContents): TBoldExternalPersistenceConfigDataSetItem; procedure FetchObject(ObjectContents: IBoldObjectContents; MemberIdList: TBoldMemberIdList; FetchContext: TObject; @@ -48,9 +55,11 @@ TBoldExternalPersistenceControllerDataSet = class(TBoldAbstractPartiallyExtern Config: TBoldExternalPersistenceConfigDataSetItems; TypeNameDictionary: TBoldTypeNameDictionary; OnStartUpdates, OnEndUpdates, OnFailUpdates: TNotifyEvent; MaxFetchBlockSize: integer); + procedure SubscribeToPeristenceEvents(Subscriber: TBoldSubscriber); override; property Config: TBoldExternalPersistenceConfigDataSetItems read fConfig; end; + implementation uses @@ -60,8 +69,7 @@ implementation BoldNameExpander, BoldValueInterfaces, BoldStringId, - BoldDefaultId, - ExPeConsts; + BoldDefaultId; function MemberIndexByName(MoldClass: TMoldClass; MemberName: String): Integer; begin @@ -195,7 +203,7 @@ function BoldValueToVariant(B: IBoldValue): Variant; Result := DT.asDateTime else if B.QueryInterface(IBoldBlobContent, BL) = S_OK then Result := BL.asBlob - else raise Exception.Create(sUnknownDataType); + else raise Exception.Create('Unknown data type'); end; procedure VariantToBoldValue(B: IBoldValue; Value: Variant); @@ -232,7 +240,7 @@ procedure VariantToBoldValue(B: IBoldValue; Value: Variant); DT.asDateTime := Value else if B.QueryInterface(IBoldBlobContent, BL) = S_OK then BL.asBlob := Value - else raise Exception.Create(sUnknownDataType); + else raise Exception.Create('Unknown data type'); end; procedure SetBoldValueToNull(B: IBoldValue); @@ -268,7 +276,7 @@ procedure SetBoldValueToNull(B: IBoldValue); DT.asDateTime := 0 else if B.QueryInterface(IBoldBlobContent, BL) = S_OK then BL.asBlob := '' - else raise Exception.Create(sUnknownDataType); + else raise Exception.Create('Unknown data type'); end; function GetKeyCount(MoldClass: TMoldClass): Integer; @@ -315,7 +323,7 @@ function GetObjectKeys(MoldClass: TMoldClass; ObjectContents: IBoldObjectContent constructor TBoldExternalPersistenceControllerDataSet.Create(MoldModel: TMoldModel; Config: TBoldExternalPersistenceConfigDataSetItems; TypeNameDictionary: TBoldTypeNameDictionary; OnStartUpdates, OnEndUpdates, OnFailUpdates: TNotifyEvent; MaxFetchBlockSize: integer); begin - inherited Create(MoldModel, TypeNameDictionary, OnStartUpdates, OnEndUpdates, OnFailUpdates); + inherited Create(MoldModel, TypeNameDictionary, OnStartUpdates, OnEndUpdates, OnFailUpdates, UpdateBoldDatabaseFirst); FConfig := Config; FMaxFetchBlockSize := MaxFetchBlockSize; end; @@ -421,7 +429,7 @@ procedure TBoldExternalPersistenceControllerDataSet.FetchObject( MultiLinkConfigItem := Config.FindExpressionName(MultiLinkClass.ExpandedExpressionName); if not Assigned(MultiLinkConfigItem) then - raise Exception.CreateFmt(sLinkToUnconfiguredTable, [MultiLinkClass.ExpandedExpressionName]); + raise Exception.CreateFmt('External link to unconfigured table %s', [MultiLinkClass.ExpandedExpressionName]); MultiLinkDataSet := MultiLinkConfigItem.DataSet; MultiLinkKeyName := RemovePreAt(MoldRole.OtherEnd); @@ -433,7 +441,7 @@ procedure TBoldExternalPersistenceControllerDataSet.FetchObject( for i := 0 to GetCharCount(';', MultiLinkKeyName) do begin if S <> '' then - S := S + ' and '; // do not localize + S := S + ' and '; S := S + '(' + GetNextWord(B, ';') + ' = ' + ConfigItem.DataSet.FieldByName(GetNextWord(A, ';')).AsString + ')'; end; @@ -451,7 +459,6 @@ procedure TBoldExternalPersistenceControllerDataSet.FetchObject( if not VarIsNull(DBValue) then begin ExternalKey := nil; - // the type of the field MUST match the type of the internal ID if VarType(DBValue) in [varInteger, varSmallint, varSingle, varDouble] then begin ExternalKey := TBoldDefaultId.Create; @@ -463,7 +470,7 @@ procedure TBoldExternalPersistenceControllerDataSet.FetchObject( TBoldStringId(ExternalKey).AsString := DBValue; end else - raise Exception.CreateFmt(sUnknownVarTypeLoadingID, [MoldClass.name, MoldRole.name]); + raise Exception.CreateFmt('Unknown vartype when loading an external ID for multilink %s.%s', [MoldClass.name, MoldRole.name]); MultiLinkList.Add(ExternalKey); ExternalKey.Free; @@ -496,7 +503,7 @@ procedure TBoldExternalPersistenceControllerDataSet.FetchObject( TBoldStringId(ExternalKey).AsString := DBValue; end else - raise Exception.CreateFmt(sUnknownVarTypeLoadingSingleID, [MoldClass.name, MoldRole.name]); + raise Exception.CreateFmt('Unknown vartype when loading an external ID for Singlelink %s.%s', [MoldClass.name, MoldRole.name]); if Value.QueryInterface(IBoldObjectIdRef, IDRef) = S_OK then SetSingleLink(IDRef, ExternalKey, MoldRole.OtherEnd.MoldClass); @@ -578,7 +585,7 @@ procedure TBoldExternalPersistenceControllerDataSet.GetExternalKeys(MoldClass: T TBoldStringId(ExternalId).AsString := DBValue; end else - raise Exception.CreateFmt(sUnknownVarTypeLoadingObject, [MoldClass.name]); + raise Exception.CreateFmt('Unknown vartype when loading an external ID for %s', [MoldClass.name]); ExternalKeys.Add(ExternalId); ExternalId.Free; ConfigItem.DataSet.Next; @@ -608,6 +615,11 @@ function TBoldExternalPersistenceControllerDataSet.ConfigItemByObjectContents( result := Config.FindExpressionName(MoldClass.ExpandedExpressionName); end; +procedure TBoldExternalPersistenceControllerDataSet.SubscribeToPeristenceEvents(Subscriber: TBoldSubscriber); +begin + inherited; +end; + procedure TBoldExternalPersistenceControllerDataSet.UpdateObjects( ObjectIdList: TBoldObjectIdList; ValueSpace: IBoldValueSpace); var @@ -672,7 +684,19 @@ function TBoldExternalPersistenceControllerDataSet.GetExternalKeyFromObject( TBoldStringId(Result).AsString := DBValue; end else - raise Exception.CreateFmt(sUnknownVarTypeLoadingObject, [MoldClass.name]); + raise Exception.CreateFmt('Unknown vartype when loading an external ID for %s', [MoldClass.name]); +end; + + +procedure TBoldExternalPersistenceControllerDataSet.PostFetch( + FetchContext: TObject; MoldClass: TMoldClass); +begin + inherited; +end; + +procedure TBoldExternalPersistenceControllerDataSet.PrepareFetchExternal(ExternalKeys: TBoldObjectIdList; ValueSpace: IBoldValueSpace; MoldClass: TMoldClass; MemberIdList: TBoldMemberIdList; var FetchContext: TObject); +begin + inherited; end; function TBoldExternalPersistenceControllerDataSet.GetMaxFetchBlockSize: integer; @@ -712,13 +736,13 @@ function TBoldExternalPersistenceControllerDataSet.ExternalKeysToInternalSQL(Mol Val(T, v, c); if c <> 0 then T := '''' + T + ''''; - SQL := SQL + '(' + GetNextWord(S, ';') + ' = ' + T + ') AND '; // do not localize + SQL := SQL + '(' + GetNextWord(S, ';') + ' = ' + T + ') AND '; end; if Length(SQL) > 1 then SetLength(SQL, Length(SQL)-5); SQL := SQL + ')'; - Result := Result + SQL + ' OR '; // do not localize + Result := Result + SQL + ' OR '; end; if Length(Result) > 0 then @@ -748,7 +772,7 @@ procedure TBoldExternalPersistenceControllerDataSet.AssignKeyToObject( else if KeyValue.QueryInterface(IBoldIntegerContent, IntContent) = S_OK then IntContent.AsInteger := StrToInt(GetNextWord(S, ';')) else - raise EBold.createFmt(sKeyTypeNotAutoHandled, [MoldClass.Name, MoldClass.AllBoldMembers[i].Name]); + raise EBold.createFmt('Keytype not handled automatically: %s.%s', [MoldClass.Name, MoldClass.AllBoldMembers[i].Name]); end; end; end; @@ -772,4 +796,6 @@ function TBoldExternalPersistenceControllerDataSet.LocateInDB( end; end; +initialization + end. diff --git a/Source/Persistence/ExternalPersistence/BoldExternalPersistenceControllerEventDriven.pas b/Source/Persistence/ExternalPersistence/BoldExternalPersistenceControllerEventDriven.pas index d4149ee..ccb7468 100644 --- a/Source/Persistence/ExternalPersistence/BoldExternalPersistenceControllerEventDriven.pas +++ b/Source/Persistence/ExternalPersistence/BoldExternalPersistenceControllerEventDriven.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldExternalPersistenceControllerEventDriven; interface @@ -18,8 +21,9 @@ TBoldExternalPersistenceControllerEventDriven = class(TBoldAbstractPartiallyEx private FConfig: TBoldExternalPersistenceConfigItems; fMaxFetchBlockSize: integer; - function PersistentObjectFromObjectContents(Obj: IBoldObjectContents; ValueSpace: IBoldValueSpace; MoldClass: TMoldClass): IPersistentBoldObject; + function PersistentObjectFromObjectContents(const Obj: IBoldObjectContents; const ValueSpace: IBoldValueSpace; MoldClass: TMoldClass): IPersistentBoldObject; protected + function FetchAllMembersWhenFetchingKey(MoldClass: TMoldClass): boolean; override; procedure PrepareFetchExternal(ExternalKeys: TBoldObjectIdList; ValueSpace: IBoldValueSpace; MoldClass: TMoldClass; MemberIdList: TBoldMemberIdList; var FetchContext: TObject); override; procedure PostFetch(FetchContext: TObject; MoldClass: TMoldClass); override; function ConfigItemByObjectContents(ObjectContents: IBoldObjectContents): TBoldExternalPersistenceConfigItem; @@ -35,7 +39,7 @@ TBoldExternalPersistenceControllerEventDriven = class(TBoldAbstractPartiallyEx procedure UpdateObjects(ObjectIdList: TBoldObjectIdList; ValueSpace: IBoldValueSpace); override; function GetMaxFetchBlockSize: integer; override; public - constructor Create(MoldModel: TMoldModel; Config: TBoldExternalPersistenceConfigItems; TypeNameDictionary: TBoldTypeNameDictionary; OnStartUpdates, OnEndUpdates, OnFailUpdates: TNotifyEvent; MaxFetchBlockSize: integer); + constructor Create(MoldModel: TMoldModel; Config: TBoldExternalPersistenceConfigItems; TypeNameDictionary: TBoldTypeNameDictionary; OnStartUpdates, OnEndUpdates, OnFailUpdates: TNotifyEvent; MaxFetchBlockSize: integer; UpdateBoldDatabaseFirst: boolean); procedure SubscribeToPeristenceEvents(Subscriber: TBoldSubscriber); override; property Config: TBoldExternalPersistenceConfigItems read fConfig; end; @@ -48,8 +52,7 @@ implementation BoldDefs, BoldValueInterfaces, BoldStringId, - BoldDefaultId, - ExPeConsts; + BoldDefaultId; { TBoldExternalPersistenceControllerEventDriven } @@ -61,7 +64,6 @@ procedure TBoldExternalPersistenceControllerEventDriven.AssignKeyToObject(MoldCl IntContent: IBoldIntegerContent; ConfigItem: TBoldExternalPersistenceConfigItem; begin - // Make sure that the object contains the data of the external key ConfigItem := Config.FindExpressionName(MoldClass.ExpandedExpressionName); if assigned(ConfigItem.OnAssignKeyToObject) then ConfigItem.OnAssignKeyToObject(PersistentObjectFromObjectContents(ObjectContents, ValueSpace, MoldClass), ExternalKey) @@ -73,7 +75,7 @@ procedure TBoldExternalPersistenceControllerEventDriven.AssignKeyToObject(MoldCl if MoldClass.AllBoldMembers[i].Storage = bsExternalKey then begin if assigned(Keyvalue) then - raise EBold.createFmt(sAssignKeyValueRequiresOneKey, [MoldClass.Name]); + raise EBold.createFmt('AssignKeyValue only supported automatically for classes with one external key: %s', [MoldClass.Name]); KeyValue := ObjectContents.ValueByIndex[i]; if KeyValue.QueryInterface(IBoldStringContent, StrContent) = S_OK then @@ -81,15 +83,15 @@ procedure TBoldExternalPersistenceControllerEventDriven.AssignKeyToObject(MoldCl else if KeyValue.QueryInterface(IBoldIntegerContent, IntContent) = S_OK then IntContent.AsInteger := StrToInt(ExternalKey.AsString) else - raise EBold.createFmt(sKeyTypeNotAutoHandled, [MoldClass.Name, MoldClass.AllBoldMembers[i].Name]); + raise EBold.createFmt('Keytype not handled automatically: %s.%s', [MoldClass.Name, MoldClass.AllBoldMembers[i].Name]); end; end; end; end; -constructor TBoldExternalPersistenceControllerEventDriven.Create(MoldModel: TMoldModel; Config: TBoldExternalPersistenceConfigItems; TypeNameDictionary: TBoldTypeNameDictionary; OnStartUpdates, OnEndUpdates, OnFailUpdates: TNotifyEvent; MaxFetchBlockSize: integer); +constructor TBoldExternalPersistenceControllerEventDriven.Create(MoldModel: TMoldModel; Config: TBoldExternalPersistenceConfigItems; TypeNameDictionary: TBoldTypeNameDictionary; OnStartUpdates, OnEndUpdates, OnFailUpdates: TNotifyEvent; MaxFetchBlockSize: integer; UpdateBoldDatabaseFirst: boolean); begin - inherited Create(MoldModel, TypeNameDictionary, OnStartUpdates, OnEndUpdates, OnFailUpdates); + inherited Create(MoldModel, TypeNameDictionary, OnStartUpdates, OnEndUpdates, OnFailUpdates, UpdateBoldDatabaseFirst); fConfig := Config; fMaxFetchBlockSize := MaxFetchBlockSize; end; @@ -111,12 +113,13 @@ procedure TBoldExternalPersistenceControllerEventDriven.CreateObjects( if assigned(ConfigItem) then begin if not assigned(ConfigItem.OnCreateObject) then - raise EBold.CreateFmt(sCreateObjectsNotAllowed, [ConfigItem.ExpressionName]); + raise EBold.CreateFmt('Creating new objects of type %s not supported/allowed', [ConfigItem.ExpressionName]); ExternalKey := GetExternalKeyFromObject(ObjectContents, ValueSpace); ConfigItem.OnCreateObject(PersistentObjectFromObjectContents(ObjectContents, ValueSpace, MoldClass), ExternalKey, ValueSpace); ExternalKey.Free; end; end; + end; procedure TBoldExternalPersistenceControllerEventDriven.DeleteObjects( @@ -136,7 +139,7 @@ procedure TBoldExternalPersistenceControllerEventDriven.DeleteObjects( if assigned(ConfigItem) then begin if not assigned(ConfigItem.OnDeleteObject) then - raise EBold.CreateFmt(sDeleteObjectsNotAllowed, [ConfigItem.ExpressionName]); + raise EBold.CreateFmt('Deleting objects of type %s not supported/allowed', [ConfigItem.ExpressionName]); ExternalKey := GetExternalKeyFromObject(ObjectContents, valueSpace); ConfigItem.OnDeleteObject(PersistentObjectFromObjectContents(ObjectContents, ValueSpace, MoldClass), ExternalKey); ExternalKey.Free; @@ -144,6 +147,15 @@ procedure TBoldExternalPersistenceControllerEventDriven.DeleteObjects( end; end; +function TBoldExternalPersistenceControllerEventDriven.FetchAllMembersWhenFetchingKey( + MoldClass: TMoldClass): boolean; +var + lConfigItem: TBoldExternalPersistenceConfigItem; +begin + lConfigItem := Config.FindExpressionName(MoldClass.ExpandedExpressionName); + result := lConfigItem.FetchAllMembersWhenFetchingKey; +end; + procedure TBoldExternalPersistenceControllerEventDriven.FetchObject( ObjectContents: IBoldObjectContents; MemberIdList: TBoldMemberIdList; FetchContext: TObject; ValueSpace: IBoldValueSpace); @@ -157,21 +169,25 @@ procedure TBoldExternalPersistenceControllerEventDriven.FetchObject( ConfigItem := ConfigItemByObjectContents(ObjectContents); MoldClass := MoldModel.Classes[ObjectContents.ObjectId.TopSortedIndex]; PersistentObject := PersistentObjectFromObjectContents(ObjectContents, valueSpace, MoldClass); - ExternalKey :=GetExternalKeyFromObject(ObjectContents, valueSpace); - if assigned(MemberidList) and assigned(ConfigItem.OnReadMember) then - begin - for i := 0 to MemberIdList.Count-1 do - ConfigItem.OnReadMember(PersistentObject, ExternalKey, MoldClass.AllBoldMembers[MemberIdList[i].MemberIndex], FetchContext); - end - else - begin - if Assigned(ConfigItem.OnReadObject) then - ConfigItem.OnReadObject(PersistentObject, ExternalKey, FetchContext) + ExternalKey := GetExternalKeyFromObject(ObjectContents, valueSpace); + try + if assigned(MemberidList) and assigned(ConfigItem.OnReadMember) then + begin + for i := 0 to MemberIdList.Count-1 do + ConfigItem.OnReadMember(PersistentObject, ExternalKey, MoldClass.AllBoldMembers[MemberIdList[i].MemberIndex], FetchContext); + end else - raise EBold.CreateFmt(sReadObjectNotImplementedForClass, [MoldClass.Name]); + begin + if Assigned(ConfigItem.OnReadObject) then + ConfigItem.OnReadObject(PersistentObject, ExternalKey, FetchContext) + else + raise EBold.CreateFmt('Event ReadObject is not implemented for class %s', [MoldClass.Name]); + end; + finally + ExternalKey.free; end; if not assigned(ConfigItem.OnUpdateObject) and not assigned(ConfigItem.OnDeleteObject) then - ObjectContents.IsReadOnly := true; + ObjectContents.IsReadOnly := true; end; procedure TBoldExternalPersistenceControllerEventDriven.GetExternalKeys(MoldClass: TMoldClass; ExternalKeys: TBoldObjectIdList); @@ -182,7 +198,7 @@ procedure TBoldExternalPersistenceControllerEventDriven.GetExternalKeys(MoldClas if assigned(ConfigItem) and assigned(ConfigItem.OngetKeyList) then ConfigItem.OnGetKeyList(ExternalKeys) else - raise EBold.CreateFmt(sGetExternalKeyNotImplementedForClass, [MoldClass.Name]); + raise EBold.CreateFmt('Getting external keys for class %s not implemented', [MoldClass.Name]); end; function TBoldExternalPersistenceControllerEventDriven.HandlesClass(MoldClass: TMoldClass): Boolean; @@ -232,7 +248,7 @@ procedure TBoldExternalPersistenceControllerEventDriven.UpdateObjects( if assigned(ConfigItem) then begin if not assigned(ConfigItem.OnUpdateObject) then - raise EBold.CreateFmt(sModifyObjectsNotAllowed, [ConfigItem.ExpressionName]); + raise EBold.CreateFmt('Modifying objects of type %s not supported/allowed', [ConfigItem.ExpressionName]); ExternalKey := GetExternalKeyFromObject(ObjectContents, ValueSpace); ConfigItem.OnUpdateObject(PersistentObjectFromObjectContents(ObjectContents, valueSpace, MoldClass), ExternalKey, ValueSpace); ExternalKey.Free; @@ -266,7 +282,7 @@ function TBoldExternalPersistenceControllerEventDriven.GetExternalKeyFromObject( if MoldClass.AllBoldMembers[i].Storage = bsExternalKey then begin if assigned(Result) then - raise EBold.createFmt(sAssignKeyValueRequiresOneKey, [MoldClass.Name]); + raise EBold.createFmt('AssignKeyValue only supported automatically for classes with one external key: %s', [MoldClass.Name]); KeyValue := ObjectContents.ValueByIndex[i]; if not assigned(KeyValue) then @@ -284,12 +300,13 @@ function TBoldExternalPersistenceControllerEventDriven.GetExternalKeyFromObject( result := DefId; end else - raise EBold.createFmt(sKeyTypeNotAutoHandled, [MoldClass.Name, MoldClass.AllBoldMembers[i].Name]); + raise EBold.createFmt('Keytype not handled automatically: %s.%s', [MoldClass.Name, MoldClass.AllBoldMembers[i].Name]); end; end; end; end; + procedure TBoldExternalPersistenceControllerEventDriven.PostFetch( FetchContext: TObject; MoldClass: TMoldClass); var @@ -317,7 +334,7 @@ function TBoldExternalPersistenceControllerEventDriven.GetMaxFetchBlockSize: int end; function TBoldExternalPersistenceControllerEventDriven.PersistentObjectFromObjectContents( - Obj: IBoldObjectContents; ValueSpace: IBoldValueSpace; MoldClass: TMoldClass): IPersistentBoldObject; + const Obj: IBoldObjectContents; const ValueSpace: IBoldValueSpace; MoldClass: TMoldClass): IPersistentBoldObject; var adapterClass: TBoldObjectPersistenceAdapterClass; begin @@ -338,4 +355,5 @@ function TBoldExternalPersistenceControllerEventDriven.ExternalKeysToInternalSQL result := inherited ExternalKeysToInternalSQL(MoldClass, ExternalKeys); end; +initialization end. diff --git a/Source/Persistence/ExternalPersistence/BoldExternalPersistenceControllerSQL.pas b/Source/Persistence/ExternalPersistence/BoldExternalPersistenceControllerSQL.pas index 1745d86..ac6811c 100644 --- a/Source/Persistence/ExternalPersistence/BoldExternalPersistenceControllerSQL.pas +++ b/Source/Persistence/ExternalPersistence/BoldExternalPersistenceControllerSQL.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldExternalPersistenceControllerSQL; interface @@ -5,7 +8,9 @@ interface uses DB, Classes, + {$IFDEF BOLD_DELPHI6_OR_LATER} Variants, + {$ENDIF} BoldSubscription, BoldPersistenceController, BoldNameExpander, @@ -88,7 +93,7 @@ TBoldExternalPersistenceControllerSQL = class(TBoldAbstractPartiallyExternalPC public constructor Create(MoldModel: TMoldModel; ADatabaseAdapter: TBoldAbstractDatabaseAdapter; TypeNameDictionary: TBoldTypeNameDictionary; OnStartUpdates, OnEndUpdates, OnFailUpdates: TNotifyEvent; - AClassesToHandle: TStrings); reintroduce; + AClassesToHandle: TStrings; AUpdateBoldDatabaseFirst: boolean); reintroduce; destructor Destroy; override; procedure SubscribeToPeristenceEvents(Subscriber: TBoldSubscriber); override; end; @@ -193,12 +198,12 @@ implementation uses SysUtils, + BoldUtils, BoldDefs, BoldTaggedValueSupport, BoldStringId, BoldDefaultId, - Math, - ExPeConsts; + Math; function _GetTableName(MoldClass: TMoldClass): String; begin @@ -229,7 +234,7 @@ function FindExternalKey(MoldClass: TMoldClass): Integer; function RemovePreAt(Member: TMoldMember): String; begin result := BoldExpandName(Member.ColumnName, Member.name, xtSQL, -1, Member.MoldClass.Model.NationalCharConversion); - if (Length(result) > 0) and {(result[1] = '@')} (result[1] in ['@', '_']) then {!!} + if (Length(result) > 0) and {(result[1] = '@')} CharInSet(result[1], ['@', '_']) then {!!} Result := Copy(result, 2, Length(result)) end; @@ -342,7 +347,7 @@ function BoldValueToVariant(B: IBoldValue): Variant; Result := DT.asDateTime else if B.QueryInterface(IBoldBlobContent, BL) = S_OK then Result := BL.asBlob - else raise Exception.Create(sUnknownDataType); + else raise Exception.Create('Unknown data type'); end; procedure VariantToBoldValue(B: IBoldValue; Value: Variant); @@ -379,7 +384,7 @@ procedure VariantToBoldValue(B: IBoldValue; Value: Variant); DT.asDateTime := Value else if B.QueryInterface(IBoldBlobContent, BL) = S_OK then BL.asBlob := Value - else raise Exception.Create(sUnknownDataType); + else raise Exception.Create('Unknown data type'); end; procedure SetBoldValueToNull(B: IBoldValue); @@ -395,7 +400,6 @@ procedure SetBoldValueToNull(B: IBoldValue); DT: IBoldDateTimeContent; BL: IBoldBlobContent; begin - // all the below types support IBoldNullableValue if B.QueryInterface(IBoldNullableValue, Nullable) = S_OK then Nullable.SetContentToNull else if B.QueryInterface(IBoldStringContent, S) = S_OK then @@ -416,7 +420,7 @@ procedure SetBoldValueToNull(B: IBoldValue); DT.asDateTime := 0 else if B.QueryInterface(IBoldBlobContent, BL) = S_OK then BL.asBlob := '' - else raise Exception.Create(sUnknownDataType); + else raise Exception.Create('Unknown data type'); end; function GetKeyCount(MoldClass: TMoldClass): Integer; @@ -486,9 +490,9 @@ function QuoteStringIfNeeded(const S: String): String; constructor TBoldExternalPersistenceControllerSQL.Create( MoldModel: TMoldModel; ADatabaseAdapter: TBoldAbstractDatabaseAdapter; TypeNameDictionary: TBoldTypeNameDictionary; - OnStartUpdates, OnEndUpdates, OnFailUpdates: TNotifyEvent; AClassesToHandle: TStrings); + OnStartUpdates, OnEndUpdates, OnFailUpdates: TNotifyEvent; AClassesToHandle: TStrings; AUpdateBoldDatabaseFirst: boolean); begin - inherited Create(MoldModel, TypeNameDictionary, OnStartUpdates, OnEndUpdates, OnFailUpdates); + inherited Create(MoldModel, TypeNameDictionary, OnStartUpdates, OnEndUpdates, OnFailUpdates, AUpdateBoldDatabaseFirst); FDatabaseAdapter := ADatabaseAdapter; FClassesToHandle := TStringList.Create; FClassesToHandle.Assign(AClassesToHandle); @@ -536,6 +540,7 @@ procedure TBoldExternalPersistenceControllerSQL.PrepareFetchExternal( var FetchMembers: TBoldMemberIdList; i: integer; + lMember: TMoldMember; begin if Assigned(MemberIdList) and (MemberIdList.Count > 0) then FetchMembers := MemberIdList @@ -543,17 +548,20 @@ procedure TBoldExternalPersistenceControllerSQL.PrepareFetchExternal( begin FetchMembers := TBoldMemberIdList.Create; for i := 0 to MoldClass.AllBoldMembers.Count-1 do - if (MoldClass.AllBoldMembers[i].Storage in [bsExternal, bsExternalKey]) and - not MoldClass.AllBoldMembers[i].Derived and - not ((MoldClass.AllBoldMembers[i] is TMoldRole) and - (TMoldRole(MoldClass.AllBoldMembers[i]).Multi)) and - not (SameText(MoldClass.AllBoldMembers[i].TVByName['DelayedFetch'], 'True')) then // do not localize + begin + lMember := MoldClass.AllBoldMembers[i]; + if (lMember.Storage in [bsExternal, bsExternalKey]) and + not lMember.Derived and + not ((lMember is TMoldRole) and + (TMoldRole(lMember).Multi)) and + not (SameText(lMember.TVByName['DelayedFetch'], 'True')) then FetchMembers.Add(TBoldMemberId.Create(i)); + end; end; FetchContext := TFetchContext.Create(Self, ExternalKeys, ValueSpace, MoldClass, FetchMembers); - + if FetchMembers <> MemberIdList then FetchMembers.Free; end; @@ -565,8 +573,8 @@ procedure TBoldExternalPersistenceControllerSQL.PostFetch( begin TFetchContext(FetchContext).PostFetch; FetchContext.Free; - end; - inherited; + end; + inherited; end; procedure TBoldExternalPersistenceControllerSQL.FetchObject( @@ -586,7 +594,7 @@ procedure TBoldExternalPersistenceControllerSQL.GetExternalKeys(MoldClass: TMold DBFieldName := FindExternalKeyColumns(MoldClass); BoldQuery := DatabaseAdapter.DatabaseInterface.GetQuery; - BoldQuery.AssignSQLText(Format('SELECT %S FROM %S', [ // do not localize + BoldQuery.AssignSQLText(Format('SELECT %S FROM %S', [ StringReplace(DBFieldName, ';', ', ', [rfReplaceAll]), _GetTableName(MoldClass)])); BoldQuery.Open; @@ -604,7 +612,7 @@ procedure TBoldExternalPersistenceControllerSQL.GetExternalKeys(MoldClass: TMold TBoldStringId(ExternalId).AsString := DBValue; end else - raise Exception.CreateFmt(sUnknownVarTypeLoadingObject, [MoldClass.name]); + raise Exception.CreateFmt('Unknown vartype when loading an external ID for %s', [MoldClass.name]); ExternalKeys.Add(ExternalId); ExternalId.Free; BoldQuery.Next; @@ -632,7 +640,7 @@ function TBoldExternalPersistenceControllerSQL.ExternalKeyExistsInExternalStorag ExternalKeys := TBoldObjectIdList.Create; try ExternalKeys.Add(ExternalKey); - AssignSQLText(Format('SELECT %S FROM %S WHERE %S', [ // do not localize + AssignSQLText(Format('SELECT %S FROM %S WHERE %S', [ StringReplace(DBFieldName, ';', ', ', [rfReplaceAll]), _GetTableName(MoldClass), ExternalKeysToInternalSQL(MoldClass, ExternalKeys)])); finally @@ -684,7 +692,7 @@ function TBoldExternalPersistenceControllerSQL.GetExternalKeyFromObject( TBoldStringId(Result).AsString := DBValue; end else - raise Exception.CreateFmt(sUnknownVarTypeLoadingObject, [MoldClass.name]); + raise Exception.CreateFmt('Unknown vartype when loading an external ID for %s', [MoldClass.name]); end; function TBoldExternalPersistenceControllerSQL.GetMaxFetchBlockSize: integer; @@ -724,13 +732,13 @@ function TBoldExternalPersistenceControllerSQL.ExternalKeysToInternalSQL(MoldCla Val(T, v, c); if c <> 0 then T := '''' + T + ''''; - SQL := SQL + '(' + GetNextWord(S, ';') + ' = ' + T + ') AND '; // do not localize + SQL := SQL + '(' + GetNextWord(S, ';') + ' = ' + T + ') AND '; end; if Length(SQL) > 1 then SetLength(SQL, Length(SQL)-5); SQL := SQL + ')'; - Result := Result + SQL + ' OR '; // do not localize + Result := Result + SQL + ' OR '; end; if Length(Result) > 0 then @@ -760,7 +768,7 @@ procedure TBoldExternalPersistenceControllerSQL.AssignKeyToObject( else if KeyValue.QueryInterface(IBoldIntegerContent, IntContent) = S_OK then IntContent.AsInteger := StrToInt(GetNextWord(S, ';')) else - raise EBold.createFmt(sKeyTypeNotAutoHandled, [MoldClass.Name, MoldClass.AllBoldMembers[i].Name]); + raise EBold.createFmt('Keytype not handled automatically: %s.%s', [MoldClass.Name, MoldClass.AllBoldMembers[i].Name]); end; end; end; @@ -796,7 +804,6 @@ procedure TBoldExternalPersistenceControllerSQL.AssignParametersWithMemberIdlist ParamName := _GetColumnName(MoldClass.AllBoldMembers[MemberIdList[i].MemberIndex]); Query.ParamByName(ParamName).asVariant := BoldValueToVariant(BoldValue); -// Createparam(ftunknown, ParamName, ptInput, 0).asVariant := BoldValueToVariant(BoldValue); end; end; @@ -850,11 +857,11 @@ function TBoldExternalPersistenceControllerSQL.GenerateInsertSQL( begin SetLength(FieldNames, Length(FieldNames)-2); SetLength(Params, Length(Params)-2); - Result := Format('INSERT INTO %s (%s) VALUES (%s)', [_GetTableName(MoldClass), FieldNames, // do not localize + Result := Format('INSERT INTO %s (%s) VALUES (%s)', [_GetTableName(MoldClass), FieldNames, Params]); end else - Result := Format('INSERT INTO %s', [_GetTableName(MoldClass)]); // do not localize + Result := Format('INSERT INTO %s', [_GetTableName(MoldClass)]); end; @@ -876,7 +883,7 @@ procedure TBoldExternalPersistenceControllerSQL.InternalDeleteObject( function TBoldExternalPersistenceControllerSQL.GenerateDeleteSQL( MoldClass: TMoldClass; ObjectContents: IBoldObjectContents): String; begin - Result := Format('DELETE FROM %S WHERE %S', [_GetTableName(MoldClass), // do not localize + Result := Format('DELETE FROM %S WHERE %S', [_GetTableName(MoldClass), ObjectContentsToInternalSQL(MoldClass, ObjectContents)]); end; @@ -918,6 +925,7 @@ function TBoldExternalPersistenceControllerSQL.GenerateUpdateSQL( var i: integer; FieldNames: String; + lMember: TMoldMember; begin FieldNames := ''; @@ -925,17 +933,18 @@ function TBoldExternalPersistenceControllerSQL.GenerateUpdateSQL( if (MoldClass.AllBoldMembers[i].Storage in [bsExternal, bsExternalKey]) and not MoldClass.AllBoldMembers[i].Derived then begin + lMember := MoldClass.AllBoldMembers[i]; { Do not store multi links and non-embedded single links } - if (MoldClass.AllBoldMembers[i] is TMoldRole) and - (TMoldRole(MoldClass.AllBoldMembers[i]).Multi or - not TMoldRole(MoldClass.AllBoldMembers[i]).Embed) then + if (lMember is TMoldRole) and + (TMoldRole(lMember).Multi or + not TMoldRole(lMember).Embed) then Continue; { Only update the record if the member has been modified } if ObjectContents.ValueByIndex[i].BoldPersistenceState = bvpsModified then begin - FieldNames := FieldNames + _GetColumnName(MoldClass.AllBoldMembers[i]) + ' = :' + - _GetColumnName(MoldClass.AllBoldMembers[i]) + ', '; + FieldNames := FieldNames + _GetColumnName(lMember) + ' = :' + + _GetColumnName(lMember) + ', '; end; end; @@ -943,8 +952,8 @@ function TBoldExternalPersistenceControllerSQL.GenerateUpdateSQL( if Length(FieldNames) > 0 then begin SetLength(FieldNames, Length(FieldNames)-2); - Result := Format('UPDATE %S SET %S', [_GetTableName(MoldClass), FieldNames]); // do not localize - Result := Result + ' WHERE ' + ObjectContentsToInternalSQL(MoldClass, ObjectContents); // do not localize + Result := Format('UPDATE %S SET %S', [_GetTableName(MoldClass), FieldNames]); + Result := Result + ' WHERE ' + ObjectContentsToInternalSQL(MoldClass, ObjectContents); end else Result := ''; @@ -956,15 +965,17 @@ procedure TBoldExternalPersistenceControllerSQL.GetExternalDirtyMembers( var i: integer; BoldValue: IBoldValue; + lMember: TMoldMember; begin for i := 0 to MoldClass.AllBoldMembers.Count-1 do if (MoldClass.AllBoldMembers[i].Storage in [bsExternal, bsExternalKey]) and not MoldClass.AllBoldMembers[i].Derived then begin + lMember := MoldClass.AllBoldMembers[i]; { Do not store multi links and non-embedded single links } - if (MoldClass.AllBoldMembers[i] is TMoldRole) and - (TMoldRole(MoldClass.AllBoldMembers[i]).Multi or - not TMoldRole(MoldClass.AllBoldMembers[i]).Embed) then + if (lMember is TMoldRole) and + (TMoldRole(lMember).Multi or + not TMoldRole(lMember).Embed) then Continue; { Only add members that has been modified } @@ -1053,22 +1064,22 @@ function TAbstractRoleFetchObject.PrepareSQL: String; {!!} { Sanity check } - Assert((W1 <> '') and (W2 <> ''), Format(sRoleHasNoColumnNames, [ + Assert((W1 <> '') and (W2 <> ''), Format('Role %s does not have any column names!', [ Role.Association.name])); Assert(GetCharCount(';', W1) = GetCharCount(';', W2), - Format(sRoleEndCountMismatch, [ + Format('Role %s does not have an equal amount of columns on both ends!', [ Role.Association.name])); {!!} { Parse SQL } SQL := ''; for i := 0 to GetCharCount(';', W1) do - SQL := SQL + '(' + GetNextWord(W1, ';') + ' = :' + GetNextWord(W2, ';') + ') AND'; // do not localize + SQL := SQL + '(' + GetNextWord(W1, ';') + ' = :' + GetNextWord(W2, ';') + ') AND'; { Remove last ' AND' } SetLength(SQL, Length(SQL)-4); - SQL := Format('SELECT %S FROM %S WHERE (%S)', [ // do not localize + SQL := Format('SELECT %S FROM %S WHERE (%S)', [ StringReplace(FindExternalKeyColumns(Role.OtherEnd.MoldClass), ';', ', ', [rfReplaceAll]), _GetTableName(Role.OtherEnd.MoldClass), SQL]); @@ -1134,7 +1145,7 @@ procedure TSingleRoleFetchObject.Fetch(Source: IBoldQuery; end else raise Exception.CreateFmt( - sUnknownVarTypeLoadingSingleID, + 'Unknown vartype when loading an external ID for singlelink %s.%s', [MoldClass.name, Role.name]); if Value.QueryInterface(IBoldObjectIdRef, IdRef) = S_OK then PersistenceController.SetSingleLink(IdRef, ExternalId, @@ -1149,7 +1160,7 @@ procedure TMultiRoleFetchObject.Fetch(Source: IBoldQuery; var Value: IBoldValue; OtherEndQuery: IBoldQuery; - IdRefList: IBoldObjectIdListRef; + IdRefList: IBoldObjectIdListRef; KeyNames: String; DBValue: Variant; ExternalId: TBoldObjectId; @@ -1180,7 +1191,7 @@ procedure TMultiRoleFetchObject.Fetch(Source: IBoldQuery; end else raise Exception.CreateFmt( - sUnknownVarTypeLoadingSingleID, + 'Unknown vartype when loading an external ID for singlelink %s.%s', [MoldClass.name, Role.name]); OtherEndQuery.Next; end; @@ -1296,7 +1307,7 @@ constructor TFetchContext.Create( SQL := SQL + S[i] + ', '; SetLength(SQL, Length(SQL)-2); - SQL := Format('SELECT %S FROM %S WHERE %S', [ // do not localize + SQL := Format('SELECT %S FROM %S WHERE %S', [ SQL, _GetTableName(MoldClass), PersistenceController.ExternalKeysToInternalSQL(MoldClass, ExternalKeys)]); finally S.Free; @@ -1322,7 +1333,7 @@ procedure TFetchContext.FetchObject(ObjectContents: IBoldObjectContents); FetchObjectList.MoldClass, ObjectContents, Source) then FetchObjectList[i].Fetch(Source, ObjectContents) else - raise Exception.Create(sObjectNoLongerInDB); + raise Exception.Create('Object no longer exists in database'); end; end; @@ -1331,6 +1342,7 @@ procedure TFetchContext.PostFetch; { Do nothing } end; + function TBoldExternalPersistenceControllerSQL.ObjectContentsToInternalSQL( MoldClass: TMoldClass; ObjectContents: IBoldObjectContents): String; var @@ -1351,4 +1363,5 @@ function TBoldExternalPersistenceControllerSQL.ObjectContentsToInternalSQL( end; end; +initialization end. diff --git a/Source/Persistence/ExternalPersistence/BoldExternalPersistenceHandleDataSet.pas b/Source/Persistence/ExternalPersistence/BoldExternalPersistenceHandleDataSet.pas index 99df201..8651bf5 100644 --- a/Source/Persistence/ExternalPersistence/BoldExternalPersistenceHandleDataSet.pas +++ b/Source/Persistence/ExternalPersistence/BoldExternalPersistenceHandleDataSet.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldExternalPersistenceHandleDataSet; interface @@ -39,7 +42,8 @@ TBoldExternalPersistenceHandleDataSet = class(TBoldAbstractPartiallyExternalPH implementation uses - SysUtils; + SysUtils, + BoldRev; { TBoldExternalPersistenceHandleDataSet } @@ -79,4 +83,6 @@ procedure TBoldExternalPersistenceHandleDataSet.SetConfig( Config.Assign(Value); end; +initialization + end. diff --git a/Source/Persistence/ExternalPersistence/BoldExternalPersistenceHandleEventDriven.pas b/Source/Persistence/ExternalPersistence/BoldExternalPersistenceHandleEventDriven.pas index 7c67865..529e2b9 100644 --- a/Source/Persistence/ExternalPersistence/BoldExternalPersistenceHandleEventDriven.pas +++ b/Source/Persistence/ExternalPersistence/BoldExternalPersistenceHandleEventDriven.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldExternalPersistenceHandleEventDriven; interface @@ -29,6 +32,7 @@ TBoldExternalPersistenceHandleEventDriven = class(TBoldAbstractpartiallyExtern published property Config: TBoldExternalPersistenceConfigItems read fConfig write SetConfig; property MaxFetchBlockSize: integer read fMaxFetchBlockSize write fMaxFetchBlockSize default 250; + property UpdateBoldDatabaseFirst; {$IFNDEF T2H} property NextPersistenceHandle; property BoldModel; @@ -52,7 +56,7 @@ constructor TBoldExternalPersistenceHandleEventDriven.Create(Owner: TComponent); begin inherited; FConfig := TBoldExternalPersistenceConfigItems.Create(self); - fMaxFetchBlockSize := 250; + fMaxFetchBlockSize := 250; end; destructor TBoldExternalPersistenceHandleEventDriven.Destroy; @@ -65,7 +69,7 @@ function TBoldExternalPersistenceHandleEventDriven.CreatePersistenceController: var Controller: TBoldExternalPersistenceControllerEventDriven; begin - Controller := TBoldExternalPersistenceControllerEventDriven.Create(BoldModel.MoldModel, Config, BoldModel.TypeNameDictionary, OnStartUpdates, OnEndUpdates, OnFailUpdates, MaxFetchBlockSize); + Controller := TBoldExternalPersistenceControllerEventDriven.Create(BoldModel.MoldModel, Config, BoldModel.TypeNameDictionary, OnStartUpdates, OnEndUpdates, OnFailUpdates, MaxFetchBlockSize, UpdateBoldDatabaseFirst); ChainPersistenceController(Controller); Result := Controller; end; @@ -83,4 +87,6 @@ function TBoldExternalPersistenceHandleEventDriven.GetPersistenceController: TBo result := inherited PersistenceController as TBoldExternalPersistenceControllerEventDriven; end; + +initialization end. diff --git a/Source/Persistence/ExternalPersistence/BoldExternalPersistenceHandleSQL.pas b/Source/Persistence/ExternalPersistence/BoldExternalPersistenceHandleSQL.pas index 8b3d6d5..b15fea0 100644 --- a/Source/Persistence/ExternalPersistence/BoldExternalPersistenceHandleSQL.pas +++ b/Source/Persistence/ExternalPersistence/BoldExternalPersistenceHandleSQL.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldExternalPersistenceHandleSQL; interface @@ -30,6 +33,7 @@ TBoldExternalPersistenceHandleSQL = class(TBoldAbstractPartiallyExternalPH) destructor Destroy; override; property PersistenceController: TBoldExternalPersistenceControllerSQL read GetPersistenceController; published + property UpdateBoldDatabaseFirst; property ClassesToHandle: TStrings read GetClassesToHandle write SetClassesToHandle; property DatabaseAdapter: TBoldAbstractDatabaseAdapter read FDatabaseAdapter write FDatabaseAdapter; {$IFNDEF T2H} @@ -45,6 +49,9 @@ TBoldExternalPersistenceHandleSQL = class(TBoldAbstractPartiallyExternalPH) implementation +uses + BoldRev; + { TBoldExternalPersistenceHandleSQL } constructor TBoldExternalPersistenceHandleSQL.Create(Owner: TComponent); @@ -65,7 +72,7 @@ function TBoldExternalPersistenceHandleSQL.CreatePersistenceController: TBoldPer begin Controller := TBoldExternalPersistenceControllerSQL.Create( BoldModel.MoldModel, FDatabaseAdapter, BoldModel.TypeNameDictionary, - OnStartUpdates, OnEndUpdates, OnFailUpdates, ClassesToHandle); + OnStartUpdates, OnEndUpdates, OnFailUpdates, ClassesToHandle, UpdateBoldDatabaseFirst); ChainPersistenceController(Controller); Result := Controller; end; @@ -86,4 +93,6 @@ function TBoldExternalPersistenceHandleSQL.GetPersistenceController: TBoldExtern result := inherited PersistenceController as TBoldExternalPersistenceControllerSQL; end; +initialization + end. diff --git a/Source/Persistence/ExternalPersistence/BoldExternalPersistenceHandleSQLPropEditor.pas b/Source/Persistence/ExternalPersistence/BoldExternalPersistenceHandleSQLPropEditor.pas index ddf8951..70f5b2d 100644 --- a/Source/Persistence/ExternalPersistence/BoldExternalPersistenceHandleSQLPropEditor.pas +++ b/Source/Persistence/ExternalPersistence/BoldExternalPersistenceHandleSQLPropEditor.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldExternalPersistenceHandleSQLPropEditor; interface diff --git a/Source/Persistence/ExternalPersistence/BoldExternalPersistenceHandlesReg.pas b/Source/Persistence/ExternalPersistence/BoldExternalPersistenceHandlesReg.pas index fb25de7..b29c282 100644 --- a/Source/Persistence/ExternalPersistence/BoldExternalPersistenceHandlesReg.pas +++ b/Source/Persistence/ExternalPersistence/BoldExternalPersistenceHandlesReg.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldExternalPersistenceHandlesReg; interface @@ -6,8 +9,6 @@ procedure Register; implementation -{$R BoldExternalPersistenceHandles.res} - uses DesignIntf, DesignEditors, @@ -26,8 +27,7 @@ implementation BoldExternalPersistenceHandleSQL, BoldAbstractPropertyEditors, - BoldIDEConsts, - ExPeConsts; + BoldIDEConsts; type { forward declarations } @@ -86,7 +86,7 @@ procedure RegisterPropertyEditors; RegisterPropertyEditor(TypeInfo(TBoldExternalPersistenceGetExistsEvent), nil, '', TBoldExternalPersistenceHandleEventProperty); RegisterPropertyEditor(TypeInfo(TBoldExternalPersistenceAssignKeyToObjectEvent), nil, '', TBoldExternalPersistenceHandleEventProperty); RegisterPropertyEditor(TypeInfo(TBoldExternalPersistenceGetKeyFromObject), nil, '', TBoldExternalPersistenceHandleEventProperty); - RegisterPropertyEditor(TypeInfo(TStrings), TBoldExternalPersistenceHandleSQL, 'ClassesToHandle', TBoldExternalPersistenceHandleSQLPropEdit); // do not localize + RegisterPropertyEditor(TypeInfo(TStrings), TBoldExternalPersistenceHandleSQL, 'ClassesToHandle', TBoldExternalPersistenceHandleSQLPropEdit); end; procedure Register; @@ -105,7 +105,7 @@ function TBoldExternalPersistenceHandleEventProperty.GetFormMethodName: string; if GetComponent(0) = Designer.GetRoot then begin Result := Designer.GetRootClassName; - if (Result <> '') and (Result[1] = 'T') then // do not localize + if (Result <> '') and (Result[1] = 'T') then Delete(Result, 1, 1); end else @@ -115,11 +115,11 @@ function TBoldExternalPersistenceHandleEventProperty.GetFormMethodName: string; else Result := Designer.GetObjectName(GetComponent(0)); for I := Length(Result) downto 1 do - if Result[I] in ['.', '[', ']', '-', '>'] then + if CharInSet(Result[I], ['.', '[', ']', '-', '>']) then Delete(Result, I, 1); end; if Result = '' then - raise Exception.Create(sCannotCreateNameNow); + raise Exception.Create('Can not create name for eventhandler. Assign an expressionname for the config-item first'); Result := Result + GetTrimmedEventName; end; @@ -144,7 +144,7 @@ procedure TBoldExternalPersistenceHandleEditor.Edit; procedure TBoldExternalPersistenceHandleEditor.EditConfig(const PropertyEditor: IProperty); begin - if SameText(PropertyEditor.GetName, 'Config') then // do not localize + if SameText(PropertyEditor.GetName, 'Config') then PropertyEditor.Edit; end; @@ -158,7 +158,7 @@ procedure TBoldExternalPersistenceHandleEditor.ExecuteVerb(Index: Integer); function TBoldExternalPersistenceHandleEditor.GetVerb(Index: Integer): string; begin case Index of - 0: result := sEditConfiguration; + 0: result := 'Edit configuration'; end; end; @@ -179,7 +179,7 @@ procedure TBoldExternalPersistenceHandleSQLPropEdit.Edit; Handle := GetComponent(0) as TBoldExternalPersistenceHandleSQL; if not Assigned(Handle.BoldModel) then - raise Exception.Create(sBoldModelNotAssigned); + raise Exception.Create('BoldModel is not assigned!'); Form := TBoldExternalPersistenceHandleSQLPropEditorForm.Create(nil); Form.Initialize(Handle.BoldModel.MoldModel, Handle.ClassesToHandle); @@ -222,12 +222,12 @@ function TBoldExternalPersistenceHandleSQLPropEdit.GetValue: string; All := False; end; if All then - Result := '(All)' // do not localize + Result := '(All)' else if Result <> '' then SetLength(Result, Length(Result)-2) else - Result := '(None)'; // do not localize + Result := '(None)'; end; var @@ -235,7 +235,7 @@ function TBoldExternalPersistenceHandleSQLPropEdit.GetValue: string; begin Result := ''; if PropCount <> 1 then - Result := '(Multi)' // do not localize + Result := '(Multi)' else with (GetComponent(0) as TBoldExternalPersistenceHandleSQL) do begin @@ -248,11 +248,9 @@ function TBoldExternalPersistenceHandleSQLPropEdit.GetValue: string; if Result <> '' then SetLength(Result, Length(Result)-2) else - Result := '(None)'; // do not localize + Result := '(None)'; end; end; end; end. - - diff --git a/Source/Persistence/ExternalPersistence/BoldExternalPersistenceSupport.pas b/Source/Persistence/ExternalPersistence/BoldExternalPersistenceSupport.pas index 37a44d8..dc67239 100644 --- a/Source/Persistence/ExternalPersistence/BoldExternalPersistenceSupport.pas +++ b/Source/Persistence/ExternalPersistence/BoldExternalPersistenceSupport.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldExternalPersistenceSupport; interface @@ -36,7 +39,8 @@ TBoldObjectPersistenceAdapter = class(TBoldRefCountedObject, IPersistentBoldOb implementation uses - Classes; + Classes, + Boldrev; var G_RegisteredPersistenceAdapters: TStringList; @@ -82,4 +86,5 @@ class procedure TBoldObjectPersistenceAdapter.RegisterPersistenceInterface( G_RegisteredPersistenceAdapters.AddObject(ExpressionName, TObject(Adapter)); end; +initialization end. diff --git a/Source/Persistence/ExternalPersistence/ExPeConsts.pas b/Source/Persistence/ExternalPersistence/ExPeConsts.pas index daf9615..f57af51 100644 --- a/Source/Persistence/ExternalPersistence/ExPeConsts.pas +++ b/Source/Persistence/ExternalPersistence/ExPeConsts.pas @@ -48,4 +48,4 @@ interface implementation -end. \ No newline at end of file +end. diff --git a/Source/Persistence/File/BoldPersistenceHandleFile.pas b/Source/Persistence/File/BoldPersistenceHandleFile.pas index 009cec4..b2ba9c6 100644 --- a/Source/Persistence/File/BoldPersistenceHandleFile.pas +++ b/Source/Persistence/File/BoldPersistenceHandleFile.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldPersistenceHandleFile; interface @@ -12,7 +15,8 @@ interface BoldUpdatePrecondition, BoldCondition, BoldFreeStandingValues, - BoldValueSpaceInterfaces; + BoldValueSpaceInterfaces, + BoldElements; type { forward declarations } @@ -20,7 +24,6 @@ TBoldAbstractPersistenceHandleFile = class; TBoldPersistenceControllerFile = class; { TBoldAbstractPersistenceHandleFile } - {$MESSAGE WARN 'BoldModel should have FreeNotification!'} TBoldAbstractPersistenceHandleFile = class(TBoldPersistenceHandle) private FFileName: String; @@ -50,18 +53,19 @@ TBoldPersistenceControllerFile = class(TBoldPersistenceController) procedure WriteValueSpace; virtual; abstract; procedure ReadValueSpace; virtual; abstract; public - constructor Create(filename: string; CacheData: Boolean; MoldModel: TMoldModel); - destructor Destroy; override; - procedure PMExactifyIds(ObjectIdList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList); override; + constructor create(filename: string; CacheData: Boolean; MoldModel: TMoldModel); + destructor destroy; override; + procedure PMExactifyIds(ObjectIdList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList; HandleNonExisting: Boolean); override; procedure PMFetch(ObjectIdList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; MemberIdList: TBoldMemberIdList; FetchMode: Integer; BoldClientID: TBoldClientID); override; procedure PMFetchIDListWithCondition(ObjectIdList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; FetchMode: Integer; Condition: TBoldCondition; BoldClientID: TBoldClientID); override; - procedure PMUpdate(ObjectIdList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; Old_Values: IBoldValueSpace; Precondition: TBoldUpdatePrecondition; TranslationList: TBoldIdTranslationList; var TimeStamp: TBoldTimeStampType; BoldClientID: TBoldClientID); override; + procedure PMUpdate(ObjectIdList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; Old_Values: IBoldValueSpace; Precondition: TBoldUpdatePrecondition; TranslationList: TBoldIdTranslationList; var TimeStamp: TBoldTimeStampType; var TimeOfLatestUpdate: TDateTime; BoldClientID: TBoldClientID); override; procedure PMTranslateToGlobalIds(ObjectIdList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList); override; procedure PMTranslateToLocalIds(GlobalIdList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList); override; - procedure PMSetReadOnlyness(ReadOnlyList, WriteableList: TBoldObjectIdList); override; + procedure PMSetReadonlyness(ReadOnlyList, WriteableList: TBoldObjectIdList); override; function MultilinksAreStoredInObject: Boolean; override; procedure ReserveNewIds(ValueSpace: IBoldValueSpace; ObjectIdList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList); override; + function CanEvaluateInPS(sOCL: string; aSystem: TBoldElement; aContext: TBoldElementTypeInfo = nil; const aVariableList: TBoldExternalVariableList = nil): Boolean; override; property FileName: String read fFileName; property LocalValueSpace: IBoldValueSpace read GetValueSpace; property CacheData: Boolean read fCacheData; @@ -73,12 +77,19 @@ implementation uses Dialogs, SysUtils, - BoldDefaultId, - PersistenceConsts, - BoldCoreConsts; + BoldDefaultId; { TBoldPersistenceControllerFile } +function TBoldPersistenceControllerFile.CanEvaluateInPS(sOCL: string; + aSystem: TBoldElement; aContext: TBoldElementTypeInfo; + const aVariableList: TBoldExternalVariableList): Boolean; +const + sMethodNotImplemented = '%s.%s: not supported/implemented'; +begin + raise EBold.CreateFmt(sMethodNotImplemented, [ClassName, 'CanEvaluateInPS']); // do not localize +end; + constructor TBoldPersistenceControllerFile.create(filename: string; CacheData: Boolean; MoldModel: TMoldModel); begin Inherited Create; @@ -94,9 +105,8 @@ function TBoldPersistenceControllerFile.GetValueSpace: IBoldValueSpace; end; procedure TBoldPersistenceControllerFile.EnsureValueSpace; - procedure FixupValueSpace; // make sure that valuspaces in old formats can be handled + procedure FixupValueSpace; begin - // Make sure persistacestate is current for everything fFreeStandingValueSpace.MarkAllObjectsAndMembersCurrent; end; begin @@ -116,22 +126,17 @@ procedure TBoldPersistenceControllerFile.EnsureValueSpace; procedure TBoldPersistenceControllerFile.PMExactifyIds( ObjectIdList: TBoldObjectIdList; - TranslationList: TBoldIdTranslationList); + TranslationList: TBoldIdTranslationList; HandleNonExisting: Boolean); begin - raise EBold.Create(sNotImplemented); + raise EBold.Create('NotImplemented'); end; procedure TBoldPersistenceControllerFile.PMFetch( ObjectIdList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; MemberIdList: TBoldMemberIdList; FetchMode: Integer; BoldClientID: TBoldClientID); -var - i: integer; begin EnsureValueSpace; - for i := 0 to ObjectIdList.Count - 1 do - if not LocalValueSpace.HasContentsForId[ObjectIdList[i]] then - raise EBold.CreateFmt(sObjectNotInFile, [ClassName, ObjectIdList[i].AsString]); BoldApplyPartialValueSpace(ValueSpace, LocalValueSpace, ObjectIdList, MemberIdList, false); if not cacheData then @@ -167,55 +172,55 @@ procedure TBoldPersistenceControllerFile.PMFetchIDListWithCondition( end else if Condition is TBoldSQLCondition then begin - ShowMessage(sSQLNotSpokenHere); + ShowMessage('This filehandler does not understand SQL, ignoring condition and orderby...'); NewCondition := TBoldConditionWithClass.Create; NewCondition.TopSortedIndex := TBoldSQLCondition(Condition).TopSortedIndex; PMFetchIDListWithCondition(ObjectIdList, ValueSpace, FetchMode, NewCondition, NOTVALIDCLIENTID); NewCondition.free; end else - raise EBold.CreateFmt(sUnknownConditionType, [Condition.Classname]); + raise EBold.Create('unknown conditiontype: ' + Condition.Classname); end; procedure TBoldPersistenceControllerFile.PMSetReadonlyness(ReadOnlyList, WriteableList: TBoldObjectIdList); begin - raise EBold.Create(sNotImplemented); + raise EBold.Create('Not Implemented'); end; procedure TBoldPersistenceControllerFile.PMTranslateToGlobalIds( ObjectIdList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList); begin - raise EBold.Create(sNotImplemented); + raise EBold.Create('Not Implemented'); end; procedure TBoldPersistenceControllerFile.PMTranslateToLocalIds( GlobalIdList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList); begin - raise EBold.Create(sNotImplemented); + raise EBold.Create('Not Implemented'); end; procedure TBoldPersistenceControllerFile.PMUpdate( ObjectIdList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; Old_Values: IBoldValueSpace; - Precondition: TBoldUpdatePrecondition; - TranslationList: TBoldIdTranslationList; var TimeStamp: TBoldTimeStampType; BoldClientID: TBoldClientID); + Precondition: TBoldUpdatePrecondition; + TranslationList: TBoldIdTranslationList; var TimeStamp: TBoldTimeStampType; var TimeOfLatestUpdate: TDateTime; BoldClientID: TBoldClientID); var NewTimeStamp: TDateTime; LocalTranslationList: TBoldIdTranslationList; begin if assigned(Precondition) then - raise EBold.CreateFmt(sPreconditionsNotSupported, [Classname, Precondition.Classname]); - + raise EBold.CreateFmt('%s.PMUpdate: Preconditions (%s) not supported in this component', [Classname, Precondition.Classname]); + EnsureValueSpace; if fileexists(Filename) then NewTimeStamp := FileDateToDateTime(FileAge(FileName)) else NewTimeStamp := 0; - + TimeOfLatestUpdate := now; if (NewTimeStamp <> fFileTimeStamp) then begin { if MessageDlg('The datafile has been written since you last accessed it... Go ahead?', @@ -242,13 +247,12 @@ procedure TBoldPersistenceControllerFile.PMUpdate( LocalTranslationList.Free; WriteValueSpace; - + fFileTimestamp := FileDateToDateTime(FileAge(FileName)); end; procedure TBoldPersistenceControllerFile.UnloadLocalValueSpace; begin - // does not work. { fFreeStandingValueSpace.Free; fFreeStandingValueSpace := nil; } @@ -284,11 +288,12 @@ procedure TBoldPersistenceControllerFile.ReserveNewIds(ValueSpace: IBoldValueSpa destructor TBoldPersistenceControllerFile.destroy; begin FreeAndNil(fFreeStandingValueSpace); - inherited; + inherited; end; { TBoldAbstractPersistenceHandleFile } + procedure TBoldAbstractPersistenceHandleFile.SetBoldModel(const Value: TBoldAbstractModel); begin FBoldModel := Value; @@ -304,4 +309,7 @@ procedure TBoldAbstractPersistenceHandleFile.SetFileName(const Value: String); FFileName := Value; end; + +initialization + end. diff --git a/Source/Persistence/File/BoldPersistenceHandleFileXML.pas b/Source/Persistence/File/BoldPersistenceHandleFileXML.pas index 4122ff5..96c5e91 100644 --- a/Source/Persistence/File/BoldPersistenceHandleFileXML.pas +++ b/Source/Persistence/File/BoldPersistenceHandleFileXML.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldPersistenceHandleFileXML; interface @@ -34,25 +37,47 @@ implementation classes, SysUtils, BoldDefs, - MSXML_TLB, + {$IFDEF OXML}OXmlPDOM, OTextReadWrite{$ELSE}MSXML_TLB{$ENDIF}, BoldId, BoldXMLStreaming, BoldDefaultXMLStreaming, - BoldGuard, - PersistenceConsts; + BoldGuard; { TBoldPersistenceHandleFileXML } function TBoldPersistenceHandleFileXML.CreatePersistenceController: TBoldPersistenceController; begin if not assigned(BoldModel) then - Raise EBold.CreateFmt(sModelRequired, [ClassName]); + Raise EBold.CreateFmt('%s.CreatePersistenceController: Unable to create, model is missing.', [ClassName]); Result := TBoldPersistenceControllerFileXML.Create(FileName, CacheData, BoldModel.MoldModel); end; { TBoldPersistenceControllerFileXML } procedure TBoldPersistenceControllerFileXML.ReadValueSpace; +{$IFDEF OXML} +var + anXMLDoc: TXMLDocument; + ParseError: IOTextParseError; + aMgr: TBoldDefaultXMLStreamManager; + aNode: TBoldXMLNode; + BoldGuard: IBoldGuard; +begin + BoldGuard := TBoldGuard.Create(aMgr, aNode); + anXMLDoc := TXMLDocument.Create; + aMgr := TBoldDefaultXMLStreamManager.Create( + TBoldDefaultXMLStreamerRegistry.MainStreamerRegistry, MoldModel); + aMgr.IgnorePersistenceState := True; + aMgr.PersistenceStatesToOverwrite := [bvpsInvalid, bvpsCurrent]; + aMgr.PersistenceStatesToBeStreamed := [bvpsInvalid, bvpsModified, bvpsCurrent]; + anXMLDoc.LoadFromFile(FileName); + ParseError := anXMLDoc.parseError; + if Assigned(ParseError) and (ParseError.ErrorCode <> 0) then + raise EBold.Create('Error reading/parsing XML file'); + aNode := aMgr.GetRootNode(anXMLDoc, 'ValueSpace'); //do not localize + aMgr.ReadValueSpace(LocalValueSpace, aNode); +end; +{$ELSE} var aStringList: TStringList; anXMLDoc: TDomDocument; @@ -74,12 +99,33 @@ procedure TBoldPersistenceControllerFileXML.ReadValueSpace; ParseError := anXMLDoc.parseError; if Assigned(ParseError) and (ParseError.errorCode <> 0) then - raise EBold.Create(sXMLParseError); - aNode := aMgr.GetRootNode(anXMLDoc, 'ValueSpace'); //do not localize + raise EBold.Create('Error reading/parsing XML file'); + aNode := aMgr.GetRootNode(anXMLDoc, 'ValueSpace'); aMgr.ReadValueSpace(LocalValueSpace, aNode); end; +{$ENDIF} procedure TBoldPersistenceControllerFileXML.WriteValueSpace; +{$IFDEF OXML} +var + aXML: TXMLDocument; + aMgr: TBoldDefaultXMLStreamManager; + aNode: TBoldXMLNode; + anIdList: TBoldObjectIdList; + BoldGuard: IBoldGuard; +begin + BoldGuard := TBoldGuard.Create(aNode, aMgr, anIDList); + aXML := TXMLDocument.Create; + aMgr := TBoldDefaultXMLStreamManager.Create(TBoldDefaultXMLStreamerRegistry.MainStreamerRegistry, MoldModel); + aMgr.IgnorePersistenceState := True; + aMgr.PersistenceStatesToBeStreamed := [bvpsInvalid, bvpsModified, bvpsCurrent]; + aNode := aMgr.NewRootNode(aXML, 'ValueSpace'); //do not localize + anIdList := TBoldObjectIdList.Create; + LocalValueSpace.AllObjectIds(anIdList, True); + aMgr.WriteValueSpace(LocalValueSpace, anIdList, nil, aNode); + aXML.SaveToFile(FileName); +end; +{$ELSE} var aStringList: TStringList; anXMLDoc: TDomDocument; @@ -94,12 +140,15 @@ procedure TBoldPersistenceControllerFileXML.WriteValueSpace; aMgr := TBoldDefaultXMLStreamManager.Create(TBoldDefaultXMLStreamerRegistry.MainStreamerRegistry, MoldModel); aMgr.IgnorePersistenceState := True; aMgr.PersistenceStatesToBeStreamed := [bvpsInvalid, bvpsModified, bvpsCurrent]; - aNode := aMgr.NewRootNode(anXMLDoc, 'ValueSpace'); //do not localize + aNode := aMgr.NewRootNode(anXMLDoc, 'ValueSpace'); anIdList := TBoldObjectIdList.Create; LocalValueSpace.AllObjectIds(anIdList, True); aMgr.WriteValueSpace(LocalValueSpace, anIdList, nil, aNode); aStringList.Text := anXMLDoc.documentElement.xml; aStringList.SaveToFile(FileName); end; +{$ENDIF} + +initialization end. diff --git a/Source/Persistence/HTTP/BoldHTTPClientPersistenceHandle.pas b/Source/Persistence/HTTP/BoldHTTPClientPersistenceHandle.pas index dc7dacb..98535d6 100644 --- a/Source/Persistence/HTTP/BoldHTTPClientPersistenceHandle.pas +++ b/Source/Persistence/HTTP/BoldHTTPClientPersistenceHandle.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldHTTPClientPersistenceHandle; interface @@ -8,7 +11,8 @@ interface BoldHTTPPersistenceControllerClient, BoldAbstractModel, BoldWebConnection, - classes; + classes + ; type { forward declarations } @@ -34,15 +38,15 @@ implementation uses SysUtils, BoldUtils, - BoldDefs, - BoldComConst; + BoldDefs + ; { TBoldHTTPClientPersistenceHandle } function TBoldHTTPClientPersistenceHandle.CreatePersistenceController: TBoldPersistenceController; begin if not assigned(BoldModel) then - raise EBold.createfmt(sModelRequired, [ClassName]); + raise EBold.createfmt('%s.CreatePersistenceController: Can not get a PersistenceController without a Model', [ClassName]); FPersistenceController := TBoldHTTPPersistenceControllerClient.Create(fModel.MoldModel); (FPersistenceController as TBoldHTTPPersistenceControllerClient).WebConnection := WebConnection; result := FPersistenceController; @@ -72,4 +76,6 @@ procedure TBoldHTTPClientPersistenceHandle.setWebConnection( end; end; +initialization + end. diff --git a/Source/Persistence/HTTP/BoldHTTPPersistenceControllerClient.pas b/Source/Persistence/HTTP/BoldHTTPPersistenceControllerClient.pas index 49179d2..c940d09 100644 --- a/Source/Persistence/HTTP/BoldHTTPPersistenceControllerClient.pas +++ b/Source/Persistence/HTTP/BoldHTTPPersistenceControllerClient.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldHTTPPersistenceControllerClient; interface @@ -8,7 +11,8 @@ interface BoldMeta, BoldSOAP_TLB, ComObj, - ActiveX; + ActiveX + ; type {forward declarations} @@ -46,8 +50,8 @@ implementation BoldDataBlock, BoldDefs, Classes, - windows, - BoldComConst; + windows + ; { TBoldHTTPSOAPService } @@ -58,7 +62,7 @@ constructor TBoldHTTPSOAPService.Create; if (LoadRegTypeLib(LIBID_BoldSOAP, 1, 0, 0, typelib) = S_OK) then inherited Create(typelib, IBoldSOAPService) else - raise EBold.CreateFmt(sUnableToLoadTypeLibBoldSoap, [ClassName]); + raise EBold.CreateFmt('%s.Create: Unable to load type library LIBID_BoldSOAP', [ClassName]); end; procedure TBoldHTTPSOAPService.Get(const request: WideString; @@ -92,6 +96,7 @@ procedure TBoldHTTPSOAPService.Get(const request: WideString; end; end; + { TBoldHTTPPersistenceControllerClient } constructor TBoldHTTPPersistenceControllerClient.Create(Model: TMoldModel); @@ -109,7 +114,6 @@ destructor TBoldHTTPPersistenceControllerClient.Destroy; procedure TBoldHTTPPersistenceControllerClient.Disconnect; begin - //do nothing end; function TBoldHTTPPersistenceControllerClient.getWebConnection: TBoldWebConnection; @@ -123,4 +127,6 @@ procedure TBoldHTTPPersistenceControllerClient.setWebConnection( fhttpSoapService.WebConnection := Value; end; +initialization + end. diff --git a/Source/Persistence/HTTP/BoldHTTPServerPersistenceHandlePassthrough.pas b/Source/Persistence/HTTP/BoldHTTPServerPersistenceHandlePassthrough.pas index 2398d4f..dbc68bb 100644 --- a/Source/Persistence/HTTP/BoldHTTPServerPersistenceHandlePassthrough.pas +++ b/Source/Persistence/HTTP/BoldHTTPServerPersistenceHandlePassthrough.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldHTTPServerPersistenceHandlePassthrough; interface @@ -8,7 +11,8 @@ interface BoldPersistenceHandle, BoldAbstractModel, BoldSubscription, - Classes; + Classes + ; type { forward declarations} @@ -38,8 +42,7 @@ implementation uses SysUtils, BoldUtils, - BoldDefs, - BoldComConst; + BoldDefs; { TBoldHTTPServerPersistenceHandlePassthrough } @@ -50,7 +53,7 @@ procedure TBoldHTTPServerPersistenceHandlePassthrough.Get(const request: WideStr if Assigned(PersistenceController) then AdapterCore.Get(request, reply, PersistenceController) else - raise EBold.CreateFmt(sPersistenceHandleNotAssigned, [ClassName, 'Get']); // do not localize + raise EBold.CreateFmt('%s.%s: PersistenceHandle not assigned', [ClassName, 'Get']); except on E: Exception do Reply := E.Message + ' ' + request; end; @@ -83,4 +86,6 @@ procedure TBoldHTTPServerPersistenceHandlePassthrough.Notification( end; end; +initialization + end. diff --git a/Source/Persistence/IBX/BoldDatabaseAdapterIB.pas b/Source/Persistence/IBX/BoldDatabaseAdapterIB.pas index f58939a..fa75748 100644 --- a/Source/Persistence/IBX/BoldDatabaseAdapterIB.pas +++ b/Source/Persistence/IBX/BoldDatabaseAdapterIB.pas @@ -1,10 +1,14 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldDatabaseAdapterIB; interface uses Classes, - IBDataBase, + Windows, + IBX.IBDatabase, BoldSQLDatabaseConfig, BoldAbstractDataBaseAdapter, BoldDBInterfaces, @@ -29,6 +33,7 @@ TBoldDatabaseAdapterIB = class(TBoldAbstractDatabaseAdapter) destructor Destroy; override; procedure CreateInterbaseDatabase(PageSize: integer = 4096); procedure EnsureInterbaseDatabase(PageSize: integer = 4096); + procedure CreateDatabase; override; published property DataBase: TIBDataBase read GetDataBase write SetDataBase; {$IFNDEF T2H} @@ -40,46 +45,23 @@ implementation uses SysUtils, - BoldDefs; + BoldDefs, + BoldRev; { TBoldDatabaseAdapterIB } -constructor TBoldDatabaseAdapterIB.create(aOwner: TComponent); +constructor TBoldDatabaseAdapterIB.Create(aOwner: TComponent); begin inherited; DatabaseEngine := dbeInterbaseSQLDialect3; end; procedure TBoldDatabaseAdapterIB.CreateInterbaseDatabase(PageSize: integer = 4096); -var - db: TIBDatabase; - username: String; - pwd: String; begin - if not assigned(Database) then - raise EBold.CreateFmt('%s.CreateInterbaseDatbase: Unable to complete operation without an IBDatabase', [classname]); - - username := Database.Params.Values['user_name']; // do not localize - pwd := Database.Params.Values['password']; // do not localize - - if (username = '') or (pwd = '') then - raise EBold.CreateFmt('%s.CreateInterbaseDatabase: username or password missing', [classname]); - if FileExists(Database.DatabaseName) then - if not DeleteFile(Database.DatabaseName) then - raise EBold.CreateFmt('%s.CreateInterbaseDatbase: Unable to remove old database file (%s)', [classname, DataBase.DatabaseName]); - db := TIBDatabase.Create(nil); - try - db.DatabaseName := Database.DatabaseName; - db.Params.add(format('USER "%s" PASSWORD "%s" PAGE_SIZE %d', [ // do not localize - username, pwd, PageSize])); - db.SQLDialect := Database.SQLDialect; - db.CreateDatabase; - finally - db.free; - end; + DatabaseInterface.CreateDatabase; end; -destructor TBoldDatabaseAdapterIB.destroy; +destructor TBoldDatabaseAdapterIB.Destroy; begin Changed; FreePublisher; @@ -97,6 +79,11 @@ procedure TBoldDatabaseAdapterIB.EnsureInterbaseDatabase( CreateInterbaseDatabase(PageSize); end; +procedure TBoldDatabaseAdapterIB.CreateDatabase; +begin + CreateInterbaseDatabase; +end; + function TBoldDatabaseAdapterIB.GetDataBase: TIBDataBase; begin result := InternalDatabase as TIBDataBase; @@ -132,5 +119,6 @@ procedure TBoldDatabaseAdapterIB.SetDataBaseEngine( 'dbeUnknown, dbeInterbaseSQLDialect1, dbeInterbaseSQLDialect3', [classname]); end; -end. +initialization +end. diff --git a/Source/Persistence/IBX/BoldIBDatabaseAction.pas b/Source/Persistence/IBX/BoldIBDatabaseAction.pas index bd9569d..e138e75 100644 --- a/Source/Persistence/IBX/BoldIBDatabaseAction.pas +++ b/Source/Persistence/IBX/BoldIBDatabaseAction.pas @@ -1,10 +1,13 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldIBDatabaseAction; interface uses Classes, - IBDatabase, + IBX.IBDatabase, BoldActions, BoldSQLDatabaseConfig, BoldPersistenceHandle, @@ -53,10 +56,11 @@ TBoldIBDatabaseAction = class(TBoldSystemHandleAction) implementation uses BoldDefs, - Controls, // crHourGlass - Forms, // screen + Controls, + Forms, BoldActionDefs, - SysUtils; + SysUtils, + BoldRev; { TBoldIBDatabaseAction } @@ -108,7 +112,7 @@ function TBoldIBDatabaseAction.GetDatabaseAdapterIB: TBoldDatabaseAdapterIB; function TBoldIBDatabaseAction.GetEffectiveDatabaseName: String; begin - result := ChangeFileExt(ParamStr(0), '.gdb'); // do not localize + result := ChangeFileExt(ParamStr(0), '.gdb'); end; function TBoldIBDatabaseAction.GetIBDatabase: TIBDatabase; @@ -154,11 +158,11 @@ procedure TBoldIBDatabaseAction.Loaded; if IBDatabase.SQLDialect = 3 then DatabaseAdapterIB.DatabaseEngine := dbeInterbaseSQLDialect3; end; - if IBDatabase.Params.Values['user_name'] = '' then // do not localize - IBDatabase.Params.Values['user_name'] := Username; // do not localize - if IBDatabase.Params.Values['password'] = '' then // do not localize - IBDatabase.Params.Values['password'] := Password; // do not localize - if IBDatabase.Params.Values['password'] <> '' then // do not localize + if IBDatabase.Params.Values['user_name'] = '' then + IBDatabase.Params.Values['user_name'] := Username; + if IBDatabase.Params.Values['password'] = '' then + IBDatabase.Params.Values['password'] := Password; + if IBDatabase.Params.Values['password'] <> '' then IBDatabase.LoginPrompt := false; if IBDatabase.DatabaseName = '' then @@ -206,4 +210,5 @@ procedure TBoldIBDatabaseAction.SetUserName(const Value: String); fUserName := trim(Value); end; +initialization end. diff --git a/Source/Persistence/IBX/BoldIBInterfaces.pas b/Source/Persistence/IBX/BoldIBInterfaces.pas index 2fbc749..2981000 100644 --- a/Source/Persistence/IBX/BoldIBInterfaces.pas +++ b/Source/Persistence/IBX/BoldIBInterfaces.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldIBInterfaces; interface @@ -5,12 +8,11 @@ interface classes, Dialogs, Db, - IB, - IBQuery, - IBTable, - IBXConst, + IBX.IB, + IBX.IBQuery, + IBX.IBTable, + IBX.IBDataBase, BoldSQLDataBaseConfig, - IBDataBase, BoldBase, BoldDefs, BoldDBInterfaces, @@ -22,33 +24,38 @@ TBoldIBDataBase = class; TBoldIBQuery = class; TBoldIBTable = class; - TBoldIBTransactionMode = (tmUnknown, tmStarted, tmNotStarted); + TBoldIBTransactionMode = (tmUnknown, tmStarted, tmNotStarted); { TBoldIBQuery } - TBoldIBQuery = class(TBoldDataSetWrapper, IBoldQuery, IBoldExecQuery, IBoldParameterized) + TBoldIBQuery = class(TBoldBatchDataSetWrapper, IBoldQuery, IBoldExecQuery, IBoldParameterized) private fQuery: TIBQuery; fOpeningTransactionMode: TBoldIBTransactionMode; function GetQuery: TIBQuery; procedure EnsureTransaction; - // methods that implement IBoldQuery procedure AssignParams(Sourceparams: TParams); function GetParamCount: integer; - function GetParams(i: integer): IBoldParameter; + function GetParamCheck: Boolean; + procedure SetParamCheck(value: Boolean); + function GetParam(i: integer): IBoldParameter; + function GetParams: TParams; function GetRequestLiveQuery: Boolean; - function ParamByName(const Value: string): IBoldParameter; + function ParamByName(const Value: string): IBoldParameter; override; + function FindParam(const Value: string): IBoldParameter; override; procedure SetRequestLiveQuery(NewValue: Boolean); function GetSQLText: String; + function GetSQLStrings: TStrings; procedure AssignSQL(SQL: TStrings); - procedure AssignSQLText(SQL: String); - function Createparam(FldType: TFieldType; const ParamName: string; ParamType: TParamType; Size: integer): IBoldParameter; + procedure AssignSQLText(const SQL: String); + function Createparam(FldType: TFieldType; const ParamName: string; ParamType: TParamType; Size: integer): IBoldParameter; override; function GetRowsAffected: integer; function GetRecordCount: integer; + function GetUseReadTransactions: boolean; + procedure SetUseReadTransactions(value: boolean); + procedure BeginExecuteQuery; + procedure EndExecuteQuery; protected function GetDataSet: TDataSet; override; - procedure StartSQLBatch; virtual; - procedure EndSQLBatch; virtual; - procedure FailSQLBatch; virtual; procedure ClearParams; procedure Open; override; procedure Close; override; @@ -70,7 +77,7 @@ TBoldIBTable = class(TBoldDataSetWrapper, IBoldTable) procedure CreateTable; procedure DeleteTable; function GetIndexDefs: TIndexDefs; - procedure SetTableName(NewName: String); + procedure SetTableName(const NewName: String); function GetTableName: String; procedure SetExclusive(NewValue: Boolean); function GetExclusive: Boolean; @@ -88,6 +95,7 @@ TBoldIBDataBase = class(TBolddatabaseWrapper, IBoldDataBase) fDataBase: TIBDataBase; fCachedTable: TIBTable; fCachedQuery: TIBQuery; + fExecuteQueryCount: integer; function GetDataBase: TIBDataBase; property DataBase: TIBDataBase read GetDataBase; function GetConnected: Boolean; @@ -102,17 +110,22 @@ TBoldIBDataBase = class(TBolddatabaseWrapper, IBoldDataBase) procedure RollBack; procedure Open; procedure Close; - function GetTable: IBoldTable; - procedure ReleaseTable(var Table: IBoldTable); + procedure Reconnect; function SupportsTableCreation: Boolean; procedure ReleaseCachedObjects; + function GetIsExecutingQuery: Boolean; + procedure BeginExecuteQuery; + procedure EndExecuteQuery; protected procedure AllTableNames(Pattern: String; ShowSystemTables: Boolean; TableNameList: TStrings); override; function GetQuery: IBoldQuery; override; procedure ReleaseQuery(var Query: IBoldQuery); override; + function GetTable: IBoldTable; override; + procedure ReleaseTable(var Table: IBoldTable); override; public - constructor Create(DataBase: TIBDataBase; SQLDataBaseConfig: TBoldSQLDatabaseConfig); - destructor Destroy; override; + constructor create(DataBase: TIBDataBase; SQLDataBaseConfig: TBoldSQLDatabaseConfig); + destructor destroy; override; + procedure CreateDatabase; end; implementation @@ -121,8 +134,7 @@ implementation SysUtils, BoldUtils; -resourcestring - SLoginPromptFailure = 'Can not find default login prompt dialog. Please add DBLogDlg to the uses section of your main file or set IBDatabase.LoginPrompt to false.'; + { TBoldIBQuery } procedure TBoldIBQuery.AssignParams(Sourceparams: tparams); @@ -140,7 +152,7 @@ procedure TBoldIBQuery.AssignSQL(SQL: TStrings); Query.SQL.EndUpdate; end; -procedure TBoldIBQuery.AssignSQLText(SQL: String); +procedure TBoldIBQuery.AssignSQLText(const SQL: String); begin Query.SQL.BeginUpdate; Query.SQL.Clear; @@ -149,15 +161,21 @@ procedure TBoldIBQuery.AssignSQLText(SQL: String); end; -constructor TBoldIBQuery.Create(Query: TIBQuery; DatabaseWrapper: TBoldDatabaseWrapper); +procedure TBoldIBQuery.BeginExecuteQuery; begin - inherited Create(DatabaseWrapper); - fQuery := Query; + (DatabaseWrapper as TBoldIBDataBase).EndExecuteQuery; +end; + +procedure TBoldIBQuery.EndExecuteQuery; +begin + (DatabaseWrapper as TBoldIBDataBase).EndExecuteQuery; end; -procedure TBoldIBQuery.EndSQLBatch; +constructor TBoldIBQuery.Create(Query: TIBQuery; DatabaseWrapper: TBoldDatabaseWrapper); begin - // intentionally left blank + inherited Create(DatabaseWrapper); + fQuery := Query; + SetParamCheck(true); end; procedure TBoldIBQuery.EnsureTransaction; @@ -181,6 +199,8 @@ procedure TBoldIBQuery.EnsureTransaction; procedure TBoldIBQuery.ExecSQL; begin + BeginExecuteQuery; + try BoldLogSQL(Query.SQL); try if Query.Transaction.InTransaction then @@ -191,15 +211,23 @@ procedure TBoldIBQuery.ExecSQL; except on e: Exception do begin - e.Message := e.Message + BOLDCRLF + 'SQL: '+Query.SQL.text; // do not localize + e.Message := e.Message + BOLDCRLF + 'SQL: '+Query.SQL.text; raise; end; - end + end; + finally + EndExecuteQuery; + end; end; -procedure TBoldIBQuery.FailSQLBatch; +function TBoldIBQuery.FindParam(const Value: string): IBoldParameter; +var + Param: TParam; begin - // intentionally left blank + result := nil; + Param := Query.Params.FindParam(Value); + if Assigned(Param) then + result := TBoldDbParameter.Create(Param, self) end; function TBoldIBQuery.GetDataSet: TDataSet; @@ -207,14 +235,26 @@ function TBoldIBQuery.GetDataSet: TDataSet; result := Query; end; +function TBoldIBQuery.GetParam(i: integer): IBoldParameter; +begin + result := TBoldDBParameter.Create(Query.Params[i], self); +end; + +function TBoldIBQuery.GetParamCheck: Boolean; +begin + Result := Query.ParamCheck; +end; + function TBoldIBQuery.GetParamCount: integer; begin result := Query.Params.count; end; -function TBoldIBQuery.GetParams(i: integer): IBoldParameter; +type TTIBQueryAccess = class(TIBQuery); + +function TBoldIBQuery.GetParams: TParams; begin - result := TBoldDBParameter.Create(Query.Params[i], self); + result := TTIBQueryAccess(Query).PSGetParams end; function TBoldIBQuery.GetQuery: TIBQuery; @@ -237,13 +277,25 @@ function TBoldIBQuery.GetRowsAffected: integer; result := Query.RowsAffected; end; +function TBoldIBQuery.GetSQLStrings: TStrings; +begin + result := Query.SQL; +end; + function TBoldIBQuery.GetSQLText: String; begin result := Query.SQL.Text; end; +function TBoldIBQuery.GetUseReadTransactions: boolean; +begin + result := false; +end; + procedure TBoldIBQuery.Open; begin + BeginExecuteQuery; + try EnsureTransaction; BoldLogSQL(Query.SQL); try @@ -255,10 +307,13 @@ procedure TBoldIBQuery.Open; except on e: Exception do begin - e.Message := e.Message + BOLDCRLF + 'SQL: '+Query.SQL.text; // do not localize + e.Message := e.Message + BOLDCRLF + 'SQL: '+Query.SQL.text; raise; end; end + finally + EndExecuteQuery; + end; end; procedure TBoldIBQuery.Close; @@ -275,10 +330,7 @@ function TBoldIBQuery.ParamByName(const Value: string): IBoldParameter; Param: TParam; begin Param := Query.ParamByName(Value); - if assigned(Param) then result := TBoldDbParameter.Create(Param, self) - else - result := nil; end; @@ -288,15 +340,19 @@ function TBoldIBQuery.ParamByName(const Value: string): IBoldParameter; end; } +procedure TBoldIBQuery.SetParamCheck(value: Boolean); +begin + Query.ParamCheck := Value; +end; + procedure TBoldIBQuery.SetRequestLiveQuery(NewValue: Boolean); begin - // ignore end; -procedure TBoldIBQuery.StartSQLBatch; +procedure TBoldIBQuery.SetUseReadTransactions(value: boolean); begin - // intentionally left blank + end; function TBoldIBQuery.Createparam(FldType: TFieldType; const ParamName: string; ParamType: TParamType; Size: integer): IBoldParameter; @@ -414,11 +470,10 @@ procedure TBoldIBTable.Open; procedure TBoldIBTable.SetExclusive(NewValue: Boolean); begin -// showmessage('cant set exclusive on IBTables'); end; -procedure TBoldIBTable.SetTableName(NewName: String); +procedure TBoldIBTable.SetTableName(const NewName: String); begin Table.TableName := NewName; end; @@ -432,6 +487,11 @@ procedure TBoldIBDataBase.AllTableNames(Pattern: String; ShowSystemTables: Boole DataBase.GetTableNames(TableNameList, ShowSystemTables); end; +procedure TBoldIBDataBase.BeginExecuteQuery; +begin + inc(fExecuteQueryCount); +end; + procedure TBoldIBDataBase.Close; begin DataBase.Close; @@ -462,6 +522,42 @@ destructor TBoldIBDataBase.destroy; inherited; end; +procedure TBoldIBDataBase.EndExecuteQuery; +begin + dec(fExecuteQueryCount); +end; + +procedure TBoldIBDataBase.CreateDatabase; +var + db: TIBDatabase; + username: String; + pwd: String; +const + cPageSize = 4096; +begin + if not assigned(Database) then + raise EBold.CreateFmt('%s.CreateInterbaseDatbase: Unable to complete operation without an IBDatabase', [classname]); + + username := Database.Params.Values['user_name']; + pwd := Database.Params.Values['password']; + + if (username = '') or (pwd = '') then + raise EBold.CreateFmt('%s.CreateInterbaseDatabase: username or password missing', [classname]); + if FileExists(Database.DatabaseName) then + if not DeleteFile(Database.DatabaseName) then + raise EBold.CreateFmt('%s.CreateInterbaseDatbase: Unable to remove old database file (%s)', [classname, DataBase.DatabaseName]); + db := TIBDatabase.Create(nil); + try + db.DatabaseName := Database.DatabaseName; + db.Params.add(format('USER "%s" PASSWORD "%s" PAGE_SIZE %d', [ + username, pwd, cPageSize])); + db.SQLDialect := Database.SQLDialect; + db.CreateDatabase; + finally + db.free; + end; +end; + function TBoldIBDataBase.GetConnected: Boolean; begin result := DataBase.Connected; @@ -480,6 +576,11 @@ function TBoldIBDataBase.GetInTransaction: Boolean; result := assigned(Transaction) and Transaction.InTransaction; end; +function TBoldIBDataBase.GetIsExecutingQuery: Boolean; +begin + Result := fExecuteQueryCount > 0; +end; + function TBoldIBDataBase.GetIsSQLBased: Boolean; begin result := true; @@ -488,7 +589,6 @@ function TBoldIBDataBase.GetIsSQLBased: Boolean; function TBoldIBDataBase.GetKeepConnection: Boolean; begin result := true - // CHEKCME end; function TBoldIBDataBase.GetLogInPrompt: Boolean; @@ -508,6 +608,7 @@ function TBoldIBDataBase.GetQuery: IBoldQuery; else begin Query := TIBQuery.Create(nil); + Query.UniDirectional := True; Query.DataBase := DataBase; end; if not assigned(Query.Transaction) then @@ -536,9 +637,6 @@ procedure TBoldIBDataBase.Open; var NewTransaction: TIBTransaction; begin - if Database.LogInPrompt and - not (assigned(Database.OnLogin) or assigned(LoginDialogExProc)) then - raise EIBError.Create(SLoginPromptFailure); if not assigned(DataBAse.DefaultTransaction) then begin NewTransaction := TIBTransaction.Create(DataBase); @@ -547,6 +645,14 @@ procedure TBoldIBDataBase.Open; DataBase.Open; end; +procedure TBoldIBDataBase.Reconnect; +begin + if Assigned(fDataBase) then begin + fDataBase.Connected := False; + fDataBase.Connected := True; + end; +end; + procedure TBoldIBDataBase.ReleaseCachedObjects; begin FreeAndNil(fCachedQuery); @@ -567,6 +673,7 @@ procedure TBoldIBDataBase.ReleaseQuery(var Query: IBoldQuery); if fCachedQuery.Active then fCachedQuery.Close; fCachedQuery.SQL.Clear; + fCachedQuery.Params.Clear; end else IBQuery.fQuery.free; @@ -605,7 +712,6 @@ procedure TBoldIBDataBase.RollBack; procedure TBoldIBDataBase.SetKeepConnection(NewValue: Boolean); begin - //CHECKME end; procedure TBoldIBDataBase.SetlogInPrompt(NewValue: Boolean); @@ -629,7 +735,5 @@ function TBoldIBDataBase.SupportsTableCreation: Boolean; result := true; end; +initialization end. - - - diff --git a/Source/Persistence/IBX/BoldPersistenceHandleIB.pas b/Source/Persistence/IBX/BoldPersistenceHandleIB.pas index ff59cce..bcc7fd3 100644 --- a/Source/Persistence/IBX/BoldPersistenceHandleIB.pas +++ b/Source/Persistence/IBX/BoldPersistenceHandleIB.pas @@ -1,10 +1,13 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldPersistenceHandleIB; interface uses Classes, - IBDataBase, + IBX.IBDatabase, BoldDBInterfaces, BoldIBInterfaces, BoldSQLDatabaseConfig, @@ -37,8 +40,8 @@ TBoldPersistenceHandleIB = class(TBoldDBPersistenceHandle) procedure InternalTransferproperties(const target: TBoldPersistenceHandleDB); override; {$ENDIF} public - constructor Create(owner: TComponent); override; - destructor Destroy; override; + constructor create(owner: TComponent); override; + destructor destroy; override; function GetDataBaseInterface: IBoldDatabase; override; published property DatabaseName: String read fDataBaseName write SetDatabaseName; @@ -87,8 +90,8 @@ function TBoldPersistenceHandleIB.getEffectiveDataBase: TIBDataBase; begin fOwnDataBase := TIBDataBase.Create(nil); fOwnDataBase.DatabaseName := DatabaseName; - fOwnDataBase.Params.Values['USER_NAME'] := Username; // do not localize - fOwnDataBase.Params.Values['PASSWORD'] := Password; // do not localize + fOwnDataBase.Params.Values['USER_NAME'] := Username; + fOwnDataBase.Params.Values['PASSWORD'] := Password; if PassWord <> '' then fOwnDataBase.LoginPrompt := false; end; @@ -115,7 +118,7 @@ procedure TBoldPersistenceHandleIB.SetIBDatabase(const Value: TIBDataBase); begin if fIBDataBase <> Value then begin - CheckInactive('SetDataBase'); // do not localize + CheckInactive('SetDataBase'); if assigned(fOwnDataBase) then begin FreeAndNil(FOwnDataBase); @@ -140,26 +143,25 @@ procedure TBoldPersistenceHandleIB.SetPassword(const Value: string); begin inherited; if assigned(fOwnDataBase) then - fOwnDataBase.Params.Values['PASSWORD'] := Password; // do not localize + fOwnDataBase.Params.Values['PASSWORD'] := Password; end; procedure TBoldPersistenceHandleIB.SetUserName(const Value: string); begin inherited; if assigned(fOwnDataBase) then - fOwnDataBase.Params.Values['USER_NAME'] := UserName; // do not localize + fOwnDataBase.Params.Values['USER_NAME'] := UserName; end; procedure TBoldPersistenceHandleIB.DefineProperties(Filer: TFiler); begin inherited DefineProperties(Filer); - // Database changed names to DatabaseName after 2.5 - Filer.DefineProperty('Database', ReadDatabase, nil, True); // do not localize + Filer.DefineProperty('Database', ReadDatabase, nil, True); end; procedure TBoldPersistenceHandleIB.ReadDatabase(Reader: TReader); begin - DatabaseName := Reader.ReadString; + DatabaseName := Reader.ReadString; end; procedure TBoldPersistenceHandleIB.SetDataBaseEngine(const Value: TBoldDataBaseEngine); @@ -181,9 +183,9 @@ procedure TBoldPersistenceHandleIB.InternalTransferproperties( if not assigned(Target.DatabaseAdapter) then begin Target.DatabaseAdapter := tBoldDatabaseAdapterIB.Create(Target.Owner); - Target.DatabaseAdapter.Name := GetNewComponentName(Target.DatabaseAdapter, 'BoldDatabaseAdapterIB'); // do not localize - LongRec(DesInfo).Lo := LongRec(DesInfo).lo+16; //set Left - LongRec(DesInfo).Hi := LongRec(DesInfo).hi+16; //Set Top; + Target.DatabaseAdapter.Name := GetNewComponentName(Target.DatabaseAdapter, 'BoldDatabaseAdapterIB'); + LongRec(DesInfo).Lo := LongRec(DesInfo).lo+16; + LongRec(DesInfo).Hi := LongRec(DesInfo).hi+16; Target.DatabaseAdapter.DesignInfo := DesInfo; showmessage('Created a new DatabaseAdapterIB'); end @@ -197,19 +199,21 @@ procedure TBoldPersistenceHandleIB.InternalTransferproperties( if not assigned(Adapter.Database) then begin Adapter.DataBase := TIBDatabase.Create(Target.owner); - Adapter.DataBase.Name := GetNewComponentName(Adapter.DataBase, 'IBDatabase'); // do not localize + Adapter.DataBase.Name := GetNewComponentName(Adapter.DataBase, 'IBDatabase'); showmessage('Created a new IBDatabase'); - LongRec(DesInfo).Lo := LongRec(DesInfo).lo+16; //set Left - LongRec(DesInfo).Hi := LongRec(DesInfo).hi+16; //Set Top; + LongRec(DesInfo).Lo := LongRec(DesInfo).lo+16; + LongRec(DesInfo).Hi := LongRec(DesInfo).hi+16; Adapter.DataBase.DesignInfo := DesInfo; end; - Adapter.Database.Params.Values['PASSWORD'] := Password; // do not localize - Adapter.Database.Params.Values['USER_NAME'] := Username; // do not localize - if Adapter.Database.Params.Values['PASSWORD'] <> '' then // do not localize + Adapter.Database.Params.Values['PASSWORD'] := Password; + Adapter.Database.Params.Values['USER_NAME'] := Username; + if Adapter.Database.Params.Values['PASSWORD'] <> '' then Adapter.Database.LoginPrompt := false; if not assigned(IBDatabase) then Adapter.DataBase.DatabaseName := DatabaseName; end; +initialization + end. diff --git a/Source/Persistence/IBX/BoldPersistenceHandleIBReg.pas b/Source/Persistence/IBX/BoldPersistenceHandleIBReg.pas index 4b478f6..8f794dc 100644 --- a/Source/Persistence/IBX/BoldPersistenceHandleIBReg.pas +++ b/Source/Persistence/IBX/BoldPersistenceHandleIBReg.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldPersistenceHandleIBReg; interface @@ -6,14 +9,13 @@ procedure Register; implementation -{$R BoldPersistenceHandleIB.res} - uses SysUtils, BoldDefs, DesignIntf, Controls, ActnList, + Actions, DesignEditors, Classes, BoldPropertyEditors, @@ -48,10 +50,8 @@ function TBoldIBDataBaseProperty.FileFilter: string; procedure Register; begin RegisterComponents(BOLDPAGENAME_PERSISTENCE, [TBoldDatabaseAdapterIB]); - {$WARNINGS OFF} RegisterComponents(BOLDPAGENAME_DEPRECATED, [TBoldPersistenceHandleIB]); - RegisterPropertyEditor(TypeInfo(string), TBoldPersistenceHandleIB, 'DataBaseName', TBoldIBDatabaseProperty); // do not localize - {$WARNINGS ON} + RegisterPropertyEditor(TypeInfo(string), TBoldPersistenceHandleIB, 'DataBaseName', TBoldIBDatabaseProperty); RegisterActions(BOLDACTIONGROUPNAME, [TBoldIBDatabaseAction], nil); RegisterComponentEditor(TBoldDatabaseAdapterIB, TBoldDatabaseAdapterIBEditor); @@ -125,6 +125,7 @@ procedure TBoldDatabaseAdapterIBEditor.ExecuteVerb(Index: Integer); end; end; + function TBoldDatabaseAdapterIBEditor.GetVerb(Index: Integer): string; begin case Index of diff --git a/Source/Persistence/IDE/BoldHandlesPropagationReg.pas b/Source/Persistence/IDE/BoldHandlesPropagationReg.pas index 91e6114..6f1295a 100644 --- a/Source/Persistence/IDE/BoldHandlesPropagationReg.pas +++ b/Source/Persistence/IDE/BoldHandlesPropagationReg.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldHandlesPropagationReg; interface @@ -6,8 +9,6 @@ procedure Register; implementation -{.$R *.res} - uses SysUtils, BoldUtils, @@ -30,8 +31,8 @@ procedure RegisterComponentsOnPalette; procedure RegisterEditors; begin - RegisterPropertyEditor(TypeInfo(TBoldAbstractDequeuer), TBoldListenerHandle, 'Dequeuer', TBoldComponentPropertyIndicateMissing); // do not localize - RegisterPropertyEditor(TypeInfo(TBoldListenerHandle), TBoldIDAdderHandle, 'BoldListener', TBoldComponentPropertyIndicateMissing); // do not localize + RegisterPropertyEditor(TypeInfo(TBoldAbstractDequeuer), TBoldListenerHandle, 'Dequeuer', TBoldComponentPropertyIndicateMissing); + RegisterPropertyEditor(TypeInfo(TBoldListenerHandle), TBoldIDAdderHandle, 'BoldListener', TBoldComponentPropertyIndicateMissing); end; procedure Register; diff --git a/Source/Persistence/IDE/BoldObjectUpgraderHandleReg.pas b/Source/Persistence/IDE/BoldObjectUpgraderHandleReg.pas index 1011dd8..fa9e67b 100644 --- a/Source/Persistence/IDE/BoldObjectUpgraderHandleReg.pas +++ b/Source/Persistence/IDE/BoldObjectUpgraderHandleReg.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldObjectUpgraderHandleReg; interface @@ -6,8 +9,6 @@ procedure Register; implementation -{.$R *.res} - uses classes, BoldObjectUpgraderHandle, @@ -19,4 +20,3 @@ procedure Register; end; end. - diff --git a/Source/Persistence/IDE/BoldPersistenceHandleFileReg.pas b/Source/Persistence/IDE/BoldPersistenceHandleFileReg.pas index d59258b..59a34f3 100644 --- a/Source/Persistence/IDE/BoldPersistenceHandleFileReg.pas +++ b/Source/Persistence/IDE/BoldPersistenceHandleFileReg.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldPersistenceHandleFileReg; interface @@ -6,8 +9,6 @@ procedure Register; implementation -{.$R BoldPersistenceHandleFile.res} - uses SysUtils, Classes, @@ -28,7 +29,7 @@ TBoldXMLFileNameProperty = class(TBoldFileNameProperty) {---TBoldRose98FileNameProperty---} function TBoldXMLFileNameProperty.FileFilter: string; begin - Result := Format('%s (*.%s)|*%1:s', [XML_LINKDESC, XML_LINKEXTENSION]); // do not localize + Result := Format('%s (*.%s)|*%1:s', [XML_LINKDESC, XML_LINKEXTENSION]); end; function TBoldXMLFileNameProperty.IsValid: boolean; @@ -48,7 +49,7 @@ function TBoldXMLFileNameProperty.IsValid: boolean; procedure RegisterEditors; begin - RegisterPropertyEditor(TypeInfo(String), TBoldPersistenceHandleFileXML, 'Filename', TBoldXMLFileNameProperty); // do not localize + RegisterPropertyEditor(TypeInfo(String), TBoldPersistenceHandleFileXML, 'Filename', TBoldXMLFileNameProperty); end; procedure Register; diff --git a/Source/Persistence/IDE/BoldPersistenceHandleReg.pas b/Source/Persistence/IDE/BoldPersistenceHandleReg.pas index 9046496..ade1a28 100644 --- a/Source/Persistence/IDE/BoldPersistenceHandleReg.pas +++ b/Source/Persistence/IDE/BoldPersistenceHandleReg.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldPersistenceHandleReg; interface @@ -7,7 +10,6 @@ procedure Register; implementation uses - SysUtils, DesignIntf, BoldAbstractPropertyEditors, BoldAbstractModel, @@ -16,8 +18,8 @@ implementation procedure Register; begin - RegisterPropertyEditor(TypeInfo(TBoldAbstractModel), TBoldPersistenceHandle, 'BoldModel', TBoldComponentPropertyIndicateMissing); // do not localize - RegisterPropertyEditor(TypeInfo(TBoldPersistenceHandle), TBoldPersistenceHandlePassthrough, 'NextPersistenceHandle', TBoldComponentPropertyIndicateMissing); // do not localize + RegisterPropertyEditor(TypeInfo(TBoldAbstractModel), TBoldPersistenceHandle, 'BoldModel', TBoldComponentPropertyIndicateMissing); + RegisterPropertyEditor(TypeInfo(TBoldPersistenceHandle), TBoldPersistenceHandlePassthrough, 'NextPersistenceHandle', TBoldComponentPropertyIndicateMissing); end; end. diff --git a/Source/Persistence/IDE/BoldPersistenceHandleSystemReg.pas b/Source/Persistence/IDE/BoldPersistenceHandleSystemReg.pas index e109608..b536704 100644 --- a/Source/Persistence/IDE/BoldPersistenceHandleSystemReg.pas +++ b/Source/Persistence/IDE/BoldPersistenceHandleSystemReg.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldPersistenceHandleSystemReg; interface @@ -5,9 +8,8 @@ interface procedure Register; implementation -{.$R BoldPersistenceHandleSystem.res} + uses - SysUtils, Classes, BoldIdeConsts, BoldPersistenceHandleSystem; diff --git a/Source/Persistence/IDE/BoldPersistenceNotifierReg.pas b/Source/Persistence/IDE/BoldPersistenceNotifierReg.pas index cf120e0..edfb9ca 100644 --- a/Source/Persistence/IDE/BoldPersistenceNotifierReg.pas +++ b/Source/Persistence/IDE/BoldPersistenceNotifierReg.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldPersistenceNotifierReg; interface @@ -14,7 +17,6 @@ implementation BoldAbstractPropertyEditors, BoldIDEConsts; -{.$R *.res} procedure RegisterComponentsOnPalette; begin @@ -27,7 +29,7 @@ procedure RegisterComponentsOnPalette; procedure RegisterEditors; begin - RegisterPropertyEditor(TypeInfo(TBoldPersistenceHandle), TBoldAbstractPersistenceNotifier, 'PersistenceHandle', TBoldComponentPropertyIndicateMissing); // do not localize + RegisterPropertyEditor(TypeInfo(TBoldPersistenceHandle), TBoldAbstractPersistenceNotifier, 'PersistenceHandle', TBoldComponentPropertyIndicateMissing); end; procedure Register; diff --git a/Source/Persistence/IDECOM/BoldComPersistenceHandleReg.pas b/Source/Persistence/IDECOM/BoldComPersistenceHandleReg.pas index d06b231..99f0535 100644 --- a/Source/Persistence/IDECOM/BoldComPersistenceHandleReg.pas +++ b/Source/Persistence/IDECOM/BoldComPersistenceHandleReg.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldComPersistenceHandleReg; interface @@ -6,8 +9,6 @@ procedure Register; implementation -{$R BoldComPersistenceHandleReg.Res} - uses Classes, DesignIntf, @@ -22,7 +23,7 @@ procedure Register; RegisterComponents(BOLDPAGENAME_PERSISTENCE,[ TBoldSOAPClientPersistenceHandle, TBoldSOAPServerPersistenceHandle]); - RegisterPropertyEditor(TypeInfo(String), TBoldSOAPClientPersistenceHandle, 'Objectname', TBoldObjectNameProperty); // do not localize + RegisterPropertyEditor(TypeInfo(String), TBoldSOAPClientPersistenceHandle, 'Objectname', TBoldObjectNameProperty); end; end. diff --git a/Source/Persistence/IDECOM/BoldHTTPClientPersistenceHandleReg.pas b/Source/Persistence/IDECOM/BoldHTTPClientPersistenceHandleReg.pas index d78a7a3..eb40e4f 100644 --- a/Source/Persistence/IDECOM/BoldHTTPClientPersistenceHandleReg.pas +++ b/Source/Persistence/IDECOM/BoldHTTPClientPersistenceHandleReg.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldHTTPClientPersistenceHandleReg; interface @@ -6,10 +9,9 @@ procedure Register; implementation -{$R *.res} - uses BoldIDEConsts, + BoldGuard, BoldHTTPClientPersistenceHandle, Classes; diff --git a/Source/Persistence/IDECOM/BoldHTTPServerPersistenceHandlePassthroughReg.pas b/Source/Persistence/IDECOM/BoldHTTPServerPersistenceHandlePassthroughReg.pas index 51f6dcf..1ccb160 100644 --- a/Source/Persistence/IDECOM/BoldHTTPServerPersistenceHandlePassthroughReg.pas +++ b/Source/Persistence/IDECOM/BoldHTTPServerPersistenceHandlePassthroughReg.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldHTTPServerPersistenceHandlePassthroughReg; interface @@ -6,10 +9,9 @@ procedure Register; implementation -{$R *.res} - uses BoldIDEConsts, + BoldGuard, BoldHTTPServerPersistenceHandlePassthrough, Classes; diff --git a/Source/Persistence/IDEUDP/BoldUDPBroadcasterReg.pas b/Source/Persistence/IDEUDP/BoldUDPBroadcasterReg.pas index 86c43b8..2d06bc5 100644 --- a/Source/Persistence/IDEUDP/BoldUDPBroadcasterReg.pas +++ b/Source/Persistence/IDEUDP/BoldUDPBroadcasterReg.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldUDPBroadcasterReg; interface @@ -11,12 +14,9 @@ implementation BoldIDEConsts, BoldUDPModificationBroadCaster; -{$R BoldUDPBroadCaster.res} - procedure Register; begin RegisterComponents(BOLDPAGENAME_OSS_CMS, [TBoldUDPModificationBroadcaster]); end; end. - diff --git a/Source/Persistence/ObjectUpgrading/BoldAbstractObjectUpgraderHandle.pas b/Source/Persistence/ObjectUpgrading/BoldAbstractObjectUpgraderHandle.pas index 246032b..78e1e92 100644 --- a/Source/Persistence/ObjectUpgrading/BoldAbstractObjectUpgraderHandle.pas +++ b/Source/Persistence/ObjectUpgrading/BoldAbstractObjectUpgraderHandle.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldAbstractObjectUpgraderHandle; interface @@ -19,7 +22,7 @@ TBoldAbstractObjectUpgraderHandle = class(TBoldHandle) function CreateObjectUpgrader: TBoldAbstractObjectUpgrader; virtual; abstract; function GetHandledObject: TObject; override; public - destructor Destroy; override; + destructor destroy; override; property ObjectUpgrader: TBoldAbstractObjectUpgrader read GetObjectUpgrader; published property Config: TBoldObjectUpgraderConfiguration read GetConfig write SetConfig; @@ -28,7 +31,8 @@ TBoldAbstractObjectUpgraderHandle = class(TBoldHandle) implementation uses - SysUtils; + SysUtils, + BoldRev; { TBoldAbstractObjectUpgraderHandle } @@ -73,5 +77,5 @@ procedure TBoldAbstractObjectUpgraderHandle.SetConfig(const Value: TBoldObjectUp fConfig.add.Assign(Value[i]); end; +initialization end. - diff --git a/Source/Persistence/ObjectUpgrading/BoldBatchUpgrader.pas b/Source/Persistence/ObjectUpgrading/BoldBatchUpgrader.pas index 08f5012..3ef6589 100644 --- a/Source/Persistence/ObjectUpgrading/BoldBatchUpgrader.pas +++ b/Source/Persistence/ObjectUpgrading/BoldBatchUpgrader.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldBatchUpgrader; interface @@ -49,8 +52,7 @@ implementation BoldCondition, BoldDbInterfaces, BoldPMappers, - BoldUtils, - PersistenceConsts; + BoldUtils; procedure TBoldBatchUpgrader.AutoUpgradeObjects; var @@ -78,7 +80,7 @@ constructor TBoldBatchUpgrader.Create(SystemMapper: TBoldSystemDefaultMapper; Up begin inherited create; if not SystemMapper.SupportsObjectUpgrading then - raise EBold.CreateFmt(sUpgradeNotSupported, [ClassName]); + raise EBold.CreateFmt('%s.Create: The SystemPersistenceMapper does not support object upgrading!', [ClassName]); fSystemMapper := SystemMapper; fUpgrader := Upgrader; fBatchSize := 100; @@ -99,8 +101,7 @@ procedure TBoldBatchUpgrader.UpgradeClass(TopSortedIndex: integer); TranslationList := TBoldIdTranslationList.Create; try Condition.TopSortedIndex := TopSortedIndex; - // exact type and not the current version. - Condition.WhereFragment := format( '%s = %d AND %s <> %d', [ // do not localize + Condition.WhereFragment := format( '%s = %d AND %s <> %d', [ TYPECOLUMN_NAME, SystemMapper.BoldDbTypeForTopSortedIndex(TopSortedIndex), SystemMapper.RootClassObjectPersistenceMapper.ModelVersionMember.ColumnDescriptions[0].SQLName, @@ -147,30 +148,28 @@ procedure TBoldBatchUpgrader.UpgradeObjectIdList(ObjectIdList: TBoldObjectIdList for i := 0 to ObjectIdList.Count - 1 do begin if not ObjectIdList[i].TopSortedIndexExact then - raise EBold.createFmt(sObjectIDListNotExact, [Classname]); + raise EBold.createFmt('%s.UpgradeObjectIdList: ObjectIdlist not Exact', [Classname]); if ObjectIdList[i].topSortedIndex <> ObjectMapper.TopSortedIndex then - raise EBold.createFmt(sObjectIDListNotHomogenous, [Classname]); + raise EBold.createFmt('%s.UpgradeObjectIdList: ObjectIdlist not homogenous', [Classname]); TempLIst.Append(ObjectIdList[i].asString); end; if (MemberPMList.Count > 0) and (TempList.Count > 0) then begin - BoldAppendToStrings(SQL, Format('in (%s)',[BoldSeparateStringList(TempList, ', ', '', '')]), False); // do not localize + BoldAppendToStrings(SQL, Format('in (%s)',[BoldSeparateStringList(TempList, ', ', '', '')]), False); if Objectmapper.versioned then - Objectmapper.RetrieveTimeStampCondition(SQL, BOLDMAXTIMESTAMP, true, 'AND', false); // do not localize + Objectmapper.RetrieveTimeStampCondition(SQL, BOLDMAXTIMESTAMP, true, 'AND', false); aQuery.AssignSQL(SQL); aQuery.Open; while not aQuery.EOF do begin - tempId := SystemMapper.NewIdFromQuery(aQuery, 1, 0, BOLDMAXTIMESTAMP); + // ClassId param -1 was added due to changes in signature of NewIdFromQuery, + // check if we can replace -1 with known ClassId if possible in order to get ExactId right away - Daniel + tempId := SystemMapper.NewIdFromQuery(aQuery, -1, 1, 0, BOLDMAXTIMESTAMP); NewId := ObjectIdList.IDByID[TempId]; TempId.Free; - // is this safe? perhaps the object was guardupgraded while we were doing other things... -// if not ObjectMapper.IsOldVersion(aQuery) then -// raise EBold.CreateFmt('%s.UpgradeObjectIdList: Was fed an object that does not need upgrading!', [ClassName]); - Upgrader.UpgradeObjectById(NewId, aQuery); inc(fUpgradedObjects); aQuery.Next; @@ -204,7 +203,7 @@ procedure TBoldBatchUpgrader.UpgradeObjects; if IsUpgrading then exit; if not assigned(SystemMapper.DataBase) then - raise EBold.CreateFmt(sDBMustBeOpened, [classname]); + raise EBold.CreateFmt('%s.UpgradeObjects: The database must be opened first', [classname]); fIsUpgrading := true; try fStartTime := now; @@ -217,4 +216,6 @@ procedure TBoldBatchUpgrader.UpgradeObjects; end; end; +initialization + end. diff --git a/Source/Persistence/ObjectUpgrading/BoldObjectUpgrader.pas b/Source/Persistence/ObjectUpgrading/BoldObjectUpgrader.pas index d2dfa6a..10e8a02 100644 --- a/Source/Persistence/ObjectUpgrading/BoldObjectUpgrader.pas +++ b/Source/Persistence/ObjectUpgrading/BoldObjectUpgrader.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldObjectUpgrader; interface @@ -80,8 +83,7 @@ implementation BoldPMappersSQL, BoldUtils, BoldGuard, - BoldDomainElement, - BoldCoreConsts; + BoldDomainElement; { TBoldObjectUpgrader } @@ -132,21 +134,19 @@ procedure TBoldObjectUpgrader.FetchObjectForId(ObjectId: TBoldObjectId; Query: I ObjectList: TBoldObjectlist; begin Guard := TBoldGuard.Create(Objectlist, IdList, MemberPMList); - + MemberPMList := TBoldMemberPersistenceMapperList.Create; MemberPMList.OwnsEntries := false; IdList := TBoldObjectIdList.Create; Objectlist := TBoldObjectList.Create; - // this procedure loads an object into the local objectlayer using the external persistencemapper, - // but bypassing the code for using the ObjectUpgrader IdList.Add(ObjectId); ObjectMapper := ObjectMapperForId(ObjectId); ObjectMapper.BuildMemberFetchLists(nil, MemberPMList, nil, fmNormal); ObjectMapper.HandleFetchData(ObjectId, ValueSpacePmIn, nil, query, MemberPMList, fmNormal, nil); Objectlist.Add(BoldSystem.EnsuredLocatorByID[ObjectId].BoldObject); - + TBoldExposedSystem(BoldSystem).SystemPersistenceHandler.EndFetchForAll(ObjectList, nil); end; @@ -175,7 +175,7 @@ procedure TBoldObjectUpgrader.GenerateAutoUpgradeScript(Script: TStrings); UpgradeWholeClass.Add(IntToStr(ObjectMapper.BoldDbType)) else if ConfigItem.UpgradeOlderThanVersion < CurrentVersion then begin - Script.Add(format('UPDATE %s SET %s = %d WHERE (%s = %d) AND (%s >= %d) AND (%s <> %d)', [ // do not localize + Script.Add(format('UPDATE %s SET %s = %d WHERE (%s = %d) AND (%s >= %d) AND (%s <> %d)', [ RootTable, VersionColumn, CurrentVersion, TYPECOLUMN_NAME, ObjectMapper.BoldDbType, @@ -185,7 +185,7 @@ procedure TBoldObjectUpgrader.GenerateAutoUpgradeScript(Script: TStrings); end; end; if UpgradeWholeClass.Count <> 0 then - Script.Add(format('UPDATE %s SET %s = %d WHERE %s IN (%s) AND (%s <> %d)', [ // do not localize + Script.Add(format('UPDATE %s SET %s = %d WHERE %s IN (%s) AND (%s <> %d)', [ RootTable, VersionColumn, CurrentVersion, TYPECOLUMN_NAME, BoldSeparateStringList(UpgradeWholeClass, ', ', '', ''), @@ -203,9 +203,9 @@ function TBoldObjectUpgrader.GetBoldSystem: TBoldSystem; aSystemTypeInfo := SystemTypeInfo; aPController := PersistenceController; if not assigned(aSystemTypeInfo) then - raise EBold.CreateFmt(sMissingTypeInfo, [classname]); + raise EBold.CreateFmt('%s.GetBoldSystem: Missing System Type Info', [classname]); if not assigned(aPController) then - raise EBold.CreateFmt(sMissingPersistenceController, [classname]); + raise EBold.CreateFmt('%s.GetBoldSystem: Missing Persistence Controller', [classname]); fBoldSystem := TBoldSystem.CreateWithTypeInfo(nil, aSystemTypeInfo, aPController) end; result := fBoldSystem; @@ -234,7 +234,7 @@ function TBoldObjectUpgrader.ObjectMapperForId(ObjectId: TBoldObjectId): TBoldOb procedure TBoldObjectUpgrader.ReleaseBoldSystem; begin if (fNestingLevel <> 0) then - raise EBold.CreateFmt(sCannotReleaseInOperation, [classname]); + raise EBold.CreateFmt('%s.ReleaseBoldSystem: can not release the system while in an upgrade operation', [classname]); FreeAndNil(fBoldSystem); end; @@ -248,13 +248,16 @@ procedure TBoldObjectUpgrader.UpgradeObject(Obj: TBoldObject); ConfigItem: TBoldObjectUpgraderConfigurationItemWithEvent; begin ConfigItem := Config.ItemByName[Obj.BoldClassTypeInfo.Expressionname] as TBoldObjectUpgraderConfigurationItemWithEvent; +{$IFNDEF CompareToOldValues} Obj.MarkObjectDirty; +{$ENDIF} if assigned(ConfigItem) and assigned(ConfigItem.OnUpgradeObject) then ConfigItem.OnUpgradeObject(Obj) else if assigned(OnUpgradeObject) then OnUpgradeObject(Obj); - // in case some user decides to call discard on the object, we better dirtify it again. +{$IFNDEF CompareToOldValues} Obj.MarkObjectDirty; +{$ENDIF} end; procedure TBoldObjectUpgrader.UpgradeObjectById(ObjectId: TBoldObjectId; Query: IBoldQuery); @@ -296,5 +299,5 @@ function TBoldObjectUpgraderConfigurationItemWithEvent.GetNamePath: String; result := Config.ConfigOwner.GetNamePath +'._'+ExpressionName+'_'; end; +initialization end. - diff --git a/Source/Persistence/ObjectUpgrading/BoldObjectUpgraderHandle.pas b/Source/Persistence/ObjectUpgrading/BoldObjectUpgraderHandle.pas index dad82ff..5ee74d8 100644 --- a/Source/Persistence/ObjectUpgrading/BoldObjectUpgraderHandle.pas +++ b/Source/Persistence/ObjectUpgrading/BoldObjectUpgraderHandle.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldObjectUpgraderHandle; interface @@ -32,8 +35,8 @@ TBoldObjectUpgraderHandle = class(TBoldAbstractObjectUpgraderHandle) function CreateObjectUpgrader: TBoldAbstractObjectUpgrader; override; function ConfigClass: TBoldObjectUpgraderConfigClass; override; public - constructor Create(owner: TComponent); override; - destructor Destroy; override; + constructor create(owner: TComponent); override; + destructor destroy; override; property ObjectUpgrader: TBoldObjectUpgrader read GetObjectUpgrader; published property PersistenceHandle: TBoldAbstractPersistenceHandleDB read FPersistenceHandle write SetPersistenceHandle; @@ -44,7 +47,8 @@ TBoldObjectUpgraderHandle = class(TBoldAbstractObjectUpgraderHandle) implementation uses - SysUtils; + SysUtils, + BoldRev; const breSystemTypeInfoHandleDestroying = 100; @@ -73,7 +77,7 @@ function TBoldObjectUpgraderHandle.CreateObjectUpgrader: TBoldAbstractObjectUpgr destructor TBoldObjectUpgraderHandle.destroy; begin FreeAndNil(fComponentSubscriber); - inherited; + inherited; end; function TBoldObjectUpgraderHandle.GetObjectUpgrader: TBoldObjectUpgrader; @@ -148,4 +152,6 @@ procedure TBoldObjectUpgraderHandle._ReceiveComponentEvents(Originator: TObject; ObjectUpgrader.ReleaseBoldSystem; end; + +initialization end. diff --git a/Source/Persistence/Propagation/BoldIDAdder.pas b/Source/Persistence/Propagation/BoldIDAdder.pas index fc37f68..1456ec4 100644 --- a/Source/Persistence/Propagation/BoldIDAdder.pas +++ b/Source/Persistence/Propagation/BoldIDAdder.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldIDAdder; interface @@ -5,7 +8,7 @@ interface uses BoldPersistenceControllerPassthrough, BoldID, - BoldUpdatePrecondition, + BoldUpdatePrecondition, BoldCondition, BoldValueSpaceInterfaces, BoldListenerThread, @@ -24,13 +27,16 @@ TBoldIDAdder = class(TBoldPersistenceControllerPassthrough) constructor Create; procedure PMFetch(ObjectIdList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; MemberIdList: TBoldMemberIdList; FetchMode: Integer; BoldClientID: TBoldClientID); override; procedure PMFetchIDListWithCondition(ObjectIdList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; FetchMode: Integer; Condition: TBoldCondition; BoldClientID: TBoldClientID); override; - procedure PMUpdate(ObjectIdList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; Old_Values: IBoldValueSpace; Precondition: TBoldUpdatePrecondition; TranslationList: TBoldIdTranslationList; var TimeStamp: TBoldTimeStampType; BoldClientID: TBoldClientID); override; + procedure PMUpdate(ObjectIdList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; Old_Values: IBoldValueSpace; Precondition: TBoldUpdatePrecondition; TranslationList: TBoldIdTranslationList; var TimeStamp: TBoldTimeStampType; var TimeOfLatestUpdate: TDateTime; BoldClientID: TBoldClientID); override; property BoldClientID: TBoldClientID read GetClientID; property Listener: TBoldListenerThread read fListener write fListener; end; implementation +uses + BoldRev; + { TBoldIDAdder } constructor TBoldIDAdder.Create; @@ -45,7 +51,7 @@ function TBoldIDAdder.GetClientID: TBoldClientID; procedure TBoldIDAdder.PMFetch(ObjectIdList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; MemberIdList: TBoldMemberIdList; - FetchMode: Integer; + FetchMode: Integer; BoldClientID: TBoldClientID); begin if Listener.Suspended then @@ -67,8 +73,8 @@ procedure TBoldIDAdder.PMFetchIDListWithCondition( procedure TBoldIDAdder.PMUpdate(ObjectIdList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; Old_Values: IBoldValueSpace; - Precondition: TBoldUpdatePrecondition; - TranslationList: TBoldIdTranslationList; var TimeStamp: TBoldTimeStampType; + Precondition: TBoldUpdatePrecondition; + TranslationList: TBoldIdTranslationList; var TimeStamp: TBoldTimeStampType; var TimeOfLatestUpdate: TDateTime; BoldClientID: TBoldClientID); begin if Listener.Suspended then @@ -77,4 +83,6 @@ procedure TBoldIDAdder.PMUpdate(ObjectIdList: TBoldObjectIdList; inherited; end; +initialization + end. diff --git a/Source/Persistence/Propagation/BoldIDAdderHandle.pas b/Source/Persistence/Propagation/BoldIDAdderHandle.pas index cc5511b..44494f9 100644 --- a/Source/Persistence/Propagation/BoldIDAdderHandle.pas +++ b/Source/Persistence/Propagation/BoldIDAdderHandle.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldIDAdderHandle; interface @@ -50,8 +53,7 @@ implementation SysUtils, BoldUtils, BoldIDAdder, - dialogs, - BoldPMConsts; + dialogs; { TBoldIDAdderHandle } @@ -75,18 +77,12 @@ function TBoldIDAdderHandle.CreatePersistenceController: TBoldPersistenceControl procedure TBoldIDAdderHandle.DefineProperties(Filer: TFiler); begin inherited; - // property AutoStart moved to TBoldListenerHandle - Filer.DefineProperty('AutoStart', ReadObsoleteAutoStartProperty, nil, True); // do not localize - // property AutoExtendLease moved to TBoldListenerHandle - Filer.DefineProperty('AutoExtendLease', ReadObsoleteAutoExtendLeaseProperty, nil, True); // do not localize - // property LeaseDuration moved to TBoldListenerHandle - Filer.DefineProperty('LeaseDuration', ReadObsoleteLeaseDurationProperty, nil, True); // do not localize - // property Polling interval moved to TBoldListenerHandle - Filer.DefineProperty('PollingInterval', ReadObsoletePollingIntervalProperty, nil, True); // do not localize - // property MachineName moved to TBoldPropagatorHandleCOM - Filer.DefineProperty('MachineName', ReadObsoleteMachineNameProperty, nil, True); // do not localize - // event handler OnRegistrationFailed moved to TBoldListenerHandle - Filer.DefineProperty('OnRegistrationFailed', ReadObsoleteOnRegistrationFailedEventHandler, nil, True); // do not localize + Filer.DefineProperty('AutoStart', ReadObsoleteAutoStartProperty, nil, True); + Filer.DefineProperty('AutoExtendLease', ReadObsoleteAutoExtendLeaseProperty, nil, True); + Filer.DefineProperty('LeaseDuration', ReadObsoleteLeaseDurationProperty, nil, True); + Filer.DefineProperty('PollingInterval', ReadObsoletePollingIntervalProperty, nil, True); + Filer.DefineProperty('MachineName', ReadObsoleteMachineNameProperty, nil, True); + Filer.DefineProperty('OnRegistrationFailed', ReadObsoleteOnRegistrationFailedEventHandler, nil, True); end; destructor TBoldIDAdderHandle.Destroy; @@ -102,10 +98,10 @@ procedure TBoldIDAdderHandle.ReadObsoleteAutoExtendLeaseProperty(Reader: TReader begin OldPropertyValue := Reader.ReadBoolean; if OldPropertyValue then - ValueAsString := 'True' // do not localize + ValueAsString := 'True' else - ValueAsString := 'False'; // do not localize - ReadObsoleteProperty(Reader, 'AutoExtendLease', 'AutoExtendLease', ValueAsString, 'TBoldListenerHandle'); // do not localize + ValueAsString := 'False'; + ReadObsoleteProperty(Reader, 'AutoExtendLease', 'AutoExtendLease', ValueAsString, 'TBoldListenerHandle'); end; procedure TBoldIDAdderHandle.ReadObsoleteAutoStartProperty(Reader: TReader); @@ -115,10 +111,10 @@ procedure TBoldIDAdderHandle.ReadObsoleteAutoStartProperty(Reader: TReader); begin OldPropertyValue := Reader.ReadBoolean; if OldPropertyValue then - ValueAsString := 'True' // do not localize + ValueAsString := 'True' else - ValueAsString := 'False'; // do not localize - ReadObsoleteProperty(Reader, 'AutoStart', 'AutoStart', ValueAsString, 'TBoldListenerHandle'); // do not localize + ValueAsString := 'False'; + ReadObsoleteProperty(Reader, 'AutoStart', 'AutoStart', ValueAsString, 'TBoldListenerHandle'); end; procedure TBoldIDAdderHandle.ReadObsoleteLeaseDurationProperty(Reader: TReader); @@ -128,7 +124,7 @@ procedure TBoldIDAdderHandle.ReadObsoleteLeaseDurationProperty(Reader: TReader); begin OldPropertyValue := Reader.ReadInteger; ValueAsString := IntToStr(OldPropertyValue); - ReadObsoleteProperty(Reader, 'LeaseDuration', 'LeaseDuration', ValueAsString, 'TBoldListenerHandle'); // do not localize + ReadObsoleteProperty(Reader, 'LeaseDuration', 'LeaseDuration', ValueAsString, 'TBoldListenerHandle'); end; procedure TBoldIDAdderHandle.ReadObsoleteMachineNameProperty(Reader: TReader); @@ -136,7 +132,7 @@ procedure TBoldIDAdderHandle.ReadObsoleteMachineNameProperty(Reader: TReader); OldPropertyValue: string; begin OldPropertyValue := Reader.ReadString; - ReadObsoleteProperty(Reader, 'MachineName', 'ServerHost', OldPropertyValue, 'TBoldPropagatorHandleCom'); // do not localize + ReadObsoleteProperty(Reader, 'MachineName', 'ServerHost', OldPropertyValue, 'TBoldPropagatorHandleCom'); end; procedure TBoldIDAdderHandle.ReadObsoleteOnRegistrationFailedEventHandler( @@ -145,7 +141,7 @@ procedure TBoldIDAdderHandle.ReadObsoleteOnRegistrationFailedEventHandler( OldPropertyValue: string; begin OldPropertyValue := Reader.ReadString; - ReadObsoleteProperty(Reader, 'OnRegistrationFailed', 'OnRegistrationFailed', OldPropertyValue, 'TBoldListenerHandle'); // do not localize + ReadObsoleteProperty(Reader, 'OnRegistrationFailed', 'OnRegistrationFailed', OldPropertyValue, 'TBoldListenerHandle'); end; procedure TBoldIDAdderHandle.ReadObsoletePollingIntervalProperty(Reader: TReader); @@ -155,14 +151,14 @@ procedure TBoldIDAdderHandle.ReadObsoletePollingIntervalProperty(Reader: TReader begin OldPropertyValue := Reader.ReadInteger; ValueAsString := IntToStr(OldPropertyValue); - ReadObsoleteProperty(Reader, 'PollingInterval', 'PollingInterval', ValueAsString, 'TBoldListenerHandle'); // do not localize + ReadObsoleteProperty(Reader, 'PollingInterval', 'PollingInterval', ValueAsString, 'TBoldListenerHandle'); end; procedure TBoldIDAdderHandle.ReadObsoleteProperty(Reader: TReader; const PropertyName, NewPropertyName, OldPropertyValue, ComponentName: string); begin if (csDesigning in ComponentState) then - MessageDlg(Format(sPropertyHasMoved, + MessageDlg(Format('%s.%s has been moved to component (%s.%s). Old value was "%s"', [ClassName, PropertyName, ComponentName, NewPropertyName, OldPropertyValue]), mtWarning, [mbOK], 0); end; @@ -204,4 +200,6 @@ procedure TBoldIDAdderHandle.Subscribe(const DoSubscribe: Boolean); fPTSubscriber.CancelAllSubscriptions; end; +initialization + end. diff --git a/Source/Persistence/Propagation/BoldListenerCOM.pas b/Source/Persistence/Propagation/BoldListenerCOM.pas index b4feda2..a03d22f 100644 --- a/Source/Persistence/Propagation/BoldListenerCOM.pas +++ b/Source/Persistence/Propagation/BoldListenerCOM.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldListenerCOM; interface @@ -24,7 +27,7 @@ EBoldPropagatorTypeLib = class(EBold); TBoldExtendLeaseResult = (elrExtended, elrFailed, elrFailedExpired, elrDenied, elrNotRegistered); TBoldExtendLeaseFailureEvent = procedure(res: TBoldExtendLeaseResult; const Msg: string) of object; - TBoldMessageEvent = function(aMessage: string): Boolean of object; + TBoldMessageEvent = function(const aMessage: string): Boolean of object; { TBoldListenerCOM } TBoldListenerCOM = class(TComObject, IBoldListener, IBoldListenerAdmin) @@ -99,8 +102,9 @@ implementation SysUtils, Variants, BoldPersistenceController, - Activex, - Windows; + Activex, + Windows, + BoldRev; { TBoldListenerCOM } @@ -116,7 +120,6 @@ constructor TBoldListenerCOM.Create( aQueue: TBoldThreadSafeStringQueue; self.fPollingInterval := PollingInterval; self.fLeaseDuration := LeaseDuration; Self.fExtendLeaseAfter := ExtendLeaseAfter; - // It is important that the leaseduration and extendLeaseAfter is set up before the AutoExtendLease to get the correct interval self.AutoExtendLease := AutoExtendLease; self.fClientIdentifierString := ClientIdentifierString; Registered := false; @@ -236,12 +239,9 @@ procedure TBoldListenerCOM.OnTimer(Sender: TObject); fTimer.Interval := DefaultExtendLeaseInterval; end; elrFailed: begin - // wait 20% of the remaining time fTimer.Interval := round(LeaseTimeLeft * 0.2); - // but no more than half the usual time if fTimer.Interval > DefaultExtendLeaseInterval div 2 then fTimer.Interval := DefaultExtendLeaseInterval div 2; - // and no less than one second if fTimer.Interval < 1000 then fTimer.Interval := 1000; end; @@ -263,7 +263,7 @@ function TBoldListenerCOM.ExtendLease: TBoldExtendLeaseResult; if extended then result := elrExtended else - result := elrDenied; + result := elrDenied; except on E: Exception do begin @@ -277,7 +277,6 @@ function TBoldListenerCOM.ExtendLease: TBoldExtendLeaseResult; if result in [elrDenied, elrFailedExpired] then begin - // in the future, when the propagator allows reconnect after timeout, this code should go away... if Assigned(fPropagator) then fPropagator._Release; Registered := false; @@ -355,7 +354,7 @@ procedure TBoldListenerCOM.DisconnectClient(const aMessage: WideString; RemainDi MSecs := TimeStampToMSecs(DateTimeToTimeStamp(now)); MSecs := MSecs + RemainDisconnected; fConnectAllowed := TimeStampToDateTime(MSecsToTimeStamp(MSecs)); - Queue.Enqueue(format('DISCONNECT:%d:%s', [RemainDisconnected, aMessage])); //do not localize + Queue.Enqueue(format('DISCONNECT:%d:%s', [RemainDisconnected, aMessage])); if Assigned(QueueNotEmptyNotifyEvent) then QueueNotEmptyNotifyEvent(Self); end; @@ -369,7 +368,8 @@ function TBoldListenerCOM.Ping: Integer; constructor TBoldListenerCOMFactory.Create(ComServer: TComServerObject); begin - inherited Create(ComServer, TBoldListenerCOM, CLASS_BoldListener, 'TBoldListenerCOM', 'BoldListenerCOM', ciInternal); //do not localize + inherited Create(ComServer, TBoldListenerCOM, CLASS_BoldListener, 'TBoldListenerCOM', 'BoldListenerCOM', ciInternal); end; +initialization end. diff --git a/Source/Persistence/Propagation/BoldListenerHandle.pas b/Source/Persistence/Propagation/BoldListenerHandle.pas index 2628066..242b15b 100644 --- a/Source/Persistence/Propagation/BoldListenerHandle.pas +++ b/Source/Persistence/Propagation/BoldListenerHandle.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldListenerHandle; interface @@ -22,7 +25,7 @@ TBoldListenerHandle = class(TBoldHandle) private fActive: Boolean; fBoldListenerThread: TBoldListenerThread; - fDequeuer: TBoldAbstractDequeuer; + fDequeuer: TBoldStringDequeuer; fPTSubscriber: TBoldPassThroughSubscriber; fAutoStart: Boolean; fLeaseDuration: integer; @@ -35,10 +38,10 @@ TBoldListenerHandle = class(TBoldHandle) fPropagatorHandle: TBoldAbstractPropagatorHandle; fOnThreadError: TBoldMessageEvent; fExtendLeaseAfter: integer; - procedure _Receive(Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent); + procedure _Receive(Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent); function GetListenerThread: TBoldListenerThread; function GetConnected: Boolean; - procedure SetDequeuer(aDequeuer: TBoldAbstractDequeuer); + procedure SetDequeuer(aDequeuer: TBoldStringDequeuer); procedure NotifyDequeuer(Sender: TObject); procedure setLeaseDuration(Value: integer); procedure setPollingInterval(Value: integer); @@ -50,11 +53,11 @@ TBoldListenerHandle = class(TBoldHandle) function GetIsLoaded: Boolean; procedure StopAndFreeListenerThread; procedure SetExtendLeaseAfter(const Value: integer); - procedure Subscribe(const DoSubscribe: Boolean); + procedure Subscribe(const DoSubscribe: Boolean); protected function GetHandledObject: TObject; override; function GetBoldClientID: TBoldClientID; - procedure Notification(AComponent: TComponent; Operation: TOperation); override; + procedure Notification(AComponent: TComponent; Operation: TOperation); override; property IsLoaded: Boolean read GetIsLoaded; public constructor Create(Owner: TComponent); override; @@ -73,7 +76,7 @@ TBoldListenerHandle = class(TBoldHandle) property ExtendLeaseAfter: integer read fExtendLeaseAfter write SetExtendLeaseAfter; property PollingInterval: integer read fPollingInterval write setPollingInterval; property AutoExtendLease: Boolean read fAutoExtendLease write setAutoExtendLease; - property Dequeuer: TBoldAbstractDequeuer read fDequeuer write SetDequeuer; + property Dequeuer: TBoldStringDequeuer read fDequeuer write SetDequeuer; property ClientIdentifierString: string read fClientIdentifierString write setClientIdentifierString; property PropagatorHandle: TBoldAbstractPropagatorHandle read fPropagatorHandle write SetPropagatorHandle; property OnRegistrationFailed: TNotifyEvent read FOnRegistrationFailed write FOnRegistrationFailed; @@ -89,7 +92,6 @@ implementation BoldEnvironment, Windows, Messages, - BoldPMConsts, BoldThreadSafeQueue; { TBoldListenerHandle } @@ -98,7 +100,7 @@ constructor TBoldListenerHandle.Create(Owner: TComponent); begin inherited; FClientIdentifierString := ''; - fPTSubscriber := TBoldPassthroughSubscriber.Create(_Receive); + fPTSubscriber := TBoldPassthroughSubscriber.Create(_Receive); fPropagatorHandleSubscriber := TBoldPassThroughSubscriber.Create(_ReceivePropagatorHandleEvents); fAutoStart := True; fLeaseDuration := DEFAULT_LEASE_DURATION; @@ -128,7 +130,7 @@ procedure TBoldListenerHandle._Receive(Originator: TObject; destructor TBoldListenerHandle.Destroy; begin StopAndFreeListenerThread; - FreeAndNil(fPTSubscriber); + FreeAndNil(fPTSubscriber); FreeAndNil(fPropagatorHandleSubscriber); inherited; end; @@ -143,13 +145,13 @@ function TBoldListenerHandle.GetConnected: Boolean; Result := ListenerThread.Registered; end; -procedure TBoldListenerHandle.SetDequeuer(aDequeuer: TBoldAbstractDequeuer); +procedure TBoldListenerHandle.SetDequeuer(aDequeuer: TBoldStringDequeuer); begin if aDequeuer <> fDequeuer then begin fDequeuer := aDequeuer; if Assigned(fDequeuer) then - fDequeuer.Queue := ListenerThread.Queue; + fDequeuer.Queue := ListenerThread.InQueue; end; end; @@ -182,13 +184,13 @@ procedure TBoldListenerHandle.StopAndFreeListenerThread; procedure TBoldListenerHandle.StartListenerThread; begin if not Assigned(fPropagatorHandle) then - raise EBold.CreateFmt(sPropagatorHandleNotAssigned, [ClassName]); + raise EBold.CreateFmt('%s.StartListenerThread: PropagatorHandle not assigned', [ClassName]); if not ListenerThread.Registered then begin ListenerThread.Resume; ListenerThread.WaitUntilInitialized; if not (fPropagatorHandle.Connected) then - raise EBold.CreateFmt(sPropagatorHandleNotConnected, [ClassName]); + raise EBold.CreateFmt('%s.StartListenerThread: PropagatorHandle not connected', [ClassName]); ListenerThread.Propagator := fPropagatorHandle.ClientHandler; ListenerThread.OnPropagatorFailure := fPropagatorHandle.DoPropagatorCallFailed; ListenerThread.OnThreadError := OnThreadError; @@ -291,7 +293,7 @@ procedure TBoldListenerHandle.SetPropagatorHandle(Value: TBoldAbstractPropagator if Value <> fPropagatorHandle then begin if fActive then - raise EBold.CreateFmt(sCannotChangeHandleWhenActive, [ClassName]); + raise EBold.Create('TBoldListenerHandle.SetPropagatorHandle: Can''t change handle on active listener'); fPropagatorHandleSubscriber.CancelAllSubscriptions; Subscribe(False); fPropagatorHandle := Value; @@ -323,7 +325,7 @@ function TBoldListenerHandle.GetIsLoaded: Boolean; procedure TBoldListenerHandle.SetExtendLeaseAfter(const Value: integer); begin if (value < 10) or (value > 90) then - raise EBold.CreateFmt(sValueOutOfRange, [ClassName]); + raise EBold.CreateFmt('%s.SetExtendLeaseAfter: Value must be between 10 and 90', [ClassName]); fExtendLeaseAfter := Value; ListenerThread.ExtendLeaseAfter := Value; end; @@ -358,4 +360,5 @@ procedure TBoldListenerHandle.Subscribe(const DoSubscribe: Boolean); fPTSubscriber.CancelAllSubscriptions; end; + end. diff --git a/Source/Persistence/Propagation/BoldListenerThread.pas b/Source/Persistence/Propagation/BoldListenerThread.pas index 64eb03e..2c0f3d7 100644 --- a/Source/Persistence/Propagation/BoldListenerThread.pas +++ b/Source/Persistence/Propagation/BoldListenerThread.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldListenerThread; interface @@ -9,7 +12,8 @@ interface Messages, BoldThreadSafeQueue, BoldPropagatorInterfaces_TLB, - BoldDefs; + BoldDefs + ; type {forward declarations} @@ -62,7 +66,6 @@ TBoldListenerThread = class(TThread) protected procedure WaitUntilInterfaceUnmarshaled; procedure UnMarshalInterface; - procedure RaiseSysErrorMessage(const CausedIn: string); public constructor Create(CreateSuspended: Boolean); destructor Destroy; override; @@ -80,7 +83,7 @@ TBoldListenerThread = class(TThread) property BoldClientID: TBoldClientID read getBoldClientID; property Registered: Boolean read GetRegistered; property Initialized: Boolean read GetInitialized; - property Queue: TBoldThreadSafeStringQueue read GetQueue; + property InQueue: TBoldThreadSafeStringQueue read GetQueue; property LeaseDuration: integer read fLeaseDuration write setLeaseDuration; property ExtendLeaseAfter: integer read fExtendLeaseAfter write SetExtendLeaseAfter; property PollingInterval: integer read fPollingInterval write setPollingInterval; @@ -97,13 +100,9 @@ implementation uses SysUtils, - BoldPMConsts, BoldPropagatorConstants, ActiveX; -const - GenericSysErrorMessage = '%s.%s: %s'; - constructor TBoldListenerThread.Create(CreateSuspended: Boolean); begin inherited Create(true); @@ -150,12 +149,11 @@ procedure TBoldListenerThread.Execute; while not Terminated do begin res := Integer(GetMessage(rMsg, 0, 0, 0)); - // if not terminating thread if ((res <> -1) and (res <> 0)) then if not Assigned(fBoldListenerCOM) then begin try - fBoldListenerCOM := TBoldListenerCOM.Create(Queue, PollingInterval, + fBoldListenerCOM := TBoldListenerCOM.Create(InQueue, PollingInterval, LeaseDuration, ExtendLeaseAfter, AutoExtendLease, ClientIdentifierString); @@ -164,28 +162,28 @@ procedure TBoldListenerThread.Execute; FBoldListenerCOM.OnExtendLeaseFailed := DoExtendLeaseFailedSynchronized; except on E: Exception do begin - fErrorMessage := Format(sInitializationLineMissing, [E.Message]); + fErrorMessage := Format('%s. You must add the following line to the initialization section of the application: TBoldListenerCOMFactory.Create(ComServer)', [E.Message]); DoThreadErrorSynchronized(fErrorMessage); - end; + end; end; end; try - if res = -1 then // error occured + if res = -1 then Terminate - else if res = 0 then // terminate signaled + else if res = 0 then Terminate else case rMsg.message of - BM_THRD_UNREGISTER: // unregister with propagator + BM_THRD_UNREGISTER: UnRegisterWithPropagator; - BM_THRD_REGISTER: // unregister with propagator + BM_THRD_REGISTER: RegisterWithPropagator; - BM_UNMARSHAL_INTERFACE: //unmarshal interface + BM_UNMARSHAL_INTERFACE: UnMarshalInterface; - BM_EXTEND_LEASE: //extend lease + BM_EXTEND_LEASE: InternalExtendLease; else DispatchMessage(rMsg); - end; //case + end; except on e: Exception do begin @@ -193,7 +191,7 @@ procedure TBoldListenerThread.Execute; raise; end; end; - end;//while + end; finally if Assigned(fBoldListenerCOM) then InterfaceForRefCounting := nil; @@ -208,7 +206,7 @@ function TBoldListenerThread.ExtendLease: Boolean; if Result then try if PostThreadMessage(ThreadID, BM_EXTEND_LEASE, 0, 0) = false then - RaiseSysErrorMessage('ExtendLease'); // do not localize + Raise EBold.CreateFmt('%s.ExtendLease: %s', [ClassName, SysErrorMessage(GetLastError)]); WaitForSingleObject(fDoneExtendLease, 3 * TIMEOUT); Result := (WaitForSingleObject(fExtendLeaseSucceeded, 0) = WAIT_OBJECT_0); finally @@ -220,7 +218,7 @@ function TBoldListenerThread.ExtendLease: Boolean; function TBoldListenerThread.GetQueue: TBoldThreadSafeStringQueue; begin if not Assigned(fQueue) then - fQueue := TBoldThreadSafeStringQueue.Create('Listener InQueue'); // do not localize + fQueue := TBoldThreadSafeStringQueue.Create('Listener InQueue'); Result := fQueue; end; @@ -275,7 +273,7 @@ procedure TBoldListenerThread.Quit(Wait: Boolean); end; UnRegister; if PostThreadMessage(ThreadID, WM_QUIT, 0, 0) = false then - RaiseSysErrorMessage('Quit'); // do not localize + Raise EBold.CreateFmt('%s.TerminateThread: %s', [ClassName, SysErrorMessage(GetLastError)]); if wait then begin @@ -291,7 +289,7 @@ procedure TBoldListenerThread.UnRegister; if Initialized and Registered and not (Suspended)then begin if PostThreadMessage(self.ThreadID, BM_THRD_UNREGISTER, 0, 0) = false then - RaiseSysErrorMessage('UnRegister'); // do not localize + raise EBold.CreateFmt('%s.TerminateThread: %s', [ClassName, SysErrorMessage(GetLastError)]); WaitUntilUnregistered; end; end; @@ -324,7 +322,7 @@ procedure TBoldListenerThread.EnsureMessageQueue; var rMsg: TMsg; begin - PeekMessage (rMsg, 0, 0, 0, PM_NOREMOVE); // force thread message queue! + PeekMessage (rMsg, 0, 0, 0, PM_NOREMOVE); end; function TBoldListenerThread.getBoldClientID: TBoldClientID; @@ -362,7 +360,7 @@ procedure TBoldListenerThread.SetPropagator(const Value: IBoldClientHandler); begin CoMarshalInterThreadInterfaceInStream(IID_IBoldClientHandler,Value,IStream(FInterfaceStream)); if PostThreadMessage(ThreadID, BM_UNMARSHAL_INTERFACE, 0, 0) = False then - RaiseSysErrorMessage('SetPropagator'); // do not localize + raise EBold.CreateFmt('%s.SetPropagator: %s', [ClassName, SysErrorMessage(GetLastError)]); WaitUntilInterfaceUnmarshaled; end else if Assigned(fBoldListenerCOM) then @@ -469,9 +467,4 @@ procedure TBoldListenerThread.SetExtendLeaseAfter(const Value: integer); fBoldListenerCOM.ExtendLeaseAfter := fExtendLeaseAfter; end; -procedure TBoldListenerThread.RaiseSysErrorMessage(const CausedIn: string); -begin - raise EBold.CreateFmt(GenericSysErrorMessage, [ClassName, CausedIn, SysErrorMessage(GetLastError)]); -end; - end. diff --git a/Source/Persistence/Propagation/BoldPersistenceControllerPassthrough.pas b/Source/Persistence/Propagation/BoldPersistenceControllerPassthrough.pas index c45a66a..916b2d6 100644 --- a/Source/Persistence/Propagation/BoldPersistenceControllerPassthrough.pas +++ b/Source/Persistence/Propagation/BoldPersistenceControllerPassthrough.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldPersistenceControllerPassthrough; interface @@ -9,7 +12,9 @@ interface BoldSubscription, BoldValueSpaceInterfaces, BoldUpdatePrecondition, - BoldDefs; + BoldDefs, + BoldElements, + BoldDbInterfaces; type {forward declarations} @@ -19,13 +24,13 @@ TBoldPersistenceControllerPassthrough = class; TBoldPersistenceControllerPassthrough = class(TBoldPersistenceController) private fNextPersistenceController: TBoldPersistenceController; - function getNextPersistenceController: TBoldPersistenceController; + function GetNextPersistenceController: TBoldPersistenceController; {$IFDEF BOLD_INLINE}inline;{$ENDIF} public constructor Create; - procedure PMExactifyIds(ObjectIdList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList); override; + procedure PMExactifyIds(ObjectIdList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList; HandleNonExisting: Boolean); override; procedure PMFetch(ObjectIdList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; MemberIdList: TBoldMemberIdList; FetchMode: Integer; BoldClientID: TBoldClientID); override; procedure PMFetchIDListWithCondition(ObjectIdList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; FetchMode: Integer; Condition: TBoldCondition; BoldClientID: TBoldClientID); override; - procedure PMUpdate(ObjectIdList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; Old_Values: IBoldValueSpace; Precondition: TBoldUpdatePrecondition; TranslationList: TBoldIdTranslationList; var TimeStamp: TBoldTimeStampType; BoldClientID: TBoldClientID); override; + procedure PMUpdate(ObjectIdList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; Old_Values: IBoldValueSpace; Precondition: TBoldUpdatePrecondition; TranslationList: TBoldIdTranslationList; var TimeStamp: TBoldTimeStampType; var TimeOfLatestUpdate: TDateTime; BoldClientID: TBoldClientID); override; procedure PMTranslateToGlobalIds(ObjectIdList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList); override; procedure PMTranslateToLocalIds(GlobalIdList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList); override; procedure PMSetReadOnlyness(ReadOnlyList, WriteableList: TBoldObjectIdList); override; @@ -34,6 +39,11 @@ TBoldPersistenceControllerPassthrough = class(TBoldPersistenceController) TranslationList: TBoldIdTranslationList); override; procedure PMTimestampForTime(ClockTime: TDateTime; var Timestamp: TBoldTimestampType); override; procedure PMTimeForTimestamp(Timestamp: TBoldTimestampType; var ClockTime: TDateTime); override; + function CanEvaluateInPS(sOCL: string; aSystem: TBoldElement; aContext: TBoldElementTypeInfo = nil; const aVariableList: TBoldExternalVariableList = nil): Boolean; override; + procedure StartTransaction; override; + procedure CommitTransaction; override; + procedure RollbackTransaction; override; + function DatabaseInterface: IBoldDatabase; override; property NextPersistenceController: TBoldPersistenceController read getNextPersistenceController write fNextPersistenceController; end; @@ -42,28 +52,58 @@ implementation uses SysUtils, - BoldPMConsts; + BoldRev; { TBoldPersistenceControllerPassthrough } +function TBoldPersistenceControllerPassthrough.CanEvaluateInPS(sOCL: string; + aSystem: TBoldElement; aContext: TBoldElementTypeInfo; + const aVariableList: TBoldExternalVariableList): Boolean; +begin + Result := NextPersistenceController.CanEvaluateInPS(sOCL, aSystem, aContext, aVariableList); +end; + +procedure TBoldPersistenceControllerPassthrough.StartTransaction; +begin + NextPersistenceController.StartTransaction; +end; + +procedure TBoldPersistenceControllerPassthrough.CommitTransaction; +begin + NextPersistenceController.CommitTransaction; +end; + +procedure TBoldPersistenceControllerPassthrough.RollbackTransaction; +begin + NextPersistenceController.RollbackTransaction; +end; + constructor TBoldPersistenceControllerPassthrough.Create; begin inherited; end; +function TBoldPersistenceControllerPassthrough.DatabaseInterface: IBoldDatabase; +begin + if Assigned(fNextPersistenceController) then + Result := fNextPersistenceController.DatabaseInterface + else + result := nil; +end; + function TBoldPersistenceControllerPassthrough.getNextPersistenceController: TBoldPersistenceController; begin if Assigned(fNextPersistenceController) then Result := fNextPersistenceController else - raise EBold.CreateFmt(sNextControllerMissing, [ClassName]); + raise EBold.CreateFmt('%s.getNextPersistenceController: NextPersistenceController not assigned', [ClassName]); end; procedure TBoldPersistenceControllerPassthrough.PMExactifyIds( ObjectIdList: TBoldObjectIdList; - TranslationList: TBoldIdTranslationList); + TranslationList: TBoldIdTranslationList; HandleNonExisting: Boolean); begin - NextPersistenceController.PMExactifyIds(ObjectIdList, TranslationList); + NextPersistenceController.PMExactifyIds(ObjectIdList, TranslationList, HandleNonExisting); end; procedure TBoldPersistenceControllerPassthrough.PMFetch( @@ -107,11 +147,11 @@ procedure TBoldPersistenceControllerPassthrough.PMUpdate( Old_Values: IBoldValueSpace; Precondition: TBoldUpdatePrecondition; TranslationList: TBoldIdTranslationList; - var TimeStamp: TBoldTimeStampType; BoldClientID: TBoldClientID); + var TimeStamp: TBoldTimeStampType; var TimeOfLatestUpdate: TDateTime; BoldClientID: TBoldClientID); begin NextPersistenceController.PMUpdate(ObjectIdList, ValueSpace, Old_Values, Precondition, - TranslationList, TimeStamp, BoldClientID); + TranslationList, TimeStamp, TimeOfLatestUpdate, BoldClientID); end; procedure TBoldPersistenceControllerPassthrough.SubscribeToPeristenceEvents( @@ -138,4 +178,6 @@ procedure TBoldPersistenceControllerPassthrough.PMTimestampForTime( NextPersistenceController.PMTimestampForTime(ClockTime, Timestamp); end; +initialization + end. diff --git a/Source/Persistence/Propagation/BoldPropagatorUtils.pas b/Source/Persistence/Propagation/BoldPropagatorUtils.pas index a833c3c..4465860 100644 --- a/Source/Persistence/Propagation/BoldPropagatorUtils.pas +++ b/Source/Persistence/Propagation/BoldPropagatorUtils.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldPropagatorUtils; interface @@ -35,9 +38,7 @@ procedure GetActiveObjectSubscriptions(Obj: TBoldObject; Subscriptions: TStringL if Obj.BoldPersistent then begin Id := Obj.BoldObjectLocator.BoldObjectId; - // Add a subscription for the embedded state changes Subscriptions.Add(TBoldObjectSpaceExternalEvent.EncodeExternalEvent(bsEmbeddedStateOfObjectChanged, '', '', '', Id)); - // and one subscription for each nonembedded member that is current/modified in memory for i := 0 to obj.BoldMemberCount - 1 do begin MemberRTInfo := obj.BoldClassTypeInfo.AllMembers[i]; @@ -65,14 +66,11 @@ procedure GetActiveSubscriptions(System: TBoldSystem; Subscriptions: TStringList begin Guard := TBoldGuard.Create(Traverser); Traverser := system.Locators.CreateTraverser; - // add subscriptions for all objects in memory - while not Traverser.EndOfList do + while Traverser.MoveNext do begin if assigned(Traverser.locator.BoldObject) then GetActiveObjectSubscriptions(Traverser.locator.BoldObject, Subscriptions); - Traverser.Next; end; - // Add subscriptions to classes (Why is the classlist transient?) TopSortedClasses := system.BoldSystemTypeInfo.TopSortedClasses; for i := 0 to TopSortedClasses.Count-1 do if system.Classes[i].BoldPersistenceState in [bvpsTransient, bvpsCurrent, bvpsmodified] then @@ -101,7 +99,6 @@ function ReConnectToPropagator( begin result := false; Guard := TBoldGuard.Create(Subscriptions); - // disconnect and reconnect the COM-interface ComConnectionHandle.Connected := false; ComConnectionHandle.Connected := true; if ComConnectionHandle.Connected then @@ -118,4 +115,6 @@ function ReConnectToPropagator( end; end; + +initialization end. diff --git a/Source/Persistence/Propagation/BoldSnooper.pas b/Source/Persistence/Propagation/BoldSnooper.pas index 4904b6f..ce3a6e7 100644 --- a/Source/Persistence/Propagation/BoldSnooper.pas +++ b/Source/Persistence/Propagation/BoldSnooper.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldSnooper; interface @@ -13,8 +16,6 @@ interface {forward declarations} TBoldSnooper = class; -// TBoldSnooperEventType = (bsetEvent, bsetSubscription); -// TBoldSnooperEventTypeSet = set of TBoldSnooperEventType; { TBoldSnooper } TBoldSnooper = class(TBoldAbstractSnooper) @@ -44,8 +45,7 @@ implementation BoldLockingDefs, BoldUtils, BoldSnooperHandle, - ComObj, - PersistenceConsts; + ComObj; function DatabaseLock_AsOLEVariant: OleVariant; begin @@ -61,15 +61,15 @@ procedure TBoldSnooper.TransmitEvents(const ClientID: TBoldClientID); if res <> S_OK then begin if Res = E_ENQUEUER_NOT_ENABLED then - s := sEnqueuerNotEnabled + s := 'Call to %s failed. Propagator Enqueuer not enabled' else if res = E_CLIENT_NOT_REGISTERED then - s := sClientNotRegistered + s := 'Call to %s failed. Client not registered with propagator' else if res = E_INVALID_PARAMETER then - s := sInvalidParameter + s := 'Call to %s failed. Invalid parameter' else if res = W_CLIENT_NOT_RECEIVING then - s := sClientNotReceivingEvents + s := 'Call to %s OK, but client is currently not receiving events' else - s := Format(sCallFailed, [SysErrorMessage(Res)]); + s := 'Call to %s failed. Error: ' + SysErrorMessage(Res); DoPropagatorFailure(self, format(s, [Action])); end; end; @@ -79,11 +79,11 @@ procedure TBoldSnooper.TransmitEvents(const ClientID: TBoldClientID); begin try if (Events.Count <> 0) then - CheckError(Propagator.SendEvents(ClientID, StringListToVarArray(Events)), 'SendEvents'); // do not localize + CheckError(Propagator.SendEvents(ClientID, StringListToVarArray(Events)), 'SendEvents'); if (Subscriptions.Count <> 0) then - CheckError(Propagator.AddSubscriptions(ClientID, StringListToVarArray(Subscriptions)), 'AddSubscriptions'); // do not localize + CheckError(Propagator.AddSubscriptions(ClientID, StringListToVarArray(Subscriptions)), 'AddSubscriptions'); if (CancelledSubscriptions.Count <> 0) then - CheckError(Propagator.CancelSubscriptions(ClientID, StringListToVarArray(CancelledSubscriptions)), 'CancelSubscriptions'); // do not localize + CheckError(Propagator.CancelSubscriptions(ClientID, StringListToVarArray(CancelledSubscriptions)), 'CancelSubscriptions'); except on E: EOleSysError do DoPropagatorFailure(self, E.Message); end; @@ -102,7 +102,7 @@ procedure TBoldSnooper.EnsureDataBaseLock(const ClientId: TBoldClientID); Exit; res := LockManager.EnsureLocks(ClientID, DatabaseLock_AsOLEVariant, null); if not res then - raise EBoldEnsureDatabaseLockError.CreateFmt(sCannotAcquireLock, [ClassName, 'EnsureDatabaseLock']); // do not localize + raise EBoldEnsureDatabaseLockError.CreateFmt('%s.EnsureDatabaseLock Cannot acquire Database Lock', [ClassName]); end; procedure TBoldSnooper.ReleaseDataBaseLock(const ClientID: TBoldClientID); @@ -115,8 +115,8 @@ procedure TBoldSnooper.ReleaseDataBaseLock(const ClientID: TBoldClientID); try LockManager.ReleaseLocks(ClientID, DatabaseLock_AsOLEVariant) except - raise EBoldLockManagerError.CreateFmt(sCannotAcquireLock, [ClassName, 'ReleaseDataBaseLock']); // do not localize - end; + raise EBoldLockManagerError.CreateFmt('%s.ReleaseDatabaseLock Cannot acquire Database Lock', [ClassName]); + end; end; constructor TBoldSnooper.Create(MoldModel: TMoldModel; aOwner: TObject); @@ -131,7 +131,7 @@ function TBoldSnooper.GetLockManager: IBoldLockManager; if Assigned((fOwner as TBoldSnooperHandle).LockManagerHandle) then Result := (fOwner as TBoldSnooperHandle).LockManagerHandle.LockManager else - raise EBoldLockManagerError.CreateFmt(sLockManagerNotAssigned, [ClassName]); + raise EBoldLockManagerError.CreateFmt('%s.GetLockManager: LockManager not assigned', [ClassName]); end; function TBoldSnooper.GetPropagator: IBoldEventPropagator; @@ -146,6 +146,6 @@ function TBoldSnooper.GetCheckDatabaseLock: Boolean; Result := (fOwner as TBoldSnooperHandle).CheckDatabaseLock; end; -end. - +initialization +end. diff --git a/Source/Persistence/Propagation/BoldSnooperHandle.pas b/Source/Persistence/Propagation/BoldSnooperHandle.pas index e2e0105..774ec7e 100644 --- a/Source/Persistence/Propagation/BoldSnooperHandle.pas +++ b/Source/Persistence/Propagation/BoldSnooperHandle.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldSnooperHandle; interface @@ -20,6 +23,10 @@ TBoldSnooperHandle = class(TBoldPersistenceHandlePassthroughWithModel) fLockManagerHandle: TBoldAbstractLockManagerHandle; FCheckDatabaseLock: Boolean; fPropagatorHandle: TBoldAbstractPropagatorHandle; + fClassesToIgnore: string; + fUseSubscriptions: boolean; + fUseClassEvents: boolean; + fUseMemberLevelOSS: boolean; procedure SetLockManagerHandle(Value: TBoldAbstractLockManagerHandle); procedure _Receive(Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent); procedure SetPropagatorHandle(Value: TBoldAbstractPropagatorHandle); @@ -44,6 +51,10 @@ TBoldSnooperHandle = class(TBoldPersistenceHandlePassthroughWithModel) property LockManagerHandle: TBoldAbstractLockManagerHandle read fLockManagerHandle write SetLockManagerHandle; property CheckDatabaseLock: Boolean read fCheckDatabaseLock write fCheckDatabaseLock; property PropagatorHandle: TBoldAbstractPropagatorHandle read fPropagatorHandle write SetPropagatorHandle; + property UseClassEvents: boolean read fUseClassEvents write fUseClassEvents; + property UseMemberLevelOSS: boolean read fUseMemberLevelOSS write fUseMemberLevelOSS; + property UseSubscriptions: boolean read fUseSubscriptions write fUseSubscriptions; + property ClassesToIgnore: string read fClassesToIgnore write fClassesToIgnore; end; implementation @@ -53,20 +64,20 @@ implementation BoldDefs, BoldPersistenceHandlePassThrough, dialogs, - PersistenceConsts; + BoldRev; function TBoldSnooperHandle.CreatePersistenceController: TBoldPersistenceController; var Snooper: TBoldSnooper; begin if not Assigned(BoldModel) then - raise EBold.CreateFmt(sBoldModelNotAssigned, [ClassName]); + raise EBold.CreateFmt('%s.CreatePersistenceController: cannot find a BoldModel', [ClassName]); Snooper := TBoldSnooper.Create(BoldModel.MoldModel, self); ChainPersistenceController(Snooper); if Assigned(PropagatorHandle) then Snooper.OnPropagatorFailure := PropagatorHandle.DoPropagatorCallFailed else - raise EBold.CreateFmt(sPropagatorHandleNotAssigned, [ClassName]); + raise EBold.CreateFmt('%s.PropagatorHandle not assigned', [ClassName]); result := Snooper; end; @@ -116,6 +127,13 @@ procedure TBoldSnooperHandle.SetPropagatorHandle( Snooper.OnPropagatorFailure := fPropagatorHandle.DoPropagatorCallFailed else if not (csDestroying in ComponentState) then Snooper.OnPropagatorFailure := nil; + if Assigned(Value) then + begin + Snooper.UseClassEvents := UseClassEvents; + Snooper.UseMemberLevelOSS := UseMemberLevelOSS; + Snooper.UseSubscriptions := UseSubscriptions; + Snooper.ClassesToIgnore := ClassesToIgnore; + end; end; Subscribe(True); end; @@ -131,8 +149,7 @@ function TBoldSnooperHandle.GetConnected: Boolean; procedure TBoldSnooperHandle.DefineProperties(Filer: TFiler); begin inherited; - // property MachineName moved to TBoldPropagatorHandleCOM - Filer.DefineProperty('MachineName', ReadObsoleteMachineNameProperty, nil, True); // do not localize + Filer.DefineProperty('MachineName', ReadObsoleteMachineNameProperty, nil, True); end; procedure TBoldSnooperHandle.ReadObsoleteMachineNameProperty( @@ -141,14 +158,14 @@ procedure TBoldSnooperHandle.ReadObsoleteMachineNameProperty( OldPropertyValue: string; begin OldPropertyValue := Reader.ReadString; - ReadObsoleteProperty(Reader, 'MachineName', 'ServerHost', OldPropertyValue, 'TBoldPropagatorHandleCom'); // do not localize + ReadObsoleteProperty(Reader, 'MachineName', 'ServerHost', OldPropertyValue, 'TBoldPropagatorHandleCom'); end; procedure TBoldSnooperHandle.ReadObsoleteProperty(Reader: TReader; const PropertyName, NewPropertyName, OldPropertyValue, ComponentName: string); begin if (csDesigning in ComponentState) then - MessageDlg(Format(sPropertyMoved, + MessageDlg(Format('%s.%s has been moved to component (%s.%s). Old value was "%s"', [ClassName, PropertyName, ComponentName, NewPropertyName, OldPropertyValue]), mtWarning, [mbOK], 0); end; @@ -178,4 +195,5 @@ procedure TBoldSnooperHandle.Subscribe(const DoSubscribe: Boolean); fPTSubscriber.CancelAllSubscriptions; end; +initialization end. diff --git a/Source/Persistence/SOAP/BoldPersistenceControllerSOAPAdapterCore.pas b/Source/Persistence/SOAP/BoldPersistenceControllerSOAPAdapterCore.pas index 81a626e..8bc0ef1 100644 --- a/Source/Persistence/SOAP/BoldPersistenceControllerSOAPAdapterCore.pas +++ b/Source/Persistence/SOAP/BoldPersistenceControllerSOAPAdapterCore.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldPersistenceControllerSOAPAdapterCore; interface @@ -6,10 +9,11 @@ interface BoldPersistenceController, BoldMeta, BoldDefaultXMLStreaming, - BoldPersistenceOperationXMLStreaming; + BoldPersistenceOperationXMLStreaming + ; type - { TBoldPersistenceControllerSOAPAdapterCore } + TBoldPersistenceControllerSOAPAdapterCore = class private fStreamManager: TBoldDefaultXMLStreamManager; @@ -23,11 +27,11 @@ implementation uses SysUtils, - MSXML_TLB, + {$IFDEF OXML}OXmlPDOM{$ELSE}MSXML_TLB{$ENDIF}, BoldDefs, BoldXMLStreaming, - BoldComConst; - + BoldRev + ; { TBoldPersistenceControllerSOAPAdapterCore } constructor TBoldPersistenceControllerSOAPAdapterCore.Create(Model: TMoldModel); @@ -47,48 +51,59 @@ destructor TBoldPersistenceControllerSOAPAdapterCore.Destroy; procedure TBoldPersistenceControllerSOAPAdapterCore.Get(const request: WideString; out reply: WideString; PersistenceController: TBoldPersistenceController); var - RequestDoc, ReplyDoc: TDOMDocument; + RequestDoc, ReplyDoc: {$IFDEF OXML}TXMLDocument{$ELSE}TDOMDocument{$ENDIF}; RequestBodyNode, ReplyBodyNode: TBoldXMLNode; - anXMLNode: IXMLDOMNode; + anXMLNode: {$IFDEF OXML}PXMLNode{$ELSE}IXMLDOMNode{$ENDIF}; OpNode: TBoldXMLNode; OpName: string; PMOperation: TBoldPersistenceOperation; begin + {$IFDEF OXML} + RequestDoc := TXMLDocument.Create; + ReplyDoc := TXMLDocument.Create; + {$ELSE} RequestDoc := TDOMDocument.Create(nil); ReplyDoc := TDOMDocument.Create(nil); + {$ENDIF} RequestBodyNode := nil; ReplyBodyNode := nil; OpNode := nil; PMOperation := nil; try + {$IFDEF OXML} + RequestDoc.LoadFromXML(request); + RequestBodyNode := fStreamManager.GetSOAP(RequestDoc); + anXMLNode := RequestBodyNode.XMLDomElement.ChildNodes.GetFirst; + OpNode := TBoldXMLNode.Create(fStreamManager, anXMLNode, nil); + {$ELSE} RequestDoc.loadXML(request); RequestBodyNode := fStreamManager.GetSOAP(RequestDoc); anXMLNode := RequestBodyNode.XMLDomElement.childNodes.nextNode; OpNode := TBoldXMLNode.Create(fStreamManager, anXMLNode as IXMLDOMElement, nil); + {$ENDIF} OpName := OpNode.Accessor; - anXMLNode := nil; ReplyBodyNode := fStreamManager.NewSOAP(ReplyDoc); - if OpName = 'PMFetch' then // do not localize + if OpName = 'PMFetch' then PMOperation := TBoldPMFetchOperation.Create(fStreamManager) - else if OpName = 'PMFetchIDListWithCondition' then // do not localize + else if OpName = 'PMFetchIDListWithCondition' then PMOperation := TBoldPMFetchIdListOperation.Create(fStreamManager) - else if OpName = 'PMExactifyIds' then // do not localize + else if OpName = 'PMExactifyIds' then PMOperation := TBoldPMExactifyIdsOperation.Create(fStreamManager) - else if OpName = 'PMUpdate' then // do not localize + else if OpName = 'PMUpdate' then PMOperation := TBoldPMUpdateOperation.Create(fStreamManager) - else if OpName = 'ReserveNewIds' then // do not localize + else if OpName = 'ReserveNewIds' then PMOperation := TBoldPMReserveNewIdsOperation.Create(fStreamManager) - else if OpName = 'PMTimeForTimestamp' then // do not localize + else if OpName = 'PMTimeForTimestamp' then PMOperation := TBoldPMTimeForTimestampOperation.Create(fStreamManager) - else if OpName = 'PMTimestampForTime' then // do not localize + else if OpName = 'PMTimestampForTime' then PMOperation := TBoldPMTimestampForTimeOperation.Create(fStreamManager) else - raise EBold.CreateFmt(sUnknownOperation, [classname, OpName]); + raise EBold.CreateFmt('%s.Get: Unrecognized operation %s', [classname, OpName]); PMOperation.ExecuteStreamed(PersistenceController, RequestBodyNode, ReplyBodyNode); - reply := ReplyDoc.DefaultInterface.xml; + reply := {$IFDEF OXML}ReplyDoc.XML{$ELSE}ReplyDoc.DefaultInterface.xml{$ENDIF}; finally RequestBodyNode.Free; ReplyBodyNode.Free; @@ -99,4 +114,6 @@ procedure TBoldPersistenceControllerSOAPAdapterCore.Get(const request: WideStrin end; end; +initialization + end. diff --git a/Source/Persistence/SOAP/BoldPersistenceOperationXMLStreaming.pas b/Source/Persistence/SOAP/BoldPersistenceOperationXMLStreaming.pas index 53b0003..c9e79dc 100644 --- a/Source/Persistence/SOAP/BoldPersistenceOperationXMLStreaming.pas +++ b/Source/Persistence/SOAP/BoldPersistenceOperationXMLStreaming.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldPersistenceOperationXMLStreaming; interface @@ -88,6 +91,7 @@ TBoldPMExactifyIdsOperation = class(TBoldPersistenceOperation) private fObjectIdList: TBoldObjectIdList; fTranslationList: TBoldIdTranslationList; + fHandleNonExisting: Boolean; protected function GetName: string; override; public @@ -101,6 +105,7 @@ TBoldPMExactifyIdsOperation = class(TBoldPersistenceOperation) property ObjectIdList: TBoldObjectIdList read fObjectIdList write fObjectIdList; property TranslationList: TBoldIdTranslationList read fTranslationList write fTranslationList; + property HandleNonExisting: Boolean read fHandleNonExisting write fHandleNonExisting; end; TBoldPMUpdateOperation = class(TBoldPersistenceOperation) @@ -113,6 +118,7 @@ TBoldPMUpdateOperation = class(TBoldPersistenceOperation) fFreestanding_old: TBoldFreeStandingValueSpace; fTranslationList: TBoldIdTranslationList; fTimestamp: TBoldTimestampType; + fTimeOfTimeStamp: TDateTIme; fBoldClientID: TBoldClientID; protected function GetName: string; override; @@ -191,11 +197,9 @@ TBoldPMTimeForTimestampOperation = class(TBoldPersistenceOperation) implementation uses - MSXML_TLB, + {$IFDEF OXML}OXmlPDOM{$ELSE}MSXML_TLB{$ENDIF}, SysUtils, -// BoldUtils, - BoldDefaultStreamNames, - BoldComConst; + BoldDefaultStreamNames; const BoldNodeName_ObjectIdList = 'ObjectIdList'; @@ -209,6 +213,7 @@ implementation BoldNodeName_Old_Values = 'Old_Values'; BoldNodeName_Timestamp = 'Timestamp'; BoldNodeName_ClockTime = 'ClockTime'; + BoldNodeName_HandleNonExisting = 'HandleNonExisting'; { TBoldPMFetchOperation } @@ -228,7 +233,7 @@ procedure TBoldPMFetchOperation.FreeParams; function TBoldPMFetchOperation.GetName: string; begin - result := 'PMFetch'; // do not localize + result := 'PMFetch'; end; procedure TBoldPMFetchOperation.InitParams; @@ -294,13 +299,13 @@ procedure TBoldPersistenceOperation.ExecuteStreamed( try Execute(PersistenceController); - OpNode := ReplyBodyNode.NewSubNode(Name + 'Response'); // do not localize + OpNode := ReplyBodyNode.NewSubNode(Name + 'Response'); WriteOutParams(OpNode); except on E: Exception do begin - OpNode := ReplyBodyNode.NewSubNode('SOAP-ENV:Fault'); // do not localize - OpNode := OpNode.NewSubNode('SOAP-ENV:faultstring'); // do not localize - OpNode.WriteString(E.Message); + OpNode := ReplyBodyNode.NewSubNode('SOAP-ENV:Fault'); + OpNode := OpNode.NewSubNode('SOAP-ENV:faultstring'); + OpNode.WriteString(E.Message); end; end; OpNode.Free; @@ -318,14 +323,19 @@ procedure TBoldPersistenceOperation.InitParams; procedure TBoldPersistenceOperation.RemoteExecute(Stub: IBoldSOAPService); var - RequestDoc: TDOMDocument; - ReplyDoc: TDOMDocument; + RequestDoc, + ReplyDoc: {$IFDEF OXML}TXMLDocument{$ELSE}TDOMDocument{$ENDIF}; BodyNode: TBoldXMLNode; OpNode: TBoldXMLNode; replyXML: WideString; begin + {$IFDEF OXML} + RequestDoc := TXMLDocument.Create; + ReplyDoc := TXMLDocument.Create; + {$ELSE} RequestDoc := TDOMDocument.Create(nil); ReplyDoc := TDOMDocument.Create(nil); + {$ENDIF} try BodyNode := StreamManager.NewSOAP(RequestDoc); OpNode := BodyNode.NewSubNode(Name); @@ -335,33 +345,37 @@ procedure TBoldPersistenceOperation.RemoteExecute(Stub: IBoldSOAPService); BodyNode.Free; OpNode.Free; end; - Stub.Get(RequestDoc.DefaultInterface.xml, replyXML); + Stub.Get({$IFDEF OXML}RequestDoc.XML{$ELSE} + RequestDoc.DefaultInterface.xml{$ENDIF}, replyXML); - if not ReplyDoc.loadXML(replyXML) then - raise EBoldXMLLoadError.CreateFmt('%s: %s', [Replydoc.parseError.reason, ReplyXML]) ; //Invalid XML data // do not localize + if not {$IFDEF OXML}ReplyDoc.LoadFromXML(replyXML){$ELSE} + ReplyDoc.loadXML(replyXML){$ENDIF} then + begin + raise EBoldXMLLoadError.CreateFmt('%s: %s', [Replydoc.parseError.Reason, ReplyXML]) ; + end; try BodyNode := StreamManager.GetSOAP(ReplyDoc); except - raise EBoldInvalidSOAP.CreateFmt(sInvalidSOAPData, [replyXML]); + raise EBoldInvalidSOAP.CreateFmt('Invalid SOAP data : %s', [replyXML]); end; - OpNode := BodyNode.GetSubNode(Name + 'Response'); // do not localize + OpNode := BodyNode.GetSubNode(Name + 'Response'); if not Assigned(OpNode) then begin - OpNode := BodyNode.GetSubNode('SOAP-ENV:Fault'); // do not localize + OpNode := BodyNode.GetSubNode('SOAP-ENV:Fault'); if not Assigned(OpNode) then - raise EBold.Create(sEmptySOAPData) + raise EBold.Create('Empty SOAP data.') else begin - OpNode := OpNode.GetSubNode('SOAP-ENV:faultstring'); // do not localize + OpNode := OpNode.GetSubNode('SOAP-ENV:faultstring'); if Assigned(OpNode) then - raise EBold.CreateFmt(sError, [OpNode.XMLDomElement.text]) + raise EBold.CreateFmt('Error: %s', [OpNode.XMLDomElement.text]) else - raise EBold.Create(sErrorNoMessage) ; + raise EBold.Create('Error: empty error message') ; end; end; - + try ReadOutParams(OpNode); finally @@ -397,7 +411,7 @@ procedure TBoldPMFetchIdListOperation.FreeParams; function TBoldPMFetchIdListOperation.GetName: string; begin - result := 'PMFetchIDListWithCondition'; // do not localize + result := 'PMFetchIDListWithCondition'; end; procedure TBoldPMFetchIdListOperation.InitParams; @@ -441,7 +455,7 @@ procedure TBoldPMFetchIdListOperation.WriteOutParams(XMLNode: TBoldXMLNode); procedure TBoldPMExactifyIdsOperation.Execute(PersistenceController: TBoldPersistenceController); begin - PersistenceController.PMExactifyIds(ObjectIdList, TranslationList); + PersistenceController.PMExactifyIds(ObjectIdList, TranslationList, HandleNonExisting); end; procedure TBoldPMExactifyIdsOperation.FreeParams; @@ -453,7 +467,7 @@ procedure TBoldPMExactifyIdsOperation.FreeParams; function TBoldPMExactifyIdsOperation.GetName: string; begin - result := 'PMExactifyIds'; // do not localize + result := 'PMExactifyIds'; end; procedure TBoldPMExactifyIdsOperation.InitParams; @@ -465,6 +479,7 @@ procedure TBoldPMExactifyIdsOperation.InitParams; procedure TBoldPMExactifyIdsOperation.ReadInParams(XMLNode: TBoldXMLNode); begin ObjectIdList := XMLNode.ReadSubNodeObject(BoldNodeName_ObjectIdList, BOLDOBJECTIDLISTNAME) as TBoldObjectIdList; + HandleNonExisting := XMLNode.ReadSubNodeBoolean(BoldNodeName_HandleNonExisting); end; procedure TBoldPMExactifyIdsOperation.ReadOutParams(XMLNode: TBoldXMLNode); @@ -472,7 +487,7 @@ procedure TBoldPMExactifyIdsOperation.ReadOutParams(XMLNode: TBoldXMLNode); aTranslationList: TBoldIDTranslationList; i: Integer; begin - aTranslationList := XMLNode.ReadSubNodeObject(BoldNodeName_TranslationList, BOLDIDTRANSLATIONLISTNAME) as TBoldIDTranslationList; //IMPORTANT: this returns an object(a list) which is up to the caller to free + aTranslationList := XMLNode.ReadSubNodeObject(BoldNodeName_TranslationList, BOLDIDTRANSLATIONLISTNAME) as TBoldIDTranslationList; try for i := 0 to aTranslationList.Count - 1 do TranslationList.AddTranslation(aTranslationList.OldIds[i], aTranslationList.NewIds[i]); @@ -484,6 +499,7 @@ procedure TBoldPMExactifyIdsOperation.ReadOutParams(XMLNode: TBoldXMLNode); procedure TBoldPMExactifyIdsOperation.WriteInParams(XMLNode: TBoldXMLNode); begin XMLNode.WriteSubNodeObject(BoldNodeName_ObjectIdList, BOLDOBJECTIDLISTNAME, ObjectIdList); + XMLNode.WriteSubNodeBoolean(BoldNodeName_HandleNonExisting, fHandleNonExisting); end; procedure TBoldPMExactifyIdsOperation.WriteOutParams(XMLNode: TBoldXMLNode); @@ -495,7 +511,7 @@ procedure TBoldPMExactifyIdsOperation.WriteOutParams(XMLNode: TBoldXMLNode); procedure TBoldPMUpdateOperation.Execute(PersistenceController: TBoldPersistenceController); begin - PersistenceController.PMUpdate(ObjectIdList, ValueSpace, Old_Values, Precondition, TranslationList, fTimestamp, BoldClientID); + PersistenceController.PMUpdate(ObjectIdList, ValueSpace, Old_Values, Precondition, TranslationList, fTimestamp, fTimeOfTimeStamp, BoldClientID); end; procedure TBoldPMUpdateOperation.FreeParams; @@ -516,7 +532,7 @@ procedure TBoldPMUpdateOperation.FreeTranslationList; function TBoldPMUpdateOperation.GetName: string; begin - result := 'PMUpdate'; // do not localize + result := 'PMUpdate'; end; procedure TBoldPMUpdateOperation.InitParams; @@ -612,7 +628,7 @@ procedure TBoldPMReserveNewIdsOperation.FreeParams; function TBoldPMReserveNewIdsOperation.GetName: string; begin - result := 'ReserveNewIds'; // do not localize + result := 'ReserveNewIds'; end; procedure TBoldPMReserveNewIdsOperation.InitParams; @@ -659,7 +675,7 @@ procedure TBoldPMTimestampForTimeOperation.Execute(PersistenceController: TBoldP function TBoldPMTimestampForTimeOperation.GetName: string; begin - result := 'PMTimestampForTime'; // do not localize + result := 'PMTimestampForTime'; end; procedure TBoldPMTimestampForTimeOperation.ReadInParams(XMLNode: TBoldXMLNode); @@ -691,7 +707,7 @@ procedure TBoldPMTimeForTimestampOperation.Execute(PersistenceController: TBoldP function TBoldPMTimeForTimestampOperation.GetName: string; begin - result := 'PMTimeForTimestamp'; // do not localize + result := 'PMTimeForTimestamp'; end; procedure TBoldPMTimeForTimestampOperation.ReadInParams(XMLNode: TBoldXMLNode); @@ -714,4 +730,6 @@ procedure TBoldPMTimeForTimestampOperation.WriteOutParams(XMLNode: TBoldXMLNode) XMLNode.WriteSubNodeString(BoldNodeName_ClockTime, DateTimeToStr(ClockTime)); end; +initialization + end. diff --git a/Source/Persistence/SOAP/BoldSOAPClientPersistenceHandles.pas b/Source/Persistence/SOAP/BoldSOAPClientPersistenceHandles.pas index feb5708..ee3e36e 100644 --- a/Source/Persistence/SOAP/BoldSOAPClientPersistenceHandles.pas +++ b/Source/Persistence/SOAP/BoldSOAPClientPersistenceHandles.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldSOAPClientPersistenceHandles; interface @@ -34,4 +37,6 @@ function TBoldSOAPClientPersistenceHandle.CreatePersistenceController: TBoldPers result := Controller; end; +initialization + end. diff --git a/Source/Persistence/SOAP/BoldSOAPPersistenceControllerProxy.pas b/Source/Persistence/SOAP/BoldSOAPPersistenceControllerProxy.pas index 49be36c..33b5e7f 100644 --- a/Source/Persistence/SOAP/BoldSOAPPersistenceControllerProxy.pas +++ b/Source/Persistence/SOAP/BoldSOAPPersistenceControllerProxy.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldSOAPPersistenceControllerProxy; interface @@ -14,7 +17,8 @@ interface BoldUpdatePrecondition, BoldPersistenceOperationXMLStreaming, BoldMeta, - BoldDefs; + BoldDefs, + BoldElements; type { forward declarations } @@ -35,7 +39,6 @@ TBoldSOAPPersistenceControllerProxy = class(TBoldAbstractComPersistenceControl protected fStub: IBoldSOAPService; function GetIsConnected: Boolean; override; - procedure CheckConnect(const Caller: string); property FetchIdListOp: TBoldPMFetchIdListOperation read GetFetchIdListOp; property FetchOp: TBoldPMFetchOperation read GetFetchOp; property ExactifyOp: TBoldPMExactifyIdsOperation read GetExactifyOp; @@ -45,8 +48,7 @@ TBoldSOAPPersistenceControllerProxy = class(TBoldAbstractComPersistenceControl destructor Destroy; override; procedure Connect(const Provider: IBoldProvider; const ObjectName: string); override; procedure Disconnect; override; - procedure PMExactifyIds(ObjectIdList: TBoldObjectidList; - TranslationList: TBoldIDTranslationList); override; + procedure PMExactifyIds(ObjectIdList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList; HandleNonExisting: Boolean); override; procedure PMFetch(ObjectIdList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; MemberIdList: TBoldMemberIdList; FetchMode: Integer; BoldClientID: TBoldClientID); override; procedure PMFetchIDListWithCondition(ObjectIdList: TBoldObjectIdList; @@ -54,18 +56,19 @@ TBoldSOAPPersistenceControllerProxy = class(TBoldAbstractComPersistenceControl procedure PMUpdate(ObjectIdList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; Old_Values: IBoldValueSpace; Precondition: TBoldUpdatePrecondition; - TranslationList: TBoldIdTranslationList; var TimeStamp: TBoldTimeStampType; + TranslationList: TBoldIdTranslationList; var TimeStamp: TBoldTimeStampType; var TimeOfLatestUpdate: TDateTime; BoldClientID: TBoldClientID); override; procedure PMTranslateToGlobalIds(ObjectIdList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList); override; procedure PMTranslateToLocalIds(GlobalIdList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList); override; - procedure PMSetReadOnlyness(ReadOnlyList, WriteableList: TBoldObjectIdList); override; + procedure PMSetReadonlyness(ReadOnlyList, WriteableList: TBoldObjectIdList); override; procedure ReserveNewIds(ValueSpace: IBoldValueSpace; ObjectIdList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList); override; procedure PMTimestampForTime(ClockTime: TDateTime; var Timestamp: TBoldTimestampType); override; procedure PMTimeForTimestamp(Timestamp: TBoldTimestampType; var ClockTime: TDateTime); override; procedure SubscribeToPeristenceEvents(Subscriber: TBoldSubscriber); override; + function CanEvaluateInPS(sOCL: string; aSystem: TBoldElement; aContext: TBoldElementTypeInfo = nil; const aVariableList: TBoldExternalVariableList = nil): Boolean; override; end; implementation @@ -73,16 +76,17 @@ implementation uses BoldComUtils, SysUtils, - BoldCursorGuard, - BoldComConst; + BoldCursorGuard; { TBoldSOAPPersistenceControllerProxy } -procedure TBoldSOAPPersistenceControllerProxy.CheckConnect( - const Caller: string); +function TBoldSOAPPersistenceControllerProxy.CanEvaluateInPS(sOCL: string; + aSystem: TBoldElement; aContext: TBoldElementTypeInfo; + const aVariableList: TBoldExternalVariableList): Boolean; +const + sMethodNotImplemented = '%s.%s: not supported/implemented'; begin - if not Connected then - raise EBoldCom.CreateFmt(sNotConnected, [ClassName, Caller]); + raise EBold.CreateFmt(sMethodNotImplemented, [ClassName, 'CanEvaluateInPS']); // do not localize end; procedure TBoldSOAPPersistenceControllerProxy.Connect( @@ -94,9 +98,9 @@ procedure TBoldSOAPPersistenceControllerProxy.Connect( ObjectNamews := Objectname; Unk := Provider.GetObject(ObjectNameWS); if not Assigned(Unk) then - raise EBoldCom.CreateFmt(sFailedToConnect, [ObjectName]); + raise EBoldCom.CreateFmt('Failed connecting to COM object ''%s''.', [ObjectName]); if Unk.QueryInterface(IBoldSOAPService, fStub) <> 0 then - raise EBoldCom.CreateFmt(sCOMObjectNotPController, [ObjectName]); + raise EBoldCom.CreateFmt('COM object ''%s'' is not a persistence controller.', [ObjectName]); end; constructor TBoldSOAPPersistenceControllerProxy.Create(Model: TMoldModel); @@ -158,10 +162,11 @@ function TBoldSOAPPersistenceControllerProxy.GetUpdateOp: TBoldPMUpdateOperation procedure TBoldSOAPPersistenceControllerProxy.PMExactifyIds( ObjectIdList: TBoldObjectidList; - TranslationList: TBoldIDTranslationList); + TranslationList: TBoldIDTranslationList; + HandleNonExisting: Boolean); begin - CheckConnect('PMFetch'); // do not localize - + if not Connected then + raise EBoldCom.CreateFmt('%s.PMFetch: Not connected.', [ClassName]); ExactifyOp.ObjectIdList := ObjectIdList; ExactifyOp.TranslationList := TranslationList; ExactifyOp.RemoteExecute(fStub); @@ -174,7 +179,8 @@ procedure TBoldSOAPPersistenceControllerProxy.PMFetch( var CursorGuard: IBoldCursorGuard; begin - CheckConnect('PMFetch'); // do not localize + if not Connected then + raise EBoldCom.CreateFmt('%s.PMFetch: Not connected.', [ClassName]); try CursorGuard := TBoldCursorGuard.Create; @@ -200,7 +206,8 @@ procedure TBoldSOAPPersistenceControllerProxy.PMFetchIDListWithCondition( var CursorGuard: IBoldCursorGuard; begin - CheckConnect('PMFetchIDListWithCondition'); // do not localize + if not Connected then + raise EBoldCom.CreateFmt('%s.PMFetchIDListWithCondition: Not connected.', [ClassName]); CursorGuard := TBoldCursorGuard.Create; SendExtendedEvent(bpeStartFetchId, [Condition]); @@ -224,7 +231,8 @@ procedure TBoldSOAPPersistenceControllerProxy.PMTimeForTimestamp( var Op: TBoldPMTimeForTimestampOperation; begin - CheckConnect('PMUpdate'); // do not localize + if not Connected then + raise EBoldCom.CreateFmt('%s.PMUpdate: Not connected.', [ClassName]); Op := TBoldPMTimeForTimestampOperation.Create(fStreamManager); try @@ -242,7 +250,8 @@ procedure TBoldSOAPPersistenceControllerProxy.PMTimestampForTime( var Op: TBoldPMTimestampForTimeOperation; begin - CheckConnect('PMUpdate'); // do not localize + if not Connected then + raise EBoldCom.CreateFmt('%s.PMUpdate: Not connected.', [ClassName]); Op := TBoldPMTimestampForTimeOperation.Create(fStreamManager); try @@ -271,13 +280,14 @@ procedure TBoldSOAPPersistenceControllerProxy.PMTranslateToLocalIds( procedure TBoldSOAPPersistenceControllerProxy.PMUpdate( ObjectIdList: TBoldObjectIdList; ValueSpace, Old_Values: IBoldValueSpace; - Precondition: TBoldUpdatePrecondition; + Precondition: TBoldUpdatePrecondition; TranslationList: TBoldIdTranslationList; - var TimeStamp: TBoldTimeStampType; BoldClientID: TBoldClientID); + var TimeStamp: TBoldTimeStampType; var TimeOfLatestUpdate: TDateTime; BoldClientID: TBoldClientID); var CursorGuard: IBoldCursorGuard; begin - CheckConnect('PMUpdate'); // do not localize + if not Connected then + raise EBoldCom.CreateFmt('%s.PMUpdate: Not connected.', [ClassName]); try CursorGuard := TBoldCursorGuard.Create; @@ -295,16 +305,16 @@ procedure TBoldSOAPPersistenceControllerProxy.PMUpdate( UpdateOp.RemoteExecute(fStub); if assigned(Precondition) and Precondition.failed then - // update failed. don't get out params. else begin TimeStamp := UpdateOp.Timestamp; + TimeOfLatestUpdate := now; // TODO implement ValueSpace.ApplytranslationList(UpdateOp.TranslationList); end; finally if not Assigned(TranslationList) then UpdateOp.FreeTranslationList; - SendEvent(bpeEndUpdate); + SendEvent(bpeEndUpdate); end; end; @@ -314,7 +324,8 @@ procedure TBoldSOAPPersistenceControllerProxy.ReserveNewIds( var ReserveOp: TBoldPMReserveNewIdsOperation; begin - CheckConnect('ReserveNewIds'); // do not localize + if not Connected then + raise EBoldCom.CreateFmt('%s.ReserveNewIds: Not connected.', [ClassName]); ReserveOp := TBoldPMReserveNewIdsOperation.Create(fStreamManager); try @@ -345,4 +356,6 @@ procedure TBoldSOAPPersistenceControllerProxy.SubscribeToPeristenceEvents( AddSubscription(Subscriber, bpeDeleteObject, bpeDeleteObject); end; +initialization + end. diff --git a/Source/Persistence/SOAP/BoldSOAPPersistenceControllerStub.pas b/Source/Persistence/SOAP/BoldSOAPPersistenceControllerStub.pas index 63430f5..ac2a1fd 100644 --- a/Source/Persistence/SOAP/BoldSOAPPersistenceControllerStub.pas +++ b/Source/Persistence/SOAP/BoldSOAPPersistenceControllerStub.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldSOAPPersistenceControllerStub; interface @@ -32,7 +35,7 @@ implementation uses sysutils, BoldComUtils, - BoldComConst; + BoldRev; { TBoldSOAPPersistenceControllerAdapter } @@ -44,7 +47,7 @@ constructor TBoldSOAPPersistenceControllerAdapter.Create(Model: TMoldModel; Adap fAdapterCore := TBoldPersistenceControllerSOAPAdapterCore.Create(Model); if Failed(LoadRegTypeLib(LIBID_BoldSOAP, BoldSOAPMajorVersion, BoldSOAPMinorVersion, 0, aTypeLibrary)) then - raise EBoldCom.CreateFmt(sUnableToLoadTypeLibBoldSoap, [classname]); + raise EBoldCom.CreateFmt('%s.Create: Cannot load type library', [classname]); inherited Create(Adaptee, Owner, aTypeLibrary, IBoldSOAPService); end; @@ -65,4 +68,6 @@ function TBoldSOAPPersistenceControllerAdapter.GetPersistenceController: TBoldPe result := Adaptee as TBoldPersistenceController; end; +initialization + end. diff --git a/Source/Persistence/SOAP/BoldSOAPServerPersistenceHandles.pas b/Source/Persistence/SOAP/BoldSOAPServerPersistenceHandles.pas index f7a2046..2087459 100644 --- a/Source/Persistence/SOAP/BoldSOAPServerPersistenceHandles.pas +++ b/Source/Persistence/SOAP/BoldSOAPServerPersistenceHandles.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldSOAPServerPersistenceHandles; interface @@ -33,6 +36,9 @@ TBoldSOAPServerPersistenceHandle = class(TBoldComExportHandle) implementation +uses + BoldRev; + {-- TBoldComServerPersistenceHandle -------------------------------------------} function TBoldSOAPServerPersistenceHandle.GetComObject: IUnknown; @@ -68,4 +74,6 @@ procedure TBoldSOAPServerPersistenceHandle.SetBoldHandle(Value: TBoldPersistence end; end; +initialization + end. diff --git a/Source/Persistence/SQLDirect/BoldDatabaseAdapterSQLDirect.pas b/Source/Persistence/SQLDirect/BoldDatabaseAdapterSQLDirect.pas index f7a94d2..8b7852e 100644 --- a/Source/Persistence/SQLDirect/BoldDatabaseAdapterSQLDirect.pas +++ b/Source/Persistence/SQLDirect/BoldDatabaseAdapterSQLDirect.pas @@ -1,9 +1,13 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldDatabaseAdapterSQLDirect; interface uses SDEngine, + SDCommon, BoldAbstractDataBaseAdapter, BoldDBInterfaces, BoldSQLDirectInterfaces; @@ -23,6 +27,11 @@ TBoldDatabaseAdapterSQLDirect = class(TBoldAbstractDatabaseAdapter) function GetDataBaseInterface: IBoldDatabase; override; public destructor Destroy; override; + procedure LostConnectError(Database: TSDDatabase; + E: ESDEngineError; var Action: TSDLostConnectAction); + procedure ReconnectError(Database: TSDDatabase; + E: ESDEngineError; var Action: TSDLostConnectAction); + procedure CreateDatabase; override; published property DataBase: TSDDataBase read GetDataBase write SetDataBase; {$IFNDEF T2H} @@ -34,11 +43,17 @@ implementation uses SysUtils, - BoldDefs; + BoldDefs, + BoldRev; { TBoldDatabaseAdapterSQLDirect } -destructor TBoldDatabaseAdapterSQLDirect.destroy; +procedure TBoldDatabaseAdapterSQLDirect.CreateDatabase; +begin + Assert(False, 'Not implemented.'); +end; + +destructor TBoldDatabaseAdapterSQLDirect.Destroy; begin Changed; FreePublisher; @@ -65,9 +80,27 @@ procedure TBoldDatabaseAdapterSQLDirect.ReleaseBoldDatabase; FreeAndNil(fBoldDatabase); end; +procedure TBoldDatabaseAdapterSQLDirect.LostConnectError( + Database: TSDDatabase; E: ESDEngineError; + var Action: TSDLostConnectAction); +begin + Action:=lcWaitReconnect; +end; + +procedure TBoldDatabaseAdapterSQLDirect.ReconnectError( + Database: TSDDatabase; E: ESDEngineError; + var Action: TSDLostConnectAction); +begin + Action:=lcWaitReconnect; +end; + procedure TBoldDatabaseAdapterSQLDirect.SetDataBase(const Value: TSDDataBase); begin + value.OnLostConnectError:=LostConnectError; + value.OnReconnectError:=ReconnectError; InternalDatabase := value; end; +initialization + end. diff --git a/Source/Persistence/SQLDirect/BoldPersistenceHandleSQLDirect.pas b/Source/Persistence/SQLDirect/BoldPersistenceHandleSQLDirect.pas index 388a50f..1d48802 100644 --- a/Source/Persistence/SQLDirect/BoldPersistenceHandleSQLDirect.pas +++ b/Source/Persistence/SQLDirect/BoldPersistenceHandleSQLDirect.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldPersistenceHandleSQLDirect; interface @@ -35,7 +38,7 @@ TBoldPersistenceHandleSQLDirect = class(TBoldDBPersistenceHandle) procedure InternalTransferproperties(const target: TBoldPersistenceHandleDB); override; {$ENDIF} public - destructor Destroy; override; + destructor destroy; override; function GetDataBaseInterface: IBoldDatabase; override; published property DatabaseName: string read FDatabaseName write SetDatabaseName; @@ -46,7 +49,8 @@ implementation uses Dialogs, - SysUtils; + SysUtils, + BoldRev; { TBoldPersistenceHandleSQLDirect } @@ -85,8 +89,8 @@ procedure TBoldPersistenceHandleSQLDirect.InternalTransferproperties( begin Target.DatabaseAdapter := TBoldDatabaseAdapterSQLDirect.Create(Target.Owner); Target.DatabaseAdapter.Name := GetNewComponentName(Target.DatabaseAdapter, 'BoldDatabaseAdapterSQLDirect'); - LongRec(DesInfo).Lo := LongRec(DesInfo).lo+16; //set Left - LongRec(DesInfo).Hi := LongRec(DesInfo).hi+16; //Set Top; + LongRec(DesInfo).Lo := LongRec(DesInfo).lo+16; + LongRec(DesInfo).Hi := LongRec(DesInfo).hi+16; Target.DatabaseAdapter.DesignInfo := DesInfo; showmessage('Created a new DatabaseAdapterSQLDirect'); end @@ -102,8 +106,8 @@ procedure TBoldPersistenceHandleSQLDirect.InternalTransferproperties( Adapter.DataBase := TSDDatabase.Create(Target.owner); Adapter.DataBase.Name := GetNewComponentName(Adapter.DataBase, 'SDDatabase'); showmessage('Created a new SDDatabase'); - LongRec(DesInfo).Lo := LongRec(DesInfo).lo+16; //set Left - LongRec(DesInfo).Hi := LongRec(DesInfo).hi+16; //Set Top; + LongRec(DesInfo).Lo := LongRec(DesInfo).lo+16; + LongRec(DesInfo).Hi := LongRec(DesInfo).hi+16; Adapter.DataBase.DesignInfo := DesInfo; end; end; @@ -154,4 +158,6 @@ procedure TBoldPersistenceHandleSQLDirect.SetEffectiveDataBase(const Value: TSDD FEffectiveDatabase := Value; end; +initialization + end. diff --git a/Source/Persistence/SQLDirect/BoldPersistenceHandleSQLDirectReg.pas b/Source/Persistence/SQLDirect/BoldPersistenceHandleSQLDirectReg.pas index d4b42b7..fd616c7 100644 --- a/Source/Persistence/SQLDirect/BoldPersistenceHandleSQLDirectReg.pas +++ b/Source/Persistence/SQLDirect/BoldPersistenceHandleSQLDirectReg.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldPersistenceHandleSQLDirectReg; interface @@ -11,16 +14,22 @@ implementation uses SysUtils, Classes, + BoldIDESupport, + BoldVersionInfo, BoldDatabaseAdapterSQLDirect, BoldPersistenceHandleSQLDirect, - BoldIDESupport, - BoldIDEConsts; + BoldIDEConsts; procedure Register; begin - RemovePackageFromDisabledPackagesRegistry(format('BoldSQLDirect%s', [LIBSUFFIX])); // do not localize + RemovePackageFromDisabledPackagesRegistry(format('Bold%d%d%sSQLDirect', [ + BoldBuildVersionNumberMajor, + BoldBuildVersionNumberMinor, + BoldBuildTarget])); RegisterComponents(BOLDPAGENAME_DEPRECATED, [TBoldPersistenceHandleSQLDirect]); RegisterComponents(BOLDPAGENAME_PERSISTENCE, [TBoldDatabaseAdapterSQLDirect]); end; +initialization + end. diff --git a/Source/Persistence/SQLDirect/BoldSQLDirectInterfaces.pas b/Source/Persistence/SQLDirect/BoldSQLDirectInterfaces.pas index 773ab54..3156f47 100644 --- a/Source/Persistence/SQLDirect/BoldSQLDirectInterfaces.pas +++ b/Source/Persistence/SQLDirect/BoldSQLDirectInterfaces.pas @@ -1,7 +1,11 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldSQLDirectInterfaces; interface uses + Windows, Classes, Db, SDEngine, @@ -12,43 +16,78 @@ interface { forward declarations } TBoldSQLDirectDatabase = class; TBoldSQLDirectQuery = class; + TBoldSQLDirectTable = class; + TBoldSQLDirectQueryClass = class of TBoldSQLDirectQuery; + TBoldSqlDirectDbParameter = class(TBoldDbParameter, IBoldDBParam) + private + function GetParameter: TParam; + end; + { TBoldSDQuery } - TBoldSQLDirectQuery = class(TBoldDataSetWrapper, IBoldQuery, IBoldExecQuery, IBoldParameterized) + TBoldSQLDirectQuery = class(TBoldBatchDataSetWrapper, IBoldQuery, IBoldExecQuery, IBoldParameterized) private FQuery: TSDQuery; + fUseReadTransactions: boolean; function GetParamCount: integer; - function GetParams(i: integer): IBoldParameter; + function GetParams: TParams; override; + function GetParam(i: integer): IBoldParameter; function GetQuery: TSDQuery; function GetRecordCount: integer; function GetRequestLiveQuery: Boolean; procedure ClearParams; function GetRowsAffected: integer; function GetSQLText: String; - function ParamByName(const Value: string): IBoldParameter; + function GetParamCheck: Boolean; + procedure SetParamCheck(value: Boolean); + function ParamByName(const Value: string): IBoldParameter; override; + function FindParam(const Value: string): IBoldParameter; override; procedure AssignParams(Sourceparams: TParams); procedure AssignSQL(SQL: TStrings); - procedure AssignSQLText(SQL: String); + procedure AssignSQLText(const SQL: String); + function GetSQLStrings: TStrings; override; procedure SetRequestLiveQuery(NewValue: Boolean); - function Createparam(FldType: TFieldType; const ParamName: string; ParamType: TParamType; Size: integer): IBoldParameter; + function GetUseReadTransactions: boolean; + procedure SetUseReadTransactions(value: boolean); + function Createparam(FldType: TFieldType; const ParamName: string; ParamType: TParamType; Size: integer): IBoldParameter; override; + procedure ExecSQL; protected function GetDataSet: TDataSet; override; - procedure EndSQLBatch; virtual; - procedure ExecSQL; - procedure FailSQLBatch; virtual; procedure Open; override; - procedure StartSQLBatch; virtual; property Query: TSDQuery read GetQuery; public - constructor Create(Query: TSDQuery; DatabaseWrapper: TBoldDatabaseWrapper); + constructor Create(Query: TSDQuery; DatabaseWrapper: TBoldDatabaseWrapper); virtual; + end; + + { TBoldSQLDirectTable } + TBoldSQLDirectTable = class(TBoldDataSetWrapper, IBoldTable) + private + fTable: TSDTable; + procedure AddIndex(const Name, Fields: string; Options: TIndexOptions; const DescFields: string = ''); + procedure CreateTable; + procedure DeleteTable; + function GetTable: TSDTable; + function GetIndexDefs: TIndexDefs; + procedure SetTableName(const NewName: String); + function GetTableName: String; + procedure SetExclusive(NewValue: Boolean); + function GetExclusive: Boolean; + function GetExists: Boolean; + property Table: TSDTable read GetTable; + protected + function GetDataSet: TDataSet; override; + public + constructor Create(Table: TSDTable; DatabaseWrapper: TBoldDatabaseWrapper); end; { TBoldSDDataBase } TBoldSQLDirectDatabase = class(TBolddatabaseWrapper, IBoldDataBase) private FDatabase: TSDDataBase; + fCachedTable: TSDTable; FCachedQuery: TSDQuery; + fExecuteQueryCount: integer; function GetConnected: Boolean; function GetDataBase: TSDDataBase; function GetInTransaction: Boolean; @@ -59,21 +98,23 @@ TBoldSQLDirectDatabase = class(TBolddatabaseWrapper, IBoldDataBase) procedure Close; procedure Commit; procedure Open; - function GetTable: IBoldTable; - procedure ReleaseTable(var Table: IBoldTable); procedure Rollback; procedure SetKeepConnection(NewValue: Boolean); procedure SetlogInPrompt(NewValue: Boolean); procedure StartTransaction; property Database: TSDDatabase read GetDatabase; procedure ReleaseCachedObjects; + function GetIsExecutingQuery: Boolean; protected procedure AllTableNames(Pattern: String; ShowSystemTables: Boolean; TableNameList: TStrings); override; function GetQuery: IBoldQuery; override; procedure ReleaseQuery(var Query: IBoldQuery); override; + function GetTable: IBoldTable; override; + procedure ReleaseTable(var Table: IBoldTable); override; public constructor Create(Database: TSDDataBase; SQLDataBaseConfig: TBoldSQLDatabaseConfig); destructor Destroy; override; + procedure Reconnect; end; var @@ -84,7 +125,11 @@ implementation uses SysUtils, BoldUtils, - Dialogs; + BoldDefs, + Controls, + Masks, + DateUtils, + StrUtils; { TBoldSDQuery } @@ -103,7 +148,7 @@ procedure TBoldSQLDirectQuery.AssignSQL(SQL: TStrings); Query.SQL.EndUpdate; end; -procedure TBoldSQLDirectQuery.AssignSQLText(SQL: String); +procedure TBoldSQLDirectQuery.AssignSQLText(const SQL: String); begin Query.SQL.BeginUpdate; Query.SQL.Clear; @@ -120,29 +165,41 @@ constructor TBoldSQLDirectQuery.Create(Query: TSDQuery; DatabaseWrapper: TBoldDa begin inherited create(DatabaseWrapper); FQuery := Query; + SetParamCheck(true); end; function TBoldSQLDirectQuery.Createparam(FldType: TFieldType; const ParamName: string; ParamType: TParamType; Size: integer): IBoldParameter; begin - result := TBoldDbParameter.Create(Query.params.CreateParam(fldType, ParamName, ParamType), self); -end; - -procedure TBoldSQLDirectQuery.EndSQLBatch; -begin + result := TBoldSqlDirectDbParameter.Create(Query.params.CreateParam(fldType, ParamName, ParamType), self); end; procedure TBoldSQLDirectQuery.ExecSQL; begin try BoldLogSQL(Query.SQL); - Query.ExecSQL; + if InBatch then + begin + BatchExecSQL; + exit; + end; + Query.ExecSQL; except - on E: Exception do MessageDlg(E.Message + #13#10 +Query.SQL.Text, mtError, [mbOk], 0); + on e: exception do + begin + e.Message := (e.Message + #13#10 +Query.SQL.Text); + raise; end; end; +end; -procedure TBoldSQLDirectQuery.FailSQLBatch; +function TBoldSQLDirectQuery.FindParam(const Value: string): IBoldParameter; +var + Param: TParam; begin + result := nil; + Param := Query.Params.FindParam(Value); + if Assigned(Param) then + result := TBoldSqlDirectDbParameter.Create(Param, self) end; function TBoldSQLDirectQuery.GetDataSet: TDataSet; @@ -150,19 +207,31 @@ function TBoldSQLDirectQuery.GetDataSet: TDataSet; result := Query; end; +function TBoldSQLDirectQuery.GetParamCheck: Boolean; +begin + Result := Query.ParamCheck; +end; + function TBoldSQLDirectQuery.GetParamCount: integer; begin result := Query.Params.count; end; -function TBoldSQLDirectQuery.GetParams(i: integer): IBoldParameter; +function TBoldSQLDirectQuery.GetParams: TParams; begin - result := TBoldDBParameter.Create(Query.Params[i], self); + result := Query.Params; +end; + +function TBoldSQLDirectQuery.GetParam(i: integer): IBoldParameter; +begin + result := TBoldSqlDirectDbParameter.Create(Query.Params[i], self); end; function TBoldSQLDirectQuery.GetQuery: TSDQuery; begin - result := FQuery; + if not assigned(fQuery) then + fQuery := TSDQuery.Create(nil); + result := fQuery; end; function TBoldSQLDirectQuery.GetRecordCount: integer; @@ -172,7 +241,7 @@ function TBoldSQLDirectQuery.GetRecordCount: integer; function TBoldSQLDirectQuery.GetRequestLiveQuery: Boolean; begin - result := false; + result := Query.RequestLive; end; function TBoldSQLDirectQuery.GetRowsAffected: integer; @@ -180,15 +249,25 @@ function TBoldSQLDirectQuery.GetRowsAffected: integer; result := Query.RowsAffected; end; +function TBoldSQLDirectQuery.GetSQLStrings: TStrings; +begin + result := Query.SQL; +end; + function TBoldSQLDirectQuery.GetSQLText: String; begin result := Query.SQL.Text; end; +function TBoldSQLDirectQuery.GetUseReadTransactions: boolean; +begin + result := fUseReadTransactions; +end; + procedure TBoldSQLDirectQuery.Open; begin BoldLogSQL(Query.SQL); - inherited; + inherited; end; function TBoldSQLDirectQuery.ParamByName(const Value: string): IBoldParameter; @@ -196,28 +275,130 @@ function TBoldSQLDirectQuery.ParamByName(const Value: string): IBoldParameter; Param: TParam; begin Param := Query.ParamByName(Value); - if assigned(Param) then - result := TBoldDbParameter.Create(Param, self) - else - result := nil; + result := TBoldSqlDirectDbParameter.Create(Param, self); end; +procedure TBoldSQLDirectQuery.SetParamCheck(value: Boolean); +begin + Query.ParamCheck := Value; +end; + procedure TBoldSQLDirectQuery.SetRequestLiveQuery(NewValue: Boolean); begin end; -procedure TBoldSQLDirectQuery.StartSQLBatch; +procedure TBoldSQLDirectQuery.SetUseReadTransactions(value: boolean); +begin + fUseReadTransactions := value; +end; + + +{ TBoldSQLDirectTable } + +procedure TBoldSQLDirectTable.AddIndex(const Name, Fields: string; + Options: TIndexOptions; const DescFields: string); +begin + Assert(False, 'TBoldSQLDirectTable.AddIndex: Not Implemented'); + // Table.AddIndex(Name, Fields, Options, DescFields); +end; + +constructor TBoldSQLDirectTable.Create(Table: TSDTable; DatabaseWrapper: TBoldDatabaseWrapper); +begin + inherited Create(DatabaseWrapper); + fTable := Table; +end; + +procedure TBoldSQLDirectTable.CreateTable; +begin + Table.CreateTable; +end; + +procedure TBoldSQLDirectTable.DeleteTable; +begin + Table.DeleteTable; +end; + +function TBoldSQLDirectTable.GetDataSet: TDataSet; begin + result := Table; +end; + +function TBoldSQLDirectTable.GetExclusive: Boolean; +begin + result:=false; + Assert(False, 'TBoldSQLDirectTable.GetExclusive: Not Implemented'); + // result := Table.Exclusive; +end; + +function TBoldSQLDirectTable.GetExists: Boolean; +begin + result := Table.Exists; +end; + +function TBoldSQLDirectTable.GetIndexDefs: TIndexDefs; +begin + result := Table.IndexDefs; +end; + +function TBoldSQLDirectTable.GetTable: TSDTable; +begin + if not assigned(fTable) then + fTable := TSDTable.Create(nil); + result := fTable +end; + +function TBoldSQLDirectTable.GetTableName: String; +begin + result := Table.TableName; +end; + +procedure TBoldSQLDirectTable.SetExclusive(NewValue: Boolean); +begin + Assert(False, 'TBoldSQLDirectTable.DetExclusive: Not Implemented'); + // Table.Exclusive := NewValue; +end; + +procedure TBoldSQLDirectTable.SetTableName(const NewName: String); +begin + Table.TableName := NewName; end; { TBoldSDDataBase } procedure TBoldSQLDirectDatabase.AllTableNames(Pattern: String; ShowSystemTables: Boolean; TableNameList: TStrings); -begin - if (Pattern <> '') and (Pattern <> '*') then - raise Exception.CreateFmt('%s.AlltableNames: This call does not allow patterns ("%s")', [ClassName, Pattern]); - Database.Session.GetTableNames(Database.DatabaseName, Pattern, ShowSystemTables, TableNameList); +var + i, dotpos: Integer; + TableOwner: String; +begin + // when ShowSystemTables = true SQLDirect returns only System tables, no user tables, which we never want + // in other DB implementations ShowSystemTables means User tables + System tables. + ShowSystemTables := false; + fDatabase.Session.GetTableNames(fDatabase.DatabaseName, Pattern, ShowSystemTables, TableNameList); + + TableOwner:=fDatabase.Params.Values['USER NAME']+'.'; + i:=0; + while i<=TableNameList.Count-1 do begin + if fDatabase.ServerType=stOracle then begin + if not AnsiSameText(LeftStr(TableNameList[i], Length(TableOwner)), TableOwner) then begin + TableNameList.Delete(i); + Continue; + end; + end; + dotPos := pos('.', TableNameList[i]); + if dotPos > 0 then begin + TableNameList[i] := Copy(TableNameList[i], dotPos+1, maxInt); + end; + Inc(i); + end; + + if Pattern <> '' then begin + for i := TableNameList.Count - 1 downto 0 do begin + if not MatchesMask(TableNameList[i], Pattern) then begin + TableNameList.Delete(i); + end; + end; + end; end; procedure TBoldSQLDirectDatabase.Close; @@ -232,14 +413,15 @@ procedure TBoldSQLDirectDatabase.Commit; constructor TBoldSQLDirectDatabase.create(DataBase: TSDDataBase; SQLDataBaseConfig: TBoldSQLDatabaseConfig); begin - inherited create(SQLDataBaseConfig); + inherited Create(SQLDataBaseConfig); FDataBase := DataBase; end; -destructor TBoldSQLDirectDatabase.destroy; +destructor TBoldSQLDirectDatabase.Destroy; begin inherited; FDatabase := nil; + FreeAndNil(fCachedTable); FreeAndNil(fCachedQuery); end; @@ -258,19 +440,24 @@ function TBoldSQLDirectDatabase.GetInTransaction: Boolean; result := Database.InTransaction; end; +function TBoldSQLDirectDatabase.GetIsExecutingQuery: Boolean; +begin + Result := fExecuteQueryCount > 0; +end; + function TBoldSQLDirectDatabase.GetIsSQLBased: Boolean; begin - result := true; + result := DataBase.IsSQLBased; end; function TBoldSQLDirectDatabase.GetKeepConnection: Boolean; begin - result := true; + result := DataBase.KeepConnection; end; function TBoldSQLDirectDatabase.GetLogInPrompt: Boolean; begin - result := dataBase.LoginPrompt; + result := DataBase.LoginPrompt; end; function TBoldSQLDirectDatabase.GetQuery: IBoldQuery; @@ -285,15 +472,28 @@ function TBoldSQLDirectDatabase.GetQuery: IBoldQuery; else begin Query := TSDQuery.Create(nil); - Query.DatabaseName := Database.DatabaseName; Query.SessionName := Database.SessionName; + Query.DatabaseName := Database.DatabaseName; end; result := BoldSQLDirectQueryClass.Create(Query, self); end; function TBoldSQLDirectDatabase.GetTable: IBoldTable; +var + Table: TSDTable; begin - result := nil; + if assigned(fCachedTable) then + begin + Table := fCachedTable; + fCachedTable := nil; + end + else + begin + Table := TSDTable.Create(nil); + Table.SessionName := Database.SessionName; + Table.DatabaseName := DataBase.DataBaseName; + end; + result := TBoldSQLDirectTable.Create(Table, self); end; procedure TBoldSQLDirectDatabase.Open; @@ -301,9 +501,14 @@ procedure TBoldSQLDirectDatabase.Open; Database.Open; end; +procedure TBoldSQLDirectDatabase.Reconnect; +begin + Assert(False, 'TBoldSQLDirectDatabase.Reconnect: Not Implemented'); +end; + procedure TBoldSQLDirectDatabase.ReleaseCachedObjects; begin - //FreeAndNil(fCachedTable); + FreeAndNil(fCachedTable); FreeAndNil(fCachedQuery); end; @@ -327,8 +532,19 @@ procedure TBoldSQLDirectDatabase.ReleaseQuery(var Query: IBoldQuery); end; procedure TBoldSQLDirectDatabase.ReleaseTable(var Table: IBoldTable); +var + SQLDirectTable: TBoldSQLDirectTable; +begin + if Table.Implementor is TBoldSQLDirectTable then begin - raise Exception.Create('TBoldSQLDirectDatabase.ReleaseTable: Operation not supported'); + SQLDirectTable := Table.Implementor as TBoldSQLDirectTable; + Table := nil; + if not assigned(fCachedTable) then + fCachedTable := SQLDirectTable.fTable + else + SQLDirectTable.fTable.free; + SQLDIrectTable.Free; + end; end; procedure TBoldSQLDirectDatabase.Rollback; @@ -338,6 +554,7 @@ procedure TBoldSQLDirectDatabase.Rollback; procedure TBoldSQLDirectDatabase.SetKeepConnection(NewValue: Boolean); begin + Database.KeepConnection := NewValue; end; procedure TBoldSQLDirectDatabase.SetlogInPrompt(NewValue: Boolean); @@ -352,7 +569,15 @@ procedure TBoldSQLDirectDatabase.StartTransaction; function TBoldSQLDirectDatabase.SupportsTableCreation: boolean; begin - result := false; + result := true; +end; + +{ TBoldSqlDirectDbParameter } + +function TBoldSqlDirectDbParameter.GetParameter: TParam; +begin + result := self.Parameter; end; +initialization end. diff --git a/Source/Persistence/System/BoldPersistenceControllerSystem.pas b/Source/Persistence/System/BoldPersistenceControllerSystem.pas index a3dace9..4fdcf8a 100644 --- a/Source/Persistence/System/BoldPersistenceControllerSystem.pas +++ b/Source/Persistence/System/BoldPersistenceControllerSystem.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldPersistenceControllerSystem; interface @@ -11,7 +14,8 @@ interface BoldSystem, BoldValueSpaceInterfaces, BoldSubscription, - BoldDefs; + BoldDefs, + BoldElements; type { forward declarations } @@ -21,25 +25,26 @@ TBoldPersistenceControllerSystem = class; TBoldPersistenceControllerSystem = class(TBoldPersistenceController) private fBoldSystem: TBoldSystem; - fLocatorSubscriber: TBoldPassthroughSubscriber; - fMapping: TBoldIndexableList; // TBoldIdLocatorMapping + fLocatorSubscriber: TBoldExtendedPassthroughSubscriber; + fMapping: TBoldIndexableList; procedure _LocatorDestroyedReceived(Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent; const Args: array of const); procedure SetBoldSystem(System: TBoldSystem); function GetLocatorById(ObjectId: TBoldObjectId): TBoldObjectLocator; function GetIdByLocator(Locator: TBoldObjectLocator): TBoldObjectId; + procedure FetchMember(const ObjectContents: IBoldObjectContents; MemberIndex: Integer; BoldMember: TBoldMember); public constructor Create; destructor Destroy; override; - procedure PMExactifyIds(ObjectIdList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList); override; + procedure PMExactifyIds(ObjectIdList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList; HandleNonExisting: Boolean); override; procedure PMFetch(ObjectIdList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; MemberIdList: TBoldMemberIdList; FetchMode: Integer; BoldClientID: TBoldClientID); override; procedure PMFetchIDListWithCondition(ObjectIdList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; FetchMode: Integer; Condition: TBoldCondition; BoldClientID: TBoldClientID); override; - procedure PMUpdate(ObjectIdList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; Old_Values: IBoldValueSpace; Precondition: TBoldUpdatePrecondition; TranslationList: TBoldIdTranslationList; var TimeStamp: TBoldTimeStampType; BoldClientID: TBoldClientID); override; + procedure PMUpdate(ObjectIdList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; Old_Values: IBoldValueSpace; Precondition: TBoldUpdatePrecondition; TranslationList: TBoldIdTranslationList; var TimeStamp: TBoldTimeStampType; var TimeOfLatestUpdate: TDateTime; BoldClientID: TBoldClientID); override; procedure PMTranslateToGlobalIds(ObjectIdList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList); override; procedure PMTranslateToLocalIds(GlobalIdList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList); override; procedure PMSetReadOnlyness(ReadOnlyList, WriteableList: TBoldObjectIdList); override; - // this info should be stored in separate Mapping model procedure ReserveNewIds(ValueSpace: IBoldValueSpace; ObjectIdList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList); override; + function CanEvaluateInPS(sOCL: string; aSystem: TBoldElement; aContext: TBoldElementTypeInfo = nil; const aVariableList: TBoldExternalVariableList = nil): Boolean; override; property BoldSystem: TBoldSystem read fBoldSystem write SetBoldSystem; property LocatorById[ObjectId: TBoldObjectId]: TBoldObjectLocator read GetLocatorById; property IdByLocator[Locator: TBoldObjectLocator]: TBoldObjectId read GetIdByLocator; @@ -53,11 +58,8 @@ implementation BoldDomainElement, BoldDefaultId, BoldSystemRT, - BoldIndex; - -var - IX_MappingIdIndex: integer = -1; - IX_MappingLocatorIndex: integer = -1; + BoldIndex, + BoldLogHandler; type { TBoldIdLocatorPair } @@ -89,16 +91,18 @@ TBoldMappingLocatorIndex = class(TBoldHashIndex) { TBoldIdLocatorMapping } TBoldIdLocatorMapping = class(TBoldIndexableList) private + class var IX_MappingIdIndex: integer; + class var IX_MappingLocatorIndex: integer; fNextId: Integer; - function GetLocatorById(ID: TBoldObjectId): TBoldObjectLocator; - function GetIdByLocator(Locator: TBoldObjectLocator): TBoldObjectId; - function GetPairByLocator(Locator: TBoldObjectLocator): TBoldIdLocatorPair; + function GetLocatorById(ID: TBoldObjectId): TBoldObjectLocator; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function GetIdByLocator(Locator: TBoldObjectLocator): TBoldObjectId; {$IFDEF BOLD_INLINE}inline;{$ENDIF} + function GetPairByLocator(Locator: TBoldObjectLocator): TBoldIdLocatorPair; {$IFDEF BOLD_INLINE}inline;{$ENDIF} public constructor Create; - procedure AddPair(Id: TBoldObjectId; Locator: TBoldObjectLocator); + procedure AddPair(Id: TBoldObjectId; Locator: TBoldObjectLocator); {$IFDEF BOLD_INLINE}inline;{$ENDIF} procedure ExactifyClassForLocator(Locator: TBoldObjectLocator; ExactClassId: Integer); function EnsuredIdByLocator(Locator: TBoldObjectLocator): TBoldObjectId; - procedure RemoveByLocator(Locator: TBoldObjectLocator); + procedure RemoveByLocator(Locator: TBoldObjectLocator); {$IFDEF BOLD_INLINE}inline;{$ENDIF} property LocatorById[ID: TBoldObjectId]: TBoldObjectLocator read GetLocatorById; property IdByLocator[Locator: TBoldObjectLocator]: TBoldObjectId read GetIdByLocator; end; @@ -106,11 +110,162 @@ TBoldIdLocatorMapping = class(TBoldIndexableList) const OBJECTIDLOCATORNAME = 'ObjectIdLocator'; +{ TBoldIdLocatorMapping } + +procedure TBoldIdLocatorMapping.AddPair(Id: TBoldObjectId; Locator: TBoldObjectLocator); +begin + Add(TBoldIdLocatorPair.Create(Id, Locator)); +end; + +constructor TBoldIdLocatorMapping.Create; +begin + inherited; + IX_MappingIdIndex := -1; + IX_MappingLocatorIndex := -1; + SetIndexVariable(IX_MappingIdIndex, AddIndex(TBoldMappingIdIndex.Create)); + SetIndexVariable(IX_MappingLocatorIndex, AddIndex(TBoldMappingLocatorIndex.Create)); + fNextId := 1; +end; + +function TBoldIdLocatorMapping.GetPairByLocator( + Locator: TBoldObjectLocator): TBoldIdLocatorPair; +begin + result := TBoldIdLocatorPair(Indexes[IX_MappingLocatorIndex].Find(Locator)); +end; + +function TBoldIdLocatorMapping.GetIdByLocator(Locator: TBoldObjectLocator): TBoldObjectId; +var + aPair: TBoldIdLocatorPair; +begin + aPair := GetPairByLocator(Locator); + if assigned(aPair) then + result := aPair.fId + else + result := nil; +end; + +function TBoldIdLocatorMapping.EnsuredIdByLocator( + Locator: TBoldObjectLocator): TBoldObjectId; +var + NewId: TBoldDefaultId; +begin + if not assigned(Locator) then + result := nil + else + begin + result := IdByLocator[Locator]; + if not assigned(result) then + begin + NewId := TBoldDefaultId.CreateWithClassID(Locator.BoldObjectID.TopSortedIndex, Locator.BoldObjectID.TopSortedIndexExact); + NewId.AsInteger := fNextId; + inc(fNextId); + AddPair(NewId, Locator); + NewId.Free; + result := IdByLocator[Locator]; + end; + end; +end; + +procedure TBoldIdLocatorMapping.ExactifyClassForLocator( + Locator: TBoldObjectLocator; ExactClassId: Integer); +var + NewId: TBoldObjectId; + aPair: TBoldIdLocatorPair; +begin + aPair := GetPairByLocator(Locator); + NewId := aPair.fId.CloneWithClassId(ExactClassId, True); + aPair.fId.Free; + aPair.fId := NewId; +end; + +function TBoldIdLocatorMapping.GetLocatorById( + ID: TBoldObjectId): TBoldObjectLocator; +var + aPair: TBoldIdLocatorPair; +begin + aPair := TBoldIdLocatorPair(Indexes[IX_MappingIdIndex].Find(Id)); + if assigned(aPair) then + result := aPair.fLocator + else + result := nil; +end; + +procedure TBoldIdLocatorMapping.RemoveByLocator( + Locator: TBoldObjectLocator); +var + aPair: TBoldIdLocatorPair; +begin + aPair := GetPairByLocator(Locator); + if assigned(aPair) then + Remove(aPair); +end; + +{ TBoldMappingIdIndex } + +function TBoldMappingIdIndex.Hash(const Key): Cardinal; +begin + Assert(TObject(Key) is TBoldObjectId); + Result := TBoldObjectId(Key).Hash; +end; + +function TBoldMappingIdIndex.HashItem(Item: TObject): Cardinal; +begin + result := (Item as TBoldIdLocatorPair).fId.Hash; +end; + +function TBoldMappingIdIndex.Match(const Key; Item: TObject): Boolean; +begin + Assert(TObject(Key) is TBoldObjectId); + result := TBoldObjectId(Key).IsEqual[TBoldIdLocatorPair(Item).fId]; +end; + +{ TBoldMappingLocatorIndex } + +function TBoldMappingLocatorIndex.Hash(const Key): Cardinal; +begin + Assert(TObject(Key) is TBoldObjectLocator); + Result := TBoldObjectLocator(Key).Hash; +end; + +function TBoldMappingLocatorIndex.HashItem(Item: TObject): Cardinal; +begin + result := (Item as TBoldIdLocatorPair).fLocator.Hash; +end; + +function TBoldMappingLocatorIndex.Match(const Key; Item:TObject): Boolean; +begin + Assert(TObject(Key) is TBoldObjectLocator); + Assert(Item is TBoldIdLocatorPair); + result := TBoldObjectLocator(Key) = TBoldIdLocatorPair(Item).fLocator; +end; + +{ TBoldIdLocatorPair } + +constructor TBoldIdLocatorPair.Create(Id: TBoldObjectId; + Locator: TBoldObjectLocator); +begin + fLocator := Locator; + fId := Id.Clone; +end; + +destructor TBoldIdLocatorPair.Destroy; +begin + FreeAndNil(fId); + inherited; +end; + { TBoldPersistenceControllerSystem } +function TBoldPersistenceControllerSystem.CanEvaluateInPS(sOCL: string; + aSystem: TBoldElement; aContext: TBoldElementTypeInfo; + const aVariableList: TBoldExternalVariableList): Boolean; +begin + result := BoldSystem.CanEvaluateInPs(sOCL, aContext, aVariableList); +end; + constructor TBoldPersistenceControllerSystem.Create; begin - fLocatorSubscriber := TBoldPassthroughSubscriber.CreateWithExtendedReceive(_LocatorDestroyedReceived); + fLocatorSubscriber := TBoldExtendedPassthroughSubscriber.CreateWithExtendedReceive(_LocatorDestroyedReceived); fMapping := TBoldIdLocatorMapping.Create; end; @@ -121,6 +276,71 @@ destructor TBoldPersistenceControllerSystem.Destroy; inherited; end; +procedure TBoldPersistenceControllerSystem.FetchMember( + const ObjectContents: IBoldObjectContents; MemberIndex: Integer; + BoldMember: TBoldMember); + + function ExtractNewIdList(ObjectList: TBoldObjectList): TBoldObjectIdList; + var + i: Integer; + begin + result := TBoldObjectIdList.Create; + for i := 0 to ObjectList.Count - 1 do + result.Add(TBoldIdLocatorMapping(fMapping).EnsuredIdByLocator(ObjectList.Locators[i])); + end; + +var + aValue: IBoldValue; + aRoleRT: TBoldRoleRTInfo; + Ids1, Ids2: TBoldObjectIdList; + aMemberId: TBoldMemberId; +begin + aValue := BoldMember.AsIBoldValue[bdepContents]; + Assert(Assigned(aValue)); + aValue := ObjectContents.EnsureMemberAndGetValueByIndex(MemberIndex, aValue.ContentName); + Assert(Assigned(aValue)); + if (aValue.BoldPersistenceState = bvpsInvalid) then + begin + if BoldMember.BoldMemberRTInfo.Persistent then + begin + BoldMember.EnsureContentsCurrent; + if not (BoldMember.BoldMemberRTInfo is TBoldRoleRTInfo) then + aValue.AssignContent(BoldMember.AsIBoldValue[bdepContents]) + else + begin + aRoleRT := BoldMember.BoldMemberRTInfo as TBoldRoleRTInfo; + if aRoleRT.IsMultiRole then + begin + if aRoleRT.IsIndirect then + begin + Ids1 := ExtractNewIdList(BoldMember.OwningObject.BoldMembers[aRoleRT.IndexOfLinkObjectRole] as TBoldObjectList); + Ids2 := ExtractNewIdList(BoldMember as TBoldObjectList); + (aValue as IBoldObjectIdListRefPair).SetFromIdLists(Ids1, Ids2); + Ids1.Free; + Ids2.Free; + end else + begin + Ids1 := ExtractNewIdList(BoldMember as TBoldObjectList); + (aValue as IBoldObjectIdListRef).SetFromIdList(Ids1); + Ids1.Free; + end; + end else + begin + if aRoleRT.IsIndirect then + (aValue as IBoldObjectIdRefPair).SetFromIds( + TBoldIdLocatorMapping(fMapping).EnsuredIdByLocator((BoldMember.OwningObject.BoldMembers[aRoleRT.IndexOfLinkObjectRole] as TBoldObjectReference).Locator), + TBoldIdLocatorMapping(fMapping).EnsuredIdByLocator((BoldMember as TBoldObjectReference).Locator)) + else + (aValue as IBoldObjectIdRef).SetFromId( + TBoldIdLocatorMapping(fMapping).EnsuredIdByLocator((BoldMember as TBoldObjectReference).Locator) + , false); //? + end; + end; + end; + end; +end; + + function TBoldPersistenceControllerSystem.GetIdByLocator( Locator: TBoldObjectLocator): TBoldObjectId; begin @@ -135,7 +355,7 @@ function TBoldPersistenceControllerSystem.GetLocatorById( procedure TBoldPersistenceControllerSystem.PMExactifyIds( ObjectIdList: TBoldObjectIdList; - TranslationList: TBoldIdTranslationList); + TranslationList: TBoldIdTranslationList; HandleNonExisting: Boolean); var i: integer; anIdList: TBoldObjectIdList; @@ -152,7 +372,7 @@ procedure TBoldPersistenceControllerSystem.PMExactifyIds( if anIdList.Count > 0 then begin - BoldSystem.PersistenceController.PMExactifyIds(anIdList, aTranslationList); + BoldSystem.PersistenceController.PMExactifyIds(anIdList, aTranslationList, HandleNonExisting); BoldSystem.AsIBoldvalueSpace[bdepContents].ApplytranslationList(aTranslationList); for i := 0 to anIdList.Count - 1 do begin @@ -178,70 +398,6 @@ procedure TBoldPersistenceControllerSystem.PMFetch( MemberIdList: TBoldMemberIdList; FetchMode: Integer; BoldClientID: TBoldClientID); - procedure FetchMember(ObjectContents: IBoldObjectContents; MemberIndex: Integer; BoldMember: TBoldMember); - - function ExtractNewIdList(ObjectList: TBoldObjectList): TBoldObjectIdList; - var - i: Integer; - begin - result := TBoldObjectIdList.Create; - for i := 0 to ObjectList.Count - 1 do - result.Add(TBoldIdLocatorMapping(fMapping).EnsuredIdByLocator(ObjectList.Locators[i])); - end; - - var - aValue: IBoldValue; - aRoleRT: TBoldRoleRTInfo; - Ids1, Ids2: TBoldObjectIdList; - aMemberId: TBoldMemberId; - begin - aMemberId := TBoldMemberID.create(MemberIndex); - try - ObjectContents.EnsureMember(aMemberId, BoldMember.AsIBoldValue[bdepContents].ContentName); - finally - aMemberId.Free; - end; - aValue := ObjectContents.ValueByIndex[MemberIndex]; - if (aValue.BoldPersistenceState = bvpsInvalid) then - begin - if BoldMember.BoldMemberRTInfo.Persistent then - begin - BoldMember.EnsureContentsCurrent; - if not (BoldMember.BoldMemberRTInfo is TBoldRoleRTInfo) then - aValue.AssignContent(BoldMember.AsIBoldValue[bdepContents]) - else - begin - aRoleRT := BoldMember.BoldMemberRTInfo as TBoldRoleRTInfo; - if aRoleRT.IsMultiRole then - begin - if aRoleRT.IsIndirect then - begin - Ids1 := ExtractNewIdList(BoldMember.OwningObject.BoldMembers[aRoleRT.IndexOfLinkObjectRole] as TBoldObjectList); - Ids2 := ExtractNewIdList(BoldMember as TBoldObjectList); - (aValue as IBoldObjectIdListRefPair).SetFromIdLists(Ids1, Ids2); - Ids1.Free; - Ids2.Free; - end else - begin - Ids1 := ExtractNewIdList(BoldMember as TBoldObjectList); - (aValue as IBoldObjectIdListRef).SetFromIdList(Ids1); - Ids1.Free; - end; - end else - begin - if aRoleRT.IsIndirect then - (aValue as IBoldObjectIdRefPair).SetFromIds( - TBoldIdLocatorMapping(fMapping).EnsuredIdByLocator((BoldMember.OwningObject.BoldMembers[aRoleRT.IndexOfLinkObjectRole] as TBoldObjectReference).Locator), - TBoldIdLocatorMapping(fMapping).EnsuredIdByLocator((BoldMember as TBoldObjectReference).Locator)) - else - (aValue as IBoldObjectIdRef).SetFromId( - TBoldIdLocatorMapping(fMapping).EnsuredIdByLocator((BoldMember as TBoldObjectReference).Locator)); - end; - end; - end; - end; - end; - var i, j: Integer; aLocator: TBoldObjectLocator; @@ -249,17 +405,48 @@ procedure TBoldPersistenceControllerSystem.PMFetch( anObjectContent: IBoldObjectContents; aMember: TBoldMember; aMemberIndex: Integer; + + FetchIdList: TBoldObjectIdList; + ExactifyTranslationList: TBoldIdTranslationList; + lObjectList: TBoldObjectList; + Locator: TBoldObjectLocator; begin - for i := 0 to ObjectIdList.Count - 1 do + ExactifyTranslationList := TBoldIdTranslationList.Create; + FetchIdList := ObjectIdList.Clone; + try + PMExactifyIDs(FetchIdList, ExactifyTranslationList, false); + if ExactifyTranslationList.Count > 0 then + begin + ValueSpace.ExactifyIDs(ExactifyTranslationList); + ObjectIdList.ExactifyIds(ExactifyTranslationList); + FetchIdList.ExactifyIds(ExactifyTranslationList); + end; + + lObjectList := TBoldObjectList.Create; + try + for I := 0 to FetchIdList.Count - 1 do + begin + Locator := TBoldIdLocatorMapping(fMapping).LocatorById[FetchIdList[i]]; + if Assigned(Locator) then + lObjectList.AddLocator(Locator); + end; + if not lObjectList.Empty then + BoldSystem.FetchMembersWithObjects(lObjectList, MemberIdList); + finally + lObjectList.free; + end; + + for i := 0 to FetchIdList.Count - 1 do begin - anObjectContent := ValueSpace.EnsuredObjectContentsByObjectId[ObjectIdList[i]]; - aLocator := TBoldIdLocatorMapping(fMapping).LocatorById[ObjectIdList[i]]; + anObjectContent := ValueSpace.EnsuredObjectContentsByObjectId[FetchIdList[i]]; + aLocator := TBoldIdLocatorMapping(fMapping).LocatorById[FetchIdList[i]]; if not assigned(aLocator) then anObjectContent.BoldExistenceState := besDeleted else begin anObject := aLocator.EnsuredBoldObject; anObjectContent.BoldExistenceState := anObject.BoldExistenceState; + anObjectContent.TimeStamp := anObject.AsIBoldObjectContents[bdepContents].TimeStamp; if assigned(MemberIdList) then begin for j := 0 to MemberIdList.Count - 1 do @@ -272,12 +459,17 @@ procedure TBoldPersistenceControllerSystem.PMFetch( for j := 0 to anObject.BoldMemberCount - 1 do begin aMember := anObject.BoldMembers[j]; - if not aMember.BoldMemberRTInfo.DelayedFetch then + if (not aMember.BoldMemberRTInfo.DelayedFetch) and aMember.BoldMemberRTInfo.Persistent then FetchMember(anObjectContent, j, aMember); end; end; end; end; + + finally + ExactifyTranslationLIst.Free; + FetchIdList.Free; + end; end; procedure TBoldPersistenceControllerSystem.PMFetchIDListWithCondition( @@ -286,12 +478,31 @@ procedure TBoldPersistenceControllerSystem.PMFetchIDListWithCondition( var anObjectList: TBoldObjectList; i: Integer; + Locator: TBoldObjectLocator; + FetchIdList: TBoldObjectIdList; begin if Condition.classtype = TBoldConditionWithClass then begin anObjectList := BoldSystem.Classes[TBoldConditionWithClass(condition).TopSortedIndex]; for i := 0 to anObjectList.Count - 1 do ObjectIdList.Add(TBoldIdLocatorMapping(fMapping).EnsuredIdByLocator(anObjectList.locators[i])); + end + else + begin + FetchIdList := TBoldObjectIdList.Create; + try + BoldSystem.PersistenceController.PMFetchIDListWithCondition(FetchIdList, BoldSystem.AsIBoldvalueSpace[bdepPMIn], FetchMode, Condition, BoldClientId); + for i := 0 to FetchIdList.Count - 1 do + begin + Locator := BoldSystem.EnsuredLocatorByID[FetchIdList[i]]; + Assert(Assigned(Locator)); + ObjectIdList.Add(TBoldIdLocatorMapping(fMapping).EnsuredIdByLocator(Locator)); + ValueSpace.EnsuredObjectContentsByObjectId[ObjectIdList[i]]; + end; + Assert(FetchIdList.Count = ObjectIdList.Count); + finally + FetchIdList.free; + end; end; end; @@ -319,7 +530,7 @@ procedure TBoldPersistenceControllerSystem.PMUpdate( ObjectIdList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; Old_Values: IBoldValueSpace; Precondition: TBoldUpdatePrecondition; TranslationList: TBoldIdTranslationList; - var TimeStamp: TBoldTimeStampType; BoldClientID: TBoldClientID); + var TimeStamp: TBoldTimeStampType; var TimeOfLatestUpdate: TDateTime; BoldClientID: TBoldClientID); procedure CopyValue(Value: IBoldValue; Member: TBoldMember); var @@ -337,7 +548,7 @@ procedure TBoldPersistenceControllerSystem.PMUpdate( TBoldObjectReference(Member).Locator := nil; end else - Member.AsIBoldValue[bdRemove].AssignContent(Value); { TODO : Check } + Member.AsIBoldValue[bdRemove].AssignContent(Value); end; var @@ -348,12 +559,23 @@ procedure TBoldPersistenceControllerSystem.PMUpdate( aClassName: string; NewId: TBoldObjectId; anObjectContents: IBoldObjectContents; + anOldObjectContents: IBoldObjectContents; aMember: TBoldMember; aValue: IBoldValue; OwnsTransList: Boolean; begin - // TODO: Support Preconditions. - + if BoldSystem.IsProcessingTransactionOrUpdatingDatabase then + raise EBold.Create('Destination BoldSystem IsProcessingTransactionOrUpdatingDatabase.'); + if BoldSystem.InTransaction then + raise EBold.Create('Destination BoldSystem InTransaction.'); + + if assigned(Precondition) then + begin // TODO: Implement + if Precondition is TBoldOptimisticLockingPrecondition then +// if not EnsurePrecondition(Precondition, translationList) then +// exit; + end; + TimeOfLatestUpdate := now; if not assigned(TranslationList) then begin TranslationList := TBoldIDTranslationList.Create; @@ -362,53 +584,68 @@ procedure TBoldPersistenceControllerSystem.PMUpdate( else OwnsTransList := False; - for i := 0 to ObjectIdList.Count - 1 do - begin - anId := ObjectIdList[i]; - if not anId.IsStorable then - begin - aClassName := BoldSystem.BoldSystemTypeInfo.TopSortedClasses[anId.TopSortedIndex].ExpressionName; - anObject := BoldSystem.CreateNewObjectByExpressionName(aClassName); - NewId := TBoldIdLocatorMapping(fMapping).EnsuredIdByLocator(anObject.BoldObjectLocator); - TranslationList.AddTranslation(anId, NewId); - end else + BoldSystem.StartTransaction(); + try + for i := 0 to ObjectIdList.Count - 1 do begin - aLocator := TBoldIdLocatorMapping(fMapping).LocatorById[anId]; - if assigned(aLocator) then - anObject := aLocator.BoldObject - else - anObject := nil; - end; + anId := ObjectIdList[i]; + if not anId.IsStorable then + begin + aClassName := BoldSystem.BoldSystemTypeInfo.TopSortedClasses[anId.TopSortedIndex].ExpressionName; + anObject := BoldSystem.CreateNewObjectByExpressionName(aClassName); + NewId := TBoldIdLocatorMapping(fMapping).EnsuredIdByLocator(anObject.BoldObjectLocator); + TranslationList.AddTranslation(anId, NewId); + end else + begin + aLocator := TBoldIdLocatorMapping(fMapping).LocatorById[anId]; + if assigned(aLocator) then + anObject := aLocator.BoldObject + else + anObject := nil; // means object is deleted in destination system + end; - if assigned(anObject) then - begin - anObjectContents := ValueSpace.EnsuredObjectContentsByObjectId[anId]; - if anObjectContents.BoldExistenceState = besDeleted then - anObject.Delete - else + if assigned(anObject) then begin - for j := 0 to anObject.BoldMemberCount - 1 do + anOldObjectContents := Old_Values.ObjectContentsByObjectId[anId]; + if Assigned(anOldObjectContents) and (anObject.AsIBoldObjectContents[bdepPMIn].TimeStamp <> anOldObjectContents.TimeStamp) then begin - aMember := anObject.BoldMembers[j]; - aValue := anObjectContents.ValueByIndex[j]; - if aMember.BoldMemberRTInfo.Persistent and aMember.BoldMemberRTInfo.IsStoredInObject and - assigned(aValue) and ((aValue.BoldPersistenceState = bvpsModified) or BoldSystem.BoldSystemTypeInfo.UpdateWholeObjects) then - CopyValue(aValue, aMember); + BoldLog.LogFmt('Optimistic Locking TimeStamp failed for %.', [ + anObject.DisplayName]); + raise EBold.CreateFmt('Optimistic Locking failed for object:%s.', [anObject.DisplayName]); + end; + anObjectContents := ValueSpace.EnsuredObjectContentsByObjectId[anId]; + if anObjectContents.BoldExistenceState = besDeleted then + anObject.Delete + else + begin + for j := 0 to anObject.BoldMemberCount - 1 do + begin + aMember := anObject.BoldMembers[j]; + aValue := anObjectContents.ValueByIndex[j]; + if Assigned(anOldObjectContents) and Assigned(anOldObjectContents.ValueByIndex[j]) and not aMember.IsEqualToValue(anOldObjectContents.ValueByIndex[j]) then + raise EBold.CreateFmt('Optimistic Locking failed for member %s.', [aMember.DisplayName]); + if aMember.BoldMemberRTInfo.Persistent and aMember.BoldMemberRTInfo.IsStoredInObject and + assigned(aValue) and ((aValue.BoldPersistenceState = bvpsModified) or BoldSystem.BoldSystemTypeInfo.UpdateWholeObjects) then + CopyValue(aValue, aMember); + end; end; end; end; - end; - ValueSpace.ApplytranslationList(TranslationList); + ValueSpace.ApplytranslationList(TranslationList); - if OwnsTransList then - TranslationList.Free; + if OwnsTransList then + TranslationList.Free; + BoldSystem.CommitTransaction(); + except + BoldSystem.RollbackTransaction(); + raise; + end; end; procedure TBoldPersistenceControllerSystem.ReserveNewIds(ValueSpace: IBoldValueSpace; ObjectIdList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList); begin - // do nothing, but implementation needed, as method is abstract in superclass end; procedure TBoldPersistenceControllerSystem.SetBoldSystem(System: TBoldSystem); @@ -431,146 +668,5 @@ procedure TBoldPersistenceControllerSystem._LocatorDestroyedReceived( TBoldIdLocatorMapping(fMapping).RemoveByLocator((Args[0].VObject as TBoldObject).BoldObjectLocator); end; -{ TBoldIdLocatorMapping } - -procedure TBoldIdLocatorMapping.AddPair(Id: TBoldObjectId; Locator: TBoldObjectLocator); -begin - Add(TBoldIdLocatorPair.Create(Id, Locator)); -end; - -constructor TBoldIdLocatorMapping.Create; -begin - inherited; - SetIndexVariable(IX_MappingIdIndex, AddIndex(TBoldMappingIdIndex.Create)); - SetIndexVariable(IX_MappingLocatorIndex, AddIndex(TBoldMappingLocatorIndex.Create)); - fNextId := 1; -end; - -function TBoldIdLocatorMapping.EnsuredIdByLocator( - Locator: TBoldObjectLocator): TBoldObjectId; -var - NewId: TBoldDefaultId; -begin - if not assigned(Locator) then - result := nil - else - begin - result := IdByLocator[Locator]; - if not assigned(result) then - begin - NewId := TBoldDefaultId.CreateWithClassID(Locator.BoldObjectID.TopSortedIndex, Locator.BoldObjectID.TopSortedIndexExact); - NewId.AsInteger := fNextId; - inc(fNextId); - AddPair(NewId, Locator); - NewId.Free; - result := IdByLocator[Locator]; - end; - end; -end; - -procedure TBoldIdLocatorMapping.ExactifyClassForLocator( - Locator: TBoldObjectLocator; ExactClassId: Integer); -var - NewId: TBoldObjectId; - aPair: TBoldIdLocatorPair; -begin - aPair := GetPairByLocator(Locator); - NewId := aPair.fId.CloneWithClassId(ExactClassId, True); - aPair.fId.Free; - aPair.fId := NewId; -end; - -function TBoldIdLocatorMapping.GetIdByLocator(Locator: TBoldObjectLocator): TBoldObjectId; -var - aPair: TBoldIdLocatorPair; -begin - aPair := GetPairByLocator(Locator); - if assigned(aPair) then - result := aPair.fId - else - result := nil; -end; - -function TBoldIdLocatorMapping.GetLocatorById( - ID: TBoldObjectId): TBoldObjectLocator; -var - aPair: TBoldIdLocatorPair; -begin - aPair := TBoldIdLocatorPair(Indexes[IX_MappingIdIndex].Find(Id)); - if assigned(aPair) then - result := aPair.fLocator - else - result := nil; -end; - -function TBoldIdLocatorMapping.GetPairByLocator( - Locator: TBoldObjectLocator): TBoldIdLocatorPair; -begin - result := TBoldIdLocatorPair(Indexes[IX_MappingLocatorIndex].Find(Locator)); -end; - -procedure TBoldIdLocatorMapping.RemoveByLocator( - Locator: TBoldObjectLocator); -var - aPair: TBoldIdLocatorPair; -begin - aPair := GetPairByLocator(Locator); - if assigned(aPair) then - Remove(aPair); -end; - -{ TBoldMappingIdIndex } - -function TBoldMappingIdIndex.Hash(const Key): Cardinal; -begin - Assert(TObject(Key) is TBoldObjectId); - Result := TBoldObjectId(Key).Hash; -end; - -function TBoldMappingIdIndex.HashItem(Item: TObject): Cardinal; -begin - result := (Item as TBoldIdLocatorPair).fId.Hash; -end; - -function TBoldMappingIdIndex.Match(const Key; Item: TObject): Boolean; -begin - Assert(TObject(Key) is TBoldObjectId); - result := TBoldObjectId(Key).IsEqual[TBoldIdLocatorPair(Item).fId]; -end; - -{ TBoldMappingLocatorIndex } - -function TBoldMappingLocatorIndex.Hash(const Key): Cardinal; -begin - Assert(TObject(Key) is TBoldObjectLocator); - Result := TBoldObjectLocator(Key).Hash; -end; - -function TBoldMappingLocatorIndex.HashItem(Item: TObject): Cardinal; -begin - result := (Item as TBoldIdLocatorPair).fLocator.Hash; -end; - -function TBoldMappingLocatorIndex.Match(const Key; Item:TObject): Boolean; -begin - Assert(TObject(Key) is TBoldObjectLocator); - Assert(Item is TBoldIdLocatorPair); - result := TBoldObjectLocator(Key) = TBoldIdLocatorPair(Item).fLocator; -end; - -{ TBoldIdLocatorPair } - -constructor TBoldIdLocatorPair.Create(Id: TBoldObjectId; - Locator: TBoldObjectLocator); -begin - fLocator := Locator; - fId := Id.Clone; -end; - -destructor TBoldIdLocatorPair.Destroy; -begin - FreeAndNil(fId); - inherited; -end; - +initialization end. diff --git a/Source/Persistence/System/BoldPersistenceHandleSystem.pas b/Source/Persistence/System/BoldPersistenceHandleSystem.pas index 25db9a0..a111411 100644 --- a/Source/Persistence/System/BoldPersistenceHandleSystem.pas +++ b/Source/Persistence/System/BoldPersistenceHandleSystem.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldPersistenceHandleSystem; interface @@ -6,24 +9,38 @@ interface BoldSystemhandle, BoldPersistenceController, BoldPersistenceControllerSystem, - BoldPersistenceHandle; + BoldPersistenceHandle, + BoldSubscription; type TBoldPersistenceHandleSystem = class(TBoldPersistenceHandle) private fSystemHandle: TBoldSystemHandle; + fSystemHandleSubscriber: TBoldPassthroughSubscriber; function GetPersistenceControllerSystem: TBoldPersistenceControllerSystem; + procedure SetSystemHandle(const Value: TBoldSystemHandle); + procedure PlaceSubscriptions; + function GetSubscriber: TBoldSubscriber; + procedure ReceiveFromSystemHandle(Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent); protected function CreatePersistenceController: TBoldPersistenceController; override; procedure SetActive(Value: Boolean); override; + property Subscriber: TBoldSubscriber read GetSubscriber; public + destructor Destroy; override; property PersistenceControllerSystem: TBoldPersistenceControllerSystem read GetPersistenceControllerSystem; published - property SystemHandle: TBoldSystemHandle read fSystemHandle write fSystemHandle; + property SystemHandle: TBoldSystemHandle read fSystemHandle write SetSystemHandle; end; implementation +uses + SysUtils, + BoldHandles, + + BoldRev; + { TBoldPersistenceHandleSystem } function TBoldPersistenceHandleSystem.CreatePersistenceController: TBoldPersistenceController; @@ -31,11 +48,44 @@ function TBoldPersistenceHandleSystem.CreatePersistenceController: TBoldPersiste result := TBoldPersistenceControllerSystem.Create; end; +destructor TBoldPersistenceHandleSystem.Destroy; +begin + FreeAndNil(fSystemHandleSubscriber); + inherited; +end; + function TBoldPersistenceHandleSystem.GetPersistenceControllerSystem: TBoldPersistenceControllerSystem; begin result := PersistenceController as TBoldPersistenceControllerSystem; end; +function TBoldPersistenceHandleSystem.GetSubscriber: TBoldSubscriber; +begin + if not Assigned(fSystemHandleSubscriber) then + fSystemHandleSubscriber := TBoldPassthroughSubscriber.Create(ReceiveFromSystemHandle); + result := fSystemHandleSubscriber; +end; + +procedure TBoldPersistenceHandleSystem.PlaceSubscriptions; +begin + Subscriber.CancelAllSubscriptions; + if Assigned(SystemHandle) then + begin + SystemHandle.AddSmallSubscription(Subscriber, [beDestroying], beDestroying); + SystemHandle.AddSmallSubscription(Subscriber, [beValueIdentityChanged], beValueIdentityChanged); + end; +end; + +procedure TBoldPersistenceHandleSystem.ReceiveFromSystemHandle( + Originator: TObject; OriginalEvent: TBoldEvent; + RequestedEvent: TBoldRequestedEvent); +begin + case RequestedEvent of + beDestroying: SystemHandle := nil; + beValueIdentityChanged: PersistenceControllerSystem.BoldSystem := fSystemHandle.System; + end; +end; + procedure TBoldPersistenceHandleSystem.SetActive(Value: Boolean); begin if value <> Active then begin @@ -45,4 +95,19 @@ procedure TBoldPersistenceHandleSystem.SetActive(Value: Boolean); inherited; end; +procedure TBoldPersistenceHandleSystem.SetSystemHandle( + const Value: TBoldSystemHandle); +begin + if Value = fSystemHandle then + exit; + fSystemHandle := Value; + if Assigned(Value) then + PersistenceControllerSystem.BoldSystem := Value.System + else + PersistenceControllerSystem.BoldSystem := nil; + PlaceSubscriptions; +end; + +initialization + end. diff --git a/Source/Persistence/UDPPropagator/BoldAbstractModificationPropagator.pas b/Source/Persistence/UDPPropagator/BoldAbstractModificationPropagator.pas index b46aa38..391255d 100644 --- a/Source/Persistence/UDPPropagator/BoldAbstractModificationPropagator.pas +++ b/Source/Persistence/UDPPropagator/BoldAbstractModificationPropagator.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldAbstractModificationPropagator; interface @@ -22,7 +25,7 @@ interface BoldThreadSafeQueue; type - TReceivePropagatorEvent = procedure(Sender: TObject; Event: String) of object; + TReceivePropagatorEvent = procedure(Sender: TObject; const Event: String) of object; { Forward declaration } TBoldAbstractNotificationPropagator = class; @@ -35,7 +38,7 @@ TBoldNotificationPropagatorPersistenceControllerPassthrough = class(TBoldAbstr fClientId: TBoldClientid; public constructor Create(MoldModel: TMoldModel; ClientId: TBoldClientId); - procedure PMUpdate(ObjectIdList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; Old_Values: IBoldValueSpace; Precondition: TBoldUpdatePrecondition; TranslationList: TBoldIdTranslationList; var TimeStamp: TBoldTimeStampType; BoldClientID: TBoldClientID); override; + procedure PMUpdate(ObjectIdList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; Old_Values: IBoldValueSpace; Precondition: TBoldUpdatePrecondition; TranslationList: TBoldIdTranslationList; var TimeStamp: TBoldTimeStampType; var TimeOfLatestUpdate: TDateTime; BoldClientID: TBoldClientID); override; procedure TransmitEvents(const ClientID: TBoldClientID); override; property BoldNotificationPropagator: TBoldAbstractNotificationPropagator read FBoldNotificationPropagator write FBoldNotificationPropagator; property ClientId: TBoldClientId read fClientId; @@ -54,9 +57,10 @@ TBoldAbstractNotificationPropagator = class(TBoldPersistenceHandlePassthrough) function GetController: TBoldNotificationPropagatorPersistenceControllerPassthrough; protected { Puts one event in the out-queue } - procedure EnqueEvent(Event: String); + procedure EnqueEvent(const Event: String); + procedure EnqueEventList(const aEventList: TStrings); { Decodes and enques a received event from the in-queue } - procedure ReceiveEvent(Event: String); virtual; + procedure ReceiveEvent(const Event: String); virtual; procedure OnReceiveQueueNotEmpty(Sender: TBoldThreadSafeQueue); virtual; { The following method must be overridden in the inheriting classes } @@ -91,14 +95,14 @@ constructor TBoldAbstractNotificationPropagator.Create(AOwner: TComponent); begin inherited; - FReceiveQueue := TBoldThreadSafeStringQueue.Create('NotificationPropagator/Receive'); // do not localize + FReceiveQueue := TBoldThreadSafeStringQueue.Create('NotificationPropagator/Receive'); FReceiveQueue.OnQueueNotEmpty := OnReceiveQueueNotEmpty; - FSendQueue := TBoldThreadSafeStringQueue.Create('NotificationPropagator/Send'); // do not localize + FSendQueue := TBoldThreadSafeStringQueue.Create('NotificationPropagator/Send'); FSendQueue.OnQueueNotEmpty := OnSendQueueNotEmpty; - FRefreshQueue := TBoldThreadSafeStringQueue.Create('NotificationPropagator/Refresh'); // do not localize - fClientId := 0; // Do we need unique clientIds for any reason? + FRefreshQueue := TBoldThreadSafeStringQueue.Create('NotificationPropagator/Refresh'); + fClientId := 0; end; destructor TBoldAbstractNotificationPropagator.Destroy; @@ -116,13 +120,19 @@ destructor TBoldAbstractNotificationPropagator.Destroy; end; { Put a single event in the out-queue } -procedure TBoldAbstractNotificationPropagator.EnqueEvent(Event: String); +procedure TBoldAbstractNotificationPropagator.EnqueEvent(const Event: String); begin FSendQueue.Enqueue(Event); end; +procedure TBoldAbstractNotificationPropagator.EnqueEventList( + const aEventList: TStrings); +begin + FSendQueue.EnqueueList(aEventList); +end; + { Decodes and deques a single event } -procedure TBoldAbstractNotificationPropagator.ReceiveEvent(Event: String); +procedure TBoldAbstractNotificationPropagator.ReceiveEvent(const Event: String); var AClassName, AMemberName, ALockName: String; begin @@ -135,8 +145,6 @@ procedure TBoldAbstractNotificationPropagator.ReceiveEvent(Event: String); if TBoldObjectSpaceExternalEvent.DecodeExternalEvent(Event, AClassName, AMemberName, ALockName, nil) in [bsClassChanged] then FRefreshQueue.Enqueue(AClassName); - - //FRefreshQueue.Enqueue(Event); end; if Assigned(FOnReceiveEvent) then @@ -164,6 +172,7 @@ function TBoldAbstractNotificationPropagator.CreatePersistenceController: TBoldP Result := TempController; end; + function TBoldAbstractNotificationPropagator.GetController: TBoldNotificationPropagatorPersistenceControllerPassthrough; begin result := PersistenceController as TBoldNotificationPropagatorPersistenceControllerPassthrough; @@ -181,17 +190,19 @@ procedure TBoldNotificationPropagatorPersistenceControllerPassthrough.PMUpdate( ObjectIdList: TBoldObjectIdList; ValueSpace, Old_Values: IBoldValueSpace; Precondition: TBoldUpdatePrecondition; TranslationList: TBoldIdTranslationList; - var TimeStamp: TBoldTimeStampType; BoldClientID: TBoldClientID); + var TimeStamp: TBoldTimeStampType; var TimeOfLatestUpdate: TDateTime; BoldClientID: TBoldClientID); begin - inherited PMUpdate(ObjectIdList, valueSpace, Old_Values, PreCondition, TranslationList, TimeStamp, ClientId); + inherited PMUpdate(ObjectIdList, valueSpace, Old_Values, PreCondition, TranslationList, TimeStamp, TimeOfLatestUpdate, ClientId); end; procedure TBoldNotificationPropagatorPersistenceControllerPassthrough.TransmitEvents(const ClientID: TBoldClientID); -var - i: integer; begin - for i := 0 to Events.Count-1 do - BoldNotificationPropagator.EnqueEvent(Events[i]); + try + BoldNotificationPropagator.EnqueEventList(Events); + finally + ClearEvents; + end; end; +initialization end. diff --git a/Source/Persistence/UDPPropagator/BoldUDPModificationBroadcaster.pas b/Source/Persistence/UDPPropagator/BoldUDPModificationBroadcaster.pas index 688b859..c721e23 100644 --- a/Source/Persistence/UDPPropagator/BoldUDPModificationBroadcaster.pas +++ b/Source/Persistence/UDPPropagator/BoldUDPModificationBroadcaster.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldUDPModificationBroadcaster; interface @@ -41,7 +44,6 @@ TBoldUDPModificationBroadcaster = class(TBoldAbstractNotificationPropagator) published property Port: Integer read GetPort write SetPort; property OnActivationError: TActivationErrorEvent read FOnActivationError write FOnActivationError; - // inherited properties {$IFNDEF T2H} property NextPersistenceHandle; property Active; @@ -68,9 +70,9 @@ constructor TBoldUDPModificationBroadcaster.Create(AOwner: TComponent); fUDPClient := TIdUDPClient.Create(Self); fUDPServer := TIdUDPServer.Create(Self); fUDPClient.BroadcastEnabled := True; - fUDPServer.OnUDPRead := InternalUDPRead; + fUDPServer.OnUDPRead := InternalUDPRead; //Fix - fUDPClient.Host := '255.255.255.255'; // do not localize + fUDPClient.Host := '255.255.255.255'; fUDPClient.Port := 4098; fUDPServer.DefaultPort := 4098; @@ -142,7 +144,7 @@ procedure TBoldUDPModificationBroadcaster.OnSendQueueNotEmpty(Sender: TBoldThrea BoldEffectiveEnvironment.ProcessMessages; while not SendQueue.Empty do - fUDPClient.Send('255.255.255.255', // do not localize + fUDPClient.Send('255.255.255.255', fUDPClient.Port, SIdentification + SendQueue.Dequeue); end; diff --git a/Source/Persistence/UniDAC/BoldDatabaseAdapterUniDAC.pas b/Source/Persistence/UniDAC/BoldDatabaseAdapterUniDAC.pas new file mode 100644 index 0000000..1e03ccf --- /dev/null +++ b/Source/Persistence/UniDAC/BoldDatabaseAdapterUniDAC.pas @@ -0,0 +1,89 @@ +{ Global compiler directives } +{$include bold.inc} +unit BoldDatabaseAdapterUniDAC; + +interface + +uses + Classes, + BoldAbstractDataBaseAdapter, + BoldDBInterfaces, + BoldUniDACInterfaces, + Uni; + +type + { forward declarations } + TBoldDatabaseAdapterUniDAC = class; + + { TBoldDatabaseAdapterUniDAC } + TBoldDatabaseAdapterUniDAC = class(TBoldAbstractDatabaseAdapter) + private + fBoldUniDACConnection: TBoldUniDACConnection; + procedure SetConnection(const Value: TUniConnection); + function GetConnection: TUniConnection; + protected + procedure ReleaseBoldDatabase; override; + function GetDataBaseInterface: IBoldDatabase; override; + public + destructor Destroy; override; + procedure CreateDatabase; override; + published + property Connection: TUniConnection read GetConnection write SetConnection; + {$IFNDEF T2H} + property DatabaseEngine; + {$ENDIF} + end; + +implementation + +uses + BoldSQLDatabaseConfig, + SysUtils, + BoldDefs, + UniDACConsts; + +{ TBoldDatabaseAdapterUniDAC } + +destructor TBoldDatabaseAdapterUniDAC.Destroy; +begin + Changed; + FreePublisher; + FreeAndNil(fBoldUniDACConnection); + inherited; +end; + +procedure TBoldDatabaseAdapterUniDAC.CreateDatabase; +begin + DatabaseInterface.CreateDatabase; +end; + +function TBoldDatabaseAdapterUniDAC.GetConnection: TUniConnection; +begin + Result := InternalDatabase as TUniConnection; +end; + +function TBoldDatabaseAdapterUniDAC.GetDataBaseInterface: IBoldDatabase; +begin + if not Assigned(Connection) then + begin + raise EBold.CreateFmt(sAdapterNotConnected, [ClassName]); + end; + if not Assigned(fBoldUniDACConnection) then + begin + fBoldUniDACConnection := TBoldUniDACConnection.Create(Connection, SQLDataBaseConfig); + end; + Result := fBoldUniDACConnection; +end; + +procedure TBoldDatabaseAdapterUniDAC.ReleaseBoldDatabase; +begin + FreeAndNil(fBoldUniDACConnection); +end; + +procedure TBoldDatabaseAdapterUniDAC.SetConnection(const Value: TUniConnection); +begin + InternalDatabase := Value; +end; + +end. + diff --git a/Source/Persistence/UniDAC/BoldPersistenceHandleUniDAC.pas b/Source/Persistence/UniDAC/BoldPersistenceHandleUniDAC.pas new file mode 100644 index 0000000..8189003 --- /dev/null +++ b/Source/Persistence/UniDAC/BoldPersistenceHandleUniDAC.pas @@ -0,0 +1,333 @@ +{ Global compiler directives } +{$include bold.inc} +unit BoldPersistenceHandleUniDAC; + +interface + +uses + Classes, + DBAccess, + Uni, +// UniProvider, + Dialogs, + BoldDBInterfaces, + BoldUniDACInterfaces, + BoldPersistenceHandleDB, + BoldPersistenceHandleDB_deprecated; + +type + TBoldNetWorkProtocol = (bnwpLocal, bnwpTcpIP, bnwpNetBEUI, bnwpNovellSPX); + + TBoldPersistenceHandleUniDAC = class(TBoldDBPersistenceHandle) + private + fUniConnection: TUniConnection; + fOwnConnection: TUniConnection; + fConnectionAdapter: TBoldUniDACConnection; + fDataSource: string; + fProvider: string; + fPersistSecurityInfo: Boolean; + fNetWorkProtocol: TBoldNetWorkProtocol; + fHostName: string; + fInitialCatalog: string; + fExtendedProperties: TStringList; + procedure SetDataSource(const Value: string); + procedure SetProvider(const Value: string); + procedure SetPersistSecurityInfo(const Value: Boolean); + procedure SetNetWorkProtocol(const Value: TBoldNetWorkProtocol); + procedure SetHostName(const Value: string); + procedure SetInitialCatalog(const Value: string); + procedure SetExtendedProperties(const Value: TStringList); + procedure SetUniConnection(const Value: TUniConnection); + function getEffectiveConnection: TUniConnection; + protected + procedure AddExtendedProperties(Result: TStrings); virtual; + procedure UpdateInternalConnectionString; virtual; + procedure Notification(AComponent: TComponent; Operation: TOperation); override; + property EffectiveConnection: TUniConnection read getEffectiveConnection; + procedure SetPassword(const Value: string); override; + procedure SetUserName(const Value: string); override; + {$IFNDEF T2H} + procedure InternalTransferproperties(const target: TBoldPersistenceHandleDB); override; + {$ENDIF} + public + constructor Create(owner: TComponent); override; + destructor Destroy; override; + function GetDataBaseInterface: IBoldDatabase; override; + procedure Assign(Source: TPersistent); override; + published + property DataSource: string read FDataSource write SetDataSource; + property Provider: string read FProvider write SetProvider; + property PersistSecurityInfo: Boolean read FPersistSecurityInfo write SetPersistSecurityInfo; + property NetWorkProtocol: TBoldNetWorkProtocol read FNetWorkProtocol write SetNetWorkProtocol; + property HostName: string read FHostName write SetHostName; + property InitialCatalog: string read FInitialCatalog write SetInitialCatalog; + property ExtendedProperties: TStringList read fExtendedProperties write SetExtendedProperties; + property UniConnection: TUniConnection read fUniConnection write SetUniConnection; + end deprecated; + +const + BoldNetWorkProtocolStringRep: array[TBoldNetWorkProtocol] of string = ('', 'tcpip', 'netbeui', 'spx'); + +function BoldStringToNetworkProtocol(s: string): TBoldNetWorkProtocol; + +implementation + +uses + SysUtils, + BoldDefs, + BoldDatabaseAdapterUniDAC, + BoldUtils, + UniDACConsts; + +function BoldStringToNetworkProtocol(s: string): TBoldNetWorkProtocol; +var + i: TBoldNetWorkProtocol; +begin + for i := low(BoldNetWorkProtocolStringRep) to high(BoldNetWorkProtocolStringRep) do + if CompareText(s, BoldNetWorkProtocolStringRep[i]) = 0 then + begin + Result := i; + exit; + end; + + Result := bnwpLocal; +end; + +{ TBoldPersistenceHandleUniDAC } + +procedure TBoldPersistenceHandleUniDAC.AddExtendedProperties( + Result: TStrings); +begin + if trim(DataSource) <> '' then + Result.Add('DSN=' + trim(DataSource)); // do not localize + if trim(HostName) <> '' then + Result.Add('Hostname=' + trim(HostName)); // do not localize + if trim(InitialCatalog) <> '' then + Result.Add('Initial Catalog=' + trim(InitialCatalog)); // do not localize + + Result.Add('NetworkProt=' + BoldNetWorkProtocolStringRep[NetWorkProtocol]); // do not localize + + Result.AddStrings(ExtendedProperties); +end; + +procedure TBoldPersistenceHandleUniDAC.Assign(Source: TPersistent); +begin + inherited; + if Source is TBoldPersistenceHandleUniDAC then + ExtendedProperties.Assign((Source as TBoldPersistenceHandleUniDAC).ExtendedProperties); +end; + +procedure TBoldPersistenceHandleUniDAC.UpdateInternalConnectionString; +const + BoolToStr: array[Boolean] of string = ('false', 'true'); +var + LExtendedProperties: TStringList; + ConnectionString: string; +begin + if Assigned(fOwnConnection) then + begin + LExtendedProperties := TStringList.Create; + AddExtendedProperties(LExtendedProperties); + + ConnectionString := format('Provider=%s;Persist Security Info=%s;Data Source=%s;Extended Properties=%s', // do not localize + [Provider, + BoolToStr[PersistSecurityInfo], + DataSource, + BoldSeparateStringList(LExtendedProperties, ';', '"', '"')]); + LExtendedProperties.Free; + fOwnConnection.ConnectString := ConnectionString; + end; +end; + +constructor TBoldPersistenceHandleUniDAC.Create(owner: TComponent); +begin + inherited; + FHostName := ''; // do not localize + fExtendedProperties := TStringList.Create; +end; + +destructor TBoldPersistenceHandleUniDAC.Destroy; +begin + Active := False; + FreeAndNil(fOwnConnection); + FreeAndNil(fConnectionAdapter); + inherited; +end; + +procedure TBoldPersistenceHandleUniDAC.SetUniConnection( + const Value: TUniConnection); +begin + if fUniConnection <> Value then + begin + CheckInactive('SetDataBase'); // do not localize + if Assigned(fOwnConnection) then + begin + FreeAndNil(fOwnConnection); + FreeAndNil(fConnectionAdapter); + end; + fUniConnection := Value; + if Assigned(fUniConnection) then + fUniConnection.FreeNotification(Self); + end; +end; + +procedure TBoldPersistenceHandleUniDAC.SetDataSource(const Value: string); +begin + FDataSource := Value; + UpdateInternalConnectionString; +end; + +procedure TBoldPersistenceHandleUniDAC.SetExtendedProperties( + const Value: TStringList); +begin + fExtendedProperties.Assign(Value); + UpdateInternalConnectionString; +end; + +procedure TBoldPersistenceHandleUniDAC.SetHostName(const Value: string); +begin + FHostName := Value; + if trim(FHostName) = '' then + FHostName := ''; // do not localize + UpdateInternalConnectionString; +end; + +procedure TBoldPersistenceHandleUniDAC.SetInitialCatalog(const Value: string); +begin + FInitialCatalog := Value; + UpdateInternalConnectionString; +end; + +procedure TBoldPersistenceHandleUniDAC.SetNetWorkProtocol( + const Value: TBoldNetWorkProtocol); +begin + FNetWorkProtocol := Value; + UpdateInternalConnectionString; +end; + +procedure TBoldPersistenceHandleUniDAC.SetPersistSecurityInfo( + const Value: Boolean); +begin + FPersistSecurityInfo := Value; + UpdateInternalConnectionString; +end; + +procedure TBoldPersistenceHandleUniDAC.SetProvider(const Value: string); +begin + FProvider := Value; + UpdateInternalConnectionString; +end; + +procedure TBoldPersistenceHandleUniDAC.Notification(AComponent: TComponent; + Operation: TOperation); +begin + inherited; + if (AComponent = fUniConnection) and (Operation = opRemove) then + begin + if AComponent = EffectiveConnection then + begin + Active := False; + fConnectionAdapter := nil; + end; + fUniConnection := nil; + end; +end; + +function TBoldPersistenceHandleUniDAC.getEffectiveConnection: TUniConnection; +begin + if Assigned(fUniConnection) then + Result := fUniConnection + else + begin + if not Assigned(fOwnConnection) then + begin + fOwnConnection := TUniConnection.Create(nil); + UpdateInternalConnectionString; + end; + Result := fOwnConnection; + end; +end; + +procedure TBoldPersistenceHandleUniDAC.SetPassword(const Value: string); +begin + inherited; + UpdateInternalConnectionString; +end; + +procedure TBoldPersistenceHandleUniDAC.SetUserName(const Value: string); +begin + inherited; + UpdateInternalConnectionString; +end; + +function TBoldPersistenceHandleUniDAC.GetDataBaseInterface: IBoldDatabase; +begin + if not Assigned(fConnectionAdapter) then + fConnectionAdapter := TBoldUniDACConnection.Create(EffectiveConnection, SQLDataBaseConfig); + Result := fConnectionAdapter; +end; + +procedure TBoldPersistenceHandleUniDAC.InternalTransferproperties( + const target: TBoldPersistenceHandleDB); +const + BoolToStr: array[Boolean] of string = ('false', 'true'); +var + Adapter: tBoldDatabaseAdapterUniDAC; + DesInfo: longint; + LExtendedProperties: TStringList; + ConnectionString: string; +begin + inherited; + DesInfo := target.DesignInfo; + if not Assigned(target.DatabaseAdapter) then + begin + target.DatabaseAdapter := tBoldDatabaseAdapterUniDAC.Create(target.owner); + target.DatabaseAdapter.Name := GetNewComponentName(target.DatabaseAdapter, 'BoldDatabaseAdapterUniDAC'); // do not localize + LongRec(DesInfo).Lo := LongRec(DesInfo).Lo + 16; //set Left + LongRec(DesInfo).Hi := LongRec(DesInfo).Hi + 16; //Set Top; + target.DatabaseAdapter.DesignInfo := DesInfo; + showmessage(sCreatedNewAdapter); + end + else if not (target.DatabaseAdapter is tBoldDatabaseAdapterUniDAC) then + raise Exception.CreateFmt(sCanOnlyTransferToUniDACAdapter, [target.DatabaseAdapter.ClassName]); + + Adapter := target.DatabaseAdapter as TBoldDatabaseAdapterUniDAC; + if Assigned(fUniConnection) then + Adapter.Connection := UniConnection; + + if not Assigned(Adapter.Connection) then + begin + Adapter.Connection := TUniConnection.Create(target.owner); + Adapter.Connection.Name := GetNewComponentName(Adapter.Connection, 'UniDACDatabase'); // do not localize + showmessage(sCreatedNewDB); + LongRec(DesInfo).Lo := LongRec(DesInfo).Lo + 16; //set Left + LongRec(DesInfo).Hi := LongRec(DesInfo).Hi + 16; //Set Top; + Adapter.Connection.DesignInfo := DesInfo; + + try + LExtendedProperties := TStringList.Create; + AddExtendedProperties(LExtendedProperties); + + ConnectionString := format('Provider=%s;Persist Security Info=%s;Data Source=%s;Extended Properties=%s', // do not localize + [Provider, + BoolToStr[PersistSecurityInfo], + DataSource, + BoldSeparateStringList(LExtendedProperties, ';', '"', '"')]); + LExtendedProperties.Free; + Adapter.Connection.ConnectString := ConnectionString; + except + on E: Exception do + begin + showmessage(sCouldNotTransferConnectionString + BOLDCRLF + BOLDCRLF + + E.Message + BOLDCRLF + BOLDCRLF + + sTransferManually); + Adapter.Connection.ConnectString := ''; + + end; + end; + + end; +end; + +end. + diff --git a/Source/Persistence/UniDAC/BoldPersistenceHandleUniDACReg.pas b/Source/Persistence/UniDAC/BoldPersistenceHandleUniDACReg.pas new file mode 100644 index 0000000..176a25c --- /dev/null +++ b/Source/Persistence/UniDAC/BoldPersistenceHandleUniDACReg.pas @@ -0,0 +1,28 @@ +{ Global compiler directives } +{$include bold.inc} +unit BoldPersistenceHandleUniDACReg; + +interface + +procedure Register; + +implementation + +//{$R BoldPersistenceHandleUniDAC.res} + +uses + SysUtils, + Classes, + BoldDatabaseAdapterUniDAC, +// BoldPersistenceHandleUniDAC, + BoldIDEConsts; + +procedure Register; +begin + {$WARNINGS OFF} +// RegisterComponents(BOLDPAGENAME_DEPRECATED, [TBoldPersistenceHandleUniDAC]); + {$WARNINGS ON} + RegisterComponents(BOLDPAGENAME_PERSISTENCE, [TBoldDatabaseAdapterUniDAC]); +end; + +end. diff --git a/Source/Persistence/UniDAC/BoldUniDACInterfaces.pas b/Source/Persistence/UniDAC/BoldUniDACInterfaces.pas new file mode 100644 index 0000000..53e72c5 --- /dev/null +++ b/Source/Persistence/UniDAC/BoldUniDACInterfaces.pas @@ -0,0 +1,1638 @@ + +///////////////////////////////////////////////////////// +// // +// Bold for Delphi // +// Copyright (c) 1996-2002 Boldsoft AB // +// (c) 2002-2005 Borland Software Corp // +// // +///////////////////////////////////////////////////////// + +{ Global compiler directives } +{$include bold.inc} +unit BoldUniDACInterfaces; + +interface + +uses + Classes, + Db, + SysUtils, + Uni, + UniProvider, + MemDS, + BoldSQLDatabaseConfig, + BoldDBInterfaces, + BoldDefs; + +type + { forward declarations } + TBoldUniDACParameter = class; + TBoldUniDACQuery = class; + TBoldUniDACTable = class; + TBoldUniDACConnection = class; + + TBoldUniDACQueryClass = class of TBoldUniDACQuery; + TBoldUniDACExecQueryClass = class of TBoldUniDACExecQuery; + + { TBoldUniDACParameter } + TBoldUniDACParameter = class(TBoldParameterWrapper, IBoldParameter) + private + fUniParam: TUniParam; + function GetAsVariant: Variant; + procedure SetAsVariant(const NewValue: Variant); + function GetName: string; + procedure Clear; + function GetDataType: TFieldType; + procedure SetDataType(Value: TFieldType); + function GetAsBCD: Currency; + function GetAsblob: TBoldBlobData; + function GetAsBoolean: Boolean; + function GetAsDateTime: TDateTime; + function GetAsCurrency: Currency; + function GetAsFloat: Double; + function GetAsInteger: Longint; + function GetAsInt64: Int64; + function GetAsMemo: string; + function GetAsString: string; + function GetIsNull: Boolean; + function GetAsWideString: WideString; + procedure SetAsBCD(const Value: Currency); + procedure SetAsBlob(const Value: TBoldBlobData); + procedure SetAsBoolean(Value: Boolean); + procedure SetAsCurrency(const Value: Currency); + procedure SetAsDate(const Value: TDateTime); + procedure SetAsDateTime(const Value: TDateTime); + procedure SetAsFloat(const Value: Double); + procedure SetAsInteger(Value: Longint); + procedure SetAsInt64(const Value: Int64); + procedure SetAsMemo(const Value: string); + procedure SetAsString(const Value: string); + procedure SetAsSmallInt(Value: Longint); + procedure SetAsTime(const Value: TDateTime); + procedure SetAsWord(Value: Longint); + procedure SetText(const Value: string); + procedure SetAsWideString(const Value: Widestring); + function GetAsAnsiString: TBoldAnsiString; + procedure SetAsAnsiString(const Value: TBoldAnsiString); + function GetUniParam: TUniParam; + procedure AssignFieldValue(const source: IBoldField); + procedure Assign(const source: IBoldParameter); + property UniParam: TUniParam read GetUniParam; + public + constructor Create(UniDACParameter: TUniParam; DatasetWrapper: TBoldAbstractQueryWrapper); + end; + + { TBoldUniDACQuery } + TBoldUniDACQuery = class(TBoldBatchDataSetWrapper, IBoldQuery, IBoldExecQuery, IBoldParameterized) + private + fQuery: TUniQuery; + fReadTransactionStarted: Boolean; + fUseReadTransactions: boolean; + function GetQuery: TUniQuery; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure AssignParams(Sourceparams: TParams); + function GetParamCount: Integer; + function GetParam(i: Integer): IBoldParameter; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetParamCheck: Boolean; + procedure SetParamCheck(value: Boolean); + function GetRequestLiveQuery: Boolean; + function ParamByName(const Value: string): IBoldParameter; override; + function FindParam(const Value: string): IBoldParameter; override; + function Createparam(FldType: TFieldType; const ParamName: string; ParamType: TParamType; Size: integer): IBoldParameter; override; + procedure SetRequestLiveQuery(NewValue: Boolean); + procedure AssignSQL(SQL: TStrings); virtual; + function GetSQLStrings: TStrings; override; + function GetRecordCount: Integer; + function GetUseReadTransactions: boolean; + procedure SetUseReadTransactions(value: boolean); + procedure BeginExecuteQuery; + procedure EndExecuteQuery; + protected + function GetParams: TParams; override; + function GetSqlText: string; override; + procedure AssignSQLText(const SQL: string); override; + function GetRowsAffected: Integer; + function GetDataSet: TDataSet; override; + procedure ClearParams; + procedure Open; override; + procedure Close; override; + procedure ExecSQL; override; + function GetRecNo: integer; override; + property Query: TUniQuery read GetQuery; + public + constructor Create(BoldUniDACConnection: TBoldUniDACConnection); reintroduce; + destructor Destroy; override; + procedure Clear; override; + end; + + { TBoldUniDACQuery } + TBoldUniDACExecQuery = class(TBoldAbstractQueryWrapper, IBoldExecQuery, IBoldParameterized) + private + fExecQuery: TUniSQL; + fReadTransactionStarted: Boolean; + fUseReadTransactions: boolean; + function GetExecQuery: TUniSQL; + function GetParams: TParams; + procedure AssignParams(Sourceparams: TParams); + function GetParamCount: Integer; + function GetParam(i: Integer): IBoldParameter; + function GetParamCheck: Boolean; + procedure SetParamCheck(value: Boolean); + function ParamByName(const Value: string): IBoldParameter; + function FindParam(const Value: string): IBoldParameter; + function Createparam(FldType: TFieldType; const ParamName: string): IBoldParameter; overload; + function CreateParam(FldType: TFieldType; const ParamName: string; ParamType: TParamType; Size: integer): IBoldParameter; overload; + function EnsureParamByName(const Value: string): IBoldParameter; + function GetSQLText: string; + function GetSQLStrings: TStrings; + procedure AssignSQL(SQL: TStrings); virtual; + procedure AssignSQLText(const SQL: string); + function GetRowsAffected: Integer; + function GetUseReadTransactions: boolean; + procedure SetUseReadTransactions(value: boolean); + procedure BeginExecuteQuery; + procedure EndExecuteQuery; + function GetBatchQueryParamCount: integer; +// procedure Prepare; + protected + procedure StartSQLBatch; virtual; + procedure EndSQLBatch; virtual; + procedure FailSQLBatch; virtual; + procedure ClearParams; + procedure ExecSQL; virtual; + property ExecQuery: TUniSQL read GetExecQuery; + public + constructor Create(BoldUniDACConnection: TBoldUniDACConnection); reintroduce; + destructor Destroy; override; + procedure Clear; override; + end; + + { TBoldUniDACTable } + TBoldUniDACTable = class(TBoldDatasetWrapper, IBoldTable) + private + fUniTable: TUniTable; + function GetUniTable: TUniTable; + property UniTable: TUniTable read GetUniTable; + procedure AddIndex(const Name, Fields: string; Options: TIndexOptions; const DescFields: string = ''); + procedure CreateTable; + procedure DeleteTable; + function GetIndexDefs: TIndexDefs; + procedure SetTableName(const NewName: string); + function GetTableName: string; + procedure SetExclusive(NewValue: Boolean); + function GetExclusive: Boolean; + function GetExists: Boolean; +// function GetCommaListOfIndexesForColumn(const aColumnName: string): string; +// function GetPrimaryIndex: string; + protected + function GetDefaultConstraintNameForColumn(const aColumnName: string): string; {override;} + function GetDataSet: TDataSet; override; + function ParamByName(const Value: string): IBoldParameter; override; + function FindParam(const Value: string): IBoldParameter; override; + public + constructor Create(aUniTable: TUniTable; BoldUniDACConnection: TBoldUniDACConnection); reintroduce; + end; + + { TBoldUniDACConnection } + TBoldUniDACConnection = class(TBoldDatabaseWrapper, IBoldDataBase) + fUniConnection: TUniConnection; + fCachedTable: TBoldUniDACTable; + fCachedQuery1: TBoldUniDACQuery; + fCachedQuery2: TBoldUniDACQuery; + fCachedExecQuery1: TBoldUniDACQuery; + fExecuteQueryCount: integer; + function GetUniConnection: TUniConnection; + property UniConnection: TUniConnection read GetUniConnection; + function GetConnected: Boolean; + function GetInTransaction: Boolean; + function GetIsSQLBased: Boolean; + procedure SetlogInPrompt(NewValue: Boolean); + function GetLogInPrompt: Boolean; + procedure SetKeepConnection(NewValue: Boolean); + function GetKeepConnection: Boolean; + procedure StartTransaction; + procedure StartReadTransaction; + procedure Commit; + procedure RollBack; + procedure Open; + procedure Close; + procedure Reconnect; + function SupportsTableCreation: Boolean; + procedure ReleaseCachedObjects; + function GetIsExecutingQuery: Boolean; + procedure BeginExecuteQuery; + procedure EndExecuteQuery; + protected + procedure AllTableNames(Pattern: string; ShowSystemTables: Boolean; TableNameList: TStrings); override; + function GetTable: IBoldTable; override; + function GetQuery: IBoldQuery; override; + function GetExecQuery: IBoldExecQuery; override; + procedure ReleaseTable(var Table: IBoldTable); override; + procedure ReleaseQuery(var Query: IBoldQuery); override; + procedure ReleaseExecQuery(var Query: IBoldExecQuery); override; + public + constructor Create(aUniConnection: TUniConnection; SQLDataBaseConfig: TBoldSQLDatabaseConfig); + destructor Destroy; override; + procedure CreateDatabase; override; + function GetDatabaseError(const E: Exception; const sSQL: string = ''): + EBoldDatabaseError; + property ExecuteQueryCount: integer read fExecuteQueryCount; + end; + +var + BoldUniDACQueryClass: TBoldUniDACQueryClass = TBoldUniDACQuery; + BoldUniDACExecQueryClass: TBoldUniDACExecQueryClass = TBoldUniDACExecQuery; + +implementation + +uses + Variants, + Masks, + + BoldUtils, + BoldGuard, + BoldCoreConsts, + + CRAccess, + UniScript; + +{ TBoldUniDACQuery } + +function TBoldUniDACQuery.GetQuery: TUniQuery; +begin + if not Assigned(fQuery) then + begin + fQuery := TUniQuery.Create(nil); + fQuery.Connection := (DatabaseWrapper as TBoldUniDACConnection).UniConnection; + end; + Result := fQuery; +end; + +function TBoldUniDACQuery.GetDataSet: TDataSet; +begin + Result := Query; +end; + +function TBoldUniDACQuery.GetParamCheck: Boolean; +begin + result := Query.ParamCheck; +end; + +function TBoldUniDACQuery.GetParamCount: Integer; +begin + Result := Query.Params.Count; +end; + +function TBoldUniDACQuery.GetParams: TParams; +begin + result := Query.Params; +end; + +function TBoldUniDACQuery.GetParam(i: Integer): IBoldParameter; +begin + Result := TBoldUniDACParameter.Create(Query.Params[i], Self); +end; + +function TBoldUniDACQuery.GetRecNo: integer; +begin + result := Query.RecNo - 1; +end; + +function TBoldUniDACQuery.GetRecordCount: Integer; +begin + Result := Query.RecordCount; +end; + +function TBoldUniDACQuery.GetRequestLiveQuery: Boolean; +begin + Result := False; +end; + +function TBoldUniDACQuery.GetRowsAffected: Integer; +begin + result := Query.RowsAffected; +end; + +function TBoldUniDACQuery.GetSQLStrings: TStrings; +begin + result := Query.SQL; +end; + +function TBoldUniDACQuery.GetSQLText: string; +begin + Result := Query.SQL.Text; +end; + +function TBoldUniDACQuery.GetUseReadTransactions: boolean; +begin + result := fUseReadTransactions; +end; + +procedure TBoldUniDACQuery.AssignParams(Sourceparams: TParams); +var + lIndexSourceParams: Integer; + lUniParam: TUniParam; +begin + Query.Params.Clear; + if Assigned(Sourceparams) and (Sourceparams.Count > 0) then + begin + for lIndexSourceParams := 0 to Sourceparams.Count - 1 do + begin + lUniParam := Query.Params.CreateParam(Sourceparams[lIndexSourceParams].DataType, Sourceparams[lIndexSourceParams].Name, Sourceparams[lIndexSourceParams].ParamType) as TUniParam; + lUniParam.Value := Sourceparams[lIndexSourceParams].Value; + end; + end; +end; + +procedure TBoldUniDACQuery.AssignSQL(SQL: TStrings); +begin + Query.SQL.Assign(SQL); + //function ParseSQL(SQL: WideString; DoCreate: Boolean): WideString; + //DoCreate indicates whether to clear all existing parameter definitions before parsing the SQL statement. +end; + +procedure TBoldUniDACQuery.AssignSQLText(const SQL: string); +begin + Query.SQL.Text := Sql; +{ if SQL = '' then + Query.Params.clear + else + Query.Params.ParseSQL(SQL, False);} +end; + +procedure TBoldUniDACQuery.BeginExecuteQuery; +begin + (DatabaseWrapper as TBoldUniDACConnection).BeginExecuteQuery; +end; + +procedure TBoldUniDACQuery.Clear; +begin + AssignSQLText(''); + ClearParams; +end; + +procedure TBoldUniDACQuery.ClearParams; +begin + Query.Params.Clear; +end; + +procedure TBoldUniDACQuery.Close; +begin + inherited; + if (fReadTransactionStarted) and (DatabaseWrapper as TBoldUniDACConnection).GetInTransaction then + (DatabaseWrapper as TBoldUniDACConnection).Commit; + fReadTransactionStarted := false; +end; + +constructor TBoldUniDACQuery.Create(BoldUniDACConnection: TBoldUniDACConnection); +begin + inherited Create(BoldUniDACConnection); + fUseReadTransactions := true; + fQuery := TUniQuery.Create(nil); + fQuery.Connection := (DatabaseWrapper as TBoldUniDACConnection).UniConnection; +end; + +function TBoldUniDACQuery.CreateParam(FldType: TFieldType; const ParamName: string; ParamType: TParamType; Size: integer): IBoldParameter; +var + lUniParam: TUniParam; +begin + lUniParam := Query.Params.CreateParam(FldType, ParamName, ptUnknown) as TUniParam; +// lUniParam.Size := Size; + lUniParam.Value := NULL; + Result := TBoldUniDACParameter.Create(lUniParam, Self); +end; + +destructor TBoldUniDACQuery.Destroy; +begin + if (fReadTransactionStarted) then + Close; + FreeAndNil(fQuery); + inherited; +end; + +procedure TBoldUniDACQuery.EndExecuteQuery; +begin + (DatabaseWrapper as TBoldUniDACConnection).EndExecuteQuery; +end; + +type TStringsAccess = class(TStrings); + +procedure TBoldUniDACQuery.ExecSQL; +var + Retries: Integer; + Done: Boolean; +begin + if InBatch then + begin + BatchExecSQL; + exit; + end; + BeginExecuteQuery; + try + BoldLogSQLWithParams(Query.SQL, self); + Retries := 0; + Done := false; + while not Done do + begin + try + if (DatabaseWrapper as TBoldUniDACConnection).GetInTransaction then + fReadTransactionStarted := false + else + begin + if fUseReadTransactions then + (DatabaseWrapper as TBoldUniDACConnection).StartReadTransaction; + fReadTransactionStarted := fUseReadTransactions; + end; + Query.Execute; + if fReadTransactionStarted and (DatabaseWrapper as TBoldUniDACConnection).GetInTransaction then + begin + (DatabaseWrapper as TBoldUniDACConnection).Commit; + fReadTransactionStarted := false; + end; + Done := true; + except + on e: Exception do + begin + if (DatabaseWrapper as TBoldUniDACConnection).GetInTransaction then + (DatabaseWrapper as TBoldUniDACConnection).Rollback; + if (not fReadTransactionStarted) or (Retries > 4) then + raise TBoldUniDACConnection(DatabaseWrapper).GetDatabaseError(E, Query.SQL.Text); + fReadTransactionStarted := false; + INC(Retries); + sleep(Retries*200); + end; + end; + end; + finally + EndExecuteQuery; + end; +end; + +function TBoldUniDACQuery.FindParam(const Value: string): IBoldParameter; +var + Param: TUniParam; +begin + result := nil; + Param := Query.FindParam(Value); + if Assigned(Param) then + Result := TBoldUniDACParameter.Create(Param, Self); +end; + +procedure TBoldUniDACQuery.Open; +var + Retries: Integer; + Done: Boolean; + EDatabase: EBoldDatabaseError; +begin + BeginExecuteQuery; + try + BoldLogSQLWithParams(Query.SQL, self); + Retries := 0; + Done := false; + while not Done do + begin + try + if (DatabaseWrapper as TBoldUniDACConnection).GetInTransaction then + fReadTransactionStarted := false + else + begin + if fUseReadTransactions then + (DatabaseWrapper as TBoldUniDACConnection).StartReadTransaction; + fReadTransactionStarted := fUseReadTransactions; + end; + Query.ReadOnly := True; + inherited; + Done := true; + except + on e: Exception do + begin + EDatabase := TBoldUniDACConnection(DatabaseWrapper). + GetDatabaseError(E, Query.SQL.Text); + if (EDatabase is EBoldDatabaseConnectionError) {and + (not Assigned(ReconnectAppExists) or ReconnectAppExists)} then + begin + EDatabase.free; +// ReconnectDatabase(Query.SQL.Text); + Reconnect; + end else + begin + if (DatabaseWrapper as TBoldUniDACConnection).GetInTransaction then + (DatabaseWrapper as TBoldUniDACConnection).Rollback; + if (not fReadTransactionStarted) or (Retries > 4) then + raise EDatabase + else + EDatabase.free; + fReadTransactionStarted := false; + INC(Retries); + sleep(Retries*200); + end; + end; + end; + end; + finally + EndExecuteQuery; + end; +end; + +function TBoldUniDACQuery.ParamByName(const Value: string): IBoldParameter; +var + lUniParam: TUniParam; +begin + lUniParam := Query.Params.ParamByName(Value); + Result := TBoldUniDACParameter.Create(lUniParam, Self) +end; + +procedure TBoldUniDACQuery.SetParamCheck(value: Boolean); +begin + if Query.ParamCheck <> Value then + Query.ParamCheck := Value; +end; + +procedure TBoldUniDACQuery.SetRequestLiveQuery(NewValue: Boolean); +begin + // ignore +end; + +procedure TBoldUniDACQuery.SetUseReadTransactions(value: boolean); +begin + fUseReadTransactions := value; +end; + +{ TBoldUniDACTable } + +constructor TBoldUniDACTable.Create(aUniTable: TUniTable; BoldUniDACConnection: TBoldUniDACConnection); +begin + inherited Create(BoldUniDACConnection); + fUniTable := aUniTable; +end; + +procedure TBoldUniDACTable.CreateTable; +begin + raise EBold.CreateFmt('MethodNotImplemented', [ClassName, 'CreateTable']); // do not localize +end; + +procedure TBoldUniDACTable.DeleteTable; +begin + raise EBold.CreateFmt('MethodNotImplemented', [ClassName, 'DeleteTable']); // do not localize +end; + +function TBoldUniDACTable.FindParam(const Value: string): IBoldParameter; +var + Param: TUniParam; +begin + result := nil; + Param := UniTable.FindParam(Value); + if Assigned(Param) then + Result := TBoldUniDACParameter.Create(Param, Self); +end; + +procedure TBoldUniDACTable.AddIndex(const Name, Fields: string; + Options: TIndexOptions; const DescFields: string); +begin + raise EBold.CreateFmt('MethodNotImplemented', [ClassName, 'AddIndex']); // do not localize +end; +(* +function TBoldUniDACTable.GetCommaListOfIndexesForColumn( + const aColumnName: string): string; +var + lUniMetaData: TUniMetaData; + lIndexList: TStringList; + lIndexedColumn: string; + lIndexName: string; + lBoldGuard: IBoldGuard; +const + cTableName = 'Table_Name'; + cIndexName = 'Index_Name'; + cColumnName = 'Column_Name'; +begin +// TODO possibly slow comment +// to improve performance move metadata to the Connection and store it there + + lBoldGuard := TBoldGuard.Create(lUniMetaData, lIndexList); + lUniMetaData := TUniMetaData.Create(nil); + lIndexList := TStringList.Create; + + Assert(Assigned(UniTable)); + Assert(Assigned(UniTable.Connection)); + lUniMetaData.Connection := UniTable.Connection; +// lUniMetaData.DatabaseName := UniTable.Connection.Database; + lUniMetaData.MetaDataKind := 'Indexes'; +{ lUniMetaData.TableName := GetTableName; + lUniMetaData.Open; + lUniMetaData.First; + while not lUniMetaData.Eof do + begin + lIndexedColumn := lUniMetaData.FieldByName(cColumnName).AsString; + if aColumnName = lIndexedColumn then + begin + lIndexName := lUniMetaData.FieldByName(cIndexName).AsString; + lIndexList.Add(lIndexName); + end; + lUniMetaData.Next; + end; + Result := lIndexList.CommaText; + lUniMetaData.Close; +} +end; + +function TBoldUniDACTable.GetPrimaryIndex: string; +var + lUniMetaData: TUniMetaData; + lIndexName: string; +const + cTableName = 'Table_Name'; + cIndexName = 'Index_Name'; + cColumnName = 'Column_Name'; + cPrimaryKey = 'Primary_Key'; +// COLUMN_NAME +begin +// TODO possibly slow comment +// to improve performance move metadata to the Connection and store it there + + lUniMetaData := TUniMetaData.Create(nil); + try + Assert(Assigned(UniTable)); + Assert(Assigned(UniTable.Connection)); + lUniMetaData.Connection := UniTable.Connection; +// lUniMetaData.DatabaseName := UniTable.Connection.Database; +{ lUniMetaData.MetaDataKind := otPrimaryKeys; + lUniMetaData.Open; + lUniMetaData.Filter := Format('(%s = ''%s'')', [cTableName, GetTableName]); + lUniMetaData.Filtered := True; + if lUniMetaData.RecordCount = 1 then + begin + lIndexName := lUniMetaData.FieldByName(cColumnName).AsString; + Result := lIndexName; + end + else + begin + Result := ''; + end; + lUniMetaData.Close; +} + finally + lUniMetaData.free; + end; +end; +*) +function TBoldUniDACTable.GetDataSet: TDataSet; +begin + Result := fUniTable; +end; + +function TBoldUniDACTable.GetDefaultConstraintNameForColumn( + const aColumnName: string): string; +var + lUniMetaData: TUniMetaData; + lDefaultConstraintName: string; + lBoldGuard: IBoldGuard; +const + cConstraintName = 'CONSTRAINT_NAME'; +begin + Assert(Assigned(UniTable)); + Assert(Assigned(UniTable.Connection)); + + lBoldGuard := TBoldGuard.Create(lUniMetaData); + lUniMetaData := TUniMetaData.Create(nil); + lUniMetaData.Connection := UniTable.Connection; +{ lUniMetaData.DatabaseName := UniTable.Connection.Database; + lUniMetaData.TableName := GetTableName; + lUniMetaData.ColumnName := aColumnName; + lUniMetaData.ObjectType := otConstraintColumnUsage; + lUniMetaData.Open; + lUniMetaData.First; + if not lUniMetaData.Eof then + begin + lDefaultConstraintName := lUniMetaData.FieldByName(cConstraintName).AsString; + end; + lUniMetaData.Close; +} + Result := lDefaultConstraintName; +end; + +function TBoldUniDACTable.GetExclusive: Boolean; +begin + Result := False; +end; + +function TBoldUniDACTable.GetExists: Boolean; +var + lAllTables: TStringList; + lGuard: IBoldGuard; +begin + lGuard := TBoldGuard.Create(lAllTables); + Result := False; + + // First we make sure we have a table component and that it is connected to a database + if Assigned(UniTable) and Assigned(UniTable.Connection) then + begin + // We now create a list that will hold all the table names in the database + lAllTables := TStringList.Create; + UniTable.Connection.GetTableNames(lAllTables); + Result := lAllTables.IndexOf(GetTableName) <> -1; + end; +end; + +function TBoldUniDACTable.GetIndexDefs: TIndexDefs; +begin + raise EBold.CreateFmt('%s MethodNotImplemented %s', [ClassName, 'GetIndexDefs']); // do not localize +// Result := UniTable.IndexFieldNames +end; + +function TBoldUniDACTable.GetUniTable: TUniTable; +begin + Result := fUniTable; +end; + +function TBoldUniDACTable.ParamByName(const Value: string): IBoldParameter; +var + lUniParam: TUniParam; +begin + lUniParam := UniTable.Params.ParamByName(Value); + Result := TBoldUniDACParameter.Create(lUniParam, Self) +end; + +function TBoldUniDACTable.GetTableName: string; +begin + Result := UniTable.TableName; +end; + +procedure TBoldUniDACTable.SetExclusive(NewValue: Boolean); +begin +end; + +procedure TBoldUniDACTable.SetTableName(const NewName: string); +begin + UniTable.TableName := NewName; +end; + +{ TBoldUniDACConnection } + +// Populate the "TableNameList" with tablenames from the database that maches "pattern" + +procedure TBoldUniDACConnection.AllTableNames(Pattern: string; ShowSystemTables: Boolean; TableNameList: TStrings); +var + lTempList: TStringList; + lIndexTempList: Integer; + lGuard: IBoldGuard; + i: integer; +begin + lGuard := TBoldGuard.Create(lTempList); + lTempList := TStringList.Create; + + // Retrieve the list of table names + // Note: This does not include views or procedures, there is a specific + // method in TUniConnection for that + UniConnection.GetTableNames(lTempList, ShowSystemTables); + + // convert from fully qualified names in format: database.catalogue.table to just table name + for i := 0 to lTempList.Count - 1 do + while pos('.', lTempList[i]) > 0 do + lTempList[i] := Copy(lTempList[i], pos('.', lTempList[i])+1, maxInt); + + if Pattern = '' then + TableNameList.Assign(lTempList) + else + // MatchesMask is used to compare filenames with wildcards, suits us here + // but there should be some care taken, when using tablenames with period + // signes, as that might be interpreted as filename extensions + for lIndexTempList := 0 to lTempList.Count - 1 do + begin + if MatchesMask(lTempList[lIndexTempList], Pattern) then + begin + TableNameList.Add(lTempList[lIndexTempList]); + end; + end; +end; + +procedure TBoldUniDACConnection.Commit; +begin + UniConnection.Commit; +end; + +function TBoldUniDACConnection.GetInTransaction: Boolean; +begin + Result := UniConnection.InTransaction; +end; + +function TBoldUniDACConnection.GetIsExecutingQuery: Boolean; +begin + Result := fExecuteQueryCount > 0; +end; + +function TBoldUniDACConnection.GetIsSQLBased: Boolean; +begin + Result := True; +end; + +function TBoldUniDACConnection.GetKeepConnection: Boolean; +begin + //CheckMe; + Result := True; +end; + +function TBoldUniDACConnection.GetLogInPrompt: Boolean; +begin + Result := UniConnection.LoginPrompt; +end; + +procedure TBoldUniDACConnection.RollBack; +begin + UniConnection.RollBack; +end; + +procedure TBoldUniDACConnection.SetKeepConnection(NewValue: Boolean); +begin + //CheckMe; +end; + +procedure TBoldUniDACConnection.SetlogInPrompt(NewValue: Boolean); +begin + UniConnection.LoginPrompt := NewValue; +end; + +procedure TBoldUniDACConnection.StartReadTransaction; +begin + UniConnection.DefaultTransaction.IsolationLevel := ilReadCommitted; + UniConnection.StartTransaction; +end; + +procedure TBoldUniDACConnection.StartTransaction; +begin + UniConnection.DefaultTransaction.IsolationLevel := ilRepeatableRead; + UniConnection.StartTransaction; +end; + +destructor TBoldUniDACConnection.Destroy; +begin + ReleaseCachedObjects; + inherited; +end; + +procedure TBoldUniDACConnection.EndExecuteQuery; +begin + dec(fExecuteQueryCount); +end; + +constructor TBoldUniDACConnection.Create(aUniConnection: TUniConnection; SQLDataBaseConfig: TBoldSQLDatabaseConfig); +begin + inherited Create(SQLDataBaseConfig); + fUniConnection := aUniConnection; +end; + +procedure TBoldUniDACConnection.BeginExecuteQuery; +begin + inc(fExecuteQueryCount); +end; + +procedure TBoldUniDACConnection.Close; +begin + UniConnection.Close; +end; + +procedure TBoldUniDACConnection.CreateDatabase; +var + vQuery: IBoldExecQuery; + vDatabaseName: string; + vUniScript: TUniScript; + vIsInterbase: boolean; + vIsMSSQL: boolean; +const + cInterbase = 'InterBase'; + cMSSQL = 'SQL Server'; + cDropDatabaseSQL = 'Drop Database %s'; + cGenerateDatabaseSQL = 'Create Database %s'; + cGenerateDatabaseInterbaseSQL = 'Create Database ''%s'' user ''%s'' password ''%s'''; + cGenerateDatabaseSQLServer = 'USE master;' + BOLDCRLF + 'GO' + BOLDCRLF + ' Create Database %s'; +begin + vDatabaseName := LowerCase(UniConnection.Database); +// UniConnection.Database := ''; // need to clear this to connect succesfully + vUniScript := TUniScript.Create(nil); + try + vUniScript.Connection := UniConnection; + vIsInterbase := UniConnection.ProviderName = cInterBase; + vIsMSSQL := UniConnection.ProviderName = cMSSQL; + vUniScript.SQL.Text := Format(cDropDatabaseSQL, [vDatabaseName]); + if vIsMSSQL then + UniConnection.Database := 'master'; + try + vUniScript.Execute; + except + // ignore + end; + vUniScript.NoPreconnect := vIsInterbase; + if vIsInterbase then + vUniScript.SQL.Text := Format(cGenerateDatabaseInterbaseSQL, [vDatabaseName, UniConnection.Username, UniConnection.Password]) + else + if vIsMSSQL then + begin + vUniScript.SQL.Text := Format(cGenerateDatabaseSQLServer, [vDatabaseName]); + end + else + vUniScript.SQL.Text := Format(cGenerateDatabaseSQL, [vDatabaseName]); + vUniScript.Execute; + UniConnection.Close; + finally + vUniScript.free; + if vIsMSSQL then + UniConnection.Database := vDatabaseName; + end; +end; + +function TBoldUniDACConnection.GetConnected: Boolean; +begin + Result := UniConnection.Connected; +end; + +function TBoldUniDACConnection.GetDatabaseError(const E: Exception; + const sSQL: string): EBoldDatabaseError; +const + SQLERRORCODE = 'SQL Error Code: '; +var + iErrorCode: Integer; + sMsg: string; + iPos: Integer; + aErrorType: TBoldDatabaseErrorType; + sServer, + sDatabase, + sUsername: string; + bUseWindowsAuth: Boolean; +const + // Provider names copied here to avoid dependancy + cMSSQLProvider = 'SQL Server'; // TSQLServerUniProvider.GetProviderName + cPostgreSQLProvider = 'PostgreSQL'; // TPostgreSQLUniProvider.GetProviderName + cOracleSQLProvider = 'Oracle'; // TOracleUniProvider.GetProviderName + cInterBaseProvider = 'InterBase'; + cMSSQLDeadLock = 1205; +begin + aErrorType := bdetError; + sServer := UniConnection.Server; + sDatabase := UniConnection.Database; + sUsername := UniConnection.Username; + bUseWindowsAuth := Pos('Authentication=Windows', UniConnection.ConnectString) > 0; + if (E is EUniError) then + begin + if UniConnection.ProviderName = cMSSQLProvider then + case EUniError(E).ErrorCode of + -2147467259, 2, 233: aErrorType := bdetConnection; // only set bdetConnection for cases where retry might work. + 208, 4145: aErrorType := bdetSQL; + 4060: aErrorType := bdetLogin; // SQLServer Error: 4060, Cannot open database "SessionStateService" requested by the login. The login failed. [SQLSTATE 42000] + 18456: aErrorType := bdetLogin; // SQLServer Error: 18456, Login failed for user 'domain\user'. [SQLSTATE 28000] + cMSSQLDeadLock: aErrorType := bdetDeadlock; + //Deadlock und weitere ErrorCodes? + end + else + if UniConnection.ProviderName = cInterBaseProvider then + case EUniError(E).ErrorCode of + -803: aErrorType := bdetUpdate; // attempt to store duplicate value (visible to active transactions) in unique index + end + else + if UniConnection.ProviderName = cPostgreSQLProvider then + case EUniError(E).ErrorCode of + 0: aErrorType := bdetLogin; + end + else + raise Exception.Create('Error codes not implemented for ' + UniConnection.ProviderName); + end; + Result := InternalGetDatabaseError(aErrorType, E, sSQL, sServer, sDatabase, + sUsername, bUseWindowsAuth); +end; + +function TBoldUniDACConnection.GetExecQuery: IBoldExecQuery; +begin + if Assigned(fCachedExecQuery1) then + begin + result := fCachedExecQuery1; + fCachedExecQuery1 := nil; + end else + begin + Result := BoldUniDACQueryClass.Create(Self); + end; +end; + +function TBoldUniDACConnection.GetUniConnection: TUniConnection; +begin + Result := fUniConnection; +end; + +function TBoldUniDACConnection.GetQuery: IBoldQuery; +begin + if Assigned(fCachedQuery1) then + begin + result := fCachedQuery1; + fCachedQuery1 := nil; + end else + if Assigned(fCachedQuery2) then + begin + result := fCachedQuery2; + fCachedQuery2 := nil; + end else + begin + Result := BoldUniDACQueryClass.Create(Self); + end; +end; + +function TBoldUniDACConnection.GetTable: IBoldTable; +var + lUniTable: TUniTable; +begin + if Assigned(fCachedTable) then + begin + result := fCachedTable; + fCachedTable := nil; + end + else + begin + lUniTable := TUniTable.Create(nil); + lUniTable.Connection := UniConnection; + Result := TBoldUniDACTable.Create(lUniTable, Self); + end; +end; + +procedure TBoldUniDACConnection.Open; +begin + try + UniConnection.Open; + except + on E: Exception do begin + raise GetDatabaseError(E); + end; + end; +end; + +procedure TBoldUniDACConnection.Reconnect; +begin + if Assigned(fUniConnection) then begin + fUniConnection.Connected := False; + fUniConnection.Connected := True; + end; +end; + +procedure TBoldUniDACConnection.ReleaseQuery(var Query: IBoldQuery); +var + lBoldUniDACQuery: TBoldUniDACQuery; +begin + if (Query.Implementor is TBoldUniDACQuery) then + begin + lBoldUniDACQuery := Query.Implementor as TBoldUniDACQuery; + lBoldUniDACQuery.clear; + Query := nil; + if not Assigned(fCachedQuery1) then + fCachedQuery1 := lBoldUniDACQuery + else + if not Assigned(fCachedQuery2) then + fCachedQuery2 := lBoldUniDACQuery + else + lBoldUniDACQuery.free; + end +end; + +procedure TBoldUniDACConnection.ReleaseExecQuery(var Query: IBoldExecQuery); +var + lBoldUniDACQuery: TBoldUniDACQuery; + lBoldUniDACExecQuery: TBoldUniDACExecQuery; +begin + if (Query.Implementor is TBoldUniDACQuery) then + begin + lBoldUniDACQuery := Query.Implementor as TBoldUniDACQuery; + if lBoldUniDACQuery.GetSQLStrings.Count <> 0 then + begin + lBoldUniDACQuery.GetSQLStrings.BeginUpdate; + lBoldUniDACQuery.clear; + end; + while TStringsAccess(lBoldUniDACQuery.GetSQLStrings).UpdateCount > 0 do + lBoldUniDACQuery.GetSQLStrings.EndUpdate; + Query := nil; + if not Assigned(fCachedExecQuery1) then + fCachedExecQuery1 := lBoldUniDACQuery + else + lBoldUniDACQuery.free; + end +{ else + if (Query.Implementor is TBoldUniDACExecQuery) then + begin + lBoldUniDACExecQuery := Query.Implementor as TBoldUniDACExecQuery; + lBoldUniDACExecQuery.clear; + Query := nil; + if not Assigned(fCachedExecQuery1) then + fCachedExecQuery1 := lBoldUniDACExecQuery + else + lBoldUniDACExecQuery.free; + end +} +end; + +procedure TBoldUniDACConnection.ReleaseTable(var Table: IBoldTable); +var + lBoldUniDACTable: TBoldUniDACTable; +begin + if Table.Implementor is TBoldUniDACTable then + begin + lBoldUniDACTable := Table.Implementor as TBoldUniDACTable; + Table := nil; + if not Assigned(fCachedTable) then + fCachedTable := lBoldUniDACTable + else + lBoldUniDACTable.free; + end; +end; + +function TBoldUniDACConnection.SupportsTableCreation: Boolean; +begin + Result := False; +end; + +{ TBoldUniDACParameter } + +procedure TBoldUniDACParameter.Clear; +begin + UniParam.Clear; +end; + +constructor TBoldUniDACParameter.Create(UniDACParameter: TUniParam; DatasetWrapper: TBoldAbstractQueryWrapper); +begin + inherited Create(DatasetWrapper); + fUniParam := UniDACParameter; +end; + +function TBoldUniDACParameter.GetAsAnsiString: TBoldAnsiString; +begin + Result := UniParam.AsAnsiString; +end; + +function TBoldUniDACParameter.GetAsBCD: Currency; +begin + Result := UniParam.AsBCD; +end; + +function TBoldUniDACParameter.GetAsblob: TBoldBlobData; +begin + Result := AnsiString(UniParam.Value); +end; + +function TBoldUniDACParameter.GetAsBoolean: Boolean; +begin + Result := UniParam.AsBoolean; +end; + +function TBoldUniDACParameter.GetAsCurrency: Currency; +begin + Result := UniParam.AsCurrency; +end; + +function TBoldUniDACParameter.GetAsDateTime: TDateTime; +begin + Result := UniParam.AsDateTime; +end; + +function TBoldUniDACParameter.GetAsFloat: Double; +begin + Result := UniParam.AsFloat; +end; + +function TBoldUniDACParameter.GetAsInt64: Int64; +begin + result := UniParam.AsLargeInt; +end; + +function TBoldUniDACParameter.GetAsInteger: Longint; +begin + Result := UniParam.AsInteger; +end; + +function TBoldUniDACParameter.GetAsMemo: string; +begin + Result := UniParam.AsMemo; +end; + +function TBoldUniDACParameter.GetAsString: string; +begin + Result := UniParam.AsString; + if Result = DatasetWrapper.DatabaseWrapper.SQLDataBaseConfig.EmptyStringMarker then + begin + Result := ''; + end; +end; + +function TBoldUniDACParameter.GetAsVariant: Variant; +begin + Result := UniParam.Value; +end; + +function TBoldUniDACParameter.GetAsWideString: WideString; +begin + Result := UniParam.AsWideString; + if Result = DatasetWrapper.DatabaseWrapper.SQLDataBaseConfig.EmptyStringMarker then + begin + Result := ''; + end; +end; + +function TBoldUniDACParameter.GetDataType: TFieldType; +begin + Result := UniParam.DataType; +end; + +function TBoldUniDACParameter.GetIsNull: Boolean; +begin + Result := VarIsNull(UniParam.Value) +end; + +function TBoldUniDACParameter.GetName: string; +begin + Result := UniParam.Name; +end; + +function TBoldUniDACParameter.GetUniParam: TUniParam; +begin + Result := fUniParam; +end; + +procedure TBoldUniDACParameter.SetAsAnsiString(const Value: TBoldAnsiString); +begin + UniParam.AsAnsiString := Value; +end; + +procedure TBoldUniDACParameter.SetAsBCD(const Value: Currency); +begin + UniParam.Value := Value; +end; + +procedure TBoldUniDACParameter.SetAsBlob(const Value: TBoldBlobData); +begin + if UniParam.DataType = ftUnknown then + begin + UniParam.DataType := ftBlob; + end; + if Value = '' then + begin +// UniParam.Value := DatasetWrapper.DatabaseWrapper.SQLDataBaseConfig.EmptyStringMarker; + UniParam.Value := Null; + end else + begin + UniParam.Value := TBoldBlobData(AnsiString(Value)); + end; +end; + +procedure TBoldUniDACParameter.SetAsBoolean(Value: Boolean); +begin + UniParam.AsBoolean := Value; +end; + +procedure TBoldUniDACParameter.SetAsCurrency(const Value: Currency); +begin + UniParam.AsCurrency := Value; +end; + +procedure TBoldUniDACParameter.SetAsDate(const Value: TDateTime); +begin + UniParam.AsDate := Value; +end; + +procedure TBoldUniDACParameter.SetAsDateTime(const Value: TDateTime); +begin + UniParam.AsDateTime := Value; +end; + +procedure TBoldUniDACParameter.SetAsFloat(const Value: Double); +begin + UniParam.AsFloat := Value; +end; + +procedure TBoldUniDACParameter.SetAsInt64(const Value: Int64); +begin + UniParam.AsLargeInt := Value; +end; + +procedure TBoldUniDACParameter.SetAsInteger(Value: Integer); +begin + UniParam.AsInteger := Value; +end; + +procedure TBoldUniDACParameter.SetAsMemo(const Value: string); +begin + UniParam.AsMemo := Value; +end; + +procedure TBoldUniDACParameter.SetAsSmallInt(Value: Integer); +begin + UniParam.AsSmallInt := Value; +end; + +procedure TBoldUniDACParameter.SetAsString(const Value: string); +begin + if Value = '' then + begin + UniParam.AsString := DatasetWrapper.DatabaseWrapper.SQLDataBaseConfig.EmptyStringMarker; + end else + begin + UniParam.AsString := Value; + end; +end; + +procedure TBoldUniDACParameter.SetAsTime(const Value: TDateTime); +begin + UniParam.AsTime := Value; +end; + +procedure TBoldUniDACParameter.SetAsVariant(const NewValue: Variant); +begin + UniParam.Value := NewValue; +end; + +procedure TBoldUniDACParameter.SetAsWideString(const Value: Widestring); +begin + if Value = '' then + begin + UniParam.AsString := DatasetWrapper.DatabaseWrapper.SQLDataBaseConfig.EmptyStringMarker; + end else + begin + UniParam.AsWideString := Value; + end; +end; + +procedure TBoldUniDACParameter.SetAsWord(Value: Integer); +begin + UniParam.AsWord := Value; +end; + +procedure TBoldUniDACParameter.SetDataType(Value: TFieldType); +begin + UniParam.DataType := Value; +end; + +procedure TBoldUniDACParameter.SetText(const Value: string); +begin + UniParam.Value := Value; +end; + +procedure TBoldUniDACParameter.Assign(const source: IBoldParameter); +begin + UniParam.Value := Source.AsVariant; +end; + +procedure TBoldUniDACParameter.AssignFieldValue(const source: IBoldField); +begin + UniParam.Assign(source.Field); +end; + +procedure TBoldUniDACConnection.ReleaseCachedObjects; +begin + FreeAndNil(fCachedTable); + FreeAndNil(fCachedQuery1); + FreeAndNil(fCachedQuery2); + FreeAndNil(fCachedExecQuery1); +end; + +{ TBoldUniDACExecQuery } + +procedure TBoldUniDACExecQuery.AssignParams(Sourceparams: TParams); +var + lIndexSourceParams: Integer; + lUniParam: TUniParam; +begin + ExecQuery.Params.Clear; + if Assigned(Sourceparams) and (Sourceparams.Count > 0) then + begin + for lIndexSourceParams := 0 to Sourceparams.Count - 1 do + begin + lUniParam := ExecQuery.Params.CreateParam(Sourceparams[lIndexSourceParams].DataType, Sourceparams[lIndexSourceParams].Name, Sourceparams[lIndexSourceParams].ParamType) as TUniParam; + lUniParam.Value := Sourceparams[lIndexSourceParams].Value; + end; + end; +end; + +procedure TBoldUniDACExecQuery.AssignSQL(SQL: TStrings); +begin + ExecQuery.SQL.BeginUpdate; + ExecQuery.SQL.Assign(SQL); + ExecQuery.SQL.EndUpdate; + ExecQuery.Params.ParseSQL(SQL.Text, False); +end; + +procedure TBoldUniDACExecQuery.AssignSQLText(const SQL: string); +var + lStringList: TStringList; + lGuard: IBoldGuard; +begin + lGuard := TBoldGuard.Create(lStringList); + lStringList := TStringList.Create; + lStringList.Add(SQL); + AssignSQL(lStringList); +end; + +procedure TBoldUniDACExecQuery.BeginExecuteQuery; +begin + (DatabaseWrapper as TBoldUniDACConnection).BeginExecuteQuery; +end; + +procedure TBoldUniDACExecQuery.Clear; +begin + inherited; + AssignSQLText(''); + ClearParams; +end; + +procedure TBoldUniDACExecQuery.ClearParams; +begin + ExecQuery.Params.Clear; +end; + +constructor TBoldUniDACExecQuery.Create(BoldUniDACConnection: TBoldUniDACConnection); +begin + inherited Create(BoldUniDACConnection); + fUseReadTransactions := true; +end; + +function TBoldUniDACExecQuery.Createparam(FldType: TFieldType; + const ParamName: string): IBoldParameter; +begin + result := CreateParam(FldType, ParamName, ptUnknown, 0); +end; + +function TBoldUniDACExecQuery.CreateParam(FldType: TFieldType; const ParamName: string; ParamType: TParamType; Size: integer): IBoldParameter; +var + lUniParam: TUniParam; +begin + lUniParam := ExecQuery.Params.CreateParam(FldType, ParamName, ptUnknown) as TUniParam; +// lUniParam.Size := Size; + lUniParam.Value := NULL; + Result := TBoldUniDACParameter.Create(lUniParam, Self); +end; + +destructor TBoldUniDACExecQuery.Destroy; +begin + FreeAndNil(fExecQuery); + inherited; +end; + +procedure TBoldUniDACExecQuery.EndExecuteQuery; +begin + (DatabaseWrapper as TBoldUniDACConnection).EndExecuteQuery; +end; + +function TBoldUniDACExecQuery.EnsureParamByName( + const Value: string): IBoldParameter; +var + lUniParam: TUniParam; +begin + lUniParam := ExecQuery.Params.FindParam(Value); + if not Assigned(lUniParam) then + lUniParam := ExecQuery.Params.CreateParam(ftUnknown, Value, ptUnknown) as TUniParam; + Result := TBoldUniDACParameter.Create(lUniParam, Self) +end; + +procedure TBoldUniDACExecQuery.ExecSQL; +var + Retries: Integer; + Done: Boolean; +begin + BeginExecuteQuery; + try + BoldLogSQLWithParams(ExecQuery.SQL, self); + Retries := 0; + Done := false; + while not Done do + begin + try + if (DatabaseWrapper as TBoldUniDACConnection).GetInTransaction then + fReadTransactionStarted := false + else + begin + if fUseReadTransactions then + (DatabaseWrapper as TBoldUniDACConnection).StartReadTransaction; + fReadTransactionStarted := fUseReadTransactions; + end; + ExecQuery.Execute; + if fReadTransactionStarted and (DatabaseWrapper as TBoldUniDACConnection).GetInTransaction then + begin + (DatabaseWrapper as TBoldUniDACConnection).Commit; + fReadTransactionStarted := false; + end; + Done := true; + except + on e: Exception do + begin + if (not fReadTransactionStarted) or (Retries > 4) then + raise TBoldUniDACConnection(DatabaseWrapper).GetDatabaseError(E, ExecQuery.SQL.Text); + if (DatabaseWrapper as TBoldUniDACConnection).GetInTransaction then + (DatabaseWrapper as TBoldUniDACConnection).Rollback; + fReadTransactionStarted := false; + INC(Retries); + sleep(Retries*200); + end; + end; + end; + finally + EndExecuteQuery; + end; +end; + +procedure TBoldUniDACExecQuery.StartSQLBatch; +begin + raise EBold.CreateFmt('MethodNotImplemented', [ClassName, 'StartSQLBatch']); // do not localize +end; + +procedure TBoldUniDACExecQuery.EndSQLBatch; +begin + raise EBold.CreateFmt('MethodNotImplemented', [ClassName, 'EndSQLBatch']); // do not localize +end; + +procedure TBoldUniDACExecQuery.FailSQLBatch; +begin + raise EBold.CreateFmt('MethodNotImplemented', [ClassName, 'FailSQLBatch']); // do not localize +end; + +function TBoldUniDACExecQuery.FindParam(const Value: string): IBoldParameter; +var + Param: TParam; +begin + Param := ExecQuery.FindParam(Value); + if not Assigned(Param) then + result := CreateParam(ftUnknown, Value); +end; + +function TBoldUniDACExecQuery.GetBatchQueryParamCount: integer; +begin + result := 0; // update when batch support is implemented +end; + +function TBoldUniDACExecQuery.GetExecQuery: TUniSQL; +begin + if not Assigned(fExecQuery) then + begin + fExecQuery := TUniSQL.Create(nil); + fExecQuery.Connection := (DatabaseWrapper as TBoldUniDACConnection).UniConnection; + end; + Result := fExecQuery; +end; + +function TBoldUniDACExecQuery.GetParamCheck: Boolean; +begin + result := ExecQuery.ParamCheck; +end; + +function TBoldUniDACExecQuery.GetParamCount: Integer; +begin + result := ExecQuery.Params.Count; +end; + +function TBoldUniDACExecQuery.GetParams: TParams; +begin + result := ExecQuery.Params; +end; + +function TBoldUniDACExecQuery.GetParam(i: Integer): IBoldParameter; +begin + Result := TBoldUniDACParameter.Create(ExecQuery.Params[i], Self); +end; + +function TBoldUniDACExecQuery.GetRowsAffected: Integer; +begin + Result := ExecQuery.RowsAffected; +end; + +function TBoldUniDACExecQuery.GetSQLStrings: TStrings; +begin + result := ExecQuery.SQL; +end; + +function TBoldUniDACExecQuery.GetSQLText: string; +begin + Result := ExecQuery.SQL.Text; +end; + +function TBoldUniDACExecQuery.GetUseReadTransactions: boolean; +begin + result := fUseReadTransactions; +end; + +function TBoldUniDACExecQuery.ParamByName(const Value: string): IBoldParameter; +var + lUniParam: TUniParam; +begin + lUniParam := ExecQuery.Params.ParamByName(Value); + if Assigned(lUniParam) then + begin + Result := TBoldUniDACParameter.Create(lUniParam, Self) + end else + begin + Result := nil; + end; +end; + +{procedure TBoldUniDACExecQuery.Prepare; +begin + ExecQuery.Prepare; +end;} + +procedure TBoldUniDACExecQuery.SetParamCheck(value: Boolean); +begin + ExecQuery.ParamCheck := Value; +end; + +procedure TBoldUniDACExecQuery.SetUseReadTransactions(value: boolean); +begin + fUseReadTransactions := value; +end; + +end. diff --git a/Source/Persistence/UniDAC/UniDACConsts.pas b/Source/Persistence/UniDAC/UniDACConsts.pas new file mode 100644 index 0000000..d6028fd --- /dev/null +++ b/Source/Persistence/UniDAC/UniDACConsts.pas @@ -0,0 +1,18 @@ +{ Global compiler directives } +{$include bold.inc} +unit UniDACConsts; + +interface + +resourcestring +//BoldDatabaseAdapterUniDAC + sAdapterNotConnected = '%s.GetDatabaseInterface: The adapter is not connected to an UniDAC connection'; + sCreatedNewAdapter = 'Created a new DatabaseAdapterUniDAC'; + sCanOnlyTransferToUniDACAdapter = 'The persistencehandle is connected to a %s, properties can only be transfered to a TBoldDatabaseAdapterUniDAC'; + sCreatedNewDB = 'Created a new UniDACDatabase'; + sCouldNotTransferConnectionString = 'Connection string settings could not be transferred to the new UniDAC connection: '; + sTransferManually = 'Please transfer these manually!'; + +implementation + +end. diff --git a/Source/Propagator/COM/BoldPropagatorHandleCOM.pas b/Source/Propagator/COM/BoldPropagatorHandleCOM.pas index e112665..06ee5c7 100644 --- a/Source/Propagator/COM/BoldPropagatorHandleCOM.pas +++ b/Source/Propagator/COM/BoldPropagatorHandleCOM.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldPropagatorHandleCOM; interface @@ -229,7 +232,7 @@ procedure TBoldPropagatorHandleCOM._Receive(Originator: TObject; end; beDestroying: ConnectionHandle := nil; - end; //end + end; end; procedure TBoldPropagatorHandleCOM.SetConnected(const Value: Boolean); @@ -238,17 +241,17 @@ procedure TBoldPropagatorHandleCOM.SetConnected(const Value: Boolean); begin if Value then begin - //request connection FConnectionHandle.Connected := True; - DoConnect; // is this necessary?? + DoConnect; end else begin - //request disconnect FConnectionHandle.Connected := false; - DoDisconnect; //is this necessary?? + DoDisconnect; end; end; end; +initialization + end. diff --git a/Source/Propagator/Common/BoldAbstractPropagatorHandle.pas b/Source/Propagator/Common/BoldAbstractPropagatorHandle.pas index 9d6cb45..2f3049a 100644 --- a/Source/Propagator/Common/BoldAbstractPropagatorHandle.pas +++ b/Source/Propagator/Common/BoldAbstractPropagatorHandle.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldAbstractPropagatorHandle; interface @@ -25,4 +28,10 @@ TBoldAbstractPropagatorHandle = class(TBoldSubscribableComponent) implementation +uses + BoldRev + ; + +initialization + end. diff --git a/Source/Propagator/Common/BoldLockingSupportInterfaces_TLB.pas b/Source/Propagator/Common/BoldLockingSupportInterfaces_TLB.pas index 1f9acb1..2a4fc75 100644 --- a/Source/Propagator/Common/BoldLockingSupportInterfaces_TLB.pas +++ b/Source/Propagator/Common/BoldLockingSupportInterfaces_TLB.pas @@ -1,51 +1,47 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldLockingSupportInterfaces_TLB; -// ************************************************************************ // -// WARNING -// ------- -// The types declared in this file were generated from data read from a -// Type Library. If this type library is explicitly or indirectly (via -// another type library referring to this type library) re-imported, or the -// 'Refresh' command of the Type Library Editor activated while editing the -// Type Library, the contents of this file will be regenerated and all -// manual modifications will be lost. -// ************************************************************************ // - -// PASTLWTR : 1.1 -// File generated on 6/1/2001 9:37:35 AM from Type Library described below. - -// *************************************************************************// -// NOTE: -// Items guarded by $IFDEF_LIVE_SERVER_AT_DESIGN_TIME are used by properties -// which return objects that may need to be explicitly created via a function -// call prior to any access via the property. These items have been disabled -// in order to prevent accidental use from within the object inspector. You -// may enable them by defining LIVE_SERVER_AT_DESIGN_TIME or by selectively -// removing them from the $IFDEF blocks. However, such items must still be -// programmatically created via a method of the appropriate CoClass before -// they can be used. -// ************************************************************************ // -// Type Lib: C:\Work\BfD\Source\Propagator\Common\BoldLockingSupportInterfaces.tlb (1) -// IID\LCID: {0EE38CD0-5848-4A2F-96E6-BFE2007AC6BD}\0 -// Helpfile: -// DepndLst: -// (1) v2.0 stdole, (C:\WINNT\System32\stdole2.tlb) -// (2) v4.0 StdVCL, (C:\WINNT\System32\STDVCL40.DLL) -// ************************************************************************ // -{$TYPEDADDRESS OFF} // Unit must be compiled without type-checked pointers. + + + + + + + + + + + + + + + + + + + + + + + + + + + + +{$TYPEDADDRESS OFF} interface uses Windows, ActiveX, Classes, Graphics, OleServer, OleCtrls, StdVCL; -// *********************************************************************// -// GUIDS declared in the TypeLibrary. Following prefixes are used: -// Type Libraries : LIBID_xxxx -// CoClasses : CLASS_xxxx -// DISPInterfaces : DIID_xxxx -// Non-DISP interfaces: IID_xxxx -// *********************************************************************// + + + + + const - // TypeLibrary Major and minor versions BoldLockingSupportInterfacesMajorVersion = 1; BoldLockingSupportInterfacesMinorVersion = 0; @@ -55,17 +51,13 @@ interface IID_IBoldLockManagerAdmin: TGUID = '{89074E8A-9A98-4D2A-A113-65F495611C6C}'; type -// *********************************************************************// -// Forward declaration of types defined in TypeLibrary -// *********************************************************************// + IBoldLockManager = interface; IBoldLockManagerAdmin = interface; -// *********************************************************************// -// Interface: IBoldLockManager -// Flags: (256) OleAutomation -// GUID: {105D857F-DD36-48F8-9554-ABCC212053ED} -// *********************************************************************// + + + IBoldLockManager = interface(IUnknown) ['{105D857F-DD36-48F8-9554-ABCC212053ED}'] function GetLocks(ClientId: Integer; TimeOut: Integer; RequestedExclusiveLocks: OleVariant; @@ -76,11 +68,9 @@ interface RequestedSharedLocks: OleVariant): WordBool; safecall; end; -// *********************************************************************// -// Interface: IBoldLockManagerAdmin -// Flags: (256) OleAutomation -// GUID: {89074E8A-9A98-4D2A-A113-65F495611C6C} -// *********************************************************************// + + + IBoldLockManagerAdmin = interface(IUnknown) ['{89074E8A-9A98-4D2A-A113-65F495611C6C}'] function ListAllClients(out Clients: OleVariant): HResult; safecall; diff --git a/Source/Propagator/Common/BoldObjectMarshaler.pas b/Source/Propagator/Common/BoldObjectMarshaler.pas index 01b8417..ae8512e 100644 --- a/Source/Propagator/Common/BoldObjectMarshaler.pas +++ b/Source/Propagator/Common/BoldObjectMarshaler.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldObjectMarshaler; interface @@ -27,7 +30,8 @@ implementation SysUtils, BoldUtils, comobj, - ActiveX; + ActiveX + ; { TBoldObjectMarshaler } @@ -48,7 +52,7 @@ destructor TBoldObjectMarshaler.Destroy; IStream(FStream) := nil; end; except on E: Exception do - BoldLogError('%s.Destroy: %s', [ClassName, E.Message]); // do not localize + BoldLogError('%s.Destroy: %s', [ClassName, E.Message]); end; inherited; end; @@ -63,13 +67,13 @@ function TBoldObjectMarshaler.MarshalObject( MSHCTX_INPROC, nil, MSHLFLAGS_TABLEWEAK); Result := true; except on E: Exception do - BoldLogError('%s.MarshalObject: %s', [ClassName, E.Message]); // do not localize + BoldLogError('%s.MarshalObject: %s', [ClassName, E.Message]); end; end; function TBoldObjectMarshaler.UnMarshalObject(out Obj): boolean; var - p: int64; + p: {$IFDEF BOLD_DELPHI13_OR_LATER}LargeUInt{$ELSE}int64{$ENDIF}; begin Result := false; try @@ -77,8 +81,10 @@ function TBoldObjectMarshaler.UnMarshalObject(out Obj): boolean; OleCheck(CoUnmarshalInterface(IStream(fStream), FMarshalIID, Obj)); Result := True; except on E: Exception do - BoldLogError('%s.UnMarshalObject: %s', [ClassName, E.Message]); // do not localize + BoldLogError('%s.UnMarshalObject: %s', [ClassName, E.Message]); end; end; +initialization + end. diff --git a/Source/Propagator/Common/BoldPropagatorConstants.pas b/Source/Propagator/Common/BoldPropagatorConstants.pas index ddeb9b5..dae20ed 100644 --- a/Source/Propagator/Common/BoldPropagatorConstants.pas +++ b/Source/Propagator/Common/BoldPropagatorConstants.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldPropagatorConstants; interface diff --git a/Source/Propagator/Common/BoldPropagatorGUIDs.pas b/Source/Propagator/Common/BoldPropagatorGUIDs.pas index ff5c39e..436cd09 100644 --- a/Source/Propagator/Common/BoldPropagatorGUIDs.pas +++ b/Source/Propagator/Common/BoldPropagatorGUIDs.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldPropagatorGUIDs; interface diff --git a/Source/Propagator/Common/BoldPropagatorInterfaces_TLB.pas b/Source/Propagator/Common/BoldPropagatorInterfaces_TLB.pas index 80f363d..1af8824 100644 --- a/Source/Propagator/Common/BoldPropagatorInterfaces_TLB.pas +++ b/Source/Propagator/Common/BoldPropagatorInterfaces_TLB.pas @@ -1,41 +1,37 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldPropagatorInterfaces_TLB; -// ************************************************************************ // -// WARNING -// ------- -// The types declared in this file were generated from data read from a -// Type Library. If this type library is explicitly or indirectly (via -// another type library referring to this type library) re-imported, or the -// 'Refresh' command of the Type Library Editor activated while editing the -// Type Library, the contents of this file will be regenerated and all -// manual modifications will be lost. -// ************************************************************************ // - -// PASTLWTR : 1.1 -// File generated on 2002-05-22 15:40:37 from Type Library described below. - -// ************************************************************************ // -// Type Lib: C:\Work\BFD\SOURCE\propagator\Common\BoldPropagatorInterfaces.tlb (1) -// IID\LCID: {DC6A300A-C8C2-4D26-9A8D-C8ECB164B54B}\0 -// Helpfile: -// DepndLst: -// (1) v2.0 stdole, (C:\WINNT\System32\stdole2.tlb) -// (2) v4.0 StdVCL, (C:\WINNT\System32\STDVCL40.DLL) -// ************************************************************************ // -{$TYPEDADDRESS OFF} // Unit must be compiled without type-checked pointers. + + + + + + + + + + + + + + + + + + +{$TYPEDADDRESS OFF} interface uses Windows, ActiveX, Classes, Graphics, OleServer, OleCtrls, StdVCL; -// *********************************************************************// -// GUIDS declared in the TypeLibrary. Following prefixes are used: -// Type Libraries : LIBID_xxxx -// CoClasses : CLASS_xxxx -// DISPInterfaces : DIID_xxxx -// Non-DISP interfaces: IID_xxxx -// *********************************************************************// + + + + + const - // TypeLibrary Major and minor versions BoldPropagatorInterfacesMajorVersion = 1; BoldPropagatorInterfacesMinorVersion = 0; @@ -49,9 +45,7 @@ interface CLASS_BoldListener: TGUID = '{A1582C23-E7AB-451A-837F-2131B425E73B}'; type -// *********************************************************************// -// Forward declaration of types defined in TypeLibrary -// *********************************************************************// + IBoldEventPropagator = interface; IBoldClientHandler = interface; IBoldListener = interface; @@ -59,19 +53,14 @@ interface IBoldListenerAdmin = interface; IBoldListenerAdminDisp = dispinterface; -// *********************************************************************// -// Declaration of CoClasses defined in Type Library -// (NOTE: Here we map each CoClass to its Default Interface) -// *********************************************************************// + + BoldPropagator = IBoldClientHandler; BoldListener = IBoldListener; -// *********************************************************************// -// Interface: IBoldEventPropagator -// Flags: (256) OleAutomation -// GUID: {BB7ABB77-BCE2-44C8-9510-F760F507A298} -// *********************************************************************// + + IBoldEventPropagator = interface(IUnknown) ['{BB7ABB77-BCE2-44C8-9510-F760F507A298}'] function SendEvents(BoldClientID: Integer; Events: OleVariant): HResult; stdcall; @@ -79,11 +68,9 @@ interface function CancelSubscriptions(BoldClientID: Integer; Subscriptions: OleVariant): HResult; stdcall; end; -// *********************************************************************// -// Interface: IBoldClientHandler -// Flags: (256) OleAutomation -// GUID: {A86E36B1-5EA3-4961-8448-45FD822A271E} -// *********************************************************************// + + + IBoldClientHandler = interface(IUnknown) ['{A86E36B1-5EA3-4961-8448-45FD822A271E}'] function RegisterClient(LeaseDuration: Integer; PollingInterval: Integer; @@ -93,67 +80,55 @@ interface function UnRegisterClient(BoldClientID: Integer): HResult; stdcall; end; -// *********************************************************************// -// Interface: IBoldListener -// Flags: (320) Dual OleAutomation -// GUID: {0326BF5B-F5AF-4BED-B5E1-F84D2549415A} -// *********************************************************************// + + + IBoldListener = interface(IUnknown) ['{0326BF5B-F5AF-4BED-B5E1-F84D2549415A}'] function ReceiveEvents(Events: OleVariant): Integer; safecall; end; -// *********************************************************************// -// DispIntf: IBoldListenerDisp -// Flags: (320) Dual OleAutomation -// GUID: {0326BF5B-F5AF-4BED-B5E1-F84D2549415A} -// *********************************************************************// + + + IBoldListenerDisp = dispinterface ['{0326BF5B-F5AF-4BED-B5E1-F84D2549415A}'] function ReceiveEvents(Events: OleVariant): Integer; dispid 1; end; -// *********************************************************************// -// Interface: IBoldListenerAdmin -// Flags: (320) Dual OleAutomation -// GUID: {7457EA48-E3B5-4E07-8496-87229ACA5E2D} -// *********************************************************************// + + + IBoldListenerAdmin = interface(IUnknown) ['{7457EA48-E3B5-4E07-8496-87229ACA5E2D}'] function Ping: Integer; safecall; procedure DisconnectClient(const aMessage: WideString; RemainDisconnected: Integer); safecall; end; -// *********************************************************************// -// DispIntf: IBoldListenerAdminDisp -// Flags: (320) Dual OleAutomation -// GUID: {7457EA48-E3B5-4E07-8496-87229ACA5E2D} -// *********************************************************************// + + + IBoldListenerAdminDisp = dispinterface ['{7457EA48-E3B5-4E07-8496-87229ACA5E2D}'] function Ping: Integer; dispid 1; procedure DisconnectClient(const aMessage: WideString; RemainDisconnected: Integer); dispid 2; end; -// *********************************************************************// -// The Class CoBoldPropagator provides a Create and CreateRemote method to -// create instances of the default interface IBoldClientHandler exposed by -// the CoClass BoldPropagator. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoBoldPropagator = class class function Create: IBoldClientHandler; class function CreateRemote(const MachineName: string): IBoldClientHandler; end; -// *********************************************************************// -// The Class CoBoldListener provides a Create and CreateRemote method to -// create instances of the default interface IBoldListener exposed by -// the CoClass BoldListener. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoBoldListener = class class function Create: IBoldListener; class function CreateRemote(const MachineName: string): IBoldListener; diff --git a/Source/Propagator/Common/PropagatorConsts.pas b/Source/Propagator/Common/PropagatorConsts.pas index b7db2cb..49fd119 100644 --- a/Source/Propagator/Common/PropagatorConsts.pas +++ b/Source/Propagator/Common/PropagatorConsts.pas @@ -86,4 +86,4 @@ interface implementation -end. \ No newline at end of file +end. diff --git a/Source/Propagator/Enterprise/BoldAbstractOutputQueueHandler.pas b/Source/Propagator/Enterprise/BoldAbstractOutputQueueHandler.pas index 4603792..d6faa70 100644 --- a/Source/Propagator/Enterprise/BoldAbstractOutputQueueHandler.pas +++ b/Source/Propagator/Enterprise/BoldAbstractOutputQueueHandler.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldAbstractOutputQueueHandler; interface @@ -8,7 +11,7 @@ interface type {forward declarations} TBoldAbstractOutputQueueHandler = class; - + TBoldAbstractOutputQueueHandler = class public procedure SendEvent(const ClientID: TBoldClientID; EventName: string); virtual; abstract; @@ -19,4 +22,9 @@ TBoldAbstractOutputQueueHandler = class implementation +uses + BoldRev; + +initialization + end. diff --git a/Source/Propagator/Enterprise/BoldAdvancedPropagator.pas b/Source/Propagator/Enterprise/BoldAdvancedPropagator.pas index cd2fb45..1cec0a8 100644 --- a/Source/Propagator/Enterprise/BoldAdvancedPropagator.pas +++ b/Source/Propagator/Enterprise/BoldAdvancedPropagator.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldAdvancedPropagator; interface @@ -16,7 +19,8 @@ interface BoldThreadSafeLog, IniFiles, BoldPropagatorMainForm, - Classes; + Classes + ; type {forward declarations} @@ -65,15 +69,14 @@ implementation BoldUtils, BoldPropagatorConstants, BoldDefs, - BoldPropagatorServer, - PropagatorConsts; + BoldPropagatorServer; {TBoldAdvancedPropagator} procedure TBoldAdvancedPropagator.Initialize; begin if fEnableLogging then BoldInitLog(fLogFileName, fErrorLogFileName, fThreadLogFileName, fMaxLogFileSize); - BoldLogError(sInitializing, [ClassName]); + BoldLogError('%s.Initialize: Starting..........................................', [ClassName]); fClientHandler := TBoldClientHandler.Create; fEnqueuer := TBoldEnqueuer.Create(fClientHandler); fUIManager := TUIManager.Create; @@ -117,7 +120,7 @@ destructor TBoldAdvancedPropagator.Destroy; FreeAndNil(fPriorityListEnlister); FreeAndNil(fClientHandler); end; - BoldLogError(sDestroying, [ClassName]); + BoldLogError('%s.Destroy: Closing down peacefully..........................................', [ClassName]); BoldDoneLog; inherited; @@ -152,7 +155,7 @@ procedure TBoldAdvancedPropagator.DoneDequeue(Sender: TObject); if Assigned(fUIManager) then fUIManager.SetDequeueIndicator(false); except on E: Exception do - BoldLogError('%s.DoneDequeue: %s', [ClassName, E.message]); // do not localize + BoldLogError('%s.DoneDequeue: error = %s', [ClassName, E.message]) end; end; @@ -160,11 +163,13 @@ procedure TBoldAdvancedPropagator.StartDequeue(Sender: TObject); begin if Assigned(fUIManager) then fUIManager.SetDequeueIndicator(true); -end; +end; function TBoldAdvancedPropagator.getClientHandler: TBoldClientHandler; begin Result := fClientHandler; end; +initialization + end. diff --git a/Source/Propagator/Enterprise/BoldAdvancedPropagatorCOM.pas b/Source/Propagator/Enterprise/BoldAdvancedPropagatorCOM.pas index b84e528..bc185c0 100644 --- a/Source/Propagator/Enterprise/BoldAdvancedPropagatorCOM.pas +++ b/Source/Propagator/Enterprise/BoldAdvancedPropagatorCOM.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldAdvancedPropagatorCOM; interface @@ -45,7 +48,6 @@ implementation {TBoldAdvancedPropagatorCOM} function TBoldAdvancedPropagatorCOM.GetBoldClientHandler: IBoldClientHandler; begin -// ClientHandlerCOMFactory.CreateInstance(nil, IID_IBoldClientHandler, Result); Result := ClienthandlerCOMFactory.CreateComObject(nil) as IBoldClientHandler; end; @@ -82,4 +84,6 @@ constructor TBoldPropagatorFactory.Create(ComServer: TComServerObject; const Cla inherited Create(ComServer, TBoldAdvancedPropagatorCOM, ClassID, ClassName, Description, ciMultiInstance, tmFree); end; +initialization + end. diff --git a/Source/Propagator/Enterprise/BoldClientHandler.pas b/Source/Propagator/Enterprise/BoldClientHandler.pas index 05c6c2b..6c38006 100644 --- a/Source/Propagator/Enterprise/BoldClientHandler.pas +++ b/Source/Propagator/Enterprise/BoldClientHandler.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldClientHandler; interface @@ -28,7 +31,7 @@ TBoldClientInfo = class; {TBoldClientHandler} TBoldClientHandler = class(TBoldPublisher) private - fClientInfoList: TBoldClientInfoList; //ClientInfoList sorted by ClientID + fClientInfoList: TBoldClientInfoList; fNOConnectedClients: integer; fEnabled: Boolean; fLockTime: TDateTime; @@ -50,7 +53,7 @@ TBoldClientHandler = class(TBoldPublisher) procedure AcquireLock; procedure ReleaseLock; protected - procedure EnqueueRemoveClientQueueEvent(const ClientId: TBoldClientId); virtual; // virtuality is for testcases... + procedure EnqueueRemoveClientQueueEvent(const ClientId: TBoldClientId); virtual; public constructor Create; virtual; destructor Destroy; override; {IBoldClientHandler} @@ -71,8 +74,7 @@ TBoldClientHandler = class(TBoldPublisher) function IsRegistered(const ClientId: TBoldClientId): Boolean; function DisconnectClient(const BoldClientId: TBoldClientId; const RegistrationTime: TTimeStamp): Boolean; procedure SendDisconnectRequest(const BoldClientId: TBoldClientId; const msg: string; RemainDisconnected: Integer); -// function ExternalRemoveClient(const ClientId: TBoldClientId; const RegistrationTime: TTimeStamp; -// const Reason: TBoldRemoveClientReasonType): Boolean; + function IsThereAClientTimingOutSoon(out ClientId: TBoldClientId; out RegistrationTime, LeaseTimeOut: TTimeStamp): Boolean; procedure RemoveExpiredLease(const ClientID: TBoldClientID; const RegistrationTime: TTimeStamp); @@ -83,7 +85,6 @@ TBoldClientHandler = class(TBoldPublisher) {$IFDEF DEBUG} procedure DebugLock; procedure DebugUnlock; - // this function can cause a deadlock between the client and the server if called at the wrong time, use with care! function ValidateClientInterface(const ListenerInterface: IBoldListener; const ClientIDString: string): Boolean; {$ENDIF} function GetListener(const ClientId: TBoldClientId; const RegistrationTime: TTimeStamp; out obj): Boolean; @@ -109,8 +110,7 @@ TBoldClientInfo = class fLongestIntervalBetweenEvents: TDateTime; fLostEvents: integer; fClientStatus: TBoldClientReceiveStatus; - // all instance variables should be cleared/initialized in - // TBoldClientInfo.Initialize + function LeaseIsExpired: Boolean; procedure ReInitializeListenerInterface; function GetClientStatusString: string; @@ -164,7 +164,6 @@ implementation uses BoldPropagatorConstants, BoldPropagatorServer, - PropagatorConsts, comobj; type @@ -199,7 +198,7 @@ constructor TBoldClientHandler.Create; begin inherited Create; fClientInfoList := TBoldClientInfoList.Create; - fClientHandlerLock := TBoldLoggableCriticalSection.Create('CH'); // do not localize + fClientHandlerLock := TBoldLoggableCriticalSection.Create('CH'); fLockTimeLock := TCriticalSection.Create; fNOConnectedClients := 0; fLockTime := 0; @@ -225,7 +224,7 @@ destructor TBoldClientHandler.Destroy; FreeAndNil(fClientHandlerLock); FreeAndNil(fLockTimeLock); except on E: Exception do - BoldLogError(sLogError, [ClassName, 'Destroy', E.Message]); // do not localize + BoldLogError('%s.Destroy Error: %s)', [ClassName, E.Message]); end; inherited; end; @@ -240,7 +239,7 @@ function TBoldClientHandler.InfoForClient(ClientID: TBoldClientID; out BoldClien Result := Assigned(BoldClientInfo); end; except on E: Exception do - BoldLogError(sLogErrorAndID, [ClassName, 'InfoForClient', ClientId, E.message]); // do not localize + BoldLogError('%s.InfoForClient Error: [ID=%d] %s)', [ClassName, ClientId, E.message]); end; end; @@ -259,13 +258,13 @@ function TBoldClientHandler.RegisterClient(LeaseDuration: Integer; PollingInterv RegistrationTime := fClientInfoList[BoldClientId].RegistrationTime; SendExtendedEvent(self, BOLD_PROPAGATOR_CLIENT_REGISTERED, [BoldClientID]); NotifyLeaseChanged; - BoldLog(sLoggingID, [ClientIdString, BoldClientId]); + BoldLog('Log In: %s [ID=%d]', [ClientIdString, BoldClientId]); inc(fTotalClients); if NoConnectedClients > fPeakClients then fPeakClients := NoConnectedClients; Result := S_OK; except on E: Exception do - BoldLogError(sLogErrorAndID, [ClassName, 'RegisterClient', BOldClientID, E.Message]); // do not localize + BoldLogError('%s.RegisterClient Error: [ID=%d] %s)', [ClassName, BOldClientID, E.Message]); end; finally ReleaseLock; @@ -291,12 +290,12 @@ function TBoldClientHandler.ExtendLease(BoldClientID: Integer; LeaseDuration: In NotifyLeaseChanged; end else - BoldLog(sExtendLeaseFailed, [BoldClientId]); + BoldLog('ExtendLease failed: [ID=%d] Client already disconnected ', [BoldClientId]); finally ReleaseLock; end; except on E: Exception do - BoldLogError(sLogErrorAndID, [ClassName, 'ExtendLease', BoldClientId, E.Message]); // do not localize + BoldLogError('%s.ExtendLease Error: [ID=%d] %s', [ClassName, BoldClientId, E.Message]); end; end; @@ -317,10 +316,9 @@ function TBoldClientHandler.UnRegisterClient(BoldClientID: Integer; Registration if InternalRemoveClient(BoldClientID) then begin Result := S_OK; - // notify all subscribers --- cleanup SendExtendedEvent(self, BOLD_PROPAGATOR_CLIENT_UNREGISTERED, [BoldClientID]); NotifyLeaseChanged; - BoldLog(sLogOff, + BoldLog('Log Off: %s [ID=%d] [Pkg: %d Ev: %d Int: %s Login: %s (%s ago) Status: %s]', [IdString, BoldClientId, ClientInfo.fSuccessfullyReceivedCount, ClientInfo.fSuccessfullyReceivedEventsCount, @@ -334,7 +332,7 @@ function TBoldClientHandler.UnRegisterClient(BoldClientID: Integer; Registration ReleaseLock; end; except on E: Exception do - BoldLogError(sLogErrorAndID, [ClassName, 'UnRegisterClient', BoldClientId, E.Message]); // do not localize + BoldLogError('%s.UnRegisterClient Error: [ID=%d] %s)', [ClassName, BoldClientId, E.Message]); end; end; @@ -343,7 +341,6 @@ function TBoldClientHandler.InternalRemoveClient(BoldClientId: TBoldClientID): B ClientInfo: TBoldClientInfo; begin Result := false; - // remove the clientid from the list if InfoForClient(BoldClientID, ClientInfo) and (ClientInfo.Initialized) then begin Result := true; @@ -374,7 +371,7 @@ procedure TBoldClientHandler.AddClient(const LeaseDuration: Integer; PollingInte ClientId := NewClientID; NOConnectedClients := NOConnectedClients + 1; except on E: Exception do - BoldLogError(sLogError, [ClassName, 'AddClient', E.Message]); // do not localize + BoldLogError('%s.AddClient: %s', [ClassName, E.Message]); end; end; @@ -396,7 +393,7 @@ procedure TBoldClientHandler.RemoveExpiredLease( IdString := ClientInfo.ClientIdentifierString; InternalRemoveClient(ClientID); SendExtendedEvent(self, BOLD_PROPAGATOR_CLIENT_LEASE_EXPIRED, [ClientID]); - BoldLog(sLeaseExpired, + BoldLog('Lease Expired: %s [ID=%d] [Pkg: %d Ev: %d Int: %s Last: %s ago Login: %s (%s ago) Status: %s]', [IdString, ClientID, ClientInfo.fSuccessfullyReceivedCount, ClientInfo.fSuccessfullyReceivedEventsCount, @@ -421,7 +418,7 @@ procedure TBoldClientHandler.GetRegisteredClientIDs(ClientIds: TStringList); if Assigned(ClientIds) then for i:= 0 to fClientInfoList.Count - 1 do if Assigned(fClientInfoList[i]) and fClientInfoList[i].Initialized then - ClientIds.Add(Format('%d=%s', [fClientInfoList[i].ClientId, fClientInfoList[i].ClientIdentifierString])); // do not localize + ClientIds.Add(Format('%d=%s', [fClientInfoList[i].ClientId, fClientInfoList[i].ClientIdentifierString])); finally ReleaseLock; end; @@ -447,18 +444,17 @@ function TBoldClientHandler.DisconnectClient( if InternalRemoveClient(BoldClientID) then begin Result := true; - // notify all subscribers --- cleanup SendExtendedEvent(self, BOLD_PROPAGATOR_CLIENT_CONNECTION_LOST, [BoldClientID]); NotifyLeaseChanged; if ClientInfo.fSuccessfullyReceivedCount = 0 then - BoldLog(sClientDisconnected, [ + BoldLog('Disconnected: %s [ID=%d] Login: %s (%s ago) Status: %s', [ IdString, BoldClientId, DateTimeToStr(TimeStampToDateTime(ClientInfo.RegistrationTime)), TimeToStr(now - TimeStampToDateTime(ClientInfo.RegistrationTime)), ClientInfo.ClientStatusString ]) else - BoldLog(sClientDisconnected_Long, + BoldLog('Disconnected: %s [ID=%d] [Pkg: %d Ev: %d Int: %s Last: %s ago Login: %s (%s) Status: %s]', [IdString, BoldClientId, ClientInfo.fSuccessfullyReceivedCount, ClientInfo.fSuccessfullyReceivedEventsCount, @@ -473,7 +469,7 @@ function TBoldClientHandler.DisconnectClient( ReleaseLock; end; except on E: Exception do - BoldLogError(sLogErrorAndID, [ClassName, 'DisconnectClient', BoldClientId, E.Message]); // do not localize + BoldLogError('%s.DisconnectClient Error: [ID=%d] %s)', [ClassName, BoldClientId, E.Message]); end; end; @@ -493,7 +489,7 @@ function TBoldClientHandler.GetRegistrationTime(const ClientID: TBoldClientId; ReleaseLock; end; except on E: Exception do - BoldLogError(sLogErrorAndID, [ClassName, 'GetRegistrationTime', ClientID, E.Message]); // do not localize + BoldLogError('%s.GetRegistrationTime Error: [ID=%d] %s)', [ClassName, ClientID, E.Message]); end; end; @@ -523,9 +519,9 @@ procedure TBoldClientHandler.GetRegisteredClientInfos( try Guard := TBoldGuard.Create(Temp); Temp := TStringList.Create; - Temp.Add('TotalClients='+IntToStr(fTotalClients)); // do not localize - Temp.Add('PeakClients='+IntToStr(fPeakClients)); // do not localize - Temp.Add('TotalLostEvents='+IntToStr(fTotalLostEvents)); // do not localize + Temp.Add('TotalClients='+IntToStr(fTotalClients)); + Temp.Add('PeakClients='+IntToStr(fPeakClients)); + Temp.Add('TotalLostEvents='+IntToStr(fTotalLostEvents)); ClientInfo.Add(temp.CommaText); if Assigned(ClientInfo) then for i:= 0 to fClientInfoList.Count - 1 do @@ -533,16 +529,16 @@ procedure TBoldClientHandler.GetRegisteredClientInfos( begin ClientInfoItem := fClientInfoList[i]; temp.Clear; - Temp.Add('ID=' +IntToStr(ClientInfoItem.ClientId)); // do not localize - Temp.Add('IDString=' +ClientInfoItem.ClientIdentifierString); // do not localize - Temp.Add('RegistrationTime=' +FormatDateTime('yyyy-mm-dd hh:nn:ss', TimeStampToDateTime(ClientInfoItem.RegistrationTime))); // do not localize - Temp.Add('LeaseTimeout=' +FormatDateTime('yyyy-mm-dd hh:nn:ss', TimeStampToDateTime(ClientInfoItem.LeaseTimeOut))); // do not localize - temp.add('Packages=' +intToStr(ClientInfoItem.fSuccessfullyReceivedCount)); // do not localize - temp.add('Events=' +intToStr(ClientInfoItem.fSuccessfullyReceivedEventsCount)); // do not localize - temp.add('LastSend=' +FormatDateTime('yyyy-mm-dd hh:nn:ss', ClientInfoItem.fLastSuccessfullReceive)); // do not localize - temp.add('LongestInterval=' +FormatDateTime('yyyy-mm-dd hh:nn:ss', ClientInfoItem.fLongestIntervalBetweenEvents)); // do not localize - temp.add('LostEvents=' +IntToStr(ClientInfoItem.fLostEvents)); // do not localize - temp.Add('Status=' +ClientInfoItem.ClientStatusString); // do not localize + Temp.Add('ID=' +IntToStr(ClientInfoItem.ClientId)); + Temp.Add('IDString=' +ClientInfoItem.ClientIdentifierString); + Temp.Add('RegistrationTime=' +FormatDateTime('yyyy-mm-dd hh:nn:ss', TimeStampToDateTime(ClientInfoItem.RegistrationTime))); + Temp.Add('LeaseTimeout=' +FormatDateTime('yyyy-mm-dd hh:nn:ss', TimeStampToDateTime(ClientInfoItem.LeaseTimeOut))); + temp.add('Packages=' +intToStr(ClientInfoItem.fSuccessfullyReceivedCount)); + temp.add('Events=' +intToStr(ClientInfoItem.fSuccessfullyReceivedEventsCount)); + temp.add('LastSend=' +FormatDateTime('yyyy-mm-dd hh:nn:ss', ClientInfoItem.fLastSuccessfullReceive)); + temp.add('LongestInterval=' +FormatDateTime('yyyy-mm-dd hh:nn:ss', ClientInfoItem.fLongestIntervalBetweenEvents)); + temp.add('LostEvents=' +IntToStr(ClientInfoItem.fLostEvents)); + temp.Add('Status=' +ClientInfoItem.ClientStatusString); ClientInfo.Add(Temp.CommaText); end; finally @@ -601,7 +597,7 @@ function TBoldClientHandler.IsThereAClientTimingOutSoon( ReleaseLock; end; except on E: Exception do - BoldLogError(sLogError, [ClassName, 'IsThereAClientTimingOutSoon', E.Message]); // do not localize + BoldLogError('%s.IsThereAClientTimingOutSoon Error: %s', [ClassName, E.Message]); end; end; @@ -758,7 +754,7 @@ function TBoldClientHandler.GetFirstLeaseTimeOutClient: TBoldClientInfo; end; end; except on E: Exception do - BoldLogError(sLogError, [ClassName, 'GetFirstLeaseTimeOutClient', E.Message]); // do not localize + BoldLogError('%s.GetFirstLeaseTimeOutClient Error: %s', [ClassName, E.Message]); end; end; @@ -834,21 +830,21 @@ function TBoldClientHandler.ValidateClientInterface( if Result then begin Events := TStringList.Create; - Events.Add('L'); {TODO: change this to a ping message} + Events.Add('L'); try OleCheck(ListenerInterface.ReceiveEvents(StringListToVarArray(Events))); except on E: Exception do begin Result := false; - ErrorMsg := Format(sInvalidListener, [ClassName, ClientIdString, E.Message]); + ErrorMsg := Format('%s.ValidateClientInterface: ClientListener not valid for Client %s; Error=%s', [ClassName, ClientIdString, E.Message]); if E is EOleSysError then - ErrorMsg := ErrorMsg + Format(sErrorCode, [(E as EOleSysError).ErrorCode]); + ErrorMsg := ErrorMsg + Format(' ErrorCode=%d', [(E as EOleSysError).ErrorCode]); BoldLogError(ErrorMsg); end; end; end else - BoldLogError(sListenerInterfaceMissing, [ClassName, ClientIdString]); + BoldLogError('%s.ValidateClientInterface Error: [ID=%s] Listener interface missing', [ClassName, ClientIdString]); end; {$ENDIF} @@ -870,7 +866,7 @@ procedure TBoldClientHandler.MarkHasReceivedEvents(const ClientID: TBoldClientID if ClientInfo.fClientStatus = crsNotReceiving then begin ClientInfo.fClientStatus := crsRecovered; - BoldLogError(sClientHasRecovered, [ + BoldLogError('!!! Client %s (%d) has recovered and received %d messages', [ ClientInfo.ClientIdentifierString, ClientId, EventCount]); end; @@ -892,7 +888,7 @@ procedure TBoldClientHandler.MarkFailedToReceiveEvents(const ClientId: TBoldClie begin ClientInfo.fLostEvents := ClientInfo.fLostEvents + EventCount; ClientInfo.fClientStatus := crsNotReceiving; - inc(fTotalLostEvents, EventCount); + inc(fTotalLostEvents, EventCount); end; finally ReleaseLock; @@ -952,7 +948,7 @@ procedure TBoldClientHandler.SendDisconnectRequest(const BoldClientId: TBoldClie ReleaseLock; end; except on E: Exception do - BoldLogError(sLogErrorAndID, [ClassName, 'SendDisconnectRequest', BoldClientId, E.Message]); // do not localize + BoldLogError('%s.SendDisconnectRequest Error: [ID=%d] %s)', [ClassName, BoldClientId, E.Message]); end; end; @@ -988,7 +984,7 @@ procedure TBoldClientInfo.Initialize(LeaseTime, PollingInterval: Cardinal; fClientStatus := crsOK; fInitialized := true; except on E: Exception do - BoldLogError(sLogErrorAndID, [ClassName, 'Initialize', ClientIdString, E.Message]); // do not localize + BoldLogError('%s.Initialize Error: [ID=%s] %s', [ClassName, ClientIdString, E.Message]); end; end; @@ -1004,7 +1000,7 @@ procedure TBoldClientInfo.UnInitialize; fInitialized := false; end except on E: Exception do - BoldLogError(sLogError, [ClassName, 'UnInitialize', E.Message]); // do not localize + BoldLogError('%s.UnInitialize Error: %s', [ClassName, E.Message]); end; end; @@ -1018,7 +1014,7 @@ function TBoldClientInfo.LeaseIsExpired: Boolean; CurrentTime := DateTimetoTimeStamp(Now); Result := TimeStampComp(LeaseTimeOut, CurrentTime) <= 0; except on E: Exception do - BoldLogError(sLogErrorAndID, [ClassName, 'LeaseIsExpired', ClientID, E.Message]); // do not localize + BoldLogError('%s.LeaseIsExpired Error: [ID=%d] %s', [ClassName, ClientID, E.Message]); end; end; @@ -1031,11 +1027,11 @@ procedure TBoldClientInfo.ReInitializeListenerInterface; function TBoldClientInfo.GetClientStatusString: string; begin case fClientStatus of - crsOK: result := sOK; - crsNotReceiving: result := sNotReceiving; - crsRecovered: result := sRecovered; - else result := sUnknown; - end; + crsOK: result := 'OK'; + crsNotReceiving: result := 'Not Receiving'; + crsRecovered: result := 'Recovered'; + else result := ''; + end; end; procedure TBoldClientInfo.ExtendLease(LeaseDuration: integer); @@ -1137,7 +1133,7 @@ function TBoldClientInfoList.GetExistingClientInfo( if ((Index >= 0) and (Index < fList.Count)) then Result := (fList[Index] as TBoldClientInfo); except on E: Exception do - BoldLogError(sLogErrorAndID, [ClassName, 'GetExistingClientInfo', index, E.message]); // do not localize + BoldLogError('%s.GetExistingClientInfo Error: [ID=%d] %s', [ClassName, index, E.message]); end; end; @@ -1159,4 +1155,5 @@ procedure TBoldClientInfoList.ReturnFreeClientID( fFreeClientIds.Add(Pointer(ClientId)); end; +initialization end. diff --git a/Source/Propagator/Enterprise/BoldClientHandlerCOM.pas b/Source/Propagator/Enterprise/BoldClientHandlerCOM.pas index ae7b9e0..13b1f7e 100644 --- a/Source/Propagator/Enterprise/BoldClientHandlerCOM.pas +++ b/Source/Propagator/Enterprise/BoldClientHandlerCOM.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldClientHandlerCOM; interface @@ -9,7 +12,8 @@ interface BoldThreadSafeLog, BoldClientHandler, BoldPropagatorInterfaces_TLB, - BoldThreadedComObjectFactory; + BoldThreadedComObjectFactory + ; type {forward declarations} @@ -55,7 +59,6 @@ TBoldClientHandlerThreadedCOMFactory = class(TBoldThreadedComObjectFactory) var ClientHandlerCOMFactory: TBoldClientHandlerThreadedCOMFactory; -// ClientHandlerCOMFactory: TBoldClientHandlerCOMFactory; implementation uses @@ -69,20 +72,20 @@ function TBoldClientHandlerCOM.RegisterClient(LeaseDuration: Integer; PollingInt const BoldClientListener: IBoldListener; const ClientIDString: WideString; out BoldClientID: Integer): HResult; stdcall; begin - BoldLogThread('ID=ClientHandler/RegCli'); // do not localize + BoldLogThread('ID=ClientHandler/RegCli'); Result := ClientHandler.RegisterClient(LeaseDuration, PollingInterval, BoldClientListener, ClientIDString, BoldClientID, fRegistrationTime); end; function TBoldClientHandlerCOM.ExtendLease(BoldClientID: Integer; LeaseDuration: Integer; out ExtensionOK: WordBool): HResult; stdcall; begin - BoldLogThread('ID=ClientHandler/ExtLease'); // do not localize + BoldLogThread('ID=ClientHandler/ExtLease'); Result := ClientHandler.ExtendLease(BoldClientID, LeaseDuration, ExtensionOK); end; function TBoldClientHandlerCOM.UnRegisterClient(BoldClientID: Integer): HResult; stdcall; begin - BoldLogThread('ID=ClientHandlerH/UnReg'); // do not localize + BoldLogThread('ID=ClientHandlerH/UnReg'); Result := ClientHandler.UnRegisterClient(BoldClientID, fRegistrationTime); end; @@ -122,4 +125,6 @@ function TBoldClientHandlerThreadedCOMFactory.CreateComObject( (Result as TBoldClientHandlerCOM).ClientHandler := ClientHandler; end; +initialization + end. diff --git a/Source/Propagator/Enterprise/BoldClientHandlerExportHandle.pas b/Source/Propagator/Enterprise/BoldClientHandlerExportHandle.pas index 5e36dc4..063990b 100644 --- a/Source/Propagator/Enterprise/BoldClientHandlerExportHandle.pas +++ b/Source/Propagator/Enterprise/BoldClientHandlerExportHandle.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldClientHandlerExportHandle; interface @@ -43,7 +46,6 @@ constructor TBoldClientHandlerExportHandle.Create(Active: Boolean; ServerHandle: function TBoldClientHandlerExportHandle.GetComObject: IUnknown; begin Result := CreateComObject(TBoldPropagatorServer.Instance.ClientHandlerCLSID); -//Result := TBoldClientHandlerCOM.CreateFromFactory(ClientHandlerCOMFactory, nil) as IUnknown; end; function TBoldClientHandlerExportHandle.GetHandledObject: TObject; @@ -51,4 +53,5 @@ function TBoldClientHandlerExportHandle.GetHandledObject: TObject; Result := nil; end; +initialization end. diff --git a/Source/Propagator/Enterprise/BoldClientNotifierHandler.pas b/Source/Propagator/Enterprise/BoldClientNotifierHandler.pas index cb03906..de8b832 100644 --- a/Source/Propagator/Enterprise/BoldClientNotifierHandler.pas +++ b/Source/Propagator/Enterprise/BoldClientNotifierHandler.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldClientNotifierHandler; interface @@ -105,8 +108,7 @@ implementation BoldGuard, BoldPriorityListEnlister, BoldPropagatorServer, - comobj, - PropagatorConsts; + comobj; { TBoldClientNotifierHandler } @@ -116,26 +118,26 @@ procedure TBoldClientNotifierHandler.Execute; begin try EnsureMessageQueue; - BoldLogThread('ID=ClientNotifierHandler'); // do not localize + BoldLogThread('ID=ClientNotifierHandler'); SignalReady; while not Terminated do begin if PeekMessage(rMsg, 0, 0, 0, PM_REMOVE) then begin - if rMsg.Message = WM_QUIT then // terminated + if rMsg.Message = WM_QUIT then Terminate - else if rMsg.message = BM_PRIORITY_CHANGED then // signal from PriorityList + else if rMsg.message = BM_PRIORITY_CHANGED then ProcessPriorityListHead else DispatchMessage(rMsg); end - else if fScheduledClients.Count > 0 then //if no messages to process then empty scheduled clients' queue + else if fScheduledClients.Count > 0 then ProcessScheduledClientsHead - else // if nothing to do then wait for a message + else WaitMessage; - end; //while + end; except on E: Exception do - BoldLogError(sLogError, [ClassName, 'Execute', E.Message]); // do not localize + BoldLogError('%s.Execute (Error: %s)', [ClassName, E.Message]); end; FreeAndNil(fTimer); end; @@ -153,7 +155,7 @@ function TBoldClientNotifierHandler.getClientNotifierPool: TBoldClientNotifierPo function TBoldClientNotifierHandler.getTimer: TTimer; begin Assert(GetCurrentThreadId = self.ThreadID, - Format('%s.getTimer: Timer should be accessed from %s''s thread', [ClassName])); // do not localize + Format('%s.getTimer: Timer should be accessed from %s''s thread', [ClassName])); if not Assigned(fTimer) then begin fTimer := TTimer.Create(nil); @@ -168,7 +170,7 @@ procedure TBoldClientNotifierHandler.OnPriorityChanged(Sender: TObject); PriorityQueue: TBoldPriorityQueue; begin Assert(Sender is TBoldPriorityQueue, - Format('%s.OnPriorityChanged: Sender is not a TBoldPriorityQueue', [ClassName])); // do not localize + Format('%s.OnPriorityChanged: Sender is not a TBoldPriorityQueue', [ClassName])); PriorityQueue := Sender as TBoldPriorityQueue; if Assigned(PriorityQueue.Head) then Notify(BM_PRIORITY_CHANGED); @@ -198,15 +200,15 @@ procedure TBoldClientNotifierHandler.SendtoClient; try aData := TBoldClientNotifierData.CreateInitialized(ClientQueueInfo.ClientID, RegistrationTime, ClientQueueInfo.QueueAsVarArray); - fScheduledClients.Push(Pointer(aData)); // add to scheduled clients' list - while ProcessScheduledClientsHead do; // empty scheduled clients' list + fScheduledClients.Push(Pointer(aData)); + while ProcessScheduledClientsHead do; except - raise EBold.CreateFmt(sFailedToSendToClient, [ClassName]); + raise EBold.CreateFmt('%s.SendToClient: could not send events to client', [ClassName]); end; finally FreeAndNil(ClientQueueInfo); end; - end; + end; end; procedure TBoldClientNotifierHandler.ProcessPriorityListHead; @@ -223,8 +225,8 @@ procedure TBoldClientNotifierHandler.ProcessPriorityListHead; begin CurrentTime := DateTimeToTimeStamp(Now); if(ClientQueueInfo.TimeOut.Date <= CurrentTime.Date) and - ((ClientQueueInfo.TimeOut.Time - CurrentTime.Time) <= 1) then //FIXME!! - SendToClient //send immediately + ((ClientQueueInfo.TimeOut.Time - CurrentTime.Time) <= 1) then + SendToClient else SetTimer(ClientQueueInfo.TimeOut); end; @@ -293,6 +295,7 @@ procedure TBoldClientNotifierHandler.SetPriorityList( end; end; + { TBoldClientNotifier } constructor TBoldClientNotifier.Create(AOwner: TBoldClientNotifierhandler); @@ -306,9 +309,9 @@ procedure TBoldClientNotifier.Execute; function BoolToStr(value: Boolean): string; begin if Value then - Result := 'True' // do not localize + Result := 'True' else - Result := 'False'; // do not localize + Result := 'False'; end; var res: integer; @@ -326,18 +329,17 @@ procedure TBoldClientNotifier.Execute; begin EnsureMessageQueue; SignalReady; - BoldLogThread('ID=ClientNotifier'); // do not localize + BoldLogThread('ID=ClientNotifier'); fAvailableEvent.SetEvent; while not (Terminated) do begin res := Integer(getMessage(rMsg, 0, 0, 0)); - if res = -1 then //error + if res = -1 then Terminate - else if res = 0 then // terminated + else if res = 0 then Terminate else if rMsg.message = BM_THRD_DOWORK then begin - // Do work here CoInitializeEx(nil, CoInitFlags); try if Owner.ClientHandler.GetListener(fClientData.FclientId, @@ -351,18 +353,16 @@ procedure TBoldClientNotifier.Execute; end; except on E: Exception do begin - // retrieve client information Owner.ClientHandler.HasInfoForClient(fClientData.FClientID, clientIdentifier, registrationTime, initialized, Status); Owner.ClientHandler.HasInfoForClient(fClientData.FClientID, clientIdentifier, LeaseDuration, pollingInterval, LeaseTimeout, Initialized); RegistrationTimeDT := TimeStampToDateTime(RegistrationTime); LeaseTimeoutDT := TimeStampToDateTime(LeaseTimeout); Owner.ClientHandler.MarkFailedToReceiveEvents(fClientData.FClientID, VarArrayHighBound(fClientData.fEvents, 1)+1); - // Log the error if Owner.fDisconnectClientsOnSendFailure then - DisconnectMsg := sDisconnectMsg + DisconnectMsg := ' [Disconnected]' else DisconnectMsg := ''; - BoldLogError(sClientFailure, [ + BoldLogError('%s.Execute: Client %s (ID=%d)%s failed to receive messages (%d msgs): %s. RegistrationTime: %s (%s ago), LeaseTimeout: %s (%s left)', [ ClassName, ClientIdentifier, fClientData.FClientId, @@ -373,7 +373,6 @@ procedure TBoldClientNotifier.Execute; TimeToStr(LeaseTimeoutDT), TimeToStr(now-LeaseTimeOutDT)]); if Owner.fDisconnectClientsOnSendFailure then - // disconnect the client Owner.DisconnectClient(fClientData.FClientID, fClientData.fRegistrationTime); end; end; @@ -388,7 +387,7 @@ procedure TBoldClientNotifier.Execute; else begin DispatchMessage(rMsg); end; - end; //while + end; if Assigned(fClientData) then FreeAndNil(fClientData); end; @@ -470,13 +469,13 @@ function TBoldClientNotifierPool.ScheduleClientNotifier(mData: TBoldClientNotifi ClientNotifier := TBoldClientNotifier(fThreadList[CurrentThread]); if ClientNotifier.IsAvailable then begin - ClientNotifier.SetClientData(mData); // should be freed by the clientnotifier + ClientNotifier.SetClientData(mData); ClientNotifier.DoWork; Result := true; end; CurrentThread := (CurrentThread + 1) mod fPoolSize; except on E: Exception do - BoldLogError(sLogError, [ClassName, 'ScheduleClientNotifier', E.Message]); // do not localize + BoldLogError('%s.ScheduleClientNotifier: %s', [ClassName, E.Message]); end; end; @@ -490,7 +489,6 @@ constructor TBoldClientNotifierData.CreateInitialized(const ClientID: TBoldClien fRegistrationTime := RegistrationTime; end; -end. - - +initialization +end. diff --git a/Source/Propagator/Enterprise/BoldClientQueue.pas b/Source/Propagator/Enterprise/BoldClientQueue.pas index ad5161d..7541299 100644 --- a/Source/Propagator/Enterprise/BoldClientQueue.pas +++ b/Source/Propagator/Enterprise/BoldClientQueue.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldClientQueue; interface @@ -24,7 +27,8 @@ implementation uses SysUtils, - BoldUtils; + BoldUtils, + BoldRev; { TBoldClientQueue } @@ -34,7 +38,7 @@ function TBoldClientQueue.AsVarArray: variant; begin Lock; try - if UnsafeIsEmpty then // already in lock + if UnsafeIsEmpty then Result := UnAssigned else begin @@ -47,4 +51,6 @@ function TBoldClientQueue.AsVarArray: variant; end; end; +initialization + end. diff --git a/Source/Propagator/Enterprise/BoldComServiceRegister.pas b/Source/Propagator/Enterprise/BoldComServiceRegister.pas index e94962a..1ab19d3 100644 --- a/Source/Propagator/Enterprise/BoldComServiceRegister.pas +++ b/Source/Propagator/Enterprise/BoldComServiceRegister.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldComServiceRegister; interface @@ -26,7 +29,7 @@ TBoldComServiceRegister = class procedure RegisterClassFactories(const Reg: Boolean; const AppId: string; ClsIds: array of string); -procedure RegisterServerAsService(const bReg: Boolean; const ClassID, ServiceName: string); +procedure RegisterServerAsService(const bReg: Boolean; const ClassID, ServiceName: string); implementation @@ -47,7 +50,7 @@ procedure DeleteAppId(const RootKey: DWord; const Key: string); try Reg.RootKey := RootKey; if Reg.OpenKey(Key, False) - then Reg.DeleteValue('AppID'); // do not localize + then Reg.DeleteValue('AppID'); finally Reg.CloseKey; Reg.Free; @@ -81,8 +84,8 @@ procedure RegisterServerAsService(const bReg: Boolean; const ClassID, ServiceNam Reg := TRegistry.Create; try Reg.RootKey := HKEY_CLASSES_ROOT; - if Reg.OpenKey('AppID\' + ClassID, False) // do not localize - then Reg.DeleteValue('LocalService'); // do not localize + if Reg.OpenKey('AppID\' + ClassID, False) + then Reg.DeleteValue('LocalService'); finally Reg.CloseKey; Reg.Free; @@ -100,13 +103,13 @@ procedure RegisterClassFactories(const Reg: Boolean; begin comserv.comserver.UpdateRegistry(true); for i := 0 to High(ClsIds) do - CreateRegKey(Format('%s\%s', ['CLSID', ClsIds[i]]), 'AppID', AppId); // do not localize + CreateRegKey(Format('%s\%s', ['CLSID', ClsIds[i]]), 'AppID', AppId); end else begin comserv.comserver.UpdateRegistry(false); for i := 0 to High(ClsIds) do - DeleteAppId(HKEY_CLASSES_ROOT, Format('%s\%s', ['CLSID', ClsIds[i]])); // do not localize + DeleteAppId(HKEY_CLASSES_ROOT, Format('%s\%s', ['CLSID', ClsIds[i]])); end; end; @@ -118,10 +121,10 @@ procedure RegisterAppIdForClass(const Reg: Boolean; begin if Reg then for i := 0 to High(ClsIds) do - CreateRegKey(Format('%s\%s', ['CLSID', ClsIds[i]]), 'AppID', AppId) // do not localize + CreateRegKey(Format('%s\%s', ['CLSID', ClsIds[i]]), 'AppID', AppId) else for i := 0 to High(ClsIds) do - DeleteAppId(HKEY_CLASSES_ROOT, Format('%s\%s', ['CLSID', ClsIds[i]])); // do not localize + DeleteAppId(HKEY_CLASSES_ROOT, Format('%s\%s', ['CLSID', ClsIds[i]])); end; procedure DeleteCLSIDs(const RootKey: DWord; ClsIds: array of string); @@ -133,7 +136,7 @@ procedure DeleteCLSIDs(const RootKey: DWord; ClsIds: array of string); Reg.RootKey := RootKey; try for i := 0 to High(ClsIds) do - Reg.DeleteKey(Format('%s\%s', ['CLSID', ClsIds[i]])); // do not localize + Reg.DeleteKey(Format('%s\%s', ['CLSID', ClsIds[i]])); finally Reg.CloseKey; Reg.Free; @@ -167,4 +170,6 @@ procedure TBoldComServiceRegister.DoServiceStop; RegisterClassFactories(False, AppID, [AppID]); end; +initialization + end. diff --git a/Source/Propagator/Enterprise/BoldEnqueuer.pas b/Source/Propagator/Enterprise/BoldEnqueuer.pas index 0a86808..bb5866f 100644 --- a/Source/Propagator/Enterprise/BoldEnqueuer.pas +++ b/Source/Propagator/Enterprise/BoldEnqueuer.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldEnqueuer; interface @@ -12,7 +15,8 @@ interface BoldLoggableCriticalSection, BoldThreadSafeLog, windows, - classes; + classes +; type TBoldExternalEventType = (bemEvent, bemSubscription, bemCancelSubscription, bemRemoveClientQueue, @@ -88,11 +92,11 @@ constructor TBoldEnqueuer.Create(ClientHandler: TBoldClientHandler); begin inherited Create; FClientHandler := ClientHandler; - fLock := TBoldLoggableCriticalSection.Create('EQ'); // do not localize + fLock := TBoldLoggableCriticalSection.Create('EQ'); fLock.Acquire; try fEnabled := false; - fInQueue := TBoldExternalEventThreadSafeObjectQueue.Create('InQ'); // do not localize + fInQueue := TBoldExternalEventThreadSafeObjectQueue.Create('InQ'); fEnabled := true; finally fLock.Release; @@ -111,7 +115,7 @@ function TBoldEnqueuer.SendEvents(BoldClientID: Integer; Events: OleVariant): H except on E: Exception do begin Result := E_FAIL; - BoldLogError('%s.SendEvents ClientId=%d: %s', [ClassName, BoldClientId, E.Message]); // do not localize + BoldLogError('%s.SendEvents ClientId=%d: %s', [ClassName, BoldClientId, E.Message]); end; end; finally @@ -131,7 +135,7 @@ function TBoldEnqueuer.AddSubscriptions(BoldClientID: Integer; Subscriptions: O except on E: Exception do begin Result := E_FAIL; - BoldLogError('%s.AddSubscriptions ClientId=%d: %s', [ClassName, BoldClientId, E.Message]); // do not localize + BoldLogError('%s.AddSubscriptions ClientId=%d: %s', [ClassName, BoldClientId, E.Message]); end; end; finally @@ -150,7 +154,7 @@ function TBoldEnqueuer.CancelSubscriptions(BoldClientID: Integer; Subscriptions except on E: Exception do begin Result := E_FAIL; - BoldLogError('%s.CancelSubscriptions ClientId=%d: %s', [ClassName, BoldClientId, E.Message]); // do not localize + BoldLogError('%s.CancelSubscriptions ClientId=%d: %s', [ClassName, BoldClientId, E.Message]); end; end; finally @@ -188,7 +192,7 @@ function TBoldEnqueuer.SendLockEvent(BoldClientID: Integer; FInQueue.Enqueue(TBoldExternalEvent.Create(BoldClientID, bemLockLost, Event)); Result := True; except on E: Exception do - BoldLogError('%s.SendLockEvent ClientId=%d: %s', [ClassName, BoldClientId, E.Message]); // do not localize + BoldLogError('%s.SendLockEvent ClientId=%d: %s', [ClassName, BoldClientId, E.Message]); end; end; finally @@ -241,7 +245,6 @@ function TBoldEnqueuer.CheckStatus(ClientId: TBoldClientId; VarArray: OLEVariant result := W_CLIENT_NOT_RECEIVING else result := S_OK; - // Currently, do not inform the client about the warning... result := S_OK; end; @@ -263,4 +266,5 @@ procedure TBoldExternalEventThreadSafeObjectQueue.EnqueueVarArray( end; end; +initialization end. diff --git a/Source/Propagator/Enterprise/BoldEnqueuerCOM.pas b/Source/Propagator/Enterprise/BoldEnqueuerCOM.pas index 6ad5ee0..96f28df 100644 --- a/Source/Propagator/Enterprise/BoldEnqueuerCOM.pas +++ b/Source/Propagator/Enterprise/BoldEnqueuerCOM.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldEnqueuerCOM; interface @@ -58,14 +61,14 @@ implementation function TBoldEnqueuerCOM.AddSubscriptions(BoldClientID: Integer; Subscriptions: OleVariant): HResult; begin - BoldLogThread('ID=Enqueuer/AddS'); // do not localize + BoldLogThread('ID=Enqueuer/AddS'); Result := Enqueuer.AddSubscriptions(BoldClientID, Subscriptions); end; function TBoldEnqueuerCOM.CancelSubscriptions(BoldClientID: Integer; Subscriptions: OleVariant): HResult; begin - BoldLogThread('ID=Enqueuer/CancelS'); // do not localize + BoldLogThread('ID=Enqueuer/CancelS'); Result := Enqueuer.CancelSubscriptions(BoldClientID, Subscriptions); end; @@ -84,7 +87,7 @@ procedure TBoldEnqueuerCOM.Initialize; function TBoldEnqueuerCOM.SendEvents(BoldClientID: Integer; Events: OleVariant): HResult; begin - BoldLogThread('ID=Enqueuer/SendEv'); // do not localize + BoldLogThread('ID=Enqueuer/SendEv'); Result := Enqueuer.SendEvents(BoldClientId, Events); end; @@ -104,4 +107,6 @@ function TBoldEnqueuerThreadedCOMFactory.CreateComObject( (Result as TBoldEnqueuerCOM).Enqueuer := Enqueuer; end; +initialization + end. diff --git a/Source/Propagator/Enterprise/BoldEnqueuerExportHandle.pas b/Source/Propagator/Enterprise/BoldEnqueuerExportHandle.pas index 75c7552..b053d78 100644 --- a/Source/Propagator/Enterprise/BoldEnqueuerExportHandle.pas +++ b/Source/Propagator/Enterprise/BoldEnqueuerExportHandle.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldEnqueuerExportHandle; interface @@ -43,7 +46,6 @@ constructor TBoldEnqueuerExportHandle.Create(Active: Boolean; ServerHandle: TBol function TBoldEnqueuerExportHandle.GetComObject: IUnknown; begin Result := CreateComObject(TBoldPropagatorServer.Instance.EnqueuerCLSID); -// Result := TBoldEnqueuerCOM.CreateFromFactory(EnqueuerCOMFactory, nil) as IUnknown; end; function TBoldEnqueuerExportHandle.GetHandledObject: TObject; @@ -51,4 +53,5 @@ function TBoldEnqueuerExportHandle.GetHandledObject: TObject; Result := nil; end; +initialization end. diff --git a/Source/Propagator/Enterprise/BoldIndexList.pas b/Source/Propagator/Enterprise/BoldIndexList.pas index b65bc4a..0a49660 100644 --- a/Source/Propagator/Enterprise/BoldIndexList.pas +++ b/Source/Propagator/Enterprise/BoldIndexList.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldIndexList; interface @@ -80,7 +83,6 @@ constructor TBoldIndexList.Create(const IndexOrder: integer); procedure TBoldIndexList.DeleteINodeByKey(Key: variant); begin - //overriden in derived classes end; procedure TBoldIndexList.RemoveKey(Key: variant); @@ -97,7 +99,7 @@ procedure TBoldIndexList.RemoveKey(Key: variant); end; if Assigned(iNode) then begin - iNode.next := nil; // is this necessary??? + iNode.next := nil; DeleteINodeByKey(Key); end; end; @@ -155,4 +157,6 @@ procedure TBoldAbstractMultiIndexedList.RemoveKey(IndexOrder: integer; Indices[IndexOrder].RemoveKey(Key); end; +initialization + end. diff --git a/Source/Propagator/Enterprise/BoldIndexedList.pas b/Source/Propagator/Enterprise/BoldIndexedList.pas index 32c2a2a..e032243 100644 --- a/Source/Propagator/Enterprise/BoldIndexedList.pas +++ b/Source/Propagator/Enterprise/BoldIndexedList.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldIndexedList; interface @@ -9,7 +12,8 @@ interface BoldHashIndexes, BoldIndexableList, BoldGuard, - BoldContainers; + BoldContainers + ; const Initial_Client_Count = 1000; @@ -42,15 +46,16 @@ TBoldClientIDList = class(TBoldIndexList) TBoldExternalEventIndex = class(TBoldStringHashIndex) protected - function ItemAsKeyString(Item: TObject): string; override; + function ItemASKeyString(Item: TObject): string; override; end; TBoldExternalEventHashTable = class(TBoldUnorderedIndexableList) private - function GetItemByEventName(EventName: string): TBoldEventNameIndexNode; + class var IX_EventName: integer; + function GetItemByEventName(EventName: string): TBoldEventNameIndexNode; {$IFDEF BOLD_INLINE} inline; {$ENDIF} public constructor Create; - procedure Add(Item: TBoldEventNameIndexNode); + procedure Add(Item: TBoldEventNameIndexNode); {$IFDEF BOLD_INLINE} inline; {$ENDIF} property ItemsByEventName[ExpressionName: string]: TBoldEventNameIndexNode read GetItemByEventName; end; @@ -58,9 +63,9 @@ TBoldEventNameList = class(TBoldIndexList) private fEvents: TBoldExternalEventHashTable; protected - function getItem(Key: variant): TBoldIndexNode; override; - procedure setItem(Key: variant; Value: TBoldIndexNode); override; - function getCount: integer; override; + function GetItem(Key: variant): TBoldIndexNode; override; + procedure SetItem(Key: variant; Value: TBoldIndexNode); override; + function GetCount: integer; override; function InsertINode(Key: variant): TBoldIndexNode; override; public constructor Create(const IndexOrder: integer); override; @@ -78,10 +83,8 @@ implementation BoldPropagatorSubscriptions, BoldDefs; -var - IX_EventName: integer = -1; - {TBoldClientIDList} +{TBoldClientIDList} constructor TBoldClientIDList.Create; begin inherited Create(IndexOrder); @@ -104,7 +107,7 @@ destructor TBoldClientIDList.Destroy; inherited; end; -function TBoldClientIDList.getClient(Index: Integer): TObject; +function TBoldClientIDList.GetClient(Index: Integer): TObject; var cnt, increment, i: integer; begin @@ -122,12 +125,12 @@ function TBoldClientIDList.getClient(Index: Integer): TObject; end; end; -function TBoldClientIDList.getCount: integer; +function TBoldClientIDList.GetCount: integer; begin Result := fClients.Count; end; -function TBoldClientIDList.getItem(Key: variant): TBoldIndexNode; +function TBoldClientIDList.GetItem(Key: variant): TBoldIndexNode; var aKey: integer; begin @@ -148,13 +151,13 @@ function TBoldClientIDList.InsertINode(Key: variant): TBoldIndexNode; Result := Clients[aKey] as TBoldIndexNode; end; -procedure TBoldClientIDList.setClient(Index: Integer; +procedure TBoldClientIDList.SetClient(Index: Integer; Value: TObject); begin Clients[Index] := Value; end; -procedure TBoldClientIDList.setItem(Key: variant; Value: TBoldIndexNode); +procedure TBoldClientIDList.SetItem(Key: variant; Value: TBoldIndexNode); var aKey: integer; begin @@ -205,14 +208,14 @@ destructor TBoldEventNameList.Destroy; inherited ; end; -function TBoldEventNameList.getCount: integer; +function TBoldEventNameList.GetCount: integer; begin Result := fEvents.Count; end; -function TBoldEventNameList.getItem(Key: variant): TBoldIndexNode; +function TBoldEventNameList.GetItem(Key: variant): TBoldIndexNode; begin - Assert(VarType(Key) = varString, Format('%s.getItem: Key is not TBoldStringKey', [ClassName])); + Assert(VarIsStr(Key), Format('%s.getItem: Key is not TBoldStringKey', [ClassName])); Result := fEvents.GetItemByEventName(string(Key)); end; @@ -242,13 +245,12 @@ procedure TBoldEventNameList.DeleteINodeByKey(Key: variant); fEvents.Remove(node); end; -procedure TBoldEventNameList.setItem(Key: variant; Value: TBoldIndexNode); +procedure TBoldEventNameList.SetItem(Key: variant; Value: TBoldIndexNode); begin Assert(Value is TBoldEventNameIndexNode); fEvents.Add(Value as TBoldEventNameIndexNode); end; - procedure TBoldEventNameList.DeleteNodes; var Traverser: TBoldIndexableListTraverser; @@ -256,12 +258,15 @@ procedure TBoldEventNameList.DeleteNodes; begin Guard := TBoldGuard.Create(Traverser); Traverser := fEvents.CreateTraverser; - while not Traverser.EndOfList do + Traverser.AutoMoveOnRemoveCurrent := false; + while Traverser.MoveNext do begin if Traverser.Item is TBoldIndexNode then - DeleteINode(Traverser.Item as TBoldIndexNode); - Traverser.Next; - end; //for + DeleteINode(Traverser.Item as TBoldIndexNode) + end; end; +initialization + TBoldExternalEventHashTable.IX_EventName := -1; + end. diff --git a/Source/Propagator/Enterprise/BoldListNodes.pas b/Source/Propagator/Enterprise/BoldListNodes.pas index eb219d6..7595607 100644 --- a/Source/Propagator/Enterprise/BoldListNodes.pas +++ b/Source/Propagator/Enterprise/BoldListNodes.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldListNodes; interface @@ -99,7 +102,6 @@ procedure TBoldAbstractLinkNode.Remove; begin for Index := 0 to NumberOfIndices - 1 do begin - // unlink next if Assigned(Next[Index]) then (Next[Index] as TBoldAbstractLinkNode).Previous[Index] := Previous[Index]; Prev := Previous[Index]; @@ -113,4 +115,6 @@ procedure TBoldAbstractLinkNode.Remove; end; end; +initialization + end. diff --git a/Source/Propagator/Enterprise/BoldLockList.pas b/Source/Propagator/Enterprise/BoldLockList.pas index 9119ef0..f0f556f 100644 --- a/Source/Propagator/Enterprise/BoldLockList.pas +++ b/Source/Propagator/Enterprise/BoldLockList.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldLockList; interface @@ -32,12 +35,10 @@ TBoldLockIndex = class(TBoldStringHashIndex) TBoldLockNameHashList = class(TBoldUnorderedIndexableList) private -// function GetItem(Index: Integer): TBoldLockNameIndexNode; function GetItembyLockName(LockName: string): TBoldLockNameIndexNode; public constructor Create; procedure Add(Item: TBoldLockNameIndexNode); -// property Items[Index: Integer]: TBoldLockNameIndexNode read GetItem; default; property ItemsByLockName[LockName: string]: TBoldLockNameIndexNode read GetItembyLockName; end; @@ -78,7 +79,6 @@ TBoldLockNameList = class(TBoldIndexList) procedure setItem(Key: variant; Value: TBoldIndexNode); override; function getCount: integer; override; function InsertINode(Key: variant): TBoldIndexNode; override; -// function getINode(Index: integer): TBoldIndexNode; override; public constructor Create(const IndexOrder: integer); override; destructor Destroy; override; @@ -112,7 +112,7 @@ TBoldLockNode = class(TBoldAbstractLinkNode) procedure EnsureLock(Ensure: Boolean); function GetLockDuration(const CurrentTime: TTimeStamp): comp; property ClientId: TBoldClientId read fClientId write fClientId; - property TimeOut: Integer read fTimeOut write fTimeOut; // duration in milliseconds + property TimeOut: Integer read fTimeOut write fTimeOut; property LockAcquisitionTime: TTimeStamp read fLockAcquisitionTime write fLockAcquisitionTime; property LockType: TBoldLockType read fLockType write setLockType; property CanTimeOut: Boolean read fCanTimeOut; @@ -145,11 +145,14 @@ TBoldLockList = class(TBoldAbstractMultiIndexedList) property Locks[Index: string]: TBoldLockNameIndexNode read getLock; property Items[ClientId: TBoldClientID; LockName: string]: TBoldLockNode read getItem; default; property ClientIdIndexOrder: integer read fClientIdIndexOrder; - property LockNameIndexOrder: integer read fLockNameIndexOrder; + property LockNameIndexOrder: integer read fLockNameIndexOrder; end; implementation +uses + BoldRev; + var IX_LockName: integer = -1; IX_ClientID: integer = -1; @@ -367,11 +370,10 @@ procedure TBoldLockNameList.DeleteNodes; begin Guard := TBoldGuard.Create(Traverser); Traverser := fLocks.CreateTraverser; - while not Traverser.EndOfList do + while Traverser.MoveNext do begin if Traverser.Item is TBoldIndexNode then DeleteINode(Traverser.Item as TBoldIndexNode); - Traverser.Next; end; end; @@ -432,19 +434,16 @@ procedure TBoldLockNameList.InsertNode(Key: variant; CurrentNode := iNode.Clients.GetItembyClientId(NewLockNode.ClientId); if Assigned(CurrentNode) then begin - // remove node CurrentNode.Remove; FreeAndNil(CurrentNode); end else begin - // add node NewNode.Previous[IndexOrder] := iNode; NewNode.Next[IndexOrder] := iNode.Next; if Assigned(iNode.Next) then iNode.Next.Previous[IndexOrder] := NewNode; iNode.Next := NewNode; - // add node to ClientIdHashList NewLockNode.AddToList(iNode.Clients); end; end; @@ -493,7 +492,7 @@ function TBoldLockNode.GetHasTimedOut: Boolean; CurrentTime := DateTimetoTimeStamp(Now); LockAcquisitionDuration := TimeStampToMSecs(CurrentTime) - TimeStampToMSecs(LockAcquisitionTime); Result := (Int(LockAcquisitionDuration) >= TimeOut); - end; + end; end; function TBoldLockNode.GetLockDuration(const CurrentTime: TTimeStamp): comp; @@ -580,7 +579,7 @@ function TBoldClientIdIndex.ItemAsKeyString(Item: TObject): string; constructor TBoldClientIdHashList.Create(OwnerIndexNode: TBoldLockNameIndexNode); begin - OwnsEntries := false;//ToReview + OwnsEntries := false; SetIndexCapacity(1); SetIndexVariable(IX_ClientID, AddIndex(TBoldClientIDIndex.Create)); fOwnerIndexNode := OwnerIndexNode; @@ -607,4 +606,6 @@ function TBoldLockNameIndexNode.getClients: TBoldClientIdHashList; Result := fClients; end; +initialization + end. diff --git a/Source/Propagator/Enterprise/BoldLockManager.pas b/Source/Propagator/Enterprise/BoldLockManager.pas index 8d4f76b..bb4e98b 100644 --- a/Source/Propagator/Enterprise/BoldLockManager.pas +++ b/Source/Propagator/Enterprise/BoldLockManager.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldLockManager; interface @@ -16,7 +19,7 @@ interface ; type - TBoldLockManager = class(TBoldPassthroughSubscriber) + TBoldLockManager = class(TBoldExtendedPassthroughSubscriber) private fHandedLocks: TBoldLockList; fPropagator: TBoldAdvancedPropagator; @@ -86,9 +89,8 @@ function TBoldLockManager.CanAcquireLocks( const ClientId: TBoldClientId; const if (CurrentNode.ClientId <> ClientId) then if CurrentNode.HasTimedOut then begin - // this is where locks get lost Temp := CurrentNode; - CurrentNode := CurrentNode.Next[HandedLocks.LockNameIndexOrder] as TBoldLockNode; //send LockLost event + CurrentNode := CurrentNode.Next[HandedLocks.LockNameIndexOrder] as TBoldLockNode; Temp.Remove; LockLostEvent := TBoldObjectSpaceExternalEvent.EncodeExternalEvent(bsLockLost, '', '',Locks[i] ,nil); Propagator.Enqueuer.SendLockEvent(Temp.ClientId, LockLostEvent, False); @@ -104,9 +106,9 @@ function TBoldLockManager.CanAcquireLocks( const ClientId: TBoldClientId; const end else CurrentNode := CurrentNode.Next[HandedLocks.LockNameIndexOrder] as TBoldLockNode; - end;//while + end; end - end;//for + end; end; constructor TBoldLockManager.Create(const Propagator: TBoldAdvancedPropagator); @@ -238,4 +240,6 @@ function TBoldLockManager.EnsureLocks(const ClientID: TBoldClientID; const Reque end; end; +initialization + end. diff --git a/Source/Propagator/Enterprise/BoldLockManagerAdmin.pas b/Source/Propagator/Enterprise/BoldLockManagerAdmin.pas index e2ca289..e24cf35 100644 --- a/Source/Propagator/Enterprise/BoldLockManagerAdmin.pas +++ b/Source/Propagator/Enterprise/BoldLockManagerAdmin.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldLockManagerAdmin; interface @@ -5,10 +8,11 @@ interface uses BoldLockManager, BoldDefs, - Classes; + Classes + ; type - { TBoldLockManagerAdmin } + TBoldLockManagerAdmin = class private fLockManager: TBoldLockManager; @@ -31,8 +35,7 @@ implementation Sysutils, BoldUtils, BoldLockList, - windows, - PropagatorConsts; + windows; { TBoldLockManagerAdmin } @@ -111,14 +114,14 @@ procedure TBoldLockManagerAdmin.LocksForClients( const ClientIds: TStringList; c result := trunc(source - temp*factor); source := temp; end; - + begin if not Assigned(ClientIds) then - raise EBold.CreateFmt(sClientIDsNotAssigned, [ClassName, 'LocksForClients']); // do not localize + raise EBold.CreateFmt('%s.LocksForClients: ClientIds is not assigned', [ClassName]); if not Assigned(Locks) then - raise EBold.CreateFmt(sLocksNotAssigned, [ClassName]); + raise EBold.CreateFmt('%s.LocksForClients: Locks is not assigned', [ClassName]); if not Assigned(LockDurations) then - raise EBold.CreateFmt(sLockDurationNotAssigned, [ClassName]); + raise EBold.CreateFmt('%s.LocksForClients: LockDurations is not assigned', [ClassName]); ClientLocks := TStringList.Create; try CurrentTime := DateTimeToTimeStamp(Now); @@ -139,11 +142,11 @@ procedure TBoldLockManagerAdmin.LocksForClients( const ClientIds: TStringList; c sec := Getpart(temp, 60); min := Getpart(temp, 60); hour := Getpart(temp, 24); - LockDur := Format('%.2d:%.2d:%.2d:%.3d', [Hour, Min, Sec, MSec]); // do not localize + LockDur := Format('%.2d:%.2d:%.2d:%.3d', [Hour, Min, Sec, MSec]); if temp > 0 then - LockDur := format('%d day(s) ', [temp])+LockDur; // do not localize + LockDur := format('%d day(s) ', [temp])+LockDur; LockDurations.Add(LockDur); - Locks.Add(Format('%d=%s', [CurrentClientId, ClientLocks[j]])); // do not localize + Locks.Add(Format('%d=%s', [CurrentClientId, ClientLocks[j]])); end; ClientLocks.Clear; end; @@ -164,4 +167,6 @@ procedure TBoldLockManagerAdmin.SetLockManagerSuspended(Value: Boolean); LockManager.Suspended := Value; end; +initialization + end. diff --git a/Source/Propagator/Enterprise/BoldLockManagerAdminCOM.pas b/Source/Propagator/Enterprise/BoldLockManagerAdminCOM.pas index 34bfa9e..f55a711 100644 --- a/Source/Propagator/Enterprise/BoldLockManagerAdminCOM.pas +++ b/Source/Propagator/Enterprise/BoldLockManagerAdminCOM.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldLockManagerAdminCOM; interface @@ -10,7 +13,6 @@ interface const CLSID_LOCKMANAGERADMIN : TGuid = '{D06C7BF6-EBC1-4D2E-954F-AEA567C262F7}'; - type {forward declarations} TBoldLockManagerAdminCOM = class; @@ -49,7 +51,8 @@ implementation BoldPropagatorServer, BoldApartmentThread, Classes, - windows; + windows + ; { TBoldLockManagerAdminCOM } @@ -148,4 +151,6 @@ constructor TBoldLockManagerAdminComFactory.Create( inherited Create(ComServer, TBoldLockManagerAdminCOM, ClassID, ClassName, Description, ciMultiInstance, batSTA); end; +initialization + end. diff --git a/Source/Propagator/Enterprise/BoldLockManagerAdminExportHandle.pas b/Source/Propagator/Enterprise/BoldLockManagerAdminExportHandle.pas index d7ae481..422297f 100644 --- a/Source/Propagator/Enterprise/BoldLockManagerAdminExportHandle.pas +++ b/Source/Propagator/Enterprise/BoldLockManagerAdminExportHandle.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldLockManagerAdminExportHandle; interface @@ -14,7 +17,7 @@ TBoldLockManagerAdminComExportHandle = class; TBoldLockManagerAdminComExportHandle = class(TBoldComExportHandle) protected function GetComObject: IUnknown; override; - function GetHandledObject: TObject; override; + function GetHandledObject: TObject; override; public constructor Create(Active: Boolean; ServerHandle: TBoldComServerHandle; ServerClass: string); reintroduce; end; @@ -42,11 +45,13 @@ constructor TBoldLockManagerAdminComExportHandle.Create(Active: Boolean; ServerH function TBoldLockManagerAdminComExportHandle.GetComObject: IUnknown; begin Result := CreateComObject(TBoldPropagatorServer.Instance.LockManagerAdminCLSID); -end; +end; function TBoldLockManagerAdminComExportHandle.GetHandledObject: TObject; begin Result := nil; end; +initialization + end. diff --git a/Source/Propagator/Enterprise/BoldLockManagerCOM.pas b/Source/Propagator/Enterprise/BoldLockManagerCOM.pas index 9ec51eb..20ac637 100644 --- a/Source/Propagator/Enterprise/BoldLockManagerCOM.pas +++ b/Source/Propagator/Enterprise/BoldLockManagerCOM.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldLockManagerCOM; interface @@ -32,7 +35,7 @@ TBoldLockManagerCOM = class(TTypedComObject, IBoldLockManager) TBoldLockManagerCOMFactory = class(TBoldThreadedComObjectFactory) public - constructor Create(ComServer: TComServerObject; + constructor Create(ComServer: TComServerObject; const ClassID: TGUID; const ClassName, Description: string); end; @@ -73,7 +76,6 @@ function TBoldLockManagerCOM.EnsureLocks(ClientId: Integer; function TBoldLockManagerCOM.getLockManager: TBoldLockManager; begin - // get the LockManager from the global application object if not Assigned(fLockManager) then fLockManager := TBoldPropagatorServer.Instance.LockManager; Result := fLockManager; @@ -85,7 +87,6 @@ function TBoldLockManagerCOM.GetLocks(ClientId, TimeOut: Integer; var SharedLocks, ExclusiveLocks: TStringList; begin - // delegate call to lockmanager SharedLocks := TStringList.Create; ExclusiveLocks := TStringList.Create; try @@ -122,4 +123,6 @@ constructor TBoldLockManagerCOMFactory.Create(ComServer: TComServerObject; inherited Create(ComServer, TBoldLockManagerCOM, ClassID, ClassName, Description, ciMultiInstance, batSTA); end; +initialization + end. diff --git a/Source/Propagator/Enterprise/BoldLockManagerExportHandle.pas b/Source/Propagator/Enterprise/BoldLockManagerExportHandle.pas index 0030a91..73b1264 100644 --- a/Source/Propagator/Enterprise/BoldLockManagerExportHandle.pas +++ b/Source/Propagator/Enterprise/BoldLockManagerExportHandle.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldLockManagerExportHandle; interface @@ -15,9 +18,9 @@ TBoldLockManagerComExportHandle = class; TBoldLockManagerComExportHandle = class(TBoldComExportHandle) protected function GetComObject: IUnknown; override; - function GetHandledObject: TObject; override; + function GetHandledObject: TObject; override; public - constructor Create(Active: Boolean; ServerHandle: TBoldComServerHandle; ServerClass: string); reintroduce; + constructor Create(Active: Boolean; ServerHandle: TBoldComServerHandle; ServerClass: string); reintroduce; end; implementation @@ -49,4 +52,6 @@ function TBoldLockManagerComExportHandle.GetHandledObject: TObject; Result := nil; end; +initialization + end. diff --git a/Source/Propagator/Enterprise/BoldOutputQueueHandler.pas b/Source/Propagator/Enterprise/BoldOutputQueueHandler.pas index 156708b..e3bbfb7 100644 --- a/Source/Propagator/Enterprise/BoldOutputQueueHandler.pas +++ b/Source/Propagator/Enterprise/BoldOutputQueueHandler.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldOutputQueueHandler; interface @@ -26,7 +29,7 @@ TBoldOutputQueueHandler = class(TBoldAbstractOutputQueueHandler) function getPriorityListEnlister: TBoldAbstractPriorityListEnlister; virtual; property PriorityListEnlister: TBoldAbstractPriorityListEnlister read GetPrioritylistEnlister; public - constructor Create; + constructor Create; destructor Destroy; override; procedure SendEvent(const ClientID: TBoldClientID; EventName: string); override; procedure ClearQueueForClient(const ClientID: TBoldClientID); override; @@ -46,6 +49,7 @@ implementation BoldPropagatorServer, BoldThreadSafeLog; + { TBoldOutputQueueHandler } procedure TBoldOutputQueueHandler.ClearQueueForClient( @@ -72,7 +76,6 @@ function TBoldOutputQueueHandler.getOutputQueue( count, i: integer; ClientQueue: TBoldClientQueue; begin - //check index range if (Index >= fOutputQueues.Count) then begin count := (Index - fOutputQueues.Count) + 1; @@ -83,7 +86,7 @@ function TBoldOutputQueueHandler.getOutputQueue( end; if not Assigned(fOutputQueues[Index]) then begin - ClientQueue := TBoldClientQueue.Create(format('CliQ[%d]', [Index])); // do not localize + ClientQueue := TBoldClientQueue.Create(format('CliQ[%d]', [Index])); ClientQueue.OnQueueNotEmpty := OnQueueNotEmpty; ClientQueue.BoldClientID := Index; fOutputQueues[Index] := ClientQueue; @@ -119,7 +122,7 @@ procedure TBoldOutputQueueHandler.SendEvent(const ClientID: TBoldClientID; Event try OutputQueues[ClientID].Enqueue(EventName); except On E: Exception do - BoldLogError('%s.SendEvent: Client = %d', [ClassName, ClientId]); // do not localize + BoldLogError('%s.SendEvent: Client = %d', [ClassName, ClientId]); end; end; @@ -130,4 +133,5 @@ procedure TBoldOutputQueueHandler.SendEventAndFlushQueue(const ClientID: TBoldCl PriorityListEnlister.FlushQueue(OutputQueues[ClientID]); end; +initialization end. diff --git a/Source/Propagator/Enterprise/BoldPriorityListEnlister.pas b/Source/Propagator/Enterprise/BoldPriorityListEnlister.pas index 8e68c79..86a3c79 100644 --- a/Source/Propagator/Enterprise/BoldPriorityListEnlister.pas +++ b/Source/Propagator/Enterprise/BoldPriorityListEnlister.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldPriorityListEnlister; interface @@ -180,4 +183,5 @@ function TBoldPriorityListEnlister.getClientHandler: TBoldClientHandler; Result := TBoldPropagatorServer.Instance.AdvancedPropagator.ClientHandler; end; +initialization end. diff --git a/Source/Propagator/Enterprise/BoldPropagatorApplication.pas b/Source/Propagator/Enterprise/BoldPropagatorApplication.pas index cb3f2fc..9b37fb2 100644 --- a/Source/Propagator/Enterprise/BoldPropagatorApplication.pas +++ b/Source/Propagator/Enterprise/BoldPropagatorApplication.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldPropagatorApplication; interface @@ -7,9 +10,12 @@ interface BoldAdvancedPropagator, BoldPropagatorServer, dialogs, - forms; + forms + ; implementation +uses + BoldRev; initialization try diff --git a/Source/Propagator/Enterprise/BoldPropagatorCleanup.pas b/Source/Propagator/Enterprise/BoldPropagatorCleanup.pas index eb3ef54..f33a565 100644 --- a/Source/Propagator/Enterprise/BoldPropagatorCleanup.pas +++ b/Source/Propagator/Enterprise/BoldPropagatorCleanup.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldPropagatorCleanup; interface @@ -13,6 +16,7 @@ interface BoldThreadSafeLog, ExtCtrls; + type {forward declarrations} TBoldCleanUpSubscriber = class; @@ -41,7 +45,7 @@ TBoldCleanUpThread = class(TBoldNotifiableThread) property Timer: TTimer read getTimer write fTimer; end; - TBoldCleanupSubscriber = class(TBoldPassthroughSubscriber) + TBoldCleanupSubscriber = class(TBoldExtendedPassthroughSubscriber) private fCleanUpThread: TBoldCleanUpThread; fClientHandler: TBoldClientHandler; @@ -64,8 +68,7 @@ implementation BoldPropagatorMainForm, BoldPropagatorServer, Messages, - Classes, - PropagatorConsts; + Classes; function BoldPropagatorCleanupWndProc(Window: HWND; Message, wParam, lParam: Longint): Longint; stdcall; @@ -80,7 +83,7 @@ function BoldPropagatorCleanupWndProc(Window: HWND; try CleanUpThread.SetTimer; except on E: Exception do - BoldLogError(sWindowProcError, [E.Message]); + BoldLogError('Error in WindowProc %s', [E.Message]); end; end; else @@ -99,7 +102,7 @@ function BoldPropagatorCleanupWndProc(Window: HWND; hCursor: 0; hbrBackground: 0; lpszMenuName: nil; - lpszClassName: 'TBoldPropagatorCleanupWindow'); // do not localize + lpszClassName: 'TBoldPropagatorCleanupWindow'); { TBoldCleanupSubscriber } @@ -124,8 +127,8 @@ procedure TBoldCleanupSubscriber.DoLeaseChanged; begin try PostMessage(fCleanUpThread.QueueWindow, BM_PROPAGATOR_CLIENT_LEASE_CHANGED, 0, Integer(fCleanUpThread)); - except on e: Exception do - BoldLogError(sLogError, [ClassName, 'DoLeaseChanged', e.Message]); // do not localize + except + BoldLogError('%s.DoLeaseChanged', [ClassName]); end; end; @@ -144,7 +147,7 @@ procedure TBoldCleanupSubscriber.OnGetExtendedEvent( end; DoLeaseChanged; except - BoldLogError('%s.OnGetExtendedEvent: Bold_propagator_client_lease_changed', [ClassName]); // do not localize + BoldLogError('%s.OnGetExtendedEvent: Bold_propagator_client_lease_changed', [ClassName]); end; end; end; @@ -198,7 +201,7 @@ procedure TBoldCleanUpThread.Execute; EnsureMessageQueue; InitServerWindow (TRUE); SignalReady; - BoldLogThread('ID=Cleanup'); // do not localize + BoldLogThread('ID=Cleanup'); while not Terminated do begin @@ -265,8 +268,10 @@ procedure TBoldCleanUpThread.SetTimer; else RemoveTimedOutClient; except on E: Exception do - BoldlogError('%s.SetTimer: %s', [ClassName, E.Message]); //do not localize + BoldlogError('%s.SetTimer: %s', [ClassName, E.Message]); end; end; +initialization + end. diff --git a/Source/Propagator/Enterprise/BoldPropagatorMainForm.pas b/Source/Propagator/Enterprise/BoldPropagatorMainForm.pas index 26f1a73..61571e7 100644 --- a/Source/Propagator/Enterprise/BoldPropagatorMainForm.pas +++ b/Source/Propagator/Enterprise/BoldPropagatorMainForm.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldPropagatorMainForm; interface @@ -10,7 +13,6 @@ interface Forms, ComCtrls, StdCtrls, - BoldMemoryManager, ExtCtrls, Messages, Grids, @@ -176,8 +178,7 @@ implementation BoldPropagatorServer, BoldThreadSafeLog, Sysutils, - Boldutils, - PropagatorConsts; + Boldutils; {$R *.dfm} @@ -216,7 +217,7 @@ function StatToStr(value: integer): string; else if Whole >= 10 then result := IntToStr(Whole) + '.' + IntToStr(tenths) + Result else - result := IntToStr(Whole) + '.' + format('%.2d', [hundreds]) + Result // do not localize + result := IntToStr(Whole) + '.' + format('%.2d', [hundreds]) + Result end; (* OldDecimalSeparator := DecimalSeparator; @@ -244,7 +245,6 @@ procedure TPropagatorMainForm.AddUser(Id: integer; IdString: string; Registratio finally fClientInfoLock.Release; end; -// NewClient.RefreshGrid; end; procedure TPropagatorMainForm.ClearAllUsers; @@ -252,9 +252,8 @@ procedure TPropagatorMainForm.ClearAllUsers; fClientINfoLock.Acquire; try fLastTopRow := sgClients.TopRow; -// sgClients.RowCount := 2; -// for i := 0 to sgClients.ColCount-1 do -// sgClients.Cells[i, 1] := ''; + + fClients.Clear; fClientsUpdated := true; finally @@ -267,27 +266,26 @@ procedure TPropagatorMainForm.FormCreate(Sender: TObject); ConfigFile: TStringList; fileName: String; begin -// ComServer.UIInteractive := false; fClientInfoLock := TCriticalSection.Create; - BoldLogThread('ID=MainThread/GUI'); // do not localize + BoldLogThread('ID=MainThread/GUI'); fClients := TClientGUIInfoList.Create; fLastTopRow := -1; - Caption := Format(sFormCaption, [TBoldPropagatorServer.Instance.ServerName]); + Caption := Format('%s Console', [TBoldPropagatorServer.Instance.ServerName]); fStartTime := now; PageControl1.ActivePage := tsClients; UpdateUptime; - sgClients.Cells[0, 0] := sClientID; - sgClients.Cells[1, 0] := sName; - sgClients.Cells[2, 0] := sRegTime; - sgClients.Cells[3, 0] := sTimeOut; - sgClients.Cells[4, 0] := sSubscriptions; - sgClients.Cells[5, 0] := sQueue; - sgClients.Cells[6, 0] := sLongestInt; - sgClients.Cells[7, 0] := sLast; - sgClients.Cells[8, 0] := sPkg; - sgClients.Cells[9, 0] := sEv; - sgClients.Cells[10, 0] := sStatus; - sgClients.Cells[11, 0] := sLost; + sgClients.Cells[0, 0] := 'ClientID'; + sgClients.Cells[1, 0] := 'Name'; + sgClients.Cells[2, 0] := 'RegTime'; + sgClients.Cells[3, 0] := 'Timeout'; + sgClients.Cells[4, 0] := 'Subscriptions'; + sgClients.Cells[5, 0] := 'Queue'; + sgClients.Cells[6, 0] := 'Longest Int'; + sgClients.Cells[7, 0] := 'Last (ago)'; + sgClients.Cells[8, 0] := 'Pkg'; + sgClients.Cells[9, 0] := 'Ev'; + sgClients.Cells[10, 0] := 'Status'; + sgClients.Cells[11, 0] := 'Lost'; mnuCountSubscriptionsClick(self); rbDequeue.Parent := StatusBar1; rbDeQueue.Height := 13; @@ -295,23 +293,23 @@ procedure TPropagatorMainForm.FormCreate(Sender: TObject); rbDequeue.Left := 2; mmoDebugInfo.lines.Clear; - mmoDebugInfo.lines.add(Format(sFile, [paramStr(0)])); + mmoDebugInfo.lines.add('File: '+paramStr(0)); mmoDebugInfo.lines.add(''); {$IFDEF DEBUG} mnuHangPropagatorDEBUG.Visible := true; formstyle := fsStayOnTop; - {$ENDIF} + {$ENDIF} - FileName := ChangeFileExt(GetModuleFileNameAsString(true), '.ini'); // do not localize + FileName := ChangeFileExt(GetModuleFileNameAsString(true), '.ini'); if not FileExists(FileName) then begin - mmoDebugInfo.lines.add(sNoINIFile); + mmoDebugInfo.lines.add('INI file: N/A'); end else begin ConfigFile := TStringList.Create; ConfigFile.LoadFromFile(FileName); - mmoDebugInfo.lines.add(sINIFile); + mmoDebugInfo.lines.add('INI file:'); mmoDebugInfo.lines.add('---------------'); mmoDebugInfo.lines.AddStrings(ConfigFile); mmoDebugInfo.lines.add('---------------'); @@ -326,14 +324,13 @@ function TPropagatorMainForm.GetUpTime: TDAteTime; procedure TPropagatorMainForm.UpdateUptime; begin - mnuStarted.Caption := format(sStarted, [DateTimeToStr(startTime)]); - mnuUptime.Caption := format(sUptime, [trunc(Uptime), TimetoStr(Frac(Uptime))]); + mnuStarted.Caption := format('Started: %s', [DateTimeToStr(startTime)]); + mnuUptime.Caption := format('Uptime: %d days %s', [trunc(Uptime), TimetoStr(Frac(Uptime))]); end; procedure TPropagatorMainForm.mnuRefreshClick(Sender: TObject); begin - // this event will be replaced by the UIManager when it takes control of the GUI. - mnuRefreshGUI.Caption := sHangon; + mnuRefreshGUI.Caption := 'Hang on...'; UpdateUptime; UpdateStatistics; UpdateMemoryStats; @@ -349,6 +346,7 @@ procedure TPropagatorMainForm.SetIsDequeueing(const Value: boolean); rbDequeue.Checked := value; end; + procedure TPropagatorMainForm.UpdateStatistics; var s: string; @@ -384,8 +382,8 @@ procedure TPropagatorMainForm.UpdateStatistics; end; s := ''; AllStatus := ''; - AddStatus(sCli, ClientCount); - AddStatus(sTot, fTotalClients); + AddStatus('Cli', ClientCount); + AddStatus('Tot', fTotalClients); AddStatus('^', fPeakClients); StatusBar1.Panels[3].Width := StatusBar1.Canvas.TextWidth(s) + 20; @@ -393,19 +391,19 @@ procedure TPropagatorMainForm.UpdateStatistics; s := ''; if mnuCountSubscriptions.Checked then - AddStatus(sSubs, Subscriptions); - AddStatus(sInQ, InQ); - AddStatus(sInQPeak, InQPeak); - AddStatus(sOutQ, OutQ); - AddStatus(sAdded, Added); - AddStatus(sSent, sent); - AddStatus(sLost, fTotalLostEvents); + AddStatus('Subs', Subscriptions); + AddStatus('InQ', InQ); + AddStatus('InQ^', InQPeak); + AddStatus('OutQ', OutQ); + AddStatus('Added', Added); + AddStatus('Sent', sent); + AddStatus('Lost', fTotalLostEvents); StatusBar1.Panels[4].Text := s; BoldLog(AllStatus); while lbStatisticsHistory.items.Count > 100 do lbStatisticsHistory.items.Delete(lbStatisticsHistory.items.Count-1); - lbStatisticsHistory.items.insert(0, DateTimeToStr(now) + ': ' + AllStatus); + lbStatisticsHistory.items.insert(0, DateTimeToStr(now)+': '+AllStatus); if fLastTopRow <> -1 then begin if fLastTopRow > sgClients.RowCount - sgClients.VisibleRowCount then @@ -415,15 +413,16 @@ procedure TPropagatorMainForm.UpdateStatistics; end; end; + + procedure TPropagatorMainForm.UpdateMemoryStats; begin - mmoMemory.Text := BoldMemoryManager_.MemoryInfo; if Subscriptions > 0 then begin mmoMemory.Lines.Add('---'); - mmoMemory.Lines.Add(format(sBytesPerSubscription, [GetHeapStatus.TotalAllocated/Subscriptions])); + mmoMemory.Lines.Add(format('%0.2f bytes per subscription', [GetHeapStatus.TotalAllocated/Subscriptions])); end; - lbxSystemMemory.Items.Add(format(sMemAllocated, [GetHeapStatus.TotalAllocated/(1024*1024)])); + lbxSystemMemory.Items.Add(format('Allocated %6.2f Mb', [GetHeapStatus.TotalAllocated/(1024*1024)])); lbxSystemMemory.TopIndex := lbxSystemMemory.items.Count - lbxSystemMemory.Height div lbxSystemMemory.ItemHeight; end; @@ -452,7 +451,7 @@ procedure TPropagatorMainForm.BMPropagatorDoneDequeue(var Msg: TMessage); procedure TPropagatorMainForm.BMPropagatorStartDequeue(var Msg: TMessage); begin - rbDequeue.Checked := true; + rbDequeue.Checked := true; end; procedure TPropagatorMainForm.ClientInfoChanged(Id: integer; ClientSubscriptions, OutQ: integer); @@ -485,8 +484,7 @@ constructor TClientGuiInfo.create(form: TPropagatorMainForm; Id: integer; Name: fLongestInterval := LongestInterval; fStatus := Status; fLostEvents := LostEvents; -// if GuiForm.fClients.Count <> 1 then -// GuiForm.sgClients.RowCount := GuiForm.sgClients.RowCount + 1; + fRow := FGuiForm.ClientCount + 1; end; @@ -495,7 +493,7 @@ procedure TPropagatorMainForm.GlobalInfoChanged(Added, Sent: integer); fAdded := Added; fSent := Sent; UpdateStatistics; - mnuRefreshGUI.Caption := sRefresh; + mnuRefreshGUI.Caption := 'Refresh'; end; procedure TClientGuiInfo.RefreshGrid; @@ -506,7 +504,7 @@ procedure TClientGuiInfo.RefreshGrid; if LeaseExpires <> 0 then GuiForm.sgClients.Cells[3, Row] := TimeToStr(LeaseExpires) else - GuiForm.sgClients.Cells[3, Row] := '?'; // do not localize + GuiForm.sgClients.Cells[3, Row] := '?'; GuiForm.sgClients.Cells[4, row] := StatToStr(Subscriptions); GuiForm.sgClients.Cells[5, row] := StatToStr(OutQ); @@ -562,13 +560,13 @@ procedure TPropagatorMainForm.mnuLockClick(Sender: TObject); begin fLocked := false; fClientHandler.DebugUnLock; - mnuHangPropagatorDEBUG.Caption := 'Hang Propagator (DEBUG)'; // do not localize + mnuHangPropagatorDEBUG.Caption := 'Hang Propagator (DEBUG)'; end else begin fLocked := true; fClientHandler.DebugLock; - mnuHangPropagatorDEBUG.Caption := 'Release propagator'; // do not localize + mnuHangPropagatorDEBUG.Caption := 'Release propagator'; end; {$ENDIF} end; @@ -591,7 +589,6 @@ procedure TPropagatorMainForm.tmrDeadLockCheckerTimer(Sender: TObject); if fClients.Count = 0 then begin - // Fix GhostRow; sgClients.RowCount := 2; SgClients.Rows[1].Text := ''; end @@ -616,16 +613,16 @@ procedure TPropagatorMainForm.tmrDeadLockCheckerTimer(Sender: TObject); if fLongestLockTime < EncodeTime(0, 0, 3, 0) then begin DecodeTime(fLongestLockTime, h, m, s, ms); - StatusBar1.Panels[1].Text := IntToStr(s*1000+ms) + 'ms'; // do not localize + StatusBar1.Panels[1].Text := IntToStr(s*1000+ms) + 'ms'; end else StatusBar1.Panels[1].Text := TimeToStr(fLongestLockTime); end; if LockTime > 0 then - StatusBar1.Panels[2].Text := sDL + StatusBar1.Panels[2].Text := 'DL?' else - StatusBar1.Panels[2].Text := sOK; + StatusBar1.Panels[2].Text := 'OK'; if LockTime > EncodeTime(0, 0, 3, 0) then begin @@ -634,6 +631,7 @@ procedure TPropagatorMainForm.tmrDeadLockCheckerTimer(Sender: TObject); end; tmrDeadLockChecker.Enabled := true; + end; procedure TPropagatorMainForm.SetClientHandlerStats(TotalClients, @@ -711,11 +709,14 @@ procedure TPropagatorMainForm.mnuCountSubscriptionsClick( sgClients.ColWidths[4] := -1; sgClients.ColWidths[1] := 225; end + end; procedure TPropagatorMainForm.rbDequeueClick(Sender: TObject); begin - ; // do nothing + ; end; +initialization + end. diff --git a/Source/Propagator/Enterprise/BoldPropagatorServer.pas b/Source/Propagator/Enterprise/BoldPropagatorServer.pas index be08a1f..d7cf484 100644 --- a/Source/Propagator/Enterprise/BoldPropagatorServer.pas +++ b/Source/Propagator/Enterprise/BoldPropagatorServer.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldPropagatorServer; interface @@ -12,8 +15,8 @@ interface BoldLockManager, BoldLockManagerAdmin, BoldContainers, - BoldThreadedComObjectFactory; - + BoldThreadedComObjectFactory + ; type TBoldPropagatorServer = class; TBoldPropagatorServerClass = class of TBoldPropagatorServer; @@ -100,8 +103,8 @@ implementation windows, comserv, registry, - BoldDefs, - PropagatorConsts; + BoldDefs + ; var G_PropagatorServer: TBoldPropagatorServer = nil; @@ -168,9 +171,8 @@ procedure TBoldPropagatorServer.Initialize; Application.Title := ServerName; FAdvancedPropagator := TBoldAdvancedPropagator.Create; dmServerHandles := TDmServerHandles.Create(nil); - if FindCmdLineSwitch('ServerName', ['-', '/'], True) then // do not localize + if FindCmdLineSwitch('ServerName', ['-', '/'], True) then begin - //setconfiguration SetConfiguration(ParamStr(2)); Halt; end @@ -186,23 +188,23 @@ procedure TBoldPropagatorServer.Initialize; procedure TBoldPropagatorServer.CreateClassFactories; begin {$IFDEF BOLD_USE_CO_ADVANCED_PROPAGATOR} - TBoldPropagatorFactory.Create(ComServer, CLASS_BoldPropagator, Format('%s.AdvancedPropagator', [Instance.ServerName]), // do not localize + TBoldPropagatorFactory.Create(ComServer, CLASS_BoldPropagator, Format('%s.AdvancedPropagator', [Instance.ServerName]), Instance.ServerName); {$ELSE} TBoldComServerConnectionFactory.Create(ComServer, Instance.PropagatorConnectionCLSID, - Format('%s.PropagatorConnection', [Instance.ServerName]), Instance.ServerName); // do not localize + Format('%s.PropagatorConnection', [Instance.ServerName]), Instance.ServerName); {$ENDIF} if not Assigned(ClientHandlerComFactory) then - ClientHandlerCOMFactory := TBoldClientHandlerThreadedCOMFactory.Create(ComServer, Instance.ClientHandlerCLSID, Format('%s.ClientHandler', [Instance.ServerName]), // do not localize + ClientHandlerCOMFactory := TBoldClientHandlerThreadedCOMFactory.Create(ComServer, Instance.ClientHandlerCLSID, Format('%s.ClientHandler', [Instance.ServerName]), Instance.ServerName); if not Assigned(EnqueuerCOMFactory) then - EnqueuerCOMFactory := TBoldEnqueuerThreadedComFactory.Create(ComServer, TBoldEnqueuerCOM, Instance.EnqueuerCLSID, Format('%s.EventPropagator', [Instance.ServerName]), 'EventPropagator', // do not localize + EnqueuerCOMFactory := TBoldEnqueuerThreadedComFactory.Create(ComServer, TBoldEnqueuerCOM, Instance.EnqueuerCLSID, Format('%s.EventPropagator', [Instance.ServerName]), 'EventPropagator', ciMultiInstance, batMTA); if not Assigned(LockManagerCOMFactory) then - LockManagerCOMFactory := TBoldLockManagerComFactory.Create(ComServer, Instance.LockManagerCLSID, Format('%s.LockManager', [Instance.ServerName]), 'Lock manager'); // do not localize + LockManagerCOMFactory := TBoldLockManagerComFactory.Create(ComServer, Instance.LockManagerCLSID, Format('%s.LockManager', [Instance.ServerName]), 'Lock manager'); if not Assigned(LockManagerAdminCOMFactory) then - LockManagerAdminCOMFactory := TBoldLockManagerAdminComFactory.Create(ComServer, Instance.LockManagerAdminCLSID, Format('%s.LockManagerAdmin', [Instance.ServerName]), 'Lock manager Admin'); // do not localize + LockManagerAdminCOMFactory := TBoldLockManagerAdminComFactory.Create(ComServer, Instance.LockManagerAdminCLSID, Format('%s.LockManagerAdmin', [Instance.ServerName]), 'Lock manager Admin'); end; procedure TBoldPropagatorServer.LoadConfiguration; @@ -212,30 +214,30 @@ procedure TBoldPropagatorServer.LoadConfiguration; ConfigFile: TMemIniFile; begin ConfigFileName := ModuleName; - ConfigFile := TMemIniFile.Create(ChangeFileExt(ConfigFileName, '.ini')); // do not localize + ConfigFile := TMemIniFile.Create(ChangeFileExt(ConfigFileName, '.ini')); try {Section 1: File Logging} - Section := 'FILE LOGGING'; // do not localize - FLogFileName := ChangeFileExt(ModuleName, '.log'); // do not localize - FErrorLogFileName := ChangeFileExt(ModuleName, '.error'); // do not localize - if ConfigFile.ReadBool(Section, 'THREAD', False) then // do not localize - fThreadLogFileName := ChangeFileExt(ModuleName, '.thread') // do not localize + Section := 'FILE LOGGING'; + FLogFileName := ChangeFileExt(ModuleName, '.log'); + FErrorLogFileName := ChangeFileExt(ModuleName, '.error'); + if ConfigFile.ReadBool(Section, 'THREAD', False) then + fThreadLogFileName := ChangeFileExt(ModuleName, '.thread') else fThreadLogFileName := ''; - FEnableLogging := ConfigFile.ReadBool(Section, 'ENABLED', DEFAULT_ENABLELOGGING); // do not localize - FMaxLogFileSize := ConfigFile.ReadInteger(Section, 'MAXFILESIZE', DEFAULT_LOGFILESIZE); //default size 20k // do not localize + FEnableLogging := ConfigFile.ReadBool(Section, 'ENABLED', DEFAULT_ENABLELOGGING); + FMaxLogFileSize := ConfigFile.ReadInteger(Section, 'MAXFILESIZE', DEFAULT_LOGFILESIZE); {Section 2: configuration parameters} - Section := 'CONFIG PARAMS'; // do not localize - FClientNotifierPoolSize := ConfigFile.ReadInteger(Section, 'THREADPOOLSIZE', DEFAULT_THREADPOOLSIZE); // do not localize - fDisconnectClientsOnSendFailure := ConfigFile.ReadBool(Section, 'DISCONNECTCLIENTSONSENDFAILURE', DEFAULT_DISCONNECT_CLIENTS_ON_SENDFAILURE); // do not localize + Section := 'CONFIG PARAMS'; + FClientNotifierPoolSize := ConfigFile.ReadInteger(Section, 'THREADPOOLSIZE', DEFAULT_THREADPOOLSIZE); + fDisconnectClientsOnSendFailure := ConfigFile.ReadBool(Section, 'DISCONNECTCLIENTSONSENDFAILURE', DEFAULT_DISCONNECT_CLIENTS_ON_SENDFAILURE); {Section 3: ComServer configuration params} - Section := 'COM SERVER'; // do not localize - FServerName := ConfigFile.ReadString(Section, 'SERVERNAME', 'EnterprisePropagator'); // do not localize - FClientHandlerCLSID := StringToGUID( ConfigFile.ReadString(Section, 'CLSIDCLIENTHANDLER', GUIDToString(CLSID_BOLDCLIENTHANDLER))); // do not localize - FEnqueuerCLSID := StringToGUID( ConfigFile.ReadString(Section, 'CLSIDEVENTPROPAGATOR', GUIDToString(CLSID_BOLDENQUEUER))); // do not localize - FLockManagerCLSID := StringToGUID( ConfigFile.ReadString(Section, 'CLSIDLOCKMANAGER', GUIDToString(CLSID_LOCKMANAGER))); // do not localize - FLockManagerAdminCLSID := StringToGUID( ConfigFile.ReadString(Section, 'CLSIDLOCKMANAGERADMIN', GUIDToString(CLSID_LOCKMANAGERADMIN))); // do not localize - FPropagatorCLSID := StringToGUID( ConfigFile.ReadString(Section, 'CLSIDENTERPRISEPROPAGATOR', GUIDToString(BoldPropagatorConnection_CLSID))); // do not localize + Section := 'COM SERVER'; + FServerName := ConfigFile.ReadString(Section, 'SERVERNAME', 'EnterprisePropagator'); + FClientHandlerCLSID := StringToGUID( ConfigFile.ReadString(Section, 'CLSIDCLIENTHANDLER', GUIDToString(CLSID_BOLDCLIENTHANDLER))); + FEnqueuerCLSID := StringToGUID( ConfigFile.ReadString(Section, 'CLSIDEVENTPROPAGATOR', GUIDToString(CLSID_BOLDENQUEUER))); + FLockManagerCLSID := StringToGUID( ConfigFile.ReadString(Section, 'CLSIDLOCKMANAGER', GUIDToString(CLSID_LOCKMANAGER))); + FLockManagerAdminCLSID := StringToGUID( ConfigFile.ReadString(Section, 'CLSIDLOCKMANAGERADMIN', GUIDToString(CLSID_LOCKMANAGERADMIN))); + FPropagatorCLSID := StringToGUID( ConfigFile.ReadString(Section, 'CLSIDENTERPRISEPROPAGATOR', GUIDToString(BoldPropagatorConnection_CLSID))); finally FreeAndNil(ConfigFile); end; @@ -267,7 +269,7 @@ procedure TBoldPropagatorServer.SetConfiguration(const ServerName: string); if Trim(aServerName) <> '' then begin tempstr := ModuleName; - ConfigFileName := ChangeFileExt(tempstr, '.ini'); // do not localize + ConfigFileName := ChangeFileExt(tempstr, '.ini'); if not FileExists(ConfigFileName) then begin FileHandle := FileCreate(ConfigFileName); @@ -276,14 +278,14 @@ procedure TBoldPropagatorServer.SetConfiguration(const ServerName: string); ConfigFile := TMemIniFile.Create(ConfigFileName); try {Section 1: File Logging} - Section := 'COM SERVER'; // do not localize - ConfigFile.WriteString(Section, 'SERVERNAME', aServerName); // do not localize + Section := 'COM SERVER'; + ConfigFile.WriteString(Section, 'SERVERNAME', aServerName); {Generate new GUIDs} - ConfigFile.WriteString(Section, 'CLSIDCLIENTHANDLER', BoldCreateGUIDAsString); // do not localize - ConfigFile.WriteString(Section, 'CLSIDEVENTPROPAGATOR', BoldCreateGUIDAsString); // do not localize - ConfigFile.WriteString(Section, 'CLSIDLOCKMANAGER', BoldCreateGUIDAsString); // do not localize - ConfigFile.WriteString(Section, 'CLSIDLOCKMANAGERADMIN', BoldCreateGUIDAsString); // do not localize - ConfigFile.WriteString(Section, 'CLSIDENTERPRISEPROPAGATOR', BoldCreateGUIDAsString); // do not localize + ConfigFile.WriteString(Section, 'CLSIDCLIENTHANDLER', BoldCreateGUIDAsString); + ConfigFile.WriteString(Section, 'CLSIDEVENTPROPAGATOR', BoldCreateGUIDAsString); + ConfigFile.WriteString(Section, 'CLSIDLOCKMANAGER', BoldCreateGUIDAsString); + ConfigFile.WriteString(Section, 'CLSIDLOCKMANAGERADMIN', BoldCreateGUIDAsString); + ConfigFile.WriteString(Section, 'CLSIDENTERPRISEPROPAGATOR', BoldCreateGUIDAsString); ConfigFile.UpdateFile; finally @@ -291,7 +293,8 @@ procedure TBoldPropagatorServer.SetConfiguration(const ServerName: string); end; end else - showmessage(Format(sInvalidCommandLineArgs, [aServerName])); + showmessage(Format('Invalid command line argument %s', [aServerName])); + ; end; function TBoldPropagatorServer.GetAppID: TGuid; @@ -306,11 +309,11 @@ function TBoldPropagatorServer.GetAppID: TGuid; ShortFileName := ExtractShortPathName(ShortFileName); ShortFileName := ExtractFileName(ShortFileName); Reg.RootKey := HKEY_CLASSES_ROOT; - Reg.OpenKey('AppID\' + ShortFileName, false); // do not localize - if Reg.ValueExists('AppId') then // do not localize - Result := StringToGuid(Reg.ReadString('AppId')) // do not localize + Reg.OpenKey('AppID\' + ShortFileName, false); + if Reg.ValueExists('AppId') then + Result := StringToGuid(Reg.ReadString('AppId')) else - raise EBold.Create(sAppIDNotFound) + raise EBold.Create('AppId not found, run DCOMCNFG to add appid to registry') finally Reg.CloseKey; Reg.Free; @@ -332,8 +335,8 @@ procedure TBoldPropagatorServer.RegServer(const AppId: TGuid); Reg := TRegistry.Create; try Reg.RootKey := HKEY_CLASSES_ROOT; - Reg.OpenKey('AppID\' + ModuleName, true); // do not localize - Reg.WriteString('AppId', GuidToString(vAppId)); // do not localize + Reg.OpenKey('AppID\' + ModuleName, true); + Reg.WriteString('AppId', GuidToString(vAppId)); finally Reg.CloseKey; Reg.Free; @@ -361,4 +364,6 @@ procedure TBoldPropagatorServer.RemoveComObject(Obj: TBoldComObject); FComObjects.Remove(Obj); end; +initialization + end. diff --git a/Source/Propagator/Enterprise/BoldPropagatorSubscriptions.pas b/Source/Propagator/Enterprise/BoldPropagatorSubscriptions.pas index 4eab13e..6063945 100644 --- a/Source/Propagator/Enterprise/BoldPropagatorSubscriptions.pas +++ b/Source/Propagator/Enterprise/BoldPropagatorSubscriptions.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldPropagatorSubscriptions; interface @@ -7,7 +10,8 @@ interface classes, BoldDefs, BoldIndexList, - BoldIndexedList; + BoldIndexedList + ; type {forward declarations} @@ -65,8 +69,7 @@ implementation uses Sysutils, - BoldUtils, - PropagatorConsts; + BoldUtils; { TBoldSortedIntegerList } @@ -206,7 +209,7 @@ procedure TBoldSubscriptionList.GetAllSubscribedClientsExcept(const EventName: s aEvent: TBoldEventNameIndexNode; begin if not Assigned(ClientIds) then - raise EBold.CreateFmt(sClientIDsNotAssigned, [ClassName, 'GetAllSubscribedClientsExcept']); // do not localize + raise EBold.CreateFmt('%s.GetAllSubscribedClientsExcept: ClientIds not assigned', [ClassName]); aEvent := getEvent(EventName); if Assigned(aEvent) then begin @@ -297,4 +300,6 @@ function TBoldSubscriptionList.GetEventCountByClientID(const ClientID: TBoldClie end; end; +initialization + end. diff --git a/Source/Propagator/Enterprise/BoldPropagatorUIManager.pas b/Source/Propagator/Enterprise/BoldPropagatorUIManager.pas index 9176cb9..8383d2a 100644 --- a/Source/Propagator/Enterprise/BoldPropagatorUIManager.pas +++ b/Source/Propagator/Enterprise/BoldPropagatorUIManager.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldPropagatorUIManager; interface @@ -14,7 +17,7 @@ interface TUIManager = class; { TUIManager } - TUIManager = class(TBoldPassthroughSubscriber) + TUIManager = class(TBoldExtendedPassthroughSubscriber) private fClientHandler: TBoldClientHandler; fEnabled: Boolean; @@ -48,8 +51,7 @@ implementation windows, ComServ, classes, - comctrls, - PropagatorConsts; + comctrls; { UIManager } @@ -86,9 +88,7 @@ procedure TUIManager.OnGetExtendedEvent(Originator: TObject; procedure TUIManager.RefreshClick(Sender: TObject); begin - // this is the method that will be executed on the console refresh button - PropagatorMainForm.mnuRefreshGUI.Caption := sHangOn; -// PropagatorMainForm.btnRefresh.Refresh; + PropagatorMainForm.mnuRefreshGUI.Caption := 'Hang on...'; UpdateDisplay(true); end; @@ -169,14 +169,13 @@ procedure TUIManager.UpdateDisplay(All: Boolean); for i := 0 to ClientInfoList.Count - 1 do begin ClientInfo.CommaText := ClientInfoList[i]; - ClientID := StrToIntDef(ClientInfo.values['ID'], -1); // do not localize + ClientID := StrToIntDef(ClientInfo.values['ID'], -1); if ClientID = -1 then begin - // Some Global info from the ClientHandler PropagatorMainForm.SetClientHandlerStats( - StrToIntDef(ClientInfo.Values['TotalClients'], -1), // do not localize - StrToIntDef(ClientInfo.Values['PeakClients'], -1), // do not localize - StrToIntDef(ClientInfo.Values['TotalLostEvents'], -1)); // do not localize + StrToIntDef(ClientInfo.Values['TotalClients'], -1), + StrToIntDef(ClientInfo.Values['PeakClients'], -1), + StrToIntDef(ClientInfo.Values['TotalLostEvents'], -1)); end else begin @@ -185,19 +184,17 @@ procedure TUIManager.UpdateDisplay(All: Boolean); PropagatorMainForm.AddUser( ClientID, - ClientInfo.values['IDString'], // do not localize - StrToDateFmt(ClientInfo.values['RegistrationTime'], 'yyyy-mm-dd hh:nn:ss', '-'), // do not localize - StrToDateFmt(ClientInfo.values['LeaseTimeout'], 'yyyy-mm-dd hh:nn:ss', '-'), // do not localize - StrToIntDef(ClientInfo.values['Packages'], -1), // do not localize - StrToIntDef(ClientInfo.values['Events'], -1), // do not localize - StrToDateFmt(ClientInfo.values['LastSend'], 'yyyy-mm-dd hh:nn:ss', '-'), // do not localize - StrToDateFmt(ClientInfo.values['LongestInterval'], 'yyyy-mm-dd hh:nn:ss', '-'), // do not localize - ClientInfo.values['Status'], // do not localize - StrToIntDef(ClientInfo.values['LostEvents'], 0)); // do not localize + ClientInfo.values['IDString'], + StrToDateFmt(ClientInfo.values['RegistrationTime'], 'yyyy-mm-dd hh:nn:ss', '-'), + StrToDateFmt(ClientInfo.values['LeaseTimeout'], 'yyyy-mm-dd hh:nn:ss', '-'), + StrToIntDef(ClientInfo.values['Packages'], -1), + StrToIntDef(ClientInfo.values['Events'], -1), + StrToDateFmt(ClientInfo.values['LastSend'], 'yyyy-mm-dd hh:nn:ss', '-'), + StrToDateFmt(ClientInfo.values['LongestInterval'], 'yyyy-mm-dd hh:nn:ss', '-'), + ClientInfo.values['Status'], + StrToIntDef(ClientInfo.values['LostEvents'], 0)); end; end; - - // some testcases does not have a real Advanced Propagator... if assigned(TBoldPropagatorServer.Instance.AdvancedPropagator) then begin PropagatorMainForm.InQ := TBoldPropagatorServer.Instance.AdvancedPropagator.Dequeuer.InQueueCount; @@ -240,11 +237,13 @@ procedure TUIManager.ShutDownClick(Sender: TObject); for i := 0 to ClientInfoList.Count - 1 do begin ClientInfo.CommaText := ClientInfoList[i]; - ClientID := StrToIntDef(ClientInfo.values['ID'], -1); // do not localize - ClientHandler.SendDisconnectRequest(ClientId, sPropagatorMustBeShutDown, 60000); + ClientID := StrToIntDef(ClientInfo.values['ID'], -1); + ClientHandler.SendDisconnectRequest(ClientId, 'Propagator must be shut down', 60000); end; ClientInfoList.Free; ClientInfo.Free; end; +initialization + end. diff --git a/Source/Propagator/Enterprise/BoldServerHandlesDataMod.pas b/Source/Propagator/Enterprise/BoldServerHandlesDataMod.pas index 08c07fb..67a7e10 100644 --- a/Source/Propagator/Enterprise/BoldServerHandlesDataMod.pas +++ b/Source/Propagator/Enterprise/BoldServerHandlesDataMod.pas @@ -1,7 +1,9 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldServerHandlesDataMod; interface - uses Messages, SysUtils, @@ -40,7 +42,6 @@ TdmServerHandles = class(TDataModule) implementation uses - BoldRev, BoldLockManagerCOM, BoldPropagatorServer, BoldComServer, @@ -86,7 +87,7 @@ procedure TdmServerHandles.DisconnectAll; while TBoldPropagatorServer.Instance.ComObjectCount > 0 do begin TBoldPropagatorServer.Instance.ComObjects[0].Disconnect; - TBoldPropagatorServer.Instance.ComObjects[0].Free; // this is because the RefCount is not zeroed after the call to CoDisconnectObject, review + TBoldPropagatorServer.Instance.ComObjects[0].Free; end; end; diff --git a/Source/Propagator/Enterprise/BoldServicePropagatorUnit.pas b/Source/Propagator/Enterprise/BoldServicePropagatorUnit.pas index 20e2cf8..41af3c7 100644 --- a/Source/Propagator/Enterprise/BoldServicePropagatorUnit.pas +++ b/Source/Propagator/Enterprise/BoldServicePropagatorUnit.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldServicePropagatorUnit; interface diff --git a/Source/Propagator/Enterprise/BoldSubscriptionHandler.pas b/Source/Propagator/Enterprise/BoldSubscriptionHandler.pas index 57625c7..7800d6b 100644 --- a/Source/Propagator/Enterprise/BoldSubscriptionHandler.pas +++ b/Source/Propagator/Enterprise/BoldSubscriptionHandler.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldSubscriptionHandler; interface @@ -12,9 +15,11 @@ interface BoldThreadSafeQueue, BoldEnqueuer, BoldAbstractOutputQueueHandler, - BoldThread; + BoldThread + ; type + {forward declarations} TBoldSubscriptionHandler = class; TBoldDequeuer = class; @@ -90,8 +95,7 @@ implementation Boldutils, BoldOutputQueueHandler, BoldPropagatorConstants, - BoldThreadSafeLog, - PropagatorConsts; + BoldThreadSafeLog; {TBoldDequeuer} constructor TBoldDequeuer.Create(InQueue: TBoldThreadSafeObjectQueue); @@ -129,7 +133,7 @@ procedure TboldDequeuer.Dequeue; Events.Clear; end; except on E: EOutOfMemory do - BoldLogError(sLogError, [ClassName, 'Dequeue', E.Message]); // do not localize + BoldLogError('%s.Dequeue: %s', [E.Message]); end; end; @@ -161,15 +165,15 @@ procedure TBoldDequeuer.Execute; begin EnsureMessageQueue; SignalReady; - BoldLogThread('ID=Dequeuer'); // do not localize + BoldLogThread('ID=Dequeuer'); while not Terminated do begin res := Integer(getMessage(rMsg, 0, 0, 0)); try - if res = -1 then //error + if res = -1 then Terminate - else if res = 0 then // terminated + else if res = 0 then Terminate else if rMsg.message = BM_QUEUE_NOT_EMPTY then begin @@ -200,7 +204,6 @@ procedure TBoldDequeuer.Execute; except on e: Exception do begin - // distinct beeps for any occasion! if (res=0) or (res=-1) then Windows.Beep(440, 500) else if (rMsg.Message = BM_REQUEST_CLIENT_INFO) or (rMsg.MEssage = BM_REQUEST_GLOBAL_INFO) then @@ -237,10 +240,11 @@ procedure TBoldDequeuer.NotifyQueueNotEmpty(Queue: TBoldThreadSafeQueue); try self.Notify(BM_QUEUE_NOT_EMPTY); except on E: Exception do - BoldLogError(sLogError, [ClassName, 'NotifyQueueNotEmpty', E.Message]); // do not localize + BoldLogError('%s.NotifyQueueNotEmpty: %s', [ClassName, E.Message]); end; end; + procedure TBoldDequeuer.EnqueueRemoveClientQueueEvent(const ClientID: TBoldClientId); begin fInQueue.Enqueue(TBoldExternalEvent.Create(ClientId, bemRemoveClientQueue, '')); @@ -300,7 +304,7 @@ function TBoldSubscriptionHandler.getOutQueueHandler: TBoldAbstractOutputQueueHa if Assigned(fOutQueueHandler) then Result := fOutQueueHandler else - raise EBold.CreateFmt(sOutputQueueHandlerNotAssigned, [ClassName]); + raise EBold.CreateFmt('%s.getQueueHandler: AbstractOutputQueueHandler is not assigned.', [ClassName]); end; function TBoldSubscriptionHandler.GetSentEventsCount: integer; @@ -323,7 +327,6 @@ procedure TBoldSubscriptionHandler.ProcessExternalEvent( case BoldExternalEvent.EventType of bemEvent: begin - // send event to all registered clients except the sender Clients := TBoldSortedIntegerList.Create; try FSubscriptions.GetAllSubscribedClientsExcept(EventNameWithoutParameters, @@ -332,7 +335,6 @@ procedure TBoldSubscriptionHandler.ProcessExternalEvent( finally FreeAndNil(Clients); end; - // cancel subscriptions for all clients that had subscriptions except the sender FSubscriptions.RemoveEvent(EventNameWithoutParameters); FSubscriptions.AddSubscription(BoldExternalEvent.BoldClientID, EventNameWithoutParameters); end; @@ -359,7 +361,7 @@ procedure TBoldSubscriptionHandler.ProcessExternalEvent( end; end; except on E: Exception do - BoldLogError(sLogError, [ClassName, 'ProcessExternalEvent', E.Message]); // do not localize + BoldLogError('%s.ProcessExternalEvent: error = %s', [ClassName, E.Message]); end; end; @@ -401,4 +403,6 @@ procedure TBoldSubscriptionHandler.SendEvent(EventName: string; end; end; +initialization + end. diff --git a/Source/Propagator/IDECOM/BoldPropagatorHandleCOMReg.pas b/Source/Propagator/IDECOM/BoldPropagatorHandleCOMReg.pas index 948d7d9..da6e7af 100644 --- a/Source/Propagator/IDECOM/BoldPropagatorHandleCOMReg.pas +++ b/Source/Propagator/IDECOM/BoldPropagatorHandleCOMReg.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldPropagatorHandleCOMReg; interface @@ -6,10 +9,9 @@ procedure Register; implementation -{$R *.res} - uses Classes, + BoldGuard, BoldPropagatorHandleCOM, BoldIDEConsts; diff --git a/Source/Propagator/LowEnd/BoldLowEndPropagatorClasses.pas b/Source/Propagator/LowEnd/BoldLowEndPropagatorClasses.pas index 0fa76f8..3ee7080 100644 --- a/Source/Propagator/LowEnd/BoldLowEndPropagatorClasses.pas +++ b/Source/Propagator/LowEnd/BoldLowEndPropagatorClasses.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldLowEndPropagatorClasses; interface @@ -99,7 +102,6 @@ procedure TBoldInternalPropagator.RefreshDisplay; Count, i: integer; Clients: TList; begin - // get the number of registered client count := 0; Clients := nil; for i := 0 to ClientList.Count - 1 do @@ -140,7 +142,6 @@ function TBoldClientPropagator.RegisterClient(LeaseDuration: Integer; PollingInt function TBoldClientPropagator.ExtendLease(BoldClientID: Integer; LeaseDuration: Integer; out ExtensionOK: WordBool): HResult; stdcall; begin - //NOT IMPLEMENTED Result := S_OK; end; @@ -174,7 +175,6 @@ function TBoldClientPropagator.SendEvents(BoldClientID: Integer; Events: OleVar function TBoldClientPropagator.CancelSubscriptions(BoldClientID: Integer; Subscriptions: OleVariant): HResult; begin - // not implemented Result := S_OK; end; diff --git a/Source/Propagator/LowEnd/BoldLowEndPropagatorMainForm.pas b/Source/Propagator/LowEnd/BoldLowEndPropagatorMainForm.pas index 6391ff1..2096445 100644 --- a/Source/Propagator/LowEnd/BoldLowEndPropagatorMainForm.pas +++ b/Source/Propagator/LowEnd/BoldLowEndPropagatorMainForm.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldLowEndPropagatorMainForm; interface @@ -40,7 +43,8 @@ implementation uses SysUtils, - BoldUtils; + BoldUtils, + BoldRev; {$R *.dfm} @@ -48,7 +52,7 @@ procedure TBoldLEPropagatorMainForm.ClearEventsList; begin try Memo1.Lines.BeginUpdate; - Memo1.Lines.Clear; + Memo1.Lines.Clear; finally Memo1.Lines.EndUpdate; end; @@ -93,4 +97,6 @@ procedure TBoldLEPropagatorMainForm.btnClearEventsClick(Sender: TObject); ClearEventsList; end; +initialization + end. diff --git a/Source/Samples/Actions/BoldDebugActions.pas b/Source/Samples/Actions/BoldDebugActions.pas index ec0b219..4df6dfb 100644 --- a/Source/Samples/Actions/BoldDebugActions.pas +++ b/Source/Samples/Actions/BoldDebugActions.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldDebugActions; interface @@ -38,7 +41,7 @@ TBoldLogAction = class(TAction) protected function GetLogHandler: TBoldLogHandler; virtual; abstract; function GetLogType: string; virtual; abstract; - procedure SetLogHandler(Value: TBoldLogHandler); virtual; abstract; + procedure SetLogHandler(Value: TBoldLogHandler); virtual; abstract; property LogType: string read GetLogType; property LogHandler: TBoldLogHandler read GetLogHandler write SetLogHandler; public @@ -73,9 +76,8 @@ TBoldLogPMAction = class(TBoldLogAction) end; { TBoldLogFormAction } - // Note that as long as it's possible to determine the visible state - // from BoldLog it's impossible to be sure if next ExecuteTarget will show - // or hide the form... + + TBoldLogFormAction = class(TAction) private fShowing: boolean; @@ -91,7 +93,8 @@ implementation SysUtils, BoldOCL, BoldDBInterfaces, - BoldPMappers; + BoldPMappers, + BoldRev; { TBoldSystemDebuggerAction } @@ -133,20 +136,15 @@ function TBoldSystemDebuggerAction.GetDebugForm: TBoldSystemDebuggerFrm; procedure TBoldSystemDebuggerAction.CloseDebugForm; begin - if assigned(fDebugForm) then - fDebugForm.Close; + fDebugForm.Close; end; - procedure TBoldSystemDebuggerAction.Notification(AComponent: TComponent; Operation: TOperation); begin inherited; if (AComponent = fDebugForm) and (Operation = opRemove) then - begin fDebugForm := nil; - Checked:=False; - end; end; { TBoldLogOCLAction } @@ -259,4 +257,6 @@ function TBoldLogFormAction.HandlesTarget(Target: TObject): Boolean; Result := True; end; +initialization + end. diff --git a/Source/Samples/Actions/BoldEditOCLAction.pas b/Source/Samples/Actions/BoldEditOCLAction.pas index e1af25e..001aaa4 100644 --- a/Source/Samples/Actions/BoldEditOCLAction.pas +++ b/Source/Samples/Actions/BoldEditOCLAction.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldEditOCLAction; interface @@ -134,4 +137,6 @@ procedure TBoldEditOCLAction.SetOCLExpression(const Value: string); raise Exception.CreateFmt('%s is not connected to an OCL Component', [Name]); end; +initialization + end. diff --git a/Source/Samples/BoldCheckListBox/BoldCheckListBox.pas b/Source/Samples/BoldCheckListBox/BoldCheckListBox.pas index 47365ce..19e22af 100644 --- a/Source/Samples/BoldCheckListBox/BoldCheckListBox.pas +++ b/Source/Samples/BoldCheckListBox/BoldCheckListBox.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldCheckListBox; interface @@ -22,4 +25,10 @@ TBoldCheckListBox = class(TBoldCustomCheckListBox) implementation +uses + BoldRev; + +{ TBoldCheckListBox } +initialization + end. diff --git a/Source/Samples/BoldCheckListBox/BoldCheckListBoxReg.pas b/Source/Samples/BoldCheckListBox/BoldCheckListBoxReg.pas index be3a322..3021ccc 100644 --- a/Source/Samples/BoldCheckListBox/BoldCheckListBoxReg.pas +++ b/Source/Samples/BoldCheckListBox/BoldCheckListBoxReg.pas @@ -1,15 +1,19 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldCheckListBoxReg; interface procedure Register; - + implementation uses Classes, BoldIDEConsts, - BoldCheckListBox; + BoldCheckListBox, + BoldRev; procedure Register; begin diff --git a/Source/Samples/BoldCheckListBox/BoldCustomCheckListBox.pas b/Source/Samples/BoldCheckListBox/BoldCustomCheckListBox.pas index 4a006c9..39b4cd9 100644 --- a/Source/Samples/BoldCheckListBox/BoldCustomCheckListBox.pas +++ b/Source/Samples/BoldCheckListBox/BoldCustomCheckListBox.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldCustomCheckListBox; interface @@ -14,7 +17,8 @@ interface BoldSystem, Classes, Controls, - CheckLst; + CheckLst, + BoldDefs; const CHECKBOXFOLLOWER_INDEX = 0; @@ -42,8 +46,8 @@ TBoldCustomCheckListBox = class(TCheckListBox, IBoldOCLComponent) function GetCurrentBoldElement: TBoldElement; function GetCurrentBoldObject: TBoldObject; function GetContextType: TBoldElementTypeInfo; - procedure SetExpression(Expression: string); - function GetExpression: String; + procedure SetExpression(const Value: TBoldExpression); + function GetExpression: TBoldExpression; function GetVariableList: TBoldExternalVariablelist; function GetBoldlistHandle: TBoldAbstractListHandle; procedure SetBoldListHandle(const Value: TBoldAbstractListHandle); @@ -60,7 +64,7 @@ TBoldCustomCheckListBox = class(TCheckListBox, IBoldOCLComponent) procedure _DisplayString(Follower: TBoldFollower); procedure Click; override; procedure DblClick; override; - procedure _ListInsertItem(Follower: TBoldFollower); + procedure _ListInsertItem(Index: integer; Follower: TBoldFollower); procedure _ListDeleteItem(Index: integer; Follower: TBoldFollower); procedure _ListBeforeMakeUpToDate(Follower: TBoldFollower); procedure _ListAfterMakeUpToDate(Follower: TBoldFollower); @@ -101,12 +105,10 @@ implementation constructor TBoldCustomCheckListBox.Create(AOwner: TComponent); begin inherited Create(AOwner); - //handle fBoldRowStringProperties := TBoldStringFollowerController.Create(self); fBoldRowStringProperties.OnGetContextType := GetContextType; fBoldRowCheckBoxProperties := TBoldCheckBoxStateFollowerController.Create(self); fBoldRowCheckBoxProperties.OnGetContextType := GetContextType; - /// fControllerList := TBoldControllerList.Create(self); fControllerList.Add(fBoldRowCheckBoxProperties); fControllerLIst.Add(fBoldRowStringProperties); @@ -221,7 +223,7 @@ procedure TBoldCustomCheckListBox.DblClick; else if BoldListProperties.DefaultDblClick and Assigned(CurrentBoldElement) then begin - {$IFDEF BOLDCOMCLIENT} // autoform + {$IFDEF BOLDCOMCLIENT} Autoform := nil; {$ELSE} AutoForm := AutoFormProviderRegistry.FormForElement(CurrentBoldElement); @@ -231,7 +233,7 @@ procedure TBoldCustomCheckListBox.DblClick; end; end; -function TBoldCustomCheckListBox.GetExpression: String; +function TBoldCustomCheckListBox.GetExpression: TBoldExpression; begin result := BoldRowStringProperties.Expression; end; @@ -241,9 +243,9 @@ function TBoldCustomCheckListBox.GetVariableList: TBoldExternalVariablelist; Result := BoldListProperties.VariableList; end; -procedure TBoldCustomCheckListBox.SetExpression(Expression: string); +procedure TBoldCustomCheckListBox.SetExpression(const Value: TBoldExpression); begin - BoldRowStringProperties.Expression := Expression; + BoldRowStringProperties.Expression := Value; end; function TBoldCustomCheckListBox.GetBoldlistHandle: TBoldAbstractListHandle; @@ -262,7 +264,7 @@ procedure TBoldCustomCheckListBox._ListDeleteItem(Index: Integer; Follower: TBol Items.Delete(Index); end; -procedure TBoldCustomCheckListBox._ListInsertItem(Follower: TBoldFollower); +procedure TBoldCustomCheckListBox._ListInsertItem(Index: integer; Follower: TBoldFollower); begin Items.Insert(Follower.Index, ''); end; @@ -299,7 +301,6 @@ procedure TBoldCustomCheckListBox._ListAfterMakeUpToDate( procedure TBoldCustomCheckListBox._ListBeforeMakeUpToDate( Follower: TBoldFollower); begin - // will fetch all if Assigned(BoldListHandle) and Assigned(BoldListHandle.List) then BoldListHandle.List.EnsureRange(0, BoldListHandle.List.Count - 1); Items.BeginUpdate; @@ -373,7 +374,6 @@ procedure TBoldCustomCheckListBox.SetAlignment(const Value: TAlignment); if Value <> FAlignment then begin FAlignment := Value; - // Enough to invalidate drawing surface Invalidate; end; end; @@ -400,4 +400,6 @@ procedure TBoldCustomCheckListBox.SetBoldListProperties( FBoldListProperties.Assign(Value); end; +initialization + end. diff --git a/Source/Samples/BoldCheckListBox/BoldSelectionListBox.pas b/Source/Samples/BoldCheckListBox/BoldSelectionListBox.pas index e461363..004085d 100644 --- a/Source/Samples/BoldCheckListBox/BoldSelectionListBox.pas +++ b/Source/Samples/BoldCheckListBox/BoldSelectionListBox.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldSelectionListBox; interface @@ -5,6 +8,7 @@ interface uses BoldCustomCheckListBox, BoldCheckBoxStateControlPack, + BoldControlPack, BoldListHandle, BoldElements, BoldDefs, @@ -24,9 +28,9 @@ TBoldSelectionListBox = class(TBoldCustomCheckListBox) fCheckBoxRenderer: TBoldAsCheckBoxStateRenderer; fPublisher: TBoldPublisher; fSelectionHandle: TBoldListHandle; - function GetAsCheckBoxState(Element: TBoldElement; Representation: TBoldRepresentation; Expression: TBoldExpression): TCheckBoxState; - procedure SetAsCheckBoxState(Element: TBoldElement; newValue: TCheckBoxState; Representation: TBoldRepresentation; Expression: TBoldExpression); - procedure OnSubscribe(Element: TBoldElement; Representation: TBoldRepresentation; Expression: TBoldExpression; Subscriber: TBoldSubscriber); + function GetAsCheckBoxState(aFollower: TBoldFollower): TCheckBoxState; + procedure SetAsCheckBoxState(aFollower: TBoldFollower; newValue: TCheckBoxState); + procedure OnSubscribe(aFollower: TBoldFollower; Subscriber: TBoldSubscriber); procedure SetSelectionHandle(const Value: TBoldListHandle); protected procedure Notification(AComponent: TComponent; Operation: TOperation); override; @@ -45,7 +49,8 @@ TBoldSelectionListBox = class(TBoldCustomCheckListBox) implementation uses - SysUtils; + SysUtils, + BoldRev; { TBoldSelectionListBox } @@ -67,13 +72,11 @@ destructor TBoldSelectionListBox.Destroy; inherited; end; -function TBoldSelectionListBox.GetAsCheckBoxState(Element: TBoldElement; - Representation: TBoldRepresentation; - Expression: TBoldExpression): TCheckBoxState; +function TBoldSelectionListBox.GetAsCheckBoxState(aFollower: TBoldFollower): TCheckBoxState; begin if Assigned(SelectionHandle) then begin - if (SelectionHandle.List.IndexOf(Element) <> -1 ) then + if (SelectionHandle.List.IndexOf(aFollower.Element) <> -1 ) then Result := cbChecked else Result := cbUnChecked; @@ -89,24 +92,20 @@ procedure TBoldSelectionListBox.Notification(AComponent: TComponent; Operation: SelectionHandle := nil; end; -procedure TBoldSelectionListBox.OnSubscribe(Element: TBoldElement; - Representation: TBoldRepresentation; Expression: TBoldExpression; - Subscriber: TBoldSubscriber); +procedure TBoldSelectionListBox.OnSubscribe(aFollower: TBoldFollower; Subscriber: TBoldSubscriber); begin SelectionHandle.AddSmallSubscription(Subscriber, [beValueIdentityChanged, beDestroying], breReSubscribe); SelectionHandle.List.DefaultSubscribe(Subscriber); fPublisher.AddSubscription(Subscriber, beSelectionHandleChanged, breReSubscribe); end; -procedure TBoldSelectionListBox.SetAsCheckBoxState(Element: TBoldElement; - newValue: TCheckBoxState; Representation: TBoldRepresentation; - Expression: TBoldExpression); +procedure TBoldSelectionListBox.SetAsCheckBoxState(aFollower: TBoldFollower; newValue: TCheckBoxState); begin if Assigned(SelectionHandle) then begin case newValue of - cbChecked: SelectionHandle.MutableList.Add(Element); - cbUnChecked: if (SelectionHandle.List.IndexOf(Element) <> -1) then SelectionHandle.MutableList.Remove(Element); + cbChecked: SelectionHandle.MutableList.Add(aFollower.Element); + cbUnChecked: if (SelectionHandle.List.IndexOf(aFollower.Element) <> -1) then SelectionHandle.MutableList.Remove(aFollower.Element); cbGrayed: ; end; end; @@ -122,4 +121,6 @@ procedure TBoldSelectionListBox.SetSelectionHandle( end; end; +initialization + end. diff --git a/Source/Samples/BoldCheckListBox/BoldSelectionListBoxReg.pas b/Source/Samples/BoldCheckListBox/BoldSelectionListBoxReg.pas index 95f0ff7..c892d05 100644 --- a/Source/Samples/BoldCheckListBox/BoldSelectionListBoxReg.pas +++ b/Source/Samples/BoldCheckListBox/BoldSelectionListBoxReg.pas @@ -1,9 +1,12 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldSelectionListBoxReg; interface procedure Register; - + implementation uses @@ -16,4 +19,5 @@ procedure Register; RegisterComponents(BOLDPAGENAME_CONTROLS, [TBoldSelectionListBox]); end; + end. diff --git a/Source/Samples/FormSaver/BoldFormSaver.pas b/Source/Samples/FormSaver/BoldFormSaver.pas index 45021ed..1bc955c 100644 --- a/Source/Samples/FormSaver/BoldFormSaver.pas +++ b/Source/Samples/FormSaver/BoldFormSaver.pas @@ -1,11 +1,16 @@ +{ Global compiler directives } +{$include bold.inc} unit BoldFormSaver; +{.$DEFINE DEBUG_BOLDFORMSAVER} + interface uses Classes, Forms, SysUtils, + Windows, BoldDefs, Boldsubscription, BoldElements, @@ -53,6 +58,8 @@ TBoldDirtyObjectListWithHandle = class(TBoldAbstractDirtyList) destructor Destroy; override; end; + TCallBackFunction = reference to function(Code: Integer; WParam: WPARAM; + var Msg: TMsg): LRESULT; TBoldFormSaver = class(TBoldElementHandle) private @@ -66,9 +73,16 @@ TBoldFormSaver = class(TBoldElementHandle) FTargetFormSaver: TBoldFormSaver; fTargetFormSaverSubscriber: TBoldPassThroughSubscriber; fOnUpdateException: TBoldFormSaverExceptionEvent; + FOrgActivate: TNotifyEvent; + FOrgDeactivate: TNotifyEvent; + class var + FFormSaverList: TList; + FWndProcHookHandle: HHOOK; + class procedure FinalizationFormSavers; static; procedure SetSaveToDBOnOk(const Value: Boolean); procedure SetSystemHandle(const Value: TBoldSystemHandle); function GetDirtyObjects: TBoldDirtyObjectListWithHandle; + class procedure RegisterFormSaver(FormSaver: TBoldFormSaver); static; procedure SetOnlyFirstDirty(const Value: Boolean); procedure _Activate(Sender: TObject); procedure _DeActivate(Sender: TObject); @@ -81,7 +95,10 @@ TBoldFormSaver = class(TBoldElementHandle) procedure SetTargetFormSaver(const Value: TBoldFormSaver); procedure SaveObjects(Objects: TBoldObjectList); procedure SetAutoRemoveCleanObjects(const Value: Boolean); + class procedure UnregisterFormSaver(FormSaver: TBoldFormSaver); static; protected + procedure DoActive; virtual; + procedure DoDeActivate; virtual; function GetValue: TBoldElement; override; function GetStaticSystemTypeInfo: TBoldSystemTypeInfo; override; function GetStaticBoldType: TBoldElementTypeInfo; override; @@ -89,7 +106,9 @@ TBoldFormSaver = class(TBoldElementHandle) procedure EnsureActive; public constructor Create(Owner: TComponent); override; + class constructor Create; destructor Destroy; override; + class destructor Destroy; procedure OK; procedure Cancel; procedure Apply; @@ -107,8 +126,86 @@ TBoldFormSaver = class(TBoldElementHandle) implementation uses + Controls, + Messages, + Types, + BoldBase, + BoldIndex, + BoldIndexableList, + BoldMetaElementList, BoldUtils; +function WndProcHook(Code: Integer; wParam: WParam; lParam: LParam): LRESULT; stdcall; + + function GetFormSaverByOwner(Owner: TComponent): TBoldFormSaver; + var + i: Integer; + begin + Result := nil; + if (Owner <> nil) and (TBoldFormSaver.FFormSaverList <> nil) then begin + for i := 0 to TBoldFormSaver.FFormSaverList.Count - 1 do begin + if TBoldFormSaver(TBoldFormSaver.FFormSaverList[i]).Owner = Owner then begin + Result := TBoldFormSaver.FFormSaverList[i]; + Break; + end; + end; + end; + end; + + function GetFormSaverByHandle(Handle: HWND): TBoldFormSaver; + var + aComp: TComponent; + i: Integer; + begin + aComp := FindControl(Handle); + if aComp is TBoldFormSaver then begin + Result := TBoldFormSaver(aComp); + end else begin + Result := GetFormSaverByOwner(aComp); + + // on modal dialogs also itertate over the calling forms + if (Result = nil) and (aComp is TForm) and + (fsModal in TForm(aComp).FormState) then + begin + for i := 0 to Screen.SaveFocusedList.Count - 1 do begin + Result := GetFormSaverByOwner(TForm(Screen.SaveFocusedList[i])); + if Assigned(Result) then begin + Break; + end; + end; + end; + end; + end; + +var + aMsg: PCWPStruct; + aFormSaver: TBoldFormSaver; +begin + aMsg := PCWPStruct(lParam); + + // Ensure, that there is always an active FormSaver, + // because OnActivate event is not always called. + if (aMsg.message = WM_ACTIVATE) and (LOWORD(aMsg.wParam) <> WA_INACTIVE) then begin + aFormSaver := GetFormSaverByHandle(aMsg.hwnd); + if Assigned(aFormSaver) then begin + aFormSaver.DoActive; + end; + end; + + Result := CallNextHookEx(TBoldFormSaver.FWndProcHookHandle, Code, wParam, lParam); + +{ Everytime a formsaverless form opens, the current FormSaver gets detached. + This is especially problematic on modal dialogues, because then they no longer + transfer their changes to the FormSaver of the owning host form. + if (aMsg.message = WM_ACTIVATE) and (LOWORD(aMsg.wParam) = WA_INACTIVE) then begin + aFormSaver := GetFormSaverByHandle(aMsg.hwnd); + if Assigned(aFormSaver) then begin + aFormSaver.DoDeActivate; + end; + end; +} +end; + const breSystemHandleDestroying = 100; breSystemHandleActivationChange = 101; @@ -127,14 +224,27 @@ procedure TBoldFormSaver.Apply; procedure TBoldFormSaver.Cancel; var - obj: TBoldObject; + aObj: TBoldObject; + aObjList: TBoldObjectList; + i: Integer; begin EnsureActive; - while DirtyObjects.count > 0 do - begin - Obj := DirtyObjects[DirtyObjects.count-1]; - DirtyObjects.removeByIndex(DirtyObjects.count-1); - obj.Discard; + aObjList := TBoldObjectList.Create; + try + while DirtyObjects.count > 0 do begin + aObj := DirtyObjects[DirtyObjects.count-1]; + DirtyObjects.removeByIndex(DirtyObjects.count-1); + + if not aObj.BoldObjectIsNew then begin + aObjList.Add(aObj); + end; + aObj.Discard; + end; + for i := aObjList.Count - 1 downto 0 do begin + aObjList[i].ReRead; + end; + finally + aObjList.Free; end; PostAction; end; @@ -156,16 +266,16 @@ procedure TBoldFormSaver.Cancel; constructor TBoldFormSaver.Create(Owner: TComponent); begin inherited; + RegisterFormSaver(Self); fSystemHandleSubscriber := TBoldPassthroughSubscriber.Create(_SystemHandleReceive); fTargetFormSaverSubscriber := TBoldPassthroughSubscriber.Create(_TargetFormSaverReveice); - if Owner is TForm then - begin - with Owner as TForm do - begin - onActivate := _Activate; - onDeActivate := _DeActivate; - if Active then - _Activate(self); + if Owner is TForm then begin + FOrgActivate := TForm(Owner).OnActivate; + FOrgDeactivate := TForm(Owner).OnDeactivate; + TForm(Owner).OnActivate := _Activate; + TForm(Owner).OnDeactivate := _DeActivate; + if TForm(Owner).Active then begin + DoActive; end; end; SaveToDBOnOk := true; @@ -173,21 +283,63 @@ constructor TBoldFormSaver.Create(Owner: TComponent); fAutoRemoveCleanObjects := true; end; -destructor TBoldFormSaver.destroy; +class constructor TBoldFormSaver.Create; +begin + inherited; + FFormSaverList := TList.Create; +end; + +destructor TBoldFormSaver.Destroy; begin RemoveMyDirtyListFromSystem; FreeAndNil(fDirtyObjects); FreeAndNil(fSystemHandleSubscriber); FreeAndNil(fTargetFormSaverSubscriber); + if Owner is TForm then begin + TForm(Owner).OnActivate := FOrgActivate; + TForm(Owner).OnDeactivate := FOrgDeactivate; + end; + UnregisterFormSaver(Self); inherited; end; +class destructor TBoldFormSaver.Destroy; +begin + FinalizationFormSavers; + FreeAndNil(FFormSaverList); + inherited; +end; + +procedure TBoldFormSaver.DoActive; +begin + {$IFDEF DEBUG_BOLDFORMSAVER} + OutputDebugString(PChar(Format( + 'Activating BoldFormSaver %s (%s)', [Name, TForm(Owner).Caption]))); + {$ENDIF} + SetDirtyListInSystem(DirtyObjects); +end; + +procedure TBoldFormSaver.DoDeActivate; +begin + {$IFDEF DEBUG_BOLDFORMSAVER} + OutputDebugString(PChar(Format( + 'Deactivating BoldFormSaver %s (%s)', [Name, TForm(Owner).Caption]))); + {$ENDIF} + SetDirtyListInSystem(nil); +end; + procedure TBoldFormSaver.EnsureActive; begin if not assigned(SystemHandle) or not SystemHandle.Active then raise EBold.Create('TBoldFormSaver: No system available'); end; +class procedure TBoldFormSaver.FinalizationFormSavers; +begin + UnhookWindowsHookEx(FWndProcHookHandle); + FWndProcHookHandle := 0; +end; + function TBoldFormSaver.GetDirtyObjects: TBoldDirtyObjectListWithHandle; begin if not assigned(fDirtyObjects) then @@ -233,6 +385,17 @@ procedure TBoldFormSaver.PostAction; (Owner as TForm).Close; end; +class procedure TBoldFormSaver.RegisterFormSaver(FormSaver: TBoldFormSaver); +begin + if FFormSaverList.IndexOf(FormSaver) < 0 then begin + if FFormSaverList.Count = 0 then begin + FWndProcHookHandle := SetWindowsHookEx( + WH_CALLWNDPROC, WndProcHook, 0, GetCurrentThreadId); + end; + FFormSaverList.Add(FormSaver); + end; +end; + procedure TBoldFormSaver.RemoveMyDirtyListFromSystem; begin @@ -273,7 +436,11 @@ procedure TBoldFormSaver.SaveObjects(Objects: TBoldObjectList); finally TempList.Free; end; - Objects.Clear; + if (not (csDestroying in ComponentState)) and + (DirtyObjects.Count = 0) then // ensure that every objects is saved + begin + Objects.Clear; + end; end; end; @@ -343,14 +510,30 @@ procedure TBoldFormSaver.SetTargetFormSaver(const Value: TBoldFormSaver); end; end; +class procedure TBoldFormSaver.UnregisterFormSaver(FormSaver: TBoldFormSaver); +begin + if FFormSaverList <> nil then + begin + FFormSaverList.Extract(FormSaver); + if FFormSaverList.Count = 0 then + FinalizationFormSavers; + end; +end; + procedure TBoldFormSaver._Activate(Sender: TObject); begin - SetDirtyListInSystem(DirtyObjects); + DoActive; + if Assigned(FOrgActivate) then begin + FOrgActivate(Sender); + end; end; procedure TBoldFormSaver._DeActivate(Sender: TObject); begin - SetDirtyListInSystem(nil); + DoDeActivate; + if Assigned(FOrgActivate) then begin + FOrgActivate(Sender); + end; end; procedure TBoldFormSaver._SystemHandleReceive(Originator: TObject; @@ -362,7 +545,7 @@ procedure TBoldFormSaver._SystemHandleReceive(Originator: TObject; if (RequestedEvent = breSystemHandleActivationChange) and (Originator = SystemHandle) and (Owner as TForm).Active then begin - _Activate(self); + DoDeActivate; end; end; diff --git a/Source/Samples/IDE/BoldEditOCLActionPropEditor.pas b/Source/Samples/IDE/BoldEditOCLActionPropEditor.pas index 35bae8f..b51ff26 100644 --- a/Source/Samples/IDE/BoldEditOCLActionPropEditor.pas +++ b/Source/Samples/IDE/BoldEditOCLActionPropEditor.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldEditOCLActionPropEditor; interface @@ -24,7 +27,8 @@ implementation uses TypInfo, SysUtils, - BoldElements; + BoldElements, + BoldRev; { TBoldOCLComponentEditor } @@ -40,4 +44,6 @@ procedure TBoldOCLComponentEditor.GetValues(Proc: TGetStrProc); Designer.GetComponentNames(GetTypeData(GetPropType), FilterOnInterface); end; +initialization + end. diff --git a/Source/Samples/IDE/BoldSamplesReg.pas b/Source/Samples/IDE/BoldSamplesReg.pas index c6663df..34460df 100644 --- a/Source/Samples/IDE/BoldSamplesReg.pas +++ b/Source/Samples/IDE/BoldSamplesReg.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldSamplesReg; interface @@ -11,30 +14,35 @@ implementation Classes, DesignIntf, ActnList, +{$IFDEF BOLD_DELPHI16_OR_LATER} + Actions, +{$ENDIF} +{$IFNDEF LightMemberDeriver} BoldFormSaver, +{$ENDIF} + BoldGuard, BoldPropertyEditors, BoldNewObjectInterceptor, - BoldSortingGrid, BoldIDEConsts, BoldEditOCLAction, BoldEditOCLActionPropEditor, BoldDebugActions; -{$R *.res} - type TTextFileProperty = class(TBoldFileNameProperty) protected function FileFilter: string; override; end; + procedure RegisterComponentsOnPalette; begin RegisterComponents(BOLDPAGENAME_MISC, [ - TBoldNewObjectInterceptor, - TBoldFormSaver, - TBoldSortingGrid + TBoldNewObjectInterceptor +{$IFNDEF LightMemberDeriver} + ,TBoldFormSaver +{$ENDIF} ]); end; @@ -54,8 +62,8 @@ procedure RegisterBoldActions; procedure RegisterEditors; begin - RegisterPropertyEditor(TypeInfo(string), TBoldNewObjectInterceptor, 'Filename', TTextFileProperty); //do not localize - RegisterPropertyEditor(TypeInfo(TComponent), TBoldEditOCLAction, 'BoldComponent', TBoldOCLComponentEditor); //do not localize + RegisterPropertyEditor(TypeInfo(string), TBoldNewObjectInterceptor, 'Filename', TTextFileProperty); + RegisterPropertyEditor(TypeInfo(TComponent), TBoldEditOCLAction, 'BoldComponent', TBoldOCLComponentEditor); end; procedure Register; @@ -71,6 +79,5 @@ function TTextFileProperty.FileFilter: string; begin Result := Format('%s (*%s)|*%1:s', ['Text files', '.txt']); end; - + end. - diff --git a/Source/Samples/Misc/BoldLockUtils.pas b/Source/Samples/Misc/BoldLockUtils.pas index 418be6d..ab91407 100644 --- a/Source/Samples/Misc/BoldLockUtils.pas +++ b/Source/Samples/Misc/BoldLockUtils.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldLockUtils; interface @@ -79,11 +82,8 @@ class procedure TBoldLockUtils.GetLockInfo(System: TBoldSystem; LockHolder: TBol Traverser: TBoldIndexTraverser; begin Traverser := List.CreateTraverser; - while not Traverser.EndOfList do - begin + while Traverser.MoveNext do AddLockInfo(Traverser.item as TBoldLock, Exclusive); - Traverser.Next; - end; Traverser.Free; end; @@ -127,11 +127,12 @@ class procedure TBoldLockUtils.LockInfoToStringGrid(StringGrid: TStringGrid; Sys InitCol(1, 60, 'Type'); InitCol(2, 120, 'Class'); InitCol(3, 200, 'Object'); - StringGrid.Rows[1].Text := ''; // Clear GhostRow + StringGrid.Rows[1].Text := ''; for i := 0 to LockInfo.Count-1 do StringGrid.Rows[i+1].CommaText := LockInfo[i]; LockInfo.Free; end; +initialization end. diff --git a/Source/Samples/Misc/BoldObjectRetriever.pas b/Source/Samples/Misc/BoldObjectRetriever.pas index f5aa4b0..5dac536 100644 --- a/Source/Samples/Misc/BoldObjectRetriever.pas +++ b/Source/Samples/Misc/BoldObjectRetriever.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldObjectRetriever; interface @@ -8,11 +11,11 @@ interface BoldValueSpaceInterfaces, BoldSystem; -function BoldRetrieveObjectByIdString(BoldSystem: TBoldSystem; IdString: String): TBoldObject; +function BoldRetrieveObjectByIdString(BoldSystem: TBoldSystem; IdString: String; aLoadIfNotInMemory: boolean = true): TBoldObject; implementation -function RetrieveObjectByInexactId(BoldSystem: TBoldSystem; ObjectId: tBoldObjectId): TBoldObject; +function RetrieveObjectByInexactId(BoldSystem: TBoldSystem; ObjectId: TBoldObjectId): TBoldObject; var TranslationList: TBoldIdTranslationList; IdList: TBoldObjectIdList; @@ -26,9 +29,9 @@ function RetrieveObjectByInexactId(BoldSystem: TBoldSystem; ObjectId: tBoldObjec IdList := TBoldObjectIdList.Create; try IdList.Add(ObjectId); - BoldSystem.PersistenceController.PMExactifyIds(IdList, TranslationList); + BoldSystem.PersistenceController.PMExactifyIds(IdList, TranslationList, true); ExactId := TranslationList.TranslateToNewId[ObjectId]; - if ExactId.TopSortedIndexExact then + if (not ExactId.NonExisting) and ExactId.TopSortedIndexExact then begin Locator := BoldSystem.EnsuredLocatorByID[ExactId]; if Locator.EnsuredBoldObject.BoldExistenceState = besExisting then @@ -41,7 +44,7 @@ function RetrieveObjectByInexactId(BoldSystem: TBoldSystem; ObjectId: tBoldObjec end; end; -function BoldRetrieveObjectByIdString(BoldSystem: TBoldSystem; IdString: String): TBoldObject; +function BoldRetrieveObjectByIdString(BoldSystem: TBoldSystem; IdString: String; aLoadIfNotInMemory: boolean): TBoldObject; var ObjectId: TBoldDefaultID; Locator: TBoldObjectLocator; @@ -54,11 +57,11 @@ function BoldRetrieveObjectByIdString(BoldSystem: TBoldSystem; IdString: String) ObjectId := TBoldDefaultID.CreateWithClassID(0, false); ObjectId.AsInteger := IdValue; try - // Check if the locator is already in memory Locator := BoldSystem.Locators.LocatorByID[ObjectId]; if assigned(Locator) then result := Locator.EnsuredBoldObject else + if aLoadIfNotInMemory then result := RetrieveObjectByInexactId(BoldSystem, ObjectId); finally ObjectId.Free; diff --git a/Source/Samples/ModelLoader/BoldModelLoader.pas b/Source/Samples/ModelLoader/BoldModelLoader.pas index 09e496a..e49b54a 100644 --- a/Source/Samples/ModelLoader/BoldModelLoader.pas +++ b/Source/Samples/ModelLoader/BoldModelLoader.pas @@ -1,7 +1,9 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldModelLoader; interface - uses Classes, Dialogs, @@ -30,7 +32,8 @@ implementation uses SysUtils, - BoldUtils; + BoldUtils, + BoldRev; var G_ModelLoader: TBoldModelLoader = nil; @@ -105,4 +108,3 @@ initialization finalization FreeAndNil(G_ModelLoader); end. - diff --git a/Source/Samples/NewObjectInterceptor/BoldNewObjectInterceptor.pas b/Source/Samples/NewObjectInterceptor/BoldNewObjectInterceptor.pas index 67561bf..9e94818 100644 --- a/Source/Samples/NewObjectInterceptor/BoldNewObjectInterceptor.pas +++ b/Source/Samples/NewObjectInterceptor/BoldNewObjectInterceptor.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldNewObjectInterceptor; interface @@ -86,7 +89,6 @@ procedure TBoldNewObjectInterceptor.InitializeAttribute(Attribute: TBoldAttribut begin if Attribute is TBAInteger then begin - // Note: Might be lengthy if range is narrow!! repeat i := Random(20000) - 10000; until (Attribute as TBAInteger).CheckRange(i); @@ -128,8 +130,6 @@ procedure TBoldNewObjectInterceptor.Receive(Originator: TObject; OriginalEvent: if Args[0].VObject is TBoldObjectLocator then begin Locator := Args[0].VObject as TBoldObjectLocator; - - // check id the object was loaded from the db... if not Locator.BoldObjectID.IsStorable then SetRandomAttributes(Locator.BoldObject); end; @@ -167,4 +167,6 @@ procedure TBoldNewObjectInterceptor.SubscribeToElement( (Element as TBoldSystem).Classes[0].DefaultSubscribe(Subscriber, breReEvaluate); end; +initialization + end. diff --git a/Source/Samples/SortingGrid/BoldSortingGrid.pas b/Source/Samples/SortingGrid/BoldSortingGrid.pas index 4b3fbd3..2d89e58 100644 --- a/Source/Samples/SortingGrid/BoldSortingGrid.pas +++ b/Source/Samples/SortingGrid/BoldSortingGrid.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldSortingGrid; interface @@ -55,8 +58,8 @@ TBoldSortingGrid = class(TBoldgrid) property Comparer: TBoldComparer read GetComparer; property ListHandle: TBoldListHandle read GetListHandle; public - constructor Create(aOwner: TComponent); override; - destructor Destroy; override; + constructor create(aOwner: TComponent); override; + destructor destroy; override; procedure DrawCell(ACol, aRow: Longint; ARect: TRect; AState: TGridDrawState); override; property OrderCol: integer read FOrderCol write SetOrderCol; property OrderDescending: Boolean read FOrderDescending write SetOrderDescending; @@ -74,7 +77,8 @@ implementation uses SysUtils, Graphics, - BoldDefs; + BoldDefs, + BoldRev; { TBoldSortingGrid } function TBoldSortingGrid.AdjustStringForNumericCompare(s: String): String; @@ -104,7 +108,6 @@ function TBoldSortingGrid.ComparerCompare(Item1, Item2: TBoldElement): Integer; begin Obj1 := Item1 as TBoldObject; Obj2 := Item2 as TBoldObject; - // if both objects are new, then sort them by ID, otherwise sort the new object after the old if Obj2.BoldObjectIsNew and Obj1.BoldObjectIsNew then begin result := StrToIntDef(Obj1.BoldObjectLocator.BoldObjectId.AsString, 0) - StrToIntDef(Obj2.BoldObjectLocator.BoldObjectId.AsString, 0); @@ -260,22 +263,16 @@ procedure TBoldSortingGrid.MouseUp(Button: TMouseButton; Col: integer; begin inherited; - // are we in the title? if (FixedRows = 0) or (csDesigning in ComponentState) or (y > RowHeights[0]) then exit; - - // has sorting been disabled if not EnableSorting then exit; - - // has the mouse moved since it was pressed? if (x <> fLastMouseDown.x) or (y <> fLastMouseDown.y) then exit; - + Col := 0; while (x > 0) and (Col < ColCount) do begin - // Act only on the visible columns if (Col < FixedCols) or (Col >= LeftCol) then begin dec(x, ColWidths[Col]); @@ -392,4 +389,5 @@ procedure TBoldSortingGrid.FetchIntelligently; end; end; +initialization end. diff --git a/Source/Samples/SystemComparer/BoldSystemComparer.pas b/Source/Samples/SystemComparer/BoldSystemComparer.pas index d7442c7..6fc23a3 100644 --- a/Source/Samples/SystemComparer/BoldSystemComparer.pas +++ b/Source/Samples/SystemComparer/BoldSystemComparer.pas @@ -1,27 +1,43 @@ -unit BoldSystemComparer; +{ Global compiler directives } +{$include bold.inc} +unit BoldSystemComparer; interface uses Classes, BoldSystem, + BoldElements, + BoldDomainElement, BoldHandles; type + TOnDifferenceEvent = procedure (ALeft, ARight: TBoldDomainElement; AMessage: string; var AContinue: boolean) of object; + TCompareOptions = set of (coDerived, // derived members + coTransient, // transient members + coTransientObjects, // transient objects + coCompareObjectTimestamp // Object timestamp + {coIgnoreCurrentTime}); TBoldSystemComparer = class + private + fOnDifference: TOnDifferenceEvent; + fOptions: TCompareOptions; protected - class function GetCorrespondingObject(LeftObject: TBoldObject; RightSystem: TBoldSystem): TBoldObject; virtual; - class function CompareObjects(Left, Right: TBoldObject): string; virtual; - class function CompareAttributes(Left, Right: TBoldAttribute): string; virtual; - class function CompareMembers(Left, Right: TBoldMember): string; virtual; - class function CompareObjectReferences(Left, Right: TBoldObjectReference): string; virtual; - class function CompareObjectLists(Left, Right: TBoldObjectList): string; virtual; - class function FullObjectName(BoldObject: TBoldObject): string; virtual; - class function FullMemberName(BoldMember: TBoldMember): string; virtual; - class function ObjectReferenceAsString(ObjectReference: TBoldObjectReference): string; virtual; + function GetCorrespondingObject(LeftObject: TBoldObject; RightSystem: TBoldSystem): TBoldObject; virtual; + function CompareObjects(Left, Right: TBoldObject): string; virtual; + function CompareAttributes(Left, Right: TBoldAttribute): string; virtual; + function CompareMembers(Left, Right: TBoldMember): string; virtual; + function CompareObjectReferences(Left, Right: TBoldObjectReference): string; virtual; + function CompareObjectLists(Left, Right: TBoldObjectList): string; virtual; + function FullObjectName(BoldObject: TBoldObject): string; virtual; + function FullMemberName(BoldMember: TBoldMember): string; virtual; + function ObjectReferenceAsString(ObjectReference: TBoldObjectReference): string; virtual; + function DoOnDifference(ALeft, ARight: TBoldDomainElement; AMessage: string): boolean; public - class function CompareSystems(Left, Right: TBoldSystem): string; virtual; + function CompareSystems(Left, Right: TBoldSystem): string; virtual; + property OnDifference: TOnDifferenceEvent read fOnDifference write fOnDifference; + property Options: TCompareOptions read fOptions write fOptions; end; @@ -31,23 +47,31 @@ implementation SysUtils, BoldUtils; - { TBoldSystemComparer } -class function TBoldSystemComparer.CompareAttributes(Left, +function TBoldSystemComparer.CompareAttributes(Left, Right: TBoldAttribute): string; begin if not Left.IsEqual(Right) then + begin result := Format('Attributes differ: %s:''%s'' <> %s:''%s''', [ FullMemberName(Left), Left.AsString, FullMemberName(right), Right.AsString]); + if DoOnDifference(Left, Right, result) then + result := ''; + end; end; -class function TBoldSystemComparer.CompareMembers(Left, +function TBoldSystemComparer.CompareMembers(Left, Right: TBoldMember): string; begin + result := ''; + if not (coDerived in Options) and left.Derived then + exit; + if not (coTransient in Options) and not left.BoldPersistent then + exit; if (Left is TBoldAttribute) and (Right is TBoldAttribute) then Result := CompareAttributes(TBoldAttribute(Left), TBoldAttribute(Right)) else if (Left is TBoldObjectReference) and (Right is TBoldObjectReference) then @@ -56,9 +80,11 @@ class function TBoldSystemComparer.CompareMembers(Left, result := CompareObjectLists(TBoldObjectList(Left), TBoldObjectList(Right)) else result := Format('members differ in type %s <> %s', [FullMemberName(Left), FullMemberName(Right)]); + if (result <> '') and DoOnDifference(Left, Right, result) then + result := ''; end; -class function TBoldSystemComparer.CompareObjectLists(Left, +function TBoldSystemComparer.CompareObjectLists(Left, Right: TBoldObjectList): string; var i: integer; @@ -66,7 +92,7 @@ class function TBoldSystemComparer.CompareObjectLists(Left, RightCopy: TBoldObjectList; Ordered: Boolean; begin - Ordered := Left.BoldRoleRTInfo.IsOrdered; + Ordered := Left.BoldRoleRTInfo.IsOrdered; if Left.Count <> Right.Count then Result := Format( 'multilinks have different count : %s:%d <> %s:%d', [ @@ -74,6 +100,8 @@ class function TBoldSystemComparer.CompareObjectLists(Left, left.Count, FullMemberName(right), right.Count]) + else if Left.Empty then + exit else if Ordered then begin for i := 0 to Left.Count-1 do @@ -86,7 +114,7 @@ class function TBoldSystemComparer.CompareObjectLists(Left, FullObjectName(Left[i]), FullMemberName(Right), FullObjectName(Right[i])]); - Exit; + break; end; end else @@ -103,21 +131,23 @@ class function TBoldSystemComparer.CompareObjectLists(Left, begin Result := Format( 'Position %d in left not found in right : %s[%d]:%s no in %s', [ - i, i, + i, FullMemberName(Left), + i, FullObjectName(Left[i]), - FullMemberName(Right), - FullObjectName(Right[i])]); - Exit; + FullMemberName(Right)]); + break; end; end; finally RightCopy.Free; end; end; + if (result <> '') and DoOnDifference(Left, Right, result) then + result := ''; end; -class function TBoldSystemComparer.CompareObjectReferences(Left, +function TBoldSystemComparer.CompareObjectReferences(Left, Right: TBoldObjectReference): string; begin if GetCorrespondingObject(Left.BoldObject, right.BoldSystem) <> Right.BoldObject then @@ -127,14 +157,16 @@ class function TBoldSystemComparer.CompareObjectReferences(Left, ObjectReferenceAsString(Left), FullMemberName(right), ObjectReferenceAsString(Right)]); + if (result <> '') and DoOnDifference(Left, Right, result) then + result := ''; end; -class function TBoldSystemComparer.CompareObjects(Left, +function TBoldSystemComparer.CompareObjects(Left, Right: TBoldObject): string; var i: integer; begin - if Left.BoldClassTypeInfo.ExpressionName <> right.BoldClassTypeInfo.ExpressionName then + if not Left.BoldClassTypeInfo.BoldIsA(right.BoldClassTypeInfo) then Result := Format( 'Objects have different ClassName : %s:%d <> %s:%d', [ FullObjectName(Left), @@ -150,21 +182,26 @@ class function TBoldSystemComparer.CompareObjects(Left, right.BoldMemberCount]) else begin + if (coCompareObjectTimestamp in Options) and + (left.AsIBoldObjectContents[bdepContents].TimeStamp <> right.AsIBoldObjectContents[bdepContents].TimeStamp) then + result := Format('Left %s Timestamp: %d <> Right %s Timestamp: %d', [Left.DebugInfo, left.AsIBoldObjectContents[bdepContents].TimeStamp, right.DebugInfo, right.AsIBoldObjectContents[bdepContents].TimeStamp]) + else for i := 0 to Left.BoldMemberCount-1 do begin result := CompareMembers(Left.BoldMembers[i], Right.BoldMembers[i]); - if Result <> ' ' then + if Result <> '' then Break; end; end; + if (result <> '') and DoOnDifference(Left, Right, result) then + result := ''; end; -class function TBoldSystemComparer.CompareSystems(Left, +function TBoldSystemComparer.CompareSystems(Left, Right: TBoldSystem): string; var i: integer; - IndexOfCorresponding: integer; - RightCopy: TBoldObjectList; + LeftObject, RightObject: TBoldObject; begin if Left.Classes[0].Count <> Right.Classes[0].Count then Result := Format( @@ -174,30 +211,42 @@ class function TBoldSystemComparer.CompareSystems(Left, ) else begin - RightCopy := TBoldObjectList.Create; - try - RightCopy.AddList(Right.Classes[0]); - for i := 0 to Left.Classes[0].Count-1 do - begin - IndexOfCorresponding := RightCopy.IndexOf(GetCorrespondingObject(Left.Classes[0][i], Right)); - if IndexOfCorresponding <> -1 then - begin - Result := Compareobjects(Left.Classes[0][i], Left.Classes[0][IndexOfCorresponding]); - RightCopy.RemoveByIndex(IndexOfCorresponding) - end - else - Result := Format( - 'Object %s in left not found in right' , [FullObjectName(Left.Classes[0][i])]); - if result <> '' then - Exit; - end; - finally - RightCopy.Free; + Left.Classes[0].EnsureObjects; + Right.Classes[0].EnsureObjects; +{$IFDEF FetchFromClassList} + for i := 0 to Left.BoldSystemTypeInfo.TopSortedClasses.Count -1 do + Left.Classes[i].EnsureObjects; + for i := 0 to Right.BoldSystemTypeInfo.TopSortedClasses.Count -1 do + Right.Classes[i].EnsureObjects; +{$ENDIF} + for i := 0 to Left.Classes[0].Count-1 do + begin + LeftObject := Left.Classes[0][i]; + if not (coTransientObjects in Options) and not LeftObject.BoldPersistent then + continue; // skip transient objects + RightObject := Right.Locators.ObjectByID[LeftObject.BoldObjectLocator.BoldObjectID]; + if Assigned(RightObject) then + Result := Compareobjects(LeftObject, RightObject) + else + Result := Format( + 'Object %s in left not found in right' , [FullObjectName(Left.Classes[0][i])]); + if result <> '' then + break; end; end; + if (result <> '') and DoOnDifference(Left, Right, result) then + result := ''; end; -class function TBoldSystemComparer.FullMemberName( +function TBoldSystemComparer.DoOnDifference(ALeft, ARight: TBoldDomainElement; + AMessage: string): boolean; +begin + result := false; + if Assigned(fOnDifference) then + fOnDifference(ALeft, ARight, AMessage, result); +end; + +function TBoldSystemComparer.FullMemberName( BoldMember: TBoldMember): string; begin if not Assigned(BoldMember) then @@ -206,7 +255,7 @@ class function TBoldSystemComparer.FullMemberName( Result := Format('%s.%s', [FullObjectName(BoldMember.OwningObject), BoldMember.BoldMemberRTInfo.expressionname]); end; -class function TBoldSystemComparer.FullObjectName( +function TBoldSystemComparer.FullObjectName( BoldObject: TBoldObject): string; begin if not Assigned(BoldObject) then @@ -215,7 +264,7 @@ class function TBoldSystemComparer.FullObjectName( Result := Format('%s:%s', [BoldObject.BoldClassTypeInfo.expressionname, BoldObject.BoldObjectLocator.AsString]); end; -class function TBoldSystemComparer.GetCorrespondingObject( +function TBoldSystemComparer.GetCorrespondingObject( LeftObject: TBoldObject; RightSystem: TBoldSystem): TBoldObject; begin if not Assigned(LeftObject) then @@ -224,13 +273,15 @@ class function TBoldSystemComparer.GetCorrespondingObject( Result := RightSystem.Locators.ObjectByID[LeftObject.BoldObjectLocator.BoldObjectID]; end; -class function TBoldSystemComparer.ObjectReferenceAsString(ObjectReference: +function TBoldSystemComparer.ObjectReferenceAsString(ObjectReference: TBoldObjectReference): string; begin if Assigned(ObjectReference) then Result := FullObjectName(ObjectReference.BoldObject) else - result := 'Nil'; //do not localize + result := 'Nil'; end; +initialization + end. diff --git a/Source/Samples/SystemDebugger/BoldSystemDebuggerForm.pas b/Source/Samples/SystemDebugger/BoldSystemDebuggerForm.pas index 6e9631d..8fe4b32 100644 --- a/Source/Samples/SystemDebugger/BoldSystemDebuggerForm.pas +++ b/Source/Samples/SystemDebugger/BoldSystemDebuggerForm.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldSystemDebuggerForm; interface @@ -11,7 +14,6 @@ interface BoldRootedHandles, BoldAFP, BoldAfpDefault, - BoldMemoryManager, BoldSystem, BoldOcl, BoldLogHandler, @@ -86,13 +88,11 @@ implementation uses SysUtils, - BoldRev, BoldUtils; procedure TBoldSystemDebuggerFrm.btnUpdateMemoryInfoClick(Sender: TObject); begin - mmoMemoryInfo.Lines.Text := BoldMemoryManager_.MemoryInfo; mmoSharedStrings.Lines.text := BoldSharedStringManager.InfoString; end; @@ -155,7 +155,6 @@ procedure TBoldSystemDebuggerFrm.btnUpdateDirtyObjectsClick(Sender: TObject); var i: integer; begin - // Only activated if system is assigned fDirtyList.Clear; for i := 0 to System.DirtyObjects.Count-1 do fDirtyList.add(TBoldObject(System.DirtyObjects[i])); @@ -163,7 +162,6 @@ procedure TBoldSystemDebuggerFrm.btnUpdateDirtyObjectsClick(Sender: TObject); procedure TBoldSystemDebuggerFrm.btnUpdateDatabaseClick(Sender: TObject); begin - // Only activated if system is assigned System.UpdateDatabase end; diff --git a/Source/Samples/UMLPlugins/BoldUMLNameTrimmer.pas b/Source/Samples/UMLPlugins/BoldUMLNameTrimmer.pas index 133909f..636ca0d 100644 --- a/Source/Samples/UMLPlugins/BoldUMLNameTrimmer.pas +++ b/Source/Samples/UMLPlugins/BoldUMLNameTrimmer.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldUMLNameTrimmer; interface @@ -32,14 +35,13 @@ implementation uses SysUtils, - BoldUtils; + BoldUtils, + BoldRev; var _UMLNameFixer: TUMLNameFixer = nil; { TUMLNameFixer } - -// Main method to invoke plug in functionality procedure TUMLNameFixer.Execute(context: IUMLModelPlugInContext); var UMLModel: TUMLModel; @@ -54,32 +56,22 @@ procedure TUMLNameFixer.Execute(context: IUMLModelPlugInContext); BoldLog.EndLog; end; end; - -// Mask color for bitmap function TUMLNameFixer.GetImageMaskColor: TColor; begin Result := clTeal; end; - -// Resource for menu and button icon function TUMLNameFixer.GetImageResourceName: String; begin result := 'NameTrimmer'; end; - -// Caption for menu and hint for button function TUMLNameFixer.GetMenuItemName: String; begin Result := 'Name trimmer'; end; - -// Type of tool function TUMLNameFixer.GetPlugInType: TPlugInType; begin Result := ptTool; end; - -// Trims name of class + all its members and association ends procedure TUMLNameFixer.TrimClassAndMembers(UMLClass: TUMLClass); var i: integer; @@ -92,8 +84,6 @@ procedure TUMLNameFixer.TrimClassAndMembers(UMLClass: TUMLClass); for i := 0 to UMLClass.AssociationEnd.Count - 1 do TrimName(UMLClass.AssociationEnd[i]); end; - -// Trimmer of names procedure TUMLNameFixer.TrimName(UMLElement: TUMLModelElement); begin if UMLElement.Name <> Trim(UMLElement.Name) then @@ -104,6 +94,7 @@ procedure TUMLNameFixer.TrimName(UMLElement: TUMLModelElement); end; initialization + _UMLNameFixer := TUMLNameFixer.Create(true); finalization diff --git a/Source/Samples/Unicode/BoldAttributeWideString.pas b/Source/Samples/Unicode/BoldAttributeWideString.pas index 97381a5..1d6eff3 100644 --- a/Source/Samples/Unicode/BoldAttributeWideString.pas +++ b/Source/Samples/Unicode/BoldAttributeWideString.pas @@ -1,22 +1,22 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldAttributeWideString; -// useful links: -// Delphi-Unicode.net: http://www.delphi-unicode.net -// Unicode components: http://mikroklubben.adsl.dk/~nikse/delphi-unicode.zip -// unicode fonts: http://www.hclrss.demon.co.uk/unicode/fonts.html -// Arial MS Unicode.ttf: http://office.microsoft.com/downloads/2000/aruniupd.aspx - -// To install this attribute type in your application, add the following to your -// TypeNameHandle: -// -// ModelName: UniCode -// ExpressionName: WideString -// DelphiName: TBAWideString -// ContentName: WideString -// PMapper: TBoldPMWideString -// Accessor: AsWideString -// NativeType: WideString -// UnitName: BoldAttributeWideString + + + + + + + + + + + + + + interface @@ -42,18 +42,18 @@ TBAWideString = class(TBoldAttribute) function GetWideStringRepresentation(Representation: TBoldRepresentation): WideString; procedure SetWideStringRepresentation(Representation: TBoldRepresentation; const Value: WideString); protected - procedure AssignContentValue(Source: IBoldValue); override; + procedure AssignContentValue(const Source: IBoldValue); override; procedure FreeContent; override; function GetStringRepresentation(Representation: TBoldRepresentation): string; override; - procedure SetStringRepresentation(Representation: TBoldRepresentation; Value: string); override; + procedure SetStringRepresentation(Representation: TBoldRepresentation; const Value: string); override; function MaySetValue(NewValue: WideString; Subscriber: TBoldSubscriber): Boolean; - function ProxyClass: TBoldMember_ProxyClass; override; + //function ProxyClass: TBoldMember_ProxyClass; override; public procedure Assign(Source: TBoldElement); override; - procedure AssignValue(Source: IBoldValue); override; + procedure AssignValue(const Source: IBoldValue); override; function CompareToAs(CompType: TBoldCompareType; BoldElement: TBoldElement): Integer; override; - function ValidateWideString(Value: WideString; Representation: TBoldRepresentation): Boolean; - function ValidateString(Value: String; Representation: TBoldRepresentation): Boolean; override; + function ValidateWideString(Value: WideString; Representation: TBoldRepresentation): Boolean; + function ValidateString(const Value: String; Representation: TBoldRepresentation): Boolean; override; function CanSetValue(NewValue: WideString; Subscriber: TBoldSubscriber): Boolean; function ProxyInterface(const IId: TGUID; Mode: TBoldDomainElementProxyMode; out Obj): Boolean; override; procedure SetEmptyValue; override; @@ -63,7 +63,7 @@ TBAWideString = class(TBoldAttribute) { The following class implements a proxy for a WideString attribute to support IBoldWideStringContent, a part of the ValueSpace-interface mechanism used for objectspace transactions, persistence and other things } - + { TBAWideString_Proxy } TBAWideString_Proxy = class(TBoldAttribute_Proxy, IBoldWideStringContent) private @@ -79,7 +79,8 @@ implementation Windows, SysUtils, { Bold } - BoldMemberTypeDictionary; + BoldMemberTypeDictionary, + BoldRev; {******************************************************************************} {* TBAWideString *} @@ -87,12 +88,14 @@ implementation {* Proxy routines *************************************************************} +(* { The following method returns a class reference to a WideString proxy class } { thus allowing Bold to instantiate it } function TBAWideString.ProxyClass: TBoldMember_ProxyClass; begin result := TBAWideString_Proxy; end; +*) function TBAWideString.ProxyInterface(const IId: TGUID; Mode: TBoldDomainElementProxyMode; out Obj): Boolean; @@ -130,7 +133,7 @@ procedure TBAWideString.FreeContent; {* Public get/set methods *****************************************************} -procedure TBAWideString.SetStringRepresentation(Representation: TBoldRepresentation; Value: string); +procedure TBAWideString.SetStringRepresentation(Representation: TBoldRepresentation; const Value: string); begin SetWideStringRepresentation(Representation, Value); end; @@ -142,15 +145,15 @@ function TBAWideString.GetStringRepresentation(Representation: TBoldRepresentati {* Validation routines ********************************************************} -function TBAWideString.ValidateString(Value: string; Representation: TBoldRepresentation): Boolean; +function TBAWideString.ValidateString(const Value: string; Representation: TBoldRepresentation): Boolean; begin Result := ValidateWideString(Value, Representation); end; function TBAWideString.CanSetValue(NewValue: Widestring; Subscriber: TBoldSubscriber): Boolean; begin - Result := MaySetValue(NewValue, Subscriber) and - SendQuery(bqMaySetValue, [NewValue], Subscriber); + Result := MaySetValue(NewValue, Subscriber) {$IFNDEF BOLD_NO_QUERIES}and + SendQuery(bqMaySetValue, [NewValue], Subscriber){$ENDIF}; end; {* Assignment routines ********************************************************} @@ -168,7 +171,7 @@ procedure TBAWideString.Assign(Source: TBoldElement); inherited; end; -procedure TBAWideString.AssignContentValue(Source: IBoldValue); +procedure TBAWideString.AssignContentValue(const Source: IBoldValue); var s: IBoldWideStringContent; begin @@ -191,7 +194,7 @@ procedure TBAWideString.AssignContentValue(Source: IBoldValue); end; end; -procedure TBAWideString.AssignValue(Source: IBoldValue); +procedure TBAWideString.AssignValue(const Source: IBoldValue); var sw: IBoldWideStringContent; begin @@ -219,16 +222,10 @@ function TBAWideString.CompareToAs(CompType: TBoldCompareType; BoldElement: TBol Result := NullSmallest(BoldElement) else case CompType of - ctDefault: - Result := WideCompareText(AsWideString, CompareString.AsWideString); - ctAsString: - Result := WideCompareStr(AsWideString, CompareString.AsWideString); - ctAsText: + ctDefault, ctCaseInsensitive: Result := WideCompareText(AsWideString, CompareString.AsWideString); - ctAsAnsiString: + ctAsString, ctCaseSensitive: Result := WideCompareStr(AsWideString, CompareString.AsWideString); - ctAsAnsiText: - Result := WideCompareText(AsWideString, CompareString.AsWideString); else Result := inherited CompareToAs(CompType, BoldElement); end @@ -243,7 +240,8 @@ function TBAWideString.CompareToAs(CompType: TBoldCompareType; BoldElement: TBol function TBAWideString_Proxy.GetProxedWideString: TBAWideString; begin - Result := ProxedElement as TBAWideString; + Result := ProxedMember as TBAWideString; + //Result := ProxedElement as TBAWideString; end; function TBAWideString.MaySetValue(NewValue: WideString; Subscriber: TBoldSubscriber): Boolean; @@ -257,7 +255,7 @@ function TBAWideString.GetWideStringRepresentation(Representation: TBoldRepresen if not CanRead(nil) then BoldRaiseLastFailure(self, 'GetWideStringRepresentation', ''); case Representation of - brDefault: + brDefault: begin if IsNull then {IsNull ensures current} Result := '' @@ -319,7 +317,7 @@ procedure TBAWideString.SetContent(Newvalue: WideString); initialization BoldmemberTypes.AddMemberTypeDescriptor(TBAWideString, alConcrete); - + finalization if BoldMemberTypesAssigned then BoldMemberTypes.RemoveDescriptorByClass(TBAWideString); diff --git a/Source/Samples/Unicode/BoldPMWideString.pas b/Source/Samples/Unicode/BoldPMWideString.pas index 7103d33..abdc18a 100644 --- a/Source/Samples/Unicode/BoldPMWideString.pas +++ b/Source/Samples/Unicode/BoldPMWideString.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldPMWideString; interface @@ -26,11 +29,11 @@ TBoldPMWideString = class(TBoldSingleColumnMember) function GetColumnTypeAsSQL(ColumnIndex: Integer): string; override; function GetColumnBDEFieldType(ColumnIndex: Integer): TFieldType; override; function GetColumnSize(ColumnIndex: Integer): Integer; override; - function CompareField(ObjectContent: IBoldObjectContents; Field: IBoldField; ColumnIndex: integer; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList): Boolean; override; + function CompareField(const ObjectContent: IBoldObjectContents; const Field: IBoldField; ColumnIndex: integer; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList): Boolean; override; public constructor CreateFromMold(Moldmember: TMoldMember; MoldClass: TMoldClass; Owner: TBoldObjectPersistenceMapper; const MemberIndex: Integer; TypeNameDictionary: TBoldTypeNameDictionary); override; - procedure ValueToParam(ObjectContent: IBoldObjectContents; Param: IBoldParameter; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList); override; - procedure ValueFromField(OwningObjectId: TBoldObjectId; ObjectContent: IBoldObjectContents; ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; Field: IBoldField; ColumnIndex: Integer); override; + procedure ValueToParam(const ObjectContent: IBoldObjectContents; const Param: IBoldParameter; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList); override; + procedure ValueFromField(OwningObjectId: TBoldObjectId; const ObjectContent: IBoldObjectContents; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; const Field: IBoldField; ColumnIndex: Integer); override; class function CanStore(const ContentName: string): Boolean; override; end; @@ -66,8 +69,8 @@ class function TBoldPMWideString.CanStore(const ContentName: string): Boolean; end; function TBoldPMWideString.CompareField( - ObjectContent: IBoldObjectContents; Field: IBoldField; - ColumnIndex: integer; ValueSpace: IBoldValueSpace; + const ObjectContent: IBoldObjectContents; const Field: IBoldField; + ColumnIndex: integer; const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList): Boolean; var aWideString: IBoldWideStringContent; @@ -97,9 +100,9 @@ function TBoldPMWideString.GetColumnTypeAsSQL(ColumnIndex: Integer): string; end; procedure TBoldPMWideString.ValueFromField( - OwningObjectId: TBoldObjectId; ObjectContent: IBoldObjectContents; - ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; - Field: IBoldField; ColumnIndex: Integer); + OwningObjectId: TBoldObjectId; const ObjectContent: IBoldObjectContents; + const ValueSpace: IBoldValueSpace; TranslationList: TBoldIdTranslationList; + const Field: IBoldField; ColumnIndex: Integer); var aWideString: IBoldWideStringContent; begin @@ -117,7 +120,7 @@ procedure TBoldPMWideString.ValueFromField( end; procedure TBoldPMWideString.ValueToParam( - ObjectContent: IBoldObjectContents; Param: IBoldParameter; + const ObjectContent: IBoldObjectContents; const Param: IBoldParameter; ColumnIndex: Integer; TranslationList: TBoldIdTranslationList); var aWideString: IBoldWideStringContent; diff --git a/Source/Samples/Unicode/BoldWideStringControlPack.pas b/Source/Samples/Unicode/BoldWideStringControlPack.pas index 4af19a9..2f22e71 100644 --- a/Source/Samples/Unicode/BoldWideStringControlPack.pas +++ b/Source/Samples/Unicode/BoldWideStringControlPack.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldWideStringControlPack; {$UNDEF BOLDCOMCLIENT} @@ -59,6 +62,7 @@ TBoldAsWideStringRenderer = class(TBoldSingleRenderer) function GetAsWideStringAndSubscribe(Element: TBoldElement; FollowerController: TBoldWideStringFollowerController; Subscriber: TBoldSubscriber): WideString; virtual; procedure SetAsWideString(Element: TBoldElement; Value: WideString; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList); virtual; procedure DrawOnCanvas(Follower: TBoldFollower; Canvas: TCanvas; Rect: TRect; Alignment: TAlignment; Margins: TPoint); override; + function HasSetValueEventOverrides: boolean; override; public class function DefaultRenderer: TBoldAsWideStringRenderer; class procedure DrawWideStringOnCanvas(Canvas: TCanvas; Rect: TRect; Alignment: TAlignment; Margins: TPoint; S: WideString); @@ -72,7 +76,7 @@ TBoldAsWideStringRenderer = class(TBoldSingleRenderer) function IsChanged(RendererData: TBoldWideStringRendererData; NewValue: WideString; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList): Boolean; procedure SetFont(Element: TBoldElement; EffectiveFont, Font: TFont; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList); procedure SetColor(Element: TBoldElement; var EffectiveColor: TColor; Color: TColor; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList); - procedure MakeUptodateAndSubscribe(Element: TBoldElement; RendererData: TBoldRendererData; FollowerController: TBoldFollowerController; Subscriber: TBoldSubscriber); override; + procedure MakeUpToDateAndSubscribe(Element: TBoldElement; RendererData: TBoldRendererData; FollowerController: TBoldFollowerController; Subscriber: TBoldSubscriber); override; procedure MultiMakeUpToDateAndSubscribe(Elements: TBoldClientableList; Subscribers: TBoldObjectArray; RendererData: TBoldObjectArray; FollowerController: TBoldFollowerController); procedure DefaultMakeUptodateAndSetMayModifyAndSubscribe(Element: TBoldElement; RendererData: TBoldRendererData; FollowerController: TBoldWideStringFollowerController; Subscriber: TBoldSubscriber); virtual; published @@ -97,7 +101,7 @@ TBoldWideStringFollowerController = class(TBoldSingleFollowerController) function GetSupportsMultiEnsure: Boolean; override; function GetEffectiveRenderer: TBoldRenderer; override; property EffectiveAsWideStringRenderer: TBoldAsWideStringRenderer read GetEffectiveAsWideStringRenderer; - procedure DoMultiMakeUptodateAndSubscribe(Followers: TBoldObjectArray); override; + procedure DoMultiMakeUptodateAndSubscribe(Followers: TBoldFollowerArray); override; public procedure MakeClean(Follower: TBoldFollower); override; function GetCurrentAsWideString(Follower: TBoldFollower): WideString; @@ -121,7 +125,8 @@ implementation {$IFNDEF BOLDCOMCLIENT} BoldSystem, {$ENDIF} - Variants; + Variants, + BoldRev; var DefaultAsWideStringRenderer: TBoldAsWideStringRenderer; @@ -194,7 +199,7 @@ procedure TBoldWideStringFollowerController.MakeClean(Follower: TBoldFollower); begin if ValidateWideString(GetCurrentAsWideString(Follower), Follower) then begin - ReleaseChangedValue(Follower); // note, must do first, since set can change element + ReleaseChangedValue(Follower); SetAsWideString(GetCurrentAsWideString(Follower), Follower); end else @@ -213,7 +218,6 @@ procedure TBoldWideStringFollowerController.DoMakeUptodateAndSubscribe(Follower: Renderer := EffectiveRenderer as TBoldAsWideStringRenderer; if Assigned(Renderer.OnGetAsWideString) or Assigned(Renderer.OnSubscribe) or Assigned(Renderer.OnMayModify) then begin Renderer.MakeUptodateAndSubscribe(Follower.Element, Follower.RendererData, Self, Subscriber); - Follower.RendererData.MayModify := Renderer.MayModify(Follower.Element, Representation, Expression, GetVariableListAndSubscribe(follower.Subscriber), Follower.Subscriber); end else renderer.DefaultMakeUptodateAndSetMayModifyAndSubscribe(Follower.Element, Follower.RendererData, Self, Subscriber); end; @@ -232,7 +236,6 @@ procedure TBoldWideStringFollowerController.SetNilWideStringRepresentation(const var Left: Integer; begin - // Adjust for alignment case Alignment of taLeftJustify: Left := Margins.X + Rect.Left; taRightJustify: Left := (Rect.Right - Rect.Left) - Canvas.TextWidth(S) + Rect.Left - 1 - Margins.X; @@ -258,7 +261,7 @@ procedure TBoldAsWideStringRenderer.MakeUpToDateAndSubscribe(Element: TBoldEleme procedure TBoldAsWideStringRenderer.DefaultMakeUptodateAndSetMayModifyAndSubscribe(Element: TBoldElement; RendererData: TBoldRendererData; FollowerController: TBoldWideStringFollowerController; Subscriber: TBoldSubscriber); var - {$IFDEF BOLDCOMCLIENT} // defaultMakeUpToDate + {$IFDEF BOLDCOMCLIENT} e: IBoldElement; {$ELSE} E: TBoldIndirectElement; @@ -272,20 +275,18 @@ procedure TBoldAsWideStringRenderer.DefaultMakeUptodateAndSetMayModifyAndSubscri S := '('+Name+')' else S := '('+ClassName+')'; - RendererData.MayModify := False; end else begin if Assigned(Element) then begin - {$IFDEF BOLDCOMCLIENT} // defaultMakeUpToDate + {$IFDEF BOLDCOMCLIENT} e := Element.EvaluateAndSubscribeToExpression(FollowerController.Expression, Subscriber.ClientId, Subscriber.SubscriberId, False, false); if Assigned(E) then begin S := E.WideStringRepresentation[FollowerController.Representation]; if Assigned(Subscriber) then E.SubscribeToWideStringRepresentation(FollowerController.Representation, Subscriber.ClientId, Subscriber.SubscriberId, breReEvaluate, false); - RendererData.MayModify := true; end else S := FollowerController.NilWideStringRepresentation @@ -298,7 +299,6 @@ procedure TBoldAsWideStringRenderer.DefaultMakeUptodateAndSetMayModifyAndSubscri s := FollowerController.NilWideStringRepresentation; if Assigned(Subscriber) then E.Value.SubscribeToStringRepresentation(FollowerController.Representation, Subscriber, breReEvaluate); - RendererData.MayModify := E.Value.ObserverMayModifyAsString(FollowerController.Representation, Subscriber); (RendererData as TBoldWideStringRendererData).MaxWideStringLength := -1; end else if Assigned(E.Value) then @@ -309,7 +309,6 @@ procedure TBoldAsWideStringRenderer.DefaultMakeUptodateAndSetMayModifyAndSubscri S := E.Value.StringRepresentation[FollowerController.Representation]; if Assigned(Subscriber) then E.Value.SubscribeToStringRepresentation(FollowerController.Representation, Subscriber, breReEvaluate); - RendererData.MayModify := E.Value.ObserverMayModifyAsString(FollowerController.Representation, Subscriber); if (E.Value is TBoldAttribute) and assigned((E.Value as TBoldAttribute).BoldAttributeRTInfo) then (RendererData as TBoldWideStringRendererData).MaxWideStringLength := (E.Value as TBoldAttribute).BoldAttributeRTInfo.Length else @@ -336,7 +335,7 @@ function TBoldAsWideStringRenderer.GetRendererDataClass: TBoldRendererDataClass; function TBoldAsWideStringRenderer.DefaultGetAsWideStringAndSubscribe(Element: TBoldElement; FollowerController: TBoldWideStringFollowerController; Subscriber: TBoldSubscriber): WideString; var - {$IFDEF BOLDCOMCLIENT} // DefaultGet + {$IFDEF BOLDCOMCLIENT} e: IBoldElement; {$ELSE} E: TBoldIndirectElement; @@ -354,7 +353,7 @@ function TBoldAsWideStringRenderer.DefaultGetAsWideStringAndSubscribe(Element: T begin if Assigned(Element) then begin - {$IFDEF BOLDCOMCLIENT} // defaultGet + {$IFDEF BOLDCOMCLIENT} e := Element.EvaluateAndSubscribeToExpression(FollowerController.Expression, Subscriber.ClientId, Subscriber.SubscriberId, False, false); if Assigned(E) then begin @@ -414,7 +413,7 @@ function TBoldAsWideStringRenderer.DefaultValidateCharacter(Element: TBoldElemen if Assigned(ValueElement) then Result := ValueElement.ValidateCharacter(C, Representation) else - Result := False; + Result := HasSetValueEventOverrides; end; function TBoldAsWideStringRenderer.DefaultValidateWideString(Element: TBoldElement; Value: WideString; Representation: TBoldRepresentation; Expression: TBoldExpression; VariableList: TBoldExternalVariableList): Boolean; @@ -430,7 +429,7 @@ function TBoldAsWideStringRenderer.DefaultValidateWideString(Element: TBoldEleme Result := ValueElement.ValidateString(Value, Representation) end else - Result := False; + Result := HasSetValueEventOverrides; end; function TBoldAsWideStringRenderer.GetAsWideStringAndSubscribe(Element: TBoldElement; FollowerController: TBoldWideStringFollowerController; Subscriber: TBoldSubscriber): WideString; @@ -520,6 +519,11 @@ function TBoldAsWideStringRenderer.GetSupportsMulti: Boolean; {$ENDIF} end; +function TBoldAsWideStringRenderer.HasSetValueEventOverrides: boolean; +begin + result := Assigned(FOnSetAsWideString); +end; + function TBoldWideStringFollowerController.GetSupportsMultiEnsure: Boolean; begin {$IFDEF BOLDCOMCLIENT} @@ -531,30 +535,28 @@ function TBoldWideStringFollowerController.GetSupportsMultiEnsure: Boolean; end; procedure TBoldWideStringFollowerController.DoMultiMakeUptodateAndSubscribe( - Followers: TBoldObjectArray); + Followers: TBoldFollowerArray); var Renderer: TBoldAsWideStringRenderer; Elements: TBoldClientableList; Subscribers: TBoldObjectArray; RendererData: TBoldObjectArray; - I: integer; - MaxIndex: integer; + F: TBoldFollower; begin Assert(SupportsMulti); - MaxIndex := Followers.Count - 1; Renderer := EffectiveRenderer as TBoldAsWideStringRenderer; - Elements := TBoldClientableList.Create(MaxIndex,[]); - Subscribers := TBoldObjectArray.Create(MaxIndex,[]); - RendererData := TBoldObjectArray.Create(MaxIndex,[]); + Elements := TBoldClientableList.Create(Length(Followers),[]); + Subscribers := TBoldObjectArray.Create(Length(Followers),[]); + RendererData := TBoldObjectArray.Create(Length(Followers),[]); try - for I := 0 to MaxIndex do + for F in Followers do begin - Elements.Add(TBoldFollower(Followers[I]).Element); - if TBoldFollower(Followers[I]).State in bfdNeedResubscribe then - Subscribers.Add(Followers[i]) + Elements.Add(F.Element); + if F.State in bfdNeedResubscribe then + Subscribers.Add(F) else Subscribers.Add(nil); - RendererData.Add(TBoldFollower(Followers[I]).RendererData); + RendererData.Add(F.RendererData); end; Renderer.MultiMakeUpToDateAndSubscribe(Elements, Subscribers, RendererData, Self); finally @@ -620,4 +622,3 @@ finalization FreeAndNil(DefaultAsWideStringRenderer); end. - diff --git a/Source/Samples/Unicode/BoldWideStringInterface.pas b/Source/Samples/Unicode/BoldWideStringInterface.pas index b755bc6..4ca0a35 100644 --- a/Source/Samples/Unicode/BoldWideStringInterface.pas +++ b/Source/Samples/Unicode/BoldWideStringInterface.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldWideStringInterface; interface @@ -34,7 +37,7 @@ TBFSWideString = class(TBoldFreeStandingNullableValue, IBoldWideStringContent) procedure SetContentAsWideString(NewValue: WideString); protected function GetStreamName: string; override; - procedure AssignContentValue(Source: IBoldValue); override; + procedure AssignContentValue(const Source: IBoldValue); override; public property asString: String read GetContentAsString write SetContentAsString; property asWideString: WideString read GetContentAsWideString write SetContentAsWideString; @@ -47,7 +50,10 @@ implementation uses { RTL / VCL } - SysUtils; + SysUtils, + + { Bold } + BoldRev; {******************************************************************************} {* TBFSUnicodeString *} @@ -61,7 +67,7 @@ function TBFSWideString.GetStreamName: String; {* Content management *********************************************************} -procedure TBFSWideString.AssignContentValue(Source: IBoldValue); +procedure TBFSWideString.AssignContentValue(const Source: IBoldValue); var U: IBoldWideStringContent; S: IBoldStringContent; @@ -103,5 +109,5 @@ procedure TBFSWideString.SetContentAsWideString(NewValue: WideString); initialization with FreeStandingValueFactory do RegisterFreeStandingClass(BoldContentName_WideString, TBFSWideString); - + end. diff --git a/Source/UMLModel/Core/BoldUMLAbstractModelValidator.pas b/Source/UMLModel/Core/BoldUMLAbstractModelValidator.pas index 1e7f7e4..9280ddf 100644 --- a/Source/UMLModel/Core/BoldUMLAbstractModelValidator.pas +++ b/Source/UMLModel/Core/BoldUMLAbstractModelValidator.pas @@ -1,8 +1,12 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldUMLAbstractModelValidator; interface uses + BoldModel, BoldUMLAttributes, BoldUMLModel, BoldSQLDatabaseConfig; @@ -14,9 +18,10 @@ TBoldUMLAbstractModelValidator = class private fSQLDataBaseConfig: TBoldSQLDataBaseConfig; fLanguage: TBoldModelValidatorSourceLanguage; - fUMLModel: TUMLModel; + fBoldModel: TBoldModel; function GetValidator: TValidator; - procedure AddViolation(severity: TSeverity; description: String; element: TUMLModelElement); + procedure AddViolation(severity: TSeverity; const description: String; element: TUMLModelElement); + function GetUMLModel: TUMLModel; protected procedure AddError(description: String; args: array of const; element: TUMLModelElement); procedure AddHint(description: String; args: array of const; element: TUMLModelElement); @@ -25,8 +30,9 @@ TBoldUMLAbstractModelValidator = class property SQLDataBaseConfig: TBoldSQLDataBaseConfig read fSQLDataBaseConfig; property Language: TBoldModelValidatorSourceLanguage read fLanguage; public - constructor Create(UMLModel: TUMLModel; SQLDataBaseConfig: TBoldSQLDataBaseConfig = nil; const Language: TBoldModelValidatorSourceLanguage = mvslNone); - property UMLModel: TUMLModel read fUMLModel; + constructor Create(ABoldModel: TBoldModel; SQLDataBaseConfig: TBoldSQLDataBaseConfig = nil; const Language: TBoldModelValidatorSourceLanguage = mvslNone); + property UMLModel: TUMLModel read GetUMLModel; + property BoldModel: TBoldModel read fBoldModel; property Validator: TValidator read GetValidator; function HighestSeverity: TSeverity; end; @@ -39,11 +45,12 @@ TBoldUMLAbstractModelValidator = class BoldDefaultValidatorSourceLanguage = mvslCpp; {$ENDIF} - implementation uses - SysUtils; + SysUtils, + BoldDefs, + BoldRev; procedure TBoldUMLAbstractModelValidator.AddError(description: String; args: array of const; element: TUMLModelElement); begin @@ -60,7 +67,7 @@ procedure TBoldUMLAbstractModelValidator.AddHint(description: String; args: arra AddViolation(sHint, format(description, args), element); end; -procedure TBoldUMLAbstractModelValidator.AddViolation(severity: TSeverity; description: String; element: TUMLModelElement); +procedure TBoldUMLAbstractModelValidator.AddViolation(severity: TSeverity; const description: String; element: TUMLModelElement); var v : TViolation; begin @@ -78,14 +85,22 @@ procedure TBoldUMLAbstractModelValidator.ClearViolations; Validator.Violation[i].Delete end; -constructor TBoldUMLAbstractModelValidator.Create(UMLModel: TUMLModel; SQLDataBaseConfig: TBoldSQLDataBaseConfig; const Language: TBoldModelValidatorSourceLanguage); +constructor TBoldUMLAbstractModelValidator.Create(ABoldModel: TBoldModel; SQLDataBaseConfig: TBoldSQLDataBaseConfig; const Language: TBoldModelValidatorSourceLanguage); begin inherited Create; fSQLDataBaseConfig := SQLDataBaseConfig; - fUMLModel := UMLModel; + fBoldModel := ABoldModel; fLanguage := Language; end; +function TBoldUMLAbstractModelValidator.GetUMLModel: TUMLModel; +begin + if Assigned(BoldModel) then + result := BoldModel.EnsuredUMLModel + else + result := nil; +end; + function TBoldUMLAbstractModelValidator.GetValidator: TValidator; begin result := UMLModel.Validator; @@ -101,4 +116,6 @@ function TBoldUMLAbstractModelValidator.HighestSeverity: TSeverity; result := Validator.violation[i].Severity; end; +initialization + end. diff --git a/Source/UMLModel/Core/BoldUMLAttributes.pas b/Source/UMLModel/Core/BoldUMLAttributes.pas index 5d23036..f23eb1e 100644 --- a/Source/UMLModel/Core/BoldUMLAttributes.pas +++ b/Source/UMLModel/Core/BoldUMLAttributes.pas @@ -1,9 +1,12 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldUMLAttributes; interface uses - Classes, + Classes, BoldAttributes, BoldDefs, BoldUMLTypes; @@ -17,17 +20,19 @@ TBAChangeableKind = class(TBAValueSet) function GetAsChangeableKind: TChangeableKind; procedure SetAsChangeableKind(ChangeableKind: TChangeableKind); protected - function GetValues: TBAValueSetValueList; override; + class function GetValues: TBAValueSetValueList; override; public property AsChangeableKind: TChangeableKind read GetAsChangeableKind write SetAsChangeableKind; end; + + TBAVisibilityKind = class(TBAValueSet) private function GetAsVisibilityKind: TVisibilityKind; procedure SetAsVisibilityKind(VisibilityKind: TVisibilityKind); protected - function GetValues: TBAValueSetValueList; override; + class function GetValues: TBAValueSetValueList; override; public property AsVisibilityKind: TVisibilityKind read GetAsVisibilityKind write SetAsVisibilityKind; end; @@ -37,7 +42,7 @@ TBAAggregationKind = class(TBAValueSet) function GetAsAggregationKind: TAggregationKind; procedure SetAsAggregationKind(AggregationKind: TAggregationKind); protected - function GetValues: TBAValueSetValueList; override; + class function GetValues: TBAValueSetValueList; override; public property AsAggregationKind: TAggregationKind read GetAsAggregationKind write SetAsAggregationKind; end; @@ -47,7 +52,7 @@ TBAScopeKind = class(TBAValueSet) function getAsScopeKind: TScopeKind; procedure setAsScopeKind(ScopeKind: TScopeKind); protected - function GetValues: TBAValueSetValueList; override; + class function GetValues: TBAValueSetValueList; override; public property AsScopeKind: TScopeKind read getAsScopeKind write setAsScopeKind; end; @@ -57,7 +62,7 @@ TBAParameterDirectionKind = class(TBAValueSet) function getAsParameterDirectionKind: TBoldParameterDirectionKind; procedure setAsParameterDirectionKind(ParameterDirectionKind: TBoldParameterDirectionKind); protected - function GetValues: TBAValueSetValueList; override; + class function GetValues: TBAValueSetValueList; override; public property AsParameterDirectionKInd: TBoldParameterDirectionKind read getAsParameterDirectionKind write setAsParameterDirectionKind; end; @@ -67,7 +72,7 @@ TBASeverity = class(TBAValueSet) function getAsSeverity: TSeverity; procedure setAsSeverity(Severity: TSeverity); protected - function GetValues: TBAValueSetValueList; override; + class function GetValues: TBAValueSetValueList; override; public property AsSeverity: TSeverity read getAsSeverity write setAsSeverity; end; @@ -77,7 +82,7 @@ TBAOrderingKind = class(TBAValueSet) function getAsOrderingKind: TOrderingKind; procedure setAsOrderingKind(OrderingKind: TOrderingKind); protected - function GetValues: TBAValueSetValueList; override; + class function GetValues: TBAValueSetValueList; override; public property AsOrderingKind: TOrderingKind read getAsOrderingKind write setAsOrderingKind; end; @@ -87,7 +92,7 @@ TBAPseudostateKind = class(TBAValueSet) function getAsPseudostateKind: TPseudostateKind; procedure setAsPseudostateKind(PseudostateKind: TPseudostateKind); protected - function GetValues: TBAValueSetValueList; override; + class function GetValues: TBAValueSetValueList; override; public property AsPseudostateKind: TPseudostateKind read getAsPseudostateKind write setAsPseudostateKind; end; @@ -97,7 +102,7 @@ TBACallConcurrencyKind = class(TBAValueSet) function getAsCallConcurrencyKind: TCallConcurrencyKind; procedure setAsCallConcurrencyKind(CallConcurrencyKind: TCallConcurrencyKind); protected - function GetValues: TBAValueSetValueList; override; + class function GetValues: TBAValueSetValueList; override; public property AsCallConcurrencyKind: TCallConcurrencyKind read getAsCallConcurrencyKind write setAsCallConcurrencyKind; end; @@ -107,7 +112,7 @@ TBAMessageDirectionKind = class(TBAValueSet) function getAsMessageDirectionKind: TMessageDirectionKind; procedure setAsMessageDirectionKind(MessageDirectionKind: TMessageDirectionKind); protected - function GetValues: TBAValueSetValueList; override; + class function GetValues: TBAValueSetValueList; override; public property AsMessageDirectionKind: TMessageDirectionKind read getAsMessageDirectionKind write setAsMessageDirectionKind; end; @@ -116,7 +121,6 @@ implementation uses SysUtils, - UMLConsts, BoldMemberTypeDictionary; var @@ -132,13 +136,13 @@ implementation _MessageDirectionKindValues: TBAValueSetValueList; -function TBAScopeKind.GetValues: TBAValueSetValueList; +class function TBAScopeKind.GetValues: TBAValueSetValueList; begin if not Assigned(_ScopeKindValues) then begin _ScopeKindValues := TBAValueSetValueList.Create; - _ScopeKindValues.Add(1, ['instance']); // do not localize - _ScopeKindValues.Add(2, ['classifier']); // do not localize + _ScopeKindValues.Add(1, ['instance']); + _ScopeKindValues.Add(2, ['classifier']); end; Result := _ScopeKindValues; end; @@ -148,7 +152,7 @@ function TBAScopeKind.getAsScopeKind: TScopeKind; case AsInteger of 1: result := skInstance; 2: result := skClassifier; - else raise EBold.CreateFmt(sWrongValue, [ClassName, 'GetAsScopeKind']); // do not localize + else raise EBold.Create('TBAScopeKind.GetAsScopeKind: Wrong value.'); end; end; @@ -160,15 +164,15 @@ procedure TBAScopeKind.setAsScopeKind(ScopeKind: TScopeKind); end; end; -function TBAParameterDirectionKind.GetValues: TBAValueSetValueList; +class function TBAParameterDirectionKind.GetValues: TBAValueSetValueList; begin if not Assigned(_ParameterDirectionKindValues) then begin _ParameterDirectionKindValues := TBAValueSetValueList.Create; - _ParameterDirectionKindValues.Add(1, ['in']); // do not localize - _ParameterDirectionKindValues.Add(2, ['out']); // do not localize - _ParameterDirectionKindValues.Add(3, ['inout']); // do not localize - _ParameterDirectionKindValues.Add(4, ['return']); // do not localize + _ParameterDirectionKindValues.Add(1, ['in']); + _ParameterDirectionKindValues.Add(2, ['out']); + _ParameterDirectionKindValues.Add(3, ['inout']); + _ParameterDirectionKindValues.Add(4, ['return']); end; Result := _ParameterDirectionKindValues; end; @@ -180,7 +184,7 @@ function TBAParameterDirectionKind.getAsParameterDirectionKind: TBoldParameterDi 2: result := pdOut; 3: Result := pdInout; 4: Result := pdReturn; - else raise EBold.CreateFmt(sWrongValue, [ClassName, 'getAsParameterDirectionKind']); // do not localize + else raise EBold.Create('TBAParameterDirectionKind.GetAsParameterDirectionKind: Wrong value.'); end; end; @@ -194,15 +198,16 @@ procedure TBAParameterDirectionKind.setAsParameterDirectionKind(ParameterDirecti end; end; -function TBASeverity.GetValues: TBAValueSetValueList; + +class function TBASeverity.GetValues: TBAValueSetValueList; begin if not Assigned(_SeverityValues) then begin _SeverityValues := TBAValueSetValueList.Create; - _SeverityValues.Add(0, ['None']); // do not localize - _SeverityValues.Add(1, ['Hint']); // do not localize - _SeverityValues.Add(2, ['Warning']); // do not localize - _SeverityValues.Add(3, ['Error']); // do not localize + _SeverityValues.Add(0, ['None']); + _SeverityValues.Add(1, ['Hint']); + _SeverityValues.Add(2, ['Warning']); + _SeverityValues.Add(3, ['Error']); end; Result := _SeverityValues; end; @@ -214,7 +219,7 @@ function TBASeverity.getAsSeverity: TSeverity; 1: Result := sHint; 2: result := sWarning; 3: result := sError; - else raise EBold.CreateFmt(sWrongValue, [ClassName, 'getAsSeverity']); // do not localize + else raise EBold.Create('TBASeverity.GetAsSeverity: Wrong value.'); end; end; @@ -236,18 +241,18 @@ function TBAAggregationKind.GetAsAggregationKind: TAggregationKind; 1: Result := akNone; 2: Result := akAggregate; 3: Result := akComposite; - else raise EBold.CreateFmt(sWrongValue, [ClassName, 'GetAsAggregationKind']); // do not localize + else raise EBold.Create('TBAAggregationKind.GetAsAggregationKind: Wrong value.'); end; end; -function TBAAggregationKind.GetValues: TBAValueSetValueList; +class function TBAAggregationKind.GetValues: TBAValueSetValueList; begin if not Assigned(_AggregationKindValues) then begin _AggregationKindValues := TBAValueSetValueList.Create; - _AggregationKindValues.Add(1, ['none']); // do not localize - _AggregationKindValues.Add(2, ['aggregate']); // do not localize - _AggregationKindValues.Add(3, ['composite']); // do not localize + _AggregationKindValues.Add(1, ['none']); + _AggregationKindValues.Add(2, ['aggregate']); + _AggregationKindValues.Add(3, ['composite']); end; Result := _AggregationKindValues; end; @@ -270,18 +275,18 @@ function TBAVisibilityKind.GetAsVisibilityKind: TVisibilityKind; 1: Result := vkPrivate; 2: Result := vkProtected; 3: Result := vkPublic; - else raise EBold.CreateFmt(sWrongValue, [ClassName, 'GetAsVisibilityKind']); // do not localize + else raise EBold.Create('TBAVisibilityKind.GetAsVisibilityKind: Wrong value.'); end; end; -function TBAVisibilityKind.GetValues: TBAValueSetValueList; +class function TBAVisibilityKind.GetValues: TBAValueSetValueList; begin if not Assigned(_VisibilityKindValues) then begin _VisibilityKindValues := TBAValueSetValueList.Create; - _VisibilityKindValues.Add(1, ['private']); // do not localize - _VisibilityKindValues.Add(2, ['protected']); // do not localize - _VisibilityKindValues.Add(3, ['public']); // do not localize + _VisibilityKindValues.Add(1, ['private']); + _VisibilityKindValues.Add(2, ['protected']); + _VisibilityKindValues.Add(3, ['public']); end; Result := _VisibilityKindValues; end; @@ -303,18 +308,18 @@ function TBAChangeableKind.GetAsChangeableKind: TChangeableKind; 1: Result := ckChangeable; 2: Result := ckFrozen; 3: Result := ckAddOnly; - else raise EBold.CreateFmt(sWrongValue, [ClassName, 'GetAsChangeableKind']); // do not localize + else raise EBold.Create('TBAChangeableKind.GetAsChangeableKind: Wrong value.'); end; end; -function TBAChangeableKind.GetValues: TBAValueSetValueList; +class function TBAChangeableKind.GetValues: TBAValueSetValueList; begin if not Assigned(_ChangeableKindValues) then begin _ChangeableKindValues := TBAValueSetValueList.Create; - _ChangeableKindValues.Add(1, ['changeable']); // do not localize - _ChangeableKindValues.Add(2, ['frozen']); // do not localize - _ChangeableKindValues.Add(3, ['addOnly']); // do not localize + _ChangeableKindValues.Add(1, ['changeable']); + _ChangeableKindValues.Add(2, ['frozen']); + _ChangeableKindValues.Add(3, ['addOnly']); end; Result := _ChangeableKindValues; end; @@ -335,17 +340,17 @@ function TBAOrderingKind.getAsOrderingKind: TOrderingKind; case AsInteger of 0: Result := okUnordered; 1: Result := okOrdered; - else raise EBold.CreateFmt(sWrongValue, [ClassName, 'getAsOrderingKind']); // do not localize + else raise EBold.Create('TBAOrderingKind.GetAsOrderingKind: Wrong value.'); end; end; -function TBAOrderingKind.GetValues: TBAValueSetValueList; +class function TBAOrderingKind.GetValues: TBAValueSetValueList; begin if not Assigned(_OrderingKindValues) then begin _OrderingKindValues := TBAValueSetValueList.Create; - _OrderingKindValues.Add(0, ['unordered']); // do not localize - _OrderingKindValues.Add(1, ['ordered']); // do not localize + _OrderingKindValues.Add(0, ['unordered']); + _OrderingKindValues.Add(1, ['ordered']); end; Result := _OrderingKindValues; end; @@ -371,23 +376,23 @@ function TBAPseudostateKind.getAsPseudostateKind: TPseudostateKind; 5: Result := pkBranch; 6: Result := pkJunction; 7: Result := pkFinal; - else raise EBold.CreateFmt(sWrongValue, [ClassName, 'getAsPseudostateKind']); // do not localize + else raise EBold.Create('TBAOrderingKind.GetAsOrderingKind: Wrong value.'); end; end; -function TBAPseudostateKind.GetValues: TBAValueSetValueList; +class function TBAPseudostateKind.GetValues: TBAValueSetValueList; begin if not Assigned(_PseudostateKindValues) then begin _PseudostateKindValues := TBAValueSetValueList.Create; - _PseudostateKindValues.Add(0, ['initial']); // do not localize - _PseudostateKindValues.Add(1, ['deepHistory']); // do not localize - _PseudostateKindValues.Add(2, ['shallowHistory']); // do not localize - _PseudostateKindValues.Add(3, ['join']); // do not localize - _PseudostateKindValues.Add(4, ['fork']); // do not localize - _PseudostateKindValues.Add(5, ['branch']); // do not localize - _PseudostateKindValues.Add(6, ['junction']); // do not localize - _PseudostateKindValues.Add(7, ['final']); // do not localize + _PseudostateKindValues.Add(0, ['initial']); + _PseudostateKindValues.Add(1, ['deepHistory']); + _PseudostateKindValues.Add(2, ['shallowHistory']); + _PseudostateKindValues.Add(3, ['join']); + _PseudostateKindValues.Add(4, ['fork']); + _PseudostateKindValues.Add(5, ['branch']); + _PseudostateKindValues.Add(6, ['junction']); + _PseudostateKindValues.Add(7, ['final']); end; Result := _PseudostateKindValues; end; @@ -405,6 +410,7 @@ procedure TBAPseudostateKind.setAsPseudostateKind( pkJunction: AsInteger := 6; pkFinal: AsInteger := 7; end; + end; { TBACallConcurrencyKind } @@ -415,18 +421,18 @@ function TBACallConcurrencyKind.getAsCallConcurrencyKind: TCallConcurrencyKind; 0: Result := cckSequential; 1: Result := cckGuarded; 2: Result := cckConcurrent; - else raise EBold.CreateFmt(sWrongValue, [ClassName, 'getAsCallConcurrencyKind']); // do not localize + else raise EBold.Create('TBAOrderingKind.GetAsOrderingKind: Wrong value.'); end; end; -function TBACallConcurrencyKind.GetValues: TBAValueSetValueList; +class function TBACallConcurrencyKind.GetValues: TBAValueSetValueList; begin if not Assigned(_CallConcurrencyKindValues) then begin _CallConcurrencyKindValues := TBAValueSetValueList.Create; - _CallConcurrencyKindValues.Add(0, ['sequential']); // do not localize - _CallConcurrencyKindValues.Add(1, ['guarded']); // do not localize - _CallConcurrencyKindValues.Add(2, ['concurrent']); // do not localize + _CallConcurrencyKindValues.Add(0, ['sequential']); + _CallConcurrencyKindValues.Add(1, ['guarded']); + _CallConcurrencyKindValues.Add(2, ['concurrent']); end; Result := _CallConcurrencyKindValues; end; @@ -448,17 +454,17 @@ function TBAMessageDirectionKind.getAsMessageDirectionKind: TMessageDirectionKin case AsInteger of 0: Result := mdkActivation; 1: Result := mdkReturn; - else raise EBold.CreateFmt(sWrongValue, [ClassName, 'getAsMessageDirectionKind']); // do not localize + else raise EBold.Create('TBAOrderingKind.GetAsOrderingKind: Wrong value.'); end; end; -function TBAMessageDirectionKind.GetValues: TBAValueSetValueList; +class function TBAMessageDirectionKind.GetValues: TBAValueSetValueList; begin if not Assigned(_MessageDirectionKindValues) then begin _MessageDirectionKindValues := TBAValueSetValueList.Create; - _MessageDirectionKindValues.Add(0, ['activation']); // do not localize - _MessageDirectionKindValues.Add(1, ['return']); // do not localize + _MessageDirectionKindValues.Add(0, ['activation']); + _MessageDirectionKindValues.Add(1, ['return']); end; Result := _MessageDirectionKindValues; end; diff --git a/Source/UMLModel/Core/BoldUMLModel.inc b/Source/UMLModel/Core/BoldUMLModel.inc index c1a9122..1d2bc26 100644 --- a/Source/UMLModel/Core/BoldUMLModel.inc +++ b/Source/UMLModel/Core/BoldUMLModel.inc @@ -10,10 +10,15 @@ procedure TUMLModel.Clear; begin + BoldSystem.StartTransaction(); + try while ownedElement.Count > 0 do ownedElement[ownedElement.Count-1].Delete; while M_taggedValue.Count > 0 do M_taggedValue[M_taggedValue.Count-1].Delete; + finally + BoldSystem.CommitTransaction(); + end; end; function TUMLAssociationEnd.GetOtherEnd: TUMLAssociationEnd; @@ -201,7 +206,9 @@ end; procedure TUMLClassifier.GetAllOverrideableMethods(Methods: TList); procedure GetSuperclassMethods(aClass: TUMLClassifier; SuperMethods: TList); - var Index: Integer; + var + Index: Integer; + UMLOperation: TUMLOperation; begin if Assigned(aClass.SuperClass) then GetSuperclassMethods(aClass.SuperClass, SuperMethods); @@ -209,9 +216,10 @@ procedure TUMLClassifier.GetAllOverrideableMethods(Methods: TList); begin if aClass.Feature[Index] is TUMLOperation then begin - if ((aClass.Feature[Index] as TUMLOperation).GetBoldTV(TAG_DELPHIOPERATIONKIND) = TV_DELPHIOPERATIONKIND_VIRTUAL) or - ((aClass.Feature[Index] as TUMLOperation).GetBoldTV(TAG_DELPHIOPERATIONKIND) = TV_DELPHIOPERATIONKIND_DYNAMIC) or - ((aClass.Feature[Index] as TUMLOperation).GetBoldTV(TAG_DELPHIOPERATIONKIND) = TV_DELPHIOPERATIONKIND_ABSTRACTVIRTUAL) then + UMLOperation := (aClass.Feature[Index] as TUMLOperation); + if (UMLOperation.GetBoldTV(TAG_DELPHIOPERATIONKIND) = TV_DELPHIOPERATIONKIND_VIRTUAL) or + (UMLOperation.GetBoldTV(TAG_DELPHIOPERATIONKIND) = TV_DELPHIOPERATIONKIND_DYNAMIC) or + (UMLOperation.GetBoldTV(TAG_DELPHIOPERATIONKIND) = TV_DELPHIOPERATIONKIND_ABSTRACTVIRTUAL) then Methods.Add(aClass.Feature[Index]); end; @@ -337,7 +345,7 @@ var i: Integer; begin Result := nil; - AllStereotypes := (aSystem.Classes[aSystem.BoldSystemTypeInfo.ClassTypeInfoByExpressionName['UMLStereotype'].TopSortedIndex] as TUMLStereotypeList); + AllStereotypes := aSystem.ClassByObjectClass[TUMLStereotype] as TUMLStereotypeList; for i := 0 to AllStereotypes.Count - 1 do begin if AllStereotypes[i].Name = aName then @@ -464,8 +472,6 @@ begin SetTaggedValue(TAG_DERIVED, NewValue); end; - - procedure TUMLAssociationEnd._isOrdered_DeriveAndSubscribe(DerivedObject: TObject; Subscriber: TBoldSubscriber); begin M_isOrdered.AsBoolean := Ordering = okOrdered; diff --git a/Source/UMLModel/Core/BoldUMLModel.pas b/Source/UMLModel/Core/BoldUMLModel.pas index 7272ef5..e0f7288 100644 --- a/Source/UMLModel/Core/BoldUMLModel.pas +++ b/Source/UMLModel/Core/BoldUMLModel.pas @@ -1,17 +1,6 @@ -(*****************************************) -(* This file is autogenerated *) -(* Any manual changes will be LOST! *) -(*****************************************) -(* Generated 2002-06-19 17:13:50 *) -(*****************************************) -(* This file should be stored in the *) -(* same directory as the form/datamodule *) -(* with the corresponding model *) -(*****************************************) -(* Copyright notice: *) -(* *) -(*****************************************) +{ Global compiler directives } +{$include bold.inc} unit BoldUMLModel; {$DEFINE BoldUMLModel_unitheader} @@ -74,8 +63,8 @@ function Targumentstimulus1._Get_M_stimulus1: TBoldObjectReference; function Targumentstimulus1._Getstimulus1: TUMLStimulus; begin - assert(not assigned(M_stimulus1.BoldObject) or (M_stimulus1.BoldObject is TUMLStimulus), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'stimulus1', M_stimulus1.BoldObject.ClassName, 'TUMLStimulus'])); Result := TUMLStimulus(M_stimulus1.BoldObject); + assert(not assigned(Result) or (Result is TUMLStimulus), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'stimulus1', Result.ClassName, 'TUMLStimulus'])); end; function Targumentstimulus1._Get_M_argument: TBoldObjectReference; @@ -86,8 +75,8 @@ function Targumentstimulus1._Get_M_argument: TBoldObjectReference; function Targumentstimulus1._Getargument: TUMLInstance; begin - assert(not assigned(M_argument.BoldObject) or (M_argument.BoldObject is TUMLInstance), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'argument', M_argument.BoldObject.ClassName, 'TUMLInstance'])); Result := TUMLInstance(M_argument.BoldObject); + assert(not assigned(Result) or (Result is TUMLInstance), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'argument', Result.ClassName, 'TUMLInstance'])); end; procedure Targumentstimulus1List.Add(NewObject: Targumentstimulus1); @@ -137,8 +126,8 @@ function TassociationEndRoleavailableQualifier._Get_M_availableQualifier: TBoldO function TassociationEndRoleavailableQualifier._GetavailableQualifier: TUMLAttribute; begin - assert(not assigned(M_availableQualifier.BoldObject) or (M_availableQualifier.BoldObject is TUMLAttribute), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'availableQualifier', M_availableQualifier.BoldObject.ClassName, 'TUMLAttribute'])); Result := TUMLAttribute(M_availableQualifier.BoldObject); + assert(not assigned(Result) or (Result is TUMLAttribute), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'availableQualifier', Result.ClassName, 'TUMLAttribute'])); end; function TassociationEndRoleavailableQualifier._Get_M_associationEndRole: TBoldObjectReference; @@ -149,8 +138,8 @@ function TassociationEndRoleavailableQualifier._Get_M_associationEndRole: TBoldO function TassociationEndRoleavailableQualifier._GetassociationEndRole: TUMLAssociationEndRole; begin - assert(not assigned(M_associationEndRole.BoldObject) or (M_associationEndRole.BoldObject is TUMLAssociationEndRole), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'associationEndRole', M_associationEndRole.BoldObject.ClassName, 'TUMLAssociationEndRole'])); Result := TUMLAssociationEndRole(M_associationEndRole.BoldObject); + assert(not assigned(Result) or (Result is TUMLAssociationEndRole), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'associationEndRole', Result.ClassName, 'TUMLAssociationEndRole'])); end; procedure TassociationEndRoleavailableQualifierList.Add(NewObject: TassociationEndRoleavailableQualifier); @@ -200,8 +189,8 @@ function TclassifierclassifierRole_._Get_M_classifierRole_: TBoldObjectReference function TclassifierclassifierRole_._GetclassifierRole_: TUMLClassifierRole; begin - assert(not assigned(M_classifierRole_.BoldObject) or (M_classifierRole_.BoldObject is TUMLClassifierRole), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'classifierRole_', M_classifierRole_.BoldObject.ClassName, 'TUMLClassifierRole'])); Result := TUMLClassifierRole(M_classifierRole_.BoldObject); + assert(not assigned(Result) or (Result is TUMLClassifierRole), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'classifierRole_', Result.ClassName, 'TUMLClassifierRole'])); end; function TclassifierclassifierRole_._Get_M_classifier: TBoldObjectReference; @@ -212,8 +201,8 @@ function TclassifierclassifierRole_._Get_M_classifier: TBoldObjectReference; function TclassifierclassifierRole_._Getclassifier: TUMLClassifier; begin - assert(not assigned(M_classifier.BoldObject) or (M_classifier.BoldObject is TUMLClassifier), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'classifier', M_classifier.BoldObject.ClassName, 'TUMLClassifier'])); Result := TUMLClassifier(M_classifier.BoldObject); + assert(not assigned(Result) or (Result is TUMLClassifier), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'classifier', Result.ClassName, 'TUMLClassifier'])); end; procedure TclassifierclassifierRole_List.Add(NewObject: TclassifierclassifierRole_); @@ -263,8 +252,8 @@ function TclassifierInStateinState._Get_M_inState: TBoldObjectReference; function TclassifierInStateinState._GetinState: TUMLState; begin - assert(not assigned(M_inState.BoldObject) or (M_inState.BoldObject is TUMLState), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'inState', M_inState.BoldObject.ClassName, 'TUMLState'])); Result := TUMLState(M_inState.BoldObject); + assert(not assigned(Result) or (Result is TUMLState), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'inState', Result.ClassName, 'TUMLState'])); end; function TclassifierInStateinState._Get_M_classifierInState: TBoldObjectReference; @@ -275,8 +264,8 @@ function TclassifierInStateinState._Get_M_classifierInState: TBoldObjectReferenc function TclassifierInStateinState._GetclassifierInState: TUMLClassifierInState; begin - assert(not assigned(M_classifierInState.BoldObject) or (M_classifierInState.BoldObject is TUMLClassifierInState), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'classifierInState', M_classifierInState.BoldObject.ClassName, 'TUMLClassifierInState'])); Result := TUMLClassifierInState(M_classifierInState.BoldObject); + assert(not assigned(Result) or (Result is TUMLClassifierInState), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'classifierInState', Result.ClassName, 'TUMLClassifierInState'])); end; procedure TclassifierInStateinStateList.Add(NewObject: TclassifierInStateinState); @@ -326,8 +315,8 @@ function TclassifierRole_availableFeature._Get_M_availableFeature: TBoldObjectRe function TclassifierRole_availableFeature._GetavailableFeature: TUMLFeature; begin - assert(not assigned(M_availableFeature.BoldObject) or (M_availableFeature.BoldObject is TUMLFeature), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'availableFeature', M_availableFeature.BoldObject.ClassName, 'TUMLFeature'])); Result := TUMLFeature(M_availableFeature.BoldObject); + assert(not assigned(Result) or (Result is TUMLFeature), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'availableFeature', Result.ClassName, 'TUMLFeature'])); end; function TclassifierRole_availableFeature._Get_M_classifierRole_: TBoldObjectReference; @@ -338,8 +327,8 @@ function TclassifierRole_availableFeature._Get_M_classifierRole_: TBoldObjectRef function TclassifierRole_availableFeature._GetclassifierRole_: TUMLClassifierRole; begin - assert(not assigned(M_classifierRole_.BoldObject) or (M_classifierRole_.BoldObject is TUMLClassifierRole), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'classifierRole_', M_classifierRole_.BoldObject.ClassName, 'TUMLClassifierRole'])); Result := TUMLClassifierRole(M_classifierRole_.BoldObject); + assert(not assigned(Result) or (Result is TUMLClassifierRole), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'classifierRole_', Result.ClassName, 'TUMLClassifierRole'])); end; procedure TclassifierRole_availableFeatureList.Add(NewObject: TclassifierRole_availableFeature); @@ -389,8 +378,8 @@ function TclassifierRoleavailableContents._Get_M_availableContents: TBoldObjectR function TclassifierRoleavailableContents._GetavailableContents: TUMLModelElement; begin - assert(not assigned(M_availableContents.BoldObject) or (M_availableContents.BoldObject is TUMLModelElement), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'availableContents', M_availableContents.BoldObject.ClassName, 'TUMLModelElement'])); Result := TUMLModelElement(M_availableContents.BoldObject); + assert(not assigned(Result) or (Result is TUMLModelElement), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'availableContents', Result.ClassName, 'TUMLModelElement'])); end; function TclassifierRoleavailableContents._Get_M_classifierRole: TBoldObjectReference; @@ -401,8 +390,8 @@ function TclassifierRoleavailableContents._Get_M_classifierRole: TBoldObjectRefe function TclassifierRoleavailableContents._GetclassifierRole: TUMLClassifierRole; begin - assert(not assigned(M_classifierRole.BoldObject) or (M_classifierRole.BoldObject is TUMLClassifierRole), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'classifierRole', M_classifierRole.BoldObject.ClassName, 'TUMLClassifierRole'])); Result := TUMLClassifierRole(M_classifierRole.BoldObject); + assert(not assigned(Result) or (Result is TUMLClassifierRole), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'classifierRole', Result.ClassName, 'TUMLClassifierRole'])); end; procedure TclassifierRoleavailableContentsList.Add(NewObject: TclassifierRoleavailableContents); @@ -452,8 +441,8 @@ function TclientclientDependency._Get_M_clientDependency: TBoldObjectReference; function TclientclientDependency._GetclientDependency: TUMLDependency; begin - assert(not assigned(M_clientDependency.BoldObject) or (M_clientDependency.BoldObject is TUMLDependency), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'clientDependency', M_clientDependency.BoldObject.ClassName, 'TUMLDependency'])); Result := TUMLDependency(M_clientDependency.BoldObject); + assert(not assigned(Result) or (Result is TUMLDependency), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'clientDependency', Result.ClassName, 'TUMLDependency'])); end; function TclientclientDependency._Get_M_client: TBoldObjectReference; @@ -464,8 +453,8 @@ function TclientclientDependency._Get_M_client: TBoldObjectReference; function TclientclientDependency._Getclient: TUMLModelElement; begin - assert(not assigned(M_client.BoldObject) or (M_client.BoldObject is TUMLModelElement), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'client', M_client.BoldObject.ClassName, 'TUMLModelElement'])); Result := TUMLModelElement(M_client.BoldObject); + assert(not assigned(Result) or (Result is TUMLModelElement), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'client', Result.ClassName, 'TUMLModelElement'])); end; procedure TclientclientDependencyList.Add(NewObject: TclientclientDependency); @@ -515,8 +504,8 @@ function TcollaborationconstrainingElement._Get_M_constrainingElement: TBoldObje function TcollaborationconstrainingElement._GetconstrainingElement: TUMLModelElement; begin - assert(not assigned(M_constrainingElement.BoldObject) or (M_constrainingElement.BoldObject is TUMLModelElement), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'constrainingElement', M_constrainingElement.BoldObject.ClassName, 'TUMLModelElement'])); Result := TUMLModelElement(M_constrainingElement.BoldObject); + assert(not assigned(Result) or (Result is TUMLModelElement), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'constrainingElement', Result.ClassName, 'TUMLModelElement'])); end; function TcollaborationconstrainingElement._Get_M_collaboration: TBoldObjectReference; @@ -527,8 +516,8 @@ function TcollaborationconstrainingElement._Get_M_collaboration: TBoldObjectRefe function TcollaborationconstrainingElement._Getcollaboration: TUMLCollaboration; begin - assert(not assigned(M_collaboration.BoldObject) or (M_collaboration.BoldObject is TUMLCollaboration), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'collaboration', M_collaboration.BoldObject.ClassName, 'TUMLCollaboration'])); Result := TUMLCollaboration(M_collaboration.BoldObject); + assert(not assigned(Result) or (Result is TUMLCollaboration), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'collaboration', Result.ClassName, 'TUMLCollaboration'])); end; procedure TcollaborationconstrainingElementList.Add(NewObject: TcollaborationconstrainingElement); @@ -578,8 +567,8 @@ function TcommentannotatedElement._Get_M_annotatedElement: TBoldObjectReference; function TcommentannotatedElement._GetannotatedElement: TUMLModelElement; begin - assert(not assigned(M_annotatedElement.BoldObject) or (M_annotatedElement.BoldObject is TUMLModelElement), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'annotatedElement', M_annotatedElement.BoldObject.ClassName, 'TUMLModelElement'])); Result := TUMLModelElement(M_annotatedElement.BoldObject); + assert(not assigned(Result) or (Result is TUMLModelElement), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'annotatedElement', Result.ClassName, 'TUMLModelElement'])); end; function TcommentannotatedElement._Get_M_comment: TBoldObjectReference; @@ -590,8 +579,8 @@ function TcommentannotatedElement._Get_M_comment: TBoldObjectReference; function TcommentannotatedElement._Getcomment: TUMLComment; begin - assert(not assigned(M_comment.BoldObject) or (M_comment.BoldObject is TUMLComment), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'comment', M_comment.BoldObject.ClassName, 'TUMLComment'])); Result := TUMLComment(M_comment.BoldObject); + assert(not assigned(Result) or (Result is TUMLComment), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'comment', Result.ClassName, 'TUMLComment'])); end; procedure TcommentannotatedElementList.Add(NewObject: TcommentannotatedElement); @@ -641,8 +630,8 @@ function TconstrainedElementconstraint._Get_M_constraint: TBoldObjectReference; function TconstrainedElementconstraint._Getconstraint: TUMLConstraint; begin - assert(not assigned(M_constraint.BoldObject) or (M_constraint.BoldObject is TUMLConstraint), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'constraint', M_constraint.BoldObject.ClassName, 'TUMLConstraint'])); Result := TUMLConstraint(M_constraint.BoldObject); + assert(not assigned(Result) or (Result is TUMLConstraint), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'constraint', Result.ClassName, 'TUMLConstraint'])); end; function TconstrainedElementconstraint._Get_M_constrainedElement: TBoldObjectReference; @@ -653,8 +642,8 @@ function TconstrainedElementconstraint._Get_M_constrainedElement: TBoldObjectRef function TconstrainedElementconstraint._GetconstrainedElement: TUMLModelElement; begin - assert(not assigned(M_constrainedElement.BoldObject) or (M_constrainedElement.BoldObject is TUMLModelElement), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'constrainedElement', M_constrainedElement.BoldObject.ClassName, 'TUMLModelElement'])); Result := TUMLModelElement(M_constrainedElement.BoldObject); + assert(not assigned(Result) or (Result is TUMLModelElement), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'constrainedElement', Result.ClassName, 'TUMLModelElement'])); end; procedure TconstrainedElementconstraintList.Add(NewObject: TconstrainedElementconstraint); @@ -704,8 +693,8 @@ function Tcontentspartition._Get_M_partition: TBoldObjectReference; function Tcontentspartition._Getpartition: TUMLPartition; begin - assert(not assigned(M_partition.BoldObject) or (M_partition.BoldObject is TUMLPartition), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'partition', M_partition.BoldObject.ClassName, 'TUMLPartition'])); Result := TUMLPartition(M_partition.BoldObject); + assert(not assigned(Result) or (Result is TUMLPartition), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'partition', Result.ClassName, 'TUMLPartition'])); end; function Tcontentspartition._Get_M_contents: TBoldObjectReference; @@ -716,8 +705,8 @@ function Tcontentspartition._Get_M_contents: TBoldObjectReference; function Tcontentspartition._Getcontents: TUMLModelElement; begin - assert(not assigned(M_contents.BoldObject) or (M_contents.BoldObject is TUMLModelElement), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'contents', M_contents.BoldObject.ClassName, 'TUMLModelElement'])); Result := TUMLModelElement(M_contents.BoldObject); + assert(not assigned(Result) or (Result is TUMLModelElement), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'contents', Result.ClassName, 'TUMLModelElement'])); end; procedure TcontentspartitionList.Add(NewObject: Tcontentspartition); @@ -767,8 +756,8 @@ function TcontextraisedSignal._Get_M_raisedSignal: TBoldObjectReference; function TcontextraisedSignal._GetraisedSignal: TUMLSignal; begin - assert(not assigned(M_raisedSignal.BoldObject) or (M_raisedSignal.BoldObject is TUMLSignal), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'raisedSignal', M_raisedSignal.BoldObject.ClassName, 'TUMLSignal'])); Result := TUMLSignal(M_raisedSignal.BoldObject); + assert(not assigned(Result) or (Result is TUMLSignal), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'raisedSignal', Result.ClassName, 'TUMLSignal'])); end; function TcontextraisedSignal._Get_M_context: TBoldObjectReference; @@ -779,8 +768,8 @@ function TcontextraisedSignal._Get_M_context: TBoldObjectReference; function TcontextraisedSignal._Getcontext: TUMLBehavioralFeature; begin - assert(not assigned(M_context.BoldObject) or (M_context.BoldObject is TUMLBehavioralFeature), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'context', M_context.BoldObject.ClassName, 'TUMLBehavioralFeature'])); Result := TUMLBehavioralFeature(M_context.BoldObject); + assert(not assigned(Result) or (Result is TUMLBehavioralFeature), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'context', Result.ClassName, 'TUMLBehavioralFeature'])); end; procedure TcontextraisedSignalList.Add(NewObject: TcontextraisedSignal); @@ -830,8 +819,8 @@ function TdeploymentLocationresident._Get_M_resident: TBoldObjectReference; function TdeploymentLocationresident._Getresident: TUMLComponent; begin - assert(not assigned(M_resident.BoldObject) or (M_resident.BoldObject is TUMLComponent), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'resident', M_resident.BoldObject.ClassName, 'TUMLComponent'])); Result := TUMLComponent(M_resident.BoldObject); + assert(not assigned(Result) or (Result is TUMLComponent), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'resident', Result.ClassName, 'TUMLComponent'])); end; function TdeploymentLocationresident._Get_M_deploymentLocation: TBoldObjectReference; @@ -842,8 +831,8 @@ function TdeploymentLocationresident._Get_M_deploymentLocation: TBoldObjectRefer function TdeploymentLocationresident._GetdeploymentLocation: TUMLNode; begin - assert(not assigned(M_deploymentLocation.BoldObject) or (M_deploymentLocation.BoldObject is TUMLNode), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'deploymentLocation', M_deploymentLocation.BoldObject.ClassName, 'TUMLNode'])); Result := TUMLNode(M_deploymentLocation.BoldObject); + assert(not assigned(Result) or (Result is TUMLNode), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'deploymentLocation', Result.ClassName, 'TUMLNode'])); end; procedure TdeploymentLocationresidentList.Add(NewObject: TdeploymentLocationresident); @@ -935,7 +924,7 @@ function TUMLElementImport._Getvisibility: TVisibilityKind; Result := M_visibility.AsVisibilityKind; end; -procedure TUMLElementImport._Setvisibility(NewValue: TVisibilityKind); +procedure TUMLElementImport._Setvisibility(const NewValue: TVisibilityKind); begin M_visibility.AsVisibilityKind := NewValue; end; @@ -951,7 +940,7 @@ function TUMLElementImport._Getalias: String; Result := M_alias.AsString; end; -procedure TUMLElementImport._Setalias(NewValue: String); +procedure TUMLElementImport._Setalias(const NewValue: String); begin M_alias.AsString := NewValue; end; @@ -964,11 +953,11 @@ function TUMLElementImport._Get_M_package: TBoldObjectReference; function TUMLElementImport._Getpackage: TUMLPackage; begin - assert(not assigned(M_package.BoldObject) or (M_package.BoldObject is TUMLPackage), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'package', M_package.BoldObject.ClassName, 'TUMLPackage'])); Result := TUMLPackage(M_package.BoldObject); + assert(not assigned(Result) or (Result is TUMLPackage), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'package', Result.ClassName, 'TUMLPackage'])); end; -procedure TUMLElementImport._Setpackage(value: TUMLPackage); +procedure TUMLElementImport._Setpackage(const value: TUMLPackage); begin M_package.BoldObject := value; end; @@ -981,11 +970,11 @@ function TUMLElementImport._Get_M_modelElement: TBoldObjectReference; function TUMLElementImport._GetmodelElement: TUMLModelElement; begin - assert(not assigned(M_modelElement.BoldObject) or (M_modelElement.BoldObject is TUMLModelElement), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'modelElement', M_modelElement.BoldObject.ClassName, 'TUMLModelElement'])); Result := TUMLModelElement(M_modelElement.BoldObject); + assert(not assigned(Result) or (Result is TUMLModelElement), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'modelElement', Result.ClassName, 'TUMLModelElement'])); end; -procedure TUMLElementImport._SetmodelElement(value: TUMLModelElement); +procedure TUMLElementImport._SetmodelElement(const value: TUMLModelElement); begin M_modelElement.BoldObject := value; end; @@ -1040,7 +1029,7 @@ function TUMLElementResidence._Getvisibility: TVisibilityKind; Result := M_visibility.AsVisibilityKind; end; -procedure TUMLElementResidence._Setvisibility(NewValue: TVisibilityKind); +procedure TUMLElementResidence._Setvisibility(const NewValue: TVisibilityKind); begin M_visibility.AsVisibilityKind := NewValue; end; @@ -1053,11 +1042,11 @@ function TUMLElementResidence._Get_M_residentElement: TBoldObjectReference; function TUMLElementResidence._GetresidentElement: TUMLComponent; begin - assert(not assigned(M_residentElement.BoldObject) or (M_residentElement.BoldObject is TUMLComponent), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'residentElement', M_residentElement.BoldObject.ClassName, 'TUMLComponent'])); Result := TUMLComponent(M_residentElement.BoldObject); + assert(not assigned(Result) or (Result is TUMLComponent), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'residentElement', Result.ClassName, 'TUMLComponent'])); end; -procedure TUMLElementResidence._SetresidentElement(value: TUMLComponent); +procedure TUMLElementResidence._SetresidentElement(const value: TUMLComponent); begin M_residentElement.BoldObject := value; end; @@ -1070,11 +1059,11 @@ function TUMLElementResidence._Get_M_residence: TBoldObjectReference; function TUMLElementResidence._Getresidence: TUMLModelElement; begin - assert(not assigned(M_residence.BoldObject) or (M_residence.BoldObject is TUMLModelElement), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'residence', M_residence.BoldObject.ClassName, 'TUMLModelElement'])); Result := TUMLModelElement(M_residence.BoldObject); + assert(not assigned(Result) or (Result is TUMLModelElement), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'residence', Result.ClassName, 'TUMLModelElement'])); end; -procedure TUMLElementResidence._Setresidence(value: TUMLModelElement); +procedure TUMLElementResidence._Setresidence(const value: TUMLModelElement); begin M_residence.BoldObject := value; end; @@ -1126,8 +1115,8 @@ function TextensionPointextend._Get_M_extend: TBoldObjectReference; function TextensionPointextend._Getextend: TUMLExtend; begin - assert(not assigned(M_extend.BoldObject) or (M_extend.BoldObject is TUMLExtend), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'extend', M_extend.BoldObject.ClassName, 'TUMLExtend'])); Result := TUMLExtend(M_extend.BoldObject); + assert(not assigned(Result) or (Result is TUMLExtend), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'extend', Result.ClassName, 'TUMLExtend'])); end; function TextensionPointextend._Get_M_extensionPoint: TBoldObjectReference; @@ -1138,8 +1127,8 @@ function TextensionPointextend._Get_M_extensionPoint: TBoldObjectReference; function TextensionPointextend._GetextensionPoint: TUMLExtensionPoint; begin - assert(not assigned(M_extensionPoint.BoldObject) or (M_extensionPoint.BoldObject is TUMLExtensionPoint), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'extensionPoint', M_extensionPoint.BoldObject.ClassName, 'TUMLExtensionPoint'])); Result := TUMLExtensionPoint(M_extensionPoint.BoldObject); + assert(not assigned(Result) or (Result is TUMLExtensionPoint), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'extensionPoint', Result.ClassName, 'TUMLExtensionPoint'])); end; procedure TextensionPointextendList.Add(NewObject: TextensionPointextend); @@ -1189,8 +1178,8 @@ function Tinstanceclassifier._Get_M_classifier: TBoldObjectReference; function Tinstanceclassifier._Getclassifier: TUMLClassifier; begin - assert(not assigned(M_classifier.BoldObject) or (M_classifier.BoldObject is TUMLClassifier), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'classifier', M_classifier.BoldObject.ClassName, 'TUMLClassifier'])); Result := TUMLClassifier(M_classifier.BoldObject); + assert(not assigned(Result) or (Result is TUMLClassifier), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'classifier', Result.ClassName, 'TUMLClassifier'])); end; function Tinstanceclassifier._Get_M_instance: TBoldObjectReference; @@ -1201,8 +1190,8 @@ function Tinstanceclassifier._Get_M_instance: TBoldObjectReference; function Tinstanceclassifier._Getinstance: TUMLInstance; begin - assert(not assigned(M_instance.BoldObject) or (M_instance.BoldObject is TUMLInstance), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'instance', M_instance.BoldObject.ClassName, 'TUMLInstance'])); Result := TUMLInstance(M_instance.BoldObject); + assert(not assigned(Result) or (Result is TUMLInstance), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'instance', Result.ClassName, 'TUMLInstance'])); end; procedure TinstanceclassifierList.Add(NewObject: Tinstanceclassifier); @@ -1252,8 +1241,8 @@ function Tparameterstate._Get_M_state: TBoldObjectReference; function Tparameterstate._Getstate: TUMLObjectFlowState; begin - assert(not assigned(M_state.BoldObject) or (M_state.BoldObject is TUMLObjectFlowState), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'state', M_state.BoldObject.ClassName, 'TUMLObjectFlowState'])); Result := TUMLObjectFlowState(M_state.BoldObject); + assert(not assigned(Result) or (Result is TUMLObjectFlowState), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'state', Result.ClassName, 'TUMLObjectFlowState'])); end; function Tparameterstate._Get_M_parameter: TBoldObjectReference; @@ -1264,8 +1253,8 @@ function Tparameterstate._Get_M_parameter: TBoldObjectReference; function Tparameterstate._Getparameter: TUMLParameter; begin - assert(not assigned(M_parameter.BoldObject) or (M_parameter.BoldObject is TUMLParameter), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'parameter', M_parameter.BoldObject.ClassName, 'TUMLParameter'])); Result := TUMLParameter(M_parameter.BoldObject); + assert(not assigned(Result) or (Result is TUMLParameter), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'parameter', Result.ClassName, 'TUMLParameter'])); end; procedure TparameterstateList.Add(NewObject: Tparameterstate); @@ -1315,8 +1304,8 @@ function Tparticipantspecification._Get_M_specification: TBoldObjectReference; function Tparticipantspecification._Getspecification: TUMLClassifier; begin - assert(not assigned(M_specification.BoldObject) or (M_specification.BoldObject is TUMLClassifier), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'specification', M_specification.BoldObject.ClassName, 'TUMLClassifier'])); Result := TUMLClassifier(M_specification.BoldObject); + assert(not assigned(Result) or (Result is TUMLClassifier), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'specification', Result.ClassName, 'TUMLClassifier'])); end; function Tparticipantspecification._Get_M_participant: TBoldObjectReference; @@ -1327,8 +1316,8 @@ function Tparticipantspecification._Get_M_participant: TBoldObjectReference; function Tparticipantspecification._Getparticipant: TUMLAssociationEnd; begin - assert(not assigned(M_participant.BoldObject) or (M_participant.BoldObject is TUMLAssociationEnd), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'participant', M_participant.BoldObject.ClassName, 'TUMLAssociationEnd'])); Result := TUMLAssociationEnd(M_participant.BoldObject); + assert(not assigned(Result) or (Result is TUMLAssociationEnd), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'participant', Result.ClassName, 'TUMLAssociationEnd'])); end; procedure TparticipantspecificationList.Add(NewObject: Tparticipantspecification); @@ -1378,8 +1367,8 @@ function Tpredecessormessage3._Get_M_message3: TBoldObjectReference; function Tpredecessormessage3._Getmessage3: TUMLMessage; begin - assert(not assigned(M_message3.BoldObject) or (M_message3.BoldObject is TUMLMessage), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'message3', M_message3.BoldObject.ClassName, 'TUMLMessage'])); Result := TUMLMessage(M_message3.BoldObject); + assert(not assigned(Result) or (Result is TUMLMessage), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'message3', Result.ClassName, 'TUMLMessage'])); end; function Tpredecessormessage3._Get_M_predecessor: TBoldObjectReference; @@ -1390,8 +1379,8 @@ function Tpredecessormessage3._Get_M_predecessor: TBoldObjectReference; function Tpredecessormessage3._Getpredecessor: TUMLMessage; begin - assert(not assigned(M_predecessor.BoldObject) or (M_predecessor.BoldObject is TUMLMessage), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'predecessor', M_predecessor.BoldObject.ClassName, 'TUMLMessage'])); Result := TUMLMessage(M_predecessor.BoldObject); + assert(not assigned(Result) or (Result is TUMLMessage), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'predecessor', Result.ClassName, 'TUMLMessage'])); end; procedure Tpredecessormessage3List.Add(NewObject: Tpredecessormessage3); @@ -1492,8 +1481,8 @@ function Tpresentationsubject._Get_M_subject: TBoldObjectReference; function Tpresentationsubject._Getsubject: TUMLModelElement; begin - assert(not assigned(M_subject.BoldObject) or (M_subject.BoldObject is TUMLModelElement), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'subject', M_subject.BoldObject.ClassName, 'TUMLModelElement'])); Result := TUMLModelElement(M_subject.BoldObject); + assert(not assigned(Result) or (Result is TUMLModelElement), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'subject', Result.ClassName, 'TUMLModelElement'])); end; function Tpresentationsubject._Get_M_presentation: TBoldObjectReference; @@ -1504,8 +1493,8 @@ function Tpresentationsubject._Get_M_presentation: TBoldObjectReference; function Tpresentationsubject._Getpresentation: TUMLPresentationElement; begin - assert(not assigned(M_presentation.BoldObject) or (M_presentation.BoldObject is TUMLPresentationElement), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'presentation', M_presentation.BoldObject.ClassName, 'TUMLPresentationElement'])); Result := TUMLPresentationElement(M_presentation.BoldObject); + assert(not assigned(Result) or (Result is TUMLPresentationElement), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'presentation', Result.ClassName, 'TUMLPresentationElement'])); end; procedure TpresentationsubjectList.Add(NewObject: Tpresentationsubject); @@ -1555,8 +1544,8 @@ function TsourceFlowsource._Get_M_source: TBoldObjectReference; function TsourceFlowsource._Getsource: TUMLModelElement; begin - assert(not assigned(M_source.BoldObject) or (M_source.BoldObject is TUMLModelElement), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'source', M_source.BoldObject.ClassName, 'TUMLModelElement'])); Result := TUMLModelElement(M_source.BoldObject); + assert(not assigned(Result) or (Result is TUMLModelElement), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'source', Result.ClassName, 'TUMLModelElement'])); end; function TsourceFlowsource._Get_M_sourceFlow: TBoldObjectReference; @@ -1567,8 +1556,8 @@ function TsourceFlowsource._Get_M_sourceFlow: TBoldObjectReference; function TsourceFlowsource._GetsourceFlow: TUMLFlow; begin - assert(not assigned(M_sourceFlow.BoldObject) or (M_sourceFlow.BoldObject is TUMLFlow), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'sourceFlow', M_sourceFlow.BoldObject.ClassName, 'TUMLFlow'])); Result := TUMLFlow(M_sourceFlow.BoldObject); + assert(not assigned(Result) or (Result is TUMLFlow), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'sourceFlow', Result.ClassName, 'TUMLFlow'])); end; procedure TsourceFlowsourceList.Add(NewObject: TsourceFlowsource); @@ -1618,8 +1607,8 @@ function TstatedeferrableEvent._Get_M_deferrableEvent: TBoldObjectReference; function TstatedeferrableEvent._GetdeferrableEvent: TUMLEvent; begin - assert(not assigned(M_deferrableEvent.BoldObject) or (M_deferrableEvent.BoldObject is TUMLEvent), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'deferrableEvent', M_deferrableEvent.BoldObject.ClassName, 'TUMLEvent'])); Result := TUMLEvent(M_deferrableEvent.BoldObject); + assert(not assigned(Result) or (Result is TUMLEvent), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'deferrableEvent', Result.ClassName, 'TUMLEvent'])); end; function TstatedeferrableEvent._Get_M_state: TBoldObjectReference; @@ -1630,8 +1619,8 @@ function TstatedeferrableEvent._Get_M_state: TBoldObjectReference; function TstatedeferrableEvent._Getstate: TUMLState; begin - assert(not assigned(M_state.BoldObject) or (M_state.BoldObject is TUMLState), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'state', M_state.BoldObject.ClassName, 'TUMLState'])); Result := TUMLState(M_state.BoldObject); + assert(not assigned(Result) or (Result is TUMLState), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'state', Result.ClassName, 'TUMLState'])); end; procedure TstatedeferrableEventList.Add(NewObject: TstatedeferrableEvent); @@ -1681,8 +1670,8 @@ function TsuppliersupplierDependency._Get_M_supplierDependency: TBoldObjectRefer function TsuppliersupplierDependency._GetsupplierDependency: TUMLDependency; begin - assert(not assigned(M_supplierDependency.BoldObject) or (M_supplierDependency.BoldObject is TUMLDependency), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'supplierDependency', M_supplierDependency.BoldObject.ClassName, 'TUMLDependency'])); Result := TUMLDependency(M_supplierDependency.BoldObject); + assert(not assigned(Result) or (Result is TUMLDependency), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'supplierDependency', Result.ClassName, 'TUMLDependency'])); end; function TsuppliersupplierDependency._Get_M_supplier: TBoldObjectReference; @@ -1693,8 +1682,8 @@ function TsuppliersupplierDependency._Get_M_supplier: TBoldObjectReference; function TsuppliersupplierDependency._Getsupplier: TUMLModelElement; begin - assert(not assigned(M_supplier.BoldObject) or (M_supplier.BoldObject is TUMLModelElement), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'supplier', M_supplier.BoldObject.ClassName, 'TUMLModelElement'])); Result := TUMLModelElement(M_supplier.BoldObject); + assert(not assigned(Result) or (Result is TUMLModelElement), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'supplier', Result.ClassName, 'TUMLModelElement'])); end; procedure TsuppliersupplierDependencyList.Add(NewObject: TsuppliersupplierDependency); @@ -1744,8 +1733,8 @@ function TtargetFlowtarget._Get_M_target: TBoldObjectReference; function TtargetFlowtarget._Gettarget: TUMLModelElement; begin - assert(not assigned(M_target.BoldObject) or (M_target.BoldObject is TUMLModelElement), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'target', M_target.BoldObject.ClassName, 'TUMLModelElement'])); Result := TUMLModelElement(M_target.BoldObject); + assert(not assigned(Result) or (Result is TUMLModelElement), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'target', Result.ClassName, 'TUMLModelElement'])); end; function TtargetFlowtarget._Get_M_targetFlow: TBoldObjectReference; @@ -1756,8 +1745,8 @@ function TtargetFlowtarget._Get_M_targetFlow: TBoldObjectReference; function TtargetFlowtarget._GettargetFlow: TUMLFlow; begin - assert(not assigned(M_targetFlow.BoldObject) or (M_targetFlow.BoldObject is TUMLFlow), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'targetFlow', M_targetFlow.BoldObject.ClassName, 'TUMLFlow'])); Result := TUMLFlow(M_targetFlow.BoldObject); + assert(not assigned(Result) or (Result is TUMLFlow), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'targetFlow', Result.ClassName, 'TUMLFlow'])); end; procedure TtargetFlowtargetList.Add(NewObject: TtargetFlowtarget); @@ -1807,11 +1796,11 @@ function TUMLTemplateParameter._Get_M_modelElement2: TBoldObjectReference; function TUMLTemplateParameter._GetmodelElement2: TUMLModelElement; begin - assert(not assigned(M_modelElement2.BoldObject) or (M_modelElement2.BoldObject is TUMLModelElement), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'modelElement2', M_modelElement2.BoldObject.ClassName, 'TUMLModelElement'])); Result := TUMLModelElement(M_modelElement2.BoldObject); + assert(not assigned(Result) or (Result is TUMLModelElement), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'modelElement2', Result.ClassName, 'TUMLModelElement'])); end; -procedure TUMLTemplateParameter._SetmodelElement2(value: TUMLModelElement); +procedure TUMLTemplateParameter._SetmodelElement2(const value: TUMLModelElement); begin M_modelElement2.BoldObject := value; end; @@ -1824,11 +1813,11 @@ function TUMLTemplateParameter._Get_M_modelElement: TBoldObjectReference; function TUMLTemplateParameter._GetmodelElement: TUMLModelElement; begin - assert(not assigned(M_modelElement.BoldObject) or (M_modelElement.BoldObject is TUMLModelElement), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'modelElement', M_modelElement.BoldObject.ClassName, 'TUMLModelElement'])); Result := TUMLModelElement(M_modelElement.BoldObject); + assert(not assigned(Result) or (Result is TUMLModelElement), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'modelElement', Result.ClassName, 'TUMLModelElement'])); end; -procedure TUMLTemplateParameter._SetmodelElement(value: TUMLModelElement); +procedure TUMLTemplateParameter._SetmodelElement(const value: TUMLModelElement); begin M_modelElement.BoldObject := value; end; @@ -1841,11 +1830,11 @@ function TUMLTemplateParameter._Get_M_defaultElement: TBoldObjectReference; function TUMLTemplateParameter._GetdefaultElement: TUMLModelElement; begin - assert(not assigned(M_defaultElement.BoldObject) or (M_defaultElement.BoldObject is TUMLModelElement), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'defaultElement', M_defaultElement.BoldObject.ClassName, 'TUMLModelElement'])); Result := TUMLModelElement(M_defaultElement.BoldObject); + assert(not assigned(Result) or (Result is TUMLModelElement), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'defaultElement', Result.ClassName, 'TUMLModelElement'])); end; -procedure TUMLTemplateParameter._SetdefaultElement(value: TUMLModelElement); +procedure TUMLTemplateParameter._SetdefaultElement(const value: TUMLModelElement); begin M_defaultElement.BoldObject := value; end; @@ -1914,11 +1903,11 @@ function TValidator._Get_M_UMLModel: TBoldObjectReference; function TValidator._GetUMLModel: TUMLModel; begin - assert(not assigned(M_UMLModel.BoldObject) or (M_UMLModel.BoldObject is TUMLModel), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'UMLModel', M_UMLModel.BoldObject.ClassName, 'TUMLModel'])); Result := TUMLModel(M_UMLModel.BoldObject); + assert(not assigned(Result) or (Result is TUMLModel), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'UMLModel', Result.ClassName, 'TUMLModel'])); end; -procedure TValidator._SetUMLModel(value: TUMLModel); +procedure TValidator._SetUMLModel(const value: TUMLModel); begin M_UMLModel.BoldObject := value; end; @@ -1960,15 +1949,12 @@ procedure TValidatorList.SetBoldObject(index: Integer; NewObject: TValidator); SetElement(index, NewObject); end; -function TValidator.GetDeriveMethodForMember(Member: TBoldMember): TBoldDeriveAndResubscribe; +function TValidator.GetDeriveMethodForMember(MemberIndex: Integer): TBoldDeriveAndResubscribe; begin - if (Member = M_HighestSeverity) then result := _HighestSeverity_DeriveAndSubscribe else - result := inherited GetDeriveMethodForMember(Member); -end; - -function TValidator.GetReverseDeriveMethodForMember(Member: TBoldMember): TBoldReverseDerive; -begin - result := inherited GetReverseDeriveMethodForMember(Member); + case MemberIndex of + 0: result := _HighestSeverity_DeriveAndSubscribe; + else result := inherited GetDeriveMethodForMember(MemberIndex); + end; end; { TViolation } @@ -1984,7 +1970,7 @@ function TViolation._GetDescription: String; Result := M_Description.AsString; end; -procedure TViolation._SetDescription(NewValue: String); +procedure TViolation._SetDescription(const NewValue: String); begin M_Description.AsString := NewValue; end; @@ -2000,7 +1986,7 @@ function TViolation._GetSeverity: TSeverity; Result := M_Severity.AsSeverity; end; -procedure TViolation._SetSeverity(NewValue: TSeverity); +procedure TViolation._SetSeverity(const NewValue: TSeverity); begin M_Severity.AsSeverity := NewValue; end; @@ -2013,11 +1999,11 @@ function TViolation._Get_M_Validator: TBoldObjectReference; function TViolation._GetValidator: TValidator; begin - assert(not assigned(M_Validator.BoldObject) or (M_Validator.BoldObject is TValidator), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'Validator', M_Validator.BoldObject.ClassName, 'TValidator'])); Result := TValidator(M_Validator.BoldObject); + assert(not assigned(Result) or (Result is TValidator), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'Validator', Result.ClassName, 'TValidator'])); end; -procedure TViolation._SetValidator(value: TValidator); +procedure TViolation._SetValidator(const value: TValidator); begin M_Validator.BoldObject := value; end; @@ -2030,11 +2016,11 @@ function TViolation._Get_M_ModelElement: TBoldObjectReference; function TViolation._GetModelElement: TUMLModelElement; begin - assert(not assigned(M_ModelElement.BoldObject) or (M_ModelElement.BoldObject is TUMLModelElement), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'ModelElement', M_ModelElement.BoldObject.ClassName, 'TUMLModelElement'])); Result := TUMLModelElement(M_ModelElement.BoldObject); + assert(not assigned(Result) or (Result is TUMLModelElement), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'ModelElement', Result.ClassName, 'TUMLModelElement'])); end; -procedure TViolation._SetModelElement(value: TUMLModelElement); +procedure TViolation._SetModelElement(const value: TUMLModelElement); begin M_ModelElement.BoldObject := value; end; @@ -2089,7 +2075,7 @@ function TUMLModelElement._Getname: String; Result := M_name.AsString; end; -procedure TUMLModelElement._Setname(NewValue: String); +procedure TUMLModelElement._Setname(const NewValue: String); begin M_name.AsString := NewValue; end; @@ -2105,7 +2091,7 @@ function TUMLModelElement._Getvisibility: TVisibilityKind; Result := M_visibility.AsVisibilityKind; end; -procedure TUMLModelElement._Setvisibility(NewValue: TVisibilityKind); +procedure TUMLModelElement._Setvisibility(const NewValue: TVisibilityKind); begin M_visibility.AsVisibilityKind := NewValue; end; @@ -2121,7 +2107,7 @@ function TUMLModelElement._GetisSpecification: boolean; Result := M_isSpecification.AsBoolean; end; -procedure TUMLModelElement._SetisSpecification(NewValue: boolean); +procedure TUMLModelElement._SetisSpecification(const NewValue: boolean); begin M_isSpecification.AsBoolean := NewValue; end; @@ -2148,7 +2134,7 @@ function TUMLModelElement._GetstereotypeName: String; Result := M_stereotypeName.AsString; end; -procedure TUMLModelElement._SetstereotypeName(NewValue: String); +procedure TUMLModelElement._SetstereotypeName(const NewValue: String); begin M_stereotypeName.AsString := NewValue; end; @@ -2175,7 +2161,7 @@ function TUMLModelElement._Getderived: boolean; Result := M_derived.AsBoolean; end; -procedure TUMLModelElement._Setderived(NewValue: boolean); +procedure TUMLModelElement._Setderived(const NewValue: boolean); begin M_derived.AsBoolean := NewValue; end; @@ -2266,11 +2252,11 @@ function TUMLModelElement._Get_M_binding: TBoldObjectReference; function TUMLModelElement._Getbinding: TUMLBinding; begin - assert(not assigned(M_binding.BoldObject) or (M_binding.BoldObject is TUMLBinding), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'binding', M_binding.BoldObject.ClassName, 'TUMLBinding'])); Result := TUMLBinding(M_binding.BoldObject); + assert(not assigned(Result) or (Result is TUMLBinding), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'binding', Result.ClassName, 'TUMLBinding'])); end; -procedure TUMLModelElement._Setbinding(value: TUMLBinding); +procedure TUMLModelElement._Setbinding(const value: TUMLBinding); begin M_binding.BoldObject := value; end; @@ -2349,11 +2335,11 @@ function TUMLModelElement._Get_M_namespace_: TBoldObjectReference; function TUMLModelElement._Getnamespace_: TUMLNamespace; begin - assert(not assigned(M_namespace_.BoldObject) or (M_namespace_.BoldObject is TUMLNamespace), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'namespace_', M_namespace_.BoldObject.ClassName, 'TUMLNamespace'])); Result := TUMLNamespace(M_namespace_.BoldObject); + assert(not assigned(Result) or (Result is TUMLNamespace), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'namespace_', Result.ClassName, 'TUMLNamespace'])); end; -procedure TUMLModelElement._Setnamespace_(value: TUMLNamespace); +procedure TUMLModelElement._Setnamespace_(const value: TUMLNamespace); begin M_namespace_.BoldObject := value; end; @@ -2393,11 +2379,11 @@ function TUMLModelElement._Get_M_stereotype: TBoldObjectReference; function TUMLModelElement._Getstereotype: TUMLStereotype; begin - assert(not assigned(M_stereotype.BoldObject) or (M_stereotype.BoldObject is TUMLStereotype), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'stereotype', M_stereotype.BoldObject.ClassName, 'TUMLStereotype'])); Result := TUMLStereotype(M_stereotype.BoldObject); + assert(not assigned(Result) or (Result is TUMLStereotype), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'stereotype', Result.ClassName, 'TUMLStereotype'])); end; -procedure TUMLModelElement._Setstereotype(value: TUMLStereotype); +procedure TUMLModelElement._Setstereotype(const value: TUMLStereotype); begin M_stereotype.BoldObject := value; end; @@ -2410,11 +2396,11 @@ function TUMLModelElement._Get_M_model: TBoldObjectReference; function TUMLModelElement._Getmodel: TUMLModel; begin - assert(not assigned(M_model.BoldObject) or (M_model.BoldObject is TUMLModel), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'model', M_model.BoldObject.ClassName, 'TUMLModel'])); Result := TUMLModel(M_model.BoldObject); + assert(not assigned(Result) or (Result is TUMLModel), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'model', Result.ClassName, 'TUMLModel'])); end; -procedure TUMLModelElement._Setmodel(value: TUMLModel); +procedure TUMLModelElement._Setmodel(const value: TUMLModel); begin M_model.BoldObject := value; end; @@ -2427,11 +2413,11 @@ function TUMLModelElement._Get_M_qualifyingOwner: TBoldObjectReference; function TUMLModelElement._GetqualifyingOwner: TUMLModelElement; begin - assert(not assigned(M_qualifyingOwner.BoldObject) or (M_qualifyingOwner.BoldObject is TUMLModelElement), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'qualifyingOwner', M_qualifyingOwner.BoldObject.ClassName, 'TUMLModelElement'])); Result := TUMLModelElement(M_qualifyingOwner.BoldObject); + assert(not assigned(Result) or (Result is TUMLModelElement), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'qualifyingOwner', Result.ClassName, 'TUMLModelElement'])); end; -procedure TUMLModelElement._SetqualifyingOwner(value: TUMLModelElement); +procedure TUMLModelElement._SetqualifyingOwner(const value: TUMLModelElement); begin M_qualifyingOwner.BoldObject := value; end; @@ -2479,19 +2465,23 @@ procedure TUMLModelElementList.SetBoldObject(index: Integer; NewObject: TUMLMode SetElement(index, NewObject); end; -function TUMLModelElement.GetDeriveMethodForMember(Member: TBoldMember): TBoldDeriveAndResubscribe; +function TUMLModelElement.GetDeriveMethodForMember(MemberIndex: Integer): TBoldDeriveAndResubscribe; begin - if (Member = M_stereotypeName) then result := _stereotypeName_DeriveAndSubscribe else - if (Member = M_documentation) then result := _documentation_DeriveAndSubscribe else - if (Member = M_derived) then result := _derived_DeriveAndSubscribe else - result := inherited GetDeriveMethodForMember(Member); + case MemberIndex of + 4: result := _stereotypeName_DeriveAndSubscribe; + 5: result := _documentation_DeriveAndSubscribe; + 6: result := _derived_DeriveAndSubscribe; + else result := inherited GetDeriveMethodForMember(MemberIndex); + end; end; -function TUMLModelElement.GetReverseDeriveMethodForMember(Member: TBoldMember): TBoldReverseDerive; +function TUMLModelElement.GetReverseDeriveMethodForMember(MemberIndex: Integer): TBoldReverseDerive; begin - result := inherited GetReverseDeriveMethodForMember(Member); - if not assigned(result) and (Member = M_stereotypeName) then result := _stereotypeName_ReverseDerive; - if not assigned(result) and (Member = M_derived) then result := _derived_ReverseDerive; + case MemberIndex of + 4: result := _stereotypeName_ReverseDerive; + 6: result := _derived_ReverseDerive; + else result := inherited GetReverseDeriveMethodForMember(MemberIndex); + end; end; { TUMLAction } @@ -2507,7 +2497,7 @@ function TUMLAction._Getrecurrence: String; Result := M_recurrence.AsString; end; -procedure TUMLAction._Setrecurrence(NewValue: String); +procedure TUMLAction._Setrecurrence(const NewValue: String); begin M_recurrence.AsString := NewValue; end; @@ -2523,7 +2513,7 @@ function TUMLAction._Gettarget: String; Result := M_target.AsString; end; -procedure TUMLAction._Settarget(NewValue: String); +procedure TUMLAction._Settarget(const NewValue: String); begin M_target.AsString := NewValue; end; @@ -2539,7 +2529,7 @@ function TUMLAction._GetisAsynchronous: boolean; Result := M_isAsynchronous.AsBoolean; end; -procedure TUMLAction._SetisAsynchronous(NewValue: boolean); +procedure TUMLAction._SetisAsynchronous(const NewValue: boolean); begin M_isAsynchronous.AsBoolean := NewValue; end; @@ -2555,7 +2545,7 @@ function TUMLAction._Getscript: String; Result := M_script.AsString; end; -procedure TUMLAction._Setscript(NewValue: String); +procedure TUMLAction._Setscript(const NewValue: String); begin M_script.AsString := NewValue; end; @@ -2568,11 +2558,11 @@ function TUMLAction._Get_M_transition: TBoldObjectReference; function TUMLAction._Gettransition: TUMLTransition; begin - assert(not assigned(M_transition.BoldObject) or (M_transition.BoldObject is TUMLTransition), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'transition', M_transition.BoldObject.ClassName, 'TUMLTransition'])); Result := TUMLTransition(M_transition.BoldObject); + assert(not assigned(Result) or (Result is TUMLTransition), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'transition', Result.ClassName, 'TUMLTransition'])); end; -procedure TUMLAction._Settransition(value: TUMLTransition); +procedure TUMLAction._Settransition(const value: TUMLTransition); begin M_transition.BoldObject := value; end; @@ -2597,11 +2587,11 @@ function TUMLAction._Get_M_actionSequence: TBoldObjectReference; function TUMLAction._GetactionSequence: TUMLActionSequence; begin - assert(not assigned(M_actionSequence.BoldObject) or (M_actionSequence.BoldObject is TUMLActionSequence), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'actionSequence', M_actionSequence.BoldObject.ClassName, 'TUMLActionSequence'])); Result := TUMLActionSequence(M_actionSequence.BoldObject); + assert(not assigned(Result) or (Result is TUMLActionSequence), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'actionSequence', Result.ClassName, 'TUMLActionSequence'])); end; -procedure TUMLAction._SetactionSequence(value: TUMLActionSequence); +procedure TUMLAction._SetactionSequence(const value: TUMLActionSequence); begin M_actionSequence.BoldObject := value; end; @@ -2662,7 +2652,7 @@ function TUMLArgument._Getvalue: String; Result := M_value.AsString; end; -procedure TUMLArgument._Setvalue(NewValue: String); +procedure TUMLArgument._Setvalue(const NewValue: String); begin M_value.AsString := NewValue; end; @@ -2675,11 +2665,11 @@ function TUMLArgument._Get_M_action: TBoldObjectReference; function TUMLArgument._Getaction: TUMLAction; begin - assert(not assigned(M_action.BoldObject) or (M_action.BoldObject is TUMLAction), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'action', M_action.BoldObject.ClassName, 'TUMLAction'])); Result := TUMLAction(M_action.BoldObject); + assert(not assigned(Result) or (Result is TUMLAction), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'action', Result.ClassName, 'TUMLAction'])); end; -procedure TUMLArgument._Setaction(value: TUMLAction); +procedure TUMLArgument._Setaction(const value: TUMLAction); begin M_action.BoldObject := value; end; @@ -2734,7 +2724,7 @@ function TUMLAssociationEnd._GetisNavigable: boolean; Result := M_isNavigable.AsBoolean; end; -procedure TUMLAssociationEnd._SetisNavigable(NewValue: boolean); +procedure TUMLAssociationEnd._SetisNavigable(const NewValue: boolean); begin M_isNavigable.AsBoolean := NewValue; end; @@ -2750,7 +2740,7 @@ function TUMLAssociationEnd._Getordering: TOrderingKind; Result := M_ordering.AsOrderingKind; end; -procedure TUMLAssociationEnd._Setordering(NewValue: TOrderingKind); +procedure TUMLAssociationEnd._Setordering(const NewValue: TOrderingKind); begin M_ordering.AsOrderingKind := NewValue; end; @@ -2766,7 +2756,7 @@ function TUMLAssociationEnd._Getaggregation: TAggregationKind; Result := M_aggregation.AsAggregationKind; end; -procedure TUMLAssociationEnd._Setaggregation(NewValue: TAggregationKind); +procedure TUMLAssociationEnd._Setaggregation(const NewValue: TAggregationKind); begin M_aggregation.AsAggregationKind := NewValue; end; @@ -2782,7 +2772,7 @@ function TUMLAssociationEnd._GettargetScope: TScopeKind; Result := M_targetScope.AsScopeKind; end; -procedure TUMLAssociationEnd._SettargetScope(NewValue: TScopeKind); +procedure TUMLAssociationEnd._SettargetScope(const NewValue: TScopeKind); begin M_targetScope.AsScopeKind := NewValue; end; @@ -2798,7 +2788,7 @@ function TUMLAssociationEnd._Getmultiplicity: String; Result := M_multiplicity.AsString; end; -procedure TUMLAssociationEnd._Setmultiplicity(NewValue: String); +procedure TUMLAssociationEnd._Setmultiplicity(const NewValue: String); begin M_multiplicity.AsString := NewValue; end; @@ -2814,7 +2804,7 @@ function TUMLAssociationEnd._Getchangeability: TChangeableKind; Result := M_changeability.AsChangeableKind; end; -procedure TUMLAssociationEnd._Setchangeability(NewValue: TChangeableKind); +procedure TUMLAssociationEnd._Setchangeability(const NewValue: TChangeableKind); begin M_changeability.AsChangeableKind := NewValue; end; @@ -2852,7 +2842,7 @@ function TUMLAssociationEnd._GetisOrdered: boolean; Result := M_isOrdered.AsBoolean; end; -procedure TUMLAssociationEnd._SetisOrdered(NewValue: boolean); +procedure TUMLAssociationEnd._SetisOrdered(const NewValue: boolean); begin M_isOrdered.AsBoolean := NewValue; end; @@ -2895,11 +2885,11 @@ function TUMLAssociationEnd._Get_M_type_: TBoldObjectReference; function TUMLAssociationEnd._Gettype_: TUMLClassifier; begin - assert(not assigned(M_type_.BoldObject) or (M_type_.BoldObject is TUMLClassifier), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'type_', M_type_.BoldObject.ClassName, 'TUMLClassifier'])); Result := TUMLClassifier(M_type_.BoldObject); + assert(not assigned(Result) or (Result is TUMLClassifier), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'type_', Result.ClassName, 'TUMLClassifier'])); end; -procedure TUMLAssociationEnd._Settype_(value: TUMLClassifier); +procedure TUMLAssociationEnd._Settype_(const value: TUMLClassifier); begin M_type_.BoldObject := value; end; @@ -2912,11 +2902,11 @@ function TUMLAssociationEnd._Get_M_otherEnd: TBoldObjectReference; function TUMLAssociationEnd._GetotherEnd: TUMLAssociationEnd; begin - assert(not assigned(M_otherEnd.BoldObject) or (M_otherEnd.BoldObject is TUMLAssociationEnd), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'otherEnd', M_otherEnd.BoldObject.ClassName, 'TUMLAssociationEnd'])); Result := TUMLAssociationEnd(M_otherEnd.BoldObject); + assert(not assigned(Result) or (Result is TUMLAssociationEnd), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'otherEnd', Result.ClassName, 'TUMLAssociationEnd'])); end; -procedure TUMLAssociationEnd._SetotherEnd(value: TUMLAssociationEnd); +procedure TUMLAssociationEnd._SetotherEnd(const value: TUMLAssociationEnd); begin M_otherEnd.BoldObject := value; end; @@ -2929,11 +2919,11 @@ function TUMLAssociationEnd._Get_M_association: TBoldObjectReference; function TUMLAssociationEnd._Getassociation: TUMLAssociation; begin - assert(not assigned(M_association.BoldObject) or (M_association.BoldObject is TUMLAssociation), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'association', M_association.BoldObject.ClassName, 'TUMLAssociation'])); Result := TUMLAssociation(M_association.BoldObject); + assert(not assigned(Result) or (Result is TUMLAssociation), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'association', Result.ClassName, 'TUMLAssociation'])); end; -procedure TUMLAssociationEnd._Setassociation(value: TUMLAssociation); +procedure TUMLAssociationEnd._Setassociation(const value: TUMLAssociation); begin M_association.BoldObject := value; end; @@ -2975,18 +2965,22 @@ procedure TUMLAssociationEndList.SetBoldObject(index: Integer; NewObject: TUMLAs SetElement(index, NewObject); end; -function TUMLAssociationEnd.GetDeriveMethodForMember(Member: TBoldMember): TBoldDeriveAndResubscribe; +function TUMLAssociationEnd.GetDeriveMethodForMember(MemberIndex: Integer): TBoldDeriveAndResubscribe; begin - if (Member = M_multi) then result := _multi_DeriveAndSubscribe else - if (Member = M_mandatory) then result := _mandatory_DeriveAndSubscribe else - if (Member = M_isOrdered) then result := _isOrdered_DeriveAndSubscribe else - result := inherited GetDeriveMethodForMember(Member); + case MemberIndex of + 46: result := _multi_DeriveAndSubscribe; + 47: result := _mandatory_DeriveAndSubscribe; + 48: result := _isOrdered_DeriveAndSubscribe; + else result := inherited GetDeriveMethodForMember(MemberIndex); + end; end; -function TUMLAssociationEnd.GetReverseDeriveMethodForMember(Member: TBoldMember): TBoldReverseDerive; +function TUMLAssociationEnd.GetReverseDeriveMethodForMember(MemberIndex: Integer): TBoldReverseDerive; begin - result := inherited GetReverseDeriveMethodForMember(Member); - if not assigned(result) and (Member = M_isOrdered) then result := _isOrdered_ReverseDerive; + case MemberIndex of + 48: result := _isOrdered_ReverseDerive; + else result := inherited GetReverseDeriveMethodForMember(MemberIndex); + end; end; { TUMLAttributeLink } @@ -2999,11 +2993,11 @@ function TUMLAttributeLink._Get_M_value: TBoldObjectReference; function TUMLAttributeLink._Getvalue: TUMLInstance; begin - assert(not assigned(M_value.BoldObject) or (M_value.BoldObject is TUMLInstance), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'value', M_value.BoldObject.ClassName, 'TUMLInstance'])); Result := TUMLInstance(M_value.BoldObject); + assert(not assigned(Result) or (Result is TUMLInstance), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'value', Result.ClassName, 'TUMLInstance'])); end; -procedure TUMLAttributeLink._Setvalue(value: TUMLInstance); +procedure TUMLAttributeLink._Setvalue(const value: TUMLInstance); begin M_value.BoldObject := value; end; @@ -3016,11 +3010,11 @@ function TUMLAttributeLink._Get_M_attribute: TBoldObjectReference; function TUMLAttributeLink._Getattribute: TUMLAttribute; begin - assert(not assigned(M_attribute.BoldObject) or (M_attribute.BoldObject is TUMLAttribute), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'attribute', M_attribute.BoldObject.ClassName, 'TUMLAttribute'])); Result := TUMLAttribute(M_attribute.BoldObject); + assert(not assigned(Result) or (Result is TUMLAttribute), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'attribute', Result.ClassName, 'TUMLAttribute'])); end; -procedure TUMLAttributeLink._Setattribute(value: TUMLAttribute); +procedure TUMLAttributeLink._Setattribute(const value: TUMLAttribute); begin M_attribute.BoldObject := value; end; @@ -3033,11 +3027,11 @@ function TUMLAttributeLink._Get_M_instance: TBoldObjectReference; function TUMLAttributeLink._Getinstance: TUMLInstance; begin - assert(not assigned(M_instance.BoldObject) or (M_instance.BoldObject is TUMLInstance), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'instance', M_instance.BoldObject.ClassName, 'TUMLInstance'])); Result := TUMLInstance(M_instance.BoldObject); + assert(not assigned(Result) or (Result is TUMLInstance), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'instance', Result.ClassName, 'TUMLInstance'])); end; -procedure TUMLAttributeLink._Setinstance(value: TUMLInstance); +procedure TUMLAttributeLink._Setinstance(const value: TUMLInstance); begin M_instance.BoldObject := value; end; @@ -3050,11 +3044,11 @@ function TUMLAttributeLink._Get_M_linkEnd: TBoldObjectReference; function TUMLAttributeLink._GetlinkEnd: TUMLLinkEnd; begin - assert(not assigned(M_linkEnd.BoldObject) or (M_linkEnd.BoldObject is TUMLLinkEnd), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'linkEnd', M_linkEnd.BoldObject.ClassName, 'TUMLLinkEnd'])); Result := TUMLLinkEnd(M_linkEnd.BoldObject); + assert(not assigned(Result) or (Result is TUMLLinkEnd), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'linkEnd', Result.ClassName, 'TUMLLinkEnd'])); end; -procedure TUMLAttributeLink._SetlinkEnd(value: TUMLLinkEnd); +procedure TUMLAttributeLink._SetlinkEnd(const value: TUMLLinkEnd); begin M_linkEnd.BoldObject := value; end; @@ -3160,7 +3154,7 @@ function TUMLConstraint._Getbody: String; Result := M_body.AsString; end; -procedure TUMLConstraint._Setbody(NewValue: String); +procedure TUMLConstraint._Setbody(const NewValue: String); begin M_body.AsString := NewValue; end; @@ -3185,11 +3179,11 @@ function TUMLConstraint._Get_M_constrainedElement2: TBoldObjectReference; function TUMLConstraint._GetconstrainedElement2: TUMLStereotype; begin - assert(not assigned(M_constrainedElement2.BoldObject) or (M_constrainedElement2.BoldObject is TUMLStereotype), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'constrainedElement2', M_constrainedElement2.BoldObject.ClassName, 'TUMLStereotype'])); Result := TUMLStereotype(M_constrainedElement2.BoldObject); + assert(not assigned(Result) or (Result is TUMLStereotype), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'constrainedElement2', Result.ClassName, 'TUMLStereotype'])); end; -procedure TUMLConstraint._SetconstrainedElement2(value: TUMLStereotype); +procedure TUMLConstraint._SetconstrainedElement2(const value: TUMLStereotype); begin M_constrainedElement2.BoldObject := value; end; @@ -3307,7 +3301,7 @@ function TUMLExtensionPoint._Getlocation: String; Result := M_location.AsString; end; -procedure TUMLExtensionPoint._Setlocation(NewValue: String); +procedure TUMLExtensionPoint._Setlocation(const NewValue: String); begin M_location.AsString := NewValue; end; @@ -3320,11 +3314,11 @@ function TUMLExtensionPoint._Get_M_useCase: TBoldObjectReference; function TUMLExtensionPoint._GetuseCase: TUMLUseCase; begin - assert(not assigned(M_useCase.BoldObject) or (M_useCase.BoldObject is TUMLUseCase), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'useCase', M_useCase.BoldObject.ClassName, 'TUMLUseCase'])); Result := TUMLUseCase(M_useCase.BoldObject); + assert(not assigned(Result) or (Result is TUMLUseCase), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'useCase', Result.ClassName, 'TUMLUseCase'])); end; -procedure TUMLExtensionPoint._SetuseCase(value: TUMLUseCase); +procedure TUMLExtensionPoint._SetuseCase(const value: TUMLUseCase); begin M_useCase.BoldObject := value; end; @@ -3391,7 +3385,7 @@ function TUMLFeature._GetownerScope: TScopeKind; Result := M_ownerScope.AsScopeKind; end; -procedure TUMLFeature._SetownerScope(NewValue: TScopeKind); +procedure TUMLFeature._SetownerScope(const NewValue: TScopeKind); begin M_ownerScope.AsScopeKind := NewValue; end; @@ -3416,11 +3410,11 @@ function TUMLFeature._Get_M_owner: TBoldObjectReference; function TUMLFeature._Getowner: TUMLClassifier; begin - assert(not assigned(M_owner.BoldObject) or (M_owner.BoldObject is TUMLClassifier), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'owner', M_owner.BoldObject.ClassName, 'TUMLClassifier'])); Result := TUMLClassifier(M_owner.BoldObject); + assert(not assigned(Result) or (Result is TUMLClassifier), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'owner', Result.ClassName, 'TUMLClassifier'])); end; -procedure TUMLFeature._Setowner(value: TUMLClassifier); +procedure TUMLFeature._Setowner(const value: TUMLClassifier); begin M_owner.BoldObject := value; end; @@ -3462,16 +3456,6 @@ procedure TUMLFeatureList.SetBoldObject(index: Integer; NewObject: TUMLFeature); SetElement(index, NewObject); end; -function TUMLFeature.GetDeriveMethodForMember(Member: TBoldMember): TBoldDeriveAndResubscribe; -begin - result := inherited GetDeriveMethodForMember(Member); -end; - -function TUMLFeature.GetReverseDeriveMethodForMember(Member: TBoldMember): TBoldReverseDerive; -begin - result := inherited GetReverseDeriveMethodForMember(Member); -end; - { TUMLGuard } function TUMLGuard._Get_M_expression: TBAString; @@ -3485,7 +3469,7 @@ function TUMLGuard._Getexpression: String; Result := M_expression.AsString; end; -procedure TUMLGuard._Setexpression(NewValue: String); +procedure TUMLGuard._Setexpression(const NewValue: String); begin M_expression.AsString := NewValue; end; @@ -3498,11 +3482,11 @@ function TUMLGuard._Get_M_transition: TBoldObjectReference; function TUMLGuard._Gettransition: TUMLTransition; begin - assert(not assigned(M_transition.BoldObject) or (M_transition.BoldObject is TUMLTransition), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'transition', M_transition.BoldObject.ClassName, 'TUMLTransition'])); Result := TUMLTransition(M_transition.BoldObject); + assert(not assigned(Result) or (Result is TUMLTransition), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'transition', Result.ClassName, 'TUMLTransition'])); end; -procedure TUMLGuard._Settransition(value: TUMLTransition); +procedure TUMLGuard._Settransition(const value: TUMLTransition); begin M_transition.BoldObject := value; end; @@ -3608,11 +3592,11 @@ function TUMLInstance._Get_M_componentInstance: TBoldObjectReference; function TUMLInstance._GetcomponentInstance: TUMLComponentInstance; begin - assert(not assigned(M_componentInstance.BoldObject) or (M_componentInstance.BoldObject is TUMLComponentInstance), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'componentInstance', M_componentInstance.BoldObject.ClassName, 'TUMLComponentInstance'])); Result := TUMLComponentInstance(M_componentInstance.BoldObject); + assert(not assigned(Result) or (Result is TUMLComponentInstance), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'componentInstance', Result.ClassName, 'TUMLComponentInstance'])); end; -procedure TUMLInstance._SetcomponentInstance(value: TUMLComponentInstance); +procedure TUMLInstance._SetcomponentInstance(const value: TUMLComponentInstance); begin M_componentInstance.BoldObject := value; end; @@ -3664,11 +3648,11 @@ function TUMLInteraction._Get_M_context: TBoldObjectReference; function TUMLInteraction._Getcontext: TUMLCollaboration; begin - assert(not assigned(M_context.BoldObject) or (M_context.BoldObject is TUMLCollaboration), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'context', M_context.BoldObject.ClassName, 'TUMLCollaboration'])); Result := TUMLCollaboration(M_context.BoldObject); + assert(not assigned(Result) or (Result is TUMLCollaboration), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'context', Result.ClassName, 'TUMLCollaboration'])); end; -procedure TUMLInteraction._Setcontext(value: TUMLCollaboration); +procedure TUMLInteraction._Setcontext(const value: TUMLCollaboration); begin M_context.BoldObject := value; end; @@ -3726,11 +3710,11 @@ function TUMLLink._Get_M_association: TBoldObjectReference; function TUMLLink._Getassociation: TUMLAssociation; begin - assert(not assigned(M_association.BoldObject) or (M_association.BoldObject is TUMLAssociation), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'association', M_association.BoldObject.ClassName, 'TUMLAssociation'])); Result := TUMLAssociation(M_association.BoldObject); + assert(not assigned(Result) or (Result is TUMLAssociation), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'association', Result.ClassName, 'TUMLAssociation'])); end; -procedure TUMLLink._Setassociation(value: TUMLAssociation); +procedure TUMLLink._Setassociation(const value: TUMLAssociation); begin M_association.BoldObject := value; end; @@ -3749,11 +3733,11 @@ function TUMLLink._Get_M_xobject: TBoldObjectReference; function TUMLLink._Getxobject: TUMLObject; begin - assert(not assigned(M_xobject.BoldObject) or (M_xobject.BoldObject is TUMLObject), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'xobject', M_xobject.BoldObject.ClassName, 'TUMLObject'])); Result := TUMLObject(M_xobject.BoldObject); + assert(not assigned(Result) or (Result is TUMLObject), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'xobject', Result.ClassName, 'TUMLObject'])); end; -procedure TUMLLink._Setxobject(value: TUMLObject); +procedure TUMLLink._Setxobject(const value: TUMLObject); begin M_xobject.BoldObject := value; end; @@ -3817,11 +3801,11 @@ function TUMLLinkEnd._Get_M_instance: TBoldObjectReference; function TUMLLinkEnd._Getinstance: TUMLInstance; begin - assert(not assigned(M_instance.BoldObject) or (M_instance.BoldObject is TUMLInstance), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'instance', M_instance.BoldObject.ClassName, 'TUMLInstance'])); Result := TUMLInstance(M_instance.BoldObject); + assert(not assigned(Result) or (Result is TUMLInstance), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'instance', Result.ClassName, 'TUMLInstance'])); end; -procedure TUMLLinkEnd._Setinstance(value: TUMLInstance); +procedure TUMLLinkEnd._Setinstance(const value: TUMLInstance); begin M_instance.BoldObject := value; end; @@ -3834,11 +3818,11 @@ function TUMLLinkEnd._Get_M_associationEnd: TBoldObjectReference; function TUMLLinkEnd._GetassociationEnd: TUMLAssociationEnd; begin - assert(not assigned(M_associationEnd.BoldObject) or (M_associationEnd.BoldObject is TUMLAssociationEnd), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'associationEnd', M_associationEnd.BoldObject.ClassName, 'TUMLAssociationEnd'])); Result := TUMLAssociationEnd(M_associationEnd.BoldObject); + assert(not assigned(Result) or (Result is TUMLAssociationEnd), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'associationEnd', Result.ClassName, 'TUMLAssociationEnd'])); end; -procedure TUMLLinkEnd._SetassociationEnd(value: TUMLAssociationEnd); +procedure TUMLLinkEnd._SetassociationEnd(const value: TUMLAssociationEnd); begin M_associationEnd.BoldObject := value; end; @@ -3851,11 +3835,11 @@ function TUMLLinkEnd._Get_M_link: TBoldObjectReference; function TUMLLinkEnd._Getlink: TUMLLink; begin - assert(not assigned(M_link.BoldObject) or (M_link.BoldObject is TUMLLink), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'link', M_link.BoldObject.ClassName, 'TUMLLink'])); Result := TUMLLink(M_link.BoldObject); + assert(not assigned(Result) or (Result is TUMLLink), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'link', Result.ClassName, 'TUMLLink'])); end; -procedure TUMLLinkEnd._Setlink(value: TUMLLink); +procedure TUMLLinkEnd._Setlink(const value: TUMLLink); begin M_link.BoldObject := value; end; @@ -3907,11 +3891,11 @@ function TUMLMessage._Get_M_interaction: TBoldObjectReference; function TUMLMessage._Getinteraction: TUMLInteraction; begin - assert(not assigned(M_interaction.BoldObject) or (M_interaction.BoldObject is TUMLInteraction), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'interaction', M_interaction.BoldObject.ClassName, 'TUMLInteraction'])); Result := TUMLInteraction(M_interaction.BoldObject); + assert(not assigned(Result) or (Result is TUMLInteraction), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'interaction', Result.ClassName, 'TUMLInteraction'])); end; -procedure TUMLMessage._Setinteraction(value: TUMLInteraction); +procedure TUMLMessage._Setinteraction(const value: TUMLInteraction); begin M_interaction.BoldObject := value; end; @@ -3924,11 +3908,11 @@ function TUMLMessage._Get_M_communicationConnection: TBoldObjectReference; function TUMLMessage._GetcommunicationConnection: TUMLAssociationRole; begin - assert(not assigned(M_communicationConnection.BoldObject) or (M_communicationConnection.BoldObject is TUMLAssociationRole), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'communicationConnection', M_communicationConnection.BoldObject.ClassName, 'TUMLAssociationRole'])); Result := TUMLAssociationRole(M_communicationConnection.BoldObject); + assert(not assigned(Result) or (Result is TUMLAssociationRole), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'communicationConnection', Result.ClassName, 'TUMLAssociationRole'])); end; -procedure TUMLMessage._SetcommunicationConnection(value: TUMLAssociationRole); +procedure TUMLMessage._SetcommunicationConnection(const value: TUMLAssociationRole); begin M_communicationConnection.BoldObject := value; end; @@ -3941,11 +3925,11 @@ function TUMLMessage._Get_M_action: TBoldObjectReference; function TUMLMessage._Getaction: TUMLAction; begin - assert(not assigned(M_action.BoldObject) or (M_action.BoldObject is TUMLAction), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'action', M_action.BoldObject.ClassName, 'TUMLAction'])); Result := TUMLAction(M_action.BoldObject); + assert(not assigned(Result) or (Result is TUMLAction), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'action', Result.ClassName, 'TUMLAction'])); end; -procedure TUMLMessage._Setaction(value: TUMLAction); +procedure TUMLMessage._Setaction(const value: TUMLAction); begin M_action.BoldObject := value; end; @@ -3988,11 +3972,11 @@ function TUMLMessage._Get_M_activator: TBoldObjectReference; function TUMLMessage._Getactivator: TUMLMessage; begin - assert(not assigned(M_activator.BoldObject) or (M_activator.BoldObject is TUMLMessage), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'activator', M_activator.BoldObject.ClassName, 'TUMLMessage'])); Result := TUMLMessage(M_activator.BoldObject); + assert(not assigned(Result) or (Result is TUMLMessage), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'activator', Result.ClassName, 'TUMLMessage'])); end; -procedure TUMLMessage._Setactivator(value: TUMLMessage); +procedure TUMLMessage._Setactivator(const value: TUMLMessage); begin M_activator.BoldObject := value; end; @@ -4005,11 +3989,11 @@ function TUMLMessage._Get_M_receiver: TBoldObjectReference; function TUMLMessage._Getreceiver: TUMLClassifierRole; begin - assert(not assigned(M_receiver.BoldObject) or (M_receiver.BoldObject is TUMLClassifierRole), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'receiver', M_receiver.BoldObject.ClassName, 'TUMLClassifierRole'])); Result := TUMLClassifierRole(M_receiver.BoldObject); + assert(not assigned(Result) or (Result is TUMLClassifierRole), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'receiver', Result.ClassName, 'TUMLClassifierRole'])); end; -procedure TUMLMessage._Setreceiver(value: TUMLClassifierRole); +procedure TUMLMessage._Setreceiver(const value: TUMLClassifierRole); begin M_receiver.BoldObject := value; end; @@ -4022,11 +4006,11 @@ function TUMLMessage._Get_M_sender: TBoldObjectReference; function TUMLMessage._Getsender: TUMLClassifierRole; begin - assert(not assigned(M_sender.BoldObject) or (M_sender.BoldObject is TUMLClassifierRole), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'sender', M_sender.BoldObject.ClassName, 'TUMLClassifierRole'])); Result := TUMLClassifierRole(M_sender.BoldObject); + assert(not assigned(Result) or (Result is TUMLClassifierRole), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'sender', Result.ClassName, 'TUMLClassifierRole'])); end; -procedure TUMLMessage._Setsender(value: TUMLClassifierRole); +procedure TUMLMessage._Setsender(const value: TUMLClassifierRole); begin M_sender.BoldObject := value; end; @@ -4144,7 +4128,7 @@ function TUMLParameter._GetdefaultValue: String; Result := M_defaultValue.AsString; end; -procedure TUMLParameter._SetdefaultValue(NewValue: String); +procedure TUMLParameter._SetdefaultValue(const NewValue: String); begin M_defaultValue.AsString := NewValue; end; @@ -4160,7 +4144,7 @@ function TUMLParameter._Getkind: TBoldParameterDirectionKind; Result := M_kind.AsParameterDirectionKind; end; -procedure TUMLParameter._Setkind(NewValue: TBoldParameterDirectionKind); +procedure TUMLParameter._Setkind(const NewValue: TBoldParameterDirectionKind); begin M_kind.AsParameterDirectionKind := NewValue; end; @@ -4176,7 +4160,7 @@ function TUMLParameter._GettypeName: String; Result := M_typeName.AsString; end; -procedure TUMLParameter._SettypeName(NewValue: String); +procedure TUMLParameter._SettypeName(const NewValue: String); begin M_typeName.AsString := NewValue; end; @@ -4189,11 +4173,11 @@ function TUMLParameter._Get_M_event: TBoldObjectReference; function TUMLParameter._Getevent: TUMLEvent; begin - assert(not assigned(M_event.BoldObject) or (M_event.BoldObject is TUMLEvent), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'event', M_event.BoldObject.ClassName, 'TUMLEvent'])); Result := TUMLEvent(M_event.BoldObject); + assert(not assigned(Result) or (Result is TUMLEvent), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'event', Result.ClassName, 'TUMLEvent'])); end; -procedure TUMLParameter._Setevent(value: TUMLEvent); +procedure TUMLParameter._Setevent(const value: TUMLEvent); begin M_event.BoldObject := value; end; @@ -4218,11 +4202,11 @@ function TUMLParameter._Get_M_type_: TBoldObjectReference; function TUMLParameter._Gettype_: TUMLClassifier; begin - assert(not assigned(M_type_.BoldObject) or (M_type_.BoldObject is TUMLClassifier), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'type_', M_type_.BoldObject.ClassName, 'TUMLClassifier'])); Result := TUMLClassifier(M_type_.BoldObject); + assert(not assigned(Result) or (Result is TUMLClassifier), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'type_', Result.ClassName, 'TUMLClassifier'])); end; -procedure TUMLParameter._Settype_(value: TUMLClassifier); +procedure TUMLParameter._Settype_(const value: TUMLClassifier); begin M_type_.BoldObject := value; end; @@ -4235,11 +4219,11 @@ function TUMLParameter._Get_M_behavioralFeature: TBoldObjectReference; function TUMLParameter._GetbehavioralFeature: TUMLBehavioralFeature; begin - assert(not assigned(M_behavioralFeature.BoldObject) or (M_behavioralFeature.BoldObject is TUMLBehavioralFeature), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'behavioralFeature', M_behavioralFeature.BoldObject.ClassName, 'TUMLBehavioralFeature'])); Result := TUMLBehavioralFeature(M_behavioralFeature.BoldObject); + assert(not assigned(Result) or (Result is TUMLBehavioralFeature), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'behavioralFeature', Result.ClassName, 'TUMLBehavioralFeature'])); end; -procedure TUMLParameter._SetbehavioralFeature(value: TUMLBehavioralFeature); +procedure TUMLParameter._SetbehavioralFeature(const value: TUMLBehavioralFeature); begin M_behavioralFeature.BoldObject := value; end; @@ -4281,16 +4265,20 @@ procedure TUMLParameterList.SetBoldObject(index: Integer; NewObject: TUMLParamet SetElement(index, NewObject); end; -function TUMLParameter.GetDeriveMethodForMember(Member: TBoldMember): TBoldDeriveAndResubscribe; +function TUMLParameter.GetDeriveMethodForMember(MemberIndex: Integer): TBoldDeriveAndResubscribe; begin - if (Member = M_typeName) then result := _typeName_DeriveAndSubscribe else - result := inherited GetDeriveMethodForMember(Member); + case MemberIndex of + 42: result := _typeName_DeriveAndSubscribe; + else result := inherited GetDeriveMethodForMember(MemberIndex); + end; end; -function TUMLParameter.GetReverseDeriveMethodForMember(Member: TBoldMember): TBoldReverseDerive; +function TUMLParameter.GetReverseDeriveMethodForMember(MemberIndex: Integer): TBoldReverseDerive; begin - result := inherited GetReverseDeriveMethodForMember(Member); - if not assigned(result) and (Member = M_typeName) then result := _typeName_ReverseDerive; + case MemberIndex of + 42: result := _typeName_ReverseDerive; + else result := inherited GetReverseDeriveMethodForMember(MemberIndex); + end; end; { TUMLPartition } @@ -4315,11 +4303,11 @@ function TUMLPartition._Get_M_activityGraph: TBoldObjectReference; function TUMLPartition._GetactivityGraph: TUMLActivityGraph; begin - assert(not assigned(M_activityGraph.BoldObject) or (M_activityGraph.BoldObject is TUMLActivityGraph), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'activityGraph', M_activityGraph.BoldObject.ClassName, 'TUMLActivityGraph'])); Result := TUMLActivityGraph(M_activityGraph.BoldObject); + assert(not assigned(Result) or (Result is TUMLActivityGraph), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'activityGraph', Result.ClassName, 'TUMLActivityGraph'])); end; -procedure TUMLPartition._SetactivityGraph(value: TUMLActivityGraph); +procedure TUMLPartition._SetactivityGraph(const value: TUMLActivityGraph); begin M_activityGraph.BoldObject := value; end; @@ -4422,11 +4410,11 @@ function TUMLStateMachine._Get_M_context: TBoldObjectReference; function TUMLStateMachine._Getcontext: TUMLModelElement; begin - assert(not assigned(M_context.BoldObject) or (M_context.BoldObject is TUMLModelElement), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'context', M_context.BoldObject.ClassName, 'TUMLModelElement'])); Result := TUMLModelElement(M_context.BoldObject); + assert(not assigned(Result) or (Result is TUMLModelElement), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'context', Result.ClassName, 'TUMLModelElement'])); end; -procedure TUMLStateMachine._Setcontext(value: TUMLModelElement); +procedure TUMLStateMachine._Setcontext(const value: TUMLModelElement); begin M_context.BoldObject := value; end; @@ -4439,11 +4427,11 @@ function TUMLStateMachine._Get_M_top: TBoldObjectReference; function TUMLStateMachine._Gettop: TUMLState; begin - assert(not assigned(M_top.BoldObject) or (M_top.BoldObject is TUMLState), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'top', M_top.BoldObject.ClassName, 'TUMLState'])); Result := TUMLState(M_top.BoldObject); + assert(not assigned(Result) or (Result is TUMLState), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'top', Result.ClassName, 'TUMLState'])); end; -procedure TUMLStateMachine._Settop(value: TUMLState); +procedure TUMLStateMachine._Settop(const value: TUMLState); begin M_top.BoldObject := value; end; @@ -4495,11 +4483,11 @@ function TUMLStateVertex._Get_M_container: TBoldObjectReference; function TUMLStateVertex._Getcontainer: TUMLCompositeState; begin - assert(not assigned(M_container.BoldObject) or (M_container.BoldObject is TUMLCompositeState), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'container', M_container.BoldObject.ClassName, 'TUMLCompositeState'])); Result := TUMLCompositeState(M_container.BoldObject); + assert(not assigned(Result) or (Result is TUMLCompositeState), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'container', Result.ClassName, 'TUMLCompositeState'])); end; -procedure TUMLStateVertex._Setcontainer(value: TUMLCompositeState); +procedure TUMLStateVertex._Setcontainer(const value: TUMLCompositeState); begin M_container.BoldObject := value; end; @@ -4575,11 +4563,11 @@ function TUMLStimulus._Get_M_dispatchAction: TBoldObjectReference; function TUMLStimulus._GetdispatchAction: TUMLAction; begin - assert(not assigned(M_dispatchAction.BoldObject) or (M_dispatchAction.BoldObject is TUMLAction), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'dispatchAction', M_dispatchAction.BoldObject.ClassName, 'TUMLAction'])); Result := TUMLAction(M_dispatchAction.BoldObject); + assert(not assigned(Result) or (Result is TUMLAction), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'dispatchAction', Result.ClassName, 'TUMLAction'])); end; -procedure TUMLStimulus._SetdispatchAction(value: TUMLAction); +procedure TUMLStimulus._SetdispatchAction(const value: TUMLAction); begin M_dispatchAction.BoldObject := value; end; @@ -4592,11 +4580,11 @@ function TUMLStimulus._Get_M_communicationLink: TBoldObjectReference; function TUMLStimulus._GetcommunicationLink: TUMLLink; begin - assert(not assigned(M_communicationLink.BoldObject) or (M_communicationLink.BoldObject is TUMLLink), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'communicationLink', M_communicationLink.BoldObject.ClassName, 'TUMLLink'])); Result := TUMLLink(M_communicationLink.BoldObject); + assert(not assigned(Result) or (Result is TUMLLink), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'communicationLink', Result.ClassName, 'TUMLLink'])); end; -procedure TUMLStimulus._SetcommunicationLink(value: TUMLLink); +procedure TUMLStimulus._SetcommunicationLink(const value: TUMLLink); begin M_communicationLink.BoldObject := value; end; @@ -4609,11 +4597,11 @@ function TUMLStimulus._Get_M_receiver: TBoldObjectReference; function TUMLStimulus._Getreceiver: TUMLInstance; begin - assert(not assigned(M_receiver.BoldObject) or (M_receiver.BoldObject is TUMLInstance), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'receiver', M_receiver.BoldObject.ClassName, 'TUMLInstance'])); Result := TUMLInstance(M_receiver.BoldObject); + assert(not assigned(Result) or (Result is TUMLInstance), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'receiver', Result.ClassName, 'TUMLInstance'])); end; -procedure TUMLStimulus._Setreceiver(value: TUMLInstance); +procedure TUMLStimulus._Setreceiver(const value: TUMLInstance); begin M_receiver.BoldObject := value; end; @@ -4626,11 +4614,11 @@ function TUMLStimulus._Get_M_sender: TBoldObjectReference; function TUMLStimulus._Getsender: TUMLInstance; begin - assert(not assigned(M_sender.BoldObject) or (M_sender.BoldObject is TUMLInstance), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'sender', M_sender.BoldObject.ClassName, 'TUMLInstance'])); Result := TUMLInstance(M_sender.BoldObject); + assert(not assigned(Result) or (Result is TUMLInstance), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'sender', Result.ClassName, 'TUMLInstance'])); end; -procedure TUMLStimulus._Setsender(value: TUMLInstance); +procedure TUMLStimulus._Setsender(const value: TUMLInstance); begin M_sender.BoldObject := value; end; @@ -4685,7 +4673,7 @@ function TUMLTaggedValue._Gettag: String; Result := M_tag.AsString; end; -procedure TUMLTaggedValue._Settag(NewValue: String); +procedure TUMLTaggedValue._Settag(const NewValue: String); begin M_tag.AsString := NewValue; end; @@ -4701,7 +4689,7 @@ function TUMLTaggedValue._Getvalue: String; Result := M_value.AsString; end; -procedure TUMLTaggedValue._Setvalue(NewValue: String); +procedure TUMLTaggedValue._Setvalue(const NewValue: String); begin M_value.AsString := NewValue; end; @@ -4714,11 +4702,11 @@ function TUMLTaggedValue._Get_M_modelElement: TBoldObjectReference; function TUMLTaggedValue._GetmodelElement: TUMLModelElement; begin - assert(not assigned(M_modelElement.BoldObject) or (M_modelElement.BoldObject is TUMLModelElement), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'modelElement', M_modelElement.BoldObject.ClassName, 'TUMLModelElement'])); Result := TUMLModelElement(M_modelElement.BoldObject); + assert(not assigned(Result) or (Result is TUMLModelElement), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'modelElement', Result.ClassName, 'TUMLModelElement'])); end; -procedure TUMLTaggedValue._SetmodelElement(value: TUMLModelElement); +procedure TUMLTaggedValue._SetmodelElement(const value: TUMLModelElement); begin M_modelElement.BoldObject := value; end; @@ -4731,11 +4719,11 @@ function TUMLTaggedValue._Get_M_stereotype_: TBoldObjectReference; function TUMLTaggedValue._Getstereotype_: TUMLStereotype; begin - assert(not assigned(M_stereotype_.BoldObject) or (M_stereotype_.BoldObject is TUMLStereotype), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'stereotype_', M_stereotype_.BoldObject.ClassName, 'TUMLStereotype'])); Result := TUMLStereotype(M_stereotype_.BoldObject); + assert(not assigned(Result) or (Result is TUMLStereotype), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'stereotype_', Result.ClassName, 'TUMLStereotype'])); end; -procedure TUMLTaggedValue._Setstereotype_(value: TUMLStereotype); +procedure TUMLTaggedValue._Setstereotype_(const value: TUMLStereotype); begin M_stereotype_.BoldObject := value; end; @@ -4787,11 +4775,11 @@ function TUMLTransition._Get_M_State: TBoldObjectReference; function TUMLTransition._GetState: TUMLState; begin - assert(not assigned(M_State.BoldObject) or (M_State.BoldObject is TUMLState), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'State', M_State.BoldObject.ClassName, 'TUMLState'])); Result := TUMLState(M_State.BoldObject); + assert(not assigned(Result) or (Result is TUMLState), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'State', Result.ClassName, 'TUMLState'])); end; -procedure TUMLTransition._SetState(value: TUMLState); +procedure TUMLTransition._SetState(const value: TUMLState); begin M_State.BoldObject := value; end; @@ -4804,11 +4792,11 @@ function TUMLTransition._Get_M_trigger: TBoldObjectReference; function TUMLTransition._Gettrigger: TUMLEvent; begin - assert(not assigned(M_trigger.BoldObject) or (M_trigger.BoldObject is TUMLEvent), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'trigger', M_trigger.BoldObject.ClassName, 'TUMLEvent'])); Result := TUMLEvent(M_trigger.BoldObject); + assert(not assigned(Result) or (Result is TUMLEvent), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'trigger', Result.ClassName, 'TUMLEvent'])); end; -procedure TUMLTransition._Settrigger(value: TUMLEvent); +procedure TUMLTransition._Settrigger(const value: TUMLEvent); begin M_trigger.BoldObject := value; end; @@ -4821,11 +4809,11 @@ function TUMLTransition._Get_M_effect: TBoldObjectReference; function TUMLTransition._Geteffect: TUMLAction; begin - assert(not assigned(M_effect.BoldObject) or (M_effect.BoldObject is TUMLAction), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'effect', M_effect.BoldObject.ClassName, 'TUMLAction'])); Result := TUMLAction(M_effect.BoldObject); + assert(not assigned(Result) or (Result is TUMLAction), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'effect', Result.ClassName, 'TUMLAction'])); end; -procedure TUMLTransition._Seteffect(value: TUMLAction); +procedure TUMLTransition._Seteffect(const value: TUMLAction); begin M_effect.BoldObject := value; end; @@ -4838,11 +4826,11 @@ function TUMLTransition._Get_M_stateMachine: TBoldObjectReference; function TUMLTransition._GetstateMachine: TUMLStateMachine; begin - assert(not assigned(M_stateMachine.BoldObject) or (M_stateMachine.BoldObject is TUMLStateMachine), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'stateMachine', M_stateMachine.BoldObject.ClassName, 'TUMLStateMachine'])); Result := TUMLStateMachine(M_stateMachine.BoldObject); + assert(not assigned(Result) or (Result is TUMLStateMachine), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'stateMachine', Result.ClassName, 'TUMLStateMachine'])); end; -procedure TUMLTransition._SetstateMachine(value: TUMLStateMachine); +procedure TUMLTransition._SetstateMachine(const value: TUMLStateMachine); begin M_stateMachine.BoldObject := value; end; @@ -4855,11 +4843,11 @@ function TUMLTransition._Get_M_source: TBoldObjectReference; function TUMLTransition._Getsource: TUMLStateVertex; begin - assert(not assigned(M_source.BoldObject) or (M_source.BoldObject is TUMLStateVertex), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'source', M_source.BoldObject.ClassName, 'TUMLStateVertex'])); Result := TUMLStateVertex(M_source.BoldObject); + assert(not assigned(Result) or (Result is TUMLStateVertex), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'source', Result.ClassName, 'TUMLStateVertex'])); end; -procedure TUMLTransition._Setsource(value: TUMLStateVertex); +procedure TUMLTransition._Setsource(const value: TUMLStateVertex); begin M_source.BoldObject := value; end; @@ -4872,11 +4860,11 @@ function TUMLTransition._Get_M_target: TBoldObjectReference; function TUMLTransition._Gettarget: TUMLStateVertex; begin - assert(not assigned(M_target.BoldObject) or (M_target.BoldObject is TUMLStateVertex), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'target', M_target.BoldObject.ClassName, 'TUMLStateVertex'])); Result := TUMLStateVertex(M_target.BoldObject); + assert(not assigned(Result) or (Result is TUMLStateVertex), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'target', Result.ClassName, 'TUMLStateVertex'])); end; -procedure TUMLTransition._Settarget(value: TUMLStateVertex); +procedure TUMLTransition._Settarget(const value: TUMLStateVertex); begin M_target.BoldObject := value; end; @@ -4889,11 +4877,11 @@ function TUMLTransition._Get_M_guard: TBoldObjectReference; function TUMLTransition._Getguard: TUMLGuard; begin - assert(not assigned(M_guard.BoldObject) or (M_guard.BoldObject is TUMLGuard), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'guard', M_guard.BoldObject.ClassName, 'TUMLGuard'])); Result := TUMLGuard(M_guard.BoldObject); + assert(not assigned(Result) or (Result is TUMLGuard), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'guard', Result.ClassName, 'TUMLGuard'])); end; -procedure TUMLTransition._Setguard(value: TUMLGuard); +procedure TUMLTransition._Setguard(const value: TUMLGuard); begin M_guard.BoldObject := value; end; @@ -4990,11 +4978,11 @@ function TUMLCallAction._Get_M_operation: TBoldObjectReference; function TUMLCallAction._Getoperation: TUMLOperation; begin - assert(not assigned(M_operation.BoldObject) or (M_operation.BoldObject is TUMLOperation), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'operation', M_operation.BoldObject.ClassName, 'TUMLOperation'])); Result := TUMLOperation(M_operation.BoldObject); + assert(not assigned(Result) or (Result is TUMLOperation), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'operation', Result.ClassName, 'TUMLOperation'])); end; -procedure TUMLCallAction._Setoperation(value: TUMLOperation); +procedure TUMLCallAction._Setoperation(const value: TUMLOperation); begin M_operation.BoldObject := value; end; @@ -5046,11 +5034,11 @@ function TUMLCreateAction._Get_M_instantiation: TBoldObjectReference; function TUMLCreateAction._Getinstantiation: TUMLClassifier; begin - assert(not assigned(M_instantiation.BoldObject) or (M_instantiation.BoldObject is TUMLClassifier), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'instantiation', M_instantiation.BoldObject.ClassName, 'TUMLClassifier'])); Result := TUMLClassifier(M_instantiation.BoldObject); + assert(not assigned(Result) or (Result is TUMLClassifier), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'instantiation', Result.ClassName, 'TUMLClassifier'])); end; -procedure TUMLCreateAction._Setinstantiation(value: TUMLClassifier); +procedure TUMLCreateAction._Setinstantiation(const value: TUMLClassifier); begin M_instantiation.BoldObject := value; end; @@ -5180,11 +5168,11 @@ function TUMLSendAction._Get_M_signal: TBoldObjectReference; function TUMLSendAction._Getsignal: TUMLSignal; begin - assert(not assigned(M_signal.BoldObject) or (M_signal.BoldObject is TUMLSignal), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'signal', M_signal.BoldObject.ClassName, 'TUMLSignal'])); Result := TUMLSignal(M_signal.BoldObject); + assert(not assigned(Result) or (Result is TUMLSignal), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'signal', Result.ClassName, 'TUMLSignal'])); end; -procedure TUMLSendAction._Setsignal(value: TUMLSignal); +procedure TUMLSendAction._Setsignal(const value: TUMLSignal); begin M_signal.BoldObject := value; end; @@ -5317,7 +5305,7 @@ function TUMLAssociationEndRole._GetcollaborationMultiplicity: String; Result := M_collaborationMultiplicity.AsString; end; -procedure TUMLAssociationEndRole._SetcollaborationMultiplicity(NewValue: String); +procedure TUMLAssociationEndRole._SetcollaborationMultiplicity(const NewValue: String); begin M_collaborationMultiplicity.AsString := NewValue; end; @@ -5330,11 +5318,11 @@ function TUMLAssociationEndRole._Get_M_base: TBoldObjectReference; function TUMLAssociationEndRole._Getbase: TUMLAssociationEnd; begin - assert(not assigned(M_base.BoldObject) or (M_base.BoldObject is TUMLAssociationEnd), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'base', M_base.BoldObject.ClassName, 'TUMLAssociationEnd'])); Result := TUMLAssociationEnd(M_base.BoldObject); + assert(not assigned(Result) or (Result is TUMLAssociationEnd), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'base', Result.ClassName, 'TUMLAssociationEnd'])); end; -procedure TUMLAssociationEndRole._Setbase(value: TUMLAssociationEnd); +procedure TUMLAssociationEndRole._Setbase(const value: TUMLAssociationEnd); begin M_base.BoldObject := value; end; @@ -5398,11 +5386,11 @@ function TUMLCallEvent._Get_M_operation: TBoldObjectReference; function TUMLCallEvent._Getoperation: TUMLOperation; begin - assert(not assigned(M_operation.BoldObject) or (M_operation.BoldObject is TUMLOperation), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'operation', M_operation.BoldObject.ClassName, 'TUMLOperation'])); Result := TUMLOperation(M_operation.BoldObject); + assert(not assigned(Result) or (Result is TUMLOperation), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'operation', Result.ClassName, 'TUMLOperation'])); end; -procedure TUMLCallEvent._Setoperation(value: TUMLOperation); +procedure TUMLCallEvent._Setoperation(const value: TUMLOperation); begin M_operation.BoldObject := value; end; @@ -5457,7 +5445,7 @@ function TUMLChangeEvent._GetchangeExpression: String; Result := M_changeExpression.AsString; end; -procedure TUMLChangeEvent._SetchangeExpression(NewValue: String); +procedure TUMLChangeEvent._SetchangeExpression(const NewValue: String); begin M_changeExpression.AsString := NewValue; end; @@ -5509,11 +5497,11 @@ function TUMLSignalEvent._Get_M_signal: TBoldObjectReference; function TUMLSignalEvent._Getsignal: TUMLSignal; begin - assert(not assigned(M_signal.BoldObject) or (M_signal.BoldObject is TUMLSignal), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'signal', M_signal.BoldObject.ClassName, 'TUMLSignal'])); Result := TUMLSignal(M_signal.BoldObject); + assert(not assigned(Result) or (Result is TUMLSignal), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'signal', Result.ClassName, 'TUMLSignal'])); end; -procedure TUMLSignalEvent._Setsignal(value: TUMLSignal); +procedure TUMLSignalEvent._Setsignal(const value: TUMLSignal); begin M_signal.BoldObject := value; end; @@ -5568,7 +5556,7 @@ function TUMLTimeEvent._Getwhen: String; Result := M_when.AsString; end; -procedure TUMLTimeEvent._Setwhen(NewValue: String); +procedure TUMLTimeEvent._Setwhen(const NewValue: String); begin M_when.AsString := NewValue; end; @@ -5623,7 +5611,7 @@ function TUMLBehavioralFeature._GetisQuery: boolean; Result := M_isQuery.AsBoolean; end; -procedure TUMLBehavioralFeature._SetisQuery(NewValue: boolean); +procedure TUMLBehavioralFeature._SetisQuery(const NewValue: boolean); begin M_isQuery.AsBoolean := NewValue; end; @@ -5696,7 +5684,7 @@ function TUMLStructuralFeature._Getmultiplicity: String; Result := M_multiplicity.AsString; end; -procedure TUMLStructuralFeature._Setmultiplicity(NewValue: String); +procedure TUMLStructuralFeature._Setmultiplicity(const NewValue: String); begin M_multiplicity.AsString := NewValue; end; @@ -5712,7 +5700,7 @@ function TUMLStructuralFeature._Getchangeability: TChangeableKind; Result := M_changeability.AsChangeableKind; end; -procedure TUMLStructuralFeature._Setchangeability(NewValue: TChangeableKind); +procedure TUMLStructuralFeature._Setchangeability(const NewValue: TChangeableKind); begin M_changeability.AsChangeableKind := NewValue; end; @@ -5728,7 +5716,7 @@ function TUMLStructuralFeature._GettargetScope: TScopeKind; Result := M_targetScope.AsScopeKind; end; -procedure TUMLStructuralFeature._SettargetScope(NewValue: TScopeKind); +procedure TUMLStructuralFeature._SettargetScope(const NewValue: TScopeKind); begin M_targetScope.AsScopeKind := NewValue; end; @@ -5744,7 +5732,7 @@ function TUMLStructuralFeature._GettypeName: String; Result := M_typeName.AsString; end; -procedure TUMLStructuralFeature._SettypeName(NewValue: String); +procedure TUMLStructuralFeature._SettypeName(const NewValue: String); begin M_typeName.AsString := NewValue; end; @@ -5757,11 +5745,11 @@ function TUMLStructuralFeature._Get_M_type_: TBoldObjectReference; function TUMLStructuralFeature._Gettype_: TUMLClassifier; begin - assert(not assigned(M_type_.BoldObject) or (M_type_.BoldObject is TUMLClassifier), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'type_', M_type_.BoldObject.ClassName, 'TUMLClassifier'])); Result := TUMLClassifier(M_type_.BoldObject); + assert(not assigned(Result) or (Result is TUMLClassifier), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'type_', Result.ClassName, 'TUMLClassifier'])); end; -procedure TUMLStructuralFeature._Settype_(value: TUMLClassifier); +procedure TUMLStructuralFeature._Settype_(const value: TUMLClassifier); begin M_type_.BoldObject := value; end; @@ -5803,16 +5791,20 @@ procedure TUMLStructuralFeatureList.SetBoldObject(index: Integer; NewObject: TUM SetElement(index, NewObject); end; -function TUMLStructuralFeature.GetDeriveMethodForMember(Member: TBoldMember): TBoldDeriveAndResubscribe; +function TUMLStructuralFeature.GetDeriveMethodForMember(MemberIndex: Integer): TBoldDeriveAndResubscribe; begin - if (Member = M_typeName) then result := _typeName_DeriveAndSubscribe else - result := inherited GetDeriveMethodForMember(Member); + case MemberIndex of + 47: result := _typeName_DeriveAndSubscribe; + else result := inherited GetDeriveMethodForMember(MemberIndex); + end; end; -function TUMLStructuralFeature.GetReverseDeriveMethodForMember(Member: TBoldMember): TBoldReverseDerive; +function TUMLStructuralFeature.GetReverseDeriveMethodForMember(MemberIndex: Integer): TBoldReverseDerive; begin - result := inherited GetReverseDeriveMethodForMember(Member); - if not assigned(result) and (Member = M_typeName) then result := _typeName_ReverseDerive; + case MemberIndex of + 47: result := _typeName_ReverseDerive; + else result := inherited GetReverseDeriveMethodForMember(MemberIndex); + end; end; { TUMLComponentInstance } @@ -5831,11 +5823,11 @@ function TUMLComponentInstance._Get_M_nodeInstance: TBoldObjectReference; function TUMLComponentInstance._GetnodeInstance: TUMLNodeInstance; begin - assert(not assigned(M_nodeInstance.BoldObject) or (M_nodeInstance.BoldObject is TUMLNodeInstance), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'nodeInstance', M_nodeInstance.BoldObject.ClassName, 'TUMLNodeInstance'])); Result := TUMLNodeInstance(M_nodeInstance.BoldObject); + assert(not assigned(Result) or (Result is TUMLNodeInstance), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'nodeInstance', Result.ClassName, 'TUMLNodeInstance'])); end; -procedure TUMLComponentInstance._SetnodeInstance(value: TUMLNodeInstance); +procedure TUMLComponentInstance._SetnodeInstance(const value: TUMLNodeInstance); begin M_nodeInstance.BoldObject := value; end; @@ -5971,11 +5963,11 @@ function TUMLObject._Get_M_link: TBoldObjectReference; function TUMLObject._Getlink: TUMLLink; begin - assert(not assigned(M_link.BoldObject) or (M_link.BoldObject is TUMLLink), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'link', M_link.BoldObject.ClassName, 'TUMLLink'])); Result := TUMLLink(M_link.BoldObject); + assert(not assigned(Result) or (Result is TUMLLink), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'link', Result.ClassName, 'TUMLLink'])); end; -procedure TUMLObject._Setlink(value: TUMLLink); +procedure TUMLObject._Setlink(const value: TUMLLink); begin M_link.BoldObject := value; end; @@ -6069,7 +6061,7 @@ function TUMLGeneralizableElement._GetisRoot: boolean; Result := M_isRoot.AsBoolean; end; -procedure TUMLGeneralizableElement._SetisRoot(NewValue: boolean); +procedure TUMLGeneralizableElement._SetisRoot(const NewValue: boolean); begin M_isRoot.AsBoolean := NewValue; end; @@ -6085,7 +6077,7 @@ function TUMLGeneralizableElement._GetisLeaf: boolean; Result := M_isLeaf.AsBoolean; end; -procedure TUMLGeneralizableElement._SetisLeaf(NewValue: boolean); +procedure TUMLGeneralizableElement._SetisLeaf(const NewValue: boolean); begin M_isLeaf.AsBoolean := NewValue; end; @@ -6101,7 +6093,7 @@ function TUMLGeneralizableElement._GetisAbstract: boolean; Result := M_isAbstract.AsBoolean; end; -procedure TUMLGeneralizableElement._SetisAbstract(NewValue: boolean); +procedure TUMLGeneralizableElement._SetisAbstract(const NewValue: boolean); begin M_isAbstract.AsBoolean := NewValue; end; @@ -6231,7 +6223,7 @@ function TUMLExtend._Getcondition: String; Result := M_condition.AsString; end; -procedure TUMLExtend._Setcondition(NewValue: String); +procedure TUMLExtend._Setcondition(const NewValue: String); begin M_condition.AsString := NewValue; end; @@ -6256,11 +6248,11 @@ function TUMLExtend._Get_M_base: TBoldObjectReference; function TUMLExtend._Getbase: TUMLUseCase; begin - assert(not assigned(M_base.BoldObject) or (M_base.BoldObject is TUMLUseCase), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'base', M_base.BoldObject.ClassName, 'TUMLUseCase'])); Result := TUMLUseCase(M_base.BoldObject); + assert(not assigned(Result) or (Result is TUMLUseCase), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'base', Result.ClassName, 'TUMLUseCase'])); end; -procedure TUMLExtend._Setbase(value: TUMLUseCase); +procedure TUMLExtend._Setbase(const value: TUMLUseCase); begin M_base.BoldObject := value; end; @@ -6273,11 +6265,11 @@ function TUMLExtend._Get_M_extension: TBoldObjectReference; function TUMLExtend._Getextension: TUMLUseCase; begin - assert(not assigned(M_extension.BoldObject) or (M_extension.BoldObject is TUMLUseCase), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'extension', M_extension.BoldObject.ClassName, 'TUMLUseCase'])); Result := TUMLUseCase(M_extension.BoldObject); + assert(not assigned(Result) or (Result is TUMLUseCase), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'extension', Result.ClassName, 'TUMLUseCase'])); end; -procedure TUMLExtend._Setextension(value: TUMLUseCase); +procedure TUMLExtend._Setextension(const value: TUMLUseCase); begin M_extension.BoldObject := value; end; @@ -6395,7 +6387,7 @@ function TUMLGeneralization._Getdiscriminator: String; Result := M_discriminator.AsString; end; -procedure TUMLGeneralization._Setdiscriminator(NewValue: String); +procedure TUMLGeneralization._Setdiscriminator(const NewValue: String); begin M_discriminator.AsString := NewValue; end; @@ -6408,11 +6400,11 @@ function TUMLGeneralization._Get_M_parent: TBoldObjectReference; function TUMLGeneralization._Getparent: TUMLGeneralizableElement; begin - assert(not assigned(M_parent.BoldObject) or (M_parent.BoldObject is TUMLGeneralizableElement), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'parent', M_parent.BoldObject.ClassName, 'TUMLGeneralizableElement'])); Result := TUMLGeneralizableElement(M_parent.BoldObject); + assert(not assigned(Result) or (Result is TUMLGeneralizableElement), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'parent', Result.ClassName, 'TUMLGeneralizableElement'])); end; -procedure TUMLGeneralization._Setparent(value: TUMLGeneralizableElement); +procedure TUMLGeneralization._Setparent(const value: TUMLGeneralizableElement); begin M_parent.BoldObject := value; end; @@ -6425,11 +6417,11 @@ function TUMLGeneralization._Get_M_child: TBoldObjectReference; function TUMLGeneralization._Getchild: TUMLGeneralizableElement; begin - assert(not assigned(M_child.BoldObject) or (M_child.BoldObject is TUMLGeneralizableElement), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'child', M_child.BoldObject.ClassName, 'TUMLGeneralizableElement'])); Result := TUMLGeneralizableElement(M_child.BoldObject); + assert(not assigned(Result) or (Result is TUMLGeneralizableElement), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'child', Result.ClassName, 'TUMLGeneralizableElement'])); end; -procedure TUMLGeneralization._Setchild(value: TUMLGeneralizableElement); +procedure TUMLGeneralization._Setchild(const value: TUMLGeneralizableElement); begin M_child.BoldObject := value; end; @@ -6442,11 +6434,11 @@ function TUMLGeneralization._Get_M_powertype: TBoldObjectReference; function TUMLGeneralization._Getpowertype: TUMLClassifier; begin - assert(not assigned(M_powertype.BoldObject) or (M_powertype.BoldObject is TUMLClassifier), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'powertype', M_powertype.BoldObject.ClassName, 'TUMLClassifier'])); Result := TUMLClassifier(M_powertype.BoldObject); + assert(not assigned(Result) or (Result is TUMLClassifier), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'powertype', Result.ClassName, 'TUMLClassifier'])); end; -procedure TUMLGeneralization._Setpowertype(value: TUMLClassifier); +procedure TUMLGeneralization._Setpowertype(const value: TUMLClassifier); begin M_powertype.BoldObject := value; end; @@ -6498,11 +6490,11 @@ function TUMLInclude._Get_M_base: TBoldObjectReference; function TUMLInclude._Getbase: TUMLUseCase; begin - assert(not assigned(M_base.BoldObject) or (M_base.BoldObject is TUMLUseCase), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'base', M_base.BoldObject.ClassName, 'TUMLUseCase'])); Result := TUMLUseCase(M_base.BoldObject); + assert(not assigned(Result) or (Result is TUMLUseCase), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'base', Result.ClassName, 'TUMLUseCase'])); end; -procedure TUMLInclude._Setbase(value: TUMLUseCase); +procedure TUMLInclude._Setbase(const value: TUMLUseCase); begin M_base.BoldObject := value; end; @@ -6515,11 +6507,11 @@ function TUMLInclude._Get_M_addition: TBoldObjectReference; function TUMLInclude._Getaddition: TUMLUseCase; begin - assert(not assigned(M_addition.BoldObject) or (M_addition.BoldObject is TUMLUseCase), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'addition', M_addition.BoldObject.ClassName, 'TUMLUseCase'])); Result := TUMLUseCase(M_addition.BoldObject); + assert(not assigned(Result) or (Result is TUMLUseCase), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'addition', Result.ClassName, 'TUMLUseCase'])); end; -procedure TUMLInclude._Setaddition(value: TUMLUseCase); +procedure TUMLInclude._Setaddition(const value: TUMLUseCase); begin M_addition.BoldObject := value; end; @@ -6619,7 +6611,7 @@ function TUMLPseudostate._Getkind: TPseudostateKind; Result := M_kind.asPseudostateKind; end; -procedure TUMLPseudostate._Setkind(NewValue: TPseudostateKind); +procedure TUMLPseudostate._Setkind(const NewValue: TPseudostateKind); begin M_kind.asPseudostateKind := NewValue; end; @@ -6671,11 +6663,11 @@ function TUMLState._Get_M_entry: TBoldObjectReference; function TUMLState._Getentry: TUMLAction; begin - assert(not assigned(M_entry.BoldObject) or (M_entry.BoldObject is TUMLAction), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'entry', M_entry.BoldObject.ClassName, 'TUMLAction'])); Result := TUMLAction(M_entry.BoldObject); + assert(not assigned(Result) or (Result is TUMLAction), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'entry', Result.ClassName, 'TUMLAction'])); end; -procedure TUMLState._Setentry(value: TUMLAction); +procedure TUMLState._Setentry(const value: TUMLAction); begin M_entry.BoldObject := value; end; @@ -6694,11 +6686,11 @@ function TUMLState._Get_M_doActivity: TBoldObjectReference; function TUMLState._GetdoActivity: TUMLAction; begin - assert(not assigned(M_doActivity.BoldObject) or (M_doActivity.BoldObject is TUMLAction), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'doActivity', M_doActivity.BoldObject.ClassName, 'TUMLAction'])); Result := TUMLAction(M_doActivity.BoldObject); + assert(not assigned(Result) or (Result is TUMLAction), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'doActivity', Result.ClassName, 'TUMLAction'])); end; -procedure TUMLState._SetdoActivity(value: TUMLAction); +procedure TUMLState._SetdoActivity(const value: TUMLAction); begin M_doActivity.BoldObject := value; end; @@ -6711,11 +6703,11 @@ function TUMLState._Get_M_exit: TBoldObjectReference; function TUMLState._Getexit: TUMLAction; begin - assert(not assigned(M_exit.BoldObject) or (M_exit.BoldObject is TUMLAction), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'exit', M_exit.BoldObject.ClassName, 'TUMLAction'])); Result := TUMLAction(M_exit.BoldObject); + assert(not assigned(Result) or (Result is TUMLAction), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'exit', Result.ClassName, 'TUMLAction'])); end; -procedure TUMLState._Setexit(value: TUMLAction); +procedure TUMLState._Setexit(const value: TUMLAction); begin M_exit.BoldObject := value; end; @@ -6740,11 +6732,11 @@ function TUMLState._Get_M_stateMachine: TBoldObjectReference; function TUMLState._GetstateMachine: TUMLStateMachine; begin - assert(not assigned(M_stateMachine.BoldObject) or (M_stateMachine.BoldObject is TUMLStateMachine), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'stateMachine', M_stateMachine.BoldObject.ClassName, 'TUMLStateMachine'])); Result := TUMLStateMachine(M_stateMachine.BoldObject); + assert(not assigned(Result) or (Result is TUMLStateMachine), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'stateMachine', Result.ClassName, 'TUMLStateMachine'])); end; -procedure TUMLState._SetstateMachine(value: TUMLStateMachine); +procedure TUMLState._SetstateMachine(const value: TUMLStateMachine); begin M_stateMachine.BoldObject := value; end; @@ -6811,7 +6803,7 @@ function TUMLStubState._GetreferenceState: String; Result := M_referenceState.AsString; end; -procedure TUMLStubState._SetreferenceState(NewValue: String); +procedure TUMLStubState._SetreferenceState(const NewValue: String); begin M_referenceState.AsString := NewValue; end; @@ -6866,7 +6858,7 @@ function TUMLSynchState._Getbound: String; Result := M_bound.AsString; end; -procedure TUMLSynchState._Setbound(NewValue: String); +procedure TUMLSynchState._Setbound(const NewValue: String); begin M_bound.AsString := NewValue; end; @@ -6921,7 +6913,7 @@ function TUMLMethod._Getbody: String; Result := M_body.AsString; end; -procedure TUMLMethod._Setbody(NewValue: String); +procedure TUMLMethod._Setbody(const NewValue: String); begin M_body.AsString := NewValue; end; @@ -6934,11 +6926,11 @@ function TUMLMethod._Get_M_specification: TBoldObjectReference; function TUMLMethod._Getspecification: TUMLOperation; begin - assert(not assigned(M_specification.BoldObject) or (M_specification.BoldObject is TUMLOperation), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'specification', M_specification.BoldObject.ClassName, 'TUMLOperation'])); Result := TUMLOperation(M_specification.BoldObject); + assert(not assigned(Result) or (Result is TUMLOperation), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'specification', Result.ClassName, 'TUMLOperation'])); end; -procedure TUMLMethod._Setspecification(value: TUMLOperation); +procedure TUMLMethod._Setspecification(const value: TUMLOperation); begin M_specification.BoldObject := value; end; @@ -6993,7 +6985,7 @@ function TUMLOperation._Getconcurrency: TCallConcurrencyKind; Result := M_concurrency.asCallConcurrencyKind; end; -procedure TUMLOperation._Setconcurrency(NewValue: TCallConcurrencyKind); +procedure TUMLOperation._Setconcurrency(const NewValue: TCallConcurrencyKind); begin M_concurrency.asCallConcurrencyKind := NewValue; end; @@ -7009,7 +7001,7 @@ function TUMLOperation._GetisRoot: boolean; Result := M_isRoot.AsBoolean; end; -procedure TUMLOperation._SetisRoot(NewValue: boolean); +procedure TUMLOperation._SetisRoot(const NewValue: boolean); begin M_isRoot.AsBoolean := NewValue; end; @@ -7025,7 +7017,7 @@ function TUMLOperation._GetisLeaf: boolean; Result := M_isLeaf.AsBoolean; end; -procedure TUMLOperation._SetisLeaf(NewValue: boolean); +procedure TUMLOperation._SetisLeaf(const NewValue: boolean); begin M_isLeaf.AsBoolean := NewValue; end; @@ -7041,7 +7033,7 @@ function TUMLOperation._GetisAbstract: boolean; Result := M_isAbstract.AsBoolean; end; -procedure TUMLOperation._SetisAbstract(NewValue: boolean); +procedure TUMLOperation._SetisAbstract(const NewValue: boolean); begin M_isAbstract.AsBoolean := NewValue; end; @@ -7057,7 +7049,7 @@ function TUMLOperation._Getspecification: String; Result := M_specification.AsString; end; -procedure TUMLOperation._Setspecification(NewValue: String); +procedure TUMLOperation._Setspecification(const NewValue: String); begin M_specification.AsString := NewValue; end; @@ -7136,7 +7128,7 @@ function TUMLReception._Getspecification: String; Result := M_specification.AsString; end; -procedure TUMLReception._Setspecification(NewValue: String); +procedure TUMLReception._Setspecification(const NewValue: String); begin M_specification.AsString := NewValue; end; @@ -7152,7 +7144,7 @@ function TUMLReception._GetisRoot: boolean; Result := M_isRoot.AsBoolean; end; -procedure TUMLReception._SetisRoot(NewValue: boolean); +procedure TUMLReception._SetisRoot(const NewValue: boolean); begin M_isRoot.AsBoolean := NewValue; end; @@ -7168,7 +7160,7 @@ function TUMLReception._GetisLeaf: boolean; Result := M_isLeaf.AsBoolean; end; -procedure TUMLReception._SetisLeaf(NewValue: boolean); +procedure TUMLReception._SetisLeaf(const NewValue: boolean); begin M_isLeaf.AsBoolean := NewValue; end; @@ -7184,7 +7176,7 @@ function TUMLReception._GetisAbstract: boolean; Result := M_isAbstract.AsBoolean; end; -procedure TUMLReception._SetisAbstract(NewValue: boolean); +procedure TUMLReception._SetisAbstract(const NewValue: boolean); begin M_isAbstract.AsBoolean := NewValue; end; @@ -7197,11 +7189,11 @@ function TUMLReception._Get_M_signal: TBoldObjectReference; function TUMLReception._Getsignal: TUMLSignal; begin - assert(not assigned(M_signal.BoldObject) or (M_signal.BoldObject is TUMLSignal), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'signal', M_signal.BoldObject.ClassName, 'TUMLSignal'])); Result := TUMLSignal(M_signal.BoldObject); + assert(not assigned(Result) or (Result is TUMLSignal), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'signal', Result.ClassName, 'TUMLSignal'])); end; -procedure TUMLReception._Setsignal(value: TUMLSignal); +procedure TUMLReception._Setsignal(const value: TUMLSignal); begin M_signal.BoldObject := value; end; @@ -7256,7 +7248,7 @@ function TUMLAttribute._GetinitialValue: String; Result := M_initialValue.AsString; end; -procedure TUMLAttribute._SetinitialValue(NewValue: String); +procedure TUMLAttribute._SetinitialValue(const NewValue: String); begin M_initialValue.AsString := NewValue; end; @@ -7272,7 +7264,7 @@ function TUMLAttribute._Getpersistent: boolean; Result := M_persistent.AsBoolean; end; -procedure TUMLAttribute._Setpersistent(NewValue: boolean); +procedure TUMLAttribute._Setpersistent(const NewValue: boolean); begin M_persistent.AsBoolean := NewValue; end; @@ -7303,11 +7295,11 @@ function TUMLAttribute._Get_M_associationEnd: TBoldObjectReference; function TUMLAttribute._GetassociationEnd: TUMLAssociationEnd; begin - assert(not assigned(M_associationEnd.BoldObject) or (M_associationEnd.BoldObject is TUMLAssociationEnd), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'associationEnd', M_associationEnd.BoldObject.ClassName, 'TUMLAssociationEnd'])); Result := TUMLAssociationEnd(M_associationEnd.BoldObject); + assert(not assigned(Result) or (Result is TUMLAssociationEnd), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'associationEnd', Result.ClassName, 'TUMLAssociationEnd'])); end; -procedure TUMLAttribute._SetassociationEnd(value: TUMLAssociationEnd); +procedure TUMLAttribute._SetassociationEnd(const value: TUMLAssociationEnd); begin M_associationEnd.BoldObject := value; end; @@ -7349,16 +7341,20 @@ procedure TUMLAttributeList.SetBoldObject(index: Integer; NewObject: TUMLAttribu SetElement(index, NewObject); end; -function TUMLAttribute.GetDeriveMethodForMember(Member: TBoldMember): TBoldDeriveAndResubscribe; +function TUMLAttribute.GetDeriveMethodForMember(MemberIndex: Integer): TBoldDeriveAndResubscribe; begin - if (Member = M_persistent) then result := _persistent_DeriveAndSubscribe else - result := inherited GetDeriveMethodForMember(Member); + case MemberIndex of + 50: result := _persistent_DeriveAndSubscribe; + else result := inherited GetDeriveMethodForMember(MemberIndex); + end; end; -function TUMLAttribute.GetReverseDeriveMethodForMember(Member: TBoldMember): TBoldReverseDerive; +function TUMLAttribute.GetReverseDeriveMethodForMember(MemberIndex: Integer): TBoldReverseDerive; begin - result := inherited GetReverseDeriveMethodForMember(Member); - if not assigned(result) and (Member = M_persistent) then result := _persistent_ReverseDerive; + case MemberIndex of + 50: result := _persistent_ReverseDerive; + else result := inherited GetReverseDeriveMethodForMember(MemberIndex); + end; end; { TUMLAssociation } @@ -7374,7 +7370,7 @@ function TUMLAssociation._Getpersistent: boolean; Result := M_persistent.AsBoolean; end; -procedure TUMLAssociation._Setpersistent(NewValue: boolean); +procedure TUMLAssociation._Setpersistent(const NewValue: boolean); begin M_persistent.AsBoolean := NewValue; end; @@ -7410,11 +7406,11 @@ function TUMLAssociation._Get_M_class_: TBoldObjectReference; function TUMLAssociation._Getclass_: TUMLClass; begin - assert(not assigned(M_class_.BoldObject) or (M_class_.BoldObject is TUMLClass), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'class_', M_class_.BoldObject.ClassName, 'TUMLClass'])); Result := TUMLClass(M_class_.BoldObject); + assert(not assigned(Result) or (Result is TUMLClass), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'class_', Result.ClassName, 'TUMLClass'])); end; -procedure TUMLAssociation._Setclass_(value: TUMLClass); +procedure TUMLAssociation._Setclass_(const value: TUMLClass); begin M_class_.BoldObject := value; end; @@ -7462,16 +7458,20 @@ procedure TUMLAssociationList.SetBoldObject(index: Integer; NewObject: TUMLAssoc SetElement(index, NewObject); end; -function TUMLAssociation.GetDeriveMethodForMember(Member: TBoldMember): TBoldDeriveAndResubscribe; +function TUMLAssociation.GetDeriveMethodForMember(MemberIndex: Integer): TBoldDeriveAndResubscribe; begin - if (Member = M_persistent) then result := _persistent_DeriveAndSubscribe else - result := inherited GetDeriveMethodForMember(Member); + case MemberIndex of + 49: result := _persistent_DeriveAndSubscribe; + else result := inherited GetDeriveMethodForMember(MemberIndex); + end; end; -function TUMLAssociation.GetReverseDeriveMethodForMember(Member: TBoldMember): TBoldReverseDerive; +function TUMLAssociation.GetReverseDeriveMethodForMember(MemberIndex: Integer): TBoldReverseDerive; begin - result := inherited GetReverseDeriveMethodForMember(Member); - if not assigned(result) and (Member = M_persistent) then result := _persistent_ReverseDerive; + case MemberIndex of + 49: result := _persistent_ReverseDerive; + else result := inherited GetReverseDeriveMethodForMember(MemberIndex); + end; end; { TUMLClassifier } @@ -7487,7 +7487,7 @@ function TUMLClassifier._Getpersistent: boolean; Result := M_persistent.AsBoolean; end; -procedure TUMLClassifier._Setpersistent(NewValue: boolean); +procedure TUMLClassifier._Setpersistent(const NewValue: boolean); begin M_persistent.AsBoolean := NewValue; end; @@ -7566,11 +7566,11 @@ function TUMLClassifier._Get_M_superclass: TBoldObjectReference; function TUMLClassifier._Getsuperclass: TUMLClassifier; begin - assert(not assigned(M_superclass.BoldObject) or (M_superclass.BoldObject is TUMLClassifier), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'superclass', M_superclass.BoldObject.ClassName, 'TUMLClassifier'])); Result := TUMLClassifier(M_superclass.BoldObject); + assert(not assigned(Result) or (Result is TUMLClassifier), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'superclass', Result.ClassName, 'TUMLClassifier'])); end; -procedure TUMLClassifier._Setsuperclass(value: TUMLClassifier); +procedure TUMLClassifier._Setsuperclass(const value: TUMLClassifier); begin M_superclass.BoldObject := value; end; @@ -7636,16 +7636,20 @@ procedure TUMLClassifierList.SetBoldObject(index: Integer; NewObject: TUMLClassi SetElement(index, NewObject); end; -function TUMLClassifier.GetDeriveMethodForMember(Member: TBoldMember): TBoldDeriveAndResubscribe; +function TUMLClassifier.GetDeriveMethodForMember(MemberIndex: Integer): TBoldDeriveAndResubscribe; begin - if (Member = M_persistent) then result := _persistent_DeriveAndSubscribe else - result := inherited GetDeriveMethodForMember(Member); + case MemberIndex of + 49: result := _persistent_DeriveAndSubscribe; + else result := inherited GetDeriveMethodForMember(MemberIndex); + end; end; -function TUMLClassifier.GetReverseDeriveMethodForMember(Member: TBoldMember): TBoldReverseDerive; +function TUMLClassifier.GetReverseDeriveMethodForMember(MemberIndex: Integer): TBoldReverseDerive; begin - result := inherited GetReverseDeriveMethodForMember(Member); - if not assigned(result) and (Member = M_persistent) then result := _persistent_ReverseDerive; + case MemberIndex of + 49: result := _persistent_ReverseDerive; + else result := inherited GetReverseDeriveMethodForMember(MemberIndex); + end; end; { TUMLCollaboration } @@ -7676,11 +7680,11 @@ function TUMLCollaboration._Get_M_representedClassifier: TBoldObjectReference; function TUMLCollaboration._GetrepresentedClassifier: TUMLClassifier; begin - assert(not assigned(M_representedClassifier.BoldObject) or (M_representedClassifier.BoldObject is TUMLClassifier), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'representedClassifier', M_representedClassifier.BoldObject.ClassName, 'TUMLClassifier'])); Result := TUMLClassifier(M_representedClassifier.BoldObject); + assert(not assigned(Result) or (Result is TUMLClassifier), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'representedClassifier', Result.ClassName, 'TUMLClassifier'])); end; -procedure TUMLCollaboration._SetrepresentedClassifier(value: TUMLClassifier); +procedure TUMLCollaboration._SetrepresentedClassifier(const value: TUMLClassifier); begin M_representedClassifier.BoldObject := value; end; @@ -7693,11 +7697,11 @@ function TUMLCollaboration._Get_M_representedOperation: TBoldObjectReference; function TUMLCollaboration._GetrepresentedOperation: TUMLOperation; begin - assert(not assigned(M_representedOperation.BoldObject) or (M_representedOperation.BoldObject is TUMLOperation), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'representedOperation', M_representedOperation.BoldObject.ClassName, 'TUMLOperation'])); Result := TUMLOperation(M_representedOperation.BoldObject); + assert(not assigned(Result) or (Result is TUMLOperation), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'representedOperation', Result.ClassName, 'TUMLOperation'])); end; -procedure TUMLCollaboration._SetrepresentedOperation(value: TUMLOperation); +procedure TUMLCollaboration._SetrepresentedOperation(const value: TUMLOperation); begin M_representedOperation.BoldObject := value; end; @@ -7797,7 +7801,7 @@ function TUMLStereotype._Geticon: String; Result := M_icon.AsString; end; -procedure TUMLStereotype._Seticon(NewValue: String); +procedure TUMLStereotype._Seticon(const NewValue: String); begin M_icon.AsString := NewValue; end; @@ -7813,7 +7817,7 @@ function TUMLStereotype._GetbaseClass: String; Result := M_baseClass.AsString; end; -procedure TUMLStereotype._SetbaseClass(NewValue: String); +procedure TUMLStereotype._SetbaseClass(const NewValue: String); begin M_baseClass.AsString := NewValue; end; @@ -7886,7 +7890,7 @@ function TUMLAbstraction._Getmapping: String; Result := M_mapping.AsString; end; -procedure TUMLAbstraction._Setmapping(NewValue: String); +procedure TUMLAbstraction._Setmapping(const NewValue: String); begin M_mapping.AsString := NewValue; end; @@ -8064,7 +8068,7 @@ function TUMLCompositeState._GetisConcurrent: boolean; Result := M_isConcurrent.AsBoolean; end; -procedure TUMLCompositeState._SetisConcurrent(NewValue: boolean); +procedure TUMLCompositeState._SetisConcurrent(const NewValue: boolean); begin M_isConcurrent.AsBoolean := NewValue; end; @@ -8203,7 +8207,7 @@ function TUMLAssociationRole._Getmultiplicity: String; Result := M_multiplicity.AsString; end; -procedure TUMLAssociationRole._Setmultiplicity(NewValue: String); +procedure TUMLAssociationRole._Setmultiplicity(const NewValue: String); begin M_multiplicity.AsString := NewValue; end; @@ -8216,11 +8220,11 @@ function TUMLAssociationRole._Get_M_base: TBoldObjectReference; function TUMLAssociationRole._Getbase: TUMLAssociation; begin - assert(not assigned(M_base.BoldObject) or (M_base.BoldObject is TUMLAssociation), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'base', M_base.BoldObject.ClassName, 'TUMLAssociation'])); Result := TUMLAssociation(M_base.BoldObject); + assert(not assigned(Result) or (Result is TUMLAssociation), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'base', Result.ClassName, 'TUMLAssociation'])); end; -procedure TUMLAssociationRole._Setbase(value: TUMLAssociation); +procedure TUMLAssociationRole._Setbase(const value: TUMLAssociation); begin M_base.BoldObject := value; end; @@ -8320,7 +8324,7 @@ function TUMLClass._GetisActive: boolean; Result := M_isActive.AsBoolean; end; -procedure TUMLClass._SetisActive(NewValue: boolean); +procedure TUMLClass._SetisActive(const NewValue: boolean); begin M_isActive.AsBoolean := NewValue; end; @@ -8344,11 +8348,11 @@ function TUMLClass._Get_M_association: TBoldObjectReference; function TUMLClass._Getassociation: TUMLAssociation; begin - assert(not assigned(M_association.BoldObject) or (M_association.BoldObject is TUMLAssociation), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'association', M_association.BoldObject.ClassName, 'TUMLAssociation'])); Result := TUMLAssociation(M_association.BoldObject); + assert(not assigned(Result) or (Result is TUMLAssociation), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'association', Result.ClassName, 'TUMLAssociation'])); end; -procedure TUMLClass._Setassociation(value: TUMLAssociation); +procedure TUMLClass._Setassociation(const value: TUMLAssociation); begin M_association.BoldObject := value; end; @@ -8390,16 +8394,6 @@ procedure TUMLClassList.SetBoldObject(index: Integer; NewObject: TUMLClass); SetElement(index, NewObject); end; -function TUMLClass.GetDeriveMethodForMember(Member: TBoldMember): TBoldDeriveAndResubscribe; -begin - result := inherited GetDeriveMethodForMember(Member); -end; - -function TUMLClass.GetReverseDeriveMethodForMember(Member: TBoldMember): TBoldReverseDerive; -begin - result := inherited GetReverseDeriveMethodForMember(Member); -end; - { TUMLClassifierInState } function TUMLClassifierInState._Get_M_type_: TBoldObjectReference; @@ -8410,11 +8404,11 @@ function TUMLClassifierInState._Get_M_type_: TBoldObjectReference; function TUMLClassifierInState._Gettype_: TUMLClassifier; begin - assert(not assigned(M_type_.BoldObject) or (M_type_.BoldObject is TUMLClassifier), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'type_', M_type_.BoldObject.ClassName, 'TUMLClassifier'])); Result := TUMLClassifier(M_type_.BoldObject); + assert(not assigned(Result) or (Result is TUMLClassifier), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'type_', Result.ClassName, 'TUMLClassifier'])); end; -procedure TUMLClassifierInState._Settype_(value: TUMLClassifier); +procedure TUMLClassifierInState._Settype_(const value: TUMLClassifier); begin M_type_.BoldObject := value; end; @@ -8481,7 +8475,7 @@ function TUMLClassifierRole._Getmultiplicity: String; Result := M_multiplicity.AsString; end; -procedure TUMLClassifierRole._Setmultiplicity(NewValue: String); +procedure TUMLClassifierRole._Setmultiplicity(const NewValue: String); begin M_multiplicity.AsString := NewValue; end; @@ -8905,11 +8899,11 @@ function TUMLModel._Get_M_Validator: TBoldObjectReference; function TUMLModel._GetValidator: TValidator; begin - assert(not assigned(M_Validator.BoldObject) or (M_Validator.BoldObject is TValidator), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'Validator', M_Validator.BoldObject.ClassName, 'TValidator'])); Result := TValidator(M_Validator.BoldObject); + assert(not assigned(Result) or (Result is TValidator), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'Validator', Result.ClassName, 'TValidator'])); end; -procedure TUMLModel._SetValidator(value: TValidator); +procedure TUMLModel._SetValidator(const value: TValidator); begin M_Validator.BoldObject := value; end; @@ -8951,16 +8945,6 @@ procedure TUMLModelList.SetBoldObject(index: Integer; NewObject: TUMLModel); SetElement(index, NewObject); end; -function TUMLModel.GetDeriveMethodForMember(Member: TBoldMember): TBoldDeriveAndResubscribe; -begin - result := inherited GetDeriveMethodForMember(Member); -end; - -function TUMLModel.GetReverseDeriveMethodForMember(Member: TBoldMember): TBoldReverseDerive; -begin - result := inherited GetReverseDeriveMethodForMember(Member); -end; - { TUMLSubsystem } function TUMLSubsystem._Get_M_isInstantiable: TBABoolean; @@ -8974,7 +8958,7 @@ function TUMLSubsystem._GetisInstantiable: boolean; Result := M_isInstantiable.AsBoolean; end; -procedure TUMLSubsystem._SetisInstantiable(NewValue: boolean); +procedure TUMLSubsystem._SetisInstantiable(const NewValue: boolean); begin M_isInstantiable.AsBoolean := NewValue; end; @@ -9026,11 +9010,11 @@ function TUMLSubmachineState._Get_M_submachine: TBoldObjectReference; function TUMLSubmachineState._Getsubmachine: TUMLStateMachine; begin - assert(not assigned(M_submachine.BoldObject) or (M_submachine.BoldObject is TUMLStateMachine), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'submachine', M_submachine.BoldObject.ClassName, 'TUMLStateMachine'])); Result := TUMLStateMachine(M_submachine.BoldObject); + assert(not assigned(Result) or (Result is TUMLStateMachine), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'submachine', Result.ClassName, 'TUMLStateMachine'])); end; -procedure TUMLSubmachineState._Setsubmachine(value: TUMLStateMachine); +procedure TUMLSubmachineState._Setsubmachine(const value: TUMLStateMachine); begin M_submachine.BoldObject := value; end; @@ -9085,7 +9069,7 @@ function TUMLActionState._GetisDynamic: boolean; Result := M_isDynamic.AsBoolean; end; -procedure TUMLActionState._SetisDynamic(NewValue: boolean); +procedure TUMLActionState._SetisDynamic(const NewValue: boolean); begin M_isDynamic.AsBoolean := NewValue; end; @@ -9101,7 +9085,7 @@ function TUMLActionState._GetdynamicArguments: String; Result := M_dynamicArguments.AsString; end; -procedure TUMLActionState._SetdynamicArguments(NewValue: String); +procedure TUMLActionState._SetdynamicArguments(const NewValue: String); begin M_dynamicArguments.AsString := NewValue; end; @@ -9117,7 +9101,7 @@ function TUMLActionState._GetdynamicMultiplicity: String; Result := M_dynamicMultiplicity.AsString; end; -procedure TUMLActionState._SetdynamicMultiplicity(NewValue: String); +procedure TUMLActionState._SetdynamicMultiplicity(const NewValue: String); begin M_dynamicMultiplicity.AsString := NewValue; end; @@ -9172,7 +9156,7 @@ function TUMLObjectFlowState._GetisSynch: boolean; Result := M_isSynch.AsBoolean; end; -procedure TUMLObjectFlowState._SetisSynch(NewValue: boolean); +procedure TUMLObjectFlowState._SetisSynch(const NewValue: boolean); begin M_isSynch.AsBoolean := NewValue; end; @@ -9185,11 +9169,11 @@ function TUMLObjectFlowState._Get_M_type_: TBoldObjectReference; function TUMLObjectFlowState._Gettype_: TUMLClassifier; begin - assert(not assigned(M_type_.BoldObject) or (M_type_.BoldObject is TUMLClassifier), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'type_', M_type_.BoldObject.ClassName, 'TUMLClassifier'])); Result := TUMLClassifier(M_type_.BoldObject); + assert(not assigned(Result) or (Result is TUMLClassifier), SysUtils.format(BoldMemberAssertInvalidObjectType, [ClassName, 'type_', Result.ClassName, 'TUMLClassifier'])); end; -procedure TUMLObjectFlowState._Settype_(value: TUMLClassifier); +procedure TUMLObjectFlowState._Settype_(const value: TUMLClassifier); begin M_type_.BoldObject := value; end; @@ -9295,7 +9279,7 @@ function TUMLSubactivityState._GetisDynamic: boolean; Result := M_isDynamic.AsBoolean; end; -procedure TUMLSubactivityState._SetisDynamic(NewValue: boolean); +procedure TUMLSubactivityState._SetisDynamic(const NewValue: boolean); begin M_isDynamic.AsBoolean := NewValue; end; @@ -9311,7 +9295,7 @@ function TUMLSubactivityState._GetdynamicArguments: String; Result := M_dynamicArguments.AsString; end; -procedure TUMLSubactivityState._SetdynamicArguments(NewValue: String); +procedure TUMLSubactivityState._SetdynamicArguments(const NewValue: String); begin M_dynamicArguments.AsString := NewValue; end; @@ -9327,7 +9311,7 @@ function TUMLSubactivityState._GetdynamicMultiplicity: String; Result := M_dynamicMultiplicity.AsString; end; -procedure TUMLSubactivityState._SetdynamicMultiplicity(NewValue: String); +procedure TUMLSubactivityState._SetdynamicMultiplicity(const NewValue: String); begin M_dynamicMultiplicity.AsString := NewValue; end; @@ -9415,263 +9399,261 @@ function GeneratedCodeCRC: String; procedure InstallObjectListClasses(BoldObjectListClasses: TBoldGeneratedClassList); begin - BoldObjectListClasses.AddObjectEntry('UMLModelRoot', TUMLModelRootList); // do not localize - BoldObjectListClasses.AddObjectEntry('Argumentstimulus1', Targumentstimulus1List); // do not localize - BoldObjectListClasses.AddObjectEntry('AssociationEndRoleavailableQualifier', TassociationEndRoleavailableQualifierList); // do not localize - BoldObjectListClasses.AddObjectEntry('ClassifierclassifierRole_', TclassifierclassifierRole_List); // do not localize - BoldObjectListClasses.AddObjectEntry('ClassifierInStateinState', TclassifierInStateinStateList); // do not localize - BoldObjectListClasses.AddObjectEntry('ClassifierRole_availableFeature', TclassifierRole_availableFeatureList); // do not localize - BoldObjectListClasses.AddObjectEntry('ClassifierRoleavailableContents', TclassifierRoleavailableContentsList); // do not localize - BoldObjectListClasses.AddObjectEntry('ClientclientDependency', TclientclientDependencyList); // do not localize - BoldObjectListClasses.AddObjectEntry('CollaborationconstrainingElement', TcollaborationconstrainingElementList); // do not localize - BoldObjectListClasses.AddObjectEntry('CommentannotatedElement', TcommentannotatedElementList); // do not localize - BoldObjectListClasses.AddObjectEntry('ConstrainedElementconstraint', TconstrainedElementconstraintList); // do not localize - BoldObjectListClasses.AddObjectEntry('Contentspartition', TcontentspartitionList); // do not localize - BoldObjectListClasses.AddObjectEntry('ContextraisedSignal', TcontextraisedSignalList); // do not localize - BoldObjectListClasses.AddObjectEntry('DeploymentLocationresident', TdeploymentLocationresidentList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLElement', TUMLElementList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLElementImport', TUMLElementImportList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLElementResidence', TUMLElementResidenceList); // do not localize - BoldObjectListClasses.AddObjectEntry('ExtensionPointextend', TextensionPointextendList); // do not localize - BoldObjectListClasses.AddObjectEntry('Instanceclassifier', TinstanceclassifierList); // do not localize - BoldObjectListClasses.AddObjectEntry('Parameterstate', TparameterstateList); // do not localize - BoldObjectListClasses.AddObjectEntry('Participantspecification', TparticipantspecificationList); // do not localize - BoldObjectListClasses.AddObjectEntry('Predecessormessage3', Tpredecessormessage3List); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLPresentationElement', TUMLPresentationElementList); // do not localize - BoldObjectListClasses.AddObjectEntry('Presentationsubject', TpresentationsubjectList); // do not localize - BoldObjectListClasses.AddObjectEntry('SourceFlowsource', TsourceFlowsourceList); // do not localize - BoldObjectListClasses.AddObjectEntry('StatedeferrableEvent', TstatedeferrableEventList); // do not localize - BoldObjectListClasses.AddObjectEntry('SuppliersupplierDependency', TsuppliersupplierDependencyList); // do not localize - BoldObjectListClasses.AddObjectEntry('TargetFlowtarget', TtargetFlowtargetList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLTemplateParameter', TUMLTemplateParameterList); // do not localize - BoldObjectListClasses.AddObjectEntry('Validator', TValidatorList); // do not localize - BoldObjectListClasses.AddObjectEntry('Violation', TViolationList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLModelElement', TUMLModelElementList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLAction', TUMLActionList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLArgument', TUMLArgumentList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLAssociationEnd', TUMLAssociationEndList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLAttributeLink', TUMLAttributeLinkList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLComment', TUMLCommentList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLConstraint', TUMLConstraintList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLEvent', TUMLEventList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLExtensionPoint', TUMLExtensionPointList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLFeature', TUMLFeatureList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLGuard', TUMLGuardList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLInstance', TUMLInstanceList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLInteraction', TUMLInteractionList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLLink', TUMLLinkList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLLinkEnd', TUMLLinkEndList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLMessage', TUMLMessageList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLNamespace', TUMLNamespaceList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLParameter', TUMLParameterList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLPartition', TUMLPartitionList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLRelationship', TUMLRelationshipList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLStateMachine', TUMLStateMachineList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLStateVertex', TUMLStateVertexList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLStimulus', TUMLStimulusList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLTaggedValue', TUMLTaggedValueList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLTransition', TUMLTransitionList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLActionSequence', TUMLActionSequenceList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLCallAction', TUMLCallActionList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLCreateAction', TUMLCreateActionList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLDestroyAction', TUMLDestroyActionList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLReturnAction', TUMLReturnActionList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLSendAction', TUMLSendActionList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLTerminateAction', TUMLTerminateActionList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLUninterpretedAction', TUMLUninterpretedActionList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLAssociationEndRole', TUMLAssociationEndRoleList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLCallEvent', TUMLCallEventList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLChangeEvent', TUMLChangeEventList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLSignalEvent', TUMLSignalEventList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLTimeEvent', TUMLTimeEventList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLBehavioralFeature', TUMLBehavioralFeatureList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLStructuralFeature', TUMLStructuralFeatureList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLComponentInstance', TUMLComponentInstanceList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLDataValue', TUMLDataValueList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLNodeInstance', TUMLNodeInstanceList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLObject', TUMLObjectList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLUseCaseInstance', TUMLUseCaseInstanceList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLGeneralizableElement', TUMLGeneralizableElementList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLDependency', TUMLDependencyList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLExtend', TUMLExtendList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLFlow', TUMLFlowList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLGeneralization', TUMLGeneralizationList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLInclude', TUMLIncludeList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLActivityGraph', TUMLActivityGraphList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLPseudostate', TUMLPseudostateList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLState', TUMLStateList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLStubState', TUMLStubStateList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLSynchState', TUMLSynchStateList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLMethod', TUMLMethodList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLOperation', TUMLOperationList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLReception', TUMLReceptionList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLAttribute', TUMLAttributeList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLAssociation', TUMLAssociationList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLClassifier', TUMLClassifierList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLCollaboration', TUMLCollaborationList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLPackage', TUMLPackageList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLStereotype', TUMLStereotypeList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLAbstraction', TUMLAbstractionList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLBinding', TUMLBindingList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLPermission', TUMLPermissionList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLUsage', TUMLUsageList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLCompositeState', TUMLCompositeStateList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLFinalState', TUMLFinalStateList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLSimpleState', TUMLSimpleStateList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLAssociationRole', TUMLAssociationRoleList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLActor', TUMLActorList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLClass', TUMLClassList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLClassifierInState', TUMLClassifierInStateList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLClassifierRole', TUMLClassifierRoleList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLComponent', TUMLComponentList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLDataType', TUMLDataTypeList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLInterface', TUMLInterfaceList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLNode', TUMLNodeList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLSignal', TUMLSignalList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLUseCase', TUMLUseCaseList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLModel', TUMLModelList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLSubsystem', TUMLSubsystemList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLSubmachineState', TUMLSubmachineStateList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLActionState', TUMLActionStateList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLObjectFlowState', TUMLObjectFlowStateList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLException', TUMLExceptionList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLSubactivityState', TUMLSubactivityStateList); // do not localize - BoldObjectListClasses.AddObjectEntry('UMLCallState', TUMLCallStateList); // do not localize + BoldObjectListClasses.AddObjectEntry('UMLModelRoot', TUMLModelRootList); + BoldObjectListClasses.AddObjectEntry('Argumentstimulus1', Targumentstimulus1List); + BoldObjectListClasses.AddObjectEntry('AssociationEndRoleavailableQualifier', TassociationEndRoleavailableQualifierList); + BoldObjectListClasses.AddObjectEntry('ClassifierclassifierRole_', TclassifierclassifierRole_List); + BoldObjectListClasses.AddObjectEntry('ClassifierInStateinState', TclassifierInStateinStateList); + BoldObjectListClasses.AddObjectEntry('ClassifierRole_availableFeature', TclassifierRole_availableFeatureList); + BoldObjectListClasses.AddObjectEntry('ClassifierRoleavailableContents', TclassifierRoleavailableContentsList); + BoldObjectListClasses.AddObjectEntry('ClientclientDependency', TclientclientDependencyList); + BoldObjectListClasses.AddObjectEntry('CollaborationconstrainingElement', TcollaborationconstrainingElementList); + BoldObjectListClasses.AddObjectEntry('CommentannotatedElement', TcommentannotatedElementList); + BoldObjectListClasses.AddObjectEntry('ConstrainedElementconstraint', TconstrainedElementconstraintList); + BoldObjectListClasses.AddObjectEntry('Contentspartition', TcontentspartitionList); + BoldObjectListClasses.AddObjectEntry('ContextraisedSignal', TcontextraisedSignalList); + BoldObjectListClasses.AddObjectEntry('DeploymentLocationresident', TdeploymentLocationresidentList); + BoldObjectListClasses.AddObjectEntry('UMLElement', TUMLElementList); + BoldObjectListClasses.AddObjectEntry('UMLElementImport', TUMLElementImportList); + BoldObjectListClasses.AddObjectEntry('UMLElementResidence', TUMLElementResidenceList); + BoldObjectListClasses.AddObjectEntry('ExtensionPointextend', TextensionPointextendList); + BoldObjectListClasses.AddObjectEntry('Instanceclassifier', TinstanceclassifierList); + BoldObjectListClasses.AddObjectEntry('Parameterstate', TparameterstateList); + BoldObjectListClasses.AddObjectEntry('Participantspecification', TparticipantspecificationList); + BoldObjectListClasses.AddObjectEntry('Predecessormessage3', Tpredecessormessage3List); + BoldObjectListClasses.AddObjectEntry('UMLPresentationElement', TUMLPresentationElementList); + BoldObjectListClasses.AddObjectEntry('Presentationsubject', TpresentationsubjectList); + BoldObjectListClasses.AddObjectEntry('SourceFlowsource', TsourceFlowsourceList); + BoldObjectListClasses.AddObjectEntry('StatedeferrableEvent', TstatedeferrableEventList); + BoldObjectListClasses.AddObjectEntry('SuppliersupplierDependency', TsuppliersupplierDependencyList); + BoldObjectListClasses.AddObjectEntry('TargetFlowtarget', TtargetFlowtargetList); + BoldObjectListClasses.AddObjectEntry('UMLTemplateParameter', TUMLTemplateParameterList); + BoldObjectListClasses.AddObjectEntry('Validator', TValidatorList); + BoldObjectListClasses.AddObjectEntry('Violation', TViolationList); + BoldObjectListClasses.AddObjectEntry('UMLModelElement', TUMLModelElementList); + BoldObjectListClasses.AddObjectEntry('UMLAction', TUMLActionList); + BoldObjectListClasses.AddObjectEntry('UMLArgument', TUMLArgumentList); + BoldObjectListClasses.AddObjectEntry('UMLAssociationEnd', TUMLAssociationEndList); + BoldObjectListClasses.AddObjectEntry('UMLAttributeLink', TUMLAttributeLinkList); + BoldObjectListClasses.AddObjectEntry('UMLComment', TUMLCommentList); + BoldObjectListClasses.AddObjectEntry('UMLConstraint', TUMLConstraintList); + BoldObjectListClasses.AddObjectEntry('UMLEvent', TUMLEventList); + BoldObjectListClasses.AddObjectEntry('UMLExtensionPoint', TUMLExtensionPointList); + BoldObjectListClasses.AddObjectEntry('UMLFeature', TUMLFeatureList); + BoldObjectListClasses.AddObjectEntry('UMLGuard', TUMLGuardList); + BoldObjectListClasses.AddObjectEntry('UMLInstance', TUMLInstanceList); + BoldObjectListClasses.AddObjectEntry('UMLInteraction', TUMLInteractionList); + BoldObjectListClasses.AddObjectEntry('UMLLink', TUMLLinkList); + BoldObjectListClasses.AddObjectEntry('UMLLinkEnd', TUMLLinkEndList); + BoldObjectListClasses.AddObjectEntry('UMLMessage', TUMLMessageList); + BoldObjectListClasses.AddObjectEntry('UMLNamespace', TUMLNamespaceList); + BoldObjectListClasses.AddObjectEntry('UMLParameter', TUMLParameterList); + BoldObjectListClasses.AddObjectEntry('UMLPartition', TUMLPartitionList); + BoldObjectListClasses.AddObjectEntry('UMLRelationship', TUMLRelationshipList); + BoldObjectListClasses.AddObjectEntry('UMLStateMachine', TUMLStateMachineList); + BoldObjectListClasses.AddObjectEntry('UMLStateVertex', TUMLStateVertexList); + BoldObjectListClasses.AddObjectEntry('UMLStimulus', TUMLStimulusList); + BoldObjectListClasses.AddObjectEntry('UMLTaggedValue', TUMLTaggedValueList); + BoldObjectListClasses.AddObjectEntry('UMLTransition', TUMLTransitionList); + BoldObjectListClasses.AddObjectEntry('UMLActionSequence', TUMLActionSequenceList); + BoldObjectListClasses.AddObjectEntry('UMLCallAction', TUMLCallActionList); + BoldObjectListClasses.AddObjectEntry('UMLCreateAction', TUMLCreateActionList); + BoldObjectListClasses.AddObjectEntry('UMLDestroyAction', TUMLDestroyActionList); + BoldObjectListClasses.AddObjectEntry('UMLReturnAction', TUMLReturnActionList); + BoldObjectListClasses.AddObjectEntry('UMLSendAction', TUMLSendActionList); + BoldObjectListClasses.AddObjectEntry('UMLTerminateAction', TUMLTerminateActionList); + BoldObjectListClasses.AddObjectEntry('UMLUninterpretedAction', TUMLUninterpretedActionList); + BoldObjectListClasses.AddObjectEntry('UMLAssociationEndRole', TUMLAssociationEndRoleList); + BoldObjectListClasses.AddObjectEntry('UMLCallEvent', TUMLCallEventList); + BoldObjectListClasses.AddObjectEntry('UMLChangeEvent', TUMLChangeEventList); + BoldObjectListClasses.AddObjectEntry('UMLSignalEvent', TUMLSignalEventList); + BoldObjectListClasses.AddObjectEntry('UMLTimeEvent', TUMLTimeEventList); + BoldObjectListClasses.AddObjectEntry('UMLBehavioralFeature', TUMLBehavioralFeatureList); + BoldObjectListClasses.AddObjectEntry('UMLStructuralFeature', TUMLStructuralFeatureList); + BoldObjectListClasses.AddObjectEntry('UMLComponentInstance', TUMLComponentInstanceList); + BoldObjectListClasses.AddObjectEntry('UMLDataValue', TUMLDataValueList); + BoldObjectListClasses.AddObjectEntry('UMLNodeInstance', TUMLNodeInstanceList); + BoldObjectListClasses.AddObjectEntry('UMLObject', TUMLObjectList); + BoldObjectListClasses.AddObjectEntry('UMLUseCaseInstance', TUMLUseCaseInstanceList); + BoldObjectListClasses.AddObjectEntry('UMLGeneralizableElement', TUMLGeneralizableElementList); + BoldObjectListClasses.AddObjectEntry('UMLDependency', TUMLDependencyList); + BoldObjectListClasses.AddObjectEntry('UMLExtend', TUMLExtendList); + BoldObjectListClasses.AddObjectEntry('UMLFlow', TUMLFlowList); + BoldObjectListClasses.AddObjectEntry('UMLGeneralization', TUMLGeneralizationList); + BoldObjectListClasses.AddObjectEntry('UMLInclude', TUMLIncludeList); + BoldObjectListClasses.AddObjectEntry('UMLActivityGraph', TUMLActivityGraphList); + BoldObjectListClasses.AddObjectEntry('UMLPseudostate', TUMLPseudostateList); + BoldObjectListClasses.AddObjectEntry('UMLState', TUMLStateList); + BoldObjectListClasses.AddObjectEntry('UMLStubState', TUMLStubStateList); + BoldObjectListClasses.AddObjectEntry('UMLSynchState', TUMLSynchStateList); + BoldObjectListClasses.AddObjectEntry('UMLMethod', TUMLMethodList); + BoldObjectListClasses.AddObjectEntry('UMLOperation', TUMLOperationList); + BoldObjectListClasses.AddObjectEntry('UMLReception', TUMLReceptionList); + BoldObjectListClasses.AddObjectEntry('UMLAttribute', TUMLAttributeList); + BoldObjectListClasses.AddObjectEntry('UMLAssociation', TUMLAssociationList); + BoldObjectListClasses.AddObjectEntry('UMLClassifier', TUMLClassifierList); + BoldObjectListClasses.AddObjectEntry('UMLCollaboration', TUMLCollaborationList); + BoldObjectListClasses.AddObjectEntry('UMLPackage', TUMLPackageList); + BoldObjectListClasses.AddObjectEntry('UMLStereotype', TUMLStereotypeList); + BoldObjectListClasses.AddObjectEntry('UMLAbstraction', TUMLAbstractionList); + BoldObjectListClasses.AddObjectEntry('UMLBinding', TUMLBindingList); + BoldObjectListClasses.AddObjectEntry('UMLPermission', TUMLPermissionList); + BoldObjectListClasses.AddObjectEntry('UMLUsage', TUMLUsageList); + BoldObjectListClasses.AddObjectEntry('UMLCompositeState', TUMLCompositeStateList); + BoldObjectListClasses.AddObjectEntry('UMLFinalState', TUMLFinalStateList); + BoldObjectListClasses.AddObjectEntry('UMLSimpleState', TUMLSimpleStateList); + BoldObjectListClasses.AddObjectEntry('UMLAssociationRole', TUMLAssociationRoleList); + BoldObjectListClasses.AddObjectEntry('UMLActor', TUMLActorList); + BoldObjectListClasses.AddObjectEntry('UMLClass', TUMLClassList); + BoldObjectListClasses.AddObjectEntry('UMLClassifierInState', TUMLClassifierInStateList); + BoldObjectListClasses.AddObjectEntry('UMLClassifierRole', TUMLClassifierRoleList); + BoldObjectListClasses.AddObjectEntry('UMLComponent', TUMLComponentList); + BoldObjectListClasses.AddObjectEntry('UMLDataType', TUMLDataTypeList); + BoldObjectListClasses.AddObjectEntry('UMLInterface', TUMLInterfaceList); + BoldObjectListClasses.AddObjectEntry('UMLNode', TUMLNodeList); + BoldObjectListClasses.AddObjectEntry('UMLSignal', TUMLSignalList); + BoldObjectListClasses.AddObjectEntry('UMLUseCase', TUMLUseCaseList); + BoldObjectListClasses.AddObjectEntry('UMLModel', TUMLModelList); + BoldObjectListClasses.AddObjectEntry('UMLSubsystem', TUMLSubsystemList); + BoldObjectListClasses.AddObjectEntry('UMLSubmachineState', TUMLSubmachineStateList); + BoldObjectListClasses.AddObjectEntry('UMLActionState', TUMLActionStateList); + BoldObjectListClasses.AddObjectEntry('UMLObjectFlowState', TUMLObjectFlowStateList); + BoldObjectListClasses.AddObjectEntry('UMLException', TUMLExceptionList); + BoldObjectListClasses.AddObjectEntry('UMLSubactivityState', TUMLSubactivityStateList); + BoldObjectListClasses.AddObjectEntry('UMLCallState', TUMLCallStateList); end; procedure InstallBusinessClasses(BoldObjectClasses: TBoldGeneratedClassList); begin - BoldObjectClasses.AddObjectEntry('UMLModelRoot', TUMLModelRoot); // do not localize - BoldObjectClasses.AddObjectEntry('Argumentstimulus1', Targumentstimulus1); // do not localize - BoldObjectClasses.AddObjectEntry('AssociationEndRoleavailableQualifier', TassociationEndRoleavailableQualifier); // do not localize - BoldObjectClasses.AddObjectEntry('ClassifierclassifierRole_', TclassifierclassifierRole_); // do not localize - BoldObjectClasses.AddObjectEntry('ClassifierInStateinState', TclassifierInStateinState); // do not localize - BoldObjectClasses.AddObjectEntry('ClassifierRole_availableFeature', TclassifierRole_availableFeature); // do not localize - BoldObjectClasses.AddObjectEntry('ClassifierRoleavailableContents', TclassifierRoleavailableContents); // do not localize - BoldObjectClasses.AddObjectEntry('ClientclientDependency', TclientclientDependency); // do not localize - BoldObjectClasses.AddObjectEntry('CollaborationconstrainingElement', TcollaborationconstrainingElement); // do not localize - BoldObjectClasses.AddObjectEntry('CommentannotatedElement', TcommentannotatedElement); // do not localize - BoldObjectClasses.AddObjectEntry('ConstrainedElementconstraint', TconstrainedElementconstraint); // do not localize - BoldObjectClasses.AddObjectEntry('Contentspartition', Tcontentspartition); // do not localize - BoldObjectClasses.AddObjectEntry('ContextraisedSignal', TcontextraisedSignal); // do not localize - BoldObjectClasses.AddObjectEntry('DeploymentLocationresident', TdeploymentLocationresident); // do not localize - BoldObjectClasses.AddObjectEntry('UMLElement', TUMLElement); // do not localize - BoldObjectClasses.AddObjectEntry('UMLElementImport', TUMLElementImport); // do not localize - BoldObjectClasses.AddObjectEntry('UMLElementResidence', TUMLElementResidence); // do not localize - BoldObjectClasses.AddObjectEntry('ExtensionPointextend', TextensionPointextend); // do not localize - BoldObjectClasses.AddObjectEntry('Instanceclassifier', Tinstanceclassifier); // do not localize - BoldObjectClasses.AddObjectEntry('Parameterstate', Tparameterstate); // do not localize - BoldObjectClasses.AddObjectEntry('Participantspecification', Tparticipantspecification); // do not localize - BoldObjectClasses.AddObjectEntry('Predecessormessage3', Tpredecessormessage3); // do not localize - BoldObjectClasses.AddObjectEntry('UMLPresentationElement', TUMLPresentationElement); // do not localize - BoldObjectClasses.AddObjectEntry('Presentationsubject', Tpresentationsubject); // do not localize - BoldObjectClasses.AddObjectEntry('SourceFlowsource', TsourceFlowsource); // do not localize - BoldObjectClasses.AddObjectEntry('StatedeferrableEvent', TstatedeferrableEvent); // do not localize - BoldObjectClasses.AddObjectEntry('SuppliersupplierDependency', TsuppliersupplierDependency); // do not localize - BoldObjectClasses.AddObjectEntry('TargetFlowtarget', TtargetFlowtarget); // do not localize - BoldObjectClasses.AddObjectEntry('UMLTemplateParameter', TUMLTemplateParameter); // do not localize - BoldObjectClasses.AddObjectEntry('Validator', TValidator); // do not localize - BoldObjectClasses.AddObjectEntry('Violation', TViolation); // do not localize - BoldObjectClasses.AddObjectEntry('UMLModelElement', TUMLModelElement); // do not localize - BoldObjectClasses.AddObjectEntry('UMLAction', TUMLAction); // do not localize - BoldObjectClasses.AddObjectEntry('UMLArgument', TUMLArgument); // do not localize - BoldObjectClasses.AddObjectEntry('UMLAssociationEnd', TUMLAssociationEnd); // do not localize - BoldObjectClasses.AddObjectEntry('UMLAttributeLink', TUMLAttributeLink); // do not localize - BoldObjectClasses.AddObjectEntry('UMLComment', TUMLComment); // do not localize - BoldObjectClasses.AddObjectEntry('UMLConstraint', TUMLConstraint); // do not localize - BoldObjectClasses.AddObjectEntry('UMLEvent', TUMLEvent); // do not localize - BoldObjectClasses.AddObjectEntry('UMLExtensionPoint', TUMLExtensionPoint); // do not localize - BoldObjectClasses.AddObjectEntry('UMLFeature', TUMLFeature); // do not localize - BoldObjectClasses.AddObjectEntry('UMLGuard', TUMLGuard); // do not localize - BoldObjectClasses.AddObjectEntry('UMLInstance', TUMLInstance); // do not localize - BoldObjectClasses.AddObjectEntry('UMLInteraction', TUMLInteraction); // do not localize - BoldObjectClasses.AddObjectEntry('UMLLink', TUMLLink); // do not localize - BoldObjectClasses.AddObjectEntry('UMLLinkEnd', TUMLLinkEnd); // do not localize - BoldObjectClasses.AddObjectEntry('UMLMessage', TUMLMessage); // do not localize - BoldObjectClasses.AddObjectEntry('UMLNamespace', TUMLNamespace); // do not localize - BoldObjectClasses.AddObjectEntry('UMLParameter', TUMLParameter); // do not localize - BoldObjectClasses.AddObjectEntry('UMLPartition', TUMLPartition); // do not localize - BoldObjectClasses.AddObjectEntry('UMLRelationship', TUMLRelationship); // do not localize - BoldObjectClasses.AddObjectEntry('UMLStateMachine', TUMLStateMachine); // do not localize - BoldObjectClasses.AddObjectEntry('UMLStateVertex', TUMLStateVertex); // do not localize - BoldObjectClasses.AddObjectEntry('UMLStimulus', TUMLStimulus); // do not localize - BoldObjectClasses.AddObjectEntry('UMLTaggedValue', TUMLTaggedValue); // do not localize - BoldObjectClasses.AddObjectEntry('UMLTransition', TUMLTransition); // do not localize - BoldObjectClasses.AddObjectEntry('UMLActionSequence', TUMLActionSequence); // do not localize - BoldObjectClasses.AddObjectEntry('UMLCallAction', TUMLCallAction); // do not localize - BoldObjectClasses.AddObjectEntry('UMLCreateAction', TUMLCreateAction); // do not localize - BoldObjectClasses.AddObjectEntry('UMLDestroyAction', TUMLDestroyAction); // do not localize - BoldObjectClasses.AddObjectEntry('UMLReturnAction', TUMLReturnAction); // do not localize - BoldObjectClasses.AddObjectEntry('UMLSendAction', TUMLSendAction); // do not localize - BoldObjectClasses.AddObjectEntry('UMLTerminateAction', TUMLTerminateAction); // do not localize - BoldObjectClasses.AddObjectEntry('UMLUninterpretedAction', TUMLUninterpretedAction); // do not localize - BoldObjectClasses.AddObjectEntry('UMLAssociationEndRole', TUMLAssociationEndRole); // do not localize - BoldObjectClasses.AddObjectEntry('UMLCallEvent', TUMLCallEvent); // do not localize - BoldObjectClasses.AddObjectEntry('UMLChangeEvent', TUMLChangeEvent); // do not localize - BoldObjectClasses.AddObjectEntry('UMLSignalEvent', TUMLSignalEvent); // do not localize - BoldObjectClasses.AddObjectEntry('UMLTimeEvent', TUMLTimeEvent); // do not localize - BoldObjectClasses.AddObjectEntry('UMLBehavioralFeature', TUMLBehavioralFeature); // do not localize - BoldObjectClasses.AddObjectEntry('UMLStructuralFeature', TUMLStructuralFeature); // do not localize - BoldObjectClasses.AddObjectEntry('UMLComponentInstance', TUMLComponentInstance); // do not localize - BoldObjectClasses.AddObjectEntry('UMLDataValue', TUMLDataValue); // do not localize - BoldObjectClasses.AddObjectEntry('UMLNodeInstance', TUMLNodeInstance); // do not localize - BoldObjectClasses.AddObjectEntry('UMLObject', TUMLObject); // do not localize - BoldObjectClasses.AddObjectEntry('UMLUseCaseInstance', TUMLUseCaseInstance); // do not localize - BoldObjectClasses.AddObjectEntry('UMLGeneralizableElement', TUMLGeneralizableElement); // do not localize - BoldObjectClasses.AddObjectEntry('UMLDependency', TUMLDependency); // do not localize - BoldObjectClasses.AddObjectEntry('UMLExtend', TUMLExtend); // do not localize - BoldObjectClasses.AddObjectEntry('UMLFlow', TUMLFlow); // do not localize - BoldObjectClasses.AddObjectEntry('UMLGeneralization', TUMLGeneralization); // do not localize - BoldObjectClasses.AddObjectEntry('UMLInclude', TUMLInclude); // do not localize - BoldObjectClasses.AddObjectEntry('UMLActivityGraph', TUMLActivityGraph); // do not localize - BoldObjectClasses.AddObjectEntry('UMLPseudostate', TUMLPseudostate); // do not localize - BoldObjectClasses.AddObjectEntry('UMLState', TUMLState); // do not localize - BoldObjectClasses.AddObjectEntry('UMLStubState', TUMLStubState); // do not localize - BoldObjectClasses.AddObjectEntry('UMLSynchState', TUMLSynchState); // do not localize - BoldObjectClasses.AddObjectEntry('UMLMethod', TUMLMethod); // do not localize - BoldObjectClasses.AddObjectEntry('UMLOperation', TUMLOperation); // do not localize - BoldObjectClasses.AddObjectEntry('UMLReception', TUMLReception); // do not localize - BoldObjectClasses.AddObjectEntry('UMLAttribute', TUMLAttribute); // do not localize - BoldObjectClasses.AddObjectEntry('UMLAssociation', TUMLAssociation); // do not localize - BoldObjectClasses.AddObjectEntry('UMLClassifier', TUMLClassifier); // do not localize - BoldObjectClasses.AddObjectEntry('UMLCollaboration', TUMLCollaboration); // do not localize - BoldObjectClasses.AddObjectEntry('UMLPackage', TUMLPackage); // do not localize - BoldObjectClasses.AddObjectEntry('UMLStereotype', TUMLStereotype); // do not localize - BoldObjectClasses.AddObjectEntry('UMLAbstraction', TUMLAbstraction); // do not localize - BoldObjectClasses.AddObjectEntry('UMLBinding', TUMLBinding); // do not localize - BoldObjectClasses.AddObjectEntry('UMLPermission', TUMLPermission); // do not localize - BoldObjectClasses.AddObjectEntry('UMLUsage', TUMLUsage); // do not localize - BoldObjectClasses.AddObjectEntry('UMLCompositeState', TUMLCompositeState); // do not localize - BoldObjectClasses.AddObjectEntry('UMLFinalState', TUMLFinalState); // do not localize - BoldObjectClasses.AddObjectEntry('UMLSimpleState', TUMLSimpleState); // do not localize - BoldObjectClasses.AddObjectEntry('UMLAssociationRole', TUMLAssociationRole); // do not localize - BoldObjectClasses.AddObjectEntry('UMLActor', TUMLActor); // do not localize - BoldObjectClasses.AddObjectEntry('UMLClass', TUMLClass); // do not localize - BoldObjectClasses.AddObjectEntry('UMLClassifierInState', TUMLClassifierInState); // do not localize - BoldObjectClasses.AddObjectEntry('UMLClassifierRole', TUMLClassifierRole); // do not localize - BoldObjectClasses.AddObjectEntry('UMLComponent', TUMLComponent); // do not localize - BoldObjectClasses.AddObjectEntry('UMLDataType', TUMLDataType); // do not localize - BoldObjectClasses.AddObjectEntry('UMLInterface', TUMLInterface); // do not localize - BoldObjectClasses.AddObjectEntry('UMLNode', TUMLNode); // do not localize - BoldObjectClasses.AddObjectEntry('UMLSignal', TUMLSignal); // do not localize - BoldObjectClasses.AddObjectEntry('UMLUseCase', TUMLUseCase); // do not localize - BoldObjectClasses.AddObjectEntry('UMLModel', TUMLModel); // do not localize - BoldObjectClasses.AddObjectEntry('UMLSubsystem', TUMLSubsystem); // do not localize - BoldObjectClasses.AddObjectEntry('UMLSubmachineState', TUMLSubmachineState); // do not localize - BoldObjectClasses.AddObjectEntry('UMLActionState', TUMLActionState); // do not localize - BoldObjectClasses.AddObjectEntry('UMLObjectFlowState', TUMLObjectFlowState); // do not localize - BoldObjectClasses.AddObjectEntry('UMLException', TUMLException); // do not localize - BoldObjectClasses.AddObjectEntry('UMLSubactivityState', TUMLSubactivityState); // do not localize - BoldObjectClasses.AddObjectEntry('UMLCallState', TUMLCallState); // do not localize + BoldObjectClasses.AddObjectEntry('UMLModelRoot', TUMLModelRoot); + BoldObjectClasses.AddObjectEntry('Argumentstimulus1', Targumentstimulus1); + BoldObjectClasses.AddObjectEntry('AssociationEndRoleavailableQualifier', TassociationEndRoleavailableQualifier); + BoldObjectClasses.AddObjectEntry('ClassifierclassifierRole_', TclassifierclassifierRole_); + BoldObjectClasses.AddObjectEntry('ClassifierInStateinState', TclassifierInStateinState); + BoldObjectClasses.AddObjectEntry('ClassifierRole_availableFeature', TclassifierRole_availableFeature); + BoldObjectClasses.AddObjectEntry('ClassifierRoleavailableContents', TclassifierRoleavailableContents); + BoldObjectClasses.AddObjectEntry('ClientclientDependency', TclientclientDependency); + BoldObjectClasses.AddObjectEntry('CollaborationconstrainingElement', TcollaborationconstrainingElement); + BoldObjectClasses.AddObjectEntry('CommentannotatedElement', TcommentannotatedElement); + BoldObjectClasses.AddObjectEntry('ConstrainedElementconstraint', TconstrainedElementconstraint); + BoldObjectClasses.AddObjectEntry('Contentspartition', Tcontentspartition); + BoldObjectClasses.AddObjectEntry('ContextraisedSignal', TcontextraisedSignal); + BoldObjectClasses.AddObjectEntry('DeploymentLocationresident', TdeploymentLocationresident); + BoldObjectClasses.AddObjectEntry('UMLElement', TUMLElement); + BoldObjectClasses.AddObjectEntry('UMLElementImport', TUMLElementImport); + BoldObjectClasses.AddObjectEntry('UMLElementResidence', TUMLElementResidence); + BoldObjectClasses.AddObjectEntry('ExtensionPointextend', TextensionPointextend); + BoldObjectClasses.AddObjectEntry('Instanceclassifier', Tinstanceclassifier); + BoldObjectClasses.AddObjectEntry('Parameterstate', Tparameterstate); + BoldObjectClasses.AddObjectEntry('Participantspecification', Tparticipantspecification); + BoldObjectClasses.AddObjectEntry('Predecessormessage3', Tpredecessormessage3); + BoldObjectClasses.AddObjectEntry('UMLPresentationElement', TUMLPresentationElement); + BoldObjectClasses.AddObjectEntry('Presentationsubject', Tpresentationsubject); + BoldObjectClasses.AddObjectEntry('SourceFlowsource', TsourceFlowsource); + BoldObjectClasses.AddObjectEntry('StatedeferrableEvent', TstatedeferrableEvent); + BoldObjectClasses.AddObjectEntry('SuppliersupplierDependency', TsuppliersupplierDependency); + BoldObjectClasses.AddObjectEntry('TargetFlowtarget', TtargetFlowtarget); + BoldObjectClasses.AddObjectEntry('UMLTemplateParameter', TUMLTemplateParameter); + BoldObjectClasses.AddObjectEntry('Validator', TValidator); + BoldObjectClasses.AddObjectEntry('Violation', TViolation); + BoldObjectClasses.AddObjectEntry('UMLModelElement', TUMLModelElement); + BoldObjectClasses.AddObjectEntry('UMLAction', TUMLAction); + BoldObjectClasses.AddObjectEntry('UMLArgument', TUMLArgument); + BoldObjectClasses.AddObjectEntry('UMLAssociationEnd', TUMLAssociationEnd); + BoldObjectClasses.AddObjectEntry('UMLAttributeLink', TUMLAttributeLink); + BoldObjectClasses.AddObjectEntry('UMLComment', TUMLComment); + BoldObjectClasses.AddObjectEntry('UMLConstraint', TUMLConstraint); + BoldObjectClasses.AddObjectEntry('UMLEvent', TUMLEvent); + BoldObjectClasses.AddObjectEntry('UMLExtensionPoint', TUMLExtensionPoint); + BoldObjectClasses.AddObjectEntry('UMLFeature', TUMLFeature); + BoldObjectClasses.AddObjectEntry('UMLGuard', TUMLGuard); + BoldObjectClasses.AddObjectEntry('UMLInstance', TUMLInstance); + BoldObjectClasses.AddObjectEntry('UMLInteraction', TUMLInteraction); + BoldObjectClasses.AddObjectEntry('UMLLink', TUMLLink); + BoldObjectClasses.AddObjectEntry('UMLLinkEnd', TUMLLinkEnd); + BoldObjectClasses.AddObjectEntry('UMLMessage', TUMLMessage); + BoldObjectClasses.AddObjectEntry('UMLNamespace', TUMLNamespace); + BoldObjectClasses.AddObjectEntry('UMLParameter', TUMLParameter); + BoldObjectClasses.AddObjectEntry('UMLPartition', TUMLPartition); + BoldObjectClasses.AddObjectEntry('UMLRelationship', TUMLRelationship); + BoldObjectClasses.AddObjectEntry('UMLStateMachine', TUMLStateMachine); + BoldObjectClasses.AddObjectEntry('UMLStateVertex', TUMLStateVertex); + BoldObjectClasses.AddObjectEntry('UMLStimulus', TUMLStimulus); + BoldObjectClasses.AddObjectEntry('UMLTaggedValue', TUMLTaggedValue); + BoldObjectClasses.AddObjectEntry('UMLTransition', TUMLTransition); + BoldObjectClasses.AddObjectEntry('UMLActionSequence', TUMLActionSequence); + BoldObjectClasses.AddObjectEntry('UMLCallAction', TUMLCallAction); + BoldObjectClasses.AddObjectEntry('UMLCreateAction', TUMLCreateAction); + BoldObjectClasses.AddObjectEntry('UMLDestroyAction', TUMLDestroyAction); + BoldObjectClasses.AddObjectEntry('UMLReturnAction', TUMLReturnAction); + BoldObjectClasses.AddObjectEntry('UMLSendAction', TUMLSendAction); + BoldObjectClasses.AddObjectEntry('UMLTerminateAction', TUMLTerminateAction); + BoldObjectClasses.AddObjectEntry('UMLUninterpretedAction', TUMLUninterpretedAction); + BoldObjectClasses.AddObjectEntry('UMLAssociationEndRole', TUMLAssociationEndRole); + BoldObjectClasses.AddObjectEntry('UMLCallEvent', TUMLCallEvent); + BoldObjectClasses.AddObjectEntry('UMLChangeEvent', TUMLChangeEvent); + BoldObjectClasses.AddObjectEntry('UMLSignalEvent', TUMLSignalEvent); + BoldObjectClasses.AddObjectEntry('UMLTimeEvent', TUMLTimeEvent); + BoldObjectClasses.AddObjectEntry('UMLBehavioralFeature', TUMLBehavioralFeature); + BoldObjectClasses.AddObjectEntry('UMLStructuralFeature', TUMLStructuralFeature); + BoldObjectClasses.AddObjectEntry('UMLComponentInstance', TUMLComponentInstance); + BoldObjectClasses.AddObjectEntry('UMLDataValue', TUMLDataValue); + BoldObjectClasses.AddObjectEntry('UMLNodeInstance', TUMLNodeInstance); + BoldObjectClasses.AddObjectEntry('UMLObject', TUMLObject); + BoldObjectClasses.AddObjectEntry('UMLUseCaseInstance', TUMLUseCaseInstance); + BoldObjectClasses.AddObjectEntry('UMLGeneralizableElement', TUMLGeneralizableElement); + BoldObjectClasses.AddObjectEntry('UMLDependency', TUMLDependency); + BoldObjectClasses.AddObjectEntry('UMLExtend', TUMLExtend); + BoldObjectClasses.AddObjectEntry('UMLFlow', TUMLFlow); + BoldObjectClasses.AddObjectEntry('UMLGeneralization', TUMLGeneralization); + BoldObjectClasses.AddObjectEntry('UMLInclude', TUMLInclude); + BoldObjectClasses.AddObjectEntry('UMLActivityGraph', TUMLActivityGraph); + BoldObjectClasses.AddObjectEntry('UMLPseudostate', TUMLPseudostate); + BoldObjectClasses.AddObjectEntry('UMLState', TUMLState); + BoldObjectClasses.AddObjectEntry('UMLStubState', TUMLStubState); + BoldObjectClasses.AddObjectEntry('UMLSynchState', TUMLSynchState); + BoldObjectClasses.AddObjectEntry('UMLMethod', TUMLMethod); + BoldObjectClasses.AddObjectEntry('UMLOperation', TUMLOperation); + BoldObjectClasses.AddObjectEntry('UMLReception', TUMLReception); + BoldObjectClasses.AddObjectEntry('UMLAttribute', TUMLAttribute); + BoldObjectClasses.AddObjectEntry('UMLAssociation', TUMLAssociation); + BoldObjectClasses.AddObjectEntry('UMLClassifier', TUMLClassifier); + BoldObjectClasses.AddObjectEntry('UMLCollaboration', TUMLCollaboration); + BoldObjectClasses.AddObjectEntry('UMLPackage', TUMLPackage); + BoldObjectClasses.AddObjectEntry('UMLStereotype', TUMLStereotype); + BoldObjectClasses.AddObjectEntry('UMLAbstraction', TUMLAbstraction); + BoldObjectClasses.AddObjectEntry('UMLBinding', TUMLBinding); + BoldObjectClasses.AddObjectEntry('UMLPermission', TUMLPermission); + BoldObjectClasses.AddObjectEntry('UMLUsage', TUMLUsage); + BoldObjectClasses.AddObjectEntry('UMLCompositeState', TUMLCompositeState); + BoldObjectClasses.AddObjectEntry('UMLFinalState', TUMLFinalState); + BoldObjectClasses.AddObjectEntry('UMLSimpleState', TUMLSimpleState); + BoldObjectClasses.AddObjectEntry('UMLAssociationRole', TUMLAssociationRole); + BoldObjectClasses.AddObjectEntry('UMLActor', TUMLActor); + BoldObjectClasses.AddObjectEntry('UMLClass', TUMLClass); + BoldObjectClasses.AddObjectEntry('UMLClassifierInState', TUMLClassifierInState); + BoldObjectClasses.AddObjectEntry('UMLClassifierRole', TUMLClassifierRole); + BoldObjectClasses.AddObjectEntry('UMLComponent', TUMLComponent); + BoldObjectClasses.AddObjectEntry('UMLDataType', TUMLDataType); + BoldObjectClasses.AddObjectEntry('UMLInterface', TUMLInterface); + BoldObjectClasses.AddObjectEntry('UMLNode', TUMLNode); + BoldObjectClasses.AddObjectEntry('UMLSignal', TUMLSignal); + BoldObjectClasses.AddObjectEntry('UMLUseCase', TUMLUseCase); + BoldObjectClasses.AddObjectEntry('UMLModel', TUMLModel); + BoldObjectClasses.AddObjectEntry('UMLSubsystem', TUMLSubsystem); + BoldObjectClasses.AddObjectEntry('UMLSubmachineState', TUMLSubmachineState); + BoldObjectClasses.AddObjectEntry('UMLActionState', TUMLActionState); + BoldObjectClasses.AddObjectEntry('UMLObjectFlowState', TUMLObjectFlowState); + BoldObjectClasses.AddObjectEntry('UMLException', TUMLException); + BoldObjectClasses.AddObjectEntry('UMLSubactivityState', TUMLSubactivityState); + BoldObjectClasses.AddObjectEntry('UMLCallState', TUMLCallState); end; var CodeDescriptor: TBoldGeneratedCodeDescriptor; initialization - CodeDescriptor := GeneratedCodes.AddGeneratedCodeDescriptorWithFunc('BoldUMLModel', InstallBusinessClasses, InstallObjectListClasses, GeneratedCodeCRC); // do not localize + CodeDescriptor := GeneratedCodes.AddGeneratedCodeDescriptorWithFunc('BoldUMLModel', InstallBusinessClasses, InstallObjectListClasses, GeneratedCodeCRC); finalization GeneratedCodes.Remove(CodeDescriptor); end. - - diff --git a/Source/UMLModel/Core/BoldUMLModelConverter.pas b/Source/UMLModel/Core/BoldUMLModelConverter.pas index 8a00e2b..3028d6f 100644 --- a/Source/UMLModel/Core/BoldUMLModelConverter.pas +++ b/Source/UMLModel/Core/BoldUMLModelConverter.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldUMLModelConverter; interface @@ -49,8 +52,7 @@ implementation BoldMetaSupport, BoldDefaultTaggedValues, BoldUMLModelSupport, - BoldUMLTypes, - UMLConsts; + BoldUMLTypes; class function TBoldModelConverter.UMLModelToMold(UMLModel: TUMLModel): TMoldModel; var @@ -62,7 +64,7 @@ class function TBoldModelConverter.UMLModelToMold(UMLModel: TUMLModel): TMoldMod begin MoldModel := TMoldModel.Create(nil, UMLModel.Name); UMLElementToMoldElement(UMLModel, MoldModel); - BoldLog.StartLog(sConvertingModelToMold); + BoldLog.StartLog('Converting UMLModel to Mold'); BoldLog.ProgressMax := UMLModel.Classes.Count + UMLModel.Associations.Count; UMLRootClass := UMLModelGetUniqueRootClass(UMLModel); @@ -191,7 +193,6 @@ class procedure TBoldModelConverter.UMLAttributeToMoldQualifier(UMLAttribute: TU with MoldQualifier do begin BoldType := UMLAttribute.typeName; - // FIXME more properties end; end; @@ -289,7 +290,7 @@ class procedure TBoldModelConverter.MoldModelToUMLModel(MoldModel: TMoldModel; U UMLAssociation: TUMLAssociation; begin MoldElementToUMLElement(MoldModel, UMLModel); - BoldLog.StartLog(sConvertingModelToUML); + BoldLog.StartLog('Converting MoldModel to UML'); BoldLog.ProgressMax := MoldModel.Classes.Count + MoldModel.Associations.Count; BoldInstalledQueue.DeactivateDisplayQueue; TBoldUMLBoldify.SetRootClassName(UMLModel, MoldModel.RootClass.Name); @@ -304,7 +305,6 @@ class procedure TBoldModelConverter.MoldModelToUMLModel(MoldModel: TMoldModel; U for i := 0 to MoldModel.Associations.Count-1 do begin - // ska alltd skapa ny!!!!! UMLAssociation := GetUMLAssociationByName(MoldModel.Associations[i].name, UMLModel); MoldAssociationToUMLAssociation(MoldModel.Associations[i], UMLAssociation); BoldLog.ProgressStep; @@ -426,7 +426,7 @@ class procedure TBoldModelConverter.MoldMethodToUMLOperation(MoldMethod: TMoldMe begin ReturnUMLParameter := TUMLParameter.Create(UMLOperation.BoldSystem); Parameter.Add(ReturnUMLParameter); - ReturnUMLParameter.Name := 'return'; // do not localize + ReturnUMLParameter.Name := 'return'; ReturnUMLParameter.kind := pdReturn; ReturnUMLParameter.typeName := MoldMethod.ReturnType; ReturnUMLParameter.SetBoldTV(TAG_DELPHINAME, TV_NAME); @@ -443,7 +443,6 @@ class procedure TBoldModelConverter.MoldRoleToUMLAssociationEnd(MoldRole: TMoldR MoldElementToUMLElement(MoldRole, UMLAssociationEnd); with UMLAssociationEnd do begin - // Fixa här if Assigned(MoldRole.OtherEnd.MoldClass) then Type_ := GetUMLClassByName(MoldRole.OtherEnd.MoldClass.name, Association.model) else @@ -469,7 +468,6 @@ class procedure TBoldModelConverter.MoldQualifierToUMLAttribute(MoldQualifier: T with UMLAttribute do begin typeName := MoldQualifier.BoldType; - // FIXME set more properties end; end; @@ -524,4 +522,6 @@ class function TBoldModelConverter.GetUMLAssociationByName(const name: string; U UMLModel.OwnedElement.Add(Result); end; +initialization + end. diff --git a/Source/UMLModel/Core/BoldUMLModelDataModule.pas b/Source/UMLModel/Core/BoldUMLModelDataModule.pas index e57b4ea..6c2b2a1 100644 --- a/Source/UMLModel/Core/BoldUMLModelDataModule.pas +++ b/Source/UMLModel/Core/BoldUMLModelDataModule.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldUMLModelDataModule; interface @@ -47,10 +50,10 @@ procedure EnsureModelEditDataModule; dmModelEdit := TdmModelEdit.Create(nil); DataModuleEnsured := true; end; -end; +end; {$R *.dfm} - + initialization finalization if DataModuleEnsured and assigned(dmModelEdit) then diff --git a/Source/UMLModel/Core/BoldUMLModelSupport.pas b/Source/UMLModel/Core/BoldUMLModelSupport.pas index 634e96a..0322d72 100644 --- a/Source/UMLModel/Core/BoldUMLModelSupport.pas +++ b/Source/UMLModel/Core/BoldUMLModelSupport.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldUMLModelSupport; interface @@ -14,7 +17,6 @@ interface BoldTaggedValueSupport; const - // tags for internal use TAG_TOOLID = 'toolId'; TAG_FLATTENED = 'flattened'; @@ -45,13 +47,12 @@ TBoldUMLSupport = class(TObject) class function GetEnsuredPackage(Package: TUMLPackage; QualifiedPackageName: String): TUMLPackage; public class function UMLModelNameToUMLName(const ModelName: string): string; - class procedure EnsureBoldTaggedValues(Element: TUMLModelElement); // Add missing tagged values + class procedure EnsureBoldTaggedValues(Element: TUMLModelElement); class procedure EnsureBoldTaggedValuesInModel(Model: TUMLModel); class procedure ManipulateAllOwnedElements(Model: TUMLModel; manipulator: TUMLModelElementManipulator); class function EnsuredTaggedValue(Element: TUMLModelElement; const Tag: string): TUMLTaggedValue; class procedure RemoveTaggedValue(Element: TUMLModelElement; const Tag: string); -// class procedure SetDefaultBoldTaggedValues(Element: TUMLModelElement); // Set all tagged values to default - class procedure RelinkSpecializations(GeneralizableElement: TUMLGeneralizableElement); // Give move all inheritance up one step. + class procedure RelinkSpecializations(GeneralizableElement: TUMLGeneralizableElement); class function UniqueName(Element: TUMLModelElement; const SuggestedName: String): String; class procedure AddQualifier(AssociationEnd: TUMLAssociationEnd; Qualifier: TUMLAttribute; const SuggestedName: String); class procedure AddToNamespace(NameSpace: TUMLNamespace; Element: TUMLModelElement; const SuggestedName: String); @@ -77,6 +78,7 @@ TBoldUMLBoldify = class(TPersistent) fMakeDerivedTransient: boolean; class procedure SetBoldifyTaggedValue(element: TUMLModelElement; const Tag: string; const value: string ); class function FullTag(const Tag: string): string; + class function FindClass(Model: TUMLModel; const AClassName: string): TUMLClass; public constructor Create; procedure Boldify(UMLModel: TUMLModel); @@ -100,7 +102,7 @@ TBoldUMLBoldify = class(TPersistent) end; { TBoldUMLOperationSupport } - TBoldUMLOperationSupport = class(TObject) // FIXME move to model editor. TO specific for support + TBoldUMLOperationSupport = class(TObject) public class procedure OverrideInClass(UMLClass: TUMLClassifier; UMLOperation: TUMLOperation); class procedure OverrideInAllSubclasses(UMLClass: TUMLClassifier;UMLOperation: TUMLOperation); @@ -116,8 +118,8 @@ implementation BoldSystemRT, BoldNameExpander, BoldUMLTaggedValues, - BoldGuard, - UMLConsts; + BoldDomainElement, + BoldGuard; { TBoldUMLSupport } @@ -143,7 +145,7 @@ class procedure TBoldUMLSupport.AddToolId(Element: TUMLModelElement; class function TBoldUMLSupport.AllModelParts( UMLModel: TUMLModel): TUMLModelElementList; begin - Result := UMLModel.EvaluateExpressionAsNewElement('UMLModelElement.allInstances->select(model=self)') as TUMLModelElementList // do not localize + Result := UMLModel.EvaluateExpressionAsNewElement('UMLModelElement.allInstances->select(model=self)') as TUMLModelElementList end; class function TBoldUMLSupport.ElementForToolId(UMLModel: TUMLModel; @@ -151,7 +153,7 @@ class function TBoldUMLSupport.ElementForToolId(UMLModel: TUMLModel; begin Result := UMLModel.EvaluateExpressionAsDirectElement ( - Format('UMLTaggedValue.allInstances->select((tag=''%s'') and (value=''%s'')).modelElement->select(model=self)->first', // do not localize + Format('UMLTaggedValue.allInstances->select((tag=''%s'') and (value=''%s'')).modelElement->select(model=self)->first', [BOLDINTERALTVPREFIX + TAG_TOOLID, ToolId]) ) as TUMLModelElement; end; @@ -202,11 +204,11 @@ class procedure TBoldUMLSupport.Flatten(UMLModel: TUMLModel); BoldGuard: IBoldGuard; begin BoldGuard := TBoldGuard.Create(List); - BoldLog.StartLog(sFlatteningModel); + BoldLog.StartLog('Flattening model'); try List := UMLModel.EvaluateExpressionAsNewElement ( - 'allOwnedElement->select(oclIsKindOf(UMLClass) or oclIsKindOf(UMLAssociation))' // do not localize + 'allOwnedElement->select(oclIsKindOf(UMLClass) or oclIsKindOf(UMLAssociation))' ) as TUMLModelElementList; BoldLog.ProgressMax := List.Count; for i := 0 to List.Count - 1 do @@ -286,7 +288,7 @@ class procedure TBoldUMLSupport.ManipulateAllOwnedElements( begin BoldGuard := TBoldGuard.Create(allOwnedElement); manipulator(model); - allOwnedElement:= Model.EvaluateExpressionAsNewElement('UMLModelElement.allInstances->select(model=self)') as TUMLModelElementList; // do not localize + allOwnedElement:= Model.EvaluateExpressionAsNewElement('UMLModelElement.allInstances->select(model=self)') as TUMLModelElementList; for i := 0 to allOwnedElement.Count - 1 do manipulator(allOwnedElement[i]); end; @@ -311,7 +313,6 @@ class procedure TBoldUMLSupport.RelinkSpecializations( Child: TUMLGeneralizableElement; s, g: integer; begin - // replace myself with all my superclasses in children for s := GeneralizableElement.specialization.Count - 1 downto 0 do begin Child := GeneralizableElement.specialization[s].child; @@ -355,7 +356,7 @@ class procedure TBoldUMLSupport.StripToolId(Model: TUMLModel); List := Model.EvaluateExpressionAsNewElement ( Format( - 'UMLTaggedValue.allInstances->select(model=self)->select(name=''%s'')', // do not localize + 'UMLTaggedValue.allInstances->select(model=self)->select(name=''%s'')', [BOLDINTERALTVPREFIX + TAG_TOOLID]) ) as TUMLModelElementList; for i := List.Count - 1 downto 0 do @@ -367,8 +368,7 @@ class procedure TBoldUMLSupport.SubscribeToAllMembers(UMLElement: TUMLModelEleme m: integer; MemberRTInfo: TBoldMemberRTInfo; OtherEnd, RoleRTInfo: TBoldRoleRTInfo; - IsTaggedValue, Subscribe: Boolean; -} + IsTaggedValue, Subscribe: Boolean;} begin UMLElement.AddSmallSubscription(subscriber, [beMemberChanged], breReEvaluate); { @@ -418,7 +418,7 @@ class procedure TBoldUMLSupport.SubscribeToEntireModel(UMLModel: TUMLModel; Subs class function TBoldUMLSupport.UMLModelNameToUMLName(const ModelName: string): string; begin - Result := Copy(ModelName, 4, MAXINT); // Names in UMLModel prefixed by UML. + Result := Copy(ModelName, 4, MAXINT); end; class procedure TBoldUMLSupport.UnFlatten(UMLModel: TUMLModel); @@ -432,9 +432,7 @@ class procedure TBoldUMLSupport.UnFlatten(UMLModel: TUMLModel); begin BoldGuard := TBoldGuard.Create(List); CurrentNameSpace := UMLModel; - List := TUMLModelElementList.Create; - // ordering by name will give topologial sort - List := UMLModel.EvaluateExpressionAsNewElement(Format('ownedElement->select(taggedValue->select(tag=''%s'')->notEmpty)->orderBy(taggedValue[''%s''].value)', // do not localize + List := UMLModel.EvaluateExpressionAsNewElement(Format('ownedElement->select(taggedValue->select(tag=''%s'')->notEmpty)->orderBy(taggedValue[''%s''].value)', [BOLDINTERALTVPREFIX + TAG_UNFLATTENEDNAMESPACE, BOLDINTERALTVPREFIX + TAG_UNFLATTENEDNAMESPACE])) as TUMLModelElementList; ; for i := 0 to List.Count - 1 do @@ -443,11 +441,9 @@ class procedure TBoldUMLSupport.UnFlatten(UMLModel: TUMLModel); UnflattenedNamespaceName := Element.taggedValue[BOLDINTERALTVPREFIX + TAG_UNFLATTENEDNAMESPACE].Value; if UnflattenedNamespaceName <> CurrentNameSpace.qualifiedName then begin - // remove the first part, it is the name of the model System.Delete(UnflattenedNameSpaceName, 1, pos('.', UnflattenedNamespaceName)); CurrentNameSpace := GetEnsuredPackage(UMLModel, UnflattenedNamespaceName); end; - // Set real namespace, and remove tagged value Element.namespace_ := CurrentNameSpace; RemoveTaggedValue(Element, BOLDINTERALTVPREFIX + TAG_UNFLATTENEDNAMESPACE); end; @@ -464,7 +460,7 @@ class function TBoldUMLSupport.UniqueName(Element: TUMLModelElement; const Sugge if i = 0 then Result := SuggestedName else - Result := Format('%s_%d', [SuggestedName, i]); // do not localize + Result := Format('%s_%d', [SuggestedName, i]); ConflictFound := False; if Assigned(Element.namespace_) then ConflictFound := NameInListExceptElement(Result, Element.namespace_.OwnedElement, Element); @@ -490,7 +486,7 @@ procedure TBoldUMLBoldify.Assign(source: TPersistent); DefaultNavigableMultiplicity := TBoldUMLBoldify(Source).DefaultNavigableMultiplicity; end else - raise EBold.Create('TBoldUMLBoldify.Assign'); // do not localize + raise EBold.Create('TBoldUMLBoldify.Assign'); end; procedure TBoldUMLBoldify.Boldify(UMLModel: TUMLModel); @@ -509,24 +505,27 @@ procedure TBoldUMLBoldify.Boldify(UMLModel: TUMLModel); UnnamedAssociationName: string; AssocEnd: TUMLAssociationEnd; RootClassImplicitlyNamed: Boolean; + /// START PATCH ////////////////////////////////////////////////////////////// + NewAttribute: TUMLAttribute; + NewColumnName: string; + /// END PATCH //////////////////////////////////////////////////////////////// begin TBoldUMLSupport.EnsureBoldTaggedValuesInModel(UMLModel); AllClasses := nil; AllAssociations := nil; - BoldLog.StartLog(sBoldifyingModel); + BoldLog.StartLog('Boldifying Model'); try SetBoldifyTaggedValue(UMLModel, TAG_BOLDIFIED, TV_TRUE); - // Create root class if it is missing RootClassName := UMLModel.GetBoldTV(TAG_ROOTCLASS); if RootClassName = '' then begin - RootClassName := 'BusinessClassesRoot'; // do not localize + RootClassName := 'BusinessClassesRoot'; RootClassImplicitlyNamed := true; end else RootClassImplicitlyNamed := false; - Rootclass := UMLModel.EvaluateExpressionAsDirectElement(Format('UMLClass.allInstances->select((model=self) and (name=''%s''))->first', [RootClassName])) as TUMLClass; // do not localize + Rootclass := UMLModel.EvaluateExpressionAsDirectElement(Format('UMLClass.allInstances->select((model=self) and (name=''%s''))->first', [RootClassName])) as TUMLClass; if not Assigned(RootClass) then begin RootClass := TUMLClass.Create(UMLModel.BoldSystem); @@ -543,7 +542,7 @@ procedure TBoldUMLBoldify.Boldify(UMLModel: TUMLModel); end; if Assigned(RootClass.SuperClass) then - raise EBold.Create(sCannotBoldifyIfRootClassHasSuperClass); + raise EBold.Create('Can''t boldify model where root class has superclass'); DefaultSuperClass := GetDefaultSuperClass(UMLModel); if not Assigned(DefaultSuperClass) then @@ -552,9 +551,7 @@ procedure TBoldUMLBoldify.Boldify(UMLModel: TUMLModel); DefaultLinkSuperClass := GetDefaultLinkSuperClass(UMLModel); if not Assigned(DefaultLinkSuperClass) then DefaultLinkSuperClass := RootClass; - - // Fixup Associations. Set default multiplicity, name unnamed associationends, create missing link-classes - AllAssociations := UMLModel.EvaluateExpressionAsNewElement('UMLAssociation.allInstances->select(model=self)') as TUMLAssociationList; // do not localize + AllAssociations := UMLModel.EvaluateExpressionAsNewElement('UMLAssociation.allInstances->select(model=self)') as TUMLAssociationList; BoldLog.ProgressMax := AllAssociations.Count; @@ -584,7 +581,6 @@ procedure TBoldUMLBoldify.Boldify(UMLModel: TUMLModel); AssocEnd.SetBoldTV(TAG_EMBED, TV_FALSE); SetBoldifyTaggedValue(AssocEnd, TAG_WASEMBEDED, TV_TRUE); end; - // Name unnamed associationends if AssocEnd.IsNavigable then begin if AssocEnd.name = '' then @@ -598,15 +594,13 @@ procedure TBoldUMLBoldify.Boldify(UMLModel: TUMLModel); UnnamedAssociationName := UnnamedAssociationName + AssocEnd.type_.name; end else - AssocEnd.name := Format('Role%d', [ConnectionIndex]); // do not localize + AssocEnd.name := Format('Role%d', [ConnectionIndex]); SetBoldifyTaggedValue(AssocEnd, TAG_NONAME, TV_TRUE); end else UnnamedAssociationName := UnnamedAssociationName + AssocEnd.name; end; end; - - // fix implicit names for non named non navigable roles for ConnectionIndex := 0 to Association.Connection.Count - 1 do begin AssocEnd := Association.Connection[ConnectionIndex]; @@ -622,8 +616,6 @@ procedure TBoldUMLBoldify.Boldify(UMLModel: TUMLModel); UnnamedAssociationName := UnnamedAssociationName + AssocEnd.Name; end; end; - - // make association transient if either end is transient if Association.persistent then begin for ConnectionIndex := 0 to Association.Connection.Count - 1 do @@ -637,22 +629,17 @@ procedure TBoldUMLBoldify.Boldify(UMLModel: TUMLModel); end; end; end; - - // make association transient if association class is transient if Association.persistent and assigned(association.class_) and not association.class_.persistent then begin Association.persistent := false; SetBoldifyTaggedValue(Association, TAG_WASPERSISTENT, TV_TRUE) end; - // Name association if unnamed - if Association.name = '' then begin Association.name := UnnamedAssociationName; SetBoldifyTaggedValue(Association, TAG_NONAME, TV_TRUE); end; - // Create link class if needed if not Association.Derived and ( (Association.Connection[0].Multi and Association.Connection[1].Multi) or @@ -664,12 +651,14 @@ procedure TBoldUMLBoldify.Boldify(UMLModel: TUMLModel); ) and not assigned(Association.Class_) then begin - // Note: allowing different names on association and linkclass is not strictly UML. LinkClassName := BoldExpandName(Association.getBoldTV(TAG_LINKCLASSNAME), Association.Name, xtDelphi, -1, TBoldTaggedValueSupport.StringToNationalCharConversion(UMLModel.GetBoldTV(TAG_NATIONALCHARCONVERSION))); if LinkClassName = '' then LinkClassName := Association.Name; - Association.Class_ := TUMLClass.Create(Association.BoldSystem); + Association.Class_ := FindClass(UMLModel, LinkClassName); + if not Assigned(Association.Class_) then + begin + Association.Class_ := TUMLClass.Create(UMLModel.BoldSystem); Association.Class_.namespace_ := Association.namespace_; Association.Class_.Association := Association; Association.Class_.persistent := Association.persistent; @@ -680,19 +669,59 @@ procedure TBoldUMLBoldify.Boldify(UMLModel: TUMLModel); Association.Class_.SetBoldTV(TAG_VERSIONED, TV_TRUE); SetBoldifyTaggedValue(Association.Class_, TAG_AUTOCREATED, TV_TRUE); if (LinkClassName = Association.name) then - Association.Class_.name := Association.name // Allow same name on class and association + Association.Class_.name := Association.name else Association.Class_.name := TBoldUMLSupport.UniqueName(Association.namespace_, LinkClassName); {will generate new name on collission} + end end; BoldLog.ProgressStep; end; - AllClasses := UMLModel.EvaluateExpressionAsNewElement('classes') as TUMLClassList; // do not localize + + AllClasses := UMLModel.EvaluateExpressionAsNewElement('classes') as TUMLClassList; BoldLog.ProgressMax := AllClasses.count; for ClassIndex := 0 to AllClasses.Count - 1 do begin iClass := AllClasses[ClassIndex]; + /// START PATCH ////////////////////////////////////////////////////////// + (************************************************************************* + * Generate buddy for persistent derivied attribute + * - Clone + * - Original: Persistent=false, WasPersistent=True PersistenBuddy=NewName + * - New: Derived=false, Name=p_Originalname, Columnname=OriginalColname + * BoldifyAutoCreate=True, Visibility=Private + *************************************************************************) + for FeatureIndex := 0 to iClass.feature.Count - 1 do + begin + Feature := iClass.feature[FeatureIndex]; + if (Feature is TUMLAttribute) then + with Feature as TUMLAttribute do + if persistent and derived then + begin + NewAttribute := TBoldCopyAndClone.BoldClone(Feature, bcmDeep) as TUMLAttribute; + NewAttribute.owner := iClass; + NewAttribute.name := 'p_'+Feature.name; + NewAttribute.type_ := type_; + //Original + persistent := false; + SetBoldifyTaggedValue(Feature, TAG_WASPERSISTENT, TV_TRUE); + //PersistenBuddy=NewName + //New Clone + SetBoldifyTaggedValue(NewAttribute, TAG_AUTOCREATED, TV_TRUE); + SetBoldifyTaggedValue(NewAttribute, 'persistentClone', Feature.name); + NewAttribute.persistent := true; + NewAttribute.derived := False; + NewAttribute.visibility := vkPrivate; + NewColumnName := NewAttribute.GetBoldTV(TAG_COLUMNNAME); + if NewColumnName=TV_NAME then + NewColumnName := Feature.GetBoldTV(TAG_COLUMNNAME); + if NewColumnName=TV_NAME then + NewColumnName := Feature.name; + NewAttribute.SetBoldTV(TAG_COLUMNNAME, NewColumnName); + end; + end; + /// END PATCH //////////////////////////////////////////////////////////// for FeatureIndex := 0 to iClass.feature.Count - 1 do begin Feature := iClass.feature[FeatureIndex]; @@ -704,8 +733,6 @@ procedure TBoldUMLBoldify.Boldify(UMLModel: TUMLModel); SetBoldifyTaggedValue(Feature, TAG_WASPERSISTENT, TV_TRUE) end; end; - - // Fixup inheritance if not Assigned(iClass.superclass) and (iClass <> RootClass) then begin if iClass.isAssociationClass then @@ -728,12 +755,17 @@ procedure TBoldUMLBoldify.Boldify(UMLModel: TUMLModel); constructor TBoldUMLBoldify.Create; begin fPluralSuffix := ''; - fDefaultNonNavigableMultiplicity := '0..*'; // do not localize - fDefaultNavigableMultiplicity := '0..1'; // do not localize + fDefaultNonNavigableMultiplicity :='0..*'; + fDefaultNavigableMultiplicity := '0..1'; fUnembedMulti := True; fMakeDerivedTransient := True; end; +class function TBoldUMLBoldify.FindClass(Model: TUMLModel; const AClassName: string): TUMLClass; +begin + result := Model.EvaluateExpressionAsDirectElement(Format('UMLClass.allInstances->select((model=self) and (name=''%s''))->first', [AClassName])) as TUMLClass; +end; + class function TBoldUMLBoldify.FullTag(const Tag: string): string; begin Result := BOLDBOLDIFYPREFIX + Tag; @@ -752,28 +784,26 @@ class function TBoldUMLBoldify.GetBoldifyTaggedValue(element: TUMLModelElement; class function TBoldUMLBoldify.GetDefaultLinkSuperClass( Model: TUMLModel): TUMLClass; -begin -{ TODO : change name to fullname when package support done. } - Result := model.EvaluateExpressionAsDirectElement(Format('UMLClass.allInstances->select((model=self) and (name=''%s''))->first', [model.GetBoldTV(TAG_DEFAULTLINKCLASSSUPERCLASS)])) as TUMLClass; // do not localize +begin + Result := model.EvaluateExpressionAsDirectElement(Format('UMLClass.allInstances->select((model=self) and (name=''%s''))->first', [model.GetBoldTV(TAG_DEFAULTLINKCLASSSUPERCLASS)])) as TUMLClass; if not Assigned(Result) then Result := GetDefaultSuperClass(model); end; class function TBoldUMLBoldify.GetDefaultSuperClass( Model: TUMLModel): TUMLClass; -begin -{ TODO : change name to fullname when package support done. } +begin Result := model.EvaluateExpressionAsDirectElement ( - Format('UMLClass.allInstances->select((model=self) and (name=''%s''))->first', [model.GetBoldTV(TAG_DEFAULTSUPERCLASS)]) // do not localize + Format('UMLClass.allInstances->select((model=self) and (name=''%s''))->first', [model.GetBoldTV(TAG_DEFAULTSUPERCLASS)]) ) as TUMLClass; end; class function TBoldUMLBoldify.GetRootClass(Model: TUMLModel): TUMLClass; begin if not IsBoldified(model) then - raise EBold.Create(sCanOnlyBeCalledIfBoldified); - Result := model.EvaluateExpressionAsDirectElement('UMLClass.allInstances->select((model=self) and (generalization->isEmpty))->first') as TUMLClass; // do not localize + raise EBold.Create('TBoldUMLBoldify.GetRootClass: can only be called on boldified model'); + Result := model.EvaluateExpressionAsDirectElement('UMLClass.allInstances->select((model=self) and (generalization->isEmpty))->first') as TUMLClass; end; class function TBoldUMLBoldify.IsAutoCreated( @@ -822,9 +852,9 @@ class procedure TBoldUMLBoldify.UnBoldify(model: TUMLModel); var expr: string; begin - expr := format('%s.allInstances->select(model=self)', [classname]); // do not localize + expr := format('%s.allInstances->select(model=self)', [classname]); if TaggedValue <> '' then - expr := expr + format('->select(taggedValue[''%s''].value=''%s'')', [TaggedValue, Value]); // do not localize + expr := expr + format('->select(taggedValue[''%s''].value=''%s'')', [TaggedValue, Value]); result := model.EvaluateExpressionAsNewElement(expr) as TUMLModelElementList; end; begin @@ -836,15 +866,9 @@ class procedure TBoldUMLBoldify.UnBoldify(model: TUMLModel); AttributesToMakePersistent); SetRootClassname(model, GetRootClass(Model).name); - - // Remove all autocreated elements - TempList := GetNewList('UMLModelElement', BOLDBOLDIFYPREFIX + TAG_AUTOCREATED, TV_TRUE); // do not localize - - // the result of the OCL-expression is immutable. Copy it to a new list + TempList := GetNewList('UMLModelElement', BOLDBOLDIFYPREFIX + TAG_AUTOCREATED, TV_TRUE); ToRemove := TUMLModelElementList.Create; ToRemove.AddList(TempList); - - // Autocreated classes that have been modified should not be removed. for i := ToRemove.Count-1 downto 0 do begin if ToRemove[i] is TUMLClass then @@ -861,7 +885,7 @@ class procedure TBoldUMLBoldify.UnBoldify(model: TUMLModel); while ToRemove.Count > 0 do ToRemove[ToRemove.Count - 1].Delete; - ToUnname := GetNewList('UMLModelElement', BOLDBOLDIFYPREFIX + TAG_NONAME, TV_TRUE); // do not localize + ToUnname := GetNewList('UMLModelElement', BOLDBOLDIFYPREFIX + TAG_NONAME, TV_TRUE); for i := 0 to ToUnname.Count - 1 do begin @@ -869,21 +893,22 @@ class procedure TBoldUMLBoldify.UnBoldify(model: TUMLModel); RemoveBoldifyTaggedValue(ToUnname[i], TAG_NONAME); end; - AssociationsToMakePersistent := GetNewlist('UMLAssociation', BOLDBOLDIFYPREFIX + TAG_WASPERSISTENT, TV_TRUE) as TUMLAssociationList; // do not localize + AssociationsToMakePersistent := GetNewlist('UMLAssociation', BOLDBOLDIFYPREFIX + TAG_WASPERSISTENT, TV_TRUE) as TUMLAssociationList; for i := 0 to AssociationsToMakePersistent.Count - 1 do begin AssociationsToMakePersistent[i].persistent := True; - RemoveBoldifyTaggedValue(AssociationsToMakePersistent[i], TAG_WASPERSISTENT); //!! Skall vara + //RemoveBoldifyTaggedValue(AttributesToMakePersistent[i], TAG_WASPERSISTENT); + RemoveBoldifyTaggedValue(AssociationsToMakePersistent[i], TAG_WASPERSISTENT); end; - AttributesToMakePersistent := GetNewList('UMLAttribute', BOLDBOLDIFYPREFIX + TAG_WASPERSISTENT, TV_TRUE) as TUMLAttributeList; // do not localize + AttributesToMakePersistent := GetNewList('UMLAttribute', BOLDBOLDIFYPREFIX + TAG_WASPERSISTENT, TV_TRUE) as TUMLAttributeList; for i := 0 to AttributesToMakePersistent.Count - 1 do begin AttributesToMakePersistent[i].persistent := True; RemoveBoldifyTaggedValue(AttributesToMakePersistent[i], TAG_WASPERSISTENT); end; - AllAssociationEnds := GetNewList('UMLAssociationEnd') as TUMLAssociationEndList; // do not localize + AllAssociationEnds := GetNewList('UMLAssociationEnd') as TUMLAssociationEndList; for i := 0 to AllAssociationEnds.Count - 1 do begin AssociationEnd := AllAssociationEnds[i]; @@ -915,11 +940,12 @@ class function TBoldCopyAndClone.BoldClone(SourceObject: TBoldObject; Mode: TBol end; class procedure TBoldCopyAndClone.BoldCopy(DestinationObject, SourceObject: TBoldObject; Mode: TBoldCopyMode; StripToolId: Boolean); - - // Note, parameter Mode used in subprocedures procedure CopyAttribute(DestinationAttr, SourceAttr: TBoldAttribute); begin - DestinationAttr.Assign(SourceAttr); + if SourceAttr.IsNull and not DestinationAttr.IsNull and not DestinationAttr.CanSetToNull(nil) then + DestinationAttr.AsIBoldValue[bdepContents].AssignContent(SourceAttr.AsIBoldValue[bdepContents]) + else + DestinationAttr.Assign(SourceAttr); end; procedure CopySingleRole(DestinationRole, SourceRole: TBoldObjectReference); @@ -930,13 +956,13 @@ class procedure TBoldCopyAndClone.BoldCopy(DestinationObject, SourceObject: TBol DestinationRtInfo := DestinationRole.BoldRoleRTInfo; case mode of bcmAttributes: - ; // no action + ; bcmShallow: if (DestinationRtInfo.Aggregation <> akComposite) and DestinationRtInfo.RoleRTInfoOfOtherEnd.IsMultiRole then DestinationRole.BoldObject := SourceRole.BoldObject; bcmDeep: if DestinationRtInfo.Aggregation = akComposite then - DestinationRole.BoldObject := BoldClone(SourceRole.BoldObject, bcmDeep, StripToolId) + DestinationRole.BoldObject := BoldClone(SourceRole.BoldObject, bcmDeep, StripToolId); else if DestinationRtInfo.RoleRTInfoOfOtherEnd.IsMultiRole then DestinationRole.BoldObject := SourceRole.BoldObject; end; @@ -958,7 +984,7 @@ class procedure TBoldCopyAndClone.BoldCopy(DestinationObject, SourceObject: TBol DestinationRtInfo := DestinationRole.BoldRoleRTInfo; case mode of bcmAttributes: - ; // no action + ; bcmShallow: if (DestinationRtInfo.Aggregation <> akComposite) and DestinationRtInfo.RoleRTInfoOfOtherEnd.IsMultiRole then DestinationRole.AddList(SourceRole); @@ -970,7 +996,6 @@ class procedure TBoldCopyAndClone.BoldCopy(DestinationObject, SourceObject: TBol begin SourceSubObject := SourceRole[i]; if (SourceSubObject is TUMLTaggedValue) and (TUMLTaggedValue(SourceSubObject).Tag = BOLDINTERALTVPREFIX + TAG_TOOLID) then - // do nothing, i.e. don't include toolid tag. else DestinationRole.Add(BoldClone(SourceSubObject, bcmDeep, StripToolId)); end; @@ -1003,20 +1028,24 @@ class procedure TBoldCopyAndClone.BoldCopy(DestinationObject, SourceObject: TBol DestinationMember := DestinationObject.BoldMembers[m]; SourceMember := SourceObject.BoldMembers[m]; if SourceMemberRtInfo.IsAttribute then - CopyAttribute(DestinationMember as TBoldAttribute, SourceMember as TBoldAttribute) - else if SourceMemberRTInfo.IsRole then + begin + if DestinationMember.Mutable and not DestinationMember.IsReadOnly then + CopyAttribute(DestinationMember as TBoldAttribute, SourceMember as TBoldAttribute) + else + DestinationMember.AsIBoldValue[bdepContents].AssignContent(SourceMember.AsIBoldValue[bdepContents]); + end + else + if SourceMemberRTInfo.IsRole then begin SourceRoleRTInfo := SourceMemberRTInfo as TBoldRoleRTInfo; - if SourceRoleRTInfo.RoleType = rtRole then + if (SourceRoleRTInfo.RoleType = rtRole) and (mode <> bcmAttributes) then begin if SourceRoleRTInfo.IsSingleRole then CopySingleRole(DestinationMember as TBoldObjectReference, SourceMember as TBoldObjectReference) else if SourceMemberRtInfo.IsMultiRole then CopyMultiRole(DestinationMember as TBoldObjectList, SourceMember as TBoldObjectList) end; - end - else - raise EBoldInternal.CreateFmt(sUnknownTypeOfMember, [classname, SourceMember.DisplayName, SourceMember.Boldtype.ExpressionName]); + end; end; end; end; @@ -1028,7 +1057,6 @@ class function TBoldUMLOperationSupport.ClassHasOperation( Index, Index2: Integer; Operation: TUMLOperation; begin - // kala 990709 returns true if the name and signature are the same. Result := False; for Index := 0 to UMLClass.Feature.Count - 1 do begin @@ -1038,13 +1066,13 @@ class function TBoldUMLOperationSupport.ClassHasOperation( if SameText(Operation.Name, MethodName) then begin if (ParamTypes.Count = Operation.Parameter.Count) or - (ParamTypes.Count = Operation.Parameter.Count - 1) then // -1 special case if there is a return-param, return-params does not affect overloading. kala 990708 + (ParamTypes.Count = Operation.Parameter.Count - 1) then begin Result := True; for Index2 := 0 to ParamTypes.Count - 1 do begin if (UpperCase(ParamTypes[Index2]) <> UpperCase(Operation.Parameter[Index2].typeName)) and - (UpperCase(Operation.Parameter[Index2].typeName) <> UpperCase('Return')) then // CHECKME // do not localize + (UpperCase(Operation.Parameter[Index2].typeName) <> UpperCase('Return')) then begin Result := False; Exit; @@ -1092,4 +1120,6 @@ class procedure TBoldUMLOperationSupport.OverrideInClass( end; end; +initialization + end. diff --git a/Source/UMLModel/Core/BoldUMLModelUpdater.pas b/Source/UMLModel/Core/BoldUMLModelUpdater.pas index ece3245..5f4dcb6 100644 --- a/Source/UMLModel/Core/BoldUMLModelUpdater.pas +++ b/Source/UMLModel/Core/BoldUMLModelUpdater.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldUMLModelUpdater; interface @@ -32,9 +35,9 @@ class procedure TBoldUMLModelUpdater.UpdateModel(ModelToUpdate: TUMLModel); var aList: TUMLModelElementList; begin - aList := ModelToUpdate.BoldSystem.ClassByExpressionName['UMLAssociation'] as TUMLModelElementList; // do not localize + aList := ModelToUpdate.BoldSystem.ClassByExpressionName['UMLAssociation'] as TUMLModelElementList; UpdatePersistentTVs(aList); - aList := ModelToUpdate.BoldSystem.ClassByExpressionName['UMLAttribute'] as TUMLModelElementList; // do not localize + aList := ModelToUpdate.BoldSystem.ClassByExpressionName['UMLAttribute'] as TUMLModelElementList; UpdatePersistentTVs(aList); end; @@ -59,4 +62,6 @@ class procedure TBoldUMLModelUpdater.UpdatePersistentTVs(aList: TUMLModelElement end; end; +initialization + end. diff --git a/Source/UMLModel/Core/BoldUMLModelValidator.pas b/Source/UMLModel/Core/BoldUMLModelValidator.pas index 690f8f1..68d07c1 100644 --- a/Source/UMLModel/Core/BoldUMLModelValidator.pas +++ b/Source/UMLModel/Core/BoldUMLModelValidator.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldUMLModelValidator; interface @@ -47,9 +50,6 @@ TBoldUMLModelValidator = class(TBoldUMLAbstractModelValidator) property TypeNameDictionary: TBoldTypeNameDictionary read fTypeNameDictionary; end; -const - beModelValidated = 1024; - implementation uses @@ -60,7 +60,9 @@ implementation BoldPMappers, BoldDefaultTaggedValues, BoldDefaultStreamNames, - BoldUMLTypes; + BoldUMLTypes, + BoldUMLModelEditForm, + BoldAttributes; resourcestring // Validator errors @@ -99,6 +101,8 @@ implementation sUMVAttributeUnknownType = 'Attribute "%s" has unknown type (%s)'; sUMVAttributeUnknownMapper = 'Attribute "%s" has unknown persistence mapper (%s)'; sUMVAttributeCantStore = 'Attribute "%s" can''t be stored, incompatible persistence mapper'; + sUMVOperationVirtualOperationMissing = 'Overridden operation "%s" has no virtual operation in superclass'; + sUMVOperationVisibilityChanged = 'Overridden operation "%s" has different visibility than the inherited operation in superclass'; sUMVAssociationEndIsMultiWithOtherEndComposite = 'Association end "%s" is multi, but other end is composite'; sUMVAssociationEndUnknownClass = 'Association end "%s" in association "%s" not associated with any class'; sUMVAssociationEndUnknownMapper = 'Unknown association end persistence mapper (%s) in association "%s"'; @@ -106,7 +110,7 @@ implementation sUMVInvalidAssociationEndIndirectAndEmbed = 'Association end "%s" in association "%s" is indirect and embedded'; sUMVInvalidAssociationEndMultiAndEmbed = 'Association end "%s" in association "%s" is multi and embedded'; sUMVInvalidAssociationEndOrderedandSingle = 'Association end "%s" in association "%s" is non-multi and ordered'; - sUMVSingleAssociationEndsEmbeddedInBothEnds = 'Association "%s"s both ends are embedded and single-single ends.'; + sUMVSingleAssociationEndsEmbeddedInBothEnds = 'SingleLink between %s - %s both ends have Embed=True meaning both are persisted in database. Set one side to Embed=False'; sUMVAssociationNeedsTwoRoles = 'Association "%s" must have two assocationEnds'; sUMVAssociationEndNeedsType = 'AssociationEnd "%s" is not assocatied with any class'; sUMVDerivedAssociationCanNotHaveClass = 'Derived association "%s" can not have an association class'; @@ -133,6 +137,7 @@ implementation sUMVRootClassMustHaveName = 'Root class must have name'; sUMVLinkClassWithSuperClassAsEnd = 'LinkClass (%s) must not inherit from any of the ends (%s)'; sUMVAssociationAndClassNotEquallyPersistent = 'Association (%s) and its association class are not equally persistent'; + sUMVClassNameClashWithAttribute = 'Class "%s" has same name as Attribute type'; function IsValidDelphiIdentifier(const Ident: string): Boolean; const @@ -142,9 +147,9 @@ function IsValidDelphiIdentifier(const Ident: string): Boolean; I: Integer; begin Result := False; - if (Length(Ident) = 0) or not (Ident[1] in Alpha) then + if (Length(Ident) = 0) or not CharInSet(Ident[1], Alpha) then Exit; - for I := 2 to Length(Ident) do if not (Ident[I] in AlphaNumeric) then + for I := 2 to Length(Ident) do if not CharInSet(Ident[I], AlphaNumeric) then Exit; Result := True; end; @@ -157,9 +162,9 @@ function IsValidCppIdentifier(const Ident: string): Boolean; I: Integer; begin Result := False; - if (Length(Ident) = 0) or not (Ident[1] in Alpha) then + if (Length(Ident) = 0) or not CharInSet(Ident[1], Alpha) then Exit; - for I := 2 to Length(Ident) do if not (Ident[I] in AlphaNumeric) then + for I := 2 to Length(Ident) do if not CharInSet(Ident[I], AlphaNumeric) then Exit; Result := True; end; @@ -179,9 +184,9 @@ function IsValidSQLIdentifier(const Ident: string): Boolean; I: Integer; begin Result := False; - if (Length(Ident) = 0) or not (Ident[1] in Alpha) then + if (Length(Ident) = 0) or not CharInSet(Ident[1], Alpha) then Exit; - for I := 2 to Length(Ident) do if not (Ident[I] in AlphaNumeric) then + for I := 2 to Length(Ident) do if not CharInSet(Ident[I], AlphaNumeric) then Exit; Result := True; end; @@ -331,100 +336,104 @@ procedure TBoldUMLModelValidator.Validate(TypeNameDictionary: TBoldTypeNameDicti if not(TBoldUMLBoldify.IsBoldified(UMLModel) and TBoldUMLSupport.IsFlattened(UMLModel)) then raise EBoldInternal.Create('Model not Boldified and flattened'); - fTypeNameDictionary := TypeNameDictionary; - - ClearViolations; BoldLog.StartLog('Validating the model'); + BoldModel.StartValidation; + try + fTypeNameDictionary := TypeNameDictionary; - if not assigned(TypeNameDictionary) then - addError('No TypeNameDictionary available', [], UMLModel); + ClearViolations; - if Assigned(UMLModel) then - begin - with UMLModel do - begin - if Name = '' then - AddError(sUMVModelNameEmpty, [], UMLModel); + if not assigned(TypeNameDictionary) then + addError('No TypeNameDictionary available', [], UMLModel); - ValidateNames(UMLModel, UMLModel.Name); + if Assigned(UMLModel) then + begin + with UMLModel do + begin + if Name = '' then + AddError(sUMVModelNameEmpty, [], UMLModel); - Mapper := GetBoldTV(TAG_PMAPPERNAME); + ValidateNames(UMLModel, UMLModel.Name); - if not SameText(Mapper, DEFAULTNAME) and CheckDbStuff then - begin - if not Assigned(BoldSystemPersistenceMappers.DescriptorByName[Mapper]) then - AddError(sUMVModelUnknownMapper, [Mapper, Name], UMLModel); - end; + Mapper := GetBoldTV(TAG_PMAPPERNAME); - Names := TStringList.Create; - SourceCodeNames := TStringList.Create; - ExpressionNames := TStringList.Create; - TableNames := TStringList.Create; + if not SameText(Mapper, DEFAULTNAME) and CheckDbStuff then + begin + if not Assigned(BoldSystemPersistenceMappers.DescriptorByName[Mapper]) then + AddError(sUMVModelUnknownMapper, [Mapper, Name], UMLModel); + end; - for I := 0 to Classes.Count - 1 do - begin - Names.AddObject(AnsiUpperCase(Classes[i].Name), Classes[i]); - SourceCodeNames.AddObject(AnsiUpperCase(ExpandedSourceName(Classes[i])), Classes[i]); - ExpressionNames.AddObject(AnsiUpperCase(Classes[i].ExpandedExpressionName), Classes[i]); - if CheckDBStuff and Classes[i].Persistent then - TableNames.AddObject(AnsiUpperCase(ExpandedDBName(Classes[i])), Classes[i]); - end; - Names.Sort; - SourceCodeNames.Sort; - ExpressionNames.Sort; - TableNames.Sort; - for i := 0 to Classes.Count-2 do - begin - if Names[i] = Names[i + 1] then - AddError(sUMVClassNameExists, [(Names.Objects[i] as TUMLClass).Name], Names.Objects[i] as TUMLClass); + Names := TStringList.Create; + SourceCodeNames := TStringList.Create; + ExpressionNames := TStringList.Create; + TableNames := TStringList.Create; - if (Language <> mvslNone) and (SourceCodeNames[i] = SourceCodeNames[i + 1]) then + for I := 0 to Classes.Count - 1 do begin - case Language of - mvslDelphi: ErrorStr := sUMVDelphiNameExists; - mvslCpp: ErrorStr := sUMVCppNameExists - else ErrorStr := 'Unknown source language in validator'; - end; - AddError(ErrorStr, [ExpandedSourceName(SourceCodeNames.Objects[i] as TUMLClass), - (SourceCodeNames.Objects[i] as TUMLClass).Name], - SourceCodeNames.Objects[i] as TUMLClass) + Names.AddObject(AnsiUpperCase(Classes[i].Name), Classes[i]); + SourceCodeNames.AddObject(AnsiUpperCase(ExpandedSourceName(Classes[i])), Classes[i]); + ExpressionNames.AddObject(AnsiUpperCase(Classes[i].ExpandedExpressionName), Classes[i]); + if CheckDBStuff and Classes[i].Persistent then + TableNames.AddObject(AnsiUpperCase(ExpandedDBName(Classes[i])), Classes[i]); end; + Names.Sort; + SourceCodeNames.Sort; + ExpressionNames.Sort; + TableNames.Sort; + for i := 0 to Classes.Count-2 do + begin + if Names[i] = Names[i + 1] then + AddError(sUMVClassNameExists, [(Names.Objects[i] as TUMLClass).Name], Names.Objects[i] as TUMLClass); + + if (Language <> mvslNone) and (SourceCodeNames[i] = SourceCodeNames[i + 1]) then + begin + case Language of + mvslDelphi: ErrorStr := sUMVDelphiNameExists; + mvslCpp: ErrorStr := sUMVCppNameExists + else ErrorStr := 'Unknown source language in validator'; + end; + AddError(ErrorStr, [ExpandedSourceName(SourceCodeNames.Objects[i] as TUMLClass), + (SourceCodeNames.Objects[i] as TUMLClass).Name], + SourceCodeNames.Objects[i] as TUMLClass) + end; - if ExpressionNames[i] = ExpressionNames[i + 1] then - AddError(sUMVExpressionNameExists, [(ExpressionNames.Objects[i] as TUMLClass).ExpandedExpressionName, - (ExpressionNames.Objects[i] as TUMLClass).Name], - ExpressionNames.Objects[i] as TUMLClass); + if ExpressionNames[i] = ExpressionNames[i + 1] then + AddError(sUMVExpressionNameExists, [(ExpressionNames.Objects[i] as TUMLClass).ExpandedExpressionName, + (ExpressionNames.Objects[i] as TUMLClass).Name], + ExpressionNames.Objects[i] as TUMLClass); - if (i < TableNames.Count - 1) and (TableNames[i] = TableNames[i + 1]) and CheckDbStuff then - AddError(sUMVTableNameExists, - [ExpandedDBName(TableNames.Objects[i] as TUMLClass), - (TableNames.Objects[i] as TUMLClass).Name, - (TableNames.Objects[i + 1] as TUMLClass).Name], - TableNames.Objects[i] as TUMLClass); - end; - Names.Free; - SourceCodeNames.Free; - ExpressionNames.Free; - TableNames.Free; + if (i < TableNames.Count - 1) and (TableNames[i] = TableNames[i + 1]) and CheckDbStuff then + AddError(sUMVTableNameExists, + [ExpandedDBName(TableNames.Objects[i] as TUMLClass), + (TableNames.Objects[i] as TUMLClass).Name, + (TableNames.Objects[i + 1] as TUMLClass).Name], + TableNames.Objects[i] as TUMLClass); + end; + Names.Free; + SourceCodeNames.Free; + ExpressionNames.Free; + TableNames.Free; - BoldLog.ProgressMax := UMLModel.Classes.Count + UMLModel.Associations.Count; + BoldLog.ProgressMax := UMLModel.Classes.Count + UMLModel.Associations.Count; - for I := 0 to UMLModel.Classes.Count - 1 do - begin - ValidateClass(UMLModel.Classes[I]); - BoldLog.ProgressStep; - end; - for I := 0 to UMLModel.Associations.Count - 1 do - begin - ValidateAssociation(UMLModel.Associations[I]); - BoldLog.ProgressStep; + for I := 0 to UMLModel.Classes.Count - 1 do + begin + ValidateClass(UMLModel.Classes[I]); + BoldLog.ProgressStep; + end; + for I := 0 to UMLModel.Associations.Count - 1 do + begin + ValidateAssociation(UMLModel.Associations[I]); + BoldLog.ProgressStep; + end; + ValidateDuplicates(UMLModel); end; - ValidateDuplicates(UMLModel); end; + finally + BoldLog.EndLog; + BoldModel.EndValidation; end; - BoldLog.EndLog; - UMLModel.SendEvent(beModelValidated); end; procedure TBoldUMLModelValidator.ValidateAttribute(attribute: TUMLAttribute); @@ -435,6 +444,8 @@ procedure TBoldUMLModelValidator.ValidateAttribute(attribute: TUMLAttribute); Mappername: String; TypeDescriptor: TBoldMemberTypeDescriptor; Mapping: TBoldTypeNameMapping; + Length: Integer; + aValueSet: TBAValueSet; begin ValidateFeature(attribute); if attribute.Name = '' then @@ -478,6 +489,33 @@ procedure TBoldUMLModelValidator.ValidateAttribute(attribute: TUMLAttribute); if CheckDbStuff and Attribute.Derived and Attribute.EffectivePersistent then AddHint(sUMVAttributeDerivedAndPersistent, [Owner.Name + '.' + Name], Attribute); + Length := StrToIntDef(GetBoldTV(TAG_LENGTH), 0); + if Length <= 0 then begin + if SameText(DelphiTypeName, 'TBAString') or + SameText(DelphiTypeName, 'TBAWideString') or + SameText(DelphiTypeName, 'TBAAnsiString') or + SameText(DelphiTypeName, 'TBAUnicodeString') or + SameText(DelphiTypeName, 'TBATrimmedString') then + begin + AddHint('%s: String has no fixed length. For unlimited length use Text instead', [Owner.Name + '.' + Name], attribute); + end; + end; + + if Assigned(MemberClass) and MemberClass.InheritsFrom(TBAValueSet) then begin + aValueSet := MemberClass.Create as TBAValueSet; + try + if (aValueSet.Values.GetFirstValue <> nil) and + (aValueSet.Values.GetFirstValue.StringRepresentationCount <= 2) then + begin + AddHint('%s: ValueSet %s is not comparable without second String Representation', [Owner.Name + '.' + Name, delphiTypeName], attribute); + end; + finally + aValueSet.Free; + end; + end; + +// if attribute.columnIndex and not attribute.persistent then +// AddHint('%s: An index for the column %s was set, but this attribute isn''t persistent', [owner.name, attribute.name], attribute); end; end; end; @@ -497,14 +535,13 @@ procedure TBoldUMLModelValidator.ValidateClass(aClass: TUMLClass); for I := 0 to aClass.Feature.Count - 1 do if aClass.Feature[i] is TUMLAttribute then begin - attr := aClass.Feature[I] as TUMLAttribute; - if Attr.EffectivePersistent and TVIsFalse(Attr.GetBoldTV(TAG_ALLOWNULL)) then - result := true; - end; + attr := aClass.Feature[I] as TUMLAttribute; + if Attr.EffectivePersistent and TVIsFalse(Attr.GetBoldTV(TAG_ALLOWNULL)) then + result := true; + end; end; begin - // check model name if aClass.Name = '' then begin AddError(sUMVClassNameEmpty, [], aClass); @@ -512,6 +549,9 @@ procedure TBoldUMLModelValidator.ValidateClass(aClass: TUMLClass); end; ValidateNames(aClass, aClass.Name); + if Assigned(BoldMemberTypes.DescriptorByDelphiName[aClass.Name]) then + AddError(sUMVClassNameClashWithAttribute, [aClass.name], AClass); + if aClass.Persistent and CheckDBStuff then begin if (aClass.GetBoldTV(TAG_TABLEMAPPING) = TV_TABLEMAPPING_IMPORTED) and @@ -638,7 +678,7 @@ procedure CheckAndAddAssociationEnd(AssoEnd: TUMLAssociationEnd); mvslDelphi: CheckAndAddName(SourceNames, aClass.Name, ExpandedSourceName(aClass.Feature[i]), aClass.Feature[i], sUMVDelphiNameExists2, reported, false); mvslCpp: CheckAndAddName(SourceNames, aClass.Name, ExpandedSourceName(aClass.Feature[i]), aClass.Feature[i], sUMVCppNameExists2, reported, false); end; - + if (aClass.Feature[i] is TUMLAttribute) and (aClass.Feature[i] as TUMLAttribute).EffectivePersistent and CheckDbStuff and @@ -726,10 +766,9 @@ procedure TBoldUMLModelValidator.ValidateAssociation(association: TUMLAssociatio if end0.Name = end1.Name then AddError(sUMVDuplicateAssociationEndName, [Association.Name, end0.Name], Association); - if CheckDbStuff and (not (end0.Multi or end1.Multi)) and - TVIsTrue(end0.GetBoldTV('Embed')) and - TVIsTrue(end1.GetBoldTV('Embed')) then - AddHint(sUMVSingleAssociationEndsEmbeddedInBothEnds, [Association.name], Association); + if not Derived and persistent and CheckDbStuff and (not (end0.Multi or end1.Multi)) and + TVIsTrue(end0.GetBoldTV('Embed')) and TVIsTrue(end1.GetBoldTV('Embed')) then + AddError(sUMVSingleAssociationEndsEmbeddedInBothEnds, [end0.AsString, end1.AsString], Association); for I := 0 to Connection.Count - 1 do ValidateAssociationEnd(Connection[I] as TUMLAssociationEnd); @@ -739,10 +778,59 @@ procedure TBoldUMLModelValidator.ValidateAssociation(association: TUMLAssociatio procedure TBoldUMLModelValidator.ValidateOperation(operation: TUMLOperation); var i: Integer; + bInheritedOperationFound: Boolean; + aClass: TUMLClassifier; + aFeature: TUMLFeature; begin ValidateFeature(operation); for i := 0 to operation.Parameter.Count - 1 do ValidateParameter(operation.Parameter[i] as TUMLParameter); + + if operation.GetBoldTV(TAG_DELPHIOPERATIONKIND) = + TV_DELPHIOPERATIONKIND_OVERRIDE then + begin + bInheritedOperationFound := False; + aClass := operation.owner.superclass; + aFeature := nil; + while Assigned(aClass) and not bInheritedOperationFound do begin + for i := 0 to aClass.feature.Count - 1 do begin + aFeature := aClass.feature[i]; + if (aFeature is TUMLOperation) and + BoldAnsiEqual(aFeature.name, operation.name) then + begin + bInheritedOperationFound := True; + Break; + end; + end; + aClass := aClass.superclass; + end; + if bInheritedOperationFound then begin + if operation.visibility <> aFeature.visibility then begin + AddHint(sUMVOperationVisibilityChanged, + [Operation.owner.name + '.' + Operation.name], Operation); + end; + end else begin + // Search for framework method + for i := 0 to Length(FrameworkMethods) - 1 do begin + if BoldAnsiEqual(TBoldModelEditFrm.GetMethodName(FrameworkMethods[i]), + operation.name) then + begin + if TBoldModelEditFrm.GetMethodVisibility(FrameworkMethods[i]) <> + operation.visibility then + begin + AddHint(sUMVOperationVisibilityChanged, + [Operation.owner.name + '.' + Operation.name], Operation); + end; + bInheritedOperationFound := True; + Break; + end; + end; + if not bInheritedOperationFound then begin + AddWarning(sUMVOperationVirtualOperationMissing, + [Operation.owner.name + '.' + Operation.name], Operation); + end; + end; + end; end; procedure TBoldUMLModelValidator.ValidateParameter(parameter: TUMLParameter); @@ -786,8 +874,9 @@ procedure TBoldUMLModelValidator.ValidateAssociationEnd(associationEnd: TUMLAsso if associationEnd.IsNavigable and associationEnd.Multi and (associationEnd.OtherEnd.Aggregation = akComposite) then AddError(sUMVAssociationEndIsMultiWithOtherEndComposite, [associationEnd.Name], AssociationEnd); - if not associationEnd.Multi and not associationEnd.IsNavigable then - AddHint(sUMVAssociationEndIsSingleAndNotNavigable, [associationEnd.Name], AssociationEnd); + // not really needed, it blows up the validation result +// if not associationEnd.Multi and not associationEnd.IsNavigable then +// AddHint(sUMVAssociationEndIsSingleAndNotNavigable, [associationEnd.Name], AssociationEnd); if not associationEnd.Multi and associationEnd.isOrdered then addHint(sUMVInvalidAssociationEndOrderedandSingle, [associationEnd.Name, @@ -915,7 +1004,7 @@ procedure TBoldUMLModelValidator.ValidateNames(Element: TUMLModelElement; Elemen end; stored := stored and (element.GetBoldTV(TAG_STORAGE) <> TV_STORAGE_EXTERNAL); - + if Stored and CheckDBStuff then begin if element is TUMLClass then @@ -952,7 +1041,7 @@ function TBoldUMLModelValidator.CheckDBStuff: Boolean; function TBoldUMLModelValidator.CheckAnsiSQLStuff: Boolean; begin - result := CheckDBStuff; // FIXME add info to SQLDatabaseConfig for this? + result := CheckDBStuff; end; function TBoldUMLModelValidator.NationalCharConversion: TBoldNationalCharConversion; @@ -995,4 +1084,6 @@ destructor TBoldUMLModelValidator.Destroy; inherited; end; +initialization + end. diff --git a/Source/UMLModel/Core/BoldUMLModel_Interface.inc b/Source/UMLModel/Core/BoldUMLModel_Interface.inc index f56973c..4d92053 100644 --- a/Source/UMLModel/Core/BoldUMLModel_Interface.inc +++ b/Source/UMLModel/Core/BoldUMLModel_Interface.inc @@ -2,7 +2,7 @@ (* This file is autogenerated *) (* Any manual changes will be LOST! *) (*****************************************) -(* Generated 2002-06-19 17:13:58 *) +(* Generated 1.9.2016 23:18:13 *) (*****************************************) (* This file should be stored in the *) (* same directory as the form/datamodule *) @@ -487,16 +487,16 @@ type private function _Get_M_visibility: TBAVisibilityKind; function _Getvisibility: TVisibilityKind; - procedure _Setvisibility(NewValue: TVisibilityKind); + procedure _Setvisibility(const NewValue: TVisibilityKind); function _Get_M_alias: TBAString; function _Getalias: String; - procedure _Setalias(NewValue: String); + procedure _Setalias(const NewValue: String); function _Getpackage: TUMLPackage; function _Get_M_package: TBoldObjectReference; - procedure _Setpackage(value: TUMLPackage); + procedure _Setpackage(const value: TUMLPackage); function _GetmodelElement: TUMLModelElement; function _Get_M_modelElement: TBoldObjectReference; - procedure _SetmodelElement(value: TUMLModelElement); + procedure _SetmodelElement(const value: TUMLModelElement); protected public property M_visibility: TBAVisibilityKind read _Get_M_visibility; @@ -513,13 +513,13 @@ type private function _Get_M_visibility: TBAVisibilityKind; function _Getvisibility: TVisibilityKind; - procedure _Setvisibility(NewValue: TVisibilityKind); + procedure _Setvisibility(const NewValue: TVisibilityKind); function _GetresidentElement: TUMLComponent; function _Get_M_residentElement: TBoldObjectReference; - procedure _SetresidentElement(value: TUMLComponent); + procedure _SetresidentElement(const value: TUMLComponent); function _Getresidence: TUMLModelElement; function _Get_M_residence: TBoldObjectReference; - procedure _Setresidence(value: TUMLModelElement); + procedure _Setresidence(const value: TUMLModelElement); protected public property M_visibility: TBAVisibilityKind read _Get_M_visibility; @@ -686,13 +686,13 @@ type private function _GetmodelElement2: TUMLModelElement; function _Get_M_modelElement2: TBoldObjectReference; - procedure _SetmodelElement2(value: TUMLModelElement); + procedure _SetmodelElement2(const value: TUMLModelElement); function _GetmodelElement: TUMLModelElement; function _Get_M_modelElement: TBoldObjectReference; - procedure _SetmodelElement(value: TUMLModelElement); + procedure _SetmodelElement(const value: TUMLModelElement); function _GetdefaultElement: TUMLModelElement; function _Get_M_defaultElement: TBoldObjectReference; - procedure _SetdefaultElement(value: TUMLModelElement); + procedure _SetdefaultElement(const value: TUMLModelElement); protected public property M_modelElement2: TBoldObjectReference read _Get_M_modelElement2; @@ -710,11 +710,10 @@ type function _GetViolation: TViolationList; function _GetUMLModel: TUMLModel; function _Get_M_UMLModel: TBoldObjectReference; - procedure _SetUMLModel(value: TUMLModel); + procedure _SetUMLModel(const value: TUMLModel); protected procedure _HighestSeverity_DeriveAndSubscribe(DerivedObject: TObject; Subscriber: TBoldSubscriber); virtual; - function GetDeriveMethodForMember(Member: TBoldMember): TBoldDeriveAndResubscribe; override; - function GetReverseDeriveMethodForMember(Member: TBoldMember): TBoldReverseDerive; override; + function GetDeriveMethodForMember(MemberIndex: Integer): TBoldDeriveAndResubscribe; override; public property M_HighestSeverity: TBASeverity read _Get_M_HighestSeverity; property M_Violation: TViolationList read _GetViolation; @@ -728,16 +727,16 @@ type private function _Get_M_Description: TBAString; function _GetDescription: String; - procedure _SetDescription(NewValue: String); + procedure _SetDescription(const NewValue: String); function _Get_M_Severity: TBASeverity; function _GetSeverity: TSeverity; - procedure _SetSeverity(NewValue: TSeverity); + procedure _SetSeverity(const NewValue: TSeverity); function _GetValidator: TValidator; function _Get_M_Validator: TBoldObjectReference; - procedure _SetValidator(value: TValidator); + procedure _SetValidator(const value: TValidator); function _GetModelElement: TUMLModelElement; function _Get_M_ModelElement: TBoldObjectReference; - procedure _SetModelElement(value: TUMLModelElement); + procedure _SetModelElement(const value: TUMLModelElement); protected public property M_Description: TBAString read _Get_M_Description; @@ -754,23 +753,23 @@ type private function _Get_M_name: TBAString; function _Getname: String; - procedure _Setname(NewValue: String); + procedure _Setname(const NewValue: String); function _Get_M_visibility: TBAVisibilityKind; function _Getvisibility: TVisibilityKind; - procedure _Setvisibility(NewValue: TVisibilityKind); + procedure _Setvisibility(const NewValue: TVisibilityKind); function _Get_M_isSpecification: TBABoolean; function _GetisSpecification: boolean; - procedure _SetisSpecification(NewValue: boolean); + procedure _SetisSpecification(const NewValue: boolean); function _Get_M_qualifiedName: TBAString; function _GetqualifiedName: String; function _Get_M_stereotypeName: TBAString; function _GetstereotypeName: String; - procedure _SetstereotypeName(NewValue: String); + procedure _SetstereotypeName(const NewValue: String); function _Get_M_documentation: TBAString; function _Getdocumentation: String; function _Get_M_derived: TBABoolean; function _Getderived: boolean; - procedure _Setderived(NewValue: boolean); + procedure _Setderived(const NewValue: boolean); function _Getbehavior: TUMLStateMachineList; function _Getcollaboration: TUMLCollaborationList; function _GetcollaborationcollaborationconstrainingElement: TcollaborationconstrainingElementList; @@ -786,7 +785,7 @@ type function _GettargetFlowtargetFlowtarget: TtargetFlowtargetList; function _Getbinding: TUMLBinding; function _Get_M_binding: TBoldObjectReference; - procedure _Setbinding(value: TUMLBinding); + procedure _Setbinding(const value: TUMLBinding); function _GetsupplierDependency: TUMLDependencyList; function _GetsupplierDependencysuppliersupplierDependency: TsuppliersupplierDependencyList; function _Getconstraint: TUMLConstraintList; @@ -800,36 +799,36 @@ type function _GetcommentcommentannotatedElement: TcommentannotatedElementList; function _Getnamespace_: TUMLNamespace; function _Get_M_namespace_: TBoldObjectReference; - procedure _Setnamespace_(value: TUMLNamespace); + procedure _Setnamespace_(const value: TUMLNamespace); function _GettaggedValue: TUMLTaggedValueList; function _Get_Q_taggedValue(tag: String): TUMLTaggedValue; function _Getstereotype: TUMLStereotype; function _Get_M_stereotype: TBoldObjectReference; - procedure _Setstereotype(value: TUMLStereotype); + procedure _Setstereotype(const value: TUMLStereotype); function _Getmodel: TUMLModel; function _Get_M_model: TBoldObjectReference; - procedure _Setmodel(value: TUMLModel); + procedure _Setmodel(const value: TUMLModel); function _GetqualifyingOwner: TUMLModelElement; function _Get_M_qualifyingOwner: TBoldObjectReference; - procedure _SetqualifyingOwner(value: TUMLModelElement); + procedure _SetqualifyingOwner(const value: TUMLModelElement); function _GetelementImport: TUMLElementImportList; - function FindTaggedValue(TagName: String): TUMLTaggedValue; + function FindTaggedValue(TagName: String): TUMLTaggedValue; protected procedure _stereotypeName_DeriveAndSubscribe(DerivedObject: TObject; Subscriber: TBoldSubscriber); virtual; procedure _stereotypeName_ReverseDerive(DerivedObject: TObject); virtual; procedure _documentation_DeriveAndSubscribe(DerivedObject: TObject; Subscriber: TBoldSubscriber); virtual; procedure _derived_DeriveAndSubscribe(DerivedObject: TObject; Subscriber: TBoldSubscriber); virtual; procedure _derived_ReverseDerive(DerivedObject: TObject); virtual; - function GetDeriveMethodForMember(Member: TBoldMember): TBoldDeriveAndResubscribe; override; - function GetReverseDeriveMethodForMember(Member: TBoldMember): TBoldReverseDerive; override; - public - function ExpandedExpressionName: String; virtual; - function GetTaggedValue(TagName: String): String; - procedure SetTaggedValue(TagName: String; Value: String); - procedure DeleteTaggedValue(TagName: String); - procedure EnsureTaggedValue(TagName: String; DefaultValue: String); - function GetBoldTV(const TagName: String): String; - procedure SetBoldTV(const TagName: String; const Value: String); + function GetDeriveMethodForMember(MemberIndex: Integer): TBoldDeriveAndResubscribe; override; + function GetReverseDeriveMethodForMember(MemberIndex: Integer): TBoldReverseDerive; override; + public + function expandedExpressionName: String; virtual; + function GetTaggedValue(TagName: String): String; + procedure SetTaggedValue(TagName: String; Value: String); + procedure DeleteTaggedValue(TagName: String); + procedure EnsureTaggedValue(TagName: String; DefaultValue: String); + function GetBoldTV(const TagName: String): String; + procedure SetBoldTV(const TagName: String; const Value: String); property M_name: TBAString read _Get_M_name; property M_visibility: TBAVisibilityKind read _Get_M_visibility; property M_isSpecification: TBABoolean read _Get_M_isSpecification; @@ -912,24 +911,24 @@ type private function _Get_M_recurrence: TBAString; function _Getrecurrence: String; - procedure _Setrecurrence(NewValue: String); + procedure _Setrecurrence(const NewValue: String); function _Get_M_target: TBAString; function _Gettarget: String; - procedure _Settarget(NewValue: String); + procedure _Settarget(const NewValue: String); function _Get_M_isAsynchronous: TBABoolean; function _GetisAsynchronous: boolean; - procedure _SetisAsynchronous(NewValue: boolean); + procedure _SetisAsynchronous(const NewValue: boolean); function _Get_M_script: TBAString; function _Getscript: String; - procedure _Setscript(NewValue: String); + procedure _Setscript(const NewValue: String); function _Gettransition: TUMLTransition; function _Get_M_transition: TBoldObjectReference; - procedure _Settransition(value: TUMLTransition); + procedure _Settransition(const value: TUMLTransition); function _GetactualArgument: TUMLArgumentList; function _Getstimulus: TUMLStimulusList; function _GetactionSequence: TUMLActionSequence; function _Get_M_actionSequence: TBoldObjectReference; - procedure _SetactionSequence(value: TUMLActionSequence); + procedure _SetactionSequence(const value: TUMLActionSequence); function _Getmessage_: TUMLMessageList; protected public @@ -957,10 +956,10 @@ type private function _Get_M_value: TBAString; function _Getvalue: String; - procedure _Setvalue(NewValue: String); + procedure _Setvalue(const NewValue: String); function _Getaction: TUMLAction; function _Get_M_action: TBoldObjectReference; - procedure _Setaction(value: TUMLAction); + procedure _Setaction(const value: TUMLAction); protected public property M_value: TBAString read _Get_M_value; @@ -973,29 +972,29 @@ type private function _Get_M_isNavigable: TBABoolean; function _GetisNavigable: boolean; - procedure _SetisNavigable(NewValue: boolean); + procedure _SetisNavigable(const NewValue: boolean); function _Get_M_ordering: TBAOrderingKind; function _Getordering: TOrderingKind; - procedure _Setordering(NewValue: TOrderingKind); + procedure _Setordering(const NewValue: TOrderingKind); function _Get_M_aggregation: TBAAggregationKind; function _Getaggregation: TAggregationKind; - procedure _Setaggregation(NewValue: TAggregationKind); + procedure _Setaggregation(const NewValue: TAggregationKind); function _Get_M_targetScope: TBAScopeKind; function _GettargetScope: TScopeKind; - procedure _SettargetScope(NewValue: TScopeKind); + procedure _SettargetScope(const NewValue: TScopeKind); function _Get_M_multiplicity: TBAString; function _Getmultiplicity: String; - procedure _Setmultiplicity(NewValue: String); + procedure _Setmultiplicity(const NewValue: String); function _Get_M_changeability: TBAChangeableKind; function _Getchangeability: TChangeableKind; - procedure _Setchangeability(NewValue: TChangeableKind); + procedure _Setchangeability(const NewValue: TChangeableKind); function _Get_M_multi: TBABoolean; function _Getmulti: boolean; function _Get_M_mandatory: TBABoolean; function _Getmandatory: boolean; function _Get_M_isOrdered: TBABoolean; function _GetisOrdered: boolean; - procedure _SetisOrdered(NewValue: boolean); + procedure _SetisOrdered(const NewValue: boolean); function _GetlinkEnd: TUMLLinkEndList; function _GetassociationEndRole: TUMLAssociationEndRoleList; function _Getqualifier: TUMLAttributeList; @@ -1003,23 +1002,23 @@ type function _Getparticipantspecification: TparticipantspecificationList; function _Gettype_: TUMLClassifier; function _Get_M_type_: TBoldObjectReference; - procedure _Settype_(value: TUMLClassifier); + procedure _Settype_(const value: TUMLClassifier); function _GetotherEnd: TUMLAssociationEnd; function _Get_M_otherEnd: TBoldObjectReference; - procedure _SetotherEnd(value: TUMLAssociationEnd); + procedure _SetotherEnd(const value: TUMLAssociationEnd); function _Getassociation: TUMLAssociation; function _Get_M_association: TBoldObjectReference; - procedure _Setassociation(value: TUMLAssociation); + procedure _Setassociation(const value: TUMLAssociation); protected procedure _multi_DeriveAndSubscribe(DerivedObject: TObject; Subscriber: TBoldSubscriber); virtual; procedure _mandatory_DeriveAndSubscribe(DerivedObject: TObject; Subscriber: TBoldSubscriber); virtual; procedure _isOrdered_DeriveAndSubscribe(DerivedObject: TObject; Subscriber: TBoldSubscriber); virtual; procedure _isOrdered_ReverseDerive(DerivedObject: TObject); virtual; - function GetDeriveMethodForMember(Member: TBoldMember): TBoldDeriveAndResubscribe; override; - function GetReverseDeriveMethodForMember(Member: TBoldMember): TBoldReverseDerive; override; + function GetDeriveMethodForMember(MemberIndex: Integer): TBoldDeriveAndResubscribe; override; + function GetReverseDeriveMethodForMember(MemberIndex: Integer): TBoldReverseDerive; override; public - function GetOtherEnd: TUMLAssociationEnd; - function GetQualifierByName(InName: String): TUMLAttribute; + function GetOtherEnd: TUMLAssociationEnd; + function GetQualifierByName(InName: String): TUMLAttribute; function ExpandedExpressionName: String; override; property M_isNavigable: TBABoolean read _Get_M_isNavigable; property M_ordering: TBAOrderingKind read _Get_M_ordering; @@ -1061,16 +1060,16 @@ type private function _Getvalue: TUMLInstance; function _Get_M_value: TBoldObjectReference; - procedure _Setvalue(value: TUMLInstance); + procedure _Setvalue(const value: TUMLInstance); function _Getattribute: TUMLAttribute; function _Get_M_attribute: TBoldObjectReference; - procedure _Setattribute(value: TUMLAttribute); + procedure _Setattribute(const value: TUMLAttribute); function _Getinstance: TUMLInstance; function _Get_M_instance: TBoldObjectReference; - procedure _Setinstance(value: TUMLInstance); + procedure _Setinstance(const value: TUMLInstance); function _GetlinkEnd: TUMLLinkEnd; function _Get_M_linkEnd: TBoldObjectReference; - procedure _SetlinkEnd(value: TUMLLinkEnd); + procedure _SetlinkEnd(const value: TUMLLinkEnd); protected public property M_value: TBoldObjectReference read _Get_M_value; @@ -1099,12 +1098,12 @@ type private function _Get_M_body: TBAString; function _Getbody: String; - procedure _Setbody(NewValue: String); + procedure _Setbody(const NewValue: String); function _GetconstrainedElement: TUMLModelElementList; function _GetconstrainedElementconstrainedElementconstraint: TconstrainedElementconstraintList; function _GetconstrainedElement2: TUMLStereotype; function _Get_M_constrainedElement2: TBoldObjectReference; - procedure _SetconstrainedElement2(value: TUMLStereotype); + procedure _SetconstrainedElement2(const value: TUMLStereotype); protected public property M_body: TBAString read _Get_M_body; @@ -1139,10 +1138,10 @@ type private function _Get_M_location: TBAString; function _Getlocation: String; - procedure _Setlocation(NewValue: String); + procedure _Setlocation(const NewValue: String); function _GetuseCase: TUMLUseCase; function _Get_M_useCase: TBoldObjectReference; - procedure _SetuseCase(value: TUMLUseCase); + procedure _SetuseCase(const value: TUMLUseCase); function _Getextend: TUMLExtendList; function _GetextensionPointextend: TextensionPointextendList; protected @@ -1161,15 +1160,13 @@ type private function _Get_M_ownerScope: TBAScopeKind; function _GetownerScope: TScopeKind; - procedure _SetownerScope(NewValue: TScopeKind); + procedure _SetownerScope(const NewValue: TScopeKind); function _GetclassifierRole_: TUMLClassifierRoleList; function _GetclassifierRole_availableFeature: TclassifierRole_availableFeatureList; function _Getowner: TUMLClassifier; function _Get_M_owner: TBoldObjectReference; - procedure _Setowner(value: TUMLClassifier); + procedure _Setowner(const value: TUMLClassifier); protected - function GetDeriveMethodForMember(Member: TBoldMember): TBoldDeriveAndResubscribe; override; - function GetReverseDeriveMethodForMember(Member: TBoldMember): TBoldReverseDerive; override; public function ExpandedExpressionName: String; override; property M_ownerScope: TBAScopeKind read _Get_M_ownerScope; @@ -1186,10 +1183,10 @@ type private function _Get_M_expression: TBAString; function _Getexpression: String; - procedure _Setexpression(NewValue: String); + procedure _Setexpression(const NewValue: String); function _Gettransition: TUMLTransition; function _Get_M_transition: TBoldObjectReference; - procedure _Settransition(value: TUMLTransition); + procedure _Settransition(const value: TUMLTransition); protected public property M_expression: TBAString read _Get_M_expression; @@ -1211,7 +1208,7 @@ type function _Getstimulus3: TUMLStimulusList; function _GetcomponentInstance: TUMLComponentInstance; function _Get_M_componentInstance: TBoldObjectReference; - procedure _SetcomponentInstance(value: TUMLComponentInstance); + procedure _SetcomponentInstance(const value: TUMLComponentInstance); protected public property M_attributeLink: TUMLAttributeLinkList read _GetattributeLink; @@ -1240,7 +1237,7 @@ type private function _Getcontext: TUMLCollaboration; function _Get_M_context: TBoldObjectReference; - procedure _Setcontext(value: TUMLCollaboration); + procedure _Setcontext(const value: TUMLCollaboration); function _Getmessage_: TUMLMessageList; protected public @@ -1254,11 +1251,11 @@ type private function _Getassociation: TUMLAssociation; function _Get_M_association: TBoldObjectReference; - procedure _Setassociation(value: TUMLAssociation); + procedure _Setassociation(const value: TUMLAssociation); function _GetStimulus: TUMLStimulusList; function _Getxobject: TUMLObject; function _Get_M_xobject: TBoldObjectReference; - procedure _Setxobject(value: TUMLObject); + procedure _Setxobject(const value: TUMLObject); function _Getconnection: TUMLLinkEndList; protected public @@ -1277,13 +1274,13 @@ type function _GetqualifiedValue: TUMLAttributeLinkList; function _Getinstance: TUMLInstance; function _Get_M_instance: TBoldObjectReference; - procedure _Setinstance(value: TUMLInstance); + procedure _Setinstance(const value: TUMLInstance); function _GetassociationEnd: TUMLAssociationEnd; function _Get_M_associationEnd: TBoldObjectReference; - procedure _SetassociationEnd(value: TUMLAssociationEnd); + procedure _SetassociationEnd(const value: TUMLAssociationEnd); function _Getlink: TUMLLink; function _Get_M_link: TBoldObjectReference; - procedure _Setlink(value: TUMLLink); + procedure _Setlink(const value: TUMLLink); protected public property M_qualifiedValue: TUMLAttributeLinkList read _GetqualifiedValue; @@ -1300,13 +1297,13 @@ type private function _Getinteraction: TUMLInteraction; function _Get_M_interaction: TBoldObjectReference; - procedure _Setinteraction(value: TUMLInteraction); + procedure _Setinteraction(const value: TUMLInteraction); function _GetcommunicationConnection: TUMLAssociationRole; function _Get_M_communicationConnection: TBoldObjectReference; - procedure _SetcommunicationConnection(value: TUMLAssociationRole); + procedure _SetcommunicationConnection(const value: TUMLAssociationRole); function _Getaction: TUMLAction; function _Get_M_action: TBoldObjectReference; - procedure _Setaction(value: TUMLAction); + procedure _Setaction(const value: TUMLAction); function _Getpredecessor: TUMLMessageList; function _Getpredecessorpredecessormessage3: Tpredecessormessage3List; function _Getmessage3: TUMLMessageList; @@ -1314,13 +1311,13 @@ type function _Getmessage4: TUMLMessageList; function _Getactivator: TUMLMessage; function _Get_M_activator: TBoldObjectReference; - procedure _Setactivator(value: TUMLMessage); + procedure _Setactivator(const value: TUMLMessage); function _Getreceiver: TUMLClassifierRole; function _Get_M_receiver: TBoldObjectReference; - procedure _Setreceiver(value: TUMLClassifierRole); + procedure _Setreceiver(const value: TUMLClassifierRole); function _Getsender: TUMLClassifierRole; function _Get_M_sender: TBoldObjectReference; - procedure _Setsender(value: TUMLClassifierRole); + procedure _Setsender(const value: TUMLClassifierRole); protected public property M_interaction: TBoldObjectReference read _Get_M_interaction; @@ -1369,29 +1366,29 @@ type private function _Get_M_defaultValue: TBAString; function _GetdefaultValue: String; - procedure _SetdefaultValue(NewValue: String); + procedure _SetdefaultValue(const NewValue: String); function _Get_M_kind: TBAParameterDirectionKind; function _Getkind: TBoldParameterDirectionKind; - procedure _Setkind(NewValue: TBoldParameterDirectionKind); + procedure _Setkind(const NewValue: TBoldParameterDirectionKind); function _Get_M_typeName: TBAString; function _GettypeName: String; - procedure _SettypeName(NewValue: String); + procedure _SettypeName(const NewValue: String); function _Getevent: TUMLEvent; function _Get_M_event: TBoldObjectReference; - procedure _Setevent(value: TUMLEvent); + procedure _Setevent(const value: TUMLEvent); function _Getstate: TUMLObjectFlowStateList; function _Getparameterstate: TparameterstateList; function _Gettype_: TUMLClassifier; function _Get_M_type_: TBoldObjectReference; - procedure _Settype_(value: TUMLClassifier); + procedure _Settype_(const value: TUMLClassifier); function _GetbehavioralFeature: TUMLBehavioralFeature; function _Get_M_behavioralFeature: TBoldObjectReference; - procedure _SetbehavioralFeature(value: TUMLBehavioralFeature); + procedure _SetbehavioralFeature(const value: TUMLBehavioralFeature); protected procedure _typeName_DeriveAndSubscribe(DerivedObject: TObject; Subscriber: TBoldSubscriber); virtual; procedure _typeName_ReverseDerive(DerivedObject: TObject); virtual; - function GetDeriveMethodForMember(Member: TBoldMember): TBoldDeriveAndResubscribe; override; - function GetReverseDeriveMethodForMember(Member: TBoldMember): TBoldReverseDerive; override; + function GetDeriveMethodForMember(MemberIndex: Integer): TBoldDeriveAndResubscribe; override; + function GetReverseDeriveMethodForMember(MemberIndex: Integer): TBoldReverseDerive; override; public property M_defaultValue: TBAString read _Get_M_defaultValue; property M_kind: TBAParameterDirectionKind read _Get_M_kind; @@ -1417,7 +1414,7 @@ type function _Getcontentscontentspartition: TcontentspartitionList; function _GetactivityGraph: TUMLActivityGraph; function _Get_M_activityGraph: TBoldObjectReference; - procedure _SetactivityGraph(value: TUMLActivityGraph); + procedure _SetactivityGraph(const value: TUMLActivityGraph); protected public property M_contents: TUMLModelElementList read _Getcontents; @@ -1443,10 +1440,10 @@ type function _GetsubMachineState: TUMLSubmachineStateList; function _Getcontext: TUMLModelElement; function _Get_M_context: TBoldObjectReference; - procedure _Setcontext(value: TUMLModelElement); + procedure _Setcontext(const value: TUMLModelElement); function _Gettop: TUMLState; function _Get_M_top: TBoldObjectReference; - procedure _Settop(value: TUMLState); + procedure _Settop(const value: TUMLState); protected public property M_transitions: TUMLTransitionList read _Gettransitions; @@ -1463,7 +1460,7 @@ type private function _Getcontainer: TUMLCompositeState; function _Get_M_container: TBoldObjectReference; - procedure _Setcontainer(value: TUMLCompositeState); + procedure _Setcontainer(const value: TUMLCompositeState); function _Getoutgoing: TUMLTransitionList; function _Getincoming: TUMLTransitionList; protected @@ -1482,16 +1479,16 @@ type function _Getargumentstimulus1: Targumentstimulus1List; function _GetdispatchAction: TUMLAction; function _Get_M_dispatchAction: TBoldObjectReference; - procedure _SetdispatchAction(value: TUMLAction); + procedure _SetdispatchAction(const value: TUMLAction); function _GetcommunicationLink: TUMLLink; function _Get_M_communicationLink: TBoldObjectReference; - procedure _SetcommunicationLink(value: TUMLLink); + procedure _SetcommunicationLink(const value: TUMLLink); function _Getreceiver: TUMLInstance; function _Get_M_receiver: TBoldObjectReference; - procedure _Setreceiver(value: TUMLInstance); + procedure _Setreceiver(const value: TUMLInstance); function _Getsender: TUMLInstance; function _Get_M_sender: TBoldObjectReference; - procedure _Setsender(value: TUMLInstance); + procedure _Setsender(const value: TUMLInstance); protected public property M_argument: TUMLInstanceList read _Getargument; @@ -1512,16 +1509,16 @@ type private function _Get_M_tag: TBAString; function _Gettag: String; - procedure _Settag(NewValue: String); + procedure _Settag(const NewValue: String); function _Get_M_value: TBAString; function _Getvalue: String; - procedure _Setvalue(NewValue: String); + procedure _Setvalue(const NewValue: String); function _GetmodelElement: TUMLModelElement; function _Get_M_modelElement: TBoldObjectReference; - procedure _SetmodelElement(value: TUMLModelElement); + procedure _SetmodelElement(const value: TUMLModelElement); function _Getstereotype_: TUMLStereotype; function _Get_M_stereotype_: TBoldObjectReference; - procedure _Setstereotype_(value: TUMLStereotype); + procedure _Setstereotype_(const value: TUMLStereotype); protected public property M_tag: TBAString read _Get_M_tag; @@ -1538,25 +1535,25 @@ type private function _GetState: TUMLState; function _Get_M_State: TBoldObjectReference; - procedure _SetState(value: TUMLState); + procedure _SetState(const value: TUMLState); function _Gettrigger: TUMLEvent; function _Get_M_trigger: TBoldObjectReference; - procedure _Settrigger(value: TUMLEvent); + procedure _Settrigger(const value: TUMLEvent); function _Geteffect: TUMLAction; function _Get_M_effect: TBoldObjectReference; - procedure _Seteffect(value: TUMLAction); + procedure _Seteffect(const value: TUMLAction); function _GetstateMachine: TUMLStateMachine; function _Get_M_stateMachine: TBoldObjectReference; - procedure _SetstateMachine(value: TUMLStateMachine); + procedure _SetstateMachine(const value: TUMLStateMachine); function _Getsource: TUMLStateVertex; function _Get_M_source: TBoldObjectReference; - procedure _Setsource(value: TUMLStateVertex); + procedure _Setsource(const value: TUMLStateVertex); function _Gettarget: TUMLStateVertex; function _Get_M_target: TBoldObjectReference; - procedure _Settarget(value: TUMLStateVertex); + procedure _Settarget(const value: TUMLStateVertex); function _Getguard: TUMLGuard; function _Get_M_guard: TBoldObjectReference; - procedure _Setguard(value: TUMLGuard); + procedure _Setguard(const value: TUMLGuard); protected public property M_State: TBoldObjectReference read _Get_M_State; @@ -1588,7 +1585,7 @@ type private function _Getoperation: TUMLOperation; function _Get_M_operation: TBoldObjectReference; - procedure _Setoperation(value: TUMLOperation); + procedure _Setoperation(const value: TUMLOperation); protected public property M_operation: TBoldObjectReference read _Get_M_operation; @@ -1599,7 +1596,7 @@ type private function _Getinstantiation: TUMLClassifier; function _Get_M_instantiation: TBoldObjectReference; - procedure _Setinstantiation(value: TUMLClassifier); + procedure _Setinstantiation(const value: TUMLClassifier); protected public property M_instantiation: TBoldObjectReference read _Get_M_instantiation; @@ -1622,7 +1619,7 @@ type private function _Getsignal: TUMLSignal; function _Get_M_signal: TBoldObjectReference; - procedure _Setsignal(value: TUMLSignal); + procedure _Setsignal(const value: TUMLSignal); protected public property M_signal: TBoldObjectReference read _Get_M_signal; @@ -1645,10 +1642,10 @@ type private function _Get_M_collaborationMultiplicity: TBAString; function _GetcollaborationMultiplicity: String; - procedure _SetcollaborationMultiplicity(NewValue: String); + procedure _SetcollaborationMultiplicity(const NewValue: String); function _Getbase: TUMLAssociationEnd; function _Get_M_base: TBoldObjectReference; - procedure _Setbase(value: TUMLAssociationEnd); + procedure _Setbase(const value: TUMLAssociationEnd); function _GetavailableQualifier: TUMLAttributeList; function _GetassociationEndRoleavailableQualifier: TassociationEndRoleavailableQualifierList; property M_collaborationMultiplicity: TBAString read _Get_M_collaborationMultiplicity; @@ -1667,7 +1664,7 @@ type private function _Getoperation: TUMLOperation; function _Get_M_operation: TBoldObjectReference; - procedure _Setoperation(value: TUMLOperation); + procedure _Setoperation(const value: TUMLOperation); protected public property M_operation: TBoldObjectReference read _Get_M_operation; @@ -1678,7 +1675,7 @@ type private function _Get_M_changeExpression: TBAString; function _GetchangeExpression: String; - procedure _SetchangeExpression(NewValue: String); + procedure _SetchangeExpression(const NewValue: String); protected public property M_changeExpression: TBAString read _Get_M_changeExpression; @@ -1689,7 +1686,7 @@ type private function _Getsignal: TUMLSignal; function _Get_M_signal: TBoldObjectReference; - procedure _Setsignal(value: TUMLSignal); + procedure _Setsignal(const value: TUMLSignal); protected public property M_signal: TBoldObjectReference read _Get_M_signal; @@ -1700,7 +1697,7 @@ type private function _Get_M_when: TBAString; function _Getwhen: String; - procedure _Setwhen(NewValue: String); + procedure _Setwhen(const NewValue: String); protected public property M_when: TBAString read _Get_M_when; @@ -1711,7 +1708,7 @@ type private function _Get_M_isQuery: TBABoolean; function _GetisQuery: boolean; - procedure _SetisQuery(NewValue: boolean); + procedure _SetisQuery(const NewValue: boolean); function _GetraisedSignal: TUMLSignalList; function _GetcontextraisedSignal: TcontextraisedSignalList; function _Getparameter: TUMLParameterList; @@ -1731,24 +1728,24 @@ type private function _Get_M_multiplicity: TBAString; function _Getmultiplicity: String; - procedure _Setmultiplicity(NewValue: String); + procedure _Setmultiplicity(const NewValue: String); function _Get_M_changeability: TBAChangeableKind; function _Getchangeability: TChangeableKind; - procedure _Setchangeability(NewValue: TChangeableKind); + procedure _Setchangeability(const NewValue: TChangeableKind); function _Get_M_targetScope: TBAScopeKind; function _GettargetScope: TScopeKind; - procedure _SettargetScope(NewValue: TScopeKind); + procedure _SettargetScope(const NewValue: TScopeKind); function _Get_M_typeName: TBAString; function _GettypeName: String; - procedure _SettypeName(NewValue: String); + procedure _SettypeName(const NewValue: String); function _Gettype_: TUMLClassifier; function _Get_M_type_: TBoldObjectReference; - procedure _Settype_(value: TUMLClassifier); + procedure _Settype_(const value: TUMLClassifier); protected procedure _typeName_DeriveAndSubscribe(DerivedObject: TObject; Subscriber: TBoldSubscriber); virtual; procedure _typeName_ReverseDerive(DerivedObject: TObject); virtual; - function GetDeriveMethodForMember(Member: TBoldMember): TBoldDeriveAndResubscribe; override; - function GetReverseDeriveMethodForMember(Member: TBoldMember): TBoldReverseDerive; override; + function GetDeriveMethodForMember(MemberIndex: Integer): TBoldDeriveAndResubscribe; override; + function GetReverseDeriveMethodForMember(MemberIndex: Integer): TBoldReverseDerive; override; public property M_multiplicity: TBAString read _Get_M_multiplicity; property M_changeability: TBAChangeableKind read _Get_M_changeability; @@ -1767,7 +1764,7 @@ type function _Getresident_: TUMLInstanceList; function _GetnodeInstance: TUMLNodeInstance; function _Get_M_nodeInstance: TBoldObjectReference; - procedure _SetnodeInstance(value: TUMLNodeInstance); + procedure _SetnodeInstance(const value: TUMLNodeInstance); protected public property M_resident_: TUMLInstanceList read _Getresident_; @@ -1795,7 +1792,7 @@ type private function _Getlink: TUMLLink; function _Get_M_link: TBoldObjectReference; - procedure _Setlink(value: TUMLLink); + procedure _Setlink(const value: TUMLLink); protected public property M_link: TBoldObjectReference read _Get_M_link; @@ -1812,13 +1809,13 @@ type private function _Get_M_isRoot: TBABoolean; function _GetisRoot: boolean; - procedure _SetisRoot(NewValue: boolean); + procedure _SetisRoot(const NewValue: boolean); function _Get_M_isLeaf: TBABoolean; function _GetisLeaf: boolean; - procedure _SetisLeaf(NewValue: boolean); + procedure _SetisLeaf(const NewValue: boolean); function _Get_M_isAbstract: TBABoolean; function _GetisAbstract: boolean; - procedure _SetisAbstract(NewValue: boolean); + procedure _SetisAbstract(const NewValue: boolean); function _Getspecialization: TUMLGeneralizationList; function _Getgeneralization: TUMLGeneralizationList; protected @@ -1857,15 +1854,15 @@ type private function _Get_M_condition: TBAString; function _Getcondition: String; - procedure _Setcondition(NewValue: String); + procedure _Setcondition(const NewValue: String); function _GetextensionPoint: TUMLExtensionPointList; function _GetextensionPointextend: TextensionPointextendList; function _Getbase: TUMLUseCase; function _Get_M_base: TBoldObjectReference; - procedure _Setbase(value: TUMLUseCase); + procedure _Setbase(const value: TUMLUseCase); function _Getextension: TUMLUseCase; function _Get_M_extension: TBoldObjectReference; - procedure _Setextension(value: TUMLUseCase); + procedure _Setextension(const value: TUMLUseCase); protected public property M_condition: TBAString read _Get_M_condition; @@ -1902,16 +1899,16 @@ type private function _Get_M_discriminator: TBAString; function _Getdiscriminator: String; - procedure _Setdiscriminator(NewValue: String); + procedure _Setdiscriminator(const NewValue: String); function _Getparent: TUMLGeneralizableElement; function _Get_M_parent: TBoldObjectReference; - procedure _Setparent(value: TUMLGeneralizableElement); + procedure _Setparent(const value: TUMLGeneralizableElement); function _Getchild: TUMLGeneralizableElement; function _Get_M_child: TBoldObjectReference; - procedure _Setchild(value: TUMLGeneralizableElement); + procedure _Setchild(const value: TUMLGeneralizableElement); function _Getpowertype: TUMLClassifier; function _Get_M_powertype: TBoldObjectReference; - procedure _Setpowertype(value: TUMLClassifier); + procedure _Setpowertype(const value: TUMLClassifier); protected public property M_discriminator: TBAString read _Get_M_discriminator; @@ -1928,10 +1925,10 @@ type private function _Getbase: TUMLUseCase; function _Get_M_base: TBoldObjectReference; - procedure _Setbase(value: TUMLUseCase); + procedure _Setbase(const value: TUMLUseCase); function _Getaddition: TUMLUseCase; function _Get_M_addition: TBoldObjectReference; - procedure _Setaddition(value: TUMLUseCase); + procedure _Setaddition(const value: TUMLUseCase); protected public property M_base: TBoldObjectReference read _Get_M_base; @@ -1953,7 +1950,7 @@ type private function _Get_M_kind: TBAPseudostateKind; function _Getkind: TPseudostateKind; - procedure _Setkind(NewValue: TPseudostateKind); + procedure _Setkind(const NewValue: TPseudostateKind); protected public property M_kind: TBAPseudostateKind read _Get_M_kind; @@ -1964,19 +1961,19 @@ type private function _Getentry: TUMLAction; function _Get_M_entry: TBoldObjectReference; - procedure _Setentry(value: TUMLAction); + procedure _Setentry(const value: TUMLAction); function _GetinternalTransition: TUMLTransitionList; function _GetdoActivity: TUMLAction; function _Get_M_doActivity: TBoldObjectReference; - procedure _SetdoActivity(value: TUMLAction); + procedure _SetdoActivity(const value: TUMLAction); function _Getexit: TUMLAction; function _Get_M_exit: TBoldObjectReference; - procedure _Setexit(value: TUMLAction); + procedure _Setexit(const value: TUMLAction); function _GetdeferrableEvent: TUMLEventList; function _GetstatedeferrableEvent: TstatedeferrableEventList; function _GetstateMachine: TUMLStateMachine; function _Get_M_stateMachine: TBoldObjectReference; - procedure _SetstateMachine(value: TUMLStateMachine); + procedure _SetstateMachine(const value: TUMLStateMachine); function _GetclassifierInState: TUMLClassifierInStateList; function _GetclassifierInStateinState: TclassifierInStateinStateList; protected @@ -2005,7 +2002,7 @@ type private function _Get_M_referenceState: TBAString; function _GetreferenceState: String; - procedure _SetreferenceState(NewValue: String); + procedure _SetreferenceState(const NewValue: String); protected public property M_referenceState: TBAString read _Get_M_referenceState; @@ -2016,7 +2013,7 @@ type private function _Get_M_bound: TBAString; function _Getbound: String; - procedure _Setbound(NewValue: String); + procedure _Setbound(const NewValue: String); protected public property M_bound: TBAString read _Get_M_bound; @@ -2027,10 +2024,10 @@ type private function _Get_M_body: TBAString; function _Getbody: String; - procedure _Setbody(NewValue: String); + procedure _Setbody(const NewValue: String); function _Getspecification: TUMLOperation; function _Get_M_specification: TBoldObjectReference; - procedure _Setspecification(value: TUMLOperation); + procedure _Setspecification(const value: TUMLOperation); protected public property M_body: TBAString read _Get_M_body; @@ -2043,19 +2040,19 @@ type private function _Get_M_concurrency: TBACallConcurrencyKind; function _Getconcurrency: TCallConcurrencyKind; - procedure _Setconcurrency(NewValue: TCallConcurrencyKind); + procedure _Setconcurrency(const NewValue: TCallConcurrencyKind); function _Get_M_isRoot: TBABoolean; function _GetisRoot: boolean; - procedure _SetisRoot(NewValue: boolean); + procedure _SetisRoot(const NewValue: boolean); function _Get_M_isLeaf: TBABoolean; function _GetisLeaf: boolean; - procedure _SetisLeaf(NewValue: boolean); + procedure _SetisLeaf(const NewValue: boolean); function _Get_M_isAbstract: TBABoolean; function _GetisAbstract: boolean; - procedure _SetisAbstract(NewValue: boolean); + procedure _SetisAbstract(const NewValue: boolean); function _Get_M_specification: TBAString; function _Getspecification: String; - procedure _Setspecification(NewValue: String); + procedure _Setspecification(const NewValue: String); function _Getoccurrences: TUMLCallEventList; function _GetcallAction: TUMLCallActionList; function _Getcollaboration_: TUMLCollaborationList; @@ -2086,19 +2083,19 @@ type private function _Get_M_specification: TBAString; function _Getspecification: String; - procedure _Setspecification(NewValue: String); + procedure _Setspecification(const NewValue: String); function _Get_M_isRoot: TBABoolean; function _GetisRoot: boolean; - procedure _SetisRoot(NewValue: boolean); + procedure _SetisRoot(const NewValue: boolean); function _Get_M_isLeaf: TBABoolean; function _GetisLeaf: boolean; - procedure _SetisLeaf(NewValue: boolean); + procedure _SetisLeaf(const NewValue: boolean); function _Get_M_isAbstract: TBABoolean; function _GetisAbstract: boolean; - procedure _SetisAbstract(NewValue: boolean); + procedure _SetisAbstract(const NewValue: boolean); function _Getsignal: TUMLSignal; function _Get_M_signal: TBoldObjectReference; - procedure _Setsignal(value: TUMLSignal); + procedure _Setsignal(const value: TUMLSignal); protected public property M_specification: TBAString read _Get_M_specification; @@ -2117,24 +2114,24 @@ type private function _Get_M_initialValue: TBAString; function _GetinitialValue: String; - procedure _SetinitialValue(NewValue: String); + procedure _SetinitialValue(const NewValue: String); function _Get_M_persistent: TBABoolean; function _Getpersistent: boolean; - procedure _Setpersistent(NewValue: boolean); + procedure _Setpersistent(const NewValue: boolean); function _GetattributeLink: TUMLAttributeLinkList; function _GetassociationEndRole: TUMLAssociationEndRoleList; function _GetassociationEndRoleavailableQualifier: TassociationEndRoleavailableQualifierList; function _GetassociationEnd: TUMLAssociationEnd; function _Get_M_associationEnd: TBoldObjectReference; - procedure _SetassociationEnd(value: TUMLAssociationEnd); + procedure _SetassociationEnd(const value: TUMLAssociationEnd); protected procedure _persistent_DeriveAndSubscribe(DerivedObject: TObject; Subscriber: TBoldSubscriber); virtual; procedure _persistent_ReverseDerive(DerivedObject: TObject); virtual; - function GetDeriveMethodForMember(Member: TBoldMember): TBoldDeriveAndResubscribe; override; - function GetReverseDeriveMethodForMember(Member: TBoldMember): TBoldReverseDerive; override; + function GetDeriveMethodForMember(MemberIndex: Integer): TBoldDeriveAndResubscribe; override; + function GetReverseDeriveMethodForMember(MemberIndex: Integer): TBoldReverseDerive; override; public - function isQualifier: Boolean; - function EffectivePersistent: Boolean; + function isQualifier: Boolean; + function EffectivePersistent: Boolean; property M_initialValue: TBAString read _Get_M_initialValue; property M_persistent: TBABoolean read _Get_M_persistent; property M_attributeLink: TUMLAttributeLinkList read _GetattributeLink; @@ -2153,22 +2150,22 @@ type private function _Get_M_persistent: TBABoolean; function _Getpersistent: boolean; - procedure _Setpersistent(NewValue: boolean); + procedure _Setpersistent(const NewValue: boolean); function _Get_M_isAssociationClass: TBABoolean; function _GetisAssociationClass: boolean; function _Getlink: TUMLLinkList; function _GetassociationRole: TUMLAssociationRoleList; function _Getclass_: TUMLClass; function _Get_M_class_: TBoldObjectReference; - procedure _Setclass_(value: TUMLClass); + procedure _Setclass_(const value: TUMLClass); function _Getconnection: TUMLAssociationEndList; protected procedure _persistent_DeriveAndSubscribe(DerivedObject: TObject; Subscriber: TBoldSubscriber); virtual; procedure _persistent_ReverseDerive(DerivedObject: TObject); virtual; - function GetDeriveMethodForMember(Member: TBoldMember): TBoldDeriveAndResubscribe; override; - function GetReverseDeriveMethodForMember(Member: TBoldMember): TBoldReverseDerive; override; + function GetDeriveMethodForMember(MemberIndex: Integer): TBoldDeriveAndResubscribe; override; + function GetReverseDeriveMethodForMember(MemberIndex: Integer): TBoldReverseDerive; override; public - function EffectivePersistent: Boolean; + function EffectivePersistent: Boolean; property M_persistent: TBABoolean read _Get_M_persistent; property M_isAssociationClass: TBABoolean read _Get_M_isAssociationClass; property M_link: TUMLLinkList read _Getlink; @@ -2187,7 +2184,7 @@ type private function _Get_M_persistent: TBABoolean; function _Getpersistent: boolean; - procedure _Setpersistent(NewValue: boolean); + procedure _Setpersistent(const NewValue: boolean); function _GetcreateAction: TUMLCreateActionList; function _Getinstance: TUMLInstanceList; function _Getinstanceclassifier: TinstanceclassifierList; @@ -2201,7 +2198,7 @@ type function _Getsubclasses: TUMLClassifierList; function _Getsuperclass: TUMLClassifier; function _Get_M_superclass: TBoldObjectReference; - procedure _Setsuperclass(value: TUMLClassifier); + procedure _Setsuperclass(const value: TUMLClassifier); function _GetassociationEnd: TUMLAssociationEndList; function _GetpowertypeRange: TUMLGeneralizationList; function _GetallFeature: TUMLFeatureList; @@ -2209,11 +2206,11 @@ type protected procedure _persistent_DeriveAndSubscribe(DerivedObject: TObject; Subscriber: TBoldSubscriber); virtual; procedure _persistent_ReverseDerive(DerivedObject: TObject); virtual; - function GetDeriveMethodForMember(Member: TBoldMember): TBoldDeriveAndResubscribe; override; - function GetReverseDeriveMethodForMember(Member: TBoldMember): TBoldReverseDerive; override; + function GetDeriveMethodForMember(MemberIndex: Integer): TBoldDeriveAndResubscribe; override; + function GetReverseDeriveMethodForMember(MemberIndex: Integer): TBoldReverseDerive; override; public - procedure GetAllOverrideableMethods(Methods: TList); - procedure SetFirstParent(parent: TUMLClassifier); + procedure GetAllOverrideableMethods(Methods: TList); + procedure SetFirstParent(parent: TUMLClassifier); property M_persistent: TBABoolean read _Get_M_persistent; property M_createAction: TUMLCreateActionList read _GetcreateAction; property M_instance: TUMLInstanceList read _Getinstance; @@ -2257,10 +2254,10 @@ type function _GetconstrainingElementcollaborationconstrainingElement: TcollaborationconstrainingElementList; function _GetrepresentedClassifier: TUMLClassifier; function _Get_M_representedClassifier: TBoldObjectReference; - procedure _SetrepresentedClassifier(value: TUMLClassifier); + procedure _SetrepresentedClassifier(const value: TUMLClassifier); function _GetrepresentedOperation: TUMLOperation; function _Get_M_representedOperation: TBoldObjectReference; - procedure _SetrepresentedOperation(value: TUMLOperation); + procedure _SetrepresentedOperation(const value: TUMLOperation); protected public property M_interaction: TUMLInteractionList read _Getinteraction; @@ -2288,16 +2285,16 @@ type private function _Get_M_icon: TBAString; function _Geticon: String; - procedure _Seticon(NewValue: String); + procedure _Seticon(const NewValue: String); function _Get_M_baseClass: TBAString; function _GetbaseClass: String; - procedure _SetbaseClass(NewValue: String); + procedure _SetbaseClass(const NewValue: String); function _GetstereotypeConstraint: TUMLConstraintList; function _GetextendedElement: TUMLModelElementList; function _GetrequiredTag: TUMLTaggedValueList; protected public - class function FindStereotypeByName(aName: String; aSystem: TBoldSystem): TUMLStereotype; + class function FindStereotypeByName(aName: String; aSystem: TBoldSystem): TUMLStereotype; property M_icon: TBAString read _Get_M_icon; property M_baseClass: TBAString read _Get_M_baseClass; property M_stereotypeConstraint: TUMLConstraintList read _GetstereotypeConstraint; @@ -2314,7 +2311,7 @@ type private function _Get_M_mapping: TBAString; function _Getmapping: String; - procedure _Setmapping(NewValue: String); + procedure _Setmapping(const NewValue: String); protected public property M_mapping: TBAString read _Get_M_mapping; @@ -2349,7 +2346,7 @@ type private function _Get_M_isConcurrent: TBABoolean; function _GetisConcurrent: boolean; - procedure _SetisConcurrent(NewValue: boolean); + procedure _SetisConcurrent(const NewValue: boolean); function _Getsubvertex: TUMLStateVertexList; protected public @@ -2375,10 +2372,10 @@ type private function _Get_M_multiplicity: TBAString; function _Getmultiplicity: String; - procedure _Setmultiplicity(NewValue: String); + procedure _Setmultiplicity(const NewValue: String); function _Getbase: TUMLAssociation; function _Get_M_base: TBoldObjectReference; - procedure _Setbase(value: TUMLAssociation); + procedure _Setbase(const value: TUMLAssociation); function _Getmessage_: TUMLMessageList; protected public @@ -2400,15 +2397,13 @@ type private function _Get_M_isActive: TBABoolean; function _GetisActive: boolean; - procedure _SetisActive(NewValue: boolean); + procedure _SetisActive(const NewValue: boolean); function _Get_M_isAssociationClass: TBABoolean; function _GetisAssociationClass: boolean; function _Getassociation: TUMLAssociation; function _Get_M_association: TBoldObjectReference; - procedure _Setassociation(value: TUMLAssociation); + procedure _Setassociation(const value: TUMLAssociation); protected - function GetDeriveMethodForMember(Member: TBoldMember): TBoldDeriveAndResubscribe; override; - function GetReverseDeriveMethodForMember(Member: TBoldMember): TBoldReverseDerive; override; public function ExpandedExpressionName: String; override; property M_isActive: TBABoolean read _Get_M_isActive; @@ -2423,7 +2418,7 @@ type private function _Gettype_: TUMLClassifier; function _Get_M_type_: TBoldObjectReference; - procedure _Settype_(value: TUMLClassifier); + procedure _Settype_(const value: TUMLClassifier); function _GetinState: TUMLStateList; function _GetclassifierInStateinState: TclassifierInStateinStateList; protected @@ -2440,7 +2435,7 @@ type private function _Get_M_multiplicity: TBAString; function _Getmultiplicity: String; - procedure _Setmultiplicity(NewValue: String); + procedure _Setmultiplicity(const NewValue: String); function _GetavailableFeature: TUMLFeatureList; function _GetclassifierRole_availableFeature: TclassifierRole_availableFeatureList; function _GetavailableContents: TUMLModelElementList; @@ -2556,12 +2551,10 @@ type private function _GetValidator: TValidator; function _Get_M_Validator: TBoldObjectReference; - procedure _SetValidator(value: TValidator); + procedure _SetValidator(const value: TValidator); protected - function GetDeriveMethodForMember(Member: TBoldMember): TBoldDeriveAndResubscribe; override; - function GetReverseDeriveMethodForMember(Member: TBoldMember): TBoldReverseDerive; override; public - procedure Clear; + procedure Clear; procedure CompleteCreate; override; property M_Validator: TBoldObjectReference read _Get_M_Validator; property Validator: TValidator read _GetValidator write _SetValidator; @@ -2571,7 +2564,7 @@ type private function _Get_M_isInstantiable: TBABoolean; function _GetisInstantiable: boolean; - procedure _SetisInstantiable(NewValue: boolean); + procedure _SetisInstantiable(const NewValue: boolean); protected public property M_isInstantiable: TBABoolean read _Get_M_isInstantiable; @@ -2582,7 +2575,7 @@ type private function _Getsubmachine: TUMLStateMachine; function _Get_M_submachine: TBoldObjectReference; - procedure _Setsubmachine(value: TUMLStateMachine); + procedure _Setsubmachine(const value: TUMLStateMachine); protected public property M_submachine: TBoldObjectReference read _Get_M_submachine; @@ -2593,13 +2586,13 @@ type private function _Get_M_isDynamic: TBABoolean; function _GetisDynamic: boolean; - procedure _SetisDynamic(NewValue: boolean); + procedure _SetisDynamic(const NewValue: boolean); function _Get_M_dynamicArguments: TBAString; function _GetdynamicArguments: String; - procedure _SetdynamicArguments(NewValue: String); + procedure _SetdynamicArguments(const NewValue: String); function _Get_M_dynamicMultiplicity: TBAString; function _GetdynamicMultiplicity: String; - procedure _SetdynamicMultiplicity(NewValue: String); + procedure _SetdynamicMultiplicity(const NewValue: String); protected public property M_isDynamic: TBABoolean read _Get_M_isDynamic; @@ -2614,10 +2607,10 @@ type private function _Get_M_isSynch: TBABoolean; function _GetisSynch: boolean; - procedure _SetisSynch(NewValue: boolean); + procedure _SetisSynch(const NewValue: boolean); function _Gettype_: TUMLClassifier; function _Get_M_type_: TBoldObjectReference; - procedure _Settype_(value: TUMLClassifier); + procedure _Settype_(const value: TUMLClassifier); function _Getparameter: TUMLParameterList; function _Getparameterstate: TparameterstateList; protected @@ -2642,13 +2635,13 @@ type private function _Get_M_isDynamic: TBABoolean; function _GetisDynamic: boolean; - procedure _SetisDynamic(NewValue: boolean); + procedure _SetisDynamic(const NewValue: boolean); function _Get_M_dynamicArguments: TBAString; function _GetdynamicArguments: String; - procedure _SetdynamicArguments(NewValue: String); + procedure _SetdynamicArguments(const NewValue: String); function _Get_M_dynamicMultiplicity: TBAString; function _GetdynamicMultiplicity: String; - procedure _SetdynamicMultiplicity(NewValue: String); + procedure _SetdynamicMultiplicity(const NewValue: String); property M_dynamicMultiplicity: TBAString read _Get_M_dynamicMultiplicity; property dynamicMultiplicity: String read _GetdynamicMultiplicity write _SetdynamicMultiplicity; protected @@ -4274,4 +4267,3 @@ uses BoldGeneratedCodeDictionary; {$ENDIF} - diff --git a/Source/UMLModel/Core/BoldUMLOCLValidator.pas b/Source/UMLModel/Core/BoldUMLOCLValidator.pas index c0caee0..dd2ad6d 100644 --- a/Source/UMLModel/Core/BoldUMLOCLValidator.pas +++ b/Source/UMLModel/Core/BoldUMLOCLValidator.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldUMLOCLValidator; interface @@ -19,11 +22,12 @@ TOCLValidityChecker = class; { TOCLValidityChecker } TOCLValidityChecker = class private + fBoldModel: TBoldModel; fUMLModel: TUMLModel; fTypeNameDictionary: TBoldTypeNameDictionary; fSystemTypeInfo: TBoldSystemTypeInfo; fOclEvaluator: TBoldOCL; - function ExtractSystemTypeInfo(UMLMOdel: TUMLModel): TBoldSystemTypeInfo; + function ExtractSystemTypeInfo(BoldModel: TBoldModel): TBoldSystemTypeInfo; function GetOCLEvaluator: TBoldOCL; function AttributeTypeInfoFromUMLAttribute(UMLAttribute: TUMLAttribute): TBoldAttributeTypeInfo; function ElementTypeInfoFromUMLAssociationEnd(UMLAssociationEnd: TUMLAssociationEnd): TBoldElementTypeInfo; @@ -39,9 +43,12 @@ TOCLValidityChecker = class procedure ValidateExpression(const ScopeName: string; Element, Context: TUMLModelElement; const Expression: string; ElementTypeInfo: TBoldElementTypeInfo); property SystemTypeInfo: TBoldSystemTypeInfo read fSystemTypeInfo; property OCLEvaluator: TBoldOCL read GetOCLEvaluator; + property UMLModel: TUMLModel read fUMLModel; + property BoldModel: TBoldModel read fBoldModel; public constructor Create(aTypeNameDictionary: TBoldTypeNameDictionary); - procedure ValidateModel(UMLModel: TUMLModel); + destructor Destroy; override; + procedure ValidateModel(BoldModel: TBoldModel); property TypeNameDictionary: TBoldTypeNameDictionary read fTypeNameDictionary; end; @@ -56,6 +63,7 @@ implementation BoldDefaultTaggedValues, BoldOCLClasses, BoldOCLError, + BoldUMLAbstractModelValidator, BoldGuard; { TOCLValidityChecker } @@ -65,16 +73,15 @@ constructor TOCLValidityChecker.Create(aTypeNameDictionary: TBoldTypeNameDiction fTypeNameDictionary := aTypeNameDictionary; end; -function TOCLValidityChecker.ExtractSystemTypeInfo(UMLModel: TUMLModel): TBoldSystemTypeInfo; -var - MoldModel: TMoldModel; +destructor TOCLValidityChecker.Destroy; begin - MoldModel := TBoldModelConverter.UMLModelToMold(UMLModel); - try - Result := TBoldSystemTypeInfo.Create(MoldModel, false, false, fTypeNameDictionary); - finally - MoldModel.Free; - end; + FreeAndNil(fSystemTypeInfo); + inherited; +end; + +function TOCLValidityChecker.ExtractSystemTypeInfo(BoldModel: TBoldModel): TBoldSystemTypeInfo; +begin + Result := TBoldSystemTypeInfo.Create(BoldModel.MoldModel, false, false, fTypeNameDictionary); end; function TOCLValidityChecker.GetOCLEvaluator: TBoldOCL; @@ -86,15 +93,13 @@ function TOCLValidityChecker.GetOCLEvaluator: TBoldOCL; procedure TOCLValidityChecker.ValidateAssociationEnd(UMLAssociationEnd: TUMLAssociationEnd); begin - // DerivationExpression if UMLAssociationEnd.GetBoldTV(TAG_DERIVATIONOCL) <> '' then begin if UMLAssociationEnd.Association.Derived then ValidateExpression('DerivationOCL', UMLAssociationEnd, UMLAssociationEnd.otherEnd.type_, UMLAssociationEnd.GetBoldTV(TAG_DERIVATIONOCL), ElementTypeInfoFromUMLAssociationEnd(UMLAssociationEnd)) else - AddViolation(sHint, UMLAssociationEnd, 'Derivation expression specified for non-derived association'); + AddViolation(sHint, UMLAssociationEnd, 'Derivation expression specified for non-derived associationEnd'+ UMLAssociationEnd.GetOtherEnd.Type_.name + '.' + UMLAssociationEnd.Name); end; - // Constraints ValidateConstraints(UMLAssociationEnd, UMLAssociationEnd.type_, UMLAssociationEnd.constraint); end; @@ -102,7 +107,6 @@ procedure TOCLValidityChecker.ValidateAssociation(UMLAssociation: TUMLAssociatio var Context: TUMLModelElement; begin - // Constraints if Assigned(UMLAssociation.class_) then Context := UMLAssociation.class_ else @@ -114,15 +118,13 @@ procedure TOCLValidityChecker.ValidateAssociation(UMLAssociation: TUMLAssociatio procedure TOCLValidityChecker.ValidateAttribute(UMLAttribute: TUMLAttribute); begin - // Derivation expression if UMLAttribute.GetBoldTV(TAG_DERIVATIONOCL) <> '' then begin if UMLAttribute.Derived then ValidateExpression('DerivationOCL', UMLAttribute, UMLAttribute.owner, UMLAttribute.GetBoldTV(TAG_DERIVATIONOCL), AttributeTypeInfoFromUMLAttribute(UMLAttribute)) else - AddViolation(sHint, UMLAttribute, 'Derivation expression specified for non-derived attribute'); + AddViolation(sHint, UMLAttribute, 'Derivation expression specified for non-derived attribute: ' + UmlAttribute.owner.name + '.' + UMLAttribute.Name); end; - // Constraints ValidateConstraints(UMLAttribute, UMLAttribute.owner, UMLAttribute.constraint); end; @@ -130,23 +132,16 @@ procedure TOCLValidityChecker.ValidateClass(UMLClass: TUMLClass); var i: integer; begin - // Default string representation if UMLClass.GetBoldTV(TAG_DEFAULTSTRINGREPRESENTATION) <> '' then ValidateExpression('DefaultStringRepresentation', UMLClass, UMLClass, UMLClass.GetBoldTV(TAG_DEFAULTSTRINGREPRESENTATION), OCLEvaluator.SymbolTable.Help.StringType); - // Members for i := 0 to UMLClass.feature.Count - 1 do begin if UMLClass.Feature[i] is TUMLAttribute then ValidateAttribute(TUMLAttribute(UMLClass.Feature[i])); end; - - // AssociationEnds for i := 0 to UMLClass.associationEnd.Count - 1 do ValidateAssociationEnd(TUMLAssociationEnd(UMLClass.associationEnd[i])); - - // Constraints ValidateConstraints(UMLCLass, UMLClass, UMLClass.constraint); - // Derivation expressions ValidateDerivationExpressions(UMLClass, UMLClass.taggedValue['Bold.DerivationExpressions']); end; @@ -166,7 +161,7 @@ procedure TOCLValidityChecker.ValidateExpression(const ScopeName: string; Elemen ValidationContext: TBoldElementTypeInfo; Mapping: TBoldTypeNameMapping; begin - ErrorHeader := 'Invalid ' + ScopeName + ': '; + ErrorHeader := 'Invalid ' + ScopeName + ': ' + Element.name + ': ' + Expression + ': '; ValidationContext := nil; if context is TUMLClass then ValidationContext := SystemTypeInfo.ClassTypeInfoByModelName[Context.Name] @@ -206,19 +201,25 @@ procedure TOCLValidityChecker.ValidateExpression(const ScopeName: string; Elemen AddViolation(sError, Element, ErrorHeader + Format(' Type mismatch: Expected %s got %s', [ElementTypeInfo.ExpressionName, Result.ExpressionName])); end; -procedure TOCLValidityChecker.ValidateModel(UMLModel: TUMLModel); +procedure TOCLValidityChecker.ValidateModel(BoldModel: TBoldModel); var i: integer; begin - fUMLModel := UMLModel; - fSystemTypeInfo := ExtractSystemTypeInfo(UMLModel); + fBoldModel := BoldModel; + fUMLModel := BoldModel.EnsuredUMLModel; + BoldModel.StartValidation; BoldLog.StartLog('Validating OCL in model'); - ClearViolations; - for i := 0 to UMLModel.Classes.Count - 1 do - ValidateClass(UMLModel.Classes[i]); - for i := 0 to UMLModel.associations.Count - 1 do - ValidateAssociation(UMLModel.associations[i]); - BoldLog.EndLog; + try + fSystemTypeInfo := ExtractSystemTypeInfo(BoldModel); + ClearViolations; + for i := 0 to UMLModel.Classes.Count - 1 do + ValidateClass(UMLModel.Classes[i]); + for i := 0 to UMLModel.associations.Count - 1 do + ValidateAssociation(UMLModel.associations[i]); + finally + BoldModel.EndValidation; + BoldLog.EndLog; + end; end; procedure TOCLValidityChecker.ValidateDerivationExpressions(UMLClass: TUMLClass; UMLTaggedValue: TUMLTaggedValue); @@ -273,9 +274,9 @@ function LocateModelElement(const FeatureName: string): TUMLModelElement; begin UMLAttribute := TUMLAttribute(UMLModelElement); if not UMLAttribute.Derived then - AddViolation(sHint, UMLAttribute, 'Derivation expression respecified for non-derived attribute') + AddViolation(sHint, UMLAttribute, 'Derivation expression respecified for non-derived attribute' + UmlAttribute.owner.name + '.' + UMLAttribute.Name) else if UMLAttribute.GetBoldTV(TAG_DERIVATIONOCL) = '' then - AddViolation(sHint, UMLAttribute, 'Derivation expression respecified for code-derived attribute') + AddViolation(sHint, UMLAttribute, 'Derivation expression respecified for code-derived attribute' + UmlAttribute.owner.name + '.' + UMLAttribute.Name) else ValidateExpression('DerivationExpression', UMLClass, UMLClass, StringList.Values[StringList.Names[i]], AttributeTypeInfoFromUMLAttribute(UMLAttribute)) end; @@ -284,9 +285,9 @@ function LocateModelElement(const FeatureName: string): TUMLModelElement; begin UMLAssociationEnd := TUMLAssociationEnd(UMLModelElement); if not UMLAssociationEnd.association.derived then - AddViolation(sHint, UMLAssociationEnd, 'Derivation expression respecified for non-derived association') + AddViolation(sHint, UMLAssociationEnd, 'Derivation expression respecified for non-derived association'+ UMLAssociationEnd.GetOtherEnd.Type_.name + '.' + UMLAssociationEnd.Name) else if UMLAssociationEnd.GetBoldTV(TAG_DERIVATIONOCL) = '' then - AddViolation(sHint, UMLAssociationEnd, 'Derivation expression respecified for code-derived association end') + AddViolation(sHint, UMLAssociationEnd, 'Derivation expression respecified for code-derived association end'+ UMLAssociationEnd.GetOtherEnd.Type_.name + '.' + UMLAssociationEnd.Name) else ValidateExpression('DerivationExpression', UMLClass, UMLClass, StringList.Values[StringList.Names[i]], ElementTypeInfoFromUMLAssociationEnd(UMLAssociationEnd)); end; @@ -321,6 +322,9 @@ procedure TOCLValidityChecker.AddViolation(Severity: TSeverity; element: TUMLMod Violation := fUMLModel.Validator.Violation.AddNew; Violation.Severity := Severity; Violation.ModelElement := Element; + if Length(Msg) > 255 then + Violation.Description := Copy(Msg, 0, 200) + ' ...' + else Violation.Description := Msg; end; @@ -328,8 +332,16 @@ procedure TOCLValidityChecker.ClearViolations; var i: integer; begin - for i := fUMLModel.Validator.Violation.count - 1 downto 0 do - fUMLModel.Validator.Violation[i].Delete + fUMLModel.BoldSystem.StartTransaction(); + try + for i := fUMLModel.Validator.Violation.count - 1 downto 0 do + fUMLModel.Validator.Violation[i].Delete; + fUMLModel.BoldSystem.CommitTransaction(); + except + fUMLModel.BoldSystem.RollbackTransaction(); + end; end; +initialization + end. diff --git a/Source/UMLModel/Core/BoldUMLUtils.pas b/Source/UMLModel/Core/BoldUMLUtils.pas index 080dd7f..f76b598 100644 --- a/Source/UMLModel/Core/BoldUMLUtils.pas +++ b/Source/UMLModel/Core/BoldUMLUtils.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldUMLUtils; interface @@ -33,4 +36,3 @@ function SQLDataBaseConfigforModel(BoldModel: TBoldModel): TBoldSQLDataBaseConfi end; end. - diff --git a/Source/UMLModel/Editor/BoldDerivationExpressionsEditor.pas b/Source/UMLModel/Editor/BoldDerivationExpressionsEditor.pas index 769318e..d8c1800 100644 --- a/Source/UMLModel/Editor/BoldDerivationExpressionsEditor.pas +++ b/Source/UMLModel/Editor/BoldDerivationExpressionsEditor.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldDerivationExpressionsEditor; interface diff --git a/Source/UMLModel/Editor/BoldDragObject.pas b/Source/UMLModel/Editor/BoldDragObject.pas index 990e56f..0c9db3b 100644 --- a/Source/UMLModel/Editor/BoldDragObject.pas +++ b/Source/UMLModel/Editor/BoldDragObject.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldDragObject; interface @@ -201,7 +204,7 @@ function GetControlAccepter(Target: TWinControl): TWinControl; begin while assigned(Target) and (not (csAcceptsControls in Target.ControlStyle)) do Target := Target.Parent; - Result := Target; + Result := Target; end; @@ -234,7 +237,6 @@ function TBoldDTDragObject.AllowDrop(Control: TControl): boolean; (BoldGUIHandler.DraggedObjects[0] is TUMLModelElement); if Result then begin - // Allow dropping on designer form if we have a matching provider. UMLElement := BoldGUIHandler.DraggedObjects[0] as TUMLModelElement; Result := ControlProviderList.MatchingProvider(UMLElement) <> nil; end; @@ -276,12 +278,9 @@ procedure TBoldDTDragObject.PerformDrop(Target: TWinControl; x, y: integer); (BoldGUIHandler.DraggedObjects.Count > 0) and (BoldGUIHandler.DraggedObjects[0] is TUMLModelElement) then begin - // At this point any component can be created on the form. GetCursorPos(p); p := Target.ScreenToClient(p); UMLElement := BoldGUIHandler.DraggedObjects[0] as TUMLModelElement; - - //Check we have a matching provider and then invoke it ControlProvider := ControlProviderList.MatchingProvider(UMLElement); if Assigned(ControlProvider) then ControlProvider.MakeComponent(UMLElement, Target, p); @@ -302,7 +301,7 @@ procedure TBoldControlProvider.CreateLabel; aLabel.Left := fPoint.x; aLabel.Caption := fUMLElement.Name; - aLabel.Name := UniqueName('lbl' + fUMLElement.ExpandedExpressionName); // do not localize + aLabel.Name := UniqueName('lbl' + fUMLElement.ExpandedExpressionName); if fControl is TWinControl then aLabel.FocusControl := fControl as TWinControl; end; @@ -326,10 +325,9 @@ function TBoldControlProvider.GetEnsuredHandle: TBoldHandle; function TBoldControlProvider.GetHandleClass: TBoldHandleClass; begin - // This method may be abstract when the mechanism is in place. - // The theory is that we should try to find the best matching provider or - // create a new handle of type HandleClass. - // Returning nil just avoids a compiler warning. + + + Result := nil; end; @@ -417,7 +415,7 @@ function TBoldControlProviderList.MatchingProvider( function TBoldControlProviderForClass.GetComponentName: string; begin - Result := PrefixedUMLName('grd'); // do not localize + Result := PrefixedUMLName('grd'); end; function TBoldControlProviderForClass.GetControlClass: TControlClass; @@ -442,7 +440,7 @@ function TBoldControlProviderForAttribute.IsMatch(UMLElement: TUMLModelElement): function TBoldControlProviderForStringAttribute.GetComponentName: string; begin - Result := PrefixedUMLName('txt'); // do not localize + Result := PrefixedUMLName('txt'); end; function TBoldControlProviderForStringAttribute.GetControlClass: TControlClass; @@ -466,7 +464,7 @@ function TBoldControlProviderForAssociationEnd.IsMatch(UMLElement: TUMLModelElem function TBoldControlProviderForAssociationEndMulti.GetComponentName: string; begin - Result := PrefixedUMLName('lbx'); // do not localize + Result := PrefixedUMLName('lbx'); end; function TBoldControlProviderForAssociationEndMulti.GetControlClass: TControlClass; @@ -484,7 +482,7 @@ function TBoldControlProviderForAssociationEndMulti.IsMatch(UMLElement: TUMLMode function TBoldControlProviderForAssociationEndSingle.GetComponentName: string; begin - Result := PrefixedUMLName('txt'); // do not localize + Result := PrefixedUMLName('txt'); end; function TBoldControlProviderForAssociationEndSingle.GetControlClass: TControlClass; @@ -502,7 +500,7 @@ function TBoldControlProviderForAssociationEndSingle.IsMatch(UMLElement: TUMLMod function TBoldControlProviderForMemoAttribute.GetComponentName: string; begin - Result := PrefixedUMLName('mmo'); // do not localize + Result := PrefixedUMLName('mmo'); end; function TBoldControlProviderForMemoAttribute.GetControlClass: TControlClass; @@ -514,14 +512,14 @@ function TBoldControlProviderForMemoAttribute.IsMatch( UMLElement: TUMLModelElement): boolean; begin Result := inherited IsMatch(UMLElement) and - (AnsiCompareStr((UMLElement as TUMLAttribute).typeName, 'Blob') = 0); // do not localize + (AnsiCompareStr((UMLElement as TUMLAttribute).typeName, 'Blob') = 0); end; { TBoldControlProviderForImageAttribute } function TBoldControlProviderForImageAttribute.GetComponentName: string; begin - Result := PrefixedUMLName('img'); // do not localize + Result := PrefixedUMLName('img'); end; function TBoldControlProviderForImageAttribute.GetControlClass: TControlClass; @@ -533,8 +531,8 @@ function TBoldControlProviderForImageAttribute.IsMatch( UMLElement: TUMLModelElement): boolean; begin Result := inherited IsMatch(UMLElement) and - ((AnsiCompareStr((UMLElement as TUMLAttribute).typeName, 'BlobImageBMP') = 0) or // do not localize - (AnsiCompareStr((UMLElement as TUMLAttribute).typeName, 'BlobImageJPEG') = 0)); // do not localize + ((AnsiCompareStr((UMLElement as TUMLAttribute).typeName, 'BlobImageBMP') = 0) or + (AnsiCompareStr((UMLElement as TUMLAttribute).typeName, 'BlobImageJPEG') = 0)); end; { TBoldControlProviderForBooleanAttribute } @@ -546,7 +544,7 @@ function TBoldControlProviderForBooleanAttribute.GetAddLabel: boolean; function TBoldControlProviderForBooleanAttribute.GetComponentName: string; begin - Result := PrefixedUMLName('cbx'); // do not localize + Result := PrefixedUMLName('cbx'); end; function TBoldControlProviderForBooleanAttribute.GetControlClass: TControlClass; @@ -558,7 +556,7 @@ function TBoldControlProviderForBooleanAttribute.IsMatch( UMLElement: TUMLModelElement): boolean; begin Result := inherited IsMatch(UMLElement) and - (AnsiCompareStr((UMLElement as TUMLAttribute).typeName, 'Boolean') = 0); // do not localize + (AnsiCompareStr((UMLElement as TUMLAttribute).typeName, 'Boolean') = 0); end; { TBoldControlProviderForOperation } @@ -570,7 +568,7 @@ function TBoldControlProviderForOperation.GetAddLabel: boolean; function TBoldControlProviderForOperation.GetComponentName: string; begin - Result := PrefixedUMLName('btn'); // do not localize + Result := PrefixedUMLName('btn'); end; function TBoldControlProviderForOperation.GetControlClass: TControlClass; @@ -586,12 +584,11 @@ function TBoldControlProviderForOperation.IsMatch(UMLElement: TUMLModelElement): procedure TBoldControlProviderForOperation.SetupComponent; begin inherited; - (fControl as TButton).Caption := fUMLElement.Name; + (fControl as TButton).Caption := fUMLElement.Name; end; initialization - // Note: Order important. List is traversed in reverse order, - // so less general should be added later in the list. + ControlProviderList.Add(TBoldControlProviderForClass.Create); ControlProviderList.Add(TBoldControlProviderForOperation.Create); ControlProviderList.Add(TBoldControlProviderForAssociationEndMulti.Create); @@ -605,6 +602,3 @@ finalization FreeAndNil(G_BoldControlProviderList); end. - - - diff --git a/Source/UMLModel/Editor/BoldUMLAddTV.pas b/Source/UMLModel/Editor/BoldUMLAddTV.pas index 39bf554..39f3713 100644 --- a/Source/UMLModel/Editor/BoldUMLAddTV.pas +++ b/Source/UMLModel/Editor/BoldUMLAddTV.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldUMLAddTV; interface diff --git a/Source/UMLModel/Editor/BoldUMLConstraintEditor.pas b/Source/UMLModel/Editor/BoldUMLConstraintEditor.pas index ad3691b..51116c1 100644 --- a/Source/UMLModel/Editor/BoldUMLConstraintEditor.pas +++ b/Source/UMLModel/Editor/BoldUMLConstraintEditor.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldUMLConstraintEditor; interface @@ -59,7 +62,6 @@ implementation SysUtils, BoldDefs, BoldQueue, - BoldRev, BoldUMLModelSupport; {$R *.dfm} diff --git a/Source/UMLModel/Editor/BoldUMLModelEdit.pas b/Source/UMLModel/Editor/BoldUMLModelEdit.pas index 97ebc35..36b0726 100644 --- a/Source/UMLModel/Editor/BoldUMLModelEdit.pas +++ b/Source/UMLModel/Editor/BoldUMLModelEdit.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldUMLModelEdit; interface @@ -39,10 +42,9 @@ implementation uses SysUtils, - BoldRev, BoldRegistry, Controls, - BoldUMLModelDataModule, + BoldUMLModelDataModule, BoldGuard; var G_ModelEditor: TModelEdit = nil; @@ -69,9 +71,8 @@ constructor TModelEdit.Create; destructor TModelEdit.Destroy; begin while EditForms.Count > 0 do - TBoldModelEditFrm(EditForms.Items[EditForms.Count - 1]).Free; // Will remove from list through notification + TBoldModelEditFrm(EditForms.Items[EditForms.Count - 1]).Free; FreeAndNil(FEditForms); - // The plugins are freed in the finalization part of BoldUMLPlugins.pas. FreeAndNil(FPlugInList); inherited; end; @@ -117,20 +118,19 @@ class procedure TModelEdit.SaveFormsettingsToRegistry(aForm: TBoldModelEditFrm); try with BoldRegistry do begin - OpenKey('\UMLModel'); // do not localize - WriteInteger('Width', aForm.Width); // do not localize - WriteInteger('Height', aForm.Height); // do not localize - WriteInteger('Left', aForm.Left); // do not localize - WriteInteger('Top', aForm.Top); // do not localize - WriteInteger('TreeViewWidth', aForm.BoldTreeView1.Width); // do not localize - WriteInteger('ModelHeight', aForm.sbModel.Height); // do not localize - WriteInteger('ClassHeight', aForm.sbClass.Height); // do not localize - WriteInteger('OperationHeight', aForm.sbOperation.Height); // do not localize - WriteInteger('AssociationHeight', aForm.sbAssociation.Height); // do not localize - WriteInteger('AssociationEndHeight', aForm.sbAssociationEnd.Height); // do not localize + OpenKey('\UMLModel'); + WriteInteger('Width', aForm.Width); + WriteInteger('Height', aForm.Height); + WriteInteger('Left', aForm.Left); + WriteInteger('Top', aForm.Top); + WriteInteger('TreeViewWidth', aForm.BoldTreeView1.Width); + WriteInteger('ModelHeight', aForm.sbModel.Height); + WriteInteger('ClassHeight', aForm.sbClass.Height); + WriteInteger('OperationHeight', aForm.sbOperation.Height); + WriteInteger('AssociationHeight', aForm.sbAssociation.Height); + WriteInteger('AssociationEndHeight', aForm.sbAssociationEnd.Height); end; except - // Silently discard exceptions end; end; @@ -144,21 +144,20 @@ class procedure TModelEdit.LoadFormsettingsFromRegistry(aForm: TBoldModelEditFrm BoldRegistry := TBoldRegistry.Create; with BoldRegistry do begin - OpenKey('\UMLModel'); // do not localize - aForm.Width := ReadInteger('Width', 800); // do not localize - aForm.Height := ReadInteger('Height', 600); // do not localize - aForm.Left := ReadInteger('Left', 0); // do not localize - aForm.Top := ReadInteger('Top', 0); // do not localize - - aForm.BoldTreeView1.Width := ReadInteger('TreeViewWidth', aForm.BoldTreeView1.Width); // do not localize - aForm.sbModel.Height := ReadInteger('ModelHeight', aForm.sbModel.Height); // do not localize - aForm.sbClass.Height := ReadInteger('ClassHeight', aForm.sbClass.Height); // do not localize - aForm.sbOperation.Height := ReadInteger('OperationHeight', aForm.sbOperation.Height); // do not localize - aForm.sbAssociation.Height := ReadInteger('AssociationHeight', aForm.sbAssociation.Height); // do not localize - aForm.sbAssociationEnd.Height := ReadInteger('AssociationEndHeight', aForm.sbAssociationEnd.Height); // do not localize + OpenKey('\UMLModel'); + aForm.Width := ReadInteger('Width', 800); + aForm.Height := ReadInteger('Height', 600); + aForm.Left := ReadInteger('Left', 0); + aForm.Top := ReadInteger('Top', 0); + + aForm.BoldTreeView1.Width := ReadInteger('TreeViewWidth', aForm.BoldTreeView1.Width); + aForm.sbModel.Height := ReadInteger('ModelHeight', aForm.sbModel.Height); + aForm.sbClass.Height := ReadInteger('ClassHeight', aForm.sbClass.Height); + aForm.sbOperation.Height := ReadInteger('OperationHeight', aForm.sbOperation.Height); + aForm.sbAssociation.Height := ReadInteger('AssociationHeight', aForm.sbAssociation.Height); + aForm.sbAssociationEnd.Height := ReadInteger('AssociationEndHeight', aForm.sbAssociationEnd.Height); end; except - //Silently discard exception end; end; diff --git a/Source/UMLModel/Editor/BoldUMLModelEditForm.pas b/Source/UMLModel/Editor/BoldUMLModelEditForm.pas index 387a449..c5240dc 100644 --- a/Source/UMLModel/Editor/BoldUMLModelEditForm.pas +++ b/Source/UMLModel/Editor/BoldUMLModelEditForm.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldUMLModelEditForm; interface @@ -19,6 +22,7 @@ interface BoldModel, BoldGrid, BoldUMLModel, + BoldUMLTypes, StdCtrls, ComCtrls, BoldXCVTreeView, @@ -487,14 +491,9 @@ TBoldModelEditFrm = class(TForm, IUnknown, IUMLModelPlugInContext) AddSubclass1: TMenuItem; AddSubclass2: TMenuItem; apeHintCatcher: TApplicationEvents; - function bcrAutoCreatedGetAsCheckBoxState( - Element: TBoldElement; Representation: Integer; - Expression: String): TCheckBoxState; - procedure bcrAutoCreatedSetAsCheckBoxState( - Element: TBoldElement; newValue: TCheckBoxState; - Representation: Integer; Expression: String); - procedure bsrRedOnAutocreatedSetColor(Element: TBoldElement; - var AColor: TColor; Representation: Integer; Expression: String); + function bcrAutoCreatedGetAsCheckBoxState(aFollower: TBoldFollower): TCheckBoxState; + procedure bcrAutoCreatedSetAsCheckBoxState(aFollower: TBoldFollower; newValue: TCheckBoxState); + procedure bsrRedOnAutocreatedSetColor(aFollower: TBoldFollower; var AColor: TColor); procedure Boldifymodel1Click(Sender: TObject); procedure FlattenClick(Sender: TObject); procedure Loggform1Click(Sender: TObject); @@ -539,36 +538,21 @@ TBoldModelEditFrm = class(TForm, IUnknown, IUMLModelPlugInContext) procedure mnuOverrideInAllSubclassesClick(Sender: TObject); procedure btInterfaceUsesClick(Sender: TObject); procedure btImplementationUsesClick(Sender: TObject); - function bsrNiceCRRendererGetAsString(Element: TBoldElement; - Representation: Integer; Expression: String): String; - procedure bsrNiceCRRendererSubscribe(Element: TBoldElement; - Representation: Integer; Expression: String; - Subscriber: TBoldSubscriber); + function bsrNiceCRRendererGetAsString(aFollower: TBoldFollower): String; + procedure bsrNiceCRRendererSubscribe(aFollower: TBoldFollower; Subscriber: TBoldSubscriber); procedure Splitter2CanResize(Sender: TObject; var NewSize: Integer; var Accept: Boolean); procedure BoldTreeView1KeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); procedure Contents1Click(Sender: TObject); procedure BoldTreeView1Expanded(Sender: TObject; Node: TTreeNode); - function bcrGetSetGetAsCheckBoxState(Element: TBoldElement; - Representation: Integer; Expression: String): TCheckBoxState; - procedure bcrGetSetSubscribe(Element: TBoldElement; - Representation: Integer; Expression: String; - Subscriber: TBoldSubscriber); - function bcrGetSetMayModify(Element: TBoldElement; - Representation: Integer; Expression: String; - Subscriber: TBoldSubscriber): Boolean; - procedure bcrBooleanToCheckBoxSubscribe(Element: TBoldElement; - Representation: Integer; Expression: String; - Subscriber: TBoldSubscriber); - function bcrBooleanToCheckBoxGetAsCheckBoxState(Element: TBoldElement; - Representation: Integer; Expression: String): TCheckBoxState; - procedure bcrBooleanToCheckBoxSetAsCheckBoxState(Element: TBoldElement; - newValue: TCheckBoxState; Representation: Integer; - Expression: String); - procedure bcrGetSetSetAsCheckBoxState(Element: TBoldElement; - newValue: TCheckBoxState; Representation: Integer; - Expression: String); + function bcrGetSetGetAsCheckBoxState(aFollower: TBoldFollower): TCheckBoxState; + procedure bcrGetSetSubscribe(aFollower: TBoldFollower; Subscriber: TBoldSubscriber); + function bcrGetSetMayModify(aFollower: TBoldFollower): Boolean; + procedure bcrBooleanToCheckBoxSubscribe(aFollower: TBoldFollower; Subscriber: TBoldSubscriber); + function bcrBooleanToCheckBoxGetAsCheckBoxState(aFollower: TBoldFollower): TCheckBoxState; + procedure bcrBooleanToCheckBoxSetAsCheckBoxState(aFollower: TBoldFollower; newValue: TCheckBoxState); + procedure bcrGetSetSetAsCheckBoxState(aFollower: TBoldFollower; newValue: TCheckBoxState); procedure btModelConstraintEditorClick(Sender: TObject); procedure btShowDerivationExpressionsEditorClick(Sender: TObject); procedure N3Click(Sender: TObject); @@ -586,9 +570,7 @@ TBoldModelEditFrm = class(TForm, IUnknown, IUMLModelPlugInContext) procedure NewDatatype1Click(Sender: TObject); procedure NewPackage1Click(Sender: TObject); procedure InsertSuperclass1Click(Sender: TObject); - function bcrBooleanToCheckBoxMayModify(Element: TBoldElement; - Representation: Integer; Expression: String; - Subscriber: TBoldSubscriber): Boolean; + function bcrBooleanToCheckBoxMayModify(aFollower: TBoldFollower): Boolean; procedure BoldTreeView1EndDrag(Sender, Target: TObject; X, Y: Integer); procedure FormClose(Sender: TObject; var Action: TCloseAction); procedure FormActivate(Sender: TObject); @@ -598,7 +580,6 @@ TBoldModelEditFrm = class(TForm, IUnknown, IUMLModelPlugInContext) private { Private declarations } fModelChangedSubscriber: TBoldPassthroughSubscriber; - fModelValidationSubscriber: TBoldPassthroughSubscriber; fModelSubscriptionsValid: Boolean; fIgnoreModelChanges: Boolean; fShowAttribKindFeaturesSubscriber: TBoldPassThroughSubscriber; @@ -612,7 +593,6 @@ TBoldModelEditFrm = class(TForm, IUnknown, IUMLModelPlugInContext) fModelNeedsValidation: Boolean; fModelHandle: TBoldModel; procedure SetCheckBoxHints; - procedure ModelValidatedReceive(Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent); procedure EditOclExpression(Element: TUMLModelElement; TaggedValue: String; Context: TUMLModelElement); function GetUMLObjectToCopyOrMove: TUMLModelElement; procedure SetUMLObjectToCopyOrMove(const Value: TUMLModelElement); @@ -630,7 +610,6 @@ TBoldModelEditFrm = class(TForm, IUnknown, IUMLModelPlugInContext) procedure CreateModelMethodItems(UMLClass: TUMLClass); procedure CreateFrameworkMethodItems(UMLClass: TUMLClass); procedure ClearMenuItems(var MenuItem: TMenuItem); - function GetMethodName(Method: String): String; procedure GetParamNames(Method: String; ResultList: TStringList); procedure GetParamTypes(Method: String; ResultList: TStringList); function GetReturnType(Method: String): String; @@ -710,6 +689,8 @@ TBoldModelEditFrm = class(TForm, IUnknown, IUMLModelPlugInContext) function CloseThisForm: TCloseAction; property ModelNeedsValidation: Boolean read FModelNeedsValidation write SetModelNeedsValidation; procedure EnsureFlattenedAndBoldified; + class function GetMethodName(Method: String): String; static; + class function GetMethodVisibility(Method: String): TVisibilityKind; static; end; //var @@ -719,29 +700,38 @@ TBoldModelEditFrm = class(TForm, IUnknown, IUMLModelPlugInContext) // kala 990707 It should not be ',' as separator between param-names. {$IFDEF BOLD_DELPHI} - FrameworkMethods: array[0..12] of String = ( + FrameworkMethods: array[0..20] of String = ( 'function GetStringRepresentation(Representation: TBoldRepresentation): string; virtual;', - 'procedure SetStringRepresentation(Representation: TBoldRepresentation; Value: string); virtual;', + 'procedure SetStringRepresentation(Representation: TBoldRepresentation; const Value: string); virtual;', 'procedure SubscribeToStringRepresentation(Representation: TBoldRepresentation; Subscriber: TBoldSubscriber; RequestedEvent: TBoldEvent); virtual;', - 'function ValidateCharacter(C: AnsiChar; Representation: TBoldRepresentation): Boolean; virtual;', - 'function ValidateString(Value: string; Representation: TBoldRepresentation): Boolean; virtual;', + 'function ValidateCharacter(C: Char; Representation: TBoldRepresentation): Boolean; virtual;', + 'function ValidateString(const Value: string; Representation: TBoldRepresentation): Boolean; virtual;', 'function CompareToAs(CompareType: TBoldCompareType; BoldDirectElement: TBoldElement): Integer; virtual;', - 'procedure ReceiveEventFromOwned(Originator: TObject; OriginalEvent: TBoldEvent); virtual;', + 'procedure ReceiveEventFromOwned(Originator: TObject; OriginalEvent: TBoldEvent; const Args: array of const); virtual;', 'function ReceiveQueryFromOwned(Originator: TObject; OriginalEvent: TBoldEvent; const Args: array of const; Subscriber: TBoldSubscriber): Boolean; virtual;', 'procedure Assign(Source: TBoldElement); virtual;', 'procedure CompleteCreate; virtual;', + 'procedure CompleteRecreate; virtual;', + 'procedure CompleteUpdate; virtual;', + 'procedure AfterConstruction; virtual;', + 'procedure BeforeDestruction; virtual;', 'function MayDelete: Boolean; virtual;', 'function MayUpdate: Boolean; virtual;', - 'procedure PrepareDelete; virtual;' + 'procedure PrepareDelete; virtual;', + 'procedure PrepareDiscard; virtual;', + 'procedure PrepareUpdate; virtual;', + 'procedure InternalPrepareDeleteOrDeleteByDiscard; virtual;', + 'function InternalCanDeleteObject: Boolean; virtual;' ); {$ENDIF} {$IFDEF BOLD_BCB} + // TODO: BCB Methods not updated, adjust from the Delphi list above FrameworkMethods: array[0..12] of String = ( - 'function GetStringRepresentation(Representation: int): AnsiString; virtual;', - 'procedure SetStringRepresentation(Representation: int; Value: AnsiString); virtual;', + 'function GetStringRepresentation(Representation: int): String; virtual;', + 'procedure SetStringRepresentation(Representation: int; const Value: String); virtual;', 'procedure SubscribeToStringRepresentation(Representation: int; Subscriber: TBoldSubscriber*; RequestedEvent: int); virtual;', - 'function ValidateCharacter(C: AnsiChar; Representation: int): Boolean; virtual;', - 'function ValidateString(Value: AnsiString; Representation: int): Boolean; virtual;', + 'function ValidateCharacter(C: Char; Representation: int): Boolean; virtual;', + 'function ValidateString(Value: String; Representation: int): Boolean; virtual;', 'function CompareToAs(CompareType: TBoldCompareType; BoldDirectElement: TBoldElement*): Integer; virtual;', 'procedure ReceiveEventFromOwned(Originator: TObject*; OriginalEvent: int); virtual;', 'function ReceiveQueryFromOwned(Originator: TObject*; OriginalEvent: int; Args: const TVarRec*; Subscriber: TBoldSubscriber*): Boolean; virtual;', @@ -757,7 +747,6 @@ TBoldModelEditFrm = class(TForm, IUnknown, IUMLModelPlugInContext) implementation uses - BoldRev, BoldDefaultTaggedValues, BoldUMLAttributes, BoldUMLModelConverter, @@ -767,7 +756,6 @@ implementation BoldCursorGuard, BoldSystem, BoldAttributes, - BoldUMLTypes, BoldUMLModelValidator, BoldUMLModelLink, BoldLogHandler, @@ -787,7 +775,8 @@ implementation BoldDerivationExpressionsEditor, BoldUMLOCLEditor, BoldUMLModelSupport, - BoldUMLPluginCallBacks; + BoldUMLPluginCallBacks, + BoldUMLAbstractModelValidator; {$R *.dfm} @@ -1068,7 +1057,6 @@ procedure TBoldModelEditFrm.mnuConsistencycheckClick(Sender: TObject); ValidationForm.ValidationProc := TBoldUMLModelValidatorCallBack.Validate; ValidationForm.Show; ValidationForm.Validate; - ModelNeedsValidation := False; end; function TBoldModelEditFrm.GetCurrentModel: TUMLModel; @@ -1346,7 +1334,6 @@ procedure TBoldModelEditFrm.FormCreate(Sender: TObject); CutOrCopy := cckNone; fModelChangedSubscriber := TBoldPassthroughSubscriber.Create(ModelChangedRecieve); - fModelValidationSubscriber := TBoldPassthroughSubscriber.Create(ModelValidatedReceive); FShowAttribKindFeaturesSubscriber := TBoldPassthroughSubscriber.Create(ShowAttribKindFeaturesRecieve); for Index := 0 to pcModelEdit.PageCount - 1 do @@ -1546,12 +1533,13 @@ procedure TBoldModelEditFrm.pcModelEditChange(Sender: TObject); procedure TBoldModelEditFrm.ModelChangedRecieve(Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent); begin + if GetCurrentModelHandle.IsValidating then + exit; fModelSubscriptionsValid := false; if not fIgnoreModelChanges then ModelNeedsValidation := True; end; - procedure TBoldModelEditFrm.FormShow(Sender: TObject); var Index: Integer; @@ -1765,7 +1753,7 @@ procedure TBoldModelEditFrm.DroppedOnUMLOperation(Dropped: TUMLParameter; Target Target.Parameter.Add(Dropped); end; -function TBoldModelEditFrm.GetMethodName(Method: String): String; +class function TBoldModelEditFrm.GetMethodName(Method: String): String; var StartPos, EndPos: Integer; begin StartPos := 0; @@ -1787,6 +1775,27 @@ function TBoldModelEditFrm.GetMethodName(Method: String): String; Result := Trim(Copy(Method, StartPos, EndPos - StartPos)); end; +class function TBoldModelEditFrm.GetMethodVisibility(Method: String): + TVisibilityKind; +var + EndPos: Integer; + sVisibility: string; +begin + EndPos := Pos('function', Method); + if EndPos = 0 then begin + EndPos := Pos('procedure', Method); + end; + + sVisibility := Copy(Method, 1, EndPos - 2); + if BoldAnsiEqual(sVisibility, 'private') then begin + Result := vkPrivate; + end else if BoldAnsiEqual(sVisibility, 'protected') then begin + Result := vkProtected; + end else begin + Result := vkPublic; + end; +end; + procedure TBoldModelEditFrm.GetParamNames(Method: String; ResultList: TStringList); var StartPos, EndPos, FinalPos: Integer; NameWithKind: String; @@ -2031,6 +2040,7 @@ procedure TBoldModelEditFrm.OverrideModelMethod(MethodName: String); TBoldUMLSupport.EnsureBoldTaggedValues(NewOperation); NewOperation.owner := Class_; NewOperation.name := OldOperation.Name; + NewOperation.visibility := OldOperation.Visibility; NewOperation.SetBoldTV(TAG_DELPHIOPERATIONKIND, TV_DELPHIOPERATIONKIND_OVERRIDE); for Index := 0 to OldOperation.Parameter.Count - 1 do begin @@ -2109,13 +2119,11 @@ procedure TBoldModelEditFrm.btImplementationUsesClick(Sender: TObject); TfrmUsesEditor.CreateEditorWithParams('Implementation Uses Editor', behModel.Value, tbxModelImplementationUses.BoldProperties.Expression); end; -function TBoldModelEditFrm.bsrNiceCRRendererGetAsString( - Element: TBoldElement; Representation: Integer; - Expression: String): String; +function TBoldModelEditFrm.bsrNiceCRRendererGetAsString(aFollower: TBoldFollower): String; begin - if Assigned(Element) then + if Assigned(aFollower.Value) then begin - Result := Element.EvaluateExpressionAsString(Expression, Representation); + Result := aFollower.Value.AsString; while Pos(BOLDCRLF, Result) > 0 do Delete(Result, Pos(BOLDCRLF, Result), 2); end @@ -2123,11 +2131,9 @@ function TBoldModelEditFrm.bsrNiceCRRendererGetAsString( Result := ''; end; -procedure TBoldModelEditFrm.bsrNiceCRRendererSubscribe( - Element: TBoldElement; Representation: Integer; Expression: String; - Subscriber: TBoldSubscriber); +procedure TBoldModelEditFrm.bsrNiceCRRendererSubscribe(aFollower: TBoldFollower; Subscriber: TBoldSubscriber); begin - Element.SubscribeToExpression(Expression, Subscriber, False); + aFollower.Element.SubscribeToExpression(aFollower.Controller.Expression, Subscriber, False); end; procedure TBoldModelEditFrm.Splitter2CanResize(Sender: TObject; @@ -2162,47 +2168,37 @@ procedure TBoldModelEditFrm.BoldTreeView1Expanded(Sender: TObject; BoldTreeView1.Items[0].Selected := True; end; -function TBoldModelEditFrm.bcrGetSetGetAsCheckBoxState( - Element: TBoldElement; Representation: Integer; - Expression: String): TCheckBoxState; +function TBoldModelEditFrm.bcrGetSetGetAsCheckBoxState(aFollower: TBoldFollower): TCheckBoxState; begin Result := cbGrayed; - if Assigned(Element) then - Result := bcrBooleanToCheckBoxGetAsCheckBoxState(Element, Representation, Expression); + if Assigned(aFollower.Element) then + Result := bcrBooleanToCheckBoxGetAsCheckBoxState(aFollower); end; -procedure TBoldModelEditFrm.bcrGetSetSubscribe(Element: TBoldElement; - Representation: Integer; Expression: String; - Subscriber: TBoldSubscriber); +procedure TBoldModelEditFrm.bcrGetSetSubscribe(aFollower: TBoldFollower; Subscriber: TBoldSubscriber); begin - (Element as TUMLAttribute).M_StereotypeName.DefaultSubscribe(Subscriber, breReEvaluate); - Element.SubscribeToExpression(Expression, Subscriber, False); + (aFollower.Element as TUMLAttribute).M_StereotypeName.DefaultSubscribe(Subscriber, breReEvaluate); + aFollower.Element.SubscribeToExpression(aFollower.Controller.Expression, Subscriber, False); end; -function TBoldModelEditFrm.bcrGetSetMayModify(Element: TBoldElement; - Representation: Integer; Expression: String; - Subscriber: TBoldSubscriber): Boolean; +function TBoldModelEditFrm.bcrGetSetMayModify(aFollower: TBoldFollower): Boolean; begin - Result := (Element as TUMLAttribute).GetBoldTV(TAG_ATTRIBUTEKIND) = TV_ATTRIBUTEKIND_DELPHI; + Result := (aFollower.Element as TUMLAttribute).GetBoldTV(TAG_ATTRIBUTEKIND) = TV_ATTRIBUTEKIND_DELPHI; end; -procedure TBoldModelEditFrm.bcrBooleanToCheckBoxSubscribe( - Element: TBoldElement; Representation: Integer; Expression: String; - Subscriber: TBoldSubscriber); +procedure TBoldModelEditFrm.bcrBooleanToCheckBoxSubscribe(aFollower: TBoldFollower; Subscriber: TBoldSubscriber); begin - Element.SubscribeToExpression(Expression, Subscriber, False); + aFollower.Element.SubscribeToExpression(aFollower.Controller.Expression, Subscriber, False); end; -function TBoldModelEditFrm.bcrBooleanToCheckBoxGetAsCheckBoxState( - Element: TBoldElement; Representation: Integer; - Expression: String): TCheckBoxState; +function TBoldModelEditFrm.bcrBooleanToCheckBoxGetAsCheckBoxState(aFollower: TBoldFollower): TCheckBoxState; var anElement: TBoldElement; begin Result := cbGrayed; - if Assigned(Element) then + if Assigned(aFollower.Element) then begin - anElement := Element.EvaluateExpressionAsDirectElement(Expression); + anElement := aFollower.Value; if Assigned(anElement) then begin if TVIsTrue(anElement.AsString)then @@ -2213,18 +2209,14 @@ function TBoldModelEditFrm.bcrBooleanToCheckBoxGetAsCheckBoxState( end; end; -procedure TBoldModelEditFrm.bcrBooleanToCheckBoxSetAsCheckBoxState( - Element: TBoldElement; newValue: TCheckBoxState; Representation: Integer; - Expression: String); +procedure TBoldModelEditFrm.bcrBooleanToCheckBoxSetAsCheckBoxState(aFollower: TBoldFollower; newValue: TCheckBoxState); begin - Element.EvaluateExpressionAsDirectElement(Expression).AsString := BooleanToString(NewValue = cbChecked); + aFollower.Value.AsString := BooleanToString(NewValue = cbChecked); end; -procedure TBoldModelEditFrm.bcrGetSetSetAsCheckBoxState( - Element: TBoldElement; newValue: TCheckBoxState; Representation: Integer; - Expression: String); +procedure TBoldModelEditFrm.bcrGetSetSetAsCheckBoxState(aFollower: TBoldFollower; newValue: TCheckBoxState); begin - bcrBooleanToCheckBoxSetAsCheckBoxState(Element, newValue, Representation, Expression); + bcrBooleanToCheckBoxSetAsCheckBoxState(aFollower, newValue); end; procedure TBoldModelEditFrm.ShowAttribKindFeaturesRecieve(Originator: TObject; OriginalEvent: TBoldEvent; @@ -2277,7 +2269,6 @@ procedure TBoldModelEditFrm.FormDestroy(Sender: TObject); FreeItemsInMenu(mnuOverrideModelMethods); EnsureFreeConstraintEditor; FreeAndNil(fModelChangedSubscriber); - FreeAndNil(fModelValidationSubscriber); FreeAndNil(FShowAttribKindFeaturesSubscriber); end; @@ -2362,13 +2353,20 @@ procedure TBoldModelEditFrm.BoldTreeView1StartDrag(Sender: TObject; procedure TBoldModelEditFrm.EditOclExpression(Element: TUMLModelElement; TaggedValue: String; Context: TUMLModelElement); var res: String; + lPrevIgnoreModelChanges: Boolean; begin EnsureFlattenedAndBoldified; - res := BoldUMLOclEditor_.EditOcl( - ModelHandle, - Context, - Element.GetBoldTV(TaggedValue)); - Element.SetBoldTV(TaggedValue, res); + lPrevIgnoreModelChanges := IgnoreModelChanges; + IgnoreModelChanges := true; + try + res := BoldUMLOclEditor_.EditOcl( + ModelHandle, + Context, + Element.GetBoldTV(TaggedValue)); + finally + IgnoreModelChanges := lPrevIgnoreModelChanges; + Element.SetBoldTV(TaggedValue, res); + end; end; procedure TBoldModelEditFrm.btClassDefaultStringRepClick(Sender: TObject); @@ -2472,29 +2470,23 @@ function TBoldModelEditFrm.GetCurrentModelIsBoldified: Boolean; Result := (behBoldified.Value as TBABoolean).AsBoolean = true; end; -function TBoldModelEditFrm.bcrAutoCreatedGetAsCheckBoxState( - Element: TBoldElement; Representation: Integer; - Expression: String): TCheckBoxState; +function TBoldModelEditFrm.bcrAutoCreatedGetAsCheckBoxState(aFollower: TBoldFollower): TCheckBoxState; begin - if Assigned(Element) and TBoldUMLBoldify.IsAutocreated(Element as TUMLModelElement) then + if Assigned(aFollower.Element) and TBoldUMLBoldify.IsAutocreated(aFollower.Element as TUMLModelElement) then Result := cbChecked else Result := cbUnchecked end; -procedure TBoldModelEditFrm.bcrAutoCreatedSetAsCheckBoxState( - Element: TBoldElement; newValue: TCheckBoxState; Representation: Integer; - Expression: String); +procedure TBoldModelEditFrm.bcrAutoCreatedSetAsCheckBoxState(aFollower: TBoldFollower; newValue: TCheckBoxState); begin - if assigned(Element) and (newValue= cbUnchecked) then - TBoldUMLBoldify.RemoveBoldifyTaggedValue(Element as TUMLModelElement, TAG_AUTOCREATED); + if assigned(aFollower.Element) and (newValue= cbUnchecked) then + TBoldUMLBoldify.RemoveBoldifyTaggedValue(aFollower.Element as TUMLModelElement, TAG_AUTOCREATED); end; -procedure TBoldModelEditFrm.bsrRedOnAutocreatedSetColor( - Element: TBoldElement; var AColor: TColor; Representation: Integer; - Expression: String); +procedure TBoldModelEditFrm.bsrRedOnAutocreatedSetColor(aFollower: TBoldFollower; var AColor: TColor); begin - if Assigned(Element) and TBoldUMLBoldify.IsAutocreated(Element as TUMLModelElement) then + if Assigned(aFollower.Element) and TBoldUMLBoldify.IsAutocreated(aFollower.Element as TUMLModelElement) then aColor := clRed; end; @@ -2717,15 +2709,13 @@ procedure TBoldModelEditFrm.ApplyGUI; TBoldQueueable.ApplyAll; end; -function TBoldModelEditFrm.bcrBooleanToCheckBoxMayModify( - Element: TBoldElement; Representation: Integer; Expression: String; - Subscriber: TBoldSubscriber): Boolean; +function TBoldModelEditFrm.bcrBooleanToCheckBoxMayModify(aFollower: TBoldFollower): Boolean; var ValueElement: TBoldElement; begin - ValueElement := Element.EvaluateExpressionAsDirectElement(Expression); + ValueElement := aFollower.Value; if Assigned(ValueElement) then - Result := ValueElement.ObserverMayModify(subscriber) + Result := ValueElement.ObserverMayModify(aFollower.subscriber) else Result := false; end; @@ -2752,11 +2742,6 @@ procedure TBoldModelEditFrm.FormClose(Sender: TObject; var Action: TCloseAction) Action := caFree; end; -procedure TBoldModelEditFrm.ModelValidatedReceive(Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent); -begin - ModelNeedsValidation := false; -end; - procedure TBoldModelEditFrm.FormActivate(Sender: TObject); begin G_ValidationFormDefaultOwner := Self; @@ -2819,20 +2804,23 @@ function TBoldModelEditFrm.GetCurrentTypeNameDictionary: TBoldTypeNameDictionary procedure TBoldModelEditFrm.SetModelHandle(const Value: TBoldModel); begin - Value.FreeNotification(Self); - fModelHandle := Value; - brhTreeRoot.Value := ModelHandle.EnsuredUMLModel; - if assigned(CurrentModel) then + if FModelHandle <> Value then begin - EnsureTypesFromTypeNameHandle(nil); - TBoldUMLSupport.EnsureBoldTaggedVAlues(CurrentModel); - end - else - raise EBoldInternal.CreateFmt('%s.SetRoot: Root must be part of Model', [ClassName]); - ModelNeedsValidation := True; - CurrentModel.AddSubscription(fModelValidationSubscriber, beModelValidated, beModelValidated); - - EnsureValidationForm(GetCurrentModelHandle, self, JumpToElement); + BoldInstalledQueue.DeActivateDisplayQueue; + Value.FreeNotification(Self); + fModelHandle := Value; + brhTreeRoot.Value := ModelHandle.EnsuredUMLModel; + if assigned(CurrentModel) then + begin + EnsureTypesFromTypeNameHandle(nil); + TBoldUMLSupport.EnsureBoldTaggedVAlues(CurrentModel); + end + else + raise EBoldInternal.CreateFmt('%s.SetRoot: Root must be part of Model', [ClassName]); + ModelNeedsValidation := True; + EnsureValidationForm(GetCurrentModelHandle, self, JumpToElement); + BoldInstalledQueue.ActivateDisplayQueue; + end; end; procedure TBoldModelEditFrm.Notification(AComponent: TComponent; @@ -2866,5 +2854,3 @@ procedure TBoldModelEditFrm.SetCheckBoxHints; initialization end. - - diff --git a/Source/UMLModel/Editor/BoldUMLModelValidationForm.pas b/Source/UMLModel/Editor/BoldUMLModelValidationForm.pas index c4e5620..42d847e 100644 --- a/Source/UMLModel/Editor/BoldUMLModelValidationForm.pas +++ b/Source/UMLModel/Editor/BoldUMLModelValidationForm.pas @@ -1,8 +1,12 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldUMLModelValidationForm; interface uses + {$IFDEF MSWINDOWS} Windows, Messages, Graphics, @@ -12,6 +16,7 @@ interface StdCtrls, Grids, ComCtrls, + {$ENDIF} ClipBrd, ToolWin, Classes, @@ -29,9 +34,11 @@ interface BoldStringcontrolPack, BoldSystem, BoldModel, + BoldElements, + BoldPlaceableSubscriber, Menus, ExtCtrls, - ImgList, BoldElements, BoldPlaceableSubscriber; + ImgList; type TBoldUMLElementClickedEvent = procedure (sender: TComponent; element: TUMLModelElement) of object; @@ -63,13 +70,12 @@ TfrmValidation = class(TForm) procedure Cut1Click(Sender: TObject); procedure Copy1Click(Sender: TObject); procedure Paste1Click(Sender: TObject); - procedure BoldPlaceableSubscriber1Receive( - sender: TBoldPlaceableSubscriber; Originator: TObject; OriginalEvent, - RequestedEvent: Integer); + procedure BoldPlaceableSubscriber1Receive(sender: TBoldPlaceableSubscriber; + Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: Integer); private FOnElementClick: TBoldUMLElementClickedEvent; fValidationProc: TBoldValidationCallBack; - fModelComponent: TBoldModel; + fBoldModel: TBoldModel; function GetUMLModel: TUMLModel; protected procedure Notification(AComponent: TComponent; Operation: TOperation); override; @@ -77,13 +83,13 @@ TfrmValidation = class(TForm) constructor CreateWithModel(ModelComponent: TBoldModel; Owner: TComponent); destructor Destroy; override; procedure Validate; - property UMLModel: TUMLModel read GetUMLModel; - property ModelComponent: TBoldModel read fModelComponent; + property BoldModel: TBoldModel read fBoldModel; + property UmlModel: TUMLModel read GetUMLModel; property OnElementClick: TBoldUMLElementClickedEvent read FOnElementClick; property ValidationProc: TBoldValidationCallBack read fValidationProc write fValidationProc; end; - function EnsureValidationForm(ModelComponent: TBoldModel; Owner: TComponent; OnElementClick: TBoldUMLElementClickedEvent): TfrmValidation; + function EnsureValidationForm(ABoldModel: TBoldModel; Owner: TComponent; OnElementClick: TBoldUMLElementClickedEvent): TfrmValidation; var G_ValidationFormDefaultOwner: TComponent; @@ -92,7 +98,6 @@ implementation uses SysUtils, - BoldRev, BoldQueue, BoldEnvironment, BoldUtils, @@ -103,15 +108,15 @@ implementation {$R *.dfm} -function EnsureValidationForm(ModelComponent: TBoldModel; Owner: TComponent; OnElementClick: TBoldUMLElementClickedEvent): TfrmValidation; +function EnsureValidationForm(ABoldModel: TBoldModel; Owner: TComponent; OnElementClick: TBoldUMLElementClickedEvent): TfrmValidation; begin - if assigned(G_ValidationForm) and (G_ValidationForm.ModelComponent <> ModelComponent) then + if assigned(G_ValidationForm) and (G_ValidationForm.BoldModel <> ABoldModel) then begin G_ValidationForm.Release; G_ValidationForm := nil; end; if not Assigned(G_ValidationForm) then - G_ValidationForm := TfrmValidation.CreateWithModel(ModelComponent, Owner); + G_ValidationForm := TfrmValidation.CreateWithModel(ABoldModel, Owner); Result := G_ValidationForm; if assigned(OnElementClick) then result.fOnElementClick := OnElementclick; @@ -143,6 +148,14 @@ procedure TfrmValidation.btStayOnTopClick(Sender: TObject); FormStyle := fsNormal; end; +procedure TfrmValidation.BoldPlaceableSubscriber1Receive( + sender: TBoldPlaceableSubscriber; Originator: TObject; + OriginalEvent: TBoldEvent; RequestedEvent: Integer); +begin + if blhViolations.Count > 0 then + show; +end; + procedure TfrmValidation.btReCheckClick(Sender: TObject); begin Validate; @@ -151,7 +164,7 @@ procedure TfrmValidation.btReCheckClick(Sender: TObject); procedure TfrmValidation.Validate; begin if Assigned(ValidationProc) then - ValidationProc(ModelComponent) + ValidationProc(BoldModel) else raise EBold.Create('No validator registered'); @@ -162,11 +175,9 @@ procedure TfrmValidation.Validate; constructor TfrmValidation.CreateWithModel(ModelComponent: TBoldModel; Owner: Tcomponent); begin inherited create(Owner); - // Workaround - Setting the handle in designtime causes an AV in inherited Create BoldGrid1.BoldHandle := blhViolations; - // EndWorkaround - fModelComponent := ModelComponent; - fModelComponent.FreeNotification(Self); + fBoldModel := ModelComponent; + fBoldModel.FreeNotification(Self); behModel.Value := ModelComponent.EnsuredUMLModel; end; @@ -177,7 +188,10 @@ procedure TfrmValidation.mnuCopyLogtoClipBoardClick(Sender: TObject); function TfrmValidation.GetUMLModel: TUMLModel; begin - result := ModelComponent.EnsuredUMLModel; + if Assigned(BoldModel) then + result := BoldModel.EnsuredUMLModel + else + result := nil; end; procedure TfrmValidation.Cut1Click(Sender: TObject); @@ -198,26 +212,18 @@ procedure TfrmValidation.Paste1Click(Sender: TObject); SendMessage(ActiveControl.handle, WM_PASTE, 0, 0); end; -destructor TfrmValidation.destroy; +destructor TfrmValidation.Destroy; begin if G_ValidationForm = self then G_ValidationForm := nil; inherited; end; -procedure TfrmValidation.BoldPlaceableSubscriber1Receive( - sender: TBoldPlaceableSubscriber; Originator: TObject; OriginalEvent, - RequestedEvent: Integer); -begin - if blhViolations.Count > 0 then - show; -end; - procedure TfrmValidation.Notification(AComponent: TComponent; Operation: TOperation); begin inherited; - if (aComponent = fModelComponent) and (operation = opRemove) then - fModelComponent := nil; + if (aComponent = BoldModel) and (operation = opRemove) then + fBoldModel := nil; end; initialization diff --git a/Source/UMLModel/Editor/BoldUMLOCLEditor.pas b/Source/UMLModel/Editor/BoldUMLOCLEditor.pas index 2343059..5d0d440 100644 --- a/Source/UMLModel/Editor/BoldUMLOCLEditor.pas +++ b/Source/UMLModel/Editor/BoldUMLOCLEditor.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldUMLOCLEditor; interface @@ -28,9 +31,8 @@ implementation uses SysUtils, - Controls, // mr_OK - BoldDefs, - BoldRev, + Controls, + BoldDefs, BoldTypeNameDictionary; var diff --git a/Source/UMLModel/Editor/BoldUMLTaggedValuesEditor.pas b/Source/UMLModel/Editor/BoldUMLTaggedValuesEditor.pas index 1c7a644..b6c6b98 100644 --- a/Source/UMLModel/Editor/BoldUMLTaggedValuesEditor.pas +++ b/Source/UMLModel/Editor/BoldUMLTaggedValuesEditor.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldUMLTaggedValuesEditor; interface @@ -68,17 +71,15 @@ TfrmBoldUMLTaggedValuesEditor = class(TForm) RootValue: TBoldElement; ResultElement: TBoldIndirectElement; Subscriber: TBoldSubscriber); procedure tcToolsChange(Sender: TObject); - function BoldAsStringRenderer1GetAsString(Element: TBoldElement; - Representation: Integer; Expression: String): String; - procedure BoldAsStringRenderer1Subscribe(Element: TBoldElement; - Representation: Integer; Expression: String; - Subscriber: TBoldSubscriber); procedure FormCreate(Sender: TObject); procedure btAddTVClick(Sender: TObject); procedure btDeleteTVClick(Sender: TObject); procedure Copy1Click(Sender: TObject); procedure Cut1Click(Sender: TObject); procedure Paste1Click(Sender: TObject); + function BoldAsStringRenderer1GetAsString(aFollower: TBoldFollower): string; + procedure BoldAsStringRenderer1Subscribe(aFollower: TBoldFollower; + Subscriber: TBoldSubscriber); private fRootSubscriber: TBoldPassThroughSubscriber; PreviousSelectedTab: Integer; @@ -91,7 +92,7 @@ TfrmBoldUMLTaggedValuesEditor = class(TForm) procedure RefreshGUI(var Message: TMessage); message WM_REFRESHGUI; procedure DoMessage(Control: TControl; Msg: Cardinal); public - destructor Destroy; override; + destructor destroy; override; procedure SwitchMode(ReadOnly: Boolean); end; @@ -102,7 +103,6 @@ implementation uses SysUtils, BoldUtils, - BoldRev, BoldUMLModelDataModule, BoldUMLAddTV; @@ -231,21 +231,20 @@ procedure TfrmBoldUMLTaggedValuesEditor.tcToolsChange(Sender: TObject); end; function TfrmBoldUMLTaggedValuesEditor.BoldAsStringRenderer1GetAsString( - Element: TBoldElement; Representation: Integer; - Expression: String): String; + aFollower: TBoldFollower): string; begin Result := ''; - if Assigned(Element) then + if Assigned(aFollower.Element) then begin - Result := GetTagName((Element as TUMLTaggedValue).Tag); + Result := GetTagName((aFollower.Element as TUMLTaggedValue).Tag); end; end; + procedure TfrmBoldUMLTaggedValuesEditor.BoldAsStringRenderer1Subscribe( - Element: TBoldElement; Representation: Integer; Expression: String; - Subscriber: TBoldSubscriber); + aFollower: TBoldFollower; Subscriber: TBoldSubscriber); begin - (Element as TUMLTaggedValue).M_Tag.DefaultSubscribe(Subscriber, breReEvaluate); + (aFollower.Element as TUMLTaggedValue).M_Tag.DefaultSubscribe(Subscriber, breReEvaluate); end; procedure TfrmBoldUMLTaggedValuesEditor.PlaceSubscriptions; @@ -267,7 +266,6 @@ procedure TfrmBoldUMLTaggedValuesEditor.RecieveRootChanged( breReSubscribe: PlaceSubscriptions; end; PostMessage(Handle, WM_REFRESHGUI, 0, 0); - //CreateTabs; end; procedure TfrmBoldUMLTaggedValuesEditor.FormCreate(Sender: TObject); diff --git a/Source/UMLModel/Editor/BoldUMLUsesEditorForm.pas b/Source/UMLModel/Editor/BoldUMLUsesEditorForm.pas index 8687103..054b730 100644 --- a/Source/UMLModel/Editor/BoldUMLUsesEditorForm.pas +++ b/Source/UMLModel/Editor/BoldUMLUsesEditorForm.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldUMLUsesEditorForm; interface @@ -52,7 +55,6 @@ implementation uses SysUtils, BoldUtils, - BoldRev, BoldQueue; {$R *.dfm} diff --git a/Source/UMLModel/Handles/BoldModel.pas b/Source/UMLModel/Handles/BoldModel.pas index 2af6ac5..720137e 100644 --- a/Source/UMLModel/Handles/BoldModel.pas +++ b/Source/UMLModel/Handles/BoldModel.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldModel; interface @@ -31,16 +34,17 @@ TBoldModel = class(TBoldAbstractModel) fSystemHandle: TBoldSystemHandle; fModelChangedSubscriber: TBoldPassthroughSubscriber; fEditableModel: boolean; + fValidateNesting: integer; procedure SetBoldify(const Value: TBoldUMLBoldify); procedure EnsureUMLModel; procedure AssertDesignTime; procedure ReadUMLModelAsString(Reader: TReader); procedure WriteUMLModelAsString(Writer: TWriter); - function UMLModelToString: string; procedure UMLModelFromString(ModelAsString: string); function GetEnsuredUMLModel: TUMLModel; function GetUMLModel: TUMLModel; procedure UMLModelChangedRecieve(Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent); + function GetIsValidating: boolean; protected procedure DefineProperties(Filer: TFiler); override; procedure SubscribeToUMLModel; @@ -54,8 +58,12 @@ TBoldModel = class(TBoldAbstractModel) constructor Create(owner: TComponent); override; destructor Destroy; override; procedure EnsureTypes; + function UMLModelToString: string; + procedure StartValidation; + procedure EndValidation; property UMLModel: TUMLModel read GetUMLModel; property EnsuredUMLModel: TUMLModel read GetEnsuredUMLModel; + property IsValidating: boolean read GetIsValidating; published property UMLModelMode: TUMLModelMode read fUMLModelMode write fUMLModelMode; property Boldify: TBoldUMLBoldify read FBoldify write SetBoldify; @@ -83,7 +91,7 @@ function TheModelList: TBoldModelList; implementation uses - BoldUMLModelDataModule, // Circular dependency + BoldUMLModelDataModule, SysUtils, BoldLogHandler, BoldUMLModelStreamer, @@ -93,6 +101,7 @@ implementation BoldUMLAttributes, BoldUMLModelConverter, BoldUMLModelValidator, + BoldUMLUtils, BoldGuard; var @@ -117,7 +126,7 @@ constructor TBoldModel.Create(owner: TComponent); procedure TBoldModel.DefineProperties(Filer: TFiler); begin inherited DefineProperties(Filer); - Filer.DefineProperty('UMLModelAsString', ReadUMLModelAsString, WriteUMLModelAsString, UMLModelMode <> ummNone); // do not localize + Filer.DefineProperty('UMLModelAsString', ReadUMLModelAsString, WriteUMLModelAsString, UMLModelMode <> ummNone); end; destructor TBoldModel.Destroy; @@ -168,7 +177,6 @@ procedure TBoldModel.EnsureTypes; for Index := 0 to Count - 1 do begin if Mapping[index].ModelName = DEFAULTNAME then - // ignore else if Assigned(BoldMemberTypeList.DescriptorByDelphiName[Mapping[Index].ExpandedDelphiName]) then begin if BoldMemberTypeList.DescriptorByDelphiName[Mapping[index].ExpandedDelphiName].AbstractionLevel = alConcrete then @@ -187,6 +195,11 @@ function TBoldModel.GetEnsuredUMLModel: TUMLModel; MarkUMLModelExposed; end; +function TBoldModel.GetIsValidating: boolean; +begin + result := fValidateNesting > 0; +end; + procedure TBoldModel.ReadUMLModelAsString(Reader: TReader); begin fUMLModelAsString := Reader.ReadString; @@ -217,7 +230,7 @@ procedure TBoldModel.EnsureUMLModel; end; ummRunTime: UMLModelFromString(fUMLModelAsString); end; - fUMLModelAsString := ''; // Reclaim memory. Saving will be straight from UMLModel + fUMLModelAsString := ''; end; end; @@ -226,6 +239,16 @@ procedure TBoldModel.SetBoldify(const Value: TBoldUMLBoldify); Boldify.Assign(Value); end; +procedure TBoldModel.StartValidation; +begin + Inc(fValidateNesting); +end; + +procedure TBoldModel.EndValidation; +begin + Dec(fValidateNesting); +end; + procedure TBoldModel.UMLModelFromString(ModelAsString: string); begin if ModelAsString <> '' then @@ -235,9 +258,8 @@ procedure TBoldModel.UMLModelFromString(ModelAsString: string); fUMLModel.Delete; fUMLModel := nil; end; - // Model always freshly created at this point. TUMLModelStreamer.FillSystemFromString(fSystemHandle.System, ModelAsString, fSystemHandle.SystemTypeInfoHandle.BoldModel.MoldModel); - fUMLModel := fSystemHandle.System.EvaluateExpressionAsDirectElement('UMLModel.allInstances->first') as TUMLModel; // do not localize + fUMLModel := fSystemHandle.System.EvaluateExpressionAsDirectElement('UMLModel.allInstances->first') as TUMLModel; if not Assigned(fUMLModel) then raise EBold.Create('Bad string format for UMLModel'); end; @@ -308,7 +330,7 @@ procedure TBoldModel.EnsureMoldModelCurrent; Errors := TStringList.Create; - Validator := TBoldUMLModelValidator.Create(UMLModel); + Validator := TBoldUMLModelValidator.Create(self, SQLDataBaseConfigforModel(self)); Validator.Validate(TypeNameDictionary); @@ -319,9 +341,8 @@ procedure TBoldModel.EnsureMoldModelCurrent; MoldModel := TBoldModelConverter.UMLModelToMold(UMLModel); MoldModel.TVByName[BOLDINTERALTVPREFIX + TV_MODELERRORS] := Errors.CommaText; - SetFromModel(MoldModel); // hands over ownership of MoldModel + SetFromModel(MoldModel); - // Restore UML model state if not FlattenState then TBoldUMLSupport.UnFlatten(UMLModel); @@ -341,6 +362,8 @@ function TBoldModel.GetUMLModel: TUMLModel; procedure TBoldModel.UMLModelChangedRecieve(Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent); begin + if IsValidating then + exit; UnSubscribeToUMLModel; SendEvent(self, beModelChanged); UpdateDesigner; @@ -351,7 +374,7 @@ procedure TBoldModel.SubscribeToUMLModel; Assert(Assigned(fUMLModel)); Assert(not Assigned(fModelChangedSubscriber)); fModelChangedSubscriber := TBoldPassthroughSubscriber.Create(UMLModelChangedRecieve); - TBoldUMLSupport.SubscribeToEntireModel(fUMLModel, fModelChangedSubscriber); // note fUMLModel to stop loops + TBoldUMLSupport.SubscribeToEntireModel(fUMLModel, fModelChangedSubscriber); end; procedure TBoldModel.UnSubscribeToUMLModel; diff --git a/Source/UMLModel/Handles/BoldUMLModelStreamer.pas b/Source/UMLModel/Handles/BoldUMLModelStreamer.pas index 2bb4765..44fd0e4 100644 --- a/Source/UMLModel/Handles/BoldUMLModelStreamer.pas +++ b/Source/UMLModel/Handles/BoldUMLModelStreamer.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldUMLModelStreamer; interface @@ -13,22 +16,47 @@ TUMLModelStreamer = class class function SystemAsString(BoldSystem: TBoldSystem; MoldModel: TMoldModel): string; end; + implementation uses - MSXML_TLB, + {$IFDEF OXML}OXmlPDOM, OTextReadWrite{$ELSE}MSXML_TLB{$ENDIF}, BoldXMLStreaming, BoldDefaultXMLStreaming, BoldDomainElement, BoldGuard, BoldDefs, BoldValueSpaceInterfaces, - BoldID; + BoldID, + BoldRev; { TUMLModelStreamer } class procedure TUMLModelStreamer.FillSystemFromString(BoldSystem: TBoldSystem; const UMLModelAsString: string; MoldModel: TMoldModel); +{$IFDEF OXML} +var + anXMLDoc: TXMLDocument; + aMgr: TBoldDefaultXMLStreamManager; + aNode: TBoldXMLNode; + ParseError: IOTextParseError; + BoldGuard: IBoldGuard; +begin + BoldGuard := TBoldGuard.Create(aMgr, aNode); + anXMLDoc := TXMLDocument.Create; + aMgr := TBoldDefaultXMLStreamManager.Create(TBoldDefaultXMLStreamerRegistry.MainStreamerRegistry, MoldModel); + + aMgr.IgnorePersistenceState := True; + aMgr.PersistenceStatesToOverWrite := [bvpsInvalid, bvpsModified, bvpsTransient, bvpsCurrent]; + anXMLDoc.LoadFromXML(UMLModelAsString); + + ParseError := anXMLDoc.ParseError; + if Assigned(ParseError) and (ParseError.ErrorCode <> 0) then + raise EBold.Create('Error reading/parsing XML file'); + aNode := aMgr.GetRootNode(anXMLDoc, 'ValueSpace'); // do not localize + aMgr.ReadValueSpace(BoldSystem.AsIBoldvalueSpace[bdepPMIn], aNode); +end; +{$ELSE} var anXMLDoc: TDomDocument; aMgr: TBoldDefaultXMLStreamManager; @@ -48,11 +76,33 @@ class procedure TUMLModelStreamer.FillSystemFromString(BoldSystem: TBoldSystem; ParseError := anXMLDoc.parseError; if Assigned(ParseError) and (ParseError.errorCode <> 0) then raise EBold.Create('Error reading/parsing XML file'); - aNode := aMgr.GetRootNode(anXMLDoc, 'ValueSpace'); // do not localize + aNode := aMgr.GetRootNode(anXMLDoc, 'ValueSpace'); aMgr.ReadValueSpace(BoldSystem.AsIBoldvalueSpace[bdepPMIn], aNode); end; +{$ENDIF} class function TUMLModelStreamer.SystemAsString(BoldSystem: TBoldSystem; MoldModel: TMoldModel): string; +{$IFDEF OXML} +var + anXMLDoc: TXMLDocument; + aMgr: TBoldDefaultXMLStreamManager; + aNode: TBoldXMLNode; + anIdList: TBoldObjectIdList; + BoldGuard: IBoldGuard; +begin + BoldGuard := TBoldGuard.Create(aNode, aMgr, anIDList); + anXMLDoc := TXMLDocument.Create; + aMgr := TBoldDefaultXMLStreamManager.Create(TBoldDefaultXMLStreamerRegistry.MainStreamerRegistry, MoldModel); + aMgr.IgnorePersistenceState := True; + aMgr.PersistenceStatesToBeStreamed := [bvpsInvalid, bvpsModified, bvpsTransient, bvpsCurrent]; + aNode := aMgr.NewRootNode(anXMLDoc, 'ValueSpace'); // do not localize + anIdList := TBoldObjectIdList.Create; + + BoldSystem.AsIBoldValueSpace[bdepPMOut].AllObjectIds(anIdList, True); + aMgr.WriteValueSpace(BoldSystem.AsIBoldValueSpace[bdepPMOut], anIdList, nil, aNode); + Result := anXMLDoc.XML; +end; +{$ELSE} var anXMLDoc: TDomDocument; aMgr: TBoldDefaultXMLStreamManager; @@ -65,12 +115,15 @@ class function TUMLModelStreamer.SystemAsString(BoldSystem: TBoldSystem; MoldMod aMgr := TBoldDefaultXMLStreamManager.Create(TBoldDefaultXMLStreamerRegistry.MainStreamerRegistry, MoldModel); aMgr.IgnorePersistenceState := True; aMgr.PersistenceStatesToBeStreamed := [bvpsInvalid, bvpsModified, bvpsTransient, bvpsCurrent]; - aNode := aMgr.NewRootNode(anXMLDoc, 'ValueSpace'); // do not localize + aNode := aMgr.NewRootNode(anXMLDoc, 'ValueSpace'); anIdList := TBoldObjectIdList.Create; BoldSystem.AsIBoldValueSpace[bdepPMOut].AllObjectIds(anIdList, True); aMgr.WriteValueSpace(BoldSystem.AsIBoldValueSpace[bdepPMOut], anIdList, nil, aNode); Result := anXMLDoc.documentElement.xml; end; +{$ENDIF} + +initialization end. diff --git a/Source/UMLModel/Ide/BoldUMLModelEditReg.pas b/Source/UMLModel/Ide/BoldUMLModelEditReg.pas index 6281f99..725b48a 100644 --- a/Source/UMLModel/Ide/BoldUMLModelEditReg.pas +++ b/Source/UMLModel/Ide/BoldUMLModelEditReg.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldUMLModelEditReg; interface @@ -14,6 +17,7 @@ implementation Classes, BoldCursorGuard, BoldSmallLogFrame, + BoldLogHandlerForm, BoldUMLModel, BoldDefsDT, BoldUMLModelEdit, @@ -119,7 +123,7 @@ function TUMLModelComponentEditor.GetCurrentElement: TUMLModelElement; procedure Register; begin RegisterComponentEditor(TBoldModel, TUMLModelComponentEditor); - RegisterPropertyEditor(TypeInfo(Boolean), TBoldModel, 'EditableModel', TUMLModelPropertyEditor); //do not localize + RegisterPropertyEditor(TypeInfo(Boolean), TBoldModel, 'EditableModel', TUMLModelPropertyEditor); end; constructor TUMLModelComponentEditor.Create(AComponent: TComponent; ADesigner: IDesigner); @@ -156,7 +160,7 @@ procedure TUMLModelPropertyEditor.Edit; function TUMLModelPropertyEditor.GetAttributes: TPropertyAttributes; begin - Result := inherited GetAttributes + [paDialog, paReadOnly] - [paMultiSelect]; + Result := inherited GetAttributes + [paDialog, paReadOnly] - [paMultiSelect]; end; function TUMLModelPropertyEditor.GetValue: string; @@ -164,5 +168,6 @@ function TUMLModelPropertyEditor.GetValue: string; Result := '(Open model editor)'; end; -end. +initialization +end. diff --git a/Source/UMLModel/Ide/BoldUMLModelHandleReg.pas b/Source/UMLModel/Ide/BoldUMLModelHandleReg.pas index d5a1867..1489a93 100644 --- a/Source/UMLModel/Ide/BoldUMLModelHandleReg.pas +++ b/Source/UMLModel/Ide/BoldUMLModelHandleReg.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldUMLModelHandleReg; interface @@ -12,7 +15,6 @@ implementation BoldIDEConsts, BoldModel; -{$R BoldUMLModelHandleReg.res} procedure RegisterComponentsOnPalette; begin diff --git a/Source/UMLModel/ModelLinks/Bld/BoldUMLBldLink.pas b/Source/UMLModel/ModelLinks/Bld/BoldUMLBldLink.pas index 9320e20..2ffb2e5 100644 --- a/Source/UMLModel/ModelLinks/Bld/BoldUMLBldLink.pas +++ b/Source/UMLModel/ModelLinks/Bld/BoldUMLBldLink.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldUMLBldLink; interface @@ -19,9 +22,13 @@ TBoldUMLBldLink = class(TBoldUMLModelLink) function GetDisplayName: string; override; function GetFileName: string; override; procedure SetFileName(const Value: string); override; + function SortCompare(Index1, Index2: integer): integer; + procedure SortExchange(Index1, Index2: integer); public function ExportModel(UMLModel: TUMLModel): Boolean; override; function ImportModel(UMLModel: TUMLModel): Boolean; override; + class function getSortStatus: Boolean; + class procedure setSortStatus(sortStatus: Boolean); published property FileName; property BoldModel; @@ -42,24 +49,80 @@ implementation BoldLogHandler, BoldMeta, BoldBld, - BoldUMLModelConverter; + BoldUMLModelConverter, + BoldSorter; + +var + msort: Boolean; + MoldModel: TMoldModel; { TBoldUMLBldLink } function TBoldUMLBldLink.ExportModel(UMLModel: TUMLModel): Boolean; var ModelAsStrings: TStringList; - MoldModel: TMoldModel; + vToolId1, vToolID2:String; G: IBoldGuard; + i,j: integer; begin Result := True; G := TBoldGuard.Create(MoldModel, ModelAsStrings); MoldModel := TBoldModelConverter.UMLModelToMold(UMLModel); + if getSortStatus then + BoldSort(0, MoldModel.Classes.Count-1, SortCompare, SortExchange); ModelAsStrings := TStringList.Create; TMoldBLDrw.ModelToStrings(MoldModel, ModelAsStrings); ModelAsStrings.SaveToFile(FileName); end; +{ 25-10-05 Bero + Tried to implement BoldSort() + It works but it don't sort the same way as bubblesort above + Also experimenting with BoldElement.CompareTo() without success... + } +function TBoldUMLBldLink.SortCompare(Index1, Index2: integer): integer; +var + vToolId1, vToolId2: string; +begin + Result := 0; + vToolId1 := MoldModel.Classes[Index1].NonDefaultTaggedValuesCommaText; + vToolId1:=copy(vToolId1,1,Ansipos(',',vToolId1)-1); + if (Length(vToolId1)>0) and (Ansipos('persistent',vToolId1)=0) + and (Ansipos('transient',vToolId1)=0) then + begin + vToolId1:=copy(vToolId1,AnsiPos('=',vToolId1)+1,Length(vToolId1)); + vToolId2 := MoldModel.Classes[Index2].NonDefaultTaggedValuesCommaText; + vToolId2:=copy(vToolId2,1,Ansipos(',',vToolId2)-1); + + if (Length(vToolId2)>0) and (Ansipos('persistent',vToolId2)=0) + and (Ansipos('transient',vToolId2)=0) then + begin + vToolId2:=copy(vToolId2,AnsiPos('=',vToolId2)+1,Length(vToolId2)); + if (Length(vToolId1) >= Length(vToolId2)) and (('$' + vToolId1)<('$' + vToolId2)) then + Result := 1; + end; + end; +end; + +procedure TBoldUMLBldLink.SortExchange(Index1, Index2: integer); +begin + MoldModel.Classes.Exchange(Index1,Index2); +end; + +{:Static method, no need for a classinstance. Get the status of the sort flag +@return true-sorted false-unsorted} +class function TBoldUMLBldLink.getSortStatus: Boolean; +begin + Result := msort; +end; + +{:Static method, no need for a classinstance. Set the status of the sort flag +@param sortstatus true-sorted false-unsorted} +class procedure TBoldUMLBldLink.setSortStatus(sortStatus: Boolean); +begin + msort := sortStatus; +end; + function TBoldUMLBldLink.GetCanExport: Boolean; begin Result := True; diff --git a/Source/UMLModel/ModelLinks/Core/BoldUMLModelLink.pas b/Source/UMLModel/ModelLinks/Core/BoldUMLModelLink.pas index 8ec1eaa..b5fe315 100644 --- a/Source/UMLModel/ModelLinks/Core/BoldUMLModelLink.pas +++ b/Source/UMLModel/ModelLinks/Core/BoldUMLModelLink.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldUMLModelLink; interface @@ -33,8 +36,8 @@ TBoldUMLModelLink = class(TBoldHandle) procedure SetFileName(const Value: string); virtual; function GetHandledObject: TObject; override; public - constructor Create(owner: TComponent); override; - destructor Destroy; override; + constructor create(owner: TComponent); override; + destructor destroy; override; function ExportModel(UMLModel: TUMLModel): Boolean; virtual; abstract; function ImportModel(UMLModel: TUMLModel): Boolean; virtual; abstract; property CanExport: Boolean read GetCanExport; diff --git a/Source/UMLModel/ModelLinks/Core/BoldUMLModelLinkSupport.pas b/Source/UMLModel/ModelLinks/Core/BoldUMLModelLinkSupport.pas index 9d267ed..1d6498b 100644 --- a/Source/UMLModel/ModelLinks/Core/BoldUMLModelLinkSupport.pas +++ b/Source/UMLModel/ModelLinks/Core/BoldUMLModelLinkSupport.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldUMLModelLinkSupport; interface @@ -100,4 +103,6 @@ class procedure TBoldUMLModelLinkSupport.StringToConstraints(Element: TUMLModelE end; end; +initialization + end. diff --git a/Source/UMLModel/ModelLinks/ModelMaker/Link/BoldMMLinkReg.pas b/Source/UMLModel/ModelLinks/ModelMaker/Link/BoldMMLinkReg.pas index fcc5b16..85bc148 100644 --- a/Source/UMLModel/ModelLinks/ModelMaker/Link/BoldMMLinkReg.pas +++ b/Source/UMLModel/ModelLinks/ModelMaker/Link/BoldMMLinkReg.pas @@ -1,6 +1,9 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldMMLinkreg; -interface +interface procedure Register; @@ -12,16 +15,15 @@ implementation TypInfo, SysUtils, BoldIDESupport, - BoldIDEConsts, BoldUtils, BoldDefs, + BoldGuard, + BoldIDEConsts, BoldAbstractPropertyEditors, BoldPropertyEditors, BoldAbstractModel, BoldUMLMMLink; -{$R *.res} - type { forward declarations } TBoldUMLMMFileNameProperty = class; @@ -36,7 +38,7 @@ TBoldUMLMMFileNameProperty = class(TBoldFileNameProperty) { TBoldUMLMMFileNameProperty } function TBoldUMLMMFileNameProperty.FileFilter: string; begin - Result := Format('%s (*%s)|*%1:s', [MM_LINKDESC, MM_LINKEXTENSION]); //do not localize + Result := Format('%s (*%s)|*%1:s', [MM_LINKDESC, MM_LINKEXTENSION]); end; function TBoldUMLMMFileNameProperty.IsValid: boolean; @@ -61,13 +63,12 @@ procedure RegisterComponentsOnPalette; procedure RegisterEditors; begin - RegisterPropertyEditor(TypeInfo(String), TBoldUMLMMLink, 'Filename', TBoldUMLMMFileNameProperty); //do not localize - RegisterPropertyEditor(TypeInfo(TBoldAbstractModel), TBoldUMLMMLink, 'BoldModel', TBoldComponentPropertyIndicateMissing); //do not localize + RegisterPropertyEditor(TypeInfo(String), TBoldUMLMMLink, 'Filename', TBoldUMLMMFileNameProperty); + RegisterPropertyEditor(TypeInfo(TBoldAbstractModel), TBoldUMLMMLink, 'BoldModel', TBoldComponentPropertyIndicateMissing); end; procedure Register; begin - RemovePackageFromDisabledPackagesRegistry(format('BoldMMLink%s', [LIBSUFFIX])); // do not localize RegisterComponentsOnPalette; RegisterEditors; end; diff --git a/Source/UMLModel/ModelLinks/ModelMaker/Link/BoldModelMaker_TLB.pas b/Source/UMLModel/ModelLinks/ModelMaker/Link/BoldModelMaker_TLB.pas index 8ccee7e..bc63d90 100644 --- a/Source/UMLModel/ModelLinks/ModelMaker/Link/BoldModelMaker_TLB.pas +++ b/Source/UMLModel/ModelLinks/ModelMaker/Link/BoldModelMaker_TLB.pas @@ -1,50 +1,46 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldModelMaker_TLB; -// ************************************************************************ // -// WARNING -// ------- -// The types declared in this file were generated from data read from a -// Type Library. If this type library is explicitly or indirectly (via -// another type library referring to this type library) re-imported, or the -// 'Refresh' command of the Type Library Editor activated while editing the -// Type Library, the contents of this file will be regenerated and all -// manual modifications will be lost. -// ************************************************************************ // - -// PASTLWTR : 1.1 -// File generated on 12/5/2001 9:07:15 AM from Type Library described below. - -// *************************************************************************// -// NOTE: -// Items guarded by $IFDEF_LIVE_SERVER_AT_DESIGN_TIME are used by properties -// which return objects that may need to be explicitly created via a function -// call prior to any access via the property. These items have been disabled -// in order to prevent accidental use from within the object inspector. You -// may enable them by defining LIVE_SERVER_AT_DESIGN_TIME or by selectively -// removing them from the $IFDEF blocks. However, such items must still be -// programmatically created via a method of the appropriate CoClass before -// they can be used. -// ************************************************************************ // -// Type Lib: E:\MM32\AutoServer\ModelMaker.tlb (1) -// IID\LCID: {D077CEC0-83F0-11D5-A1D2-00C0DFE529B9}\0 -// Helpfile: -// DepndLst: -// (1) v2.0 stdole, (C:\WINNT\System32\stdole2.tlb) -// ************************************************************************ // -{$TYPEDADDRESS OFF} // Unit must be compiled without type-checked pointers. + + + + + + + + + + + + + + + + + + + + + + + + + + + +{$TYPEDADDRESS OFF} interface uses Windows, ActiveX, Classes, Graphics, OleServer, OleCtrls, StdVCL; -// *********************************************************************// -// GUIDS declared in the TypeLibrary. Following prefixes are used: -// Type Libraries : LIBID_xxxx -// CoClasses : CLASS_xxxx -// DISPInterfaces : DIID_xxxx -// Non-DISP interfaces: IID_xxxx -// *********************************************************************// + + + + + const - // TypeLibrary Major and minor versions ModelMakerMajorVersion = 1; ModelMakerMinorVersion = 0; @@ -54,61 +50,47 @@ interface CLASS_App: TGUID = '{D077CEC3-83F0-11D5-A1D2-00C0DFE529B9}'; type -// *********************************************************************// -// Forward declaration of types defined in TypeLibrary -// *********************************************************************// + IApp = interface; IAppDisp = dispinterface; -// *********************************************************************// -// Declaration of CoClasses defined in Type Library -// (NOTE: Here we map each CoClass to its Default Interface) -// *********************************************************************// + + App = IApp; -// *********************************************************************// -// Interface: IApp -// Flags: (4416) Dual OleAutomation Dispatchable -// GUID: {D077CEC1-83F0-11D5-A1D2-00C0DFE529B9} -// *********************************************************************// + + IApp = interface(IDispatch) ['{D077CEC1-83F0-11D5-A1D2-00C0DFE529B9}'] function GetExpert(const ExpertID: WideString): IDispatch; safecall; end; -// *********************************************************************// -// DispIntf: IAppDisp -// Flags: (4416) Dual OleAutomation Dispatchable -// GUID: {D077CEC1-83F0-11D5-A1D2-00C0DFE529B9} -// *********************************************************************// + + + IAppDisp = dispinterface ['{D077CEC1-83F0-11D5-A1D2-00C0DFE529B9}'] function GetExpert(const ExpertID: WideString): IDispatch; dispid 1; end; -// *********************************************************************// -// The Class CoApp provides a Create and CreateRemote method to -// create instances of the default interface IApp exposed by -// the CoClass App. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoApp = class class function Create: IApp; class function CreateRemote(const MachineName: string): IApp; end; -// *********************************************************************// -// OLE Server Proxy class declaration -// Server Object : TApp -// Help String : ModelMaker Object -// Default Interface: IApp -// Def. Intf. DISP? : No -// Event Interface: -// TypeFlags : (2) CanCreate -// *********************************************************************// + + + + + + {$IFDEF LIVE_SERVER_AT_DESIGN_TIME} TAppProperties= class; {$ENDIF} @@ -137,12 +119,11 @@ TApp = class(TOleServer) end; {$IFDEF LIVE_SERVER_AT_DESIGN_TIME} -// *********************************************************************// -// OLE Server Properties Proxy Class -// Server Object : TApp -// (This object is used by the IDE's Property Inspector to allow editing -// of the properties of this server) -// *********************************************************************// + + + + + TAppProperties = class(TPersistent) private FServer: TApp; diff --git a/Source/UMLModel/ModelLinks/ModelMaker/Link/BoldUMLMMLink.pas b/Source/UMLModel/ModelLinks/ModelMaker/Link/BoldUMLMMLink.pas index 3488425..5d0b448 100644 --- a/Source/UMLModel/ModelLinks/ModelMaker/Link/BoldUMLMMLink.pas +++ b/Source/UMLModel/ModelLinks/ModelMaker/Link/BoldUMLMMLink.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldUMLMMLink; {$WARN SYMBOL_PLATFORM OFF} @@ -41,7 +44,7 @@ implementation SysUtils, Classes, BoldModelmaker_TLB, - BoldMMPlugin_TLB, + BoldMMPlugin_TLB, BoldDefs, BoldUtils, BoldGuard, @@ -51,9 +54,6 @@ implementation BoldBld, BoldUMLModelConverter; -const - BoldExpertName = 'BoldSoft.BoldExpert'; - { TBoldUMLMMLink } function TBoldUMLMMLink.ExportModel(UMLModel: TUMLModel): Boolean; @@ -70,11 +70,11 @@ function TBoldUMLMMLink.ExportModel(UMLModel: TUMLModel): Boolean; App := CoApp.Create; if not Assigned(App) then raise EBold.Create('Failed to Launch ModelMaker'); - Expert := App.GetExpert(BoldExpertName) as IBoldExpertDisp; + Expert := App.GetExpert('BoldSoft.BoldExpert') as IBoldExpertDisp; if not Assigned(Expert) then begin Sleep(10); - Expert := App.GetExpert(BoldExpertName) as IBoldExpertDisp; + Expert := App.GetExpert('BoldSoft.BoldExpert') as IBoldExpertDisp; end; if not Assigned(Expert) then raise EBold.Create('Bold Expert not installed in ModelMaker. Make sure the file BoldMMPlugin.dll is in the ModelMaker\Experts directory, and register the DLL using RegSvr32.exe'); @@ -96,7 +96,7 @@ function TBoldUMLMMLink.ExportModel(UMLModel: TUMLModel): Boolean; if ResultString <> '' then raise EBold.Createfmt(' Error during export: %s', [ResultString]) else - Expert.SaveProject(False); + Expert.SaveProject(False); end; function TBoldUMLMMLink.GetCanExport: Boolean; @@ -126,11 +126,11 @@ function TBoldUMLMMLink.ImportModel(UMLModel: TUMLModel): Boolean; App := CoApp.Create; if not Assigned(App) then raise EBoldImport.Create('Failed to Launch ModelMaker'); - Expert := App.GetExpert(BoldExpertName) as IBoldExpertDisp; + Expert := App.GetExpert('BoldSoft.BoldExpert') as IBoldExpertDisp; if not Assigned(Expert) then begin - Sleep(10); - Expert := App.GetExpert(BoldExpertName) as IBoldExpertDisp; + Sleep(10); + Expert := App.GetExpert('BoldSoft.BoldExpert') as IBoldExpertDisp; end; if not Assigned(Expert) then raise EBoldImport.Create('Bold Expert not installed in ModelMaker. Make sure the file BoldMMPlugin.dll is in the ModelMaker\Experts directory, and register the DLL using RegSvr32.exe'); diff --git a/Source/UMLModel/ModelLinks/ModelMaker/MMPlugin/BoldMMExpert.pas b/Source/UMLModel/ModelLinks/ModelMaker/MMPlugin/BoldMMExpert.pas index 5b7185a..d5e599c 100644 --- a/Source/UMLModel/ModelLinks/ModelMaker/MMPlugin/BoldMMExpert.pas +++ b/Source/UMLModel/ModelLinks/ModelMaker/MMPlugin/BoldMMExpert.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldMMExpert; interface @@ -61,7 +64,6 @@ procedure TBoldMMExpert.Destroyed; procedure TBoldMMExpert.Execute(Index: Integer); begin - // the menu item was clicked: perform associated action here case Index of 0: SaveModelToFile; @@ -74,7 +76,6 @@ procedure TBoldMMExpert.Execute(Index: Integer); function TBoldMMExpert.GetMenuPositions(Index: Integer): TMMMenuPosition; begin - // Define to which ModelMaker sub-menu should each verb be added case Index of 0, 1: Result := mpToolsMenu; else @@ -95,7 +96,6 @@ function TBoldMMExpert.GetVerbCount: Integer; function TBoldMMExpert.GetVerbs(Index: Integer): WideString; begin - // Return menu items Captions here case Index of 0: Result := 'Save in Bold format'; 1: Result := 'Bold tagged value editor'; @@ -125,7 +125,6 @@ function TBoldMMExpert.GetModelAsDelphiString: string; MoldModel: TMoldModel; ModelAsStrings: TStrings; begin - // Stream in .bld format for the time being. G := TBoldGuard.Create(Importer, Boldify, MoldModel); EnsureModelEditDataModule; UMLModel := TUMLModel.Create(dmModelEdit.bshUMLModel.System); diff --git a/Source/UMLModel/ModelLinks/ModelMaker/MMPlugin/BoldMMPlugin_TLB.pas b/Source/UMLModel/ModelLinks/ModelMaker/MMPlugin/BoldMMPlugin_TLB.pas index 8a0bf44..b2e0669 100644 --- a/Source/UMLModel/ModelLinks/ModelMaker/MMPlugin/BoldMMPlugin_TLB.pas +++ b/Source/UMLModel/ModelLinks/ModelMaker/MMPlugin/BoldMMPlugin_TLB.pas @@ -1,46 +1,41 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldMMPlugin_TLB; -// ************************************************************************ // -// WARNING -// ------- -// The types declared in this file were generated from data read from a -// Type Library. If this type library is explicitly or indirectly (via -// another type library referring to this type library) re-imported, or the -// 'Refresh' command of the Type Library Editor activated while editing the -// Type Library, the contents of this file will be regenerated and all -// manual modifications will be lost. -// ************************************************************************ // - -// PASTLWTR : 1.2 -// File generated on 8/12/2002 10:25:54 AM from Type Library described below. - -// ************************************************************************ // -// Type Lib: C:\vss\Development\BfD\Source\UMLModel\ModelLinks\ModelMaker\MMPlugin\BoldMMPlugin.tlb (1) -// LIBID: {08A3186D-598D-4595-8B1C-76D9FFDF952A} -// LCID: 0 -// Helpfile: -// HelpString: TypeLib1 Library -// DepndLst: -// (1) v2.0 stdole, (C:\WINDOWS\System32\stdole2.tlb) -// ************************************************************************ // -{$TYPEDADDRESS OFF} // Unit must be compiled without type-checked pointers. + + + + + + + + + + + + + + + + + + + +{$TYPEDADDRESS OFF} {$WARN SYMBOL_PLATFORM OFF} {$WRITEABLECONST ON} {$VARPROPSETTER ON} interface uses Windows, ActiveX, Classes, Graphics, StdVCL, Variants; - - -// *********************************************************************// -// GUIDS declared in the TypeLibrary. Following prefixes are used: -// Type Libraries : LIBID_xxxx -// CoClasses : CLASS_xxxx -// DISPInterfaces : DIID_xxxx -// Non-DISP interfaces: IID_xxxx -// *********************************************************************// + + + + + + const - // TypeLibrary Major and minor versions BoldMMPluginMajorVersion = 1; BoldMMPluginMinorVersion = 0; @@ -50,24 +45,17 @@ interface CLASS_CBoldExpert: TGUID = '{72789CDE-7A9C-475D-B935-ABF9283D9400}'; type -// *********************************************************************// -// Forward declaration of types defined in TypeLibrary -// *********************************************************************// + IBoldExpert = interface; IBoldExpertDisp = dispinterface; -// *********************************************************************// -// Declaration of CoClasses defined in Type Library -// (NOTE: Here we map each CoClass to its Default Interface) -// *********************************************************************// + + CBoldExpert = IBoldExpert; -// *********************************************************************// -// Interface: IBoldExpert -// Flags: (4416) Dual OleAutomation Dispatchable -// GUID: {4BBAE613-E7D6-4924-B2C3-43BB849EEC79} -// *********************************************************************// + + IBoldExpert = interface(IDispatch) ['{4BBAE613-E7D6-4924-B2C3-43BB849EEC79}'] function GetModelAsString: WideString; safecall; @@ -79,11 +67,9 @@ interface property ProjectFileName: WideString read Get_ProjectFileName; end; -// *********************************************************************// -// DispIntf: IBoldExpertDisp -// Flags: (4416) Dual OleAutomation Dispatchable -// GUID: {4BBAE613-E7D6-4924-B2C3-43BB849EEC79} -// *********************************************************************// + + + IBoldExpertDisp = dispinterface ['{4BBAE613-E7D6-4924-B2C3-43BB849EEC79}'] function GetModelAsString: WideString; dispid 1; @@ -94,13 +80,11 @@ interface procedure SaveProject(SaveAs: WordBool); dispid 6; end; -// *********************************************************************// -// The Class CoCBoldExpert provides a Create and CreateRemote method to -// create instances of the default interface IBoldExpert exposed by -// the CoClass CBoldExpert. The functions are intended to be used by -// clients wishing to automate the CoClass objects exposed by the -// server of this typelibrary. -// *********************************************************************// + + + + + CoCBoldExpert = class class function Create: IBoldExpert; class function CreateRemote(const MachineName: string): IBoldExpert; diff --git a/Source/UMLModel/ModelLinks/ModelMaker/MMPlugin/BoldMMTVDefGen.pas b/Source/UMLModel/ModelLinks/ModelMaker/MMPlugin/BoldMMTVDefGen.pas index f9351c3..dbc9a64 100644 --- a/Source/UMLModel/ModelLinks/ModelMaker/MMPlugin/BoldMMTVDefGen.pas +++ b/Source/UMLModel/ModelLinks/ModelMaker/MMPlugin/BoldMMTVDefGen.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldMMTVDefGen; interface @@ -54,7 +57,7 @@ procedure TBoldMMTVDefGen.Generate(FileName: string); ModelDefElement: IXMLDOMElement; begin fDoc := TDOMDocument.Create(nil); - fDoc.documentElement := fDoc.createElement('TagDefinitions'); // do not localize + fDoc.documentElement := fDoc.createElement('TagDefinitions'); RootElement := fDoc.documentElement; fEnumDefElement := AddElement(NODENAME_ENUMS, RootElement); @@ -64,40 +67,39 @@ procedure TBoldMMTVDefGen.Generate(FileName: string); MethodDefElement := AddElement(NODENAME_METHODTAGS, RootElement); ModelDefElement := AddElement(NODENAME_MODELTAGS, RootElement); - AddEnumDef('Boolean', 'True, False'); // do not localize - AddEnumDef('AttributeKindSet', TV_ATTRIBUTEKIND_BOLD + ', ' + TV_ATTRIBUTEKIND_DELPHI); // do not localize - AddEnumDef('BoldOperationKindSet', TV_DELPHIOPERATIONKIND_NORMAL + ', ' + // do not localize + AddEnumDef('Boolean', 'True, False'); + AddEnumDef('AttributeKindSet', TV_ATTRIBUTEKIND_BOLD + ', ' + TV_ATTRIBUTEKIND_DELPHI); + AddEnumDef('BoldOperationKindSet', TV_DELPHIOPERATIONKIND_NORMAL + ', ' + TV_DELPHIOPERATIONKIND_VIRTUAL + ', ' + TV_DELPHIOPERATIONKIND_ABSTRACTVIRTUAL + ', ' + TV_DELPHIOPERATIONKIND_DYNAMIC + ', ' + TV_DELPHIOPERATIONKIND_OVERRIDE); -// AddEnumDef('ChangeabilityKind', TV_CHANGEABILITY_ADDONLY + ', ' + -// TV_CHANGEABILITY_CHANGEABLE + ', ' + -// TV_CHANGEABILITY_FROZEN); - AddEnumDef('DeleteActions', TV_DELETEACTION_DEFAULT + ', ' + // do not localize + + + AddEnumDef('DeleteActions', TV_DELETEACTION_DEFAULT + ', ' + TV_DELETEACTION_ALLOW + ', ' + TV_DELETEACTION_PROHIBIT + ', ' + TV_DELETEACTION_CASCADE); - AddEnumDef('DelphiPropertySet', TV_DPNONE + ', ' + // do not localize + AddEnumDef('DelphiPropertySet', TV_DPNONE + ', ' + TV_DPFIELD + ', ' + TV_DPPRIVATEMETHOD + ', ' + TV_DPPROTECTEDVIRTUALMETHOD); - AddEnumDef('EvolutionStateEnum', TV_EVOLUTIONSTATE_NORMAL + ', ' + // do not localize + AddEnumDef('EvolutionStateEnum', TV_EVOLUTIONSTATE_NORMAL + ', ' + TV_EVOLUTIONSTATE_TOBEREMOVED + ', ' + TV_EVOLUTIONSTATE_REMOVED); - AddEnumDef('NationalCharConversionEnum', TV_NATIONALCHARCONVERSION_DEFAULT + ', ' + // do not localize + AddEnumDef('NationalCharConversionEnum', TV_NATIONALCHARCONVERSION_DEFAULT + ', ' + TV_NATIONALCHARCONVERSION_TRUE + ', ' + TV_NATIONALCHARCONVERSION_FALSE); - AddEnumDef('OptimisticLockingSet', TV_OPTIMISTICLOCKING_DEFAULT + ', ' + // do not localize + AddEnumDef('OptimisticLockingSet', TV_OPTIMISTICLOCKING_DEFAULT + ', ' + TV_OPTIMISTICLOCKING_OFF + ', ' + TV_OPTIMISTICLOCKING_MODIFIEDMEMBERS + ', ' + TV_OPTIMISTICLOCKING_ALLMEMBERS + ', ' + TV_OPTIMISTICLOCKING_TIMESTAMP); - AddEnumDef('TableMappingSet', TV_TABLEMAPPING_OWN + ', ' + // do not localize + AddEnumDef('TableMappingSet', TV_TABLEMAPPING_OWN + ', ' + TV_TABLEMAPPING_PARENT + ', ' + TV_TABLEMAPPING_CHILDREN + ', ' + TV_TABLEMAPPING_IMPORTED); - AddEnumDef('DefaultRegionModeAssociationEnum', TV_DEFAULTREGIONMODE_ASSOCIATIONEND_DEFAULT + ', ' + // do not localize + AddEnumDef('DefaultRegionModeAssociationEnum', TV_DEFAULTREGIONMODE_ASSOCIATIONEND_DEFAULT + ', ' + TV_DEFAULTREGIONMODE_ASSOCIATIONEND_NONE + ', ' + TV_DEFAULTREGIONMODE_ASSOCIATIONEND_EXISTENCE + ', ' + TV_DEFAULTREGIONMODE_ASSOCIATIONEND_CASCADE + ', ' + @@ -113,23 +115,23 @@ procedure TBoldMMTVDefGen.Generate(FileName: string); AddEnumDef(ENUM_TAG_PERSISTENCE, TV_PERSISTENCE_PERSISTENT + ', ' + TV_PERSISTENCE_TRANSIENT); - GenTVList(ClassDefElement, BoldDefaultTaggedValueList.ListForClassName['Class'], BOLDTVPREFIX); // do not localize - GenTVList(AttrDefElement, BoldDefaultTaggedValueList.ListForClassName['Attribute'], BOLDTVPREFIX); // do not localize - GenTVList(AssocDefElement, BoldDefaultTaggedValueList.ListForClassName['Association'], BOLDTVPREFIX); // do not localize - GenTVList(AssocDefElement, BoldDefaultTaggedValueList.ListForClassName['AssociationEnd'], PREFIX_SOURCE_ASSOC_END + BOLDTVPREFIX); // do not localize - GenTVList(AssocDefElement, BoldDefaultTaggedValueList.ListForClassName['AssociationEnd'], PREFIX_TARGET_ASSOC_END + BOLDTVPREFIX); // do not localize - GenTVList(MethodDefElement, BoldDefaultTaggedValueList.ListForClassName['Operation'], BOLDTVPREFIX); // do not localize - GenTVList(ModelDefElement, BoldDefaultTaggedValueList.ListForClassName['Model'], PREFIX_MODEL + BOLDTVPREFIX); // do not localize - - GenTVList(ClassDefElement, UMLTaggedValueList.ListForClassName['Class'], ''); // do not localize - GenTVList(AttrDefElement, UMLTaggedValueList.ListForClassName['Attribute'], ''); // do not localize - GenTVList(AssocDefElement, UMLTaggedValueList.ListForClassName['Association'], ''); // do not localize - - GenTV(ClassDefElement, BOLDTVPREFIX + TAG_CONSTRAINTS, 'Text', ''); // do not localize - GenTV(AttrDefElement, BOLDTVPREFIX + TAG_CONSTRAINTS, 'Text', ''); // do not localize - GenTV(MethodDefElement, BOLDTVPREFIX + TAG_CONSTRAINTS, 'Text', ''); // do not localize - GenTV(AssocDefElement, PREFIX_SOURCE_ASSOC_END + BOLDTVPREFIX + TAG_CONSTRAINTS, 'Text', ''); // do not localize - GenTV(AssocDefElement, PREFIX_TARGET_ASSOC_END + BOLDTVPREFIX + TAG_CONSTRAINTS, 'Text', ''); // do not localize + GenTVList(ClassDefElement, BoldDefaultTaggedValueList.ListForClassName['Class'], BOLDTVPREFIX); + GenTVList(AttrDefElement, BoldDefaultTaggedValueList.ListForClassName['Attribute'], BOLDTVPREFIX); + GenTVList(AssocDefElement, BoldDefaultTaggedValueList.ListForClassName['Association'], BOLDTVPREFIX); + GenTVList(AssocDefElement, BoldDefaultTaggedValueList.ListForClassName['AssociationEnd'], PREFIX_SOURCE_ASSOC_END + BOLDTVPREFIX); + GenTVList(AssocDefElement, BoldDefaultTaggedValueList.ListForClassName['AssociationEnd'], PREFIX_TARGET_ASSOC_END + BOLDTVPREFIX); + GenTVList(MethodDefElement, BoldDefaultTaggedValueList.ListForClassName['Operation'], BOLDTVPREFIX); + GenTVList(ModelDefElement, BoldDefaultTaggedValueList.ListForClassName['Model'], PREFIX_MODEL + BOLDTVPREFIX); + + GenTVList(ClassDefElement, UMLTaggedValueList.ListForClassName['Class'], ''); + GenTVList(AttrDefElement, UMLTaggedValueList.ListForClassName['Attribute'], ''); + GenTVList(AssocDefElement, UMLTaggedValueList.ListForClassName['Association'], ''); + + GenTV(ClassDefElement, BOLDTVPREFIX + TAG_CONSTRAINTS, 'Text', ''); + GenTV(AttrDefElement, BOLDTVPREFIX + TAG_CONSTRAINTS, 'Text', ''); + GenTV(MethodDefElement, BOLDTVPREFIX + TAG_CONSTRAINTS, 'Text', ''); + GenTV(AssocDefElement, PREFIX_SOURCE_ASSOC_END + BOLDTVPREFIX + TAG_CONSTRAINTS, 'Text', ''); + GenTV(AssocDefElement, PREFIX_TARGET_ASSOC_END + BOLDTVPREFIX + TAG_CONSTRAINTS, 'Text', ''); fDoc.save(FileName); end; diff --git a/Source/UMLModel/ModelLinks/ModelMaker/MMPlugin/BoldMMTVDefGenGUI.pas b/Source/UMLModel/ModelLinks/ModelMaker/MMPlugin/BoldMMTVDefGenGUI.pas index 0506d79..0cb462f 100644 --- a/Source/UMLModel/ModelLinks/ModelMaker/MMPlugin/BoldMMTVDefGenGUI.pas +++ b/Source/UMLModel/ModelLinks/ModelMaker/MMPlugin/BoldMMTVDefGenGUI.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldMMTVDefGenGUI; interface diff --git a/Source/UMLModel/ModelLinks/ModelMaker/MMPlugin/BoldMMTVDefs.pas b/Source/UMLModel/ModelLinks/ModelMaker/MMPlugin/BoldMMTVDefs.pas index b11c9cf..a2407bc 100644 --- a/Source/UMLModel/ModelLinks/ModelMaker/MMPlugin/BoldMMTVDefs.pas +++ b/Source/UMLModel/ModelLinks/ModelMaker/MMPlugin/BoldMMTVDefs.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldMMTVDefs; interface diff --git a/Source/UMLModel/ModelLinks/ModelMaker/MMPlugin/BoldMMTVEditor.pas b/Source/UMLModel/ModelLinks/ModelMaker/MMPlugin/BoldMMTVEditor.pas index d8da4a9..e1a0b38 100644 --- a/Source/UMLModel/ModelLinks/ModelMaker/MMPlugin/BoldMMTVEditor.pas +++ b/Source/UMLModel/ModelLinks/ModelMaker/MMPlugin/BoldMMTVEditor.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldMMTVEditor; interface diff --git a/Source/UMLModel/ModelLinks/ModelMaker/MMPlugin/BoldMMTVMemo.pas b/Source/UMLModel/ModelLinks/ModelMaker/MMPlugin/BoldMMTVMemo.pas index 592439b..c1e853d 100644 --- a/Source/UMLModel/ModelLinks/ModelMaker/MMPlugin/BoldMMTVMemo.pas +++ b/Source/UMLModel/ModelLinks/ModelMaker/MMPlugin/BoldMMTVMemo.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldMMTVMemo; interface diff --git a/Source/UMLModel/ModelLinks/ModelMaker/Support/BoldMMImporter.pas b/Source/UMLModel/ModelLinks/ModelMaker/Support/BoldMMImporter.pas index 8aff760..bfdf3ab 100644 --- a/Source/UMLModel/ModelLinks/ModelMaker/Support/BoldMMImporter.pas +++ b/Source/UMLModel/ModelLinks/ModelMaker/Support/BoldMMImporter.pas @@ -1,7 +1,9 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldMMImporter; -interface - { TODO : Optimize datatype access in same way as roselink } +interface uses BoldUMLModel, @@ -14,7 +16,7 @@ interface aeTarget = 2; type - TPass = (PASS1, PASS2); // Pass1 = classes only, pass2 = attributes, inheritance and associations + TPass = (PASS1, PASS2); TMMModelImporter = class private @@ -45,12 +47,10 @@ implementation BoldDefaultTaggedValues, BoldTaggedValueSupport, BoldUMLTypes, - BoldUMLDelphiSupport, // Needs new version + BoldUMLDelphiSupport, BoldUMLModelLinkSupport ; -// Utility functions - function Prefix(name: string): string; begin result := Copy(name, 1, pos('.', name)); @@ -238,13 +238,10 @@ procedure TMMModelImporter.ImportAssociationProperty( TBoldUMLSupport.AddToolId(UMLAssociation, IntToStr(MMProperty.ID)); Name := MMProperty.Name; UMLAssociation.name := Name; - UMLAssociation.stereotypeName := MMProperty.Category; - {TODO : Persistance for Association. Add a tagged value, as in Rose} + UMLAssociation.stereotypeName := MMProperty.Category; UMLAssociation.visibility := UMLVisibility(MMProperty.Visibility); - // Create the two AssociationEnds, and pull information from the "visualisation" - // Treat ends separately + MMMemberVisualization := MMProperty as IMMMemberVisualization; - // Note! Order of source and target is important. Used when distributing TVs. SourceUMLAssociationEnd := UMLAssociation.connection.AddNew; TargetUMLAssociationEnd := UMLAssociation.connection.AddNew; GetTaggedValuesAndConstraints(MMProperty as IMMModelPart, UMLAssociation); @@ -325,8 +322,7 @@ procedure TMMModelImporter.ImportAttributeProperty(MMProperty: IMMProperty; Name := MMProperty.Name; UMLAttribute.name := Name; UMLAttribute.stereotypeName := MMProperty.Category; - GetTaggedValuesAndConstraints(MMProperty as IMMModelPart, UMLAttribute); - {TODO : Persistance for attributes. Add a tagged value, as in Rose} + GetTaggedValuesAndConstraints(MMProperty as IMMModelPart, UMLAttribute); UMLAttribute.typeName := MMProperty.DataName; if MMProperty.DefaultSpec = dsDefault then UMLAttribute.initialValue := MMProperty.DefaultSpecStr; @@ -341,7 +337,6 @@ procedure TMMModelImporter.ImportClass(MMClass: IMMClass; var i: integer; UMLClass: TUMLClass; -// MMV9ClassBase: IMMV9ClassBase; MMMember: IMMMember; name: string; begin @@ -359,11 +354,10 @@ procedure TMMModelImporter.ImportClass(MMClass: IMMClass; end; UMLClass.stereotypeName := MMClass.Category; UMLClass.isAbstract := MMClass.Options[classAbstract]; -// if MMClass.QueryInterface(IMMV9ClassBase, MMV9ClassBase) = S_OK then -// UMLClass.Persistent := MMV9ClassBase.IsPersistent; + GetTaggedValuesAndConstraints(MMClass as IMMModelPart, UMLClass); end - else // pass2 + else begin name := MMclass.Name; if name = 'TObject' then @@ -371,24 +365,24 @@ procedure TMMModelImporter.ImportClass(MMClass: IMMClass; name := 'BusinessClassesRoot'; end; - UMLClass := UMLPackage.EvaluateExpressionAsDirectElement(Format('classes->select(name=''%s'')->first', [Name])) as TUMLClass; { TODO : Locate by MM-id } + UMLClass := UMLPackage.EvaluateExpressionAsDirectElement(Format('classes->select(name=''%s'')->first', [Name])) as TUMLClass; Assert(Assigned(UMLClass)); if MMClass.Ancestor <> nil then - UMLClass.SetFirstParent(UMLPackage.EvaluateExpressionAsDirectElement(Format('classes->select(name=''%s'')->first', [MMClass.Ancestor.Name])) as TUMLClass); { TODO : Locate by MM-id } + UMLClass.SetFirstParent(UMLPackage.EvaluateExpressionAsDirectElement(Format('classes->select(name=''%s'')->first', [MMClass.Ancestor.Name])) as TUMLClass); for I := 0 to MMClass.MemberCount-1 do begin MMMember := MMClass.Members[i]; case MMMember.MemberType of cpResClause: - ; // Just ignore silently + ; cpField: - ; // Just ignore silently + ; cpMethod: ImportMethod(MMMember as IMMMethod, UMLClass); cpProperty: ImportProperty(MMMember as IMMProperty, UMLClass); cpEvent: - ; // Just ignore silently + ; else raise EBold.Create('Unknown Membertype'); end; @@ -404,7 +398,7 @@ procedure TMMModelImporter.ImportMethod(MMethod: IMMMethod; begin if (MMethod.MethodKind in [mkConstructor, mkDestructor]) or (MMethod.BindingKind = bkMessage) then - Exit; // Silently ignore constructors/destructors + Exit; UMLOperation := TUMLOperation.Create(UMLClass.BoldSystem); UMLOperation.owner := UMLClass; TBoldUMLSupport.EnsureBoldTaggedValues(UMLOperation); @@ -452,7 +446,7 @@ procedure TMMModelImporter.ImportProperty(MMProperty: IMMProperty; begin if Pass = PASS2 then begin - TypeAsUMLClass := UMLClass.namespace_.EvaluateExpressionAsDirectElement(Format('classes->select(name=''%s'')->first', [MMProperty.DataName])) as TUMLClass; { TODO : Locate by MM-id }; + TypeAsUMLClass := UMLClass.namespace_.EvaluateExpressionAsDirectElement(Format('classes->select(name=''%s'')->first', [MMProperty.DataName])) as TUMLClass; ; if Assigned(TypeAsUMLClass) then ImportAssociationProperty(MMProperty, UMLClass, TypeAsUMLClass) else @@ -469,7 +463,6 @@ procedure TMMModelImporter.ImportModel(MMModel: IMMCodeModel); begin ClassBase := MMModel.Classes[i]; if ClassBase.IsInterface then - // Nothing yet else ImportClass(ClassBase as IMMClass, fUMLModel) end; diff --git a/Source/UMLModel/ModelLinks/Rose98/BoldRose98TaggedValues.pas b/Source/UMLModel/ModelLinks/Rose98/BoldRose98TaggedValues.pas index 3ef1c6d..2acfbf2 100644 --- a/Source/UMLModel/ModelLinks/Rose98/BoldRose98TaggedValues.pas +++ b/Source/UMLModel/ModelLinks/Rose98/BoldRose98TaggedValues.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldRose98TaggedValues; interface @@ -30,59 +33,49 @@ TBoldRose98TaggedValueSupport = class function Rose98TaggedValueList: TBoldTaggedValuePerClassList; + implementation uses SysUtils, BoldDefaultTaggedValues, BoldDefs, - UMLConsts, - BoldUtils; + BoldUtils, + BoldRev; var G_Rose98TaggedValues: TBoldTaggedValuePerClassList = nil; procedure AddDefaultTaggedValues; begin -// Tagged values for Model - with G_Rose98TaggedValues.ListForClassName['Model'] do // do not localize + with G_Rose98TaggedValues.ListForClassName['Model'] do begin - Add('String', TAG_MODELNAME, 'BusinessClasses'); // do not localize - Add('Text', TAG_CONSTRAINTS, ''); // do not localize - Add('PTYVersionSet', // do not localize - 'PTYVersion', BOLDTVREV); // do not localize + Add('String', TAG_MODELNAME, 'BusinessClasses'); + Add('Text', TAG_CONSTRAINTS, ''); + Add('PTYVersionSet', + 'PTYVersion', BOLDTVREV); end; - -// Tagged values for Class - with G_Rose98TaggedValues.ListForClassName['Class'] do // do not localize + with G_Rose98TaggedValues.ListForClassName['Class'] do begin - Add('Text', TAG_CONSTRAINTS, ''); // do not localize + Add('Text', TAG_CONSTRAINTS, ''); end; - -// Tagged values for Association - with G_Rose98TaggedValues.ListForClassName['Association'] do // do not localize + with G_Rose98TaggedValues.ListForClassName['Association'] do begin end; - -// Tagged values for Attribute - with G_Rose98TaggedValues.ListForClassName['Attribute'] do // do not localize + with G_Rose98TaggedValues.ListForClassName['Attribute'] do begin - Add('Text', TAG_CONSTRAINTS, ''); // do not localize + Add('Text', TAG_CONSTRAINTS, ''); end; - -// Tagged values for AssociationEnd - with G_Rose98TaggedValues.ListForClassName['AssociationEnd'] do // do not localize + with G_Rose98TaggedValues.ListForClassName['AssociationEnd'] do begin - Add('ChangeabilityKind', // do not localize + Add('ChangeabilityKind', TAG_CHANGEABILITY, TV_CHANGEABILITY_CHANGEABLE); - Add('Text', TAG_CONSTRAINTS, ''); // do not localize + Add('Text', TAG_CONSTRAINTS, ''); end; - -// Tagged values for Operation - with G_Rose98TaggedValues.ListForClassName['Operation'] do // do not localize + with G_Rose98TaggedValues.ListForClassName['Operation'] do begin - Add('Text', TAG_CONSTRAINTS, ''); // do not localize - Add('Boolean', TAG_ISCLASSMETHOD, TV_FALSE); // do not localize + Add('Text', TAG_CONSTRAINTS, ''); + Add('Boolean', TAG_ISCLASSMETHOD, TV_FALSE); end; end; @@ -109,7 +102,7 @@ class function TBoldRose98TaggedValueSupport.ChangeableKindToString( ckAddOnly: Result := TV_CHANGEABILITY_ADDONLY; else - raise EBold.CreateFmt(sWrongValue, [ClassName, 'ChangeableKindToString']); // do not localize + raise EBold.CreateFmt('%s.ChangeableKindToString: Unknown TChangeableKind', [ClassName]); end; end; diff --git a/Source/UMLModel/ModelLinks/Rose98/BoldRose98ptyCreator.pas b/Source/UMLModel/ModelLinks/Rose98/BoldRose98ptyCreator.pas index ab687d8..dab59de 100644 --- a/Source/UMLModel/ModelLinks/Rose98/BoldRose98ptyCreator.pas +++ b/Source/UMLModel/ModelLinks/Rose98/BoldRose98ptyCreator.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldRose98ptyCreator; interface @@ -15,7 +18,7 @@ TBoldRose98ptyCreator = class private fLeadingSpaces: integer; fList: TStrings; - fRoseEnums: TBoldTaggedValuePerClassList; // Slightly unorthodox reuse, ClassName=EnumName + fRoseEnums: TBoldTaggedValuePerClassList; procedure InitializeRoseEnums; procedure PutLine(const s: string); overload; procedure PutLine; overload; @@ -42,7 +45,7 @@ implementation sysutils, BoldDefaultTaggedValues, BoldUMLTaggedValues, - BoldUMLRose98Support, + BoldUMLRose98Support, BoldRose98TaggedValues; const @@ -67,131 +70,131 @@ constructor TBoldRose98ptyCreator.Create; procedure TBoldRose98ptyCreator.CreateContents; begin - PutLine('(object Petal version 40)'); // do not localize + PutLine('(object Petal version 40)'); PutLine; - PutLine('(list Attribute_Set'); // do not localize + PutLine('(list Attribute_Set'); Indent; - PutLine('(object Attribute tool "Bold" name "roseId" value "753117540")'); // do not localize - PutLine('(object Attribute tool "Bold" name "propertyId" value "809135966")'); // do not localize + PutLine('(object Attribute tool "Bold" name "roseId" value "753117540")'); + PutLine('(object Attribute tool "Bold" name "propertyId" value "809135966")'); - StartSection('Project', 'Model'); // do not localize - PutLine('## Enum Declarations'); // do not localize + StartSection('Project', 'Model'); + PutLine('## Enum Declarations'); PutLine; - PutEnumDefinition('OptimisticLockingSet'); // do not localize - PutEnumDefinition('NationalCharConversionEnum'); // do not localize + PutEnumDefinition('OptimisticLockingSet'); + PutEnumDefinition('NationalCharConversionEnum'); - PutLine('## Enum Declarations'); // do not localize + PutLine('## Enum Declarations'); PutLine; - PutLine('## This enum has only one value and is used to ensure the correct PTY-version when importing to BfD'); // do not localize - PutEnumDefinition('PTYVersionSet'); // do not localize + PutLine('## This enum has only one value and is used to ensure the correct PTY-version when importing to BfD'); + PutEnumDefinition('PTYVersionSet'); - PutTaggedValuesForClass('Model'); // do not localize - PutLine('## removed tagged values'); // do not localize - PutLine('## (object Attribute tool "Bold" name "DefaultMemberInfoClass" value "")'); // do not localize + PutTaggedValuesForClass('Model'); + PutLine('## removed tagged values'); + PutLine('## (object Attribute tool "Bold" name "DefaultMemberInfoClass" value "")'); EndSection; - PutSeparator('Class definitions'); // do not localize - PutLine('(object Attribute tool "Bold" name "default__Class" value'); // do not localize + PutSeparator('Class definitions'); + PutLine('(object Attribute tool "Bold" name "default__Class" value'); Indent; - PutLine('(list Attribute_Set'); // do not localize + PutLine('(list Attribute_Set'); Indent; PutLine; - PutLine('## Enum Declarations'); // do not localize + PutLine('## Enum Declarations'); PutLine; - PutEnumDefinition('EvolutionStateEnum'); // do not localize - PutEnumDefinition('TableMappingSet'); // do not localize - PutEnumDefinition('OptimisticLockingSet'); // do not localize + PutEnumDefinition('EvolutionStateEnum'); + PutEnumDefinition('TableMappingSet'); + PutEnumDefinition('OptimisticLockingSet'); PutEnumDefinition(ENUM_TAG_CLASS_STORAGE); - PutTaggedValuesForClass('Class'); // do not localize + PutTaggedValuesForClass('Class'); EndSection; - StartSection('Attribute', 'Attribute'); // do not localize - PutLine('## Enum Declarations'); // do not localize + StartSection('Attribute', 'Attribute'); + PutLine('## Enum Declarations'); PutLine; - PutEnumDefinition('AttributeKindSet'); // do not localize - PutEnumDefinition('DelphiPropertySet'); // do not localize - PutEnumDefinition('EvolutionStateEnum'); // do not localize + PutEnumDefinition('AttributeKindSet'); + PutEnumDefinition('DelphiPropertySet'); + PutEnumDefinition('EvolutionStateEnum'); PutEnumDefinition(ENUM_TAG_ATTRIBUTE_STORAGE); - PutTaggedValuesForClass('Attribute'); // do not localize - PutLine('## removed tagged values'); // do not localize - PutLine('## (object Attribute tool "Bold" name "MemberInfoClass" value "")'); // do not localize + PutTaggedValuesForClass('Attribute'); + PutLine('## removed tagged values'); + PutLine('## (object Attribute tool "Bold" name "MemberInfoClass" value "")'); EndSection; - PutSeparator('Attribute definitions STDUML'); // do not localize - PutLine(Format('(object Attribute tool "%s" name "roseId" value "753117540")', [BOLDSTDUMLTOOLNAME])); // do not localize - PutLine(Format('(object Attribute tool "%s" name "propertyId" value "809135966")', [BOLDSTDUMLTOOLNAME])); // do not localize + PutSeparator('Attribute definitions STDUML'); + PutLine(Format('(object Attribute tool "%s" name "roseId" value "753117540")', [BOLDSTDUMLTOOLNAME])); + PutLine(Format('(object Attribute tool "%s" name "propertyId" value "809135966")', [BOLDSTDUMLTOOLNAME])); PutLine; PutLine; - PutLine(Format('(object Attribute tool "%s" name "default__Attribute" value', [BOLDSTDUMLTOOLNAME])); // do not localize + PutLine(Format('(object Attribute tool "%s" name "default__Attribute" value', [BOLDSTDUMLTOOLNAME])); Indent; - PutLine('(list Attribute_Set'); // do not localize + PutLine('(list Attribute_Set'); PutLine; Indent; Indent; - PutLine('## Enum Declarations'); // do not localize + PutLine('## Enum Declarations'); PutLine; - PutLine(Format('(object Attribute tool "%s" name "PersistenceSet" value', [BOLDSTDUMLTOOLNAME])); // do not localize + PutLine(Format('(object Attribute tool "%s" name "PersistenceSet" value', [BOLDSTDUMLTOOLNAME])); Indent; - PutLine('(list Attribute_Set'); // do not localize - PutLine(Format(' (object Attribute tool "%s" name "%s" value 0)', [BOLDSTDUMLTOOLNAME, TV_PERSISTENCE_PERSISTENT])); // do not localize - PutLine(Format(' (object Attribute tool "%s" name "%s" value 1)', [BOLDSTDUMLTOOLNAME, TV_PERSISTENCE_TRANSIENT])); // do not localize + PutLine('(list Attribute_Set'); + PutLine(Format(' (object Attribute tool "%s" name "%s" value 0)', [BOLDSTDUMLTOOLNAME, TV_PERSISTENCE_PERSISTENT])); + PutLine(Format(' (object Attribute tool "%s" name "%s" value 1)', [BOLDSTDUMLTOOLNAME, TV_PERSISTENCE_TRANSIENT])); EndSection; PutLine; - PutLine(Format('(object Attribute tool "%s" name "%s" value ("PersistenceSet" 0))', [BOLDSTDUMLTOOLNAME, TAG_PERSISTENCE])); // do not localize + PutLine(Format('(object Attribute tool "%s" name "%s" value ("PersistenceSet" 0))', [BOLDSTDUMLTOOLNAME, TAG_PERSISTENCE])); EndSection; - StartSection('Association', 'Association'); // do not localize - PutLine('## Enum Declarations'); // do not localize - PutEnumDefinition('EvolutionStateEnum'); // do not localize + StartSection('Association', 'Association'); + PutLine('## Enum Declarations'); + PutEnumDefinition('EvolutionStateEnum'); PutEnumDefinition(ENUM_TAG_ASSOCIATION_STORAGE); - PutTaggedValuesForClass('Association'); // do not localize - PutLine('## removed tagged values:'); // do not localize - PutLine('## (object Attribute tool "Bold" name "LinkClassId" value -1)'); // do not localize + PutTaggedValuesForClass('Association'); + PutLine('## removed tagged values:'); + PutLine('## (object Attribute tool "Bold" name "LinkClassId" value -1)'); EndSection; - PutSeparator(' Association definitions STDUML'); // do not localize + PutSeparator(' Association definitions STDUML'); Indent; - PutLine(Format('(object Attribute tool "%s" name "roseId" value "753117540")', [BOLDSTDUMLTOOLNAME])); // do not localize - PutLine(Format('(object Attribute tool "%s" name "propertyId" value "809135966")', [BOLDSTDUMLTOOLNAME])); // do not localize + PutLine(Format('(object Attribute tool "%s" name "roseId" value "753117540")', [BOLDSTDUMLTOOLNAME])); + PutLine(Format('(object Attribute tool "%s" name "propertyId" value "809135966")', [BOLDSTDUMLTOOLNAME])); PutLine; - PutLine(Format('(object Attribute tool "%s" name "default__Association" value', [BOLDSTDUMLTOOLNAME])); // do not localize + PutLine(Format('(object Attribute tool "%s" name "default__Association" value', [BOLDSTDUMLTOOLNAME])); Indent; - PutLine('(list Attribute_Set'); // do not localize + PutLine('(list Attribute_Set'); Indent; - PutLine(Format('(object Attribute tool "%s" name "PersistenceSet" value', [BOLDSTDUMLTOOLNAME])); // do not localize + PutLine(Format('(object Attribute tool "%s" name "PersistenceSet" value', [BOLDSTDUMLTOOLNAME])); Indent; - PutLine('(list Attribute_Set'); // do not localize - PutLine(Format(' (object Attribute tool "%s" name "%s" value 0)', [BOLDSTDUMLTOOLNAME, TV_PERSISTENCE_PERSISTENT])); // do not localize - PutLine(Format(' (object Attribute tool "%s" name "%s" value 1)', [BOLDSTDUMLTOOLNAME, TV_PERSISTENCE_TRANSIENT])); // do not localize + PutLine('(list Attribute_Set'); + PutLine(Format(' (object Attribute tool "%s" name "%s" value 0)', [BOLDSTDUMLTOOLNAME, TV_PERSISTENCE_PERSISTENT])); + PutLine(Format(' (object Attribute tool "%s" name "%s" value 1)', [BOLDSTDUMLTOOLNAME, TV_PERSISTENCE_TRANSIENT])); EndSection; PutLine; - PutLine(Format('(object Attribute tool "%s" name "%s" value ("PersistenceSet" 0))', [BOLDSTDUMLTOOLNAME, TAG_PERSISTENCE])); // do not localize + PutLine(Format('(object Attribute tool "%s" name "%s" value ("PersistenceSet" 0))', [BOLDSTDUMLTOOLNAME, TAG_PERSISTENCE])); EndSection; - StartSection('Role', 'AssociationEnd'); // do not localize - PutEnumDefinition('DeleteActions'); // do not localize - PutEnumDefinition('ChangeabilityKind'); // do not localize - PutEnumDefinition('DefaultRegionModeAssociationEnum'); // do not localize - PutTaggedValuesForClass('AssociationEnd'); // do not localize + StartSection('Role', 'AssociationEnd'); + PutEnumDefinition('DeleteActions'); + PutEnumDefinition('ChangeabilityKind'); + PutEnumDefinition('DefaultRegionModeAssociationEnum'); + PutTaggedValuesForClass('AssociationEnd'); - PutLine('## removed tagged values'); // do not localize - PutLine('## (object Attribute tool "Bold" name "MemberInfoClass" value "")'); // do not localize + PutLine('## removed tagged values'); + PutLine('## (object Attribute tool "Bold" name "MemberInfoClass" value "")'); EndSection; - StartSection('Operation', 'Operation'); // do not localize - PutLine('## Enum Declarations'); // do not localize + StartSection('Operation', 'Operation'); + PutLine('## Enum Declarations'); PutLine; - PutEnumDefinition('BoldOperationKindSet'); // do not localize - PutTaggedValuesForClass('Operation'); // do not localize + PutEnumDefinition('BoldOperationKindSet'); + PutTaggedValuesForClass('Operation'); EndSection; - PutSeparator('Module definitions'); // do not localize - PutLine('(object Attribute tool "Bold" name "default__Module-Spec" value'); // do not localize + PutSeparator('Module definitions'); + PutLine('(object Attribute tool "Bold" name "default__Module-Spec" value'); Indent; - PutLine('(list Attribute_Set'); // do not localize + PutLine('(list Attribute_Set'); Indent; - PutLine('(object Attribute tool "Bold" name "CopyrightNotice" value "")'); // do not localize - PutLine('(object Attribute tool "Bold" name "FileName" value ".inc")'); // do not localize + PutLine('(object Attribute tool "Bold" name "CopyrightNotice" value "")'); + PutLine('(object Attribute tool "Bold" name "FileName" value ".inc")'); EndSection; Dedent; PutLine(')'); @@ -214,7 +217,7 @@ procedure TBoldRose98ptyCreator.Indent; Inc(fLeadingSpaces, INDENTSIZE); end; -procedure TBoldRose98ptyCreator.PutSeparator(const s: string); +procedure TBoldRose98ptyCreator.PutSeparator(const s: string); begin PutLine; PutLine(StringOfChar('#', 60)); @@ -227,7 +230,7 @@ procedure TBoldRose98ptyCreator.PutTaggedValuesForClass(const UMLName: string); var i: integer; begin - PutLine(Format('## Tagged values for %s', [UMLName])); // do not localize + PutLine(Format('## Tagged values for %s', [UMLName])); PutLine; with BoldDefaultTaggedValueList.ListForClassName[UMLName] do for i := 0 to Count - 1 do @@ -241,96 +244,96 @@ procedure TBoldRose98ptyCreator.PutTaggedValuesForClass(const UMLName: string); procedure TBoldRose98ptyCreator.InitializeRoseEnums; begin fRoseEnums := TBoldTaggedValuePerClassList.Create; - with fRoseEnums.ListForClassName['AttributeKindSet'] do // do not localize + with fRoseEnums.ListForClassName['AttributeKindSet'] do begin - Add('Integer', TV_ATTRIBUTEKIND_BOLD, '0'); // do not localize - Add('Integer', TV_ATTRIBUTEKIND_DELPHI, '1'); // do not localize + Add('Integer', TV_ATTRIBUTEKIND_BOLD, '0'); + Add('Integer', TV_ATTRIBUTEKIND_DELPHI, '1'); end; - with fRoseEnums.ListForClassName['BoldOperationKindSet'] do // do not localize + with fRoseEnums.ListForClassName['BoldOperationKindSet'] do begin - Add('Integer', TV_DELPHIOPERATIONKIND_NORMAL, '200'); // do not localize - Add('Integer', TV_DELPHIOPERATIONKIND_VIRTUAL, '201'); // do not localize - Add('Integer', TV_DELPHIOPERATIONKIND_ABSTRACTVIRTUAL, '204'); // do not localize - Add('Integer', TV_DELPHIOPERATIONKIND_DYNAMIC, '203'); // do not localize - Add('Integer', TV_DELPHIOPERATIONKIND_OVERRIDE, '202'); // do not localize + Add('Integer', TV_DELPHIOPERATIONKIND_NORMAL, '200'); + Add('Integer', TV_DELPHIOPERATIONKIND_VIRTUAL, '201'); + Add('Integer', TV_DELPHIOPERATIONKIND_ABSTRACTVIRTUAL, '204'); + Add('Integer', TV_DELPHIOPERATIONKIND_DYNAMIC, '203'); + Add('Integer', TV_DELPHIOPERATIONKIND_OVERRIDE, '202'); end; - with fRoseEnums.ListForClassName['ChangeabilityKind'] do // do not localize + with fRoseEnums.ListForClassName['ChangeabilityKind'] do begin - Add('Integer', TV_CHANGEABILITY_ADDONLY, '0'); // do not localize - Add('Integer', TV_CHANGEABILITY_CHANGEABLE, '1'); // do not localize - Add('Integer', TV_CHANGEABILITY_FROZEN, '2'); // do not localize + Add('Integer', TV_CHANGEABILITY_ADDONLY, '0'); + Add('Integer', TV_CHANGEABILITY_CHANGEABLE, '1'); + Add('Integer', TV_CHANGEABILITY_FROZEN, '2'); end; - with fRoseEnums.ListForClassName['DeleteActions'] do // do not localize + with fRoseEnums.ListForClassName['DeleteActions'] do begin - Add('Integer', TV_DELETEACTION_DEFAULT, '0'); // do not localize - Add('Integer', TV_DELETEACTION_ALLOW, '1'); // do not localize - Add('Integer', TV_DELETEACTION_PROHIBIT, '2'); // do not localize - Add('Integer', TV_DELETEACTION_CASCADE, '3'); // do not localize + Add('Integer', TV_DELETEACTION_DEFAULT, '0'); + Add('Integer', TV_DELETEACTION_ALLOW, '1'); + Add('Integer', TV_DELETEACTION_PROHIBIT, '2'); + Add('Integer', TV_DELETEACTION_CASCADE, '3'); end; - with fRoseEnums.ListForClassName['DelphiPropertySet'] do // do not localize + with fRoseEnums.ListForClassName['DelphiPropertySet'] do begin - Add('Integer', TV_DPNONE, '0'); // do not localize - Add('Integer', TV_DPFIELD, '1'); // do not localize - Add('Integer', TV_DPPRIVATEMETHOD, '2'); // do not localize - Add('Integer', TV_DPPROTECTEDVIRTUALMETHOD, '3'); // do not localize + Add('Integer', TV_DPNONE, '0'); + Add('Integer', TV_DPFIELD, '1'); + Add('Integer', TV_DPPRIVATEMETHOD, '2'); + Add('Integer', TV_DPPROTECTEDVIRTUALMETHOD, '3'); end; - with fRoseEnums.ListForClassName['EvolutionStateEnum'] do // do not localize + with fRoseEnums.ListForClassName['EvolutionStateEnum'] do begin - Add('Integer', TV_EVOLUTIONSTATE_NORMAL, '0'); // do not localize - Add('Integer', TV_EVOLUTIONSTATE_TOBEREMOVED, '1'); // do not localize - Add('Integer', TV_EVOLUTIONSTATE_REMOVED, '2'); // do not localize + Add('Integer', TV_EVOLUTIONSTATE_NORMAL, '0'); + Add('Integer', TV_EVOLUTIONSTATE_TOBEREMOVED, '1'); + Add('Integer', TV_EVOLUTIONSTATE_REMOVED, '2'); end; - with fRoseEnums.ListForClassName['NationalCharConversionEnum'] do // do not localize + with fRoseEnums.ListForClassName['NationalCharConversionEnum'] do begin - Add('Integer', TV_NATIONALCHARCONVERSION_DEFAULT, '0'); // do not localize - Add('Integer', TV_NATIONALCHARCONVERSION_TRUE, '1'); // do not localize - Add('Integer', TV_NATIONALCHARCONVERSION_FALSE, '2'); // do not localize + Add('Integer', TV_NATIONALCHARCONVERSION_DEFAULT, '0'); + Add('Integer', TV_NATIONALCHARCONVERSION_TRUE, '1'); + Add('Integer', TV_NATIONALCHARCONVERSION_FALSE, '2'); end; - with fRoseEnums.ListForClassName['OptimisticLockingSet'] do // do not localize + with fRoseEnums.ListForClassName['OptimisticLockingSet'] do begin - Add('Integer', TV_OPTIMISTICLOCKING_DEFAULT, '0'); // do not localize - Add('Integer', TV_OPTIMISTICLOCKING_OFF, '1'); // do not localize - Add('Integer', TV_OPTIMISTICLOCKING_MODIFIEDMEMBERS, '2'); // do not localize - Add('Integer', TV_OPTIMISTICLOCKING_ALLMEMBERS, '3'); // do not localize - Add('Integer', TV_OPTIMISTICLOCKING_TIMESTAMP, '4'); // do not localize + Add('Integer', TV_OPTIMISTICLOCKING_DEFAULT, '0'); + Add('Integer', TV_OPTIMISTICLOCKING_OFF, '1'); + Add('Integer', TV_OPTIMISTICLOCKING_MODIFIEDMEMBERS, '2'); + Add('Integer', TV_OPTIMISTICLOCKING_ALLMEMBERS, '3'); + Add('Integer', TV_OPTIMISTICLOCKING_TIMESTAMP, '4'); end; - with fRoseEnums.ListForClassName['TableMappingSet'] do // do not localize + with fRoseEnums.ListForClassName['TableMappingSet'] do begin - Add('Integer', TV_TABLEMAPPING_OWN, '0'); // do not localize - Add('Integer', TV_TABLEMAPPING_PARENT, '1'); // do not localize - Add('Integer', TV_TABLEMAPPING_CHILDREN, '2'); // do not localize - Add('Integer', TV_TABLEMAPPING_IMPORTED, '3'); // do not localize + Add('Integer', TV_TABLEMAPPING_OWN, '0'); + Add('Integer', TV_TABLEMAPPING_PARENT, '1'); + Add('Integer', TV_TABLEMAPPING_CHILDREN, '2'); + Add('Integer', TV_TABLEMAPPING_IMPORTED, '3'); end; - with fRoseEnums.ListForClassName['DefaultRegionModeAssociationEnum'] do // do not localize + with fRoseEnums.ListForClassName['DefaultRegionModeAssociationEnum'] do begin - Add('Integer', TV_DEFAULTREGIONMODE_ASSOCIATIONEND_DEFAULT, '0'); // do not localize - Add('Integer', TV_DEFAULTREGIONMODE_ASSOCIATIONEND_NONE, '1'); // do not localize - Add('Integer', TV_DEFAULTREGIONMODE_ASSOCIATIONEND_EXISTENCE, '2'); // do not localize - Add('Integer', TV_DEFAULTREGIONMODE_ASSOCIATIONEND_CASCADE, '3'); // do not localize - Add('Integer', TV_DEFAULTREGIONMODE_ASSOCIATIONEND_INDEPENDENTCASCADE, '4'); // do not localize + Add('Integer', TV_DEFAULTREGIONMODE_ASSOCIATIONEND_DEFAULT, '0'); + Add('Integer', TV_DEFAULTREGIONMODE_ASSOCIATIONEND_NONE, '1'); + Add('Integer', TV_DEFAULTREGIONMODE_ASSOCIATIONEND_EXISTENCE, '2'); + Add('Integer', TV_DEFAULTREGIONMODE_ASSOCIATIONEND_CASCADE, '3'); + Add('Integer', TV_DEFAULTREGIONMODE_ASSOCIATIONEND_INDEPENDENTCASCADE, '4'); end; - fRoseEnums.ListForClassName['PTYVersionSet'].Add('Integer', BOLDTVREV, '0'); // do not localize + fRoseEnums.ListForClassName['PTYVersionSet'].Add('Integer', BOLDTVREV, '0'); with fRoseEnums.ListForClassName[ENUM_TAG_CLASS_STORAGE] do begin - Add('Integer', TV_STORAGE_INTERNAL, '0'); // do not localize - Add('Integer', TV_STORAGE_PARTIALLYEXTERNAL, '1'); // do not localize - Add('Integer', TV_STORAGE_EXTERNAL, '2'); // do not localize + Add('Integer', TV_STORAGE_INTERNAL, '0'); + Add('Integer', TV_STORAGE_PARTIALLYEXTERNAL, '1'); + Add('Integer', TV_STORAGE_EXTERNAL, '2'); end; with fRoseEnums.ListForClassName[ENUM_TAG_ASSOCIATION_STORAGE] do begin - Add('Integer', TV_STORAGE_INTERNAL, '0'); // do not localize - Add('Integer', TV_STORAGE_EXTERNAL, '1'); // do not localize + Add('Integer', TV_STORAGE_INTERNAL, '0'); + Add('Integer', TV_STORAGE_EXTERNAL, '1'); end; with fRoseEnums.ListForClassName[ENUM_TAG_ATTRIBUTE_STORAGE] do begin - Add('Integer', TV_STORAGE_INTERNAL, '0'); // do not localize - Add('Integer', TV_STORAGE_EXTERNAL, '1'); // do not localize - Add('Integer', TV_STORAGE_EXTERNALKEY, '2'); // do not localize + Add('Integer', TV_STORAGE_INTERNAL, '0'); + Add('Integer', TV_STORAGE_EXTERNAL, '1'); + Add('Integer', TV_STORAGE_EXTERNALKEY, '2'); end; end; @@ -340,18 +343,18 @@ procedure TBoldRose98ptyCreator.PutRoseAttribute(TaggedValue: TBoldTaggedValueDe begin With TaggedValue do begin - if TypeName = 'String' then // do not localize + if TypeName = 'String' then ValueString := Format('"%s"', [DefaultValue]) - else if TypeName = 'Boolean' then // do not localize + else if TypeName = 'Boolean' then ValueString := UpperCase(DefaultValue) - else if TypeName = 'Integer' then // do not localize + else if TypeName = 'Integer' then ValueString := DefaultValue - else if TypeName = 'Text' then // do not localize - ValueString := Format('(value Text "%s")', [DefaultValue]) // do not localize + else if TypeName = 'Text' then + ValueString := Format('(value Text "%s")', [DefaultValue]) else - ValueString := Format('("%s" %s)', [TypeName, LookupRoseEnumValue(TypeName, DefaultValue)]); // do not localize + ValueString := Format('("%s" %s)', [TypeName, LookupRoseEnumValue(TypeName, DefaultValue)]); - PutLine(Format('(object Attribute tool "Bold" name %-33s value %s)', ['"' + Tag + '"', ValueString])); // do not localize + PutLine(Format('(object Attribute tool "Bold" name %-33s value %s)', ['"' + Tag + '"', ValueString])); end; end; @@ -375,9 +378,9 @@ procedure TBoldRose98ptyCreator.PutEnumDefinition(const EnumName: string); var i: integer; begin - PutLine(Format('(object Attribute tool "Bold" name "%s" value', [EnumName])); // do not localize + PutLine(Format('(object Attribute tool "Bold" name "%s" value', [EnumName])); Indent; - PutLine('(list Attribute_Set'); // do not localize + PutLine('(list Attribute_Set'); Indent; with fRoseEnums.ListForClassName[EnumName] do for i := 0 to Count - 1 do @@ -396,10 +399,10 @@ procedure TBoldRose98ptyCreator.EndSection; procedure TBoldRose98ptyCreator.StartSection(const RoseName, UMLName: string); begin - putSeparator(Format('%s definitions', [UMLName])); // do not localize - PutLine(Format('(object Attribute tool "Bold" name "default__%s" value', [RoseName])); // do not localize + putSeparator(Format('%s definitions', [UMLName])); + PutLine(Format('(object Attribute tool "Bold" name "default__%s" value', [RoseName])); Indent; - PutLine('(list Attribute_Set'); // do not localize + PutLine('(list Attribute_Set'); Indent; PutLine; end; @@ -409,4 +412,6 @@ procedure TBoldRose98ptyCreator.PutLine; PutLine(''); end; +initialization + end. diff --git a/Source/UMLModel/ModelLinks/Rose98/BoldUMLRose98Link.pas b/Source/UMLModel/ModelLinks/Rose98/BoldUMLRose98Link.pas index 97b9c1c..af4ae86 100644 --- a/Source/UMLModel/ModelLinks/Rose98/BoldUMLRose98Link.pas +++ b/Source/UMLModel/ModelLinks/Rose98/BoldUMLRose98Link.pas @@ -1,8 +1,8 @@ -unit BoldUMLRose98Link; -{ TODO : Use new signature support methods on import to. } -{ TODO : Write specific importer for Rose2K } -{$WARN SYMBOL_PLATFORM OFF} // WINDOWS only +{ Global compiler directives } +{$include bold.inc} +unit BoldUMLRose98Link; +{$WARN SYMBOL_PLATFORM OFF} interface @@ -43,7 +43,7 @@ TBoldUMLRoseLink = class(TBoldUMLModelLink) fImplicitRolesUMLCompliant: Boolean; fMapping: TBoldUMLRose98MappingUtils; fGetToolIdOnExport: Boolean; - function DefaultLogicalPackage: IRoseCategory; + function DefaultLogicalPackage: IRoseCategory; {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure EnsureModel; procedure ExportAssociation(UMLAssociation: TUMLAssociation; RoseAssociation : IRoseAssociation); procedure EnsureandExportAssociations(TheModel: TUMLModel); @@ -65,20 +65,20 @@ TBoldUMLRoseLink = class(TBoldUMLModelLink) procedure ImportQualifier(RoseAttribute: IRoseAttribute; UMLAssociationEnd: TUMLAssociationEnd); procedure ImportSignature(RoseOperation: IRoseOperation; UMLOperation: TUMLOperation); procedure ImportConstraints(RoseItem: IRoseItem; UMLElement: TUMLModelElement); - procedure SetLogicalPackages(Value: TStrings); - procedure SetTools(Value: TStrings); + procedure SetLogicalPackages(Value: TStrings); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure SetTools(Value: TStrings); {$IFDEF BOLD_INLINE} inline; {$ENDIF} property RoseModel: IRoseModel read fRoseModel; - function GetBoldSystem: TBoldSystem; + function GetBoldSystem: TBoldSystem; {$IFDEF BOLD_INLINE} inline; {$ENDIF} function FindPackage(const UniqueId: String): TUMLPackage; procedure RefreshCache(var Cache: TStringList; FilterType: TClass); function FindInCache(Cache: TStringList; UniqueId: string): TUMLElement; - procedure ReadObsoleteProperty(Reader: TReader; const PropertyName, NewPropertyName: string); // Compatibility - procedure ReadObsoletePluralSuffix(Reader: TReader); // Compatibility - procedure ReadObsoletMultiplicityForRoles(Reader: TReader); // Compatibility - procedure ReadObsoleteMultiplicityForNonNavigableRoles(Reader: TReader); - function GetLogicalPackages: TStrings; - function GetIncludeSubPackages: Boolean; - procedure SetIncludeSubPackages(const Value: Boolean); + procedure ReadObsoleteProperty(Reader: TReader; const PropertyName, NewPropertyName: string); + procedure ReadObsoletePluralSuffix(Reader: TReader); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure ReadObsoletMultiplicityForRoles(Reader: TReader); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure ReadObsoleteMultiplicityForNonNavigableRoles(Reader: TReader); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetLogicalPackages: TStrings; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetIncludeSubPackages: Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure SetIncludeSubPackages(const Value: Boolean); {$IFDEF BOLD_INLINE} inline; {$ENDIF} protected function GetCanExport: Boolean; override; function GetDisplayName: string; override; @@ -270,20 +270,16 @@ procedure TBoldUMLRoseLink.ImportAssociation(RoseAssociation: IRoseAssociation; TBoldUMLSupport.AddToolId(UMLAssociation, RoseAssociation.getUniqueId); RoseProp.GetTaggedValues(RoseItem, (UMLAssociation as TUMLModelElement), Tools); - - // "unroseify" the standard tagged values TVPersistence := taggedValue[BOLDSTDUMLTOOLNAME + '.' + TAG_PERSISTENCE ]; if not assigned(TVPersistence) then - TVPersistence := taggedValue[ BOLDSTDUMLTOOLNAME + '.' + 'Persistence' ]; // do not localize + TVPersistence := taggedValue[ BOLDSTDUMLTOOLNAME + '.' + 'Persistence' ]; if assigned(TVPersistence) then TVPersistence.tag := TAG_PERSISTENCE; - - // if both tagged values existed in the model, then remove the obsolete. - TVPersistence := taggedValue[ BOLDSTDUMLTOOLNAME + '.' + 'Persistence' ]; // do not localize + TVPersistence := taggedValue[ BOLDSTDUMLTOOLNAME + '.' + 'Persistence' ]; if assigned(TVPersistence) then TVPersistence.Delete; - TVPersistence := taggedValue[BOLDSTDUMLTOOLNAME + '.' + 'PersistenceSet']; // do not localize + TVPersistence := taggedValue[BOLDSTDUMLTOOLNAME + '.' + 'PersistenceSet']; if assigned(TVPersistence) then TVPersistence.Delete; @@ -316,19 +312,16 @@ procedure TBoldUMLRoseLink.ImportAttribute(RoseAttribute: IRoseAttribute; UMLAtt Name := RoseAttribute.Name; TBoldUMLSupport.AddToolId(UMLAttribute, RoseAttribute.getUniqueId); RoseProp.GetTaggedValues(RoseItem, (UMLAttribute as TUMLModelElement), Tools); - // "unroseify" the standard tagged values TVPersistence := taggedValue[ BOLDSTDUMLTOOLNAME + '.' + TAG_PERSISTENCE ]; if not assigned(TVPersistence) then - TVPersistence := taggedValue[ BOLDSTDUMLTOOLNAME + '.' + 'Persistence' ]; // do not localize + TVPersistence := taggedValue[ BOLDSTDUMLTOOLNAME + '.' + 'Persistence' ]; if assigned(TVPersistence) then TVPersistence.tag := TAG_PERSISTENCE; - - // if both tagged values existed in the model, then remove the obsolete. - TVPersistence := taggedValue[ BOLDSTDUMLTOOLNAME + '.' + 'Persistence' ]; // do not localize + TVPersistence := taggedValue[ BOLDSTDUMLTOOLNAME + '.' + 'Persistence' ]; if assigned(TVPersistence) then TVPersistence.Delete; - TVPersistence := taggedValue[BOLDSTDUMLTOOLNAME + '.' + 'PersistenceSet']; // do not localize + TVPersistence := taggedValue[BOLDSTDUMLTOOLNAME + '.' + 'PersistenceSet']; if assigned(TVPersistence) then TVPersistence.Delete; @@ -400,10 +393,10 @@ procedure TBoldUMLRoseLink.ImportClass(RoseClass: IRoseClass; UMLClass: TUMLClas ImportOperation(RoseOperation, UMLOperation); end; end - else // pass2 + else case RoseClass.GetSuperClasses.Count of 0: - ; // no action + ; 1: SetFirstParent(fMapping.FindClass(RoseClass.GetSuperClasses.GetAt(1).GetUniqueID)); else @@ -441,7 +434,7 @@ procedure TBoldUMLRoseLink.ImportOperation(RoseOperation: IRoseOperation; UMLOpe TBoldUMLSupport.EnsureBoldTaggedValues(NewParameter); with NewParameter do begin - name := 'return'; // do not localize + name := 'return'; kind := pdReturn; SetBoldTV(TAG_EXPRESSIONNAME, RoseProp.GetString(RoseItem, TAG_EXPRESSIONNAME, TV_NAME)); type_ := GetEnsuredUMLDataType(RoseOperation.ReturnType); @@ -451,10 +444,6 @@ procedure TBoldUMLRoseLink.ImportOperation(RoseOperation: IRoseOperation; UMLOpe end; procedure TBoldUMLRoseLink.ImportSignature(RoseOperation: IRoseOperation; UMLOperation: TUMLOperation); -const - var_var = 'VAR '; - var_out = 'OUT '; - var_const = 'CONST '; var Index: Integer; RoseParams: IRoseParameterCollection; @@ -474,27 +463,25 @@ procedure TBoldUMLRoseLink.ImportSignature(RoseOperation: IRoseOperation; UMLOpe TBoldUMLSupport.AddToolId(UMLParameter, RoseParam.getUniqueId); UMLParameter.StereotypeName := RoseParam.Stereotype; UMLParameter.type_ := GetEnsuredUMLDataType(RoseParam.Type_); - - //Check for occurence of "var" and "const"... ParamName := UMLParameter.Name; - if Pos(var_var, UpperCase(ParamName)) > 0 then + if Pos(UpperCase('var '), UpperCase(ParamName)) > 0 then begin UMLParameter.SetBoldTV(TAG_ISCONST, TV_FALSE); UMLParameter.kind := pdInOut; - Delete(ParamName, Pos(var_var, UpperCase(ParamName)), Length(var_var)); + Delete(ParamName, Pos(UpperCase('var '), UpperCase(ParamName)), Length('var ')); UMLParameter.Name := ParamName; end - else if Pos(var_out, UpperCase(ParamName)) > 0 then + else if Pos(UpperCase('out '), UpperCase(ParamName)) > 0 then begin UMLParameter.SetBoldTV(TAG_ISCONST, TV_FALSE); UMLParameter.kind := pdOut; - Delete(ParamName, Pos(var_out, UpperCase(ParamName)), Length(var_out)); + Delete(ParamName, Pos(UpperCase('out '), UpperCase(ParamName)), Length('out ')); UMLParameter.Name := ParamName; end - else if Pos(var_const, UpperCase(ParamName)) > 0 then + else if Pos(UpperCase('const '), UpperCase(ParamName)) > 0 then begin UMLParameter.SetBoldTV(TAG_ISCONST, TV_TRUE); - Delete(ParamName, Pos(var_const, UpperCase(ParamName)), Length(var_const)); + Delete(ParamName, Pos(UpperCase('const '), UpperCase(ParamName)), Length('const ')); UMLParameter.Name := ParamName; end; end; @@ -563,11 +550,9 @@ procedure SplitVersion(Version: string; var Major, Minor: string); Assert(UMLModel.Associations.Count = 0); BoldLog.ProgressMax := 2 * RoseModel.GetAllClasses.Count + RoseModel.GetAllAssociations.Count + RoseModel.GetAllCategories.Count; BoldLog.Progress := 0; - // import tagged values for the model first, to initialize what is overriden RoseProp.GetTaggedValues(RoseItem, UMLModel, Tools); ImportPackage(RoseModel.RootCategory, UMLModel, pass1); - // reimport the tagged values for the model since it is overwritten by the top-package... - // this is a workaround... why is the top rose package imported to the UMLModel? + RoseProp.GetTaggedValues(RoseItem, UMLModel, Tools); if not BoldLog.ProcessInterruption then ImportPackage(RoseModel.RootCategory, UMLModel, pass2); @@ -621,7 +606,7 @@ procedure TBoldUMLRoseLink.ImportRole(RoseRole: IRoseRole; OtherRole: IRoseRole; if AdjustEmbedFlag and (UMLAssociationEnd.Multi or assigned(UMLAssociationEnd.Association.Class_)) then UMLAssociationEnd.SetBoldTV(TAG_EMBED, TV_FALSE); - with RoseRole.Keys do // Rose seems to publish the qualifiers at the wrong end, compared to the UML + with RoseRole.Keys do for i := 1 to Count do ImportQualifier(GetAt(I), UMLAssociationEnd); end; end; @@ -713,7 +698,7 @@ procedure TBoldUMLRoseLink.ExportAssociation(UMLAssociation: TUMLAssociation; Ro RoseLinkClassName := RoseProp.GetString(RoseItem, TAG_LINKCLASSNAME, TV_NAME); if CompareText(BoldExpandName(RoseLinkClassName, RoseAssociation.Name, xtDelphi, -1, TBoldTaggedValueSupport.StringToNationalCharConversion(UMLAssociation.model.GetBoldTV(TAG_NATIONALCHARCONVERSION))), UMLAssociation.Class_.Name) <> 0 then - RoseProp.SetString(RoseItem, 'LinkClassName', TV_NAME, UMLAssociation.Class_.Name, LogName); // do not localize + RoseProp.SetString(RoseItem, 'LinkClassName', TV_NAME, UMLAssociation.Class_.Name, LogName); end else RoseAssociation.LinkClass := LinkClass; @@ -800,7 +785,6 @@ procedure TBoldUMLRoseLink.ExportClass(UMLClass: TUMLClass); RoseItem := RoseClass as IRoseItem; with UMLClass do begin - // properties RoseProp.SetTaggedValues(RoseItem, UMLClass, Tools); ExportConstraints(RoseItem, UMLClass); if RoseClass.Stereotype <> StereotypeName then @@ -823,7 +807,6 @@ procedure TBoldUMLRoseLink.ExportClass(UMLClass: TUMLClass); BoldLog.LogFmt('Setting %s.Persistence to %s', [LogName, BooleanToString(Persistent)]); RoseClass.Persistence := Persistent; end; - // Trim attributes RoseAttributes := RoseClass.Attributes; I := 1; while I <= RoseAttributes.Count do @@ -839,7 +822,6 @@ procedure TBoldUMLRoseLink.ExportClass(UMLClass: TUMLClass); I := 1; end; end; - // Trim operations RoseOperations := RoseClass.Operations; I := 1; while I <= RoseOperations.Count do @@ -873,7 +855,7 @@ procedure TBoldUMLRoseLink.ExportOperation(UMLOperation: TUMLOperation; RoseClas UMLReturnType: TUMLClassifier; begin LogName := TBoldUMLRose98Properties.LogName(UMLOperation); - UMLReturnType := UMLOperation.EvaluateExpressionAsDirectElement('parameter->select(kind=#return)->first.type->first') as TUMLClassifier; // do not localize + UMLReturnType := UMLOperation.EvaluateExpressionAsDirectElement('parameter->select(kind=#return)->first.type->first') as TUMLClassifier; if ASsigned(UMLReturnType) then ReturnTypeName := UMLReturnType.name else @@ -897,7 +879,7 @@ procedure TBoldUMLRoseLink.ExportOperation(UMLOperation: TUMLOperation; RoseClas ExportConstraints(RoseItem, UMLOperation); TBoldUMLRose98Support.SetExportControl(UMLOperation.Visibility, RoseOperation.ExportControl, UMLOperation.qualifiedName); RoseProp.SetTaggedValues(RoseItem, UMLOperation, Tools); - RoseProp.SetBoolean(RoseItem, 'IsClassMethod', False, UMLOperation.ownerScope = skClassifier, LogName); // do not localize + RoseProp.SetBoolean(RoseItem, 'IsClassMethod', False, UMLOperation.ownerScope = skClassifier, LogName); if CompareText(RoseOperation.ReturnType, ReturnTypeName) <> 0 then begin BoldLog.LogFmt('Setting %s.Type to %s', [LogName, ReturnTypeName]); @@ -948,7 +930,6 @@ function TBoldUMLRoseLink.ExportModel(UMLModel: TUMLModel): Boolean; RoseModel.Stereotype := UMLModel.StereotypeName; end; ExportConstraints(RoseItem, UMLModel); - // Remove all classes in Rose that are not in Bold RoseClasses := RoseModel.GetAllClasses; I := 1; BoldLog.ProgressMax := RoseClasses.Count - 1; @@ -968,7 +949,6 @@ function TBoldUMLRoseLink.ExportModel(UMLModel: TUMLModel): Boolean; else begin BoldLog.LogFmt('Deleting class %s', [RoseClass.Name]); - // we must remove all associations also or the model will be corrupt RoseAssociations := RoseClass.GetAssociations; while roseAssociations.count > 0 do begin @@ -984,8 +964,6 @@ function TBoldUMLRoseLink.ExportModel(UMLModel: TUMLModel): Boolean; else inc(i); end; - - // Remove all associations in Rose that are not in Bold RoseAssociations := RoseModel.GetAllAssociations; I := 1; BoldLog.ProgressMax := RoseAssociations.Count - 1; @@ -1049,7 +1027,7 @@ function TBoldUMLRoseLink.ExportModel(UMLModel: TUMLModel): Boolean; end; finally fRoseModel := nil; - end; + end; end; procedure TBoldUMLRoseLink.ExportSignature(UMLOperation: TUMLOperation; RoseOperation: IRoseOperation); @@ -1148,7 +1126,7 @@ procedure TBoldUMLRoseLink.ExportRole(UMLAssociationEnd: TUMLAssociationEnd; Ros TBoldUMLRose98Support.SetContainment(UMLAssociationEnd.Aggregation, RoseRole, OtherRoseRole, UMLAssociationEnd.qualifiedName); TBoldUMLRose98Support.SetExportControl(UMLAssociationEnd.visibility, RoseRole.ExportControl, UMLAssociationEnd.qualifiedName); - RoseProp.SetString(RoseItem, 'Changeability', 'Changeable', TBoldRose98TaggedValueSupport.ChangeableKindToString(UMLAssociationEnd.Changeability), LogName); // do not localize + RoseProp.SetString(RoseItem, 'Changeability', 'Changeable', TBoldRose98TaggedValueSupport.ChangeableKindToString(UMLAssociationEnd.Changeability), LogName); RoseProp.SetTaggedValues(RoseItem, UMLAssociationEnd, Tools); RoseProp.SetBoolean(RoseItem, TAG_ORDERED, False, UMLAssociationEnd.isOrdered, LogName); @@ -1157,8 +1135,6 @@ procedure TBoldUMLRoseLink.ExportRole(UMLAssociationEnd: TUMLAssociationEnd; Ros BoldLog.LogFmt('Setting %s.Navigable to %s', [LogName, BooleanToString(UMLAssociationEnd.isNavigable)]); RoseRole.Navigable := UMLAssociationEnd.isNavigable; end; - - // Trim qualifiers RoseAttributes := RoseRole.Keys; I := 1; while I <= RoseAttributes.Count do @@ -1299,8 +1275,7 @@ procedure TBoldUMLRoseLink.ExportConstraints(RoseItem: IRoseItem; UMLElement: TU begin ConstrString := TBoldUMLModelLinkSupport.ConstraintsAsString(UMLElement); RoseConstr := RoseProp.GetString(RoseItem, TAG_CONSTRAINTS, ''); - // if the Rose constraint does not end with CRLF then add that, this is because a CRLF - // should not affect the export. And empty strings should not affect anything + if (RoseConstr <> '') and (Copy(RoseConstr, Length(RoseConstr) - 2, MaxInt) <> BOLDCRLF) then RoseConstr := RoseConstr + BOLDCRLF; if ConstrString <> RoseConstr then @@ -1485,24 +1460,24 @@ function TBoldUMLRoseLink.FindInCache(Cache: TStringList; UniqueId: string): TUM procedure TBoldUMLRoseLink.DefineProperties(Filer: TFiler); begin inherited; - Filer.DefineProperty('PluralSuffix', ReadObsoletePluralSuffix, nil, False); // do not localize - Filer.DefineProperty('DefaultMultiplicityForRoles', ReadObsoletMultiplicityForRoles, nil, False); // do not localize - Filer.DefineProperty('DefaultMultiplicityForNonNavigableRoles', ReadObsoleteMultiplicityForNonNavigableRoles, nil, False); // do not localize + Filer.DefineProperty('PluralSuffix', ReadObsoletePluralSuffix, nil, False); + Filer.DefineProperty('DefaultMultiplicityForRoles', ReadObsoletMultiplicityForRoles, nil, False); + Filer.DefineProperty('DefaultMultiplicityForNonNavigableRoles', ReadObsoleteMultiplicityForNonNavigableRoles, nil, False); end; procedure TBoldUMLRoseLink.ReadObsoletePluralSuffix(Reader: TReader); begin - ReadObsoleteProperty(Reader, 'PluralSuffix', 'PluralSuffix'); // do not localize + ReadObsoleteProperty(Reader, 'PluralSuffix', 'PluralSuffix'); end; procedure TBoldUMLRoseLink.ReadObsoleteMultiplicityForNonNavigableRoles(Reader: TReader); begin - ReadObsoleteProperty(Reader, 'DefaultMultiplicityForNonNavigableRoles', 'DefaultNonNavigableMultiplicity'); // do not localize + ReadObsoleteProperty(Reader, 'DefaultMultiplicityForNonNavigableRoles', 'DefaultNonNavigableMultiplicity'); end; procedure TBoldUMLRoseLink.ReadObsoletMultiplicityForRoles(Reader: TReader); begin - ReadObsoleteProperty(Reader, 'DefaultMultiplicityForRoles', 'DefaultNavigableMultiplicity'); // do not localize + ReadObsoleteProperty(Reader, 'DefaultMultiplicityForRoles', 'DefaultNavigableMultiplicity'); end; procedure TBoldUMLRoseLink.ReadObsoleteProperty(Reader: TReader; const PropertyName, NewPropertyName: string); @@ -1534,6 +1509,7 @@ procedure TBoldUMLRoseLink.SetIncludeSubPackages(const Value: Boolean); fMapping.IncludeSubPackages := Value; end; + initialization BoldUMLModelLinkList.AddLink(ROSE_LINKEXTENSION, ROSE_LINKDESC, TBoldUMLRoseLink); RoseProp := TBoldUMLRose98Properties.Create(BOLDTOOLNAME); diff --git a/Source/UMLModel/ModelLinks/Rose98/BoldUMLRose98Linkreg.pas b/Source/UMLModel/ModelLinks/Rose98/BoldUMLRose98Linkreg.pas index 469c32f..b647d44 100644 --- a/Source/UMLModel/ModelLinks/Rose98/BoldUMLRose98Linkreg.pas +++ b/Source/UMLModel/ModelLinks/Rose98/BoldUMLRose98Linkreg.pas @@ -1,6 +1,9 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldUMLRose98Linkreg; -interface +interface procedure Register; @@ -13,14 +16,13 @@ implementation DesignIntf, TypInfo, BoldDefs, + BoldGuard, BoldIDEConsts, BoldAbstractPropertyEditors, BoldPropertyEditors, BoldAbstractModel, BoldUMLRose98Link; -{$R *.res} - type { TBoldRoseFileNameProperty } @@ -33,7 +35,7 @@ TBoldUMLRoseFileNameProperty = class(TBoldFileNameProperty) { TBoldRose98FileNameProperty } function TBoldUMLRoseFileNameProperty.FileFilter: string; begin - Result := Format('%s (*%s)|*%1:s', [ROSE_LINKDESC, ROSE_LINKEXTENSION]); //do not localize + Result := Format('%s (*%s)|*%1:s', [ROSE_LINKDESC, ROSE_LINKEXTENSION]); end; function TBoldUMLRoseFileNameProperty.IsValid: boolean; @@ -59,8 +61,8 @@ procedure RegisterComponentsOnPalette; procedure RegisterEditors; begin - RegisterPropertyEditor(TypeInfo(String), TBoldUMLRoseLink, 'Filename', TBoldUMLRoseFileNameProperty); //do not localize - RegisterPropertyEditor(TypeInfo(TBoldAbstractModel), TBoldUMLRoseLink, 'BoldModel', TBoldComponentPropertyIndicateMissing); //do not localize + RegisterPropertyEditor(TypeInfo(String), TBoldUMLRoseLink, 'Filename', TBoldUMLRoseFileNameProperty); + RegisterPropertyEditor(TypeInfo(TBoldAbstractModel), TBoldUMLRoseLink, 'BoldModel', TBoldComponentPropertyIndicateMissing); end; procedure Register; diff --git a/Source/UMLModel/ModelLinks/Rose98/BoldUMLRose98MappingUtils.pas b/Source/UMLModel/ModelLinks/Rose98/BoldUMLRose98MappingUtils.pas index 669f5bd..9830f2b 100644 --- a/Source/UMLModel/ModelLinks/Rose98/BoldUMLRose98MappingUtils.pas +++ b/Source/UMLModel/ModelLinks/Rose98/BoldUMLRose98MappingUtils.pas @@ -1,8 +1,9 @@ -{$WARN SYMBOL_PLATFORM OFF} // This is WINDOWS only +{ Global compiler directives } +{$include bold.inc} unit BoldUMLRose98MappingUtils; -interface +interface uses Classes, @@ -31,8 +32,8 @@ TBoldUMLRose98MappingUtils = class fCachedAssociations: TStringList; fCachedElements: TSTringList; fUMLModelreadOnly: Boolean; - procedure SetLogicalPackages(Value: TStrings); - procedure SetUMLModel(const Value: TUMLModel); + procedure SetLogicalPackages(Value: TStrings); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure SetUMLModel(const Value: TUMLModel); {$IFDEF BOLD_INLINE} inline; {$ENDIF} public constructor Create; destructor Destroy; override; @@ -85,7 +86,6 @@ function TBoldUMLRose98MappingUtils.RoseClassForUMLClassifier(RoseModel: IRoseMo I: Integer; begin Result := nil; - // If UMLClassifier has toolid then only accept that, else search for name match if TBoldUMLSupport.GetToolId(UMLClassifier) <> '' then Result := RoseModel.FindClassWithID(TBoldUMLSupport.GetToolId(UMLClassifier)) else @@ -110,14 +110,13 @@ function TBoldUMLRose98MappingUtils.UMLClassifierForRoseClass(UMLModel: TUMLMode result := nil; if assigned(RoseClass) then begin - // Class is in UMLModel if toolid mathces, or if name matches class that lacks toolid Result := FindClass(RoseClass.GetUniqueID); if not Assigned(Result) then begin Result := UMLModel.EvaluateExpressionAsDirectElement ( - Format('UMLClassifier.allInstances->select(model=self)->select(name=''%s'')->first', //do not localize + Format('UMLClassifier.allInstances->select(model=self)->select(name=''%s'')->first', [RoseClass.Name]) ) as TUMLClassifier; if Assigned(Result) and (TBoldUMLSupport.GetToolId(Result) <> '') then @@ -131,18 +130,15 @@ function TBoldUMLRose98MappingUtils.UMLAssociationForRoseAssociation(UMLModel: T UMLClassifier1: TUMLClassifier; i: integer; begin - // Association is in UMLModel if toolid matches, or if role names and classes match Result := FindAssocation(RoseAssociation.GetUniqueID); if not Assigned(Result) then begin - // first try name Result := UMLModel.EvaluateExpressionAsDirectElement ( - Format('UMLAssociation.allInstances->select(model=self)->select(name=''%s'')->first', //do not localize + Format('UMLAssociation.allInstances->select(model=self)->select(name=''%s'')->first', [RoseAssociation.Name]) ) as TUMLAssociation; - // else match on classes and role names if not Assigned(Result) then begin UMLClassifier1 := UMLClassifierForRoseClass(UMLModel, RoseAssociation.Role1.Class_); @@ -176,7 +172,6 @@ function TBoldUMLRose98MappingUtils.RoseAssociationForUMLAssociation( I: Integer; begin Result := nil; - // If UMLAssociation has toolid then only accept that, else search for match if TBoldUMLSupport.GetToolId(UMLAssociation) <> '' then Result := RoseModel.GetAllAssociations.GetWithUniqueID(TBoldUMLSupport.GetToolId(UMLAssociation)) else @@ -202,14 +197,13 @@ function TBoldUMLRose98MappingUtils.RoseAssociationForUMLAssociation( function TBoldUMLRose98MappingUtils.UMLAttributeForRoseAttribute( UMLClass: TUMLClass; RoseAttribute: IRoseAttribute): TUMLAttribute; begin - // Try Toolid first, then name match Result := FindElement(RoseAttribute.GetUniqueID) as TUMLAttribute; if not Assigned(Result) or (Result.Owner <> UMLClass) then begin Result := UMLClass.EvaluateExpressionAsDirectElement ( - Format('feature->select((name=''%s'') and oclIsKindOf(UMLAttribute))->first', //do not localize + Format('feature->select((name=''%s'') and oclIsKindOf(UMLAttribute))->first', [RoseAttribute.Name]) ) as TUMLAttribute; if Assigned(Result) and (TBoldUMLSupport.GetToolId(Result) <> '') then @@ -221,7 +215,6 @@ function TBoldUMLRose98MappingUtils.RoseAttributeForUMLAttribute( RoseClass: IRoseClass; UMLAttribute: TUMLAttribute): IRoseAttribute; begin Result := nil; - // If UMLClassifier has toolid then only accept that, else search for name match if TBoldUMLSupport.GetToolId(UMLAttribute) <> '' then Result := RoseClass.Attributes.GetWithUniqueID(TBoldUMLSupport.GetToolId(UMLAttribute)) else @@ -232,7 +225,6 @@ function TBoldUMLRose98MappingUtils.RoseOperationForUMLOperation( RoseClass: IRoseClass; UMLOperation: TUMLOperation): IRoseOperation; begin Result := nil; - // If UMLClassifier has toolid then only accept that, else search for name match if TBoldUMLSupport.GetToolId(UMLOperation) <> '' then Result := RoseClass.Operations.GetWithUniqueID(TBoldUMLSupport.GetToolId(UMLOperation)) else @@ -242,14 +234,13 @@ function TBoldUMLRose98MappingUtils.RoseOperationForUMLOperation( function TBoldUMLRose98MappingUtils.UMLOperationForRoseOperation( UMLClass: TUMLClass; RoseOperation: IRoseOperation): TUMLOperation; begin - // Try Toolid first, then name match Result := FindElement(RoseOperation.GetUniqueID) as TUMLOperation; if not Assigned(Result) or (Result.Owner <> UMLClass) then begin Result := UMLClass.EvaluateExpressionAsDirectElement ( - Format('feature->select((name=''%s'') and oclIsKindOf(UMLOperation))->first', //do not localize + Format('feature->select((name=''%s'') and oclIsKindOf(UMLOperation))->first', [RoseOperation.Name]) ) as TUMLOperation; if Assigned(Result) and (TBoldUMLSupport.GetToolId(Result) <> '') then @@ -267,7 +258,7 @@ constructor TBoldUMLRose98MappingUtils.Create; destructor TBoldUMLRose98MappingUtils.Destroy; begin FreeAndNil(fLogicalPackages); - ClearCaches; // this will free the cache-lists. + ClearCaches; inherited; end; @@ -322,14 +313,13 @@ function TBoldUMLRose98MappingUtils.ClassInLogicalPackages( cat := RoseClass.ParentCategory; while assigned(cat) and not Cat.TopLevel do Cat := cat.ParentCategory; - // only include classes that are in the Rootcategory or subcategories. Result := assigned(Cat) and (Cat = RoseClass.Model.RootCategory); end else begin Cat := RoseClass.ParentCategory; if Cat.TopLevel then - Result := LogicalPackages.IndexOf('') <> -1 //do not localize + Result := LogicalPackages.IndexOf('') <> -1 else begin Result := LogicalPackages.IndexOf(Cat.Name) <> -1; @@ -394,7 +384,7 @@ function TBoldUMLRose98MappingUtils.FindClass(const UniqueId: String): TUMLClass Result := FindInCache(fCachedClasses, UniqueId) as TUMLClass; if not Assigned(Result) then begin - RefreshCache(fCachedClasses, 'Class'); //do not localize + RefreshCache(fCachedClasses, 'Class'); Result := FindInCache(fCachedClasses, UniqueId) as TUMLClass; end; end; @@ -425,7 +415,7 @@ procedure TBoldUMLRose98MappingUtils.RefreshCache(var Cache: TStringList; FreeAndNil(Cache); Cache := TStringList.Create; Elementlist := UMLModel.EvaluateExpressionAsNewElement( - Format('UML%s.allInstances->reject(oclIsKindOf(UMLTaggedValue))->select(model=self)', [FilterType])) as TUMLModelElementList; //do not localize + Format('UML%s.allInstances->reject(oclIsKindOf(UMLTaggedValue))->select(model=self)', [FilterType])) as TUMLModelElementList; try for i := 0 to Elementlist.Count-1 do begin @@ -450,7 +440,7 @@ function TBoldUMLRose98MappingUtils.FindAssocation(const UniqueId: String): TUML result := nil; if not Assigned(Result) then begin - RefreshCache(fCachedAssociations, 'Association'); //do not localize + RefreshCache(fCachedAssociations, 'Association'); Result := FindInCache(fCachedAssociations, UniqueId) as TUMLASsociation; end; end; @@ -460,9 +450,11 @@ function TBoldUMLRose98MappingUtils.FindElement(const UniqueId: String): TUMLEle Result := FindInCache(fCachedElements , UniqueId) as TUMLElement; if not Assigned(Result) then begin - RefreshCache(fCachedElements, 'ModelElement'); //do not localize + RefreshCache(fCachedElements, 'ModelElement'); Result := FindInCache(fCachedElements, UniqueId) as TUMLElement; end; end; +initialization + end. diff --git a/Source/UMLModel/ModelLinks/Rose98/BoldUMLRose98Support.pas b/Source/UMLModel/ModelLinks/Rose98/BoldUMLRose98Support.pas index 8b8b3db..34d3a75 100644 --- a/Source/UMLModel/ModelLinks/Rose98/BoldUMLRose98Support.pas +++ b/Source/UMLModel/ModelLinks/Rose98/BoldUMLRose98Support.pas @@ -1,6 +1,9 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldUMLRose98Support; -{$WARN SYMBOL_PLATFORM OFF} // WINDOWS only +{$WARN SYMBOL_PLATFORM OFF} interface @@ -34,9 +37,9 @@ TBoldUMLRose98Properties = class(TBoldRose98Properties) procedure TaggedValueToElement(UmlElement: TUMLModelElement; RoseProp: IRoseProperty; Toolname: String); function GetEffectiveDefaults: TBoldTaggedValuePerClassList; function GetBoldDefaultsForClass(const UMLModelName: string; RoseItem: IRoseItem): TBoldTaggedValueList; - property EffectiveDefaults: TBoldTaggedValuePerClassList read GetEffectiveDefaults; + property EffectiveDefaults: TBoldTaggedValuePerClassList read GetEffectiveDefaults; public - destructor Destroy; override; + destructor destroy; override; procedure GetTaggedValues(RoseItem: IRoseItem; UMLElement: TUMLModelElement; AdditionalTools: TStrings); procedure SetTaggedValues(RoseItem: IRoseItem; UMLElement: TUMLModelElement; AdditionalTools: TStrings); procedure SetTaggedValuesAsDefaultProps(RoseItem: IRoseItem; UMLElement: TUMLModelElement; AdditionalTools: TStrings); @@ -73,7 +76,7 @@ class function TBoldUMLRose98Properties.LogName(UMLElement: TUMLModelElement): s if Assocation.connection.Count = 2 then Result := EffectiveName(Assocation.connection[0]) + EffectiveName(Assocation.connection[1]) else - Result := ''; + Result := ''; end else if (UMLElement is TUMLAssociationEnd) then begin @@ -118,7 +121,6 @@ procedure TBoldUMLRose98Properties.GetTaggedValuesForTool(RoseItem: IRoseItem; U else begin PropCollection := GetToolProps(RoseItem, aToolName); -// aToolName := aToolName + '.'; for Index := 1 to PropCollection.Count do TaggedValueToElement(UmlElement, PropCollection.GetAt(Index), aToolname); end; @@ -240,8 +242,7 @@ procedure TBoldUMLRose98Properties.GetTaggedValues(RoseItem: IRoseItem; PropCollection: IRosePropertyCollection; DefaultProp: IRoseProperty;} begin - // the import spends quite a lot of time here... - + GetTaggedValuesForTool(RoseItem, UMLElement, ToolName); GetTaggedValuesForTool(RoseItem, UMLElement, BOLDSTDUMLTOOLNAME); for i := 0 to AdditionalTools.Count-1 do @@ -337,4 +338,6 @@ function TBoldUMLRose98Properties.StripToolName( end; end; +initialization + end. diff --git a/Source/UMLModel/ModelLinks/XMI/BoldDTDParser.pas b/Source/UMLModel/ModelLinks/XMI/BoldDTDParser.pas index 6b82fa6..51a6d09 100644 --- a/Source/UMLModel/ModelLinks/XMI/BoldDTDParser.pas +++ b/Source/UMLModel/ModelLinks/XMI/BoldDTDParser.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldDTDParser; interface @@ -73,9 +76,11 @@ TBoldDTDParser = class implementation uses - classes, + Classes, + SysUtils, BoldDefs, - BoldStringList; + BoldStringList, + BoldUtils; const SpaceChars = [#$20, #$9, #$D, #$A]; @@ -127,19 +132,15 @@ procedure TBoldDTDParser.Parse(DTD: string); function TBoldDTDParser.ParseAttListDecl: Boolean; begin -// AttlistDecl ::= '' if ParseToken(dtAttlistDecl) then begin -// Cheat! I don't really care, so just skip everything... while fScanner.LastToken <> dtEndDecl do fScanner.NextToken; fScanner.NextToken; -// AssertToken(dtSpace); -// AssertToken(dtName); -// while ParseAttDef do; -// OptionalToken(dtSpace); -// AssertToken(dtEndDecl); + + + result := true; end else result := false; @@ -152,25 +153,21 @@ function TBoldDTDParser.ParseChildren: Boolean; function TBoldDTDParser.ParseChildren2: Boolean; begin -// children ::= (choice | seq) ('?' | '*' | '+')? -// cp ::= (Name | choice | seq) ('?' | '*' | '+')? -// choice ::= '(' S? cp S? ( '|' S? cp S? )+ ')' /* */ -// seq ::= '(' S? cp S? ( ',' S? cp S? )* ')' -// note! '(' S? already parsed + + + result := ParseChoiceOrSeq; if result then if ParseToken(dtOptional) or ParseToken(dtZeroOrMore) or ParseToken(dtOneOrMore) then - ;//nothing + ; end; function TBoldDTDParser.ParseChoiceOrSeq: Boolean; begin -// choice ::= '(' S? cp S? ( '|' S? cp S? )+ ')' /* */ -// seq ::= '(' S? cp S? ( ',' S? cp S? )* ')' -// note! '(' S? already parsed + AssertNonterminal(ParseCp); OptionalToken(dtSpace); @@ -196,7 +193,7 @@ function TBoldDTDParser.ParseChoiceOrSeq: Boolean; end; AssertToken(dtCloseParen); end - else // seq without comma + else begin AssertToken(dtCloseParen); end; @@ -205,7 +202,6 @@ function TBoldDTDParser.ParseChoiceOrSeq: Boolean; function TBoldDTDParser.ParseContentSpec: Boolean; begin -// contentspec ::= 'EMPTY' | 'ANY' | Mixed | children result := ParseToken(dtEmptyContent) or ParseToken(dtAnyContent) or ParseMixedOrChildren; @@ -213,7 +209,6 @@ function TBoldDTDParser.ParseContentSpec: Boolean; function TBoldDTDParser.ParseCp: Boolean; begin -// cp ::= (Name | choice | seq) ('?' | '*' | '+')? if fScanner.LastToken = dtName then begin FoundCpName(fScanner.LastTokenText); @@ -231,12 +226,11 @@ function TBoldDTDParser.ParseCp: Boolean; if result then if ParseToken(dtOptional) or ParseToken(dtZeroOrMore) or ParseToken(dtOneOrMore) then - ;//nothing... + ; end; function TBoldDTDParser.ParseElementDecl: Boolean; begin -// elementDecl ::= '' if ParseToken(dtElementDecl) then begin AssertToken(dtSpace); @@ -257,13 +251,11 @@ function TBoldDTDParser.ParseElementDecl: Boolean; function TBoldDTDParser.ParseEntityDecl: Boolean; begin -// EntityDecl ::= GEDecl | PEDecl -// GEDecl ::= '' -// PEDecl ::= '' + + if ParseToken(dtEntityDecl) then begin -// Cheat! I don't really care, so just skip everything... while fScanner.LastToken <> dtEndDecl do fScanner.NextToken; fScanner.NextToken; @@ -276,13 +268,11 @@ function TBoldDTDParser.ParseEntityDecl: Boolean; procedure TBoldDTDParser.ParseExtSubsetDecl; begin -// extSubsetDecl ::= ( markupdecl | conditionalSect | DeclSep)* while (ParseMarkupDecl or ParseToken(dtSpace)) do; end; function TBoldDTDParser.ParseMarkupDecl: Boolean; begin -// markupdecl ::= elementdecl | AttlistDecl | EntityDecl | NotationDecl | PI | Comment result := ParseElementDecl or ParseAttListDecl or ParseEntityDecl or @@ -291,15 +281,13 @@ function TBoldDTDParser.ParseMarkupDecl: Boolean; function TBoldDTDParser.ParseMixed: Boolean; begin -//Mixed ::= '(' S? '#PCDATA' (S? '|' S? Name)* S? ')*' -// | '(' S? '#PCDATA' S? ')' + raise EBold.Create('Not implemented'); end; function TBoldDTDParser.ParseMixed2: Boolean; begin -//Mixed ::= '#PCDATA' S? ( '|' S? Name S? )* ')*' -// | '#PCDATA' S? ')' + result := ParseToken(dtPCDataDecl); if result then @@ -384,13 +372,12 @@ function TBoldDTDParser.Preprocess(DTD: string): string; PETable.Sort; DTDStrings := TStringList.Create; DTDStrings.Text := DTD; -// BoldAppendToStrings(DTDStrings, DTD, True); for i := 0 to DTDStrings.Count-1 do begin j := 1; while j <= length(DTDStrings[i]) do begin - if (DTDStrings[i][j] = '%') and not (DTDStrings[i][j+1] in SpaceChars) then + if (DTDStrings[i][j] = '%') and not CharInSet(DTDStrings[i][j+1], SpaceChars) then begin k := j+1; while DTDStrings[i][k] <> ';' do @@ -423,9 +410,9 @@ constructor TBoldDTDScanner.Create(DTD: string); procedure TBoldDTDScanner.DeclarationToken; begin - if not (TryToken(' 0) then begin dotpos := pos('.', fAttr.AsString); - result := 'RationalRose$' + Copy(fAttr.AsString, 1, dotpos-1) + ':' + // do not localize + result := 'RationalRose$' + Copy(fAttr.AsString, 1, dotpos-1) + ':' + Copy(fAttr.AsString, dotpos+1, MAXINT); end else @@ -528,6 +531,7 @@ constructor TBoldUMLMOFReferenceListAdapter.Create(Obj: TBoldObject; OwningLink: GetReferences(fRefs, Obj); end; + destructor TBoldUMLMOFReferenceListAdapter.Destroy; begin FreeAndNil(fRefs); @@ -547,13 +551,11 @@ procedure TBoldUMLMOFReferenceListAdapter.GetMIReferences(List: TList; GetReferences(List2, Obj2); for i := 0 to List2.Count-1 do begin - // The two halves should have the common part (diamond inheritence) first. if TBoldMember(List[i]).BoldMemberRTInfo.ModelName = - TBoldMember(List2[i]).BoldMemberRTInfo.ModelName then // FIXME: use qualified names + TBoldMember(List2[i]).BoldMemberRTInfo.ModelName then begin - // Just keep the first one. - // FIXME: Merge? - // Note: Tagged Values will be handled by ObjectListAdapter-factory + + end else List.Add(List2[i]); end; @@ -582,10 +584,10 @@ function TBoldUMLMOFReferenceListAdapter.IsBoldAddedRole( begin assert(Role.BoldMemberRTInfo.IsRole); RoleRt := TBoldRoleRTInfo(Role.BoldMemberRTInfo); - Result := (RoleRt.Stereotype = 'Bold') or // do not localize - (RoleRt.AssociationStereotype = 'Bold') or // do not localize - (RoleRt.ClassTypeInfoOfOtherEnd.Stereotype = 'Bold') or // do not localize - ((RoleRt.ModelName = 'associationEnd') and (RoleRt.ClassTypeInfo.ModelName = 'Classifier')) or // do not localize + Result := (RoleRt.Stereotype = 'Bold') or + (RoleRt.AssociationStereotype = 'Bold') or + (RoleRt.ClassTypeInfoOfOtherEnd.Stereotype = 'Bold') or + ((RoleRt.ModelName = 'associationEnd') and (RoleRt.ClassTypeInfo.ModelName = 'Classifier')) or IsInheritedButShouldNotBe(Role); end; @@ -763,7 +765,7 @@ function TBoldUMLMOFMultiplicityAdapter.IsComposite: Boolean; function TBoldUMLMOFMultiplicityAdapter.IsDerived: Boolean; begin - result := false; + result := false; end; function TBoldUMLMOFMultiplicityAdapter.IsMulti: Boolean; @@ -788,12 +790,12 @@ function TBoldUMLMOFMultiplicityAdapter.Objects: IBoldMOFObjectList; function TBoldUMLMOFMultiplicityAdapter.QualifiedClassName: string; begin - result := 'Foundation.Data_Types.Multiplicity'; // do not localize + result := 'Foundation.Data_Types.Multiplicity'; end; function TBoldUMLMOFMultiplicityAdapter.QualifiedName: string; begin - result := 'Foundation.Data_Types.Multiplicity.range'; // do not localize + result := 'Foundation.Data_Types.Multiplicity.range'; end; function TBoldUMLMOFMultiplicityAdapter.Reference( @@ -819,9 +821,9 @@ function TBoldUMLMOFMultiplicityRangeAdapter.Attribute( index: Integer): IBoldMOFAttribute; begin if index = 0 then - result := TBoldUMLMOFMultiplicityRangeBoundAdapter.Create('lower', fLower) // do not localize + result := TBoldUMLMOFMultiplicityRangeBoundAdapter.Create('lower', fLower) else if index = 1 then - result := TBoldUMLMOFMultiplicityRangeBoundAdapter.Create('upper', fUpper) // do not localize + result := TBoldUMLMOFMultiplicityRangeBoundAdapter.Create('upper', fUpper) else raise EBoldInternal.CreateFmt('%s.Attribute: index out of bounds %d', [classname, index]); end; @@ -845,24 +847,24 @@ constructor TBoldUMLMOFMultiplicityRangeAdapter.Create(Range: string; OwningLink splitpos := pos('..', Range); if splitpos = 0 then begin - if (trim(Range) = '*') or (trim(Range) = 'n') then + if Range = '*' then begin fLower := 0; fUpper := -1; end else begin - fLower := StrToInt(trim(Range)); + fLower := StrToInt(Range); fUpper := fLower; - end; + end; end else begin - fLower := StrToInt(trim(Copy(Range, 1, splitpos-1))); + fLower := StrToInt(Copy(Range, 1, splitpos-1)); Upper := Copy(Range, splitpos+2, maxint); - if (trim(Upper) = '*') or (trim(Upper) = 'n') then + if Upper = '*' then fUpper := -1 else - fUpper := StrToInt(trim(Upper)); + fUpper := StrToInt(Upper); end; end; @@ -873,7 +875,7 @@ function TBoldUMLMOFMultiplicityRangeAdapter.LocalId: string; function TBoldUMLMOFMultiplicityRangeAdapter.QualifiedClassName: string; begin - result := 'Foundation.Data_Types.MultiplicityRange'; // do not localize + result := 'Foundation.Data_Types.MultiplicityRange'; end; function TBoldUMLMOFMultiplicityRangeAdapter.RefCount: Integer; @@ -938,7 +940,7 @@ function TBoldUMLMOFMultiplicityRangeBoundAdapter.IsObject: Boolean; function TBoldUMLMOFMultiplicityRangeBoundAdapter.QualifiedName: string; begin - result := 'Foundation.Data_Types.MultiplicityRange.' + fAttrName; // do not localize + result := 'Foundation.Data_Types.MultiplicityRange.' + fAttrName; end; { TBoldUMLMOFExpressionAdapter } @@ -962,7 +964,7 @@ function TBoldUMLMOFExpressionAdapter.Attribute( index: Integer): IBoldMOFAttribute; begin if index = 0 then - result := TBoldUMLMOFDummyAttrAdapter.Create('Foundation.Data_Types.Expression.language') // do not localize + result := TBoldUMLMOFDummyAttrAdapter.Create('Foundation.Data_Types.Expression.language') else if index = 1 then result := self else @@ -1017,12 +1019,12 @@ function TBoldUMLMOFExpressionAdapter.LocalId: string; function TBoldUMLMOFExpressionAdapter.QualifiedClassName: string; begin - result := 'Foundation.Data_Types.' + fExprAttr.BoldType.ModelName; // do not localize + result := 'Foundation.Data_Types.' + fExprAttr.BoldType.ModelName; end; function TBoldUMLMOFExpressionAdapter.QualifiedName: string; begin - result := 'Foundation.Data_Types.Expression.body'; // do not localize + result := 'Foundation.Data_Types.Expression.body'; end; function TBoldUMLMOFExpressionAdapter.Reference( @@ -1083,4 +1085,6 @@ function TBoldUMLMOFDummyAttrAdapter.QualifiedName: string; result := fQualifiedName; end; +initialization + end. diff --git a/Source/UMLModel/ModelLinks/XMI/BoldUMLXMICommon.pas b/Source/UMLModel/ModelLinks/XMI/BoldUMLXMICommon.pas index 9ced9ee..73a4d28 100644 --- a/Source/UMLModel/ModelLinks/XMI/BoldUMLXMICommon.pas +++ b/Source/UMLModel/ModelLinks/XMI/BoldUMLXMICommon.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldUMLXMICommon; interface @@ -23,7 +26,7 @@ function UnqualifiedName(const aText: String): String; function RemoveBoldPackageNames(Name: string): string; const - BoldPackagePrefix = 'BoldUMLModel.UMLMeta.'; // do not localize + BoldPackagePrefix = 'BoldUMLModel.UMLMeta.'; begin assert(Copy(Name, 1, Length(BoldPackagePrefix)) = BoldPackagePrefix); result := Copy(Name, Length(BoldPackagePrefix)+1, maxint); @@ -55,16 +58,16 @@ function QualifiedMemberName(MemberRT: TBoldMemberRTInfo): string; function IsNameOfExpressionClass(Name: string): Boolean; begin - result :=(Name = 'Expression') or // do not localize - (Name = 'ActionExpression') or // do not localize - (Name = 'ArgListsExpression') or // do not localize - (Name = 'BooleanExpression') or // do not localize - (Name = 'IterationExpression') or // do not localize - (Name = 'MappingExpression') or // do not localize - (Name = 'ObjectSetExpression') or // do not localize - (Name = 'ProcedureExpression') or // do not localize - (Name = 'TimeExpression') or // do not localize - (Name = 'TypeExpression'); // do not localize + result :=(Name = 'Expression') or + (Name = 'ActionExpression') or + (Name = 'ArgListsExpression') or + (Name = 'BooleanExpression') or + (Name = 'IterationExpression') or + (Name = 'MappingExpression') or + (Name = 'ObjectSetExpression') or + (Name = 'ProcedureExpression') or + (Name = 'TimeExpression') or + (Name = 'TypeExpression'); end; end. diff --git a/Source/UMLModel/ModelLinks/XMI/BoldUMLXMIImporter.pas b/Source/UMLModel/ModelLinks/XMI/BoldUMLXMIImporter.pas index 35dd7a5..c2d7528 100644 --- a/Source/UMLModel/ModelLinks/XMI/BoldUMLXMIImporter.pas +++ b/Source/UMLModel/ModelLinks/XMI/BoldUMLXMIImporter.pas @@ -1,7 +1,10 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldUMLXMIImporter; interface - + uses Variants, BoldContainers, @@ -12,7 +15,7 @@ interface BoldSystemRT, BoldUMLXMILinkSupport, MSXML_TLB, - Sysutils, // for TFileName + Sysutils, Classes; type @@ -28,7 +31,7 @@ TBoldUMLXMIImporter = class fTheUMLModel: TUMLModel; fTheUMLModelFound: Boolean; fDOMDocument: TDOMDocument; -// fDebugLog: TBoldLogForm; + fDebugLog: TBoldLogForm; fBoldSystem: TBoldSystem; fSkipMetaClassList: TStringList; fTraverseOnlyMetaClassList: TStringList; @@ -46,7 +49,6 @@ TBoldUMLXMIImporter = class procedure ImportMetaAssociationEndFromElement(BoldMember: TBoldMember; XMLElement: IXMLDOMElement; Multi: Boolean); property DOMDocument: TDOMDocument read GetDOMDocument; class function GetUMLName(const aText: String): String; -// class function UnqualifiedName(const aText: String): String; procedure ImportMetaAttributeFromElement(BoldAttribute: TBoldAttribute; XMLElement: IXMLDOMElement); function CreateUMLObjectsForMetaObject(XMLElement: IXMLDOMElement): TBoldUMLElementArray; function MetaClassAction(XMLElement: IXMLDOMElement): TClassAction; @@ -93,7 +95,7 @@ constructor TBoldUMLXMIImporter.Create(OwningLink: TBoldUMLXMILink; UMLModel: TU fOwningLink := OwningLink; fTheUMLModel := UMLModel; fBoldSystem := UMLModel.BoldSystem; -// fDebugLog := TBoldLogForm.Create(nil); + fDebugLog := TBoldLogForm.Create(nil); fImportedElementList := TBoldXMIIObjectList.Create; InitializeLists; end; @@ -101,7 +103,7 @@ constructor TBoldUMLXMIImporter.Create(OwningLink: TBoldUMLXMILink; UMLModel: TU destructor TBoldUMLXMIImporter.Destroy; begin FreeAndNil(fDOMDocument); -// FreeAndNil(fDebugLog); + FreeAndNil(fDebugLog); FreeAndNil(fSkipMetaClassList); FreeAndNil(fTraverseOnlyMetaClassList); FreeAndNil(fImportedElementList); @@ -160,7 +162,6 @@ procedure TBoldUMLXMIImporter.ImportMetaAssociationEndFromElement(BoldMember: TB TBoldObjectReference(BoldMember).BoldObject := nil else TBoldObjectReference(BoldMember).BoldObject := ObjectsToAdd[0]; - // raise EBold.Create('Multiple elements to single reference'); end else raise Exception.Create('Wrong association type, expected single.'); @@ -182,7 +183,7 @@ procedure TBoldUMLXMIImporter.ImportXMIObjectList(list: TUMLELementList; XMLElem childElement := FirstElementFromNodeList(nodeList); while Assigned(ChildElement) do begin - if (IsNonBlank(GetXMIIdref(ChildElement))) then // Object Reference + if (IsNonBlank(GetXMIIdref(ChildElement))) then ObjectsToAdd := (fImportedElementList.UMLElementsById[GetXMIIdref(ChildElement)]) else ObjectsToAdd := ImportMetaObject(childElement); @@ -201,7 +202,7 @@ class function TBoldUMLXMIImporter.UnqualifiedName(const aText: String): String; } class function TBoldUMLXMIImporter.GetUMLName(const aText: String): String; begin - Result := 'UML' + UnqualifiedName(aText); //do not localize + Result := 'UML' + UnqualifiedName(aText); end; function TBoldUMLXMIImporter.ImportMetaObject(XMLElement: IXMLDOMElement): TBoldUMLElementArray; @@ -232,7 +233,7 @@ function TBoldUMLXMIImporter.ImportMetaObject(XMLElement: IXMLDOMElement): TBold else Result := nil end - else // PASS2, objects refered in previous pass must exist, the rest created now + else begin if IsNonBlank(Id) then begin @@ -255,26 +256,25 @@ function TBoldUMLXMIImporter.ImportMetaObject(XMLElement: IXMLDOMElement): TBold ; caSkip: begin -// fDebugLog.AddLog(Format('Skipping metaobject: %s', [XMLElement.NodeName])); + fDebugLog.AddLog(Format('Skipping metaobject: %s', [XMLElement.NodeName])); Exit; end; caUNKNOWN: begin -// fDebugLog.AddLog(Format('Skipping Unknown metaobject: (%s),(%s)', [XMLElement.ParentNode.Nodename, XMLElement.NodeName])); + fDebugLog.AddLog(Format('Skipping Unknown metaobject: (%s),(%s)', [XMLElement.ParentNode.Nodename, XMLElement.NodeName])); Exit; end; end; - // Very hardcoded for max two types, and only AssociationClass having two if Assigned(Result) then begin for i := 0 to Result.Count-1 do ClassTypeInfo[i] := Result[i].BoldClassTypeInfo; ClassTypeInfoCount := Result.Count; end - else if GetUMLName(XMLElement.tagName) = 'AssociationClass' then //do not localize + else if GetUMLName(XMLElement.tagName) = 'AssociationClass' then begin - ClassTypeInfo[0] := BoldSystem.BoldSystemTypeInfo.ClassTypeInfoByExpressionName[GetUMLName('Class')]; //do not localize - ClassTypeInfo[1] := BoldSystem.BoldSystemTypeInfo.ClassTypeInfoByExpressionName[GetUMLName('Association')]; //do not localize + ClassTypeInfo[0] := BoldSystem.BoldSystemTypeInfo.ClassTypeInfoByExpressionName[GetUMLName('Class')]; + ClassTypeInfo[1] := BoldSystem.BoldSystemTypeInfo.ClassTypeInfoByExpressionName[GetUMLName('Association')]; ClassTypeInfoCount := 2; end else @@ -336,7 +336,6 @@ function TBoldUMLXMIImporter.ImportMetaObject(XMLElement: IXMLDOMElement): TBold if rtInfo.IsAttribute then ImportMetaAttributeFromElement(Boldmember as TBoldAttribute, Element) else - // don't import associations twice if (i = 0) or not assigned(ClassTypeInfo[0].MemberRTInfoByExpressionName[UnqualifiedName(Element.nodeName)]) then ImportMetaAssociationEndFromElement(Boldmember, Element, rtinfo.IsMultiRole) end @@ -350,13 +349,12 @@ function TBoldUMLXMIImporter.ImportMetaObject(XMLElement: IXMLDOMElement): TBold procedure TBoldUMLXMIImporter.ImportMetaAttributeFromElement(BoldAttribute: TBoldAttribute; XMLElement: IXMLDOMElement); function ValueIsMultiplicity(DOMElement: IXMLDOMElement): Boolean; begin - Result := UnqualifiedName(DOMElement.nodeName) = 'multiplicity'; //do not localize + Result := UnqualifiedName(DOMElement.nodeName) = 'multiplicity'; end; function ValueIsXmiValue(DOMElement: IXMLDOMElement): Boolean; begin - Result := assigned(DOMElement.getAttributeNode('xmi.value')); //do not localize -//not (ValueIsMultiplicity(DOMElement) or ValueISCData(DOMElement)); + Result := assigned(DOMElement.getAttributeNode('xmi.value')); end; function ValueIsExpression(DOMElement: IXMLDOMElement): Boolean; @@ -369,17 +367,16 @@ procedure TBoldUMLXMIImporter.ImportMetaAttributeFromElement(BoldAttribute: TBol begin Result := not (ValueIsXmiValue(DOMElement) or ValueIsMultiplicity(DOMElement) or ValueIsExpression(DOMElement)); -// DOMElement.nodeName = XMI_CORE_MODELELEMENT_NAME; end; var anAttribValue: String; begin if (pass = PASS1) then - Exit; // only set attributes on pass 2 + Exit; if ValueIsXmiValue(XMLElement) then begin - anAttribValue := BoldSharedStringManager.GetSharedString(VarToStr(XMLElement.getAttribute('xmi.value'))); //do not localize + anAttribValue := BoldSharedStringManager.GetSharedString(VarToStr(XMLElement.getAttribute('xmi.value'))); if anAttribValue <> '' then ImportAttributeFromString(BoldAttribute, anAttribValue); end @@ -393,8 +390,7 @@ procedure TBoldUMLXMIImporter.ImportMetaAttributeFromElement(BoldAttribute: TBol else if ValueIsExpression(XMLElement) then BoldAttribute.AsString := BoldSharedStringManager.GetSharedString(ImportExpressionAsString(XMLElement.firstChild as IXMLDOMElement)) else - begin - { TODO : Further types } + begin end; end; @@ -402,7 +398,7 @@ function TBoldUMLXMIImporter.MetaClassAction(XMLElement: IXMLDOMElement): TClass begin if Assigned(BoldSystem.BoldSystemTypeInfo.ClassTypeInfoByExpressionName[GetUMLName(XMLElement.nodeName)]) then Result := caIMPORT - else if GetUMLName(XMLElement.nodeName) = 'UMLAssociationClass' then //do not localize + else if GetUMLName(XMLElement.nodeName) = 'UMLAssociationClass' then Result := caIMPORT else if SkipMetaClassList.IndexOf(XMLElement.nodeName) <> -1 then Result := caSkip @@ -424,8 +420,6 @@ function TBoldUMLXMIImporter.GetAttributeMember(OwningObject: TUMLElement; const Result := TBoldAttribute(OwningObject.BoldMembers[aMemberRTInfo.Index]); end; end; - -// Due to implementation of multiple inheritance more than one UMLObject may be created function TBoldUMLXMIImporter.CreateUMLObjectsForMetaObject(XMLElement: IXMLDOMElement): TBoldUMLElementArray; var UMLClassName: String; @@ -434,43 +428,41 @@ function TBoldUMLXMIImporter.CreateUMLObjectsForMetaObject(XMLElement: IXMLDOMEl Element1, Element2: TUMLModelElement; begin XMIId := GetXMIId(XMLElement); -// fDebugLog.AddLog(Format('Creating model part: %s(%s)', [XMLElement.nodeName, FormatId(XMIId)])); + fDebugLog.AddLog(Format('Creating model part: %s(%s)', [XMLElement.nodeName, FormatId(XMIId)])); if Assigned(fImportedElementList.ItemsById[XMIId]) then begin raise EBoldInternal.Create('Modelpart already exists'); end else begin - // Handle Model and AssociationClass separately UMLClassName := GetUMLName(XMLElement.nodeName); - if UMLClassName = 'UMLModel' then //do not localize + if UMLClassName = 'UMLModel' then begin if not fTheUMLModelFound then begin - // We already have a model, just associate it with ID. Result := fImportedElementList.Add(XMIId, fTheUMLModel); fTheUMLModelFound := True; end else begin Element1 := BoldSystem.CreateNewObjectByExpressionName(UMLClassName, False) as TUMLModelElement; -// TBoldUMLSupport.EnsureBoldTaggedValues(Element1); + TBoldUMLSupport.EnsureBoldTaggedValues(Element1); Result := fImportedElementList.Add(XMIId, Element1); end; end - else if UMLClassName = 'UMLAssociationClass' then //do not localize + else if UMLClassName = 'UMLAssociationClass' then begin - Element1 := BoldSystem.CreateNewObjectByExpressionName('UMLClass', False) as TUMLModelElement; //do not localize -// TBoldUMLSupport.EnsureBoldTaggedValues(Element1); - Element2 := BoldSystem.CreateNewObjectByExpressionName('UMLAssociation', False) as TUMLModelElement; //do not localize -// TBoldUMLSupport.EnsureBoldTaggedValues(Element2); + Element1 := BoldSystem.CreateNewObjectByExpressionName('UMLClass', False) as TUMLModelElement; + TBoldUMLSupport.EnsureBoldTaggedValues(Element1); + Element2 := BoldSystem.CreateNewObjectByExpressionName('UMLAssociation', False) as TUMLModelElement; + TBoldUMLSupport.EnsureBoldTaggedValues(Element2); Result := fImportedElementList.Add(XMIId, Element1, Element2); (Result[1] as TUMLAssociation).Class_ := (Result[0] as TUMLClass); end else begin Element1 := BoldSystem.CreateNewObjectByExpressionName(UMLClassName, False) as TUMLModelElement; -// TBoldUMLSupport.EnsureBoldTaggedValues(Element1); + TBoldUMLSupport.EnsureBoldTaggedValues(Element1); Result := fImportedElementList.Add(XMIId, Element1); end; end; @@ -483,12 +475,10 @@ function TBoldUMLXMIImporter.CreateUMLObjectsForMetaObject(XMLElement: IXMLDOMEl procedure TBoldUMLXMIImporter.InitializeLists; begin - // Initialize skip list fSkipMetaClassList := TStringList.Create; fTraverseOnlyMetaClassList := TStringList.Create; -// if XMIExporter = UNISYS_TCR_2 then -// SkipMetaClassList.Add('Diagramming.Diagram'); - // Initialize travsrse list + + SkipMetaClassList.Sorted := True; TraverseOnlyMetaClassList.Sorted := True; end; @@ -499,18 +489,18 @@ function TBoldUMLXMIImporter.ImportMultiplicityAsString(XMLElement: IXMLDOMELeme nodeList: IXMLDOMNodeList; Ranges: TStringList; begin - if UnqualifiedName(XMLElement.nodeName) <> 'Multiplicity' then //do not localize + if UnqualifiedName(XMLElement.nodeName) <> 'Multiplicity' then raise EBold.CreateFmt('Wrong nodename: %s', [XMLElement.nodeName]); if (XMLElement.childNodes.length = 0) or (XMLElement.firstChild.childNodes.length = 0) then begin Result := ImportCdataValue(XMLElement); if result = '' then - result := '0..*'; //do not localize + result := '0..*'; end else begin - if UnqualifiedName(XMLElement.firstChild.nodeName) <> 'range' then //do not localize + if UnqualifiedName(XMLElement.firstChild.nodeName) <> 'range' then raise EBold.CreateFmt('Wrong nodename: %s', [XMLElement.nodeName]); nodeList := XMLElement.firstChild.childNodes; @@ -536,14 +526,14 @@ function TBoldUMLXMIImporter.ImportMultiplicityRangeAsString(XMLElement: IXMLDOM nodeList: IXMLDOMNodeList; attr: IXMLDOMAttribute; begin - if UnqualifiedName(XMLElement.nodeName) <> 'MultiplicityRange' then //do not localize + if UnqualifiedName(XMLElement.nodeName) <> 'MultiplicityRange' then raise EBold.CreateFmt('Wrong nodename: %s', [XMLElement.nodeName]); - attr := XMLElement.getAttributeNode('lower'); //do not localize + attr := XMLElement.getAttributeNode('lower'); if assigned(attr) then Lower := attr.value; - attr := XMLElement.getAttributeNode('upper'); //do not localize + attr := XMLElement.getAttributeNode('upper'); if assigned(attr) then Upper := attr.value; @@ -551,9 +541,9 @@ function TBoldUMLXMIImporter.ImportMultiplicityRangeAsString(XMLElement: IXMLDOM childElement := FirstElementFromNodeList(nodeList); while Assigned(ChildElement) do begin - if UnqualifiedName(childElement.nodeName) = 'lower' then //do not localize + if UnqualifiedName(childElement.nodeName) = 'lower' then Lower := ImportCdataValue(childElement) - else if UnqualifiedName(childElement.nodeName) = 'upper' then //do not localize + else if UnqualifiedName(childElement.nodeName) = 'upper' then Upper := ImportCdataValue(childElement) else raise EBoldInternal.Create('Import error'); @@ -589,8 +579,6 @@ function TBoldUMLXMIImporter.ImportCdataValue(XMLElement: IXMLDOMELement): strin procedure TBoldUMLXMIImporter.RawImport; var RootElement, ContentElement: IXMLDOMElement; - AllElements: TUMLModelElementList; - i: integer; function FindContent(XMLElement: IXMLDOMElement): IXMLDOMElement; var @@ -615,7 +603,7 @@ procedure TBoldUMLXMIImporter.RawImport; begin LoadAndCheck(OwningLink.Filename); -// fDebugLog.Show; + fDebugLog.Show; fImportedElementList.Clear; DOMDocument.preserveWhiteSpace := True; @@ -627,18 +615,13 @@ procedure TBoldUMLXMIImporter.RawImport; if not Assigned(ContentElement) then raise EBold.Create('Content missing'); -// fDebugLog.AddLog('PASS 1'); + fDebugLog.AddLog('PASS 1'); fPass := PASS1; ImportXMIObjectList(nil, ContentElement, nil); -// fDebugLog.AddLog('PASS 2'); + fDebugLog.AddLog('PASS 2'); fPass := PASS2; ImportXMIObjectList(nil, ContentElement, nil); - - AllElements := fBoldSystem.ClassByExpressionName['UMLModelElement'] as TUMLModelElementList; //do not localize - for i := AllElements.Count-1 downto 0 do - TBoldUMLSupport.EnsureBoldTaggedValues(AllElements[i]); - -// fDebugLog.AddLog('DONE'); + fDebugLog.AddLog('DONE'); end; function TBoldUMLXMIImporter.FindMemberRt( @@ -667,7 +650,7 @@ function TBoldUMLXMIImporter.ImportExpressionAsString( nodeList: IXMLDOMNodeList; childElement: IXMLDOMElement; begin - attr := XMLElement.getAttributeNode('body'); //do not localize + attr := XMLElement.getAttributeNode('body'); if assigned(attr) then result := attr.value else @@ -677,7 +660,7 @@ function TBoldUMLXMIImporter.ImportExpressionAsString( childElement := FirstElementFromNodeList(nodeList); while assigned(childElement) do begin - if UnqualifiedName(childElement.nodeName) = 'body' then //do not localize + if UnqualifiedName(childElement.nodeName) = 'body' then result := ImportCdataValue(childElement); childElement := NextElementFromNodeList(nodeList); end; @@ -690,11 +673,11 @@ procedure TBoldUMLXMIImporter.ImportAttributeFromString( colonpos: integer; begin if OwningLink.TranslateRoseTaggedValues and - (BoldAttribute.DisplayName = 'UMLTaggedValue.tag') and //do not localize - (pos('RationalRose$', AttributeValue) = 1) and //do not localize + (BoldAttribute.DisplayName = 'UMLTaggedValue.tag') and + (pos('RationalRose$', AttributeValue) = 1) and (pos(':', AttributeValue) <> 0) then begin - AttributeValue := Copy(AttributeValue, length('RationalRose$')+1, MAXINT); //do not localize + AttributeValue := Copy(AttributeValue, length('RationalRose$')+1, MAXINT); colonpos := pos(':', AttributeValue); BoldAttribute.AsString := Copy(AttributeValue, 1, colonpos-1) + '.' + Copy(AttributeValue, colonpos+1, MAXINT); @@ -702,12 +685,9 @@ procedure TBoldUMLXMIImporter.ImportAttributeFromString( else if BoldAttribute is TBABoolean then BoldAttribute.StringRepresentation[3] := AttributeValue else - begin - if (BoldAttribute is TBAVisibilityKind) and - (AttributeValue = 'package') then //do not localize - AttributeValue := 'public'; //do not localize BoldAttribute.AsString := AttributeValue; - end end; +initialization + end. diff --git a/Source/UMLModel/ModelLinks/XMI/BoldUMLXMILink.pas b/Source/UMLModel/ModelLinks/XMI/BoldUMLXMILink.pas index 91b0b4f..10259d4 100644 --- a/Source/UMLModel/ModelLinks/XMI/BoldUMLXMILink.pas +++ b/Source/UMLModel/ModelLinks/XMI/BoldUMLXMILink.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldUMLXMILink; interface @@ -61,7 +64,7 @@ function TBoldUMLXMILink.ExportModel(UMLModel: TUMLModel): Boolean; BoldLog.EndLog; finally exporter.Free; - end; + end; result := true; end; diff --git a/Source/UMLModel/ModelLinks/XMI/BoldUMLXMILinkSupport.pas b/Source/UMLModel/ModelLinks/XMI/BoldUMLXMILinkSupport.pas index 0067121..68f9cdb 100644 --- a/Source/UMLModel/ModelLinks/XMI/BoldUMLXMILinkSupport.pas +++ b/Source/UMLModel/ModelLinks/XMI/BoldUMLXMILinkSupport.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldUMLXMILinkSupport; interface @@ -89,17 +92,17 @@ TUUIdIndex = class(TBoldStringHashIndex) function FormatId(const id: TXMIId): string; begin if id.id <> '' then - Result := Format('id:%s ', [id.id]); // do not localize + Result := Format('id:%s ', [id.id]); if id.UUid <> '' then - Result := Format('UUid:%s ', [id.id]); // do not localize + Result := Format('UUid:%s ', [id.id]); end; function GetXMIId(UMLElementNode: IXMLDOMElement): TXMIId; begin - if not VarIsNull(UMLElementNode.getAttribute('xmi.id')) then // do not localize - Result.Id := UMLElementNode.getAttribute('xmi.id'); // do not localize - if not VarIsNull(UMLElementNode.getAttribute('xmi.uuid')) then // do not localize - Result.UUId := UMLElementNode.getAttribute('xmi.uuid'); // do not localize + if not VarIsNull(UMLElementNode.getAttribute('xmi.id')) then + Result.Id := UMLElementNode.getAttribute('xmi.id'); + if not VarIsNull(UMLElementNode.getAttribute('xmi.uuid')) then + Result.UUId := UMLElementNode.getAttribute('xmi.uuid'); end; function IsNonBlank(const XMIId: TXMIId): boolean; @@ -109,18 +112,16 @@ function IsNonBlank(const XMIId: TXMIId): boolean; function GetXMIIdRef(UMLElementNode: IXMLDOMElement): TXMIId; begin - if not VarIsNull(UMLElementNode.getAttribute('xmi.idref')) then // do not localize - Result.Id := UMLElementNode.getAttribute('xmi.idref'); // do not localize - if not VarIsNull(UMLElementNode.getAttribute('xmi.uuidref')) then // do not localize - Result.UUId := UMLElementNode.getAttribute('xmi.uuidref'); // do not localize + if not VarIsNull(UMLElementNode.getAttribute('xmi.idref')) then + Result.Id := UMLElementNode.getAttribute('xmi.idref'); + if not VarIsNull(UMLElementNode.getAttribute('xmi.uuidref')) then + Result.UUId := UMLElementNode.getAttribute('xmi.uuidref'); end; function XMIIdforId(const id: string): TXMIId; begin Result.Id := id; -end; - -{ TODO : move to common IXMLDOMSupport unit} +end; function NextElementFromNodeList(List: IXMLDOMNodeList): IXMLDOMElement; var Node: IXMLDOMNode; @@ -132,8 +133,7 @@ function NextElementFromNodeList(List: IXMLDOMNodeList): IXMLDOMElement; Result := Node as IXMLDOMElement else Node := List.NextNode; -end; -{ TODO : move to common IXMLDOMSupport unit} +end; function FirstElementFromNodeList(List: IXMLDOMNodeList): IXMLDOMElement; begin List.Reset; @@ -222,4 +222,6 @@ function TUUIdIndex.ItemAsKeyString(Item: TObject): string; Result := (Item as TBoldXMIObjectItem).xmiid.uuid; end; +initialization + end. diff --git a/Source/UMLModel/ModelLinks/XMI/BoldUMXMILinkreg.pas b/Source/UMLModel/ModelLinks/XMI/BoldUMXMILinkreg.pas index 385d3de..d8fdd88 100644 --- a/Source/UMLModel/ModelLinks/XMI/BoldUMXMILinkreg.pas +++ b/Source/UMLModel/ModelLinks/XMI/BoldUMXMILinkreg.pas @@ -1,6 +1,9 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldUMXMILinkreg; -interface +interface procedure Register; @@ -20,8 +23,6 @@ implementation BoldAbstractModel, BoldUMLXMILink; -{$R *.res} - type {---TBoldRose98FileNameProperty---} @@ -34,7 +35,7 @@ TBoldUMLXMIFileNameProperty = class(TBoldFileNameProperty) {---TBoldRose98FileNameProperty---} function TBoldUMLXMIFileNameProperty.FileFilter: string; begin - Result := Format('%s (*%s)|*%1:s', [XMI_LINKDESC, XMI_LINKEXTENSION]); // do not localize + Result := Format('%s (*%s)|*%1:s', [XMI_LINKDESC, XMI_LINKEXTENSION]); end; function TBoldUMLXMIFileNameProperty.IsValid: boolean; @@ -59,8 +60,8 @@ procedure RegisterComponentsOnPalette; procedure RegisterEditors; begin - RegisterPropertyEditor(TypeInfo(String), TBoldUMLXMILink, 'Filename', TBoldUMLXMIFileNameProperty); // do not localize - RegisterPropertyEditor(TypeInfo(TBoldAbstractModel), TBoldUMLXMILink, 'BoldModel', TBoldComponentPropertyIndicateMissing); // do not localize + RegisterPropertyEditor(TypeInfo(String), TBoldUMLXMILink, 'Filename', TBoldUMLXMIFileNameProperty); + RegisterPropertyEditor(TypeInfo(TBoldAbstractModel), TBoldUMLXMILink, 'BoldModel', TBoldComponentPropertyIndicateMissing); end; procedure Register; diff --git a/Source/UMLModel/ModelLinks/XMI/BoldXMI10Exporter.pas b/Source/UMLModel/ModelLinks/XMI/BoldXMI10Exporter.pas index 3c25468..9b15d42 100644 --- a/Source/UMLModel/ModelLinks/XMI/BoldXMI10Exporter.pas +++ b/Source/UMLModel/ModelLinks/XMI/BoldXMI10Exporter.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldXMI10Exporter; interface @@ -5,16 +8,12 @@ interface uses Variants, BoldContainers, -// BoldUMLModel, BoldLogForm, -// BoldSystem, -// BoldAttributes, + BoldUMLXMILink, -// BoldSystemRT, BoldMOFInterfaces, -// BoldUMLXMILinkSupport, MSXML_TLB, - Sysutils, // for TFileName + Sysutils, BoldStringList, BoldUMLDTDData, Classes; @@ -90,9 +89,9 @@ function TBoldXMI10Exporter.BooleanAsString(Value: IBoldMOFAttribute): string; begin assert(Value.IsBoolean); if Value.AsBoolean then - result := 'true' // do not localize + result := 'true' else - result := 'false'; // do not localize + result := 'false'; end; procedure TBoldXMI10Exporter.CompositeAsElement(Composite: IBoldMOFReference; @@ -290,7 +289,7 @@ function TBoldXMI10Exporter.QualifiedClassName(Obj: IBoldMOFObject): string; function TBoldXMI10Exporter.QualifiedAttributeName( Attribute: IBoldMOFAttribute): string; begin - result := Attribute.QualifiedName; + result := Attribute.QualifiedName; end; procedure TBoldXMI10Exporter.RawExport(RootObj: IBoldMOFObject); @@ -300,14 +299,14 @@ procedure TBoldXMI10Exporter.RawExport(RootObj: IBoldMOFObject); begin aDom := TDOMDocument.Create(nil); aDom.documentElement := aDom.createElement(XMI_NODENAME_ROOT); - aDom.documentElement.setAttribute(XMI_ATTRIBUTENAME_VERSION, '1.0'); // do not localize + aDom.documentElement.setAttribute(XMI_ATTRIBUTENAME_VERSION, '1.0'); ProduceHeader(aDom.documentElement); ContentsFromRoot(RootObj, aDom.documentElement); aStringList := TStringList.Create; - aStringList.Add(''); // do not localize - aStringList.Add(''); // do not localize + aStringList.Add(''); + aStringList.Add(''); aStringList.Add(aDom.DefaultInterface.xml); aStringList.SaveToFile(OwningLink.FileName); @@ -380,7 +379,7 @@ procedure TBoldXMI10Exporter.SvAttributeContents( function TBoldXMI10Exporter.QualifiedReferenceName( Reference: IBoldMOFReference): string; begin - result := Reference.QualifiedName; + result := Reference.QualifiedName; end; procedure TBoldXMI10Exporter.EmbeddedObject(Attribute: IBoldMOFAttribute; @@ -402,4 +401,6 @@ destructor TBoldXMI10Exporter.Destroy; inherited; end; +initialization + end. diff --git a/Source/UMLModel/Plugins/BoldCodePlugins.pas b/Source/UMLModel/Plugins/BoldCodePlugins.pas index dff78d0..930f46e 100644 --- a/Source/UMLModel/Plugins/BoldCodePlugins.pas +++ b/Source/UMLModel/Plugins/BoldCodePlugins.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldCodePlugins; interface @@ -112,7 +115,7 @@ function TUMLCodeGenerator.GetMenuItemName: String; function TUMLCodeGenerator.GetImageResourceName: String; begin - result := 'UMLPluginGenCodeImage'; // do not localize + result := 'UMLPluginGenCodeImage'; end; procedure TUMLCodeGenerator.GenerateCode(Generator: TBoldGenerator); @@ -131,7 +134,7 @@ procedure TUMLIDLGenerator.GenerateCode(Generator: TBoldGenerator); function TUMLIDLGenerator.GetImageResourceName: String; begin - result := 'UMLPluginGenIDLImage'; // do not localize + result := 'UMLPluginGenIDLImage'; end; function TUMLIDLGenerator.GetMenuItemName: String; @@ -144,13 +147,13 @@ function TUMLIDLGenerator.GetMenuItemName: String; procedure TUMLMIDLGenerator.GenerateCode(Generator: TBoldGenerator); begin Generator.GenerateMIDLCode := true; - Generator.UseTypedLists := true; + Generator.UseTypedLists := false; Generator.GenerateComInterfaces; end; function TUMLMIDLGenerator.GetImageResourceName: String; begin - result := 'UMLPluginGenMIDLImage'; // do not localize + result := 'UMLPluginGenMIDLImage'; end; function TUMLMIDLGenerator.GetMenuItemName: String; @@ -169,7 +172,7 @@ procedure TUMLAbstractCodeGenerator.Execute(context: IUMLModelPlugInContext); BoldGuard := TBoldGuard.Create(Validator); BoldModel := Context.GetCurrentModelHandle; - Validator := TBoldUMLModelValidator.Create(Context.GetCurrentModelHandle.EnsuredUMLModel, nil, BoldDefaultValidatorSourceLanguage); + Validator := TBoldUMLModelValidator.Create(Context.GetCurrentModelHandle, nil, BoldDefaultValidatorSourceLanguage); Validator.validate(BoldModel.TypeNameDictionary); if context.GetCurrentModelHandle.EnsuredUMLModel.Validator.HighestSeverity = sError then @@ -191,7 +194,7 @@ procedure TUMLAbstractCodeGenerator.Generate(MoldModel: TMoldModel; BoldGuard: IBoldGuard; begin BoldGuard := TBoldGuard.Create(Generator); - Generator := BoldGeneratorClass.Create(TypenameDictionary); + Generator := TBoldGenerator.Create(TypenameDictionary); Generator.BaseFilePath := Path; Generator.UseTypedLists := true; Generator.MoldModel := MoldModel; @@ -247,7 +250,7 @@ function TUMLGUIDGenerator.GetImageMaskColor: TColor; function TUMLGUIDGenerator.GetImageResourceName: String; begin - result := 'UMLPluginGenGUIDs'; // do not localize + result := 'UMLPluginGenGUIDs'; end; function TUMLGUIDGenerator.GetMenuItemName: String; @@ -274,7 +277,7 @@ procedure TUMLPersistenceInterfaceGenerator.GenerateCode(Generator: TBoldGenerat function TUMLPersistenceInterfaceGenerator.GetImageResourceName: String; begin - result := 'UMLPluginGenPersistenceInterfaceImage'; // do not localize + result := 'UMLPluginGenPersistenceInterfaceImage'; end; function TUMLPersistenceInterfaceGenerator.GetMenuItemName: String; @@ -296,5 +299,3 @@ finalization FreeAndNil(_IDLGenerator); FreeAndNil(_MIDLGenerator); end. - - diff --git a/Source/UMLModel/Plugins/BoldDbPlugins.pas b/Source/UMLModel/Plugins/BoldDbPlugins.pas index bfde0bd..2a44dc3 100644 --- a/Source/UMLModel/Plugins/BoldDbPlugins.pas +++ b/Source/UMLModel/Plugins/BoldDbPlugins.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldDbPlugins; interface @@ -24,7 +27,7 @@ TUMLGenericDBPlugin = class(TUMLPlugInFunction) private function GetPersistenceHandle(BoldModel: TBoldModel): TBoldAbstractPersistenceHandleDB; protected - function GetImageMaskColor: TColor; override; + function GetImageMaskColor: TColor; override; function GetPlugInType: TPlugInType; override; function GetOptions: TBoldUMLPluginOptions; override; function GetValidPersistenceHandle(Context: IUMLModelPlugInContext): TBoldAbstractPersistenceHandleDB; @@ -104,7 +107,7 @@ function TUMLDBGenerator.GetMenuItemName: String; function TUMLDBGenerator.GetImageResourceName: String; begin - result := 'UMLPluginGenDBImage'; // do not localize + result := 'UMLPluginGenDBImage'; end; procedure TUMLDBGenerator.Execute(context: IUMLModelPlugInContext); @@ -146,7 +149,7 @@ procedure TBoldDbDataValidatorPlugin.Execute(context: IUMLModelPlugInContext); function TBoldDbDataValidatorPlugin.GetImageResourceName: String; begin - result := 'UMLPluginDataValidator'; // do not localize + result := 'UMLPluginDataValidator'; end; function TBoldDbDataValidatorPlugin.GetMenuItemName: String; @@ -185,7 +188,7 @@ procedure TBoldUMLDBEvolutorPlugin.Execute(context: IUMLModelPlugInContext); function TBoldUMLDBEvolutorPlugin.GetImageResourceName: String; begin - result := 'UMLPluginDbEvolutor'; // do not localize + result := 'UMLPluginDbEvolutor'; end; function TBoldUMLDBEvolutorPlugin.GetMenuItemName: String; @@ -210,21 +213,35 @@ function TUMLGenericDBPlugin.GetPersistenceHandle(BoldModel: TBoldModel): TBoldA var i: integer; temp: TBoldAbstractPersistenceHandleDB; + List: TList; begin result := nil; - for i := 0 to BoldHandle.BoldHandleList.Count - 1 do - if (BoldHandleList[i] is TBoldAbstractPersistenceHandleDB) then + List := TList.Create; + try + for i := 0 to BoldHandle.BoldHandleList.Count - 1 do + if (BoldHandleList[i] is TBoldAbstractPersistenceHandleDB) then + begin + temp := BoldHandleList[i] as TBoldAbstractPersistenceHandleDB; + if (temp.BoldModel = BoldModel) then + List.Add(Temp); + end; + if List.Count = 0 then + raise Exception.Create('No persistencehandle found. If your persistencehandle is on a datamodule/form that has not been opened, please open the datamodule/form and try again'); + if List.Count = 1 then + Result := TBoldAbstractPersistenceHandleDB(List[0]) + else + for I := 0 to List.Count - 1 do begin - temp := BoldHandleList[i] as TBoldAbstractPersistenceHandleDB; - if (temp.BoldModel = BoldModel) and - (MessageDlg(format('Use Database settings from %s?', [Temp.Name]), mtConfirmation, [mbYes, mbNo], 0) = mrYes) then + Temp := TBoldAbstractPersistenceHandleDB(List[0]); + if (MessageDlg(format('Use Database settings from %s?', [Temp.Name]), mtConfirmation, [mbYes, mbNo], 0) = mrYes) then begin result := temp; break; end; end; - if not assigned(Result) then - raise Exception.Create('No persistencehandle found. If your persistencehandle is on a datamodule/form that has not been opened, please open the datamodule/form and try again'); + finally + List.free; + end; end; function TUMLGenericDBPlugin.GetPlugInType: TPlugInType; @@ -246,7 +263,9 @@ function TUMLGenericDBPlugin.GetValidPersistenceHandle( Result := GetPersistenceHandle(BoldModel); if not assigned(Result) then raise EBold.CreateFmt('%s: No persistence handle to act on', [MenuItemName]); - Validator := TBoldUMLModelValidator.Create(Context.GetCurrentModelHandle.EnsuredUMLModel, Result.SQLDataBaseConfig); + if not assigned(Result.SQLDataBaseConfig) then + raise EBold.CreateFmt('%s: No SQLDataBaseConfig found.', [MenuItemName]); + Validator := TBoldUMLModelValidator.Create(Context.GetCurrentModelHandle, Result.SQLDataBaseConfig); Validator.validate(BoldModel.TypeNameDictionary); if Context.GetCurrentModelHandle.EnsuredUMLModel.Validator.HighestSeverity = sError then @@ -254,6 +273,7 @@ function TUMLGenericDBPlugin.GetValidPersistenceHandle( end; initialization + _DBGenerator := TUMLDBGenerator.Create(true); _dbStructureValidator := TBolddbStructureValidatorPlugin.Create(true); _dbDataValidator := TBolddbDataValidatorPlugin.Create(true); @@ -265,4 +285,3 @@ finalization FreeAndNil(_dbDataValidator); FreeAndNil(_DbEvolutor); end. - diff --git a/Source/UMLModel/Plugins/BoldModelOCLValidatorPlugIn.pas b/Source/UMLModel/Plugins/BoldModelOCLValidatorPlugIn.pas index 03bfff1..97c55a4 100644 --- a/Source/UMLModel/Plugins/BoldModelOCLValidatorPlugIn.pas +++ b/Source/UMLModel/Plugins/BoldModelOCLValidatorPlugIn.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldModelOCLValidatorPlugIn; interface @@ -43,7 +46,6 @@ procedure TUMLOCLValidator.Execute(Context: IUMLModelPlugInContext); var frmValidation: TfrmValidation; begin - // We delegate to the validation form to invoke the validation via the callback method. frmValidation := EnsureValidationForm(context.GetCurrentModelHandle, G_ValidationFormDefaultOwner, nil); frmValidation.ValidationProc := TUMLOCLValidatorCallBack.Validate; frmValidation.Validate; @@ -76,6 +78,7 @@ function TUMLOCLValidator.GetPlugInType: TPlugInType; end; initialization + _UMLOCLValidator := TUMLOCLValidator.Create(true); finalization diff --git a/Source/UMLModel/Plugins/BoldUMLModelEditPlugIn.pas b/Source/UMLModel/Plugins/BoldUMLModelEditPlugIn.pas index 49ad39b..28d572f 100644 --- a/Source/UMLModel/Plugins/BoldUMLModelEditPlugIn.pas +++ b/Source/UMLModel/Plugins/BoldUMLModelEditPlugIn.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldUMLModelEditPlugIn; interface @@ -58,8 +61,6 @@ TUMLPlugIn = class property PluginClassName: string read fPlugInClassName; procedure GuardedExecute(Context: IUMLModelPlugInContext); procedure UnGuardedExecute(Context: IUMLModelPlugInContext); - - //property Action: TAction read FAction write FAction; end; TUMLPlugInMenuItem = class(TMenuItem) @@ -122,4 +123,6 @@ procedure TUMLPlugIn.UnGuardedExecute(Context: IUMLModelPlugInContext); OnExecute(Context); end; +initialization + end. diff --git a/Source/UMLModel/Plugins/BoldUMLPluginCallBacks.pas b/Source/UMLModel/Plugins/BoldUMLPluginCallBacks.pas index 5860d49..6506e92 100644 --- a/Source/UMLModel/Plugins/BoldUMLPluginCallBacks.pas +++ b/Source/UMLModel/Plugins/BoldUMLPluginCallBacks.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldUMLPluginCallBacks; interface @@ -21,7 +24,7 @@ TUMLOCLValidatorCallBack = class TBoldUMLModelValidatorCallBack = class public class procedure Validate(Modelhandle: TBoldModel); - end; + end; implementation @@ -40,7 +43,7 @@ class procedure TUMLOCLValidatorCallBack.Validate(Modelhandle: TBoldModel); begin OCLValidityChecker := TOCLValidityChecker.Create(Modelhandle.TypeNameDictionary); try - OCLValidityChecker.ValidateModel(Modelhandle.EnsuredUMLModel); + OCLValidityChecker.ValidateModel(Modelhandle); finally OCLValidityChecker.Free; end; @@ -52,7 +55,7 @@ class procedure TBoldUMLModelValidatorCallBack.Validate(Modelhandle: TBoldModel) var ModelValidator: TBoldUMLModelValidator; begin - ModelValidator := TBoldUMLModelValidator.Create(Modelhandle.EnsuredUMLModel, SQLDataBaseConfigforModel(Modelhandle)); + ModelValidator := TBoldUMLModelValidator.Create(Modelhandle, SQLDataBaseConfigforModel(Modelhandle)); try ModelValidator.Validate(Modelhandle.TypeNameDictionary); finally @@ -60,4 +63,6 @@ class procedure TBoldUMLModelValidatorCallBack.Validate(Modelhandle: TBoldModel) end; end; +initialization + end. diff --git a/Source/UMLModel/Plugins/BoldUMLPlugins.pas b/Source/UMLModel/Plugins/BoldUMLPlugins.pas index a6d6b53..8bf9c39 100644 --- a/Source/UMLModel/Plugins/BoldUMLPlugins.pas +++ b/Source/UMLModel/Plugins/BoldUMLPlugins.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldUMLPlugins; interface @@ -68,7 +71,7 @@ TUMLLinkExporter = class(TUMLLinkImporterExporter) function GetPlugInType: TPlugInType; override; function GetImageResourceName: String; override; function GetImageMaskColor: TColor; override; - function GetOptions: TBoldUMLPluginOptions; override; + function GetOptions: TBoldUMLPluginOptions; override; public procedure Execute(context: IUMLModelPlugInContext); override; end; @@ -85,7 +88,6 @@ TUMLModelUpdaterPlugIn = class(TUMLPlugInFunction) end; implementation -{$R BoldUMLPlugins.res} uses SysUtils, @@ -106,7 +108,6 @@ implementation var _LinkExporter: TUMLLinkExporter; _LinkImporter: TUMLLinkImporter; -// _ModelUpdater: TUMLModelUpdaterPlugIn; { TUMLPlugInFunction } @@ -169,7 +170,7 @@ function TUMLLinkImporter.GetPlugInType: TPlugInType; function TUMLLinkImporter.GetImageResourceName: String; begin - result := 'UMLPluginImportImage'; // do not localize + result := 'UMLPluginImportImage'; end; function TUMLLinkImporter.GetImageMaskColor: TColor; @@ -214,7 +215,7 @@ function TUMLLinkExporter.GetPlugInType: TPlugInType; function TUMLLinkExporter.GetImageResourceName: String; begin - result := 'UMLPluginExportImage'; // do not localize + result := 'UMLPluginExportImage'; end; function TUMLLinkExporter.GetImageMaskColor: TColor; @@ -279,7 +280,7 @@ function TUMLModelUpdaterPlugIn.GetImageMaskColor: TColor; function TUMLModelUpdaterPlugIn.GetImageResourceName: String; begin - result := 'UMLPluginModelUpdater'; // do not localize + result := 'UMLPluginModelUpdater'; end; function TUMLModelUpdaterPlugIn.GetMenuItemName: String; @@ -293,13 +294,12 @@ function TUMLModelUpdaterPlugIn.GetPlugInType: TPlugInType; end; initialization + _LinkExporter := TUMLLinkExporter.Create(true); _LinkImporter := TUMLLinkImporter.Create(true); -// _ModelUpdater := TUMLModelUpdaterPlugIn.Create(true); finalization FreeAndNil(_LinkExporter); FreeAndNil(_LinkImporter); -// FreeAndNil(_ModelUpdater); end. diff --git a/Source/ValueSpace/Condition/BoldCondition.pas b/Source/ValueSpace/Condition/BoldCondition.pas index f81ad76..a5e6db1 100644 --- a/Source/ValueSpace/Condition/BoldCondition.pas +++ b/Source/ValueSpace/Condition/BoldCondition.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldCondition; interface @@ -60,6 +63,17 @@ TBoldSQLCondition = class(TBoldConditionWithClass) property JoinInheritedTables: Boolean read fJoinInheritedTables write fJoinInheritedTables; end; + {---TBoldRawSQLCondition---} + TBoldRawSQLCondition = class(TBoldConditionWithClass) + private + fSQL: string; + fParams: TParams; + public + function GetStreamName: string; override; + property Params: TParams read fParams write fParams; + property SQL: string read fSQL write fSQL; + end; + {---TBoldTimestampCondition---} TBoldTimestampCondition = class(TBoldConditionWithClass) private @@ -105,8 +119,8 @@ implementation uses classes, - MSXML_TLB, - BoldDefaultStreamNames; + {$IFDEF OXML}OXmlPDOM{$ELSE}MSXML_TLB{$ENDIF}, + BoldDefaultStreamNames; const BoldNodeName_MaxAnswers = 'MaxAnswers'; @@ -130,6 +144,10 @@ implementation BoldNodeName_MemberIds = 'MemberIds'; type + {$IFNDEF BOLD_DELPHI17_OR_LATER} + TValueBuffer = Pointer; + {$ENDIF} + { TBoldXMLSQLConditionStreamer} TBoldXMLSQLConditionStreamer = class(TBoldXMLConditionWithClassStreamer) protected @@ -162,6 +180,7 @@ TBoldXMLChangePointConditionStreamer = class(TBoldXMLConditionStreamer) const SQLConditionName = 'SQLCondition'; + RawSQLConditionName = 'RawSQLCondition'; ClassConditionName = 'ClassCondition'; TimestampConditionName = 'TimestampCondition'; OclConditionName = 'OclCondition'; @@ -193,6 +212,13 @@ function TBoldSQLCondition.GetStreamName: string; result := SQLConditionName; end; +{ TBoldRawSQLCondition } + +function TBoldRawSQLCondition.GetStreamName: string; +begin + Result := RawSQLConditionName; +end; + { TBoldTimestampCondition } function TBoldTimestampCondition.GetStreamName: string; @@ -278,13 +304,19 @@ function TBoldXMLSQLConditionStreamer.GetStreamName: string; procedure TBoldXMLSQLConditionStreamer.ReadObject(Obj: TObject; Node: TBoldXMLNode); var anSQLCond: TBoldSQLCondition; + {$IFDEF OXML} + aNodeEnumerator: TXMLResNodeListEnumerator; + aNodeList: IXMLNodeList; + aNode: PXMLNode; + {$ELSE} aNodeList: IXMLDOMNodeList; aNode: IXMLDOMNode; + {$ENDIF} aSubNode: TBoldXMLNode; ParamsNode: TBoldXMLNode; DataNode: TBoldXMLNode; aParam: TParam; - Buf: string; + Buf: TBoldAnsiString; begin inherited; anSQLCond := Obj as TBoldSQLCondition; @@ -296,6 +328,32 @@ procedure TBoldXMLSQLConditionStreamer.ReadObject(Obj: TObject; Node: TBoldXMLNo if not ParamsNode.IsNull then begin anSQLCond.Params := TParams.Create; + {$IFDEF OXML} + if Node.XMLDomElement.GetElementsByTagName(BoldNodeName_Param, aNodeList) then + begin + aNodeEnumerator := aNodeList.GetEnumerator; + try + while aNodeEnumerator.MoveNext do begin + aNode := aNodeEnumerator.Current; + aSubNode := Node.MakeNodeForElement(aNode); + aParam := anSQLCond.Params.Add as TParam; + aParam.Name := aSubNode.ReadSubNodeString(BoldNodeName_Name); + aParam.DataType := TFieldType(aSubNode.ReadSubNodeInteger(BoldNodeName_DataType)); + aParam.ParamType := TParamType(aSubNode.ReadSubNodeInteger(BoldNodeName_ParamType)); + DataNode := aSubNode.GetSubNode(BoldNodeName_Data); + if Assigned(DataNode) then + begin + Buf := DataNode.ReadData; + aParam.SetData(TValueBuffer(PAnsiChar(Buf))); + end; + DataNode.Free; + aSubNode.Free; + end; + finally + aNodeEnumerator.Free; + end; + end; + {$ELSE} aNodeList := Node.XMLDomElement.getElementsByTagName(BoldNodeName_Param); aNode := aNodeList.nextNode; @@ -311,12 +369,13 @@ procedure TBoldXMLSQLConditionStreamer.ReadObject(Obj: TObject; Node: TBoldXMLNo if assigned(DataNode) then begin Buf := DataNode.ReadData; - aParam.SetData(PChar(Buf)); + aParam.SetData(PAnsiChar(Buf)); end; DataNode.Free; aSubNode.Free; aNode := aNodeList.nextNode; end; + {$ENDIF} end else anSQLCond.Params := nil; @@ -326,7 +385,7 @@ procedure TBoldXMLSQLConditionStreamer.ReadObject(Obj: TObject; Node: TBoldXMLNo procedure TBoldXMLSQLConditionStreamer.WriteObject(Obj: TBoldInterfacedObject; Node: TBoldXMLNode); var anSQLCond: TBoldSQLCondition; - Buf: string; + Buf: TBoldAnsiString; i: Integer; SubNode: TBoldXMLNode; ParamsNode: TBoldXMLNode; @@ -344,7 +403,7 @@ procedure TBoldXMLSQLConditionStreamer.WriteObject(Obj: TBoldInterfacedObject; N begin SubNode := ParamsNode.NewSubNode(BoldNodeName_Param); SetLength(Buf, anSQLCond.Params[i].GetDataSize); - anSQLCond.Params[i].GetData(PChar(Buf)); + anSQLCond.Params[i].GetData(TValueBuffer(PAnsiChar(Buf))); SubNode.WriteSubNodeString(BoldNodeName_Name, anSQLCond.Params[i].Name); SubNode.WriteSubNodeInteger(BoldNodeName_DataType, Integer(anSQLCond.Params[i].DataType)); SubNode.WriteSubNodeInteger(BoldNodeName_ParamType, Integer(anSQLCond.Params[i].ParamType)); @@ -417,6 +476,7 @@ procedure TBoldXMLChangePointConditionStreamer.WriteObject(Obj: TBoldInterfacedO Node.WriteSubNodeObject(BoldNodeName_MemberIds, BOLDMEMBERIDLISTNAME, aCond.MemberIdList); end; + { TBoldCondition } constructor TBoldCondition.create; diff --git a/Source/ValueSpace/ExternalEvents/BoldObjectSpaceExternalEvents.pas b/Source/ValueSpace/ExternalEvents/BoldObjectSpaceExternalEvents.pas index 75099aa..9f8eddf 100644 --- a/Source/ValueSpace/ExternalEvents/BoldObjectSpaceExternalEvents.pas +++ b/Source/ValueSpace/ExternalEvents/BoldObjectSpaceExternalEvents.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldObjectSpaceExternalEvents; interface @@ -11,18 +14,25 @@ interface TBoldExternalEvent = String; TBoldObjectSpaceExternalEvent = class; - TBoldObjectSpaceSubscriptionType = (bsClassChanged, bsEmbeddedStateOfObjectChanged, - bsNonEmbeddedStateOfObjectChanged, bsGotLocks, bsLockLost{, bsDBLock}, bsObjectDeleted); + TBoldObjectSpaceSubscriptionType = + (bsClassChanged, + bsEmbeddedStateOfObjectChanged, + bsNonEmbeddedStateOfObjectChanged, + bsGotLocks, + bsLockLost{, bsDBLock}, + bsObjectCreated, + bsObjectDeleted, + bsMemberChanged); TBoldObjectSpaceExternalEvent = class private - class procedure GetID(Event: TBoldExternalEvent; ObjectID: TBoldDefaultID); - class function GetParameter(Event: tBoldExternalEvent): String; - class function GetEventType(Event: TBoldExternalEvent): TBoldObjectSpaceSubscriptionType; + class procedure GetID(const Event: TBoldExternalEvent; ObjectID: TBoldDefaultID; AClassName: string = ''); + class function GetParameter(const Event: TBoldExternalEvent): String; + class function GetEventType(const Event: TBoldExternalEvent): TBoldObjectSpaceSubscriptionType; public - class function EncodeExternalEvent(SubscriptionType: TBoldObjectSpaceSubscriptionType; ClassName,MemberName, LockName: string; + class function EncodeExternalEvent(SubscriptionType: TBoldObjectSpaceSubscriptionType; const ClassName,MemberName, LockName: string; ObjectID: TBoldObjectID): String; - class function DecodeExternalEvent(Event: TBoldExternalEvent; + class function DecodeExternalEvent(const Event: TBoldExternalEvent; var Classname, MemberName, LockName: String; ObjectID: TBoldDefaultID): TBoldObjectSpaceSubscriptionType; end; @@ -32,19 +42,21 @@ implementation uses SysUtils, BoldDefs, - ValueSpaceConst; + BoldRev; const SUBSCRIPTION_DELIMITER_CHAR = ':'; + CLASS_MEMBER_SEPARATOR = '.'; EXTERNAL_EVENT_CLASSCHANGED = 'C'; + EXTERNAL_EVENT_MEMBERCHANGED = 'M'; EXTERNAL_EVENT_EMBEDDEDSTATEOFOBJECTCHANGED = 'E'; EXTERNAL_EVENT_NONEMBEDDEDSTATEOFOBJECTCHANGED = 'I'; + EXTERNAL_EVENT_OBJECTCREATED = 'N'; EXTERNAL_EVENT_EMBEDDEDSTATE_OBJECTDELETED = 'D'; EXTERNAL_EVENT_LOCKLOST = 'L'; EXTERNAL_EVENT_GOTLOCK = 'GotLocks'; -// EXTERNAL_EVENT_DBLOCK = 'DBLock'; -class function TBoldObjectSpaceExternalEvent.GetEventType(Event: TBoldExternalEvent): TBoldObjectSpaceSubscriptionType; +class function TBoldObjectSpaceExternalEvent.GetEventType(const Event: TBoldExternalEvent): TBoldObjectSpaceSubscriptionType; var ExternalEvent: char; begin @@ -53,6 +65,7 @@ class function TBoldObjectSpaceExternalEvent.GetEventType(Event: TBoldExternalEv ExternalEvent := Event[1]; case ExternalEvent of EXTERNAL_EVENT_CLASSCHANGED: Result := bsClassChanged; + EXTERNAL_EVENT_MEMBERCHANGED: Result := bsMemberChanged; EXTERNAL_EVENT_EMBEDDEDSTATEOFOBJECTCHANGED: begin if GetParameter(Event) = EXTERNAL_EVENT_EMBEDDEDSTATE_OBJECTDELETED then @@ -61,18 +74,19 @@ class function TBoldObjectSpaceExternalEvent.GetEventType(Event: TBoldExternalEv Result := bsEmbeddedStateOfObjectChanged; end; EXTERNAL_EVENT_NONEMBEDDEDSTATEOFOBJECTCHANGED: Result := bsNonEmbeddedStateOfObjectChanged; + EXTERNAL_EVENT_OBJECTCREATED: Result := bsObjectCreated; EXTERNAL_EVENT_LOCKLOST: Result := bsLockLost; else if Pos(EXTERNAL_EVENT_GOTLOCK, Event) = 1 then Result := bsGotLocks -// else if Pos(EXTERNAL_EVENT_DBLock, Event) = 1 then -// Result := bsDBLock + else - raise EBold.CreateFmt(sInvalidEvent, [Event]); + raise EBold.CreateFmt('Invalid event: %s', [Event]); end end; -class procedure TBoldObjectSpaceExternalEvent.GetID(Event: TBoldExternalEvent; ObjectID: TBoldDefaultID); +class procedure TBoldObjectSpaceExternalEvent.GetID(const Event: TBoldExternalEvent; + ObjectID: TBoldDefaultID; AClassName: string); var p, IDAsInt: Integer; IDAsString: String; @@ -80,41 +94,46 @@ class procedure TBoldObjectSpaceExternalEvent.GetID(Event: TBoldExternalEvent; O if assigned(ObjectId) then begin case GetEventType(Event) of - bsObjectdeleted, bsEmbeddedStateOfObjectChanged: + bsObjectDeleted, bsEmbeddedStateOfObjectChanged, bsObjectCreated, bsNonEmbeddedStateOfObjectChanged, bsMemberChanged: begin - p := pos(PROPAGATOR_PARAMETER_DELIMITER_CHAR, Event); - if p <> 0 then - Delete(Event, p, maxint); - IDAsString := Copy(Event, 3, MaxInt); + IDAsString := Event; + Delete(IDAsString, 1, Pos(SUBSCRIPTION_DELIMITER_CHAR, IDAsString)); + Delete(IDAsString, 1, Pos(SUBSCRIPTION_DELIMITER_CHAR, IDAsString)); + Delete(IDAsString, Pos(PROPAGATOR_PARAMETER_DELIMITER_CHAR,IDAsString), MaxInt); end; - bsNonEmbeddedStateOfObjectChanged: - begin - Delete(Event, 1, Pos(SUBSCRIPTION_DELIMITER_CHAR, Event)); - Delete(Event, 1, Pos(SUBSCRIPTION_DELIMITER_CHAR, Event)); - IDAsString := Event; - end; end; try IDAsInt := StrToInt(IDAsString); ObjectID.AsInteger := IDAsInt; except - raise EBold.CreateFmt(sInvalidID, [IDAsString]); + raise EBold.CreateFmt('Invalid ID, %s is not an valid integer.', [IDAsString]); end; end; end; class function TBoldObjectSpaceExternalEvent.EncodeExternalEvent(SubscriptionType: TBoldObjectSpaceSubscriptionType; - ClassName,MemberName, LockName: string; ObjectID: TBoldObjectID): String; + const ClassName,MemberName, LockName: string; ObjectID: TBoldObjectID): String; begin case SubscriptionType of bsClassChanged: Result := EXTERNAL_EVENT_CLASSCHANGED + SUBSCRIPTION_DELIMITER_CHAR + ClassName; + bsMemberChanged: Result := EXTERNAL_EVENT_MEMBERCHANGED + + SUBSCRIPTION_DELIMITER_CHAR + + ClassName + + CLASS_MEMBER_SEPARATOR + + MemberName + + SUBSCRIPTION_DELIMITER_CHAR + + ObjectID.AsString; bsEmbeddedStateOfObjectChanged: Result := EXTERNAL_EVENT_EMBEDDEDSTATEOFOBJECTCHANGED + + SUBSCRIPTION_DELIMITER_CHAR + + ClassName + SUBSCRIPTION_DELIMITER_CHAR + ObjectID.AsString; bsNonEmbeddedStateOfObjectChanged: Result := EXTERNAL_EVENT_NONEMBEDDEDSTATEOFOBJECTCHANGED + SUBSCRIPTION_DELIMITER_CHAR + + ClassName + + CLASS_MEMBER_SEPARATOR + MemberName + SUBSCRIPTION_DELIMITER_CHAR + ObjectID.AsString; @@ -122,33 +141,62 @@ class function TBoldObjectSpaceExternalEvent.EncodeExternalEvent(SubscriptionTyp SUBSCRIPTION_DELIMITER_CHAR + LockName; bsGotLocks: Result := EXTERNAL_EVENT_GOTLOCK; + bsObjectCreated: Result := EXTERNAL_EVENT_OBJECTCREATED + + SUBSCRIPTION_DELIMITER_CHAR + + ClassName + + SUBSCRIPTION_DELIMITER_CHAR + + ObjectID.AsString; + bsObjectDeleted: Result := EXTERNAL_EVENT_EMBEDDEDSTATEOFOBJECTCHANGED + + SUBSCRIPTION_DELIMITER_CHAR + + ClassName + SUBSCRIPTION_DELIMITER_CHAR + ObjectID.AsString + PROPAGATOR_PARAMETER_DELIMITER_CHAR + EXTERNAL_EVENT_EMBEDDEDSTATE_OBJECTDELETED -// bsDBLock: Result := EXTERNAL_EVENT_DBLOCK; else Result := ''; end; end; -class function TBoldObjectSpaceExternalEvent.DecodeExternalEvent(Event: TBoldExternalEvent; +class function TBoldObjectSpaceExternalEvent.DecodeExternalEvent(const Event: TBoldExternalEvent; var Classname, MemberName, LockName: String; ObjectID: TBoldDefaultID): TBoldObjectSpaceSubscriptionType; +var + s: string; + i: integer; begin Result := GetEventType(Event); - case Result of bsClassChanged: ClassName := Copy(Event, Length(EXTERNAL_EVENT_CLASSCHANGED + SUBSCRIPTION_DELIMITER_CHAR) + 1, MaxInt); - bsObjectdeleted, bsEmbeddedStateOfObjectChanged: - begin - GetID(Event, ObjectID); - end; + bsObjectCreated: + begin + ClassName := Copy(Event, Length(EXTERNAL_EVENT_OBJECTCREATED + SUBSCRIPTION_DELIMITER_CHAR) + 1, MaxInt); + ClassName := Copy(ClassName, 1, Pos(SUBSCRIPTION_DELIMITER_CHAR,ClassName) - 1); + GetID(Event, ObjectID, ClassName); + end; + bsMemberChanged: + begin + s := Copy(Event, pos(SUBSCRIPTION_DELIMITER_CHAR, Event) + 1, maxint); + i := Pos(CLASS_MEMBER_SEPARATOR, s); + ClassName := Copy(s, 1, i-1); + MemberName := Copy(s, i+1, Pos(SUBSCRIPTION_DELIMITER_CHAR, s)-i-1); + s := Copy(s, Pos(SUBSCRIPTION_DELIMITER_CHAR, s) + 1, MaxInt); + ObjectID.AsInteger := StrToInt(s); + end; + bsObjectDeleted, bsEmbeddedStateOfObjectChanged: + begin + i := pos(SUBSCRIPTION_DELIMITER_CHAR, Event) + 1; + ClassName := Copy(Event, i, Pos(SUBSCRIPTION_DELIMITER_CHAR, Copy(Event, i, maxint)) - 1); + GetID(Event, ObjectID, ClassName); + end; bsNonEmbeddedStateOfObjectChanged: begin - MemberName := Copy(Event, pos(SUBSCRIPTION_DELIMITER_CHAR, Event) + 1, Pos(SUBSCRIPTION_DELIMITER_CHAR, Copy(Event, pos(SUBSCRIPTION_DELIMITER_CHAR, Event) + 1, maxint)) - 1); - GetID(Event, ObjectID); + i := pos(SUBSCRIPTION_DELIMITER_CHAR, Event) + 1; + s := Copy(Event, i, Pos(SUBSCRIPTION_DELIMITER_CHAR, Copy(Event, i, maxint)) - 1); + ClassName := Copy(s, 1, Pos(CLASS_MEMBER_SEPARATOR, s) - 1); + MemberName := Copy(s, Pos(CLASS_MEMBER_SEPARATOR, s) +1, maxint); + GetID(Event, ObjectID, ClassName); end; bsLockLost: LockName := Copy(Event, Length(EXTERNAL_EVENT_LOCKLOST + SUBSCRIPTION_DELIMITER_CHAR) + 1, MaxInt); bsGotLocks{, bsDBLock}: ; @@ -156,7 +204,7 @@ class function TBoldObjectSpaceExternalEvent.DecodeExternalEvent(Event: TBoldExt end; -class function TBoldObjectSpaceExternalEvent.GetParameter(Event: tBoldExternalEvent): String; +class function TBoldObjectSpaceExternalEvent.GetParameter(const Event: TBoldExternalEvent): String; var p: integer; begin @@ -167,4 +215,7 @@ class function TBoldObjectSpaceExternalEvent.GetParameter(Event: tBoldExternalEv result := ''; end; +initialization + end. + diff --git a/Source/ValueSpace/Id/BoldDefaultId.pas b/Source/ValueSpace/Id/BoldDefaultId.pas index 3799958..dac96f8 100644 --- a/Source/ValueSpace/Id/BoldDefaultId.pas +++ b/Source/ValueSpace/Id/BoldDefaultId.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldDefaultId; interface @@ -15,8 +18,8 @@ TBoldTimestampedDefaultId = class; TBoldDefaultID = class(TBoldExternalObjectID) protected fDBValue: integer; - procedure SetAsInteger(NewValue: integer); - function GetAsInteger: Integer; + procedure SetAsInteger(NewValue: integer); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetAsInteger: Integer; {$IFDEF BOLD_INLINE} inline; {$ENDIF} function GetAsString: string; override; function GetHash: cardinal; override; function GetStreamName: string; override; @@ -35,8 +38,10 @@ TBoldTimestampedDefaultId = class(TBoldDefaultId) protected function GetStreamName: string; override; function GetTimeStamp: TBoldTimeStampType; override; + function GetHash: cardinal; override; + function GetIsEqual(MatchID: TBoldObjectID): Boolean; override; public - constructor createWithTimeAndClassId(TimeStamp: TBoldTimeStampType; TopSortedIndex: integer; Exact: Boolean); + constructor CreateWithTimeAndClassId(TimeStamp: TBoldTimeStampType; TopSortedIndex: integer; Exact: Boolean); function CloneWithClassId(TopSortedIndex: integer; Exact: Boolean): TBoldObjectId; override; property TimeStamp: TBoldTimeStampType read GetTimeStamp write fTimeStamp; end; @@ -88,16 +93,22 @@ function TBoldDefaultID.GetAsInteger: Integer; Result := FDbValue; end; -Function TBolddefaultID.GetIsEqual(MatchID: TBoldObjectID): Boolean; +Function TBoldDefaultID.GetIsEqual(MatchID: TBoldObjectID): Boolean; begin - result := assigned(MatchId) and ((MatchID.ClassType = TBoldDefaultId ) or (MatchID.ClassType = TBoldTimestampedDefaultId )) and - (fdbValue = TBoldDefaultId(MatchId).fDbValue) and - (MatchId.TimeStamp = TimeStamp); + if not assigned(MatchId) then + Result := false + else if MatchID.ClassType = TBoldDefaultId then + Result := fdbValue = TBoldDefaultId(MatchId).fDbValue + else if MatchID.ClassType = TBoldTimestampedDefaultId then + Result := (fdbValue = TBoldTimestampedDefaultId(MatchId).fDbValue) and + (MatchId.TimeStamp = BOLDMAXTIMESTAMP) + else + Result := false; end; function TBoldDefaultID.GetHash: cardinal; begin - result := cardinal(fDBValue) + cardinal(Timestamp); + result := cardinal(fDBValue) + cardinal(BOLDMAXTIMESTAMP); end; procedure TBoldDefaultId.SetAsInteger(NewValue: integer); @@ -124,12 +135,35 @@ function TBoldTimestampedDefaultId.CloneWithClassId(TopSortedIndex: integer; Exa (result as TBoldTimestampedDefaultId).fTimeStamp := fTimeStamp; end; -constructor TBoldTimestampedDefaultId.createWithTimeAndClassId(TimeStamp: TBoldTimeStampType; TopSortedIndex: integer; Exact: Boolean); +constructor TBoldTimestampedDefaultId.CreateWithTimeAndClassId(TimeStamp: TBoldTimeStampType; TopSortedIndex: integer; Exact: Boolean); begin inherited CreateWithClassId(TopSortedIndex, Exact); fTimeStamp := TimeStamp; end; +function TBoldTimestampedDefaultId.GetHash: cardinal; +begin + result := cardinal(fDBValue) + cardinal(fTimestamp); +end; + +function TBoldTimestampedDefaultId.GetIsEqual(MatchID: TBoldObjectID): Boolean; +var + TimestampedMatchId: TBoldTimestampedDefaultId; +begin + if not assigned(MatchId) then + Result := false + else if MatchID.ClassType = TBoldDefaultId then + Result := (fdbValue = TBoldDefaultId(MatchId).fDbValue) and (fTimeStamp = BOLDMAXTIMESTAMP) + else if MatchID.ClassType = TBoldTimestampedDefaultId then + begin + TimestampedMatchId := TBoldTimestampedDefaultId(MatchId); + Result := (fdbValue = TimestampedMatchId.fDbValue) and + (TimestampedMatchId.fTimeStamp = fTimeStamp) + end + else + Result := false; +end; + function TBoldTimestampedDefaultId.GetStreamName: string; begin result := BOLDTIMESTAMPEDDEFAULTIDNAME; @@ -207,6 +241,7 @@ procedure TBoldXMLTimestampedDefaultIdStreamer.WriteObject(Obj: TBoldInterfacedO Node.WriteSubNodeInteger(BoldNodeName_Timestamp, (Obj as TBoldTimestampedDefaultId).TimeStamp); end; + function TBoldDefaultID.CloneWithTimeStamp(Time: TBoldTimeStampType): TBoldDefaultId; begin result := CloneWithClassIdAndTimeStamp(TopSortedIndex, TopSortedIndexExact, time); diff --git a/Source/ValueSpace/Id/BoldGlobalId.pas b/Source/ValueSpace/Id/BoldGlobalId.pas index 75661c2..f953183 100644 --- a/Source/ValueSpace/Id/BoldGlobalId.pas +++ b/Source/ValueSpace/Id/BoldGlobalId.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldGlobalId; interface @@ -5,7 +8,7 @@ interface uses BoldId, BoldStreams; - + const BOLDGLOBALIDNAME = 'BoldGlobalId'; @@ -29,6 +32,7 @@ TBoldGlobalId = class(TBoldObjectId) property AsString: String read GetAsString; end; + implementation uses diff --git a/Source/ValueSpace/Id/BoldId.pas b/Source/ValueSpace/Id/BoldId.pas index e42b35c..ca42c70 100644 --- a/Source/ValueSpace/Id/BoldId.pas +++ b/Source/ValueSpace/Id/BoldId.pas @@ -1,14 +1,15 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldId; interface uses - Classes, BoldDefs, BoldBase, BoldStreams, BoldIndex, - BoldHashIndexes, BoldXMLStreaming, BoldIndexableList; @@ -29,6 +30,10 @@ TBoldIDTranslationList = class; TBoldID = class (TBoldNonRefCountedObject, IBoldStreamable) protected function GetStreamName: string; virtual; abstract; + function GetAsString: string; virtual; abstract; + function GetDebugInfo: string; override; + public + property AsString: string read GetAsString; end; {---TBoldMemberID---} @@ -37,8 +42,10 @@ TBoldMemberID = class(TBoldID) fMemberIndex: Integer; protected function GetStreamName: string; override; + function GetAsString: string; override; public - constructor create(MemberIndex: Integer); + constructor Create(MemberIndex: Integer); + function Clone: TBoldMemberID; property MemberIndex: integer read fMemberIndex; end; @@ -48,32 +55,32 @@ TBoldSubMemberID = class(TBoldmemberID) fOwnsPartof: Boolean; fPartOf: TBoldMemberID; public - constructor Create(partOf: TBoldMemberID; OwnspartOf: Boolean; IndexInMemberList: integer); - destructor Destroy; override; + constructor create(partOf: TBoldMemberID; OwnspartOf: Boolean; IndexInMemberList: integer); + destructor destroy; override; end; {---TBoldObjectId---} TBoldObjectId = class(TBoldID) private FClassId: integer; - function getTopSortedIndex: integer; - function GetTopSortedIndexExact: Boolean; - procedure SetClassIdData(TopSortedIndex: integer; Exact: boolean); + function GetTopSortedIndex: integer; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetTopSortedIndexExact: Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure SetClassIdData(TopSortedIndex: integer; Exact: boolean); {$IFDEF BOLD_INLINE} inline; {$ENDIF} protected - function GetAsString: string; virtual; abstract; function GetIsStorable: Boolean; virtual; abstract; function GetHash: Cardinal; virtual; abstract; Function GetIsEqual(MatchID: TBoldObjectID): Boolean; virtual; abstract; function GetTimeStamp: TBoldTimeStampType; virtual; + function GetNonExisting: Boolean; virtual; public constructor CreateWithClassID(TopSortedIndex: integer; Exact: Boolean); virtual; function CloneWithClassId(TopSortedIndex: integer; Exact: Boolean): TBoldObjectid; virtual; abstract; - function Clone: TBoldObjectId; + function Clone: TBoldObjectId; {$IFDEF BOLD_INLINE} inline; {$ENDIF} property TopSortedIndex: integer read getTopSortedIndex; property TopSortedIndexExact: Boolean read GetTopSortedIndexExact; - property AsString: string read GetAsString; property IsStorable: Boolean read GetIsStorable; property IsEqual[MatchId: TBoldObjectId]: Boolean read GetIsEqual; + property NonExisting: Boolean read GetNonExisting; property Hash: Cardinal read GetHash; property TimeStamp: TBoldTimeStampType read GetTimeStamp; end; @@ -88,7 +95,6 @@ TBoldInternalObjectId = class(TBoldObjectId) function GetIsStorable: Boolean; override; function GetIsEqual(MatchID: TBoldObjectID): Boolean; override; function GetStreamName: string; override; - public constructor CreateWithClassID(TopSortedIndex: integer; Exact: Boolean); override; constructor CreateWithClassIDandInternalId(InternalIdentifier: integer; TopSortedIndex: integer; Exact: Boolean); @@ -101,8 +107,24 @@ TBoldExternalObjectID = class(TBoldObjectId) function GetIsStorable: Boolean; override; end; + TBoldNonExistingObjectId = class(TBoldObjectId) + protected + function GetStreamName: string; override; + function GetAsString: string; override; + function GetNonExisting: Boolean; override; + function GetIsStorable: Boolean; override; + function GetHash: Cardinal; override; + function GetIsEqual(MatchID: TBoldObjectID): Boolean; override; + public + function CloneWithClassId(TopSortedIndex: integer; Exact: Boolean): TBoldObjectid; override; + end; + {---TBoldIdList---} - TBoldIdList = class(TBoldIndexableList); + TBoldIdList = class(TBoldIndexableList) + public + function CommaSeparatedIdList: String; + property AsString: string read CommaSeparatedIdList; + end; {---TBoldObjectIdHashIndex---} TBoldObjectIdHashIndex = class(TBoldHashIndex) @@ -111,75 +133,88 @@ TBoldObjectIdHashIndex = class(TBoldHashIndex) function HashItem(Item: TObject): Cardinal; override; function Match(const Key; Item:TObject):Boolean; override; function Hash(const Key): Cardinal; override; - function FindById(boldObjectId:TboldObjectId): TObject; + function FindById(BoldObjectId: TBoldObjectId): TObject; {$IFDEF BOLD_INLINE} inline; {$ENDIF} end; {---TBoldObjectIdList---} TBoldObjectIdList = class(TBoldIdList, IBoldStreamable) private + class var IX_ObjectID: integer; function GetObjectIDIndex: TBoldObjectIDHashIndex; + function GetHasInexactIds: boolean; + function GetHasNonExistingIds: boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} protected - function GetCount: integer; + function GetCount: integer; {$IFDEF BOLD_INLINE} inline; {$ENDIF} function GetIDByID(ObjectID: TBoldObjectId): TBoldObjectId; function GetIndexByID(ObjectID: TBoldObjectId): Integer; - function GetObjectId(index: Integer): TBoldObjectId; - function GetIdInList(ObjectID: TBoldObjectId): Boolean; - function GetStreamName: string; + function GetObjectId(index: Integer): TBoldObjectId; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetIdInList(ObjectID: TBoldObjectId): Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetStreamName: string; {$IFDEF BOLD_INLINE} inline; {$ENDIF} property ObjectIDIndex: TBoldObjectIDHashIndex read GetObjectIDIndex; public constructor Create; - procedure Add(ObjectID: TBoldObjectId); - procedure AddIfNotInList(ObjectID: TBoldObjectId); - procedure AddList(ObjectIdList: TBoldObjectIdList); - procedure Insert(Index: integer; ObjectID: TBoldObjectId); + procedure Add(ObjectID: TBoldObjectId); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure AddAndAdopt(ObjectID: TBoldObjectId); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure AddIfNotInList(ObjectID: TBoldObjectId); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure AddList(ObjectIdList: TBoldObjectIdList); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function AddAndGetID(aBoldObjectId: TBoldObjectId): TBoldObjectId; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure Insert(Index: integer; ObjectID: TBoldObjectId); {$IFDEF BOLD_INLINE} inline; {$ENDIF} function ContainsSameIDs(List: TBoldObjectIdList): Boolean; function Clone: TBoldObjectIdList; - function CommaSeparatedIdList: String; - procedure remove(Id: TBoldObjectId); - procedure ReplaceID(OldId, NewId: TBoldObjectId); + procedure Remove(Id: TBoldObjectId); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure ReplaceID(OldId, NewId: TBoldObjectId); {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure ExactifyIds(TranslationList: TBoldIDTranslationList); procedure ApplyTranslationList(TranslationList: TBoldIdTranslationList); + procedure RemoveNonExistingIds; property IDByID[ObjectID: TBoldObjectId]: TBoldObjectId read GetIdById; property IndexByID[ObjectID: TBoldObjectId]: Integer read GetIndexByID; property ObjectIds[index: Integer]: TBoldObjectId read GetObjectId; default; property IdInList[Objectid: TBoldObjectId]: Boolean read GetIdInList; + property HasInexactIds: boolean read GetHasInexactIds; + property HasNonExistingIds: boolean read GetHasNonExistingIds; end; {---TBoldMemberIdList---} TBoldMemberIdList = class(TBoldIdList, IBoldStreamable) - function GetStreamName: string; + function GetStreamName: string; {$IFDEF BOLD_INLINE} inline; {$ENDIF} protected - function GetMemberIds(Index: Integer): TBoldMemberId; + function GetMemberIds(Index: Integer): TBoldMemberId; {$IFDEF BOLD_INLINE} inline; {$ENDIF} public - Property MemberIds[Index: integer]: TBoldmemberId read GetMemberIds; default; + function IsEqual(AList: TBoldMemberIdList): boolean; + function HasId(AId: TBoldMemberId): boolean; + function Clone: TBoldMemberIdList; + property MemberIds[Index: integer]: TBoldMemberId read GetMemberIds; default; end; {---TBoldIDTranslationList---} TBoldIDTranslationList = class(TBoldNonRefCountedObject, IBoldStreamable) - // Possible Translations: - // In Create-phase: ObjectID changed (Internal -> external), ClassID unchanged - // In Update-Phase: ObjectID Changed (internal -> external) - // In Delete-Phase: Nothing changed - // In Fetch-phase: ObjectID unchanged, ClassID changed private fOldIds: TBoldObjectIdList; fNewIds: TBoldObjectIdList; - function GetOldId(index: Integer): TBoldObjectId; - function GetNewId(index: Integer): TBoldObjectId; - function GetCount: Integer; - function GetTranslateToOldId(NewID: TBoldObjectId): TBoldObjectId; - function GetTranslateToNewId(OldID: TBoldObjectId): TBoldObjectId; + function GetOldId(index: Integer): TBoldObjectId; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetNewId(index: Integer): TBoldObjectId; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetCount: Integer; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetTranslateToOldId(NewID: TBoldObjectId): TBoldObjectId; overload; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetTranslateToNewId(OldID: TBoldObjectId): TBoldObjectId; overload; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + + function GetTranslateToOldId(Index: integer): TBoldObjectId; overload; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetTranslateToNewId(Index: integer): TBoldObjectId; overload;{$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetCapacity: Integer; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure SetCapacity(const Value: Integer); {$IFDEF BOLD_INLINE} inline; {$ENDIF} protected - function GetStreamName: string; + function GetStreamName: string; {$IFDEF BOLD_INLINE} inline; {$ENDIF} public constructor Create; destructor Destroy; override; - procedure AddTranslation(OldId, NewId: TBoldObjectId); + procedure AddTranslation(OldId, NewId: TBoldObjectId); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure AddTranslationAdoptNew(OldId, NewId: TBoldObjectId); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure AddTranslationAdoptBoth(OldId, NewId: TBoldObjectId); {$IFDEF BOLD_INLINE} inline; {$ENDIF} property Count: Integer read GetCount; property TranslateToOldId[NewID: TBoldObjectId]: TBoldObjectId read GetTranslateToOldId; property TranslateToNewId[OldID: TBoldObjectId]: TBoldObjectId read GetTranslateToNewId; property OldIds[Index: integer] :TBoldObjectId read GetOldId; property NewIds[Index: integer] :TBoldObjectId read GetNewId; + property Capacity: Integer read GetCapacity write SetCapacity; end; { EBoldOperationFailedForIdList } @@ -187,8 +222,8 @@ EBoldOperationFailedForIdList = class(EBold) private fIdList: TBoldObjectIdList; public - constructor Create(msg: string; args: array of const; IdList: TBoldObjectIdList); - destructor Destroy; override; + constructor create(msg: string; args: array of const; IdList: TBoldObjectIdList); + destructor destroy; override; property IdList: TBoldObjectIdList read fIdList; end; @@ -202,16 +237,17 @@ TBoldXMLObjectIdStreamer = class(TBoldXMLObjectStreamer) implementation uses + {$IFDEF OXML}OXmlPDOM{$ELSE}MSXML_TLB{$ENDIF}, SysUtils, - BoldUtils, - MSXML_TLB, + {$IFNDEF BOLD_UNICODE} + StringBuilder, + {$ENDIF} BoldDefaultXMLStreaming, BoldDefaultStreamNames, BoldMeta; var InternalIdCounter: Integer = 0; - IX_ObjectID: integer = -1; const TOPSORTEDINDEXTMASK = $0FFFFFFF; @@ -269,6 +305,31 @@ TBoldXMLMemberIdListStreamer = class(TBoldXMLObjectStreamer) function CreateObject: TObject; override; end; +{---TBoldObjectId---} + +function TBoldObjectId.getTopSortedIndex: integer; +const + TOPSORTEDINDEXTMASK = TOPSORTEDINDEXTMASK; // copied here for inlining +begin + result := fClassId and TOPSORTEDINDEXTMASK; +end; + +function TBoldObjectId.GetTopSortedIndexExact: Boolean; +const + CLASSIDEXACTMASK = CLASSIDEXACTMASK; // copied here for inlining +begin + result := (fClassId and CLASSIDEXACTMASK) = CLASSIDEXACTMASK; +end; + +procedure TBoldObjectId.SetClassIdData(TopSortedIndex: integer; Exact: boolean); +const + CLASSIDEXACTMASK = CLASSIDEXACTMASK; // copied here for inlining +begin + if exact then + fClassId := TopSortedIndex or CLASSIDEXACTMASK + else + fClassId := TopSortedIndex; +end; {---TBoldObjectIdHashIndex---} @@ -288,23 +349,35 @@ function TBoldObjectIdHashIndex.Match(const Key; Item:TObject):Boolean; Result := TBoldObjectId(Key).IsEqual[ItemAsBoldObjectId(Item)]; end; -function TBoldObjectIdHashIndex.FindById(boldObjectId:TboldObjectId): TObject; +function TBoldObjectIdHashIndex.FindById(BoldObjectId: TBoldObjectId): TObject; begin - Result := Find(boldObjectId); + Result := Find(BoldObjectId); end; {---TBoldMemberID---} -constructor TBoldMemberId.create(MemberIndex: Integer); + +function TBoldMemberID.Clone: TBoldMemberID; +begin + result := TBoldMemberID.Create(MemberIndex); +end; + +constructor TBoldMemberId.Create(MemberIndex: Integer); begin fMemberIndex := MemberIndex; end; +function TBoldMemberID.GetAsString: string; +begin + result := IntToStr(fMemberIndex); +end; + function TBoldMemberId.GetStreamName: string; begin result := BOLDMEMBERIDNAME; end; {---TBoldSubMemberID---} + constructor TBoldSubMemberId.create(partOf: TBoldMemberID; OwnsPartOf: Boolean; IndexInMemberList: integer); begin Inherited Create(IndexInMemberList); @@ -323,6 +396,7 @@ destructor TBoldSubMemberId.destroy; end; {---TBoldObjectId---} + function TBoldObjectId.Clone: TBoldObjectId; begin result := CloneWithClassId(TopSortedIndex, TopSortedIndexExact); @@ -344,8 +418,7 @@ constructor TBoldInternalObjectID.CreateWithClassIDandInternalId(InternalIdentif function TBoldInternalObjectID.CloneWithClassId(TopSortedIndex: integer; Exact: Boolean):TBoldObjectid; begin - result := TBoldInternalObjectId.CreateWithClassId(TopSortedIndex, Exact); - (result as TBoldInternalObjectId).fInternalIdentifier := fInternalIdentifier; + result := TBoldInternalObjectId.CreateWithClassIDandInternalId(fInternalIdentifier, TopSortedIndex, Exact); end; constructor TBoldInternalObjectId.CreateWithClassID(TopSortedIndex: integer; Exact: Boolean); @@ -397,6 +470,11 @@ constructor TBoldObjectIdList.Create; OwnsEntries := true; end; +function TBoldObjectIdList.GetIdInList(ObjectID: TBoldObjectId): Boolean; +begin + Result := Assigned(ObjectId) and Assigned(GetIdByID(ObjectID)); +end; + function TBoldObjectIdList.ContainsSameIDs(List: TBoldObjectIdList): Boolean; var i: integer; @@ -409,6 +487,42 @@ function TBoldObjectIdList.ContainsSameIDs(List: TBoldObjectIdList): Boolean; end; end; +function TBoldObjectIdList.GetObjectIDIndex: TBoldObjectIDHashIndex; +begin + if UnorderedIndexCount = 0 then + begin + IX_ObjectID := -1; + SetIndexVariable(IX_ObjectID, AddIndex(TBoldObjectIDHashIndex.Create)); + end; + result := TBoldObjectIDHashIndex(Indexes[IX_ObjectID]); +end; + +function TBoldObjectIdList.GetHasInexactIds: boolean; +var + i: integer; +begin + result := false; + for i := 0 to Count - 1 do + if not TBoldObjectId(Items[i]).TopSortedIndexExact then + begin + result := true; + exit; + end; +end; + +function TBoldObjectIdList.GetHasNonExistingIds: boolean; +var + i: integer; +begin + result := false; + for i := 0 to Count - 1 do + if TBoldObjectId(Items[i]).NonExisting then + begin + result := true; + exit; + end; +end; + function TBoldObjectIdList.GetIDByID(ObjectID: TBoldObjectId): TBoldObjectId; var i: integer; @@ -438,34 +552,35 @@ function TBoldObjectIdList.GetIndexByID(ObjectID: TBoldObjectId): Integer; result := -1; end; -function TBoldObjectIdList.GetIdInList(ObjectID: TBoldObjectId): Boolean; +function TBoldObjectIdList.GetObjectId(index: Integer): TBoldObjectId; begin - Result := Assigned(ObjectId) and Assigned(GetIdByID(ObjectID)); + Result := TBoldObjectId(Items[index]); end; -function TBoldObjectIdList.Clone: TBoldObjectIdList; -var - i: Integer; +procedure TBoldObjectIdList.Add(ObjectID: TBoldObjectId); begin - Result := TBoldObjectIdList.Create; - for i := 0 to Count - 1 do - Result.Add(ObjectIDs[i]); + if assigned(ObjectID) then + inherited Add(ObjectId.Clone) + else + inherited Add(nil); end; -function TBoldObjectIdList.GetObjectId(index: Integer): TBoldObjectId; +procedure TBoldObjectIdList.AddAndAdopt(ObjectID: TBoldObjectId); begin - Result := TBoldObjectId(Items[index]); + inherited Add(ObjectId); end; -procedure TBoldObjectIdList.Add(ObjectID: TBoldObjectId); -var - newObjectID: TBoldObjectID; +function TBoldObjectIdList.AddAndGetID( + aBoldObjectId: TBoldObjectId): TBoldObjectId; begin - if assigned(ObjectID) then - NewObjectId := ObjectId.Clone - else - NewObjectId := nil; - inherited Add(NewObjectID); + if assigned(aBoldObjectId) then + begin + result := aBoldObjectId.Clone + end else + begin + result := nil; + end; + inherited Add(result); end; procedure TBoldObjectIdList.AddIfNotInList(ObjectID: TBoldObjectId); @@ -476,14 +591,11 @@ procedure TBoldObjectIdList.AddIfNotInList(ObjectID: TBoldObjectId); procedure TBoldObjectIdList.Insert(Index: integer; ObjectID: TBoldObjectId); -var - newObjectID: TBoldObjectID; begin if assigned(ObjectID) then - NewObjectId := ObjectId.Clone + inherited insert(index, ObjectId.Clone) else - NewObjectId := nil; - inherited insert(index, NewObjectID); + inherited insert(index, nil); end; procedure TBoldObjectIdList.ReplaceID(OldId, NewId: TBoldObjectId); @@ -495,8 +607,7 @@ procedure TBoldObjectIdList.ReplaceID(OldId, NewId: TBoldObjectId); exit; TempID := IDByID[OldId]; OldIndex := IndexOf(tempId); - RemoveByIndex(OldIndex); - Insert(OldIndex, NewId); + Items[OldIndex] := NewId.Clone; end; function TBoldObjectIdList.GetCount: integer; @@ -504,11 +615,23 @@ function TBoldObjectIdList.GetCount: integer; result := count; end; +function TBoldObjectIdList.Clone: TBoldObjectIdList; +var + i: Integer; +begin + Result := TBoldObjectIdList.Create; + Result.Capacity := Count; + for i := 0 to Count - 1 do + Result.Add(ObjectIDs[i]); +end; + function TBoldObjectIdList.GetStreamName: string; begin result := BOLDOBJECTIDLISTNAME; end; + {---TBoldMemberIdList---} + function TBoldMemberIdList.GetStreamName: string; begin result := BOLDMEMBERIDLISTNAME; @@ -516,12 +639,74 @@ function TBoldMemberIdList.GetStreamName: string; function TBoldMemberIdList.GetMemberIds(Index: Integer): TBoldMemberId; begin - Assert(Items[Index] is TBoldmemberId); - result := Items[Index] as TBoldmemberId; - assert(Assigned(Result)); + result := TBoldmemberId(Items[Index]); + Assert(result is TBoldmemberId); +end; + +function TBoldMemberIdList.HasId(AId: TBoldMemberId): boolean; +var + i: integer; +begin + for I := 0 to Count - 1 do + if MemberIds[i].MemberIndex = AId.MemberIndex then + begin + result := true; + exit; + end; + result := false; +end; + +function TBoldMemberIdList.IsEqual(AList: TBoldMemberIdList): boolean; +var + i: integer; +begin + result := Assigned(AList) and (AList.Count = Count); + if result then + for I := 0 to Count - 1 do + begin + if not AList.HasId(MemberIds[i]) then + begin + result := false; + exit; + end; + end; +end; + +function TBoldMemberIdList.Clone: TBoldMemberIdList; +var + i: integer; +begin + result := TBoldMemberIdList.Create; + for I := 0 to Count - 1 do + Result.Add(MemberIds[i].clone); end; {---TBoldIDTranslationList---} + +function TBoldIDTranslationList.GetCapacity: Integer; +begin + result := fOldIds.Capacity; +end; + +function TBoldIDTranslationList.GetCount: Integer; +begin + Result := fOldIds.Count; +end; + +procedure TBoldIDTranslationList.AddTranslationAdoptNew(OldId, + NewId: TBoldObjectId); +begin + fOldIDs.Add(OldId); + fNewIds.AddAndAdopt(NewId) +end; + +procedure TBoldIDTranslationList.AddTranslationAdoptBoth(OldId, + NewId: TBoldObjectId); +begin + fOldIDs.AddAndAdopt(OldId); + fNewIds.AddAndAdopt(NewId) +end; + constructor TBoldIDTranslationList.Create; begin fOldIds := TBoldObjectIdList.Create; @@ -545,15 +730,54 @@ function TBoldIDTranslationList.GetNewId(index: Integer): TBoldObjectId; Result := fNewIds[index]; end; -function TBoldIDTranslationList.GetCount: Integer; -begin - Result := fOldIds.Count; -end; - procedure TBoldIDTranslationList.AddTranslation(OldId, NewId: TBoldObjectId); +var + iIndex: Integer; begin + // This routine no longer handles multiple translations! +{ + if Assigned(OldId) then begin + iIndex := fOldIds.IndexByID[OldId]; + if (iIndex > -1) then begin + if ((NewID = nil) and (fNewIds[iIndex] = nil)) or + ((fNewIds[iIndex] <> nil) and fNewIds[iIndex].IsEqual[NewId]) then + begin + Exit; + end; + end; + end; + if Assigned(NewId) then begin + iIndex := fNewIds.IndexByID[NewId]; + if (iIndex > -1) then begin + if ((OldID = nil) and (fOldIds[iIndex] = nil)) or + ((fOldIds[iIndex] <> nil) and fOldIds[iIndex].IsEqual[OldId]) then + begin + Exit; + end; + end; + end; + fOldIDs.Add(OldId); - fNewIds.Add(NewId) + fNewIds.Add(NewId); +} + // Translation only makes sense, if both IDs are set + if Assigned(OldId) and Assigned(NewId) then begin + iIndex := fOldIds.IndexByID[OldId]; + if (iIndex > -1) then begin + if fNewIds[iIndex].IsEqual[NewId] then begin + Exit; + end; + end; + iIndex := fNewIds.IndexByID[NewId]; + if (iIndex > -1) then begin + if fOldIds[iIndex].IsEqual[OldId] then begin + Exit; + end; + end; + + fOldIDs.Add(OldId); + fNewIds.Add(NewId); + end; end; function TBoldIDTranslationList.GetTranslateToOldId(NewID: TBoldObjectId): TBoldObjectId; @@ -564,7 +788,6 @@ function TBoldIDTranslationList.GetTranslateToOldId(NewID: TBoldObjectId): TBold Pos := fNewIds.IndexByID[Result]; if pos <> -1 then result := GetOldId(Pos); - // This routine no longer handles multiple translations! { while Pos <> -1 do begin result := OriginalId[Pos]; @@ -572,6 +795,12 @@ function TBoldIDTranslationList.GetTranslateToOldId(NewID: TBoldObjectId): TBold end;} end; +procedure TBoldIDTranslationList.SetCapacity(const Value: Integer); +begin + fOldIds.Capacity := Value; + fNewIds.Capacity := Value; +end; + function TBoldIDTranslationList.GetTranslateToNewId(OldID: TBoldObjectId): TBoldObjectId; var Pos: Integer; @@ -580,7 +809,7 @@ function TBoldIDTranslationList.GetTranslateToNewId(OldID: TBoldObjectId): TBold Pos := fOldIds.IndexById[Result]; if pos <> -1 then Result := GetNewId(Pos); - // This routine no longer handles multiple translations! + { while Pos <> -1 do begin Result := FinalId[Pos]; @@ -588,6 +817,16 @@ function TBoldIDTranslationList.GetTranslateToNewId(OldID: TBoldObjectId): TBold end;} end; +function TBoldIDTranslationList.GetTranslateToOldId(Index: integer): TBoldObjectId; +begin + result := fOldIds[Index]; +end; + +function TBoldIDTranslationList.GetTranslateToNewId(Index: integer): TBoldObjectId; +begin + Result := GetNewId(Index); +end; + function TBoldIDTranslationList.GetStreamName: string; begin result := BOLDIDTRANSLATIONLISTNAME; @@ -600,7 +839,7 @@ procedure TBoldObjectIdList.ExactifyIds( begin for i := 0 to count - 1 do if not ObjectIds[i].TopSortedIndexExact then - ReplaceID(ObjectIds[i], TranslationList.TranslateToNewId[ObjectIds[i]]); + Items[i] := TranslationList.TranslateToNewId[ObjectIds[i]].Clone; end; procedure TBoldObjectIdList.ApplyTranslationList( @@ -608,16 +847,32 @@ procedure TBoldObjectIdList.ApplyTranslationList( var i: Integer; anId: TBoldObjectId; + SameCount: boolean; begin + SameCount := TranslationList.Count = count; for i := Count - 1 downto 0 do - begin - anId := TranslationList.TranslateToNewId[ObjectIds[i]]; - if assigned(anId) then - ReplaceId(ObjectIds[i], anId); - end; + begin + Assert(Assigned(ObjectIds[i])); + if SameCount and Assigned(TranslationList.OldIds[i]) then + begin + if TranslationList.OldIds[i].IsEqual[self.ObjectIds[i]] then + begin // faster handling for special but most common case, where both lists contain same elements at same places + self.Items[i] := TranslationList.NewIds[i].Clone; + continue; + end; + end; + anId := TranslationList.TranslateToNewId[ObjectIds[i]]; + if assigned(anId) then + ReplaceId(ObjectIds[i], anId); + end; end; { TBoldClassIdWithExpressionName } +function TBoldObjectId.GetNonExisting: Boolean; +begin + Result := false; +end; + function TBoldObjectId.GetTimeStamp: TBoldTimeStampType; begin result := BOLDMAXTIMESTAMP; @@ -637,7 +892,6 @@ destructor EBoldOperationFailedForIdList.destroy; inherited; end; - { TBoldXMLObjectIdStreamer } procedure TBoldXMLObjectIdStreamer.ReadObject(Obj: TObject; Node: TBoldXMLNode); @@ -652,13 +906,13 @@ procedure TBoldXMLObjectIdStreamer.ReadObject(Obj: TObject; Node: TBoldXMLNode); inherited; aModel := (Node.Manager as TBoldDefaultXMLStreamManager).Model; - aSubNode := Node.GetSubNode('ClassName'); // do not localize + aSubNode := Node.GetSubNode('ClassName'); if assigned(aSubNode) then begin TopSortedIndex := aModel.Classes.ItemsByName[aSubNode.ReadString].TopSortedIndex;; aSubNode.Free; - aSubNode := Node.GetSubNode('Exact'); // do not localize + aSubNode := Node.GetSubNode('Exact'); if assigned(aSubNode) then Exact := aSubNode.ReadBoolean else @@ -667,12 +921,11 @@ procedure TBoldXMLObjectIdStreamer.ReadObject(Obj: TObject; Node: TBoldXMLNode); end else begin - // BackwardCompatibility - ClassIdNode := Node.GetSubNode('classid'); // do not localize - aSubNode := ClassIdNode.GetSubNode('name'); // do not localize + ClassIdNode := Node.GetSubNode('classid'); + aSubNode := ClassIdNode.GetSubNode('name'); TopSortedIndex := aModel.Classes.ItemsByName[aSubNode.ReadString].TopSortedIndex; aSubNode.Free; - aSubNode := ClassIdNode.GetSubNode('exact'); // do not localize + aSubNode := ClassIdNode.GetSubNode('exact'); Exact := aSubNode.ReadBoolean; aSubNode.Free; end; @@ -685,19 +938,19 @@ procedure TBoldXMLObjectIdStreamer.WriteObject(Obj: TBoldInterfacedObject; Node: var aSubNode: TBoldXMLNode; aModel: TMoldModel; - ObjectId: TBoldObjectId; + ObjectId: TBoldObjectId; begin inherited; aModel := (Node.Manager as TBoldDefaultXMLStreamManager).Model; ObjectId := Obj as TBoldObjectId; - aSubNode := Node.NewSubNode('ClassName'); // do not localize + aSubNode := Node.NewSubNode('ClassName'); aSubNode.WriteString(aModel.Classes[ObjectId.TopSortedIndex].Name); aSubNode.Free; if not ObjectId.TopSortedIndexExact then begin - aSubNode := Node.NewSubNode('Exact'); // do not localize + aSubNode := Node.NewSubNode('Exact'); aSubNode.WriteBoolean(ObjectId.TopSortedIndexExact); aSubNode.Free; end; @@ -721,7 +974,7 @@ procedure TBoldXMLInternalObjectIdStreamer.ReadObject(Obj: TObject; aSubNode: TBoldXMLNode; begin inherited; - aSubNode := Node.GetSubNode('identifier'); // do not localize + aSubNode := Node.GetSubNode('identifier'); (Obj as TBoldInternalObjectId).fInternalIdentifier := aSubNode.ReadInteger; aSubNode.Free; end; @@ -732,7 +985,7 @@ procedure TBoldXMLInternalObjectIdStreamer.WriteObject( aSubNode: TBoldXMLNode; begin inherited; - aSubNode := Node.NewSubNode('identifier'); // do not localize + aSubNode := Node.NewSubNode('identifier'); aSubNode.WriteInteger((Obj as TBoldInternalObjectId).fInternalIdentifier); aSubNode.Free; end; @@ -753,13 +1006,36 @@ procedure TBoldXMLObjectIdListStreamer.ReadObject(Obj: TObject; Node: TBoldXMLNode); var anIdList: TBoldObjectIdList; + {$IFDEF OXML} + aNodeEnumerator: TXMLResNodeListEnumerator; + aNodeList: IXMLNodeList; + aNode: PXMLNode; + {$ELSE} aNodeList: IXMLDOMNodeList; aNode: IXMLDOMNode; + {$ENDIF} aSubNode: TBoldXMLNode; ObjectId: TBoldObjectId; begin inherited; anIdList := Obj as TBoldObjectIdList; + {$IFDEF OXML} + if Node.XMLDomElement.GetElementsByTagName('id', aNodeList) then begin + aNodeEnumerator := aNodeList.GetEnumerator; + try + while aNodeEnumerator.MoveNext do begin + aNode := aNodeEnumerator.Current; + aSubNode := Node.MakeNodeForElement(aNode); + ObjectId := aSubNode.ReadObject('') as TBoldObjectId; + anIdList.Add(ObjectId); + ObjectId.Free; + aSubNode.Free; + end; + finally + aNodeEnumerator.Free; + end; + end; + {$ELSE} aNodeList := Node.XMLDomElement.getElementsByTagName('id'); // do not localize aNode := aNodeList.nextNode; while assigned(aNode) do @@ -771,6 +1047,7 @@ procedure TBoldXMLObjectIdListStreamer.ReadObject(Obj: TObject; aSubNode.Free; aNode := aNodeList.nextNode; end; + {$ENDIF} end; procedure TBoldXMLObjectIdListStreamer.WriteObject(Obj: TBoldInterfacedObject; @@ -784,7 +1061,7 @@ procedure TBoldXMLObjectIdListStreamer.WriteObject(Obj: TBoldInterfacedObject; anIdList := Obj as TBoldObjectIdList; for i := 0 to anIdList.Count - 1 do begin - aSubNode := Node.NewSubNode('id'); // do not localize + aSubNode := Node.NewSubNode('id'); aSubNode.WriteObject('', anIdList[i]); aSubNode.Free; end; @@ -811,8 +1088,8 @@ procedure TBoldXMLTranslationListStreamer.ReadObject(Obj: TObject; aTranslationList := Obj as TBoldIDTranslationList; aTranslationList.fOldIds.Free; aTranslationList.fNewIds.Free; - aTranslationList.fOldIds := Node.ReadSubNodeObject('OldIds', BOLDOBJECTIDLISTNAME) as TBoldObjectIdList; // do not localize - aTranslationList.fNewIds := Node.ReadSubNodeObject('NewIds', BOLDOBJECTIDLISTNAME) as TBoldObjectIdList; // do not localize + aTranslationList.fOldIds := Node.ReadSubNodeObject('OldIds', BOLDOBJECTIDLISTNAME) as TBoldObjectIdList; + aTranslationList.fNewIds := Node.ReadSubNodeObject('NewIds', BOLDOBJECTIDLISTNAME) as TBoldObjectIdList; end; procedure TBoldXMLTranslationListStreamer.WriteObject( @@ -822,15 +1099,15 @@ procedure TBoldXMLTranslationListStreamer.WriteObject( begin inherited; aTranslationList := Obj as TBoldIDTranslationList; - Node.WriteSubNodeObject('OldIds', BOLDOBJECTIDLISTNAME, aTranslationList.fOldIds); // do not localize - Node.WriteSubNodeObject('NewIds', BOLDOBJECTIDLISTNAME, aTranslationList.fNewIds); // do not localize + Node.WriteSubNodeObject('OldIds', BOLDOBJECTIDLISTNAME, aTranslationList.fOldIds); + Node.WriteSubNodeObject('NewIds', BOLDOBJECTIDLISTNAME, aTranslationList.fNewIds); end; { TBoldXMLMemberIdStreamer } function TBoldXMLMemberIdStreamer.CreateObject: TObject; begin - result := TBoldMemberID.create(0); // index param to constructor chosen arbitrarily, will be overwritten anyway + result := TBoldMemberID.create(0); end; function TBoldXMLMemberIdStreamer.GetStreamName: string; @@ -842,14 +1119,14 @@ procedure TBoldXMLMemberIdStreamer.ReadObject(Obj: TObject; Node: TBoldXMLNode); begin inherited; - (Obj as TBoldMemberId).fMemberIndex := Node.ReadSubNodeInteger('MemberIndex'); // do not localize + (Obj as TBoldMemberId).fMemberIndex := Node.ReadSubNodeInteger('MemberIndex'); end; procedure TBoldXMLMemberIdStreamer.WriteObject(Obj: TBoldInterfacedObject; Node: TBoldXMLNode); begin inherited; - Node.WriteSubNodeInteger('MemberIndex', (Obj as TBoldMemberId).MemberIndex); // do not localize + Node.WriteSubNodeInteger('MemberIndex', (Obj as TBoldMemberId).MemberIndex); end; { TBoldXMLMemberIdListStreamer } @@ -868,12 +1145,33 @@ procedure TBoldXMLMemberIdListStreamer.ReadObject(Obj: TObject; Node: TBoldXMLNode); var aMemberIdList: TBoldMemberIdList; + {$IFDEF OXML} + aNodeEnumerator: TXMLResNodeListEnumerator; + aNodeList: IXMLNodeList; + aNode: PXMLNode; + {$ELSE} aNodeList: IXMLDOMNodeList; aNode: IXMLDOMNode; + {$ENDIF} aSubNode: TBoldXMLNode; begin inherited; aMemberIdList := Obj as TBoldMemberIdList; + {$IFDEF OXML} + if Node.XMLDomElement.GetElementsByTagName('id', aNodeList) then begin + aNodeEnumerator := aNodeList.GetEnumerator; + try + while aNodeEnumerator.MoveNext do begin + aNode := aNodeEnumerator.Current; + aSubNode := Node.MakeNodeForElement(aNode); + aMemberIdList.Add(aSubNode.ReadObject('') as TBoldMemberId); + aSubNode.Free; + end; + finally + aNodeEnumerator.Free; + end; + end; + {$ELSE} aNodeList := Node.XMLDomElement.getElementsByTagName('id'); // do not localize aNode := aNodeList.nextNode; while assigned(aNode) do @@ -883,6 +1181,7 @@ procedure TBoldXMLMemberIdListStreamer.ReadObject(Obj: TObject; aSubNode.Free; aNode := aNodeList.nextNode; end; + {$ENDIF} end; procedure TBoldXMLMemberIdListStreamer.WriteObject( @@ -896,73 +1195,116 @@ procedure TBoldXMLMemberIdListStreamer.WriteObject( aMemberIdList := Obj as TBoldMemberIdList; for i := 0 to aMemberIdList.Count - 1 do begin - aSubNode := Node.NewSubNode('id'); // do not localize + aSubNode := Node.NewSubNode('id'); aSubNode.WriteObject('', aMemberIdList[i]); aSubNode.Free; end; end; - { TBoldID } -function TBoldObjectIdList.GetObjectIDIndex: TBoldObjectIDHashIndex; -begin - if UnorderedIndexCount = 0 then - SetIndexVariable(IX_ObjectID, AddIndex(TBoldObjectIDHashIndex.Create)); - result := TBoldObjectIDHashIndex(Indexes[IX_ObjectID]); -end; - procedure TBoldObjectIdList.AddList(ObjectIdList: TBoldObjectIdList); var i: integer; begin + Capacity := Count + ObjectidList.Count; for i := 0 to ObjectidList.Count - 1 do Add(ObjectidList[i]); end; -function TBoldObjectId.getTopSortedIndex: integer; +function TBoldObjectIdHashIndex.Hash(const Key): Cardinal; begin - result := fClassId and TOPSORTEDINDEXTMASK; + Result := TBoldObjectId(Key).Hash; end; -function TBoldObjectId.GetTopSortedIndexExact: Boolean; +procedure TBoldObjectIdList.remove(Id: TBoldObjectId); +var + p: integer; begin - result := (fClassId and CLASSIDEXACTMASK) = CLASSIDEXACTMASK; + p := IndexOf(Id); + if p <> -1 then + removebyIndex(p); end; -procedure TBoldObjectId.SetClassIdData(TopSortedIndex: integer; Exact: boolean); +procedure TBoldObjectIdList.RemoveNonExistingIds; +var + i: integer; begin - if exact then - fClassId := TopSortedIndex or CLASSIDEXACTMASK - else - fClassId := TopSortedIndex; + for i := 0 to Count - 1 do + if TBoldObjectId(Items[i]).NonExisting then + RemoveByIndex(i); end; -function TBoldObjectIdHashIndex.Hash(const Key): Cardinal; +{ TBoldID } + +function TBoldID.GetDebugInfo: string; begin - Result := TBoldObjectId(Key).Hash; + result := AsString; end; -function TBoldObjectIdList.CommaSeparatedIdList: String; -var - i: integer; +{ TBoldNonExistingObjectId } + +function TBoldNonExistingObjectId.CloneWithClassId(TopSortedIndex: integer; Exact: Boolean): TBoldObjectid; +begin +// raise EBold.CreateFmt('CloneWithClassId not available in %s',[ClassName]); + result := TBoldNonExistingObjectId.CreateWithClassID(TopSortedIndex, Exact); +end; + +function TBoldNonExistingObjectId.GetAsString: string; +begin + result := '-1'; +end; + +function TBoldNonExistingObjectId.GetHash: Cardinal; +begin + result := 0; +end; + +function TBoldNonExistingObjectId.GetIsEqual(MatchID: TBoldObjectID): Boolean; +begin + result := MatchId is TBoldNonExistingObjectId; +end; + +function TBoldNonExistingObjectId.GetIsStorable: Boolean; +begin + result := false; +end; + +function TBoldNonExistingObjectId.GetNonExisting: Boolean; +begin + Result := true; +end; + +function TBoldNonExistingObjectId.GetStreamName: string; begin result := ''; - for i := 0 to Count - 1 do - begin - if i <> 0 then - result := result + ', '; - result := result + ObjectIds[i].AsString; - end; end; -procedure TBoldObjectIdList.remove(Id: TBoldObjectId); +{ TBoldIdList } + +function TBoldIdList.CommaSeparatedIdList: String; var - p: integer; + i: integer; + sb: TStringBuilder; begin - p := IndexOf(Id); - if p <> -1 then - removebyIndex(p); + case count of + 0 : result := ''; + 1 : result := TBoldId(Items[0]).AsString; + 2..MaxInt: + begin + sb := TStringBuilder.Create(TBoldId(Items[0]).AsString); + try + for i := 1 to Count - 1 do + begin + sb.Append(','); + sb.Append(TBoldId(Items[i]).AsString); + end; + result := sb.ToString; + finally + sb.free; + end; + end; + end; end; initialization @@ -973,4 +1315,3 @@ initialization TBoldXMLStreamerRegistry.MainStreamerRegistry.RegisterStreamer(TBoldXMLTranslationListStreamer.Create); end. - diff --git a/Source/ValueSpace/Id/BoldStringId.pas b/Source/ValueSpace/Id/BoldStringId.pas index 49552a5..8528f55 100644 --- a/Source/ValueSpace/Id/BoldStringId.pas +++ b/Source/ValueSpace/Id/BoldStringId.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldStringId; interface @@ -5,11 +8,12 @@ interface uses BoldId; + type TBoldStringID = class(TBoldExternalObjectID) protected fIdValue: String; - procedure SetAsString(NewValue: String); + procedure SetAsString(NewValue: String); {$IFDEF BOLD_INLINE} inline; {$ENDIF} function GetAsString: string; override; function GetHash: cardinal; override; function GetStreamName: string; override; @@ -19,6 +23,7 @@ TBoldStringID = class(TBoldExternalObjectID) property AsString: String read GetAsString write SetAsString; end; + implementation uses @@ -42,7 +47,7 @@ TBoldXMLStringIdStreamer = class(TBoldXMLObjectIdStreamer) { TBoldStringID } -function HashString(const S: string): CARDINAL; +function HashString(const S: string): CARDINAL; {$IFDEF BOLD_INLINE} inline; {$ENDIF} var i: integer; begin @@ -111,7 +116,6 @@ procedure TBoldXMLStringIdStreamer.WriteObject(Obj: TBoldInterfacedObject; inherited; Node.WriteSubNodeString(BoldNodeName_IdValue, (Obj as TBoldStringID).fIdValue); end; - initialization TBoldXMLStreamerRegistry.MainStreamerRegistry.RegisterStreamer(TBoldXMLStringIdStreamer.Create); end. diff --git a/Source/ValueSpace/Id/ValueSpaceConst.pas b/Source/ValueSpace/Id/ValueSpaceConst.pas index ec37c97..a3d1c30 100644 --- a/Source/ValueSpace/Id/ValueSpaceConst.pas +++ b/Source/ValueSpace/Id/ValueSpaceConst.pas @@ -12,4 +12,4 @@ interface implementation -end. \ No newline at end of file +end. diff --git a/Source/ValueSpace/Interfaces/BoldValueInterfaces.pas b/Source/ValueSpace/Interfaces/BoldValueInterfaces.pas index 50d1c71..cf7822a 100644 --- a/Source/ValueSpace/Interfaces/BoldValueInterfaces.pas +++ b/Source/ValueSpace/Interfaces/BoldValueInterfaces.pas @@ -1,8 +1,13 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldValueInterfaces; interface uses + Classes, // for TStream + BoldId, BoldDefs; @@ -25,15 +30,35 @@ interface IBoldObjectIdListRef = interface; IBoldObjectIdListRefPair = interface; + TBoldValueContentType = ( + bctValueSpace, + bctObject, + bctString, + bctCurrency, + bctFloat, + bctInteger, + bctBoolean, + bctDate, + bctTime, + bctDateTime, + bctBlob, + bctTypedBlob, + + bctObjectIdRef, + bctObjectIdRefPair, + bctObjectIdListRef, + bctObjectIdListRefPair); IBoldValue = interface ['{67C57AD9-621B-11D2-AFF7-006008F62CFF}'] function GetContentName: String; - procedure AssignContent(Source: IBoldValue); + procedure AssignContent(const Source: IBoldValue); function GetBoldPersistenceState: TBoldValuePersistenceState; procedure SetBoldPersistenceState(Value: TBoldValuePersistenceState); + function GetContentType: TBoldValueContentType; property BoldPersistenceState: TBoldValuePersistenceState read GetBoldPersistenceState write SetBoldPersistenceState; property ContentName: String read GetContentName; + property ContentType: TBoldValueContentType read GetContentType; end; IBoldNullableValue = interface(IBoldValue) @@ -43,78 +68,106 @@ interface property IsNull: Boolean read GetContentIsNull; end; + IBoldStringRepresentable = interface(IBoldNullableValue) + ['{67C57AC7-621B-11D2-AFF7-006008F62CFF}'] + function GetStringRepresentation(representation:integer): String; +// procedure SetStringRepresentation(Representation: integer; const NewValue: String); + property StringRepresentation[representation: integer]: String read GetStringRepresentation {write SetStringRepresentation}; + function GetContentAsString: String; + property asString: String read GetContentAsString; + end; - IBoldStringContent = interface(IBoldNullableValue) + IBoldStringContent = interface(IBoldStringRepresentable) ['{67C57AC6-621B-11D2-AFF7-006008F62CFF}'] procedure SetContentAsString(const NewValue: String); - function GetContentAsString: String; property asString: String read GetContentAsString write SetContentAsString; end; - IBoldStringRepresentable = interface(IBoldNullableValue) - ['{67C57AC7-621B-11D2-AFF7-006008F62CFF}'] - function GetStringRepresentation(representation:integer): String; - procedure SetStringRepresentation(Representation: integer; const NewValue: String); - property StringRepresentation[representation: integer]: String read GetStringRepresentation write SetStringRepresentation; + IBoldAnsiStringContent = interface(IBoldStringContent) + ['{67C57ADA-621B-11D2-AFF7-006008F62CFF}'] + procedure SetContentAsAnsiString(const NewValue: TBoldAnsiString); + function GetContentAsAnsiString: TBoldAnsiString; + property asAnsiString: TBoldAnsiString read GetContentAsAnsiString write SetContentAsAnsiString; end; - IBoldIntegerContent = interface(IBoldNullableValue) + IBoldUnicodeStringContent = interface(IBoldStringContent) + ['{67C57ADB-621B-11D2-AFF7-006008F62CFF}'] + procedure SetContentAsUnicodeString(const NewValue: TBoldUnicodeString); + function GetContentAsUnicodeString: TBoldUnicodeString; + property asUnicodeString: TBoldUnicodeString read GetContentAsUnicodeString write SetContentAsUnicodeString; + end; + + IBoldVariantReadable = interface(IBoldStringRepresentable) + ['{4284362D-6830-4FB1-87CD-AEED41E57192}'] + function GetAsVariant: Variant; + property AsVariant: Variant read GetAsVariant; + end; + + IBoldIntegerContent = interface(IBoldStringRepresentable) ['{67C57AC8-621B-11D2-AFF7-006008F62CFF}'] function GetContentAsInteger: Integer; procedure SetContentAsInteger(NewValue: Integer); property asInteger: Integer read GetContentAsInteger write SetContentAsInteger; end; - IBoldFloatContent = interface(IBoldNullableValue) + IBoldFloatContent = interface(IBoldStringRepresentable) ['{67C57AC9-621B-11D2-AFF7-006008F62CFF}'] function GetContentAsFloat: Double; procedure SetContentAsFloat(NewValue: Double); property asFloat: Double read GetContentAsFloat write SetContentAsFloat; end; - IBoldCurrencyContent = interface(IBoldNullableValue) + IBoldCurrencyContent = interface(IBoldStringRepresentable) ['{67C57ACA-621B-11D2-AFF7-006008F62CFF}'] function GetContentAsCurrency: Currency; procedure SetContentAsCurrency(NewValue: Currency); property asCurrency: Currency read GetContentAsCurrency write SetContentAsCurrency; end; - IBoldBooleanContent = interface(IBoldNullableValue) + IBoldBooleanContent = interface(IBoldStringRepresentable) ['{67C57ACB-621B-11D2-AFF7-006008F62CFF}'] function GetContentAsBoolean: Boolean; procedure SetContentAsBoolean(NewValue: Boolean); property asBoolean: Boolean read GetContentAsBoolean write SetContentAsBoolean; end; - IBoldDateContent = interface(IBoldNullableValue) + IBoldDateContent = interface(IBoldStringRepresentable) ['{67C57ACC-621B-11D2-AFF7-006008F62CFF}'] function GetContentAsDate: TDateTime; procedure SetContentAsDate(NewValue: TDateTime); property asDate: TDateTime read GetContentAsDate write SetContentAsDate; end; - IBoldTimeContent = interface(IBoldNullableValue) + IBoldTimeContent = interface(IBoldStringRepresentable) ['{67C57ACD-621B-11D2-AFF7-006008F62CFF}'] function GetContentAsTime: TDateTime; procedure SetContentAsTime(NewValue: TDateTime); property asTime: TDateTime read GetContentAsTime write SetContentAsTime; end; - IBoldDateTimeContent = interface(IBoldNullableValue) + IBoldDateTimeContent = interface(IBoldStringRepresentable) ['{67C57ACE-621B-11D2-AFF7-006008F62CFF}'] function GetContentAsDateTime: TDateTime; procedure SetContentAsDateTime(NewValue: TDateTime); property asDateTime: TDateTime read GetContentAsDateTime write SetContentAsDateTime; end; - IBoldBlobContent = interface(IBoldNullableValue) + IBoldBlobContent = interface(IBoldStringRepresentable) ['{F6CE03A0-6283-11D2-AFF7-006008F62CFF}'] - function GetContentAsBlob: String; - procedure SetContentAsBlob(const NewValue: String); - property asBlob: String read GetContentAsBlob write SetContentAsBlob; + function GetContentAsBlob: TBoldAnsiString; + procedure SetContentAsBlob(const NewValue: TBoldAnsiString); + property asBlob: TBoldAnsiString read GetContentAsBlob write SetContentAsBlob; end; - IBoldTypedBlob = interface(IBoldNullableValue) + IBoldBlobStreamContent = interface(IBoldBlobContent) + ['{193BF532-CEC6-4749-919E-12FB5A9E98E7}'] + procedure BeginSupressEvents; + procedure EndSupressEvents; + function GetBlobAsStream: TStream; + property AsStream: TStream read GetBlobAsStream; + end; + + IBoldTypedBlob = interface(IBoldBlobContent) ['{6EFB7D60-65BF-11D2-AFF7-006008F62CFF}'] function GetContentTypeContent: String; procedure SetContentTypeContent(const NewValue: String); @@ -123,7 +176,7 @@ interface IBoldObjectIdRef = Interface(IBoldValue) ['{E5AD30CD-544F-4941-998B-947DDDC4E698}'] - procedure SetFromId(Id: TBoldObjectId); + procedure SetFromId(Id: TBoldObjectId; Adopt: Boolean); function GetId: TBoldObjectID; function GetOrderNo: integer; procedure SetOrderNo(NewOrder: Integer); @@ -133,7 +186,8 @@ interface IBoldObjectIdListRef = Interface(IBoldValue) ['{2EFDD2F7-F998-4ADB-842B-9AEA65C9E602}'] - procedure SetFromIdList(IdLIst: TBoldObjectIdList); + procedure SetFromIdList(IdList: TBoldObjectIdList); + procedure SetList(IdList: TBoldObjectIdList); function GetIdList(Index: Integer): TBoldObjectID; property IdList[Index: integer]: TBoldObjectID read GetIdList; function GetCount: integer; @@ -165,4 +219,9 @@ interface implementation +uses + BoldRev; + +initialization + end. diff --git a/Source/ValueSpace/Interfaces/BoldValueSpaceInterfaces.pas b/Source/ValueSpace/Interfaces/BoldValueSpaceInterfaces.pas index 38b4e67..0d975ba 100644 --- a/Source/ValueSpace/Interfaces/BoldValueSpaceInterfaces.pas +++ b/Source/ValueSpace/Interfaces/BoldValueSpaceInterfaces.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldValueSpaceInterfaces; interface @@ -20,21 +23,25 @@ interface ['{A90FA286-018A-4032-8392-72EA9213F3F5}'] procedure AllObjectIds(resultList: TBoldObjectIdList; OnlyLoaded: Boolean); procedure ApplytranslationList(IdTranslationList: TBoldIdTranslationList); - procedure ApplyValueSpace(ValueSpace: IBoldValueSpace; IgnorePersistenceState: Boolean); + procedure ApplyValueSpace(const ValueSpace: IBoldValueSpace; IgnorePersistenceState: Boolean); procedure EnsureObjectContents(ObjectId: TBoldObjectId); procedure EnsureObjectId(ObjectId: TBoldObjectId); procedure ExactifyIDs(TranslationList: TBoldIdTranslationList); function GetHasContentsForId(ObjectId: TBoldObjectId): boolean; function GetObjectContentsByObjectId(ObjectId: TBoldObjectId): IBoldObjectContents; function GetEnsuredObjectContentsByObjectId(ObjectId: TBoldObjectId): IBoldObjectContents; + function GetEnsuredObjectContentsByObjectIdAndCheckIfCreated(ObjectId: TBoldObjectId; out aBoldObjectContents: IBoldObjectContents): boolean; property HasContentsForId[ObjectId: TBoldObjectId]: boolean read GetHasContentsForId; property ObjectContentsByObjectId[ObjectId: TBoldObjectId]: IBoldObjectContents read GetObjectContentsByObjectId; property EnsuredObjectContentsByObjectId[ObjectId: TBoldObjectId]: IBoldObjectContents read GetEnsuredObjectContentsByObjectId; + function IdCount: integer; + function IsEmpty: boolean; end; IBoldObjectContents = interface ['{67C57AC5-621B-11D2-AFF7-006008F62CFF}'] procedure EnsureMember(MemberId: TBoldMemberId; const ContentName: string); + function EnsureMemberAndGetValueByIndex(MemberIndex: Integer; const ContentName: string): IBoldValue; function GetBoldExistenceState: TBoldExistenceState; function GetBoldMemberCount: Integer; function GetBoldPersistenceState: TBoldValuePersistenceState; @@ -63,22 +70,23 @@ interface end; -procedure BoldApplyPartialValueSpace(DestVS, SourceVS: IBoldValueSpace; ObjectidList: TBoldObjectIdList; MemberIdList: TBoldMemberIdList; +procedure BoldApplyPartialValueSpace(const DestVS, SourceVS: IBoldValueSpace; ObjectidList: TBoldObjectIdList; MemberIdList: TBoldMemberIdList; ForceCurrent: Boolean; PersistenceStatesToIgnore: TBoldValuePersistenceStateSet = [bvpsInvalid]); + implementation uses SysUtils, BoldGuard, - BoldUtils; + BoldRev; -procedure BoldApplyPartialValueSpace(DestVS, SourceVS: IBoldValueSpace; ObjectidList: TBoldObjectIdList; MemberIdList: TBoldMemberIdList; ForceCurrent: Boolean; PersistenceStatesToIgnore: TBoldValuePersistenceStateSet = [bvpsInvalid]); +procedure BoldApplyPartialValueSpace(const DestVS, SourceVS: IBoldValueSpace; ObjectidList: TBoldObjectIdList; MemberIdList: TBoldMemberIdList; ForceCurrent: Boolean; PersistenceStatesToIgnore: TBoldValuePersistenceStateSet = [bvpsInvalid]); var O, M: integer; SourceObjectContents, DestObjectContents: IBoldObjectContents; - MemberId, OwnMemberId: TBoldMemberId; + MemberId: TBoldMemberId; ObjectId: TBoldObjectId; SourceValue, DestValue: IBoldValue; @@ -86,7 +94,7 @@ procedure BoldApplyPartialValueSpace(DestVS, SourceVS: IBoldValueSpace; Objectid ListToCopy: TBoldObjectIdList; G: IBoldGuard; begin - G := TBoldGuard.Create(OwnIdList, OwnmemberId); + G := TBoldGuard.Create(OwnIdList); if Assigned(ObjectIdList) then ListToCopy := ObjectIdList else @@ -116,8 +124,7 @@ procedure BoldApplyPartialValueSpace(DestVS, SourceVS: IBoldValueSpace; Objectid SourceValue := SourceObjectContents.ValueByMemberId[MemberId]; if assigned(SourceValue) and not (SourceValue.BoldPersistenceState in PersistenceStatesToIgnore) then begin - DestObjectContents.EnsureMember(MemberId, SourceValue.ContentName);; - DestValue := DestObjectContents.ValueByMemberId[MemberId]; + DestValue := DestObjectContents.EnsureMemberAndGetValueByIndex(MemberId.MemberIndex, SourceValue.ContentName);; DestValue.AssignContent(SourceValue); if ForceCurrent then DestValue.BoldPersistenceState := bvpsCurrent; @@ -131,13 +138,10 @@ procedure BoldApplyPartialValueSpace(DestVS, SourceVS: IBoldValueSpace; Objectid SourceValue := SourceObjectContents.ValueByIndex[M]; if assigned(SourceValue) and not (SourceValue.BoldPersistenceState in PersistenceStatesToIgnore) then begin - OwnMemberId := TBoldmemberId.Create(M); - DestObjectContents.EnsureMember(OwnMemberId, SourceValue.ContentName); - DestValue := DestObjectContents.ValueByMemberId[OwnMemberId]; + DestValue := DestObjectContents.EnsureMemberAndGetValueByIndex(M, SourceValue.ContentName); DestValue.AssignContent(SourceValue); if ForceCurrent then DestValue.BoldPersistenceState := bvpsCurrent; - FreeAndNil(OwnmemberId); end; end; end; @@ -145,4 +149,6 @@ procedure BoldApplyPartialValueSpace(DestVS, SourceVS: IBoldValueSpace; Objectid end; end; +initialization + end. diff --git a/Source/ValueSpace/XMLStreaming/BoldDefaultStreamNames.pas b/Source/ValueSpace/XMLStreaming/BoldDefaultStreamNames.pas index b1b11c3..e96f77b 100644 --- a/Source/ValueSpace/XMLStreaming/BoldDefaultStreamNames.pas +++ b/Source/ValueSpace/XMLStreaming/BoldDefaultStreamNames.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldDefaultStreamNames; interface @@ -15,22 +18,43 @@ interface BOLDMEMBERIDLISTNAME = 'BoldMemberIdList'; BOLDIDTRANSLATIONLISTNAME = 'BoldIDTranslationList'; - BoldContentName_String = 'String'; - BoldContentName_Integer = 'Integer'; - BoldContentName_Float = 'Float'; - BoldContentName_Currency = 'Currency'; - BoldContentName_Blob = 'Blob'; - BoldContentName_TypedBlob = 'TypedBlob'; - BoldContentName_DateTime = 'DateTime'; - BoldContentName_Date = 'Date'; - BoldContentName_Time = 'Time'; - BoldContentName_Boolean = 'Boolean'; - - BoldContentName_ObjectIdRef = 'ObjectIdRef'; - BoldContentName_ObjectIdRefPair = 'ObjectIdRefPair'; - BoldContentName_ObjectIdListRef = 'ObjectIdListRef'; - BoldContentName_ObjectIdListRefPair = 'ObjectIdListRefPair'; +var + BoldContentName_String: string; + BoldContentName_Integer: string; + BoldContentName_Float: string; + BoldContentName_Currency: string; + BoldContentName_Blob: string; + BoldContentName_TypedBlob: string; + BoldContentName_DateTime: string; + BoldContentName_Date: string; + BoldContentName_Time: string; + BoldContentName_Boolean: string; + + BoldContentName_ObjectIdRef: string; + BoldContentName_ObjectIdRefPair: string; + BoldContentName_ObjectIdListRef: string; + BoldContentName_ObjectIdListRefPair: string; implementation +uses + BoldSharedStrings, + BoldRev; + +initialization + BoldContentName_ObjectIdRef := BoldSharedStringManager.GetSharedString('ObjectIdRef'); + BoldContentName_ObjectIdRefPair := BoldSharedStringManager.GetSharedString('ObjectIdRefPair'); + BoldContentName_ObjectIdListRef := BoldSharedStringManager.GetSharedString('ObjectIdListRef'); + BoldContentName_ObjectIdListRefPair := BoldSharedStringManager.GetSharedString('ObjectIdListRefPair'); + BoldContentName_String := BoldSharedStringManager.GetSharedString('String'); + BoldContentName_Integer := BoldSharedStringManager.GetSharedString('Integer'); + BoldContentName_Float := BoldSharedStringManager.GetSharedString('Float'); + BoldContentName_Currency := BoldSharedStringManager.GetSharedString('Currency'); + BoldContentName_Blob := BoldSharedStringManager.GetSharedString('Blob'); + BoldContentName_TypedBlob := BoldSharedStringManager.GetSharedString('TypedBlob'); + BoldContentName_DateTime := BoldSharedStringManager.GetSharedString('DateTime'); + BoldContentName_Date := BoldSharedStringManager.GetSharedString('Date'); + BoldContentName_Time := BoldSharedStringManager.GetSharedString('Time'); + BoldContentName_Boolean := BoldSharedStringManager.GetSharedString('Boolean'); + end. diff --git a/Source/ValueSpace/XMLStreaming/BoldDefaultXMLStreaming.pas b/Source/ValueSpace/XMLStreaming/BoldDefaultXMLStreaming.pas index f4e288d..91a7d2b 100644 --- a/Source/ValueSpace/XMLStreaming/BoldDefaultXMLStreaming.pas +++ b/Source/ValueSpace/XMLStreaming/BoldDefaultXMLStreaming.pas @@ -1,3 +1,6 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldDefaultXMLStreaming; interface @@ -72,8 +75,8 @@ TBoldXMLMemberStreamer = class(TBoldXMLModelElementStreamer) public constructor Create(MoldMember: TMoldMember; Owner: TBoldXMLClassStreamer); destructor Destroy; override; - procedure WriteValue(Node: TBoldXMLNode; Value: IBoldValue); - procedure ReadValue(Node: TBoldXMLNode; Value: IBoldValue); + procedure WriteValue(Node: TBoldXMLNode; const Value: IBoldValue); + procedure ReadValue(Node: TBoldXMLNode; const Value: IBoldValue); property TypeStreamName: string read fTypeStreamName; property Persistent: Boolean read fPersistent; property MemberId: TBoldMemberId read fMemberId; @@ -86,14 +89,14 @@ TBoldXMLClassStreamer = class(TBoldXMLModelElementStreamer) fMemberStreamers: TBoldXMLModelElementStreamerList; fOwner: TBoldDefaultXMLStreamManager; function GetMemberStreamer(Index: Integer): TBoldXMLMemberStreamer; - function GetMemberStreamerByName(Name: string): TBoldXMLMemberStreamer; + function GetMemberStreamerByName(const Name: string): TBoldXMLMemberStreamer; public constructor Create(MoldClass: TMoldClass; Owner: TBoldDefaultXMLStreamManager); destructor Destroy; override; - procedure WriteObject(Node: TBoldXMLNode; ObjectContents: IBoldObjectContents; ObjectId: TBoldObjectId; MemberIdList: TBoldMemberIdList); - procedure ReadObject(Node: TBoldXMLNode; ValueSpace: IBoldValueSpace); + procedure WriteObject(Node: TBoldXMLNode; const ObjectContents: IBoldObjectContents; ObjectId: TBoldObjectId; MemberIdList: TBoldMemberIdList); + procedure ReadObject(Node: TBoldXMLNode; const ValueSpace: IBoldValueSpace); property MemberStreamers[Index: integer]: TBoldXMLMemberStreamer read GetMemberStreamer; - property MemberStreamerByName[Name: String]: TBoldXMLMemberStreamer read GetMemberStreamerByName; + property MemberStreamerByName[const Name: String]: TBoldXMLMemberStreamer read GetMemberStreamerByName; end; { TBoldDefaultXMLStreamManager } @@ -105,15 +108,15 @@ TBoldDefaultXMLStreamManager = class(TBoldXMLStreamManager) fPersistenceStatesToBeStreamed: TBoldValuePersistenceStateSet; fPersistenceStatesToOverwrite: TBoldValuePersistenceStateSet; function GetClassStreamer(TopSortedIndex: Integer): TBoldXMLClassStreamer; - function GetClassStreamerByName(Name: string): TBoldXMLClassStreamer; + function GetClassStreamerByName(const Name: string): TBoldXMLClassStreamer; public constructor Create(Registry: TBoldXMLStreamerRegistry; Model: TMoldModel); destructor Destroy; override; - procedure WriteValueSpace(ValueSpace: IBoldValueSpace; IdList: TBoldObjectIdList; MemberIdList: TBoldMemberIdList; Node: TBoldXMLNode); - procedure ReadValueSpace(ValueSpace: IBoldValueSpace; Node: TBoldXMLNode); + procedure WriteValueSpace(const ValueSpace: IBoldValueSpace; IdList: TBoldObjectIdList; MemberIdList: TBoldMemberIdList; Node: TBoldXMLNode); + procedure ReadValueSpace(const ValueSpace: IBoldValueSpace; Node: TBoldXMLNode); property Model: TMoldModel read fModel; property ClassStreamers[TopSortedIndex: Integer]: TBoldXMLClassStreamer read GetClassStreamer; - property ClassStreamerByName[Name: string]: TBoldXMLClassStreamer read GetClassStreamerByName; + property ClassStreamerByName[const Name: string]: TBoldXMLClassStreamer read GetClassStreamerByName; property IgnorePersistenceState: Boolean read fIgnorePersistenceState write fIgnorePersistenceState; property PersistenceStatesToOverwrite: TBoldValuePersistenceStateSet read fPersistenceStatesToOverwrite write fPersistenceStatesToOverwrite; property PersistenceStatesToBeStreamed: TBoldValuePersistenceStateSet read fPersistenceStatesToBeStreamed write fPersistenceStatesToBeStreamed; @@ -122,151 +125,149 @@ TBoldDefaultXMLStreamManager = class(TBoldXMLStreamManager) { TBoldXMLValueStreamer } TBoldXMLValueStreamer = class(TBoldXMLInterfaceStreamer) public - procedure WriteInterface(Item: IBoldStreamable; Node: TBoldXMLNode); override; - procedure ReadInterface(Item: IBoldStreamable; Node: TBoldXMLNode); override; + procedure WriteInterface(const Item: IBoldStreamable; Node: TBoldXMLNode); override; + procedure ReadInterface(const Item: IBoldStreamable; Node: TBoldXMLNode); override; end; { TBoldXMLNullableValueStreamer } TBoldXMLNullableValueStreamer = class(TBoldXMLValueStreamer) protected - procedure WriteContent(Item: IBoldValue; Node: TBoldXMLNode); virtual; - procedure ReadContent(Item: IBoldValue; Node: TBoldXMLNode); virtual; + procedure WriteContent(const Item: IBoldValue; Node: TBoldXMLNode); virtual; + procedure ReadContent(const Item: IBoldValue; Node: TBoldXMLNode); virtual; public - procedure WriteInterface(Item: IBoldStreamable; Node: TBoldXMLNode); override; - procedure ReadInterface(Item: IBoldStreamable; Node: TboldXMLNode); override; + procedure WriteInterface(const Item: IBoldStreamable; Node: TBoldXMLNode); override; + procedure ReadInterface(const Item: IBoldStreamable; Node: TboldXMLNode); override; end; { TBoldXMLStringContentStreamer } TBoldXMLStringContentStreamer = class(TBoldXMLNullableValueStreamer) protected function GetStreamName: string; override; - procedure WriteContent(Item: IBoldValue; Node: TBoldXMLNode); override; - procedure ReadContent(Item: IBoldValue; Node: TBoldXMLNode); override; + procedure WriteContent(const Item: IBoldValue; Node: TBoldXMLNode); override; + procedure ReadContent(const Item: IBoldValue; Node: TBoldXMLNode); override; end; { TBoldXMLIntegerContentStreamer } TBoldXMLIntegerContentStreamer = class(TBoldXMLNullableValueStreamer) protected function GetStreamName: string; override; - procedure WriteContent(Item: IBoldValue; Node: TBoldXMLNode); override; - procedure ReadContent(Item: IBoldValue; Node: TBoldXMLNode); override; + procedure WriteContent(const Item: IBoldValue; Node: TBoldXMLNode); override; + procedure ReadContent(const Item: IBoldValue; Node: TBoldXMLNode); override; end; { TBoldXMLFloatContentStreamer } TBoldXMLFloatContentStreamer = class(TBoldXMLNullableValueStreamer) protected function GetStreamName: string; override; - procedure WriteContent(Item: IBoldValue; Node: TBoldXMLNode); override; - procedure ReadContent(Item: IBoldValue; Node: TBoldXMLNode); override; + procedure WriteContent(const Item: IBoldValue; Node: TBoldXMLNode); override; + procedure ReadContent(const Item: IBoldValue; Node: TBoldXMLNode); override; end; { TBoldXMLCurrencyContentStreamer } TBoldXMLCurrencyContentStreamer = class(TBoldXMLNullableValueStreamer) protected function GetStreamName: string; override; - procedure WriteContent(Item: IBoldValue; Node: TBoldXMLNode); override; - procedure ReadContent(Item: IBoldValue; Node: TBoldXMLNode); override; + procedure WriteContent(const Item: IBoldValue; Node: TBoldXMLNode); override; + procedure ReadContent(const Item: IBoldValue; Node: TBoldXMLNode); override; end; { TBoldXMLBooleanContentStreamer } TBoldXMLBooleanContentStreamer = class(TBoldXMLNullableValueStreamer) protected function GetStreamName: string; override; - procedure WriteContent(Item: IBoldValue; Node: TBoldXMLNode); override; - procedure ReadContent(Item: IBoldValue; Node: TBoldXMLNode); override; + procedure WriteContent(const Item: IBoldValue; Node: TBoldXMLNode); override; + procedure ReadContent(const Item: IBoldValue; Node: TBoldXMLNode); override; end; { TBoldXMLDateContentStreamer } TBoldXMLDateContentStreamer = class(TBoldXMLNullableValueStreamer) protected function GetStreamName: string; override; - procedure WriteContent(Item: IBoldValue; Node: TBoldXMLNode); override; - procedure ReadContent(Item: IBoldValue; Node: TBoldXMLNode); override; + procedure WriteContent(const Item: IBoldValue; Node: TBoldXMLNode); override; + procedure ReadContent(const Item: IBoldValue; Node: TBoldXMLNode); override; end; { TBoldXMLTimeContentStreamer } TBoldXMLTimeContentStreamer = class(TBoldXMLNullableValueStreamer) protected function GetStreamName: string; override; - procedure WriteContent(Item: IBoldValue; Node: TBoldXMLNode); override; - procedure ReadContent(Item: IBoldValue; Node: TBoldXMLNode); override; + procedure WriteContent(const Item: IBoldValue; Node: TBoldXMLNode); override; + procedure ReadContent(const Item: IBoldValue; Node: TBoldXMLNode); override; end; { TBoldXMLDateTimeContentStreamer } TBoldXMLDateTimeContentStreamer = class(TBoldXMLNullableValueStreamer) protected function GetStreamName: string; override; - procedure WriteContent(Item: IBoldValue; Node: TBoldXMLNode); override; - procedure ReadContent(Item: IBoldValue; Node: TBoldXMLNode); override; + procedure WriteContent(const Item: IBoldValue; Node: TBoldXMLNode); override; + procedure ReadContent(const Item: IBoldValue; Node: TBoldXMLNode); override; end; { TBoldXMLBlobContentStreamer } TBoldXMLBlobContentStreamer = class(TBoldXMLNullableValueStreamer) protected function GetStreamName: string; override; - procedure WriteContent(Item: IBoldValue; Node: TBoldXMLNode); override; - procedure ReadContent(Item: IBoldValue; Node: TBoldXMLNode); override; + procedure WriteContent(const Item: IBoldValue; Node: TBoldXMLNode); override; + procedure ReadContent(const Item: IBoldValue; Node: TBoldXMLNode); override; end; { TBoldXMLTypedBlobStreamer } TBoldXMLTypedBlobStreamer = class(TBoldXMLBlobContentStreamer) protected function GetStreamName: string; override; - procedure WriteContent(Item: IBoldValue; Node: TBoldXMLNode); override; - procedure ReadContent(Item: IBoldValue; Node: TBoldXMLNode); override; + procedure WriteContent(const Item: IBoldValue; Node: TBoldXMLNode); override; + procedure ReadContent(const Item: IBoldValue; Node: TBoldXMLNode); override; end; { TBoldXMLRoleStreamer } TBoldXMLRoleStreamer = class(TBoldXMLValueStreamer) protected - procedure WriteContent(Item: IBoldValue; Node: TBoldXMLNode); virtual; - procedure ReadContent(Item: IBoldValue; Node: TBoldXMLNode); virtual; + procedure WriteContent(const Item: IBoldValue; Node: TBoldXMLNode); virtual; + procedure ReadContent(const Item: IBoldValue; Node: TBoldXMLNode); virtual; public - procedure WriteInterface(Item: IBoldStreamable; Node: TBoldXMLNode); override; - procedure ReadInterface(Item: IBoldStreamable; Node: TBoldXMLNode); override; + procedure WriteInterface(const Item: IBoldStreamable; Node: TBoldXMLNode); override; + procedure ReadInterface(const Item: IBoldStreamable; Node: TBoldXMLNode); override; end; { TBoldXMLIdRefStreamer } TBoldXMLIdRefStreamer = class(TBoldXMLRoleStreamer) protected function GetStreamName: string; override; - procedure WriteContent(Item: IBoldValue; Node: TBoldXMLNode); override; - procedure ReadContent(Item: IBoldValue; Node: TBoldXMLNode); override; + procedure WriteContent(const Item: IBoldValue; Node: TBoldXMLNode); override; + procedure ReadContent(const Item: IBoldValue; Node: TBoldXMLNode); override; end; { TBoldXMLIdRefPairStreamer } TBoldXMLIdRefPairStreamer = class(TBoldXMLRoleStreamer) protected function GetStreamName: string; override; - procedure WriteContent(Item: IBoldValue; Node: TBoldXMLNode); override; - procedure ReadContent(Item: IBoldValue; Node: TBoldXMLNode); override; + procedure WriteContent(const Item: IBoldValue; Node: TBoldXMLNode); override; + procedure ReadContent(const Item: IBoldValue; Node: TBoldXMLNode); override; end; { TBoldXMLIdListRefStreamer } TBoldXMLIdListRefStreamer = class(TBoldXMLRoleStreamer) protected function GetStreamName: string; override; - procedure WriteContent(Item: IBoldValue; Node: TBoldXMLNode); override; - procedure ReadContent(Item: IBoldValue; Node: TBoldXMLNode); override; + procedure WriteContent(const Item: IBoldValue; Node: TBoldXMLNode); override; + procedure ReadContent(const Item: IBoldValue; Node: TBoldXMLNode); override; end; { TBoldXMLIdListRefPairStreamer } TBoldXMLIdListRefPairStreamer = class(TBoldXMLRoleStreamer) protected function GetStreamName: string; override; - procedure WriteContent(Item: IBoldValue; Node: TBoldXMLNode); override; - procedure ReadContent(Item: IBoldValue; Node: TBoldXMLNode); override; + procedure WriteContent(const Item: IBoldValue; Node: TBoldXMLNode); override; + procedure ReadContent(const Item: IBoldValue; Node: TBoldXMLNode); override; end; implementation uses BoldHashIndexes, - MSXML_TLB, + {$IFDEF OXML}OXmlPDOM{$ELSE}MSXML_TLB{$ENDIF}, SysUtils, - ValueSpaceConst, BoldDefaultStreamNames; -// BoldUtils; const BoldNodeName_persistencestate = 'persistencestate'; @@ -320,40 +321,60 @@ destructor TBoldDefaultXMLStreamManager.Destroy; function TBoldDefaultXMLStreamManager.GetClassStreamer(TopSortedIndex: Integer): TBoldXMLClassStreamer; begin if TopSortedIndex >= fClassStreamers.Count then - raise EBold.CreateFmt(sInvalidIndex, [classname]); + raise EBold.CreateFmt('%s.GetClassStreamer: Not a valid index', [classname]); result := TBoldXMLClassStreamer(fClassStreamers.Items[TopSortedIndex]); end; -function TBoldDefaultXMLStreamManager.GetClassStreamerByName(Name: string): TBoldXMLClassStreamer; +function TBoldDefaultXMLStreamManager.GetClassStreamerByName(const Name: string): TBoldXMLClassStreamer; begin result := fClassStreamers.StreamerByName[Name] as TBoldXMLClassStreamer; if not assigned(result) then - raise EBold.CreateFmt(sUnrecognizedClassName, [classname, 'GetClassStreamerByName', name]); // Do not localize + raise EBold.CreateFmt('%s.GetClassStreamerByName: Unrecognized class name %s', [classname, name]); end; -procedure TBoldDefaultXMLStreamManager.ReadValueSpace(ValueSpace: IBoldValueSpace; Node: TBoldXMLNode); +procedure TBoldDefaultXMLStreamManager.ReadValueSpace(const ValueSpace: IBoldValueSpace; Node: TBoldXMLNode); var aSubNode: TBoldXMLNode; + {$IFDEF OXML} + aNodeListEnumerator: TXMLChildNodeListEnumerator; + aNode: PXMLNode; + {$ELSE} aNodeList: IXMLDomNodeList; aNode: IXMLDomNode; + {$ENDIF} begin - if not assigned(ValueSpace) then + if not assigned(ValueSpace) then begin exit; + end; + {$IFDEF OXML} + aNodeListEnumerator := Node.XMLDomElement.ChildNodes.GetEnumerator; + try + while aNodeListEnumerator.MoveNext do + begin + aNode := aNodeListEnumerator.Current; + aSubNode := TBoldXMLNode.Create(Node.Manager, aNode, nil); + ClassStreamerByName[aSubNode.Accessor].ReadObject(aSubNode, ValueSpace); + aSubNode.Free; + end; + finally + aNodeListEnumerator.Free; + end; + {$ELSE} aNodeList := Node.XMLDomElement.childNodes; aNode := aNodeList.nextNode; - while assigned(aNode) do - begin + while assigned(aNode) do begin aSubNode := TBoldXMLNode.Create(Node.Manager, aNode as IXMLDOMElement, nil); ClassStreamerByName[aSubNode.Accessor].ReadObject(aSubNode, ValueSpace); aSubNode.Free; aNode := aNodeList.nextNode; end; + {$ENDIF} end; -procedure TBoldDefaultXMLStreamManager.WriteValueSpace(ValueSpace: IBoldValueSpace; IdList: TBoldObjectIdList; +procedure TBoldDefaultXMLStreamManager.WriteValueSpace(const ValueSpace: IBoldValueSpace; IdList: TBoldObjectIdList; MemberIdList: TBoldMemberIdList; Node: TBoldXMLNode); var i: integer; @@ -373,7 +394,7 @@ procedure TBoldDefaultXMLStreamManager.WriteValueSpace(ValueSpace: IBoldValueSpa { TBoldXMLValueStreamer } -procedure TBoldXMLValueStreamer.ReadInterface(Item: IBoldStreamable; Node: TBoldXMLNode); +procedure TBoldXMLValueStreamer.ReadInterface(const Item: IBoldStreamable; Node: TBoldXMLNode); var SubNode: TBoldXMLNode; begin @@ -381,28 +402,39 @@ procedure TBoldXMLValueStreamer.ReadInterface(Item: IBoldStreamable; Node: TBold if not (Node.Manager as TBoldDefaultXMLStreamManager).IgnorePersistenceState then begin SubNode := Node.GetSubNode(BoldNodeName_persistencestate); - (Item as IBoldValue).BoldPersistenceState := TBoldValuePersistenceState(SubNode.ReadInteger); - SubNode.Free; + if Assigned(SubNode) then begin + (Item as IBoldValue).BoldPersistenceState := + TBoldValuePersistenceState(SubNode.ReadInteger); + SubNode.Free; + end else begin + // No node found -> set default BoldPersistenceState (bvpsCurrent) + (Item as IBoldValue).BoldPersistenceState := bvpsCurrent; + end; end; end; -procedure TBoldXMLValueStreamer.WriteInterface(Item: IBoldStreamable; Node: TBoldXMLNode); +procedure TBoldXMLValueStreamer.WriteInterface(const Item: IBoldStreamable; Node: TBoldXMLNode); var SubNode: TBoldXMLNode; + iPersistenceState: Integer; begin inherited; - SubNode := Node.NewSubNode(BoldNodeName_persistencestate); - SubNode.WriteInteger(Integer((Item as IBoldValue).BoldPersistenceState)); - SubNode.Free; + iPersistenceState := Integer((Item as IBoldValue).BoldPersistenceState); + // Only write BoldPersistenceState other than bvpsCurrent, to minimize XML size + if iPersistenceState <> 0 then begin + SubNode := Node.NewSubNode(BoldNodeName_persistencestate); + SubNode.WriteInteger(iPersistenceState); + SubNode.Free; + end; end; { TBoldXMLNullableValueStreamer } -procedure TBoldXMLNullableValueStreamer.ReadContent(Item: IBoldValue; Node: TBoldXMLNode); +procedure TBoldXMLNullableValueStreamer.ReadContent(const Item: IBoldValue; Node: TBoldXMLNode); begin end; -procedure TBoldXMLNullableValueStreamer.ReadInterface(Item: IBoldStreamable; Node: TboldXMLNode); +procedure TBoldXMLNullableValueStreamer.ReadInterface(const Item: IBoldStreamable; Node: TboldXMLNode); var ContentNode: TBoldXMLNode; begin @@ -415,11 +447,11 @@ procedure TBoldXMLNullableValueStreamer.ReadInterface(Item: IBoldStreamable; Nod ContentNode.Free; end; -procedure TBoldXMLNullableValueStreamer.WriteContent(Item: IBoldValue; Node: TBoldXMLNode); +procedure TBoldXMLNullableValueStreamer.WriteContent(const Item: IBoldValue; Node: TBoldXMLNode); begin end; -procedure TBoldXMLNullableValueStreamer.WriteInterface(Item: IBoldStreamable; Node: TBoldXMLNode); +procedure TBoldXMLNullableValueStreamer.WriteInterface(const Item: IBoldStreamable; Node: TBoldXMLNode); var ContentNode: TBoldXMLNode; begin @@ -439,13 +471,13 @@ function TBoldXMLStringContentStreamer.GetStreamName: string; result := BoldContentName_String; end; -procedure TBoldXMLStringContentStreamer.ReadContent(Item: IBoldValue; Node: TBoldXMLNode); +procedure TBoldXMLStringContentStreamer.ReadContent(const Item: IBoldValue; Node: TBoldXMLNode); begin inherited; (Item as IBoldStringContent).asString := Node.ReadString; end; -procedure TBoldXMLStringContentStreamer.WriteContent(Item: IBoldValue; Node: TBoldXMLNode); +procedure TBoldXMLStringContentStreamer.WriteContent(const Item: IBoldValue; Node: TBoldXMLNode); begin inherited; Node.WriteString((Item as IBoldStringContent).asString); @@ -458,13 +490,13 @@ function TBoldXMLIntegerContentStreamer.GetStreamName: string; result := BoldContentName_Integer; end; -procedure TBoldXMLIntegerContentStreamer.ReadContent(Item: IBoldValue; Node: TBoldXMLNode); +procedure TBoldXMLIntegerContentStreamer.ReadContent(const Item: IBoldValue; Node: TBoldXMLNode); begin inherited; (Item as IBoldIntegerContent).asInteger := Node.ReadInteger; end; -procedure TBoldXMLIntegerContentStreamer.WriteContent(Item: IBoldValue; Node: TBoldXMLNode); +procedure TBoldXMLIntegerContentStreamer.WriteContent(const Item: IBoldValue; Node: TBoldXMLNode); begin inherited; Node.WriteInteger((Item as IBoldIntegerContent).asInteger); @@ -472,11 +504,11 @@ procedure TBoldXMLIntegerContentStreamer.WriteContent(Item: IBoldValue; Node: TB { TBoldXMLRefStreamer } -procedure TBoldXMLRoleStreamer.ReadContent(Item: IBoldValue; Node: TBoldXMLNode); +procedure TBoldXMLRoleStreamer.ReadContent(const Item: IBoldValue; Node: TBoldXMLNode); begin end; -procedure TBoldXMLRoleStreamer.ReadInterface(Item: IBoldStreamable; Node: TBoldXMLNode); +procedure TBoldXMLRoleStreamer.ReadInterface(const Item: IBoldStreamable; Node: TBoldXMLNode); var ContentNode: TBoldXMLNode; begin @@ -486,11 +518,11 @@ procedure TBoldXMLRoleStreamer.ReadInterface(Item: IBoldStreamable; Node: TBoldX ContentNode.Free; end; -procedure TBoldXMLRoleStreamer.WriteContent(Item: IBoldValue; Node: TBoldXMLNode); +procedure TBoldXMLRoleStreamer.WriteContent(const Item: IBoldValue; Node: TBoldXMLNode); begin end; -procedure TBoldXMLRoleStreamer.WriteInterface(Item: IBoldStreamable; Node: TBoldXMLNode); +procedure TBoldXMLRoleStreamer.WriteInterface(const Item: IBoldStreamable; Node: TBoldXMLNode); var ContentNode: TBoldXMLNode; begin @@ -507,7 +539,7 @@ function TBoldXMLIdRefStreamer.GetStreamName: string; result := BoldContentName_ObjectIdRef; end; -procedure TBoldXMLIdRefStreamer.ReadContent(Item: IBoldValue; Node: TBoldXMLNode); +procedure TBoldXMLIdRefStreamer.ReadContent(const Item: IBoldValue; Node: TBoldXMLNode); var SubNode: TBoldXMLNode; anId: TBoldObjectId; @@ -516,17 +548,15 @@ procedure TBoldXMLIdRefStreamer.ReadContent(Item: IBoldValue; Node: TBoldXMLNode inherited; anIdRef := Item as IBoldObjectIdRef; anId := Node.ReadSubNodeObject(BoldNodeName_id , '') as TBoldObjectId; - anIdRef.SetFromId(anId); - anId.Free; + anIdRef.SetFromId(anId, true); SubNode := Node.GetSubNode(BoldNodeName_OrderNo); if assigned(SubNode) then anIdRef.OrderNo := SubNode.ReadInteger; SubNode.Free; end; -procedure TBoldXMLIdRefStreamer.WriteContent(Item: IBoldValue; Node: TBoldXMLNode); +procedure TBoldXMLIdRefStreamer.WriteContent(const Item: IBoldValue; Node: TBoldXMLNode); var -// SubNode: TBoldXMLNode; anIdRef: IBoldObjectIdRef; begin inherited; @@ -545,7 +575,7 @@ function TBoldXMLIdRefPairStreamer.GetStreamName: string; result := BoldContentName_ObjectIdRefPair; end; -procedure TBoldXMLIdRefPairStreamer.ReadContent(Item: IBoldValue; Node: TBoldXMLNode); +procedure TBoldXMLIdRefPairStreamer.ReadContent(const Item: IBoldValue; Node: TBoldXMLNode); var SubNode: TBoldXMLNode; Id1, Id2: TBoldObjectId; @@ -562,7 +592,7 @@ procedure TBoldXMLIdRefPairStreamer.ReadContent(Item: IBoldValue; Node: TBoldXML Id2.Free; end; -procedure TBoldXMLIdRefPairStreamer.WriteContent(Item: IBoldValue; Node: TBoldXMLNode); +procedure TBoldXMLIdRefPairStreamer.WriteContent(const Item: IBoldValue; Node: TBoldXMLNode); var SubNode: TBoldXMLNode; begin @@ -582,7 +612,7 @@ function TBoldXMLIdListRefStreamer.GetStreamName: string; result := BoldContentName_ObjectIdListRef; end; -procedure TBoldXMLIdListRefStreamer.ReadContent(Item: IBoldValue; Node: TBoldXMLNode); +procedure TBoldXMLIdListRefStreamer.ReadContent(const Item: IBoldValue; Node: TBoldXMLNode); var SubNode: TBoldXMLNode; anIdList: TBoldObjectIdList; @@ -595,7 +625,7 @@ procedure TBoldXMLIdListRefStreamer.ReadContent(Item: IBoldValue; Node: TBoldXML anIdList.Free; end; -procedure TBoldXMLIdListRefStreamer.WriteContent(Item: IBoldValue; Node: TBoldXMLNode); +procedure TBoldXMLIdListRefStreamer.WriteContent(const Item: IBoldValue; Node: TBoldXMLNode); var SubNode: TBoldXMLNode; anIdList: TBoldobjectIdList; @@ -620,7 +650,7 @@ function TBoldXMLIdListRefPairStreamer.GetStreamName: string; result := BoldContentName_ObjectIdListRefPair; end; -procedure TBoldXMLIdListRefPairStreamer.ReadContent(Item: IBoldValue; Node: TBoldXMLNode); +procedure TBoldXMLIdListRefPairStreamer.ReadContent(const Item: IBoldValue; Node: TBoldXMLNode); var SubNode: TBoldXMLNode; IdList1, IdList2: TBoldObjectIdList; @@ -637,7 +667,7 @@ procedure TBoldXMLIdListRefPairStreamer.ReadContent(Item: IBoldValue; Node: TBol IdList2.Free; end; -procedure TBoldXMLIdListRefPairStreamer.WriteContent(Item: IBoldValue; Node: TBoldXMLNode); +procedure TBoldXMLIdListRefPairStreamer.WriteContent(const Item: IBoldValue; Node: TBoldXMLNode); var SubNode: TBoldXMLNode; anIdList: TBoldobjectIdList; @@ -683,7 +713,7 @@ constructor TBoldXMLClassStreamer.Create(MoldClass: TMoldClass; Owner: TBoldDefa fExpressionName := MoldClass.ExpandedExpressionName; fMemberStreamers := TBoldXMLModelElementStreamerList.Create; for i := 0 to MoldClass.AllBoldMembers.Count - 1 do - fMemberStreamers.Add(TBoldXMLMemberStreamer.Create(MoldClass.AllBoldMembers[i], self)); + fMemberStreamers.Add(TBoldXMLMemberStreamer.Create(MoldClass.AllBoldMembers[i], self)); end; destructor TBoldXMLClassStreamer.Destroy; @@ -700,23 +730,28 @@ function TBoldXMLClassStreamer.GetMemberStreamer(Index: Integer): TBoldXMLMember result := nil; end; -function TBoldXMLClassStreamer.GetMemberStreamerByName(Name: string): TBoldXMLMemberStreamer; +function TBoldXMLClassStreamer.GetMemberStreamerByName(const Name: string): TBoldXMLMemberStreamer; begin result := fMemberStreamers.StreamerByName[Name] as TBoldXMLMemberStreamer; if not assigned(result) then - raise EBold.CreateFmt(sUnrecognizedClassName, [classname, 'GetMemberStreamerByName', name]); // do not localize + raise EBold.CreateFmt('%s.GetMemberStreamerByName: Unrecognized class name %s', [classname, name]); end; -procedure TBoldXMLClassStreamer.ReadObject(Node: TBoldXMLNode; ValueSpace: IBoldValueSpace); +procedure TBoldXMLClassStreamer.ReadObject(Node: TBoldXMLNode; const ValueSpace: IBoldValueSpace); var aSubNode: TBoldXMLNode; MembersNode: TBoldXMLNode; anId: TboldObjectId; ObjectContents: IBoldObjectContents; + aMemberStreamer: TBoldXMLMemberStreamer; + {$IFDEF OXML} + aNodeEnumerator: TXMLChildNodeListEnumerator; + aNode: PXMLNode; + {$ELSE} aNodeList: IXMLDomNodeList; aNode: IXMLDomNode; - aMemberStreamer: TBoldXMLMemberStreamer; + {$ENDIF} begin aSubNode := Node.GetSubNode(BoldNodeName_id); anId := aSubNode.ReadObject('') as TBoldObjectId; @@ -726,12 +761,23 @@ procedure TBoldXMLClassStreamer.ReadObject(Node: TBoldXMLNode; ValueSpace: IBold if not fOwner.IgnorePersistenceState then begin aSubNode := Node.GetSubNode(BoldNodeName_persistencestate); - ObjectContents.BoldPersistenceState := TBoldValuePersistenceState(aSubNode.ReadInteger); - aSubNode.Free; + if Assigned(aSubNode) then begin + ObjectContents.BoldPersistenceState := TBoldValuePersistenceState(aSubNode.ReadInteger); + aSubNode.Free; + end else begin + // No node found -> set default BoldPersistenceState (bvpsCurrent) + ObjectContents.BoldPersistenceState := bvpsCurrent; + end; end; aSubNode := Node.GetSubNode(BoldNodeName_existencestate); - ObjectContents.BoldExistenceState := TBoldExistenceState(aSubNode.ReadInteger); - aSubNode.Free; + if Assigned(aSubNode) then begin + ObjectContents.BoldExistenceState := TBoldExistenceState(aSubNode.ReadInteger); + aSubNode.Free; + end else begin + // No node found -> set default BoldExistenceState (besExisting) + ObjectContents.BoldExistenceState := besExisting; + end; + aSubNode := Node.GetSubNode(BoldNodeName_timestamp); if assigned(aSubNode) then @@ -748,6 +794,22 @@ procedure TBoldXMLClassStreamer.ReadObject(Node: TBoldXMLNode; ValueSpace: IBold end; MembersNode := Node.GetSubNode(BoldNodeName_members); + {$IFDEF OXML} + aNodeEnumerator := MembersNode.XMLDomElement.ChildNodes.GetEnumerator; + try + while aNodeEnumerator.MoveNext do begin + aNode := aNodeEnumerator.Current; + aSubNode := TBoldXMLNode.Create(Node.Manager, aNode, nil); + aMemberStreamer := MemberStreamerByName[aSubNode.Accessor]; + ObjectContents.EnsureMember(aMemberStreamer.MemberId, aMemberStreamer.TypeStreamName); + aMemberStreamer.ReadValue(aSubNode, ObjectContents.ValueByIndex[aMemberStreamer.Index]); + aSubNode.Free; + end; + finally + aNodeEnumerator.Free; + MembersNode.Free; + end; + {$ELSE} aNodeList := MembersNode.XMLDomElement.childNodes; aNode := aNodeList.nextNode; while assigned(aNode) do @@ -756,20 +818,22 @@ procedure TBoldXMLClassStreamer.ReadObject(Node: TBoldXMLNode; ValueSpace: IBold aMemberStreamer := MemberStreamerByName[aSubNode.Accessor]; ObjectContents.EnsureMember(aMemberStreamer.MemberId, aMemberStreamer.TypeStreamName); aMemberStreamer.ReadValue(aSubNode, ObjectContents.ValueByIndex[aMemberStreamer.Index]); - aSubNode.Free; aNode := aNodeList.nextNode; end; MembersNode.Free; + {$ENDIF} end; procedure TBoldXMLClassStreamer.WriteObject(Node: TBoldXMLNode; - ObjectContents: IBoldObjectContents; ObjectId: TBoldObjectId; MemberIdList: TBoldMemberIdList); + const ObjectContents: IBoldObjectContents; ObjectId: TBoldObjectId; MemberIdList: TBoldMemberIdList); var i: Integer; ObjNode: TBoldXMLNode; MembersNode: TBoldXMLNode; aSubNode: TBoldXMLNode; + iBoldPersistenceState, + iBoldExistenceState: Integer; begin if not assigned(ObjectContents) then exit; @@ -779,15 +843,26 @@ procedure TBoldXMLClassStreamer.WriteObject(Node: TBoldXMLNode; aSubNode := ObjNode.NewSubNode(BoldNodeName_id); aSubNode.WriteObject('', ObjectId); aSubNode.Free; - aSubNode := ObjNode.NewSubNode(BoldNodeName_persistencestate); - aSubNode.WriteInteger(Integer(ObjectContents.BoldPersistenceState)); - aSubNode.Free; - aSubNode := ObjNode.NewSubNode(BoldNodeName_existencestate); - aSubNode.WriteInteger(Integer(ObjectContents.BoldExistenceState)); - aSubNode.Free; - aSubNode := ObjNode.NewSubNode(BoldNodeName_timestamp); - aSubNode.WriteInteger(ObjectContents.TimeStamp); - aSubNode.Free; + iBoldPersistenceState := Integer(ObjectContents.BoldPersistenceState); + // Only write BoldPersistenceState other than bvpsCurrent, to minimize XML size + if iBoldPersistenceState <> 0 then begin + aSubNode := ObjNode.NewSubNode(BoldNodeName_persistencestate); + aSubNode.WriteInteger(iBoldPersistenceState); + aSubNode.Free; + end; + iBoldExistenceState := Integer(ObjectContents.BoldExistenceState); + // Only write BoldExistenceState other than besExisting, to minimize XML size + if iBoldExistenceState <> 1 then begin + aSubNode := ObjNode.NewSubNode(BoldNodeName_existencestate); + aSubNode.WriteInteger(iBoldExistenceState); + aSubNode.Free; + end; + // Onyl write TimeStamp if it is set, to minimize XML size + if ObjectContents.TimeStamp <> -1 then begin + aSubNode := ObjNode.NewSubNode(BoldNodeName_timestamp); + aSubNode.WriteInteger(ObjectContents.TimeStamp); + aSubNode.Free; + end; if ObjectContents.GlobalId <> '' then ObjNode.WriteSubNodeString(BoldNodeName_globalid, ObjectContents.GlobalId); @@ -826,14 +901,14 @@ destructor TBoldXMLMemberStreamer.Destroy; end; procedure TBoldXMLMemberStreamer.ReadValue(Node: TBoldXMLNode; - Value: IBoldValue); + const Value: IBoldValue); begin if assigned(self) and assigned(Value) then if (Value.BoldPersistenceState in fOwner.fOwner.PersistenceStatesToOverwrite) then Node.ReadInterface(TypeStreamName, Value as IBoldStreamable); end; -procedure TBoldXMLMemberStreamer.WriteValue(Node: TBoldXMLNode; Value: IBoldValue); +procedure TBoldXMLMemberStreamer.WriteValue(Node: TBoldXMLNode; const Value: IBoldValue); var aSubNode: TBoldXMLNode; begin @@ -853,12 +928,12 @@ function TBoldXMLFloatContentStreamer.GetStreamName: string; result := BoldContentName_Float; end; -procedure TBoldXMLFloatContentStreamer.ReadContent(Item: IBoldValue; Node: TBoldXMLNode); +procedure TBoldXMLFloatContentStreamer.ReadContent(const Item: IBoldValue; Node: TBoldXMLNode); begin (Item as IBoldFloatContent).asFloat := Node.ReadFloat; end; -procedure TBoldXMLFloatContentStreamer.WriteContent(Item: IBoldValue; Node: TBoldXMLNode); +procedure TBoldXMLFloatContentStreamer.WriteContent(const Item: IBoldValue; Node: TBoldXMLNode); begin Node.WriteFloat((Item as IBoldFloatContent).asFloat); end; @@ -870,12 +945,12 @@ function TBoldXMLCurrencyContentStreamer.GetStreamName: string; result := BoldContentName_Currency; end; -procedure TBoldXMLCurrencyContentStreamer.ReadContent(Item: IBoldValue; Node: TBoldXMLNode); +procedure TBoldXMLCurrencyContentStreamer.ReadContent(const Item: IBoldValue; Node: TBoldXMLNode); begin (Item as IBoldCurrencyContent).asCurrency := Node.ReadCurrency; end; -procedure TBoldXMLCurrencyContentStreamer.WriteContent(Item: IBoldValue; Node: TBoldXMLNode); +procedure TBoldXMLCurrencyContentStreamer.WriteContent(const Item: IBoldValue; Node: TBoldXMLNode); begin Node.WriteCurrency((Item as IBoldCurrencyContent).asCurrency); end; @@ -887,13 +962,13 @@ function TBoldXMLBooleanContentStreamer.GetStreamName: string; result := BoldContentName_Boolean; end; -procedure TBoldXMLBooleanContentStreamer.ReadContent(Item: IBoldValue; +procedure TBoldXMLBooleanContentStreamer.ReadContent(const Item: IBoldValue; Node: TBoldXMLNode); begin (Item as IBoldBooleanContent).asBoolean := Node.ReadBoolean; end; -procedure TBoldXMLBooleanContentStreamer.WriteContent(Item: IBoldValue; +procedure TBoldXMLBooleanContentStreamer.WriteContent(const Item: IBoldValue; Node: TBoldXMLNode); begin Node.WriteBoolean((Item as IBoldBooleanContent).asBoolean); @@ -906,12 +981,12 @@ function TBoldXMLDateContentStreamer.GetStreamName: string; result := BoldContentName_Date; end; -procedure TBoldXMLDateContentStreamer.ReadContent(Item: IBoldValue; Node: TBoldXMLNode); +procedure TBoldXMLDateContentStreamer.ReadContent(const Item: IBoldValue; Node: TBoldXMLNode); begin (Item as IBoldDateContent).asDate := Node.ReadDate; end; -procedure TBoldXMLDateContentStreamer.WriteContent(Item: IBoldValue; Node: TBoldXMLNode); +procedure TBoldXMLDateContentStreamer.WriteContent(const Item: IBoldValue; Node: TBoldXMLNode); begin Node.WriteDate((Item as IBoldDateContent).asDate); end; @@ -923,14 +998,14 @@ function TBoldXMLTimeContentStreamer.GetStreamName: string; result := BoldContentName_Time; end; -procedure TBoldXMLTimeContentStreamer.ReadContent(Item: IBoldValue; Node: TBoldXMLNode); +procedure TBoldXMLTimeContentStreamer.ReadContent(const Item: IBoldValue; Node: TBoldXMLNode); begin (Item as IBoldTimeContent).asTime := Node.ReadTime; end; -procedure TBoldXMLTimeContentStreamer.WriteContent(Item: IBoldValue; Node: TBoldXMLNode); +procedure TBoldXMLTimeContentStreamer.WriteContent(const Item: IBoldValue; Node: TBoldXMLNode); begin - Node.WriteTime((Item as IBoldTimeContent).asTime); + Node.WriteTime((Item as IBoldTimeContent).asTime); end; { TBoldXMLDateTimeContentStreamer } @@ -940,12 +1015,12 @@ function TBoldXMLDateTimeContentStreamer.GetStreamName: string; result := BoldContentName_DateTime; end; -procedure TBoldXMLDateTimeContentStreamer.ReadContent(Item: IBoldValue; Node: TBoldXMLNode); +procedure TBoldXMLDateTimeContentStreamer.ReadContent(const Item: IBoldValue; Node: TBoldXMLNode); begin (Item as IBoldDateTimeContent).asDateTime := Node.ReadDateTime; end; -procedure TBoldXMLDateTimeContentStreamer.WriteContent(Item: IBoldValue; Node: TBoldXMLNode); +procedure TBoldXMLDateTimeContentStreamer.WriteContent(const Item: IBoldValue; Node: TBoldXMLNode); begin Node.WriteDateTime((Item as IBoldDateTimeContent).asDateTime); end; @@ -957,12 +1032,12 @@ function TBoldXMLBlobContentStreamer.GetStreamName: string; result := BoldContentName_Blob; end; -procedure TBoldXMLBlobContentStreamer.ReadContent(Item: IBoldValue; Node: TBoldXMLNode); +procedure TBoldXMLBlobContentStreamer.ReadContent(const Item: IBoldValue; Node: TBoldXMLNode); begin (Item as IBoldBlobContent).asBlob := Node.ReadData; end; -procedure TBoldXMLBlobContentStreamer.WriteContent(Item: IBoldValue; Node: TBoldXMLNode); +procedure TBoldXMLBlobContentStreamer.WriteContent(const Item: IBoldValue; Node: TBoldXMLNode); begin inherited; Node.WriteData((Item as IBoldBlobContent).asBlob); @@ -975,13 +1050,13 @@ function TBoldXMLTypedBlobStreamer.GetStreamName: string; result := BoldContentName_TypedBlob; end; -procedure TBoldXMLTypedBlobStreamer.ReadContent(Item: IBoldValue; Node: TBoldXMLNode); +procedure TBoldXMLTypedBlobStreamer.ReadContent(const Item: IBoldValue; Node: TBoldXMLNode); begin inherited; (Item as IBoldTypedBlob).ContentTypeContent := Node.ReadSubNodeString(BoldNodeName_ContentType); end; -procedure TBoldXMLTypedBlobStreamer.WriteContent(Item: IBoldValue; Node: TBoldXMLNode); +procedure TBoldXMLTypedBlobStreamer.WriteContent(const Item: IBoldValue; Node: TBoldXMLNode); begin inherited; Node.WriteSubNodeString(BoldNodeName_ContentType, (Item as IBoldTypedBlob).ContentTypeContent); @@ -1025,6 +1100,6 @@ initialization TBoldXMLStreamerRegistry.MainStreamerRegistry.RegisterStreamer(TBoldXMLIdListRefPairStreamer.Create); finalization - FreeAndNil(G_MainRegistry); + FreeAndNil(G_MainRegistry); end. From 2251f854e6a0ac31b1afdb3b1005b001cc10e427 Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Fri, 30 Apr 2021 13:56:07 +0300 Subject: [PATCH 002/112] Updated search path for packages to find bold.inc --- Bold.dproj | 35 ++-- BoldAdo.dproj | 131 ++++++++++++ BoldAdvantage.dproj | 130 ++++++++++++ BoldBDE.dproj | 134 +++++++++++++ BoldCom.dproj | 186 ++++++++++++++++++ BoldComGUI.dproj | 185 +++++++++++++++++ BoldDBExpress.dproj | 130 ++++++++++++ BoldDBIsam.dproj | 131 ++++++++++++ BoldDOA.dproj | 131 ++++++++++++ BoldExPe.dproj | 143 ++++++++++++++ BoldIB.dproj | 132 +++++++++++++ BoldMMLink.dproj | 133 +++++++++++++ BoldOLLE.dproj | 134 +++++++++++++ BoldSQLDirect.dproj | 130 ++++++++++++ BoldUDPProp.dproj | 129 ++++++++++++ BoldUml.dproj | 167 ++++++++++++++++ BoldUtility.dproj | 145 ++++++++++++++ BoldVCLGUI.dproj | 178 +++++++++++++++++ BoldXMILink.dproj | 136 +++++++++++++ Source/Common/Include/Bold.inc | 2 +- .../BoldAbstractPartiallyExternalPH.pas | 2 +- 21 files changed, 2600 insertions(+), 24 deletions(-) create mode 100644 BoldAdo.dproj create mode 100644 BoldAdvantage.dproj create mode 100644 BoldBDE.dproj create mode 100644 BoldCom.dproj create mode 100644 BoldComGUI.dproj create mode 100644 BoldDBExpress.dproj create mode 100644 BoldDBIsam.dproj create mode 100644 BoldDOA.dproj create mode 100644 BoldExPe.dproj create mode 100644 BoldIB.dproj create mode 100644 BoldMMLink.dproj create mode 100644 BoldOLLE.dproj create mode 100644 BoldSQLDirect.dproj create mode 100644 BoldUDPProp.dproj create mode 100644 BoldUml.dproj create mode 100644 BoldUtility.dproj create mode 100644 BoldVCLGUI.dproj create mode 100644 BoldXMILink.dproj diff --git a/Bold.dproj b/Bold.dproj index a800311..9e64151 100644 --- a/Bold.dproj +++ b/Bold.dproj @@ -28,6 +28,12 @@ Base true + + true + Cfg_1 + true + true + true Base @@ -61,11 +67,11 @@ CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=;CFBundleName= true false + Source\Common\Include\;$(DCC_UnitSearchPath) CompanyName=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName);FileDescription=$(MSBuildProjectName);ProductName=$(MSBuildProjectName) System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) - 1033 true @@ -80,6 +86,10 @@ 0 0 + + true + CompanyName=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName);FileDescription=$(MSBuildProjectName);ProductName=$(MSBuildProjectName) + true DEBUG;$(DCC_Define) @@ -425,27 +435,8 @@ Bold.dpk - Embarcadero FireDAC Common Components - Embarcadero FireDAC Infx Driver Components - Embarcadero FireDAC ODBC Driver Components - Embarcadero FireDAC Common Driver Components - Embarcadero FireDAC Db2 Driver Components - Embarcadero FireDAC SQL Server Driver Components - Embarcadero FireDAC Oracle Driver Components - Embarcadero FireDAC Database Components - Embarcadero FireDAC Sqlite Driver Components - Embarcadero FireDAC PostgreSQL Driver Components - Embarcadero FireDAC ASA Driver Components - Embarcadero FireDAC MS Access Driver Components - Embarcadero FireDAC IB Driver Components - Embarcadero FireDAC MySQL Driver Components - Embarcadero FireDAC ADS Driver Components - Embarcadero FireDAC DBX Driver Components - Embarcadero FireDAC DataSnap Driver Components - Embarcadero C++Builder Office 2000 Servers Package - Embarcadero C++Builder Office XP Servers Package - Microsoft Office 2000 Sample Automation Server Wrapper Components - Microsoft Office XP Sample Automation Server Wrapper Components + Microsoft Office 2000 Sample Automation Server Wrapper Components + Microsoft Office XP Sample Automation Server Wrapper Components diff --git a/BoldAdo.dproj b/BoldAdo.dproj new file mode 100644 index 0000000..ab4c41b --- /dev/null +++ b/BoldAdo.dproj @@ -0,0 +1,131 @@ + + + {BE726EF9-DAC0-4138-B2C9-AF623827CC4C} + BoldAdo.dpk + True + Debug + 1 + Package + VCL + 19.2 + Win32 + + + true + + + true + Base + true + + + true + Base + true + + + true + Base + true + + + true + Cfg_2 + true + true + + + false + false + false + false + false + 00400000 + true + true + BoldAdo + 1 + false + true + true + true + true + true + Bold 4.0 for Delphi (ADO Support) + 90 + Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;System;Xml;Data;Datasnap;Web;Soap;DUnitX.Loggers.GUI;Data.Win;$(DCC_Namespace) + 2077 + CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=;CFBundleName= + Source\Common\Include\;$(DCC_UnitSearchPath) + + + Winapi;System.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) + Debug + true + CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName) + 1033 + + + RELEASE;$(DCC_Define) + 0 + false + 0 + + + DEBUG;$(DCC_Define) + false + true + + + true + 1033 + CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName) + + + + MainSource + + + + + + + + + + + + Cfg_2 + Base + + + Base + + + Cfg_1 + Base + + + + Delphi.Personality.12 + Package + + + + BoldAdo.dpk + + + Microsoft Office 2000 Sample Automation Server Wrapper Components + Microsoft Office XP Sample Automation Server Wrapper Components + + + + True + False + + + 12 + + + + diff --git a/BoldAdvantage.dproj b/BoldAdvantage.dproj new file mode 100644 index 0000000..4df1e01 --- /dev/null +++ b/BoldAdvantage.dproj @@ -0,0 +1,130 @@ + + + {A770C0F0-9130-4024-8968-458A685FA8A3} + BoldAdvantage.dpk + True + Debug + 1 + Package + VCL + 19.2 + Win32 + + + true + + + true + Base + true + + + true + Base + true + + + true + Base + true + + + true + Cfg_2 + true + true + + + false + false + false + false + false + 00400000 + true + true + BoldAdvantage + 1 + false + true + true + true + true + true + Bold 4.0 for Delphi (dvantage Support) + 90 + Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;System;Xml;Data;Datasnap;Web;Soap;DUnitX.Loggers.GUI;System.Win;$(DCC_Namespace) + 2077 + CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=;CFBundleName= + Source\Common\Include\;$(DCC_UnitSearchPath) + + + Winapi;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) + Debug + true + CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName) + 1033 + + + RELEASE;$(DCC_Define) + 0 + false + 0 + + + DEBUG;$(DCC_Define) + false + true + + + true + 1033 + CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName) + + + + MainSource + + + + + + + + + + + Cfg_2 + Base + + + Base + + + Cfg_1 + Base + + + + Delphi.Personality.12 + Package + + + + BoldAdvantage.dpk + + + Microsoft Office 2000 Sample Automation Server Wrapper Components + Microsoft Office XP Sample Automation Server Wrapper Components + + + + True + False + + + 12 + + + + diff --git a/BoldBDE.dproj b/BoldBDE.dproj new file mode 100644 index 0000000..615bc85 --- /dev/null +++ b/BoldBDE.dproj @@ -0,0 +1,134 @@ + + + {4105301E-57B2-4100-95E6-CFEFFF810168} + BoldBDE.dpk + True + Debug + 1 + Package + VCL + 19.2 + Win32 + + + true + + + true + Base + true + + + true + Base + true + + + true + Base + true + + + true + Cfg_2 + true + true + + + false + false + false + false + false + 00400000 + true + true + BoldBDE + 1 + false + true + true + true + true + true + Bold 4.0 for Delphi (BDE Support) + 90 + Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;System;Xml;Data;Datasnap;Web;Soap;DUnitX.Loggers.GUI;$(DCC_Namespace) + 2077 + CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=;CFBundleName= + Source\Common\Include\;$(DCC_UnitSearchPath) + + + Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) + Debug + true + CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName) + 1033 + + + RELEASE;$(DCC_Define) + 0 + false + 0 + + + DEBUG;$(DCC_Define) + false + true + + + true + 1033 + CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName) + + + + MainSource + + + + + + + + + + + + + + + Cfg_2 + Base + + + Base + + + Cfg_1 + Base + + + + Delphi.Personality.12 + Package + + + + BoldBDE.dpk + + + Microsoft Office 2000 Sample Automation Server Wrapper Components + Microsoft Office XP Sample Automation Server Wrapper Components + + + + True + False + + + 12 + + + + diff --git a/BoldCom.dproj b/BoldCom.dproj new file mode 100644 index 0000000..a4bcfad --- /dev/null +++ b/BoldCom.dproj @@ -0,0 +1,186 @@ + + + {D19FAF40-7E3D-47AA-A13C-E4A727F5CE66} + BoldCom.dpk + True + Debug + 1 + Package + VCL + 19.2 + Win32 + + + true + + + true + Base + true + + + true + Base + true + + + true + Cfg_1 + true + true + + + true + Base + true + + + true + Cfg_2 + true + true + + + false + false + false + false + false + 00400000 + true + true + BoldCom + 1 + false + true + true + true + true + true + Bold 4.0 for Delphi (COM Support) + 90 + Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;System;Xml;Data;Datasnap;Web;Soap;DUnitX.Loggers.GUI;Winapi;System.Win;$(DCC_Namespace) + 2077 + CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=;CFBundleName= + Source\Common\Include\;$(DCC_UnitSearchPath) + Bold_Delphi;$(DCC_Define) + + + Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) + Debug + true + CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName) + 1033 + + + RELEASE;$(DCC_Define) + 0 + false + 0 + + + true + 1033 + CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName) + + + DEBUG;$(DCC_Define) + false + true + + + true + 1033 + CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName) + + + + MainSource + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Cfg_2 + Base + + + Base + + + Cfg_1 + Base + + + + Delphi.Personality.12 + Package + + + + BoldCom.dpk + + + Microsoft Office 2000 Sample Automation Server Wrapper Components + Microsoft Office XP Sample Automation Server Wrapper Components + + + + True + False + + + 12 + + + + diff --git a/BoldComGUI.dproj b/BoldComGUI.dproj new file mode 100644 index 0000000..d748ef9 --- /dev/null +++ b/BoldComGUI.dproj @@ -0,0 +1,185 @@ + + + {D112DB24-A42C-4AEC-BBED-D20E54732156} + BoldComGUI.dpk + True + Debug + 1 + Package + VCL + 19.2 + Win32 + + + true + + + true + Base + true + + + true + Base + true + + + true + Base + true + + + true + Cfg_2 + true + true + + + false + false + false + false + false + 00400000 + true + true + BoldComGUI + 1 + false + true + true + true + true + true + Bold 4.0 for Delphi (COM GUI controls) + 90 + Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;System;Xml;Data;Datasnap;Web;Soap;DUnitX.Loggers.GUI;Winapi;$(DCC_Namespace) + 2077 + CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=;CFBundleName= + Source\Common\Include\;$(DCC_UnitSearchPath) + + + System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) + Debug + true + CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName) + 1033 + + + RELEASE;$(DCC_Define) + 0 + false + 0 + + + DEBUG;$(DCC_Define) + false + true + + + true + 1033 + CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName) + + + + MainSource + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Cfg_2 + Base + + + Base + + + Cfg_1 + Base + + + + Delphi.Personality.12 + Package + + + + BoldComGUI.dpk + + + Microsoft Office 2000 Sample Automation Server Wrapper Components + Microsoft Office XP Sample Automation Server Wrapper Components + + + + True + False + + + 12 + + + + diff --git a/BoldDBExpress.dproj b/BoldDBExpress.dproj new file mode 100644 index 0000000..4d1d587 --- /dev/null +++ b/BoldDBExpress.dproj @@ -0,0 +1,130 @@ + + + {A4468009-7C69-4778-A981-841EC1C5F3CB} + BoldDBExpress.dpk + True + Debug + 1 + Package + VCL + 19.2 + Win32 + + + true + + + true + Base + true + + + true + Base + true + + + true + Base + true + + + true + Cfg_2 + true + true + + + false + false + false + false + false + 00400000 + true + true + BoldDBExpress + 1 + false + true + true + true + true + true + Bold 4.0 for Delphi (DBExpress Support) + 90 + Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;System;Xml;Data;Datasnap;Web;Soap;DUnitX.Loggers.GUI;$(DCC_Namespace) + 2077 + CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=;CFBundleName= + Source\Common\Include\;$(DCC_UnitSearchPath) + + + Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) + Debug + true + CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName) + 1033 + + + RELEASE;$(DCC_Define) + 0 + false + 0 + + + DEBUG;$(DCC_Define) + false + true + + + true + 1033 + CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName) + + + + MainSource + + + + + + + + + + + Cfg_2 + Base + + + Base + + + Cfg_1 + Base + + + + Delphi.Personality.12 + Package + + + + BoldDBExpress.dpk + + + Microsoft Office 2000 Sample Automation Server Wrapper Components + Microsoft Office XP Sample Automation Server Wrapper Components + + + + True + False + + + 12 + + + + diff --git a/BoldDBIsam.dproj b/BoldDBIsam.dproj new file mode 100644 index 0000000..c2f924b --- /dev/null +++ b/BoldDBIsam.dproj @@ -0,0 +1,131 @@ + + + {C33FD3D7-70BD-4A8C-8889-F542C9E07FBC} + BoldDBIsam.dpk + True + Debug + 1 + Package + VCL + 19.2 + Win32 + + + true + + + true + Base + true + + + true + Base + true + + + true + Base + true + + + true + Cfg_2 + true + true + + + false + false + false + false + false + 00400000 + true + true + BoldDBIsam + 1 + false + true + true + true + true + true + Bold 4.0 for Delphi (DBIsam Support) + 90 + Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;System;Xml;Data;Datasnap;Web;Soap;DUnitX.Loggers.GUI;$(DCC_Namespace) + 2077 + CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=;CFBundleName= + Source\Common\Include\;$(DCC_UnitSearchPath) + + + Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) + Debug + true + CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName) + 1033 + + + RELEASE;$(DCC_Define) + 0 + false + 0 + + + DEBUG;$(DCC_Define) + false + true + + + true + 1033 + CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName) + + + + MainSource + + + + + + + + + + + + Cfg_2 + Base + + + Base + + + Cfg_1 + Base + + + + Delphi.Personality.12 + Package + + + + BoldDBIsam.dpk + + + Microsoft Office 2000 Sample Automation Server Wrapper Components + Microsoft Office XP Sample Automation Server Wrapper Components + + + + True + False + + + 12 + + + + diff --git a/BoldDOA.dproj b/BoldDOA.dproj new file mode 100644 index 0000000..b4c6364 --- /dev/null +++ b/BoldDOA.dproj @@ -0,0 +1,131 @@ + + + {6E5ACB9F-CA4D-4279-8FEF-60F92A76AF1D} + BoldDOA.dpk + True + Debug + 1 + Package + VCL + 19.2 + Win32 + + + true + + + true + Base + true + + + true + Base + true + + + true + Base + true + + + true + Cfg_2 + true + true + + + false + false + false + false + false + 00400000 + true + true + BoldDOA + 1 + false + true + true + true + true + true + Bold 4.0 for Delphi (DOA Support) + 90 + Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;System;Xml;Data;Datasnap;Web;Soap;DUnitX.Loggers.GUI;FireDAC.Phys;$(DCC_Namespace) + 2077 + CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=;CFBundleName= + Source\Common\Include\;$(DCC_UnitSearchPath) + + + Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) + Debug + true + CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName) + 1033 + + + RELEASE;$(DCC_Define) + 0 + false + 0 + + + DEBUG;$(DCC_Define) + false + true + + + true + 1033 + CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName) + + + + MainSource + + + + + + + + + + + + Cfg_2 + Base + + + Base + + + Cfg_1 + Base + + + + Delphi.Personality.12 + Package + + + + BoldDOA.dpk + + + Microsoft Office 2000 Sample Automation Server Wrapper Components + Microsoft Office XP Sample Automation Server Wrapper Components + + + + True + False + + + 12 + + + + diff --git a/BoldExPe.dproj b/BoldExPe.dproj new file mode 100644 index 0000000..83a1107 --- /dev/null +++ b/BoldExPe.dproj @@ -0,0 +1,143 @@ + + + {EDD022ED-7B27-4C5A-AAFA-50B225F31963} + BoldExPe.dpk + True + Debug + 1 + Package + VCL + 19.2 + Win32 + + + true + + + true + Base + true + + + true + Base + true + + + true + Base + true + + + true + Cfg_2 + true + true + + + false + false + false + false + false + 00400000 + true + true + BoldExPe + 1 + false + true + true + true + true + true + Bold 4.0 for Delphi (External Persistence) + 90 + Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;System;Xml;Data;Datasnap;Web;Soap;DUnitX.Loggers.GUI;Winapi;$(DCC_Namespace) + 2077 + CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=;CFBundleName= + Source\Common\Include\;$(DCC_UnitSearchPath) + + + System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) + Debug + true + CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName) + 1033 + + + RELEASE;$(DCC_Define) + 0 + false + 0 + + + DEBUG;$(DCC_Define) + false + true + + + true + 1033 + CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName) + + + + MainSource + + + + + + + + + + + + + + + + + + + + + + + + Cfg_2 + Base + + + Base + + + Cfg_1 + Base + + + + Delphi.Personality.12 + Package + + + + BoldExPe.dpk + + + Microsoft Office 2000 Sample Automation Server Wrapper Components + Microsoft Office XP Sample Automation Server Wrapper Components + + + + True + False + + + 12 + + + + diff --git a/BoldIB.dproj b/BoldIB.dproj new file mode 100644 index 0000000..35006cc --- /dev/null +++ b/BoldIB.dproj @@ -0,0 +1,132 @@ + + + {325F8AA8-90A0-45A3-9F01-A7487802FD96} + BoldIB.dpk + True + Debug + 1 + Package + VCL + 19.2 + Win32 + + + true + + + true + Base + true + + + true + Base + true + + + true + Base + true + + + true + Cfg_2 + true + true + + + false + false + false + false + false + 00400000 + true + true + BoldIB + 1 + false + true + true + true + true + true + Bold 4.0 for Delphi (IBX Support) + 90 + Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;System;Xml;Data;Datasnap;Web;Soap;DUnitX.Loggers.GUI;IBX;$(DCC_Namespace) + 2077 + CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=;CFBundleName= + Source\Common\Include\;$(DCC_UnitSearchPath) + + + Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) + Debug + true + CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName) + 1033 + + + RELEASE;$(DCC_Define) + 0 + false + 0 + + + DEBUG;$(DCC_Define) + false + true + + + true + 1033 + CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName) + + + + MainSource + + + + + + + + + + + + + Cfg_2 + Base + + + Base + + + Cfg_1 + Base + + + + Delphi.Personality.12 + Package + + + + BoldIB.dpk + + + Microsoft Office 2000 Sample Automation Server Wrapper Components + Microsoft Office XP Sample Automation Server Wrapper Components + + + + True + False + + + 12 + + + + diff --git a/BoldMMLink.dproj b/BoldMMLink.dproj new file mode 100644 index 0000000..6132c93 --- /dev/null +++ b/BoldMMLink.dproj @@ -0,0 +1,133 @@ + + + {835F6110-BA89-4082-88F1-A8ACE5E95BD7} + BoldMMLink.dpk + True + Debug + 1 + Package + VCL + 19.2 + Win32 + + + true + + + true + Base + true + + + true + Base + true + + + true + Base + true + + + true + Cfg_2 + true + true + + + false + false + false + false + false + 00400000 + true + true + BoldMMLink + 1 + false + true + true + true + true + true + Bold 4.0 for Delphi (ModelMaker Link) + 90 + Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;System;Xml;Data;Datasnap;Web;Soap;DUnitX.Loggers.GUI;Winapi;System.Win;$(DCC_Namespace) + 2077 + CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=;CFBundleName= + Source\Common\Include\;$(DCC_UnitSearchPath) + + + Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) + Debug + true + CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName) + 1033 + + + RELEASE;$(DCC_Define) + 0 + false + 0 + + + DEBUG;$(DCC_Define) + false + true + + + true + 1033 + CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName) + + + + MainSource + + + + + + + + + + + + + + Cfg_2 + Base + + + Base + + + Cfg_1 + Base + + + + Delphi.Personality.12 + Package + + + + BoldMMLink.dpk + + + Microsoft Office 2000 Sample Automation Server Wrapper Components + Microsoft Office XP Sample Automation Server Wrapper Components + + + + True + False + + + 12 + + + + diff --git a/BoldOLLE.dproj b/BoldOLLE.dproj new file mode 100644 index 0000000..533e84e --- /dev/null +++ b/BoldOLLE.dproj @@ -0,0 +1,134 @@ + + + {3DB8E904-04CC-476B-8625-6B4AFD40AD5F} + BoldOLLE.dpk + True + Debug + 1 + Package + VCL + 19.2 + Win32 + + + true + + + true + Base + true + + + true + Base + true + + + true + Base + true + + + true + Cfg_2 + true + true + + + false + false + false + false + false + 00400000 + true + true + BoldOLLE + 1 + false + true + true + true + true + true + Bold 4.0 for Delphi (Object Lending Library Extension) + 90 + Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;System;Xml;Data;Datasnap;Web;Soap;DUnitX.Loggers.GUI;Winapi;$(DCC_Namespace) + 2077 + CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=;CFBundleName= + Source\Common\Include\;$(DCC_UnitSearchPath) + + + System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) + Debug + true + CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName) + 1033 + + + RELEASE;$(DCC_Define) + 0 + false + 0 + + + DEBUG;$(DCC_Define) + false + true + + + true + 1033 + CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName) + + + + MainSource + + + + + + + + + + + + + + + Cfg_2 + Base + + + Base + + + Cfg_1 + Base + + + + Delphi.Personality.12 + Package + + + + BoldOLLE.dpk + + + Microsoft Office 2000 Sample Automation Server Wrapper Components + Microsoft Office XP Sample Automation Server Wrapper Components + + + + True + False + + + 12 + + + + diff --git a/BoldSQLDirect.dproj b/BoldSQLDirect.dproj new file mode 100644 index 0000000..1fadfb3 --- /dev/null +++ b/BoldSQLDirect.dproj @@ -0,0 +1,130 @@ + + + {132CB408-63B0-4ACE-AF3D-9A62692C9204} + BoldSQLDirect.dpk + True + Debug + 1 + Package + VCL + 19.2 + Win32 + + + true + + + true + Base + true + + + true + Base + true + + + true + Base + true + + + true + Cfg_2 + true + true + + + false + false + false + false + false + 00400000 + true + true + BoldSQLDirect + 1 + false + true + true + true + true + true + Bold 4.0 for Delphi (SQLDirect Support) + 90 + Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;System;Xml;Data;Datasnap;Web;Soap;DUnitX.Loggers.GUI;$(DCC_Namespace) + 2077 + CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=;CFBundleName= + Source\Common\Include\;$(DCC_UnitSearchPath) + + + Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) + Debug + true + CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName) + 1033 + + + RELEASE;$(DCC_Define) + 0 + false + 0 + + + DEBUG;$(DCC_Define) + false + true + + + true + 1033 + CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName) + + + + MainSource + + + + + + + + + + + Cfg_2 + Base + + + Base + + + Cfg_1 + Base + + + + Delphi.Personality.12 + Package + + + + BoldSQLDirect.dpk + + + Microsoft Office 2000 Sample Automation Server Wrapper Components + Microsoft Office XP Sample Automation Server Wrapper Components + + + + True + False + + + 12 + + + + diff --git a/BoldUDPProp.dproj b/BoldUDPProp.dproj new file mode 100644 index 0000000..6e0c624 --- /dev/null +++ b/BoldUDPProp.dproj @@ -0,0 +1,129 @@ + + + {B7BDFC5E-E47C-470B-A1F5-538B26AF78AA} + BoldUDPProp.dpk + True + Debug + 1 + Package + VCL + 19.2 + Win32 + + + true + + + true + Base + true + + + true + Base + true + + + true + Base + true + + + true + Cfg_2 + true + true + + + false + false + false + false + false + 00400000 + true + true + BoldUDPProp + 1 + false + true + true + true + true + true + Bold 4.0 for Delphi (UDP Based Propagation) + 90 + Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;System;Xml;Data;Datasnap;Web;Soap;DUnitX.Loggers.GUI;$(DCC_Namespace) + 2077 + CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=;CFBundleName= + Source\Common\Include\;$(DCC_UnitSearchPath) + + + Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) + Debug + true + CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName) + 1033 + + + RELEASE;$(DCC_Define) + 0 + false + 0 + + + DEBUG;$(DCC_Define) + false + true + + + true + 1033 + CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName) + + + + MainSource + + + + + + + + + + Cfg_2 + Base + + + Base + + + Cfg_1 + Base + + + + Delphi.Personality.12 + Package + + + + BoldUDPProp.dpk + + + Microsoft Office 2000 Sample Automation Server Wrapper Components + Microsoft Office XP Sample Automation Server Wrapper Components + + + + True + False + + + 12 + + + + diff --git a/BoldUml.dproj b/BoldUml.dproj new file mode 100644 index 0000000..72fb2ee --- /dev/null +++ b/BoldUml.dproj @@ -0,0 +1,167 @@ + + + {6FA5D617-693C-48B5-9532-360227794754} + BoldUml.dpk + True + Debug + 1 + Package + VCL + 19.2 + Win32 + + + true + + + true + Base + true + + + true + Base + true + + + true + Base + true + + + true + Cfg_2 + true + true + + + false + false + false + false + false + 00400000 + true + true + BoldUml + 1 + false + true + true + true + true + true + Bold 4.0 for Delphi (Model editor) + 90 + Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;System;Xml;Data;Datasnap;Web;Soap;DUnitX.Loggers.GUI;Winapi;$(DCC_Namespace) + 2077 + CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=;CFBundleName= + Source\Common\Include\;$(DCC_UnitSearchPath) + + + System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) + Debug + true + CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName) + 1033 + + + RELEASE;$(DCC_Define) + 0 + false + 0 + + + DEBUG;$(DCC_Define) + false + true + + + true + 1033 + CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName) + + + + MainSource + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Cfg_2 + Base + + + Base + + + Cfg_1 + Base + + + + Delphi.Personality.12 + Package + + + + BoldUml.dpk + + + Microsoft Office 2000 Sample Automation Server Wrapper Components + Microsoft Office XP Sample Automation Server Wrapper Components + + + + True + False + + + 12 + + + + diff --git a/BoldUtility.dproj b/BoldUtility.dproj new file mode 100644 index 0000000..18ef944 --- /dev/null +++ b/BoldUtility.dproj @@ -0,0 +1,145 @@ + + + {2420DB83-B31E-48DD-BAC8-DC63F60827C0} + BoldUtility.dpk + True + Debug + 1 + Package + VCL + 19.2 + Win32 + + + true + + + true + Base + true + + + true + Base + true + + + true + Base + true + + + true + Cfg_2 + true + true + + + false + false + false + false + false + 00400000 + true + true + BoldUtility + 1 + false + true + true + true + true + true + Bold 4.0 for Delphi (Utils) + 90 + Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;System;Xml;Data;Datasnap;Web;Soap;DUnitX.Loggers.GUI;Winapi;$(DCC_Namespace) + 2077 + CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=;CFBundleName= + Source\Common\Include\;$(DCC_UnitSearchPath) + + + System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) + Debug + true + CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName) + 1033 + + + RELEASE;$(DCC_Define) + 0 + false + 0 + + + DEBUG;$(DCC_Define) + false + true + + + true + 1033 + CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName) + + + + MainSource + + + + + + + + + + + + + + + + + + + + + + + + + + Cfg_2 + Base + + + Base + + + Cfg_1 + Base + + + + Delphi.Personality.12 + Package + + + + BoldUtility.dpk + + + Microsoft Office 2000 Sample Automation Server Wrapper Components + Microsoft Office XP Sample Automation Server Wrapper Components + + + + True + False + + + 12 + + + + diff --git a/BoldVCLGUI.dproj b/BoldVCLGUI.dproj new file mode 100644 index 0000000..9900ed7 --- /dev/null +++ b/BoldVCLGUI.dproj @@ -0,0 +1,178 @@ + + + {4130A696-64EA-434B-989A-0F7ED2D11003} + BoldVCLGUI.dpk + True + Debug + 1 + Package + VCL + 19.2 + Win32 + + + true + + + true + Base + true + + + true + Base + true + + + true + Base + true + + + true + Cfg_2 + true + true + + + false + false + false + false + false + 00400000 + true + true + BoldVCLGUI + 1 + false + true + true + true + true + true + Bold 4.0 for Delphi (VCL GUI) + 90 + Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;System;Xml;Data;Datasnap;Web;Soap;DUnitX.Loggers.GUI;Winapi;$(DCC_Namespace) + 2077 + CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=;CFBundleName= + Source\Common\Include\;$(DCC_UnitSearchPath) + + + System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) + Debug + true + CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName) + 1033 + + + RELEASE;$(DCC_Define) + 0 + false + 0 + + + DEBUG;$(DCC_Define) + false + true + + + true + 1033 + CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName) + + + + MainSource + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Cfg_2 + Base + + + Base + + + Cfg_1 + Base + + + + Delphi.Personality.12 + Package + + + + BoldVCLGUI.dpk + + + Microsoft Office 2000 Sample Automation Server Wrapper Components + Microsoft Office XP Sample Automation Server Wrapper Components + + + + True + False + + + 12 + + + + diff --git a/BoldXMILink.dproj b/BoldXMILink.dproj new file mode 100644 index 0000000..6874e1c --- /dev/null +++ b/BoldXMILink.dproj @@ -0,0 +1,136 @@ + + + {2A4FC5D4-D12F-4EC3-9966-704BCD084A11} + BoldXMILink.dpk + True + Debug + 1 + Package + VCL + 19.2 + Win32 + + + true + + + true + Base + true + + + true + Base + true + + + true + Base + true + + + true + Cfg_2 + true + true + + + false + false + false + false + false + 00400000 + true + true + BoldXMILink + 1 + false + true + true + true + true + true + Bold 4.0 for Delphi (XMI Link) + 90 + Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;System;Xml;Data;Datasnap;Web;Soap;DUnitX.Loggers.GUI;$(DCC_Namespace) + 2077 + CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=;CFBundleName= + Source\Common\Include\;$(DCC_UnitSearchPath) + + + Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) + Debug + true + CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName) + 1033 + + + RELEASE;$(DCC_Define) + 0 + false + 0 + + + DEBUG;$(DCC_Define) + false + true + + + true + 1033 + CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName) + + + + MainSource + + + + + + + + + + + + + + + + + Cfg_2 + Base + + + Base + + + Cfg_1 + Base + + + + Delphi.Personality.12 + Package + + + + BoldXMILink.dpk + + + Microsoft Office 2000 Sample Automation Server Wrapper Components + Microsoft Office XP Sample Automation Server Wrapper Components + + + + True + False + + + 12 + + + + diff --git a/Source/Common/Include/Bold.inc b/Source/Common/Include/Bold.inc index d6d4416..6ef4683 100644 --- a/Source/Common/Include/Bold.inc +++ b/Source/Common/Include/Bold.inc @@ -424,7 +424,7 @@ Illegal symbol combination {.$DEFINE DebugInstanceCounter} // It saves memory to use LightMemberDeriver, but FormSaver is not compatible with LightMemberDeriver -{$DEFINE LightMemberDeriver} +{.$DEFINE LightMemberDeriver} // Define to use string comparison for all attributes. This may be faster, it uses IBoldStringRepresentable // but assumes each value has distinct string representation. diff --git a/Source/Persistence/ExternalPersistence/BoldAbstractPartiallyExternalPH.pas b/Source/Persistence/ExternalPersistence/BoldAbstractPartiallyExternalPH.pas index fb10cc1..4d48857 100644 --- a/Source/Persistence/ExternalPersistence/BoldAbstractPartiallyExternalPH.pas +++ b/Source/Persistence/ExternalPersistence/BoldAbstractPartiallyExternalPH.pas @@ -38,7 +38,7 @@ implementation BoldStringId, BoldDefaultId, BoldDefs, - BoldGuard, + BoldGuard; { TBoldAbstractpartiallyExternalPH } From 7acdca08f89f7c2c3aab8ce84a92889a696500ba Mon Sep 17 00:00:00 2001 From: Roland Bengtsson Date: Fri, 30 Apr 2021 15:11:27 +0300 Subject: [PATCH 003/112] Add missing BoldExpert.res --- BoldExpert.res | Bin 0 -> 880 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 BoldExpert.res diff --git a/BoldExpert.res b/BoldExpert.res new file mode 100644 index 0000000000000000000000000000000000000000..c00e4b8ed8b0e0d26109e0bf52cb7fef14bdac7d GIT binary patch literal 880 zcmc&zJ5Iw;5F7^zSCLnuMRu7o1qXmANEApQlp@D@NEGgJCDXacLDKpJ%j_;mUW8H7 zW$gXT?yTQR)&qcsrW(fd1iQ(;e?v{-y{fvu-HT>S8rmbRK$H__#*qNNNGSq6Q(8jT zb!^xY7Bm8V?4^)D=vyV)c4OgFLi0`2~3{-%>C2;8qXJM7T@TYO5L_Lr-&9IwP;0JrN9B}{u literal 0 HcmV?d00001 From eee95d253fcd145180de967101c62d3284e4a776 Mon Sep 17 00:00:00 2001 From: Ivan Date: Sun, 2 May 2021 00:19:04 -0300 Subject: [PATCH 004/112] Access violation preventing component installation All resource files were pointing to the wrong location for the images. I edited the .rc files, generated new .res with brcc32, edited in the source code the calls to the .res files where I had some comments and compiled the project --- .gitignore | 7 +++ Bold.dpk | 40 +++++++++--------- Bold.dproj | 6 ++- Bold.res | Bin 448 -> 616 bytes BoldAdo.res | Bin 0 -> 628 bytes BoldAdvantage.res | Bin 0 -> 664 bytes BoldCom.res | Bin 0 -> 628 bytes Source/Common/IDE/BoldReg.RES | Bin 0 -> 492 bytes Source/Common/IDE/BoldReg.pas | 2 +- Source/Common/IDE/BoldReg.rc | 2 +- Source/Common/IDE/BoldWebConnectionReg.RES | Bin 0 -> 492 bytes Source/Common/IDE/BoldWebConnectionReg.pas | 2 +- Source/Common/IDE/BoldWebConnectionReg.rc | 2 +- Source/Common/Support/BoldCommonBitmaps.RES | Bin 0 -> 5100 bytes Source/Common/Support/BoldCommonBitmaps.pas | 2 +- Source/Common/Support/BoldCommonBitmaps.rc | 26 ++++++------ ...BoldExternalObjectSpaceEventHandlerReg.RES | Bin 0 -> 528 bytes ...BoldExternalObjectSpaceEventHandlerReg.pas | 2 +- .../BoldExternalObjectSpaceEventHandlerReg.rc | 2 +- 19 files changed, 51 insertions(+), 42 deletions(-) create mode 100644 .gitignore create mode 100644 BoldAdo.res create mode 100644 BoldAdvantage.res create mode 100644 BoldCom.res create mode 100644 Source/Common/IDE/BoldReg.RES create mode 100644 Source/Common/IDE/BoldWebConnectionReg.RES create mode 100644 Source/Common/Support/BoldCommonBitmaps.RES create mode 100644 Source/ObjectSpace/IDE/BoldExternalObjectSpaceEventHandlerReg.RES diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e0e4ceb --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ + +*.dcu +*.~1~ +*.~2~ +*.local +*.dsk +*.identcache diff --git a/Bold.dpk b/Bold.dpk index 155ec5e..e1dd85a 100644 --- a/Bold.dpk +++ b/Bold.dpk @@ -1,27 +1,27 @@ package Bold; -{.$R *.res} +{$R *.res} {$IFDEF IMPLICITBUILDING This IFDEF should not be used by users} -{ ALIGN 8} -{ ASSERTIONS ON} -{ BOOLEVAL OFF} -{ DEBUGINFO ON} -{ EXTENDEDSYNTAX ON} -{ IMPORTEDDATA ON} -{ IOCHECKS ON} -{ LOCALSYMBOLS ON} -{ LONGSTRINGS ON} -{ OPENSTRINGS ON} -{ OPTIMIZATION OFF} -{ OVERFLOWCHECKS ON} -{ RANGECHECKS ON} +{$ALIGN 8} +{$ASSERTIONS ON} +{$BOOLEVAL OFF} +{$DEBUGINFO ON} +{$EXTENDEDSYNTAX ON} +{$IMPORTEDDATA ON} +{$IOCHECKS ON} +{$LOCALSYMBOLS ON} +{$LONGSTRINGS ON} +{$OPENSTRINGS ON} +{$OPTIMIZATION OFF} +{$OVERFLOWCHECKS ON} +{$RANGECHECKS ON} {$REFERENCEINFO ON} -{ SAFEDIVIDE OFF} -{ STACKFRAMES ON} -{ TYPEDADDRESS OFF} -{ VARSTRINGCHECKS ON} -{ WRITEABLECONST ON} -{ MINENUMSIZE 1} +{$SAFEDIVIDE OFF} +{$STACKFRAMES ON} +{$TYPEDADDRESS OFF} +{$VARSTRINGCHECKS ON} +{$WRITEABLECONST ON} +{$MINENUMSIZE 1} {$IMAGEBASE $400000} {$DEFINE BOLD_DELPHI} {$DEFINE DEBUG} diff --git a/Bold.dproj b/Bold.dproj index 9e64151..e154fb4 100644 --- a/Bold.dproj +++ b/Bold.dproj @@ -73,12 +73,14 @@ CompanyName=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName);FileDescription=$(MSBuildProjectName);ProductName=$(MSBuildProjectName) System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) true + vcl;vclx;vcldb;$(DCC_UsePackage) System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;$(DCC_Namespace) Debug true CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments= + vcl;vclx;vcldb;$(DCC_UsePackage) false @@ -435,8 +437,8 @@ Bold.dpk - Microsoft Office 2000 Sample Automation Server Wrapper Components - Microsoft Office XP Sample Automation Server Wrapper Components + QuickReport 6 Components + Componentes Softcenter Sydney - Completo diff --git a/Bold.res b/Bold.res index a64cea33b7bbf9c30d10d7750693ab849f870abc..348af5e980f626b3ebea2958d9db5b58ab15d940 100644 GIT binary patch delta 199 zcmX@W{DNhI0^^H`it<3hF`CJZapF8BCMCv+hpOt`7(^Ku83GuJ81fm?fn*{>E`uk7 z3j+uw1I2O~^cYfsWD-!O2q==skOJg`RO>M~0m&R79|VjTSb^raF=PToQi1wY8H$0b ri-7zBh7ur|&yWXJhpb17fmID|c?v@*P(ulWAJ_@0sEQ|BGPVN%HL4`n delta 32 ncmaFCa)5b)0;9u3MR_3M7|pbRVd6X`rW%HchpHw&VQc{aswoQ^ diff --git a/BoldAdo.res b/BoldAdo.res new file mode 100644 index 0000000000000000000000000000000000000000..800ca8b6fc5df43552a1673a0b8306ca5b62ba0e GIT binary patch literal 628 zcmZvaPfNo<5XE042kXhBM-QGQLJkTAsZ=FU|4>7(rPf*kX(F+HJim>1FFhN7v+3G4 zI53;Z?wj{!XI7Gq@w#rDaK~1GKR*P+4;HBtdeAC}2}gR;nDtsiqC^k6=RaY+AvXIA zzkejlZ#ew-(w$01=ug&LO4$hDTdGo~LUY(M<(k1<=v5`a$YCPIRCR&J)L<2zYoAoUev=K-%j3$yo$^X{!FK+c(-1d&LgN2h7UBB+*rL8g0(VxZ~C1X$2cl=Xy7t}LjedeU1f(eya-6i{Neai}%lp%e0Hri5QR@l7S@Hh>`Gj?mI&Dhf>f$f@Q)gbJBhW1K$=Lb;>-Cq?tKI6cPCz& zcF_xSJDoXm&SdUL(mu9WG={r!dL5tN1rt~t2uC=NjP+b*mfx54kV! z-T4ZCekE7maQNR-%Sw*WXZ}O_BoM$iSFK#7GT3qzn!;S_MHRrrFp*+KI>uspa2*Y_ zL#@XTsCm=GcwXVlsVz}Pap}NbD>22Ai4-8)Gwp`oA#1}t+)i!N;T7{uY!^nl#_O{um%LQM>o%vo IQ*ICb0QBQq5C8xG literal 0 HcmV?d00001 diff --git a/BoldCom.res b/BoldCom.res new file mode 100644 index 0000000000000000000000000000000000000000..ea559daaef87a55a110e6e891d2cc71c5d2f0622 GIT binary patch literal 628 zcmZvaPfNo<5XE042kXhBM-QG$gd7wEsa7RW|4>7(Qfn=NG?7?8p5Mm1m!6Hkow&3K zE=+bd``(+kJ1a?tL|r#Q+8XP?@9%?Q!HCogJ!l=oq!T^riSL!hWQp!|$2#GAP432L z`28a}exu>%bK8}ipx^oXrIa55dMj1RRA_-(rd)HB3%#lY7#Su~jH^>3#)EToqFuNi zKZNtHnd!Wtm%%Np%mrDl7hN(honDJKfmgxY;E&Y@2ZW8IPscmp?dA*FN8*nTgr$G?P1RRjP4 literal 0 HcmV?d00001 diff --git a/Source/Common/IDE/BoldReg.RES b/Source/Common/IDE/BoldReg.RES new file mode 100644 index 0000000000000000000000000000000000000000..8e7ed242e70fd6da5af3cfb28211e2235e939623 GIT binary patch literal 492 zcmbu5v1-FG5QhK6B_b3WX(`E;v17KZZAeOo7Kf4t@N``begTj6meG%qJ&U2Q)cyKP zXHz=o@UQ#y%Xc~i0BcIsMEn=c1lZG2o#KQYa=deY!T}#Rl3xgUv zXH|8Zzp(z+Cx0FLtEOv(J|}plU4Zv8He`gX^vYiIm4T3IOMS%hdzTwy)Az9EwqIF?yN;fDp6fQ|e>CcITKZt_< z82e%z3f7+6w{!Mr0bovfA4L39?-M}jcz=R59G;MKe#VM?$LW#JinPWOrY_I*-V6!0D%$GO3ZFz%C)eu4;wp(sr)?`z#pbOPm(wRRQKVIM_SL0}1lTpaQVXb6 zt6*XX1`V13;Soqo#01g46cDXQ)Sy_Sf}kJ>rC5Hh-*@hwWw+2xNkDpb&%HBe=FFM- zX70IXS41Qm-RCnq$dL95xI%QFFG7lBhB%}|9+Mg=$Gt&{r4DqBluDJ%3e1}%=@!jQ z0Acs{VPXzvgHMSydlKjytx*JDX>2raxPnA)l(x1u290c$3v?YwGvsN!HhDfC2Xj{%A`_!FrrJV^?-AUDFlZp<;=eX^O_eUQ4 zrCp@fTavdart(zcyi1w$FK0nM?Lhnlw>>F0vSNOb$RqpXE4q@G_T+Eqoz>hscUezC zb$4psn=xq*Thbqm5_zyWrs3kamTS&k*I(Xu{f%|KHTCDR^52U~onpx-f!x?LectJ@ zYp*{3?!TT7`qngFt(<)(1M=Zhqa07e{?U`|lUrh@A4z)VLe6tnCf1+NEc+q>9^2C+ z5T%OG`A%7KZshm{_Q|is9muB6+`xI`6DINkdLVDeArh)uWMsV9Z1+iY^g|LKUoV-NABw|qjyaR; z?B66U?Iks4vrSZT@_LN=qzBTYtza4L>NPmtUlu&Ja^=NQS!!);9Z( z>vcIN+&X%Gu)Y6l?X&YZs#7K;}BElo}T$mY#GvUl$_HNU$0PiztwWYwxmYW|cdXJq5XE0U41P1$H@ zI4|3`_eyMRsf-a^HvOO;ZO~WZHhOfY zsv-JGJJiq2+$UU@{&6mKsmGWZ7j-D-8kEy+T%1GsNZa&_W1L6%@Zqnibs2w3ibwgS z?J*9@IfphzjM$>=a2@)Qm32rG6Q7dgWVc$6^Qlk0hzP6jnXp*WBr0l@SgqsK^T8Uh z+b1cEXp?zjO)*EbML%edwo+5qsGKl1ZI@W<^@$N@pRAD^+o)-&gE zzJ5l7Ygdoy=hlYS(QyD*L5!zPob3Mfcq{4SKYjjL`{^ILNPoAZ`SndZzW@5L$e~?Z zTbf>M-qi*A(>=RadsnS}y9>L>Cwq6VUbh1D5$J!sVezuX8}?J*c5wZI=NsSu=CHDF z>po05=zQ!w1(+B7o~purHXHAw66|Pv+wxtjTmQW+3xarbeP;L;wBFn9=$V0s1J(GF z4Q_+xU22c-gT4yJa49Q;;mze-UN-87wA<&2c|Lr&73O6)4b-TUfpSuYGTy#E!|)Lg z8vt1XJo^lv;pdkKd7t6umq5z}sh~=s;q&ttP&_iC?P z{q{|0i8uPq_-f?Md-y$tXI-9@YKAK2ZdNs8beeVL0fu3Cl(f%BISa^Y*0g&tylLO% z^%yQs82d(GeLu=xR{hO6u!PxDs(|;LFnFiI_24~xEBL#&hX?!ar`>=UF*!ZBdB}hk zFdhR8X)s{jsAbUNp`QE3xXTmJS6G^MKx&)-a)1WapALuJOjK$)eoxn6UAF%F!#&3i z(YW!u4L6sS5CIpEC`CX=+J&+tq@Y2H)sLMTCqw~#Fp5@oTpp8#Sy%(UicptOn%E6= zey9X)vr&6>>X)#BZ)o9%*SUx9bX7m7E5Ky0vf*(;P?dgP2C1lgPjQ??05bQ#<;i# z=~(!(&@l$lq4*$fKR%&&2C#J^xLe}Sm3VOLW61q43SFOL`G45m*#n(|vcSiQz0CY*-i*#E{{hdi9W(#{ literal 0 HcmV?d00001 diff --git a/Source/Common/Support/BoldCommonBitmaps.pas b/Source/Common/Support/BoldCommonBitmaps.pas index d5d67f1..66cb72c 100644 --- a/Source/Common/Support/BoldCommonBitmaps.pas +++ b/Source/Common/Support/BoldCommonBitmaps.pas @@ -27,7 +27,7 @@ interface implementation -{.$R *.res} +{$R *.res} uses SysUtils; diff --git a/Source/Common/Support/BoldCommonBitmaps.rc b/Source/Common/Support/BoldCommonBitmaps.rc index 596effc..1bc5713 100644 --- a/Source/Common/Support/BoldCommonBitmaps.rc +++ b/Source/Common/Support/BoldCommonBitmaps.rc @@ -1,19 +1,19 @@ /* Grid bitmaps */ -BOLDGRID_CURRENT BITMAP LOADONCALL "BoldGrid Current.bmp" -BOLDGRID_SELECTED BITMAP LOADONCALL "BoldGrid Selected.bmp" -BOLDGRID_CONSTRAINT_TRUE BITMAP LOADONCALL "BoldGrid Constraint True.bmp" -BOLDGRID_CONSTRAINT_FALSE BITMAP LOADONCALL "BoldGrid Constraint False.bmp" +BOLDGRID_CURRENT BITMAP LOADONCALL "..\..\..\Images\BoldGrid Current.bmp" +BOLDGRID_SELECTED BITMAP LOADONCALL "..\..\..\Images\BoldGrid Selected.bmp" +BOLDGRID_CONSTRAINT_TRUE BITMAP LOADONCALL "..\..\..\Images\BoldGrid Constraint True.bmp" +BOLDGRID_CONSTRAINT_FALSE BITMAP LOADONCALL "..\..\..\Images\BoldGrid Constraint False.bmp" /* Navigator bitmaps */ -BOLDNAV_DELETE BITMAP LOADONCALL "BoldNavigator Delete.bmp" -BOLDNAV_FIRST BITMAP LOADONCALL "BoldNavigator First.bmp" -BOLDNAV_LAST BITMAP LOADONCALL "BoldNavigator Last.bmp" -BOLDNAV_INSERT BITMAP LOADONCALL "BoldNavigator Insert.bmp" -BOLDNAV_NEXT BITMAP LOADONCALL "BoldNavigator Next.bmp" -BOLDNAV_PRIOR BITMAP LOADONCALL "BoldNavigator Prior.bmp" -BOLDNAV_MOVEUP BITMAP LOADONCALL "BoldNavigator MoveUp.bmp" -BOLDNAV_MOVEDOWN BITMAP LOADONCALL "BoldNavigator MoveDown.bmp" +BOLDNAV_DELETE BITMAP LOADONCALL "..\..\..\Images\BoldNavigator Delete.bmp" +BOLDNAV_FIRST BITMAP LOADONCALL "..\..\..\Images\BoldNavigator First.bmp" +BOLDNAV_LAST BITMAP LOADONCALL "..\..\..\Images\BoldNavigator Last.bmp" +BOLDNAV_INSERT BITMAP LOADONCALL "..\..\..\Images\BoldNavigator Insert.bmp" +BOLDNAV_NEXT BITMAP LOADONCALL "..\..\..\Images\BoldNavigator Next.bmp" +BOLDNAV_PRIOR BITMAP LOADONCALL "..\..\..\Images\BoldNavigator Prior.bmp" +BOLDNAV_MOVEUP BITMAP LOADONCALL "..\..\..\Images\BoldNavigator MoveUp.bmp" +BOLDNAV_MOVEDOWN BITMAP LOADONCALL "..\..\..\Images\BoldNavigator MoveDown.bmp" /* Editbox bitmaps */ -BOLDEDIT_ELLIPSIS BITMAP LOADONCALL "BoldEdit Ellipsis.bmp" +BOLDEDIT_ELLIPSIS BITMAP LOADONCALL "..\..\..\Images\BoldEdit Ellipsis.bmp" diff --git a/Source/ObjectSpace/IDE/BoldExternalObjectSpaceEventHandlerReg.RES b/Source/ObjectSpace/IDE/BoldExternalObjectSpaceEventHandlerReg.RES new file mode 100644 index 0000000000000000000000000000000000000000..3311a7b06db6f4bab7278807cffb24dff21a78b3 GIT binary patch literal 528 zcmY+9u}*|Q5QhIV2E0%lSQzat6von5(1XO73tUcPED6QrN?SrhX=%r6Tz3TxkHj0S z|1faI4YTvjH@ia?0M-oWEQtTs_X0T3ICp_}JR`>z2~vErO0h?VCz_m{SJoTaH|*#( ztWtb1GP)O-`9afI3FBy1MoxBSmI7Z-}lVg(8p+U zmblyd97Gpex{T|t>rN;DPkhwGuh9o5bf}M_jexf9jv)d#D^jWjk8@7?<}VOY^02WIk5D8+{qaXHOROI$sne UT2@u%NvRyRZF{A__4g-{Ux_?|)&Kwi literal 0 HcmV?d00001 diff --git a/Source/ObjectSpace/IDE/BoldExternalObjectSpaceEventHandlerReg.pas b/Source/ObjectSpace/IDE/BoldExternalObjectSpaceEventHandlerReg.pas index 7d33105..5e3ba6c 100644 --- a/Source/ObjectSpace/IDE/BoldExternalObjectSpaceEventHandlerReg.pas +++ b/Source/ObjectSpace/IDE/BoldExternalObjectSpaceEventHandlerReg.pas @@ -9,7 +9,7 @@ procedure Register; implementation -{.$R *.res} +{$R *.res} uses SysUtils, diff --git a/Source/ObjectSpace/IDE/BoldExternalObjectSpaceEventHandlerReg.rc b/Source/ObjectSpace/IDE/BoldExternalObjectSpaceEventHandlerReg.rc index a5f2439..6134951 100644 --- a/Source/ObjectSpace/IDE/BoldExternalObjectSpaceEventHandlerReg.rc +++ b/Source/ObjectSpace/IDE/BoldExternalObjectSpaceEventHandlerReg.rc @@ -1 +1 @@ -TBOLDEXTERNALOBJECTSPACEEVENTHANDLER BITMAP LOADONCALL TBoldExternalObjectSpaceEventHandler.bmp +TBOLDEXTERNALOBJECTSPACEEVENTHANDLER BITMAP LOADONCALL ..\..\..\Images\Components\TBoldExternalObjectSpaceEventHandler.bmp From 1bf5a3d394b798415db539f8482a37e368801bfe Mon Sep 17 00:00:00 2001 From: Ivan Date: Sun, 2 May 2021 15:13:21 -0300 Subject: [PATCH 005/112] File MSXML_TLB.pas renamed The Archive was in conflict with other components that used the same name. --- Bold.dpk | 2 +- Bold.dproj | 2 +- Bold.~dsk | 923 ++++++++++++++++++ .../{MSXML_TLB.pas => Bold_MSXML_TLB.pas} | 2 +- Source/Common/SOAP/BoldXMLRequests.pas | 3 +- Source/Common/Support/BoldXMLStreaming.pas | 2 +- Source/Handles/XML/BoldXMLProducers.pas | 2 +- .../Ocl/BoldOclLightWeightNodes.pas | 2 +- .../File/BoldPersistenceHandleFileXML.pas | 2 +- Source/ValueSpace/Condition/BoldCondition.pas | 2 +- Source/ValueSpace/Id/BoldId.pas | 2 +- .../XMLStreaming/BoldDefaultXMLStreaming.pas | 2 +- __history/Bold.dpk.~3~ | 348 +++++++ 13 files changed, 1282 insertions(+), 12 deletions(-) create mode 100644 Bold.~dsk rename Source/Common/MsXml/{MSXML_TLB.pas => Bold_MSXML_TLB.pas} (99%) create mode 100644 __history/Bold.dpk.~3~ diff --git a/Bold.dpk b/Bold.dpk index e1dd85a..e8dc73b 100644 --- a/Bold.dpk +++ b/Bold.dpk @@ -145,7 +145,7 @@ contains BoldLogReceiverInterface in 'Source\Common\Logging\BoldLogReceiverInterface.pas', BoldSmallLogFrame in 'Source\Common\Logging\BoldSmallLogFrame.pas', BoldThreadSafeLog in 'Source\Common\Logging\BoldThreadSafeLog.pas', - MSXML_TLB in 'Source\Common\MsXml\MSXML_TLB.pas', + Bold_MSXML_TLB in 'Source\Common\MsXml\Bold_MSXML_TLB.pas', BoldAbstractDequeuer in 'Source\Common\Queue\BoldAbstractDequeuer.pas', BoldEventQueue in 'Source\Common\Queue\BoldEventQueue.pas', BoldQueue in 'Source\Common\Queue\BoldQueue.pas', diff --git a/Bold.dproj b/Bold.dproj index e154fb4..451b30a 100644 --- a/Bold.dproj +++ b/Bold.dproj @@ -217,7 +217,7 @@ - + diff --git a/Bold.~dsk b/Bold.~dsk new file mode 100644 index 0000000..4777846 --- /dev/null +++ b/Bold.~dsk @@ -0,0 +1,923 @@ +[Closed Files] +File_0=TSourceModule,'D:\Developer\DELPHI\BoldForDelphi\Source\Handles\IDE\BoldHandleReg.pas',0,1,51,73,71,0,0,, +File_1=TSourceModule,'D:\Developer\DELPHI\BoldForDelphi\Source\Propagator\Common\BoldLockingSupportInterfaces_TLB.pas',0,1,28,77,40,0,0,, +File_2=TSourceModule,'D:\Developer\DELPHI\BoldForDelphi\Source\Common\Support\BoldControlsDefs.pas',0,1,1,7,12,0,0,, +File_3=TSourceModule,'D:\Developer\DELPHI\BoldForDelphi\Source\Common\UtilsGUI\BoldQueryUserDlg.pas',0,1,1,7,11,0,0,, +File_4=TSourceModule,'D:\Developer\DELPHI\BoldForDelphi\Source\MoldModel\UtilsGUI\BoldTypeNameEditor.pas',0,1,1,7,10,0,0,, +File_5=TSourceModule,'D:\Developer\DELPHI\BoldForDelphi\Source\Common\SOAP\BoldSOAP2_TLB.pas',0,1,29,37,38,0,0,, +File_6=TSourceModule,'D:\Developer\DELPHI\BoldForDelphi\Source\Common\SOAP\BoldSOAP_TLB.pas',0,1,29,37,38,0,0,, +File_7=TSourceModule,'D:\Developer\DELPHI\BoldForDelphi\Source\Common\Rose98\RationalRose98_TLB.pas',0,1,21,37,30,0,0,, +File_8=TSourceModule,'D:\Developer\DELPHI\BoldForDelphi\Source\Common\Rose2000\RationalRose2000_TLB.pas',0,1,22,37,31,0,0,, +File_9=TSourceModule,'D:\Developer\DELPHI\BoldForDelphi\Source\Common\MsXml\MSXML_TLB.pas',0,1,34,37,43,0,0,, + +[Modules] +Module0=D:\Developer\DELPHI\BoldForDelphi\Bold.dproj +Module1=D:\Developer\DELPHI\BoldForDelphi\Source\Common\IDE\BoldExpert.pas +Module2=D:\Developer\DELPHI\BoldForDelphi\Source\ObjectSpace\IDE\BoldExternalObjectSpaceEventHandlerReg.pas +Module3=D:\Developer\DELPHI\BoldForDelphi\Source\Common\Support\BoldCommonBitmaps.pas +Module4=D:\Developer\DELPHI\BoldForDelphi\Source\Common\IDE\BoldWebConnectionReg.pas +Module5=D:\Developer\DELPHI\BoldForDelphi\Source\Common\IDE\BoldReg.pas +Module6=default.htm +Count=7 +EditWindowCount=1 + +[D:\Developer\DELPHI\BoldForDelphi\Bold.dproj] +ModuleType=TBaseProject + +[D:\Developer\DELPHI\BoldForDelphi\Source\Common\IDE\BoldExpert.pas] +ModuleType=TSourceModule + +[D:\Developer\DELPHI\BoldForDelphi\Source\ObjectSpace\IDE\BoldExternalObjectSpaceEventHandlerReg.pas] +ModuleType=TSourceModule + +[D:\Developer\DELPHI\BoldForDelphi\Source\Common\Support\BoldCommonBitmaps.pas] +ModuleType=TSourceModule + +[D:\Developer\DELPHI\BoldForDelphi\Source\Common\IDE\BoldWebConnectionReg.pas] +ModuleType=TSourceModule + +[D:\Developer\DELPHI\BoldForDelphi\Source\Common\IDE\BoldReg.pas] +ModuleType=TSourceModule + +[default.htm] +ModuleType=TURLModule + +[EditWindow0] +ViewCount=7 +CurrentEditView=D:\Developer\DELPHI\BoldForDelphi\Bold.dpk +View0=0 +View1=1 +View2=2 +View3=3 +View4=4 +View5=5 +View6=6 +PercentageSizes=1 +Create=1 +Visible=1 +Docked=1 +State=0 +Left=0 +Top=0 +Width=9917 +Height=9052 +MaxLeft=-1 +MaxTop=-1 +ClientWidth=9917 +ClientHeight=9052 +DockedToMainForm=1 +BorlandEditorCodeExplorer=BorlandEditorCodeExplorer@EditWindow0 +TopPanelSize=0 +LeftPanelSize=2005 +LeftPanelClients=DockSite2 +LeftPanelData=00000800010100000000F10B00000000000001D50700000000000001000000003B15000009000000446F636B5369746532FFFFFFFF +RightPanelSize=2052 +RightPanelClients=DockSite1 +RightPanelData=00000800010100000000F10B00000000000001040800000000000001000000003B15000009000000446F636B5369746531FFFFFFFF +BottomPanelSize=3157 +BottomPanelClients=DockSite0,MessageView +BottomPanelData=0000080001020100000009000000446F636B5369746530DE4400000000000002550C0000000000000100000000DE4400000F0000004D65737361676556696577466F726DFFFFFFFF +BottomMiddlePanelSize=0 +BottomMiddlePanelClients=GraphDrawingModel +BottomMiddelPanelData=0000080001000100000010000000477261706844726177696E67566965771D2800000000000000B621000000000000FFFFFFFF + +[View0] +CustomEditViewType=TWelcomePageView +WelcomePageURL=bds:/default.htm + +[View1] +CustomEditViewType=TEditView +Module=D:\Developer\DELPHI\BoldForDelphi\Bold.dpk +CursorX=80 +CursorY=25 +TopLine=13 +LeftCol=1 +Elisions= +Bookmarks= +EditViewName=D:\Developer\DELPHI\BoldForDelphi\Bold.dpk + +[View2] +CustomEditViewType=TEditView +Module=D:\Developer\DELPHI\BoldForDelphi\Source\ObjectSpace\IDE\BoldExternalObjectSpaceEventHandlerReg.pas +CursorX=5 +CursorY=12 +TopLine=1 +LeftCol=1 +Elisions= +Bookmarks= +EditViewName=D:\Developer\DELPHI\BoldForDelphi\Source\ObjectSpace\IDE\BoldExternalObjectSpaceEventHandlerReg.pas + +[View3] +CustomEditViewType=TEditView +Module=D:\Developer\DELPHI\BoldForDelphi\Source\Common\IDE\BoldExpert.pas +CursorX=56 +CursorY=55 +TopLine=33 +LeftCol=1 +Elisions= +Bookmarks= +EditViewName=D:\Developer\DELPHI\BoldForDelphi\Source\Common\IDE\BoldExpert.pas + +[View4] +CustomEditViewType=TEditView +Module=D:\Developer\DELPHI\BoldForDelphi\Source\Common\IDE\BoldReg.pas +CursorX=2 +CursorY=19 +TopLine=1 +LeftCol=1 +Elisions= +Bookmarks= +EditViewName=D:\Developer\DELPHI\BoldForDelphi\Source\Common\IDE\BoldReg.pas + +[View5] +CustomEditViewType=TEditView +Module=D:\Developer\DELPHI\BoldForDelphi\Source\Common\IDE\BoldWebConnectionReg.pas +CursorX=2 +CursorY=12 +TopLine=1 +LeftCol=1 +Elisions= +Bookmarks= +EditViewName=D:\Developer\DELPHI\BoldForDelphi\Source\Common\IDE\BoldWebConnectionReg.pas + +[View6] +CustomEditViewType=TEditView +Module=D:\Developer\DELPHI\BoldForDelphi\Source\Common\Support\BoldCommonBitmaps.pas +CursorX=2 +CursorY=30 +TopLine=17 +LeftCol=1 +Elisions= +Bookmarks= +EditViewName=D:\Developer\DELPHI\BoldForDelphi\Source\Common\Support\BoldCommonBitmaps.pas + +[Watches] +Count=0 + +[WatchWindow] +WatchColumnWidth=120 +WatchShowColumnHeaders=1 +PercentageSizes=1 +Create=1 +Visible=1 +Docked=1 +State=0 +Left=0 +Top=0 +Width=3823 +Height=1151 +MaxLeft=-1 +MaxTop=-1 +ClientWidth=3823 +ClientHeight=1151 +TBDockHeight=213 +LRDockWidth=13604 +Dockable=1 +StayOnTop=0 + +[Breakpoints] +Count=0 + +[EmbarcaderoWin32Debugger_AddressBreakpoints] +Count=0 + +[EmbarcaderoWin64Debugger_AddressBreakpoints] +Count=0 + +[EmbarcaderoLinux64Debugger_AddressBreakpoints] +Count=0 + +[EmbarcaderoOSX32Debugger_AddressBreakpoints] +Count=0 + +[EmbarcaderoOSX64Debugger_AddressBreakpoints] +Count=0 + +[EmbarcaderoIOS64DeviceDebugger_AddressBreakpoints] +Count=0 + +[EmbarcaderoAndroid32Debugger_AddressBreakpoints] +Count=0 + +[EmbarcaderoAndroid64Debugger_AddressBreakpoints] +Count=0 + +[Main Window] +PercentageSizes=1 +Create=1 +Visible=1 +Docked=0 +State=2 +Left=11120 +Top=0 +Width=8922 +Height=8491 +MaxLeft=-5 +MaxTop=-10 +MaxWidth=8922 +MaxHeight=8491 +ClientWidth=10000 +ClientHeight=10135 +BottomPanelSize=8667 +BottomPanelClients=EditWindow0 +BottomPanelData=0000080000000000000000000000000000000000000000000000000100000000000000000C0000004564697457696E646F775F30FFFFFFFF + +[ProjectManager] +PercentageSizes=1 +Create=1 +Visible=1 +Docked=1 +State=0 +Left=0 +Top=0 +Width=2052 +Height=5135 +MaxLeft=-1 +MaxTop=-1 +ClientWidth=2052 +ClientHeight=5135 +TBDockHeight=5890 +LRDockWidth=2349 +Dockable=1 +StayOnTop=0 + +[MessageView] +PercentageSizes=1 +Create=1 +Visible=1 +Docked=1 +State=0 +Left=0 +Top=28 +Width=9917 +Height=3027 +MaxLeft=-1 +MaxTop=-1 +ClientWidth=9917 +ClientHeight=3027 +TBDockHeight=3027 +LRDockWidth=2771 +Dockable=1 +StayOnTop=0 + +[ConfigurationManager] +PercentageSizes=1 +Create=1 +Visible=0 +Docked=0 +State=0 +Left=3531 +Top=2930 +Width=2932 +Height=4091 +MaxLeft=-5 +MaxTop=-10 +ClientWidth=2849 +ClientHeight=3714 +TBDockHeight=4091 +LRDockWidth=2932 +Dockable=1 +StayOnTop=0 + +[TConfigMgrDlg] +Column0=120 +Column1=120 +Column2=120 +Column3=100 +Column4=140 + +[ToolForm] +PercentageSizes=1 +Create=1 +Visible=1 +Docked=1 +State=0 +Left=0 +Top=0 +Width=2052 +Height=6557 +MaxLeft=-1 +MaxTop=-1 +ClientWidth=2052 +ClientHeight=6557 +TBDockHeight=7137 +LRDockWidth=2000 +Dockable=1 +StayOnTop=0 + +[PropertyInspector] +PercentageSizes=1 +Create=1 +Visible=1 +Docked=1 +State=0 +Left=0 +Top=0 +Width=2005 +Height=5135 +MaxLeft=-1 +MaxTop=-1 +ClientWidth=2005 +ClientHeight=5135 +TBDockHeight=8985 +LRDockWidth=1682 +Dockable=1 +StayOnTop=0 +SplitPos=178 + +[frmDesignPreview] +PercentageSizes=1 +Create=1 +Visible=1 +Docked=1 +State=0 +Left=0 +Top=0 +Width=2005 +Height=6557 +MaxLeft=-1 +MaxTop=-1 +ClientWidth=2005 +ClientHeight=6557 +TBDockHeight=5948 +LRDockWidth=2510 +Dockable=1 +StayOnTop=0 + +[TemplateView] +PercentageSizes=1 +Create=1 +Visible=0 +Docked=1 +State=0 +Left=0 +Top=0 +Width=276 +Height=368 +MaxLeft=-1 +MaxTop=-1 +ClientWidth=276 +ClientHeight=368 +TBDockHeight=368 +LRDockWidth=276 +Dockable=1 +StayOnTop=0 +Name=120 +Description=334 +filter=1 + +[DebugLogView] +PercentageSizes=1 +Create=1 +Visible=1 +Docked=1 +State=0 +Left=0 +Top=0 +Width=3823 +Height=1151 +MaxLeft=-1 +MaxTop=-1 +ClientWidth=3823 +ClientHeight=1151 +TBDockHeight=416 +LRDockWidth=4953 +Dockable=1 +StayOnTop=0 + +[ThreadStatusWindow] +PercentageSizes=1 +Create=1 +Visible=1 +Docked=1 +State=0 +Left=0 +Top=0 +Width=3823 +Height=1151 +MaxLeft=-1 +MaxTop=-1 +ClientWidth=3823 +ClientHeight=1151 +TBDockHeight=213 +LRDockWidth=7406 +Dockable=1 +StayOnTop=0 +Column0Width=145 +Column1Width=100 +Column2Width=115 +Column3Width=374 +Column4Width=10 + +[LocalVarsWindow] +PercentageSizes=1 +Create=1 +Visible=1 +Docked=1 +State=0 +Left=0 +Top=0 +Width=3823 +Height=1151 +MaxLeft=-1 +MaxTop=-1 +ClientWidth=3823 +ClientHeight=1151 +TBDockHeight=1538 +LRDockWidth=3484 +Dockable=1 +StayOnTop=0 + +[CallStackWindow] +PercentageSizes=1 +Create=1 +Visible=1 +Docked=1 +State=0 +Left=0 +Top=0 +Width=3823 +Height=1151 +MaxLeft=-1 +MaxTop=-1 +ClientWidth=3823 +ClientHeight=1151 +TBDockHeight=2060 +LRDockWidth=3484 +Dockable=1 +StayOnTop=0 + +[FindReferencsForm] +PercentageSizes=1 +Create=1 +Visible=0 +Docked=0 +State=0 +Left=3135 +Top=4265 +Width=2339 +Height=1209 +MaxLeft=-5 +MaxTop=-10 +ClientWidth=2255 +ClientHeight=832 +TBDockHeight=2311 +LRDockWidth=2823 +Dockable=1 +StayOnTop=0 + +[RefactoringForm] +PercentageSizes=1 +Create=1 +Visible=0 +Docked=0 +State=0 +Left=3453 +Top=3501 +Width=2339 +Height=1209 +MaxLeft=-5 +MaxTop=-10 +ClientWidth=2255 +ClientHeight=832 +TBDockHeight=3201 +LRDockWidth=2823 +Dockable=1 +StayOnTop=0 + +[ToDo List] +PercentageSizes=1 +Create=1 +Visible=1 +Docked=1 +State=0 +Left=0 +Top=0 +Width=2005 +Height=6557 +MaxLeft=-1 +MaxTop=-1 +ClientWidth=2005 +ClientHeight=6557 +TBDockHeight=1151 +LRDockWidth=3677 +Dockable=1 +StayOnTop=0 +Column0Width=314 +Column1Width=30 +Column2Width=150 +Column3Width=172 +Column4Width=129 +SortOrder=4 +ShowHints=1 +ShowChecked=1 + +[DataExplorerContainer] +PercentageSizes=1 +Create=1 +Visible=1 +Docked=1 +State=0 +Left=0 +Top=0 +Width=2052 +Height=6557 +MaxLeft=-1 +MaxTop=-1 +ClientWidth=2052 +ClientHeight=6557 +TBDockHeight=4874 +LRDockWidth=7151 +Dockable=1 +StayOnTop=0 + +[GraphDrawingModel] +PercentageSizes=1 +Create=1 +Visible=0 +Docked=1 +State=0 +Left=0 +Top=0 +Width=2854 +Height=3201 +MaxLeft=-1 +MaxTop=-1 +ClientWidth=2854 +ClientHeight=3201 +TBDockHeight=3201 +LRDockWidth=2854 +Dockable=1 +StayOnTop=0 + +[ClassBrowserTool] +PercentageSizes=1 +Create=1 +Visible=0 +Docked=1 +State=0 +Left=-172 +Top=-399 +Width=1849 +Height=3133 +MaxLeft=-1 +MaxTop=-1 +ClientWidth=1849 +ClientHeight=3133 +TBDockHeight=3133 +LRDockWidth=1849 +Dockable=1 +StayOnTop=0 + +[MetricsView] +PercentageSizes=1 +Create=1 +Visible=0 +Docked=0 +State=0 +Left=3594 +Top=4178 +Width=2339 +Height=1209 +MaxLeft=-5 +MaxTop=-10 +ClientWidth=2255 +ClientHeight=832 +TBDockHeight=4826 +LRDockWidth=3562 +Dockable=1 +StayOnTop=0 + +[QAView] +PercentageSizes=1 +Create=1 +Visible=0 +Docked=0 +State=0 +Left=3812 +Top=3694 +Width=2339 +Height=1209 +MaxLeft=-5 +MaxTop=-10 +ClientWidth=2255 +ClientHeight=832 +TBDockHeight=4826 +LRDockWidth=3562 +Dockable=1 +StayOnTop=0 + +[BreakpointWindow] +PercentageSizes=1 +Create=1 +Visible=1 +Docked=1 +State=0 +Left=0 +Top=0 +Width=3823 +Height=1151 +MaxLeft=-1 +MaxTop=-1 +ClientWidth=3823 +ClientHeight=1151 +TBDockHeight=1547 +LRDockWidth=8740 +Dockable=1 +StayOnTop=0 +Column0Width=200 +Column1Width=75 +Column2Width=200 +Column3Width=200 +Column4Width=200 +Column5Width=75 +Column6Width=75 + +[StructureView] +PercentageSizes=1 +Create=1 +Visible=1 +Docked=1 +State=0 +Left=0 +Top=0 +Width=2052 +Height=6557 +MaxLeft=-1 +MaxTop=-1 +ClientWidth=2052 +ClientHeight=6557 +TBDockHeight=3675 +LRDockWidth=1896 +Dockable=1 +StayOnTop=0 + +[ParnassusBookmarksForm] +PercentageSizes=1 +Create=1 +Visible=0 +Docked=1 +State=0 +Left=-172 +Top=-399 +Width=2969 +Height=3153 +MaxLeft=-1 +MaxTop=-1 +ClientWidth=2969 +ClientHeight=3153 +TBDockHeight=3153 +LRDockWidth=2969 +Dockable=1 +StayOnTop=0 + +[MMXCodeExplorer] +PercentageSizes=1 +Create=1 +Visible=1 +Docked=1 +State=0 +Left=0 +Top=0 +Width=2052 +Height=6557 +MaxLeft=-1 +MaxTop=-1 +ClientWidth=2052 +ClientHeight=6557 +TBDockHeight=8288 +LRDockWidth=1464 +Dockable=1 +StayOnTop=0 +Layout=0 +Split=30 +ContentsClosed=0 + +[MMXSourceIndexerView] +PercentageSizes=1 +Create=1 +Visible=0 +Docked=0 +State=0 +Left=3250 +Top=2911 +Width=3495 +Height=4139 +MaxLeft=-5 +MaxTop=-10 +ClientWidth=3411 +ClientHeight=3762 +TBDockHeight=4139 +LRDockWidth=3495 +Dockable=1 +StayOnTop=0 + +[ParnassusThreadListForm] +PercentageSizes=1 +Create=1 +Visible=0 +Docked=0 +State=0 +Left=0 +Top=0 +Width=3797 +Height=3104 +MaxLeft=-5 +MaxTop=-10 +ClientWidth=3714 +ClientHeight=2727 +TBDockHeight=3104 +LRDockWidth=3797 +Dockable=1 +StayOnTop=0 + +[ParnassusProcessForm] +PercentageSizes=1 +Create=1 +Visible=0 +Docked=0 +State=0 +Left=0 +Top=0 +Width=3797 +Height=3104 +MaxLeft=-5 +MaxTop=-10 +ClientWidth=3714 +ClientHeight=2727 +TBDockHeight=3104 +LRDockWidth=3797 +Dockable=1 +StayOnTop=0 + +[fmGrepResults] +PercentageSizes=1 +Create=1 +Visible=0 +Docked=0 +State=0 +Left=0 +Top=0 +Width=2146 +Height=3636 +MaxLeft=-5 +MaxTop=-10 +ClientWidth=2062 +ClientHeight=3259 +TBDockHeight=3607 +LRDockWidth=2146 +Dockable=1 +StayOnTop=0 + +[fmMacroLibrary] +PercentageSizes=1 +Create=1 +Visible=0 +Docked=0 +State=0 +Left=0 +Top=0 +Width=1719 +Height=2485 +MaxLeft=-5 +MaxTop=-10 +ClientWidth=1635 +ClientHeight=2108 +TBDockHeight=2466 +LRDockWidth=1719 +Dockable=1 +StayOnTop=0 + +[TestInsightForm] +PercentageSizes=1 +Create=1 +Visible=0 +Docked=0 +State=0 +Left=0 +Top=0 +Width=2969 +Height=3172 +MaxLeft=-5 +MaxTop=-10 +ClientWidth=2885 +ClientHeight=2795 +TBDockHeight=3172 +LRDockWidth=2969 +Dockable=1 +StayOnTop=0 +TabIndex=0 + +[ModelViewTool] +PercentageSizes=1 +Create=1 +Visible=1 +Docked=1 +State=0 +Left=0 +Top=0 +Width=2005 +Height=6557 +MaxLeft=-1 +MaxTop=-1 +ClientWidth=2005 +ClientHeight=6557 +TBDockHeight=4874 +LRDockWidth=5307 +Dockable=1 +StayOnTop=0 + +[BorlandEditorCodeExplorer@EditWindow0] +PercentageSizes=1 +Create=1 +Visible=0 +Docked=0 +State=0 +Left=0 +Top=0 +Width=1823 +Height=6151 +MaxLeft=-5 +MaxTop=-10 +ClientWidth=1740 +ClientHeight=5774 +TBDockHeight=6151 +LRDockWidth=1823 +Dockable=1 +StayOnTop=0 + +[DockHosts] +DockHostCount=3 + +[DockSite0] +HostDockSite=DockBottomPanel +DockSiteType=1 +PercentageSizes=1 +Create=1 +Visible=0 +Docked=1 +State=0 +Left=8 +Top=8 +Width=3823 +Height=1422 +MaxLeft=-1 +MaxTop=-1 +ClientWidth=3823 +ClientHeight=1422 +TBDockHeight=1422 +LRDockWidth=3823 +Dockable=1 +StayOnTop=0 +TabPosition=1 +ActiveTabID=DebugLogView +TabDockClients=DebugLogView,BreakpointWindow,ThreadStatusWindow,CallStackWindow,WatchWindow,LocalVarsWindow + +[DockSite1] +HostDockSite=DockRightPanel +DockSiteType=1 +PercentageSizes=1 +Create=1 +Visible=1 +Docked=1 +State=0 +Left=0 +Top=28 +Width=2052 +Height=5406 +MaxLeft=-1 +MaxTop=-1 +ClientWidth=2052 +ClientHeight=5406 +TBDockHeight=8985 +LRDockWidth=2052 +Dockable=1 +StayOnTop=0 +TabPosition=0 +ActiveTabID=ProjectManager +TabDockClients=ProjectManager,ToolForm,StructureView,MMXCodeExplorer,DataExplorerContainer,TemplateView + +[DockSite2] +HostDockSite=DockLeftPanel +DockSiteType=1 +PercentageSizes=1 +Create=1 +Visible=1 +Docked=1 +State=0 +Left=0 +Top=28 +Width=2005 +Height=5406 +MaxLeft=-1 +MaxTop=-1 +ClientWidth=2005 +ClientHeight=5406 +TBDockHeight=3627 +LRDockWidth=2005 +Dockable=1 +StayOnTop=0 +TabPosition=0 +ActiveTabID=PropertyInspector +TabDockClients=PropertyInspector,frmDesignPreview,ModelViewTool,ToDo List,ParnassusBookmarksForm,ClassBrowserTool + diff --git a/Source/Common/MsXml/MSXML_TLB.pas b/Source/Common/MsXml/Bold_MSXML_TLB.pas similarity index 99% rename from Source/Common/MsXml/MSXML_TLB.pas rename to Source/Common/MsXml/Bold_MSXML_TLB.pas index 85b2482..dd4f223 100644 --- a/Source/Common/MsXml/MSXML_TLB.pas +++ b/Source/Common/MsXml/Bold_MSXML_TLB.pas @@ -1,7 +1,7 @@ { Global compiler directives } {$include bold.inc} -unit MSXML_TLB; +unit Bold_MSXML_TLB; diff --git a/Source/Common/SOAP/BoldXMLRequests.pas b/Source/Common/SOAP/BoldXMLRequests.pas index 48bce4c..a783b6c 100644 --- a/Source/Common/SOAP/BoldXMLRequests.pas +++ b/Source/Common/SOAP/BoldXMLRequests.pas @@ -1,4 +1,3 @@ - { Global compiler directives } {$include bold.inc} unit BoldXMLRequests; @@ -6,7 +5,7 @@ interface uses - MSXML_TLB, + Bold_MSXML_TLB, Classes, BoldStringList, BoldDefs; diff --git a/Source/Common/Support/BoldXMLStreaming.pas b/Source/Common/Support/BoldXMLStreaming.pas index 3dad0d4..f73d7f5 100644 --- a/Source/Common/Support/BoldXMLStreaming.pas +++ b/Source/Common/Support/BoldXMLStreaming.pas @@ -6,7 +6,7 @@ interface uses - {$IFDEF OXML}OXmlPDOM{$ELSE}MSXML_TLB{$ENDIF}, + {$IFDEF OXML}OXmlPDOM{$ELSE}Bold_MSXML_TLB{$ENDIF}, BoldDefs, BoldBase, BoldStreams, diff --git a/Source/Handles/XML/BoldXMLProducers.pas b/Source/Handles/XML/BoldXMLProducers.pas index 5b86e49..64b52a0 100644 --- a/Source/Handles/XML/BoldXMLProducers.pas +++ b/Source/Handles/XML/BoldXMLProducers.pas @@ -5,7 +5,7 @@ interface uses - MSXML_TLB, + Bold_MSXML_TLB, BoldStringList, BoldManipulators, BoldDefs, diff --git a/Source/ObjectSpace/Ocl/BoldOclLightWeightNodes.pas b/Source/ObjectSpace/Ocl/BoldOclLightWeightNodes.pas index 59508f0..9e4c3cb 100644 --- a/Source/ObjectSpace/Ocl/BoldOclLightWeightNodes.pas +++ b/Source/ObjectSpace/Ocl/BoldOclLightWeightNodes.pas @@ -283,7 +283,7 @@ implementation uses SysUtils, - {$IFDEF OXML}OXmlPDOM{$ELSE}MSXML_TLB{$ENDIF}, + {$IFDEF OXML}OXmlPDOM{$ELSE}Bold_MSXML_TLB{$ENDIF}, BoldXMLStreaming, BoldDefaultStreamNames, BoldDefs; diff --git a/Source/Persistence/File/BoldPersistenceHandleFileXML.pas b/Source/Persistence/File/BoldPersistenceHandleFileXML.pas index 96c5e91..b9d0cbf 100644 --- a/Source/Persistence/File/BoldPersistenceHandleFileXML.pas +++ b/Source/Persistence/File/BoldPersistenceHandleFileXML.pas @@ -37,7 +37,7 @@ implementation classes, SysUtils, BoldDefs, - {$IFDEF OXML}OXmlPDOM, OTextReadWrite{$ELSE}MSXML_TLB{$ENDIF}, + {$IFDEF OXML}OXmlPDOM, OTextReadWrite{$ELSE}Bold_MSXML_TLB{$ENDIF}, BoldId, BoldXMLStreaming, BoldDefaultXMLStreaming, diff --git a/Source/ValueSpace/Condition/BoldCondition.pas b/Source/ValueSpace/Condition/BoldCondition.pas index a5e6db1..e30f0c5 100644 --- a/Source/ValueSpace/Condition/BoldCondition.pas +++ b/Source/ValueSpace/Condition/BoldCondition.pas @@ -119,7 +119,7 @@ implementation uses classes, - {$IFDEF OXML}OXmlPDOM{$ELSE}MSXML_TLB{$ENDIF}, + {$IFDEF OXML}OXmlPDOM{$ELSE}Bold_MSXML_TLB{$ENDIF}, BoldDefaultStreamNames; const diff --git a/Source/ValueSpace/Id/BoldId.pas b/Source/ValueSpace/Id/BoldId.pas index ca42c70..fc5a820 100644 --- a/Source/ValueSpace/Id/BoldId.pas +++ b/Source/ValueSpace/Id/BoldId.pas @@ -237,7 +237,7 @@ TBoldXMLObjectIdStreamer = class(TBoldXMLObjectStreamer) implementation uses - {$IFDEF OXML}OXmlPDOM{$ELSE}MSXML_TLB{$ENDIF}, + {$IFDEF OXML}OXmlPDOM{$ELSE}Bold_MSXML_TLB{$ENDIF}, SysUtils, {$IFNDEF BOLD_UNICODE} StringBuilder, diff --git a/Source/ValueSpace/XMLStreaming/BoldDefaultXMLStreaming.pas b/Source/ValueSpace/XMLStreaming/BoldDefaultXMLStreaming.pas index 91a7d2b..e81b897 100644 --- a/Source/ValueSpace/XMLStreaming/BoldDefaultXMLStreaming.pas +++ b/Source/ValueSpace/XMLStreaming/BoldDefaultXMLStreaming.pas @@ -265,7 +265,7 @@ implementation uses BoldHashIndexes, - {$IFDEF OXML}OXmlPDOM{$ELSE}MSXML_TLB{$ENDIF}, + {$IFDEF OXML}OXmlPDOM{$ELSE}Bold_MSXML_TLB{$ENDIF}, SysUtils, BoldDefaultStreamNames; diff --git a/__history/Bold.dpk.~3~ b/__history/Bold.dpk.~3~ new file mode 100644 index 0000000..e1dd85a --- /dev/null +++ b/__history/Bold.dpk.~3~ @@ -0,0 +1,348 @@ +package Bold; + +{$R *.res} +{$IFDEF IMPLICITBUILDING This IFDEF should not be used by users} +{$ALIGN 8} +{$ASSERTIONS ON} +{$BOOLEVAL OFF} +{$DEBUGINFO ON} +{$EXTENDEDSYNTAX ON} +{$IMPORTEDDATA ON} +{$IOCHECKS ON} +{$LOCALSYMBOLS ON} +{$LONGSTRINGS ON} +{$OPENSTRINGS ON} +{$OPTIMIZATION OFF} +{$OVERFLOWCHECKS ON} +{$RANGECHECKS ON} +{$REFERENCEINFO ON} +{$SAFEDIVIDE OFF} +{$STACKFRAMES ON} +{$TYPEDADDRESS OFF} +{$VARSTRINGCHECKS ON} +{$WRITEABLECONST ON} +{$MINENUMSIZE 1} +{$IMAGEBASE $400000} +{$DEFINE BOLD_DELPHI} +{$DEFINE DEBUG} +{$ENDIF IMPLICITBUILDING} +{$DESCRIPTION 'Bold 4.0 for Delphi'} +{$LIBSUFFIX '90'} +{$DESIGNONLY} +{$IMPLICITBUILD ON} + +requires + vcl, + vcldb, + VclX, + DesignIDE; + +contains + BoldSystem in 'Source\ObjectSpace\BORepresentation\BoldSystem.pas', + BoldAttributes in 'Source\ObjectSpace\BORepresentation\BoldAttributes.pas', + BoldDerivedValueSet in 'Source\ObjectSpace\BORepresentation\BoldDerivedValueSet.pas', + BoldDomainElement in 'Source\ObjectSpace\BORepresentation\BoldDomainElement.pas', + BoldElementList in 'Source\ObjectSpace\BORepresentation\BoldElementList.pas', + BoldExternalObjectSpaceEventHandler in 'Source\ObjectSpace\BORepresentation\BoldExternalObjectSpaceEventHandler.pas', + BoldLinks in 'Source\ObjectSpace\BORepresentation\BoldLinks.pas', + BoldMLAttributes in 'Source\ObjectSpace\BORepresentation\BoldMLAttributes.pas', + BoldObjectListControllers in 'Source\ObjectSpace\BORepresentation\BoldObjectListControllers.pas', + BoldObjectSpaceLists in 'Source\ObjectSpace\BORepresentation\BoldObjectSpaceLists.pas', + BoldOptimisticLockingSupport in 'Source\ObjectSpace\BORepresentation\BoldOptimisticLockingSupport.pas', + BoldSystemOldValuehandler in 'Source\ObjectSpace\BORepresentation\BoldSystemOldValuehandler.pas', + BoldSystemPersistenceHandler in 'Source\ObjectSpace\BORepresentation\BoldSystemPersistenceHandler.pas', + BoldTypeList in 'Source\ObjectSpace\BORepresentation\BoldTypeList.pas', + BoldCoreConsts in 'Source\ObjectSpace\Core\BoldCoreConsts.pas', + BoldElements in 'Source\ObjectSpace\Core\BoldElements.pas', + BoldMetaElementList in 'Source\ObjectSpace\Core\BoldMetaElementList.pas', + BoldComponentValidatorIDE in 'Source\ObjectSpace\IDE\BoldComponentValidatorIDE.pas', + BoldExternalObjectSpaceEventHandlerReg in 'Source\ObjectSpace\IDE\BoldExternalObjectSpaceEventHandlerReg.pas', + BoldWSimpleMenuWizard in 'Source\ObjectSpace\IDE\BoldWSimpleMenuWizard.pas', + BoldAttributeWizard in 'Source\ObjectSpace\IDE\AttributeWizard\BoldAttributeWizard.pas', + BoldOTACodeGen in 'Source\ObjectSpace\IDE\AttributeWizard\BoldOTACodeGen.pas', + BoldWAClassInfo in 'Source\ObjectSpace\IDE\AttributeWizard\BoldWAClassInfo.pas', + BoldWACustomAttr in 'Source\ObjectSpace\IDE\AttributeWizard\BoldWACustomAttr.pas', + BoldWACustomAttrForm1 in 'Source\ObjectSpace\IDE\AttributeWizard\BoldWACustomAttrForm1.pas', + BoldWAdatamodule in 'Source\ObjectSpace\IDE\AttributeWizard\BoldWAdatamodule.pas', + BoldWAdmTemplates in 'Source\ObjectSpace\IDE\AttributeWizard\BoldWAdmTemplates.pas', + BoldWAInputFormUnit in 'Source\ObjectSpace\IDE\AttributeWizard\BoldWAInputFormUnit.pas', + BoldWAInterfaces in 'Source\ObjectSpace\IDE\AttributeWizard\BoldWAInterfaces.pas', + BoldWAMainForm in 'Source\ObjectSpace\IDE\AttributeWizard\BoldWAMainForm.pas', + BoldWAMethodInfo in 'Source\ObjectSpace\IDE\AttributeWizard\BoldWAMethodInfo.pas', + BoldWAStringGridManager in 'Source\ObjectSpace\IDE\AttributeWizard\BoldWAStringGridManager.pas', + BoldWASubClassForm1 in 'Source\ObjectSpace\IDE\AttributeWizard\BoldWASubClassForm1.pas', + BoldWAValueSetDlg in 'Source\ObjectSpace\IDE\AttributeWizard\BoldWAValueSetDlg.pas', + BoldWAValueSetForm1 in 'Source\ObjectSpace\IDE\AttributeWizard\BoldWAValueSetForm1.pas', + BoldVclUtils in 'Source\ObjectSpace\IDE\AttributeWizard\BoldVclUtils.pas', + BoldWCodeInformer in 'Source\ObjectSpace\IDE\AttributeWizard\BoldWCodeInformer.pas', + BoldWProjectWizard in 'Source\ObjectSpace\IDE\AttributeWizard\BoldWProjectWizard.pas', + BoldWScanner in 'Source\ObjectSpace\IDE\AttributeWizard\BoldWScanner.pas', + BoldUndoInterfaces in 'Source\ObjectSpace\Interfaces\BoldUndoInterfaces.pas', + BoldOcl in 'Source\ObjectSpace\Ocl\BoldOcl.pas', + BoldOclClasses in 'Source\ObjectSpace\Ocl\BoldOclClasses.pas', + BoldOclError in 'Source\ObjectSpace\Ocl\BoldOclError.pas', + BoldOclEvaluator in 'Source\ObjectSpace\Ocl\BoldOclEvaluator.pas', + BoldOclLightWeightNodeMaker in 'Source\ObjectSpace\Ocl\BoldOclLightWeightNodeMaker.pas', + BoldOclLightWeightNodes in 'Source\ObjectSpace\Ocl\BoldOclLightWeightNodes.pas', + BoldOclRTDebug in 'Source\ObjectSpace\Ocl\BoldOclRTDebug.pas', + BoldOclSemantics in 'Source\ObjectSpace\Ocl\BoldOclSemantics.pas', + BoldOclSymbolImplementations in 'Source\ObjectSpace\Ocl\BoldOclSymbolImplementations.pas', + BoldORed in 'Source\ObjectSpace\Ocl\BoldORed.pas', + BoldSSExcept in 'Source\ObjectSpace\Ocl\BoldSSExcept.pas', + BoldSSLexU in 'Source\ObjectSpace\Ocl\BoldSSLexU.pas', + BoldSSYaccU in 'Source\ObjectSpace\Ocl\BoldSSYaccU.pas', + BoldLockHandler in 'Source\ObjectSpace\PessimisticLocking\BoldLockHandler.pas', + BoldLockHolder in 'Source\ObjectSpace\PessimisticLocking\BoldLockHolder.pas', + BoldLockRegions in 'Source\ObjectSpace\PessimisticLocking\BoldLockRegions.pas', + BoldRegionDefinitionParser in 'Source\ObjectSpace\PessimisticLocking\BoldRegionDefinitionParser.pas', + BoldRegionDefinitions in 'Source\ObjectSpace\PessimisticLocking\BoldRegionDefinitions.pas', + BoldGeneratedCodeDictionary in 'Source\ObjectSpace\RTModel\BoldGeneratedCodeDictionary.pas', + BoldMemberTypeDictionary in 'Source\ObjectSpace\RTModel\BoldMemberTypeDictionary.pas', + BoldSystemRT in 'Source\ObjectSpace\RTModel\BoldSystemRT.pas', + BoldUndoHandler in 'Source\ObjectSpace\Undo\BoldUndoHandler.pas', + BoldUnloader in 'Source\ObjectSpace\Unloader\BoldUnloader.pas', + BoldComponentValidator in 'Source\ObjectSpace\UtilsGUI\BoldComponentValidator.pas', + BoldOCLGraphicRTDebug in 'Source\ObjectSpace\UtilsGUI\BoldOCLGraphicRTDebug.pas', + BoldOclPropEditor in 'Source\ObjectSpace\UtilsGUI\BoldOclPropEditor.pas', + BoldTypeNameSelector in 'Source\ObjectSpace\UtilsGUI\BoldTypeNameSelector.pas', + BoldClient in 'Source\Common\Connection\BoldClient.pas', + BoldServer in 'Source\Common\Connection\BoldServer.pas', + BoldClientHandles in 'Source\Common\ConnectionHandles\BoldClientHandles.pas', + BoldServerHandles in 'Source\Common\ConnectionHandles\BoldServerHandles.pas', + BoldAggeregates in 'Source\Common\Core\BoldAggeregates.pas', + BoldBase in 'Source\Common\Core\BoldBase.pas', + BoldCommonConst in 'Source\Common\Core\BoldCommonConst.pas', + BoldContainers in 'Source\Common\Core\BoldContainers.pas', + BoldDefs in 'Source\Common\Core\BoldDefs.pas', + BoldStreams in 'Source\Common\Core\BoldStreams.pas', + BoldThreadSafeQueue in 'Source\Common\Core\BoldThreadSafeQueue.pas', + BoldEnvironment in 'Source\Common\Environment\BoldEnvironment.pas', + BoldEnvironmentIDE in 'Source\Common\Environment\BoldEnvironmentIDE.pas', + BoldEnvironmentVCL in 'Source\Common\Environment\BoldEnvironmentVCL.pas', + BoldHandle in 'Source\Common\Handles\BoldHandle.pas', + BoldDataBlock in 'Source\Common\HTTP\BoldDataBlock.pas', + BoldWebConnection in 'Source\Common\HTTP\BoldWebConnection.pas', + BoldAbstractPropertyEditors in 'Source\Common\IDE\BoldAbstractPropertyEditors.pas', + BoldDefsDT in 'Source\Common\IDE\BoldDefsDT.pas', + BoldExpert in 'Source\Common\IDE\BoldExpert.pas', + BoldExpertMenus in 'Source\Common\IDE\BoldExpertMenus.pas', + BoldGettingStartedExpert in 'Source\Common\IDE\BoldGettingStartedExpert.pas', + BoldGettingStartedForm in 'Source\Common\IDE\BoldGettingStartedForm.pas', + BoldIDEConsts in 'Source\Common\IDE\BoldIDEConsts.pas', + BoldIDEMenus in 'Source\Common\IDE\BoldIDEMenus.pas', + BoldIDESupport in 'Source\Common\IDE\BoldIDESupport.pas', + BoldModelAwareComponentEditor in 'Source\Common\IDE\BoldModelAwareComponentEditor.pas', + BoldOTAFileHandler in 'Source\Common\IDE\BoldOTAFileHandler.pas', + BoldOTASupport in 'Source\Common\IDE\BoldOTASupport.pas', + BoldPropertyEditors in 'Source\Common\IDE\BoldPropertyEditors.pas', + BoldReg in 'Source\Common\IDE\BoldReg.pas', + BoldTextStream in 'Source\Common\IDE\BoldTextStream.pas', + BoldWebConnectionReg in 'Source\Common\IDE\BoldWebConnectionReg.pas', + BoldLogForm in 'Source\Common\Logging\BoldLogForm.pas', + BoldLogHandler in 'Source\Common\Logging\BoldLogHandler.pas', + BoldLogHandlerForm in 'Source\Common\Logging\BoldLogHandlerForm.pas', + BoldLogHandlerSimple in 'Source\Common\Logging\BoldLogHandlerSimple.pas', + BoldLogReceiverInterface in 'Source\Common\Logging\BoldLogReceiverInterface.pas', + BoldSmallLogFrame in 'Source\Common\Logging\BoldSmallLogFrame.pas', + BoldThreadSafeLog in 'Source\Common\Logging\BoldThreadSafeLog.pas', + MSXML_TLB in 'Source\Common\MsXml\MSXML_TLB.pas', + BoldAbstractDequeuer in 'Source\Common\Queue\BoldAbstractDequeuer.pas', + BoldEventQueue in 'Source\Common\Queue\BoldEventQueue.pas', + BoldQueue in 'Source\Common\Queue\BoldQueue.pas', + BoldRose2000Support in 'Source\Common\Rose2000\BoldRose2000Support.pas', + RationalRose2000_TLB in 'Source\Common\Rose2000\RationalRose2000_TLB.pas', + BoldRose98Support in 'Source\Common\Rose98\BoldRose98Support.pas', + RationalRose98_TLB in 'Source\Common\Rose98\RationalRose98_TLB.pas', + BoldSOAP_TLB in 'Source\Common\SOAP\BoldSOAP_TLB.pas', + BoldSOAP2_TLB in 'Source\Common\SOAP\BoldSOAP2_TLB.pas', + BoldXMLRequests in 'Source\Common\SOAP\BoldXMLRequests.pas', + BoldDeriver in 'Source\Common\Subscription\BoldDeriver.pas', + BoldSubscribableCollection in 'Source\Common\Subscription\BoldSubscribableCollection.pas', + BoldSubscription in 'Source\Common\Subscription\BoldSubscription.pas', + BoldBase64 in 'Source\Common\Support\BoldBase64.pas', + BoldCollections in 'Source\Common\Support\BoldCollections.pas', + BoldIndexCollection in 'Source\Common\Support\BoldIndexCollection.pas', + BoldCommonBitmaps in 'Source\Common\Support\BoldCommonBitmaps.pas', + BoldControlPackDefs in 'Source\Common\Support\BoldControlPackDefs.pas', + BoldControlsDefs in 'Source\Common\Support\BoldControlsDefs.pas', + BoldDirectoryTraverser in 'Source\Common\Support\BoldDirectoryTraverser.pas', + BoldExternalizedReferences in 'Source\Common\Support\BoldExternalizedReferences.pas', + BoldFileHandler in 'Source\Common\Support\BoldFileHandler.pas', + BoldGuard in 'Source\Common\Support\BoldGuard.pas', + BoldGUIDUtils in 'Source\Common\Support\BoldGUIDUtils.pas', + BoldHashIndexes in 'Source\Common\Support\BoldHashIndexes.pas', + BoldIndex in 'Source\Common\Support\BoldIndex.pas', + BoldIndexableList in 'Source\Common\Support\BoldIndexableList.pas', + BoldIsoDateTime in 'Source\Common\Support\BoldIsoDateTime.pas', + BoldLoggableCriticalSection in 'Source\Common\Support\BoldLoggableCriticalSection.pas', + BoldMath in 'Source\Common\Support\BoldMath.pas', + BoldMemoryManager in 'Source\Common\Support\BoldMemoryManager.pas', + BoldNamedValueList in 'Source\Common\Support\BoldNamedValueList.pas', + BoldNavigatorDefs in 'Source\Common\Support\BoldNavigatorDefs.pas', + BoldPerformanceCounter in 'Source\Common\Support\BoldPerformanceCounter.pas', + BoldPriorityQueue in 'Source\Common\Support\BoldPriorityQueue.pas', + BoldRegistry in 'Source\Common\Support\BoldRegistry.pas', + BoldRev in 'Source\Common\Support\BoldRev.pas', + BoldSharedStrings in 'Source\Common\Support\BoldSharedStrings.pas', + BoldSorter in 'Source\Common\Support\BoldSorter.pas', + BoldStringList in 'Source\Common\Support\BoldStringList.pas', + BoldSupportConst in 'Source\Common\Support\BoldSupportConst.pas', + BoldTemplateExpander in 'Source\Common\Support\BoldTemplateExpander.pas', + BoldUtils in 'Source\Common\Support\BoldUtils.pas', + BoldXMLStreaming in 'Source\Common\Support\BoldXMLStreaming.pas', + BoldThread in 'Source\Common\SupportWin\BoldThread.pas', + BoldWinINet in 'Source\Common\SupportWin\BoldWinINet.pas', + BoldWinUtils in 'Source\Common\SupportWin\BoldWinUtils.pas', + BoldDefaultTaggedValues in 'Source\Common\TaggedValues\BoldDefaultTaggedValues.pas', + BoldTaggedValueList in 'Source\Common\TaggedValues\BoldTaggedValueList.pas', + BoldTaggedValueSupport in 'Source\Common\TaggedValues\BoldTaggedValueSupport.pas', + BoldUMLTaggedValues in 'Source\Common\TaggedValues\BoldUMLTaggedValues.pas', + BoldTemplate in 'Source\Common\Template\BoldTemplate.pas', + BoldUMLDelphiSupport in 'Source\Common\UML\BoldUMLDelphiSupport.pas', + BoldUMLTypes in 'Source\Common\UML\BoldUMLTypes.pas', + BoldCursorGuard in 'Source\Common\UtilsGUI\BoldCursorGuard.pas', + BoldQueryUserDlg in 'Source\Common\UtilsGUI\BoldQueryUserDlg.pas', + BoldAbstractLockManagerAdminHandle in 'Source\ConcurrencyControl\Common\BoldAbstractLockManagerAdminHandle.pas', + BoldAbstractLockManagerHandle in 'Source\ConcurrencyControl\Common\BoldAbstractLockManagerHandle.pas', + BoldLockingDefs in 'Source\ConcurrencyControl\Common\BoldLockingDefs.pas', + BoldFreeStandingValueFactories in 'Source\FreestandingValueSpace\Core\BoldFreeStandingValueFactories.pas', + BoldFreeStandingValues in 'Source\FreestandingValueSpace\Core\BoldFreeStandingValues.pas', + FreeStandingValuesConst in 'Source\FreestandingValueSpace\Core\FreeStandingValuesConst.pas', + BoldActionDefs in 'Source\Handles\Actions\BoldActionDefs.pas', + BoldActions in 'Source\Handles\Actions\BoldActions.pas', + BoldHandleAction in 'Source\Handles\Actions\BoldHandleAction.pas', + BoldListActions in 'Source\Handles\Actions\BoldListActions.pas', + BoldUndoActions in 'Source\Handles\Actions\BoldUndoActions.pas', + BoldAbstractListHandle in 'Source\Handles\Core\BoldAbstractListHandle.pas', + BoldCursorHandle in 'Source\Handles\Core\BoldCursorHandle.pas', + BoldDerivedHandle in 'Source\Handles\Core\BoldDerivedHandle.pas', + BoldExpressionHandle in 'Source\Handles\Core\BoldExpressionHandle.pas', + BoldFilteredHandle in 'Source\Handles\Core\BoldFilteredHandle.pas', + BoldHandles in 'Source\Handles\Core\BoldHandles.pas', + BoldListHandle in 'Source\Handles\Core\BoldListHandle.pas', + BoldOclRepository in 'Source\Handles\Core\BoldOclRepository.pas', + BoldOclVariables in 'Source\Handles\Core\BoldOclVariables.pas', + BoldOSSMessage in 'Source\ObjectSpace\BORepresentation\BoldOSSMessage.pas', + BoldPlaceableSubscriber in 'Source\Handles\Core\BoldPlaceableSubscriber.pas', + BoldReferenceHandle in 'Source\Handles\Core\BoldReferenceHandle.pas', + BoldRootedHandles in 'Source\Handles\Core\BoldRootedHandles.pas', + BoldSortedHandle in 'Source\Handles\Core\BoldSortedHandle.pas', + BoldSQLHandle in 'Source\Handles\Core\BoldSQLHandle.pas', + BoldRawSQLHandle in 'Source\Handles\Core\BoldRawSQLHandle.pas', + BoldSystemHandle in 'Source\Handles\Core\BoldSystemHandle.pas', + BoldVariableDefinition in 'Source\Handles\Core\BoldVariableDefinition.pas', + BoldVariableHandle in 'Source\Handles\Core\BoldVariableHandle.pas', + HandlesConst in 'Source\Handles\Core\HandlesConst.pas', + BoldHandlePropEditor in 'Source\Handles\IDE\BoldHandlePropEditor.pas', + BoldHandleReg in 'Source\Handles\IDE\BoldHandleReg.pas', + BoldLockingReg in 'Source\Handles\IDE\BoldLockingReg.pas', + BoldManipulatorReg in 'Source\Handles\IDE\BoldManipulatorReg.pas', + BoldXMLReg in 'Source\Handles\IDE\BoldXMLReg.pas', + BoldManipulators in 'Source\Handles\Manipulators\BoldManipulators.pas', + BoldLockingHandles in 'Source\Handles\PessimisticLocking\BoldLockingHandles.pas', + BoldUnloaderHandle in 'Source\Handles\UnLoader\BoldUnloaderHandle.pas', + BoldXMLProducers in 'Source\Handles\XML\BoldXMLProducers.pas', + BoldBld in 'Source\MoldModel\Bld\BoldBld.pas', + BoldGen in 'Source\MoldModel\CodeGenerator\BoldGen.pas', + BoldGeneratorTemplates in 'Source\MoldModel\CodeGenerator\BoldGeneratorTemplates.pas', + BoldGeneratorTemplatesCPP in 'Source\MoldModel\CodeGenerator\BoldGeneratorTemplatesCPP.pas', + BoldGeneratorTemplatesDelphi in 'Source\MoldModel\CodeGenerator\BoldGeneratorTemplatesDelphi.pas', + BoldMeta in 'Source\MoldModel\Core\BoldMeta.pas', + BoldMetaSupport in 'Source\MoldModel\Core\BoldMetaSupport.pas', + BoldMoldConsts in 'Source\MoldModel\Core\BoldMoldConsts.pas', + BoldNameExpander in 'Source\MoldModel\Core\BoldNameExpander.pas', + BoldAbstractModel in 'Source\MoldModel\Handles\BoldAbstractModel.pas', + BoldTypeNameHandle in 'Source\MoldModel\Handles\BoldTypeNameHandle.pas', + BoldModelReg in 'Source\MoldModel\IDE\BoldModelReg.pas', + BoldTypeNameHandleReg in 'Source\MoldModel\IDE\BoldTypeNameHandleReg.pas', + BoldTypeNameDictionary in 'Source\MoldModel\TypeNameDictionary\BoldTypeNameDictionary.pas', + BoldTypeNameEditor in 'Source\MoldModel\UtilsGUI\BoldTypeNameEditor.pas', + BoldAbstractSnooper in 'Source\Persistence\Core\BoldAbstractSnooper.pas', + BoldPersistenceController in 'Source\Persistence\Core\BoldPersistenceController.pas', + BoldPersistenceHandle in 'Source\Persistence\Core\BoldPersistenceHandle.pas', + BoldPersistenceHandlePassthrough in 'Source\Persistence\Core\BoldPersistenceHandlePassthrough.pas', + BoldPersistenceHandlePTWithModel in 'Source\Persistence\Core\BoldPersistenceHandlePTWithModel.pas', + BoldPersistenceNotifier in 'Source\Persistence\Core\BoldPersistenceNotifier.pas', + BoldUpdatePrecondition in 'Source\Persistence\Core\BoldUpdatePrecondition.pas', + PersistenceConsts in 'Source\Persistence\Core\PersistenceConsts.pas', + BoldAbstractDatabaseAdapter in 'Source\Persistence\DB\BoldAbstractDatabaseAdapter.pas', + BoldAbstractPersistenceHandleDB in 'Source\Persistence\DB\BoldAbstractPersistenceHandleDB.pas', + BoldDBActions in 'Source\Persistence\DB\BoldDBActions.pas', + BoldDBInterfaces in 'Source\Persistence\DB\BoldDBInterfaces.pas', + BoldPersistenceControllerDefault in 'Source\Persistence\DB\BoldPersistenceControllerDefault.pas', + BoldPersistenceHandleDB_deprecated in 'Source\Persistence\DB\BoldPersistenceHandleDB_deprecated.pas', + BoldPersistenceHandleDB in 'Source\Persistence\DB\BoldPersistenceHandleDB.pas', + BoldPersistenceHandleDBreg in 'Source\Persistence\DB\BoldPersistenceHandleDBreg.pas', + BoldPersistenceHandleFile in 'Source\Persistence\File\BoldPersistenceHandleFile.pas', + BoldPersistenceHandleFileXML in 'Source\Persistence\File\BoldPersistenceHandleFileXML.pas', + BoldHandlesPropagationReg in 'Source\Persistence\IDE\BoldHandlesPropagationReg.pas', + BoldObjectUpgraderHandleReg in 'Source\Persistence\IDE\BoldObjectUpgraderHandleReg.pas', + BoldPersistenceHandleFileReg in 'Source\Persistence\IDE\BoldPersistenceHandleFileReg.pas', + BoldPersistenceHandleReg in 'Source\Persistence\IDE\BoldPersistenceHandleReg.pas', + BoldPersistenceHandleSystemReg in 'Source\Persistence\IDE\BoldPersistenceHandleSystemReg.pas', + BoldPersistenceNotifierReg in 'Source\Persistence\IDE\BoldPersistenceNotifierReg.pas', + BoldAbstractObjectUpgraderHandle in 'Source\Persistence\ObjectUpgrading\BoldAbstractObjectUpgraderHandle.pas', + BoldBatchUpgrader in 'Source\Persistence\ObjectUpgrading\BoldBatchUpgrader.pas', + BoldObjectUpgrader in 'Source\Persistence\ObjectUpgrading\BoldObjectUpgrader.pas', + BoldObjectUpgraderHandle in 'Source\Persistence\ObjectUpgrading\BoldObjectUpgraderHandle.pas', + BoldIDAdder in 'Source\Persistence\Propagation\BoldIDAdder.pas', + BoldIDAdderHandle in 'Source\Persistence\Propagation\BoldIDAdderHandle.pas', + BoldListenerCOM in 'Source\Persistence\Propagation\BoldListenerCOM.pas', + BoldListenerHandle in 'Source\Persistence\Propagation\BoldListenerHandle.pas', + BoldListenerThread in 'Source\Persistence\Propagation\BoldListenerThread.pas', + BoldPersistenceControllerPassthrough in 'Source\Persistence\Propagation\BoldPersistenceControllerPassthrough.pas', + BoldSnooper in 'Source\Persistence\Propagation\BoldSnooper.pas', + BoldSnooperHandle in 'Source\Persistence\Propagation\BoldSnooperHandle.pas', + BoldPersistenceControllerSystem in 'Source\Persistence\System\BoldPersistenceControllerSystem.pas', + BoldPersistenceHandleSystem in 'Source\Persistence\System\BoldPersistenceHandleSystem.pas', + BoldAbstractObjectUpgrader in 'Source\PMapper\Core\BoldAbstractObjectUpgrader.pas', + BoldPMapper in 'Source\PMapper\Core\BoldPMapper.pas', + BoldPMapperLists in 'Source\PMapper\Core\BoldPMapperLists.pas', + BoldPMappers in 'Source\PMapper\Core\BoldPMappers.pas', + BoldPMConsts in 'Source\PMapper\Core\BoldPMConsts.pas', + BoldPSDescriptions in 'Source\PMapper\Core\BoldPSDescriptions.pas', + BoldPSParams in 'Source\PMapper\Core\BoldPSParams.pas', + BoldDbEvolutor in 'Source\PMapper\DbEvolutor\BoldDbEvolutor.pas', + BoldDbEvolutorForm in 'Source\PMapper\DbEvolutor\BoldDbEvolutorForm.pas', + BoldDbEvolutorScript in 'Source\PMapper\DbEvolutor\BoldDbEvolutorScript.pas', + BoldCustomBlobMapper in 'Source\PMapper\Default\BoldCustomBlobMapper.pas', + BoldMappingInfo in 'Source\PMapper\Default\BoldMappingInfo.pas', + BoldPMappersAttributeDefault in 'Source\PMapper\Default\BoldPMappersAttributeDefault.pas', + BoldPMappersDefault in 'Source\PMapper\Default\BoldPMappersDefault.pas', + BoldPMappersLinkDefault in 'Source\PMapper\Default\BoldPMappersLinkDefault.pas', + BoldPSDescriptionsDefault in 'Source\PMapper\Default\BoldPSDescriptionsDefault.pas', + BoldPSParamsDefault in 'Source\PMapper\Default\BoldPSParamsDefault.pas', + BoldPMappersSQL in 'Source\PMapper\SQL\BoldPMappersSQL.pas', + BoldPSDescriptionsSQL in 'Source\PMapper\SQL\BoldPSDescriptionsSQL.pas', + BoldPSParamsSQL in 'Source\PMapper\SQL\BoldPSParamsSQL.pas', + BoldSQLDatabaseConfig in 'Source\PMapper\SQL\BoldSQLDatabaseConfig.pas', + BoldSQLMappingInfo in 'Source\PMapper\SQL\BoldSQLMappingInfo.pas', + BoldSqlNodeMaker in 'Source\PMapper\SQL\BoldSqlNodeMaker.pas', + BoldSqlNodes in 'Source\PMapper\SQL\BoldSqlNodes.pas', + BoldSqlNodesResolver in 'Source\PMapper\SQL\BoldSqlNodesResolver.pas', + BoldSQLQuery in 'Source\PMapper\SQL\BoldSQLQuery.pas', + BoldSqlQueryGenerator in 'Source\PMapper\SQL\BoldSqlQueryGenerator.pas', + BoldSqlSymbols in 'Source\PMapper\SQL\BoldSqlSymbols.pas', + BoldDbDataValidator in 'Source\PMapper\Validator\BoldDbDataValidator.pas', + BoldDbStructureValidator in 'Source\PMapper\Validator\BoldDbStructureValidator.pas', + BoldDbValidator in 'Source\PMapper\Validator\BoldDbValidator.pas', + BoldAbstractPropagatorHandle in 'Source\Propagator\Common\BoldAbstractPropagatorHandle.pas', + BoldLockingSupportInterfaces_TLB in 'Source\Propagator\Common\BoldLockingSupportInterfaces_TLB.pas', + BoldObjectMarshaler in 'Source\Propagator\Common\BoldObjectMarshaler.pas', + BoldPropagatorConstants in 'Source\Propagator\Common\BoldPropagatorConstants.pas', + BoldPropagatorGUIDs in 'Source\Propagator\Common\BoldPropagatorGUIDs.pas', + BoldPropagatorInterfaces_TLB in 'Source\Propagator\Common\BoldPropagatorInterfaces_TLB.pas', + PropagatorConsts in 'Source\Propagator\Common\PropagatorConsts.pas', + BoldCondition in 'Source\ValueSpace\Condition\BoldCondition.pas', + BoldObjectSpaceExternalEvents in 'Source\ValueSpace\ExternalEvents\BoldObjectSpaceExternalEvents.pas', + BoldDefaultId in 'Source\ValueSpace\Id\BoldDefaultId.pas', + BoldGlobalId in 'Source\ValueSpace\Id\BoldGlobalId.pas', + BoldId in 'Source\ValueSpace\Id\BoldId.pas', + BoldStringId in 'Source\ValueSpace\Id\BoldStringId.pas', + ValueSpaceConst in 'Source\ValueSpace\Id\ValueSpaceConst.pas', + BoldValueInterfaces in 'Source\ValueSpace\Interfaces\BoldValueInterfaces.pas', + BoldValueSpaceInterfaces in 'Source\ValueSpace\Interfaces\BoldValueSpaceInterfaces.pas', + BoldDefaultStreamNames in 'Source\ValueSpace\XMLStreaming\BoldDefaultStreamNames.pas', + BoldDefaultXMLStreaming in 'Source\ValueSpace\XMLStreaming\BoldDefaultXMLStreaming.pas'; + +end. From 005ba2119e888a19e342b350d68e5da39147268c Mon Sep 17 00:00:00 2001 From: Ivan Date: Sun, 2 May 2021 16:40:46 -0300 Subject: [PATCH 006/112] More packages converted Converting more packages --- BoldBDE.dproj | 9 + BoldBDE.res | Bin 0 -> 628 bytes BoldCom.dproj | 9 + BoldComGUI.dproj | 9 + BoldComGUI.res | Bin 0 -> 652 bytes BoldDBExpress.res | Bin 0 -> 664 bytes BoldDOA.res | Bin 0 -> 628 bytes BoldExPe.dproj | 9 + BoldExPe.res | Bin 0 -> 640 bytes BoldForDelphi.groupproj | 264 ++++ BoldIB.dproj | 9 + BoldIB.res | Bin 0 -> 628 bytes BoldMMLink.dproj | 9 + BoldMMLink.res | Bin 0 -> 652 bytes BoldOLLE.res | Bin 0 -> 640 bytes BoldSQLDirect.res | Bin 0 -> 664 bytes BoldUDPProp.res | Bin 0 -> 652 bytes BoldUml.dproj | 9 + BoldUml.res | Bin 0 -> 628 bytes BoldUtility.dproj | 9 + BoldUtility.res | Bin 0 -> 652 bytes BoldVCLGUI.dproj | 9 + BoldVCLGUI.res | Bin 0 -> 652 bytes BoldXMILink.dproj | 9 + BoldXMILink.res | Bin 0 -> 652 bytes .../BoldControls/BoldAwareGuiComReg.rc | 34 + .../BoldControls/BoldAwareGuiComReg.res | Bin 0 -> 15248 bytes .../ClientGuiCom/BoldControls/BoldGridCom.pas | 4 +- .../ClientGuiCom/BoldControls/BoldMemoCom.pas | 2 +- .../BoldControls/BoldRichEditCom.pas | 2 +- .../BoldControls/BoldTreeViewCom.pas | 2 +- .../ClientGuiCom/IDE/BoldAwareGuiComReg.res | Bin 0 -> 15248 bytes .../ClientHandlesCom/IDE/BoldHandleComReg.RES | Bin 0 -> 5608 bytes .../ClientHandlesCom/IDE/BoldHandleComReg.rc | 24 +- .../BoldXMLDispatcher.pas | 2 +- ...oldOLLEDistributableObjectHandlers.pas.~3~ | 1175 +++++++++++++++++ .../BDE/BoldPersistenceHandleBde.RES | Bin 0 -> 972 bytes .../BDE/BoldPersistenceHandleBde.rc | 4 +- ...ldPersistenceControllerSOAPAdapterCore.pas | 2 +- .../BoldPersistenceOperationXMLStreaming.pas | 2 +- .../UMLModel/Handles/BoldUMLModelStreamer.pas | 2 +- .../ModelMaker/MMPlugin/BoldMMTVDefGen.pas | 2 +- .../ModelLinks/XMI/BoldMOFInterfaces.pas | 2 +- .../XMI/BoldUMLModelMOFAdapters.pas | 2 +- .../ModelLinks/XMI/BoldUMLXMIImporter.pas | 2 +- .../ModelLinks/XMI/BoldUMLXMILinkSupport.pas | 2 +- .../ModelLinks/XMI/BoldXMI10Exporter.pas | 2 +- .../Plugins/BoldUMLModelToEcoIIIGenerator.pas | 2 +- Source/Unassigned/Asta/AstaforBfD.dproj | 176 +++ Source/Unassigned/Asta/AstaforBfD.res | Bin 0 -> 652 bytes Source/Unassigned/BoldDataSetIPD4.dproj | 168 +++ Source/Unassigned/BoldDataSetIPD4.res | Bin 0 -> 676 bytes .../Unassigned/BoldUMLModelEditorDebugger.dpk | 10 +- .../BoldUMLModelEditorDebugger.dproj | 170 +++ .../Unassigned/BoldUMLModelEditorDebugger.res | Bin 0 -> 748 bytes .../BoldUMLModelEditorDebugger.dpk.~3~ | 37 + .../BoldUMLModelEditorDebugger.dpk.~4~ | 37 + .../BoldUMLModelEditorDebugger.dpk.~5~ | 37 + .../BoldUMLModelEditorDebugger.dpk.~6~ | 37 + .../BoldUMLModelEditorDebugger.dpk.~7~ | 37 + 60 files changed, 2297 insertions(+), 35 deletions(-) create mode 100644 BoldBDE.res create mode 100644 BoldComGUI.res create mode 100644 BoldDBExpress.res create mode 100644 BoldDOA.res create mode 100644 BoldExPe.res create mode 100644 BoldForDelphi.groupproj create mode 100644 BoldIB.res create mode 100644 BoldMMLink.res create mode 100644 BoldOLLE.res create mode 100644 BoldSQLDirect.res create mode 100644 BoldUDPProp.res create mode 100644 BoldUml.res create mode 100644 BoldUtility.res create mode 100644 BoldVCLGUI.res create mode 100644 BoldXMILink.res create mode 100644 Source/ClientGuiCom/BoldControls/BoldAwareGuiComReg.rc create mode 100644 Source/ClientGuiCom/BoldControls/BoldAwareGuiComReg.res create mode 100644 Source/ClientGuiCom/IDE/BoldAwareGuiComReg.res create mode 100644 Source/ClientHandlesCom/IDE/BoldHandleComReg.RES create mode 100644 Source/Extensions/OLLE/Core/__history/BoldOLLEDistributableObjectHandlers.pas.~3~ create mode 100644 Source/Persistence/BDE/BoldPersistenceHandleBde.RES create mode 100644 Source/Unassigned/Asta/AstaforBfD.dproj create mode 100644 Source/Unassigned/Asta/AstaforBfD.res create mode 100644 Source/Unassigned/BoldDataSetIPD4.dproj create mode 100644 Source/Unassigned/BoldDataSetIPD4.res create mode 100644 Source/Unassigned/BoldUMLModelEditorDebugger.dproj create mode 100644 Source/Unassigned/BoldUMLModelEditorDebugger.res create mode 100644 Source/Unassigned/__history/BoldUMLModelEditorDebugger.dpk.~3~ create mode 100644 Source/Unassigned/__history/BoldUMLModelEditorDebugger.dpk.~4~ create mode 100644 Source/Unassigned/__history/BoldUMLModelEditorDebugger.dpk.~5~ create mode 100644 Source/Unassigned/__history/BoldUMLModelEditorDebugger.dpk.~6~ create mode 100644 Source/Unassigned/__history/BoldUMLModelEditorDebugger.dpk.~7~ diff --git a/BoldBDE.dproj b/BoldBDE.dproj index 615bc85..071267d 100644 --- a/BoldBDE.dproj +++ b/BoldBDE.dproj @@ -18,6 +18,11 @@ Base true + + true + Base + true + true Base @@ -64,6 +69,10 @@ true CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName) 1033 + vcl;vcldb;bdertl;$(DCC_UsePackage) + + + vcl;vcldb;$(DCC_UsePackage) RELEASE;$(DCC_Define) diff --git a/BoldBDE.res b/BoldBDE.res new file mode 100644 index 0000000000000000000000000000000000000000..a1b23a8216f7ec7a0d6b44ffa33801897af4f1d0 GIT binary patch literal 628 zcmZ9KPfNo<5XE042kXhBM-QGQLJkTAX{kz}{-K6mrLDCD(nMnYczzr2UV1kEX5-Q{ z1GAazy!U2yXC>(ruj|GM_iP*Z{4p4Qut>eogSJ6TIMuUWSZ_2TO7y4){u9<)VzaOC z=T|a*qv5~TE-RU!&-`yGWg|duqe__ytx(I9Yl(89HDCzQgtIi96_rdqpWSx_#*qPCZ^xt#7P=Ng2}L&h9p)GdGFU uRVg@m4zhh;z3@9cK%^$}f-HBjp2JkdSTfH!c*U8YQ~vG#kh8UF!^%~S{g literal 0 HcmV?d00001 diff --git a/BoldCom.dproj b/BoldCom.dproj index a4bcfad..6f9f182 100644 --- a/BoldCom.dproj +++ b/BoldCom.dproj @@ -18,6 +18,11 @@ Base true + + true + Base + true + true Base @@ -71,6 +76,10 @@ true CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName) 1033 + vcl;$(DCC_UsePackage) + + + vcl;$(DCC_UsePackage) RELEASE;$(DCC_Define) diff --git a/BoldComGUI.dproj b/BoldComGUI.dproj index d748ef9..71f1295 100644 --- a/BoldComGUI.dproj +++ b/BoldComGUI.dproj @@ -18,6 +18,11 @@ Base true + + true + Base + true + true Base @@ -64,6 +69,10 @@ true CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName) 1033 + vcl;$(DCC_UsePackage) + + + vcl;$(DCC_UsePackage) RELEASE;$(DCC_Define) diff --git a/BoldComGUI.res b/BoldComGUI.res new file mode 100644 index 0000000000000000000000000000000000000000..42e41efe9ee1965d7c641b733330cb2c3e2ac3f0 GIT binary patch literal 652 zcmaKqK}*9x5QSe#4pw{c?!|-W5+MkJDAn2$uqrY3Dz(-UNfU|n=lO5E`wxuYZd{rc zbYONTnR)Nc?yMy3<5g8V;hJ??F275SXLEttzANgqLc+1`^uT(lm?+YXuKA8w2gJrc z{I74x;A;-IpV_Qr2wmp)mtOec!M9YYRJrD`rOGseIoGoa3J10(P^du1ct{VXqf_mG zb@hEPZ<<=3SNKw}xs^F5%JifQ_JxMJhuc`7tpi5QR@l7S@Hh>`Gj?mI&Dhg0xg6;7_TcxRY9I38YC$EA-`j8~46}^_v?n z{aJM2-cD!EIWw6%l61;ht?GljWvzzKAA<>8E>bh}pjIQs9q3uF+&AjuC3?~${}b+8 ze6z3c=T|a*t>J&KT~;zdpZO1INgzOPp-PzwO;F2}Ym9QC50wB@hlvy`(j_OR2kWS- zBe)*lg)`U4>CDi};1;e-2QSw<_zujaW?&3ECmZQtLt{X^BEIHc=p2kc(v_>(1688< zNxcOV7-|aBY+tR|)!OFnR@|-kq7(Y7ITNZ{rGzgr8_~m*-p1T-WGW&a$3lRM^}^18Kc I?v(ApADBH_zW@LL literal 0 HcmV?d00001 diff --git a/BoldDOA.res b/BoldDOA.res new file mode 100644 index 0000000000000000000000000000000000000000..d7963959af8a1dea3bb1416eff1368e3637f7c4f GIT binary patch literal 628 zcmZ9KPfNo<5XE042kXhBM-QGQLJkTAsZ=FU|4>7(rPf*kX(F+HJim>1FFhN7v+2?% z1GAazy!U2yXC>(ruj|GMTeb;&{um5DSfpO)L7N~ZoajYU)?1B<5t`cD6Fp*-qy24|6u#PTu2-o9> za6UD6Iv?m|a0^%FhA7vYhV(fwy%ui*uY$S5U+5f+caMJtRig4mjWws9X$8})s~TVtdX&eCv}R5JC1j?L!OUD3~i^_5J;&Wuj1?~?s)ePabo%8>qccDE^=xk;q1 tO2NrzR3iWY literal 0 HcmV?d00001 diff --git a/BoldExPe.dproj b/BoldExPe.dproj index 83a1107..d328026 100644 --- a/BoldExPe.dproj +++ b/BoldExPe.dproj @@ -18,6 +18,11 @@ Base true + + true + Base + true + true Base @@ -64,6 +69,10 @@ true CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName) 1033 + vcl;vclx;vcldb;$(DCC_UsePackage) + + + vcl;vclx;vcldb;$(DCC_UsePackage) RELEASE;$(DCC_Define) diff --git a/BoldExPe.res b/BoldExPe.res new file mode 100644 index 0000000000000000000000000000000000000000..36c6894c3cf92af160da52b7f16852a83bb104a9 GIT binary patch literal 640 zcmZvaK~KU!5QSe!57v`cZXP_FYI>277z}EfC=zHmY7mh$DXpoP_~-mL-u(yGZ?~)z z!X~pFcHf)#m|00WCaS6q((To9_eWqndlxG3|3R&YbfU4I*snDri}j!Zzhm|ral*HRX>TP{(A}($^vHony_HI(%C(?cs!Ve#=XzBEuwyZyB89pjB0LyJ9R+Y5 zz7OYJGh644dMVu8%3P6UdV%$+Atw5b%BCD~@*;U%r8K{k~nzKO7D8%Yp&oi`_c$%|6b5r7CiW}p-;C!D4!}OS%LAy?E zIxC&nsU%h@rvn+tX72+3+vj + + {DFD5A34D-3F28-461E-9001-16DFEADD40A9} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Default.Personality.12 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/BoldIB.dproj b/BoldIB.dproj index 35006cc..412cf44 100644 --- a/BoldIB.dproj +++ b/BoldIB.dproj @@ -18,6 +18,11 @@ Base true + + true + Base + true + true Base @@ -64,6 +69,10 @@ true CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName) 1033 + vcl;vcldb;ibxpress;$(DCC_UsePackage) + + + vcl;vcldb;ibxpress;$(DCC_UsePackage) RELEASE;$(DCC_Define) diff --git a/BoldIB.res b/BoldIB.res new file mode 100644 index 0000000000000000000000000000000000000000..b9f9acf203b664c69b4883c89958ff1b977d1e2b GIT binary patch literal 628 zcmZ9KO-sW-5Qg7KK`gdhllv{WVH7culIwbl|y6RGv*`ER^?>Dl<~#HDEl zb~C&CeoS^&l8zX4-3-#LSO@<601OKvQZMwNbr6$|^`vL!OQmFq9(2z-VZI`F@fH63 zN{-)X`0s_CN>0$9{BJ2`BS3GZrE-;;qn4}C4CPX9ssQ#46Dg*uGe%4euA)=z!u9wO zoDWS+=N-KqZfQ0{vO=#Y4s9K2uf-d~Tf*GnPt?c75B$yN5mbfBCmt*QdZGnP7hV0> z^tbU{m#)W+4ymc(%yDw+iAJVB#dkp!Gv*ggmQ*mI5?6P{e%Ifz0y^c8{&qIEDIHrU vGIJ^U^8#f1zIx$zxP!(yqptU<>Q)0~*5_1rWCPy7HC@Q)Todj0;(GiCx)f78 literal 0 HcmV?d00001 diff --git a/BoldMMLink.dproj b/BoldMMLink.dproj index 6132c93..bb62a3a 100644 --- a/BoldMMLink.dproj +++ b/BoldMMLink.dproj @@ -18,6 +18,11 @@ Base true + + true + Base + true + true Base @@ -64,6 +69,10 @@ true CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName) 1033 + vcl;$(DCC_UsePackage) + + + vcl;$(DCC_UsePackage) RELEASE;$(DCC_Define) diff --git a/BoldMMLink.res b/BoldMMLink.res new file mode 100644 index 0000000000000000000000000000000000000000..a70827e2ae1ff364df368de19bd3293d8ce88d6b GIT binary patch literal 652 zcmZ{iPfNo<5XE0g4pw{c?!|*=i4X)q6s1-I^$#)hDz(-UO;f4$>Sfn{;e^_hike_6gU5 zzaMG}(ydKAvGJ_p*4fs%QthFw#!O&zEQz|tGlGALt}*))kvU3+D02E|oNvg7nEe{xtxx~^ zM{@YOM)SV3sN@PZk-sB7a^O*KrBbPKEvS|%)11n=UR99TwVY6qLY-p~8l0l80DN!*+jniImzDt8cdQ8n_H=SB{ zRyww+B*v7}fsD*{?*jkJ=X&S@tEzpJ4b@X(Gau^~ug873p{of~tXKQ)xOx8q(JWJ9 literal 0 HcmV?d00001 diff --git a/BoldSQLDirect.res b/BoldSQLDirect.res new file mode 100644 index 0000000000000000000000000000000000000000..4b1a68d0cfce9437496c8cf6ea28e1256b51549b GIT binary patch literal 664 zcmaKqK}*9x5QSe#4%UNs>`6R$mI%2Bf>f#!s8wqy-lW!A0%;<#f`86`NANbS&rI;|LYqz655UuuY#=vD*%C)`)~ zW?$jYuVnmM!~dSUtYm^d^B>YDfdIXQDrG7(LoHLTDawUjRRT;MCQ__Or<|A`tfQXx z;Cg%y&buZ~=MB9KZsE#Y;N^Ou%DwuqGB8t+3$l@R8X6_xBvV>Y literal 0 HcmV?d00001 diff --git a/BoldUDPProp.res b/BoldUDPProp.res new file mode 100644 index 0000000000000000000000000000000000000000..e15e0ec94c5611606b05299189b56ba5872e2855 GIT binary patch literal 652 zcmZ{i%}T>i5QR@l7FM$G0bICnEfKO%5VTT%0{&5Bw^G|$0%=-eeLUaBy>DRr=Eh5Z zpcCe1a%aw*lRHA%2jGYw_JtBbT0L-8HKm5CRUK~mQ0CZ5PNJZ4^&H#bcgR)I8D7`BsJl}~nVWx4_e34;#tqZSm}q0G_sC}d E2jHt$%K!iX literal 0 HcmV?d00001 diff --git a/BoldUml.dproj b/BoldUml.dproj index 72fb2ee..0aaaeb6 100644 --- a/BoldUml.dproj +++ b/BoldUml.dproj @@ -18,6 +18,11 @@ Base true + + true + Base + true + true Base @@ -64,6 +69,10 @@ true CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName) 1033 + vcl;$(DCC_UsePackage) + + + vcl;$(DCC_UsePackage) RELEASE;$(DCC_Define) diff --git a/BoldUml.res b/BoldUml.res new file mode 100644 index 0000000000000000000000000000000000000000..4fba3de8a5e17b2093c0eef3f285ac1d7e2b36a3 GIT binary patch literal 628 zcmZvaPfNo<5XE042kXhBM-QH*LJkUoRH_oFe`sT`Qfn-MG?7?8p5Mm1m!6Hk*|;ig4WqAK=t1is!kucOC*~`S@nYTUj(yC0jc?;K z{Qi-Q-)Q*t!re+H=x_dxlyDHBw^F4{g%+q~%9WyA=v5`azQgntk<}R%k%MJ)s$IAq zKZNtHxzl+=FN0gSFqe3_Ui7FXtJT)#P2p8AH~14BgYo9^51>j^K8UfR>KSV3zxt8W z-^O>NbYqNkKrIbtK_pX;HFWxO;x5T2Wq#(SB7+&3Sl%V)-TI6b&?!Uu*V(+LbmTgb uxF`jc=OEkf)eFDE9W>6dy51wJkp@a!pU1kz8}J8i=t4s0n$i9**5hBXo>egb literal 0 HcmV?d00001 diff --git a/BoldUtility.dproj b/BoldUtility.dproj index 18ef944..ce7db65 100644 --- a/BoldUtility.dproj +++ b/BoldUtility.dproj @@ -18,6 +18,11 @@ Base true + + true + Base + true + true Base @@ -64,6 +69,10 @@ true CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName) 1033 + vcl;vclx;$(DCC_UsePackage) + + + vcl;vclx;$(DCC_UsePackage) RELEASE;$(DCC_Define) diff --git a/BoldUtility.res b/BoldUtility.res new file mode 100644 index 0000000000000000000000000000000000000000..aea73fb4fd167f774dba8e964f483bb08629465e GIT binary patch literal 652 zcmZ{i%}T>S5Xb*1Iaukz2k_v*vqZ>2LC{M52xyfWdzD&i38abCdhp?V8}Gh>@wXF~ zriCudX1X)~kM67_?GaT~2kFY{w0wPsp1^96+M#div|`es9`wY1p#fQ2;f_2u1tlduw}|Mfw|DDN*b@NCsM3P$3%<==jcow zu)eCVx+UxKHm;aX%0%ncd`E8f Ee=iGJ2><{9 literal 0 HcmV?d00001 diff --git a/BoldVCLGUI.dproj b/BoldVCLGUI.dproj index 9900ed7..8ce4dd8 100644 --- a/BoldVCLGUI.dproj +++ b/BoldVCLGUI.dproj @@ -18,6 +18,11 @@ Base true + + true + Base + true + true Base @@ -64,6 +69,10 @@ true CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName) 1033 + vcl;$(DCC_UsePackage) + + + vcl;$(DCC_UsePackage) RELEASE;$(DCC_Define) diff --git a/BoldVCLGUI.res b/BoldVCLGUI.res new file mode 100644 index 0000000000000000000000000000000000000000..d122be742a807abcedfa65544af3f4638a8fb047 GIT binary patch literal 652 zcmZ{iK}*9x5QSe#4pw{c?!|*=i4X)qlxl4Wv??+7Dz(-UNfU|n=lO5E`wxuYZd{rc zIxw5*&b;@gGb>4lcvaO-xMrP}%kNX;*<7Hu?}|FDkZ`OAJ#pSBCW>^YTYg8JePUx@ z{?D&u@HL0~UfQf=2wmp?N^e|v@GVs;RjxT~sWQ!A&h@H-!oIBu6e`de9@2y9=t6s7 zU40MCho+Y29ljK7Ze^~BGQH6IwT2q#5pH9Fb{hCG_!5Q{?nKAbIG0YX-aSBase true + + true + Base + true + true Base @@ -64,6 +69,10 @@ true CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName) 1033 + vcl;$(DCC_UsePackage) + + + vcl;$(DCC_UsePackage) RELEASE;$(DCC_Define) diff --git a/BoldXMILink.res b/BoldXMILink.res new file mode 100644 index 0000000000000000000000000000000000000000..381f78415b7978017e8fade57110b8098fdc79ee GIT binary patch literal 652 zcmZ{i%}T>i5QR@l7FM$G0bICnEfKO%5d5M31ZtHSiaV*bmSUPnt&iv1xc3c=-<^2r z5A?#^%)K+`oXO0Uq&=*z8^c{$QOn17$O$YKs~!5JsFmRM^`IyAOJ#Ve?$qO)vR~o5 z^%eg7N)F#}`0uGjB}eEZ|5qxw2;iG*rin_8VVkJX2Ohq z&H4L*rXbzgq?4G=DsEkET`SivwKbSAicTd}$8?71PpNCf{!C;>B?BsQ^;g_)s>7iJ zCg>2pYl|*R`!=E6)Ji&0kh$E)cK99gRCI#X^)}UYb*|jzpV8Z#Q>JUClQYp~Ex#i- F`#-hgSD^p^ literal 0 HcmV?d00001 diff --git a/Source/ClientGuiCom/BoldControls/BoldAwareGuiComReg.rc b/Source/ClientGuiCom/BoldControls/BoldAwareGuiComReg.rc new file mode 100644 index 0000000..88b657d --- /dev/null +++ b/Source/ClientGuiCom/BoldControls/BoldAwareGuiComReg.rc @@ -0,0 +1,34 @@ +TBoldAsCheckBoxStateRendererCom BITMAP LOADONCALL ..\..\..\Images\ComponentsCom\TBoldAsCheckBoxStateRendererCom.bmp +TBoldAsFloatRendererCom BITMAP LOADONCALL ..\..\..\Images\ComponentsCom\TBoldAsFloatRendererCom.bmp +TBoldAsIntegerRendererCom BITMAP LOADONCALL ..\..\..\Images\ComponentsCom\TBoldAsIntegerRendererCom.bmp +TBoldAsViewerRendererCom BITMAP LOADONCALL ..\..\..\Images\ComponentsCom\TBoldAsViewerRendererCom.bmp +TBoldAsStringRendererCom BITMAP LOADONCALL ..\..\..\Images\ComponentsCom\TBoldAsStringRendererCom.bmp +TBoldAsMLStringRendererCom BITMAP LOADONCALL ..\..\..\Images\ComponentsCom\TBoldAsMLStringRendererCom.bmp +TBoldCaptionControllerCom BITMAP LOADONCALL ..\..\..\Images\ComponentsCom\TBoldCaptionControllerCom.bmp +TBoldChartCom BITMAP LOADONCALL ..\..\..\Images\ComponentsCom\TBoldChartCom.bmp +TBoldCheckBoxCom BITMAP LOADONCALL ..\..\..\Images\ComponentsCom\TBoldCheckBoxCom.bmp +TBoldComboBoxCom BITMAP LOADONCALL ..\..\..\Images\ComponentsCom\TBoldComboBoxCom.bmp +TBoldControlGridCom BITMAP LOADONCALL ..\..\..\Images\ComponentsCom\TBoldControlGridCom.bmp +TBoldEditCom BITMAP LOADONCALL ..\..\..\Images\ComponentsCom\TBoldEditCom.bmp +TBoldGridCom BITMAP LOADONCALL ..\..\..\Images\ComponentsCom\TBoldGridCom.bmp +TBoldImageCom BITMAP LOADONCALL ..\..\..\Images\ComponentsCom\TBoldImageCom.bmp +TBoldLabelCom BITMAP LOADONCALL ..\..\..\Images\ComponentsCom\TBoldLabelCom.bmp +TBoldListBoxCom BITMAP LOADONCALL ..\..\..\Images\ComponentsCom\TBoldListBoxCom.bmp +TBoldListViewCom BITMAP LOADONCALL ..\..\..\Images\ComponentsCom\TBoldListViewCom.bmp +TBoldMemoCom BITMAP LOADONCALL ..\..\..\Images\ComponentsCom\TBoldMemoCom.bmp +TBoldNavigatorCom BITMAP LOADONCALL ..\..\..\Images\ComponentsCom\TBoldNavigatorCom.bmp +TBoldProgressBarCom BITMAP LOADONCALL ..\..\..\Images\ComponentsCom\TBoldProgressBarCom.bmp +TBoldRadioGroupCom BITMAP LOADONCALL ..\..\..\Images\ComponentsCom\TBoldRadioGroupCom.bmp +TBoldRendererCom BITMAP LOADONCALL ..\..\..\Images\ComponentsCom\TBoldRendererCom.bmp +TBoldRichEditCom BITMAP LOADONCALL ..\..\..\Images\ComponentsCom\TBoldRichEditCom.bmp +TBoldTimePickerCom BITMAP LOADONCALL ..\..\..\Images\ComponentsCom\TBoldTimePickerCom.bmp +TBoldTrackBarCom BITMAP LOADONCALL ..\..\..\Images\ComponentsCom\TBoldTrackBarCom.bmp +TBoldTreeViewCom BITMAP LOADONCALL ..\..\..\Images\ComponentsCom\TBoldTreeViewCom.bmp +TBoldXCVTreeViewCom BITMAP LOADONCALL ..\..\..\Images\ComponentsCom\TBoldXCVTreeViewCom.bmp +TBoldDataSetCom BITMAP LOADONCALL ..\..\..\Images\ComponentsCom\TBoldDataSetCom.bmp +TBoldDropTargetCom BITMAP LOADONCALL ..\..\..\Images\ComponentsCom\TBoldDropTargetCom.bmp +TBoldPageControlCom BITMAP LOADONCALL ..\..\..\Images\ComponentsCom\TBoldPageControlCom.bmp +TBoldPropertiesControllerCom BITMAP LOADONCALL ..\..\..\Images\ComponentsCom\TBoldPropertiesControllerCom.bmp +TBoldStringsPropertyControllerCom BITMAP LOADONCALL ..\..\..\Images\ComponentsCom\TBoldStringsPropertyControllerCom.bmp +TBoldExceptionHandlerCom BITMAP LOADONCALL ..\..\..\Images\ComponentsCom\TBoldExceptionHandlerCom.bmp + \ No newline at end of file diff --git a/Source/ClientGuiCom/BoldControls/BoldAwareGuiComReg.res b/Source/ClientGuiCom/BoldControls/BoldAwareGuiComReg.res new file mode 100644 index 0000000000000000000000000000000000000000..98825a08ee61c8cebb618bfccaf68b932dd35c11 GIT binary patch literal 15248 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 literal 0 HcmV?d00001 diff --git a/Source/ClientGuiCom/BoldControls/BoldGridCom.pas b/Source/ClientGuiCom/BoldControls/BoldGridCom.pas index aaa13a7..fb662b6 100644 --- a/Source/ClientGuiCom/BoldControls/BoldGridCom.pas +++ b/Source/ClientGuiCom/BoldControls/BoldGridCom.pas @@ -632,7 +632,7 @@ procedure TBoldInplaceEditCom.KeyPress(var Key: Char); Grid := TBoldCustomGridCom(Owner); Grid.SetSelection(grid.DataRow(grid.Row), [], true, false); if (Key in [#32..#255]) and - not Grid.Columns[Grid.Col].BoldProperties.ValidateCharacter(Key, Grid.CurrentCellFollower) then + not Grid.Columns[Grid.Col].BoldProperties.ValidateCharacter(AnsiChar(Key), Grid.CurrentCellFollower) then begin MessageBeep(0); Key := BOLDNULL; @@ -1918,7 +1918,7 @@ procedure TBoldCustomGridCom.ColWidthsChanged; function TBoldCustomGridCom.CanEditAcceptKey(KEY: Char): Boolean; begin Result := Assigned(CurrentCellFollower) and - TBoldStringFollowerControllerCom(CurrentCellFollower.Controller).ValidateCharacter(KEY, CurrentCellFollower); + TBoldStringFollowerControllerCom(CurrentCellFollower.Controller).ValidateCharacter(AnsiChar(Key), CurrentCellFollower); end; function TBoldCustomGridCom.CanEditModify: Boolean; diff --git a/Source/ClientGuiCom/BoldControls/BoldMemoCom.pas b/Source/ClientGuiCom/BoldControls/BoldMemoCom.pas index 6298663..81da733 100644 --- a/Source/ClientGuiCom/BoldControls/BoldMemoCom.pas +++ b/Source/ClientGuiCom/BoldControls/BoldMemoCom.pas @@ -324,7 +324,7 @@ procedure TBoldCustomMemoCom.KeyPress(var Key: Char); begin inherited KeyPress(Key); if (Key in [#32..#255]) and - not BoldProperties.ValidateCharacter(Key, Follower) then + not BoldProperties.ValidateCharacter(AnsiChar(Key), Follower) then begin MessageBeep(0); Key := BOLDNULL; diff --git a/Source/ClientGuiCom/BoldControls/BoldRichEditCom.pas b/Source/ClientGuiCom/BoldControls/BoldRichEditCom.pas index e58dccb..f0a5a54 100644 --- a/Source/ClientGuiCom/BoldControls/BoldRichEditCom.pas +++ b/Source/ClientGuiCom/BoldControls/BoldRichEditCom.pas @@ -312,7 +312,7 @@ procedure TBoldCustomRichEditCom.KeyPress(var Key: Char); begin inherited KeyPress(Key); if (Key in [#32..#255]) and - not BoldProperties.ValidateCharacter(Key, Follower) then + not BoldProperties.ValidateCharacter(AnsiChar(Key), Follower) then begin MessageBeep(0); Key := BOLDNULL; diff --git a/Source/ClientGuiCom/BoldControls/BoldTreeViewCom.pas b/Source/ClientGuiCom/BoldControls/BoldTreeViewCom.pas index 33de1df..344fe63 100644 --- a/Source/ClientGuiCom/BoldControls/BoldTreeViewCom.pas +++ b/Source/ClientGuiCom/BoldControls/BoldTreeViewCom.pas @@ -742,7 +742,7 @@ procedure TBoldCustomTreeViewCom.KeyPress(var Key: Char); begin inherited KeyPress(Key); if Assigned(FEditFollower) and (Key > #32) and - not (FEditFollower.Controller as TBoldStringFollowerControllerCom).ValidateCharacter(Key, FEditFollower) then + not (FEditFollower.Controller as TBoldStringFollowerControllerCom).ValidateCharacter(AnsiChar(Key), FEditFollower) then begin MessageBeep(0); Key := #0; diff --git a/Source/ClientGuiCom/IDE/BoldAwareGuiComReg.res b/Source/ClientGuiCom/IDE/BoldAwareGuiComReg.res new file mode 100644 index 0000000000000000000000000000000000000000..98825a08ee61c8cebb618bfccaf68b932dd35c11 GIT binary patch literal 15248 zcmds8&uUtroN~0}14u+#!!};57{&r;L!=z~Fe(oxe2R^bGJRN? ziI6g!mRLDBXHJ{~(H>$cIplzpe}P+aV-6MutwiPf-mB`ac8{Tl_1Gq5Pxm*kUR8J3 z*YDM#X_755on14)9a|`OK*J9Ip4zAL}RR={YwB|0d7%gd-q6x!Kv- zK?WayC#NSI^_iTpnjDkD)mFdXA9$QVT;S=wq`+%yy#nt|mpZXL){pAJjhIk&9qD)e z9`uwk8!*Gi%+1Zs@;qf%XB8vcW>38wIx{NIs6VH2W2ddXBywn@_Ck)TF3n2)tliGd zJbd_Yipbj8=g*&`m?U4jU~;^KB6W@zAa4t+-hauaE!)eQ>Ng)T<=6JZSkec>T&Og3(`pkX2)v_}~fH>ndB4 z39Y*NLeox!&z1OmiO(y3g>>HIcT7S4-vM((|J~p@a|FM7_=ZJZvd(vJ{z&@yu35lb#>o)rZ;-zKS>>?tk8xs4nzr87u^OAVy zapU1}d@*C;oI%tF;$g(UlF+<&)eEj~2xgG%oZt<~=rzYu;{&ZnD;1n-y2kob=h|*J z72Mu+_y^8RQpnBR=V=OgnqKS90=r$oh@BvpbPc}vbGb|BUi-LL-V*PN1y|*04)MP9 z#rN;upAr>2`|R1Xmcp7ZzQ`7=jCnZTxeOjx#vad1f&tg1-Ylgm**RS$a_J~zE>K~K8d6cO07mrtCD{R(xPKHN) zli3!wD~KffG~UA)YeGoku_Z>VJaSx$q&zA< z2|RK(fin^O+^$&T@$rbaT#~exQp$MKb{&0I+hfUyH%DZu^9a1;k=SF3``mAj>>oqV$k=uf zb4IaM9`-n;Vc&?>(S)XXAl=v++O)uE(*o~BSUi+8Z$FRq8{-jWQDRZ>{%@SHaxkzMip}EsirDX~f?^je|#<`^aW}y=QZk8~V{4#pLd?Fxn0Yb~cS( zu!p9kpG>BePTJfgG}B_+kMx2CMEE$bYI=y^YX0q zZtwSAZZ3)thnL-1?Fwm(N8K0J?QaR}UBTFJY3%;*(ETS~e(A{&Ljc;0$FA8V?t)R+ z10j?)t<7~9U~`(t6s1zYt4o2P&H_Ol1*d{KE7aOq81D{GlEMwJZZ8UJCHQ)r_V)|i zQ8kuXLhr}9oO(ohOfig7;#*F-#G%9?c7U+3&A1Rr<$H=DcNjHL{xxtqulirJTMIan zvmO`fgie7WZ~JtERyWO9Q4a9U!Dd8nQ18a*ibeCQttT>mTMk+dSH*YKJ$_7t#j5#CZigPImu5 zGafyOI3YA-Gi>0KBP7Lpys?La;(TMT<#BE{_DoCUYlhfNi%ukmW~m?50~+3t3;5;u zx_mo)$|(2vg!GB^@%^&QdFz_hE%c68z~^MSZ01u#Bknu**yNI|CA*T~{x)9xi+|#F z55!)bTS^Mgw!ZHI2Yfw%%di)Or4BDXZRS(!T;2qC9O1WR4YF;1g%yqy?q4^0BvXBA zu2B!$auCafZm$!|MSq0+z54Le;IgQHpMMQ+$l-C>Y#n1Bo}%hsKj}4OQaJe(Y%;^8 zf`2{c{aK@UT!amB58lVly^RyEHtQ!(NW8P{wk4hdkAtnPZSe!N$G1+f#5-S4Oe^4$qduK5xWBWG@L2>;q@wKP1YEj^^@~x zpsH`>YQ|+@u^#O-8$*sWpVNrPsm%I+8vrEYL!(Wps}D-Ay3sE(?)LjdMuZ*lT{iV= zyH32y)<&sFr;4HKFOc!A@;LZbd_B&1XC8M{=kY2m@za{(A^KFn!g0VRNeY~l@~CX66LSH>P$%XBu=dO};9NlBG3Nq;{3zxE>b{k$!(Yi7 z<3VgTnV&m!o3sbd>qskl{t&*FoP~DBoK4a0f>GjQ_>1e|ypHG0g3G`kxeRi08SV{S z(ukQ7%0p=bg6>D};7h0D_d+fZ>t0ANmtFAG?{v5yy*|gvUmfrl2Df0B zlih>U$gdV-bNaGYB13i=Z6rzh1`C8kI=LXvfmNOkb7T~9WCZ;jxGsnOKDjnLcga(~ z-+zOd2;eNpO^%qg$berhG8pTG48}SkV^aNN-5yh!6X5PR&IND>dX>q;?<1SWtsv;m z77ihO6F|A*0ZEo5CS)X7_MP%y5*VuDJDG$14DT@G&Le4IsWz5_^Fkjus>j!#v7BFN zF=x-7J!38Jr+Y@Q+-LSk<-E=*l@r>tk^E-|%B6nQKXvcky(xkA%;U$8{fdq)Yqys6 zSm$yX9FjrCs^vb8IC5>`TgMrLG_y;67CnZojSOfIn@BnY{D7YDHS5gt2b>J_bwYku z;~dTAO(>T{`0*yR33{*HjZ?}~Y??_6zWs}til-X~0q-Q+mw zZ#e|Z-s4o|qcFFW7jkT0F3S3S=^#l;Jl2ov3H4{F!Q}XC u2LCMg6ZRLd!Z2q`9QN0>?44roG6J!`hS)c2W#1I>R6e!ucY7b6Bl;g^06sGS literal 0 HcmV?d00001 diff --git a/Source/ClientHandlesCom/IDE/BoldHandleComReg.RES b/Source/ClientHandlesCom/IDE/BoldHandleComReg.RES new file mode 100644 index 0000000000000000000000000000000000000000..c9a496738c37a3342285e3ff49728fa44922d23b GIT binary patch literal 5608 zcmds5zi-<{6n;($N`QeO+Mxpxc#vbD*YCZ%BgM!dp}4bqBU&B z*bT5EgC(MGpfTnS9nd=M&=$qCPd{KgpbdJ8(Z{q6-4@QCVEk!ueMGCD`I9dJzHr+T zS@jxx|M|Jy8s1QjJtF*5uV)X~17hpZXf(nA-z*=DJz#I|-;mZC10sOxZc`)zUM{gZ zFY$7#!0CCZSFKN~FYZ~jq92>JmB#bSnoiGZKmA%8HeS38w0eFSp3^mj{~YV|#mlTy z%bHP!$NKrNm3t2!UVH_p(`l+7C+Em1AFna{GQAuX zT&91IwC6JYcccq0;pbK^;m7NF{k0kmd3bE~#?4Pv0WP&SG*N zxweh@kCQmYq+#NcBu)}cG#)tC31Sp@*Z{Q-dTI`glidM1K_nD`NZDFs6w0aSWVB5$mtmUY&_vd@e^qjF8hji+bb10RKJkHK{L| z@jT+j3LY63JhJ{h9uKB?+y#q|Q7JdDUze)6Pu~IUL$`-`UB}2?rIOBrTYfGbcI0pi zRx)YUhWc4%4XK`E0tKt^l;@MNs*lG`5A7-RSr_{7xAA!B^!4HC@RipOhpz^M(3n8$ zI$*!w;Y6$I46}|@_;Aq8GUDu1O&GwLsfn8L?6xV*Hhdk z;BQO%qAG(#bK|g*9Fb(bq`yyKB-uhHljD)o^4yTivP|LWDbwIvtuSD$5L1ZMoUsl~ zPNDGw;V(TIP()$=*2n>l$^x>iB5LmA|4v&CV z9k+}ru<;3u9AxwC(IMv`8=s7?8vAqkis!VygK)#Y>9!6ffzl66y{3Sa6P9`9FD2ndUQ= z_}rvtIL0#>olkt0RTK;anpEKE!N(TrIo#28synVa$13Q!_*7CT@eT*U#n{>SwAIwb zCo*gyBv$s6YvPnFV0=!$ue@JJnP2X6x3L{y<8MU^@ZHaUQ@|vD@cWRnfgvZzz}idy zn%nO~Xq|G`$)b(oVr#i`HuglWwXm|cdc_B4FS%El5PocrWc}M7$=bLcNv^HFmq^Dt cp||$7*HwILx$SjvpSWw=>slN4rX$z>2V@IV3IG5A literal 0 HcmV?d00001 diff --git a/Source/ClientHandlesCom/IDE/BoldHandleComReg.rc b/Source/ClientHandlesCom/IDE/BoldHandleComReg.rc index 7c31f80..7995978 100644 --- a/Source/ClientHandlesCom/IDE/BoldHandleComReg.rc +++ b/Source/ClientHandlesCom/IDE/BoldHandleComReg.rc @@ -1,12 +1,12 @@ -TBOLDSYSTEMHANDLECOM BITMAP LOADONCALL TBoldSystemHandleCom.bmp -TBOLDEXPRESSIONHANDLECOM BITMAP LOADONCALL TBoldExpressionHandleCom.bmp -TBOLDLISTHANDLECOM BITMAP LOADONCALL TBoldListHandleCom.bmp -TBOLDSQLHANDLECOM BITMAP LOADONCALL TBoldSQLHandleCom.bmp -TBOLDPLACEABLESUBSCRIBERCOM BITMAP LOADONCALL TBoldPlaceableSubscriberCom.bmp -TBOLDFILTERCOM BITMAP LOADONCALL TBoldFilterCom.bmp -TBOLDCOMPARERCOM BITMAP LOADONCALL TBoldComparerCom.bmp -TBOLDVARIABLEHANDLECOM BITMAP LOADONCALL TBoldVariableHandleCom.bmp -TBOLDREFERENCEHANDLECOM BITMAP LOADONCALL TBoldReferenceHandleCom.bmp -TBOLDCURSORHANDLECOM BITMAP LOADONCALL TBoldCursorHandleCom.bmp -TBOLDDERIVEDHANDLECOM BITMAP LOADONCALL TBoldDerivedHandleCom.bmp -TBOLDVARIABLEDEFINITIONCOM BITMAP LOADONCALL TBoldVariableDefinitionCom.bmp +TBOLDSYSTEMHANDLECOM BITMAP LOADONCALL ..\..\..\Images\ComponentsCom\TBoldSystemHandleCom.bmp +TBOLDEXPRESSIONHANDLECOM BITMAP LOADONCALL ..\..\..\Images\ComponentsCom\TBoldExpressionHandleCom.bmp +TBOLDLISTHANDLECOM BITMAP LOADONCALL ..\..\..\Images\ComponentsCom\TBoldListHandleCom.bmp +TBOLDSQLHANDLECOM BITMAP LOADONCALL ..\..\..\Images\ComponentsCom\TBoldSQLHandleCom.bmp +TBOLDPLACEABLESUBSCRIBERCOM BITMAP LOADONCALL ..\..\..\Images\ComponentsCom\TBoldPlaceableSubscriberCom.bmp +TBOLDFILTERCOM BITMAP LOADONCALL ..\..\..\Images\ComponentsCom\TBoldFilterCom.bmp +TBOLDCOMPARERCOM BITMAP LOADONCALL ..\..\..\Images\ComponentsCom\TBoldComparerCom.bmp +TBOLDVARIABLEHANDLECOM BITMAP LOADONCALL ..\..\..\Images\ComponentsCom\TBoldVariableHandleCom.bmp +TBOLDREFERENCEHANDLECOM BITMAP LOADONCALL ..\..\..\Images\ComponentsCom\TBoldReferenceHandleCom.bmp +TBOLDCURSORHANDLECOM BITMAP LOADONCALL ..\..\..\Images\ComponentsCom\TBoldCursorHandleCom.bmp +TBOLDDERIVEDHANDLECOM BITMAP LOADONCALL ..\..\..\Images\ComponentsCom\TBoldDerivedHandleCom.bmp +TBOLDVARIABLEDEFINITIONCOM BITMAP LOADONCALL ..\..\..\Images\ComponentsCom\TBoldVariableDefinitionCom.bmp diff --git a/Source/Common/ConnectionHandlesCOM/BoldXMLDispatcher.pas b/Source/Common/ConnectionHandlesCOM/BoldXMLDispatcher.pas index 73e4eef..b4aa967 100644 --- a/Source/Common/ConnectionHandlesCOM/BoldXMLDispatcher.pas +++ b/Source/Common/ConnectionHandlesCOM/BoldXMLDispatcher.pas @@ -10,7 +10,7 @@ interface BoldUtils, BoldSOAP_TLB, BoldStringList, - MSXML_TLB, + Bold_MSXML_TLB, BoldComServerHandles, BoldDefs, BoldXMLRequests, diff --git a/Source/Extensions/OLLE/Core/__history/BoldOLLEDistributableObjectHandlers.pas.~3~ b/Source/Extensions/OLLE/Core/__history/BoldOLLEDistributableObjectHandlers.pas.~3~ new file mode 100644 index 0000000..460ca39 --- /dev/null +++ b/Source/Extensions/OLLE/Core/__history/BoldOLLEDistributableObjectHandlers.pas.~3~ @@ -0,0 +1,1175 @@ + +{ Global compiler directives } +{$include bold.inc} +unit BoldOLLEDistributableObjectHandlers; + +interface + +uses + Windows, + BoldDefs, + BoldId, + BoldDefaultId, + BoldGlobalId, + DistributableInfo, + BoldValueInterfaces, + BoldValueSpaceInterfaces, + BoldFreeStandingValues, + BoldElements, + BoldSystem, + BoldCondition, + BoldPersistenceControllerDefault, + BoldPMappers, + BoldPMappersDefault, + BoldPersistenceController, + BoldDbInterfaces, + BoldOLLEdmmain; + + + +const + BOLD_OLL_IDATTRIBUTECOLUMN_NAME = 'LOCALID'; + BOLD_OLL_PSIDATTRIBUTECOLUMN_NAME = 'GLOBALID'; + BOLD_OLL_NAMEOFCLASSATTRIBUTECOLUMN_NAME = 'NAMEOFCLASS'; + +type + TBoldPSId = string; + TBoldDistributableObjectHandler = class; + TBoldForeignObjectHandler = class; + TBoldOwnObjecthandler = class; + TBoldBrokenLinkResolver = class; + + TBoldLinkResolveAction = (blraCut, blraAbort, blraFailObject, blraIgnore, blraMissing); + + TBoldBrokenLinkResolver = class + private + fHeldObjectAction: TBoldLinkResolveAction; + fNonheldObjectAction: TBoldLinkResolveAction; + public + function ResolveBrokenLink(ObjectContents: IBoldObjectContents; MemberIndex: Integer; Hold: Boolean): Boolean; + property HeldObjectAction: TBoldLinkResolveAction read fHeldObjectAction write fHeldObjectAction; + property NonheldObjectAction: TBoldLinkResolveAction read fNonheldObjectAction write fNonheldObjectAction; + end; + + TBoldDistributableObjectHandler = class + private + fPController: TBoldPersistenceControllerDefault; + fOllSystem: TBoldSystem; + fBrokenLinkResolver: TBoldBrokenLinkResolver; + fMyTransaction: Boolean; + fTheMapping: TMapping; + function TheMapping: TMapping; + function LookupInfoByLocalId(LocalId: TBoldDefaultId): TDistributableObjectInfo; + procedure AddToMapping(anObj: TDistributableObjectInfo); + procedure GetLocalIdsFor(InfoObjects: TDistributableObjectInfoList; IdList: TBoldObjectIdList); + function GetForeignPSInfo(PSId: TBoldPSId): TForeignPSInfo; + procedure ExtractAllIds(IdList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; OutIdList: TBoldObjectIdList); + procedure Fetch(IdList: TBoldObjectIdList; ValueSpace: IBoldValueSpace); + procedure GetInfoObjectsFor(IdList: TBoldObjectIdList; InfoObjectList: TDistributableObjectInfoList; RemainingIdList: TBoldObjectIdList); + procedure NewOwnInfoObjectsFor(IdList: TBoldObjectIdList; InfoObjectList: TDistributableObjectInfoList); + procedure NewForeignInfoObjectsFor(IdList: TBoldObjectIdList; InfoObjectList: TDistributableObjectInfoList; Owner: TForeignPSInfo; Hold: Boolean = false); + procedure MakeGlobalTranslationListFor(ValueSpace: IBoldValueSpace; IdList: TBoldObjectIdList; GlobalTranslationList: TBoldIdTranslationList); + procedure MakeLocalizingTranslationList(ValueSpace: IBoldValueSpace; GlobalIdList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList); + procedure SearchByOcl(OclExpr: string; IdList: TBoldObjectIdList); + procedure Update(ValueSpace: IBoldValueSpace; IdList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList; var TimeStamp: Integer); + procedure LockAndFreeObjects(IdList, FreeList: TBoldObjectIdList); + procedure VerifyAssociations(ValueSpace: IBoldValueSpace; IdList, HoldList: TBoldObjectIdList); + procedure StartTransaction; + procedure CommitTransaction; + procedure RollbackTransaction; + public + property PController: TBoldPersistenceControllerDefault read fPController write fPController; + property OllSystem: TBoldSystem read fOllSystem write fOllSystem; + property BrokenLinkResolver: TBoldBrokenLinkResolver read fBrokenLinkResolver write fBrokenLinkResolver; + end; + + TBoldForeignObjectHandler = class(TBoldDistributableObjectHandler) + private + procedure PutObjects(ValueSpace: IBoldValueSpace; IdList, HoldList: TBoldObjectIdList; NewLocalTimeStamp: Integer; Owner: TForeignPSInfo); + procedure StartCheckInObjects(ValueSpace: IBoldValueSpace; IdList, ReleaseList: TBoldObjectIdList; Owner: TForeignPSInfo); + procedure ReleaseObjects(ValueSpace: IBoldValueSpace; IdList: TBoldObjectIdList); + procedure UnReleaseObjects(IdList: TBoldObjectIdList); + public + procedure Put(ValueSpace: IBoldValueSpace; IdList: TBoldObjectIdList; HoldList: TBoldObjectIdList; Owner: TBoldPSId); + procedure StartCheckIn(IdList, ReleaseList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; Owner: TBoldPSId); + procedure AcknowledgeCheckIn(Owner: TBoldPSId; NewTimeStamp: Integer); + procedure FailCheckIn(Owner: TBoldPSId); + procedure ObjectsFrom(Owner: TBoldPSId; Objects: TBoldObjectIdList); + procedure HeldObjectsFrom(Owner: TBoldPSId; Objects: TBoldObjectIdList); + procedure ModifiedObjectsFrom(Owner: TBoldPSId; Objects: TBoldObjectIdList); + end; + + TBoldOwnObjectHandler = class(TBoldDistributableObjectHandler) + private + procedure GetObjects(ValueSpace: IBoldValueSpace; IdList, HoldList: TBoldObjectIdList; Holder: TForeignPSinfo); + procedure CheckInObjects(ValueSpace: IBoldValueSpace; IdList, ReleaseList: TBoldObjectIdList; Holder: TForeignPSInfo); + procedure ReserveObjects(ValueSpace: IBoldValueSpace; HoldList: TBoldObjectIdList); + procedure UnCheckOutObjects(IdList: TBoldObjectIdList; Holder: TForeignPSInfo); + procedure InternalGet(IdList, HoldList: TBoldObjectIdList; Holder: TBoldPSId; ValueSpace: IBoldValueSpace); + public + procedure GetSynch(ForeignPS: TBoldPSId; IdList: TBoldObjectIdList; Valuespace: IBoldValueSpace); + procedure AcknowledgeSynch(ForeignPS: TBoldPSId); + procedure FailSynch(ForeignPS: TBoldPSId); + procedure Get(IdList, HoldList: TBoldObjectIdList; Holder: TBoldPSId; ValueSpace: IBoldValueSpace); + procedure CheckIn(ValueSpace: IBoldValueSpace; IdList, ReleaseList: TBoldObjectIdList; Holder: TBoldPSId; var NewTimeStamp: Integer); + procedure UnCheckOut(IdList: TBoldObjectIdList; Holder: TBoldPSId); + end; + +implementation + +uses + SysUtils, + BoldUtils, + BoldDomainElement; + +procedure AddObjectToIdList(aDistributableInfo: TDistributableObjectInfo; anIdList: TBoldObjectIdList); +var + anId: TBoldDefaultId; +begin + anId := TBoldDefaultId.CreateWithClassId(BUSINESSCLASSESROOT_TOPSORTEDINDEX, false); + + anId.AsInteger := aDistributableInfo.LocalId; + anIdList.Add(anId); + + anId.Free; +end; + + +{ TForeignObjectHandler } + +procedure TBoldForeignObjectHandler.PutObjects( + ValueSpace: IBoldValueSpace; IdList, HoldList: TBoldObjectIdList; NewLocalTimeStamp: Integer; Owner: TForeignPSInfo); +var + InfoObjects: TDistributableObjectInfoList; + i: Integer; + anObjectId: TBoldDefaultId; + anObject: TBoldObject; + MissingInfos: TBoldObjectIdList; + aForeignObjectInfo: TForeignObjectInfo; +begin + InfoObjects := TDistributableObjectInfoList.Create; + anObjectId := TBoldDefaultId.Create; + MissingInfos := TBoldObjectIdList.Create; + try + GetInfoObjectsFor(IdList, InfoObjects, MissingInfos); + NewForeignInfoObjectsFor(MissingInfos, InfoObjects, Owner); + for i := 0 to InfoObjects.Count - 1 do + begin + anObject := InfoObjects[i]; + if not (anObject is TForeignObjectInfo) then + raise EBold.CreateFmt('%s.EnsureForeignInfo: Object is not a foreign object', [Classname]); + aForeignObjectInfo := anObject as TForeignObjectInfo; + if not (aForeignObjectInfo.Owner = Owner) then + raise EBold.CreateFmt('%s.EnsureForeignInfo: Wrong owner', [Classname]); + anObjectId.AsInteger := aForeignObjectInfo.LocalId; + aForeignObjectInfo.Put(ValueSpace, HoldList.IdInList[anObjectId], NewLocalTimeStamp); + end; +{ for i := 0 to MissingInfos.Count - 1 do + begin + aForeignObjectInfo := TForeignObjectInfo.Create(OllSystem); + aForeignObjectInfo.LocalId := (MissingInfos[i] as TBoldDefaultId).AsInteger; + aForeignObjectInfo.Owner := Owner; + aForeignObjectInfo.Put(ValueSpace, HoldList.IdInList[MissingInfos[i]], NewLocalTimeStamp); + end;} + finally + InfoObjects.Free; + anObjectId.Free; + MissingInfos.Free; + end; +end; + +procedure TBoldForeignObjectHandler.Put(ValueSpace: IBoldValueSpace; IdList: TBoldObjectIdList; HoldList: TBoldObjectIdList; Owner: TBoldPSId); +var + TranslationList, TranslationList2: TBoldIdTranslationList; + IdList2, HoldList2: TBoldObjectIdList; + NewLocalTimeStamp: Integer; +begin + TranslationList := TBoldIdTranslationList.Create; + TranslationList2 := TBoldIdTranslationList.Create; + IdList2 := IdList.Clone; + HoldList2 := HoldList.Clone; + + try + StartTransaction; + try + MakeLocalizingTranslationList(ValueSpace, IdList, TranslationList); + + ValueSpace.ApplyTranslationList(TranslationList); + IdList2.ApplyTranslationList(TranslationList); + HoldList2.ApplyTranslationList(TranslationList); + + VerifyAssociations(ValueSpace, IdList2, HoldList2); + Update(ValueSpace, IdList2, TranslationList2, NewLocalTimeStamp); + IdList2.ApplyTranslationList(TranslationList2); + HoldList2.ApplyTranslationList(TranslationList2); + + LockAndFreeObjects(IdList2, HoldList2); + PutObjects(ValueSpace, IdList2, HoldList2, NewLocalTimeStamp, GetForeignPSInfo(Owner)); + OllSystem.UpdateDatabase; + + CommitTransaction; + except + RollbackTransaction; + raise; + end; + finally + IdList2.Free; + HoldList2.Free; + TranslationList.Free; + TranslationList2.Free; + end; +end; + +procedure TBoldForeignObjectHandler.ReleaseObjects(ValueSpace: IBoldValueSpace; + IdList: TBoldObjectIdList); +begin + PController.PMSetReadonlyness(IdList, nil); +end; + +procedure TBoldForeignObjectHandler.StartCheckIn(IdList, + ReleaseList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; Owner: TBoldPSId); +var + GlobalTranslationList: TBoldIdTranslationList; + OwnerForeignPSInfo: TForeignPSInfo; +begin + GlobalTranslationList := TBoldIdTranslationList.Create; + try + StartTransaction; + try + OwnerForeignPSInfo := GetForeignPSInfo(Owner); + if OwnerForeignPSInfo.IsCheckingIn then + raise EBold.CreateFmt('%s.StartCheckIn: Already checking in objects for this persistent storage', [Classname]); + Fetch(Idlist, ValueSpace); + StartCheckInObjects(ValueSpace, IdList, ReleaseList, OwnerForeignPSInfo); + ReleaseObjects(ValueSpace, ReleaseList); + + MakeGlobalTranslationListFor(ValueSpace, IdList, GlobalTranslationList); + ValueSpace.ApplytranslationList(GlobalTranslationList); + IdList.ApplyTranslationList(GlobalTranslationList); + ReleaseList.ApplyTranslationList(GlobalTranslationList); + + OllSystem.UpdateDatabase; + + CommitTransaction; + except + RollbackTransaction; + raise; + end; + finally + GlobalTranslationList.Free; + end; +end; + +procedure TBoldForeignObjectHandler.StartCheckInObjects( + ValueSpace: IBoldValueSpace; IdList, ReleaseList: TBoldObjectIdList; Owner: TForeignPSinfo); +var + i: Integer; + InfoObjectList: TDistributableObjectInfoList; + NewInfoObjectList: TBoldObjectIdList; + aDistributableObjectInfo: TDistributableObjectInfo; + anId: TBoldDefaultId; +begin + InfoObjectList := TDistributableObjectInfoList.Create; + NewInfoObjectList := TBoldObjectIdList.Create; + anId := TBoldDefaultID.Create; + try + GetInfoObjectsFor(IdList, InfoObjectList, NewInfoObjectList); + NewForeignInfoObjectsFor(NewInfoObjectList, InfoObjectList, Owner, True); + for i := 0 to InfoObjectList.Count - 1 do + begin + aDistributableObjectInfo := InfoObjectList[i] as TDistributableObjectInfo; + anId.AsInteger := aDistributableObjectInfo.LocalId; + aDistributableObjectInfo.StartCheckIn(ValueSpace, not ReleaseList.IdInList[anId]); + end; + finally + InfoObjectList.Free; + NewInfoObjectList.Free; + anId.Free; + end; +end; + +procedure TBoldForeignObjectHandler.AcknowledgeCheckIn(Owner: TBoldPSId; + NewTimeStamp: Integer); +begin + GetForeignPSInfo(Owner).AcknowledgeCheckIn(NewTimeStamp); + OllSystem.UpdateDatabase; +end; + +procedure TBoldForeignObjectHandler.FailCheckIn(Owner: TBoldPSId); +var + FailedReleaseList: TBoldObjectIdList; +begin + FailedReleaseList := TBoldObjectIdList.Create; + try + StartTransaction; + try + GetForeignPSInfo(Owner).FailCheckIn(FailedReleaseList); + UnReleaseObjects(FailedReleaseList); + OllSystem.UpdateDatabase; + + CommitTransaction; + except + RollbackTransaction; + raise; + end; + finally + FailedReleaseList.Free; + end; +end; + +procedure TBoldForeignObjectHandler.UnReleaseObjects( + IdList: TBoldObjectIdList); +begin + PController.PMSetReadonlyness(nil, IdList); +end; + +procedure TBoldForeignObjectHandler.HeldObjectsFrom(Owner: TBoldPSId; + Objects: TBoldObjectIdList); +var + anObjectList: TForeignObjectInfoList; + i: Integer; +begin + Objects.Clear; + anObjectList := GetForeignPSInfo(Owner).OwnedObjectInfos; + anObjectList.EnsureObjects; + for i := 0 to anObjectList.Count-1 do + if assigned(anObjectList[i].HeldObjectInfo) then + AddObjectToIdList(anObjectList[i], Objects); +end; + +procedure TBoldForeignObjectHandler.ModifiedObjectsFrom(Owner: TBoldPSId; + Objects: TBoldObjectIdList); +var + i: Integer; + anObjectList: TBoldObjectList; + anElement: TBoldIndirectElement; + anObjectIdList: TBoldObjectIdList; + aValueSpace: TBoldFreeStandingValueSpace; + + function DifferentTimeStamp: Boolean; + var + anObjectContents: IBOldObjectContents; + begin + anObjectContents := (aValueSpace as IBoldValueSpace).GetObjectContentsByObjectId(anObjectIdList[i]); + result := anObjectContents.TimeStamp <> + (anObjectList[i] as THeldObjectInfo).OriginalLocalTimeStamp; + end; + +begin + anElement := TBoldIndirectElement.Create; + anObjectIdList := TBoldObjectIdList.Create; + aValueSpace := TBoldFreeStandingValueSpace.Create; + try + GetForeignPSInfo(Owner).EvaluateExpression('ownedObjectInfos.heldObjectInfo', anElement); + anObjectList := anElement.Value as TBoldObjectList; + anObjectList.EnsureObjects; + for i := 0 to anObjectList.Count-1 do + AddObjectToIdList((anObjectList[i] as THeldObjectInfo).ForeignObjectInfo, anObjectIdList); + Fetch(anObjectIdList, aValueSpace); + for i := 0 to anObjectList.Count-1 do + if DifferentTimeStamp then + Objects.Add(anObjectIdList[i]); + finally + anObjectIdList.Free; + aValueSpace.Free; + anElement.Free; + end; +end; + +procedure TBoldForeignObjectHandler.ObjectsFrom(Owner: TBoldPSId; + Objects: TBoldObjectIdList); +var + anObjectList: TForeignObjectInfoList; + i: Integer; +begin + Objects.Clear; + anObjectList := GetForeignPSInfo(Owner).OwnedObjectInfos; + anObjectList.EnsureObjects; + for i := 0 to anObjectList.Count-1 do + AddObjectToIdList(anObjectList[i], Objects); +end; + + +{ TOwnObjectHandler } + +procedure TBoldOwnObjectHandler.AcknowledgeSynch(ForeignPS: TBoldPSId); +var + aForeignPS: TForeignPSInfo; +begin + aForeignPS := GetForeignPSInfo(ForeignPS); + aForeignPS.LastSynchTimestamp := aForeignPS.OngoingSynchTimestamp; + aForeignPS.OngoingSynchTimestamp := -1; + OllSystem.UpdateDatabase; +end; + +procedure TBoldOwnObjectHandler.CheckIn(ValueSpace: IBoldValueSpace; IdList, + ReleaseList: TBoldObjectIdList; Holder: TBoldPSId; var NewTimeStamp: Integer); +var + TranslationList, TranslationList2: TBoldIdTranslationList; + IdList2, ReleaseList2: TBoldObjectIdList; +begin + TranslationList := TBoldIdTranslationList.Create; + TranslationList2 := TBoldIdTranslationList.Create; + IdList2 := IdList.Clone; + ReleaseList2 := ReleaseList.Clone; + + try + StartTransaction; + try + MakeLocalizingTranslationList(ValueSpace, IdList, TranslationList); + + ValueSpace.ApplyTranslationList(TranslationList); + IdList2.ApplyTranslationList(TranslationList); + ReleaseList2.ApplyTranslationList(TranslationList); + + VerifyAssociations(ValueSpace, IdList2, IdList2); + Update(ValueSpace, IdList2, TranslationList2, NewTimeStamp); + IdList2.ApplyTranslationList(TranslationList2); + ReleaseList2.ApplyTranslationList(TranslationList2); + + LockAndFreeObjects(IdList2, ReleaseList2); + CheckInObjects(ValueSpace, IdList2, ReleaseList2, GetForeignPSInfo(Holder)); + OllSystem.UpdateDatabase; + + CommitTransaction; + except + RollbackTransaction; + raise; + end; + finally + IdList2.Free; + ReleaseList2.Free; + TranslationList.Free; + TranslationList2.Free; + end; +end; + +procedure TBoldOwnObjectHandler.CheckInObjects(ValueSpace: IBoldValueSpace; + IdList, ReleaseList: TBoldObjectIdList; Holder: TForeignPSInfo); +var + InfoObjects: TDistributableObjectInfoList; + NewInfoIds: TBoldObjectIdList; + i: Integer; + anObject: TBoldObject; + anOwnObjectInfo: TOwnObjectInfo; + anObjectId: TBoldDefaultId; +begin + InfoObjects := TDistributableObjectInfoList.Create; + NewInfoIds := TBoldObjectIdList.Create; + anObjectId := TBoldDefaultId.Create; + try + GetInfoObjectsFor(IdList, InfoObjects, NewInfoIds); + for i := 0 to InfoObjects.Count - 1 do + begin + anObject := InfoObjects[i]; + if not (anObject is TOwnObjectInfo) then + raise EBold.CreateFmt('%s.CheckInObjects: Object is not an owned object', [Classname]); + anOwnObjectInfo := anObject as TOwnObjectInfo; + anObjectId.AsInteger := anOwnObjectInfo.LocalId; + anOwnObjectInfo.CheckIn(ValueSpace, ReleaseList.IdInList[anObjectId], Holder); + end; + for i := 0 to NewInfoIds.Count - 1 do + begin + anOwnObjectInfo := TOwnObjectInfo.Create(OllSystem); + anOwnObjectInfo.LocalId := (NewInfoIds[i] as TBoldDefaultId).AsInteger; + AddToMapping(anOwnObjectInfo); + anOwnObjectInfo.CheckedOutObjectInfo := TCheckedOutObjectInfo.Create(OllSystem); + anOwnObjectInfo.CheckedOutObjectInfo.Holder := Holder; + anOwnObjectInfo.CheckIn(ValueSpace, ReleaseList.IdInList[NewInfoIds[i]], Holder); + end; + finally + InfoObjects.Free; + NewInfoIds.Free; + anObjectId.Free; + end; +end; + +procedure TBoldOwnObjectHandler.FailSynch(ForeignPS: TBoldPSId); +begin + GetForeignPSInfo(ForeignPS).OngoingSynchTimestamp := -1; + OllSystem.UpdateDatabase; +end; + +procedure TBoldOwnObjectHandler.Get(IdList, HoldList: TBoldObjectIdList; + Holder: TBoldPSId; ValueSpace: IBoldValueSpace); +begin + StartTransaction; + try + InternalGet(IdList, HoldList, Holder, ValueSpace); + + OllSystem.UpdateDatabase; + CommitTransaction; + except + RollbackTransaction; + raise; + end; +end; + +procedure TBoldOwnObjectHandler.GetObjects(ValueSpace: IBoldValueSpace; IdList, + HoldList: TBoldObjectIdList; Holder: TForeignPSInfo); +var + i: Integer; + InfoObjectList: TDistributableObjectInfoList; + NewInfoObjectList: TBoldObjectIdList; + aDistributableObjectInfo: TDistributableObjectInfo; + anId: TBoldDefaultId; +begin + InfoObjectList := TDistributableObjectInfoList.Create; + NewInfoObjectList := TBoldObjectIdList.Create; + anId := TBoldDefaultID.Create; + try + GetInfoObjectsFor(IdList, InfoObjectList, NewInfoObjectList); + NewOwnInfoObjectsFor(NewInfoObjectList, InfoObjectList); + for i := 0 to InfoObjectList.Count - 1 do + begin + aDistributableObjectInfo := InfoObjectList[i]; + anId.AsInteger := aDistributableObjectInfo.LocalId; + aDistributableObjectInfo.Get(ValueSpace, HoldList.IdInList[anId], Holder); + end; + finally + InfoObjectList.Free; + NewInfoObjectList.Free; + anId.Free; + end; +end; + +procedure TBoldOwnObjectHandler.GetSynch(ForeignPS: TBoldPSId; + IdList: TBoldObjectIdList; Valuespace: IBoldValueSpace); +var + aCond: TBoldTimestampCondition; + i: Integer; + HoldList: TBoldObjectIdList; + MaxTimestamp: Integer; + aTimestamp: Integer; + aForeignPS: TForeignPSInfo; + InfoObjects: TDistributableObjectInfoList; + ChangedObjects: TBoldObjectIdList; + MissingIds: TBoldObjectIdList; +begin + StartTransaction; + try + aForeignPS := GetForeignPSInfo(ForeignPS); + if aForeignPS.IsSynching then + raise EBold.CreateFmt('%s.GetSynch: There is already an ongoing synch that must either be acknowledged or failed.', [classname]); + + ChangedObjects := TBoldObjectIdList.Create; + HoldList := TBoldObjectIdList.Create; + aCond := TBoldTimestampCondition.create; + InfoObjects := TDistributableObjectInfoList.Create; + MissingIds := TBoldObjectIdList.Create; + try + aCond.Timestamp := aForeignPS.LastSynchTimestamp; + fPController.PMFetchIDListWithCondition(ChangedObjects, Valuespace, fmDistributable, aCond, -1); + GetInfoObjectsFor(ChangedObjects, InfoObjects, MissingIds); + NewOwnInfoObjectsFor(MissingIds, InfoObjects); + for i := InfoObjects.Count-1 downto 0 do + if not (InfoObjects[i] is TOwnObjectInfo) then + InfoObjects.RemoveByIndex(i); + + GetLocalIdsFor(InfoObjects, IdList); + InternalGet(IdList, HoldList, ForeignPS, ValueSpace); + MaxTimestamp := 0; + for i := 0 to IdList.Count-1 do + begin + aTimestamp := Valuespace.ObjectContentsByObjectId[IdList[i]].TimeStamp; + if aTimestamp > MaxTimestamp then + MaxTimestamp := aTimestamp; + end; + aForeignPS.OngoingSynchTimestamp := MaxTimestamp; + finally + ChangedObjects.Free; + HoldList.Free; + aCond.Free; + InfoObjects.Free; + end; + + OllSystem.UpdateDatabase; + CommitTransaction; + except + RollbackTransaction; + raise; + end; +end; + +procedure TBoldOwnObjectHandler.InternalGet(IdList, + HoldList: TBoldObjectIdList; Holder: TBoldPSId; + ValueSpace: IBoldValueSpace); +var + GlobalTranslationList: TBoldIdTranslationList; +begin + GlobalTranslationList := TBoldIdTranslationList.Create; + try + Fetch(Idlist, ValueSpace); + GetObjects(ValueSpace, IdList, HoldList, GetForeignPSInfo(Holder)); + ReserveObjects(ValueSpace, HoldList); + + MakeGlobalTranslationListFor(ValueSpace, IdList, GlobalTranslationList); + ValueSpace.ApplytranslationList(GlobalTranslationList); + IdList.ApplyTranslationList(GlobalTranslationList); + HoldList.ApplyTranslationList(GlobalTranslationList); + finally + GlobalTranslationList.Free; + end; +end; + +procedure TBoldOwnObjectHandler.ReserveObjects(ValueSpace: IBoldValueSpace; + HoldList: TBoldObjectIdList); +begin + PController.PMSetReadonlyness(HoldList, nil); +end; + + +procedure TBoldOwnObjectHandler.UnCheckOut(IdList: TBoldObjectIdList; + Holder: TBoldPSId); +var + EmptyIdList: TBoldObjectIdList; + TranslationList: TBoldIdTranslationList; +begin + TranslationList := TBoldIDTranslationList.Create; + EmptyIdList := TBoldObjectIdList.Create; + try + StartTransaction; + try + PController.PMTranslateToLocalIds(IdList, TranslationList); + IdList.ApplyTranslationList(TranslationList); + UnCheckOutObjects(IdList, GetForeignPSInfo(Holder)); + LockAndFreeObjects(EmptyIdList, IdList); + OllSystem.UpdateDatabase; + + CommitTransaction; + except + RollbackTransaction; + raise; + end; + finally + TranslationList.Free; + EmptyIdList.Free; + end; +end; + +procedure TBoldOwnObjectHandler.UnCheckOutObjects(IdList: TBoldObjectIdList; + Holder: TForeignPSInfo); +var + InfoObjects: TDistributableObjectInfoList; + i: Integer; + anOwnObjectInfo: TOwnObjectInfo; + MissingList: TBoldObjectIdList; +begin + InfoObjects := TDistributableObjectInfoList.Create; + MissingList := TBoldObjectIdList.Create; + try + GetInfoObjectsFor(IdList, InfoObjects, MissingList); + for i := 0 to InfoObjects.Count - 1 do + begin + if not (InfoObjects[i] is TOwnObjectInfo) then + raise EBold.CreateFmt('%s.UnCheckOutObjects: Object is not an owned object', [Classname]); + anOwnObjectInfo := InfoObjects[i] as TOwnObjectInfo; + anOwnObjectInfo.UnCheckOut(Holder); + end; + finally + InfoObjects.Free; + MissingList.Free; + end; +end; + +{ TDistributableObjectHandler } + +function TBoldDistributableObjectHandler.GetForeignPSInfo( + PSId: TBoldPSId): TForeignPSInfo; +var + aCondition: TBoldSQLCondition; + PSInfoObjectIdList: TBoldObjectIdList; + aLocator: TBoldObjectLocator; +begin + aCondition := TBoldSQLCondition.Create; + PSInfoObjectIdList := TBoldObjectIdList.Create; + try +{ if assigned(OllSystem.PersistenceController) then + begin + aCondition.TopSortedIndex := OllSystem.BoldSystemTypeInfo.ClassTypeInfoByModelName['ForeignPSInfo'].TopSortedIndex; + aCondition.WhereFragment := BOLD_OLL_PSIDATTRIBUTECOLUMN_NAME + ' = ''' + PSId + ''''; + OllSystem.PersistenceController.PMFetchIDListWithCondition(PSInfoObjectIdList, OllSystem.AsIBoldvalueSpace[bdepPMIn], fmNormal, aCondition, 0); + end else} + SearchByOcl('ForeignPSInfo.allInstances->select(globalId = ''' + PSId + ''')', PSInfoObjectIdList); + if PSInfoObjectIdList.Count = 0 then + begin + result := TForeignPSInfo.Create(OllSystem); + result.GlobalID := PSId; + end else + begin + assert(PSInfoObjectIdList.Count = 1); + aLocator := OllSystem.EnsuredLocatorByID[PSInfoObjectIdList[0]]; + aLocator.EnsureBoldObject; + result := aLocator.BoldObject as TForeignPSInfo; + end; + finally + aCondition.Free; + PSInfoObjectIdList.Free; + end; +end; + +procedure TBoldDistributableObjectHandler.ExtractAllIds(IdList: TBoldObjectIdList; + ValueSpace: IBoldValueSpace; OutIdList: TBoldObjectIdList); + + procedure EnsureIdInList(Id: TBoldObjectId; IdList: TBoldObjectIdList); + begin + if assigned(Id) and + not IdList.IdInList[Id] then + IdList.Add(Id); + end; + +var + i, j: Integer; + anObject: IBoldObjectContents; + aValue: IBoldValue; + IdRef: IBoldObjectIdRef; + IdRefPair: IBoldObjectIdRefPair; +begin + for i := 0 to IdList.Count - 1 do + begin + EnsureIdInList(IdList[i], OutIdList); + anObject := ValueSpace.ObjectContentsByObjectId[IdList[i]]; + if not assigned(anObject) then + anObject := ValueSpace.ObjectContentsByObjectId[IdList[i]]; + for j := 0 to anObject.MemberCount - 1 do + begin + aValue := anObject.ValueByIndex[j]; + if assigned(aValue) then + if aValue.QueryInterface(IBoldObjectIdRef, IdRef) = S_OK then + EnsureIdInList(IdRef.Id, OutIdList) + else if aValue.QueryInterface(IBoldObjectIdRefPair, IdRefPair) = S_OK then + begin + EnsureIdInList(IdRefPair.Id1, OutIdList); + EnsureIdInList(IdRefPair.Id2, OutIdList); + end; + end; + end; +end; + +procedure TBoldDistributableObjectHandler.Fetch(IdList: TBoldObjectIdList; + ValueSpace: IBoldValueSpace); +begin + PController.PMFetch(IdList, ValueSpace, nil, fmDistributable, 0); +end; + +procedure TBoldDistributableObjectHandler.MakeGlobalTranslationListFor( + ValueSpace: IBoldValueSpace; IdList: TBoldObjectIdList; + GlobalTranslationList: TBoldIdTranslationList); +var + anIdList: TBoldObjectIdList; +begin + anIdList := TBoldObjectIdList.Create; + try + ExtractAllIds(IdList, ValueSpace, anIdList); + PController.PMTranslateToGlobalIds(anIdList, GlobalTranslationList); + finally + anIdList.Free; + end; +end; + +procedure TBoldDistributableObjectHandler.GetInfoObjectsFor(IdList: TBoldObjectIdList; + InfoObjectList: TDistributableObjectInfoList; RemainingIdList: TBoldObjectIdList); + + function IdListToSQL(IdList: TBoldObjectIdList): string; + var + i: Integer; + begin + result := IdList[0].AsString; + for i := 1 to IdList.Count - 1 do + result := result + ', ' + IdList[i].AsString; + end; + +var + aCondition: TBoldSQLCondition; + i: Integer; + InfoObj: TDistributableObjectInfo; + RemainingIds: TBoldObjectIdList; + FoundIds: TBoldObjectIdList; + FetchedInfoObjs: TDistributableObjectInfoList; +begin + RemainingIds := IdList.Clone; + FetchedInfoObjs := TDistributableObjectInfoList.Create; + try + for i := RemainingIds.Count-1 downto 0 do + begin + InfoObj := LookupInfoByLocalId(RemainingIds[i] as TBoldDefaultId); + if assigned(InfoObj) then + begin + InfoObjectList.Add(InfoObj); + RemainingIds.RemoveByIndex(i); + end; + end; + + if (RemainingIds.Count > 0) and + assigned(OllSystem.PersistenceController) then + begin + aCondition := TBoldSQLCondition.Create; + FoundIds := TBoldObjectIdList.Create; + try + aCondition.TopSortedIndex := OllSystem.BoldSystemTypeInfo.ClassTypeInfoByModelName['DistributableObjectInfo'].TopSortedIndex; + aCondition.WhereFragment := BOLD_OLL_IDATTRIBUTECOLUMN_NAME + ' IN (' + IdListToSQL(RemainingIds) + ')'; + OllSystem.GetAllWithCondition(FetchedInfoObjs, aCondition); + FetchedInfoObjs.EnsureObjects; + for i := 0 to FetchedInfoObjs.Count-1 do + AddToMapping(FetchedInfoObjs[i]); + GetLocalIdsFor(FetchedInfoObjs, FoundIds); + for i := 0 to FoundIds.Count-1 do + RemainingIds.Remove(RemainingIds.IDByID[FoundIds[i]]); + InfoObjectList.AddList(FetchedInfoObjs); + finally + aCondition.Free; + FoundIds.Free; + end; + end; + + RemainingIdList.AddList(RemainingIds); + + finally + RemainingIds.Free; + FetchedInfoObjs.Free; + end; +end; + +procedure TBoldDistributableObjectHandler.MakeLocalizingTranslationList( + ValueSpace: IBoldValueSpace; + GlobalIdList: TBoldObjectIdList; + TranslationList: TBoldIdTranslationList); +var + AllIdList: TBoldObjectIdList; +begin + AllIdList := TBoldObjectIdList.Create; + try + ExtractAllIds(GlobalIdList, ValueSpace, AllIdList); + PController.PMTranslateToLocalIds(AllIdList, TranslationList); + finally + AllIdList.Free; + end; +end; + +procedure TBoldDistributableObjectHandler.Update(ValueSpace: IBoldValueSpace; + IdList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList; + var TimeStamp: Integer); +var + anObject: IBoldObjectContents; + i, j: Integer; +begin + for i := IdList.Count-1 downto 0 do + begin + anObject := ValueSpace.ObjectContentsByObjectId[IdList[i]]; + for j := 0 to anObject.MemberCount-1 do + anObject.ValueByIndex[j].BoldPersistenceState := bvpsModified; + if IdList[i] is TBoldGlobalId then + begin + if anObject.BoldExistenceState = besDeleted then + IdList.RemoveByIndex(i) + else + begin + anObject.BoldExistenceState := besExisting; + anObject.BoldPersistenceState := bvpsModified; + end; + end else if anObject.BoldExistenceState = besDeleted then + begin + anObject.BoldPersistenceState := bvpsModified; + end; + end; + PController.PMUpdate(IdList, ValueSpace, nil, nil, TranslationList, TimeStamp, TimeStamp, 0); +end; + +procedure TBoldDistributableObjectHandler.LockAndFreeObjects(IdList, + FreeList: TBoldObjectIdList); +var + ReadOnlyList: TBoldObjectIdList; + i: Integer; +begin + ReadOnlyList := IdList.Clone; + try + for i := 0 to FreeList.Count-1 do + ReadOnlyList.Remove(ReadOnlyList.IDByID[FreeList[i]]); + PController.PMSetReadonlyness(ReadOnlyList, FreeList); + finally + ReadOnlyList.Free; + end; +end; + +{ +function TBoldDistributableObjectHandler.NewLocalClassIdFor( + ClassId: TBoldClassIdWithExpressionName): TBoldClassId; +var + i: Integer; + PMapper: TBoldSystemPersistenceMapper; +begin + PMapper := (PController as TBoldPersistenceControllerDefault).PersistenceMapper; + i := 0; + while (i < PMapper.ObjectPersistenceMappers.Count) and + not (PMapper.ObjectPersistenceMappers[i].ExpressionName = ClassId.ExpressionName) do + inc(i); + if not (PMapper.ObjectPersistenceMappers[i].ExpressionName = ClassId.ExpressionName) then + raise EBold.CreateFmt('%s.NewLocalClassIdFor: There is no class with expressionname "%s"', [Classname, ClassId.ExpressionName]); + result := TBoldClassID.CreateWithInfo(True, i); +end; +} +procedure TBoldDistributableObjectHandler.VerifyAssociations( + ValueSpace: IBoldValueSpace; IdList, HoldList: TBoldObjectIdList); +var + i: Integer; + anObject: IBoldObjectContents; + + procedure VerifyObjectRoles(ObjectContents: IBoldObjectContents); + + procedure CascadeToNeighbours; + + procedure VerifyAllInList(anIdList: TBoldObjectIdList); + var + i: Integer; + begin + for i := 0 to anIdList.Count-1 do + begin + if ValueSpace.HasContentsForId[anIdList[i]] then + VerifyObjectRoles(ValueSpace.ObjectContentsByObjectId[anIdList[i]]); + end; + end; + + var + k: Integer; + aMember: IBoldValue; + anIdRef: IBoldObjectIdRef; + anIdRefPair: IBoldObjectIdRefPair; + anIdListRef: IBoldObjectIdListRef; + anIdListRefPair: IBoldObjectIdListRefPair; + begin + for k := 0 to ObjectContents.MemberCount-1 do + begin + aMember := ObjectContents.ValueByIndex[k]; + if assigned(aMember) then + begin + if (aMember.QueryInterface(IBoldObjectIdRef, anIdRef) = S_OK) then + begin + if ValueSpace.HasContentsForId[anIdRef.Id] then + VerifyObjectRoles(ValueSpace.ObjectContentsByObjectId[anIdRef.Id]); + end else if (aMember.QueryInterface(IBoldObjectIdRefPair, anIdRefPair) = S_OK) then + begin + if ValueSpace.HasContentsForId[anIdRefPair.Id1] then + VerifyObjectRoles(ValueSpace.ObjectContentsByObjectId[anIdRefPair.Id1]); + if ValueSpace.HasContentsForId[anIdRefPair.Id2] then + VerifyObjectRoles(ValueSpace.ObjectContentsByObjectId[anIdRefPair.Id2]); + end else if aMember.QueryInterface(IBoldObjectIdListRef, anIdListRef) = S_OK then + begin + end else if aMember.QueryInterface(IBoldObjectIdListRefPair, anIdListRefPair) = S_OK then + begin + + end; + end; + end; + end; + + var + j: integer; + aMember: IBoldValue; + anIdRef: IBoldObjectIdRef; + anIdRefPair: IBoldObjectIdRefPair; + begin + for j := 0 to ObjectContents.MemberCount-1 do + begin + aMember := ObjectContents.ValueByIndex[j]; + if assigned(aMember) then + begin + if ((aMember.QueryInterface(IBoldObjectIdRef, anIdRef) = S_OK) and + (anIdRef.Id is TBoldGlobalId) and + (not ValueSpace.HasContentsForId[anIdRef.Id])) or + ((aMember.QueryInterface(IBoldObjectIdRefPair, anIdRefPair) = S_OK) and + (anIdRefPair.Id1 is TBoldGlobalId) and + (not ValueSpace.HasContentsForId[anIdRefPair.Id1])) then + if assigned(BrokenLinkResolver) then + begin + if not BrokenLinkResolver.ResolveBrokenLink(ObjectContents, j, HoldList.IdInList[IdList[i]]) then + begin + raise EBoldFeatureNotImplementedYet.CreateFmt('%s.VerifyAssociations: Failing inidividual objects not implemented', [classname]); + + end; + end else + raise EBold.Create('Operation failed: Unresolved link'); + end; + end; + end; + +begin + for i := 0 to IdList.Count-1 do + begin + anObject := ValueSpace.ObjectContentsByObjectId[Idlist[i]]; + if assigned(anObject) then + VerifyObjectRoles(anObject); + end; +end; + + +procedure TBoldDistributableObjectHandler.SearchByOcl(OclExpr: string; + IdList: TBoldObjectIdList); +var + anElement: TBoldIndirectElement; + anObjectList: TBoldObjectList; + i: integer; +begin + anElement := TBoldIndirectElement.Create; + try + OllSystem.EvaluateExpression(OclExpr, anElement); + anObjectList := anElement.Value as TBoldObjectList; + for i := 0 to anObjectList.Count-1 do + IdList.Add(anObjectList.Locators[i].BoldObjectID); + finally + anElement.Free; + end; +end; + +procedure TBoldDistributableObjectHandler.CommitTransaction; +begin + if fMyTransaction then + PController.CommitTransaction; + fMyTransaction := false; +end; + +procedure TBoldDistributableObjectHandler.RollbackTransaction; +begin + if fMyTransaction then + PController.RollbackTransaction; + fMyTransaction := false; +end; + +procedure TBoldDistributableObjectHandler.StartTransaction; +begin + if not PController.InTransaction then + begin + PController.StartTransaction; + fMyTransaction := true; + end; +end; +{ +function TBoldDistributableObjectHandler.GetDatabase: IBoldDatabase; +begin + result := ((PController as TBoldPersistenceControllerDefault).PersistenceMapper as TBoldSystemDefaultMapper).Database; +end; + } +{ TBoldBrokenLinkResolver } + +function TBoldBrokenLinkResolver.ResolveBrokenLink( + ObjectContents: IBoldObjectContents; MemberIndex: Integer; + Hold: Boolean): Boolean; +var + ResolveAction: TBoldLinkResolveAction; + + procedure Cut; + var + aMember: IBoldValue; + anIdRef: IBoldObjectIdRef; + anIdRefPair: IBoldObjectIdrefPair; + begin + aMember := ObjectContents.ValueByIndex[MemberIndex]; + if (aMember.QueryInterface(IBoldObjectIdRef, anIdRef) = S_OK) then + anIdRef.SetFromId(nil, false) + else if (aMember.QueryInterface(IBoldObjectIdRefPair, anIdRefPair) = S_OK) then + anIdRefPair.SetFromIds(nil, nil) + else + raise EBoldInternal.CreateFmt('%.ResolveBrokenLink: Member is not a singlelink', [Classname]); + end; + +begin + result := True; + if Hold then + ResolveAction := HeldObjectAction + else + ResolveAction := NonheldObjectAction; + + case ResolveAction of + blraCut: Cut; + blraAbort: raise EBold.Create('Operation failed: Unresolved link'); + blraFailObject: result := False; + blraIgnore:; + blraMissing: raise EBoldFeatureNotImplementedYet.Create('Missing Objects not implemented'); + end; +end; + +procedure TBoldDistributableObjectHandler.GetLocalIdsFor( + InfoObjects: TDistributableObjectInfoList; IdList: TBoldObjectIdList); +var + TempId: TBoldDefaultId; + i: Integer; +begin + TempId := TBoldDefaultID.CreateWithClassID(0, false); + try + for i := 0 to InfoObjects.Count-1 do + begin + TempId.AsInteger := InfoObjects[i].LocalId; + IdList.Add(TempId); + end; + finally + TempId.Free; + end; +end; + +procedure TBoldDistributableObjectHandler.NewOwnInfoObjectsFor( + IdList: TBoldObjectIdList; InfoObjectList: TDistributableObjectInfoList); +var + anOwnObjectInfo: TOwnObjectInfo; + i: integer; +begin + for i := IdList.Count-1 downto 0 do + begin + anOwnObjectInfo := TOwnObjectInfo.Create(OllSystem); + anOwnObjectInfo.LocalId := (IdList[i] as TBoldDefaultId).AsInteger; + AddToMapping(anOwnObjectInfo); + InfoObjectList.Add(anOwnObjectInfo); + end; +end; + +procedure TBoldDistributableObjectHandler.NewForeignInfoObjectsFor( + IdList: TBoldObjectIdList; InfoObjectList: TDistributableObjectInfoList; Owner: TForeignPSInfo; Hold: Boolean = false); +var + i: Integer; + aForeignObjectInfo: TForeignObjectInfo; +begin + for i := 0 to IdList.Count - 1 do + begin + aForeignObjectInfo := TForeignObjectInfo.Create(OllSystem); + if Hold then + aForeignObjectInfo.InitializeHolding(IdList[i], Owner) + else + begin + aForeignObjectInfo.LocalId := (IdList[i] as TBoldDefaultId).AsInteger; + aForeignObjectInfo.Owner := Owner; + end; + AddToMapping(aForeignObjectInfo); + InfoObjectList.Add(aForeignObjectInfo); + end; +end; + +function TBoldDistributableObjectHandler.LookupInfoByLocalId( + LocalId: TBoldDefaultId): TDistributableObjectInfo; +begin + result := TheMapping.ObjectInfo[LocalId.AsInteger]; +end; + +function TBoldDistributableObjectHandler.TheMapping: TMapping; +var + Mappings: TBoldObjectList; +begin + if not assigned(fTheMapping) then + begin + Mappings := fOllSystem.ClassByExpressionName['Mapping']; + if Mappings.Count = 0 then + fTheMapping := TMapping.Create(fOllSystem) + else + begin + assert(Mappings.Count = 1); + fTheMapping := Mappings[0] as TMapping; + end; + end; + result := fTheMapping; +end; + +procedure TBoldDistributableObjectHandler.AddToMapping( + anObj: TDistributableObjectInfo); +begin + TheMapping.M_ObjectInfo.Add(anObj); +end; + +initialization +end. diff --git a/Source/Persistence/BDE/BoldPersistenceHandleBde.RES b/Source/Persistence/BDE/BoldPersistenceHandleBde.RES new file mode 100644 index 0000000000000000000000000000000000000000..3263cc293b8761deb780fcceb9590e034336bed8 GIT binary patch literal 972 zcmc(cv2NQi5Qcvjh6OEwxCHf>b{V$;jI>Dn02&Au-aHhLyLq!b#Q};$_ck6h z>VeWp{mGL8H$bw6@bP|rJRd3k0C2%*TMf$pMmYd}khJXwEHT4(EMQ44af4f2F_zTV z_`>-crc{;{m#nm$b$rJ8uy6W_;$s&BD8Aqs^_fOrr+EwThwWAqXG+Ev$K#P3;nE?s znmFrsv{?P|cJA!l`;~~y=gxT!k(E5Crf}SF&IasVShI%7JA$Bzy|ZD%UJ+{p#X)l; zRO{d&vPKaXJh6Hz*Q2-)xoda3walg!;gLW@aphRI0K-ejv^g5%M$}%YByo zma2d`h?p$diC{e@HW@a5~C!4)Ii0t?KkuLxqQdL#b-RhpzQSuvt zuZ#F}r@mS`xMa*2xAbpH7pHVPczpBjp3)8o2ITO!Bb#JZlk9rQ%+C$(#q*+(6K%};YPWwfyp>>#6BHw_y_XPKgXiR S$fUieh0mTn^*(g(FaHmYT^Wi1 literal 0 HcmV?d00001 diff --git a/Source/Persistence/BDE/BoldPersistenceHandleBde.rc b/Source/Persistence/BDE/BoldPersistenceHandleBde.rc index cbc9c49..f2449cf 100644 --- a/Source/Persistence/BDE/BoldPersistenceHandleBde.rc +++ b/Source/Persistence/BDE/BoldPersistenceHandleBde.rc @@ -1,2 +1,2 @@ -TBOLDPERSISTENCEHANDLEBDE BITMAP LOADONCALL TBoldPersistenceHandleBde.bmp -TBOLDDATABASEADAPTERBDE BITMAP LOADONCALL TBoldDatabaseAdapterBde.bmp +TBOLDPERSISTENCEHANDLEBDE BITMAP LOADONCALL ..\..\..\Images\Components\TBoldPersistenceHandleBde.bmp +TBOLDDATABASEADAPTERBDE BITMAP LOADONCALL ..\..\..\Images\Components\TBoldDatabaseAdapterBde.bmp diff --git a/Source/Persistence/SOAP/BoldPersistenceControllerSOAPAdapterCore.pas b/Source/Persistence/SOAP/BoldPersistenceControllerSOAPAdapterCore.pas index 8bc0ef1..df45497 100644 --- a/Source/Persistence/SOAP/BoldPersistenceControllerSOAPAdapterCore.pas +++ b/Source/Persistence/SOAP/BoldPersistenceControllerSOAPAdapterCore.pas @@ -27,7 +27,7 @@ implementation uses SysUtils, - {$IFDEF OXML}OXmlPDOM{$ELSE}MSXML_TLB{$ENDIF}, + {$IFDEF OXML}OXmlPDOM{$ELSE}Bold_MSXML_TLB{$ENDIF}, BoldDefs, BoldXMLStreaming, BoldRev diff --git a/Source/Persistence/SOAP/BoldPersistenceOperationXMLStreaming.pas b/Source/Persistence/SOAP/BoldPersistenceOperationXMLStreaming.pas index c9e79dc..487429f 100644 --- a/Source/Persistence/SOAP/BoldPersistenceOperationXMLStreaming.pas +++ b/Source/Persistence/SOAP/BoldPersistenceOperationXMLStreaming.pas @@ -197,7 +197,7 @@ TBoldPMTimeForTimestampOperation = class(TBoldPersistenceOperation) implementation uses - {$IFDEF OXML}OXmlPDOM{$ELSE}MSXML_TLB{$ENDIF}, + {$IFDEF OXML}OXmlPDOM{$ELSE}Bold_MSXML_TLB{$ENDIF}, SysUtils, BoldDefaultStreamNames; diff --git a/Source/UMLModel/Handles/BoldUMLModelStreamer.pas b/Source/UMLModel/Handles/BoldUMLModelStreamer.pas index 44fd0e4..3c51340 100644 --- a/Source/UMLModel/Handles/BoldUMLModelStreamer.pas +++ b/Source/UMLModel/Handles/BoldUMLModelStreamer.pas @@ -20,7 +20,7 @@ TUMLModelStreamer = class implementation uses - {$IFDEF OXML}OXmlPDOM, OTextReadWrite{$ELSE}MSXML_TLB{$ENDIF}, + {$IFDEF OXML}OXmlPDOM, OTextReadWrite{$ELSE}Bold_MSXML_TLB{$ENDIF}, BoldXMLStreaming, BoldDefaultXMLStreaming, BoldDomainElement, diff --git a/Source/UMLModel/ModelLinks/ModelMaker/MMPlugin/BoldMMTVDefGen.pas b/Source/UMLModel/ModelLinks/ModelMaker/MMPlugin/BoldMMTVDefGen.pas index dbc9a64..d5b9858 100644 --- a/Source/UMLModel/ModelLinks/ModelMaker/MMPlugin/BoldMMTVDefGen.pas +++ b/Source/UMLModel/ModelLinks/ModelMaker/MMPlugin/BoldMMTVDefGen.pas @@ -8,7 +8,7 @@ interface uses BoldDefaultTaggedValues, BoldUMLTaggedValues, - MSXML_TLB, + Bold_MSXML_TLB, BoldTaggedValueList; type diff --git a/Source/UMLModel/ModelLinks/XMI/BoldMOFInterfaces.pas b/Source/UMLModel/ModelLinks/XMI/BoldMOFInterfaces.pas index a0a1846..9e3f14e 100644 --- a/Source/UMLModel/ModelLinks/XMI/BoldMOFInterfaces.pas +++ b/Source/UMLModel/ModelLinks/XMI/BoldMOFInterfaces.pas @@ -6,7 +6,7 @@ interface uses - MSXML_TLB; + Bold_MSXML_TLB; type IBoldMOFObject = interface; diff --git a/Source/UMLModel/ModelLinks/XMI/BoldUMLModelMOFAdapters.pas b/Source/UMLModel/ModelLinks/XMI/BoldUMLModelMOFAdapters.pas index 46de989..0efa473 100644 --- a/Source/UMLModel/ModelLinks/XMI/BoldUMLModelMOFAdapters.pas +++ b/Source/UMLModel/ModelLinks/XMI/BoldUMLModelMOFAdapters.pas @@ -13,7 +13,7 @@ interface BoldSystem, BoldAttributes, BoldUMLXMILink, - MSXML_TLB, + Bold_MSXML_TLB, BoldUMLModel; type diff --git a/Source/UMLModel/ModelLinks/XMI/BoldUMLXMIImporter.pas b/Source/UMLModel/ModelLinks/XMI/BoldUMLXMIImporter.pas index c2d7528..2186311 100644 --- a/Source/UMLModel/ModelLinks/XMI/BoldUMLXMIImporter.pas +++ b/Source/UMLModel/ModelLinks/XMI/BoldUMLXMIImporter.pas @@ -14,7 +14,7 @@ interface BoldUMLXMILink, BoldSystemRT, BoldUMLXMILinkSupport, - MSXML_TLB, + Bold_MSXML_TLB, Sysutils, Classes; diff --git a/Source/UMLModel/ModelLinks/XMI/BoldUMLXMILinkSupport.pas b/Source/UMLModel/ModelLinks/XMI/BoldUMLXMILinkSupport.pas index 68f9cdb..138a44f 100644 --- a/Source/UMLModel/ModelLinks/XMI/BoldUMLXMILinkSupport.pas +++ b/Source/UMLModel/ModelLinks/XMI/BoldUMLXMILinkSupport.pas @@ -7,7 +7,7 @@ interface uses Variants, - MSXML_TLB, + Bold_MSXML_TLB, BoldContainers, BoldIndexableList, BoldUMLModel; diff --git a/Source/UMLModel/ModelLinks/XMI/BoldXMI10Exporter.pas b/Source/UMLModel/ModelLinks/XMI/BoldXMI10Exporter.pas index 9b15d42..edba15b 100644 --- a/Source/UMLModel/ModelLinks/XMI/BoldXMI10Exporter.pas +++ b/Source/UMLModel/ModelLinks/XMI/BoldXMI10Exporter.pas @@ -12,7 +12,7 @@ interface BoldUMLXMILink, BoldMOFInterfaces, - MSXML_TLB, + Bold_MSXML_TLB, Sysutils, BoldStringList, BoldUMLDTDData, diff --git a/Source/UMLModel/Plugins/BoldUMLModelToEcoIIIGenerator.pas b/Source/UMLModel/Plugins/BoldUMLModelToEcoIIIGenerator.pas index 46dac18..363a933 100644 --- a/Source/UMLModel/Plugins/BoldUMLModelToEcoIIIGenerator.pas +++ b/Source/UMLModel/Plugins/BoldUMLModelToEcoIIIGenerator.pas @@ -8,7 +8,7 @@ interface Dialogs, BoldSystem, BoldGuidUtils, - MSXML_TLB, + Bold_MSXML_TLB, BoldUMLModel, BoldUMLTypes, BoldUMLPlugins, diff --git a/Source/Unassigned/Asta/AstaforBfD.dproj b/Source/Unassigned/Asta/AstaforBfD.dproj new file mode 100644 index 0000000..9a61c9e --- /dev/null +++ b/Source/Unassigned/Asta/AstaforBfD.dproj @@ -0,0 +1,176 @@ + + + {80E62428-6352-4CB3-B8F0-613CE169AA20} + AstaforBfD.dpk + True + Debug + 38017 + Package + None + 19.2 + Win32 + + + true + + + true + Base + true + + + true + Base + true + + + true + Base + true + + + true + Base + true + + + true + Base + true + + + true + Base + true + + + true + Cfg_2 + true + true + + + true + Cfg_2 + true + true + + + true + Cfg_2 + true + true + + + false + false + false + false + false + 00400000 + true + true + AstaforBfD + 1 + false + 0 + true + Asta support for Bold for Delphi + true + true + 1046 + CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=;CFBundleName= + System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace) + + + package=com.embarcadero.$(MSBuildProjectName);label=$(MSBuildProjectName);versionCode=1;versionName=1.0.0;persistent=False;restoreAnyVersion=False;installLocation=auto;largeHeap=False;theme=TitleBar;hardwareAccelerated=true;apiKey= + Debug + $(BDS)\bin\Artwork\Android\FM_LauncherIcon_192x192.png + android-support-v4.dex.jar;cloud-messaging.dex.jar;com-google-android-gms.play-services-ads-base.17.2.0.dex.jar;com-google-android-gms.play-services-ads-identifier.16.0.0.dex.jar;com-google-android-gms.play-services-ads-lite.17.2.0.dex.jar;com-google-android-gms.play-services-ads.17.2.0.dex.jar;com-google-android-gms.play-services-analytics-impl.16.0.8.dex.jar;com-google-android-gms.play-services-analytics.16.0.8.dex.jar;com-google-android-gms.play-services-base.16.0.1.dex.jar;com-google-android-gms.play-services-basement.16.2.0.dex.jar;com-google-android-gms.play-services-gass.17.2.0.dex.jar;com-google-android-gms.play-services-identity.16.0.0.dex.jar;com-google-android-gms.play-services-maps.16.1.0.dex.jar;com-google-android-gms.play-services-measurement-base.16.4.0.dex.jar;com-google-android-gms.play-services-measurement-sdk-api.16.4.0.dex.jar;com-google-android-gms.play-services-stats.16.0.1.dex.jar;com-google-android-gms.play-services-tagmanager-v4-impl.16.0.8.dex.jar;com-google-android-gms.play-services-tasks.16.0.1.dex.jar;com-google-android-gms.play-services-wallet.16.0.1.dex.jar;com-google-firebase.firebase-analytics.16.4.0.dex.jar;com-google-firebase.firebase-common.16.1.0.dex.jar;com-google-firebase.firebase-iid-interop.16.0.1.dex.jar;com-google-firebase.firebase-iid.17.1.1.dex.jar;com-google-firebase.firebase-measurement-connector.17.0.1.dex.jar;com-google-firebase.firebase-messaging.17.5.0.dex.jar;fmx.dex.jar;google-play-billing.dex.jar;google-play-licensing.dex.jar + + + $(BDS)\bin\Artwork\Android\FM_LauncherIcon_192x192.png + android-support-v4.dex.jar;cloud-messaging.dex.jar;com-google-android-gms.play-services-ads-base.17.2.0.dex.jar;com-google-android-gms.play-services-ads-identifier.16.0.0.dex.jar;com-google-android-gms.play-services-ads-lite.17.2.0.dex.jar;com-google-android-gms.play-services-ads.17.2.0.dex.jar;com-google-android-gms.play-services-analytics-impl.16.0.8.dex.jar;com-google-android-gms.play-services-analytics.16.0.8.dex.jar;com-google-android-gms.play-services-base.16.0.1.dex.jar;com-google-android-gms.play-services-basement.16.2.0.dex.jar;com-google-android-gms.play-services-gass.17.2.0.dex.jar;com-google-android-gms.play-services-identity.16.0.0.dex.jar;com-google-android-gms.play-services-maps.16.1.0.dex.jar;com-google-android-gms.play-services-measurement-base.16.4.0.dex.jar;com-google-android-gms.play-services-measurement-sdk-api.16.4.0.dex.jar;com-google-android-gms.play-services-stats.16.0.1.dex.jar;com-google-android-gms.play-services-tagmanager-v4-impl.16.0.8.dex.jar;com-google-android-gms.play-services-tasks.16.0.1.dex.jar;com-google-android-gms.play-services-wallet.16.0.1.dex.jar;com-google-firebase.firebase-analytics.16.4.0.dex.jar;com-google-firebase.firebase-common.16.1.0.dex.jar;com-google-firebase.firebase-iid-interop.16.0.1.dex.jar;com-google-firebase.firebase-iid.17.1.1.dex.jar;com-google-firebase.firebase-measurement-connector.17.0.1.dex.jar;com-google-firebase.firebase-messaging.17.5.0.dex.jar;fmx.dex.jar;google-play-billing.dex.jar;google-play-licensing.dex.jar + + + $(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_1024x1024.png + + + Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) + Debug + true + CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName) + 1033 + + + RELEASE;$(DCC_Define) + 0 + false + 0 + + + DEBUG;$(DCC_Define) + false + true + + + Debug + + + Debug + + + Debug + + + + MainSource + + + + + + + + + + + + Cfg_2 + Base + + + Base + + + Cfg_1 + Base + + + + Delphi.Personality.12 + Package + + + + AstaforBfD.dpk + + + + False + True + False + True + False + True + False + True + True + False + + + 12 + + + + diff --git a/Source/Unassigned/Asta/AstaforBfD.res b/Source/Unassigned/Asta/AstaforBfD.res new file mode 100644 index 0000000000000000000000000000000000000000..89beac0bbaa8af1c294f2ba943d8ba29bbed20a5 GIT binary patch literal 652 zcmZ{i&q~8U5XQfh9IW=>-HQj$5+MkJD3w|X_>UNRl~`+uw28#{0KS8-A+4Xv1~avF{845k6r)A=c(uvtLtslUBi{w`Nz7!>+?3Qm`=h(o7H|t HpI_2H=`>g6 literal 0 HcmV?d00001 diff --git a/Source/Unassigned/BoldDataSetIPD4.dproj b/Source/Unassigned/BoldDataSetIPD4.dproj new file mode 100644 index 0000000..f547a21 --- /dev/null +++ b/Source/Unassigned/BoldDataSetIPD4.dproj @@ -0,0 +1,168 @@ + + + {AA2B7764-D39D-459A-A19F-D2ED3E34A62B} + BoldDataSetIPD4.dpk + True + Debug + 38017 + Package + None + 19.2 + Win32 + + + true + + + true + Base + true + + + true + Base + true + + + true + Base + true + + + true + Base + true + + + true + Base + true + + + true + Base + true + + + true + Cfg_2 + true + true + + + true + Cfg_2 + true + true + + + true + Cfg_2 + true + true + + + false + false + false + false + false + 00400000 + true + true + BoldDataSetIPD4 + 1 + true + true + 1046 + CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=;CFBundleName= + System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace) + + + package=com.embarcadero.$(MSBuildProjectName);label=$(MSBuildProjectName);versionCode=1;versionName=1.0.0;persistent=False;restoreAnyVersion=False;installLocation=auto;largeHeap=False;theme=TitleBar;hardwareAccelerated=true;apiKey= + Debug + $(BDS)\bin\Artwork\Android\FM_LauncherIcon_192x192.png + android-support-v4.dex.jar;cloud-messaging.dex.jar;com-google-android-gms.play-services-ads-base.17.2.0.dex.jar;com-google-android-gms.play-services-ads-identifier.16.0.0.dex.jar;com-google-android-gms.play-services-ads-lite.17.2.0.dex.jar;com-google-android-gms.play-services-ads.17.2.0.dex.jar;com-google-android-gms.play-services-analytics-impl.16.0.8.dex.jar;com-google-android-gms.play-services-analytics.16.0.8.dex.jar;com-google-android-gms.play-services-base.16.0.1.dex.jar;com-google-android-gms.play-services-basement.16.2.0.dex.jar;com-google-android-gms.play-services-gass.17.2.0.dex.jar;com-google-android-gms.play-services-identity.16.0.0.dex.jar;com-google-android-gms.play-services-maps.16.1.0.dex.jar;com-google-android-gms.play-services-measurement-base.16.4.0.dex.jar;com-google-android-gms.play-services-measurement-sdk-api.16.4.0.dex.jar;com-google-android-gms.play-services-stats.16.0.1.dex.jar;com-google-android-gms.play-services-tagmanager-v4-impl.16.0.8.dex.jar;com-google-android-gms.play-services-tasks.16.0.1.dex.jar;com-google-android-gms.play-services-wallet.16.0.1.dex.jar;com-google-firebase.firebase-analytics.16.4.0.dex.jar;com-google-firebase.firebase-common.16.1.0.dex.jar;com-google-firebase.firebase-iid-interop.16.0.1.dex.jar;com-google-firebase.firebase-iid.17.1.1.dex.jar;com-google-firebase.firebase-measurement-connector.17.0.1.dex.jar;com-google-firebase.firebase-messaging.17.5.0.dex.jar;fmx.dex.jar;google-play-billing.dex.jar;google-play-licensing.dex.jar + + + $(BDS)\bin\Artwork\Android\FM_LauncherIcon_192x192.png + android-support-v4.dex.jar;cloud-messaging.dex.jar;com-google-android-gms.play-services-ads-base.17.2.0.dex.jar;com-google-android-gms.play-services-ads-identifier.16.0.0.dex.jar;com-google-android-gms.play-services-ads-lite.17.2.0.dex.jar;com-google-android-gms.play-services-ads.17.2.0.dex.jar;com-google-android-gms.play-services-analytics-impl.16.0.8.dex.jar;com-google-android-gms.play-services-analytics.16.0.8.dex.jar;com-google-android-gms.play-services-base.16.0.1.dex.jar;com-google-android-gms.play-services-basement.16.2.0.dex.jar;com-google-android-gms.play-services-gass.17.2.0.dex.jar;com-google-android-gms.play-services-identity.16.0.0.dex.jar;com-google-android-gms.play-services-maps.16.1.0.dex.jar;com-google-android-gms.play-services-measurement-base.16.4.0.dex.jar;com-google-android-gms.play-services-measurement-sdk-api.16.4.0.dex.jar;com-google-android-gms.play-services-stats.16.0.1.dex.jar;com-google-android-gms.play-services-tagmanager-v4-impl.16.0.8.dex.jar;com-google-android-gms.play-services-tasks.16.0.1.dex.jar;com-google-android-gms.play-services-wallet.16.0.1.dex.jar;com-google-firebase.firebase-analytics.16.4.0.dex.jar;com-google-firebase.firebase-common.16.1.0.dex.jar;com-google-firebase.firebase-iid-interop.16.0.1.dex.jar;com-google-firebase.firebase-iid.17.1.1.dex.jar;com-google-firebase.firebase-measurement-connector.17.0.1.dex.jar;com-google-firebase.firebase-messaging.17.5.0.dex.jar;fmx.dex.jar;google-play-billing.dex.jar;google-play-licensing.dex.jar + + + $(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_1024x1024.png + + + Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) + Debug + true + CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName) + 1033 + + + RELEASE;$(DCC_Define) + 0 + false + 0 + + + DEBUG;$(DCC_Define) + false + true + + + Debug + + + Debug + + + Debug + + + + MainSource + + + + + + + + Cfg_2 + Base + + + Base + + + Cfg_1 + Base + + + + Delphi.Personality.12 + Package + + + + BoldDataSetIPD4.dpk + + + + False + True + False + True + False + True + False + True + True + False + + + 12 + + + + diff --git a/Source/Unassigned/BoldDataSetIPD4.res b/Source/Unassigned/BoldDataSetIPD4.res new file mode 100644 index 0000000000000000000000000000000000000000..c29ccf6f1dcea1a897ef49c728acad9b0e1a5ade GIT binary patch literal 676 zcmaiy%}T>i5QR@l7S>fCp^K~~LN`otbmabnca;KHfB~6Rug%arGWOo~?!I`mQPHM1&LF>YnpdW1?6$y5@Jx zc}8sP%m4Y648G-X-y>U<456$1r}RO>gKwc)xk}Ao%T*|Yxzw{N8Xs&=s7Rp>@Q4}A zL>KCTb^SvyubNt(7x;3prIk4$D)gkGQt~Nk8Q)kVGKMGA&I-?jY7Ns8zpp)doJ+@6 zcSKhO>l>O2wvcKL(%3e=$m*@*H&r(^@6>0;7BfTHsKv~0Y|0#S=F2!AsnldrCNuw| zBEM}O!{TwX2I;oB+`bgpn@g-}$z}>VSNGfXzkQyN4)LbhWy(tpl-PGM))mo!H*?Od OCG5Vn)%W%ODg6P48(iuD literal 0 HcmV?d00001 diff --git a/Source/Unassigned/BoldUMLModelEditorDebugger.dpk b/Source/Unassigned/BoldUMLModelEditorDebugger.dpk index e913745..1e24c0f 100644 --- a/Source/Unassigned/BoldUMLModelEditorDebugger.dpk +++ b/Source/Unassigned/BoldUMLModelEditorDebugger.dpk @@ -25,11 +25,11 @@ package BoldUMLModelEditorDebugger; {$IMPLICITBUILD OFF} requires - vcl50, - Vcldb50, - Bold30D5, - Bold30D5Uml, - Bold30D5Utils; + vcl, + Vcldb, + Bold90, + BoldUml90, + BoldUtility; contains BoldUMLModelEditorDebuggerPlugin in 'BoldUMLModelEditorDebuggerPlugin.pas'; diff --git a/Source/Unassigned/BoldUMLModelEditorDebugger.dproj b/Source/Unassigned/BoldUMLModelEditorDebugger.dproj new file mode 100644 index 0000000..ecd84c7 --- /dev/null +++ b/Source/Unassigned/BoldUMLModelEditorDebugger.dproj @@ -0,0 +1,170 @@ + + + {B1033BC2-F58D-4BB6-A117-26186C23A3EF} + BoldUMLModelEditorDebugger.dpk + True + Debug + 38017 + Package + None + 19.2 + Win32 + + + true + + + true + Base + true + + + true + Base + true + + + true + Base + true + + + true + Base + true + + + true + Base + true + + + true + Base + true + + + true + Cfg_2 + true + true + + + true + Cfg_2 + true + true + + + true + Cfg_2 + true + true + + + false + false + false + false + false + 00400000 + true + true + BoldUMLModelEditorDebugger + 1 + false + true + true + 1046 + CompanyName=;FileDescription=;FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=;ProductVersion=1.0.0.0;Comments=;CFBundleName= + System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace) + + + package=com.embarcadero.$(MSBuildProjectName);label=$(MSBuildProjectName);versionCode=1;versionName=1.0.0;persistent=False;restoreAnyVersion=False;installLocation=auto;largeHeap=False;theme=TitleBar;hardwareAccelerated=true;apiKey= + Debug + $(BDS)\bin\Artwork\Android\FM_LauncherIcon_192x192.png + android-support-v4.dex.jar;cloud-messaging.dex.jar;com-google-android-gms.play-services-ads-base.17.2.0.dex.jar;com-google-android-gms.play-services-ads-identifier.16.0.0.dex.jar;com-google-android-gms.play-services-ads-lite.17.2.0.dex.jar;com-google-android-gms.play-services-ads.17.2.0.dex.jar;com-google-android-gms.play-services-analytics-impl.16.0.8.dex.jar;com-google-android-gms.play-services-analytics.16.0.8.dex.jar;com-google-android-gms.play-services-base.16.0.1.dex.jar;com-google-android-gms.play-services-basement.16.2.0.dex.jar;com-google-android-gms.play-services-gass.17.2.0.dex.jar;com-google-android-gms.play-services-identity.16.0.0.dex.jar;com-google-android-gms.play-services-maps.16.1.0.dex.jar;com-google-android-gms.play-services-measurement-base.16.4.0.dex.jar;com-google-android-gms.play-services-measurement-sdk-api.16.4.0.dex.jar;com-google-android-gms.play-services-stats.16.0.1.dex.jar;com-google-android-gms.play-services-tagmanager-v4-impl.16.0.8.dex.jar;com-google-android-gms.play-services-tasks.16.0.1.dex.jar;com-google-android-gms.play-services-wallet.16.0.1.dex.jar;com-google-firebase.firebase-analytics.16.4.0.dex.jar;com-google-firebase.firebase-common.16.1.0.dex.jar;com-google-firebase.firebase-iid-interop.16.0.1.dex.jar;com-google-firebase.firebase-iid.17.1.1.dex.jar;com-google-firebase.firebase-measurement-connector.17.0.1.dex.jar;com-google-firebase.firebase-messaging.17.5.0.dex.jar;fmx.dex.jar;google-play-billing.dex.jar;google-play-licensing.dex.jar + + + $(BDS)\bin\Artwork\Android\FM_LauncherIcon_192x192.png + android-support-v4.dex.jar;cloud-messaging.dex.jar;com-google-android-gms.play-services-ads-base.17.2.0.dex.jar;com-google-android-gms.play-services-ads-identifier.16.0.0.dex.jar;com-google-android-gms.play-services-ads-lite.17.2.0.dex.jar;com-google-android-gms.play-services-ads.17.2.0.dex.jar;com-google-android-gms.play-services-analytics-impl.16.0.8.dex.jar;com-google-android-gms.play-services-analytics.16.0.8.dex.jar;com-google-android-gms.play-services-base.16.0.1.dex.jar;com-google-android-gms.play-services-basement.16.2.0.dex.jar;com-google-android-gms.play-services-gass.17.2.0.dex.jar;com-google-android-gms.play-services-identity.16.0.0.dex.jar;com-google-android-gms.play-services-maps.16.1.0.dex.jar;com-google-android-gms.play-services-measurement-base.16.4.0.dex.jar;com-google-android-gms.play-services-measurement-sdk-api.16.4.0.dex.jar;com-google-android-gms.play-services-stats.16.0.1.dex.jar;com-google-android-gms.play-services-tagmanager-v4-impl.16.0.8.dex.jar;com-google-android-gms.play-services-tasks.16.0.1.dex.jar;com-google-android-gms.play-services-wallet.16.0.1.dex.jar;com-google-firebase.firebase-analytics.16.4.0.dex.jar;com-google-firebase.firebase-common.16.1.0.dex.jar;com-google-firebase.firebase-iid-interop.16.0.1.dex.jar;com-google-firebase.firebase-iid.17.1.1.dex.jar;com-google-firebase.firebase-measurement-connector.17.0.1.dex.jar;com-google-firebase.firebase-messaging.17.5.0.dex.jar;fmx.dex.jar;google-play-billing.dex.jar;google-play-licensing.dex.jar + + + $(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_1024x1024.png + + + Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) + Debug + true + CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=;ProgramID=com.embarcadero.$(MSBuildProjectName) + 1033 + + + RELEASE;$(DCC_Define) + 0 + false + 0 + + + DEBUG;$(DCC_Define) + false + true + + + Debug + + + Debug + + + Debug + + + + MainSource + + + + + + + + + Cfg_2 + Base + + + Base + + + Cfg_1 + Base + + + + Delphi.Personality.12 + Package + + + + BoldUMLModelEditorDebugger.dpk + + + + False + True + False + True + False + True + False + True + True + False + + + 12 + + + + diff --git a/Source/Unassigned/BoldUMLModelEditorDebugger.res b/Source/Unassigned/BoldUMLModelEditorDebugger.res new file mode 100644 index 0000000000000000000000000000000000000000..3ac2f8381d3d624fd59f762bb1277cd0c8f80acc GIT binary patch literal 748 zcmbV~Pfo&65XL`97vjpj8yD_ONKLviF)$SWvKx~(xenq-~isiGk6Ox;5poT z1Iuq-eOg#D$-Fn6Ki~U0Gm^B27DcI;E0WfIe21Kxi-l?gJ}Iq7m_6O;k+Y>PR$Di^ z=DW>#fo<{;eE&#RUt;+C#6=|o^pRheK5^8*n=4nMOk>azr5b^p=~+_}-(60qNTH6< z2oA>RLA%uY{Bvq%8akX8@Dge>_skhqswds+N*#2HJ;KxCPRN{6W7PvKcz=wQySh+Y z75tv_&nmcwYQn~=b;$VKQf)6R;4-H>eNCt|*_21*c&y^Cvsveo>)?;e7)HjT&0m@f z;WvTzh;u+B$J2K`G3L#Uc^Z0+E*PSp%KsFleYXLzW0Ntfl+5a!8o^h Date: Tue, 4 May 2021 16:33:23 +0300 Subject: [PATCH 007/112] #5 Added missing resource and uncomment action registration --- Source/BoldAwareGUI/IDE/BoldAwareGuiReg.pas | 2 ++ Source/BoldAwareGUI/IDE/BoldAwareGuiReg.res | Bin 0 -> 15044 bytes Source/Handles/IDE/BoldHandleReg.pas | 36 ++++++++++---------- 3 files changed, 20 insertions(+), 18 deletions(-) create mode 100644 Source/BoldAwareGUI/IDE/BoldAwareGuiReg.res diff --git a/Source/BoldAwareGUI/IDE/BoldAwareGuiReg.pas b/Source/BoldAwareGUI/IDE/BoldAwareGuiReg.pas index fa2d6ca..630fea7 100644 --- a/Source/BoldAwareGUI/IDE/BoldAwareGuiReg.pas +++ b/Source/BoldAwareGUI/IDE/BoldAwareGuiReg.pas @@ -57,6 +57,8 @@ implementation BoldPageControl, BoldIDEConsts; +{$R BoldAwareGUIReg.res} + procedure RegisterEditors; begin RegisterPropertyEditor(TypeInfo(TBoldSubscribe), nil, '', TBoldElementSubscribeMethodProperty); diff --git a/Source/BoldAwareGUI/IDE/BoldAwareGuiReg.res b/Source/BoldAwareGUI/IDE/BoldAwareGuiReg.res new file mode 100644 index 0000000000000000000000000000000000000000..a5890c789083b3d78031c5222b9f11c2b71d0299 GIT binary patch literal 15044 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 Rw^h7UOda^m+y9^A`5)L`ZAkzC literal 0 HcmV?d00001 diff --git a/Source/Handles/IDE/BoldHandleReg.pas b/Source/Handles/IDE/BoldHandleReg.pas index 553e677..0807ccb 100644 --- a/Source/Handles/IDE/BoldHandleReg.pas +++ b/Source/Handles/IDE/BoldHandleReg.pas @@ -13,6 +13,7 @@ implementation SysUtils, BoldUtils, ActnList, + Actions, Classes, DesignIntf, BoldElements, @@ -52,24 +53,23 @@ implementation procedure RegisterActionsInDelphi; begin - // marco -// RegisterActions(BOLDACTIONGROUPNAME, -// [ -// TBoldUpdateDBAction, -// TBoldActivateSystemAction, -// TBoldFailureDetectionAction, -// TBoldListHandleAddNewAction, -// TBoldListHandleDeleteAction, -// TBoldListHandleFirstAction, -// TBoldListHandleLastAction, -// TBoldListHandleNextAction, -// TBoldListHandlePrevAction, -// TBoldListHandleMoveUpAction, -// TBoldListHandleMoveDownAction, -// TBoldSetCheckPointAction, -// TBoldUndoAction, -// TBoldRedoAction -// ], nil); + RegisterActions(BOLDACTIONGROUPNAME, + [ + TBoldUpdateDBAction, + TBoldActivateSystemAction, + TBoldFailureDetectionAction, + TBoldListHandleAddNewAction, + TBoldListHandleDeleteAction, + TBoldListHandleFirstAction, + TBoldListHandleLastAction, + TBoldListHandleNextAction, + TBoldListHandlePrevAction, + TBoldListHandleMoveUpAction, + TBoldListHandleMoveDownAction, + TBoldSetCheckPointAction, + TBoldUndoAction, + TBoldRedoAction + ], nil); end; procedure RegisterComponentsOnPalette; From c39ed0efab454462b729bdfa39488e547f32572f Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Tue, 4 May 2021 17:22:19 +0300 Subject: [PATCH 008/112] Added missing res --- Source/UMLModel/Plugins/BoldUMLPlugins.pas | 2 ++ Source/UMLModel/Plugins/BoldUMLPlugins.res | Bin 0 -> 4308 bytes 2 files changed, 2 insertions(+) create mode 100644 Source/UMLModel/Plugins/BoldUMLPlugins.res diff --git a/Source/UMLModel/Plugins/BoldUMLPlugins.pas b/Source/UMLModel/Plugins/BoldUMLPlugins.pas index 8bf9c39..af6ecaf 100644 --- a/Source/UMLModel/Plugins/BoldUMLPlugins.pas +++ b/Source/UMLModel/Plugins/BoldUMLPlugins.pas @@ -89,6 +89,8 @@ TUMLModelUpdaterPlugIn = class(TUMLPlugInFunction) implementation +{$R BoldUMLPlugins.res} + uses SysUtils, BoldUtils, diff --git a/Source/UMLModel/Plugins/BoldUMLPlugins.res b/Source/UMLModel/Plugins/BoldUMLPlugins.res new file mode 100644 index 0000000000000000000000000000000000000000..1f5cda28ea152e5c071cba3a8a9e92ffecd461dd GIT binary patch literal 4308 zcmd5L~bnad;^+`}aN4G(*0PojG$zptvBg#hcI5VqLrufKZLJzd|v_v)31 z$P~J@zT@^(`yK2HbZaZJF3YkctLW=;M;7HSt_!$+CM#0M-6HJsZp^=8M&5b7eAx%M zd9&!Ri64%^-x~FuwihiH!9R&(54hqMJ(gat2LnHrU_IdKzu$@}8mvMxX06RnqU3VS zAHrUhJXgiM4iI)B+B_fnNnrnTwA<|l;6l!~YS`IIG|Ew9@V-IxT7+6lXVelIM6X}p z5Me*vVu*tg=;Hua++IqrVg)Ba7g`2SxIB^3uEP3^0q20xQm(&1O?`}MI=wi-^A|dm z^DnE{GPF8Rv76KjE7b~%tU(xMMAiDxM?Z>)BHfPkM?2)hA{EsXHJnwZl{Us9pU5gx z3J77V(cBDQ6~WJ(XNl*=(9TvOo~M6(g8s62yo30pV)rnQZ4jM)flsktSsW^UxW=Dr zN^5uxIy6wCLCFm%+Cz8*nDOj5uKurI)v@;Tb-IT^t(mvMh7CjN>-9idfBa^R?p&(_Aj&Z_=kO z*2?Gjx_o*jV-4b0SFTknk`}&MZyhC(LN?m5?REqNr-G+A$7$y{=OelTFagSzjhUZ< zr0w#R4z?UOEfLORyL`Ul4!DZla7`L#)VeX>YPQf2WOSmy=vFmJc7UYB-EEui1R`00 zEiM?&vfXWPU`9K6Vdoae`S8H7c%F!fyCn)@oE#g4d;h=fhYRxME2|g71M4+Sua~1v zFRULpyenhSgUcN|p;yUE`+w1^fgipoZ#Cds>!`RIxUM0C-A5*4El~$Hoagbg2lKUS zsU;Kw2QeypK1O3;u+#64>?_3Jp&c0k?(}>6BYTcZ1cd!*w6AFYEgIQ#yd~gANgF}# zVm82@xn(_15}UN(YQdI^dB$u|)Lu(i`}x{=g_!rxSM26BgA_imIn8X_Yj%`)&1~#7 zJ4(D}%zM;~c@LVk5yFvHQvLAV$AY@#`NuyzL;m~b@nrh*N5*VFOQ)X$o7?G+@3W3; zw*Gz(@bY?fxv1<}@vjy>wgA8LZIJwb)pZ4`PKD1l+F+3mwMSR&`w=&Q86~RX?i6Ca zFkLAWB=}>cQX*ebpIE*p(4{dL{ z0t4)lbK-&N_b>tcX##^(4+IASU6Wp|k8@&Gdg=fO?hw2NZUk2aEE;v%yfAP1`fC+_ zwT6m*5xs$Xp1OJBzU$bUe2%QCIFBR$u7f}*XnS#bA$*j)qu13JHDMF0Q* literal 0 HcmV?d00001 From 62b0d6a9f068b22751c3295a58d61a45a96fcd71 Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Tue, 4 May 2021 20:19:39 +0300 Subject: [PATCH 009/112] Added more missing resources --- .../FormGen/BoldAFPPluggableReg.pas | 2 + .../FormGen/BoldAFPPluggableReg.res | Bin 0 -> 488 bytes Source/Common/IDE/BoldWebConnectionReg.pas | 3 +- Source/Common/IDECOM/BoldComReg.pas | 2 + Source/Common/IDECOM/BoldComReg.res | Bin 0 -> 1920 bytes Source/Extensions/OLLE/IDE/BoldOLLEHandles.rc | 2 +- .../OLLE/IDE/BoldOLLEHandlesReg.pas | 2 + Source/Handles/IDE/BoldHandleReg.pas | 2 +- Source/Handles/IDE/BoldLockingReg.pas | 2 + Source/Handles/IDE/BoldLockingReg.res | Bin 0 -> 492 bytes Source/Handles/IDE/BoldManipulatorReg.pas | 2 + .../IDECOM/BoldComElementHandleReg.pas | 2 + .../IDECOM/BoldComElementHandleReg.res | Bin 0 -> 508 bytes .../Handles/Manipulators/BoldManipulators.rc | 2 +- Source/Handles/XML/BoldXMLProducers.pas | 3 + Source/Handles/XML/BoldXMLProducers.res | Bin 0 -> 488 bytes Source/MoldModel/IDE/BoldModelReg.pas | 2 + Source/MoldModel/IDE/BoldModelReg.res | Bin 0 -> 492 bytes .../UtilsGUI/BoldOclPropEditor.dfm | 354 ++++++++---------- .../DB/BoldPersistenceHandleDB.res | Bin 0 -> 504 bytes .../DB/BoldPersistenceHandleDBreg.pas | 2 + .../BoldExternalPersistenceHandles.res | Bin 0 -> 1520 bytes .../BoldExternalPersistenceHandlesReg.pas | 2 + .../IBX/BoldPersistenceHandleIB.res | Bin 0 -> 972 bytes .../IBX/BoldPersistenceHandleIBReg.pas | 2 + .../IDE/BoldHandlesPropagationReg.pas | 2 + .../IDE/BoldHandlesPropagationReg.res | Bin 0 -> 1412 bytes .../IDE/BoldObjectUpgraderHandleReg.pas | 2 + .../IDE/BoldObjectUpgraderHandleReg.res | Bin 0 -> 504 bytes .../IDE/BoldPersistenceHandleSystem.res | Bin 0 -> 512 bytes .../IDE/BoldPersistenceHandleSystemReg.pas | 2 + .../IDE/BoldPersistenceNotifierReg.pas | 2 + .../IDECOM/BoldComPersistenceHandleReg.pas | 2 + .../IDECOM/BoldComPersistenceHandleReg.res | Bin 0 -> 1008 bytes .../BoldHTTPClientPersistenceHandleReg.pas | 2 + .../BoldHTTPClientPersistenceHandleReg.res | Bin 0 -> 520 bytes ...PServerPersistenceHandlePassthroughReg.pas | 2 + ...PServerPersistenceHandlePassthroughReg.res | Bin 0 -> 540 bytes .../IDECOM/BoldPropagatorHandleCOMReg.pas | 2 + .../IDECOM/BoldPropagatorHandleComReg.res | Bin 0 -> 504 bytes Source/Samples/IDE/BoldSamplesReg.pas | 2 + Source/Samples/IDE/BoldSamplesReg.res | Bin 0 -> 4884 bytes Source/UMLModel/Ide/BoldUMLModelHandleReg.pas | 2 + Source/UMLModel/Ide/BoldUMLModelHandleReg.res | Bin 0 -> 476 bytes .../Rose98/BoldUMLRose98LinkReg.res | Bin 0 -> 948 bytes .../Rose98/BoldUMLRose98Linkreg.pas | 2 + .../ModelLinks/XMI/BoldUMXMILinkReg.res | Bin 0 -> 484 bytes .../ModelLinks/XMI/BoldUMXMILinkreg.pas | 2 + 48 files changed, 212 insertions(+), 198 deletions(-) create mode 100644 Source/BoldAwareGUI/FormGen/BoldAFPPluggableReg.res create mode 100644 Source/Common/IDECOM/BoldComReg.res create mode 100644 Source/Handles/IDE/BoldLockingReg.res create mode 100644 Source/Handles/IDECOM/BoldComElementHandleReg.res create mode 100644 Source/Handles/XML/BoldXMLProducers.res create mode 100644 Source/MoldModel/IDE/BoldModelReg.res create mode 100644 Source/Persistence/DB/BoldPersistenceHandleDB.res create mode 100644 Source/Persistence/ExternalPersistence/BoldExternalPersistenceHandles.res create mode 100644 Source/Persistence/IBX/BoldPersistenceHandleIB.res create mode 100644 Source/Persistence/IDE/BoldHandlesPropagationReg.res create mode 100644 Source/Persistence/IDE/BoldObjectUpgraderHandleReg.res create mode 100644 Source/Persistence/IDE/BoldPersistenceHandleSystem.res create mode 100644 Source/Persistence/IDECOM/BoldComPersistenceHandleReg.res create mode 100644 Source/Persistence/IDECOM/BoldHTTPClientPersistenceHandleReg.res create mode 100644 Source/Persistence/IDECOM/BoldHTTPServerPersistenceHandlePassthroughReg.res create mode 100644 Source/Propagator/IDECOM/BoldPropagatorHandleComReg.res create mode 100644 Source/Samples/IDE/BoldSamplesReg.res create mode 100644 Source/UMLModel/Ide/BoldUMLModelHandleReg.res create mode 100644 Source/UMLModel/ModelLinks/Rose98/BoldUMLRose98LinkReg.res create mode 100644 Source/UMLModel/ModelLinks/XMI/BoldUMXMILinkReg.res diff --git a/Source/BoldAwareGUI/FormGen/BoldAFPPluggableReg.pas b/Source/BoldAwareGUI/FormGen/BoldAFPPluggableReg.pas index cde91b7..ffb969a 100644 --- a/Source/BoldAwareGUI/FormGen/BoldAFPPluggableReg.pas +++ b/Source/BoldAwareGUI/FormGen/BoldAFPPluggableReg.pas @@ -6,6 +6,8 @@ procedure Register; implementation +{$R BoldAFPPluggableReg.res} + uses Classes, BoldAFPPluggable, diff --git a/Source/BoldAwareGUI/FormGen/BoldAFPPluggableReg.res b/Source/BoldAwareGUI/FormGen/BoldAFPPluggableReg.res new file mode 100644 index 0000000000000000000000000000000000000000..24d4660c5f8dcd0bb54768cb32e3d9787b433c39 GIT binary patch literal 488 zcma)&F;2rk5Ji6wB1(h26{J8)Ny!mHShhlff&-+m#z#oIC9aav$FanPT%@2|{>*Gd z((&b)d468)t_%PxRw-V@i+s(1HBBj3_{0Y9ctgYo`!inf%Dy4%OthXSJX}}ABjLW* z46aw)^ZVATIW4rA0Y1pt2Ro6KF^(fY=p}U&AMAebf>u(JRxB4BQ%r3<_sL$O#8|z( zpS6xhXjFASmdUv6HThqD3(QaJ5yD;Fr)$X7Zx70rX`wz^)y>5qo<23 W?Z-KXMc?-~&do3kb4U4GE%FP+A)DX; literal 0 HcmV?d00001 diff --git a/Source/Common/IDE/BoldWebConnectionReg.pas b/Source/Common/IDE/BoldWebConnectionReg.pas index 8ce2a10..5e3113b 100644 --- a/Source/Common/IDE/BoldWebConnectionReg.pas +++ b/Source/Common/IDE/BoldWebConnectionReg.pas @@ -9,7 +9,8 @@ procedure Register; implementation -{$R *.res} +{$R BoldWebConnectionReg.res} + uses BoldWebConnection, BoldIDEConsts, diff --git a/Source/Common/IDECOM/BoldComReg.pas b/Source/Common/IDECOM/BoldComReg.pas index 82f7343..8b6e2a6 100644 --- a/Source/Common/IDECOM/BoldComReg.pas +++ b/Source/Common/IDECOM/BoldComReg.pas @@ -9,6 +9,8 @@ procedure Register; implementation +{$R BoldComReg.Res} + uses Classes, DesignIntf, diff --git a/Source/Common/IDECOM/BoldComReg.res b/Source/Common/IDECOM/BoldComReg.res new file mode 100644 index 0000000000000000000000000000000000000000..b4f9eba11f262626b97b18963abdcfb428d02957 GIT binary patch literal 1920 zcmds%v2W8r6vkfxIjOwZ3Ot#bV={&j83Ub z9rT~*Gku^7`l8okdPjZCoMPl7rB~0qehu-`wF5Hy2x~tNtwlaj`;rJ>Dog8dg+wc9 zv)N!m9#*=_I$Z7fE8;E}y@Cry6x{0-Tg}iIsef1Zy1RVS^>t)!Pvk^_pU%hQI~ub@ zY(B+t9GSj~b~^uIx~c*`bbi?mIIj80gTAd_{Y3uZWHJdjmvy4WV$ov8?(k(-7sB%r zxBQ9c8CZV=%MP+1%T}K3ev|+S7c8~I6;inh-@R=8A)0!*mD)BFt`SRU9Nz1ETJH3E zNlkt|Usm!tqU-Bp7>Jk4o=!Wq81h$R)m|aVu?^SIj;;Eht>inlQ0$qjPP8agg6(KD z3QR}y`P`lK9@}#~Q4?FK*gif+^h8IG<@z7gti4FR&T2Y&p#$YQxKT}6mZf|hV{nzK z<|F~vrRu>A?g-5nn=|iY*|#qL8WYZE9?am|?*`;K3#Zd*AUh3a>1wq?&1%?AruWrs z2miPypxQ^B{_C3ktN&wnp2lw2lCY_#I5A$d*6cUYZ}5`8583-UYPQLjn)SY{oM literal 0 HcmV?d00001 diff --git a/Source/Extensions/OLLE/IDE/BoldOLLEHandles.rc b/Source/Extensions/OLLE/IDE/BoldOLLEHandles.rc index c6490b9..8e3ebe9 100644 --- a/Source/Extensions/OLLE/IDE/BoldOLLEHandles.rc +++ b/Source/Extensions/OLLE/IDE/BoldOLLEHandles.rc @@ -1 +1 @@ -TBOLDOLLEHANDLE BITMAP LOADONCALL TBoldOLLEHandle.bmp \ No newline at end of file +TBOLDOLLEHANDLE BITMAP LOADONCALL ..\..\..\Images\Components\TBoldOLLEHandle.bmp diff --git a/Source/Extensions/OLLE/IDE/BoldOLLEHandlesReg.pas b/Source/Extensions/OLLE/IDE/BoldOLLEHandlesReg.pas index 409dd8e..4681626 100644 --- a/Source/Extensions/OLLE/IDE/BoldOLLEHandlesReg.pas +++ b/Source/Extensions/OLLE/IDE/BoldOLLEHandlesReg.pas @@ -9,6 +9,8 @@ procedure Register; implementation +{$R BoldOLLEHandles.res} + uses SysUtils, BoldUtils, diff --git a/Source/Handles/IDE/BoldHandleReg.pas b/Source/Handles/IDE/BoldHandleReg.pas index 0807ccb..18351aa 100644 --- a/Source/Handles/IDE/BoldHandleReg.pas +++ b/Source/Handles/IDE/BoldHandleReg.pas @@ -48,7 +48,7 @@ implementation BoldUnloaderHandle ; -{.$R BoldHandleReg.res} +{$R BoldHandleReg.res} procedure RegisterActionsInDelphi; diff --git a/Source/Handles/IDE/BoldLockingReg.pas b/Source/Handles/IDE/BoldLockingReg.pas index 85483a0..ac46d9e 100644 --- a/Source/Handles/IDE/BoldLockingReg.pas +++ b/Source/Handles/IDE/BoldLockingReg.pas @@ -9,6 +9,8 @@ procedure Register; implementation +{$R BoldLockingReg.res} + uses SysUtils, BoldUtils, diff --git a/Source/Handles/IDE/BoldLockingReg.res b/Source/Handles/IDE/BoldLockingReg.res new file mode 100644 index 0000000000000000000000000000000000000000..b1c708217d332b6cb20fbe8339d8a57b35d8d52a GIT binary patch literal 492 zcmb79F>V4e5F8*vToawUP#{rKBArB^kcgn5(C`2xODlS+>#j_h?jDlznk)DbWePLv zH9;VyVCD6U$K$aL0AqFt)}&YU)d60qgwVwXFIZ#6^@=#h2bTE60`GVxs`~bKc8bx% zc`+e*O5K6UW9A+nt Y5C7FK-*Z`6mb_9cuj_hXRAPGKCjeo9vH$=8 literal 0 HcmV?d00001 diff --git a/Source/Handles/IDE/BoldManipulatorReg.pas b/Source/Handles/IDE/BoldManipulatorReg.pas index fd7de7a..503998c 100644 --- a/Source/Handles/IDE/BoldManipulatorReg.pas +++ b/Source/Handles/IDE/BoldManipulatorReg.pas @@ -9,6 +9,8 @@ procedure Register; implementation +{$R BoldManipulators.res} + uses SysUtils, BoldUtils, diff --git a/Source/Handles/IDECOM/BoldComElementHandleReg.pas b/Source/Handles/IDECOM/BoldComElementHandleReg.pas index 2eb7ed0..082ae3b 100644 --- a/Source/Handles/IDECOM/BoldComElementHandleReg.pas +++ b/Source/Handles/IDECOM/BoldComElementHandleReg.pas @@ -9,6 +9,8 @@ procedure Register; implementation +{$R BoldComElementHandleReg.Res} + uses Classes, BoldComServerElementHandles; diff --git a/Source/Handles/IDECOM/BoldComElementHandleReg.res b/Source/Handles/IDECOM/BoldComElementHandleReg.res new file mode 100644 index 0000000000000000000000000000000000000000..11da8b902c2357d30cd7bb38aeaa74f6b388d1d5 GIT binary patch literal 508 zcmZ{fv2MaJ5QcwHWr0|HTN#iT8F>X-B6TROL=iKSl~>5-E>$W9%9PjWSSd^1%=~AE z5+pd~?*IMye2xKN$_ybT?NyXLU_%l@pZbJ%ykd!G>Ixsou*Nplj65UD@W#FuEU3%K z(zrP$59h%%n#VSKNO;P7Ziff>!TThvv}l@!svG*_Dj^ALdP{)2A30Cpi~BpcUCl7` zgFo}{M>P;ROoy9Jzn*aIoai}BQOARaHB@*J6WDtKt|4OUUwRI)^pUgWM?~8GA-PyK pe2Nj}>c5X>eCCJah3BOkTYZ&IbWVmvQJ83*t*UB}tZS#l)d??jf6M>? literal 0 HcmV?d00001 diff --git a/Source/Handles/Manipulators/BoldManipulators.rc b/Source/Handles/Manipulators/BoldManipulators.rc index e392ae4..c60b00a 100644 --- a/Source/Handles/Manipulators/BoldManipulators.rc +++ b/Source/Handles/Manipulators/BoldManipulators.rc @@ -1 +1 @@ -TBOLDMANIPULATOR BITMAP LOADONCALL TBoldManipulator.bmp \ No newline at end of file +TBOLDMANIPULATOR BITMAP LOADONCALL ..\..\..\Images\Components\TBoldManipulator.bmp diff --git a/Source/Handles/XML/BoldXMLProducers.pas b/Source/Handles/XML/BoldXMLProducers.pas index 64b52a0..c343782 100644 --- a/Source/Handles/XML/BoldXMLProducers.pas +++ b/Source/Handles/XML/BoldXMLProducers.pas @@ -4,6 +4,7 @@ unit BoldXMLProducers; interface + uses Bold_MSXML_TLB, BoldStringList, @@ -65,6 +66,8 @@ TBoldXMLProducer = class(TBoldAbstractXMLProducer) implementation +{$R BoldXMLProducers.res} + uses SysUtils, BoldUtils, diff --git a/Source/Handles/XML/BoldXMLProducers.res b/Source/Handles/XML/BoldXMLProducers.res new file mode 100644 index 0000000000000000000000000000000000000000..c9a68e022ef1f94db0034fe1545a9ad074a016ca GIT binary patch literal 488 zcmZWkyAHxI3_K75vCw9N0f~{3Pe4#M5D0<9$Yg$_Bi$JLIhFXK{((8ygy$uWFPDqs z0KkNy>OuO2YYUiDQElUZ1-4it!wDPa9roO3IAVzvdBhCkPUKUP;WJurdBU3afkzsR zP0j&MLO@Rq?=@w4|Q6dfy890bPbhP1I03uWRLSo+wAu)lUBXO2){R+iPu>;jQ;!`7>LG2OkrDOCzxCJmB=n1-U=2fB MmSxYWyl;v;0RAtalmGw# literal 0 HcmV?d00001 diff --git a/Source/MoldModel/IDE/BoldModelReg.pas b/Source/MoldModel/IDE/BoldModelReg.pas index 41ba779..9131ff2 100644 --- a/Source/MoldModel/IDE/BoldModelReg.pas +++ b/Source/MoldModel/IDE/BoldModelReg.pas @@ -13,6 +13,8 @@ procedure Register; implementation +{$R BoldModelReg.res} + uses SysUtils, BoldUtils, diff --git a/Source/MoldModel/IDE/BoldModelReg.res b/Source/MoldModel/IDE/BoldModelReg.res new file mode 100644 index 0000000000000000000000000000000000000000..056025f7f2b1be1b31aa48b99490a478285e796e GIT binary patch literal 492 zcmZ{ft&YM#6on6jEFqZADprsnS8jr=Adp#t;7?$1RhKsa9F^1|`xtcy#P*$#h}ko} zP>SH(-Z^K!X>O+g&|^EN&G@2Y4X`B6)v>||3rx9RVT~nzF~<-y`h-3wpE9d{&}}>h zeKU0KU4!Bt=YF=egU5@7#{eJ1u^LxKc8omFdEhVV&8czKyE}+i#4}3spI2t>xa4E; z`I7l6xC{=gExEN49>RUNE%~nC9M#{klt;HSE7SSaZ@CMlT;Td)_MvwXTp0z%n1IH( k2{ii|(dn666>cj0>n$(;R7@*L63+Gt(ll*ql;?Dje<' + '< Attributes >' + '< Single links >' + '< Multi links >' + '< Operations >') end end end @@ -2420,136 +2514,8 @@ object BoldOclPropEditForm: TBoldOclPropEditForm Left = 470 Top = 50 Bitmap = { - 494C010105000900040010001000FFFFFFFFFF10FFFFFFFFFFFFFFFF424D3600 - 0000000000003600000028000000400000003000000001002000000000000030 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 + 494C010105000700040010001000FFFFFFFFFF10FFFFFFFFFFFFFFFF424D3600 + 0000000000003600000028000000400000002000000001002000000000000020 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 @@ -2807,12 +2773,8 @@ object BoldOclPropEditForm: TBoldOclPropEditForm 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000424D3E000000000000003E000000 - 2800000040000000300000000100010000000000800100000000000000000000 - 000000000000000000000000FFFFFF0000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 0000000000000000000000000000000000000000000000000000000000000000 - 00000000000000000000000000000000FFFF000000000000C01F000000000000 + 2800000040000000200000000100010000000000000100000000000000000000 + 000000000000000000000000FFFFFF00FFFF000000000000C01F000000000000 801F000000000000801F000000000000801F000000000000801F000000000000 801F000000000000801F000000000000801F000000000000801F000000000000 801F000000000000801F000000000000801F000000000000801F000000000000 @@ -2831,4 +2793,8 @@ object BoldOclPropEditForm: TBoldOclPropEditForm OnClick = Copymessagestoclipboard1Click end end + object MRUPopupMenu: TPopupMenu + Left = 345 + Top = 223 + end end diff --git a/Source/Persistence/DB/BoldPersistenceHandleDB.res b/Source/Persistence/DB/BoldPersistenceHandleDB.res new file mode 100644 index 0000000000000000000000000000000000000000..af85a4487d57455f4dd56b093a76e0d69cbb17c4 GIT binary patch literal 504 zcmb7Au?~VT6g-WFxEQ+WVB+ZLFNm6GVw9+jzrhA0TVc|X&tdSR-0HzAf`fxi@4f5w z<=$%nU`|*oApKfd4+yDP+s73FPB>sgWs5T|*b`UsBi4*NtjIR3*fItmpCx94=CB}{ zIP@U$oIRdnK~pC=1-Ox>k{C&e6lGcRq8hqNRuZGU!$Ql7BgBq|$t#P7a`5ifn8 Pd#PU(g(t0a>#p@1{Y`wm literal 0 HcmV?d00001 diff --git a/Source/Persistence/DB/BoldPersistenceHandleDBreg.pas b/Source/Persistence/DB/BoldPersistenceHandleDBreg.pas index 14dc3d3..8ef3721 100644 --- a/Source/Persistence/DB/BoldPersistenceHandleDBreg.pas +++ b/Source/Persistence/DB/BoldPersistenceHandleDBreg.pas @@ -9,6 +9,8 @@ procedure Register; implementation +{$R BoldPersistenceHandleDB.res} + uses Classes, Dialogs, diff --git a/Source/Persistence/ExternalPersistence/BoldExternalPersistenceHandles.res b/Source/Persistence/ExternalPersistence/BoldExternalPersistenceHandles.res new file mode 100644 index 0000000000000000000000000000000000000000..d7547a4181c26499702734637e101667c2a8dd67 GIT binary patch literal 1520 zcmd6mJ5K^Z6on6Jme3fs)53((l7x~mEKH`M@JHFL z=gyto#llJxnQ&*$o_Xxu`M3bkV&u67<+qmBfGM3kKfnZ+xWy1X^zp=}J{~Z_1)V#u z#~5Jj{SmI{Tyt*3)kEq&9vLIf_PA>hp7d31oE;S}J*PMcQG?no=J0W>QLNL^0{p>R z9oSPcEVkP%C*-4K$aP?^-UJ{EKSgKA+UiHLCis!; zRX>6Hyr`)OYwD{7sQuo#_2>s2dfx$ly5$8Ac^ zUFS;9l^-RgPtM*CoZG@ba6WV!B!P1`a|LHZKPou$J{54_urHin{(y6jwLW2tS>=;G z;O+m?p{^yJqOPrTwyf*78(Y+M<+ElBpS-;vczZwa*7aJ~a(+?Q_C2+McjA5RwZitG GuD<})+Kd4J literal 0 HcmV?d00001 diff --git a/Source/Persistence/ExternalPersistence/BoldExternalPersistenceHandlesReg.pas b/Source/Persistence/ExternalPersistence/BoldExternalPersistenceHandlesReg.pas index b29c282..1d290dd 100644 --- a/Source/Persistence/ExternalPersistence/BoldExternalPersistenceHandlesReg.pas +++ b/Source/Persistence/ExternalPersistence/BoldExternalPersistenceHandlesReg.pas @@ -9,6 +9,8 @@ procedure Register; implementation +{$R BoldExternalPersistenceHandles.res} + uses DesignIntf, DesignEditors, diff --git a/Source/Persistence/IBX/BoldPersistenceHandleIB.res b/Source/Persistence/IBX/BoldPersistenceHandleIB.res new file mode 100644 index 0000000000000000000000000000000000000000..42f910a8ca1a41e224725502229d86c48a053d2d GIT binary patch literal 972 zcmc(dv2NQi6h&_e!-AGV-0Gn~#*X;}+g02KFxn#V2WT)Dc=HfI>E_M$R0jxL-M{gm zQ6JP!>V2dXxClCz&?7GopB^b*0l=lAZDUCO)pi%aH<7k|g9WDeiaBzTYuw@vH;RSy z7kpIz855~o8P{5wzSOzG`$0eXAn~q?3q*XWJ?ghH`n))906o}j;-FqqvBBwd(t;h@ zhBglB<9D=JJuh<~+KS}T&w?gbe2#j>qbFky>HQ6lmSfn@NYjRwc_5+dkYQ_LJ+@qO zjj~%{^=r2th6(wj-EP;u08$z+;o+R+8^6!oh=-JwcySQU5>hpWcDxv#k# zTqvfBJGnTKn-jTh9^d|VPnUV`slH;?d-_UuzQ5w#KVY7o)#)zeAHxIisaq=MO*0axh?sct%Qd1^Z3r)S(np4Y&56gWbijyHNi-0ByY*BH9A_q6oc Mi>KaO_5SRC0LQW#jsO4v literal 0 HcmV?d00001 diff --git a/Source/Persistence/IBX/BoldPersistenceHandleIBReg.pas b/Source/Persistence/IBX/BoldPersistenceHandleIBReg.pas index 8f794dc..3b89912 100644 --- a/Source/Persistence/IBX/BoldPersistenceHandleIBReg.pas +++ b/Source/Persistence/IBX/BoldPersistenceHandleIBReg.pas @@ -9,6 +9,8 @@ procedure Register; implementation +{$R BoldPersistenceHandleIB.res} + uses SysUtils, BoldDefs, diff --git a/Source/Persistence/IDE/BoldHandlesPropagationReg.pas b/Source/Persistence/IDE/BoldHandlesPropagationReg.pas index 6f1295a..1364266 100644 --- a/Source/Persistence/IDE/BoldHandlesPropagationReg.pas +++ b/Source/Persistence/IDE/BoldHandlesPropagationReg.pas @@ -9,6 +9,8 @@ procedure Register; implementation +{$R BoldHandlesPropagationReg.res} + uses SysUtils, BoldUtils, diff --git a/Source/Persistence/IDE/BoldHandlesPropagationReg.res b/Source/Persistence/IDE/BoldHandlesPropagationReg.res new file mode 100644 index 0000000000000000000000000000000000000000..892ade93e854262d2ffd4ff91f90c86c588a4984 GIT binary patch literal 1412 zcmd5*v2NQi6ui_0=Cda#<@4R!Dn3KlIGuWMd%t| zagJ~Jf-{;gC~`jR{e%y1)8r$8_pu*==^5qy`;L2_7KYIP^uQP%=uMEi!G6D|fG^Y! zjt6>k?GE~J8!_si7^3R`Y`|JR3;@4kOv1J)ftuPw6$8rJO&gODwzmm4&JKJXu%bFq zW{su2D2gK2sB7pl54iMasow#IGmn`MxES##&+OzG*omU3zVYdWuG;=Puc>zt$7yp}m*;kC@Cl&Ld1QYlQ1#1~} z6*_1sJg->Gh@aN-5*Osn8&dM>88u&pFa331ZdLk+wXW(~qz&2HnuyDG(^nBMceUHa zMayu3{|@6()^fU-m6E!Mot-umo1fW2k1SU;s5{u literal 0 HcmV?d00001 diff --git a/Source/Persistence/IDE/BoldObjectUpgraderHandleReg.pas b/Source/Persistence/IDE/BoldObjectUpgraderHandleReg.pas index fa9e67b..792b94a 100644 --- a/Source/Persistence/IDE/BoldObjectUpgraderHandleReg.pas +++ b/Source/Persistence/IDE/BoldObjectUpgraderHandleReg.pas @@ -9,6 +9,8 @@ procedure Register; implementation +{$R BoldObjectUpgraderHandleReg.res} + uses classes, BoldObjectUpgraderHandle, diff --git a/Source/Persistence/IDE/BoldObjectUpgraderHandleReg.res b/Source/Persistence/IDE/BoldObjectUpgraderHandleReg.res new file mode 100644 index 0000000000000000000000000000000000000000..13ca72d29fb8827443a5e5bae900cd8128deed99 GIT binary patch literal 504 zcmY+AF;BxV5QSe6s_9bM3!(#3N5=kzwp1Wg0Yb26x~xpi>e1O4(|;3*U&UnJ`C=rj zobU7Vy|ZHgSTl0AApRR^2E0A;t3$auO3icz3s4=}zdDS~Aq}*qI0PY7N9#klo*d0r2*C^H uyw!qw@U1RWD0+J)V`ch}XLHk~JCRrA;q*l6i@xvY1;r1;;0&d7pZFJ2UUo+S literal 0 HcmV?d00001 diff --git a/Source/Persistence/IDE/BoldPersistenceHandleSystem.res b/Source/Persistence/IDE/BoldPersistenceHandleSystem.res new file mode 100644 index 0000000000000000000000000000000000000000..4130335d2298d5ed38f52eb5f8ac419ac75594d2 GIT binary patch literal 512 zcmb79v2MaJ6ucl*#8TN)$$-Sj*k5P~QY#gTAOqbpxpV#?BiZog{7r^_RGHjMp3{VZ z0n7K^`TTr-4*(W~_X5(Zb&7x^74Jt#@rqA;Ai)l6>~X+5k&;Z&-MY0v@In0B`&8AX^UtE#^52Yo!sKZBfz~>_`c^&9&OM(FbUo1H Yn|kZtj-;n$S%yiKb8aGon%>=*Kd1_TB>(^b literal 0 HcmV?d00001 diff --git a/Source/Persistence/IDE/BoldPersistenceHandleSystemReg.pas b/Source/Persistence/IDE/BoldPersistenceHandleSystemReg.pas index b536704..2322a19 100644 --- a/Source/Persistence/IDE/BoldPersistenceHandleSystemReg.pas +++ b/Source/Persistence/IDE/BoldPersistenceHandleSystemReg.pas @@ -9,6 +9,8 @@ procedure Register; implementation +{$R BoldPersistenceHandleSystem.res} + uses Classes, BoldIdeConsts, diff --git a/Source/Persistence/IDE/BoldPersistenceNotifierReg.pas b/Source/Persistence/IDE/BoldPersistenceNotifierReg.pas index edfb9ca..275dba4 100644 --- a/Source/Persistence/IDE/BoldPersistenceNotifierReg.pas +++ b/Source/Persistence/IDE/BoldPersistenceNotifierReg.pas @@ -9,6 +9,8 @@ procedure Register; implementation +{$R *.res} + uses DesignIntf, Classes, diff --git a/Source/Persistence/IDECOM/BoldComPersistenceHandleReg.pas b/Source/Persistence/IDECOM/BoldComPersistenceHandleReg.pas index 99f0535..8a72e74 100644 --- a/Source/Persistence/IDECOM/BoldComPersistenceHandleReg.pas +++ b/Source/Persistence/IDECOM/BoldComPersistenceHandleReg.pas @@ -9,6 +9,8 @@ procedure Register; implementation +{$R BoldComPersistenceHandleReg.Res} + uses Classes, DesignIntf, diff --git a/Source/Persistence/IDECOM/BoldComPersistenceHandleReg.res b/Source/Persistence/IDECOM/BoldComPersistenceHandleReg.res new file mode 100644 index 0000000000000000000000000000000000000000..9ef6c635eae7cfc47a41ced24b3f042bbb19ca5d GIT binary patch literal 1008 zcmd6kKTE?<6van40-Oub(NoFDJ?1;we~9XQP(PldB&oW4{Qy^XFav;!(eKDS#5*XmlSGSH-Wo} zp0$*XC^#n~@)iO~lEjWb#a3HhyngZS0Z$y4k|%LyIh1A}&+B?C$xZ(vQnCq>?qabB zL<`OnuU4zbPi4A$DSq~ONdHFG(>Yx?p8ti<#$)64Kl8b+Q2S#nv7tU-hZWruO1zAGmnd%DP0 z%o{vVY4(+uxdrZ~XS1Z3rQn17G5LG&-dV$YA}6n4p_D3wzZIh%x%s&A t**C6)dk?t#k)sZrlX%;nJb9dN^4hyh&AP73Yz5w@==(lTw~Et~v|r(`iy#01 literal 0 HcmV?d00001 diff --git a/Source/Persistence/IDECOM/BoldHTTPServerPersistenceHandlePassthroughReg.pas b/Source/Persistence/IDECOM/BoldHTTPServerPersistenceHandlePassthroughReg.pas index 1ccb160..5967382 100644 --- a/Source/Persistence/IDECOM/BoldHTTPServerPersistenceHandlePassthroughReg.pas +++ b/Source/Persistence/IDECOM/BoldHTTPServerPersistenceHandlePassthroughReg.pas @@ -9,6 +9,8 @@ procedure Register; implementation +{$R BoldHTTPServerPersistenceHandlePassthroughReg.res} + uses BoldIDEConsts, BoldGuard, diff --git a/Source/Persistence/IDECOM/BoldHTTPServerPersistenceHandlePassthroughReg.res b/Source/Persistence/IDECOM/BoldHTTPServerPersistenceHandlePassthroughReg.res new file mode 100644 index 0000000000000000000000000000000000000000..d4c666b816759a8b82f57676755e4b18efa55d66 GIT binary patch literal 540 zcmaKnu};G<5QhIEl&A}eHyDsQGV%(gZV3{i6%EW8DtFC*l#JP&OfcqgBJon)%x|Bo z0ungByWiiPFJ}Ol(VP>b{IR+T@J8a?84BECjYnwY)CD%!Vu@$G2EPe@iwDwz`UwmA z9CIqoTT9l@ne*A4x7K*UJ(a9mT%R9*d_!>=Z34kF&hdF6mK_U2Yyobxtps{XT8nWU zneY$u!AYQ(w>s?1il4YYwT?B6r<&bwt@X-pcKd(T73x?~HixcC6^;N{1OPrq>`+*+Wz3LK4NpUAuJV99;|GHq;?sA=E#iK)SPvSAp~IF;`n GrTGFsNr-L$ literal 0 HcmV?d00001 diff --git a/Source/Propagator/IDECOM/BoldPropagatorHandleCOMReg.pas b/Source/Propagator/IDECOM/BoldPropagatorHandleCOMReg.pas index da6e7af..6172d38 100644 --- a/Source/Propagator/IDECOM/BoldPropagatorHandleCOMReg.pas +++ b/Source/Propagator/IDECOM/BoldPropagatorHandleCOMReg.pas @@ -9,6 +9,8 @@ procedure Register; implementation +{$R BoldPropagatorHandleCOMReg.res} + uses Classes, BoldGuard, diff --git a/Source/Propagator/IDECOM/BoldPropagatorHandleComReg.res b/Source/Propagator/IDECOM/BoldPropagatorHandleComReg.res new file mode 100644 index 0000000000000000000000000000000000000000..0c139f75af48fb7529b670925157f9992348ffc2 GIT binary patch literal 504 zcmY+9F>V4e5JmqYWKp5r6sr&ki7G;(p`s52k%AC}IDly^aSNB*($MA*xxh+XhdY@6 z?KM)Y9nYKp$KEjjOc)`gApToT0qm)S(8Cc+{9ubuDhJXYAJ{OC%enRe9>T z5MNl(ugGpxJNc1a?c`V8S!w0pCwrPy~^V_=<%h%O51S3DP9~k+OsYl>u xskOWmG|C)16=DpI@qM7txb!aAKtvu(GIe%oHjqhTineuz{OzO!qi60Bed@cY0 literal 0 HcmV?d00001 diff --git a/Source/Samples/IDE/BoldSamplesReg.pas b/Source/Samples/IDE/BoldSamplesReg.pas index 34460df..c0c29be 100644 --- a/Source/Samples/IDE/BoldSamplesReg.pas +++ b/Source/Samples/IDE/BoldSamplesReg.pas @@ -9,6 +9,8 @@ procedure Register; implementation +{$R BoldSamplesReg.res} + uses SysUtils, Classes, diff --git a/Source/Samples/IDE/BoldSamplesReg.res b/Source/Samples/IDE/BoldSamplesReg.res new file mode 100644 index 0000000000000000000000000000000000000000..11260faa4c48b2f480ec0bcf72fbd2b9442e6d46 GIT binary patch literal 4884 zcmeHL&uiR96n<`sw5Fjeowhj?LN3YCH0iB}wY_%hw*Eov{<`U~NK5cx?StiQp%yK4 z6)-p{ZJj`&P=%~U_*-I!a`b_|DcB^(8C@K-q2Fzd+&|3TE%gE2u%(huSTCf zy_tEMPjB?bL`0`?B#9n?10^0Js)0$8=V*b(XqMi_^%T%3&=l%<8mEgi0knX-7ftIC zdinXZqjLZ+nPZ5QK8=2FzNm+j8p=5$!jGazPpAQLM6|QBgB$E9pAtQxR^Jn<*ZkUK zy*BBi)cwiHdYut)%?GY29^^B7xp{bn!H6um7xZG3$Y6>~@G8Vr(2Yx_QWQ5~#+c%$ z-ER7xZTOIUa(ZG9K5(3bOE(V5yW&d!W$?p}>$;A;+5_)i5!`MQHBSjot4W`a<6av) zH}&k*cGGf)FJHcF`60m{=i0Svw)p7#+>3!eYxxFR3~D(~A3(zeC^!ub$APBk-GZ7# zPeV`kTP8=RKR5`bG(oEnacnTpEMu~J5i0@g4OJKu+YBpa-n$AMt9|PfV=2uc@FEIi z0q^Qi;R<+6q0S-mDSkAs9<%Q)IzQq%ogKy}J3ozFckT-Qc>V8@`_8|&m|yz~_9xC; zjDsb2`OHV3t}ymnS3mq@?S|sDt83o|{GOo%VTwf0xkL0Eg?s%8k*RKpLkr&~gH6?l|f>(e-JrzvfXMandCe(~QZmEu1WX zQWydUu0!px9ET;~>kcKoa<9$!KCf_PTw4B0xT0-=(OL^x-j6Bv{T%jA+<>)*))c(3 zwY6pYs;lsU(Ut8}T^VP(T39zzy%B-O(^b}AaptJ?_ceGlxc*McS92O`u*Pkw;PKYn zpYaXlW3WW{V1hv$$_X`~d_Nx-n;x2BR;AwHaEVOK0TpeSdYSQ3C9HrsbC!8`3H9>X zGmLSAEtk)tuDF6j;3eE(zTc001UIB^@K~Q|-B%PyTrtcu5Sw=~GZ%2MhBHuX8j-hv z2%G|9oT^t`SNTQeBh7yz;3u8`V3qEoXB4~`62z#rH}Gk^A1<{RFlfK`>z(atRlCs|4b`%5-)|BjW-&zG9vGI{ zFYg{mbpG4#chICTN@fp`xu@N-Ws*GXSfL3nGdIv=dwcultzQ_VkMq^n->8CGzjEQ# zd=s=qlPHSnf8HxRf)1qWU^cQ*KL6rN7}It_Yuo(Lxu?#g1erB~FDwu5Qt*%i_W8Ej zMD?mS?x6`r0VvqulJoc~W^3>}GB4i|&faI}b^P&~RMR;{U0jd;i~X1^8O8(PQaMR@ zvF`$xOT6CeR;s|ScRG8eNbUc*opgyY+jnC0W%}uK6*IrShwR_*>$j6K_b;P%Qu{dG z=&+3^G@aZ*Kk_YE>~waKW@LGuW%7Z=-9_-44=C1rK!y?!l_y1Bl)2B8P)bm-cJjq^CAr@Mb@kB(U!pe!o_$ZfvN{ z{_K7=&*$xVERXE0e{w6*KgNZQm4y4pSjg)toN6@DHp}baOqSOHKgqoAuzmFe6ihR9 R-f{8&Oa9jrIzQujJ^-?Pn5+N* literal 0 HcmV?d00001 diff --git a/Source/UMLModel/Ide/BoldUMLModelHandleReg.pas b/Source/UMLModel/Ide/BoldUMLModelHandleReg.pas index 1489a93..3502265 100644 --- a/Source/UMLModel/Ide/BoldUMLModelHandleReg.pas +++ b/Source/UMLModel/Ide/BoldUMLModelHandleReg.pas @@ -9,6 +9,8 @@ procedure Register; implementation +{$R BoldUMLModelHandleReg.res} + uses SysUtils, Classes, diff --git a/Source/UMLModel/Ide/BoldUMLModelHandleReg.res b/Source/UMLModel/Ide/BoldUMLModelHandleReg.res new file mode 100644 index 0000000000000000000000000000000000000000..f7aa563518c717738a02de7f81e6f448832dfd4e GIT binary patch literal 476 zcmZutF;2rk5S$=nD-FKupg>AVNs$*sp##zIfK;2-6{K_*yTYZPV~N&}xd)uI%z4j| zB3OBD$K%m@_5ff*s2WJGs$BtFDyld5zz*+t#U5|$d%Tb@^^C{cg+GzpXRKiIhI4-I z3~n*by#e^3X{_-iB^r$5$PX!4YHE$AWmSkA@hMAH=bE-uB2`=KT!H*t$7$kQ;%yx@ zW`3bzNb*yI~kgqvE}HnaVFan7i}< literal 0 HcmV?d00001 diff --git a/Source/UMLModel/ModelLinks/Rose98/BoldUMLRose98LinkReg.res b/Source/UMLModel/ModelLinks/Rose98/BoldUMLRose98LinkReg.res new file mode 100644 index 0000000000000000000000000000000000000000..07448d184d5f91512759e10b57ab2eb91687a3d1 GIT binary patch literal 948 zcmbV}Jx{|x42E5VKwVJ0G|7NqWMqU5p)w%8BtCY!9O{@UY$Q{XsqI4Je^Uwm5L3c* zyuM3{7?2RB`0TvCiyc2iMEfvny&?Ru$^p>{6l*u=o=)k8E@?~;bOnElw>vsRbWYcF zvA%amyPN&X0fMNr0eN{J-+bHg7W4<5&xr6)mU)LAAuOZSYK4S0sm^+b-S=(D=wco@ zk8P6f<$W9`w(Sy-t?d$!tu0&va%-P+)*E5crloE5Qry|m`6q(8^Fo2~7BA%rln95RFR*(%6%2H)xVyV;e zQx+K6Bo%225zn%cI+jJp5=EqE`6;qovxMBUtV9+)OMl+6tYlfq!n4$Gi=fmnKwaio n+u^y0vebTJlvI}5J_OGaiCE?s6xu~Xq-TjLYnGV9H%s{f0KXy& literal 0 HcmV?d00001 diff --git a/Source/UMLModel/ModelLinks/Rose98/BoldUMLRose98Linkreg.pas b/Source/UMLModel/ModelLinks/Rose98/BoldUMLRose98Linkreg.pas index b647d44..6a2d5a4 100644 --- a/Source/UMLModel/ModelLinks/Rose98/BoldUMLRose98Linkreg.pas +++ b/Source/UMLModel/ModelLinks/Rose98/BoldUMLRose98Linkreg.pas @@ -9,6 +9,8 @@ procedure Register; implementation +{$R *.res} + uses SysUtils, BoldUtils, diff --git a/Source/UMLModel/ModelLinks/XMI/BoldUMXMILinkReg.res b/Source/UMLModel/ModelLinks/XMI/BoldUMXMILinkReg.res new file mode 100644 index 0000000000000000000000000000000000000000..16eb42b6c53b2230f84932dffba29e7bae83580a GIT binary patch literal 484 zcmZvYJ!->15QU#j8aF}P#YMnn${fIz5dx9F#)gzCgnW%HtuCdGBS^c4*#ihB?`b6k zfrp)$$G2~HhXsHG(<~+BDsCI#NMg3d87F+<9XT%eVE<+<*-L!lZ94Ue=ZE=%7mBAT zH%R!v`+gr&X0vhZ9^iuasj*TrJ^H@qh6Yr#)L7HZhPtV>@ Date: Tue, 4 May 2021 20:22:59 +0300 Subject: [PATCH 010/112] Bugfix for blob invalidate causing member to become dirty --- Source/ObjectSpace/BORepresentation/BoldAttributes.pas | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/ObjectSpace/BORepresentation/BoldAttributes.pas b/Source/ObjectSpace/BORepresentation/BoldAttributes.pas index 9942dc0..0b0ea64 100644 --- a/Source/ObjectSpace/BORepresentation/BoldAttributes.pas +++ b/Source/ObjectSpace/BORepresentation/BoldAttributes.pas @@ -2529,7 +2529,7 @@ procedure TBoldBlobStream.InternalSetSize(NewSize: Int64; BlobEvents: Boolean); (not assigned(fBlobAttr.BoldAttributeRTInfo) or fBlobAttr.BoldAttributeRTInfo.AllowNull) then begin SetLength(fData, 0); - if not fBlobAttr.SupressEvents then + if not fBlobAttr.SupressEvents and not fBlobAttr.BoldPersistenceStateIsInvalid then fBlobAttr.SetToNull; end else From ea112fe6d344b6f1a3853938b01bf11e8375a911 Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Tue, 4 May 2021 20:36:18 +0300 Subject: [PATCH 011/112] More res files --- Source/Handles/IDE/BoldHandleReg.res | Bin 0 -> 7376 bytes Source/Handles/Manipulators/BoldManipulators.res | Bin 0 -> 488 bytes .../IDE/BoldPersistenceNotifierReg.res | Bin 0 -> 992 bytes .../SQLDirect/BoldDatabaseAdapterSQLDirect.pas | 2 +- 4 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 Source/Handles/IDE/BoldHandleReg.res create mode 100644 Source/Handles/Manipulators/BoldManipulators.res create mode 100644 Source/Persistence/IDE/BoldPersistenceNotifierReg.res diff --git a/Source/Handles/IDE/BoldHandleReg.res b/Source/Handles/IDE/BoldHandleReg.res new file mode 100644 index 0000000000000000000000000000000000000000..cefccf4dddce81ee105b8b37402caae18d4d4a79 GIT binary patch literal 7376 zcmds6zi$*r6n+lT`m9K~y%gXpBCKn07bHhYq@=*GoUmkm1RE5(!8*;_-615O5eP0u z!iR+9b7L_TElNv+L=j6#>Hi}sC>BI<1}mHIy_wm)ri(O75zWyx9P@OR&eJ)XrVG%`;?BxR`ucMRX%b-E z9V2Ab6Y%-_m-Yy~pJ_@wDvt52hJ5+wTtmC_n zTFuec)X5fJ>)xN0W3>~{zXQ~9%N%=p;+O^LPorwm*;a;PetW zoB^A4@O)T!Rep@XaWi$2fbQMxZQQ+16RoBLR zBO7clX2~tDPel(md+Oh_mtSK)@Gre^ex!HKzs1&nrWb${+h^}J(k(r<(p|na_RvZ@ z(B!p2{&52qgn2zT!0TE18C+fln{)U#12!)l7Cs~0s5hcIzeGdV>y3te9mY_IWS9c6 zVSQW)GyB*euEh`ZI~?Oq{8#Vqhq=n<uQ0cP z#UZ#Ibw8VX*P8kKae&WRaLDuRA&E)Pq2q@+jB67)S5N!!+Z?ewV<1l3X8@5+n z(TmTqFq=QYRoL!zI{0gYtA2gXisulW$v9-3amf1jI2_EEm%!jOox!|1jarB+o;kV# zGzZ;f#OP^gE+cxa90afYPP*Kb%N|&9&zzptS}kixr38Z~Se4g#EE%g(ujlm8u0!8i zfxi5(*E3FEGVA8C*BkS=(PT31%B|Vu(5b$t;3#UiJi4Izyj9tv+h%nR*b5z}J31 z|C6;xG{9pdF*!q5agFw1@}Oce&z4{@(4+!K4K~53?Qm0^G!u%REV{ri&i{ zr(*_~_vx5Z(>1bB$DHnnHM#{mGR$cNP~_CcCRah1z#s3t&P(pR#%)A~;qs&B%$!S5 z~GZ`NSnpZgHEm1k(<@pWDPQj2aC8ct_enI3mc19C((Ab z1};mmha)JcvMS9MJCle{!HcVt55VO(Y!=y$<8ypyZxUy9su`Zjj3>h`(8|Hw~V7SLblmKm30~Uhciju`Ce%gTAX$ zawAJnheuw$LRiJDSG}}{<%}fR8|!KM%W^D97P~pTpCg6u2v$94AW0V61+veBB&%+$ zC$Jaq6k@}Or|Td9m+T*DHVDAwF)V#=P6ffTn`>|14+6ixbMINO?Dh!knzlFxbJ%F< SvfFzV?Dp+qel5=>zsf(^WoC*1 literal 0 HcmV?d00001 diff --git a/Source/Handles/Manipulators/BoldManipulators.res b/Source/Handles/Manipulators/BoldManipulators.res new file mode 100644 index 0000000000000000000000000000000000000000..d1baa5d0b408173625d1b52dfd57fd4c9bae2ba4 GIT binary patch literal 488 zcmaJ*J#RuW3_MVk!crw03`mR}`x8pVQi(5BuxB!Jr>avk_HAW*Kj%sPVc`^)&ND$OIwq|X8F zvOMR_-v>=w1~UeL4c1o8R`}jd2yaZ9eRsx-uwnf?B?+WP zzB12qa{Qo}9G|Lio5LEW*K$|x7c-&fKe>)KfT|JR(WV17sv7eDYpb`rMAJefC zgL#hQv@D3R=iJ@%^X2T*1Ar0TTJMCv%nX1T8Ea3lzzwEuM2o-xOSz94?WZ5yZD zO>j?l=fSRVc^dE)!FlHcczVP;KF+*np|H&rzzDi`_1=Vm^DR`bZJG{)Ivz{k@{x85Q|{ z@ycqgq~JRdlP@5V=XvJ&W!B=B7jJuhc);hL*BVe4EsxT&Psbax)8t)$5tmv;`LM3* zNEYCGvh{i$cZ0d^VMeE`;2;0dbw(|xcwih;?>W^zBAvrPF2CAfQkJH(74g@nTgLo_ S59*8F4!Z~Jb#8aZuk#Pq)f`6v literal 0 HcmV?d00001 diff --git a/Source/Persistence/SQLDirect/BoldDatabaseAdapterSQLDirect.pas b/Source/Persistence/SQLDirect/BoldDatabaseAdapterSQLDirect.pas index 8b7852e..91d45c4 100644 --- a/Source/Persistence/SQLDirect/BoldDatabaseAdapterSQLDirect.pas +++ b/Source/Persistence/SQLDirect/BoldDatabaseAdapterSQLDirect.pas @@ -50,7 +50,7 @@ implementation procedure TBoldDatabaseAdapterSQLDirect.CreateDatabase; begin - Assert(False, 'Not implemented.'); + DatabaseInterface.CreateDatabase; end; destructor TBoldDatabaseAdapterSQLDirect.Destroy; From 0cd38b84fc37b94b18e01982336daf1e64dd96d4 Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Tue, 4 May 2021 21:09:12 +0300 Subject: [PATCH 012/112] More missing resources --- .../BoldAwareGUI/FormGen/BoldAFPDefault.pas | 2 ++ .../BoldAwareGUI/FormGen/BoldAFPDefault.res | Bin 0 -> 476 bytes Source/Common/Logging/BoldLogForm.dfm | 19 +++++++++--------- .../UtilsGUI/BoldTypeNameSelector.pas | 1 + .../UtilsGUI/BoldTypeNameSelector.res | Bin 0 -> 3068 bytes .../Plugins/BoldUMLModelToEcoIIIGenerator.pas | 2 +- 6 files changed, 13 insertions(+), 11 deletions(-) create mode 100644 Source/BoldAwareGUI/FormGen/BoldAFPDefault.res create mode 100644 Source/ObjectSpace/UtilsGUI/BoldTypeNameSelector.res diff --git a/Source/BoldAwareGUI/FormGen/BoldAFPDefault.pas b/Source/BoldAwareGUI/FormGen/BoldAFPDefault.pas index 2d257d0..14bceef 100644 --- a/Source/BoldAwareGUI/FormGen/BoldAFPDefault.pas +++ b/Source/BoldAwareGUI/FormGen/BoldAFPDefault.pas @@ -206,6 +206,8 @@ TRoleMenu = class(TPopupMenu) implementation +{$R BoldAFPDefault.res} + uses SysUtils, Dialogs, diff --git a/Source/BoldAwareGUI/FormGen/BoldAFPDefault.res b/Source/BoldAwareGUI/FormGen/BoldAFPDefault.res new file mode 100644 index 0000000000000000000000000000000000000000..7239ab2954af2326d3e291a905d77f1af43ebfec GIT binary patch literal 476 zcmZXOJqiLb5QX20q_I&Ev=J;VJ%XZQsrb{UinWypg1Le>%FW`-PA0qRu#@@b6uadFwg0kSBprFyALpNI kJ&#S?elyElpvZ|;CO7V~n7a*%>>h7*IQMGt^i_@% literal 0 HcmV?d00001 diff --git a/Source/Common/Logging/BoldLogForm.dfm b/Source/Common/Logging/BoldLogForm.dfm index 6bb3c46..7d97f55 100644 --- a/Source/Common/Logging/BoldLogForm.dfm +++ b/Source/Common/Logging/BoldLogForm.dfm @@ -1,9 +1,9 @@ object BoldLogForm: TBoldLogForm Left = 477 Top = 234 - Width = 469 - Height = 347 Caption = 'Bold' + ClientHeight = 289 + ClientWidth = 453 Color = clBtnFace Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText @@ -38,15 +38,13 @@ object BoldLogForm: TBoldLogForm Menu = MainMenu1 OldCreateOrder = True Position = poScreenCenter - OnCreate = FormCreate - OnDestroy = FormDestroy PixelsPerInch = 96 TextHeight = 13 object Log: TRichEdit Left = 0 Top = 0 - Width = 461 - Height = 281 + Width = 453 + Height = 269 Align = alClient ReadOnly = True ScrollBars = ssBoth @@ -54,8 +52,8 @@ object BoldLogForm: TBoldLogForm end object Panel1: TPanel Left = 0 - Top = 281 - Width = 461 + Top = 269 + Width = 453 Height = 20 Align = alBottom BevelOuter = bvNone @@ -63,7 +61,7 @@ object BoldLogForm: TBoldLogForm object ProgressBar1: TProgressBar Left = 0 Top = 0 - Width = 461 + Width = 453 Height = 20 Align = alClient Step = 1 @@ -108,6 +106,7 @@ object BoldLogForm: TBoldLogForm end object mnuShowAll: TMenuItem Caption = 'Show all log' + Visible = False OnClick = mnuShowAllClick end end @@ -116,7 +115,7 @@ object BoldLogForm: TBoldLogForm Left = 44 Top = 8 Bitmap = { - 494C010103000400040010001000FFFFFFFFFF10FFFFFFFFFFFFFFFF424D3600 + 494C0101030004000C0010001000FFFFFFFFFF10FFFFFFFFFFFFFFFF424D3600 0000000000003600000028000000400000001000000001002000000000000010 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000 diff --git a/Source/ObjectSpace/UtilsGUI/BoldTypeNameSelector.pas b/Source/ObjectSpace/UtilsGUI/BoldTypeNameSelector.pas index d1d7277..8ec9e67 100644 --- a/Source/ObjectSpace/UtilsGUI/BoldTypeNameSelector.pas +++ b/Source/ObjectSpace/UtilsGUI/BoldTypeNameSelector.pas @@ -51,6 +51,7 @@ implementation BoldUtils; {$R *.dfm} +{$R BoldTypeNameSelector.res} { TfrmBoldTypeNameSelector } diff --git a/Source/ObjectSpace/UtilsGUI/BoldTypeNameSelector.res b/Source/ObjectSpace/UtilsGUI/BoldTypeNameSelector.res new file mode 100644 index 0000000000000000000000000000000000000000..391b0764eb417bdb98db03f64bbea9e36fef730f GIT binary patch literal 3068 zcmd5;&1(}u6n}oO8z`8q2R#Ym$zvc;FCJP=#6nDpNe|uv!tBLEHL#0S=u!{nmgbmi z{{o>GA(tF_EX_aBLl0%yLk=kh$KQK1Yqus=iv{z#?{nY0$^2&CY>9~OgS9pc^Bf(+ ztAMq>PIY=gEAT3`4yyvLQHjd1Uc#zTgPzbTBxkMJDh0ZCGcEWKhG+R2nQ#RE_JZN` z9YUZ;9*QEi!1#kP7!05}!atamHVV?LfwiT!(B}kcpj^@yx~y)GL!ma0|3cK!3;lkc zr$FI!s;p+rO5jSfvY~9FW55IvjwIg+k=V?KV59FB_8a^T4{3@gu@M zv2VvoekYyfr)I34{}HS59O0GVBvPdHnAb4I8DKZDZercUyiF+KtOTS158Tur1LquN z-UFs~f-`FJ^%%Q=3~k0?BF@ig&3OH;A6L+O4fNtF&el4t^1PlgUZbI!QKJK+_m3nn zs>b^qn8fkXkd0~_S6Gh_V66{hGjenyuGY4Y_0B8CYz;iCAEz;!)tN;9>mD1~rBnn5 zJ*k!?P>N4v#fKSSh8oF0s-}@#0Z>SuRI5Xc=H^ZzqT`Yk>c*ALkxBUJ}!6%+4BE-e($knK6`x#9;2pAy<)xgf2vPQiN`RiRKdp2@`yYyUSMr9{h4>EWzIh-3^zGAZQg3-w9jA zA~5K=t-a!-K=pQR^ovVM^%n2EUP4;$t{aAKpt|bg8z`>Bn(G|6Y`}kJ>+?L8egNwR BkJA7E literal 0 HcmV?d00001 diff --git a/Source/UMLModel/Plugins/BoldUMLModelToEcoIIIGenerator.pas b/Source/UMLModel/Plugins/BoldUMLModelToEcoIIIGenerator.pas index 363a933..7003c77 100644 --- a/Source/UMLModel/Plugins/BoldUMLModelToEcoIIIGenerator.pas +++ b/Source/UMLModel/Plugins/BoldUMLModelToEcoIIIGenerator.pas @@ -334,7 +334,7 @@ function TUMLModelToEcoIIIGenerator.GetImageMaskColor: TColor; // Resource for menu and button icon function TUMLModelToEcoIIIGenerator.GetImageResourceName: String; begin - result := 'EcoIII package file generator'; + result := 'UMLPluginExportImage'; end; // Caption for menu and hint for button From 7a52d89a82d1661f130b5764d8973ee945f67728 Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Tue, 4 May 2021 21:14:15 +0300 Subject: [PATCH 013/112] Added .rc to project resources --- Bold.dproj | 704 +++++++++++++++++++++++++++++++++++++++++++++++++ BoldOLLE.dproj | 704 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 1408 insertions(+) diff --git a/Bold.dproj b/Bold.dproj index 451b30a..aea33ff 100644 --- a/Bold.dproj +++ b/Bold.dproj @@ -416,6 +416,9 @@ + +
BoldManipulators.res
+
Cfg_2 Base @@ -445,9 +448,710 @@ True False + + + + Bold.bpl + true + + + + + 1 + + + 0 + + + + + classes + 1 + + + classes + 1 + + + + + res\xml + 1 + + + res\xml + 1 + + + + + library\lib\armeabi-v7a + 1 + + + + + library\lib\armeabi + 1 + + + library\lib\armeabi + 1 + + + + + library\lib\armeabi-v7a + 1 + + + + + library\lib\mips + 1 + + + library\lib\mips + 1 + + + + + library\lib\armeabi-v7a + 1 + + + library\lib\arm64-v8a + 1 + + + + + library\lib\armeabi-v7a + 1 + + + + + res\drawable + 1 + + + res\drawable + 1 + + + + + res\values + 1 + + + res\values + 1 + + + + + res\values-v21 + 1 + + + res\values-v21 + 1 + + + + + res\values + 1 + + + res\values + 1 + + + + + res\drawable + 1 + + + res\drawable + 1 + + + + + res\drawable-xxhdpi + 1 + + + res\drawable-xxhdpi + 1 + + + + + res\drawable-xxxhdpi + 1 + + + res\drawable-xxxhdpi + 1 + + + + + res\drawable-ldpi + 1 + + + res\drawable-ldpi + 1 + + + + + res\drawable-mdpi + 1 + + + res\drawable-mdpi + 1 + + + + + res\drawable-hdpi + 1 + + + res\drawable-hdpi + 1 + + + + + res\drawable-xhdpi + 1 + + + res\drawable-xhdpi + 1 + + + + + res\drawable-mdpi + 1 + + + res\drawable-mdpi + 1 + + + + + res\drawable-hdpi + 1 + + + res\drawable-hdpi + 1 + + + + + res\drawable-xhdpi + 1 + + + res\drawable-xhdpi + 1 + + + + + res\drawable-xxhdpi + 1 + + + res\drawable-xxhdpi + 1 + + + + + res\drawable-xxxhdpi + 1 + + + res\drawable-xxxhdpi + 1 + + + + + res\drawable-small + 1 + + + res\drawable-small + 1 + + + + + res\drawable-normal + 1 + + + res\drawable-normal + 1 + + + + + res\drawable-large + 1 + + + res\drawable-large + 1 + + + + + res\drawable-xlarge + 1 + + + res\drawable-xlarge + 1 + + + + + res\values + 1 + + + res\values + 1 + + + + + 1 + + + 1 + + + 0 + + + + + 1 + .framework + + + 1 + .framework + + + 0 + + + + + 1 + .dylib + + + 1 + .dylib + + + 0 + .dll;.bpl + + + + + 1 + .dylib + + + 1 + .dylib + + + 1 + .dylib + + + 1 + .dylib + + + 1 + .dylib + + + 0 + .bpl + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + 1 + + + 1 + + + + + ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF + 1 + + + ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF + 1 + + + + + + + + 1 + + + 1 + + + 1 + + + + + + + + Contents\Resources + 1 + + + Contents\Resources + 1 + + + + + library\lib\armeabi-v7a + 1 + + + library\lib\arm64-v8a + 1 + + + 1 + + + 1 + + + 1 + + + 1 + + + 1 + + + 1 + + + 0 + + + + + library\lib\armeabi-v7a + 1 + + + + + 1 + + + 1 + + + + + Assets + 1 + + + Assets + 1 + + + + + Assets + 1 + + + Assets + 1 + + + + + + + + + + + + + 12 + diff --git a/BoldOLLE.dproj b/BoldOLLE.dproj index 533e84e..8aa157f 100644 --- a/BoldOLLE.dproj +++ b/BoldOLLE.dproj @@ -97,6 +97,9 @@ + +
BoldOLLEHandles.res
+
Cfg_2 Base @@ -126,9 +129,710 @@ True False + + + + BoldOLLE.bpl + true + + + + + 1 + + + 0 + + + + + classes + 1 + + + classes + 1 + + + + + res\xml + 1 + + + res\xml + 1 + + + + + library\lib\armeabi-v7a + 1 + + + + + library\lib\armeabi + 1 + + + library\lib\armeabi + 1 + + + + + library\lib\armeabi-v7a + 1 + + + + + library\lib\mips + 1 + + + library\lib\mips + 1 + + + + + library\lib\armeabi-v7a + 1 + + + library\lib\arm64-v8a + 1 + + + + + library\lib\armeabi-v7a + 1 + + + + + res\drawable + 1 + + + res\drawable + 1 + + + + + res\values + 1 + + + res\values + 1 + + + + + res\values-v21 + 1 + + + res\values-v21 + 1 + + + + + res\values + 1 + + + res\values + 1 + + + + + res\drawable + 1 + + + res\drawable + 1 + + + + + res\drawable-xxhdpi + 1 + + + res\drawable-xxhdpi + 1 + + + + + res\drawable-xxxhdpi + 1 + + + res\drawable-xxxhdpi + 1 + + + + + res\drawable-ldpi + 1 + + + res\drawable-ldpi + 1 + + + + + res\drawable-mdpi + 1 + + + res\drawable-mdpi + 1 + + + + + res\drawable-hdpi + 1 + + + res\drawable-hdpi + 1 + + + + + res\drawable-xhdpi + 1 + + + res\drawable-xhdpi + 1 + + + + + res\drawable-mdpi + 1 + + + res\drawable-mdpi + 1 + + + + + res\drawable-hdpi + 1 + + + res\drawable-hdpi + 1 + + + + + res\drawable-xhdpi + 1 + + + res\drawable-xhdpi + 1 + + + + + res\drawable-xxhdpi + 1 + + + res\drawable-xxhdpi + 1 + + + + + res\drawable-xxxhdpi + 1 + + + res\drawable-xxxhdpi + 1 + + + + + res\drawable-small + 1 + + + res\drawable-small + 1 + + + + + res\drawable-normal + 1 + + + res\drawable-normal + 1 + + + + + res\drawable-large + 1 + + + res\drawable-large + 1 + + + + + res\drawable-xlarge + 1 + + + res\drawable-xlarge + 1 + + + + + res\values + 1 + + + res\values + 1 + + + + + 1 + + + 1 + + + 0 + + + + + 1 + .framework + + + 1 + .framework + + + 0 + + + + + 1 + .dylib + + + 1 + .dylib + + + 0 + .dll;.bpl + + + + + 1 + .dylib + + + 1 + .dylib + + + 1 + .dylib + + + 1 + .dylib + + + 1 + .dylib + + + 0 + .bpl + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + 1 + + + 1 + + + + + ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF + 1 + + + ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF + 1 + + + + + + + + 1 + + + 1 + + + 1 + + + + + + + + Contents\Resources + 1 + + + Contents\Resources + 1 + + + + + library\lib\armeabi-v7a + 1 + + + library\lib\arm64-v8a + 1 + + + 1 + + + 1 + + + 1 + + + 1 + + + 1 + + + 1 + + + 0 + + + + + library\lib\armeabi-v7a + 1 + + + + + 1 + + + 1 + + + + + Assets + 1 + + + Assets + 1 + + + + + Assets + 1 + + + Assets + 1 + + + + + + + + + + + + + 12 + From f58a6f5b34f82f1ae947c45d9ede4a66d2527acd Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Wed, 5 May 2021 03:25:20 +0300 Subject: [PATCH 014/112] Added BoldUniDac Package --- BoldUniDAC.dpk | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 BoldUniDAC.dpk diff --git a/BoldUniDAC.dpk b/BoldUniDAC.dpk new file mode 100644 index 0000000..4a5296d --- /dev/null +++ b/BoldUniDAC.dpk @@ -0,0 +1,46 @@ +package BoldUniDAC; + +{$R *.res} +{$IFDEF IMPLICITBUILDING This IFDEF should not be used by users} +{$ALIGN 8} +{$ASSERTIONS ON} +{$BOOLEVAL OFF} +{$DEBUGINFO OFF} +{$EXTENDEDSYNTAX ON} +{$IMPORTEDDATA ON} +{$IOCHECKS ON} +{$LOCALSYMBOLS ON} +{$LONGSTRINGS ON} +{$OPENSTRINGS ON} +{$OPTIMIZATION OFF} +{$OVERFLOWCHECKS OFF} +{$RANGECHECKS OFF} +{$REFERENCEINFO ON} +{$SAFEDIVIDE OFF} +{$STACKFRAMES ON} +{$TYPEDADDRESS OFF} +{$VARSTRINGCHECKS ON} +{$WRITEABLECONST OFF} +{$MINENUMSIZE 1} +{$IMAGEBASE $400000} +{$DEFINE DEBUG} +{$ENDIF IMPLICITBUILDING} +{$DESCRIPTION 'Bold 4.0 for Delphi (UniDAC Support)'} +{$DESIGNONLY} +{$IMPLICITBUILD ON} + +requires + rtl, + vcldb, + ibxpress, + DesignIDE, + Bold; + +contains + BoldPersistenceHandleUniDACReg in 'Source\Persistence\UniDAC\BoldPersistenceHandleUniDACReg.pas', + BoldUniDACInterfaces in 'Source\Persistence\UniDAC\BoldUniDACInterfaces.pas', + UniDACConsts in 'Source\Persistence\UniDAC\UniDACConsts.pas', + BoldDatabaseAdapterUniDAC in 'Source\Persistence\UniDAC\BoldDatabaseAdapterUniDAC.pas', + BoldPersistenceHandleUniDAC in 'Source\Persistence\UniDAC\BoldPersistenceHandleUniDAC.pas'; + +end. From 7f615b62987fa1c5d980379654304f563e17bf28 Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Thu, 6 May 2021 16:35:47 +0300 Subject: [PATCH 015/112] Now using TPerlRegEx.EscapeRegExChars for escaping --- Source/ObjectSpace/Ocl/BoldOclSymbolImplementations.pas | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/ObjectSpace/Ocl/BoldOclSymbolImplementations.pas b/Source/ObjectSpace/Ocl/BoldOclSymbolImplementations.pas index 74c8614..db2944d 100644 --- a/Source/ObjectSpace/Ocl/BoldOclSymbolImplementations.pas +++ b/Source/ObjectSpace/Ocl/BoldOclSymbolImplementations.pas @@ -30,6 +30,7 @@ implementation BoldSubscription, BoldValueSpaceInterfaces, System.RegularExpressions, + System.RegularExpressionsCore, BoldIsoDateTime; var @@ -3043,8 +3044,7 @@ procedure TBOS_AllSubClasses.Evaluate(const Params: TBoldOclSymbolParameters); function EscapeRegEx(const ASource: string): string; begin - result := StringReplace(ASource, '[', '\[', [rfReplaceAll]); - result := StringReplace(result, '%', '', [rfReplaceAll]); + result := TPerlRegEx.EscapeRegExChars(ASource); end; procedure TBOS_SQLLike.Evaluate(const Params: TBoldOclSymbolParameters); From c96df5cdb66dee519b7388e833dac339fabb0eec Mon Sep 17 00:00:00 2001 From: Roland Bengtsson Date: Wed, 12 May 2021 08:02:10 +0300 Subject: [PATCH 016/112] #8 % char is now removed for SQLLike as TRegEx works different than original BoldRegularExpression unit. Sync codechanges from Attracs --- .../Ocl/BoldOclSymbolImplementations.pas | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/Source/ObjectSpace/Ocl/BoldOclSymbolImplementations.pas b/Source/ObjectSpace/Ocl/BoldOclSymbolImplementations.pas index db2944d..c86cd64 100644 --- a/Source/ObjectSpace/Ocl/BoldOclSymbolImplementations.pas +++ b/Source/ObjectSpace/Ocl/BoldOclSymbolImplementations.pas @@ -3044,7 +3044,8 @@ procedure TBOS_AllSubClasses.Evaluate(const Params: TBoldOclSymbolParameters); function EscapeRegEx(const ASource: string): string; begin - result := TPerlRegEx.EscapeRegExChars(ASource); + result := StringReplace(ASource, '%', '', [rfReplaceAll]); + result := TPerlRegEx.EscapeRegExChars(result); end; procedure TBOS_SQLLike.Evaluate(const Params: TBoldOclSymbolParameters); @@ -3053,7 +3054,10 @@ procedure TBOS_SQLLike.Evaluate(const Params: TBoldOclSymbolParameters); begin s := XString(Params.values[1]); s := EscapeRegEx(s); - Help.MakeNewBoolean(Params.Result, TRegEx.IsMatch(XString(Params.values[0]), s)); + if s = '' then + Help.MakeNewBoolean(Params.Result, false) + else + Help.MakeNewBoolean(Params.Result, TRegEx.IsMatch(XString(Params.values[0]), s)); end; procedure TBOS_SQLLikeCaseInSensitive.Evaluate(const Params: TBoldOclSymbolParameters); @@ -3062,7 +3066,10 @@ procedure TBOS_SQLLikeCaseInSensitive.Evaluate(const Params: TBoldOclSymbolParam begin s := XString(Params.values[1]); s := EscapeRegEx(s); - Help.MakeNewBoolean(Params.Result, TRegEx.IsMatch(XString(Params.values[0]), s, [roIgnoreCase])); + if s = '' then + Help.MakeNewBoolean(Params.Result, false) + else + Help.MakeNewBoolean(Params.Result, TRegEx.IsMatch(XString(Params.values[0]), s, [roIgnoreCase])); end; procedure TBOS_RegExpMatch.Evaluate(const Params: TBoldOclSymbolParameters); From e71bb4454ebb7d0315dbddaf2a69d91aca692458 Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Mon, 17 May 2021 19:53:13 +0300 Subject: [PATCH 017/112] Removed conditional UseSynCommons --- Source/Persistence/DB/BoldDBInterfaces.pas | 23 ---------------------- 1 file changed, 23 deletions(-) diff --git a/Source/Persistence/DB/BoldDBInterfaces.pas b/Source/Persistence/DB/BoldDBInterfaces.pas index c5b92e7..bb0c9cc 100644 --- a/Source/Persistence/DB/BoldDBInterfaces.pas +++ b/Source/Persistence/DB/BoldDBInterfaces.pas @@ -450,11 +450,7 @@ TBoldBatchDataSetWrapper = class(TBoldDataSetWrapper) FInBatch: Boolean; fAccumulatedSQLLength: integer; fParamsInBeginUpdate: Boolean; - {$IFDEF UseSynCommons} - SB: SynCommons.TTextWriter; - {$ELSE} SB: TStringBuilder; - {$ENDIF} function GetAccumulatedSQL: TStrings; function GetHasCachedStatements: boolean; procedure ReplaceParamMarkers(sql: TStrings; const Source, Dest: IBoldExecQuery); @@ -1673,11 +1669,7 @@ procedure TBoldBatchDataSetWrapper.ReplaceParamMarkers(sql: TStrings; procedure AddLine(const s: string); begin - {$IFDEF UseSynCommons} - SB.AddString(SynCommons.StringReplaceAll(RawUTF8(s), BOLDCRLF, ' ')); - {$ELSE} sb.Append(StringReplace(s, BOLDCRLF, ' ', [rfReplaceAll])); - {$ENDIF} end; begin @@ -1741,11 +1733,7 @@ procedure TBoldBatchDataSetWrapper.ReplaceParamMarkers(sql: TStrings; NewParam.Name := NewParamName; AddLine(Copy(Line, PrevPos, StartPos-PrevPos+1)); PrevPos := CurPos; - {$IFDEF UseSynCommons} - SB.AddString(RawUTF8(NewParamName)); - {$ELSE} SB.Append(NewParamName); - {$ENDIF} inc(ParamIndex); end else @@ -1758,17 +1746,10 @@ procedure TBoldBatchDataSetWrapper.ReplaceParamMarkers(sql: TStrings; end; end; end; - {$IFDEF UseSynCommons} - SB.AddString(RawUTF8(DatabaseWrapper.SQLDatabaseConfig.BatchQuerySeparator)); - Inc(fAccumulatedSQLLength, Integer(sb.TextLength) + Length(Dest.SQLStrings.LineBreak)); - Dest.SQLStrings.Add(String(sb.text)); - sb.CancelAll; - {$ELSE} SB.Append(DatabaseWrapper.SQLDatabaseConfig.BatchQuerySeparator); Dest.SQLStrings.Add(sb.ToString); Inc(fAccumulatedSQLLength, SB.Length + Length(Dest.SQLStrings.LineBreak)); SB.Clear; - {$ENDIF} end; function TBoldBatchDataSetWrapper.GetHasCachedStatements: boolean; @@ -1853,11 +1834,7 @@ constructor TBoldBatchDataSetWrapper.Create( DatabaseWrapper: TBoldDatabaseWrapper); begin inherited Create(DatabaseWrapper); - {$IFDEF UseSynCommons} - SB := SynCommons.TTextWriter.CreateOwnedStream(cInitialBatchBufferSize); - {$ELSE} SB := TStringBuilder.Create(cInitialBatchBufferSize); - {$ENDIF} end; destructor TBoldBatchDataSetWrapper.Destroy; From 310fa6ddc5fbc370a97ec1559a747a9913b5fb93 Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Mon, 17 May 2021 19:55:17 +0300 Subject: [PATCH 018/112] Added FireDac support --- BoldFireDAC.dpk | 46 + BoldFireDAC.dproj | 856 +++++++++ .../FireDAC/BoldDatabaseAdapterFireDAC.pas | 89 + .../Persistence/FireDAC/BoldFireDACConsts.pas | 18 + .../FireDAC/BoldFireDACInterfaces.pas | 1656 +++++++++++++++++ .../FireDAC/BoldPersistenceHandleFireDAC.pas | 334 ++++ .../BoldPersistenceHandleFireDACReg.pas | 28 + 7 files changed, 3027 insertions(+) create mode 100644 BoldFireDAC.dpk create mode 100644 BoldFireDAC.dproj create mode 100644 Source/Persistence/FireDAC/BoldDatabaseAdapterFireDAC.pas create mode 100644 Source/Persistence/FireDAC/BoldFireDACConsts.pas create mode 100644 Source/Persistence/FireDAC/BoldFireDACInterfaces.pas create mode 100644 Source/Persistence/FireDAC/BoldPersistenceHandleFireDAC.pas create mode 100644 Source/Persistence/FireDAC/BoldPersistenceHandleFireDACReg.pas diff --git a/BoldFireDAC.dpk b/BoldFireDAC.dpk new file mode 100644 index 0000000..455b3ff --- /dev/null +++ b/BoldFireDAC.dpk @@ -0,0 +1,46 @@ +package BoldFireDAC; + +{$R *.res} +{$IFDEF IMPLICITBUILDING This IFDEF should not be used by users} +{$ALIGN 8} +{$ASSERTIONS ON} +{$BOOLEVAL OFF} +{$DEBUGINFO OFF} +{$EXTENDEDSYNTAX ON} +{$IMPORTEDDATA ON} +{$IOCHECKS ON} +{$LOCALSYMBOLS ON} +{$LONGSTRINGS ON} +{$OPENSTRINGS ON} +{$OPTIMIZATION OFF} +{$OVERFLOWCHECKS OFF} +{$RANGECHECKS OFF} +{$REFERENCEINFO ON} +{$SAFEDIVIDE OFF} +{$STACKFRAMES ON} +{$TYPEDADDRESS OFF} +{$VARSTRINGCHECKS ON} +{$WRITEABLECONST OFF} +{$MINENUMSIZE 1} +{$IMAGEBASE $400000} +{$DEFINE DEBUG} +{$ENDIF IMPLICITBUILDING} +{$DESCRIPTION 'Bold 4.0 for Delphi (FireDAC Support)'} +{$DESIGNONLY} +{$IMPLICITBUILD ON} + +requires + rtl, + vcldb, + FireDAC, + DesignIDE, + Bold; + +contains + BoldPersistenceHandleFireDAC in 'Source\Persistence\FireDAC\BoldPersistenceHandleFireDAC.pas', + BoldPersistenceHandleFireDACReg in 'Source\Persistence\FireDAC\BoldPersistenceHandleFireDACReg.pas', + BoldDatabaseAdapterFireDAC in 'Source\Persistence\FireDAC\BoldDatabaseAdapterFireDAC.pas', + BoldFireDACInterfaces in 'Source\Persistence\FireDAC\BoldFireDACInterfaces.pas', + BoldFireDACConsts in 'Source\Persistence\FireDAC\BoldFireDACConsts.pas'; + +end. diff --git a/BoldFireDAC.dproj b/BoldFireDAC.dproj new file mode 100644 index 0000000..841188e --- /dev/null +++ b/BoldFireDAC.dproj @@ -0,0 +1,856 @@ + + + {34E63FCA-EC80-4315-BAF9-24523C7226CD} + BoldFireDAC.dpk + 19.2 + None + True + Debug + Win32 + 1 + Package + + + true + + + true + Base + true + + + true + Base + true + + + true + Base + true + + + true + Cfg_1 + true + true + + + true + Base + true + + + .\$(Platform)\$(Config) + .\$(Platform)\$(Config) + false + false + false + false + false + true + true + Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;System;Xml;Data;Datasnap;Web;Soap;Winapi;$(DCC_Namespace) + All + BoldFireDAC + $(BoldDelphi)\Source\Common\Include;$(BDS)\Source\data\firedac;$(DCC_UnitSearchPath) + 2077 + CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments= + Bold 4.0 for Delphi (FireDAC Support) + true + + + System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) + Debug + true + CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments= + 1033 + rtl;vcldb;FireDAC;$(DCC_UsePackage) + + + rtl;vcldb;FireDAC;$(DCC_UsePackage) + + + DEBUG;$(DCC_Define) + true + false + true + true + true + + + false + true + 1033 + + + false + RELEASE;$(DCC_Define) + 0 + 0 + + + + MainSource + + + + + + + + + + + + + Cfg_2 + Base + + + Base + + + Cfg_1 + Base + + + + Delphi.Personality.12 + Package + + + + BoldFireDAC.dpk + + + Attracs Components for Delphi 10.4 Sydney + Microsoft Office 2000 Sample Automation Server Wrapper Components + Microsoft Office XP Sample Automation Server Wrapper Components + + + + + + true + + + + + true + + + + + true + + + + + BoldFireDAC.bpl + true + + + + + 1 + + + 0 + + + + + classes + 1 + + + classes + 1 + + + + + res\xml + 1 + + + res\xml + 1 + + + + + library\lib\armeabi-v7a + 1 + + + + + library\lib\armeabi + 1 + + + library\lib\armeabi + 1 + + + + + library\lib\armeabi-v7a + 1 + + + + + library\lib\mips + 1 + + + library\lib\mips + 1 + + + + + library\lib\armeabi-v7a + 1 + + + library\lib\arm64-v8a + 1 + + + + + library\lib\armeabi-v7a + 1 + + + + + res\drawable + 1 + + + res\drawable + 1 + + + + + res\values + 1 + + + res\values + 1 + + + + + res\values-v21 + 1 + + + res\values-v21 + 1 + + + + + res\values + 1 + + + res\values + 1 + + + + + res\drawable + 1 + + + res\drawable + 1 + + + + + res\drawable-xxhdpi + 1 + + + res\drawable-xxhdpi + 1 + + + + + res\drawable-xxxhdpi + 1 + + + res\drawable-xxxhdpi + 1 + + + + + res\drawable-ldpi + 1 + + + res\drawable-ldpi + 1 + + + + + res\drawable-mdpi + 1 + + + res\drawable-mdpi + 1 + + + + + res\drawable-hdpi + 1 + + + res\drawable-hdpi + 1 + + + + + res\drawable-xhdpi + 1 + + + res\drawable-xhdpi + 1 + + + + + res\drawable-mdpi + 1 + + + res\drawable-mdpi + 1 + + + + + res\drawable-hdpi + 1 + + + res\drawable-hdpi + 1 + + + + + res\drawable-xhdpi + 1 + + + res\drawable-xhdpi + 1 + + + + + res\drawable-xxhdpi + 1 + + + res\drawable-xxhdpi + 1 + + + + + res\drawable-xxxhdpi + 1 + + + res\drawable-xxxhdpi + 1 + + + + + res\drawable-small + 1 + + + res\drawable-small + 1 + + + + + res\drawable-normal + 1 + + + res\drawable-normal + 1 + + + + + res\drawable-large + 1 + + + res\drawable-large + 1 + + + + + res\drawable-xlarge + 1 + + + res\drawable-xlarge + 1 + + + + + res\values + 1 + + + res\values + 1 + + + + + 1 + + + 1 + + + 0 + + + + + 1 + .framework + + + 1 + .framework + + + 0 + + + + + 1 + .dylib + + + 1 + .dylib + + + 0 + .dll;.bpl + + + + + 1 + .dylib + + + 1 + .dylib + + + 1 + .dylib + + + 1 + .dylib + + + 1 + .dylib + + + 0 + .bpl + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + 1 + + + 1 + + + + + ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF + 1 + + + ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF + 1 + + + + + + + + 1 + + + 1 + + + 1 + + + + + + + + Contents\Resources + 1 + + + Contents\Resources + 1 + + + + + library\lib\armeabi-v7a + 1 + + + library\lib\arm64-v8a + 1 + + + 1 + + + 1 + + + 1 + + + 1 + + + 1 + + + 1 + + + 0 + + + + + library\lib\armeabi-v7a + 1 + + + + + 1 + + + 1 + + + + + Assets + 1 + + + Assets + 1 + + + + + Assets + 1 + + + Assets + 1 + + + + + + + + + + + + + + + True + False + + + 12 + + + + + diff --git a/Source/Persistence/FireDAC/BoldDatabaseAdapterFireDAC.pas b/Source/Persistence/FireDAC/BoldDatabaseAdapterFireDAC.pas new file mode 100644 index 0000000..3e7ba0c --- /dev/null +++ b/Source/Persistence/FireDAC/BoldDatabaseAdapterFireDAC.pas @@ -0,0 +1,89 @@ +{ Global compiler directives } +{$include bold.inc} +unit BoldDatabaseAdapterFireDAC; + +interface + +uses + Classes, + BoldAbstractDataBaseAdapter, + BoldDBInterfaces, + BoldFireDACInterfaces, + FireDAC.Comp.Client; + +type + { forward declarations } + TBoldDatabaseAdapterFireDAC = class; + + { TBoldDatabaseAdapterFireDAC } + TBoldDatabaseAdapterFireDAC = class(TBoldAbstractDatabaseAdapter) + private + fBoldFireDACConnection: TBoldFireDACConnection; + procedure SetConnection(const Value: TFDConnection); + function GetConnection: TFDConnection; + protected + procedure ReleaseBoldDatabase; override; + function GetDataBaseInterface: IBoldDatabase; override; + public + destructor Destroy; override; + procedure CreateDatabase; override; + published + property Connection: TFDConnection read GetConnection write SetConnection; + {$IFNDEF T2H} + property DatabaseEngine; + {$ENDIF} + end; + +implementation + +uses + BoldSQLDatabaseConfig, + SysUtils, + BoldDefs, + BoldFireDACConsts; + +{ TBoldDatabaseAdapterFireDAC } + +destructor TBoldDatabaseAdapterFireDAC.Destroy; +begin + Changed; + FreePublisher; + FreeAndNil(fBoldFireDACConnection); + inherited; +end; + +procedure TBoldDatabaseAdapterFireDAC.CreateDatabase; +begin + DatabaseInterface.CreateDatabase; +end; + +function TBoldDatabaseAdapterFireDAC.GetConnection: TFDConnection; +begin + Result := InternalDatabase as TFDConnection; +end; + +function TBoldDatabaseAdapterFireDAC.GetDataBaseInterface: IBoldDatabase; +begin + if not Assigned(Connection) then + begin + raise EBold.CreateFmt(sAdapterNotConnected, [ClassName]); + end; + if not Assigned(fBoldFireDACConnection) then + begin + fBoldFireDACConnection := TBoldFireDACConnection.Create(Connection, SQLDataBaseConfig); + end; + Result := fBoldFireDACConnection; +end; + +procedure TBoldDatabaseAdapterFireDAC.ReleaseBoldDatabase; +begin + FreeAndNil(fBoldFireDACConnection); +end; + +procedure TBoldDatabaseAdapterFireDAC.SetConnection(const Value: TFDConnection); +begin + InternalDatabase := Value; +end; + +end. + diff --git a/Source/Persistence/FireDAC/BoldFireDACConsts.pas b/Source/Persistence/FireDAC/BoldFireDACConsts.pas new file mode 100644 index 0000000..d7c84d5 --- /dev/null +++ b/Source/Persistence/FireDAC/BoldFireDACConsts.pas @@ -0,0 +1,18 @@ +{ Global compiler directives } +{$include bold.inc} +unit BoldFireDACConsts; + +interface + +resourcestring +//BoldDatabaseAdapterFireDAC + sAdapterNotConnected = '%s.GetDatabaseInterface: The adapter is not connected to an FireDAC connection'; + sCreatedNewAdapter = 'Created a new DatabaseAdapterFireDAC'; + sCanOnlyTransferToFireDACAdapter = 'The persistencehandle is connected to a %s, properties can only be transfered to a TBoldDatabaseAdapterFireDAC'; + sCreatedNewDB = 'Created a new FireDACDatabase'; + sCouldNotTransferConnectionString = 'Connection string settings could not be transferred to the new FireDAC connection: '; + sTransferManually = 'Please transfer these manually!'; + +implementation + +end. diff --git a/Source/Persistence/FireDAC/BoldFireDACInterfaces.pas b/Source/Persistence/FireDAC/BoldFireDACInterfaces.pas new file mode 100644 index 0000000..ef76516 --- /dev/null +++ b/Source/Persistence/FireDAC/BoldFireDACInterfaces.pas @@ -0,0 +1,1656 @@ + +///////////////////////////////////////////////////////// +// // +// Bold for Delphi // +// Copyright (c) 1996-2002 Boldsoft AB // +// (c) 2002-2005 Borland Software Corp // +// // +///////////////////////////////////////////////////////// + +{ Global compiler directives } +{$include bold.inc} +unit BoldFireDACInterfaces; + +interface + +uses + Classes, + Db, + SysUtils, + + FireDAC.Comp.Client, + FireDAC.Stan.Param, + + BoldSQLDatabaseConfig, + BoldDBInterfaces, + BoldDefs; + +type + { forward declarations } + TBoldFireDACParameter = class; + TBoldFireDACQuery = class; + TBoldFireDACTable = class; + TBoldFireDACConnection = class; + + TFireDacParam = TFDParam; + + TBoldFireDACQueryClass = class of TBoldFireDACQuery; + TBoldFireDACExecQueryClass = class of TBoldFireDACExecQuery; + + { TBoldFireDACParameter } + TBoldFireDACParameter = class(TBoldParameterWrapper, IBoldParameter) + private + fFDParam: TFireDacParam; + function GetAsVariant: Variant; + procedure SetAsVariant(const NewValue: Variant); + function GetName: string; + procedure Clear; + function GetDataType: TFieldType; + procedure SetDataType(Value: TFieldType); + function GetAsBCD: Currency; + function GetAsblob: TBoldBlobData; + function GetAsBoolean: Boolean; + function GetAsDateTime: TDateTime; + function GetAsCurrency: Currency; + function GetAsFloat: Double; + function GetAsInteger: Longint; + function GetAsInt64: Int64; + function GetAsMemo: string; + function GetAsString: string; + function GetIsNull: Boolean; + function GetAsWideString: WideString; + procedure SetAsBCD(const Value: Currency); + procedure SetAsBlob(const Value: TBoldBlobData); + procedure SetAsBoolean(Value: Boolean); + procedure SetAsCurrency(const Value: Currency); + procedure SetAsDate(const Value: TDateTime); + procedure SetAsDateTime(const Value: TDateTime); + procedure SetAsFloat(const Value: Double); + procedure SetAsInteger(Value: Longint); + procedure SetAsInt64(const Value: Int64); + procedure SetAsMemo(const Value: string); + procedure SetAsString(const Value: string); + procedure SetAsSmallInt(Value: Longint); + procedure SetAsTime(const Value: TDateTime); + procedure SetAsWord(Value: Longint); + procedure SetText(const Value: string); + procedure SetAsWideString(const Value: Widestring); + function GetAsAnsiString: TBoldAnsiString; + procedure SetAsAnsiString(const Value: TBoldAnsiString); + function GetFDParam: TFireDacParam; + procedure AssignFieldValue(const source: IBoldField); + procedure Assign(const source: IBoldParameter); + property FDParam: TFireDacParam read GetFDParam; + public + constructor Create(FireDACParameter: TFireDacParam; DatasetWrapper: TBoldAbstractQueryWrapper); + end; + + { TBoldFireDACQuery } + TBoldFireDACQuery = class(TBoldBatchDataSetWrapper, IBoldQuery, IBoldExecQuery, IBoldParameterized) + private + fQuery: TFDQuery; + fReadTransactionStarted: Boolean; + fUseReadTransactions: boolean; + function GetQuery: TFDQuery; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure AssignParams(Sourceparams: TParams); + function GetParamCount: Integer; + function GetParam(i: Integer): IBoldParameter; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetParamCheck: Boolean; + procedure SetParamCheck(value: Boolean); + function GetRequestLiveQuery: Boolean; + function ParamByName(const Value: string): IBoldParameter; override; + function FindParam(const Value: string): IBoldParameter; override; + function Createparam(FldType: TFieldType; const ParamName: string; ParamType: TParamType; Size: integer): IBoldParameter; override; + procedure SetRequestLiveQuery(NewValue: Boolean); + procedure AssignSQL(SQL: TStrings); virtual; + function GetSQLStrings: TStrings; override; + function GetRecordCount: Integer; + function GetUseReadTransactions: boolean; + procedure SetUseReadTransactions(value: boolean); + procedure BeginExecuteQuery; + procedure EndExecuteQuery; + protected + function GetParams: TParams; override; + function GetSqlText: string; override; + procedure AssignSQLText(const SQL: string); override; + function GetRowsAffected: Integer; + function GetDataSet: TDataSet; override; + procedure ClearParams; + procedure Open; override; + procedure Close; override; + procedure ExecSQL; override; + function GetRecNo: integer; override; + property Query: TFDQuery read GetQuery; + public + constructor Create(BoldFireDACConnection: TBoldFireDACConnection); reintroduce; + destructor Destroy; override; + procedure Clear; override; + end; + + { TBoldFireDACQuery } + TBoldFireDACExecQuery = class(TBoldAbstractQueryWrapper, IBoldExecQuery, IBoldParameterized) + private + fExecQuery: TFDQuery; + fReadTransactionStarted: Boolean; + fUseReadTransactions: boolean; + function GetExecQuery: TFDQuery; + function GetParams: TParams; + procedure AssignParams(Sourceparams: TParams); + function GetParamCount: Integer; + function GetParam(i: Integer): IBoldParameter; + function GetParamCheck: Boolean; + procedure SetParamCheck(value: Boolean); + function ParamByName(const Value: string): IBoldParameter; + function FindParam(const Value: string): IBoldParameter; + function Createparam(FldType: TFieldType; const ParamName: string): IBoldParameter; overload; + function CreateParam(FldType: TFieldType; const ParamName: string; ParamType: TParamType; Size: integer): IBoldParameter; overload; + function EnsureParamByName(const Value: string): IBoldParameter; + function GetSQLText: string; + function GetSQLStrings: TStrings; + procedure AssignSQL(SQL: TStrings); virtual; + procedure AssignSQLText(const SQL: string); + function GetRowsAffected: Integer; + function GetUseReadTransactions: boolean; + procedure SetUseReadTransactions(value: boolean); + procedure BeginExecuteQuery; + procedure EndExecuteQuery; + function GetBatchQueryParamCount: integer; +// procedure Prepare; + protected + procedure StartSQLBatch; virtual; + procedure EndSQLBatch; virtual; + procedure FailSQLBatch; virtual; + procedure ClearParams; + procedure ExecSQL; virtual; + property ExecQuery: TFDQuery read GetExecQuery; + public + constructor Create(BoldFireDACConnection: TBoldFireDACConnection); reintroduce; + destructor Destroy; override; + procedure Clear; override; + end; + + { TBoldFireDACTable } + TBoldFireDACTable = class(TBoldDatasetWrapper, IBoldTable) + private + fFDTable: TFDTable; + function GetFDTable: TFDTable; + property FDTable: TFDTable read GetFDTable; + procedure AddIndex(const Name, Fields: string; Options: TIndexOptions; const DescFields: string = ''); + procedure CreateTable; + procedure DeleteTable; + function GetIndexDefs: TIndexDefs; + procedure SetTableName(const NewName: string); + function GetTableName: string; + procedure SetExclusive(NewValue: Boolean); + function GetExclusive: Boolean; + function GetExists: Boolean; +// function GetCommaListOfIndexesForColumn(const aColumnName: string): string; +// function GetPrimaryIndex: string; + protected + function GetDefaultConstraintNameForColumn(const aColumnName: string): string; {override;} + function GetDataSet: TDataSet; override; + function ParamByName(const Value: string): IBoldParameter; override; + function FindParam(const Value: string): IBoldParameter; override; + public + constructor Create(aFDTable: TFDTable; BoldFireDACConnection: TBoldFireDACConnection); reintroduce; + end; + + { TBoldFireDACConnection } + TBoldFireDACConnection = class(TBoldDatabaseWrapper, IBoldDataBase) + fFDConnection: TFDConnection; + fCachedTable: TBoldFireDACTable; + fCachedQuery1: TBoldFireDACQuery; + fCachedQuery2: TBoldFireDACQuery; + fCachedExecQuery1: TBoldFireDACQuery; + fExecuteQueryCount: integer; + function GetFDConnection: TFDConnection; + property FDConnection: TFDConnection read GetFDConnection; + function GetConnected: Boolean; + function GetInTransaction: Boolean; + function GetIsSQLBased: Boolean; + procedure SetlogInPrompt(NewValue: Boolean); + function GetLogInPrompt: Boolean; + procedure SetKeepConnection(NewValue: Boolean); + function GetKeepConnection: Boolean; + procedure StartTransaction; + procedure StartReadTransaction; + procedure Commit; + procedure RollBack; + procedure Open; + procedure Close; + procedure Reconnect; + function SupportsTableCreation: Boolean; + procedure ReleaseCachedObjects; + function GetIsExecutingQuery: Boolean; + procedure BeginExecuteQuery; + procedure EndExecuteQuery; + private + function GetTransaction: TFDTransaction; + function GetUpdateTransaction: TFDTransaction; + procedure SetTransaction(const Value: TFDTransaction); + procedure SetUpdateTransaction(const Value: TFDTransaction); + protected + procedure AllTableNames(Pattern: string; ShowSystemTables: Boolean; TableNameList: TStrings); override; + function GetTable: IBoldTable; override; + function GetQuery: IBoldQuery; override; + function GetExecQuery: IBoldExecQuery; override; + procedure ReleaseTable(var Table: IBoldTable); override; + procedure ReleaseQuery(var Query: IBoldQuery); override; + procedure ReleaseExecQuery(var Query: IBoldExecQuery); override; + property Transaction: TFDTransaction read GetTransaction write SetTransaction; + property UpdateTransaction: TFDTransaction read GetUpdateTransaction write SetUpdateTransaction; + public + constructor Create(aFDConnection: TFDConnection; SQLDataBaseConfig: TBoldSQLDatabaseConfig); + destructor Destroy; override; + procedure CreateDatabase; override; + function GetDatabaseError(const E: Exception; const sSQL: string = ''): + EBoldDatabaseError; + property ExecuteQueryCount: integer read fExecuteQueryCount; + end; + +var + BoldFireDACQueryClass: TBoldFireDACQueryClass = TBoldFireDACQuery; + BoldFireDACExecQueryClass: TBoldFireDACExecQueryClass = TBoldFireDACExecQuery; + +implementation + +uses + Variants, + Masks, + + FireDAC.Stan.Option, + FireDAC.Comp.Script, + + BoldUtils, + BoldGuard, + BoldCoreConsts; + +{ TBoldFireDACQuery } + +function TBoldFireDACQuery.GetQuery: TFDQuery; +begin + if not Assigned(fQuery) then + begin + fQuery := TFDQuery.Create(nil); + fQuery.Connection := (DatabaseWrapper as TBoldFireDACConnection).FDConnection; + end; + Result := fQuery; +end; + +function TBoldFireDACQuery.GetDataSet: TDataSet; +begin + Result := Query; +end; + +function TBoldFireDACQuery.GetParamCheck: Boolean; +begin + result := true; // ? +end; + +function TBoldFireDACQuery.GetParamCount: Integer; +begin + Result := Query.Params.Count; +end; + +type TFDAdaptedDataSetAccess = class(TFDAdaptedDataSet); + +function TBoldFireDACQuery.GetParams: TParams; +begin + result := TFDAdaptedDataSetAccess(Query).PSGetParams; +end; + +function TBoldFireDACQuery.GetParam(i: Integer): IBoldParameter; +begin + Result := TBoldFireDACParameter.Create(Query.Params[i], Self); +end; + +function TBoldFireDACQuery.GetRecNo: integer; +begin + result := Query.RecNo - 1; +end; + +function TBoldFireDACQuery.GetRecordCount: Integer; +begin + Result := Query.RecordCount; +end; + +function TBoldFireDACQuery.GetRequestLiveQuery: Boolean; +begin + Result := False; +end; + +function TBoldFireDACQuery.GetRowsAffected: Integer; +begin + result := Query.RowsAffected; +end; + +function TBoldFireDACQuery.GetSQLStrings: TStrings; +begin + result := Query.SQL; +end; + +function TBoldFireDACQuery.GetSQLText: string; +begin + Result := Query.SQL.Text; +end; + +function TBoldFireDACQuery.GetUseReadTransactions: boolean; +begin + result := fUseReadTransactions; +end; + +procedure TBoldFireDACQuery.AssignParams(Sourceparams: TParams); +var + lIndexSourceParams: Integer; + lFDParam: TFireDacParam; +begin + Query.Params.Clear; + if Assigned(Sourceparams) and (Sourceparams.Count > 0) then + begin + for lIndexSourceParams := 0 to Sourceparams.Count - 1 do + begin + lFDParam := Query.Params.CreateParam(Sourceparams[lIndexSourceParams].DataType, Sourceparams[lIndexSourceParams].Name, Sourceparams[lIndexSourceParams].ParamType) as TFireDacParam; + lFDParam.Value := Sourceparams[lIndexSourceParams].Value; + end; + end; +end; + +procedure TBoldFireDACQuery.AssignSQL(SQL: TStrings); +begin + Query.SQL.Assign(SQL); + //function ParseSQL(SQL: WideString; DoCreate: Boolean): WideString; + //DoCreate indicates whether to clear all existing parameter definitions before parsing the SQL statement. +end; + +procedure TBoldFireDACQuery.AssignSQLText(const SQL: string); +begin + Query.SQL.Text := Sql; +{ if SQL = '' then + Query.Params.clear + else + Query.Params.ParseSQL(SQL, False);} +end; + +procedure TBoldFireDACQuery.BeginExecuteQuery; +begin + (DatabaseWrapper as TBoldFireDACConnection).BeginExecuteQuery; +end; + +procedure TBoldFireDACQuery.Clear; +begin + AssignSQLText(''); + ClearParams; +end; + +procedure TBoldFireDACQuery.ClearParams; +begin + Query.Params.Clear; +end; + +procedure TBoldFireDACQuery.Close; +begin + inherited; + if (fReadTransactionStarted) and (DatabaseWrapper as TBoldFireDACConnection).GetInTransaction then + (DatabaseWrapper as TBoldFireDACConnection).Commit; + fReadTransactionStarted := false; +end; + +constructor TBoldFireDACQuery.Create(BoldFireDACConnection: TBoldFireDACConnection); +begin + inherited Create(BoldFireDACConnection); + fUseReadTransactions := true; + fQuery := TFDQuery.Create(nil); + fQuery.Connection := (DatabaseWrapper as TBoldFireDACConnection).FDConnection; +end; + +function TBoldFireDACQuery.CreateParam(FldType: TFieldType; const ParamName: string; ParamType: TParamType; Size: integer): IBoldParameter; +var + lFDParam: TFireDacParam; +begin + lFDParam := Query.Params.CreateParam(FldType, ParamName, ptUnknown) as TFireDacParam; +// lFDParam.Size := Size; + lFDParam.Value := NULL; + Result := TBoldFireDACParameter.Create(lFDParam, Self); +end; + +destructor TBoldFireDACQuery.Destroy; +begin + if (fReadTransactionStarted) then + Close; + FreeAndNil(fQuery); + inherited; +end; + +procedure TBoldFireDACQuery.EndExecuteQuery; +begin + (DatabaseWrapper as TBoldFireDACConnection).EndExecuteQuery; +end; + +type TStringsAccess = class(TStrings); + +procedure TBoldFireDACQuery.ExecSQL; +var + Retries: Integer; + Done: Boolean; +begin + if InBatch then + begin + BatchExecSQL; + exit; + end; + BeginExecuteQuery; + try + BoldLogSQLWithParams(Query.SQL, self); + Retries := 0; + Done := false; + while not Done do + begin + try + if (DatabaseWrapper as TBoldFireDACConnection).GetInTransaction then + fReadTransactionStarted := false + else + begin + if fUseReadTransactions then + (DatabaseWrapper as TBoldFireDACConnection).StartReadTransaction; + fReadTransactionStarted := fUseReadTransactions; + end; + Query.Execute; + if fReadTransactionStarted and (DatabaseWrapper as TBoldFireDACConnection).GetInTransaction then + begin + (DatabaseWrapper as TBoldFireDACConnection).Commit; + fReadTransactionStarted := false; + end; + Done := true; + except + on e: Exception do + begin + if (DatabaseWrapper as TBoldFireDACConnection).GetInTransaction then + (DatabaseWrapper as TBoldFireDACConnection).Rollback; + if (not fReadTransactionStarted) or (Retries > 4) then + raise TBoldFireDACConnection(DatabaseWrapper).GetDatabaseError(E, Query.SQL.Text); + fReadTransactionStarted := false; + INC(Retries); + sleep(Retries*200); + end; + end; + end; + finally + EndExecuteQuery; + end; +end; + +function TBoldFireDACQuery.FindParam(const Value: string): IBoldParameter; +var + Param: TFireDacParam; +begin + result := nil; + Param := Query.FindParam(Value); + if Assigned(Param) then + Result := TBoldFireDACParameter.Create(Param, Self); +end; + +procedure TBoldFireDACQuery.Open; +var + Retries: Integer; + Done: Boolean; + EDatabase: EBoldDatabaseError; +begin + BeginExecuteQuery; + try + BoldLogSQLWithParams(Query.SQL, self); + Retries := 0; + Done := false; + while not Done do + begin + try + if (DatabaseWrapper as TBoldFireDACConnection).GetInTransaction then + fReadTransactionStarted := false + else + begin + if fUseReadTransactions then + (DatabaseWrapper as TBoldFireDACConnection).StartReadTransaction; + fReadTransactionStarted := fUseReadTransactions; + end; + Query.UpdateOptions.ReadOnly := true; + inherited; + Done := true; + except + on e: Exception do + begin + EDatabase := TBoldFireDACConnection(DatabaseWrapper). + GetDatabaseError(E, Query.SQL.Text); + if (EDatabase is EBoldDatabaseConnectionError) {and + (not Assigned(ReconnectAppExists) or ReconnectAppExists)} then + begin + EDatabase.free; +// ReconnectDatabase(Query.SQL.Text); + Reconnect; + end else + begin + if (DatabaseWrapper as TBoldFireDACConnection).GetInTransaction then + (DatabaseWrapper as TBoldFireDACConnection).Rollback; + if (not fReadTransactionStarted) or (Retries > 4) then + raise EDatabase + else + EDatabase.free; + fReadTransactionStarted := false; + INC(Retries); + sleep(Retries*200); + end; + end; + end; + end; + finally + EndExecuteQuery; + end; +end; + +function TBoldFireDACQuery.ParamByName(const Value: string): IBoldParameter; +var + lFDParam: TFireDacParam; +begin + lFDParam := Query.Params.ParamByName(Value); + Result := TBoldFireDACParameter.Create(lFDParam, Self) +end; + +procedure TBoldFireDACQuery.SetParamCheck(value: Boolean); +begin +// if Query.ParamCheck <> Value then +// Query.ParamCheck := Value; +end; + +procedure TBoldFireDACQuery.SetRequestLiveQuery(NewValue: Boolean); +begin + // ignore +end; + +procedure TBoldFireDACQuery.SetUseReadTransactions(value: boolean); +begin + fUseReadTransactions := value; +end; + +{ TBoldFireDACTable } + +constructor TBoldFireDACTable.Create(aFDTable: TFDTable; BoldFireDACConnection: TBoldFireDACConnection); +begin + inherited Create(BoldFireDACConnection); + fFDTable := aFDTable; +end; + +procedure TBoldFireDACTable.CreateTable; +begin + raise EBold.CreateFmt('MethodNotImplemented', [ClassName, 'CreateTable']); // do not localize +end; + +procedure TBoldFireDACTable.DeleteTable; +begin + raise EBold.CreateFmt('MethodNotImplemented', [ClassName, 'DeleteTable']); // do not localize +end; + +function TBoldFireDACTable.FindParam(const Value: string): IBoldParameter; +var + Param: TFireDacParam; +begin + result := nil; + Param := FDTable.FindParam(Value); + if Assigned(Param) then + Result := TBoldFireDACParameter.Create(Param, Self); +end; + +procedure TBoldFireDACTable.AddIndex(const Name, Fields: string; + Options: TIndexOptions; const DescFields: string); +begin + raise EBold.CreateFmt('MethodNotImplemented', [ClassName, 'AddIndex']); // do not localize +end; +(* +function TBoldFireDACTable.GetCommaListOfIndexesForColumn( + const aColumnName: string): string; +var + lUniMetaData: TUniMetaData; + lIndexList: TStringList; + lIndexedColumn: string; + lIndexName: string; + lBoldGuard: IBoldGuard; +const + cTableName = 'Table_Name'; + cIndexName = 'Index_Name'; + cColumnName = 'Column_Name'; +begin +// TODO possibly slow comment +// to improve performance move metadata to the Connection and store it there + + lBoldGuard := TBoldGuard.Create(lUniMetaData, lIndexList); + lUniMetaData := TUniMetaData.Create(nil); + lIndexList := TStringList.Create; + + Assert(Assigned(UniTable)); + Assert(Assigned(UniTable.Connection)); + lUniMetaData.Connection := UniTable.Connection; +// lUniMetaData.DatabaseName := UniTable.Connection.Database; + lUniMetaData.MetaDataKind := 'Indexes'; +{ lUniMetaData.TableName := GetTableName; + lUniMetaData.Open; + lUniMetaData.First; + while not lUniMetaData.Eof do + begin + lIndexedColumn := lUniMetaData.FieldByName(cColumnName).AsString; + if aColumnName = lIndexedColumn then + begin + lIndexName := lUniMetaData.FieldByName(cIndexName).AsString; + lIndexList.Add(lIndexName); + end; + lUniMetaData.Next; + end; + Result := lIndexList.CommaText; + lUniMetaData.Close; +} +end; + +function TBoldFireDACTable.GetPrimaryIndex: string; +var + lUniMetaData: TUniMetaData; + lIndexName: string; +const + cTableName = 'Table_Name'; + cIndexName = 'Index_Name'; + cColumnName = 'Column_Name'; + cPrimaryKey = 'Primary_Key'; +// COLUMN_NAME +begin +// TODO possibly slow comment +// to improve performance move metadata to the Connection and store it there + + lUniMetaData := TUniMetaData.Create(nil); + try + Assert(Assigned(UniTable)); + Assert(Assigned(UniTable.Connection)); + lUniMetaData.Connection := UniTable.Connection; +// lUniMetaData.DatabaseName := UniTable.Connection.Database; +{ lUniMetaData.MetaDataKind := otPrimaryKeys; + lUniMetaData.Open; + lUniMetaData.Filter := Format('(%s = ''%s'')', [cTableName, GetTableName]); + lUniMetaData.Filtered := True; + if lUniMetaData.RecordCount = 1 then + begin + lIndexName := lUniMetaData.FieldByName(cColumnName).AsString; + Result := lIndexName; + end + else + begin + Result := ''; + end; + lUniMetaData.Close; +} + finally + lUniMetaData.free; + end; +end; +*) +function TBoldFireDACTable.GetDataSet: TDataSet; +begin + Result := fFDTable; +end; + +function TBoldFireDACTable.GetDefaultConstraintNameForColumn( + const aColumnName: string): string; +var + lFDMetaData: TFDMetaInfoQuery; + lDefaultConstraintName: string; + lBoldGuard: IBoldGuard; +const + cConstraintName = 'CONSTRAINT_NAME'; +begin + Assert(Assigned(FDTable)); + Assert(Assigned(FDTable.Connection)); + + lBoldGuard := TBoldGuard.Create(lFDMetaData); + lFDMetaData := TFDMetaInfoQuery.Create(nil); + lFDMetaData.Connection := FDTable.Connection; +{ lUniMetaData.DatabaseName := UniTable.Connection.Database; + lUniMetaData.TableName := GetTableName; + lUniMetaData.ColumnName := aColumnName; + lUniMetaData.ObjectType := otConstraintColumnUsage; + lUniMetaData.Open; + lUniMetaData.First; + if not lUniMetaData.Eof then + begin + lDefaultConstraintName := lUniMetaData.FieldByName(cConstraintName).AsString; + end; + lUniMetaData.Close; +} + Result := lDefaultConstraintName; +end; + +function TBoldFireDACTable.GetExclusive: Boolean; +begin + Result := False; +end; + +function TBoldFireDACTable.GetExists: Boolean; +var + lAllTables: TStringList; + lGuard: IBoldGuard; +begin + lGuard := TBoldGuard.Create(lAllTables); + Result := False; + + // First we make sure we have a table component and that it is connected to a database + if Assigned(FDTable) and Assigned(FDTable.Connection) then + begin + // We now create a list that will hold all the table names in the database + lAllTables := TStringList.Create; + FDTable.Connection.GetTableNames('', '', '', lAllTables); // ? + Result := lAllTables.IndexOf(GetTableName) <> -1; + end; +end; + +function TBoldFireDACTable.GetIndexDefs: TIndexDefs; +begin + raise EBold.CreateFmt('%s MethodNotImplemented %s', [ClassName, 'GetIndexDefs']); // do not localize +// Result := FDTable.IndexFieldNames +end; + +function TBoldFireDACTable.GetFDTable: TFDTable; +begin + Result := fFDTable; +end; + +function TBoldFireDACTable.ParamByName(const Value: string): IBoldParameter; +var + lFDParam: TFireDacParam; +begin + lFDParam := FDTable.Params.ParamByName(Value); + Result := TBoldFireDACParameter.Create(lFDParam, Self) +end; + +function TBoldFireDACTable.GetTableName: string; +begin + Result := FDTable.TableName; +end; + +procedure TBoldFireDACTable.SetExclusive(NewValue: Boolean); +begin +end; + +procedure TBoldFireDACTable.SetTableName(const NewName: string); +begin + FDTable.TableName := NewName; +end; + +{ TBoldFireDACConnection } + +// Populate the "TableNameList" with tablenames from the database that maches "pattern" + +procedure TBoldFireDACConnection.AllTableNames(Pattern: string; ShowSystemTables: Boolean; TableNameList: TStrings); +var + lTempList: TStringList; + lIndexTempList: Integer; + lGuard: IBoldGuard; + i: integer; +begin + lGuard := TBoldGuard.Create(lTempList); + lTempList := TStringList.Create; + + // Retrieve the list of table names + // Note: This does not include views or procedures, there is a specific + // method in TFDConnection for that + FDConnection.GetTableNames('','','',lTempList{, ShowSystemTables}); + + // convert from fully qualified names in format: database.catalogue.table to just table name + for i := 0 to lTempList.Count - 1 do + while pos('.', lTempList[i]) > 0 do + lTempList[i] := Copy(lTempList[i], pos('.', lTempList[i])+1, maxInt); + + if Pattern = '' then + TableNameList.Assign(lTempList) + else + // MatchesMask is used to compare filenames with wildcards, suits us here + // but there should be some care taken, when using tablenames with period + // signes, as that might be interpreted as filename extensions + for lIndexTempList := 0 to lTempList.Count - 1 do + begin + if MatchesMask(lTempList[lIndexTempList], Pattern) then + begin + TableNameList.Add(lTempList[lIndexTempList]); + end; + end; +end; + +procedure TBoldFireDACConnection.Commit; +begin + FDConnection.Commit; +end; + +function TBoldFireDACConnection.GetInTransaction: Boolean; +begin + Result := FDConnection.InTransaction; +end; + +function TBoldFireDACConnection.GetIsExecutingQuery: Boolean; +begin + Result := fExecuteQueryCount > 0; +end; + +function TBoldFireDACConnection.GetIsSQLBased: Boolean; +begin + Result := True; +end; + +function TBoldFireDACConnection.GetKeepConnection: Boolean; +begin + //CheckMe; + Result := True; +end; + +function TBoldFireDACConnection.GetLogInPrompt: Boolean; +begin + Result := FDConnection.LoginPrompt; +end; + +procedure TBoldFireDACConnection.RollBack; +begin + FDConnection.RollBack; +end; + +procedure TBoldFireDACConnection.SetKeepConnection(NewValue: Boolean); +begin + //CheckMe; +end; + +procedure TBoldFireDACConnection.SetlogInPrompt(NewValue: Boolean); +begin + FDConnection.LoginPrompt := NewValue; +end; + +procedure TBoldFireDACConnection.SetTransaction(const Value: TFDTransaction); +begin + FDConnection.Transaction := Value; +end; + +procedure TBoldFireDACConnection.SetUpdateTransaction( + const Value: TFDTransaction); +begin + FDConnection.UpdateTransaction := value; +end; + +procedure TBoldFireDACConnection.StartReadTransaction; +begin + Transaction.Options.Isolation := xiReadCommitted; + FDConnection.StartTransaction; +end; + +procedure TBoldFireDACConnection.StartTransaction; +begin + Transaction.Options.Isolation := xiRepeatableRead; + FDConnection.StartTransaction; +end; + +destructor TBoldFireDACConnection.Destroy; +begin + ReleaseCachedObjects; + inherited; +end; + +procedure TBoldFireDACConnection.EndExecuteQuery; +begin + dec(fExecuteQueryCount); +end; + +constructor TBoldFireDACConnection.Create(aFDConnection: TFDConnection; SQLDataBaseConfig: TBoldSQLDatabaseConfig); +begin + inherited Create(SQLDataBaseConfig); + fFDConnection := aFDConnection; +end; + +procedure TBoldFireDACConnection.BeginExecuteQuery; +begin + inc(fExecuteQueryCount); +end; + +procedure TBoldFireDACConnection.Close; +begin + FDConnection.Close; +end; + +procedure TBoldFireDACConnection.CreateDatabase; +var + vQuery: IBoldExecQuery; + vDatabaseName: string; + vScript: TFDScript; + sl: TStringList; +const + cInterbase = 'InterBase'; + cMSSQL = 'SQL Server'; + cDropDatabaseSQL = 'Drop Database %s'; + cGenerateDatabaseSQL = 'Create Database %s'; + cGenerateDatabaseInterbaseSQL = 'Create Database ''%s'' user ''%s'' password ''%s'''; + cGenerateDatabaseSQLServer = 'USE master;' + BOLDCRLF + 'GO' + BOLDCRLF + ' Create Database %s'; +begin + vDatabaseName := LowerCase(FDConnection.Params.Database); + FDConnection.Params.Database := ''; // need to clear this to connect succesfully + vScript := TFDScript.Create(nil); + sl := TStringList.Create; + try + sl.Text := Format(SQLDataBaseConfig.CreateDatabaseTemplate , [vDatabaseName]); + vScript.Connection := FDConnection; + vScript.ExecuteScript(sl); + FDConnection.Close; + finally + FDConnection.Params.Database := vDatabaseName; + vScript.free; + sl.free; + end; +end; + +function TBoldFireDACConnection.GetConnected: Boolean; +begin + Result := FDConnection.Connected; +end; + +function TBoldFireDACConnection.GetDatabaseError(const E: Exception; + const sSQL: string): EBoldDatabaseError; +const + SQLERRORCODE = 'SQL Error Code: '; +var + iErrorCode: Integer; + sMsg: string; + iPos: Integer; + aErrorType: TBoldDatabaseErrorType; + sServer, + sDatabase, + sUsername: string; + bUseWindowsAuth: Boolean; + vConnectionString: string; +const + // Provider names copied here to avoid dependancy + cMSSQLProvider = 'SQL Server'; // TSQLServerFDProvider.GetProviderName + cPostgreSQLProvider = 'PostgreSQL'; // TPostgreSQLFDProvider.GetProviderName + cOracleSQLProvider = 'Oracle'; // TOracleFDProvider.GetProviderName + cInterBaseProvider = 'InterBase'; + cMSSQLDeadLock = 1205; +begin + aErrorType := bdetError; + vConnectionString := FDConnection.ConnectionString; +{ + bUseWindowsAuth := Pos('Authentication=Windows', FDConnection.ConnectString) > 0; + if (E is EFDError) then + begin + if FDConnection.ProviderName = cMSSQLProvider then + case EFDError(E).ErrorCode of + -2147467259, 2, 233: aErrorType := bdetConnection; // only set bdetConnection for cases where retry might work. + 208, 4145: aErrorType := bdetSQL; + 4060: aErrorType := bdetLogin; // SQLServer Error: 4060, Cannot open database "SessionStateService" requested by the login. The login failed. [SQLSTATE 42000] + 18456: aErrorType := bdetLogin; // SQLServer Error: 18456, Login failed for user 'domain\user'. [SQLSTATE 28000] + cMSSQLDeadLock: aErrorType := bdetDeadlock; + //Deadlock und weitere ErrorCodes? + end + else + if FDConnection.ProviderName = cInterBaseProvider then + case EFDError(E).ErrorCode of + -803: aErrorType := bdetUpdate; // attempt to store duplicate value (visible to active transactions) in FDque index + end + else + if FDConnection.ProviderName = cPostgreSQLProvider then + case EFDError(E).ErrorCode of + 0: aErrorType := bdetLogin; + end + else + raise Exception.Create('Error codes not implemented for ' + FDConnection.ProviderName); + end; + Result := InternalGetDatabaseError(aErrorType, E, sSQL, sServer, sDatabase, + sUsername, bUseWindowsAuth); +} +end; + +function TBoldFireDACConnection.GetExecQuery: IBoldExecQuery; +begin + if Assigned(fCachedExecQuery1) then + begin + result := fCachedExecQuery1; + fCachedExecQuery1 := nil; + end else + begin + Result := BoldFireDACQueryClass.Create(Self); + end; +end; + +function TBoldFireDACConnection.GetFDConnection: TFDConnection; +begin + Result := fFDConnection; +end; + +function TBoldFireDACConnection.GetQuery: IBoldQuery; +begin + if Assigned(fCachedQuery1) then + begin + result := fCachedQuery1; + fCachedQuery1 := nil; + end else + if Assigned(fCachedQuery2) then + begin + result := fCachedQuery2; + fCachedQuery2 := nil; + end else + begin + Result := BoldFireDACQueryClass.Create(Self); + end; +end; + +function TBoldFireDACConnection.GetTable: IBoldTable; +var + lFDTable: TFDTable; +begin + if Assigned(fCachedTable) then + begin + result := fCachedTable; + fCachedTable := nil; + end + else + begin + lFDTable := TFDTable.Create(nil); + lFDTable.Connection := FDConnection; + Result := TBoldFireDACTable.Create(lFDTable, Self); + end; +end; + +function TBoldFireDACConnection.GetTransaction: TFDTransaction; +begin + if not Assigned(FDConnection.Transaction) then + FDConnection.Transaction := TFDTransaction.Create(FDConnection); + result := FDConnection.Transaction as TFDTransaction; +end; + +function TBoldFireDACConnection.GetUpdateTransaction: TFDTransaction; +begin + if not Assigned(FDConnection.UpdateTransaction) then + FDConnection.UpdateTransaction := TFDTransaction.Create(FDConnection); + result := FDConnection.UpdateTransaction as TFDTransaction; +end; + +procedure TBoldFireDACConnection.Open; +begin + try + FDConnection.Open; + except + on E: Exception do begin + raise GetDatabaseError(E); + end; + end; +end; + +procedure TBoldFireDACConnection.Reconnect; +begin + if Assigned(fFDConnection) then begin + fFDConnection.Connected := False; + fFDConnection.Connected := True; + end; +end; + +procedure TBoldFireDACConnection.ReleaseQuery(var Query: IBoldQuery); +var + lBoldFireDACQuery: TBoldFireDACQuery; +begin + if (Query.Implementor is TBoldFireDACQuery) then + begin + lBoldFireDACQuery := Query.Implementor as TBoldFireDACQuery; + lBoldFireDACQuery.clear; + Query := nil; + if not Assigned(fCachedQuery1) then + fCachedQuery1 := lBoldFireDACQuery + else + if not Assigned(fCachedQuery2) then + fCachedQuery2 := lBoldFireDACQuery + else + lBoldFireDACQuery.free; + end +end; + +procedure TBoldFireDACConnection.ReleaseExecQuery(var Query: IBoldExecQuery); +var + lBoldFireDACQuery: TBoldFireDACQuery; + lBoldFireDACExecQuery: TBoldFireDACExecQuery; +begin + if (Query.Implementor is TBoldFireDACQuery) then + begin + lBoldFireDACQuery := Query.Implementor as TBoldFireDACQuery; + if lBoldFireDACQuery.GetSQLStrings.Count <> 0 then + begin + lBoldFireDACQuery.GetSQLStrings.BeginUpdate; + lBoldFireDACQuery.clear; + end; + while TStringsAccess(lBoldFireDACQuery.GetSQLStrings).UpdateCount > 0 do + lBoldFireDACQuery.GetSQLStrings.EndUpdate; + Query := nil; + if not Assigned(fCachedExecQuery1) then + fCachedExecQuery1 := lBoldFireDACQuery + else + lBoldFireDACQuery.free; + end +{ else + if (Query.Implementor is TBoldFireDACExecQuery) then + begin + lBoldFireDACExecQuery := Query.Implementor as TBoldFireDACExecQuery; + lBoldFireDACExecQuery.clear; + Query := nil; + if not Assigned(fCachedExecQuery1) then + fCachedExecQuery1 := lBoldFireDACExecQuery + else + lBoldFireDACExecQuery.free; + end +} +end; + +procedure TBoldFireDACConnection.ReleaseTable(var Table: IBoldTable); +var + lBoldFireDACTable: TBoldFireDACTable; +begin + if Table.Implementor is TBoldFireDACTable then + begin + lBoldFireDACTable := Table.Implementor as TBoldFireDACTable; + Table := nil; + if not Assigned(fCachedTable) then + fCachedTable := lBoldFireDACTable + else + lBoldFireDACTable.free; + end; +end; + +function TBoldFireDACConnection.SupportsTableCreation: Boolean; +begin + Result := False; +end; + +{ TBoldFireDACParameter } + +procedure TBoldFireDACParameter.Clear; +begin + FDParam.Clear; +end; + +constructor TBoldFireDACParameter.Create(FireDACParameter: TFireDacParam; DatasetWrapper: TBoldAbstractQueryWrapper); +begin + inherited Create(DatasetWrapper); + fFDParam := FireDACParameter; +end; + +function TBoldFireDACParameter.GetAsAnsiString: TBoldAnsiString; +begin + Result := FDParam.AsAnsiString; +end; + +function TBoldFireDACParameter.GetAsBCD: Currency; +begin + Result := FDParam.AsBCD; +end; + +function TBoldFireDACParameter.GetAsblob: TBoldBlobData; +begin + Result := AnsiString(FDParam.Value); +end; + +function TBoldFireDACParameter.GetAsBoolean: Boolean; +begin + Result := FDParam.AsBoolean; +end; + +function TBoldFireDACParameter.GetAsCurrency: Currency; +begin + Result := FDParam.AsCurrency; +end; + +function TBoldFireDACParameter.GetAsDateTime: TDateTime; +begin + Result := FDParam.AsDateTime; +end; + +function TBoldFireDACParameter.GetAsFloat: Double; +begin + Result := FDParam.AsFloat; +end; + +function TBoldFireDACParameter.GetAsInt64: Int64; +begin + result := FDParam.AsLargeInt; +end; + +function TBoldFireDACParameter.GetAsInteger: Longint; +begin + Result := FDParam.AsInteger; +end; + +function TBoldFireDACParameter.GetAsMemo: string; +begin + Result := FDParam.AsMemo; +end; + +function TBoldFireDACParameter.GetAsString: string; +begin + Result := FDParam.AsString; + if Result = DatasetWrapper.DatabaseWrapper.SQLDataBaseConfig.EmptyStringMarker then + begin + Result := ''; + end; +end; + +function TBoldFireDACParameter.GetAsVariant: Variant; +begin + Result := FDParam.Value; +end; + +function TBoldFireDACParameter.GetAsWideString: WideString; +begin + Result := FDParam.AsWideString; + if Result = DatasetWrapper.DatabaseWrapper.SQLDataBaseConfig.EmptyStringMarker then + begin + Result := ''; + end; +end; + +function TBoldFireDACParameter.GetDataType: TFieldType; +begin + Result := FDParam.DataType; +end; + +function TBoldFireDACParameter.GetIsNull: Boolean; +begin + Result := VarIsNull(FDParam.Value) +end; + +function TBoldFireDACParameter.GetName: string; +begin + Result := FDParam.Name; +end; + +function TBoldFireDACParameter.GetFDParam: TFireDacParam; +begin + Result := fFDParam; +end; + +procedure TBoldFireDACParameter.SetAsAnsiString(const Value: TBoldAnsiString); +begin + FDParam.AsAnsiString := Value; +end; + +procedure TBoldFireDACParameter.SetAsBCD(const Value: Currency); +begin + FDParam.Value := Value; +end; + +procedure TBoldFireDACParameter.SetAsBlob(const Value: TBoldBlobData); +begin + if FDParam.DataType = ftUnknown then + begin + FDParam.DataType := ftBlob; + end; + if Value = '' then + begin +// FDParam.Value := DatasetWrapper.DatabaseWrapper.SQLDataBaseConfig.EmptyStringMarker; + FDParam.Value := Null; + end else + begin + FDParam.Value := TBoldBlobData(AnsiString(Value)); + end; +end; + +procedure TBoldFireDACParameter.SetAsBoolean(Value: Boolean); +begin + FDParam.AsBoolean := Value; +end; + +procedure TBoldFireDACParameter.SetAsCurrency(const Value: Currency); +begin + FDParam.AsCurrency := Value; +end; + +procedure TBoldFireDACParameter.SetAsDate(const Value: TDateTime); +begin + FDParam.AsDate := Value; +end; + +procedure TBoldFireDACParameter.SetAsDateTime(const Value: TDateTime); +begin + FDParam.AsDateTime := Value; +end; + +procedure TBoldFireDACParameter.SetAsFloat(const Value: Double); +begin + FDParam.AsFloat := Value; +end; + +procedure TBoldFireDACParameter.SetAsInt64(const Value: Int64); +begin + FDParam.AsLargeInt := Value; +end; + +procedure TBoldFireDACParameter.SetAsInteger(Value: Integer); +begin + FDParam.AsInteger := Value; +end; + +procedure TBoldFireDACParameter.SetAsMemo(const Value: string); +begin + FDParam.AsMemo := Value; +end; + +procedure TBoldFireDACParameter.SetAsSmallInt(Value: Integer); +begin + FDParam.AsSmallInt := Value; +end; + +procedure TBoldFireDACParameter.SetAsString(const Value: string); +begin + if Value = '' then + begin + FDParam.AsString := DatasetWrapper.DatabaseWrapper.SQLDataBaseConfig.EmptyStringMarker; + end else + begin + FDParam.AsString := Value; + end; +end; + +procedure TBoldFireDACParameter.SetAsTime(const Value: TDateTime); +begin + FDParam.AsTime := Value; +end; + +procedure TBoldFireDACParameter.SetAsVariant(const NewValue: Variant); +begin + FDParam.Value := NewValue; +end; + +procedure TBoldFireDACParameter.SetAsWideString(const Value: Widestring); +begin + if Value = '' then + begin + FDParam.AsString := DatasetWrapper.DatabaseWrapper.SQLDataBaseConfig.EmptyStringMarker; + end else + begin + FDParam.AsWideString := Value; + end; +end; + +procedure TBoldFireDACParameter.SetAsWord(Value: Integer); +begin + FDParam.AsWord := Value; +end; + +procedure TBoldFireDACParameter.SetDataType(Value: TFieldType); +begin + FDParam.DataType := Value; +end; + +procedure TBoldFireDACParameter.SetText(const Value: string); +begin + FDParam.Value := Value; +end; + +procedure TBoldFireDACParameter.Assign(const source: IBoldParameter); +begin + FDParam.Value := Source.AsVariant; +end; + +procedure TBoldFireDACParameter.AssignFieldValue(const source: IBoldField); +begin + FDParam.Assign(source.Field); +end; + +procedure TBoldFireDACConnection.ReleaseCachedObjects; +begin + FreeAndNil(fCachedTable); + FreeAndNil(fCachedQuery1); + FreeAndNil(fCachedQuery2); + FreeAndNil(fCachedExecQuery1); +end; + +{ TBoldFireDACExecQuery } + +procedure TBoldFireDACExecQuery.AssignParams(Sourceparams: TParams); +var + lIndexSourceParams: Integer; + lFDParam: TFireDacParam; +begin + ExecQuery.Params.Clear; + if Assigned(Sourceparams) and (Sourceparams.Count > 0) then + begin + for lIndexSourceParams := 0 to Sourceparams.Count - 1 do + begin + lFDParam := ExecQuery.Params.CreateParam(Sourceparams[lIndexSourceParams].DataType, Sourceparams[lIndexSourceParams].Name, Sourceparams[lIndexSourceParams].ParamType) as TFireDacParam; + lFDParam.Value := Sourceparams[lIndexSourceParams].Value; + end; + end; +end; + +procedure TBoldFireDACExecQuery.AssignSQL(SQL: TStrings); +begin + ExecQuery.SQL.BeginUpdate; + ExecQuery.SQL.Assign(SQL); + ExecQuery.SQL.EndUpdate; +end; + +procedure TBoldFireDACExecQuery.AssignSQLText(const SQL: string); +var + lStringList: TStringList; + lGuard: IBoldGuard; +begin + lGuard := TBoldGuard.Create(lStringList); + lStringList := TStringList.Create; + lStringList.Add(SQL); + AssignSQL(lStringList); +end; + +procedure TBoldFireDACExecQuery.BeginExecuteQuery; +begin + (DatabaseWrapper as TBoldFireDACConnection).BeginExecuteQuery; +end; + +procedure TBoldFireDACExecQuery.Clear; +begin + inherited; + AssignSQLText(''); + ClearParams; +end; + +procedure TBoldFireDACExecQuery.ClearParams; +begin + ExecQuery.Params.Clear; +end; + +constructor TBoldFireDACExecQuery.Create(BoldFireDACConnection: TBoldFireDACConnection); +begin + inherited Create(BoldFireDACConnection); + fUseReadTransactions := true; +end; + +function TBoldFireDACExecQuery.Createparam(FldType: TFieldType; + const ParamName: string): IBoldParameter; +begin + result := CreateParam(FldType, ParamName, ptUnknown, 0); +end; + +function TBoldFireDACExecQuery.CreateParam(FldType: TFieldType; const ParamName: string; ParamType: TParamType; Size: integer): IBoldParameter; +var + lFDParam: TFireDacParam; +begin + lFDParam := ExecQuery.Params.CreateParam(FldType, ParamName, ptUnknown) as TFireDacParam; + lFDParam.Size := Size; + lFDParam.Value := NULL; + Result := TBoldFireDACParameter.Create(lFDParam, Self); +end; + +destructor TBoldFireDACExecQuery.Destroy; +begin + FreeAndNil(fExecQuery); + inherited; +end; + +procedure TBoldFireDACExecQuery.EndExecuteQuery; +begin + (DatabaseWrapper as TBoldFireDACConnection).EndExecuteQuery; +end; + +function TBoldFireDACExecQuery.EnsureParamByName( + const Value: string): IBoldParameter; +var + lFDParam: TFireDacParam; +begin + lFDParam := ExecQuery.Params.FindParam(Value); + if not Assigned(lFDParam) then + lFDParam := ExecQuery.Params.CreateParam(ftUnknown, Value, ptUnknown) as TFireDacParam; + Result := TBoldFireDACParameter.Create(lFDParam, Self) +end; + +procedure TBoldFireDACExecQuery.ExecSQL; +var + Retries: Integer; + Done: Boolean; +begin + BeginExecuteQuery; + try + BoldLogSQLWithParams(ExecQuery.SQL, self); + Retries := 0; + Done := false; + while not Done do + begin + try + if (DatabaseWrapper as TBoldFireDACConnection).GetInTransaction then + fReadTransactionStarted := false + else + begin + if fUseReadTransactions then + (DatabaseWrapper as TBoldFireDACConnection).StartReadTransaction; + fReadTransactionStarted := fUseReadTransactions; + end; + ExecQuery.Execute; + if fReadTransactionStarted and (DatabaseWrapper as TBoldFireDACConnection).GetInTransaction then + begin + (DatabaseWrapper as TBoldFireDACConnection).Commit; + fReadTransactionStarted := false; + end; + Done := true; + except + on e: Exception do + begin + if (not fReadTransactionStarted) or (Retries > 4) then + raise TBoldFireDACConnection(DatabaseWrapper).GetDatabaseError(E, ExecQuery.SQL.Text); + if (DatabaseWrapper as TBoldFireDACConnection).GetInTransaction then + (DatabaseWrapper as TBoldFireDACConnection).Rollback; + fReadTransactionStarted := false; + INC(Retries); + sleep(Retries*200); + end; + end; + end; + finally + EndExecuteQuery; + end; +end; + +procedure TBoldFireDACExecQuery.StartSQLBatch; +begin + raise EBold.CreateFmt('MethodNotImplemented', [ClassName, 'StartSQLBatch']); // do not localize +end; + +procedure TBoldFireDACExecQuery.EndSQLBatch; +begin + raise EBold.CreateFmt('MethodNotImplemented', [ClassName, 'EndSQLBatch']); // do not localize +end; + +procedure TBoldFireDACExecQuery.FailSQLBatch; +begin + raise EBold.CreateFmt('MethodNotImplemented', [ClassName, 'FailSQLBatch']); // do not localize +end; + +function TBoldFireDACExecQuery.FindParam(const Value: string): IBoldParameter; +var + Param: TFDParam; +begin + Param := ExecQuery.FindParam(Value); + if not Assigned(Param) then + result := CreateParam(ftUnknown, Value); +end; + +function TBoldFireDACExecQuery.GetBatchQueryParamCount: integer; +begin + result := 0; // update when batch support is implemented +end; + +function TBoldFireDACExecQuery.GetExecQuery: TFDQuery; +begin + if not Assigned(fExecQuery) then + begin + fExecQuery := TFDQuery.Create(nil); + fExecQuery.Connection := (DatabaseWrapper as TBoldFireDACConnection).FDConnection; + end; + Result := fExecQuery; +end; + +function TBoldFireDACExecQuery.GetParamCheck: Boolean; +begin + result := true; +end; + +function TBoldFireDACExecQuery.GetParamCount: Integer; +begin + result := ExecQuery.Params.Count; +end; + +function TBoldFireDACExecQuery.GetParams: TParams; +begin + result := TFDAdaptedDataSetAccess(ExecQuery).fVclParams; +end; + +function TBoldFireDACExecQuery.GetParam(i: Integer): IBoldParameter; +begin + Result := TBoldFireDACParameter.Create(ExecQuery.Params[i], Self); +end; + +function TBoldFireDACExecQuery.GetRowsAffected: Integer; +begin + Result := ExecQuery.RowsAffected; +end; + +function TBoldFireDACExecQuery.GetSQLStrings: TStrings; +begin + result := ExecQuery.SQL; +end; + +function TBoldFireDACExecQuery.GetSQLText: string; +begin + Result := ExecQuery.SQL.Text; +end; + +function TBoldFireDACExecQuery.GetUseReadTransactions: boolean; +begin + result := fUseReadTransactions; +end; + +function TBoldFireDACExecQuery.ParamByName(const Value: string): IBoldParameter; +var + lFDParam: TFireDacParam; +begin + lFDParam := ExecQuery.Params.ParamByName(Value); + if Assigned(lFDParam) then + begin + Result := TBoldFireDACParameter.Create(lFDParam, Self) + end else + begin + Result := nil; + end; +end; + +{procedure TBoldFireDACExecQuery.Prepare; +begin + ExecQuery.Prepare; +end;} + +procedure TBoldFireDACExecQuery.SetParamCheck(value: Boolean); +begin +// ExecQuery.ParamCheck := Value; +end; + +procedure TBoldFireDACExecQuery.SetUseReadTransactions(value: boolean); +begin + fUseReadTransactions := value; +end; + +end. diff --git a/Source/Persistence/FireDAC/BoldPersistenceHandleFireDAC.pas b/Source/Persistence/FireDAC/BoldPersistenceHandleFireDAC.pas new file mode 100644 index 0000000..035d632 --- /dev/null +++ b/Source/Persistence/FireDAC/BoldPersistenceHandleFireDAC.pas @@ -0,0 +1,334 @@ +{ Global compiler directives } +{$include bold.inc} +unit BoldPersistenceHandleFireDAC; + +interface + +uses + Classes, + Dialogs, + + FireDAC.Comp.Client, + + + BoldDBInterfaces, + BoldFireDACInterfaces, + BoldPersistenceHandleDB, + BoldPersistenceHandleDB_deprecated; + +type + TBoldNetWorkProtocol = (bnwpLocal, bnwpTcpIP, bnwpNetBEUI, bnwpNovellSPX); + + TBoldPersistenceHandleFireDAC = class(TBoldDBPersistenceHandle) + private + fFDConnection: TFDConnection; + fOwnConnection: TFDConnection; + fConnectionAdapter: TBoldFireDACConnection; + fDataSource: string; + fProvider: string; + fPersistSecurityInfo: Boolean; + fNetWorkProtocol: TBoldNetWorkProtocol; + fHostName: string; + fInitialCatalog: string; + fExtendedProperties: TStringList; + procedure SetDataSource(const Value: string); + procedure SetProvider(const Value: string); + procedure SetPersistSecurityInfo(const Value: Boolean); + procedure SetNetWorkProtocol(const Value: TBoldNetWorkProtocol); + procedure SetHostName(const Value: string); + procedure SetInitialCatalog(const Value: string); + procedure SetExtendedProperties(const Value: TStringList); + procedure SetFDConnection(const Value: TFDConnection); + function getEffectiveConnection: TFDConnection; + protected + procedure AddExtendedProperties(Result: TStrings); virtual; + procedure UpdateInternalConnectionString; virtual; + procedure Notification(AComponent: TComponent; Operation: TOperation); override; + property EffectiveConnection: TFDConnection read getEffectiveConnection; + procedure SetPassword(const Value: string); override; + procedure SetUserName(const Value: string); override; + {$IFNDEF T2H} + procedure InternalTransferproperties(const target: TBoldPersistenceHandleDB); override; + {$ENDIF} + public + constructor Create(owner: TComponent); override; + destructor Destroy; override; + function GetDataBaseInterface: IBoldDatabase; override; + procedure Assign(Source: TPersistent); override; + published + property DataSource: string read FDataSource write SetDataSource; + property Provider: string read FProvider write SetProvider; + property PersistSecurityInfo: Boolean read FPersistSecurityInfo write SetPersistSecurityInfo; + property NetWorkProtocol: TBoldNetWorkProtocol read FNetWorkProtocol write SetNetWorkProtocol; + property HostName: string read FHostName write SetHostName; + property InitialCatalog: string read FInitialCatalog write SetInitialCatalog; + property ExtendedProperties: TStringList read fExtendedProperties write SetExtendedProperties; + property FDConnection: TFDConnection read fFDConnection write SetFDConnection; + end deprecated; + +const + BoldNetWorkProtocolStringRep: array[TBoldNetWorkProtocol] of string = ('', 'tcpip', 'netbeui', 'spx'); + +function BoldStringToNetworkProtocol(s: string): TBoldNetWorkProtocol; + +implementation + +uses + SysUtils, + BoldDefs, + BoldDatabaseAdapterFireDAC, + BoldUtils, + BoldFireDACConsts; + +function BoldStringToNetworkProtocol(s: string): TBoldNetWorkProtocol; +var + i: TBoldNetWorkProtocol; +begin + for i := low(BoldNetWorkProtocolStringRep) to high(BoldNetWorkProtocolStringRep) do + if CompareText(s, BoldNetWorkProtocolStringRep[i]) = 0 then + begin + Result := i; + exit; + end; + + Result := bnwpLocal; +end; + +{ TBoldPersistenceHandleFireDAC } + +procedure TBoldPersistenceHandleFireDAC.AddExtendedProperties( + Result: TStrings); +begin + if trim(DataSource) <> '' then + Result.Add('DSN=' + trim(DataSource)); // do not localize + if trim(HostName) <> '' then + Result.Add('Hostname=' + trim(HostName)); // do not localize + if trim(InitialCatalog) <> '' then + Result.Add('Initial Catalog=' + trim(InitialCatalog)); // do not localize + + Result.Add('NetworkProt=' + BoldNetWorkProtocolStringRep[NetWorkProtocol]); // do not localize + + Result.AddStrings(ExtendedProperties); +end; + +procedure TBoldPersistenceHandleFireDAC.Assign(Source: TPersistent); +begin + inherited; + if Source is TBoldPersistenceHandleFireDAC then + ExtendedProperties.Assign((Source as TBoldPersistenceHandleFireDAC).ExtendedProperties); +end; + +procedure TBoldPersistenceHandleFireDAC.UpdateInternalConnectionString; +const + BoolToStr: array[Boolean] of string = ('false', 'true'); +var + LExtendedProperties: TStringList; + ConnectionString: string; +begin + if Assigned(fOwnConnection) then + begin + LExtendedProperties := TStringList.Create; + AddExtendedProperties(LExtendedProperties); + + ConnectionString := format('Provider=%s;Persist Security Info=%s;Data Source=%s;Extended Properties=%s', // do not localize + [Provider, + BoolToStr[PersistSecurityInfo], + DataSource, + BoldSeparateStringList(LExtendedProperties, ';', '"', '"')]); + LExtendedProperties.Free; + fOwnConnection.ConnectionString := ConnectionString; + end; +end; + +constructor TBoldPersistenceHandleFireDAC.Create(owner: TComponent); +begin + inherited; + FHostName := ''; // do not localize + fExtendedProperties := TStringList.Create; +end; + +destructor TBoldPersistenceHandleFireDAC.Destroy; +begin + Active := False; + FreeAndNil(fOwnConnection); + FreeAndNil(fConnectionAdapter); + inherited; +end; + +procedure TBoldPersistenceHandleFireDAC.SetFDConnection( + const Value: TFDConnection); +begin + if fFDConnection <> Value then + begin + CheckInactive('SetDataBase'); // do not localize + if Assigned(fOwnConnection) then + begin + FreeAndNil(fOwnConnection); + FreeAndNil(fConnectionAdapter); + end; + fFDConnection := Value; + if Assigned(fFDConnection) then + fFDConnection.FreeNotification(Self); + end; +end; + +procedure TBoldPersistenceHandleFireDAC.SetDataSource(const Value: string); +begin + FDataSource := Value; + UpdateInternalConnectionString; +end; + +procedure TBoldPersistenceHandleFireDAC.SetExtendedProperties( + const Value: TStringList); +begin + fExtendedProperties.Assign(Value); + UpdateInternalConnectionString; +end; + +procedure TBoldPersistenceHandleFireDAC.SetHostName(const Value: string); +begin + FHostName := Value; + if trim(FHostName) = '' then + FHostName := ''; // do not localize + UpdateInternalConnectionString; +end; + +procedure TBoldPersistenceHandleFireDAC.SetInitialCatalog(const Value: string); +begin + FInitialCatalog := Value; + UpdateInternalConnectionString; +end; + +procedure TBoldPersistenceHandleFireDAC.SetNetWorkProtocol( + const Value: TBoldNetWorkProtocol); +begin + FNetWorkProtocol := Value; + UpdateInternalConnectionString; +end; + +procedure TBoldPersistenceHandleFireDAC.SetPersistSecurityInfo( + const Value: Boolean); +begin + FPersistSecurityInfo := Value; + UpdateInternalConnectionString; +end; + +procedure TBoldPersistenceHandleFireDAC.SetProvider(const Value: string); +begin + FProvider := Value; + UpdateInternalConnectionString; +end; + +procedure TBoldPersistenceHandleFireDAC.Notification(AComponent: TComponent; + Operation: TOperation); +begin + inherited; + if (AComponent = fFDConnection) and (Operation = opRemove) then + begin + if AComponent = EffectiveConnection then + begin + Active := False; + fConnectionAdapter := nil; + end; + fFDConnection := nil; + end; +end; + +function TBoldPersistenceHandleFireDAC.getEffectiveConnection: TFDConnection; +begin + if Assigned(fFDConnection) then + Result := fFDConnection + else + begin + if not Assigned(fOwnConnection) then + begin + fOwnConnection := TFDConnection.Create(nil); + UpdateInternalConnectionString; + end; + Result := fOwnConnection; + end; +end; + +procedure TBoldPersistenceHandleFireDAC.SetPassword(const Value: string); +begin + inherited; + UpdateInternalConnectionString; +end; + +procedure TBoldPersistenceHandleFireDAC.SetUserName(const Value: string); +begin + inherited; + UpdateInternalConnectionString; +end; + +function TBoldPersistenceHandleFireDAC.GetDataBaseInterface: IBoldDatabase; +begin + if not Assigned(fConnectionAdapter) then + fConnectionAdapter := TBoldFireDACConnection.Create(EffectiveConnection, SQLDataBaseConfig); + Result := fConnectionAdapter; +end; + +procedure TBoldPersistenceHandleFireDAC.InternalTransferproperties( + const target: TBoldPersistenceHandleDB); +const + BoolToStr: array[Boolean] of string = ('false', 'true'); +var + Adapter: tBoldDatabaseAdapterFireDAC; + DesInfo: longint; + LExtendedProperties: TStringList; + ConnectionString: string; +begin + inherited; + DesInfo := target.DesignInfo; + if not Assigned(target.DatabaseAdapter) then + begin + target.DatabaseAdapter := tBoldDatabaseAdapterFireDAC.Create(target.owner); + target.DatabaseAdapter.Name := GetNewComponentName(target.DatabaseAdapter, 'BoldDatabaseAdapterFireDAC'); // do not localize + LongRec(DesInfo).Lo := LongRec(DesInfo).Lo + 16; //set Left + LongRec(DesInfo).Hi := LongRec(DesInfo).Hi + 16; //Set Top; + target.DatabaseAdapter.DesignInfo := DesInfo; + showmessage(sCreatedNewAdapter); + end + else if not (target.DatabaseAdapter is tBoldDatabaseAdapterFireDAC) then + raise Exception.CreateFmt(sCanOnlyTransferToFireDACAdapter, [target.DatabaseAdapter.ClassName]); + + Adapter := target.DatabaseAdapter as TBoldDatabaseAdapterFireDAC; + if Assigned(fFDConnection) then + Adapter.Connection := FDConnection; + + if not Assigned(Adapter.Connection) then + begin + Adapter.Connection := TFDConnection.Create(target.owner); + Adapter.Connection.Name := GetNewComponentName(Adapter.Connection, 'FireDACDatabase'); // do not localize + showmessage(sCreatedNewDB); + LongRec(DesInfo).Lo := LongRec(DesInfo).Lo + 16; //set Left + LongRec(DesInfo).Hi := LongRec(DesInfo).Hi + 16; //Set Top; + Adapter.Connection.DesignInfo := DesInfo; + + try + LExtendedProperties := TStringList.Create; + AddExtendedProperties(LExtendedProperties); + + ConnectionString := format('Provider=%s;Persist Security Info=%s;Data Source=%s;Extended Properties=%s', // do not localize + [Provider, + BoolToStr[PersistSecurityInfo], + DataSource, + BoldSeparateStringList(LExtendedProperties, ';', '"', '"')]); + LExtendedProperties.Free; + Adapter.Connection.ConnectionString := ConnectionString; + except + on E: Exception do + begin + showmessage(sCouldNotTransferConnectionString + BOLDCRLF + BOLDCRLF + + E.Message + BOLDCRLF + BOLDCRLF + + sTransferManually); + Adapter.Connection.ConnectionString := ''; + + end; + end; + + end; +end; + +end. + diff --git a/Source/Persistence/FireDAC/BoldPersistenceHandleFireDACReg.pas b/Source/Persistence/FireDAC/BoldPersistenceHandleFireDACReg.pas new file mode 100644 index 0000000..1114616 --- /dev/null +++ b/Source/Persistence/FireDAC/BoldPersistenceHandleFireDACReg.pas @@ -0,0 +1,28 @@ +{ Global compiler directives } +{$include bold.inc} +unit BoldPersistenceHandleFireDACReg; + +interface + +procedure Register; + +implementation + +//{$R BoldPersistenceHandleFireDAC.res} + +uses + SysUtils, + Classes, + BoldDatabaseAdapterFireDAC, +// BoldPersistenceHandleFireDAC, + BoldIDEConsts; + +procedure Register; +begin + {$WARNINGS OFF} +// RegisterComponents(BOLDPAGENAME_DEPRECATED, [TBoldPersistenceHandleFireDAC]); + {$WARNINGS ON} + RegisterComponents(BOLDPAGENAME_PERSISTENCE, [TBoldDatabaseAdapterFireDAC]); +end; + +end. From e3d897df59349ff33a4146a5beaa76c76441c1be Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Mon, 17 May 2021 20:05:43 +0300 Subject: [PATCH 019/112] Added BoldAction, Fixes for FireDac DB Creation and minor changes --- .../BoldControls/BoldCaptionController.pas | 5 -- .../BoldAwareGUI/FormGen/BoldAFPDefault.pas | 2 +- .../BoldAwareGUI/FormGen/BoldAFPPluggable.pas | 4 ++ Source/BoldAwareGUI/IDE/BoldAwareGuiReg.pas | 13 ++++ Source/Handles/Actions/BoldActions.pas | 65 ++++++++++++++++++- Source/Handles/Actions/BoldUndoActions.pas | 6 +- Source/Handles/IDE/BoldHandleReg.pas | 1 + .../Default/BoldPSDescriptionsDefault.pas | 7 +- Source/PMapper/SQL/BoldPSDescriptionsSQL.pas | 30 +++++---- Source/PMapper/SQL/BoldSQLDatabaseConfig.pas | 14 ++++ .../SystemDebugger/BoldSystemDebuggerForm.pas | 4 +- 11 files changed, 126 insertions(+), 25 deletions(-) diff --git a/Source/BoldAwareGUI/BoldControls/BoldCaptionController.pas b/Source/BoldAwareGUI/BoldControls/BoldCaptionController.pas index 767e8cd..8b70ed9 100644 --- a/Source/BoldAwareGUI/BoldControls/BoldCaptionController.pas +++ b/Source/BoldAwareGUI/BoldControls/BoldCaptionController.pas @@ -59,11 +59,9 @@ TBoldCustomCaptionController = class(TComponent, IBoldOCLComponent) {---TBoldCaptionController---} TBoldCaptionController = class(TBoldCustomCaptionController) published - {$IFNDEF T2H} property BoldHandle; property BoldProperties; property TrackControl; - {$ENDIF} end; implementation @@ -77,7 +75,6 @@ implementation {Dummy class to access protected caption property of TWinControl} TWinControlWithCaption = class(TwinControl); - {---TBoldCustomCaptionController---} constructor TBoldCustomCaptionController.Create(AOwner: TComponent); begin @@ -128,7 +125,6 @@ procedure TBoldCustomCaptionController.SetTrackControl(Control: TWinControl); end; end; - procedure TBoldCustomCaptionController.SetBoldHandle(value: TBoldElementHandle); begin fHandleFollower.BoldHandle := value; @@ -163,7 +159,6 @@ function TBoldCustomCaptionController.GetBoldHandle: TBoldElementHandle; Result := fHandleFollower.BoldHandle; end; - function TBoldCustomCaptionController.GetContextType: TBoldElementTypeInfo; begin if assigned(BoldHandle) then diff --git a/Source/BoldAwareGUI/FormGen/BoldAFPDefault.pas b/Source/BoldAwareGUI/FormGen/BoldAFPDefault.pas index 14bceef..ad4d558 100644 --- a/Source/BoldAwareGUI/FormGen/BoldAFPDefault.pas +++ b/Source/BoldAwareGUI/FormGen/BoldAFPDefault.pas @@ -202,7 +202,7 @@ TRoleMenu = class(TPopupMenu) var BoldShowConstraintsInAutoFormGrids: boolean = true; - BoldShowHistoryTabInAutoForms: boolean = true; + BoldShowHistoryTabInAutoForms: boolean = false; implementation diff --git a/Source/BoldAwareGUI/FormGen/BoldAFPPluggable.pas b/Source/BoldAwareGUI/FormGen/BoldAFPPluggable.pas index 34b1fd4..71a3434 100644 --- a/Source/BoldAwareGUI/FormGen/BoldAFPPluggable.pas +++ b/Source/BoldAwareGUI/FormGen/BoldAFPPluggable.pas @@ -240,7 +240,11 @@ procedure TBoldPluggableAFP.EnsureHandle; if DefaultBehaviour then inherited else + begin BoldHandle := RetrieveHandle; + if not Assigned(BoldHandle) then + inherited; + end; end; procedure TBoldPluggableAFP.EnsureComponents; diff --git a/Source/BoldAwareGUI/IDE/BoldAwareGuiReg.pas b/Source/BoldAwareGUI/IDE/BoldAwareGuiReg.pas index 630fea7..865c12f 100644 --- a/Source/BoldAwareGUI/IDE/BoldAwareGuiReg.pas +++ b/Source/BoldAwareGUI/IDE/BoldAwareGuiReg.pas @@ -12,6 +12,8 @@ procedure Register; implementation uses + ActnList, + Actions, Classes, DesignIntf, BoldDefs, @@ -55,6 +57,7 @@ implementation BoldImage, BoldComboBox, BoldPageControl, + BoldAction, BoldIDEConsts; {$R BoldAwareGUIReg.res} @@ -167,10 +170,20 @@ procedure RegisterComponentsOnPalette; ]); end; +procedure RegisterActionsInDelphi; +begin + RegisterActions(BOLDACTIONGROUPNAME, + [ + TBoldAction + ], nil); +end; + + procedure Register; begin RegisterComponentsOnPalette; RegisterEditors; + RegisterActionsInDelphi; end; end. diff --git a/Source/Handles/Actions/BoldActions.pas b/Source/Handles/Actions/BoldActions.pas index 70dbd1e..8e72e2f 100644 --- a/Source/Handles/Actions/BoldActions.pas +++ b/Source/Handles/Actions/BoldActions.pas @@ -80,14 +80,30 @@ TBoldActivateSystemAction = class(TBoldSystemHandleAction) property SaveOnClose: TBoldSaveAction read FSaveOnClose write fSaveOnClose; end; + TBoldCreateDatabaseAction = class(TBoldSystemHandleAction) + private + fOnSchemaGenerated: TNotifyEvent; + procedure SchemaGenerated; + protected + procedure GenerateSchema; + procedure CheckAllowEnable(var EnableAction: boolean); override; + public + constructor Create(AOwner: TComponent); override; + procedure ExecuteTarget(Target: TObject); override; + published + property OnSchemaGenerated: TNotifyEvent read fOnSchemaGenerated write fOnSchemaGenerated; + end; + implementation uses SysUtils, BoldDefs, + Forms, Controls, Dialogs, ComCtrls, + Menus, // for TextToShortCut BoldSystem; const @@ -107,6 +123,7 @@ constructor TBoldUpdateDBAction.Create(AOwner: TComponent); begin inherited; Caption := 'Update DB'; + ShortCut := TextToShortCut('Ctrl+S'); end; procedure TBoldUpdateDBAction.ExecuteTarget(Target: TObject); @@ -247,6 +264,8 @@ function TBoldFailureDetectionAction.HandlesTarget( ((Target as TControl).Action = self); end; +type TControlAccess = class(TControl); + procedure TBoldFailureDetectionAction.UpdateTarget(Target: TObject); var failure: TBoldFailureReason; @@ -257,10 +276,11 @@ procedure TBoldFailureDetectionAction.UpdateTarget(Target: TObject); Caption := failure.Reason else Caption := ''; - - if Target is TStatusBar then - (Target as TStatusBar).SimpleText := Caption; + (Target as TStatusBar).SimpleText := Caption + else + if Target is TControl then + (Target as TControlAccess).Caption := Caption end; { TBoldSystemHandleAction } @@ -276,6 +296,45 @@ procedure TBoldSystemHandleAction.SetBoldSystemHandle( BoldElementHandle := Value; end; +{ TBoldCreateDatabaseAction } + +procedure TBoldCreateDatabaseAction.CheckAllowEnable(var EnableAction: boolean); +begin + EnableAction := Assigned(BoldSystemHandle) and Assigned(BoldSystemHandle.PersistenceHandleDB) and not BoldSystemHandle.Active; +end; + +constructor TBoldCreateDatabaseAction.Create(AOwner: TComponent); +begin + inherited; + Caption := 'Create DB'; +end; + +procedure TBoldCreateDatabaseAction.ExecuteTarget(Target: TObject); +begin + GenerateSchema; +end; + +procedure TBoldCreateDatabaseAction.GenerateSchema; +begin + if Assigned(BoldSystemHandle) and Assigned(BoldSystemHandle.PersistenceHandleDB) then + begin + Screen.Cursor := crHourGlass; + try + BoldSystemHandle.PersistenceHandleDB.CreateDataBase; + BoldSystemHandle.PersistenceHandleDB.CreateDataBaseSchema; + finally + Screen.Cursor := crDefault; + end; + SchemaGenerated; + end; +end; + +procedure TBoldCreateDatabaseAction.SchemaGenerated; +begin + if Assigned(fOnSchemaGenerated) then + fOnSchemaGenerated(Self); +end; + initialization end. diff --git a/Source/Handles/Actions/BoldUndoActions.pas b/Source/Handles/Actions/BoldUndoActions.pas index 78a1edb..aae4a20 100644 --- a/Source/Handles/Actions/BoldUndoActions.pas +++ b/Source/Handles/Actions/BoldUndoActions.pas @@ -38,12 +38,12 @@ TBoldRedoAction = class(TBoldSystemHandleAction) procedure ExecuteTarget(Target: TObject); override; end; - implementation uses BoldSystem, ActnList, + Menus, // for TextToShortCut BoldUndoInterfaces; @@ -85,6 +85,7 @@ constructor TBoldUndoAction.Create(AOwner: TComponent); begin inherited; Caption := 'Undo'; + ShortCut := TextToShortCut('Ctrl+Z'); end; procedure TBoldUndoAction.ExecuteTarget(Target: TObject); @@ -107,6 +108,7 @@ constructor TBoldRedoAction.Create(AOwner: TComponent); begin inherited; Caption := 'Redo'; + ShortCut := TextToShortCut('Shift+Ctrl+Z'); end; procedure TBoldRedoAction.ExecuteTarget(Target: TObject); @@ -115,6 +117,4 @@ procedure TBoldRedoAction.ExecuteTarget(Target: TObject); BoldSystemHandle.System.UndoHandlerInterface.RedoLatest; end; -initialization - end. diff --git a/Source/Handles/IDE/BoldHandleReg.pas b/Source/Handles/IDE/BoldHandleReg.pas index 18351aa..1d3b832 100644 --- a/Source/Handles/IDE/BoldHandleReg.pas +++ b/Source/Handles/IDE/BoldHandleReg.pas @@ -58,6 +58,7 @@ procedure RegisterActionsInDelphi; TBoldUpdateDBAction, TBoldActivateSystemAction, TBoldFailureDetectionAction, + TBoldCreateDatabaseAction, TBoldListHandleAddNewAction, TBoldListHandleDeleteAction, TBoldListHandleFirstAction, diff --git a/Source/PMapper/Default/BoldPSDescriptionsDefault.pas b/Source/PMapper/Default/BoldPSDescriptionsDefault.pas index 0901142..2f47336 100644 --- a/Source/PMapper/Default/BoldPSDescriptionsDefault.pas +++ b/Source/PMapper/Default/BoldPSDescriptionsDefault.pas @@ -100,11 +100,16 @@ procedure TBoldDefaultSystemDescription.AddFirstClock(PSParams: TBoldPSDefaultPa end; procedure AddFirstClockUsingQuery; + var + vParam: IBoldParameter; begin Query.AssignSQLText(format( 'INSERT INTO %s (%s, %s) VALUES (0, :FirstClock)', [LastClockTable.SQLName, LASTTIMESTAMPCOLUMN_NAME, LASTCLOCKCOLUMN_NAME] )); - Query.CreateParam(ftDateTime, 'FirstClock').AsDateTime := 0; + vParam := Query.FindParam('FirstClock'); + if not Assigned(vParam) then + vParam := Query.CreateParam(ftDateTime, 'FirstClock'); + vParam.AsDateTime := 0; Query.ParamCheck := true; Query.ExecSQL; Query.ParamCheck := false; diff --git a/Source/PMapper/SQL/BoldPSDescriptionsSQL.pas b/Source/PMapper/SQL/BoldPSDescriptionsSQL.pas index 32bd600..04c778d 100644 --- a/Source/PMapper/SQL/BoldPSDescriptionsSQL.pas +++ b/Source/PMapper/SQL/BoldPSDescriptionsSQL.pas @@ -40,7 +40,7 @@ TBoldSQLIndexDescriptionList = class; {---TBoldSQLSystemDescription---} TBoldSQLSystemDescription = class(TBoldPSSystemDescription) private - Query: IBoldExecQuery; + fExecQuery: IBoldExecQuery; fTables: TBoldSQLTableDescriptionList; fSQLDatabaseConfig: TBoldSQLDatabaseConfig; fNationalCharConversion: TBoldNationalCharConversion; @@ -274,9 +274,9 @@ procedure TBoldSQLSystemDescription.CreatePersistentStorage(PSParams: TBoldPSPar var i: integer; begin - Query := PSParamsSQL.Database.GetExecQuery; - Query.ParamCheck := false; - Query.StartSQLBatch; + fExecQuery := PSParamsSQL.Database.GetExecQuery; + fExecQuery.ParamCheck := false; + fExecQuery.StartSQLBatch; try if BoldLog.ProcessInterruption then exit; @@ -290,11 +290,11 @@ procedure TBoldSQLSystemDescription.CreatePersistentStorage(PSParams: TBoldPSPar if BoldLog.ProcessInterruption then exit; end; - Query.EndSQLBatch; + fExecQuery.EndSQLBatch; CommitMetaDataTransaction(PSParamsSQL); except RollBackMetaDataTransaction(PSParamsSQL); - Query.FailSQLBatch; + fExecQuery.FailSQLBatch; raise; end; end; @@ -308,7 +308,7 @@ procedure TBoldSQLSystemDescription.CreatePersistentStorage(PSParams: TBoldPSPar try CreateTables; finally - PSParamsSQL.Database.ReleaseExecQuery(Query); + PSParamsSQL.Database.ReleaseExecQuery(fExecQuery); end; end; @@ -352,10 +352,19 @@ function DeleteTableBDE: boolean; end; function DeleteTableSQL: boolean; +var + PsParamsSQL: TBoldPSSQLParams; + Query: IBoldExecQuery; begin result := true; - self.Query.AssignSQLText('DROP TABLE '+Tablenamelist[i]); - self.Query.ExecSQL; + PSParamsSQL := PSParams as TBoldPSSQLParams; + Query := PSParamsSQL.Database.GetExecQuery; + try + Query.AssignSQLText('DROP TABLE '+Tablenamelist[i]); + Query.ExecSQL; + finally + PSParamsSQL.Database.ReleaseExecQuery(Query); + end; end; function DeleteTable: Boolean; @@ -555,7 +564,7 @@ procedure TBoldSQLTableDescription.CreateTableSQL(PSParams: TBoldPSSQLParams); i: integer; Query: IBoldExecQuery; begin - Query := SystemDescription.Query; + Query := SystemDescription.fExecQuery; Query.AssignSQLText(SQLForCreateTable(PSParams.Database)); Query.ExecSQL; for i := 0 to IndexList.count-1 do @@ -959,5 +968,4 @@ procedure TBoldSQLSystemDescription.StartMetaDataTransaction(PSParams: TBoldPSSQ PsParams.Database.StartTransaction; end; -initialization end. diff --git a/Source/PMapper/SQL/BoldSQLDatabaseConfig.pas b/Source/PMapper/SQL/BoldSQLDatabaseConfig.pas index e3683f3..1bf21e7 100644 --- a/Source/PMapper/SQL/BoldSQLDatabaseConfig.pas +++ b/Source/PMapper/SQL/BoldSQLDatabaseConfig.pas @@ -101,6 +101,7 @@ TBoldSQLDataBaseConfig = class(TPersistent) fUseMultiRowInserts: boolean; fSQLforNull: string; fEvolveDropsUnknownIndexes: boolean; + fCreateDatabaseTemplate: string; procedure SetIfTemplate(const Value: string); procedure SetColumnExistsTemplate(const Value: string); procedure SetTableExistsTemplate(const Value: string); @@ -171,6 +172,7 @@ TBoldSQLDataBaseConfig = class(TPersistent) procedure SetUseParamsForEmptyString(const Value: boolean); procedure SetSQLforNull(const Value: string); procedure SetEvolveDropsUnknownIndexes(const Value: boolean); + procedure SetCreateDatabaseTemplate(const Value: string); protected procedure DefineProperties(Filer: TFiler); override; public @@ -227,6 +229,7 @@ TBoldSQLDataBaseConfig = class(TPersistent) property UseSQL92Joins: boolean read fUseSQL92Joins write SetUseSQL92Joins default false; property SingleIndexOrderedLinks: boolean read fSingleIndexOrderedLinks write SetSingleIndexOrderedLinks default false; property IgnoreMissingObjects: boolean read fIgnoreMissingObjects write SetIgnoreMissingObjects default false; + property CreateDatabaseTemplate: string read fCreateDatabaseTemplate write SetCreateDatabaseTemplate; property DropColumnTemplate: string read fDropColumnTemplate write SetDropColumnTemplate; property DropTableTemplate: string read fDropTableTemplate write SetDropTableTemplate; property IndexInfoTemplate: string read fIndexInfoTemplate write SetIndexInfoTemplate; @@ -334,6 +337,7 @@ procedure TBoldSQLDataBaseConfig.AssignConfig(Source: TBoldSQLDataBaseConfig); fAllowMetadataChangesInTransaction := Source.AllowMetadataChangesInTransaction; fDbGenerationMode := Source.DBGenerationMode; fDefaultStringLength := Source.DefaultStringLength; + fCreateDatabaseTemplate := Source.CreateDatabaseTemplate; fDropColumnTemplate := Source.DropColumnTemplate; fDropTableTemplate := Source.DropTableTemplate; fDropIndexTemplate := Source.DropIndexTemplate; @@ -498,6 +502,15 @@ procedure TBoldSQLDataBaseConfig.SetColumnTypeForUnicodeText(const Value: string end; end; +procedure TBoldSQLDataBaseConfig.SetCreateDatabaseTemplate(const Value: string); +begin + if fCreateDatabaseTemplate <> Value then + begin + fCreateDatabaseTemplate := Value; + Change; + end; +end; + procedure TBoldSQLDataBaseConfig.SetColumnTypeForTime(const Value: string); begin if fColumnTypeForTime <> Value then @@ -730,6 +743,7 @@ procedure TBoldSQLDataBaseConfig.SetInitialValues; fIgnoreMissingObjects := false; fAllowMetadataChangesInTransaction := true; fDBGenerationMode := dbgQuery; + fCreateDatabaseTemplate := 'CREATE DATABASE %s'; fDropColumnTemplate := 'ALTER TABLE DROP '; fDropTableTemplate := 'DROP TABLE '; fDropIndexTemplate := 'DROP INDEX '; diff --git a/Source/Samples/SystemDebugger/BoldSystemDebuggerForm.pas b/Source/Samples/SystemDebugger/BoldSystemDebuggerForm.pas index 8fe4b32..7d54ad7 100644 --- a/Source/Samples/SystemDebugger/BoldSystemDebuggerForm.pas +++ b/Source/Samples/SystemDebugger/BoldSystemDebuggerForm.pas @@ -26,7 +26,9 @@ interface BoldCursorHandle, BoldDBInterfaces, BoldGui, - BoldListHandle, BoldReferenceHandle, ExtCtrls; + BoldListHandle, + BoldReferenceHandle, + ExtCtrls; type TBoldSystemDebuggerFrm = class(TForm) From 4af3996683aaebd8ab65940d61ad24417ad286b4 Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Mon, 17 May 2021 20:08:26 +0300 Subject: [PATCH 020/112] Updated Buildings demo to work with latest --- .../Compound/Building/BuildingClasses.pas | 43 +-- .../Building/BuildingClasses_Interface.inc | 32 ++- examples/Delphi/Compound/Building/Datamod.dfm | Bin 9302 -> 17712 bytes examples/Delphi/Compound/Building/Datamod.pas | 83 +++--- .../Delphi/Compound/Building/Mainform.dfm | Bin 12963 -> 26955 bytes .../Delphi/Compound/Building/Mainform.pas | 262 ++++++++++-------- .../Compound/Building/PersonAutoFormUnit.dfm | 23 +- .../Compound/Building/PersonAutoFormUnit.pas | 10 +- 8 files changed, 267 insertions(+), 186 deletions(-) diff --git a/examples/Delphi/Compound/Building/BuildingClasses.pas b/examples/Delphi/Compound/Building/BuildingClasses.pas index 9873b86..8ff3bf0 100644 --- a/examples/Delphi/Compound/Building/BuildingClasses.pas +++ b/examples/Delphi/Compound/Building/BuildingClasses.pas @@ -2,7 +2,7 @@ (* This file is autogenerated *) (* Any manual changes will be LOST! *) (*****************************************) -(* Generated 2002-05-24 16:22:04 *) +(* Generated 17.05.2021 12:57:35 *) (*****************************************) (* This file should be stored in the *) (* same directory as the form/datamodule *) @@ -78,7 +78,7 @@ function TBuilding._GetZipCode: Integer; Result := M_ZipCode.AsInteger; end; -procedure TBuilding._SetZipCode(NewValue: Integer); +procedure TBuilding._SetZipCode(const NewValue: Integer); begin M_ZipCode.AsInteger := NewValue; end; @@ -94,7 +94,7 @@ function TBuilding._GetAddress: String; Result := M_Address.AsString; end; -procedure TBuilding._SetAddress(NewValue: String); +procedure TBuilding._SetAddress(const NewValue: String); begin M_Address.AsString := NewValue; end; @@ -224,7 +224,7 @@ function TPerson._GetFirstName: String; Result := M_FirstName.AsString; end; -procedure TPerson._SetFirstName(NewValue: String); +procedure TPerson._SetFirstName(const NewValue: String); begin M_FirstName.AsString := NewValue; end; @@ -240,7 +240,7 @@ function TPerson._GetLastName: String; Result := M_LastName.AsString; end; -procedure TPerson._SetLastName(NewValue: String); +procedure TPerson._SetLastName(const NewValue: String); begin M_LastName.AsString := NewValue; end; @@ -256,7 +256,7 @@ function TPerson._GetAssets: Currency; Result := M_Assets.AsCurrency; end; -procedure TPerson._SetAssets(NewValue: Currency); +procedure TPerson._SetAssets(const NewValue: Currency); begin M_Assets.AsCurrency := NewValue; end; @@ -272,15 +272,26 @@ function TPerson._GetIsMarried: Boolean; Result := M_IsMarried.AsBoolean; end; -procedure TPerson._SetIsMarried(NewValue: Boolean); +procedure TPerson._SetIsMarried(const NewValue: Boolean); begin M_IsMarried.AsBoolean := NewValue; end; +function TPerson._Get_M_name: TBAString; +begin + assert(ValidateMember('TPerson', 'name', 4, TBAString)); + Result := TBAString(BoldMembers[4]); +end; + +function TPerson._Getname: String; +begin + Result := M_name.AsString; +end; + function TPerson._Get_M_Home: TBoldObjectReference; begin - assert(ValidateMember('TPerson', 'Home', 4, TBoldObjectReference)); - Result := TBoldObjectReference(BoldMembers[4]); + assert(ValidateMember('TPerson', 'Home', 5, TBoldObjectReference)); + Result := TBoldObjectReference(BoldMembers[5]); end; function TPerson._GetHome: TResidential_Building; @@ -289,21 +300,21 @@ function TPerson._GetHome: TResidential_Building; Result := TResidential_Building(M_Home.BoldObject); end; -procedure TPerson._SetHome(value: TResidential_Building); +procedure TPerson._SetHome(const value: TResidential_Building); begin M_Home.BoldObject := value; end; function TPerson._GetOwnedBuildings: TBuildingList; begin - assert(ValidateMember('TPerson', 'OwnedBuildings', 5, TBuildingList)); - Result := TBuildingList(BoldMembers[5]); + assert(ValidateMember('TPerson', 'OwnedBuildings', 6, TBuildingList)); + Result := TBuildingList(BoldMembers[6]); end; function TPerson._GetOwnership: TOwnershipList; begin - assert(ValidateMember('TPerson', 'Ownership', 6, TOwnershipList)); - Result := TOwnershipList(BoldMembers[6]); + assert(ValidateMember('TPerson', 'Ownership', 7, TOwnershipList)); + Result := TOwnershipList(BoldMembers[7]); end; procedure TPersonList.Add(NewObject: TPerson); @@ -356,7 +367,7 @@ function TResidential_Building._GetTotalRent: Currency; Result := M_TotalRent.AsCurrency; end; -procedure TResidential_Building._SetTotalRent(NewValue: Currency); +procedure TResidential_Building._SetTotalRent(const NewValue: Currency); begin M_TotalRent.AsCurrency := NewValue; end; @@ -406,7 +417,7 @@ procedure TResidential_BuildingList.SetBoldObject(index: Integer; NewObject: TRe function GeneratedCodeCRC: String; begin - result := '1091338414'; + result := '1756829375'; end; procedure InstallObjectListClasses(BoldObjectListClasses: TBoldGeneratedClassList); diff --git a/examples/Delphi/Compound/Building/BuildingClasses_Interface.inc b/examples/Delphi/Compound/Building/BuildingClasses_Interface.inc index 7c5bee6..0cb992b 100644 --- a/examples/Delphi/Compound/Building/BuildingClasses_Interface.inc +++ b/examples/Delphi/Compound/Building/BuildingClasses_Interface.inc @@ -2,7 +2,7 @@ (* This file is autogenerated *) (* Any manual changes will be LOST! *) (*****************************************) -(* Generated 2002-05-24 16:22:04 *) +(* Generated 17.05.2021 12:57:35 *) (*****************************************) (* This file should be stored in the *) (* same directory as the form/datamodule *) @@ -62,15 +62,15 @@ type private function _Get_M_ZipCode: TBAInteger; function _GetZipCode: Integer; - procedure _SetZipCode(NewValue: Integer); + procedure _SetZipCode(const NewValue: Integer); function _Get_M_Address: TBAString; function _GetAddress: String; - procedure _SetAddress(NewValue: String); + procedure _SetAddress(const NewValue: String); function _GetOwners: TPersonList; function _GetOwnership: TOwnershipList; protected - procedure CompleteCreate; override; public + procedure CompleteCreate; override; property M_ZipCode: TBAInteger read _Get_M_ZipCode; property M_Address: TBAString read _Get_M_Address; property M_Owners: TPersonList read _GetOwners; @@ -99,29 +99,32 @@ type private function _Get_M_FirstName: TBAString; function _GetFirstName: String; - procedure _SetFirstName(NewValue: String); + procedure _SetFirstName(const NewValue: String); function _Get_M_LastName: TBAString; function _GetLastName: String; - procedure _SetLastName(NewValue: String); + procedure _SetLastName(const NewValue: String); function _Get_M_Assets: TBACurrency; function _GetAssets: Currency; - procedure _SetAssets(NewValue: Currency); + procedure _SetAssets(const NewValue: Currency); function _Get_M_IsMarried: TBABoolean; function _GetIsMarried: Boolean; - procedure _SetIsMarried(NewValue: Boolean); + procedure _SetIsMarried(const NewValue: Boolean); + function _Get_M_name: TBAString; + function _Getname: String; function _GetHome: TResidential_Building; function _Get_M_Home: TBoldObjectReference; - procedure _SetHome(value: TResidential_Building); + procedure _SetHome(const value: TResidential_Building); function _GetOwnedBuildings: TBuildingList; function _GetOwnership: TOwnershipList; protected - procedure CompleteCreate; override; public - procedure BorrowFrom(Lender: TPerson; Amount: Integer); + procedure CompleteCreate; override; + procedure BorrowFrom(Lender: TPerson; Amount: Integer); property M_FirstName: TBAString read _Get_M_FirstName; property M_LastName: TBAString read _Get_M_LastName; property M_Assets: TBACurrency read _Get_M_Assets; property M_IsMarried: TBABoolean read _Get_M_IsMarried; + property M_name: TBAString read _Get_M_name; property M_Home: TBoldObjectReference read _Get_M_Home; property M_OwnedBuildings: TBuildingList read _GetOwnedBuildings; property M_Ownership: TOwnershipList read _GetOwnership; @@ -129,6 +132,7 @@ type property LastName: String read _GetLastName write _SetLastName; property Assets: Currency read _GetAssets write _SetAssets; property IsMarried: Boolean read _GetIsMarried write _SetIsMarried; + property name: String read _Getname; property Home: TResidential_Building read _GetHome write _SetHome; property OwnedBuildings: TBuildingList read _GetOwnedBuildings; property Ownership: TOwnershipList read _GetOwnership; @@ -138,12 +142,12 @@ type private function _Get_M_TotalRent: TBACurrency; function _GetTotalRent: Currency; - procedure _SetTotalRent(NewValue: Currency); + procedure _SetTotalRent(const NewValue: Currency); function _GetResidents: TPersonList; protected - procedure CompleteCreate; override; public - procedure ChargeRent; + procedure ChargeRent; + procedure CompleteCreate; override; property M_TotalRent: TBACurrency read _Get_M_TotalRent; property M_Residents: TPersonList read _GetResidents; property TotalRent: Currency read _GetTotalRent write _SetTotalRent; diff --git a/examples/Delphi/Compound/Building/Datamod.dfm b/examples/Delphi/Compound/Building/Datamod.dfm index 08c6322e80d3dfe7716574087c9b636787841906..a91cceef54dda6cdb1422974aa6aed571331a05d 100644 GIT binary patch literal 17712 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 D1hK*# diff --git a/examples/Delphi/Compound/Building/Datamod.pas b/examples/Delphi/Compound/Building/Datamod.pas index 21197ae..5c5ab07 100644 --- a/examples/Delphi/Compound/Building/Datamod.pas +++ b/examples/Delphi/Compound/Building/Datamod.pas @@ -33,8 +33,17 @@ interface BoldreferenceHandle, ActnList, BoldHandleAction, BoldAFPPluggable, BoldAbstractPersistenceHandleDB, - DB, IBDatabase, - BoldAbstractDatabaseAdapter, BoldDatabaseAdapterIB; + DB, + BoldAbstractDatabaseAdapter, + FireDAC.Stan.Intf, + FireDAC.Stan.Option, FireDAC.Stan.Error, FireDAC.UI.Intf, FireDAC.Phys.Intf, + FireDAC.Stan.Def, FireDAC.Stan.Pool, FireDAC.Stan.Async, FireDAC.Phys, + FireDAC.Phys.FB, FireDAC.Phys.FBDef, FireDAC.VCLUI.Wait, FireDAC.Comp.Client, + BoldDatabaseAdapterFireDAC, FireDAC.Phys.MSSQL, FireDAC.Phys.MSSQLDef, + FireDAC.DApt, BoldAbstractPropagatorHandle, + BoldPropagatorHandleCOM, BoldPersistenceHandlePassthrough, + BoldPersistenceHandlePTWithModel, BoldSnooperHandle, BoldAbstractDequeuer, + BoldExternalObjectSpaceEventHandler; type TDataModule1 = class(TDataModule) @@ -48,19 +57,22 @@ TDataModule1 = class(TDataModule) BoldSystemTypeInfoHandle1: TBoldSystemTypeInfoHandle; BoldPlaceableAFP1: TBoldPlaceableAFP; BoldPersistenceHandleDB1: TBoldPersistenceHandleDB; - IBDatabase1: TIBDatabase; - BoldDatabaseAdapterIB1: TBoldDatabaseAdapterIB; - procedure IsRichRendererSubscribe(Element: TBoldElement; Representation: Integer; Expression: String; Subscriber: TBoldSubscriber); - function IsRichRendererGetAsCheckBoxState(element: TBoldElement; representation: Integer; Expression: String): TCheckBoxState; + BoldDatabaseAdapterFireDAC1: TBoldDatabaseAdapterFireDAC; + FDConnection1: TFDConnection; function NameComparerCompare(item1, item2: TBoldElement): Integer; procedure NameComparerSubscribe(boldElement: TBoldElement; subscriber: TBoldSubscriber); - procedure NegativeRedRendererHoldsChangedValue(element: TBoldElement; representation: Integer; Expression: String; Subscriber: TBoldSubscriber); - procedure NegativeRedRendererSetFont(element: TBoldElement; aFont: TFont; representation: Integer; Expression: String); function IsRichFilterFilter(element: TBoldElement): Boolean; procedure IsRichFilterSubscribe(element: TBoldElement; subscriber: TBoldSubscriber); procedure BoldPlaceableAFP1GetFormClass(Element: TBoldElement; var Result: TFormClass); procedure BoldPlaceableAFP1RetrieveHandle(Form: TForm; var Result: TBoldReferenceHandle); + function IsRichRendererGetAsCheckBoxState( + aFollower: TBoldFollower): TCheckBoxState; + procedure IsRichRendererSubscribe(aFollower: TBoldFollower; + Subscriber: TBoldSubscriber); + procedure NegativeRedRendererSetFont(aFollower: TBoldFollower; + AFont: TFont); + function IsRichRendererMayModify(aFollower: TBoldFollower): Boolean; private { Private declarations } public @@ -77,19 +89,6 @@ implementation {$R *.DFM} -function TDataModule1.IsRichRendererGetAsCheckBoxState( - element: TBoldElement; representation: Integer; - Expression: String): TCheckBoxState; -begin - result := cbGrayed; - if element is TPerson then - begin - if TPerson(element).Assets > 10000 then - Result := cbChecked - else - Result := cbUnChecked - end; -end; function TDataModule1.NameComparerCompare(item1, item2: TBoldElement): Integer; begin @@ -111,22 +110,12 @@ function TDataModule1.IsRichFilterFilter(element: TBoldElement): Boolean; Result := TPerson(element).Assets > 10000; end; -procedure TDataModule1.NegativeRedRendererHoldsChangedValue( - element: TBoldElement; representation: Integer; - Expression: String; Subscriber: TBoldSubscriber); +procedure TDataModule1.NegativeRedRendererSetFont(aFollower: TBoldFollower; + AFont: TFont); begin - if assigned(element) then - with NegativeRedRenderer do - DefaultHoldsChangedValue(element, representation, Expression, nil, subscriber); -end; - -procedure TDataModule1.NegativeRedRendererSetFont( - element: TBoldElement; aFont: TFont; representation: Integer; - Expression: String); -begin - if Element is TPerson then + if aFollower.Element is TPerson then begin - if TPerson(Element).Assets < 0 then + if TPerson(aFollower.Element).Assets < 0 then aFont.Color := clRed else aFont.Color := clBlue; @@ -138,11 +127,29 @@ procedure TDataModule1.IsRichFilterSubscribe(element: TBoldElement; subscriber: Element.SubscribeToExpression('assets', Subscriber, False); end; -procedure TDataModule1.IsRichRendererSubscribe(Element: TBoldElement; - Representation: Integer; Expression: String; +function TDataModule1.IsRichRendererGetAsCheckBoxState( + aFollower: TBoldFollower): TCheckBoxState; +begin + result := cbGrayed; + if aFollower.element is TPerson then + begin + if TPerson(aFollower.element).Assets > 10000 then + Result := cbChecked + else + Result := cbUnChecked + end; +end; + +function TDataModule1.IsRichRendererMayModify( + aFollower: TBoldFollower): Boolean; +begin + result := false; +end; + +procedure TDataModule1.IsRichRendererSubscribe(aFollower: TBoldFollower; Subscriber: TBoldSubscriber); begin - Element.SubscribeToExpression('assets', Subscriber, False); + aFollower.Element.SubscribeToExpression('assets', Subscriber, False); end; procedure TDataModule1.BoldPlaceableAFP1GetFormClass(Element: TBoldElement; var Result: TFormClass); diff --git a/examples/Delphi/Compound/Building/Mainform.dfm b/examples/Delphi/Compound/Building/Mainform.dfm index 6f0498354e667809ece53e21b8b6f31bb7019d50..16547e0a3d3c3bce92136713f7e0acdb59f29fe9 100644 GIT binary patch literal 26955 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 diff --git a/examples/Delphi/Compound/Building/Mainform.pas b/examples/Delphi/Compound/Building/Mainform.pas index a2b8bdf..04e1311 100644 --- a/examples/Delphi/Compound/Building/Mainform.pas +++ b/examples/Delphi/Compound/Building/Mainform.pas @@ -14,6 +14,7 @@ interface ExtCtrls, ComCtrls, Grids, + Actions, ActnList, BoldSubscription, BoldElements, @@ -37,7 +38,12 @@ interface BoldActions, BoldDBActions, BoldAFP, - BoldReferenceHandle, BoldIBDatabaseAction; + BoldReferenceHandle, + BoldNavigatorDefs, + BoldDebugActions, + BoldUndoActions, + BoldCaptionController, + BoldAction; type Tallform = class(TForm) @@ -54,7 +60,6 @@ Tallform = class(TForm) Label3: TLabel; Label1: TLabel; FirstName: TLabel; - btnUpdateDB: TButton; bedFirstName: TBoldEdit; PersonCount: TBoldEdit; bedPersonHome: TBoldEdit; @@ -111,9 +116,46 @@ Tallform = class(TForm) BoldUpdateDBAction1: TBoldUpdateDBAction; HighRentRenderer: TBoldAsStringRenderer; btnCheckpoint: TButton; + BoldCreateDatabaseAction1: TBoldCreateDatabaseAction; + GroupBox2: TGroupBox; btnUnDo: TButton; btnRedo: TButton; - BoldIBDatabaseAction1: TBoldIBDatabaseAction; + GroupBox3: TGroupBox; + btnUpdateDB: TButton; + BoldFailureDetectionAction1: TBoldFailureDetectionAction; + BoldUndoAction1: TBoldUndoAction; + BoldRedoAction1: TBoldRedoAction; + BoldSystemDebuggerAction1: TBoldSystemDebuggerAction; + BoldNavigator1: TBoldNavigator; + BoldNavigator2: TBoldNavigator; + BoldNavigator3: TBoldNavigator; + StatusBar1: TStatusBar; + MainMenu1: TMainMenu; + Opensystem1: TMenuItem; + CreateDB1: TMenuItem; + Opensystem2: TMenuItem; + UpdateDB1: TMenuItem; + BoldFailureDetectionAction11: TMenuItem; + ogglelog1: TMenuItem; + Systemdebugger1: TMenuItem; + Edit1: TMenuItem; + Undo1: TMenuItem; + Redo1: TMenuItem; + BoldModelEditorAction: TAction; + BoldModelEditorAction1: TMenuItem; + Log1: TMenuItem; + BoldLogOCLAction1: TBoldLogOCLAction; + BoldLogSQLAction1: TBoldLogSQLAction; + BoldLogPMAction1: TBoldLogPMAction; + oggleOCLlogs1: TMenuItem; + ogglePMCallslogs1: TMenuItem; + oggleSQLlogs1: TMenuItem; + BoldSetCheckPointAction1: TBoldSetCheckPointAction; + BoldCaptionController1: TBoldCaptionController; + actChargeRent: TBoldAction; + BoldLogFormAction1: TBoldLogFormAction; + ListBox1: TListBox; + Label8: TLabel; procedure newBuildingClick(Sender: TObject); procedure DeleteCurrentObject(Sender: TObject); procedure NewPersonClick(Sender: TObject); @@ -121,29 +163,35 @@ Tallform = class(TForm) procedure SingleItemRemove(Sender: TObject); procedure PopupPopup(Sender: TObject); procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean); - procedure ShowInOwnWindow(Sender: TObject); - function bsrRentPerResidentGetAsString(Element: TBoldElement; representation: Integer; Expression: String): string; - function bsrRentPerResidentMayModify(element: TBoldElement; representation: Integer; Expression: String; Subscriber: TBoldSubscriber): Boolean; - function bsrRentPerResidentValidateCharacter(element: TBoldElement; value: String; representation: Integer; Expression: String): Boolean; - function bsrRentPerResidentValidateString(element: TBoldElement; value: String; representation: Integer; Expression: String): Boolean; - procedure bsrRentPerResidentHoldsChangedValue(Element: TBoldElement; representation: Integer; Expression: String; Subscriber: TBoldSubscriber); - procedure bsrRentPerResidentReleaseChangedValue(Element: TBoldElement; representation: Integer; Expression: String; Subscriber: TBoldSubscriber); - procedure bsrRentPerResidentSubscribe(Element: TBoldElement; representation: Integer; Expression: String; Subscriber: TBoldSubscriber); - procedure bsrRentPerResidentSetAsString(Element: TBoldElement; value: string; representation: Integer; Expression: String); procedure rgNameRepresentationClick(Sender: TObject); - procedure btnChargeRentClick(Sender: TObject); procedure CheckBox1Click(Sender: TObject); + procedure ShowInOwnWindow(Sender: TObject); procedure CheckBox1Click(Sender: TObject); procedure CheckBox2Click(Sender: TObject); - - function bsrResidentsTotalAssetsGetAsString(element: TBoldElement; representation: Integer; Expression: String): String; - procedure bsrResidentsTotalAssetsSubscribe(element: TBoldElement; representation: Integer; Expression: String; Subscriber: TBoldSubscriber); - procedure bsrAddressSetColor(element: TBoldElement; var aColor: TColor; representation: Integer; Expression: String); - procedure bsrAddressSetFont(element: TBoldElement; aFont: TFont; representation: Integer; Expression: String); procedure NewBuilding1Click(Sender: TObject); - procedure BoldActivateSystemAction1SystemOpened(Sender: TObject); - procedure HighRentRendererSetColor(Element: TBoldElement; var AColor: TColor; Representation: Integer; Expression: String); - procedure HighRentRendererSetFont(Element: TBoldElement; AFont: TFont; Representation: Integer; Expression: String); - procedure btnCheckpointClick(Sender: TObject); - procedure btnUnDoClick(Sender: TObject); - procedure btnRedoClick(Sender: TObject); + function bsrRentPerResidentGetAsString(aFollower: TBoldFollower): string; + procedure bsrRentPerResidentHoldsChangedValue(aFollower: TBoldFollower); + function bsrRentPerResidentMayModify(aFollower: TBoldFollower): Boolean; + procedure bsrRentPerResidentReleaseChangedValue(aFollower: TBoldFollower); + procedure bsrRentPerResidentSetAsString(aFollower: TBoldFollower; + const NewValue: string); + procedure rgNameRepresentationClick(Sender: TObject); + procedure bsrRentPerResidentSubscribe(aFollower: TBoldFollower; + Subscriber: TBoldSubscriber); + function bsrRentPerResidentValidateCharacter(aFollower: TBoldFollower; + const Value: string): Boolean; + function bsrRentPerResidentValidateString(aFollower: TBoldFollower; + const Value: string): Boolean; + function bsrResidentsTotalAssetsGetAsString( + aFollower: TBoldFollower): string; + procedure bsrResidentsTotalAssetsSubscribe(aFollower: TBoldFollower; + Subscriber: TBoldSubscriber); + procedure bsrAddressSetColor(aFollower: TBoldFollower; var AColor: TColor); + procedure bsrAddressSetFont(aFollower: TBoldFollower; AFont: TFont); + procedure HighRentRendererSetColor(aFollower: TBoldFollower; + var AColor: TColor); + procedure HighRentRendererSetFont(aFollower: TBoldFollower; AFont: TFont); + procedure CheckBox3Click(Sender: TObject); + procedure BoldModelEditorActionExecute(Sender: TObject); + procedure actChargeRentExecute(Sender: TObject); + procedure FormCreate(Sender: TObject); private { Private declarations } function CurrentBuildingHandle: TBoldListHandle; @@ -160,7 +208,8 @@ implementation BuildingClasses, BoldGUI, PersonAutoFormUnit, - datamod; + datamod, + BoldUMLModelEdit; {$R *.DFM} @@ -230,6 +279,13 @@ procedure Tallform.FormCloseQuery(Sender: TObject; var CanClose: Boolean); Canclose := False; end; +procedure Tallform.FormCreate(Sender: TObject); +begin + Randomize; + datamodule1.BoldSystemHandle1.System.UndoHandlerInterface.Enabled := true; + BoldCaptionController1.TrackControl := self; +end; + procedure Tallform.ShowInOwnWindow(Sender: TObject); var BoldObject: TBoldObject; @@ -248,12 +304,11 @@ procedure Tallform.ShowInOwnWindow(Sender: TObject); end; function Tallform.bsrRentPerResidentGetAsString( - Element: TBoldElement; representation: Integer; - Expression: String): string; + aFollower: TBoldFollower): string; begin result := ''; - if element is TResidential_Building then - with TResidential_Building(Element) do + if AFollower.element is TResidential_Building then + with TResidential_Building(AFollower.Element) do if M_TotalRent.IsNull then Result := '***' else if Residents.Count = 0 then @@ -263,45 +318,49 @@ function Tallform.bsrRentPerResidentGetAsString( end; procedure Tallform.bsrRentPerResidentHoldsChangedValue( - Element: TBoldElement; representation: Integer; Expression: String; - subscriber: TBoldsubscriber); + aFollower: TBoldFollower); begin - if element is TResidential_Building then - TResidential_Building(Element).M_TotalRent.RegisterModifiedValueHolder(subscriber); + if AFollower.element is TResidential_Building then + TResidential_Building(AFollower.Element).M_TotalRent.RegisterModifiedValueHolder(AFollower.subscriber); end; -procedure Tallform.bsrRentPerResidentReleaseChangedValue( - Element: TBoldElement; representation: Integer; Expression: String; - subscriber: TBoldSubscriber); +function Tallform.bsrRentPerResidentMayModify( + aFollower: TBoldFollower): Boolean; begin - if element is TResidential_Building then - TResidential_Building(Element).M_TotalRent.UnRegisterModifiedValueHolder(Subscriber); + Result := False; + if AFollower.element is TResidential_Building then + Result := TResidential_Building(AFollower.element).Residents.Count > 0; end; -procedure Tallform.bsrRentPerResidentSubscribe( - Element: TBoldElement; representation: Integer; Expression: String; - Subscriber: TBoldSubscriber); +procedure Tallform.bsrRentPerResidentReleaseChangedValue( + aFollower: TBoldFollower); begin - if element is TResidential_Building then - with Element do - begin - SubscribeToExpression('totalRent', Subscriber, False); - SubscribeToExpression('residents', Subscriber, False); - end; + if AFollower.element is TResidential_Building then + TResidential_Building(AFollower.Element).M_TotalRent.UnRegisterModifiedValueHolder(AFollower.Subscriber); end; -procedure Tallform.bsrRentPerResidentSetAsString( - Element: TBoldElement; value: string; representation: Integer; - Expression: String); +procedure Tallform.bsrRentPerResidentSetAsString(aFollower: TBoldFollower; + const NewValue: string); var v: string; begin - v := value; {avoid name clash} - if element is TResidential_Building then - with TResidential_Building(Element) do + v := NewValue; {avoid name clash} + if aFollower.element is TResidential_Building then + with TResidential_Building(aFollower.Element) do TotalRent := StrToCurr(v) * Residents.Count; end; +procedure Tallform.bsrRentPerResidentSubscribe(aFollower: TBoldFollower; + Subscriber: TBoldSubscriber); +begin + if AFollower.element is TResidential_Building then + with AFollower.Element do + begin + SubscribeToExpression('totalRent', Subscriber, False); + SubscribeToExpression('residents', Subscriber, False); + end; +end; + procedure Tallform.rgNameRepresentationClick(Sender: TObject); begin with blbBuildingOwners.BoldRowProperties do @@ -312,12 +371,6 @@ procedure Tallform.rgNameRepresentationClick(Sender: TObject); end; end; -procedure Tallform.btnChargeRentClick(Sender: TObject); -begin - if blhAllResidentialBuilding.CurrentBoldObject is TResidential_Building then - TResidential_Building(blhAllResidentialBuilding.CurrentBoldObject).ChargeRent; -end; - procedure Tallform.CheckBox1Click(Sender: TObject); begin if CheckBox1.Checked then @@ -334,25 +387,19 @@ procedure Tallform.CheckBox2Click(Sender: TObject); blhAllPerson.BoldComparer := nil; end; -function Tallform.bsrRentPerResidentMayModify( - element: TBoldElement; representation: Integer; - Expression: String; Subscriber: TBoldSubscriber): Boolean; +procedure Tallform.CheckBox3Click(Sender: TObject); begin - Result := False; - if element is TResidential_Building then - Result := TResidential_Building(element).Residents.Count > 0; + datamodule1.BoldSystemHandle1.System.UndoHandlerInterface.Enabled := (Sender as TCheckBox).Checked; end; -function Tallform.bsrRentPerResidentValidateCharacter( - element: TBoldElement; value: String; representation: Integer; - Expression: String): Boolean; +function Tallform.bsrRentPerResidentValidateCharacter(aFollower: TBoldFollower; + const Value: string): Boolean; begin - Result := value[1] in ['0'..'9', '-', '+', 'e', 'E', DecimalSeparator]; + Result := value[1] in ['0'..'9', '-', '+', 'e', 'E', FormatSettings.DecimalSeparator]; end; -function Tallform.bsrRentPerResidentValidateString( - element: TBoldElement; value: String; representation: Integer; - Expression: String): Boolean; +function Tallform.bsrRentPerResidentValidateString(aFollower: TBoldFollower; + const Value: string): Boolean; begin try StrToCurr(value); @@ -363,28 +410,26 @@ function Tallform.bsrRentPerResidentValidateString( end; function Tallform.bsrResidentsTotalAssetsGetAsString( - element: TBoldElement; representation: Integer; - Expression: String): String; + aFollower: TBoldFollower): string; var i: integer; sum: Currency; begin Sum := 0; - if element is TResidential_Building then - with TResidential_Building(Element) do + if AFollower.element is TResidential_Building then + with TResidential_Building(AFollower.Element) do for i := 0 to Residents.Count - 1 do Sum := Sum + Residents[i].Assets; Result := CurrToStr(Sum); end; -procedure Tallform.bsrResidentsTotalAssetsSubscribe(element: TBoldElement; - representation: Integer; Expression: String; +procedure Tallform.bsrResidentsTotalAssetsSubscribe(aFollower: TBoldFollower; Subscriber: TBoldSubscriber); var i: integer; begin - if element is TResidential_Building then - with TResidential_Building(Element) do + if AFollower.element is TResidential_Building then + with TResidential_Building(AFollower.Element) do begin SubscribeToExpression('residents', subscriber, true); for i := 0 to Residents.Count - 1 do @@ -392,23 +437,26 @@ procedure Tallform.bsrResidentsTotalAssetsSubscribe(element: TBoldElement; end; end; -procedure Tallform.bsrAddressSetColor( - element: TBoldElement; var aColor: TColor; representation: Integer; - Expression: String); +procedure Tallform.BoldModelEditorActionExecute(Sender: TObject); +begin + BoldUMLModelEdit.UMLModelEditor.ShowEditFormForBoldModel(DataModule1.BoldModel1); +end; + +procedure Tallform.bsrAddressSetColor(aFollower: TBoldFollower; + var AColor: TColor); begin - if Assigned(element) then - with TBuilding(element) do + if Assigned(AFollower.element) then + with TBuilding(AFollower.element) do begin if Pos('Bold', Address) > 0 then aColor := clAqua; end; end; -procedure Tallform.bsrAddressSetFont(element: TBoldElement; - aFont: TFont; representation: Integer; Expression: String); +procedure Tallform.bsrAddressSetFont(aFollower: TBoldFollower; AFont: TFont); begin - if Assigned(element) then - with TBuilding(element).M_Address do + if Assigned(AFollower.element) then + with TBuilding(AFollower.element).M_Address do begin if Pos( 'Bold', AsString ) > 0 then aFont.Style := aFont.Style + [fsBold]; @@ -432,50 +480,36 @@ function Tallform.CurrentBuildingHandle: TBoldListHandle; result := blhAllResidentialBuilding; end; -procedure Tallform.BoldActivateSystemAction1SystemOpened(Sender: TObject); +procedure Tallform.actChargeRentExecute(Sender: TObject); begin - Randomize; + if blhAllResidentialBuilding.CurrentBoldObject is TResidential_Building then + TResidential_Building(blhAllResidentialBuilding.CurrentBoldObject).ChargeRent; end; -procedure Tallform.HighRentRendererSetColor(Element: TBoldElement; - var AColor: TColor; Representation: Integer; Expression: String); +procedure Tallform.HighRentRendererSetColor(aFollower: TBoldFollower; + var AColor: TColor); begin - if element is TResidential_Building then + if AFollower.element is TResidential_Building then begin - if (TResidential_Building(element).totalRent) >= 1500 then + if (TResidential_Building(AFollower.element).totalRent) >= 1500 then aColor := clSilver else aColor := clWhite; end; end; -procedure Tallform.HighRentRendererSetFont(Element: TBoldElement; - AFont: TFont; Representation: Integer; Expression: String); +procedure Tallform.HighRentRendererSetFont(aFollower: TBoldFollower; + AFont: TFont); begin - if element is TResidential_Building then + if aFollower.element is TResidential_Building then begin - if (TResidential_Building(element).totalRent) >= 1500 then + if (TResidential_Building(aFollower.element).totalRent) >= 1500 then AFont.Color := clRed else AFont.Color := clWindowText; end; end; -procedure Tallform.btnCheckpointClick(Sender: TObject); -begin - datamodule1.BoldSystemHandle1.System.UndoHandlerInterface.SetCheckPoint; -end; - -procedure Tallform.btnUnDoClick(Sender: TObject); -begin - datamodule1.BoldSystemHandle1.System.UndoHandlerInterface.UnDoLatest; -end; - -procedure Tallform.btnRedoClick(Sender: TObject); -begin - datamodule1.BoldSystemHandle1.System.UndoHandlerInterface.Redolatest; -end; - end. diff --git a/examples/Delphi/Compound/Building/PersonAutoFormUnit.dfm b/examples/Delphi/Compound/Building/PersonAutoFormUnit.dfm index 6092292..265e6c5 100644 --- a/examples/Delphi/Compound/Building/PersonAutoFormUnit.dfm +++ b/examples/Delphi/Compound/Building/PersonAutoFormUnit.dfm @@ -1,9 +1,9 @@ object PersonAutoForm: TPersonAutoForm Left = 31 Top = 96 - Width = 323 - Height = 419 Caption = 'Person Detail' + ClientHeight = 380 + ClientWidth = 307 Color = clBtnFace Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText @@ -12,6 +12,7 @@ object PersonAutoForm: TPersonAutoForm Font.Style = [] OldCreateOrder = False Position = poScreenCenter + OnCreate = FormCreate PixelsPerInch = 96 TextHeight = 13 object Label1: TLabel @@ -126,15 +127,16 @@ object PersonAutoForm: TPersonAutoForm BoldAutoColumns = True BoldShowConstraints = False BoldHandle = blhOwnedBuildings - BoldProperties.NilElementMode = neNone Columns = < item + BoldProperties.Expression = '' Color = clBtnFace Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText Font.Height = -11 Font.Name = 'MS Sans Serif' Font.Style = [] + LookUpProperties.Expression = '' end item BoldProperties.Expression = 'zipCode' @@ -144,6 +146,7 @@ object PersonAutoForm: TPersonAutoForm Font.Name = 'MS Sans Serif' Font.Style = [] Title.Caption = 'ZipCode' + LookUpProperties.Expression = '' end item BoldProperties.Expression = 'address' @@ -153,6 +156,7 @@ object PersonAutoForm: TPersonAutoForm Font.Name = 'MS Sans Serif' Font.Style = [] Title.Caption = 'Address' + LookUpProperties.Expression = '' end item BoldProperties.Expression = 'owners->size' @@ -162,9 +166,16 @@ object PersonAutoForm: TPersonAutoForm Font.Name = 'MS Sans Serif' Font.Style = [] Title.Caption = '# owners' + LookUpProperties.Expression = '' end> DefaultRowHeight = 17 EnableColAdjust = False + Font.Charset = DEFAULT_CHARSET + Font.Color = clWindowText + Font.Height = -11 + Font.Name = 'MS Sans Serif' + Font.Style = [] + ParentFont = False TabOrder = 4 TitleFont.Charset = DEFAULT_CHARSET TitleFont.Color = clWindowText @@ -191,4 +202,10 @@ object PersonAutoForm: TPersonAutoForm Left = 24 Top = 168 end + object BoldCaptionController1: TBoldCaptionController + BoldHandle = brhPerson + BoldProperties.Expression = 'name' + Left = 160 + Top = 184 + end end diff --git a/examples/Delphi/Compound/Building/PersonAutoFormUnit.pas b/examples/Delphi/Compound/Building/PersonAutoFormUnit.pas index d3552ba..4531f5e 100644 --- a/examples/Delphi/Compound/Building/PersonAutoFormUnit.pas +++ b/examples/Delphi/Compound/Building/PersonAutoFormUnit.pas @@ -18,7 +18,7 @@ interface BoldGrid, StdCtrls, BoldCheckBox, - BoldEdit; + BoldEdit, BoldCaptionController; type TPersonAutoForm = class(TForm) @@ -34,7 +34,9 @@ TPersonAutoForm = class(TForm) brhPerson: TBoldReferenceHandle; blhOwnedBuildings: TBoldListHandle; Label5: TLabel; + BoldCaptionController1: TBoldCaptionController; procedure brhPersonObjectDeleted(Sender: TObject); + procedure FormCreate(Sender: TObject); private { Private declarations } public @@ -51,4 +53,10 @@ procedure TPersonAutoForm.brhPersonObjectDeleted(Sender: TObject); TForm(TComponent(Sender).Owner).Release; end; +procedure TPersonAutoForm.FormCreate(Sender: TObject); +begin + // Links the form caption to person name + BoldCaptionController1.TrackControl := self; +end; + end. From 6aa8dcf191d2673d96800fe706446e0e52df71bf Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Mon, 17 May 2021 20:29:38 +0300 Subject: [PATCH 021/112] Added new BoldDesignPackage, single package containing everything. --- BoldDesignPackage.dpk | 91 ++++ BoldDesignPackage.dproj | 896 ++++++++++++++++++++++++++++++++++++++++ BoldDesignPackage.res | Bin 0 -> 688 bytes 3 files changed, 987 insertions(+) create mode 100644 BoldDesignPackage.dpk create mode 100644 BoldDesignPackage.dproj create mode 100644 BoldDesignPackage.res diff --git a/BoldDesignPackage.dpk b/BoldDesignPackage.dpk new file mode 100644 index 0000000..a9ad097 --- /dev/null +++ b/BoldDesignPackage.dpk @@ -0,0 +1,91 @@ +package BoldDesignPackage; + +{$R *.res} +{$IFDEF IMPLICITBUILDING This IFDEF should not be used by users} +{$ALIGN 8} +{$ASSERTIONS ON} +{$BOOLEVAL OFF} +{$DEBUGINFO OFF} +{$EXTENDEDSYNTAX ON} +{$IMPORTEDDATA ON} +{$IOCHECKS ON} +{$LOCALSYMBOLS ON} +{$LONGSTRINGS ON} +{$OPENSTRINGS ON} +{$OPTIMIZATION OFF} +{$OVERFLOWCHECKS ON} +{$RANGECHECKS ON} +{$REFERENCEINFO ON} +{$SAFEDIVIDE OFF} +{$STACKFRAMES ON} +{$TYPEDADDRESS OFF} +{$VARSTRINGCHECKS ON} +{$WRITEABLECONST OFF} +{$MINENUMSIZE 1} +{$IMAGEBASE $400000} +{$DEFINE DEBUG} +{$DEFINE Bold_Delphi} +{$ENDIF IMPLICITBUILDING} +{$DESCRIPTION 'Bold 4.0 for Delphi'} +{$DESIGNONLY} +{$IMPLICITBUILD ON} + +requires + vcl, + vcldb, + DesignIDE, + FireDac, + FireDACCommonDriver, + FireDACCommon, + IndySystem, + IndyCore; + +contains + BoldExternalPersistenceHandlesReg in 'Source\Persistence\ExternalPersistence\BoldExternalPersistenceHandlesReg.pas', + BoldAction in 'Source\BoldAwareGUI\Actions\BoldAction.pas', + BoldAwareGuiReg in 'Source\BoldAwareGUI\IDE\BoldAwareGuiReg.pas', + BoldHandleReg in 'Source\Handles\IDE\BoldHandleReg.pas', + BoldUMLModelEditReg in 'Source\UMLModel\Ide\BoldUMLModelEditReg.pas', + BoldUMLModelLinkSupport in 'Source\UMLModel\ModelLinks\Core\BoldUMLModelLinkSupport.pas', + BoldTypeNameHandleReg in 'Source\MoldModel\IDE\BoldTypeNameHandleReg.pas', + BoldPersistenceHandleDBreg in 'Source\Persistence\DB\BoldPersistenceHandleDBreg.pas', + BoldSamplesReg in 'Source\Samples\IDE\BoldSamplesReg.pas', + BoldUMLRose98Linkreg in 'Source\UMLModel\ModelLinks\Rose98\BoldUMLRose98Linkreg.pas', + BoldHandleComReg in 'Source\ClientHandlesCom\IDE\BoldHandleComReg.pas', + BoldUMXMILinkreg in 'Source\UMLModel\ModelLinks\XMI\BoldUMXMILinkreg.pas', + BoldPersistenceHandleFileReg in 'Source\Persistence\IDE\BoldPersistenceHandleFileReg.pas', + BoldHandlesPropagationReg in 'Source\Persistence\IDE\BoldHandlesPropagationReg.pas', + BoldComReg in 'Source\Common\IDECOM\BoldComReg.pas', + BoldExternalObjectSpaceEventHandlerReg in 'Source\ObjectSpace\IDE\BoldExternalObjectSpaceEventHandlerReg.pas', + BoldPersistenceNotifierReg in 'Source\Persistence\IDE\BoldPersistenceNotifierReg.pas', + BoldOLLEHandlesReg in 'Source\Extensions\OLLE\IDE\BoldOLLEHandlesReg.pas', + BoldComPersistenceHandleReg in 'Source\Persistence\IDECOM\BoldComPersistenceHandleReg.pas', + BoldPersistenceHandleReg in 'Source\Persistence\IDE\BoldPersistenceHandleReg.pas', + BoldHTTPServerPersistenceHandlePassthroughReg in 'Source\Persistence\IDECOM\BoldHTTPServerPersistenceHandlePassthroughReg.pas', + BoldPropagatorHandleCOMReg in 'Source\Propagator\IDECOM\BoldPropagatorHandleCOMReg.pas', + BoldHTTPClientPersistenceHandleReg in 'Source\Persistence\IDECOM\BoldHTTPClientPersistenceHandleReg.pas', + BoldConcurrencyControlReg in 'Source\ConcurrencyControl\IDECOM\BoldConcurrencyControlReg.pas', + BoldUMLModelHandleReg in 'Source\UMLModel\Ide\BoldUMLModelHandleReg.pas', + BoldLockingReg in 'Source\Handles\IDE\BoldLockingReg.pas', + BoldManipulatorReg in 'Source\Handles\IDE\BoldManipulatorReg.pas', + BoldWebConnectionReg in 'Source\Common\IDE\BoldWebConnectionReg.pas', + BoldReg in 'Source\Common\IDE\BoldReg.pas', + BoldXMLDispatcherReg in 'Source\Common\IDECOM\BoldXMLDispatcherReg.pas', + BoldModelReg in 'Source\MoldModel\IDE\BoldModelReg.pas', + BoldPersistenceHandleSystemReg in 'Source\Persistence\IDE\BoldPersistenceHandleSystemReg.pas', + BoldObjectUpgraderHandleReg in 'Source\Persistence\IDE\BoldObjectUpgraderHandleReg.pas', + BoldComElementHandleReg in 'Source\Handles\IDECOM\BoldComElementHandleReg.pas', + BoldUDPBroadcasterReg in 'Source\Persistence\IDEUDP\BoldUDPBroadcasterReg.pas', + BoldSelectionListBoxReg in 'Source\Samples\BoldCheckListBox\BoldSelectionListBoxReg.pas', + BoldCheckListBoxReg in 'Source\Samples\BoldCheckListBox\BoldCheckListBoxReg.pas', + BoldXMLDispatcherVBReg in 'Source\Common\IDECOM\BoldXMLDispatcherVBReg.pas', + BoldXMLReg in 'Source\Handles\IDE\BoldXMLReg.pas', + BoldAFPPluggableReg in 'Source\BoldAwareGUI\FormGen\BoldAFPPluggableReg.pas', + BoldAwareGuiComReg in 'Source\ClientGuiCom\IDE\BoldAwareGuiComReg.pas', + BoldPersistenceHandleFireDACReg in 'Source\Persistence\FireDAC\BoldPersistenceHandleFireDACReg.pas', + BoldPersistenceHandleFireDAC in 'Source\Persistence\FireDAC\BoldPersistenceHandleFireDAC.pas', + BoldDatabaseAdapterFireDAC in 'Source\Persistence\FireDAC\BoldDatabaseAdapterFireDAC.pas', + BoldFireDACInterfaces in 'Source\Persistence\FireDAC\BoldFireDACInterfaces.pas', + BoldFireDACConsts in 'Source\Persistence\FireDAC\BoldFireDACConsts.pas'; + +end. diff --git a/BoldDesignPackage.dproj b/BoldDesignPackage.dproj new file mode 100644 index 0000000..8e68937 --- /dev/null +++ b/BoldDesignPackage.dproj @@ -0,0 +1,896 @@ + + + {BA681BD2-4AA5-4AB0-8850-FFE2B8AAC9E0} + BoldDesignPackage.dpk + 19.2 + None + True + Debug + Win32 + 1 + Package + + + true + + + true + Base + true + + + true + Base + true + + + true + Cfg_1 + true + true + + + true + Base + true + + + .\$(Platform)\$(Config) + .\$(Platform)\$(Config) + false + false + false + false + false + true + true + Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;System;Xml;Data;Datasnap;Web;Soap;Winapi;$(DCC_Namespace) + All + BoldDesignPackage + $(BoldDelphi)\Source\UMLModel\Handles;$(BoldDelphi)\Source\Common\Subscription;$(BoldDelphi)\Source\Common\Include;$(BoldDelphi)\Source\Common\Core;$(BoldDelphi)\Source\Common\Support;$(BoldDelphi)\Source\Common\Queue;$(BoldDelphi)\Source\MoldModel\Handles;$(BoldDelphi)\Source\MoldModel\Core;$(BoldDelphi)\Source\Common\UML;$(BoldDelphi)\Source\MoldModel\TypeNameDictionary;$(BoldDelphi)\Source\Common\TaggedValues;$(BoldDelphi)\Source\ValueSpace\XMLStreaming;$(BoldDelphi)\Source\MoldModel\Bld;$(BoldDelphi)\Source\Common\Environment;$(BoldDelphi)\Source\Common\TaggedValues;$(BoldDelphi)\Source\Common\TaggedValues;$(BoldDelphi)\Source\Handles\Core;$(BoldDelphi)\Source\ObjectSpace\BORepresentation;$(BoldDelphi)\Source\ObjectSpace\RTModel;$(BoldDelphi)\Source\ObjectSpace\Core;$(BoldDelphi)\Source\ObjectSpace\Ocl;$(BoldDelphi)\Source\Persistence\Core;$(BoldDelphi)\Source\FreestandingValueSpace\Core;$(BoldDelphi)\Source\ValueSpace\Id;$(BoldDelphi)\Source\Common\MsXml;$(BoldDelphi)\Source\ValueSpace\Interfaces;$(BoldDelphi)\Source\ValueSpace\Condition;$(BoldDelphi)\Source\ValueSpace\Condition;$(BoldDelphi)\Source\Persistence\DB;$(BoldDelphi)\Source\PMapper\SQL;$(BoldDelphi)\Source\Common\Logging;$(BoldDelphi)\Source\ObjectSpace\Interfaces;$(BoldDelphi)\Source\ObjectSpace\PessimisticLocking;$(BoldDelphi)\Source\ObjectSpace\Undo;$(BoldDelphi)\Source\ObjectSpace\UtilsGUI;$(BoldDelphi)\Source\Common\Handles;$(BoldDelphi)\Source\Persistence\ObjectUpgrading;$(BoldDelphi)\Source\PMapper\Core;$(BoldDelphi)\Source\PMapper\Default;$(BoldDelphi)\Source\Common\UtilsGUI;$(BoldDelphi)\Source\Persistence\Propagation;$(BoldDelphi)\Source\UMLModel\Core;$(BoldDelphi)\Source\UMLModel\ModelLinks\Rose98;$(BoldDelphi)\Source\UMLModel\ModelLinks\Core;$(BoldDelphi)\Source\Common\Rose98;$(BoldDelphi)\Source\UMLModel\Editor;$(BoldDelphi)\Source\BoldAwareGUI\BoldControls;$(BoldDelphi)\Source\BoldAwareGUI\BoldControls;$(BoldDelphi)\Source\BoldAwareGUI\ControlPacks;$(BoldDelphi)\Source\BoldAwareGUI\Core;$(BoldDelphi)\Source\BoldAwareGUI\FormGen;$(BoldDelphi)\Source\UMLModel\Plugins;$(BoldDelphi)\Source\Common\IDE;$(BoldDelphi)\Source\Handles\Actions\;$(BoldDelphi)\Source\Persistence\IBX;$(BoldDelphi)\Source\Persistence\ExternalPersistence;$(BoldDelphi)\Source\BoldAwareGUI\IDE;$(BoldDelphi)\Source\ClientGuiCom\IDE;$(BoldDelphi)\Source\Handles\IDE;$(BoldDelphi)\Source\Handles\UnLoader;$(BoldDelphi)\Source\ObjectSpace\Unloader;$(BoldDelphi)\Source\MoldModel\UtilsGUI;$(BoldDelphi)\Source\Samples\FormSaver;$(BoldDelphi)\Source\Samples\NewObjectInterceptor;$(BoldDelphi)\Source\Samples\Actions;$(BoldDelphi)\Source\Samples\Misc;$(BoldDelphi)\Source\Samples\IDE;$(BoldDelphi)\Source\Samples\SystemDebugger;$(BoldDelphi)\Source\ClientHandlesCom\Core;$(BoldDelphi)\Source\ObjectSpace\COM;$(BoldDelphi)\Source\Common\COM;$(BoldDelphi)\Source\Common\ConnectionCOM;$(BoldDelphi)\Source\Common\Connection;$(BoldDelphi)\Source\Common\ConnectionHandlesCOM;$(BoldDelphi)\Source\UMLModel\ModelLinks\Bld;$(BoldDelphi)\Source\Common\ConnectionHandles;$(BoldDelphi)\Source\Common\IDECOM;$(BoldDelphi)\Source\UMLModel\ModelLinks\XMI;$(BoldDelphi)\Source\Persistence\File;$(BoldDelphi)\Source\Propagator\Common;$(BoldDelphi)\Source\ConcurrencyControl\Common;$(BoldDelphi)\Source\ValueSpace\ExternalEvents;$(BoldDelphi)\Source\Common\SupportWin;$(BoldDelphi)\Source\Persistence\DBExpress;$(BoldDelphi)\Source\Persistence\System;$(BoldDelphi)\Source\Persistence\UDPPropagator;$(BoldDelphi)\Source\Persistence\COM;$(BoldDelphi)\Source\Extensions\OLLE\Core;$(BoldDelphi)\Source\Extensions\OLLE\IDE;$(BoldDelphi)\Source\Persistence\SOAP;$(BoldDelphi)\Source\Common\SOAP;$(BoldDelphi)\Source\Persistence\HTTP;$(BoldDelphi)\Source\Propagator\COM;$(BoldDelphi)\Source\Propagator\IDECOM;$(BoldDelphi)\Source\Propagator\Enterprise;$(BoldDelphi)\Source\Common\HTTP;$(BoldDelphi)\Source\ConcurrencyControl\COM;$(BoldDelphi)\Source\ConcurrencyControl\IDECOM;$(BoldDelphi)\Source\Handles\PessimisticLocking;$(BoldDelphi)\Source\Handles\Manipulators;$(BoldDelphi)\Source\Handles\XML;$(BoldDelphi)\Source\Handles\COM;$(BoldDelphi)\Source\Handles\IDECOM;$(BoldDelphi)\Source\Handles\Actions;$(BoldDelphi)\Source\Samples\BoldCheckListBox;$(BoldDelphi)\Source\ClientGuiCom\BoldControls;$(BoldDelphi)\Source\ClientGuiCom\ControlPacks;$(BoldDelphi)\Source\ClientGuiCom\Core;$(DCC_UnitSearchPath) + 2077 + CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments= + true + true + true + true + true + Bold 4.0 for Delphi + Bold_Delphi;$(DCC_Define) + true + + + System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) + Debug + true + CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments= + 1033 + + + DEBUG;$(DCC_Define) + true + false + true + true + true + + + false + true + 1033 + + + false + RELEASE;$(DCC_Define) + 0 + 0 + + + + MainSource + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Cfg_2 + Base + + + Base + + + Cfg_1 + Base + + + + Delphi.Personality.12 + Package + + + + BoldDesignPackage.dpk + + + Microsoft Office 2000 Sample Automation Server Wrapper Components + Microsoft Office XP Sample Automation Server Wrapper Components + + + + + + true + + + + + true + + + + + true + + + + + BoldDesignPackage.bpl + true + + + + + 1 + + + 0 + + + + + classes + 1 + + + classes + 1 + + + + + res\xml + 1 + + + res\xml + 1 + + + + + library\lib\armeabi-v7a + 1 + + + + + library\lib\armeabi + 1 + + + library\lib\armeabi + 1 + + + + + library\lib\armeabi-v7a + 1 + + + + + library\lib\mips + 1 + + + library\lib\mips + 1 + + + + + library\lib\armeabi-v7a + 1 + + + library\lib\arm64-v8a + 1 + + + + + library\lib\armeabi-v7a + 1 + + + + + res\drawable + 1 + + + res\drawable + 1 + + + + + res\values + 1 + + + res\values + 1 + + + + + res\values-v21 + 1 + + + res\values-v21 + 1 + + + + + res\values + 1 + + + res\values + 1 + + + + + res\drawable + 1 + + + res\drawable + 1 + + + + + res\drawable-xxhdpi + 1 + + + res\drawable-xxhdpi + 1 + + + + + res\drawable-xxxhdpi + 1 + + + res\drawable-xxxhdpi + 1 + + + + + res\drawable-ldpi + 1 + + + res\drawable-ldpi + 1 + + + + + res\drawable-mdpi + 1 + + + res\drawable-mdpi + 1 + + + + + res\drawable-hdpi + 1 + + + res\drawable-hdpi + 1 + + + + + res\drawable-xhdpi + 1 + + + res\drawable-xhdpi + 1 + + + + + res\drawable-mdpi + 1 + + + res\drawable-mdpi + 1 + + + + + res\drawable-hdpi + 1 + + + res\drawable-hdpi + 1 + + + + + res\drawable-xhdpi + 1 + + + res\drawable-xhdpi + 1 + + + + + res\drawable-xxhdpi + 1 + + + res\drawable-xxhdpi + 1 + + + + + res\drawable-xxxhdpi + 1 + + + res\drawable-xxxhdpi + 1 + + + + + res\drawable-small + 1 + + + res\drawable-small + 1 + + + + + res\drawable-normal + 1 + + + res\drawable-normal + 1 + + + + + res\drawable-large + 1 + + + res\drawable-large + 1 + + + + + res\drawable-xlarge + 1 + + + res\drawable-xlarge + 1 + + + + + res\values + 1 + + + res\values + 1 + + + + + 1 + + + 1 + + + 0 + + + + + 1 + .framework + + + 1 + .framework + + + 0 + + + + + 1 + .dylib + + + 1 + .dylib + + + 0 + .dll;.bpl + + + + + 1 + .dylib + + + 1 + .dylib + + + 1 + .dylib + + + 1 + .dylib + + + 1 + .dylib + + + 0 + .bpl + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + 1 + + + 1 + + + + + ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF + 1 + + + ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF + 1 + + + + + + + + 1 + + + 1 + + + 1 + + + + + + + + Contents\Resources + 1 + + + Contents\Resources + 1 + + + + + library\lib\armeabi-v7a + 1 + + + library\lib\arm64-v8a + 1 + + + 1 + + + 1 + + + 1 + + + 1 + + + 1 + + + 1 + + + 0 + + + + + library\lib\armeabi-v7a + 1 + + + + + 1 + + + 1 + + + + + Assets + 1 + + + Assets + 1 + + + + + Assets + 1 + + + Assets + 1 + + + + + + + + + + + + + + + True + False + + + 12 + + + + + diff --git a/BoldDesignPackage.res b/BoldDesignPackage.res new file mode 100644 index 0000000000000000000000000000000000000000..79ffeb0ee02001863d5662f0121d3607c66e8699 GIT binary patch literal 688 zcma))%}T>i5QR@l7S@&c1R|~_LNDRr?xdHd zUG>7;OzxaH^D9Y5NLAH>x^beGw;zBB%oeE~dQjAgQHOfe6Zf?SXk9(%p8qcQ4Z1tu z;qRa1{A&*Xy)>)j2)$+Xq%R%<_?9Y_sn86zOu42o7kbqKU~ZU5u_B!#F*&%5dOF0{ z;}d*7G&Y`h_%eJ83v-2*YoZ#F5u;FFBd~AWGyDYWUW04MTM65m<4mVuyhzVF2Hyv@ zfT4tEPR5DF8}l{?JLP`CQW9xIe8;)qeV2R^tF7jr=o5w|opw=Nw%Um!wwg9MwkzAN z%T*9CWtX+@?0OQ?iA^!JiVHfFgKYM?9sY!@lP-{|+NVQ3b(GqU40MOqVSjF!V9M0% J)7&+;AOD&GU Date: Mon, 17 May 2021 23:11:49 +0300 Subject: [PATCH 022/112] Updated Buildings demo --- .../Compound/Building/BuildingClasses.pas | 24 +++++++++-- .../Building/BuildingClasses_Interface.inc | 7 ++- examples/Delphi/Compound/Building/Datamod.dfm | 42 ++++++++++++++++++ examples/Delphi/Compound/Building/Datamod.pas | 4 +- .../Delphi/Compound/Building/Mainform.dfm | 7 +-- .../Delphi/Compound/Building/Mainform.pas | 1 - .../Compound/Building/PersonAutoFormUnit.dfm | 43 +++++++++++++++---- .../Compound/Building/PersonAutoFormUnit.pas | 7 ++- .../Compound/Building/ResidentialBuilding.inc | 4 +- 9 files changed, 116 insertions(+), 23 deletions(-) diff --git a/examples/Delphi/Compound/Building/BuildingClasses.pas b/examples/Delphi/Compound/Building/BuildingClasses.pas index 8ff3bf0..e0a1cdc 100644 --- a/examples/Delphi/Compound/Building/BuildingClasses.pas +++ b/examples/Delphi/Compound/Building/BuildingClasses.pas @@ -2,7 +2,7 @@ (* This file is autogenerated *) (* Any manual changes will be LOST! *) (*****************************************) -(* Generated 17.05.2021 12:57:35 *) +(* Generated 17.05.2021 21:03:18 *) (*****************************************) (* This file should be stored in the *) (* same directory as the form/datamodule *) @@ -372,10 +372,26 @@ procedure TResidential_Building._SetTotalRent(const NewValue: Currency); M_TotalRent.AsCurrency := NewValue; end; +function TResidential_Building._Get_M_Capacity: TBAInteger; +begin + assert(ValidateMember('TResidential_Building', 'Capacity', 5, TBAInteger)); + Result := TBAInteger(BoldMembers[5]); +end; + +function TResidential_Building._GetCapacity: Integer; +begin + Result := M_Capacity.AsInteger; +end; + +procedure TResidential_Building._SetCapacity(const NewValue: Integer); +begin + M_Capacity.AsInteger := NewValue; +end; + function TResidential_Building._GetResidents: TPersonList; begin - assert(ValidateMember('TResidential_Building', 'Residents', 5, TPersonList)); - Result := TPersonList(BoldMembers[5]); + assert(ValidateMember('TResidential_Building', 'Residents', 6, TPersonList)); + Result := TPersonList(BoldMembers[6]); end; procedure TResidential_BuildingList.Add(NewObject: TResidential_Building); @@ -417,7 +433,7 @@ procedure TResidential_BuildingList.SetBoldObject(index: Integer; NewObject: TRe function GeneratedCodeCRC: String; begin - result := '1756829375'; + result := '63867191'; end; procedure InstallObjectListClasses(BoldObjectListClasses: TBoldGeneratedClassList); diff --git a/examples/Delphi/Compound/Building/BuildingClasses_Interface.inc b/examples/Delphi/Compound/Building/BuildingClasses_Interface.inc index 0cb992b..d4083de 100644 --- a/examples/Delphi/Compound/Building/BuildingClasses_Interface.inc +++ b/examples/Delphi/Compound/Building/BuildingClasses_Interface.inc @@ -2,7 +2,7 @@ (* This file is autogenerated *) (* Any manual changes will be LOST! *) (*****************************************) -(* Generated 17.05.2021 12:57:35 *) +(* Generated 17.05.2021 21:03:19 *) (*****************************************) (* This file should be stored in the *) (* same directory as the form/datamodule *) @@ -143,14 +143,19 @@ type function _Get_M_TotalRent: TBACurrency; function _GetTotalRent: Currency; procedure _SetTotalRent(const NewValue: Currency); + function _Get_M_Capacity: TBAInteger; + function _GetCapacity: Integer; + procedure _SetCapacity(const NewValue: Integer); function _GetResidents: TPersonList; protected public procedure ChargeRent; procedure CompleteCreate; override; property M_TotalRent: TBACurrency read _Get_M_TotalRent; + property M_Capacity: TBAInteger read _Get_M_Capacity; property M_Residents: TPersonList read _GetResidents; property TotalRent: Currency read _GetTotalRent write _SetTotalRent; + property Capacity: Integer read _GetCapacity write _SetCapacity; property Residents: TPersonList read _GetResidents; end; diff --git a/examples/Delphi/Compound/Building/Datamod.dfm b/examples/Delphi/Compound/Building/Datamod.dfm index a91ccee..9b650db 100644 --- a/examples/Delphi/Compound/Building/Datamod.dfm +++ b/examples/Delphi/Compound/Building/Datamod.dfm @@ -209,6 +209,16 @@ object DataModule1: TDataModule1 #9#9#9#9#9'""' #9#9#9#9#9'"_BoldInternal.toolId=39885C1B002E,persistence=persistent"' #9#9#9#9')' + #9#9#9#9'(Attribute' + #9#9#9#9#9'"Capacity"' + #9#9#9#9#9'"Integer"' + #9#9#9#9#9'FALSE' + #9#9#9#9#9'""' + #9#9#9#9#9'""' + #9#9#9#9#9'2' + #9#9#9#9#9'""' + #9#9#9#9#9'"derived=False,persistence=persistent"' + #9#9#9#9')' #9#9#9')' #9#9#9'(Methods' #9#9#9#9'(Method' @@ -359,6 +369,7 @@ object DataModule1: TDataModule1 AutoActivate = True SystemTypeInfoHandle = BoldSystemTypeInfoHandle1 Active = False + PersistenceHandle = BoldPersistenceHandleDB1 Left = 128 Top = 8 end @@ -524,8 +535,39 @@ object DataModule1: TDataModule1 'MARS=yes' 'Database=Buildings' 'DriverID=MSSQL') + TxOptions.Isolation = xiRepeatableRead LoginPrompt = False Left = 384 Top = 256 end + object BoldConstraintValidatorOnModify: TBoldConstraintValidator + StaticSystemHandle = BoldSystemHandle1 + Constraints = < + item + Context = 'Residential_Building' + Expression = 'residents->size <= capacity' + ErrorMessage = #39'Building capacity limit is '#39' + capacity.asString' + end> + ValidationMode = vmOnModify + Enabled = True + Left = 424 + Top = 56 + end + object BoldConstraintValidatorOnUpdate: TBoldConstraintValidator + StaticSystemHandle = BoldSystemHandle1 + Constraints = < + item + Context = 'Person' + Expression = + '(ownedBuildings->filterOnType(Residential_Building)->notEmpty'#13#10')' + + ' implies (home <> nil)'#13#10 + ErrorMessage = + 'name + '#39' can not be homeless while owning at least one non full ' + + 'residential building'#39 + end> + ValidationMode = vmPreUpdate + Enabled = True + Left = 424 + Top = 128 + end end diff --git a/examples/Delphi/Compound/Building/Datamod.pas b/examples/Delphi/Compound/Building/Datamod.pas index 5c5ab07..fb387c2 100644 --- a/examples/Delphi/Compound/Building/Datamod.pas +++ b/examples/Delphi/Compound/Building/Datamod.pas @@ -43,7 +43,7 @@ interface FireDAC.DApt, BoldAbstractPropagatorHandle, BoldPropagatorHandleCOM, BoldPersistenceHandlePassthrough, BoldPersistenceHandlePTWithModel, BoldSnooperHandle, BoldAbstractDequeuer, - BoldExternalObjectSpaceEventHandler; + BoldExternalObjectSpaceEventHandler, BoldConstraintValidator; type TDataModule1 = class(TDataModule) @@ -59,6 +59,8 @@ TDataModule1 = class(TDataModule) BoldPersistenceHandleDB1: TBoldPersistenceHandleDB; BoldDatabaseAdapterFireDAC1: TBoldDatabaseAdapterFireDAC; FDConnection1: TFDConnection; + BoldConstraintValidatorOnModify: TBoldConstraintValidator; + BoldConstraintValidatorOnUpdate: TBoldConstraintValidator; function NameComparerCompare(item1, item2: TBoldElement): Integer; procedure NameComparerSubscribe(boldElement: TBoldElement; subscriber: TBoldSubscriber); function IsRichFilterFilter(element: TBoldElement): Boolean; diff --git a/examples/Delphi/Compound/Building/Mainform.dfm b/examples/Delphi/Compound/Building/Mainform.dfm index 16547e0..5295418 100644 --- a/examples/Delphi/Compound/Building/Mainform.dfm +++ b/examples/Delphi/Compound/Building/Mainform.dfm @@ -26,9 +26,9 @@ object allform: Tallform object Label8: TLabel Left = 32 Top = 464 - Width = 32 + Width = 30 Height = 13 - Caption = 'Label8' + Caption = 'Status' end object PersonGroup: TGroupBox Left = 208 @@ -965,9 +965,6 @@ object allform: Tallform object UpdateDB1: TMenuItem Action = BoldUpdateDBAction1 end - object BoldFailureDetectionAction11: TMenuItem - Action = BoldFailureDetectionAction1 - end object Systemdebugger1: TMenuItem Action = BoldSystemDebuggerAction1 end diff --git a/examples/Delphi/Compound/Building/Mainform.pas b/examples/Delphi/Compound/Building/Mainform.pas index 04e1311..d90a8d4 100644 --- a/examples/Delphi/Compound/Building/Mainform.pas +++ b/examples/Delphi/Compound/Building/Mainform.pas @@ -135,7 +135,6 @@ Tallform = class(TForm) CreateDB1: TMenuItem; Opensystem2: TMenuItem; UpdateDB1: TMenuItem; - BoldFailureDetectionAction11: TMenuItem; ogglelog1: TMenuItem; Systemdebugger1: TMenuItem; Edit1: TMenuItem; diff --git a/examples/Delphi/Compound/Building/PersonAutoFormUnit.dfm b/examples/Delphi/Compound/Building/PersonAutoFormUnit.dfm index 265e6c5..0f486c3 100644 --- a/examples/Delphi/Compound/Building/PersonAutoFormUnit.dfm +++ b/examples/Delphi/Compound/Building/PersonAutoFormUnit.dfm @@ -36,16 +36,9 @@ object PersonAutoForm: TPersonAutoForm Height = 13 Caption = 'Assets' end - object Label3: TLabel - Left = 9 - Top = 116 - Width = 82 - Height = 13 - Caption = 'Owned Buildings:' - end object Label5: TLabel Left = 8 - Top = 272 + Top = 346 Width = 214 Height = 26 Caption = @@ -53,6 +46,20 @@ object PersonAutoForm: TPersonAutoForm 'module' WordWrap = True end + object Label3: TLabel + Left = 9 + Top = 116 + Width = 82 + Height = 13 + Caption = 'Owned Buildings:' + end + object Label6: TLabel + Left = 8 + Top = 269 + Width = 31 + Height = 13 + Caption = 'Home:' + end object BoldEdit1: TBoldEdit Left = 8 Top = 67 @@ -188,6 +195,20 @@ object PersonAutoForm: TPersonAutoForm 64 64) end + object BoldComboBox1: TBoldComboBox + Left = 8 + Top = 288 + Width = 249 + Height = 21 + Alignment = taLeftJustify + BoldHandle = brhPerson + BoldListHandle = blhOwnedResidentialBuildings + BoldProperties.Expression = 'home' + BoldRowProperties.Expression = '' + BoldSetValueExpression = 'home' + BoldSelectChangeAction = bdcsSetValue + TabOrder = 5 + end object brhPerson: TBoldReferenceHandle StaticSystemHandle = DataModule1.BoldSystemHandle1 StaticValueTypeName = 'Person' @@ -208,4 +229,10 @@ object PersonAutoForm: TPersonAutoForm Left = 160 Top = 184 end + object blhOwnedResidentialBuildings: TBoldListHandle + RootHandle = brhPerson + Expression = 'ownedBuildings->filterOnType(Residential_Building)' + Left = 24 + Top = 240 + end end diff --git a/examples/Delphi/Compound/Building/PersonAutoFormUnit.pas b/examples/Delphi/Compound/Building/PersonAutoFormUnit.pas index 4531f5e..edcb18a 100644 --- a/examples/Delphi/Compound/Building/PersonAutoFormUnit.pas +++ b/examples/Delphi/Compound/Building/PersonAutoFormUnit.pas @@ -18,14 +18,13 @@ interface BoldGrid, StdCtrls, BoldCheckBox, - BoldEdit, BoldCaptionController; + BoldEdit, BoldCaptionController, BoldComboBox; type TPersonAutoForm = class(TForm) Label1: TLabel; Label2: TLabel; Label4: TLabel; - Label3: TLabel; BoldEdit1: TBoldEdit; beFirstName: TBoldEdit; BoldEdit7: TBoldEdit; @@ -35,6 +34,10 @@ TPersonAutoForm = class(TForm) blhOwnedBuildings: TBoldListHandle; Label5: TLabel; BoldCaptionController1: TBoldCaptionController; + BoldComboBox1: TBoldComboBox; + Label3: TLabel; + Label6: TLabel; + blhOwnedResidentialBuildings: TBoldListHandle; procedure brhPersonObjectDeleted(Sender: TObject); procedure FormCreate(Sender: TObject); private diff --git a/examples/Delphi/Compound/Building/ResidentialBuilding.inc b/examples/Delphi/Compound/Building/ResidentialBuilding.inc index 97f9297..532e74d 100644 --- a/examples/Delphi/Compound/Building/ResidentialBuilding.inc +++ b/examples/Delphi/Compound/Building/ResidentialBuilding.inc @@ -15,12 +15,13 @@ procedure TResidential_Building.ChargeRent; var O, R: Integer; begin + if Residents.Count = 0 then raise Exception.Create('No residents to pay rent'); if Owners.Count = 0 then raise Exception.Create('No owners to receive payment'); - + for R := Residents.Count - 1 downto 0 do with Residents[R] do begin @@ -43,6 +44,7 @@ begin inherited; Address := IntToStr(Random(250)) + ' ' + streets[random(5)]; TotalRent := random(100) * 100; + Capacity := random(20); end; From 37c8c152a1e2eb7bcee8b3748fad5482d9362c3e Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Mon, 17 May 2021 23:13:55 +0300 Subject: [PATCH 023/112] Added BoldConstraintValidator --- BoldDesignPackage.dpk | 4 +- BoldUml.dpk | 51 +- BoldVCLGUI.dpk | 52 +- .../BoldAwareGUI/FormGen/BoldAFPDefault.pas | 7 +- .../FireDAC/BoldFireDACInterfaces.pas | 1 + .../BoldConstraintValidator.pas | 601 ++++++++++++++++++ 6 files changed, 665 insertions(+), 51 deletions(-) create mode 100644 Source/Samples/ConstraintValidator/BoldConstraintValidator.pas diff --git a/BoldDesignPackage.dpk b/BoldDesignPackage.dpk index a9ad097..9b43a8f 100644 --- a/BoldDesignPackage.dpk +++ b/BoldDesignPackage.dpk @@ -86,6 +86,8 @@ contains BoldPersistenceHandleFireDAC in 'Source\Persistence\FireDAC\BoldPersistenceHandleFireDAC.pas', BoldDatabaseAdapterFireDAC in 'Source\Persistence\FireDAC\BoldDatabaseAdapterFireDAC.pas', BoldFireDACInterfaces in 'Source\Persistence\FireDAC\BoldFireDACInterfaces.pas', - BoldFireDACConsts in 'Source\Persistence\FireDAC\BoldFireDACConsts.pas'; + BoldFireDACConsts in 'Source\Persistence\FireDAC\BoldFireDACConsts.pas', + BoldConstraintValidator in 'Source\Samples\ConstraintValidator\BoldConstraintValidator.pas', + BoldConstraintValidatorReg in 'Source\Samples\ConstraintValidator\BoldConstraintValidatorReg.pas'; end. diff --git a/BoldUml.dpk b/BoldUml.dpk index 2706a0e..2b1191b 100644 --- a/BoldUml.dpk +++ b/BoldUml.dpk @@ -1,33 +1,34 @@ package BoldUml; {$R *.res} -{A}{ ALIGN ON} -{C}{ ASSERTIONS ON} -{B}{ BOOLEVAL OFF} -{D}{ DEBUGINFO ON} -{X}{ EXTENDEDSYNTAX ON} -{G}{ IMPORTEDDATA ON} -{I}{ IOCHECKS ON} -{L}{ LOCALSYMBOLS ON} -{H}{ LONGSTRINGS ON} -{Z1}{ MINENUMSIZE 1} -{P}{ OPENSTRINGS ON} -{O}{ OPTIMIZATION OFF} -{Q}{ OVERFLOWCHECKS ON} -{R}{ RANGECHECKS ON} -{U}{ SAFEDIVIDE OFF} -{W}{ STACKFRAMES ON} -{T}{ TYPEDADDRESS OFF} -{V}{ VARSTRINGCHECKS ON} -{J}{ WRITEABLECONST ON} - -{$IMAGEBASE $00400000} -{$DESIGNONLY} +{$IFDEF IMPLICITBUILDING This IFDEF should not be used by users} +{ ALIGN 8} +{ ASSERTIONS ON} +{ BOOLEVAL OFF} +{ DEBUGINFO ON} +{ EXTENDEDSYNTAX ON} +{ IMPORTEDDATA ON} +{ IOCHECKS ON} +{ LOCALSYMBOLS ON} +{ LONGSTRINGS ON} +{ OPENSTRINGS ON} +{ OPTIMIZATION OFF} +{ OVERFLOWCHECKS ON} +{ RANGECHECKS ON} {$REFERENCEINFO ON} -{$IMPLICITBUILD ON} - +{ SAFEDIVIDE OFF} +{ STACKFRAMES ON} +{ TYPEDADDRESS OFF} +{ VARSTRINGCHECKS ON} +{ WRITEABLECONST ON} +{ MINENUMSIZE 1} +{$IMAGEBASE $400000} +{$DEFINE DEBUG} +{$ENDIF IMPLICITBUILDING} {$DESCRIPTION 'Bold 4.0 for Delphi (Model editor)'} {$LIBSUFFIX '90'} +{$DESIGNONLY} +{$IMPLICITBUILD ON} requires vcl, @@ -72,6 +73,8 @@ contains BoldUMLBldLink in 'Source\UMLModel\ModelLinks\Bld\BoldUMLBldLink.pas', BoldCodePlugins in 'Source\UMLModel\Plugins\BoldCodePlugins.pas', BoldDbPlugins in 'Source\UMLModel\Plugins\BoldDbPlugins.pas', + BoldConstraintValidator in 'Source\Samples\ConstraintValidator\BoldConstraintValidator.pas', + BoldConstraintValidatorReg in 'Source\Samples\ConstraintValidator\BoldConstraintValidatorReg.pas', BoldModelOCLValidatorPlugIn in 'Source\UMLModel\Plugins\BoldModelOCLValidatorPlugIn.pas', BoldUMLModelEditPlugIn in 'Source\UMLModel\Plugins\BoldUMLModelEditPlugIn.pas', BoldUMLPluginCallBacks in 'Source\UMLModel\Plugins\BoldUMLPluginCallBacks.pas', diff --git a/BoldVCLGUI.dpk b/BoldVCLGUI.dpk index f9d804f..772595f 100644 --- a/BoldVCLGUI.dpk +++ b/BoldVCLGUI.dpk @@ -1,33 +1,34 @@ package BoldVCLGUI; -{$R *.RES} -{A}{ ALIGN ON} -{C}{ ASSERTIONS ON} -{B}{ BOOLEVAL OFF} -{D}{ DEBUGINFO ON} -{X}{ EXTENDEDSYNTAX ON} -{G}{ IMPORTEDDATA ON} -{I}{ IOCHECKS ON} -{L}{ LOCALSYMBOLS ON} -{H}{ LONGSTRINGS ON} -{Z1}{ MINENUMSIZE 1} -{P}{ OPENSTRINGS ON} -{O}{ OPTIMIZATION OFF} -{Q}{ OVERFLOWCHECKS ON} -{R}{ RANGECHECKS ON} -{U}{ SAFEDIVIDE OFF} -{W}{ STACKFRAMES ON} -{T}{ TYPEDADDRESS OFF} -{V}{ VARSTRINGCHECKS ON} -{J}{ WRITEABLECONST ON} - -{$IMAGEBASE $00400000} -{$DESIGNONLY} +{$R *.res} +{$IFDEF IMPLICITBUILDING This IFDEF should not be used by users} +{ ALIGN 8} +{ ASSERTIONS ON} +{ BOOLEVAL OFF} +{ DEBUGINFO ON} +{ EXTENDEDSYNTAX ON} +{ IMPORTEDDATA ON} +{ IOCHECKS ON} +{ LOCALSYMBOLS ON} +{ LONGSTRINGS ON} +{ OPENSTRINGS ON} +{ OPTIMIZATION OFF} +{ OVERFLOWCHECKS ON} +{ RANGECHECKS ON} {$REFERENCEINFO ON} -{$IMPLICITBUILD ON} - +{ SAFEDIVIDE OFF} +{ STACKFRAMES ON} +{ TYPEDADDRESS OFF} +{ VARSTRINGCHECKS ON} +{ WRITEABLECONST ON} +{ MINENUMSIZE 1} +{$IMAGEBASE $400000} +{$DEFINE DEBUG} +{$ENDIF IMPLICITBUILDING} {$DESCRIPTION 'Bold 4.0 for Delphi (VCL GUI)'} {$LIBSUFFIX '90'} +{$DESIGNONLY} +{$IMPLICITBUILD ON} requires vcl, @@ -75,6 +76,7 @@ contains BoldStringControlPack in 'Source\BoldAwareGUI\ControlPacks\BoldStringControlPack.pas', BoldViewerControlPack in 'Source\BoldAwareGUI\ControlPacks\BoldViewerControlPack.pas', BoldExceptionHandlers in 'Source\BoldAwareGUI\Core\BoldExceptionHandlers.pas', + BoldAction in 'Source\BoldAwareGUI\Actions\BoldAction.pas', BoldGUI in 'Source\BoldAwareGUI\Core\BoldGUI.pas', BoldGuiResourceStrings in 'Source\BoldAwareGUI\Core\BoldGuiResourceStrings.pas', BoldAFP in 'Source\BoldAwareGUI\FormGen\BoldAFP.pas', diff --git a/Source/BoldAwareGUI/FormGen/BoldAFPDefault.pas b/Source/BoldAwareGUI/FormGen/BoldAFPDefault.pas index ad4d558..66070a5 100644 --- a/Source/BoldAwareGUI/FormGen/BoldAFPDefault.pas +++ b/Source/BoldAwareGUI/FormGen/BoldAFPDefault.pas @@ -520,7 +520,12 @@ procedure TBoldDefaultFormProvider.EnsureForm; // No inherited, because form needs to be created with CreateNew. // In this way, no resources are needed (because its not inherited from TForm anymore) if Assigned(FormClass) then - Form := FormClass.CreateNew(Application) + begin + if FormClass.InheritsFrom(TFormAFPDefault) then + Form := FormClass.CreateNew(Application) // TFormAFPDefault descendants have no .dfm + else + Form := FormClass.Create(Application); + end else Form := nil; diff --git a/Source/Persistence/FireDAC/BoldFireDACInterfaces.pas b/Source/Persistence/FireDAC/BoldFireDACInterfaces.pas index ef76516..6c99b27 100644 --- a/Source/Persistence/FireDAC/BoldFireDACInterfaces.pas +++ b/Source/Persistence/FireDAC/BoldFireDACInterfaces.pas @@ -260,6 +260,7 @@ implementation FireDAC.Stan.Option, FireDAC.Comp.Script, + FireDAC.Comp.ScriptCommands, BoldUtils, BoldGuard, diff --git a/Source/Samples/ConstraintValidator/BoldConstraintValidator.pas b/Source/Samples/ConstraintValidator/BoldConstraintValidator.pas new file mode 100644 index 0000000..1679bea --- /dev/null +++ b/Source/Samples/ConstraintValidator/BoldConstraintValidator.pas @@ -0,0 +1,601 @@ +{ Global compiler directives } +{$include bold.inc} +unit BoldConstraintValidator; + +interface + +uses + Classes, + SysUtils, + Contnrs, + + BoldElements, + BoldSubscription, + BoldSystem, + BoldHandles, + BoldDefs, + BoldBase, + BoldComponentValidator; + +type + TBoldConstraintSeverity = (csError, csWarning); + TValidationMode = (vmManual, vmOnModify, vmPreUpdate); + +const + cDefaultSeverity = csError; + +type + TBoldConstraintValidator = class; + TBoldConstraintItem = class; + TBoldConstraintCollection = class; + TBoldConstraintFailureList = class; + EBoldConstraintFailure = class; + + TBoldConstraintsFailureEvent = procedure(var AHandled: boolean; AFailedConstraints: TBoldConstraintFailureList) of object; + TBoldConstraintFailureEvent = procedure(ABoldObject: TBoldObject; AConstraint: TBoldConstraintItem; const AFailureMessage: string) of object; + TBoldConstraintCheckEvent = procedure(ABoldObject: TBoldObject; AConstraint: TBoldConstraintItem; var AFailureMessage: string) of object; + + TBoldConstraintFailure = class(TBoldMemoryManagedObject) + private + fBoldObject: TBoldObject; + fConstraint: TBoldConstraintItem; + fFailureMessage: string; + public + constructor Create(ABoldObject: TBoldObject; AConstraint: TBoldConstraintItem; const AFailureMessage: string); + property BoldObject: TBoldObject read fBoldObject; + property Constraint: TBoldConstraintItem read fConstraint; + property FailureMessage: string read fFailureMessage; + end; + + TBoldConstraintFailureList = class(TObjectList) + private + function GetBoldObject(const index: integer): TBoldObject; + function GeTBoldConstraint(const index: integer): TBoldConstraintItem; + function GeTBoldConstraintFailure(const index: integer): TBoldConstraintFailure; + function GetFailureMessage(const index: integer): string; + function GetHasErrors: boolean; + function GetAsString: string; + public + property ConstraintFailure[const index: integer]: TBoldConstraintFailure read GeTBoldConstraintFailure; default; + property BoldObjects[const index: integer]: TBoldObject read GetBoldObject; + property Constraints[const index: integer]: TBoldConstraintItem read GeTBoldConstraint; + property FailureMessages[const index: integer]: string read GetFailureMessage; + property HasErrors: boolean read GetHasErrors; + property AsString: string read GetAsString; + end; + + TBoldConstraintValidator = class(TBoldNonSystemHandle, IBoldValidateableComponent) + strict private + fValidatioNesting: integer; + fConstraints: TBoldConstraintCollection; + fValidationMode: TValidationMode; + fSubscriber: TBoldExtendedPassthroughSubscriber; + fFailedConstraints: TBoldConstraintFailureList; + procedure PreUpdate(Sender: TObject); + procedure Receive(Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent; const Args: array of const); + { IBoldValidateableComponent } + function ValidateComponent(ComponentValidator: TBoldComponentValidator; NamePrefix: String): Boolean; override; + private +// fCheckModelConstraints: boolean; + fOnConstraintsFailed: TBoldConstraintsFailureEvent; + fOnConstraintFailed: TBoldConstraintFailureEvent; + fEnabled: Boolean; + procedure SetValidationMode(const Value: TValidationMode); + function GetSubscriber: TBoldSubscriber; + procedure ProcessFailedConstraints; + procedure SetEnabled(const Value: Boolean); + protected + procedure StaticBoldTypeChanged; override; + procedure Changed; + function BoldSystem: TBoldSystem; + procedure BeginValidate; + procedure EndValidate; + procedure AddFailure(ABoldObject: TBoldObject; AConstraint: TBoldConstraintItem; const AFailureMessage: string); + property Subscriber: TBoldSubscriber read GetSubscriber; + public + procedure AfterConstruction; override; + procedure BeforeDestruction; override; + procedure ValidateObject(ABoldObject: TBoldObject); + procedure ValidateDirtyObjects; + procedure ValidateList(AList: TBoldObjectList); + procedure ValidateObjects(const aObjects: array of TBoldObject); + published + property Constraints: TBoldConstraintCollection read fConstraints write fConstraints; + property ValidationMode: TValidationMode read fValidationMode write SetValidationMode default vmManual; +// TODO: +// property CheckModelConstraints: boolean read fCheckModelConstraints write fCheckModelConstraints; + property OnConstraintFailed: TBoldConstraintFailureEvent read fOnConstraintFailed write fOnConstraintFailed; + property OnConstraintsFailed: TBoldConstraintsFailureEvent read fOnConstraintsFailed write fOnConstraintsFailed; + property Enabled: Boolean read fEnabled write SetEnabled; + end; + + TBoldConstraintCollectionEnumerator = class(TCollectionEnumerator) + public + function GetCurrent: TBoldConstraintItem; + property Current: TBoldConstraintItem read GetCurrent; + end; + + TBoldConstraintCollection = class(TCollection) + strict private + fValidator: TBoldConstraintValidator; + protected + function GetItems(Index: integer): TBoldConstraintItem; + function GetOwner: TPersistent; override; + property Validator: TBoldConstraintValidator read fValidator; + public + constructor Create(Validator: TBoldConstraintValidator); + function GetEnumerator: TBoldConstraintCollectionEnumerator; + property Items[Index: integer]: TBoldConstraintItem read GetItems; default; + end; + + TBoldConstraintItem = class(TCollectionItem, IBoldOCLComponent) + strict private + fContext: String; + fExpression: TBoldExpression; + fErrorMessage: TBoldExpression; + fSeverity: TBoldConstraintSeverity; + fConstraintCheckEvent: TBoldConstraintCheckEvent; + private + function QueryInterface(const IId: TGUID; out Obj): HResult; virtual; stdcall; + function _AddRef: Integer; stdcall; + function _Release: Integer; stdcall; + protected + function GetDisplayName: string; override; + { IBoldOCLComponent } + function GetContextType: TBoldElementTypeInfo; + procedure SetExpression(const Value: TBoldExpression); + function GetVariableList: TBoldExternalVariableList; + function GetExpression: TBoldExpression; + public + procedure Assign(Source: TPersistent); override; + function Check(ABoldObject: TBoldObject): string; + published + property Context: String read fContext write fContext; + property Expression: TBoldExpression read GetExpression write SetExpression; + property Severity: TBoldConstraintSeverity read fSeverity write fSeverity default cDefaultSeverity; + property ErrorMessage: TBoldExpression read fErrorMessage write fErrorMessage; // default cDefaultErrorMessage; + property OnCheckConstraint: TBoldConstraintCheckEvent read fConstraintCheckEvent write fConstraintCheckEvent; + end; + + EBoldConstraintFailure = class(Exception) + private + fFailedConstraints: TBoldConstraintFailureList; + public + constructor Create(AFailedConstraints: TBoldConstraintFailureList); + property FailedConstraints: TBoldConstraintFailureList read fFailedConstraints; + end; + +implementation + +uses + BoldSystemRT; + +{ TBoldConstraintCollection } + +constructor TBoldConstraintCollection.Create(Validator: TBoldConstraintValidator); +begin + inherited Create(TBoldConstraintItem); + fValidator := Validator; +end; + +function TBoldConstraintCollection.GetEnumerator: TBoldConstraintCollectionEnumerator; +begin + result := TBoldConstraintCollectionEnumerator.Create(self); +end; + +function TBoldConstraintCollection.GetItems(Index: integer): TBoldConstraintItem; +begin + result := TBoldConstraintItem(inherited items[index]); +end; + +function TBoldConstraintCollection.GetOwner: TPersistent; +begin + result := Validator; +end; + +{ TBoldConstraintItem } + +procedure TBoldConstraintItem.Assign(Source: TPersistent); +var + SourceItem: TBoldConstraintItem; +begin + if Source is TBoldConstraintItem then + begin + SourceItem := Source as TBoldConstraintItem; + Context := SourceItem.Context; + Expression := SourceItem.Expression; + ErrorMessage := SourceItem.ErrorMessage; + Severity := SourceItem.Severity; + OnCheckConstraint := SourceItem.OnCheckConstraint; + end + else + inherited; +end; + +function TBoldConstraintItem.Check(ABoldObject: TBoldObject): string; +begin + result := ''; + if ABoldObject.BoldClassTypeInfo.BoldIsA(GetContextType) then + begin + if Assigned(fConstraintCheckEvent) then + try + fConstraintCheckEvent(ABoldObject, self, result); + except + on e:exception do + begin + result := ''; + raise; +// TraceLog.SystemMessage(E.ClassName+':'+E.Message, ekError); + end; + end + else + if not ABoldObject.EvaluateExpressionAsBoolean(Expression) then + result := ABoldObject.EvaluateExpressionAsString(ErrorMessage); + end; +end; + +function TBoldConstraintItem.GetContextType: TBoldElementTypeInfo; +var + BoldSystemTypeInfo: TBoldSystemTypeInfo; +begin + result := nil; + BoldSystemTypeInfo := (Collection as TBoldConstraintCollection).Validator.StaticSystemTypeInfo; + if Assigned(BoldSystemTypeInfo) then + result := BoldSystemTypeInfo.ClassTypeInfoByExpressionName[Context]; +end; + +function TBoldConstraintItem.GetDisplayName: string; +begin + if ErrorMessage = '' then + result := Format('[%s]:%s', [Context, Expression]) + else + result := Format('[%s]:%s', [Context, ErrorMessage]); +end; + +function TBoldConstraintItem.GetExpression: TBoldExpression; +begin + result := fExpression; +end; + +function TBoldConstraintItem.GetVariableList: TBoldExternalVariableList; +begin + result := nil; +end; + +function TBoldConstraintItem.QueryInterface(const IId: TGUID; out Obj): HResult; +begin + if GetInterface(IID, Obj) then + Result := S_OK + else + Result := E_NOINTERFACE; +end; + +procedure TBoldConstraintItem.SetExpression(const Value: TBoldExpression); +begin + fExpression := Value; +end; + +function TBoldConstraintItem._AddRef: Integer; +begin + result := -1; +end; + +function TBoldConstraintItem._Release: Integer; +begin + result := -1; +end; + +{ TBoldConstraintCollectionEnumerator } + +function TBoldConstraintCollectionEnumerator.GetCurrent: TBoldConstraintItem; +begin + result := inherited GetCurrent as TBoldConstraintItem; +end; + +{ TBoldConstraintValidator } + +procedure TBoldConstraintValidator.AddFailure(ABoldObject: TBoldObject; + AConstraint: TBoldConstraintItem; const AFailureMessage: string); +begin + fFailedConstraints.Add(TBoldConstraintFailure.Create(ABoldObject, AConstraint, AFailureMessage)); + if Assigned(fOnConstraintFailed) then + OnConstraintFailed(ABoldObject, AConstraint, AFailureMessage); +end; + +procedure TBoldConstraintValidator.AfterConstruction; +begin + inherited; + Enabled := true; + fConstraints := TBoldConstraintCollection.Create(self); + fFailedConstraints := TBoldConstraintFailureList.Create; +end; + +procedure TBoldConstraintValidator.BeforeDestruction; +begin + FreeAndNil(fFailedConstraints); + FreeAndNil(fConstraints); + FreeAndNil(fSubscriber); + inherited; +end; + +procedure TBoldConstraintValidator.BeginValidate; +begin + inc(fValidatioNesting); +end; + +procedure TBoldConstraintValidator.EndValidate; +begin + dec(fValidatioNesting); + Assert(fValidatioNesting >= 0); + if (fValidatioNesting = 0) and (fFailedConstraints.count > 0) then + begin + ProcessFailedConstraints; + end; +end; + +function TBoldConstraintValidator.BoldSystem: TBoldSystem; +begin + result := nil; + if Assigned(StaticSystemHandle) then + result := StaticSystemHandle.System; +end; + +procedure TBoldConstraintValidator.Changed; +begin + FreeAndNil(fSubscriber); + if (BoldSystem <> nil) and Enabled then + begin + BoldSystem.OnPreUpdate := nil; + case ValidationMode of + vmManual:; + vmOnModify: + {$IFDEF BoldSystemBroadcastMemberEvents} + BoldSystem.AddSubscription(Subscriber, beCompleteModify, beCompleteModify); + {$ELSE} + raise Exception.Create(ClassName + ': vmOnModify mode requires BoldSystemBroadcastMemberEvents conditional define.'); + {$ENDIF} + vmPreUpdate: + BoldSystem.OnPreUpdate := PreUpdate; + end; + end; +end; + +function TBoldConstraintValidator.GetSubscriber: TBoldSubscriber; +begin + if not Assigned(fSubscriber) then + fSubscriber := TBoldExtendedPassthroughSubscriber.CreateWithExtendedReceive(Receive); + result := fSubscriber; +end; + +procedure TBoldConstraintValidator.PreUpdate(Sender: TObject); +begin + if Enabled and (ValidationMode = vmPreUpdate) then + ValidateList(Sender as TBoldObjectList); +end; + +procedure TBoldConstraintValidator.ProcessFailedConstraints; +var + Handled: boolean; +begin + Handled := false; + try + if Assigned(fOnConstraintsFailed) then + OnConstraintsFailed(Handled, fFailedConstraints); + if not Handled and fFailedConstraints.HasErrors then + raise EBoldConstraintFailure.Create(fFailedConstraints); + finally + fFailedConstraints.clear; + end; +end; + +procedure TBoldConstraintValidator.Receive(Originator: TObject; + OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent; + const Args: array of const); +var + BoldObject: TBoldObject; +begin + if Enabled then + case RequestedEvent of + beCompleteModify: + if (Originator is TBoldMember) then + begin + Assert(Args[0].VObject is TBoldMember); + BoldObject := TBoldMember(Args[0].VObject).OwningObject; + ValidateObject(BoldObject); + end; + end; +end; + +procedure TBoldConstraintValidator.SetEnabled(const Value: Boolean); +begin + if Value <> fEnabled then + begin + fEnabled := Value; + Changed; + end; +end; + +procedure TBoldConstraintValidator.SetValidationMode(const Value: TValidationMode); +begin + if fValidationMode <> Value then + begin + fValidationMode := Value; + Changed; + end; +end; + +procedure TBoldConstraintValidator.StaticBoldTypeChanged; +begin + inherited; + Changed; +end; + +procedure TBoldConstraintValidator.ValidateList(AList: TBoldObjectList); +var + BoldObject: TBoldObject; +begin + BeginValidate; + try + for BoldObject in AList do + ValidateObject(BoldObject); + finally + EndValidate; + end; +end; + +procedure TBoldConstraintValidator.ValidateObject(ABoldObject: TBoldObject); +var + Constraint: TBoldConstraintItem; + FailureMessage: string; +begin + if ABoldObject.BoldObjectIsDeleted then // do not check contraints for deleted objects + exit; + BeginValidate; + try + for Constraint in Constraints do + begin + FailureMessage := Constraint.Check(ABoldObject); + if FailureMessage <> '' then + AddFailure(ABoldObject, Constraint, FailureMessage); + end; + finally + EndValidate; + end; +end; + +procedure TBoldConstraintValidator.ValidateObjects(const aObjects: array of TBoldObject); +var + i: integer; +begin + BeginValidate; + try + for i := 0 to high(AObjects) do + ValidateObject(AObjects[i]); + finally + EndValidate; + end; +end; + +function TBoldConstraintValidator.ValidateComponent( + ComponentValidator: TBoldComponentValidator; NamePrefix: String): Boolean; +var + Context: TBoldElementTypeInfo; + Constraint: TBoldConstraintItem; +begin + result := inherited ValidateComponent(ComponentValidator, NamePrefix); + for Constraint in Constraints do + begin + result := ComponentValidator.ValidateExpressionInContext( + Constraint.Expression, + Constraint.GetContextType, + format('%s%s.Constraint[%d]', [NamePrefix, Constraint.DisplayName, Constraint.Index])) and result; + result := ComponentValidator.ValidateExpressionInContext( + Constraint.ErrorMessage, + Constraint.GetContextType, + format('%s%s.Constraint[%d]', [NamePrefix, Constraint.DisplayName, Constraint.Index])) and result; + end; +end; + +procedure TBoldConstraintValidator.ValidateDirtyObjects; +var + List: TBoldObjectList; +begin + if Assigned(StaticSystemHandle) and Assigned(StaticSystemHandle.System) and StaticSystemHandle.System.BoldDirty then + begin + List := StaticSystemHandle.System.DirtyObjectsAsBoldList; + try + ValidateList(List) + finally + List.free; + end; + end; +end; + +{ EBoldConstraintFailure } + +constructor EBoldConstraintFailure.Create( + AFailedConstraints: TBoldConstraintFailureList); +var + i: integer; + sl: TStringList; +begin + fFailedConstraints := AFailedConstraints; + sl := TStringList.Create; + try + for I := 0 to fFailedConstraints.Count - 1 do + begin + if fFailedConstraints[i].Constraint.Severity = csError then + sl.Add(fFailedConstraints.FailureMessages[i]); + end; + inherited Create(sl.text); + finally + sl.free; + end; +end; + +{ TBoldConstraintFailure } + +constructor TBoldConstraintFailure.Create(ABoldObject: TBoldObject; + AConstraint: TBoldConstraintItem; const AFailureMessage: string); +begin + inherited Create; + fBoldObject := ABoldObject; + fConstraint := AConstraint; + fFailureMessage := AFailureMessage; +end; + +{ TBoldConstraintFailureList } + +function TBoldConstraintFailureList.GeTBoldConstraintFailure( + const index: integer): TBoldConstraintFailure; +begin + result := self.Items[index] as TBoldConstraintFailure; +end; + +function TBoldConstraintFailureList.GetAsString: string; +var + i: integer; + sl: TStringList; +begin + sl := TStringList.Create; + try + for I := 0 to Count - 1 do + sl.Add(FailureMessages[i]); + result := sl.text; + finally + sl.free; + end; +end; + +function TBoldConstraintFailureList.GetBoldObject( + const index: integer): TBoldObject; +begin + result := ConstraintFailure[index].BoldObject +end; + +function TBoldConstraintFailureList.GeTBoldConstraint( + const index: integer): TBoldConstraintItem; +begin + result := ConstraintFailure[index].Constraint +end; + +function TBoldConstraintFailureList.GetFailureMessage(const index: integer): string; +begin + result := ConstraintFailure[index].FailureMessage; +end; + +function TBoldConstraintFailureList.GetHasErrors: boolean; +var + i: integer; +begin + for I := 0 to Count - 1 do + if Constraints[i].severity = csError then + begin + result := true; + exit; + end; + result := false; +end; + +end. + From c2e37ae58e83f2811cc721b52a937acc03479357 Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Mon, 17 May 2021 23:14:30 +0300 Subject: [PATCH 024/112] Registration for BoldConstraintValidator --- .../BoldConstraintValidatorReg.pas | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 Source/Samples/ConstraintValidator/BoldConstraintValidatorReg.pas diff --git a/Source/Samples/ConstraintValidator/BoldConstraintValidatorReg.pas b/Source/Samples/ConstraintValidator/BoldConstraintValidatorReg.pas new file mode 100644 index 0000000..a001aed --- /dev/null +++ b/Source/Samples/ConstraintValidator/BoldConstraintValidatorReg.pas @@ -0,0 +1,66 @@ +{ Global compiler directives } +{$include bold.inc} +unit BoldConstraintValidatorReg; + +interface + +procedure Register; + +implementation + +uses + Classes, + DesignIntf, + + BoldConstraintValidator, + + BoldDefs, + BoldElements, + BoldSystemRt, + BoldPropertyEditors, + BoldIDEConsts; + +type + { TBoldTypeNameSelectorForConstraintValidator } + TBoldTypeNameSelectorForConstraintValidator = class (TBoldTypeNameSelectorForHandles) + protected + function GetApprovedTypes: TBoldValueTypes; override; + function GetContextType(Component: TPersistent): TBoldSystemTypeInfo; override; + end; + + { TBoldOclVariablesEditor } + TBoldConstraintValidatorEditor = class(TBoldComponentDblClickEditor) + protected + function GetDefaultMethodName: string; override; + end; + +procedure Register; +begin + RegisterComponents(BOLDPAGENAME_MISC, [TBoldConstraintValidator]); + RegisterPropertyEditor(TypeInfo(String), TBoldConstraintItem, 'Context', TBoldTypeNameSelectorForConstraintValidator); + RegisterPropertyEditor(TypeInfo(TBoldExpression), TBoldConstraintItem, 'Expression', TBoldOCLExpressionForOCLComponent); + RegisterPropertyEditor(TypeInfo(TBoldExpression), TBoldConstraintItem, 'ErrorMessage', TBoldOCLExpressionForOCLComponent); + RegisterComponentEditor(TBoldConstraintValidator, TBoldConstraintValidatorEditor); +end; + +{ TBoldTypeNameSelectorForConstraintValidator } + +function TBoldTypeNameSelectorForConstraintValidator.GetApprovedTypes: TBoldValueTypes; +begin + Result := [bvtClass]; +end; + +function TBoldTypeNameSelectorForConstraintValidator.GetContextType( + Component: TPersistent): TBoldSystemTypeInfo; +begin + result := (TBoldConstraintItem(Component).Collection.Owner as TBoldConstraintValidator).StaticSystemTypeInfo; +end; + +{ TBoldConstraintValidatorEditor } + +function TBoldConstraintValidatorEditor.GetDefaultMethodName: string; +begin + Result := 'Constraints'; +end; + +end. From ebcd388fda7752fde6879fc9cadfdb4ad70bf43b Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Tue, 18 May 2021 11:11:24 +0300 Subject: [PATCH 025/112] Added BoldAction --- Source/BoldAwareGUI/Actions/BoldAction.pas | 233 +++++++++++++++++++++ 1 file changed, 233 insertions(+) create mode 100644 Source/BoldAwareGUI/Actions/BoldAction.pas diff --git a/Source/BoldAwareGUI/Actions/BoldAction.pas b/Source/BoldAwareGUI/Actions/BoldAction.pas new file mode 100644 index 0000000..a657a57 --- /dev/null +++ b/Source/BoldAwareGUI/Actions/BoldAction.pas @@ -0,0 +1,233 @@ +unit BoldAction; + +{$include bold.inc} + +interface + +uses + SysUtils, Windows, Messages, Classes, Graphics, Controls, + Forms, Dialogs, BoldControlPack, BoldHandles, BoldElements, + BoldElementHandleFollower, ExtCtrls, ActnList, + BoldCheckBoxStateControlPack, BoldStringControlPack, BoldHandle, + BoldVariantControlPack, StdCtrls; + +type + TBoldCheckBoxWithNilStateFollowerController = class(TBoldCheckBoxStateFollowerController) + private + FNilRepresentation: boolean; + published + property NilRepresentation: boolean read FNilRepresentation write FNilRepresentation default False; + end; + + TBoldAction = class(TCustomAction) + private + FBoldEnabled: TBoldCheckBoxWithNilStateFollowerController; + FBoldCaption: TBoldStringFollowerController; + FBoldVisible: TBoldCheckBoxWithNilStateFollowerController; + FBoldProperties: TBoldVariantFollowerController; + fBoldHandleFollower: TBoldElementHandleFollower; + fCaptionHandleFollower: TBoldElementHandleFollower; + fVisibleHandleFollower: TBoldElementHandleFollower; + fEnabledHandleFollower: TBoldElementHandleFollower; + procedure SetBoldEnabled(const Value: TBoldCheckBoxWithNilStateFollowerController); + procedure SetBoldCaption(const Value: TBoldStringFollowerController); + procedure SetBoldVisible(const Value: TBoldCheckBoxWithNilStateFollowerController); + procedure SetBoldHandle(const Value: TBoldElementHandle); + function GetBoldHandle: TBoldElementHandle; + function GetContextType: TBoldElementTypeInfo; + procedure AfterCaptionMakeUptoDate(Follower: TBoldFollower); + procedure AfterVisibleMakeUptoDate(Follower: TBoldFollower); + procedure AfterEnabledMakeUptoDate(Follower: TBoldFollower); + procedure AfterMakeUptoDate(Follower: TBoldFollower); + procedure SetBoldProperties(const Value: TBoldVariantFollowerController); + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + function Update: boolean; override; + published + property BoldHandle: TBoldElementHandle read GetBoldHandle write SetBoldHandle; + property BoldProperties: TBoldVariantFollowerController read fBoldProperties write SetBoldProperties; + property BoldCaption: TBoldStringFollowerController read FBoldCaption write SetBoldCaption; + property BoldEnabled: TBoldCheckBoxWithNilStateFollowerController read FBoldEnabled write SetBoldEnabled; + property HelpContext; + property HelpKeyword; + property HelpType; + property Hint; + property ImageIndex; + property ShortCut; + property SecondaryShortCuts; + property BoldVisible: TBoldCheckBoxWithNilStateFollowerController read FBoldVisible write SetBoldVisible; + property OnExecute; + property OnHint; + end; + +implementation + +uses +{$IFDEF BOLD_DELPHI16_OR_LATER} + Actions, +{$ENDIF} + Variants; + +const + // this is used for enabled and visible properties to avoid having to write true/false in expression + cDefaultValueForEmptyOcl = true; + cDefaultVisibleNilRepresentation = True; + cDefaultEnabledNilRepresentation = True; + +{ TBoldAction } + +procedure TBoldAction.AfterCaptionMakeUptoDate(Follower: TBoldFollower); +var + newText: string; +begin + if (csDesigning in ComponentState) then + begin + with fBoldCaption do + if Assigned(Renderer) then + NewText := Format('%s.%s', [Renderer.name, Expression]) + else if Expression <> '' then + NewText := Expression + else + NewText := name; + end + else + newText := fBoldCaption.GetCurrentAsString(Follower); + + if Caption <> newText then + Caption := newText; + + Self.Change; +end; + +procedure TBoldAction.AfterEnabledMakeUptoDate(Follower: TBoldFollower); +var + state: TCheckBoxState; +begin + state := fBoldEnabled.GetCurrentAsCheckBoxState(Follower); + if State = cbGrayed then + begin + if (FBoldEnabled.Expression = '') then + Enabled := cDefaultValueForEmptyOcl + else + Enabled := FBoldEnabled.NilRepresentation; + end + else + Enabled := state = cbChecked; +end; + +procedure TBoldAction.AfterMakeUptoDate(Follower: TBoldFollower); +var + Value: Variant; +begin + Value := TBoldVariantFollowerController(Follower.Controller).GetAsVariant(Follower); + Checked := VarIsType(Value, varBoolean) and Value; +end; + +procedure TBoldAction.AfterVisibleMakeUptoDate(Follower: TBoldFollower); +var + state: TCheckBoxState; +begin + state := fBoldVisible.GetCurrentAsCheckBoxState(Follower); + if State = cbGrayed then + begin + if (FBoldVisible.Expression = '') then + Visible := cDefaultValueForEmptyOcl + else + Visible := FBoldVisible.NilRepresentation; + end + else + Visible := state = cbChecked; +end; + +constructor TBoldAction.Create(AOwner: TComponent); +begin + inherited; + fBoldCaption := TBoldStringFollowerController.Create(Self); + fBoldCaption.OnGetContextType := GetContextType; + fBoldCaption.AfterMakeUptoDate := AfterCaptionMakeUptoDate; + + fBoldEnabled := TBoldCheckBoxWithNilStateFollowerController.Create(Self); + fBoldEnabled.NilRepresentation := cDefaultEnabledNilRepresentation; + fBoldEnabled.OnGetContextType := GetContextType; + fBoldEnabled.AfterMakeUptoDate := AfterEnabledMakeUptoDate; + + fBoldVisible := TBoldCheckBoxWithNilStateFollowerController.Create(Self); + fBoldVisible.NilRepresentation := cDefaultVisibleNilRepresentation; + FBoldVisible.OnGetContextType := GetContextType; + FBoldVisible.AfterMakeUptoDate := AfterVisibleMakeUptoDate; + + FBoldProperties:= TBoldVariantFollowerController.Create(self); + FBoldProperties.OnGetContextType := GetContextType; + FBoldProperties.AfterMakeUptoDate := AfterMakeUptoDate; + + fVisibleHandleFollower := TBoldElementHandleFollower.Create(AOwner, fBoldVisible); + fCaptionHandleFollower := TBoldElementHandleFollower.Create(AOwner, FBoldCaption); + fEnabledHandleFollower := TBoldElementHandleFollower.Create(AOwner, FBoldEnabled); + fBoldHandleFollower := TBoldElementHandleFollower.Create(AOwner, FBoldProperties); +end; + +destructor TBoldAction.Destroy; +begin + fVisibleHandleFollower.Free; + fEnabledHandleFollower.Free; + fCaptionHandleFollower.Free; + fBoldHandleFollower.Free; + + FBoldProperties.Free; + FBoldEnabled.Free; + FBoldCaption.Free; + FBoldVisible.Free; + inherited; +end; + +function TBoldAction.GetBoldHandle: TBoldElementHandle; +begin + Result := fBoldHandleFollower.BoldHandle; +end; + +function TBoldAction.GetContextType: TBoldElementTypeInfo; +begin + if assigned(BoldHandle) then + result := BoldHandle.StaticBoldType + else + result := nil; +end; + +procedure TBoldAction.SetBoldCaption( + const Value: TBoldStringFollowerController); +begin + FBoldCaption.Assign(Value); +end; + +procedure TBoldAction.SetBoldEnabled( + const Value: TBoldCheckBoxWithNilStateFollowerController); +begin + FBoldEnabled.Assign(Value); +end; + +procedure TBoldAction.SetBoldHandle(const Value: TBoldElementHandle); +begin + fVisibleHandleFollower.BoldHandle := Value; + fEnabledHandleFollower.BoldHandle := Value; + fCaptionHandleFollower.BoldHandle := Value; + fBoldHandleFollower.BoldHandle := Value; +end; + +procedure TBoldAction.SetBoldProperties(const Value: TBoldVariantFollowerController); +begin + FBoldProperties.Assign(Value); +end; + +procedure TBoldAction.SetBoldVisible( + const Value: TBoldCheckBoxWithNilStateFollowerController); +begin + FBoldVisible.Assign(Value); +end; + +function TBoldAction.Update: boolean; +begin + Result := true; //not inherited! +end; + +end. From 13d212bdeb0c5b5a86f04cca8a27def77ec961af Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Tue, 18 May 2021 11:29:33 +0300 Subject: [PATCH 026/112] Minor changes for XE5 compatibility --- Source/Common/IDE/BoldAbout.pas | 2 +- .../UtilsGUI/BoldTypeNameSelector.pas | 3 +- .../PMapper/DbEvolutor/BoldDbEvolutorForm.dfm | 36 +++++++++---------- .../PMapper/DbEvolutor/BoldDbEvolutorForm.pas | 27 ++++++++++++-- .../FireDAC/BoldFireDACInterfaces.pas | 12 +++---- .../UMLModel/Editor/BoldUMLModelEditForm.pas | 4 ++- 6 files changed, 54 insertions(+), 30 deletions(-) diff --git a/Source/Common/IDE/BoldAbout.pas b/Source/Common/IDE/BoldAbout.pas index ed2bb7c..df28d89 100644 --- a/Source/Common/IDE/BoldAbout.pas +++ b/Source/Common/IDE/BoldAbout.pas @@ -18,7 +18,7 @@ interface ExtCtrls, Menus, ImgList, - Graphics, System.ImageList; + Graphics; type TfrmAboutBold = class(TForm) diff --git a/Source/ObjectSpace/UtilsGUI/BoldTypeNameSelector.pas b/Source/ObjectSpace/UtilsGUI/BoldTypeNameSelector.pas index 8ec9e67..d01ca9d 100644 --- a/Source/ObjectSpace/UtilsGUI/BoldTypeNameSelector.pas +++ b/Source/ObjectSpace/UtilsGUI/BoldTypeNameSelector.pas @@ -15,7 +15,8 @@ interface StdCtrls, BoldSystemRT, BoldElements, - ImgList, Menus, System.ImageList; + ImgList, + Menus; type TNodeType = (ntClass, ntClasses, ntAttributes, ntList, ntAttribute, ntClassList, diff --git a/Source/PMapper/DbEvolutor/BoldDbEvolutorForm.dfm b/Source/PMapper/DbEvolutor/BoldDbEvolutorForm.dfm index 43dc78c..20ee15e 100644 --- a/Source/PMapper/DbEvolutor/BoldDbEvolutorForm.dfm +++ b/Source/PMapper/DbEvolutor/BoldDbEvolutorForm.dfm @@ -1,8 +1,6 @@ object frmBoldDbEvolutor: TfrmBoldDbEvolutor Left = 510 Top = 257 - Width = 640 - Height = 480 Caption = 'Db Evolution' Color = clBtnFace Constraints.MinHeight = 200 @@ -43,16 +41,16 @@ object frmBoldDbEvolutor: TfrmBoldDbEvolutor OnCreate = FormCreate OnDestroy = FormDestroy DesignSize = ( - 632 - 446) + 624 + 445) PixelsPerInch = 96 TextHeight = 13 object PageControl1: TPageControl Left = 0 Top = 0 Width = 632 - Height = 388 - ActivePage = tsMappingInfo + Height = 392 + ActivePage = tsActions Anchors = [akLeft, akTop, akRight, akBottom] Images = ImageList1 TabOrder = 0 @@ -62,7 +60,7 @@ object frmBoldDbEvolutor: TfrmBoldDbEvolutor Left = 0 Top = 0 Width = 624 - Height = 359 + Height = 363 Align = alClient ReadOnly = True ScrollBars = ssBoth @@ -76,7 +74,7 @@ object frmBoldDbEvolutor: TfrmBoldDbEvolutor Left = 0 Top = 0 Width = 624 - Height = 359 + Height = 363 Align = alClient ReadOnly = True ScrollBars = ssBoth @@ -90,7 +88,7 @@ object frmBoldDbEvolutor: TfrmBoldDbEvolutor Left = 0 Top = 0 Width = 624 - Height = 359 + Height = 363 Align = alClient ReadOnly = True ScrollBars = ssBoth @@ -104,7 +102,7 @@ object frmBoldDbEvolutor: TfrmBoldDbEvolutor Left = 0 Top = 0 Width = 624 - Height = 359 + Height = 363 Align = alClient ReadOnly = True ScrollBars = ssBoth @@ -122,8 +120,8 @@ object frmBoldDbEvolutor: TfrmBoldDbEvolutor TabOrder = 1 end object btnCancel: TButton - Left = 545 - Top = 421 + Left = 539 + Top = 418 Width = 81 Height = 25 Anchors = [akRight, akBottom] @@ -132,8 +130,8 @@ object frmBoldDbEvolutor: TfrmBoldDbEvolutor TabOrder = 2 end object btnExecute: TButton - Left = 457 - Top = 421 + Left = 451 + Top = 418 Width = 81 Height = 25 Anchors = [akRight, akBottom] @@ -142,14 +140,16 @@ object frmBoldDbEvolutor: TfrmBoldDbEvolutor ModalResult = 1 TabOrder = 3 end - object Button1: TButton - Left = 373 - Top = 421 + object btnSaveScript: TButton + Left = 367 + Top = 418 Width = 75 Height = 25 + Anchors = [akRight, akBottom] Caption = 'Save scripts' TabOrder = 4 - OnClick = Button1Click + OnClick = btnSaveScriptClick + ExplicitTop = 414 end object ImageList1: TImageList Left = 52 diff --git a/Source/PMapper/DbEvolutor/BoldDbEvolutorForm.pas b/Source/PMapper/DbEvolutor/BoldDbEvolutorForm.pas index 33134a8..a885e9f 100644 --- a/Source/PMapper/DbEvolutor/BoldDbEvolutorForm.pas +++ b/Source/PMapper/DbEvolutor/BoldDbEvolutorForm.pas @@ -34,9 +34,11 @@ TfrmBoldDbEvolutor = class(TForm, IBoldLogReceiver) tsWarnings: TTabSheet; mmoWarnings: TMemo; ImageList1: TImageList; + SaveDialog1: TSaveDialog; procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure FormClose(Sender: TObject; var Action: TCloseAction); + procedure btnSaveScriptClick(Sender: TObject); private { Private declarations } fSQLScript: TStringList; @@ -78,19 +80,39 @@ implementation SysUtils, BoldUtils, BoldDbEvolutor, + BoldIsoDateTime, BoldGuard; {$R *.DFM} { TfrmBoldDbEvolutor } +procedure TfrmBoldDbEvolutor.btnSaveScriptClick(Sender: TObject); +var + sl: TStringList; +begin + if SaveDialog1.Execute then + begin + sl := TStringList.Create; + try + sl.Add('-- Mapping Info Script'); + sl.AddStrings(MappingInfoScript); + sl.Add('-- SQL Script'); + sl.AddStrings(SQLScript); + SQLScript.SaveToFile(SaveDialog1.FileName); + finally + sl.free; + end; + end; +end; + procedure TfrmBoldDbEvolutor.Clear; begin end; procedure TfrmBoldDbEvolutor.EndLog; begin - Log(format('%s: Done %s', [formatDateTime('c', now), fSessionName])); + Log(format('%s: Done %s', [AsIsoDateTime(now), fSessionName])); end; procedure TfrmBoldDbEvolutor.Hide; @@ -143,7 +165,7 @@ procedure TfrmBoldDbEvolutor.MappingInfoScriptChange(Sender: TObject); procedure TfrmBoldDbEvolutor.StartLog(const SessionName: String); begin - Log(format('%s: Starting %s', [formatDateTime('c', now), sessionName])); + Log(format('%s: Starting %s', [AsIsoDateTime(now), sessionName])); fSessionName := SessionName; Show; end; @@ -300,5 +322,4 @@ class procedure TfrmBoldDbEvolutor.EvolveDB(PersistenceHandle: TBoldAbstractPers end; end; -initialization end. diff --git a/Source/Persistence/FireDAC/BoldFireDACInterfaces.pas b/Source/Persistence/FireDAC/BoldFireDACInterfaces.pas index 6c99b27..e9242ff 100644 --- a/Source/Persistence/FireDAC/BoldFireDACInterfaces.pas +++ b/Source/Persistence/FireDAC/BoldFireDACInterfaces.pas @@ -261,6 +261,7 @@ implementation FireDAC.Stan.Option, FireDAC.Comp.Script, FireDAC.Comp.ScriptCommands, + FireDAC.Phys.Intf, BoldUtils, BoldGuard, @@ -456,7 +457,7 @@ procedure TBoldFireDACQuery.ExecSQL; fReadTransactionStarted := fUseReadTransactions; end; Query.Execute; - if fReadTransactionStarted and (DatabaseWrapper as TBoldFireDACConnection).GetInTransaction then + if fReadTransactionStarted and (DatabaseWrapper as TBoldFireDACConnection).GetInTransaction then begin (DatabaseWrapper as TBoldFireDACConnection).Commit; fReadTransactionStarted := false; @@ -791,11 +792,10 @@ procedure TBoldFireDACConnection.AllTableNames(Pattern: string; ShowSystemTables begin lGuard := TBoldGuard.Create(lTempList); lTempList := TStringList.Create; - - // Retrieve the list of table names - // Note: This does not include views or procedures, there is a specific - // method in TFDConnection for that - FDConnection.GetTableNames('','','',lTempList{, ShowSystemTables}); + if ShowSystemTables then + FDConnection.GetTableNames(FDConnection.Params.Database,'','',lTempList, [osMy, osSystem, osOther], [tkTable]) + else + FDConnection.GetTableNames(FDConnection.Params.Database,'','',lTempList, [osMy, osOther], [tkTable]); // convert from fully qualified names in format: database.catalogue.table to just table name for i := 0 to lTempList.Count - 1 do diff --git a/Source/UMLModel/Editor/BoldUMLModelEditForm.pas b/Source/UMLModel/Editor/BoldUMLModelEditForm.pas index c5240dc..2ec00c7 100644 --- a/Source/UMLModel/Editor/BoldUMLModelEditForm.pas +++ b/Source/UMLModel/Editor/BoldUMLModelEditForm.pas @@ -52,7 +52,9 @@ interface BoldTreeView, Commctrl, BoldSmallLogFrame, - BoldDragObject, BoldDerivedHandle, BoldPropertiesController, + BoldDragObject, + BoldDerivedHandle, + BoldPropertiesController, AppEvnts; type From fbb075837c6ba01b4036bf54c81088795a16c62f Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Fri, 21 May 2021 16:06:54 +0300 Subject: [PATCH 027/112] Added SearchPath.txt for convenience, paste into project search path --- Source/SearchPath.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 Source/SearchPath.txt diff --git a/Source/SearchPath.txt b/Source/SearchPath.txt new file mode 100644 index 0000000..bab5eb1 --- /dev/null +++ b/Source/SearchPath.txt @@ -0,0 +1 @@ +$(BoldDelphi)\Source\BoldAwareGUI;$(BoldDelphi)\Source\BoldQAwareGUI;$(BoldDelphi)\Source\ClientGuiCom;$(BoldDelphi)\Source\ClientHandlesCom;$(BoldDelphi)\Source\Common;$(BoldDelphi)\Source\ConcurrencyControl;$(BoldDelphi)\Source\Extensions;$(BoldDelphi)\Source\FreestandingValueSpace;$(BoldDelphi)\Source\Handles;$(BoldDelphi)\Source\MoldModel;$(BoldDelphi)\Source\ObjectSpace;$(BoldDelphi)\Source\Persistence;$(BoldDelphi)\Source\PMapper;$(BoldDelphi)\Source\Propagator;$(BoldDelphi)\Source\Samples;$(BoldDelphi)\Source\UMLModel;$(BoldDelphi)\Source\Unassigned;$(BoldDelphi)\Source\ValueSpace;$(BoldDelphi)\Source\BoldAwareGUI\Actions;$(BoldDelphi)\Source\BoldAwareGUI\BoldControls;$(BoldDelphi)\Source\BoldAwareGUI\ControlPacks;$(BoldDelphi)\Source\BoldAwareGUI\Core;$(BoldDelphi)\Source\BoldAwareGUI\FormGen;$(BoldDelphi)\Source\BoldAwareGUI\IDE;$(BoldDelphi)\Source\BoldQAwareGUI\BoldControls;$(BoldDelphi)\Source\BoldQAwareGUI\ControlPacks;$(BoldDelphi)\Source\BoldQAwareGUI\Core;$(BoldDelphi)\Source\ClientGuiCom\BoldControls;$(BoldDelphi)\Source\ClientGuiCom\ControlPacks;$(BoldDelphi)\Source\ClientGuiCom\Core;$(BoldDelphi)\Source\ClientGuiCom\IDE;$(BoldDelphi)\Source\ClientHandlesCom\Core;$(BoldDelphi)\Source\ClientHandlesCom\IDE;$(BoldDelphi)\Source\Common\COM;$(BoldDelphi)\Source\Common\Connection;$(BoldDelphi)\Source\Common\ConnectionCOM;$(BoldDelphi)\Source\Common\ConnectionHandles;$(BoldDelphi)\Source\Common\ConnectionHandlesCOM;$(BoldDelphi)\Source\Common\Core;$(BoldDelphi)\Source\Common\Environment;$(BoldDelphi)\Source\Common\Handles;$(BoldDelphi)\Source\Common\HTTP;$(BoldDelphi)\Source\Common\IDE;$(BoldDelphi)\Source\Common\IDECOM;$(BoldDelphi)\Source\Common\Include;$(BoldDelphi)\Source\Common\Logging;$(BoldDelphi)\Source\Common\MsXml;$(BoldDelphi)\Source\Common\Queue;$(BoldDelphi)\Source\Common\Rose2000;$(BoldDelphi)\Source\Common\Rose98;$(BoldDelphi)\Source\Common\SOAP;$(BoldDelphi)\Source\Common\Subscription;$(BoldDelphi)\Source\Common\Support;$(BoldDelphi)\Source\Common\SupportWin;$(BoldDelphi)\Source\Common\TaggedValues;$(BoldDelphi)\Source\Common\Template;$(BoldDelphi)\Source\Common\UML;$(BoldDelphi)\Source\Common\UtilsGUI;$(BoldDelphi)\Source\ConcurrencyControl\COM;$(BoldDelphi)\Source\ConcurrencyControl\Common;$(BoldDelphi)\Source\ConcurrencyControl\IDECOM;$(BoldDelphi)\Source\Extensions\OLLE;$(BoldDelphi)\Source\Extensions\OLLE\Core;$(BoldDelphi)\Source\Extensions\OLLE\IDE;$(BoldDelphi)\Source\FreestandingValueSpace\Core;$(BoldDelphi)\Source\Handles\Actions;$(BoldDelphi)\Source\Handles\COM;$(BoldDelphi)\Source\Handles\Core;$(BoldDelphi)\Source\Handles\IDE;$(BoldDelphi)\Source\Handles\IDECOM;$(BoldDelphi)\Source\Handles\Manipulators;$(BoldDelphi)\Source\Handles\PessimisticLocking;$(BoldDelphi)\Source\Handles\UnLoader;$(BoldDelphi)\Source\Handles\XML;$(BoldDelphi)\Source\MoldModel\Bld;$(BoldDelphi)\Source\MoldModel\CodeGenerator;$(BoldDelphi)\Source\MoldModel\Core;$(BoldDelphi)\Source\MoldModel\Handles;$(BoldDelphi)\Source\MoldModel\IDE;$(BoldDelphi)\Source\MoldModel\TypeNameDictionary;$(BoldDelphi)\Source\MoldModel\UtilsGUI;$(BoldDelphi)\Source\ObjectSpace\BORepresentation;$(BoldDelphi)\Source\ObjectSpace\COM;$(BoldDelphi)\Source\ObjectSpace\Core;$(BoldDelphi)\Source\ObjectSpace\IDE;$(BoldDelphi)\Source\ObjectSpace\Interfaces;$(BoldDelphi)\Source\ObjectSpace\Ocl;$(BoldDelphi)\Source\ObjectSpace\PessimisticLocking;$(BoldDelphi)\Source\ObjectSpace\RTModel;$(BoldDelphi)\Source\ObjectSpace\Undo;$(BoldDelphi)\Source\ObjectSpace\Unloader;$(BoldDelphi)\Source\ObjectSpace\UtilsGUI;$(BoldDelphi)\Source\ObjectSpace\IDE\AttributeWizard;$(BoldDelphi)\Source\Persistence\ADO;$(BoldDelphi)\Source\Persistence\Advantage;$(BoldDelphi)\Source\Persistence\BDE;$(BoldDelphi)\Source\Persistence\COM;$(BoldDelphi)\Source\Persistence\Core;$(BoldDelphi)\Source\Persistence\DB;$(BoldDelphi)\Source\Persistence\DBExpress;$(BoldDelphi)\Source\Persistence\DBISAM;$(BoldDelphi)\Source\Persistence\DOA;$(BoldDelphi)\Source\Persistence\ExternalPersistence;$(BoldDelphi)\Source\Persistence\File;$(BoldDelphi)\Source\Persistence\FireDAC;$(BoldDelphi)\Source\Persistence\HTTP;$(BoldDelphi)\Source\Persistence\IBX;$(BoldDelphi)\Source\Persistence\IDE;$(BoldDelphi)\Source\Persistence\IDECOM;$(BoldDelphi)\Source\Persistence\IDEUDP;$(BoldDelphi)\Source\Persistence\ObjectUpgrading;$(BoldDelphi)\Source\Persistence\Propagation;$(BoldDelphi)\Source\Persistence\SOAP;$(BoldDelphi)\Source\Persistence\SQLDirect;$(BoldDelphi)\Source\Persistence\System;$(BoldDelphi)\Source\Persistence\UDPPropagator;$(BoldDelphi)\Source\Persistence\UniDAC;$(BoldDelphi)\Source\PMapper\Core;$(BoldDelphi)\Source\PMapper\DbEvolutor;$(BoldDelphi)\Source\PMapper\Default;$(BoldDelphi)\Source\PMapper\SQL;$(BoldDelphi)\Source\PMapper\Validator;$(BoldDelphi)\Source\Propagator\COM;$(BoldDelphi)\Source\Propagator\Common;$(BoldDelphi)\Source\Propagator\Enterprise;$(BoldDelphi)\Source\Propagator\IDECOM;$(BoldDelphi)\Source\Propagator\LowEnd;$(BoldDelphi)\Source\Samples\Actions;$(BoldDelphi)\Source\Samples\BoldCheckListBox;$(BoldDelphi)\Source\Samples\ConstraintValidator;$(BoldDelphi)\Source\Samples\FormSaver;$(BoldDelphi)\Source\Samples\IDE;$(BoldDelphi)\Source\Samples\Misc;$(BoldDelphi)\Source\Samples\ModelLoader;$(BoldDelphi)\Source\Samples\NewObjectInterceptor;$(BoldDelphi)\Source\Samples\SortingGrid;$(BoldDelphi)\Source\Samples\SystemComparer;$(BoldDelphi)\Source\Samples\SystemDebugger;$(BoldDelphi)\Source\Samples\UMLPlugins;$(BoldDelphi)\Source\Samples\Unicode;$(BoldDelphi)\Source\UMLModel\Core;$(BoldDelphi)\Source\UMLModel\Editor;$(BoldDelphi)\Source\UMLModel\Handles;$(BoldDelphi)\Source\UMLModel\Ide;$(BoldDelphi)\Source\UMLModel\ModelLinks;$(BoldDelphi)\Source\UMLModel\Plugins;$(BoldDelphi)\Source\UMLModel\ModelLinks\Bld;$(BoldDelphi)\Source\UMLModel\ModelLinks\Core;$(BoldDelphi)\Source\UMLModel\ModelLinks\ModelMaker;$(BoldDelphi)\Source\UMLModel\ModelLinks\Rose98;$(BoldDelphi)\Source\UMLModel\ModelLinks\XMI;$(BoldDelphi)\Source\UMLModel\ModelLinks\ModelMaker\Link;$(BoldDelphi)\Source\UMLModel\ModelLinks\ModelMaker\MMPlugin;$(BoldDelphi)\Source\UMLModel\ModelLinks\ModelMaker\Support;$(BoldDelphi)\Source\ValueSpace\Condition;$(BoldDelphi)\Source\ValueSpace\ExternalEvents;$(BoldDelphi)\Source\ValueSpace\Id;$(BoldDelphi)\Source\ValueSpace\Interfaces;$(BoldDelphi)\Source\ValueSpace\XMLStreaming; \ No newline at end of file From 5063ed25e656a88e229ad955660c9c761f2236b4 Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Fri, 21 May 2021 16:07:31 +0300 Subject: [PATCH 028/112] Updated PMUpdate call to match required params --- .../OLLE/Core/BoldOLLEDistributableObjectHandlers.pas | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/Source/Extensions/OLLE/Core/BoldOLLEDistributableObjectHandlers.pas b/Source/Extensions/OLLE/Core/BoldOLLEDistributableObjectHandlers.pas index c4ca2b6..5faedcd 100644 --- a/Source/Extensions/OLLE/Core/BoldOLLEDistributableObjectHandlers.pas +++ b/Source/Extensions/OLLE/Core/BoldOLLEDistributableObjectHandlers.pas @@ -71,7 +71,7 @@ TBoldDistributableObjectHandler = class procedure MakeGlobalTranslationListFor(ValueSpace: IBoldValueSpace; IdList: TBoldObjectIdList; GlobalTranslationList: TBoldIdTranslationList); procedure MakeLocalizingTranslationList(ValueSpace: IBoldValueSpace; GlobalIdList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList); procedure SearchByOcl(OclExpr: string; IdList: TBoldObjectIdList); - procedure Update(ValueSpace: IBoldValueSpace; IdList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList; var TimeStamp: Integer); + procedure Update(ValueSpace: IBoldValueSpace; IdList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList; var TimeStamp: TBoldTimeStampType); procedure LockAndFreeObjects(IdList, FreeList: TBoldObjectIdList); procedure VerifyAssociations(ValueSpace: IBoldValueSpace; IdList, HoldList: TBoldObjectIdList); procedure StartTransaction; @@ -848,10 +848,11 @@ procedure TBoldDistributableObjectHandler.MakeLocalizingTranslationList( procedure TBoldDistributableObjectHandler.Update(ValueSpace: IBoldValueSpace; IdList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList; - var TimeStamp: Integer); + var TimeStamp: TBoldTimeStampType); var anObject: IBoldObjectContents; - i, j: Integer; + ClientId, i, j: Integer; + TimeOfLatestUpdate: TDateTime; begin for i := IdList.Count-1 downto 0 do begin @@ -872,7 +873,9 @@ procedure TBoldDistributableObjectHandler.Update(ValueSpace: IBoldValueSpace; anObject.BoldPersistenceState := bvpsModified; end; end; - PController.PMUpdate(IdList, ValueSpace, nil, nil, TranslationList, TimeStamp, 0); + ClientId := 0; + TimeOfLatestUpdate:= now; + PController.PMUpdate(IdList, ValueSpace, nil, nil, TranslationList, TimeStamp, TimeOfLatestUpdate, ClientId); end; procedure TBoldDistributableObjectHandler.LockAndFreeObjects(IdList, From f839c6caa9cddc9c315eda2b15a7e892e991f3e1 Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Fri, 21 May 2021 16:10:16 +0300 Subject: [PATCH 029/112] Now writes UTF8. Added ms to time --- Source/Common/Logging/BoldThreadSafeLog.pas | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/Source/Common/Logging/BoldThreadSafeLog.pas b/Source/Common/Logging/BoldThreadSafeLog.pas index 59f9182..c42a254 100644 --- a/Source/Common/Logging/BoldThreadSafeLog.pas +++ b/Source/Common/Logging/BoldThreadSafeLog.pas @@ -72,7 +72,8 @@ implementation SysUtils, BoldUtils, Windows, - BoldDefs; + BoldDefs, + BoldIsoDateTime; var LogThreadActivities: Boolean; @@ -227,6 +228,7 @@ function TFileLogging.OpenStream: Boolean; procedure TFileLogging.Trace(const Entry: string); var line: string; + Bytes: TBytes; begin fLocker.Acquire; try @@ -235,9 +237,9 @@ procedure TFileLogging.Trace(const Entry: string); if (fMaxSize > 0) and (fFileStream.Size > fMaxSize) then FlushStream; if IncludeDate then - Line := DateTimeToStr(now) + Line := AsISODateTimeMS(now) else - Line := TimeToStr(now); + Line := AsISOTimeMS(now); Line := Line + ' ' + Entry; @@ -250,7 +252,8 @@ procedure TFileLogging.Trace(const Entry: string); end; Line := Line + BOLDCRLF; - fFileStream.Write(Pointer(line)^, Length(line)); + Bytes := TEncoding.UTF8.GetBytes(line); + fFileStream.write(Bytes, Length(Bytes)); end; finally fLocker.Release; @@ -290,6 +293,4 @@ procedure TFileLogging.Trace(const Msg: string; self.Trace(Format(Msg, Args)); end; -initialization - end. From d409cd6a79cfda1047f78a9c62331cdb45a2bc37 Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Fri, 21 May 2021 19:01:32 +0300 Subject: [PATCH 030/112] Removed files --- ...oldOLLEDistributableObjectHandlers.pas.~3~ | 1175 ----------------- .../BoldUMLModelEditorDebugger.dpk.~3~ | 37 - .../BoldUMLModelEditorDebugger.dpk.~4~ | 37 - .../BoldUMLModelEditorDebugger.dpk.~5~ | 37 - .../BoldUMLModelEditorDebugger.dpk.~6~ | 37 - .../BoldUMLModelEditorDebugger.dpk.~7~ | 37 - 6 files changed, 1360 deletions(-) delete mode 100644 Source/Extensions/OLLE/Core/__history/BoldOLLEDistributableObjectHandlers.pas.~3~ delete mode 100644 Source/Unassigned/__history/BoldUMLModelEditorDebugger.dpk.~3~ delete mode 100644 Source/Unassigned/__history/BoldUMLModelEditorDebugger.dpk.~4~ delete mode 100644 Source/Unassigned/__history/BoldUMLModelEditorDebugger.dpk.~5~ delete mode 100644 Source/Unassigned/__history/BoldUMLModelEditorDebugger.dpk.~6~ delete mode 100644 Source/Unassigned/__history/BoldUMLModelEditorDebugger.dpk.~7~ diff --git a/Source/Extensions/OLLE/Core/__history/BoldOLLEDistributableObjectHandlers.pas.~3~ b/Source/Extensions/OLLE/Core/__history/BoldOLLEDistributableObjectHandlers.pas.~3~ deleted file mode 100644 index 460ca39..0000000 --- a/Source/Extensions/OLLE/Core/__history/BoldOLLEDistributableObjectHandlers.pas.~3~ +++ /dev/null @@ -1,1175 +0,0 @@ - -{ Global compiler directives } -{$include bold.inc} -unit BoldOLLEDistributableObjectHandlers; - -interface - -uses - Windows, - BoldDefs, - BoldId, - BoldDefaultId, - BoldGlobalId, - DistributableInfo, - BoldValueInterfaces, - BoldValueSpaceInterfaces, - BoldFreeStandingValues, - BoldElements, - BoldSystem, - BoldCondition, - BoldPersistenceControllerDefault, - BoldPMappers, - BoldPMappersDefault, - BoldPersistenceController, - BoldDbInterfaces, - BoldOLLEdmmain; - - - -const - BOLD_OLL_IDATTRIBUTECOLUMN_NAME = 'LOCALID'; - BOLD_OLL_PSIDATTRIBUTECOLUMN_NAME = 'GLOBALID'; - BOLD_OLL_NAMEOFCLASSATTRIBUTECOLUMN_NAME = 'NAMEOFCLASS'; - -type - TBoldPSId = string; - TBoldDistributableObjectHandler = class; - TBoldForeignObjectHandler = class; - TBoldOwnObjecthandler = class; - TBoldBrokenLinkResolver = class; - - TBoldLinkResolveAction = (blraCut, blraAbort, blraFailObject, blraIgnore, blraMissing); - - TBoldBrokenLinkResolver = class - private - fHeldObjectAction: TBoldLinkResolveAction; - fNonheldObjectAction: TBoldLinkResolveAction; - public - function ResolveBrokenLink(ObjectContents: IBoldObjectContents; MemberIndex: Integer; Hold: Boolean): Boolean; - property HeldObjectAction: TBoldLinkResolveAction read fHeldObjectAction write fHeldObjectAction; - property NonheldObjectAction: TBoldLinkResolveAction read fNonheldObjectAction write fNonheldObjectAction; - end; - - TBoldDistributableObjectHandler = class - private - fPController: TBoldPersistenceControllerDefault; - fOllSystem: TBoldSystem; - fBrokenLinkResolver: TBoldBrokenLinkResolver; - fMyTransaction: Boolean; - fTheMapping: TMapping; - function TheMapping: TMapping; - function LookupInfoByLocalId(LocalId: TBoldDefaultId): TDistributableObjectInfo; - procedure AddToMapping(anObj: TDistributableObjectInfo); - procedure GetLocalIdsFor(InfoObjects: TDistributableObjectInfoList; IdList: TBoldObjectIdList); - function GetForeignPSInfo(PSId: TBoldPSId): TForeignPSInfo; - procedure ExtractAllIds(IdList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; OutIdList: TBoldObjectIdList); - procedure Fetch(IdList: TBoldObjectIdList; ValueSpace: IBoldValueSpace); - procedure GetInfoObjectsFor(IdList: TBoldObjectIdList; InfoObjectList: TDistributableObjectInfoList; RemainingIdList: TBoldObjectIdList); - procedure NewOwnInfoObjectsFor(IdList: TBoldObjectIdList; InfoObjectList: TDistributableObjectInfoList); - procedure NewForeignInfoObjectsFor(IdList: TBoldObjectIdList; InfoObjectList: TDistributableObjectInfoList; Owner: TForeignPSInfo; Hold: Boolean = false); - procedure MakeGlobalTranslationListFor(ValueSpace: IBoldValueSpace; IdList: TBoldObjectIdList; GlobalTranslationList: TBoldIdTranslationList); - procedure MakeLocalizingTranslationList(ValueSpace: IBoldValueSpace; GlobalIdList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList); - procedure SearchByOcl(OclExpr: string; IdList: TBoldObjectIdList); - procedure Update(ValueSpace: IBoldValueSpace; IdList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList; var TimeStamp: Integer); - procedure LockAndFreeObjects(IdList, FreeList: TBoldObjectIdList); - procedure VerifyAssociations(ValueSpace: IBoldValueSpace; IdList, HoldList: TBoldObjectIdList); - procedure StartTransaction; - procedure CommitTransaction; - procedure RollbackTransaction; - public - property PController: TBoldPersistenceControllerDefault read fPController write fPController; - property OllSystem: TBoldSystem read fOllSystem write fOllSystem; - property BrokenLinkResolver: TBoldBrokenLinkResolver read fBrokenLinkResolver write fBrokenLinkResolver; - end; - - TBoldForeignObjectHandler = class(TBoldDistributableObjectHandler) - private - procedure PutObjects(ValueSpace: IBoldValueSpace; IdList, HoldList: TBoldObjectIdList; NewLocalTimeStamp: Integer; Owner: TForeignPSInfo); - procedure StartCheckInObjects(ValueSpace: IBoldValueSpace; IdList, ReleaseList: TBoldObjectIdList; Owner: TForeignPSInfo); - procedure ReleaseObjects(ValueSpace: IBoldValueSpace; IdList: TBoldObjectIdList); - procedure UnReleaseObjects(IdList: TBoldObjectIdList); - public - procedure Put(ValueSpace: IBoldValueSpace; IdList: TBoldObjectIdList; HoldList: TBoldObjectIdList; Owner: TBoldPSId); - procedure StartCheckIn(IdList, ReleaseList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; Owner: TBoldPSId); - procedure AcknowledgeCheckIn(Owner: TBoldPSId; NewTimeStamp: Integer); - procedure FailCheckIn(Owner: TBoldPSId); - procedure ObjectsFrom(Owner: TBoldPSId; Objects: TBoldObjectIdList); - procedure HeldObjectsFrom(Owner: TBoldPSId; Objects: TBoldObjectIdList); - procedure ModifiedObjectsFrom(Owner: TBoldPSId; Objects: TBoldObjectIdList); - end; - - TBoldOwnObjectHandler = class(TBoldDistributableObjectHandler) - private - procedure GetObjects(ValueSpace: IBoldValueSpace; IdList, HoldList: TBoldObjectIdList; Holder: TForeignPSinfo); - procedure CheckInObjects(ValueSpace: IBoldValueSpace; IdList, ReleaseList: TBoldObjectIdList; Holder: TForeignPSInfo); - procedure ReserveObjects(ValueSpace: IBoldValueSpace; HoldList: TBoldObjectIdList); - procedure UnCheckOutObjects(IdList: TBoldObjectIdList; Holder: TForeignPSInfo); - procedure InternalGet(IdList, HoldList: TBoldObjectIdList; Holder: TBoldPSId; ValueSpace: IBoldValueSpace); - public - procedure GetSynch(ForeignPS: TBoldPSId; IdList: TBoldObjectIdList; Valuespace: IBoldValueSpace); - procedure AcknowledgeSynch(ForeignPS: TBoldPSId); - procedure FailSynch(ForeignPS: TBoldPSId); - procedure Get(IdList, HoldList: TBoldObjectIdList; Holder: TBoldPSId; ValueSpace: IBoldValueSpace); - procedure CheckIn(ValueSpace: IBoldValueSpace; IdList, ReleaseList: TBoldObjectIdList; Holder: TBoldPSId; var NewTimeStamp: Integer); - procedure UnCheckOut(IdList: TBoldObjectIdList; Holder: TBoldPSId); - end; - -implementation - -uses - SysUtils, - BoldUtils, - BoldDomainElement; - -procedure AddObjectToIdList(aDistributableInfo: TDistributableObjectInfo; anIdList: TBoldObjectIdList); -var - anId: TBoldDefaultId; -begin - anId := TBoldDefaultId.CreateWithClassId(BUSINESSCLASSESROOT_TOPSORTEDINDEX, false); - - anId.AsInteger := aDistributableInfo.LocalId; - anIdList.Add(anId); - - anId.Free; -end; - - -{ TForeignObjectHandler } - -procedure TBoldForeignObjectHandler.PutObjects( - ValueSpace: IBoldValueSpace; IdList, HoldList: TBoldObjectIdList; NewLocalTimeStamp: Integer; Owner: TForeignPSInfo); -var - InfoObjects: TDistributableObjectInfoList; - i: Integer; - anObjectId: TBoldDefaultId; - anObject: TBoldObject; - MissingInfos: TBoldObjectIdList; - aForeignObjectInfo: TForeignObjectInfo; -begin - InfoObjects := TDistributableObjectInfoList.Create; - anObjectId := TBoldDefaultId.Create; - MissingInfos := TBoldObjectIdList.Create; - try - GetInfoObjectsFor(IdList, InfoObjects, MissingInfos); - NewForeignInfoObjectsFor(MissingInfos, InfoObjects, Owner); - for i := 0 to InfoObjects.Count - 1 do - begin - anObject := InfoObjects[i]; - if not (anObject is TForeignObjectInfo) then - raise EBold.CreateFmt('%s.EnsureForeignInfo: Object is not a foreign object', [Classname]); - aForeignObjectInfo := anObject as TForeignObjectInfo; - if not (aForeignObjectInfo.Owner = Owner) then - raise EBold.CreateFmt('%s.EnsureForeignInfo: Wrong owner', [Classname]); - anObjectId.AsInteger := aForeignObjectInfo.LocalId; - aForeignObjectInfo.Put(ValueSpace, HoldList.IdInList[anObjectId], NewLocalTimeStamp); - end; -{ for i := 0 to MissingInfos.Count - 1 do - begin - aForeignObjectInfo := TForeignObjectInfo.Create(OllSystem); - aForeignObjectInfo.LocalId := (MissingInfos[i] as TBoldDefaultId).AsInteger; - aForeignObjectInfo.Owner := Owner; - aForeignObjectInfo.Put(ValueSpace, HoldList.IdInList[MissingInfos[i]], NewLocalTimeStamp); - end;} - finally - InfoObjects.Free; - anObjectId.Free; - MissingInfos.Free; - end; -end; - -procedure TBoldForeignObjectHandler.Put(ValueSpace: IBoldValueSpace; IdList: TBoldObjectIdList; HoldList: TBoldObjectIdList; Owner: TBoldPSId); -var - TranslationList, TranslationList2: TBoldIdTranslationList; - IdList2, HoldList2: TBoldObjectIdList; - NewLocalTimeStamp: Integer; -begin - TranslationList := TBoldIdTranslationList.Create; - TranslationList2 := TBoldIdTranslationList.Create; - IdList2 := IdList.Clone; - HoldList2 := HoldList.Clone; - - try - StartTransaction; - try - MakeLocalizingTranslationList(ValueSpace, IdList, TranslationList); - - ValueSpace.ApplyTranslationList(TranslationList); - IdList2.ApplyTranslationList(TranslationList); - HoldList2.ApplyTranslationList(TranslationList); - - VerifyAssociations(ValueSpace, IdList2, HoldList2); - Update(ValueSpace, IdList2, TranslationList2, NewLocalTimeStamp); - IdList2.ApplyTranslationList(TranslationList2); - HoldList2.ApplyTranslationList(TranslationList2); - - LockAndFreeObjects(IdList2, HoldList2); - PutObjects(ValueSpace, IdList2, HoldList2, NewLocalTimeStamp, GetForeignPSInfo(Owner)); - OllSystem.UpdateDatabase; - - CommitTransaction; - except - RollbackTransaction; - raise; - end; - finally - IdList2.Free; - HoldList2.Free; - TranslationList.Free; - TranslationList2.Free; - end; -end; - -procedure TBoldForeignObjectHandler.ReleaseObjects(ValueSpace: IBoldValueSpace; - IdList: TBoldObjectIdList); -begin - PController.PMSetReadonlyness(IdList, nil); -end; - -procedure TBoldForeignObjectHandler.StartCheckIn(IdList, - ReleaseList: TBoldObjectIdList; ValueSpace: IBoldValueSpace; Owner: TBoldPSId); -var - GlobalTranslationList: TBoldIdTranslationList; - OwnerForeignPSInfo: TForeignPSInfo; -begin - GlobalTranslationList := TBoldIdTranslationList.Create; - try - StartTransaction; - try - OwnerForeignPSInfo := GetForeignPSInfo(Owner); - if OwnerForeignPSInfo.IsCheckingIn then - raise EBold.CreateFmt('%s.StartCheckIn: Already checking in objects for this persistent storage', [Classname]); - Fetch(Idlist, ValueSpace); - StartCheckInObjects(ValueSpace, IdList, ReleaseList, OwnerForeignPSInfo); - ReleaseObjects(ValueSpace, ReleaseList); - - MakeGlobalTranslationListFor(ValueSpace, IdList, GlobalTranslationList); - ValueSpace.ApplytranslationList(GlobalTranslationList); - IdList.ApplyTranslationList(GlobalTranslationList); - ReleaseList.ApplyTranslationList(GlobalTranslationList); - - OllSystem.UpdateDatabase; - - CommitTransaction; - except - RollbackTransaction; - raise; - end; - finally - GlobalTranslationList.Free; - end; -end; - -procedure TBoldForeignObjectHandler.StartCheckInObjects( - ValueSpace: IBoldValueSpace; IdList, ReleaseList: TBoldObjectIdList; Owner: TForeignPSinfo); -var - i: Integer; - InfoObjectList: TDistributableObjectInfoList; - NewInfoObjectList: TBoldObjectIdList; - aDistributableObjectInfo: TDistributableObjectInfo; - anId: TBoldDefaultId; -begin - InfoObjectList := TDistributableObjectInfoList.Create; - NewInfoObjectList := TBoldObjectIdList.Create; - anId := TBoldDefaultID.Create; - try - GetInfoObjectsFor(IdList, InfoObjectList, NewInfoObjectList); - NewForeignInfoObjectsFor(NewInfoObjectList, InfoObjectList, Owner, True); - for i := 0 to InfoObjectList.Count - 1 do - begin - aDistributableObjectInfo := InfoObjectList[i] as TDistributableObjectInfo; - anId.AsInteger := aDistributableObjectInfo.LocalId; - aDistributableObjectInfo.StartCheckIn(ValueSpace, not ReleaseList.IdInList[anId]); - end; - finally - InfoObjectList.Free; - NewInfoObjectList.Free; - anId.Free; - end; -end; - -procedure TBoldForeignObjectHandler.AcknowledgeCheckIn(Owner: TBoldPSId; - NewTimeStamp: Integer); -begin - GetForeignPSInfo(Owner).AcknowledgeCheckIn(NewTimeStamp); - OllSystem.UpdateDatabase; -end; - -procedure TBoldForeignObjectHandler.FailCheckIn(Owner: TBoldPSId); -var - FailedReleaseList: TBoldObjectIdList; -begin - FailedReleaseList := TBoldObjectIdList.Create; - try - StartTransaction; - try - GetForeignPSInfo(Owner).FailCheckIn(FailedReleaseList); - UnReleaseObjects(FailedReleaseList); - OllSystem.UpdateDatabase; - - CommitTransaction; - except - RollbackTransaction; - raise; - end; - finally - FailedReleaseList.Free; - end; -end; - -procedure TBoldForeignObjectHandler.UnReleaseObjects( - IdList: TBoldObjectIdList); -begin - PController.PMSetReadonlyness(nil, IdList); -end; - -procedure TBoldForeignObjectHandler.HeldObjectsFrom(Owner: TBoldPSId; - Objects: TBoldObjectIdList); -var - anObjectList: TForeignObjectInfoList; - i: Integer; -begin - Objects.Clear; - anObjectList := GetForeignPSInfo(Owner).OwnedObjectInfos; - anObjectList.EnsureObjects; - for i := 0 to anObjectList.Count-1 do - if assigned(anObjectList[i].HeldObjectInfo) then - AddObjectToIdList(anObjectList[i], Objects); -end; - -procedure TBoldForeignObjectHandler.ModifiedObjectsFrom(Owner: TBoldPSId; - Objects: TBoldObjectIdList); -var - i: Integer; - anObjectList: TBoldObjectList; - anElement: TBoldIndirectElement; - anObjectIdList: TBoldObjectIdList; - aValueSpace: TBoldFreeStandingValueSpace; - - function DifferentTimeStamp: Boolean; - var - anObjectContents: IBOldObjectContents; - begin - anObjectContents := (aValueSpace as IBoldValueSpace).GetObjectContentsByObjectId(anObjectIdList[i]); - result := anObjectContents.TimeStamp <> - (anObjectList[i] as THeldObjectInfo).OriginalLocalTimeStamp; - end; - -begin - anElement := TBoldIndirectElement.Create; - anObjectIdList := TBoldObjectIdList.Create; - aValueSpace := TBoldFreeStandingValueSpace.Create; - try - GetForeignPSInfo(Owner).EvaluateExpression('ownedObjectInfos.heldObjectInfo', anElement); - anObjectList := anElement.Value as TBoldObjectList; - anObjectList.EnsureObjects; - for i := 0 to anObjectList.Count-1 do - AddObjectToIdList((anObjectList[i] as THeldObjectInfo).ForeignObjectInfo, anObjectIdList); - Fetch(anObjectIdList, aValueSpace); - for i := 0 to anObjectList.Count-1 do - if DifferentTimeStamp then - Objects.Add(anObjectIdList[i]); - finally - anObjectIdList.Free; - aValueSpace.Free; - anElement.Free; - end; -end; - -procedure TBoldForeignObjectHandler.ObjectsFrom(Owner: TBoldPSId; - Objects: TBoldObjectIdList); -var - anObjectList: TForeignObjectInfoList; - i: Integer; -begin - Objects.Clear; - anObjectList := GetForeignPSInfo(Owner).OwnedObjectInfos; - anObjectList.EnsureObjects; - for i := 0 to anObjectList.Count-1 do - AddObjectToIdList(anObjectList[i], Objects); -end; - - -{ TOwnObjectHandler } - -procedure TBoldOwnObjectHandler.AcknowledgeSynch(ForeignPS: TBoldPSId); -var - aForeignPS: TForeignPSInfo; -begin - aForeignPS := GetForeignPSInfo(ForeignPS); - aForeignPS.LastSynchTimestamp := aForeignPS.OngoingSynchTimestamp; - aForeignPS.OngoingSynchTimestamp := -1; - OllSystem.UpdateDatabase; -end; - -procedure TBoldOwnObjectHandler.CheckIn(ValueSpace: IBoldValueSpace; IdList, - ReleaseList: TBoldObjectIdList; Holder: TBoldPSId; var NewTimeStamp: Integer); -var - TranslationList, TranslationList2: TBoldIdTranslationList; - IdList2, ReleaseList2: TBoldObjectIdList; -begin - TranslationList := TBoldIdTranslationList.Create; - TranslationList2 := TBoldIdTranslationList.Create; - IdList2 := IdList.Clone; - ReleaseList2 := ReleaseList.Clone; - - try - StartTransaction; - try - MakeLocalizingTranslationList(ValueSpace, IdList, TranslationList); - - ValueSpace.ApplyTranslationList(TranslationList); - IdList2.ApplyTranslationList(TranslationList); - ReleaseList2.ApplyTranslationList(TranslationList); - - VerifyAssociations(ValueSpace, IdList2, IdList2); - Update(ValueSpace, IdList2, TranslationList2, NewTimeStamp); - IdList2.ApplyTranslationList(TranslationList2); - ReleaseList2.ApplyTranslationList(TranslationList2); - - LockAndFreeObjects(IdList2, ReleaseList2); - CheckInObjects(ValueSpace, IdList2, ReleaseList2, GetForeignPSInfo(Holder)); - OllSystem.UpdateDatabase; - - CommitTransaction; - except - RollbackTransaction; - raise; - end; - finally - IdList2.Free; - ReleaseList2.Free; - TranslationList.Free; - TranslationList2.Free; - end; -end; - -procedure TBoldOwnObjectHandler.CheckInObjects(ValueSpace: IBoldValueSpace; - IdList, ReleaseList: TBoldObjectIdList; Holder: TForeignPSInfo); -var - InfoObjects: TDistributableObjectInfoList; - NewInfoIds: TBoldObjectIdList; - i: Integer; - anObject: TBoldObject; - anOwnObjectInfo: TOwnObjectInfo; - anObjectId: TBoldDefaultId; -begin - InfoObjects := TDistributableObjectInfoList.Create; - NewInfoIds := TBoldObjectIdList.Create; - anObjectId := TBoldDefaultId.Create; - try - GetInfoObjectsFor(IdList, InfoObjects, NewInfoIds); - for i := 0 to InfoObjects.Count - 1 do - begin - anObject := InfoObjects[i]; - if not (anObject is TOwnObjectInfo) then - raise EBold.CreateFmt('%s.CheckInObjects: Object is not an owned object', [Classname]); - anOwnObjectInfo := anObject as TOwnObjectInfo; - anObjectId.AsInteger := anOwnObjectInfo.LocalId; - anOwnObjectInfo.CheckIn(ValueSpace, ReleaseList.IdInList[anObjectId], Holder); - end; - for i := 0 to NewInfoIds.Count - 1 do - begin - anOwnObjectInfo := TOwnObjectInfo.Create(OllSystem); - anOwnObjectInfo.LocalId := (NewInfoIds[i] as TBoldDefaultId).AsInteger; - AddToMapping(anOwnObjectInfo); - anOwnObjectInfo.CheckedOutObjectInfo := TCheckedOutObjectInfo.Create(OllSystem); - anOwnObjectInfo.CheckedOutObjectInfo.Holder := Holder; - anOwnObjectInfo.CheckIn(ValueSpace, ReleaseList.IdInList[NewInfoIds[i]], Holder); - end; - finally - InfoObjects.Free; - NewInfoIds.Free; - anObjectId.Free; - end; -end; - -procedure TBoldOwnObjectHandler.FailSynch(ForeignPS: TBoldPSId); -begin - GetForeignPSInfo(ForeignPS).OngoingSynchTimestamp := -1; - OllSystem.UpdateDatabase; -end; - -procedure TBoldOwnObjectHandler.Get(IdList, HoldList: TBoldObjectIdList; - Holder: TBoldPSId; ValueSpace: IBoldValueSpace); -begin - StartTransaction; - try - InternalGet(IdList, HoldList, Holder, ValueSpace); - - OllSystem.UpdateDatabase; - CommitTransaction; - except - RollbackTransaction; - raise; - end; -end; - -procedure TBoldOwnObjectHandler.GetObjects(ValueSpace: IBoldValueSpace; IdList, - HoldList: TBoldObjectIdList; Holder: TForeignPSInfo); -var - i: Integer; - InfoObjectList: TDistributableObjectInfoList; - NewInfoObjectList: TBoldObjectIdList; - aDistributableObjectInfo: TDistributableObjectInfo; - anId: TBoldDefaultId; -begin - InfoObjectList := TDistributableObjectInfoList.Create; - NewInfoObjectList := TBoldObjectIdList.Create; - anId := TBoldDefaultID.Create; - try - GetInfoObjectsFor(IdList, InfoObjectList, NewInfoObjectList); - NewOwnInfoObjectsFor(NewInfoObjectList, InfoObjectList); - for i := 0 to InfoObjectList.Count - 1 do - begin - aDistributableObjectInfo := InfoObjectList[i]; - anId.AsInteger := aDistributableObjectInfo.LocalId; - aDistributableObjectInfo.Get(ValueSpace, HoldList.IdInList[anId], Holder); - end; - finally - InfoObjectList.Free; - NewInfoObjectList.Free; - anId.Free; - end; -end; - -procedure TBoldOwnObjectHandler.GetSynch(ForeignPS: TBoldPSId; - IdList: TBoldObjectIdList; Valuespace: IBoldValueSpace); -var - aCond: TBoldTimestampCondition; - i: Integer; - HoldList: TBoldObjectIdList; - MaxTimestamp: Integer; - aTimestamp: Integer; - aForeignPS: TForeignPSInfo; - InfoObjects: TDistributableObjectInfoList; - ChangedObjects: TBoldObjectIdList; - MissingIds: TBoldObjectIdList; -begin - StartTransaction; - try - aForeignPS := GetForeignPSInfo(ForeignPS); - if aForeignPS.IsSynching then - raise EBold.CreateFmt('%s.GetSynch: There is already an ongoing synch that must either be acknowledged or failed.', [classname]); - - ChangedObjects := TBoldObjectIdList.Create; - HoldList := TBoldObjectIdList.Create; - aCond := TBoldTimestampCondition.create; - InfoObjects := TDistributableObjectInfoList.Create; - MissingIds := TBoldObjectIdList.Create; - try - aCond.Timestamp := aForeignPS.LastSynchTimestamp; - fPController.PMFetchIDListWithCondition(ChangedObjects, Valuespace, fmDistributable, aCond, -1); - GetInfoObjectsFor(ChangedObjects, InfoObjects, MissingIds); - NewOwnInfoObjectsFor(MissingIds, InfoObjects); - for i := InfoObjects.Count-1 downto 0 do - if not (InfoObjects[i] is TOwnObjectInfo) then - InfoObjects.RemoveByIndex(i); - - GetLocalIdsFor(InfoObjects, IdList); - InternalGet(IdList, HoldList, ForeignPS, ValueSpace); - MaxTimestamp := 0; - for i := 0 to IdList.Count-1 do - begin - aTimestamp := Valuespace.ObjectContentsByObjectId[IdList[i]].TimeStamp; - if aTimestamp > MaxTimestamp then - MaxTimestamp := aTimestamp; - end; - aForeignPS.OngoingSynchTimestamp := MaxTimestamp; - finally - ChangedObjects.Free; - HoldList.Free; - aCond.Free; - InfoObjects.Free; - end; - - OllSystem.UpdateDatabase; - CommitTransaction; - except - RollbackTransaction; - raise; - end; -end; - -procedure TBoldOwnObjectHandler.InternalGet(IdList, - HoldList: TBoldObjectIdList; Holder: TBoldPSId; - ValueSpace: IBoldValueSpace); -var - GlobalTranslationList: TBoldIdTranslationList; -begin - GlobalTranslationList := TBoldIdTranslationList.Create; - try - Fetch(Idlist, ValueSpace); - GetObjects(ValueSpace, IdList, HoldList, GetForeignPSInfo(Holder)); - ReserveObjects(ValueSpace, HoldList); - - MakeGlobalTranslationListFor(ValueSpace, IdList, GlobalTranslationList); - ValueSpace.ApplytranslationList(GlobalTranslationList); - IdList.ApplyTranslationList(GlobalTranslationList); - HoldList.ApplyTranslationList(GlobalTranslationList); - finally - GlobalTranslationList.Free; - end; -end; - -procedure TBoldOwnObjectHandler.ReserveObjects(ValueSpace: IBoldValueSpace; - HoldList: TBoldObjectIdList); -begin - PController.PMSetReadonlyness(HoldList, nil); -end; - - -procedure TBoldOwnObjectHandler.UnCheckOut(IdList: TBoldObjectIdList; - Holder: TBoldPSId); -var - EmptyIdList: TBoldObjectIdList; - TranslationList: TBoldIdTranslationList; -begin - TranslationList := TBoldIDTranslationList.Create; - EmptyIdList := TBoldObjectIdList.Create; - try - StartTransaction; - try - PController.PMTranslateToLocalIds(IdList, TranslationList); - IdList.ApplyTranslationList(TranslationList); - UnCheckOutObjects(IdList, GetForeignPSInfo(Holder)); - LockAndFreeObjects(EmptyIdList, IdList); - OllSystem.UpdateDatabase; - - CommitTransaction; - except - RollbackTransaction; - raise; - end; - finally - TranslationList.Free; - EmptyIdList.Free; - end; -end; - -procedure TBoldOwnObjectHandler.UnCheckOutObjects(IdList: TBoldObjectIdList; - Holder: TForeignPSInfo); -var - InfoObjects: TDistributableObjectInfoList; - i: Integer; - anOwnObjectInfo: TOwnObjectInfo; - MissingList: TBoldObjectIdList; -begin - InfoObjects := TDistributableObjectInfoList.Create; - MissingList := TBoldObjectIdList.Create; - try - GetInfoObjectsFor(IdList, InfoObjects, MissingList); - for i := 0 to InfoObjects.Count - 1 do - begin - if not (InfoObjects[i] is TOwnObjectInfo) then - raise EBold.CreateFmt('%s.UnCheckOutObjects: Object is not an owned object', [Classname]); - anOwnObjectInfo := InfoObjects[i] as TOwnObjectInfo; - anOwnObjectInfo.UnCheckOut(Holder); - end; - finally - InfoObjects.Free; - MissingList.Free; - end; -end; - -{ TDistributableObjectHandler } - -function TBoldDistributableObjectHandler.GetForeignPSInfo( - PSId: TBoldPSId): TForeignPSInfo; -var - aCondition: TBoldSQLCondition; - PSInfoObjectIdList: TBoldObjectIdList; - aLocator: TBoldObjectLocator; -begin - aCondition := TBoldSQLCondition.Create; - PSInfoObjectIdList := TBoldObjectIdList.Create; - try -{ if assigned(OllSystem.PersistenceController) then - begin - aCondition.TopSortedIndex := OllSystem.BoldSystemTypeInfo.ClassTypeInfoByModelName['ForeignPSInfo'].TopSortedIndex; - aCondition.WhereFragment := BOLD_OLL_PSIDATTRIBUTECOLUMN_NAME + ' = ''' + PSId + ''''; - OllSystem.PersistenceController.PMFetchIDListWithCondition(PSInfoObjectIdList, OllSystem.AsIBoldvalueSpace[bdepPMIn], fmNormal, aCondition, 0); - end else} - SearchByOcl('ForeignPSInfo.allInstances->select(globalId = ''' + PSId + ''')', PSInfoObjectIdList); - if PSInfoObjectIdList.Count = 0 then - begin - result := TForeignPSInfo.Create(OllSystem); - result.GlobalID := PSId; - end else - begin - assert(PSInfoObjectIdList.Count = 1); - aLocator := OllSystem.EnsuredLocatorByID[PSInfoObjectIdList[0]]; - aLocator.EnsureBoldObject; - result := aLocator.BoldObject as TForeignPSInfo; - end; - finally - aCondition.Free; - PSInfoObjectIdList.Free; - end; -end; - -procedure TBoldDistributableObjectHandler.ExtractAllIds(IdList: TBoldObjectIdList; - ValueSpace: IBoldValueSpace; OutIdList: TBoldObjectIdList); - - procedure EnsureIdInList(Id: TBoldObjectId; IdList: TBoldObjectIdList); - begin - if assigned(Id) and - not IdList.IdInList[Id] then - IdList.Add(Id); - end; - -var - i, j: Integer; - anObject: IBoldObjectContents; - aValue: IBoldValue; - IdRef: IBoldObjectIdRef; - IdRefPair: IBoldObjectIdRefPair; -begin - for i := 0 to IdList.Count - 1 do - begin - EnsureIdInList(IdList[i], OutIdList); - anObject := ValueSpace.ObjectContentsByObjectId[IdList[i]]; - if not assigned(anObject) then - anObject := ValueSpace.ObjectContentsByObjectId[IdList[i]]; - for j := 0 to anObject.MemberCount - 1 do - begin - aValue := anObject.ValueByIndex[j]; - if assigned(aValue) then - if aValue.QueryInterface(IBoldObjectIdRef, IdRef) = S_OK then - EnsureIdInList(IdRef.Id, OutIdList) - else if aValue.QueryInterface(IBoldObjectIdRefPair, IdRefPair) = S_OK then - begin - EnsureIdInList(IdRefPair.Id1, OutIdList); - EnsureIdInList(IdRefPair.Id2, OutIdList); - end; - end; - end; -end; - -procedure TBoldDistributableObjectHandler.Fetch(IdList: TBoldObjectIdList; - ValueSpace: IBoldValueSpace); -begin - PController.PMFetch(IdList, ValueSpace, nil, fmDistributable, 0); -end; - -procedure TBoldDistributableObjectHandler.MakeGlobalTranslationListFor( - ValueSpace: IBoldValueSpace; IdList: TBoldObjectIdList; - GlobalTranslationList: TBoldIdTranslationList); -var - anIdList: TBoldObjectIdList; -begin - anIdList := TBoldObjectIdList.Create; - try - ExtractAllIds(IdList, ValueSpace, anIdList); - PController.PMTranslateToGlobalIds(anIdList, GlobalTranslationList); - finally - anIdList.Free; - end; -end; - -procedure TBoldDistributableObjectHandler.GetInfoObjectsFor(IdList: TBoldObjectIdList; - InfoObjectList: TDistributableObjectInfoList; RemainingIdList: TBoldObjectIdList); - - function IdListToSQL(IdList: TBoldObjectIdList): string; - var - i: Integer; - begin - result := IdList[0].AsString; - for i := 1 to IdList.Count - 1 do - result := result + ', ' + IdList[i].AsString; - end; - -var - aCondition: TBoldSQLCondition; - i: Integer; - InfoObj: TDistributableObjectInfo; - RemainingIds: TBoldObjectIdList; - FoundIds: TBoldObjectIdList; - FetchedInfoObjs: TDistributableObjectInfoList; -begin - RemainingIds := IdList.Clone; - FetchedInfoObjs := TDistributableObjectInfoList.Create; - try - for i := RemainingIds.Count-1 downto 0 do - begin - InfoObj := LookupInfoByLocalId(RemainingIds[i] as TBoldDefaultId); - if assigned(InfoObj) then - begin - InfoObjectList.Add(InfoObj); - RemainingIds.RemoveByIndex(i); - end; - end; - - if (RemainingIds.Count > 0) and - assigned(OllSystem.PersistenceController) then - begin - aCondition := TBoldSQLCondition.Create; - FoundIds := TBoldObjectIdList.Create; - try - aCondition.TopSortedIndex := OllSystem.BoldSystemTypeInfo.ClassTypeInfoByModelName['DistributableObjectInfo'].TopSortedIndex; - aCondition.WhereFragment := BOLD_OLL_IDATTRIBUTECOLUMN_NAME + ' IN (' + IdListToSQL(RemainingIds) + ')'; - OllSystem.GetAllWithCondition(FetchedInfoObjs, aCondition); - FetchedInfoObjs.EnsureObjects; - for i := 0 to FetchedInfoObjs.Count-1 do - AddToMapping(FetchedInfoObjs[i]); - GetLocalIdsFor(FetchedInfoObjs, FoundIds); - for i := 0 to FoundIds.Count-1 do - RemainingIds.Remove(RemainingIds.IDByID[FoundIds[i]]); - InfoObjectList.AddList(FetchedInfoObjs); - finally - aCondition.Free; - FoundIds.Free; - end; - end; - - RemainingIdList.AddList(RemainingIds); - - finally - RemainingIds.Free; - FetchedInfoObjs.Free; - end; -end; - -procedure TBoldDistributableObjectHandler.MakeLocalizingTranslationList( - ValueSpace: IBoldValueSpace; - GlobalIdList: TBoldObjectIdList; - TranslationList: TBoldIdTranslationList); -var - AllIdList: TBoldObjectIdList; -begin - AllIdList := TBoldObjectIdList.Create; - try - ExtractAllIds(GlobalIdList, ValueSpace, AllIdList); - PController.PMTranslateToLocalIds(AllIdList, TranslationList); - finally - AllIdList.Free; - end; -end; - -procedure TBoldDistributableObjectHandler.Update(ValueSpace: IBoldValueSpace; - IdList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList; - var TimeStamp: Integer); -var - anObject: IBoldObjectContents; - i, j: Integer; -begin - for i := IdList.Count-1 downto 0 do - begin - anObject := ValueSpace.ObjectContentsByObjectId[IdList[i]]; - for j := 0 to anObject.MemberCount-1 do - anObject.ValueByIndex[j].BoldPersistenceState := bvpsModified; - if IdList[i] is TBoldGlobalId then - begin - if anObject.BoldExistenceState = besDeleted then - IdList.RemoveByIndex(i) - else - begin - anObject.BoldExistenceState := besExisting; - anObject.BoldPersistenceState := bvpsModified; - end; - end else if anObject.BoldExistenceState = besDeleted then - begin - anObject.BoldPersistenceState := bvpsModified; - end; - end; - PController.PMUpdate(IdList, ValueSpace, nil, nil, TranslationList, TimeStamp, TimeStamp, 0); -end; - -procedure TBoldDistributableObjectHandler.LockAndFreeObjects(IdList, - FreeList: TBoldObjectIdList); -var - ReadOnlyList: TBoldObjectIdList; - i: Integer; -begin - ReadOnlyList := IdList.Clone; - try - for i := 0 to FreeList.Count-1 do - ReadOnlyList.Remove(ReadOnlyList.IDByID[FreeList[i]]); - PController.PMSetReadonlyness(ReadOnlyList, FreeList); - finally - ReadOnlyList.Free; - end; -end; - -{ -function TBoldDistributableObjectHandler.NewLocalClassIdFor( - ClassId: TBoldClassIdWithExpressionName): TBoldClassId; -var - i: Integer; - PMapper: TBoldSystemPersistenceMapper; -begin - PMapper := (PController as TBoldPersistenceControllerDefault).PersistenceMapper; - i := 0; - while (i < PMapper.ObjectPersistenceMappers.Count) and - not (PMapper.ObjectPersistenceMappers[i].ExpressionName = ClassId.ExpressionName) do - inc(i); - if not (PMapper.ObjectPersistenceMappers[i].ExpressionName = ClassId.ExpressionName) then - raise EBold.CreateFmt('%s.NewLocalClassIdFor: There is no class with expressionname "%s"', [Classname, ClassId.ExpressionName]); - result := TBoldClassID.CreateWithInfo(True, i); -end; -} -procedure TBoldDistributableObjectHandler.VerifyAssociations( - ValueSpace: IBoldValueSpace; IdList, HoldList: TBoldObjectIdList); -var - i: Integer; - anObject: IBoldObjectContents; - - procedure VerifyObjectRoles(ObjectContents: IBoldObjectContents); - - procedure CascadeToNeighbours; - - procedure VerifyAllInList(anIdList: TBoldObjectIdList); - var - i: Integer; - begin - for i := 0 to anIdList.Count-1 do - begin - if ValueSpace.HasContentsForId[anIdList[i]] then - VerifyObjectRoles(ValueSpace.ObjectContentsByObjectId[anIdList[i]]); - end; - end; - - var - k: Integer; - aMember: IBoldValue; - anIdRef: IBoldObjectIdRef; - anIdRefPair: IBoldObjectIdRefPair; - anIdListRef: IBoldObjectIdListRef; - anIdListRefPair: IBoldObjectIdListRefPair; - begin - for k := 0 to ObjectContents.MemberCount-1 do - begin - aMember := ObjectContents.ValueByIndex[k]; - if assigned(aMember) then - begin - if (aMember.QueryInterface(IBoldObjectIdRef, anIdRef) = S_OK) then - begin - if ValueSpace.HasContentsForId[anIdRef.Id] then - VerifyObjectRoles(ValueSpace.ObjectContentsByObjectId[anIdRef.Id]); - end else if (aMember.QueryInterface(IBoldObjectIdRefPair, anIdRefPair) = S_OK) then - begin - if ValueSpace.HasContentsForId[anIdRefPair.Id1] then - VerifyObjectRoles(ValueSpace.ObjectContentsByObjectId[anIdRefPair.Id1]); - if ValueSpace.HasContentsForId[anIdRefPair.Id2] then - VerifyObjectRoles(ValueSpace.ObjectContentsByObjectId[anIdRefPair.Id2]); - end else if aMember.QueryInterface(IBoldObjectIdListRef, anIdListRef) = S_OK then - begin - end else if aMember.QueryInterface(IBoldObjectIdListRefPair, anIdListRefPair) = S_OK then - begin - - end; - end; - end; - end; - - var - j: integer; - aMember: IBoldValue; - anIdRef: IBoldObjectIdRef; - anIdRefPair: IBoldObjectIdRefPair; - begin - for j := 0 to ObjectContents.MemberCount-1 do - begin - aMember := ObjectContents.ValueByIndex[j]; - if assigned(aMember) then - begin - if ((aMember.QueryInterface(IBoldObjectIdRef, anIdRef) = S_OK) and - (anIdRef.Id is TBoldGlobalId) and - (not ValueSpace.HasContentsForId[anIdRef.Id])) or - ((aMember.QueryInterface(IBoldObjectIdRefPair, anIdRefPair) = S_OK) and - (anIdRefPair.Id1 is TBoldGlobalId) and - (not ValueSpace.HasContentsForId[anIdRefPair.Id1])) then - if assigned(BrokenLinkResolver) then - begin - if not BrokenLinkResolver.ResolveBrokenLink(ObjectContents, j, HoldList.IdInList[IdList[i]]) then - begin - raise EBoldFeatureNotImplementedYet.CreateFmt('%s.VerifyAssociations: Failing inidividual objects not implemented', [classname]); - - end; - end else - raise EBold.Create('Operation failed: Unresolved link'); - end; - end; - end; - -begin - for i := 0 to IdList.Count-1 do - begin - anObject := ValueSpace.ObjectContentsByObjectId[Idlist[i]]; - if assigned(anObject) then - VerifyObjectRoles(anObject); - end; -end; - - -procedure TBoldDistributableObjectHandler.SearchByOcl(OclExpr: string; - IdList: TBoldObjectIdList); -var - anElement: TBoldIndirectElement; - anObjectList: TBoldObjectList; - i: integer; -begin - anElement := TBoldIndirectElement.Create; - try - OllSystem.EvaluateExpression(OclExpr, anElement); - anObjectList := anElement.Value as TBoldObjectList; - for i := 0 to anObjectList.Count-1 do - IdList.Add(anObjectList.Locators[i].BoldObjectID); - finally - anElement.Free; - end; -end; - -procedure TBoldDistributableObjectHandler.CommitTransaction; -begin - if fMyTransaction then - PController.CommitTransaction; - fMyTransaction := false; -end; - -procedure TBoldDistributableObjectHandler.RollbackTransaction; -begin - if fMyTransaction then - PController.RollbackTransaction; - fMyTransaction := false; -end; - -procedure TBoldDistributableObjectHandler.StartTransaction; -begin - if not PController.InTransaction then - begin - PController.StartTransaction; - fMyTransaction := true; - end; -end; -{ -function TBoldDistributableObjectHandler.GetDatabase: IBoldDatabase; -begin - result := ((PController as TBoldPersistenceControllerDefault).PersistenceMapper as TBoldSystemDefaultMapper).Database; -end; - } -{ TBoldBrokenLinkResolver } - -function TBoldBrokenLinkResolver.ResolveBrokenLink( - ObjectContents: IBoldObjectContents; MemberIndex: Integer; - Hold: Boolean): Boolean; -var - ResolveAction: TBoldLinkResolveAction; - - procedure Cut; - var - aMember: IBoldValue; - anIdRef: IBoldObjectIdRef; - anIdRefPair: IBoldObjectIdrefPair; - begin - aMember := ObjectContents.ValueByIndex[MemberIndex]; - if (aMember.QueryInterface(IBoldObjectIdRef, anIdRef) = S_OK) then - anIdRef.SetFromId(nil, false) - else if (aMember.QueryInterface(IBoldObjectIdRefPair, anIdRefPair) = S_OK) then - anIdRefPair.SetFromIds(nil, nil) - else - raise EBoldInternal.CreateFmt('%.ResolveBrokenLink: Member is not a singlelink', [Classname]); - end; - -begin - result := True; - if Hold then - ResolveAction := HeldObjectAction - else - ResolveAction := NonheldObjectAction; - - case ResolveAction of - blraCut: Cut; - blraAbort: raise EBold.Create('Operation failed: Unresolved link'); - blraFailObject: result := False; - blraIgnore:; - blraMissing: raise EBoldFeatureNotImplementedYet.Create('Missing Objects not implemented'); - end; -end; - -procedure TBoldDistributableObjectHandler.GetLocalIdsFor( - InfoObjects: TDistributableObjectInfoList; IdList: TBoldObjectIdList); -var - TempId: TBoldDefaultId; - i: Integer; -begin - TempId := TBoldDefaultID.CreateWithClassID(0, false); - try - for i := 0 to InfoObjects.Count-1 do - begin - TempId.AsInteger := InfoObjects[i].LocalId; - IdList.Add(TempId); - end; - finally - TempId.Free; - end; -end; - -procedure TBoldDistributableObjectHandler.NewOwnInfoObjectsFor( - IdList: TBoldObjectIdList; InfoObjectList: TDistributableObjectInfoList); -var - anOwnObjectInfo: TOwnObjectInfo; - i: integer; -begin - for i := IdList.Count-1 downto 0 do - begin - anOwnObjectInfo := TOwnObjectInfo.Create(OllSystem); - anOwnObjectInfo.LocalId := (IdList[i] as TBoldDefaultId).AsInteger; - AddToMapping(anOwnObjectInfo); - InfoObjectList.Add(anOwnObjectInfo); - end; -end; - -procedure TBoldDistributableObjectHandler.NewForeignInfoObjectsFor( - IdList: TBoldObjectIdList; InfoObjectList: TDistributableObjectInfoList; Owner: TForeignPSInfo; Hold: Boolean = false); -var - i: Integer; - aForeignObjectInfo: TForeignObjectInfo; -begin - for i := 0 to IdList.Count - 1 do - begin - aForeignObjectInfo := TForeignObjectInfo.Create(OllSystem); - if Hold then - aForeignObjectInfo.InitializeHolding(IdList[i], Owner) - else - begin - aForeignObjectInfo.LocalId := (IdList[i] as TBoldDefaultId).AsInteger; - aForeignObjectInfo.Owner := Owner; - end; - AddToMapping(aForeignObjectInfo); - InfoObjectList.Add(aForeignObjectInfo); - end; -end; - -function TBoldDistributableObjectHandler.LookupInfoByLocalId( - LocalId: TBoldDefaultId): TDistributableObjectInfo; -begin - result := TheMapping.ObjectInfo[LocalId.AsInteger]; -end; - -function TBoldDistributableObjectHandler.TheMapping: TMapping; -var - Mappings: TBoldObjectList; -begin - if not assigned(fTheMapping) then - begin - Mappings := fOllSystem.ClassByExpressionName['Mapping']; - if Mappings.Count = 0 then - fTheMapping := TMapping.Create(fOllSystem) - else - begin - assert(Mappings.Count = 1); - fTheMapping := Mappings[0] as TMapping; - end; - end; - result := fTheMapping; -end; - -procedure TBoldDistributableObjectHandler.AddToMapping( - anObj: TDistributableObjectInfo); -begin - TheMapping.M_ObjectInfo.Add(anObj); -end; - -initialization -end. diff --git a/Source/Unassigned/__history/BoldUMLModelEditorDebugger.dpk.~3~ b/Source/Unassigned/__history/BoldUMLModelEditorDebugger.dpk.~3~ deleted file mode 100644 index e870625..0000000 --- a/Source/Unassigned/__history/BoldUMLModelEditorDebugger.dpk.~3~ +++ /dev/null @@ -1,37 +0,0 @@ -package BoldUMLModelEditorDebugger; - -{$R *.RES} -{$ALIGN ON} -{$ASSERTIONS ON} -{$BOOLEVAL OFF} -{$DEBUGINFO ON} -{$EXTENDEDSYNTAX ON} -{$IMPORTEDDATA ON} -{$IOCHECKS ON} -{$LOCALSYMBOLS ON} -{$LONGSTRINGS ON} -{$OPENSTRINGS ON} -{$OPTIMIZATION OFF} -{$OVERFLOWCHECKS OFF} -{$RANGECHECKS OFF} -{$REFERENCEINFO ON} -{$SAFEDIVIDE OFF} -{$STACKFRAMES OFF} -{$TYPEDADDRESS OFF} -{$VARSTRINGCHECKS ON} -{$WRITEABLECONST ON} -{$MINENUMSIZE 1} -{$IMAGEBASE $400000} -{$IMPLICITBUILD OFF} - -requires - vcl270, - Vcldb270, - Bold30D5, - Bold30D5Uml, - Bold30D5Utils; - -contains - BoldUMLModelEditorDebuggerPlugin in 'BoldUMLModelEditorDebuggerPlugin.pas'; - -end. diff --git a/Source/Unassigned/__history/BoldUMLModelEditorDebugger.dpk.~4~ b/Source/Unassigned/__history/BoldUMLModelEditorDebugger.dpk.~4~ deleted file mode 100644 index ea34266..0000000 --- a/Source/Unassigned/__history/BoldUMLModelEditorDebugger.dpk.~4~ +++ /dev/null @@ -1,37 +0,0 @@ -package BoldUMLModelEditorDebugger; - -{$R *.RES} -{$ALIGN ON} -{$ASSERTIONS ON} -{$BOOLEVAL OFF} -{$DEBUGINFO ON} -{$EXTENDEDSYNTAX ON} -{$IMPORTEDDATA ON} -{$IOCHECKS ON} -{$LOCALSYMBOLS ON} -{$LONGSTRINGS ON} -{$OPENSTRINGS ON} -{$OPTIMIZATION OFF} -{$OVERFLOWCHECKS OFF} -{$RANGECHECKS OFF} -{$REFERENCEINFO ON} -{$SAFEDIVIDE OFF} -{$STACKFRAMES OFF} -{$TYPEDADDRESS OFF} -{$VARSTRINGCHECKS ON} -{$WRITEABLECONST ON} -{$MINENUMSIZE 1} -{$IMAGEBASE $400000} -{$IMPLICITBUILD OFF} - -requires - vcl, - Vcldb270, - Bold30D5, - Bold30D5Uml, - Bold30D5Utils; - -contains - BoldUMLModelEditorDebuggerPlugin in 'BoldUMLModelEditorDebuggerPlugin.pas'; - -end. diff --git a/Source/Unassigned/__history/BoldUMLModelEditorDebugger.dpk.~5~ b/Source/Unassigned/__history/BoldUMLModelEditorDebugger.dpk.~5~ deleted file mode 100644 index ce19000..0000000 --- a/Source/Unassigned/__history/BoldUMLModelEditorDebugger.dpk.~5~ +++ /dev/null @@ -1,37 +0,0 @@ -package BoldUMLModelEditorDebugger; - -{$R *.RES} -{$ALIGN ON} -{$ASSERTIONS ON} -{$BOOLEVAL OFF} -{$DEBUGINFO ON} -{$EXTENDEDSYNTAX ON} -{$IMPORTEDDATA ON} -{$IOCHECKS ON} -{$LOCALSYMBOLS ON} -{$LONGSTRINGS ON} -{$OPENSTRINGS ON} -{$OPTIMIZATION OFF} -{$OVERFLOWCHECKS OFF} -{$RANGECHECKS OFF} -{$REFERENCEINFO ON} -{$SAFEDIVIDE OFF} -{$STACKFRAMES OFF} -{$TYPEDADDRESS OFF} -{$VARSTRINGCHECKS ON} -{$WRITEABLECONST ON} -{$MINENUMSIZE 1} -{$IMAGEBASE $400000} -{$IMPLICITBUILD OFF} - -requires - vcl, - Vcldb, - Bold30D5, - Bold30D5Uml, - Bold30D5Utils; - -contains - BoldUMLModelEditorDebuggerPlugin in 'BoldUMLModelEditorDebuggerPlugin.pas'; - -end. diff --git a/Source/Unassigned/__history/BoldUMLModelEditorDebugger.dpk.~6~ b/Source/Unassigned/__history/BoldUMLModelEditorDebugger.dpk.~6~ deleted file mode 100644 index a194f26..0000000 --- a/Source/Unassigned/__history/BoldUMLModelEditorDebugger.dpk.~6~ +++ /dev/null @@ -1,37 +0,0 @@ -package BoldUMLModelEditorDebugger; - -{$R *.RES} -{$ALIGN ON} -{$ASSERTIONS ON} -{$BOOLEVAL OFF} -{$DEBUGINFO ON} -{$EXTENDEDSYNTAX ON} -{$IMPORTEDDATA ON} -{$IOCHECKS ON} -{$LOCALSYMBOLS ON} -{$LONGSTRINGS ON} -{$OPENSTRINGS ON} -{$OPTIMIZATION OFF} -{$OVERFLOWCHECKS OFF} -{$RANGECHECKS OFF} -{$REFERENCEINFO ON} -{$SAFEDIVIDE OFF} -{$STACKFRAMES OFF} -{$TYPEDADDRESS OFF} -{$VARSTRINGCHECKS ON} -{$WRITEABLECONST ON} -{$MINENUMSIZE 1} -{$IMAGEBASE $400000} -{$IMPLICITBUILD OFF} - -requires - vcl, - Vcldb, - Bold90, - Bold90Uml, - Bold90Utils; - -contains - BoldUMLModelEditorDebuggerPlugin in 'BoldUMLModelEditorDebuggerPlugin.pas'; - -end. diff --git a/Source/Unassigned/__history/BoldUMLModelEditorDebugger.dpk.~7~ b/Source/Unassigned/__history/BoldUMLModelEditorDebugger.dpk.~7~ deleted file mode 100644 index 347ef18..0000000 --- a/Source/Unassigned/__history/BoldUMLModelEditorDebugger.dpk.~7~ +++ /dev/null @@ -1,37 +0,0 @@ -package BoldUMLModelEditorDebugger; - -{$R *.RES} -{$ALIGN ON} -{$ASSERTIONS ON} -{$BOOLEVAL OFF} -{$DEBUGINFO ON} -{$EXTENDEDSYNTAX ON} -{$IMPORTEDDATA ON} -{$IOCHECKS ON} -{$LOCALSYMBOLS ON} -{$LONGSTRINGS ON} -{$OPENSTRINGS ON} -{$OPTIMIZATION OFF} -{$OVERFLOWCHECKS OFF} -{$RANGECHECKS OFF} -{$REFERENCEINFO ON} -{$SAFEDIVIDE OFF} -{$STACKFRAMES OFF} -{$TYPEDADDRESS OFF} -{$VARSTRINGCHECKS ON} -{$WRITEABLECONST ON} -{$MINENUMSIZE 1} -{$IMAGEBASE $400000} -{$IMPLICITBUILD OFF} - -requires - vcl, - Vcldb, - Bold90, - Bold30D5Uml, - Bold30D5Utils; - -contains - BoldUMLModelEditorDebuggerPlugin in 'BoldUMLModelEditorDebuggerPlugin.pas'; - -end. From 14ef2db3386a52c24f52bbefdb2b4627164d166a Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Sat, 22 May 2021 12:59:18 +0300 Subject: [PATCH 031/112] Updated for Indy10 --- .../BoldUDPModificationBroadcaster.pas | 20 ++++++++----------- 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/Source/Persistence/UDPPropagator/BoldUDPModificationBroadcaster.pas b/Source/Persistence/UDPPropagator/BoldUDPModificationBroadcaster.pas index c721e23..431ca9c 100644 --- a/Source/Persistence/UDPPropagator/BoldUDPModificationBroadcaster.pas +++ b/Source/Persistence/UDPPropagator/BoldUDPModificationBroadcaster.pas @@ -15,6 +15,7 @@ interface BoldAbstractModificationPropagator, { Indy } + IdGlobal, IdUDPClient, IdUDPServer, IdSocketHandle; @@ -37,7 +38,7 @@ TBoldUDPModificationBroadcaster = class(TBoldAbstractNotificationPropagator) protected procedure OnSendQueueNotEmpty(Sender: TBoldThreadSafeQueue); override; procedure SetActive(Value: Boolean); override; - procedure InternalUDPRead(Sender: TObject; AData: TStream; ABinding: TIdSocketHandle); + procedure InternalUDPRead(AThread: TIdUDPListenerThread; const AData: TIdBytes; ABinding: TIdSocketHandle); public constructor Create(AOwner: TComponent); override; destructor Destroy; override; @@ -70,7 +71,8 @@ constructor TBoldUDPModificationBroadcaster.Create(AOwner: TComponent); fUDPClient := TIdUDPClient.Create(Self); fUDPServer := TIdUDPServer.Create(Self); fUDPClient.BroadcastEnabled := True; - fUDPServer.OnUDPRead := InternalUDPRead; //Fix + fUDPServer.OnUDPRead := InternalUDPRead; +// procedure(AThread: TIdUDPListenerThread; const AData: TIdBytes; ABinding: TIdSocketHandle) fUDPClient.Host := '255.255.255.255'; fUDPClient.Port := 4098; @@ -123,19 +125,13 @@ procedure TBoldUDPModificationBroadcaster.SetPort(Value: Integer); fUDPServer.Bindings.Add.Port := Value; end; -procedure TBoldUDPModificationBroadcaster.InternalUDPRead(Sender: TObject; AData: TStream; - ABinding: TIdSocketHandle); +procedure TBoldUDPModificationBroadcaster.InternalUDPRead(AThread: TIdUDPListenerThread; const AData: TIdBytes; ABinding: TIdSocketHandle); var S: String; begin - if AData.Size - AData.Position > 0 then - begin - SetLength(S, AData.Size - AData.Position); - AData.Read(S[1], Length(S)); - if Length(S) > 0 then - if SameText(Copy(S, 1, Length(SIdentification)), SIdentification) then - ReceiveEvent(Copy(S, Length(SIdentification) + 1, Length(S))); - end; + s := BytesToString(AData); + if SameText(Copy(S, 1, Length(SIdentification)), SIdentification) then + ReceiveEvent(Copy(S, Length(SIdentification) + 1, Length(S))); end; procedure TBoldUDPModificationBroadcaster.OnSendQueueNotEmpty(Sender: TBoldThreadSafeQueue); From d49f019a6d859eb6276df92a9b46823483a62146 Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Sat, 22 May 2021 13:00:43 +0300 Subject: [PATCH 032/112] Check if IBoldBlobStreamContent is supported, it won't be with remote persistence. --- .../PMapper/Default/BoldPMappersAttributeDefault.pas | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Source/PMapper/Default/BoldPMappersAttributeDefault.pas b/Source/PMapper/Default/BoldPMappersAttributeDefault.pas index b4ddb48..96d1127 100644 --- a/Source/PMapper/Default/BoldPMappersAttributeDefault.pas +++ b/Source/PMapper/Default/BoldPMappersAttributeDefault.pas @@ -751,8 +751,11 @@ procedure TBoldPMBlob.ValueFromField(OwningObjectId: TBoldObjectId; const Object begin EnsureFirstColumn(ColumnIndex); aBlob := GetEnsuredValue(ObjectContent) as IBoldBlobContent; - aBlobStreamContent := aBlob as IBoldBlobStreamContent; - aBlobStreamContent.BeginSupressEvents; + if Supports(aBlob, IBoldBlobStreamContent) then + begin + aBlobStreamContent := aBlob as IBoldBlobStreamContent; + aBlobStreamContent.BeginSupressEvents; + end; try if Field.IsNull then aBlob.SetContentToNull @@ -764,7 +767,8 @@ procedure TBoldPMBlob.ValueFromField(OwningObjectId: TBoldObjectId; const Object aBlob.AsBlob := Field.AsBlob; end; finally - aBlobStreamContent.EndSupressEvents; + if Assigned(aBlobStreamContent) then + aBlobStreamContent.EndSupressEvents; end; end; From 07f42a305b43f4746e28daf1c045bcc955a1f15d Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Sat, 22 May 2021 13:02:35 +0300 Subject: [PATCH 033/112] fix delete from end when full --- Source/Common/Logging/BoldLogForm.pas | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/Source/Common/Logging/BoldLogForm.pas b/Source/Common/Logging/BoldLogForm.pas index 30479ef..cc8cb26 100644 --- a/Source/Common/Logging/BoldLogForm.pas +++ b/Source/Common/Logging/BoldLogForm.pas @@ -66,11 +66,10 @@ implementation procedure TBoldLogForm.AddLog(const s: string); const - cMaxLines = 10000; + cMaxLines = 20000; begin while LogLines.Count > cMaxLines do - LogLines.Delete(LogLines.Count-1); - + LogLines.Delete(0); LogLines.Add(s); try UpdateView; @@ -157,6 +156,4 @@ procedure TBoldLogForm.mnuClearLogClick(Sender: TObject); UpdateView; end; -initialization - end. From d1506f62894b930a8f0f5689274ad6af6570afce Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Sat, 22 May 2021 13:04:13 +0300 Subject: [PATCH 034/112] Added OnExpressionChanged and changed info link to www.omg.org/spec/OCL --- .../UtilsGUI/BoldOclPropEditor.pas | 27 +++++++++---------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/Source/ObjectSpace/UtilsGUI/BoldOclPropEditor.pas b/Source/ObjectSpace/UtilsGUI/BoldOclPropEditor.pas index badde87..cb42f74 100644 --- a/Source/ObjectSpace/UtilsGUI/BoldOclPropEditor.pas +++ b/Source/ObjectSpace/UtilsGUI/BoldOclPropEditor.pas @@ -103,6 +103,7 @@ TBoldOclPropEditForm = class(TForm) fVariables: TBoldExternalVariableList; fCompleteSelectList: TStrings; fMRUExpressionList: TStringList; + FOnExpressionChanged: TNotifyEvent; procedure SetOclExpr(Expr: String); function GetOclExpr: String; procedure SetContext(Context: TBoldElementTypeInfo); @@ -133,6 +134,7 @@ TBoldOclPropEditForm = class(TForm) property SystemTypeInfo: TBoldSystemTypeInfo read fSystemTypeInfo; property OclExpr: String read GetOclExpr write SetOclExpr; property Variables: TBoldExternalVariableList read fVariables write SetVariables; + property OnExpressionChanged: TNotifyEvent read FOnExpressionChanged write FOnExpressionChanged; end; implementation @@ -140,7 +142,7 @@ implementation uses SysUtils, StrUtils, - BoldUtils, + BoldUtils, BoldDefs, BoldRegistry, BoldOclError, @@ -150,8 +152,7 @@ implementation {$R *.dfm} const - OCLInfoURL = 'http://www.boldsoft.com/go/oclinfo'; - OCLInfoLocal = 'doc\oclinfo.html'; + OCLInfoURL = 'https://www.omg.org/spec/OCL/'; cMRUExpressionRegKey = '\MRU'; cMRUExpressionRegKeyName = 'OCL Expression'; cHiddenOCLVariables: array[0..3] of string = ('Nil', 'True', 'False', 'TimeStampNow'); @@ -368,7 +369,7 @@ function TBoldOclPropEditForm.CheckOcl(Ocl: String): TBoldElementTypeInfo; insert('-------', errorPointer, length(ErrorPointer)); end else ErrorPointer := ErrorPointer + '-------'; - + ParserMessages.lines.Insert(i+1, ErrorPointer); end; @@ -456,7 +457,7 @@ procedure TBoldOclPropEditForm.OperationHelp(Ocl: String); if (not Assigned(Symbol.FormalArguments[0]) or ExpressionType.ConformsTo(Symbol.formalArguments[0]) or ((ExpressionType is TBoldListTypeInfo) and - assigned(TBoldListTypeInfo(ExpressionType).ListElementTypeInfo) and + assigned(TBoldListTypeInfo(ExpressionType).ListElementTypeInfo) and TBoldListTypeInfo(ExpressionType).ListElementTypeInfo.ConformsTo(Symbol.FormalArguments[0]))) and symbol.IsPostFix then begin Addition := '5 | ' + prefix[Symbol.IsDotNotation] + Symbol.SymbolName; @@ -612,7 +613,7 @@ procedure TBoldOclPropEditForm.SelectBoxDblClick(Sender: TObject); if filterCombo.ItemIndex = -1 then filterCombo.Clear; - + EditMemoChange(Sender); end; @@ -655,6 +656,8 @@ procedure TBoldOclPropEditForm.EditMemoChange(Sender: TObject); SelectBox.Items.EndUpdate; fCompleteSelectList.EndUpdate; end; + if Assigned(fOnExpressionChanged) then + OnExpressionChanged(self); { if Ocl = '' then begin @@ -834,7 +837,7 @@ procedure TBoldOclPropEditForm.filterComboExit(Sender: TObject); if (FilterCombo.ItemIndex = -1) and (FilterCombo.Text = '') then begin FilterCombo.ItemIndex := 0; - EditMemoChange(Sender); + EditMemoChange(Sender); end; end; @@ -859,7 +862,7 @@ procedure TBoldOclPropEditForm.EditMemoKeyPress(Sender: TObject; var Key: Char); procedure TBoldOclPropEditForm.OKClick(Sender: TObject); begin Modalresult := mrOK; - AddExpressionToMRUList; + AddExpressionToMRUList; end; procedure TBoldOclPropEditForm.CancelClick(Sender: TObject); @@ -1044,14 +1047,8 @@ procedure TBoldOclPropEditForm.InfoBrowserClick(Sender: TObject); var URL: String; begin - if (GetBoldBasePath <> '') and fileexists(GetBoldBasePath+'\'+OCLInfoLocal) then - URL := GetBoldBasePath+'\'+OCLInfoLocal - else - URL := OCLInfoURL; - + URL := OCLInfoURL; ShellExecute(0, 'open', PChar(URL), '', '', SW_SHOWMAXIMIZED); end; -initialization - end. From a45109d978cd36c4ff65680004717f5b5b8c1f2d Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Sat, 22 May 2021 13:11:54 +0300 Subject: [PATCH 035/112] TBoldSetCheckPointAction now only enabled if there is a non empty current undo block --- Source/Handles/Actions/BoldUndoActions.pas | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Source/Handles/Actions/BoldUndoActions.pas b/Source/Handles/Actions/BoldUndoActions.pas index aae4a20..79394f7 100644 --- a/Source/Handles/Actions/BoldUndoActions.pas +++ b/Source/Handles/Actions/BoldUndoActions.pas @@ -54,7 +54,8 @@ procedure TBoldSetCheckPointAction.CheckAllowEnable( begin inherited; if EnableAction then - EnableAction := BoldSystemHandle.Active; + EnableAction := BoldSystemHandle.Active and BoldSystemHandle.System.UndoHandlerInterface.Enabled + and not ((BoldSystemHandle.System.UndoHandlerInterface.UndoList.Count > 0) and not BoldSystemHandle.System.UndoHandlerInterface.CurrentUndoBlockHasChanges); end; constructor TBoldSetCheckPointAction.Create(AOwner: TComponent); From 053e87c37e5f38f5209e969b848d23a99f024830 Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Sat, 22 May 2021 13:12:28 +0300 Subject: [PATCH 036/112] New TBoldDiscardChangesAction and CreateDB now has IgnoreUnknownTables property --- Source/Handles/Actions/BoldActions.pas | 40 ++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/Source/Handles/Actions/BoldActions.pas b/Source/Handles/Actions/BoldActions.pas index 8e72e2f..d6027e6 100644 --- a/Source/Handles/Actions/BoldActions.pas +++ b/Source/Handles/Actions/BoldActions.pas @@ -18,7 +18,9 @@ TBoldSystemHandleAction = class; TBoldActivateSystemAction = class; TBoldUpdateDBAction = class; TBoldFailureDetectionAction = class; - + TBoldCreateDatabaseAction = class; + TBoldDiscardChangesAction = class; + TBoldSaveAction = (saAsk, saYes, saNo, saFail); { TBoldSystemHandleAction } @@ -47,6 +49,15 @@ TBoldUpdateDBAction = class(TBoldSystemHandleAction) procedure ExecuteTarget(Target: TObject); override; end; + { TBoldDiscardChangesAction } + TBoldDiscardChangesAction = class(TBoldSystemHandleAction) + protected + procedure CheckAllowEnable(var EnableAction: boolean); override; + public + constructor Create(AOwner: TComponent); override; + procedure ExecuteTarget(Target: TObject); override; + end; + { TBoldActivateSystemAction } TBoldActivateSystemAction = class(TBoldSystemHandleAction) private @@ -83,6 +94,7 @@ TBoldActivateSystemAction = class(TBoldSystemHandleAction) TBoldCreateDatabaseAction = class(TBoldSystemHandleAction) private fOnSchemaGenerated: TNotifyEvent; + fIgnoreUnknownTables: boolean; procedure SchemaGenerated; protected procedure GenerateSchema; @@ -92,6 +104,7 @@ TBoldCreateDatabaseAction = class(TBoldSystemHandleAction) procedure ExecuteTarget(Target: TObject); override; published property OnSchemaGenerated: TNotifyEvent read fOnSchemaGenerated write fOnSchemaGenerated; + property IgnoreUnknownTables: boolean read fIgnoreUnknownTables write fIgnoreUnknownTables; end; implementation @@ -321,7 +334,7 @@ procedure TBoldCreateDatabaseAction.GenerateSchema; Screen.Cursor := crHourGlass; try BoldSystemHandle.PersistenceHandleDB.CreateDataBase; - BoldSystemHandle.PersistenceHandleDB.CreateDataBaseSchema; + BoldSystemHandle.PersistenceHandleDB.CreateDataBaseSchema(IgnoreUnknownTables); finally Screen.Cursor := crDefault; end; @@ -335,6 +348,27 @@ procedure TBoldCreateDatabaseAction.SchemaGenerated; fOnSchemaGenerated(Self); end; -initialization +{ TBoldDiscardChangesAction } + +procedure TBoldDiscardChangesAction.CheckAllowEnable(var EnableAction: boolean); +begin + inherited; + if EnableAction then + EnableAction := BoldSystemHandle.Active and + (BoldSystemHandle.System.DirtyObjects.Count > 0); +end; + +constructor TBoldDiscardChangesAction.Create(AOwner: TComponent); +begin + inherited; + Caption := 'Discard changes'; +end; + +procedure TBoldDiscardChangesAction.ExecuteTarget(Target: TObject); +begin + inherited; + if Assigned(BoldSystemHandle) then + BoldSystemHandle.Discard; +end; end. From c8d311f55913c69993aff14b2dfde0f6ddc567db Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Sat, 22 May 2021 13:14:16 +0300 Subject: [PATCH 037/112] Added comment where x64 compile fails with Cardinal typecast of interface. --- Source/Common/ConnectionCOM/BoldComServer.pas | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Common/ConnectionCOM/BoldComServer.pas b/Source/Common/ConnectionCOM/BoldComServer.pas index 6e7a990..6bfec25 100644 --- a/Source/Common/ConnectionCOM/BoldComServer.pas +++ b/Source/Common/ConnectionCOM/BoldComServer.pas @@ -462,7 +462,7 @@ destructor TBoldComServerConnection.Destroy; FConnected := False; FActive := False; TBoldComServer.Instance.RemoveConnection(Self); - BoldEventSenderThreadList.DisconnectClient(Cardinal(FClientInterface)); + BoldEventSenderThreadList.DisconnectClient(Cardinal(FClientInterface)); // does not compile in x64 !!! // if Assigned(FSenderThread) then // begin // FSenderThread.Terminate; From 098a72235afcaff0a2ede74b8592fadbcfb68b00 Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Sat, 22 May 2021 16:34:21 +0300 Subject: [PATCH 038/112] New DropDatabase and DatabaseExists methods in db and adapter. CreateDatabase now has param DropExisting. Times now logged with ms. Params handling updated for FireDac. --- .../DB/BoldAbstractDatabaseAdapter.pas | 4 +- .../DB/BoldAbstractPersistenceHandleDB.pas | 12 ++- Source/Persistence/DB/BoldDBInterfaces.pas | 28 ++++-- .../FireDAC/BoldDatabaseAdapterFireDAC.pas | 18 +++- .../FireDAC/BoldFireDACInterfaces.pas | 94 +++++++++++++++---- .../Persistence/IBX/BoldDatabaseAdapterIB.pas | 12 ++- Source/Persistence/IBX/BoldIBInterfaces.pas | 4 +- .../UniDAC/BoldDatabaseAdapterUniDAC.pas | 8 +- .../UniDAC/BoldUniDACInterfaces.pas | 83 +++++++++++++--- 9 files changed, 209 insertions(+), 54 deletions(-) diff --git a/Source/Persistence/DB/BoldAbstractDatabaseAdapter.pas b/Source/Persistence/DB/BoldAbstractDatabaseAdapter.pas index dd314e8..67a1c26 100644 --- a/Source/Persistence/DB/BoldAbstractDatabaseAdapter.pas +++ b/Source/Persistence/DB/BoldAbstractDatabaseAdapter.pas @@ -40,7 +40,9 @@ TBoldAbstractDatabaseAdapter = class(TBoldSubscribableComponent) public constructor create(aOwner: TComponent); override; destructor destroy; override; - procedure CreateDatabase; virtual; abstract; + procedure CreateDatabase(DropExisting: boolean = true); virtual; abstract; + procedure DropDatabase; virtual; abstract; + function DatabaseExists: boolean; virtual; abstract; property DatabaseInterface: IBoldDatabase read GetDatabaseInterface; published property SQLDatabaseConfig: TBoldSQLDatabaseConfig read FSQLDatabaseConfig write SetSQLDatabaseConfig; diff --git a/Source/Persistence/DB/BoldAbstractPersistenceHandleDB.pas b/Source/Persistence/DB/BoldAbstractPersistenceHandleDB.pas index 9ef9831..76dd08e 100644 --- a/Source/Persistence/DB/BoldAbstractPersistenceHandleDB.pas +++ b/Source/Persistence/DB/BoldAbstractPersistenceHandleDB.pas @@ -53,7 +53,8 @@ TBoldAbstractPersistenceHandleDB = class(TBoldPersistenceHandle) destructor destroy; override; property PersistenceControllerDefault: TBoldPersistenceControllerDefault read GetPersistenceControllerDefault; procedure CreateDataBaseSchema(IgnoreUnknownTables: Boolean = false); - procedure CreateDataBase; + procedure CreateDataBase(DropExisting: boolean = true); + procedure DropDataBase; procedure AddModelEvolutionInfoToDatabase; property DatabaseInterface: IBoldDatabase read GetDatabaseInterface; property SQLDatabaseConfig: TBoldSQLDatabaseConfig read GetSQLDatabaseConfig; @@ -156,9 +157,9 @@ constructor TBoldAbstractPersistenceHandleDB.create(Owner: TComponent); fComponentSubscriber := TBoldPassthroughSubscriber.Create(_ReceiveComponentEvents); end; -procedure TBoldAbstractPersistenceHandleDB.CreateDataBase; +procedure TBoldAbstractPersistenceHandleDB.CreateDataBase(DropExisting: boolean); begin - DatabaseInterface.CreateDatabase; + DatabaseInterface.CreateDatabase(DropExisting); end; procedure TBoldAbstractPersistenceHandleDB.CreateDataBaseSchema( @@ -220,6 +221,11 @@ destructor TBoldAbstractPersistenceHandleDB.destroy; inherited; end; +procedure TBoldAbstractPersistenceHandleDB.DropDataBase; +begin + DatabaseInterface.DropDatabase; +end; + function TBoldAbstractPersistenceHandleDB.GetClockLogGranularity: string; var hrs, mins, secs, msecs: Word; diff --git a/Source/Persistence/DB/BoldDBInterfaces.pas b/Source/Persistence/DB/BoldDBInterfaces.pas index bb0c9cc..cee54a9 100644 --- a/Source/Persistence/DB/BoldDBInterfaces.pas +++ b/Source/Persistence/DB/BoldDBInterfaces.pas @@ -326,7 +326,9 @@ TBoldIndexDescription = record property SQLDatabaseConfig: TBoldSQLDatabaseConfig read GetSQLDatabaseConfig; function GetIsExecutingQuery: Boolean; property IsExecutingQuery: Boolean read GetIsExecutingQuery; - procedure CreateDatabase; + procedure CreateDatabase(DropExisting: boolean = true); + procedure DropDatabase; + function DatabaseExists: boolean; end; TBoldParameterWrapper = class(TBoldRefCountedObject) @@ -506,7 +508,9 @@ TBoldDatabaseWrapper = class(TBoldNonRefCountedObject) public constructor Create(SQLDataBaseConfig: TBoldSQLDatabaseConfig); destructor Destroy; override; - procedure CreateDatabase; virtual; abstract; + procedure CreateDatabase(DropExisting: boolean = true); virtual; abstract; + procedure DropDatabase; virtual; abstract; + function DatabaseExists: boolean; virtual; abstract; property SQLDatabaseConfig: TBoldSQLDatabaseConfig read GetSQLDatabaseConfig; end; @@ -573,7 +577,8 @@ implementation Variants, Windows, BoldSharedStrings, - BoldUtils; + BoldUtils, + BoldIsoDateTime; procedure BoldLogSQL(const sql: TStrings); var @@ -585,7 +590,7 @@ procedure BoldLogSQL(const sql: TStrings); if BoldSQLMessage <> '' then BoldSQLLogHandler.Log(BoldSQLMessage); BoldSQLLogHandler.Log( - formatDateTime('c: ', now) + + AsIsoDateTimeMs(now) +':'+ format('SQL %3d- %s', [BoldSQLLogCount, trim(SQL[0])])); for i := 1 to SQL.Count - 1 do begin @@ -606,7 +611,7 @@ procedure BoldLogSQLWide(const sql: TWideStrings; const Params: IBoldParameteriz if BoldSQLMessage <> '' then BoldSQLLogHandler.Log(BoldSQLMessage); BoldSQLLogHandler.Log( - formatDateTime('c: ', now) + + AsIsoDateTimeMs(now) +':'+ format('SQL %3d- %s', [BoldSQLLogCount, trim(SQL[0])])); for i := 1 to SQL.Count - 1 do begin @@ -652,7 +657,7 @@ procedure BoldLogSQLWithParams(const sql: TStrings; const Params: IBoldParameter if BoldSQLMessage <> '' then BoldSQLLogHandler.Log(BoldSQLMessage); BoldSQLLogHandler.Log( - formatDateTime('c: ', now) + + AsIsoDateTimeMs(now) +':'+ format('SQL %3d- %s', [BoldSQLLogCount, trim(SQL[0])])); for i := 1 to SQL.Count - 1 do begin @@ -1635,6 +1640,8 @@ function TBoldBatchDataSetWrapper.ParamsContainBlob: Boolean; end; end; +type TCollectionAccess = class(TCollection); + procedure TBoldBatchDataSetWrapper.ReplaceParamMarkers(sql: TStrings; const Source, Dest: IBoldExecQuery); const @@ -1673,7 +1680,6 @@ procedure TBoldBatchDataSetWrapper.ReplaceParamMarkers(sql: TStrings; end; begin - SourceParams := Source.Params; DestParams := Dest.Params; if Source.ParamCount = 0 then begin @@ -1685,9 +1691,12 @@ procedure TBoldBatchDataSetWrapper.ReplaceParamMarkers(sql: TStrings; end else begin + SourceParams := Source.Params; if Dest.ParamCount = 0 then begin - Dest.Params.Assign(Source.Params); + DestParams.Assign(SourceParams); + while TCollectionAccess(DestParams).UpdateCount > 0 do + DestParams.EndUpdate; for i := 0 to Sql.Count - 1 do begin Line := sql[i]; @@ -1747,6 +1756,7 @@ procedure TBoldBatchDataSetWrapper.ReplaceParamMarkers(sql: TStrings; end; end; SB.Append(DatabaseWrapper.SQLDatabaseConfig.BatchQuerySeparator); + Dest.AssignParams(DestParams); Dest.SQLStrings.Add(sb.ToString); Inc(fAccumulatedSQLLength, SB.Length + Length(Dest.SQLStrings.LineBreak)); SB.Clear; @@ -1892,6 +1902,4 @@ procedure TBoldBatchDataSetWrapper.ExecuteBatch; end; end; -initialization - end. diff --git a/Source/Persistence/FireDAC/BoldDatabaseAdapterFireDAC.pas b/Source/Persistence/FireDAC/BoldDatabaseAdapterFireDAC.pas index 3e7ba0c..3e4eda5 100644 --- a/Source/Persistence/FireDAC/BoldDatabaseAdapterFireDAC.pas +++ b/Source/Persistence/FireDAC/BoldDatabaseAdapterFireDAC.pas @@ -26,7 +26,9 @@ TBoldDatabaseAdapterFireDAC = class(TBoldAbstractDatabaseAdapter) function GetDataBaseInterface: IBoldDatabase; override; public destructor Destroy; override; - procedure CreateDatabase; override; + procedure CreateDatabase(DropExisting: boolean = true); override; + procedure DropDatabase; override; + function DatabaseExists: boolean; override; published property Connection: TFDConnection read GetConnection write SetConnection; {$IFNDEF T2H} @@ -44,6 +46,11 @@ implementation { TBoldDatabaseAdapterFireDAC } +function TBoldDatabaseAdapterFireDAC.DatabaseExists: boolean; +begin + result := DatabaseInterface.DatabaseExists; +end; + destructor TBoldDatabaseAdapterFireDAC.Destroy; begin Changed; @@ -52,9 +59,14 @@ destructor TBoldDatabaseAdapterFireDAC.Destroy; inherited; end; -procedure TBoldDatabaseAdapterFireDAC.CreateDatabase; +procedure TBoldDatabaseAdapterFireDAC.DropDatabase; +begin + DatabaseInterface.DropDatabase; +end; + +procedure TBoldDatabaseAdapterFireDAC.CreateDatabase(DropExisting: boolean = true); begin - DatabaseInterface.CreateDatabase; + DatabaseInterface.CreateDatabase(DropExisting); end; function TBoldDatabaseAdapterFireDAC.GetConnection: TFDConnection; diff --git a/Source/Persistence/FireDAC/BoldFireDACInterfaces.pas b/Source/Persistence/FireDAC/BoldFireDACInterfaces.pas index e9242ff..74e5546 100644 --- a/Source/Persistence/FireDAC/BoldFireDACInterfaces.pas +++ b/Source/Persistence/FireDAC/BoldFireDACInterfaces.pas @@ -242,7 +242,9 @@ TBoldFireDACConnection = class(TBoldDatabaseWrapper, IBoldDataBase) public constructor Create(aFDConnection: TFDConnection; SQLDataBaseConfig: TBoldSQLDatabaseConfig); destructor Destroy; override; - procedure CreateDatabase; override; + procedure CreateDatabase(DropExisting: boolean = true); override; + procedure DropDatabase; override; + function DatabaseExists: boolean; override; function GetDatabaseError(const E: Exception; const sSQL: string = ''): EBoldDatabaseError; property ExecuteQueryCount: integer read fExecuteQueryCount; @@ -262,6 +264,8 @@ implementation FireDAC.Comp.Script, FireDAC.Comp.ScriptCommands, FireDAC.Phys.Intf, + FireDAC.Phys.PGWrapper, + FireDAC.Stan.Intf, BoldUtils, BoldGuard, @@ -581,12 +585,12 @@ constructor TBoldFireDACTable.Create(aFDTable: TFDTable; BoldFireDACConnection: procedure TBoldFireDACTable.CreateTable; begin - raise EBold.CreateFmt('MethodNotImplemented', [ClassName, 'CreateTable']); // do not localize + FDTable.CreateTable(true); end; procedure TBoldFireDACTable.DeleteTable; begin - raise EBold.CreateFmt('MethodNotImplemented', [ClassName, 'DeleteTable']); // do not localize + FDTable.ExecSQL('Drop Table ' + FDTable.TableName); end; function TBoldFireDACTable.FindParam(const Value: string): IBoldParameter; @@ -601,8 +605,21 @@ function TBoldFireDACTable.FindParam(const Value: string): IBoldParameter; procedure TBoldFireDACTable.AddIndex(const Name, Fields: string; Options: TIndexOptions; const DescFields: string); -begin - raise EBold.CreateFmt('MethodNotImplemented', [ClassName, 'AddIndex']); // do not localize +var + SortOption: TFDSortOptions; +begin +// ixPrimary, ixUnique, ixDescending, ixCaseInsensitive, ixExpression, ixNonMaintained); +// soNoCase, soNullFirst, soDescNullLast, soDescending, soUnique, soPrimary, soNoSymbols); + SortOption := []; + if ixCaseInsensitive in Options then + Include(SortOption, soNoCase); + if ixUnique in Options then + Include(SortOption, soUnique); + if ixPrimary in Options then + Include(SortOption, soPrimary); + if ixDescending in Options then + Include(SortOption, soDescending); + FDTable.AddIndex(Name, Fields, '', SortOption, DescFields); end; (* function TBoldFireDACTable.GetCommaListOfIndexesForColumn( @@ -748,8 +765,7 @@ function TBoldFireDACTable.GetExists: Boolean; function TBoldFireDACTable.GetIndexDefs: TIndexDefs; begin - raise EBold.CreateFmt('%s MethodNotImplemented %s', [ClassName, 'GetIndexDefs']); // do not localize -// Result := FDTable.IndexFieldNames + Result := FDTable.IndexDefs; end; function TBoldFireDACTable.GetFDTable: TFDTable; @@ -757,12 +773,14 @@ function TBoldFireDACTable.GetFDTable: TFDTable; Result := fFDTable; end; +type TFDTableAccess = class(TFDTable); + function TBoldFireDACTable.ParamByName(const Value: string): IBoldParameter; var lFDParam: TFireDacParam; begin - lFDParam := FDTable.Params.ParamByName(Value); - Result := TBoldFireDACParameter.Create(lFDParam, Self) + lFDParam := TFDTableAccess(FDTable).Params.ParamByName(Value); + Result := TBoldFireDACParameter.Create(lFDParam, Self); end; function TBoldFireDACTable.GetTableName: string; @@ -795,7 +813,7 @@ procedure TBoldFireDACConnection.AllTableNames(Pattern: string; ShowSystemTables if ShowSystemTables then FDConnection.GetTableNames(FDConnection.Params.Database,'','',lTempList, [osMy, osSystem, osOther], [tkTable]) else - FDConnection.GetTableNames(FDConnection.Params.Database,'','',lTempList, [osMy, osOther], [tkTable]); + FDConnection.GetTableNames(FDConnection.Params.Database,'','',lTempList, [osMy], [tkTable]); // convert from fully qualified names in format: database.catalogue.table to just table name for i := 0 to lTempList.Count - 1 do @@ -886,12 +904,52 @@ procedure TBoldFireDACConnection.StartTransaction; FDConnection.StartTransaction; end; +function TBoldFireDACConnection.DatabaseExists: boolean; +var + vQuery: IBoldQuery; + vDatabaseName: string; +begin + vDatabaseName := LowerCase(FDConnection.Params.Database); + FDConnection.Params.Database := ''; // need to clear this to connect succesfully + vQuery := GetQuery; + try + vQuery.SQLText := Format(SQLDataBaseConfig.DatabaseExistsTemplate , [vDatabaseName]); + vQuery.Open; + result := vQuery.Fields[0].AsBoolean; + finally + ReleaseQuery(vQuery); + FDConnection.Params.Database := vDatabaseName; + end; +end; + destructor TBoldFireDACConnection.Destroy; begin ReleaseCachedObjects; inherited; end; +procedure TBoldFireDACConnection.DropDatabase; +var + vDatabaseName: string; + vScript: TFDScript; + sl: TStringList; +begin + vDatabaseName := LowerCase(FDConnection.Params.Database); + FDConnection.Params.Database := ''; // need to clear this to connect succesfully + vScript := TFDScript.Create(nil); + sl := TStringList.Create; + try + sl.Text := Format(SQLDataBaseConfig.DropDatabaseTemplate , [vDatabaseName]); + vScript.Connection := FDConnection; + vScript.ExecuteScript(sl); + FDConnection.Close; + finally + FDConnection.Params.Database := vDatabaseName; + vScript.free; + sl.free; + end; +end; + procedure TBoldFireDACConnection.EndExecuteQuery; begin dec(fExecuteQueryCount); @@ -913,21 +971,15 @@ procedure TBoldFireDACConnection.Close; FDConnection.Close; end; -procedure TBoldFireDACConnection.CreateDatabase; +procedure TBoldFireDACConnection.CreateDatabase(DropExisting: boolean = true); var - vQuery: IBoldExecQuery; vDatabaseName: string; vScript: TFDScript; sl: TStringList; -const - cInterbase = 'InterBase'; - cMSSQL = 'SQL Server'; - cDropDatabaseSQL = 'Drop Database %s'; - cGenerateDatabaseSQL = 'Create Database %s'; - cGenerateDatabaseInterbaseSQL = 'Create Database ''%s'' user ''%s'' password ''%s'''; - cGenerateDatabaseSQLServer = 'USE master;' + BOLDCRLF + 'GO' + BOLDCRLF + ' Create Database %s'; begin vDatabaseName := LowerCase(FDConnection.Params.Database); + if DropExisting and DatabaseExists then + DropDatabase; FDConnection.Params.Database := ''; // need to clear this to connect succesfully vScript := TFDScript.Create(nil); sl := TStringList.Create; @@ -970,8 +1022,11 @@ function TBoldFireDACConnection.GetDatabaseError(const E: Exception; cInterBaseProvider = 'InterBase'; cMSSQLDeadLock = 1205; begin + sMsg := E.Message; aErrorType := bdetError; vConnectionString := FDConnection.ConnectionString; + Result := InternalGetDatabaseError(aErrorType, E, vConnectionString, '', '', '', false); + { bUseWindowsAuth := Pos('Authentication=Windows', FDConnection.ConnectString) > 0; if (E is EFDError) then @@ -1071,6 +1126,7 @@ function TBoldFireDACConnection.GetUpdateTransaction: TFDTransaction; procedure TBoldFireDACConnection.Open; begin try + FDConnection.Params.Database := LowerCase(FDConnection.Params.Database); FDConnection.Open; except on E: Exception do begin diff --git a/Source/Persistence/IBX/BoldDatabaseAdapterIB.pas b/Source/Persistence/IBX/BoldDatabaseAdapterIB.pas index fa75748..5a309cf 100644 --- a/Source/Persistence/IBX/BoldDatabaseAdapterIB.pas +++ b/Source/Persistence/IBX/BoldDatabaseAdapterIB.pas @@ -33,7 +33,8 @@ TBoldDatabaseAdapterIB = class(TBoldAbstractDatabaseAdapter) destructor Destroy; override; procedure CreateInterbaseDatabase(PageSize: integer = 4096); procedure EnsureInterbaseDatabase(PageSize: integer = 4096); - procedure CreateDatabase; override; + procedure CreateDatabase(DropExisting: boolean = true); override; + procedure DropDatabase; override; published property DataBase: TIBDataBase read GetDataBase write SetDataBase; {$IFNDEF T2H} @@ -69,6 +70,11 @@ destructor TBoldDatabaseAdapterIB.Destroy; inherited; end; +procedure TBoldDatabaseAdapterIB.DropDatabase; +begin + DatabaseInterface.DropDatabase; +end; + procedure TBoldDatabaseAdapterIB.EnsureInterbaseDatabase( PageSize: integer); begin @@ -79,9 +85,9 @@ procedure TBoldDatabaseAdapterIB.EnsureInterbaseDatabase( CreateInterbaseDatabase(PageSize); end; -procedure TBoldDatabaseAdapterIB.CreateDatabase; +procedure TBoldDatabaseAdapterIB.CreateDatabase(DropExisting: boolean); begin - CreateInterbaseDatabase; + CreateInterbaseDatabase(); end; function TBoldDatabaseAdapterIB.GetDataBase: TIBDataBase; diff --git a/Source/Persistence/IBX/BoldIBInterfaces.pas b/Source/Persistence/IBX/BoldIBInterfaces.pas index 2981000..c3c300d 100644 --- a/Source/Persistence/IBX/BoldIBInterfaces.pas +++ b/Source/Persistence/IBX/BoldIBInterfaces.pas @@ -125,7 +125,7 @@ TBoldIBDataBase = class(TBolddatabaseWrapper, IBoldDataBase) public constructor create(DataBase: TIBDataBase; SQLDataBaseConfig: TBoldSQLDatabaseConfig); destructor destroy; override; - procedure CreateDatabase; + procedure CreateDatabase(DropExisting: boolean = true); override; end; implementation @@ -527,7 +527,7 @@ procedure TBoldIBDataBase.EndExecuteQuery; dec(fExecuteQueryCount); end; -procedure TBoldIBDataBase.CreateDatabase; +procedure TBoldIBDataBase.CreateDatabase(DropExisting: boolean = true); var db: TIBDatabase; username: String; diff --git a/Source/Persistence/UniDAC/BoldDatabaseAdapterUniDAC.pas b/Source/Persistence/UniDAC/BoldDatabaseAdapterUniDAC.pas index 1e03ccf..e250d69 100644 --- a/Source/Persistence/UniDAC/BoldDatabaseAdapterUniDAC.pas +++ b/Source/Persistence/UniDAC/BoldDatabaseAdapterUniDAC.pas @@ -26,7 +26,8 @@ TBoldDatabaseAdapterUniDAC = class(TBoldAbstractDatabaseAdapter) function GetDataBaseInterface: IBoldDatabase; override; public destructor Destroy; override; - procedure CreateDatabase; override; + procedure CreateDatabase; override; + procedure DropDatabase; override; published property Connection: TUniConnection read GetConnection write SetConnection; {$IFNDEF T2H} @@ -52,6 +53,11 @@ destructor TBoldDatabaseAdapterUniDAC.Destroy; inherited; end; +procedure TBoldDatabaseAdapterUniDAC.DropDatabase; +begin + DatabaseInterface.DropDatabase; +end; + procedure TBoldDatabaseAdapterUniDAC.CreateDatabase; begin DatabaseInterface.CreateDatabase; diff --git a/Source/Persistence/UniDAC/BoldUniDACInterfaces.pas b/Source/Persistence/UniDAC/BoldUniDACInterfaces.pas index 53e72c5..45c840c 100644 --- a/Source/Persistence/UniDAC/BoldUniDACInterfaces.pas +++ b/Source/Persistence/UniDAC/BoldUniDACInterfaces.pas @@ -233,6 +233,8 @@ TBoldUniDACConnection = class(TBoldDatabaseWrapper, IBoldDataBase) constructor Create(aUniConnection: TUniConnection; SQLDataBaseConfig: TBoldSQLDatabaseConfig); destructor Destroy; override; procedure CreateDatabase; override; + procedure DropDatabase; override; + function DatabaseExists: boolean; override; function GetDatabaseError(const E: Exception; const sSQL: string = ''): EBoldDatabaseError; property ExecuteQueryCount: integer read fExecuteQueryCount; @@ -862,12 +864,80 @@ procedure TBoldUniDACConnection.StartTransaction; UniConnection.StartTransaction; end; +function TBoldUniDACConnection.DatabaseExists: boolean; +var + vQuery: IBoldQuery; + vDatabaseName: string; +begin + vDatabaseName := LowerCase(UniConnection.Database); + UniConnection.Database := ''; // need to clear this to connect succesfully + vQuery := GetQuery; + try + (vQuery.Implementor as TUniQuery).Connection := UniConnection; + vQuery.SQLText := Format(SQLDataBaseConfig.DatabaseExistsTemplate, [vDatabaseName]); + vQuery.Open; + result := vQuery.Fields[0].AsBoolean; + finally + ReleaseQuery(vQuery); + UniConnection.Database := vDatabaseName; + end; +end; + destructor TBoldUniDACConnection.Destroy; begin ReleaseCachedObjects; inherited; end; +procedure TBoldUniDACConnection.DropDatabase; +var + vQuery: IBoldExecQuery; + vDatabaseName: string; + vUniScript: TUniScript; + vIsInterbase: boolean; + vIsMSSQL: boolean; +const + cInterbase = 'InterBase'; + cMSSQL = 'SQL Server'; + cDropDatabaseSQL = 'Drop Database %s'; + cGenerateDatabaseSQL = 'Create Database %s'; + cGenerateDatabaseInterbaseSQL = 'Create Database ''%s'' user ''%s'' password ''%s'''; + cGenerateDatabaseSQLServer = 'USE master;' + BOLDCRLF + 'GO' + BOLDCRLF + ' Create Database %s'; +begin + vDatabaseName := LowerCase(UniConnection.Database); +// UniConnection.Database := ''; // need to clear this to connect succesfully + vUniScript := TUniScript.Create(nil); + try + vUniScript.Connection := UniConnection; + vIsInterbase := UniConnection.ProviderName = cInterBase; + vIsMSSQL := UniConnection.ProviderName = cMSSQL; + vUniScript.SQL.Text := Format(cDropDatabaseSQL, [vDatabaseName]); + if vIsMSSQL then + UniConnection.Database := 'master'; + try + vUniScript.Execute; + except + // ignore + end; + vUniScript.NoPreconnect := vIsInterbase; + if vIsInterbase then + vUniScript.SQL.Text := Format(cGenerateDatabaseInterbaseSQL, [vDatabaseName, UniConnection.Username, UniConnection.Password]) + else + if vIsMSSQL then + begin + vUniScript.SQL.Text := Format(cGenerateDatabaseSQLServer, [vDatabaseName]); + end + else + vUniScript.SQL.Text := Format(cGenerateDatabaseSQL, [vDatabaseName]); + vUniScript.Execute; + UniConnection.Close; + finally + vUniScript.free; + if vIsMSSQL then + UniConnection.Database := vDatabaseName; + end; +end; + procedure TBoldUniDACConnection.EndExecuteQuery; begin dec(fExecuteQueryCount); @@ -911,7 +981,7 @@ procedure TBoldUniDACConnection.CreateDatabase; vUniScript.Connection := UniConnection; vIsInterbase := UniConnection.ProviderName = cInterBase; vIsMSSQL := UniConnection.ProviderName = cMSSQL; - vUniScript.SQL.Text := Format(cDropDatabaseSQL, [vDatabaseName]); + vUniScript.SQL.Text := Format(SQLDatabaseConfig.DropDatabaseTemplate, [vDatabaseName]); if vIsMSSQL then UniConnection.Database := 'master'; try @@ -919,17 +989,6 @@ procedure TBoldUniDACConnection.CreateDatabase; except // ignore end; - vUniScript.NoPreconnect := vIsInterbase; - if vIsInterbase then - vUniScript.SQL.Text := Format(cGenerateDatabaseInterbaseSQL, [vDatabaseName, UniConnection.Username, UniConnection.Password]) - else - if vIsMSSQL then - begin - vUniScript.SQL.Text := Format(cGenerateDatabaseSQLServer, [vDatabaseName]); - end - else - vUniScript.SQL.Text := Format(cGenerateDatabaseSQL, [vDatabaseName]); - vUniScript.Execute; UniConnection.Close; finally vUniScript.free; From 75e46df3bbcb6b81fa98d0ebebbeec848d489d11 Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Sat, 22 May 2021 16:36:05 +0300 Subject: [PATCH 039/112] New DropDatabase and DatabaseExists templates. Only implemented templates PG and SQLServer, blank for others. --- Source/PMapper/SQL/BoldSQLDatabaseConfig.pas | 30 ++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/Source/PMapper/SQL/BoldSQLDatabaseConfig.pas b/Source/PMapper/SQL/BoldSQLDatabaseConfig.pas index 1bf21e7..b422d3e 100644 --- a/Source/PMapper/SQL/BoldSQLDatabaseConfig.pas +++ b/Source/PMapper/SQL/BoldSQLDatabaseConfig.pas @@ -102,6 +102,8 @@ TBoldSQLDataBaseConfig = class(TPersistent) fSQLforNull: string; fEvolveDropsUnknownIndexes: boolean; fCreateDatabaseTemplate: string; + fDropDatabaseTemplate: string; + fDatabaseExistsTemplate: string; procedure SetIfTemplate(const Value: string); procedure SetColumnExistsTemplate(const Value: string); procedure SetTableExistsTemplate(const Value: string); @@ -173,6 +175,8 @@ TBoldSQLDataBaseConfig = class(TPersistent) procedure SetSQLforNull(const Value: string); procedure SetEvolveDropsUnknownIndexes(const Value: boolean); procedure SetCreateDatabaseTemplate(const Value: string); + procedure SetDropDatabaseTemplate(const Value: string); + procedure SetDatabaseExistsTemplate(const Value: string); protected procedure DefineProperties(Filer: TFiler); override; public @@ -230,6 +234,8 @@ TBoldSQLDataBaseConfig = class(TPersistent) property SingleIndexOrderedLinks: boolean read fSingleIndexOrderedLinks write SetSingleIndexOrderedLinks default false; property IgnoreMissingObjects: boolean read fIgnoreMissingObjects write SetIgnoreMissingObjects default false; property CreateDatabaseTemplate: string read fCreateDatabaseTemplate write SetCreateDatabaseTemplate; + property DropDatabaseTemplate: string read fDropDatabaseTemplate write SetDropDatabaseTemplate; + property DatabaseExistsTemplate: string read fDatabaseExistsTemplate write SetDatabaseExistsTemplate; property DropColumnTemplate: string read fDropColumnTemplate write SetDropColumnTemplate; property DropTableTemplate: string read fDropTableTemplate write SetDropTableTemplate; property IndexInfoTemplate: string read fIndexInfoTemplate write SetIndexInfoTemplate; @@ -338,6 +344,8 @@ procedure TBoldSQLDataBaseConfig.AssignConfig(Source: TBoldSQLDataBaseConfig); fDbGenerationMode := Source.DBGenerationMode; fDefaultStringLength := Source.DefaultStringLength; fCreateDatabaseTemplate := Source.CreateDatabaseTemplate; + fDropDatabaseTemplate := Source.DropDatabaseTemplate; + fDatabaseExistsTemplate := Source.DatabaseExistsTemplate; fDropColumnTemplate := Source.DropColumnTemplate; fDropTableTemplate := Source.DropTableTemplate; fDropIndexTemplate := Source.DropIndexTemplate; @@ -566,6 +574,15 @@ procedure TBoldSQLDataBaseConfig.SetDropColumnTemplate(const Value: string); end; end; +procedure TBoldSQLDataBaseConfig.SetDropDatabaseTemplate(const Value: string); +begin + if fDropDatabaseTemplate <> Value then + begin + fDropDatabaseTemplate := Value; + Change; + end; +end; + procedure TBoldSQLDataBaseConfig.SetDropIndexTemplate(const Value: string); begin if fDropIndexTemplate <> Value then @@ -744,6 +761,8 @@ procedure TBoldSQLDataBaseConfig.SetInitialValues; fAllowMetadataChangesInTransaction := true; fDBGenerationMode := dbgQuery; fCreateDatabaseTemplate := 'CREATE DATABASE %s'; + fDropDatabaseTemplate := 'DROP DATABASE %s'; + fDatabaseExistsTemplate := ''; fDropColumnTemplate := 'ALTER TABLE DROP '; fDropTableTemplate := 'DROP TABLE '; fDropIndexTemplate := 'DROP INDEX '; @@ -871,6 +890,7 @@ procedure TBoldSQLDataBaseConfig.InitializeDbEngineSettings(Engine: TBoldDatabas fMaxIndexNameLength := 63; fMaxDbIdentifierLength := 63; fMultiRowInsertLimit := 1000; + fDatabaseExistsTemplate := 'select exists(SELECT datname FROM pg_catalog.pg_database WHERE lower(datname) = lower(''%s''));'; // IndexInfoTemplate := 'select indexname from pg_indexes where tablename = '''''; // this is not complete IndexName, IsPrimary, IsUnique, ColumnName fReservedWords.Text := 'ALL, ANALYSE, AND, ANY, ARRAY, AS, ASC, ASYMMETRIC, AUTHORIZATION,'#10 + // do not localize 'BETWEEN, BINARY, BOOLEAN, BOTH, CASE, CAST, CHAR, CHARACTER, CHECK,'#10 + // do not localize @@ -907,6 +927,7 @@ procedure TBoldSQLDataBaseConfig.InitializeDbEngineSettings(Engine: TBoldDatabas fColumnTypeForDate := 'DATETIME'; // do not localize fColumnTypeForTime := 'DATETIME'; // do not localize fColumnTypeForDateTime := 'DATETIME'; // do not localize + fDatabaseExistsTemplate := 'IF EXISTS (SELECT name FROM master.sys.databases WHERE name = N''%s'')'; fColumnTypeForFloat := 'DECIMAL (28,10)'; // do not localize fColumnTypeForCurrency := 'DECIMAL (28,10)'; // do not localize fColumnTypeForText := 'VARCHAR(MAX)'; // do not localize @@ -1389,6 +1410,15 @@ procedure TBoldSQLDataBaseConfig.SetDatabaseCaseSensitiveTemplate(const Value: end; end; +procedure TBoldSQLDataBaseConfig.SetDatabaseExistsTemplate(const Value: string); +begin + if fDatabaseExistsTemplate <> Value then + begin + fDatabaseExistsTemplate := Value; + Change; + end; +end; + procedure TBoldSQLDataBaseConfig.SetFieldTypeForBlob(const Value: TFieldType); begin if fFieldTypeForBlob <> Value then From 246263cd048181f38d15d74fbdf631abb1c7ed59 Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Sat, 22 May 2021 16:43:23 +0300 Subject: [PATCH 040/112] CanEvaluateInPS can now also work without active system. Failure reason now created to show what failed. --- .../PMapper/Default/BoldPMappersDefault.pas | 35 ++++++++++++------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/Source/PMapper/Default/BoldPMappersDefault.pas b/Source/PMapper/Default/BoldPMappersDefault.pas index a406401..2ba58c5 100644 --- a/Source/PMapper/Default/BoldPMappersDefault.pas +++ b/Source/PMapper/Default/BoldPMappersDefault.pas @@ -152,7 +152,7 @@ TBoldObjectDefaultMapper = class(TBoldObjectSQLMapper) procedure MakeIDsExactUsingTable(ObjectIDList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList; Table: TBoldSQLTableDescription; EnsureAll: Boolean; HandleNonExisting: Boolean); function InternalIdListSegmentToWhereFragment(IdList: TBoldObjectIdList; Start, Stop: Integer; AllowParms: Boolean; const Parameterized: IBoldParameterized): String; procedure InternalMakeIDsExact(ObjectIDList: TBoldObjectIdList; TranslationList: TBoldIdTranslationList; EnsureAll: Boolean; HandleNonExisting: Boolean); - procedure FetchRawSqlCondition(ObjectIDList: TBoldObjectIdList; const ValueSpace: IBoldValueSpace; RawCondition: TBoldRawSqlCondition; FetchMode: Integer; TranslationList: TBoldIdTranslationList); + procedure FetchRawSqlCondition(ObjectIDList: TBoldObjectIdList; const ValueSpace: IBoldValueSpace; RawCondition: TBoldRawSqlCondition; FetchMode: Integer; TranslationList: TBoldIdTranslationList); protected procedure JoinSQLTableByKey(SQL: TStringList; MainTable, JoinTable: TBoldSQLTableDescription); override; procedure SQLForID(Table: TBoldSQLTableDescription; SQL: TStrings; UseAlias: Boolean); override; @@ -457,20 +457,25 @@ function TBoldSystemDefaultMapper.CanEvaluateInPS(sOCL: string; // On empty OCL a PS evaluation is unnecessary (objects are loaded already). // System parameter must be type of TBoldSystem (see TBoldPersistenceController). // Also OCL evaluator must be type of TBoldOCL, otherwise validation is not possible. - if (sOCL = '') or not ((aSystem is TBoldSystem) and - (TBoldSystem(aSystem).Evaluator is TBoldOCL)) then + if (sOCL = '') {or not ((aSystem is TBoldSystem) and + (TBoldSystem(aSystem).Evaluator is TBoldOCL))} then begin Exit; end; // Validation does not work with collection as context, though evaluation // would be possible. Therefore always use ListElementTypeInfo. + aBoldSystem := TBoldSystem(aSystem); + if Assigned(aBoldSystem) then + aBoldOCL := TBoldOcl(aBoldSystem.Evaluator) + else + if Assigned(aContext) then + aBoldOCL := TBoldOcl(aContext.Evaluator) + else + raise Exception.Create('No system nor context provided.'); if Assigned(aContext) and (aContext is TBoldListTypeInfo) then begin aContext := TBoldListTypeInfo(aContext).ListElementTypeInfo; end; - - aBoldSystem := TBoldSystem(aSystem); - aBoldOCL := TBoldOcl(aBoldSystem.Evaluator); aVariableIDLists := TBoldObjectArray.Create(0, [bcoDataOwner]); Result := True; try @@ -478,7 +483,7 @@ function TBoldSystemDefaultMapper.CanEvaluateInPS(sOCL: string; aEnv := TBoldOclEnvironment.Create(aBoldOCL.GlobalEnv); // OCL semantic check aResultEntry := aBoldOCL.SemanticCheck(sOCL, aContext, aVariableList, true, aEnv); - aOLWNodeMaker := TBoldOLWNodeMaker.Create(aResultEntry.Ocl, aBoldSystem.BoldSystemTypeInfo, aBoldSystem, aEnv); + aOLWNodeMaker := TBoldOLWNodeMaker.Create(aResultEntry.Ocl, aContext.SystemTypeInfo as TBoldSystemTypeInfo, aBoldSystem, aEnv); aResultEntry.Ocl.AcceptVisitor(aOLWNodeMaker); // Can OCL be evaluated in PS in general? if not aOLWNodeMaker.Failed then begin @@ -517,10 +522,15 @@ function TBoldSystemDefaultMapper.CanEvaluateInPS(sOCL: string; aSQLNodeMaker.RootNode.AcceptVisitor(aSQlGenerator); end else begin Result := False; + SetBoldLastFailureReason(TBoldFailureReason.CreateFmt('%s at position: %d', [aOLWNodeMaker.FailureReason, aOLWNodeMaker.FailurePosition], nil)); end; except + on E:Exception do + begin + SetBoldLastFailureReason(TBoldFailureReason.Create(E.Message, nil)); Result := False; end; + end; finally if Assigned(aResultEntry) then begin if aResultEntry.OwnedByDictionary then begin @@ -1478,7 +1488,7 @@ procedure TBoldObjectDefaultMapper.PMTemporalUpdate(ObjectIdList: TBoldObjectIdL SystemPersistenceMapper.ReleaseQuery(OldDataQuery); SQL.Free; end; -end; +end; procedure TBoldObjectDefaultMapper.PMUpdate(ObjectIDList: TBoldObjectIdList; const ValueSpace: IBoldValueSpace; const Old_Values: IBoldValueSpace; TranslationList: TBoldIdTranslationList); var @@ -1569,7 +1579,7 @@ procedure TBoldObjectDefaultMapper.PMUpdate(ObjectIDList: TBoldObjectIdList; con aQuery.SQLStrings.EndUpdate; SystemPersistenceMapper.ReleaseExecQuery(aQuery); end; - + for A := 0 to MemberPersistenceMappers.Count - 1 do begin with MemberPersistenceMappers[A] do @@ -2466,7 +2476,7 @@ function TBoldObjectDefaultMapper.InternalIdListSegmentToWhereFragment( if UseParams then begin result := ':ID'+IntToStr(ParamIndex); - Assert(IdList[IdIndex] is TBoldDefaultId, IdList[IdIndex].ClassName); + Assert(IdList[IdIndex] is TBoldDefaultId, IdList[IdIndex].ClassName); Parameterized.CreateParam(ftInteger, 'ID'+IntToStr(ParamIndex)).AsInteger := (IdList[IdIndex] as TBoldDefaultId).AsInteger; end else @@ -2894,7 +2904,7 @@ procedure TBoldSystemDefaultMapper.PMTranslateToGlobalIds( aQuery.Open; - TranslationList.Capacity := TranslationList.Count + aQuery.RecordCount; + TranslationList.Capacity := TranslationList.Count + aQuery.RecordCount; while not aQuery.EOF do begin anObjectId := NewIdFromQuery(aQuery, NO_CLASS, 1, 0, BOLDMAXTIMESTAMP); @@ -3218,7 +3228,7 @@ procedure TBoldSystemDefaultMapper.PMFetchClassWithCondition( aCPCond: TBoldChangePointCondition; GlobalNameSpace: TBoldSqlNameSpace; aVariableIDLists: TBoldObjectArray; - vBoldParameterized: IBoldParameterized; + vBoldParameterized: IBoldParameterized; procedure FixQueriesForEnv(VarBinding: TBoldSQLVariableBinding; Context: TBoldObjectIdList; NameSpace: TBoldSqlNameSpace); var @@ -4238,4 +4248,3 @@ finalization BoldObjectPersistenceMappers.RemoveDescriptorByName(DEFAULTNAME); end. - From f27798fa37c52f09265205cc3c861390f8958324 Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Sat, 22 May 2021 16:44:01 +0300 Subject: [PATCH 041/112] Log using AsISODateTimeMS --- Source/PMapper/Core/BoldPMappers.pas | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Source/PMapper/Core/BoldPMappers.pas b/Source/PMapper/Core/BoldPMappers.pas index 8f3cef1..bc6cd3c 100644 --- a/Source/PMapper/Core/BoldPMappers.pas +++ b/Source/PMapper/Core/BoldPMappers.pas @@ -308,18 +308,19 @@ implementation BoldPMConsts, BoldGuard, BoldDefaultStreamNames, - BoldPMapperLists; + BoldPMapperLists, + BoldIsoDateTime; procedure BoldPMLog(const s: string); begin if assigned(BoldPMLogHandler) then - BoldPMLogHandler.Log(formatDateTime('c: ', now)+trim(s)); + BoldPMLogHandler.Log(AsISODateTimeMS(now)+':'+trim(s)); end; procedure BoldPMLogFmt(const s: string; const Args: array of const); begin if assigned(BoldPMLogHandler) then - BoldPMLogHandler.LogFmt(formatDateTime('c: ', now) +trim(s), Args); + BoldPMLogHandler.LogFmt(AsISODateTimeMS(now)+':'+trim(s), Args); end; { TBoldObjectPersistenceMapperList } From c41763e1f4c2ebc6a43090418557e9ee4fca4258 Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Sat, 22 May 2021 16:48:44 +0300 Subject: [PATCH 042/112] Log using AsISODateTimeMS --- Source/Common/Logging/BoldLogHandlerForm.pas | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/Common/Logging/BoldLogHandlerForm.pas b/Source/Common/Logging/BoldLogHandlerForm.pas index 927a29c..73f5ba1 100644 --- a/Source/Common/Logging/BoldLogHandlerForm.pas +++ b/Source/Common/Logging/BoldLogHandlerForm.pas @@ -47,7 +47,7 @@ implementation uses SysUtils, BoldUtils, - BoldRev; + BoldIsoDateTime; var LogHandlerForm: TBoldLogHandlerReceiver; @@ -67,7 +67,7 @@ destructor TBoldLogHandlerReceiver.destroy; procedure TBoldLogHandlerReceiver.EndLog; begin - Log(format('%s: Done %s', [formatDateTime('c', now), fSessionName])); + Log(format('%s: Done %s', [AsIsoDateTimeMs(now), fSessionName])); Hideprogressbar; end; @@ -125,7 +125,7 @@ procedure TBoldLogHandlerReceiver.StartLog(const SessionName: String); begin LogForm.Caption := 'Logging Activity: ' + SessionName; fSessionName := SessionName; - Log(format('%s: Starting %s', [formatDateTime('c', now), SessionName])); + Log(format('%s: Starting %s', [AsIsoDateTimeMs(now), SessionName])); end; procedure TBoldLogHandlerReceiver.ProcessInterruption; From 196530dee02dc09251af72415ba8ad049225f2fa Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Sat, 22 May 2021 16:50:14 +0300 Subject: [PATCH 043/112] Removed BoldGettingStartedExpert --- Bold.dpk | 2 -- Source/Common/Core/BoldCommonConst.pas | 4 ---- 2 files changed, 6 deletions(-) diff --git a/Bold.dpk b/Bold.dpk index e8dc73b..957a5dd 100644 --- a/Bold.dpk +++ b/Bold.dpk @@ -126,8 +126,6 @@ contains BoldDefsDT in 'Source\Common\IDE\BoldDefsDT.pas', BoldExpert in 'Source\Common\IDE\BoldExpert.pas', BoldExpertMenus in 'Source\Common\IDE\BoldExpertMenus.pas', - BoldGettingStartedExpert in 'Source\Common\IDE\BoldGettingStartedExpert.pas', - BoldGettingStartedForm in 'Source\Common\IDE\BoldGettingStartedForm.pas', BoldIDEConsts in 'Source\Common\IDE\BoldIDEConsts.pas', BoldIDEMenus in 'Source\Common\IDE\BoldIDEMenus.pas', BoldIDESupport in 'Source\Common\IDE\BoldIDESupport.pas', diff --git a/Source/Common/Core/BoldCommonConst.pas b/Source/Common/Core/BoldCommonConst.pas index e90c7ae..67976d4 100644 --- a/Source/Common/Core/BoldCommonConst.pas +++ b/Source/Common/Core/BoldCommonConst.pas @@ -94,10 +94,6 @@ interface sNotRunningInIDE = '%s: Not running in IDE'; sUnknownDisplayMode = '%s.ApplicationEventsOnIdle: Unknown displaymode'; -//BoldGettingStartedExpert - sGettingStarted = 'Getting Started'; - sCouldNotFindGettingStarted = 'Could not find Bold for Delphi''s GettingStarted document: %s'; - //BoldIDEMenus sCompanyHomePage = '&BoldSoft Home Page'; sProductHomePage = 'Bold for &Delphi Home Page'; From 629e96f7ffe43c653a2a42bd445464518deb1cc8 Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Sat, 22 May 2021 16:52:23 +0300 Subject: [PATCH 044/112] Now Requires FireDACPgDriver Postgres becomes default for demos. Added BoldFormSaverActions. --- BoldDesignPackage.dpk | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/BoldDesignPackage.dpk b/BoldDesignPackage.dpk index 9b43a8f..82b859d 100644 --- a/BoldDesignPackage.dpk +++ b/BoldDesignPackage.dpk @@ -37,6 +37,7 @@ requires FireDac, FireDACCommonDriver, FireDACCommon, + FireDACPgDriver, IndySystem, IndyCore; @@ -88,6 +89,7 @@ contains BoldFireDACInterfaces in 'Source\Persistence\FireDAC\BoldFireDACInterfaces.pas', BoldFireDACConsts in 'Source\Persistence\FireDAC\BoldFireDACConsts.pas', BoldConstraintValidator in 'Source\Samples\ConstraintValidator\BoldConstraintValidator.pas', - BoldConstraintValidatorReg in 'Source\Samples\ConstraintValidator\BoldConstraintValidatorReg.pas'; + BoldConstraintValidatorReg in 'Source\Samples\ConstraintValidator\BoldConstraintValidatorReg.pas', + BoldFormSaverActions in 'Source\Samples\FormSaver\BoldFormSaverActions.pas'; end. From c3e45821932d82e67ccf4a3c18fe0232e2b53c04 Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Sat, 22 May 2021 16:53:07 +0300 Subject: [PATCH 045/112] New BoldFormSaverActions implement Ok/Apply/Cancel --- .../FormSaver/BoldFormSaverActions.pas | 169 ++++++++++++++++++ 1 file changed, 169 insertions(+) create mode 100644 Source/Samples/FormSaver/BoldFormSaverActions.pas diff --git a/Source/Samples/FormSaver/BoldFormSaverActions.pas b/Source/Samples/FormSaver/BoldFormSaverActions.pas new file mode 100644 index 0000000..a3f94f8 --- /dev/null +++ b/Source/Samples/FormSaver/BoldFormSaverActions.pas @@ -0,0 +1,169 @@ + +{ Global compiler directives } +{$include bold.inc} +unit BoldFormSaverActions; + +interface + +uses + classes, + BoldFormSaver, + BoldHandleAction; + +type + TBoldFormSaverAction = class; + TBoldFormSaverApplyAction = class; + TBoldFormSaverCancelAction = class; + TBoldFormSaverOkAction = class; + + TBoldFormSaverAction = class(TBoldHandleAction) + private + function GetBoldFormSaver: TBoldFormSaver; + protected + procedure SetBoldFormSaver(const Value: TBoldFormSaver); virtual; + procedure CheckAllowEnable(var EnableAction: boolean); override; + public + constructor Create(AOwner: TComponent); override; + published + property BoldFormSaver: TBoldFormSaver read GetBoldFormSaver write SetBoldFormSaver; + end; + + TBoldFormSaverApplyAction = class(TBoldFormSaverAction) + protected + procedure CheckAllowEnable(var EnableAction: boolean); override; + public + constructor Create(AOwner: TComponent); override; + procedure ExecuteTarget(Target: TObject); override; + end; + + TBoldFormSaverCancelAction = class(TBoldFormSaverAction) + protected + procedure CheckAllowEnable(var EnableAction: boolean); override; + public + constructor Create(AOwner: TComponent); override; + procedure ExecuteTarget(Target: TObject); override; + end; + + TBoldFormSaverOkAction = class(TBoldFormSaverAction) + protected + procedure CheckAllowEnable(var EnableAction: boolean); override; + public + constructor Create(AOwner: TComponent); override; + procedure ExecuteTarget(Target: TObject); override; + end; + +implementation + +uses + BoldSystem, + ActnList, + SysUtils, + Menus; // for TextToShortCut + +{ TBoldFormSaverAction } + +procedure TBoldFormSaverAction.CheckAllowEnable(var EnableAction: boolean); +begin + inherited; + if EnableAction then + EnableAction := Assigned(BoldFormSaver); +end; + +constructor TBoldFormSaverAction.Create(AOwner: TComponent); +begin + inherited; + Caption := 'FormSaver'; + ShortCut := TextToShortCut('Ctrl+Z'); +end; + +function TBoldFormSaverAction.GetBoldFormSaver: TBoldFormSaver; +begin + result := BoldElementHandle as TBoldFormSaver; +end; + +procedure TBoldFormSaverAction.SetBoldFormSaver(const Value: TBoldFormSaver); +begin + BoldElementHandle := Value; +end; + +{ TBoldFormSaverApplyAction } + +procedure TBoldFormSaverApplyAction.CheckAllowEnable(var EnableAction: boolean); +begin + inherited; + if EnableAction then + begin + if BoldFormSaver.DirtyObjects.Empty then + Caption := '&Close' + else + Caption := '&Apply' + end; +end; + +constructor TBoldFormSaverApplyAction.Create(AOwner: TComponent); +begin + inherited; + Caption := '&Apply'; +end; + +procedure TBoldFormSaverApplyAction.ExecuteTarget(Target: TObject); +begin + inherited; + BoldFormSaver.Apply; +end; + +{ TBoldFormSaverCancelAction } + +procedure TBoldFormSaverCancelAction.CheckAllowEnable( + var EnableAction: boolean); +begin + inherited; + if EnableAction then + begin + if BoldFormSaver.DirtyObjects.Empty then + Caption := '&Close' + else + Caption := '&Cancel' + end; +end; + +constructor TBoldFormSaverCancelAction.Create(AOwner: TComponent); +begin + inherited; + Caption := '&Cancel'; + ShortCut := TextToShortCut('Escape'); +end; + +procedure TBoldFormSaverCancelAction.ExecuteTarget(Target: TObject); +begin + inherited; + BoldFormSaver.Cancel; +end; + +{ TBoldFormSaverOkAction } + +procedure TBoldFormSaverOkAction.CheckAllowEnable(var EnableAction: boolean); +begin + inherited; + if EnableAction then + begin + if BoldFormSaver.DirtyObjects.Empty then + Caption := '&Close' + else + Caption := '&OK' + end; +end; + +constructor TBoldFormSaverOkAction.Create(AOwner: TComponent); +begin + inherited; + Caption := '&Ok'; +end; + +procedure TBoldFormSaverOkAction.ExecuteTarget(Target: TObject); +begin + inherited; + BoldFormSaver.OK; +end; + +end. From b6a3c13ede94ffc1a7a908a49965650824bf2edf Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Sat, 22 May 2021 16:55:25 +0300 Subject: [PATCH 046/112] Register BoldFormSaverActions. FormSaver now works with LightMemberDeriver, removed conditional. --- Source/Samples/IDE/BoldSamplesReg.pas | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/Source/Samples/IDE/BoldSamplesReg.pas b/Source/Samples/IDE/BoldSamplesReg.pas index c0c29be..3593c87 100644 --- a/Source/Samples/IDE/BoldSamplesReg.pas +++ b/Source/Samples/IDE/BoldSamplesReg.pas @@ -19,16 +19,15 @@ implementation {$IFDEF BOLD_DELPHI16_OR_LATER} Actions, {$ENDIF} -{$IFNDEF LightMemberDeriver} BoldFormSaver, -{$ENDIF} BoldGuard, BoldPropertyEditors, BoldNewObjectInterceptor, BoldIDEConsts, BoldEditOCLAction, BoldEditOCLActionPropEditor, - BoldDebugActions; + BoldDebugActions, + BoldFormSaverActions; type TTextFileProperty = class(TBoldFileNameProperty) @@ -41,10 +40,8 @@ procedure RegisterComponentsOnPalette; begin RegisterComponents(BOLDPAGENAME_MISC, [ - TBoldNewObjectInterceptor -{$IFNDEF LightMemberDeriver} - ,TBoldFormSaver -{$ENDIF} + TBoldNewObjectInterceptor, + TBoldFormSaver ]); end; @@ -57,7 +54,11 @@ procedure RegisterBoldActions; TBoldLogOCLAction, TBoldLogSQLAction, TBoldLogPMAction, - TBoldLogFormAction + TBoldLogOSSAction, + TBoldLogFormAction, + TBoldFormSaverApplyAction, + TBoldFormSaverCancelAction, + TBoldFormSaverOkAction ], nil); end; From bdd98bd0e9f06ce159cac1f62b9725ea676b766f Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Sat, 22 May 2021 16:55:53 +0300 Subject: [PATCH 047/112] New TBoldLogOSSAction, not implemented yet --- Source/Samples/Actions/BoldDebugActions.pas | 33 ++++++++++++++++++--- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/Source/Samples/Actions/BoldDebugActions.pas b/Source/Samples/Actions/BoldDebugActions.pas index 4df6dfb..3d8256d 100644 --- a/Source/Samples/Actions/BoldDebugActions.pas +++ b/Source/Samples/Actions/BoldDebugActions.pas @@ -75,9 +75,15 @@ TBoldLogPMAction = class(TBoldLogAction) procedure SetLogHandler(Value: TBoldLogHandler); override; end; - { TBoldLogFormAction } - + { TBoldLogOSSAction } + TBoldLogOSSAction = class(TBoldLogAction) + protected + function GetLogHandler: TBoldLogHandler; override; + function GetLogType: string; override; + procedure SetLogHandler(Value: TBoldLogHandler); override; + end; + { TBoldLogFormAction } TBoldLogFormAction = class(TAction) private fShowing: boolean; @@ -91,10 +97,11 @@ implementation uses SysUtils, + Menus, // for TextToShortCut BoldOCL, BoldDBInterfaces, BoldPMappers, - BoldRev; + BoldObjectSpaceExternalEvents; { TBoldSystemDebuggerAction } @@ -108,6 +115,7 @@ constructor TBoldSystemDebuggerAction.Create(AOwner: TComponent); begin inherited; Caption := 'System debugger'; + ShortCut := TextToShortCut('Ctrl+Shift+D'); end; procedure TBoldSystemDebuggerAction.ExecuteTarget(Target: TObject); @@ -239,7 +247,7 @@ procedure TBoldLogPMAction.SetLogHandler(Value: TBoldLogHandler); constructor TBoldLogFormAction.Create(AOwner: TComponent); begin inherited; - Caption := 'Toggle log'; + Caption := 'Log view'; end; procedure TBoldLogFormAction.ExecuteTarget(Target: TObject); @@ -257,6 +265,23 @@ function TBoldLogFormAction.HandlesTarget(Target: TObject): Boolean; Result := True; end; +{ TBoldLogOSSAction } + +function TBoldLogOSSAction.GetLogHandler: TBoldLogHandler; +begin + result := BoldOSSLogHandler; +end; + +function TBoldLogOSSAction.GetLogType: string; +begin + Result := 'OSS traffic'; +end; + +procedure TBoldLogOSSAction.SetLogHandler(Value: TBoldLogHandler); +begin + BoldOSSLogHandler := Value; +end; + initialization end. From 60ef9a5ab8f24f76d176d1b1d57f9df24c2c1577 Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Sat, 22 May 2021 16:56:47 +0300 Subject: [PATCH 048/112] SystemHandle now has Discard --- Source/Handles/Core/BoldSystemHandle.pas | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Source/Handles/Core/BoldSystemHandle.pas b/Source/Handles/Core/BoldSystemHandle.pas index 9f37c8e..e58db5c 100644 --- a/Source/Handles/Core/BoldSystemHandle.pas +++ b/Source/Handles/Core/BoldSystemHandle.pas @@ -57,6 +57,7 @@ TBoldSystemHandle = class(TBoldAbstractSystemHandle) procedure UpdateDatabase; procedure InstallOclDefinitionLookUp(const Value: TBoldLookUpOclDefinition); function RefersToComponent(Component: TBoldSubscribableComponent): Boolean; override; + procedure Discard; property Persistent: Boolean read GetPersistent; property RegionFactory: TBoldRegionFactory read fRegionFactory; property PersistenceHandleDB: TBoldAbstractPersistenceHandleDB read GetPersistenceHandleDB; @@ -98,6 +99,12 @@ destructor TBoldSystemHandle.Destroy; inherited Destroy; end; +procedure TBoldSystemHandle.Discard; +begin + if Assigned(System) then + System.Discard; +end; + procedure TBoldSystemHandle.Loaded; begin inherited Loaded; From 7ae8625d79f4c396bbb0ee517ff6f64008f42cec Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Sat, 22 May 2021 16:57:05 +0300 Subject: [PATCH 049/112] Register TBoldDiscardChangesAction --- Source/Handles/IDE/BoldHandleReg.pas | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/Handles/IDE/BoldHandleReg.pas b/Source/Handles/IDE/BoldHandleReg.pas index 1d3b832..5f4c607 100644 --- a/Source/Handles/IDE/BoldHandleReg.pas +++ b/Source/Handles/IDE/BoldHandleReg.pas @@ -56,6 +56,7 @@ procedure RegisterActionsInDelphi; RegisterActions(BOLDACTIONGROUPNAME, [ TBoldUpdateDBAction, + TBoldDiscardChangesAction, TBoldActivateSystemAction, TBoldFailureDetectionAction, TBoldCreateDatabaseAction, From fd576ccfd6900ac916500456090d2de35a258608 Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Sat, 22 May 2021 16:57:42 +0300 Subject: [PATCH 050/112] Fix - check if BoldList is assigned --- Source/Handles/Core/BoldAbstractListHandle.pas | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Handles/Core/BoldAbstractListHandle.pas b/Source/Handles/Core/BoldAbstractListHandle.pas index 97b535c..82d7971 100644 --- a/Source/Handles/Core/BoldAbstractListHandle.pas +++ b/Source/Handles/Core/BoldAbstractListHandle.pas @@ -152,7 +152,7 @@ function TBoldAbstractListHandle.GetListElementType: TBoldElementTypeInfo; BoldList: TBoldList; begin BoldList := List; - if Assigned(BoldList) then + if Assigned(BoldList) and Assigned(BoldList.BoldType) then Result := TBoldListTypeInfo(BoldList.BoldType).ListElementTypeInfo else Result := StaticBoldType; From f1b0db5799c3a4fd3b19378c32bb032a98e63733 Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Sat, 22 May 2021 17:00:23 +0300 Subject: [PATCH 051/112] Using JSON for OSS messages. Renamed TOSSMessage to TBoldOssMessage. --- .../BoldExternalObjectSpaceEventHandler.pas | 4 +- .../BORepresentation/BoldOSSMessage.pas | 95 ++++++++++--------- 2 files changed, 52 insertions(+), 47 deletions(-) diff --git a/Source/ObjectSpace/BORepresentation/BoldExternalObjectSpaceEventHandler.pas b/Source/ObjectSpace/BORepresentation/BoldExternalObjectSpaceEventHandler.pas index e26f855..26f90da 100644 --- a/Source/ObjectSpace/BORepresentation/BoldExternalObjectSpaceEventHandler.pas +++ b/Source/ObjectSpace/BORepresentation/BoldExternalObjectSpaceEventHandler.pas @@ -71,7 +71,7 @@ TBoldExternalObjectSpaceEventHandler = class(TBoldStringDequeuer) protected procedure HandleMessage(const aMsg: String); override; {$IFDEF UseBoldOSSMessage} - procedure HandleObjectMessage(const AOSSMessage: TOSSMessage); + procedure HandleObjectMessage(const AOSSMessage: TBoldOssMessage); {$ENDIF} procedure ClassChanged(const ClassName: String); virtual; procedure MemberChanged(const ClassName, MemberName: String; ObjectID: TBoldDefaultID); virtual; @@ -230,7 +230,7 @@ procedure TBoldExternalObjectSpaceEventHandler.HandleMessage(const aMsg: String) {$IFDEF UseBoldOSSMessage} procedure TBoldExternalObjectSpaceEventHandler.HandleObjectMessage( - const AOSSMessage: TOSSMessage); + const AOSSMessage: TBoldOssMessage); var vEvents: TStringList; vEvent: string; diff --git a/Source/ObjectSpace/BORepresentation/BoldOSSMessage.pas b/Source/ObjectSpace/BORepresentation/BoldOSSMessage.pas index 9a54df7..c61b044 100644 --- a/Source/ObjectSpace/BORepresentation/BoldOSSMessage.pas +++ b/Source/ObjectSpace/BORepresentation/BoldOSSMessage.pas @@ -1,10 +1,12 @@ + +{ Global compiler directives } +{$include bold.inc} unit BoldOSSMessage; interface uses Classes; // for TPersistent -// SynCommons; // for TDateTimeMS // BoldDefs; // for TBoldTimeStampType const @@ -14,12 +16,12 @@ interface type TSessionId = Int64; TBoldTimeStampType = integer; // copy from BoldDefs - TOSSMessageType = (mtSync, mtFail); + TBoldOSSMessageType = (mtSync, mtFail); TDateTimeMS = TDateTime; - TOSSMessage = class(TInterfacedPersistent) + TBoldOSSMessage = class(TInterfacedPersistent) private - fMessageType: TOSSMessageType; + fMessageType: TBoldOSSMessageType; fEvents: string; fBoldTimeStamp: TBoldTimeStampType; fTimeOfTimeStamp: TDateTimeMS; @@ -34,7 +36,7 @@ TOSSMessage = class(TInterfacedPersistent) public constructor Create; overload; constructor Create( - AMessageType: TOSSMessageType; + AMessageType: TBoldOSSMessageType; AEvents: string; ABoldTimeStamp: TBoldTimeStampType; ATimeOfTimeStamp: TDateTimeMS; @@ -43,10 +45,10 @@ TOSSMessage = class(TInterfacedPersistent) AComputer: string = ''; AApplication: string = ''); overload; destructor Destroy; override; - function Clone: TOSSMessage; + function Clone: TBoldOSSMessage; property AsString: string read GetAsString write SetAsString; published - property MessageType: TOSSMessageType read fMessageType; + property MessageType: TBoldOSSMessageType read fMessageType; property Events: string read fEvents; property BoldTimeStamp: TBoldTimeStampType read fBoldTimeStamp; property TimeOfTimeStamp: TDateTimeMS read fTimeOfTimeStamp; @@ -62,69 +64,71 @@ implementation uses System.SysUtils, BoldIsoDateTime, + System.JSON, + System.JSON.Writers, + System.JSON.Readers, TypInfo; -{ TOSSMessage } +{ TBoldOSSMessage } -constructor TOSSMessage.Create; +constructor TBoldOSSMessage.Create; begin inherited; end; -destructor TOSSMessage.Destroy; +destructor TBoldOSSMessage.Destroy; begin inherited; end; -function TOSSMessage.GetAsString: string; +function TBoldOSSMessage.GetAsString: string; var - sb: TStringBuilder; + JSONObject,t1: TJSONObject; begin - sb := TStringBuilder.Create; + JSONObject := TJSONObject.Create; try - sb.EnsureCapacity(Length(Events)+100); - sb.AppendLine(String((GetEnumName(TypeInfo(TOSSMessageType), Ord(MessageType))))); - sb.AppendLine(IntToStr(BoldTimeStamp)); - sb.AppendLine(AsISODateTimeMS(TimeOfTimeStamp)); - sb.AppendLine(AsISODateTimeMS(ClientSendTime)); - sb.AppendLine(User); - sb.AppendLine(Computer); - sb.AppendLine(Application); - sb.AppendLine(Events); - result := sb.ToString; + JSONObject.AddPair('MessageType', String((GetEnumName(TypeInfo(TBoldOSSMessageType), Ord(MessageType))))); + JSONObject.AddPair('BoldTimeStamp', IntToStr(BoldTimeStamp)); + JSONObject.AddPair('BoldTimeOfTimeStamp', AsISODateTimeMS(TimeOfTimeStamp)); + JSONObject.AddPair('SendTime', AsISODateTimeMS(ClientSendTime)); + JSONObject.AddPair('User', User); + JSONObject.AddPair('Computer', Computer); + JSONObject.AddPair('Application', Application); + JSONObject.AddPair('Events', Events); + result := JSONObject.ToString; finally - sb.free; + JSONObject.free; end; end; -procedure TOSSMessage.SetAsString(const Value: string); +procedure TBoldOSSMessage.SetAsString(const Value: string); var - sl: TStringList; + JSONObject: TJSONObject; + s: string; begin - sl := TStringList.Create; + JSONObject:= TJSONObject.ParseJSONValue(Value) as TJSONObject; try - sl.Text := Value; - Assert(sl.Count = 8, 'Wrong count of lines in OSSMessage:' + IntToStr(sl.count)); - if sl[0] = 'mtSync' then + s := JSONObject.GetValue('MessageType').Value; + if s = 'mtSync' then fMessageType := mtSync else - if sl[0] = 'mtFail' then + if s = 'mtFail' then fMessageType := mtFail else raise Exception.Create('Unknown MessageType'); - fBoldTimeStamp := StrToint(sl[1]); - fTimeOfTimeStamp :=ParseISODateTime(sl[2]); - fClientSendTime := ParseISODateTime(sl[3]); - fUser := sl[4]; - fComputer := sl[5]; - fApplication := sl[6]; - fEvents := sl[7]; + fBoldTimeStamp := StrToInt(JSONObject.GetValue('BoldTimeStamp').Value); + fTimeOfTimeStamp := ParseISODateTime(JSONObject.GetValue('BoldTimeOfTimeStamp').Value); + fClientSendTime := ParseISODateTime(JSONObject.GetValue('SendTime').Value); + fUser := JSONObject.GetValue('User').Value; + fComputer := JSONObject.GetValue('Computer').Value; + fApplication := JSONObject.GetValue('Application').Value; + fEvents := JSONObject.GetValue('Events').Value; finally - sl.Free; + JSONObject.Free; end; end; -constructor TOSSMessage.Create(AMessageType: TOSSMessageType; AEvents: string; +constructor TBoldOSSMessage.Create(AMessageType: TBoldOSSMessageType; AEvents: string; ABoldTimeStamp: TBoldTimeStampType; ATimeOfTimeStamp, AClientSendTime: TDateTimeMS; AUser: string; AComputer: string; AApplication: string); @@ -139,10 +143,10 @@ constructor TOSSMessage.Create(AMessageType: TOSSMessageType; AEvents: string; fApplication := AApplication; end; -procedure TOSSMessage.AssignTo(Dest: TPersistent); +procedure TBoldOSSMessage.AssignTo(Dest: TPersistent); begin - if Dest is TOSSMessage then - with Dest as TOSSMessage do + if Dest is TBoldOSSMessage then + with Dest as TBoldOSSMessage do begin fMessageType := self.fMessageType; fEvents := self.fEvents; @@ -157,10 +161,11 @@ procedure TOSSMessage.AssignTo(Dest: TPersistent); inherited; end; -function TOSSMessage.Clone: TOSSMessage; +function TBoldOSSMessage.Clone: TBoldOSSMessage; begin - result := TOSSMessage.Create; + result := TBoldOSSMessage.Create; self.AssignTo(result); end; end. + From b069356897c7e7ae47d4109d979aa482223d089a Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Sat, 22 May 2021 17:02:10 +0300 Subject: [PATCH 052/112] RegEx delete all %. Check if empty string before evaluating --- .../Ocl/BoldOclSymbolImplementations.pas | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/Source/ObjectSpace/Ocl/BoldOclSymbolImplementations.pas b/Source/ObjectSpace/Ocl/BoldOclSymbolImplementations.pas index db2944d..0fa0bae 100644 --- a/Source/ObjectSpace/Ocl/BoldOclSymbolImplementations.pas +++ b/Source/ObjectSpace/Ocl/BoldOclSymbolImplementations.pas @@ -3044,7 +3044,8 @@ procedure TBOS_AllSubClasses.Evaluate(const Params: TBoldOclSymbolParameters); function EscapeRegEx(const ASource: string): string; begin - result := TPerlRegEx.EscapeRegExChars(ASource); + result := StringReplace(ASource, '%', '', [rfReplaceAll]); + result := TPerlRegEx.EscapeRegExChars(result); end; procedure TBOS_SQLLike.Evaluate(const Params: TBoldOclSymbolParameters); @@ -3053,7 +3054,10 @@ procedure TBOS_SQLLike.Evaluate(const Params: TBoldOclSymbolParameters); begin s := XString(Params.values[1]); s := EscapeRegEx(s); - Help.MakeNewBoolean(Params.Result, TRegEx.IsMatch(XString(Params.values[0]), s)); + if s = '' then + Help.MakeNewBoolean(Params.Result, false) + else + Help.MakeNewBoolean(Params.Result, TRegEx.IsMatch(XString(Params.values[0]), s)); end; procedure TBOS_SQLLikeCaseInSensitive.Evaluate(const Params: TBoldOclSymbolParameters); @@ -3062,7 +3066,10 @@ procedure TBOS_SQLLikeCaseInSensitive.Evaluate(const Params: TBoldOclSymbolParam begin s := XString(Params.values[1]); s := EscapeRegEx(s); - Help.MakeNewBoolean(Params.Result, TRegEx.IsMatch(XString(Params.values[0]), s, [roIgnoreCase])); + if s = '' then + Help.MakeNewBoolean(Params.Result, false) + else + Help.MakeNewBoolean(Params.Result, TRegEx.IsMatch(XString(Params.values[0]), s, [roIgnoreCase])); end; procedure TBOS_RegExpMatch.Evaluate(const Params: TBoldOclSymbolParameters); @@ -3166,7 +3173,10 @@ procedure TBOS_AtTime.Evaluate(const Params: TBoldOclSymbolParameters); NewTime: Integer; begin OldObject := Params.values[0] as TBoldObject; - NewTime := (Params.values[1] as TBAInteger).AsInteger; + if (Params.values[1] as TBAInteger).IsNull then + NewTime := maxInt + else + NewTime := (Params.values[1] as TBAInteger).AsInteger; Params.Result.SetReferenceValue(OldObject.AtTime(NewTime)); end; From e562e05bee01dcc41506b7275fc44f9f21fcd37b Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Sat, 22 May 2021 18:18:05 +0300 Subject: [PATCH 053/112] Added all units to package --- BoldDesignPackage.dpk | 521 +++++++++++++++++++++++++++++++++++--- BoldDesignPackage.dproj | 543 +++++++++++++++++++++++++++++++++++++--- 2 files changed, 990 insertions(+), 74 deletions(-) diff --git a/BoldDesignPackage.dpk b/BoldDesignPackage.dpk index 82b859d..5f12634 100644 --- a/BoldDesignPackage.dpk +++ b/BoldDesignPackage.dpk @@ -26,7 +26,7 @@ package BoldDesignPackage; {$DEFINE DEBUG} {$DEFINE Bold_Delphi} {$ENDIF IMPLICITBUILDING} -{$DESCRIPTION 'Bold 4.0 for Delphi'} +{$DESCRIPTION 'Bold for Delphi Design Package'} {$DESIGNONLY} {$IMPLICITBUILD ON} @@ -42,54 +42,499 @@ requires IndyCore; contains - BoldExternalPersistenceHandlesReg in 'Source\Persistence\ExternalPersistence\BoldExternalPersistenceHandlesReg.pas', + Bold_MSXML_TLB in 'Source\Common\MsXml\Bold_MSXML_TLB.pas', + BoldAbstractComClientPersistenceHandles in 'Source\Persistence\COM\BoldAbstractComClientPersistenceHandles.pas', + BoldAbstractComPersistenceControllerProxy in 'Source\Persistence\COM\BoldAbstractComPersistenceControllerProxy.pas', + BoldAbstractDatabaseAdapter in 'Source\Persistence\DB\BoldAbstractDatabaseAdapter.pas', + BoldAbstractDequeuer in 'Source\Common\Queue\BoldAbstractDequeuer.pas', + BoldAbstractListHandle in 'Source\Handles\Core\BoldAbstractListHandle.pas', + BoldAbstractLockManagerAdminHandle in 'Source\ConcurrencyControl\Common\BoldAbstractLockManagerAdminHandle.pas', + BoldAbstractLockManagerHandle in 'Source\ConcurrencyControl\Common\BoldAbstractLockManagerHandle.pas', + BoldAbstractModel in 'Source\MoldModel\Handles\BoldAbstractModel.pas', + BoldAbstractObjectUpgrader in 'Source\PMapper\Core\BoldAbstractObjectUpgrader.pas', + BoldAbstractObjectUpgraderHandle in 'Source\Persistence\ObjectUpgrading\BoldAbstractObjectUpgraderHandle.pas', + BoldAbstractPersistenceHandleDB in 'Source\Persistence\DB\BoldAbstractPersistenceHandleDB.pas', + BoldAbstractPropagatorHandle in 'Source\Propagator\Common\BoldAbstractPropagatorHandle.pas', + BoldAbstractPropertyEditors in 'Source\Common\IDE\BoldAbstractPropertyEditors.pas', + BoldAbstractSnooper in 'Source\Persistence\Core\BoldAbstractSnooper.pas', BoldAction in 'Source\BoldAwareGUI\Actions\BoldAction.pas', + BoldActionDefs in 'Source\Handles\Actions\BoldActionDefs.pas', + BoldActions in 'Source\Handles\Actions\BoldActions.pas', + BoldAFP in 'Source\BoldAwareGUI\FormGen\BoldAFP.pas', + BoldAFPDefault in 'Source\BoldAwareGUI\FormGen\BoldAFPDefault.pas', + BoldAFPPluggable in 'Source\BoldAwareGUI\FormGen\BoldAFPPluggable.pas', + BoldAFPPluggableReg in 'Source\BoldAwareGUI\FormGen\BoldAFPPluggableReg.pas', + BoldAFPUser in 'Source\BoldAwareGUI\FormGen\BoldAFPUser.pas', + BoldAggeregates in 'Source\Common\Core\BoldAggeregates.pas', + BoldApartmentThread in 'Source\Common\COM\BoldApartmentThread.pas', + BoldAttributes in 'Source\ObjectSpace\BORepresentation\BoldAttributes.pas', + BoldAttributeWizard in 'Source\ObjectSpace\IDE\AttributeWizard\BoldAttributeWizard.pas', + BoldAwareGuiComReg in 'Source\ClientGuiCom\IDE\BoldAwareGuiComReg.pas', BoldAwareGuiReg in 'Source\BoldAwareGUI\IDE\BoldAwareGuiReg.pas', - BoldHandleReg in 'Source\Handles\IDE\BoldHandleReg.pas', - BoldUMLModelEditReg in 'Source\UMLModel\Ide\BoldUMLModelEditReg.pas', - BoldUMLModelLinkSupport in 'Source\UMLModel\ModelLinks\Core\BoldUMLModelLinkSupport.pas', - BoldTypeNameHandleReg in 'Source\MoldModel\IDE\BoldTypeNameHandleReg.pas', - BoldPersistenceHandleDBreg in 'Source\Persistence\DB\BoldPersistenceHandleDBreg.pas', - BoldSamplesReg in 'Source\Samples\IDE\BoldSamplesReg.pas', - BoldUMLRose98Linkreg in 'Source\UMLModel\ModelLinks\Rose98\BoldUMLRose98Linkreg.pas', - BoldHandleComReg in 'Source\ClientHandlesCom\IDE\BoldHandleComReg.pas', - BoldUMXMILinkreg in 'Source\UMLModel\ModelLinks\XMI\BoldUMXMILinkreg.pas', - BoldPersistenceHandleFileReg in 'Source\Persistence\IDE\BoldPersistenceHandleFileReg.pas', - BoldHandlesPropagationReg in 'Source\Persistence\IDE\BoldHandlesPropagationReg.pas', + BoldBase in 'Source\Common\Core\BoldBase.pas', + BoldBase64 in 'Source\Common\Support\BoldBase64.pas', + BoldBatchUpgrader in 'Source\Persistence\ObjectUpgrading\BoldBatchUpgrader.pas', + BoldBld in 'Source\MoldModel\Bld\BoldBld.pas', + BoldCaptionController in 'Source\BoldAwareGUI\BoldControls\BoldCaptionController.pas', + BoldCheckBox in 'Source\BoldAwareGUI\BoldControls\BoldCheckBox.pas', + BoldCheckboxStateControlPack in 'Source\BoldAwareGUI\ControlPacks\BoldCheckboxStateControlPack.pas', + BoldCheckListBox in 'Source\Samples\BoldCheckListBox\BoldCheckListBox.pas', + BoldCheckListBoxReg in 'Source\Samples\BoldCheckListBox\BoldCheckListBoxReg.pas', + BoldClient in 'Source\Common\Connection\BoldClient.pas', + BoldClientHandles in 'Source\Common\ConnectionHandles\BoldClientHandles.pas', + BoldCodePlugins in 'Source\UMLModel\Plugins\BoldCodePlugins.pas', + BoldCollections in 'Source\Common\Support\BoldCollections.pas', + BoldComAdapter in 'Source\Common\COM\BoldComAdapter.pas', + BoldComboBox in 'Source\BoldAwareGUI\BoldControls\BoldComboBox.pas', + BoldComboBoxPropertyEditors in 'Source\BoldAwareGUI\IDE\BoldComboBoxPropertyEditors.pas', + BoldComClient in 'Source\Common\ConnectionCOM\BoldComClient.pas', + BoldComClientElementHandles in 'Source\Handles\COM\BoldComClientElementHandles.pas', + BoldComClientHandles in 'Source\Common\ConnectionHandlesCOM\BoldComClientHandles.pas', + BoldComConnection in 'Source\Common\ConnectionCOM\BoldComConnection.pas', + BoldComConst in 'Source\Common\COM\BoldComConst.pas', + BoldComEditors in 'Source\Common\IDECOM\BoldComEditors.pas', + BoldComElementHandleReg in 'Source\Handles\IDECOM\BoldComElementHandleReg.pas', + BoldComEventQueue in 'Source\Common\COM\BoldComEventQueue.pas', + BoldCommonBitmaps in 'Source\Common\Support\BoldCommonBitmaps.pas', + BoldCommonConst in 'Source\Common\Core\BoldCommonConst.pas', + BoldComObj in 'Source\Common\COM\BoldComObj.pas', + BoldComObjectSpace in 'Source\ObjectSpace\COM\BoldComObjectSpace.pas', + BoldComObjectSpace_TLB in 'Source\ObjectSpace\COM\BoldComObjectSpace_TLB.pas', + BoldComObjectSpaceAdapters in 'Source\ObjectSpace\COM\BoldComObjectSpaceAdapters.pas', + BoldComPersistenceHandleReg in 'Source\Persistence\IDECOM\BoldComPersistenceHandleReg.pas', + BoldComponentValidator in 'Source\ObjectSpace\UtilsGUI\BoldComponentValidator.pas', + BoldComponentValidatorCom in 'Source\ObjectSpace\COM\BoldComponentValidatorCom.pas', + BoldComponentValidatorIDE in 'Source\ObjectSpace\IDE\BoldComponentValidatorIDE.pas', BoldComReg in 'Source\Common\IDECOM\BoldComReg.pas', + BoldComServer in 'Source\Common\ConnectionCOM\BoldComServer.pas', + BoldComServerElementHandleFactory in 'Source\Handles\COM\BoldComServerElementHandleFactory.pas', + BoldComServerElementHandles in 'Source\Handles\COM\BoldComServerElementHandles.pas', + BoldComServerHandles in 'Source\Common\ConnectionHandlesCOM\BoldComServerHandles.pas', + BoldComThreads in 'Source\Common\COM\BoldComThreads.pas', + BoldComUtils in 'Source\Common\COM\BoldComUtils.pas', + BoldConcurrencyControlReg in 'Source\ConcurrencyControl\IDECOM\BoldConcurrencyControlReg.pas', + BoldCondition in 'Source\ValueSpace\Condition\BoldCondition.pas', + BoldConstraintValidator in 'Source\Samples\ConstraintValidator\BoldConstraintValidator.pas', + BoldConstraintValidatorReg in 'Source\Samples\ConstraintValidator\BoldConstraintValidatorReg.pas', + BoldContainers in 'Source\Common\Core\BoldContainers.pas', + BoldControllerListControlPack in 'Source\BoldAwareGUI\ControlPacks\BoldControllerListControlPack.pas', + BoldControlPack in 'Source\BoldAwareGUI\ControlPacks\BoldControlPack.pas', + BoldControlPackDefs in 'Source\Common\Support\BoldControlPackDefs.pas', + BoldControlPackPropertyEditors in 'Source\BoldAwareGUI\IDE\BoldControlPackPropertyEditors.pas', + BoldControlsDefs in 'Source\Common\Support\BoldControlsDefs.pas', + BoldCoreConsts in 'Source\ObjectSpace\Core\BoldCoreConsts.pas', + BoldCursorGuard in 'Source\Common\UtilsGUI\BoldCursorGuard.pas', + BoldCursorHandle in 'Source\Handles\Core\BoldCursorHandle.pas', + BoldCustomBlobMapper in 'Source\PMapper\Default\BoldCustomBlobMapper.pas', + BoldCustomCheckListBox in 'Source\Samples\BoldCheckListBox\BoldCustomCheckListBox.pas', + BoldDatabaseAdapterFireDAC in 'Source\Persistence\FireDAC\BoldDatabaseAdapterFireDAC.pas', + BoldDataBlock in 'Source\Common\HTTP\BoldDataBlock.pas', + BoldDateTimeControlPack in 'Source\BoldAwareGUI\ControlPacks\BoldDateTimeControlPack.pas', + BoldDBActions in 'Source\Persistence\DB\BoldDBActions.pas', + BoldDbDataValidator in 'Source\PMapper\Validator\BoldDbDataValidator.pas', + BoldDbEvolutor in 'Source\PMapper\DbEvolutor\BoldDbEvolutor.pas', + BoldDbEvolutorForm in 'Source\PMapper\DbEvolutor\BoldDbEvolutorForm.pas', + BoldDbEvolutorScript in 'Source\PMapper\DbEvolutor\BoldDbEvolutorScript.pas', + BoldDBInterfaces in 'Source\Persistence\DB\BoldDBInterfaces.pas', + BoldDbPlugins in 'Source\UMLModel\Plugins\BoldDbPlugins.pas', + BoldDbStructureValidator in 'Source\PMapper\Validator\BoldDbStructureValidator.pas', + BoldDbValidator in 'Source\PMapper\Validator\BoldDbValidator.pas', + BoldDebugActions in 'Source\Samples\Actions\BoldDebugActions.pas', + BoldDefaultId in 'Source\ValueSpace\Id\BoldDefaultId.pas', + BoldDefaultStreamNames in 'Source\ValueSpace\XMLStreaming\BoldDefaultStreamNames.pas', + BoldDefaultTaggedValues in 'Source\Common\TaggedValues\BoldDefaultTaggedValues.pas', + BoldDefaultXMLStreaming in 'Source\ValueSpace\XMLStreaming\BoldDefaultXMLStreaming.pas', + BoldDefs in 'Source\Common\Core\BoldDefs.pas', + BoldDefsDT in 'Source\Common\IDE\BoldDefsDT.pas', + BoldDerivationExpressionsEditor in 'Source\UMLModel\Editor\BoldDerivationExpressionsEditor.pas', + BoldDerivedHandle in 'Source\Handles\Core\BoldDerivedHandle.pas', + BoldDerivedValueSet in 'Source\ObjectSpace\BORepresentation\BoldDerivedValueSet.pas', + BoldDeriver in 'Source\Common\Subscription\BoldDeriver.pas', + BoldDirectoryTraverser in 'Source\Common\Support\BoldDirectoryTraverser.pas', + BoldDomainElement in 'Source\ObjectSpace\BORepresentation\BoldDomainElement.pas', + BoldDragDropTarget in 'Source\BoldAwareGUI\BoldControls\BoldDragDropTarget.pas', + BoldDragObject in 'Source\UMLModel\Editor\BoldDragObject.pas', + BoldEdit in 'Source\BoldAwareGUI\BoldControls\BoldEdit.pas', + BoldEditOCLAction in 'Source\Samples\Actions\BoldEditOCLAction.pas', + BoldEditOCLActionPropEditor in 'Source\Samples\IDE\BoldEditOCLActionPropEditor.pas', + BoldElementHandleFollower in 'Source\BoldAwareGUI\ControlPacks\BoldElementHandleFollower.pas', + BoldElementList in 'Source\ObjectSpace\BORepresentation\BoldElementList.pas', + BoldElements in 'Source\ObjectSpace\Core\BoldElements.pas', + BoldEnvironment in 'Source\Common\Environment\BoldEnvironment.pas', + BoldEnvironmentIDE in 'Source\Common\Environment\BoldEnvironmentIDE.pas', + BoldEnvironmentVCL in 'Source\Common\Environment\BoldEnvironmentVCL.pas', + BoldEventQueue in 'Source\Common\Queue\BoldEventQueue.pas', + BoldExceptionHandlers in 'Source\BoldAwareGUI\Core\BoldExceptionHandlers.pas', + BoldExpert in 'Source\Common\IDE\BoldExpert.pas', + BoldExpertMenus in 'Source\Common\IDE\BoldExpertMenus.pas', + BoldExpressionHandle in 'Source\Handles\Core\BoldExpressionHandle.pas', + BoldExternalizedReferences in 'Source\Common\Support\BoldExternalizedReferences.pas', + BoldExternalObjectSpaceEventHandler in 'Source\ObjectSpace\BORepresentation\BoldExternalObjectSpaceEventHandler.pas', BoldExternalObjectSpaceEventHandlerReg in 'Source\ObjectSpace\IDE\BoldExternalObjectSpaceEventHandlerReg.pas', - BoldPersistenceNotifierReg in 'Source\Persistence\IDE\BoldPersistenceNotifierReg.pas', - BoldOLLEHandlesReg in 'Source\Extensions\OLLE\IDE\BoldOLLEHandlesReg.pas', - BoldComPersistenceHandleReg in 'Source\Persistence\IDECOM\BoldComPersistenceHandleReg.pas', - BoldPersistenceHandleReg in 'Source\Persistence\IDE\BoldPersistenceHandleReg.pas', - BoldHTTPServerPersistenceHandlePassthroughReg in 'Source\Persistence\IDECOM\BoldHTTPServerPersistenceHandlePassthroughReg.pas', - BoldPropagatorHandleCOMReg in 'Source\Propagator\IDECOM\BoldPropagatorHandleCOMReg.pas', + BoldFileHandler in 'Source\Common\Support\BoldFileHandler.pas', + BoldFilteredHandle in 'Source\Handles\Core\BoldFilteredHandle.pas', + BoldFireDACConsts in 'Source\Persistence\FireDAC\BoldFireDACConsts.pas', + BoldFireDACInterfaces in 'Source\Persistence\FireDAC\BoldFireDACInterfaces.pas', + BoldFloatControlPack in 'Source\BoldAwareGUI\ControlPacks\BoldFloatControlPack.pas', + BoldFormSaver in 'Source\Samples\FormSaver\BoldFormSaver.pas', + BoldFormSaverActions in 'Source\Samples\FormSaver\BoldFormSaverActions.pas', + BoldFreeStandingValueFactories in 'Source\FreestandingValueSpace\Core\BoldFreeStandingValueFactories.pas', + BoldFreeStandingValues in 'Source\FreestandingValueSpace\Core\BoldFreeStandingValues.pas', + BoldGen in 'Source\MoldModel\CodeGenerator\BoldGen.pas', + BoldGeneratedCodeDictionary in 'Source\ObjectSpace\RTModel\BoldGeneratedCodeDictionary.pas', + BoldGeneratorTemplates in 'Source\MoldModel\CodeGenerator\BoldGeneratorTemplates.pas', + BoldGeneratorTemplatesCPP in 'Source\MoldModel\CodeGenerator\BoldGeneratorTemplatesCPP.pas', + BoldGeneratorTemplatesDelphi in 'Source\MoldModel\CodeGenerator\BoldGeneratorTemplatesDelphi.pas', + BoldGenericListControlPack in 'Source\BoldAwareGUI\ControlPacks\BoldGenericListControlPack.pas', + BoldGlobalId in 'Source\ValueSpace\Id\BoldGlobalId.pas', + BoldGrid in 'Source\BoldAwareGUI\BoldControls\BoldGrid.pas', + BoldGridPropertyEditors in 'Source\BoldAwareGUI\IDE\BoldGridPropertyEditors.pas', + BoldGridRTColEditor in 'Source\BoldAwareGUI\BoldControls\BoldGridRTColEditor.pas', + BoldGuard in 'Source\Common\Support\BoldGuard.pas', + BoldGUI in 'Source\BoldAwareGUI\Core\BoldGUI.pas', + BoldGUIDUtils in 'Source\Common\Support\BoldGUIDUtils.pas', + BoldGuiResourceStrings in 'Source\BoldAwareGUI\Core\BoldGuiResourceStrings.pas', + BoldHandle in 'Source\Common\Handles\BoldHandle.pas', + BoldHandleAction in 'Source\Handles\Actions\BoldHandleAction.pas', + BoldHandleComReg in 'Source\ClientHandlesCom\IDE\BoldHandleComReg.pas', + BoldHandlePropEditor in 'Source\Handles\IDE\BoldHandlePropEditor.pas', + BoldHandleReg in 'Source\Handles\IDE\BoldHandleReg.pas', + BoldHandles in 'Source\Handles\Core\BoldHandles.pas', + BoldHandlesPropagationReg in 'Source\Persistence\IDE\BoldHandlesPropagationReg.pas', + BoldHashIndexes in 'Source\Common\Support\BoldHashIndexes.pas', + BoldHTTPClientPersistenceHandle in 'Source\Persistence\HTTP\BoldHTTPClientPersistenceHandle.pas', BoldHTTPClientPersistenceHandleReg in 'Source\Persistence\IDECOM\BoldHTTPClientPersistenceHandleReg.pas', - BoldConcurrencyControlReg in 'Source\ConcurrencyControl\IDECOM\BoldConcurrencyControlReg.pas', - BoldUMLModelHandleReg in 'Source\UMLModel\Ide\BoldUMLModelHandleReg.pas', + BoldHTTPPersistenceControllerClient in 'Source\Persistence\HTTP\BoldHTTPPersistenceControllerClient.pas', + BoldHTTPServerPersistenceHandlePassthrough in 'Source\Persistence\HTTP\BoldHTTPServerPersistenceHandlePassthrough.pas', + BoldHTTPServerPersistenceHandlePassthroughReg in 'Source\Persistence\IDECOM\BoldHTTPServerPersistenceHandlePassthroughReg.pas', + BoldId in 'Source\ValueSpace\Id\BoldId.pas', + BoldIDAdder in 'Source\Persistence\Propagation\BoldIDAdder.pas', + BoldIDAdderHandle in 'Source\Persistence\Propagation\BoldIDAdderHandle.pas', + BoldIDEConsts in 'Source\Common\IDE\BoldIDEConsts.pas', + BoldIDEMenus in 'Source\Common\IDE\BoldIDEMenus.pas', + BoldIDESupport in 'Source\Common\IDE\BoldIDESupport.pas', + BoldImage in 'Source\BoldAwareGUI\BoldControls\BoldImage.pas', + BoldImageBitmap in 'Source\BoldAwareGUI\BoldControls\BoldImageBitmap.pas', + BoldImageJPEG in 'Source\BoldAwareGUI\BoldControls\BoldImageJPEG.pas', + BoldIndex in 'Source\Common\Support\BoldIndex.pas', + BoldIndexableList in 'Source\Common\Support\BoldIndexableList.pas', + BoldIndexCollection in 'Source\Common\Support\BoldIndexCollection.pas', + BoldIsoDateTime in 'Source\Common\Support\BoldIsoDateTime.pas', + BoldLabel in 'Source\BoldAwareGUI\BoldControls\BoldLabel.pas', + BoldLinks in 'Source\ObjectSpace\BORepresentation\BoldLinks.pas', + BoldListActions in 'Source\Handles\Actions\BoldListActions.pas', + BoldListBox in 'Source\BoldAwareGUI\BoldControls\BoldListBox.pas', + BoldListControlPack in 'Source\BoldAwareGUI\ControlPacks\BoldListControlPack.pas', + BoldListenerCOM in 'Source\Persistence\Propagation\BoldListenerCOM.pas', + BoldListenerHandle in 'Source\Persistence\Propagation\BoldListenerHandle.pas', + BoldListenerThread in 'Source\Persistence\Propagation\BoldListenerThread.pas', + BoldListHandle in 'Source\Handles\Core\BoldListHandle.pas', + BoldListHandleFollower in 'Source\BoldAwareGUI\ControlPacks\BoldListHandleFollower.pas', + BoldListListControlPack in 'Source\BoldAwareGUI\ControlPacks\BoldListListControlPack.pas', + BoldLockHandler in 'Source\ObjectSpace\PessimisticLocking\BoldLockHandler.pas', + BoldLockHolder in 'Source\ObjectSpace\PessimisticLocking\BoldLockHolder.pas', + BoldLockingDefs in 'Source\ConcurrencyControl\Common\BoldLockingDefs.pas', + BoldLockingHandles in 'Source\Handles\PessimisticLocking\BoldLockingHandles.pas', BoldLockingReg in 'Source\Handles\IDE\BoldLockingReg.pas', + BoldLockingSupportInterfaces_TLB in 'Source\Propagator\Common\BoldLockingSupportInterfaces_TLB.pas', + BoldLockManagerAdminHandleCom in 'Source\ConcurrencyControl\COM\BoldLockManagerAdminHandleCom.pas', + BoldLockManagerHandleCom in 'Source\ConcurrencyControl\COM\BoldLockManagerHandleCom.pas', + BoldLockRegions in 'Source\ObjectSpace\PessimisticLocking\BoldLockRegions.pas', + BoldLockUtils in 'Source\Samples\Misc\BoldLockUtils.pas', + BoldLogForm in 'Source\Common\Logging\BoldLogForm.pas', + BoldLoggableCriticalSection in 'Source\Common\Support\BoldLoggableCriticalSection.pas', + BoldLogHandler in 'Source\Common\Logging\BoldLogHandler.pas', + BoldLogHandlerForm in 'Source\Common\Logging\BoldLogHandlerForm.pas', + BoldLogHandlerSimple in 'Source\Common\Logging\BoldLogHandlerSimple.pas', + BoldLogReceiverInterface in 'Source\Common\Logging\BoldLogReceiverInterface.pas', BoldManipulatorReg in 'Source\Handles\IDE\BoldManipulatorReg.pas', - BoldWebConnectionReg in 'Source\Common\IDE\BoldWebConnectionReg.pas', - BoldReg in 'Source\Common\IDE\BoldReg.pas', - BoldXMLDispatcherReg in 'Source\Common\IDECOM\BoldXMLDispatcherReg.pas', + BoldManipulators in 'Source\Handles\Manipulators\BoldManipulators.pas', + BoldMappingInfo in 'Source\PMapper\Default\BoldMappingInfo.pas', + BoldMath in 'Source\Common\Support\BoldMath.pas', + BoldMemberTypeDictionary in 'Source\ObjectSpace\RTModel\BoldMemberTypeDictionary.pas', + BoldMemo in 'Source\BoldAwareGUI\BoldControls\BoldMemo.pas', + BoldMemoryManager in 'Source\Common\Support\BoldMemoryManager.pas', + BoldMeta in 'Source\MoldModel\Core\BoldMeta.pas', + BoldMetaElementList in 'Source\ObjectSpace\Core\BoldMetaElementList.pas', + BoldMetaSupport in 'Source\MoldModel\Core\BoldMetaSupport.pas', + BoldMLAttributes in 'Source\ObjectSpace\BORepresentation\BoldMLAttributes.pas', + BoldMLRenderers in 'Source\BoldAwareGUI\ControlPacks\BoldMLRenderers.pas', + BoldModel in 'Source\UMLModel\Handles\BoldModel.pas', + BoldModelAwareComponentEditor in 'Source\Common\IDE\BoldModelAwareComponentEditor.pas', + BoldModelLoader in 'Source\Samples\ModelLoader\BoldModelLoader.pas', + BoldModelOCLValidatorPlugIn in 'Source\UMLModel\Plugins\BoldModelOCLValidatorPlugIn.pas', BoldModelReg in 'Source\MoldModel\IDE\BoldModelReg.pas', - BoldPersistenceHandleSystemReg in 'Source\Persistence\IDE\BoldPersistenceHandleSystemReg.pas', + BoldMoldConsts in 'Source\MoldModel\Core\BoldMoldConsts.pas', + BoldNamedValueList in 'Source\Common\Support\BoldNamedValueList.pas', + BoldNameExpander in 'Source\MoldModel\Core\BoldNameExpander.pas', + BoldNavigator in 'Source\BoldAwareGUI\BoldControls\BoldNavigator.pas', + BoldNavigatorDefs in 'Source\Common\Support\BoldNavigatorDefs.pas', + BoldNewObjectInterceptor in 'Source\Samples\NewObjectInterceptor\BoldNewObjectInterceptor.pas', + BoldNodeControlPack in 'Source\BoldAwareGUI\ControlPacks\BoldNodeControlPack.pas', + BoldNodeDescriptionEditor in 'Source\BoldAwareGUI\IDE\BoldNodeDescriptionEditor.pas', + BoldNumericControlPack in 'Source\BoldAwareGUI\ControlPacks\BoldNumericControlPack.pas', + BoldObjectListControllers in 'Source\ObjectSpace\BORepresentation\BoldObjectListControllers.pas', + BoldObjectMarshaler in 'Source\Propagator\Common\BoldObjectMarshaler.pas', + BoldObjectNamePropertyEditor in 'Source\Common\IDECOM\BoldObjectNamePropertyEditor.pas', + BoldObjectRetriever in 'Source\Samples\Misc\BoldObjectRetriever.pas', + BoldObjectSpaceExternalEvents in 'Source\ValueSpace\ExternalEvents\BoldObjectSpaceExternalEvents.pas', + BoldObjectSpaceLists in 'Source\ObjectSpace\BORepresentation\BoldObjectSpaceLists.pas', + BoldObjectUpgrader in 'Source\Persistence\ObjectUpgrading\BoldObjectUpgrader.pas', + BoldObjectUpgraderHandle in 'Source\Persistence\ObjectUpgrading\BoldObjectUpgraderHandle.pas', BoldObjectUpgraderHandleReg in 'Source\Persistence\IDE\BoldObjectUpgraderHandleReg.pas', - BoldComElementHandleReg in 'Source\Handles\IDECOM\BoldComElementHandleReg.pas', - BoldUDPBroadcasterReg in 'Source\Persistence\IDEUDP\BoldUDPBroadcasterReg.pas', + BoldOcl in 'Source\ObjectSpace\Ocl\BoldOcl.pas', + BoldOclClasses in 'Source\ObjectSpace\Ocl\BoldOclClasses.pas', + BoldOclError in 'Source\ObjectSpace\Ocl\BoldOclError.pas', + BoldOclEvaluator in 'Source\ObjectSpace\Ocl\BoldOclEvaluator.pas', + BoldOCLGraphicRTDebug in 'Source\ObjectSpace\UtilsGUI\BoldOCLGraphicRTDebug.pas', + BoldOclLightWeightNodeMaker in 'Source\ObjectSpace\Ocl\BoldOclLightWeightNodeMaker.pas', + BoldOclLightWeightNodes in 'Source\ObjectSpace\Ocl\BoldOclLightWeightNodes.pas', + BoldOclPropEditor in 'Source\ObjectSpace\UtilsGUI\BoldOclPropEditor.pas', + BoldOclRepository in 'Source\Handles\Core\BoldOclRepository.pas', + BoldOclRTDebug in 'Source\ObjectSpace\Ocl\BoldOclRTDebug.pas', + BoldOclSemantics in 'Source\ObjectSpace\Ocl\BoldOclSemantics.pas', + BoldOclSymbolImplementations in 'Source\ObjectSpace\Ocl\BoldOclSymbolImplementations.pas', + BoldOclVariables in 'Source\Handles\Core\BoldOclVariables.pas', + BoldOLLEHandlesReg in 'Source\Extensions\OLLE\IDE\BoldOLLEHandlesReg.pas', + BoldOptimisticLockingSupport in 'Source\ObjectSpace\BORepresentation\BoldOptimisticLockingSupport.pas', + BoldORed in 'Source\ObjectSpace\Ocl\BoldORed.pas', + BoldOSSMessage in 'Source\ObjectSpace\BORepresentation\BoldOSSMessage.pas', + BoldOTACodeGen in 'Source\ObjectSpace\IDE\AttributeWizard\BoldOTACodeGen.pas', + BoldOTAFileHandler in 'Source\Common\IDE\BoldOTAFileHandler.pas', + BoldOTASupport in 'Source\Common\IDE\BoldOTASupport.pas', + BoldPageControl in 'Source\BoldAwareGUI\BoldControls\BoldPageControl.pas', + BoldPerformanceCounter in 'Source\Common\Support\BoldPerformanceCounter.pas', + BoldPersistenceController in 'Source\Persistence\Core\BoldPersistenceController.pas', + BoldPersistenceControllerDefault in 'Source\Persistence\DB\BoldPersistenceControllerDefault.pas', + BoldPersistenceControllerPassthrough in 'Source\Persistence\Propagation\BoldPersistenceControllerPassthrough.pas', + BoldPersistenceControllerSOAPAdapterCore in 'Source\Persistence\SOAP\BoldPersistenceControllerSOAPAdapterCore.pas', + BoldPersistenceControllerSystem in 'Source\Persistence\System\BoldPersistenceControllerSystem.pas', + BoldPersistenceHandle in 'Source\Persistence\Core\BoldPersistenceHandle.pas', + BoldPersistenceHandleDB in 'Source\Persistence\DB\BoldPersistenceHandleDB.pas', + BoldPersistenceHandleDB_deprecated in 'Source\Persistence\DB\BoldPersistenceHandleDB_deprecated.pas', + BoldPersistenceHandleDBreg in 'Source\Persistence\DB\BoldPersistenceHandleDBreg.pas', + BoldPersistenceHandleFile in 'Source\Persistence\File\BoldPersistenceHandleFile.pas', + BoldPersistenceHandleFileReg in 'Source\Persistence\IDE\BoldPersistenceHandleFileReg.pas', + BoldPersistenceHandleFileXML in 'Source\Persistence\File\BoldPersistenceHandleFileXML.pas', + BoldPersistenceHandleFireDAC in 'Source\Persistence\FireDAC\BoldPersistenceHandleFireDAC.pas', + BoldPersistenceHandleFireDACReg in 'Source\Persistence\FireDAC\BoldPersistenceHandleFireDACReg.pas', + BoldPersistenceHandlePassthrough in 'Source\Persistence\Core\BoldPersistenceHandlePassthrough.pas', + BoldPersistenceHandlePTWithModel in 'Source\Persistence\Core\BoldPersistenceHandlePTWithModel.pas', + BoldPersistenceHandleReg in 'Source\Persistence\IDE\BoldPersistenceHandleReg.pas', + BoldPersistenceHandleSystem in 'Source\Persistence\System\BoldPersistenceHandleSystem.pas', + BoldPersistenceHandleSystemReg in 'Source\Persistence\IDE\BoldPersistenceHandleSystemReg.pas', + BoldPersistenceNotifier in 'Source\Persistence\Core\BoldPersistenceNotifier.pas', + BoldPersistenceNotifierReg in 'Source\Persistence\IDE\BoldPersistenceNotifierReg.pas', + BoldPersistenceOperationXMLStreaming in 'Source\Persistence\SOAP\BoldPersistenceOperationXMLStreaming.pas', + BoldPlaceableSubscriber in 'Source\Handles\Core\BoldPlaceableSubscriber.pas', + BoldPMapper in 'Source\PMapper\Core\BoldPMapper.pas', + BoldPMapperLists in 'Source\PMapper\Core\BoldPMapperLists.pas', + BoldPMappers in 'Source\PMapper\Core\BoldPMappers.pas', + BoldPMappersAttributeDefault in 'Source\PMapper\Default\BoldPMappersAttributeDefault.pas', + BoldPMappersDefault in 'Source\PMapper\Default\BoldPMappersDefault.pas', + BoldPMappersLinkDefault in 'Source\PMapper\Default\BoldPMappersLinkDefault.pas', + BoldPMappersSQL in 'Source\PMapper\SQL\BoldPMappersSQL.pas', + BoldPMConsts in 'Source\PMapper\Core\BoldPMConsts.pas', + BoldPriorityQueue in 'Source\Common\Support\BoldPriorityQueue.pas', + BoldProgressBar in 'Source\BoldAwareGUI\BoldControls\BoldProgressBar.pas', + BoldPropagatorConstants in 'Source\Propagator\Common\BoldPropagatorConstants.pas', + BoldPropagatorGUIDs in 'Source\Propagator\Common\BoldPropagatorGUIDs.pas', + BoldPropagatorHandleCOM in 'Source\Propagator\COM\BoldPropagatorHandleCOM.pas', + BoldPropagatorHandleCOMReg in 'Source\Propagator\IDECOM\BoldPropagatorHandleCOMReg.pas', + BoldPropagatorInterfaces_TLB in 'Source\Propagator\Common\BoldPropagatorInterfaces_TLB.pas', + BoldPropagatorUtils in 'Source\Persistence\Propagation\BoldPropagatorUtils.pas', + BoldPropertiesController in 'Source\BoldAwareGUI\BoldControls\BoldPropertiesController.pas', + BoldPropertiesControllerPropertyEditors in 'Source\BoldAwareGUI\IDE\BoldPropertiesControllerPropertyEditors.pas', + BoldPropertyEditors in 'Source\Common\IDE\BoldPropertyEditors.pas', + BoldPSDescriptions in 'Source\PMapper\Core\BoldPSDescriptions.pas', + BoldPSDescriptionsDefault in 'Source\PMapper\Default\BoldPSDescriptionsDefault.pas', + BoldPSDescriptionsSQL in 'Source\PMapper\SQL\BoldPSDescriptionsSQL.pas', + BoldPSParams in 'Source\PMapper\Core\BoldPSParams.pas', + BoldPSParamsDefault in 'Source\PMapper\Default\BoldPSParamsDefault.pas', + BoldPSParamsSQL in 'Source\PMapper\SQL\BoldPSParamsSQL.pas', + BoldQueryUserDlg in 'Source\Common\UtilsGUI\BoldQueryUserDlg.pas', + BoldQueue in 'Source\Common\Queue\BoldQueue.pas', + BoldRawSQLHandle in 'Source\Handles\Core\BoldRawSQLHandle.pas', + BoldReferenceHandle in 'Source\Handles\Core\BoldReferenceHandle.pas', + BoldReg in 'Source\Common\IDE\BoldReg.pas', + BoldRegionDefinitionParser in 'Source\ObjectSpace\PessimisticLocking\BoldRegionDefinitionParser.pas', + BoldRegionDefinitions in 'Source\ObjectSpace\PessimisticLocking\BoldRegionDefinitions.pas', + BoldRegistry in 'Source\Common\Support\BoldRegistry.pas', + BoldRev in 'Source\Common\Support\BoldRev.pas', + BoldRichEdit in 'Source\BoldAwareGUI\BoldControls\BoldRichEdit.pas', + BoldRootedHandles in 'Source\Handles\Core\BoldRootedHandles.pas', + BoldRose2000Support in 'Source\Common\Rose2000\BoldRose2000Support.pas', + BoldRose98ptyCreator in 'Source\UMLModel\ModelLinks\Rose98\BoldRose98ptyCreator.pas', + BoldRose98Support in 'Source\Common\Rose98\BoldRose98Support.pas', + BoldRose98TaggedValues in 'Source\UMLModel\ModelLinks\Rose98\BoldRose98TaggedValues.pas', + BoldSamplesReg in 'Source\Samples\IDE\BoldSamplesReg.pas', + BoldSelectionListBox in 'Source\Samples\BoldCheckListBox\BoldSelectionListBox.pas', BoldSelectionListBoxReg in 'Source\Samples\BoldCheckListBox\BoldSelectionListBoxReg.pas', - BoldCheckListBoxReg in 'Source\Samples\BoldCheckListBox\BoldCheckListBoxReg.pas', + BoldServer in 'Source\Common\Connection\BoldServer.pas', + BoldServerHandles in 'Source\Common\ConnectionHandles\BoldServerHandles.pas', + BoldSharedStrings in 'Source\Common\Support\BoldSharedStrings.pas', + BoldSmallLogFrame in 'Source\Common\Logging\BoldSmallLogFrame.pas', + BoldSnooper in 'Source\Persistence\Propagation\BoldSnooper.pas', + BoldSnooperHandle in 'Source\Persistence\Propagation\BoldSnooperHandle.pas', + BoldSOAP_TLB in 'Source\Common\SOAP\BoldSOAP_TLB.pas', + BoldSOAP2_TLB in 'Source\Common\SOAP\BoldSOAP2_TLB.pas', + BoldSOAPClientPersistenceHandles in 'Source\Persistence\SOAP\BoldSOAPClientPersistenceHandles.pas', + BoldSOAPPersistenceControllerProxy in 'Source\Persistence\SOAP\BoldSOAPPersistenceControllerProxy.pas', + BoldSOAPPersistenceControllerStub in 'Source\Persistence\SOAP\BoldSOAPPersistenceControllerStub.pas', + BoldSOAPServerPersistenceHandles in 'Source\Persistence\SOAP\BoldSOAPServerPersistenceHandles.pas', + BoldSortedHandle in 'Source\Handles\Core\BoldSortedHandle.pas', + BoldSorter in 'Source\Common\Support\BoldSorter.pas', + BoldSQLDatabaseConfig in 'Source\PMapper\SQL\BoldSQLDatabaseConfig.pas', + BoldSQLHandle in 'Source\Handles\Core\BoldSQLHandle.pas', + BoldSQLMappingInfo in 'Source\PMapper\SQL\BoldSQLMappingInfo.pas', + BoldSqlNodeMaker in 'Source\PMapper\SQL\BoldSqlNodeMaker.pas', + BoldSqlNodes in 'Source\PMapper\SQL\BoldSqlNodes.pas', + BoldSqlNodesResolver in 'Source\PMapper\SQL\BoldSqlNodesResolver.pas', + BoldSQLQuery in 'Source\PMapper\SQL\BoldSQLQuery.pas', + BoldSqlQueryGenerator in 'Source\PMapper\SQL\BoldSqlQueryGenerator.pas', + BoldSqlSymbols in 'Source\PMapper\SQL\BoldSqlSymbols.pas', + BoldSSExcept in 'Source\ObjectSpace\Ocl\BoldSSExcept.pas', + BoldSSLexU in 'Source\ObjectSpace\Ocl\BoldSSLexU.pas', + BoldSSYaccU in 'Source\ObjectSpace\Ocl\BoldSSYaccU.pas', + BoldStreams in 'Source\Common\Core\BoldStreams.pas', + BoldStringControlPack in 'Source\BoldAwareGUI\ControlPacks\BoldStringControlPack.pas', + BoldStringId in 'Source\ValueSpace\Id\BoldStringId.pas', + BoldStringList in 'Source\Common\Support\BoldStringList.pas', + BoldStringsPropertyController in 'Source\BoldAwareGUI\BoldControls\BoldStringsPropertyController.pas', + BoldSubscribableCollection in 'Source\Common\Subscription\BoldSubscribableCollection.pas', + BoldSubscription in 'Source\Common\Subscription\BoldSubscription.pas', + BoldSupportConst in 'Source\Common\Support\BoldSupportConst.pas', + BoldSystem in 'Source\ObjectSpace\BORepresentation\BoldSystem.pas', + BoldSystemComparer in 'Source\Samples\SystemComparer\BoldSystemComparer.pas', + BoldSystemDebuggerForm in 'Source\Samples\SystemDebugger\BoldSystemDebuggerForm.pas', + BoldSystemHandle in 'Source\Handles\Core\BoldSystemHandle.pas', + BoldSystemOldValuehandler in 'Source\ObjectSpace\BORepresentation\BoldSystemOldValuehandler.pas', + BoldSystemPersistenceHandler in 'Source\ObjectSpace\BORepresentation\BoldSystemPersistenceHandler.pas', + BoldSystemRT in 'Source\ObjectSpace\RTModel\BoldSystemRT.pas', + BoldTaggedValueList in 'Source\Common\TaggedValues\BoldTaggedValueList.pas', + BoldTaggedValueSupport in 'Source\Common\TaggedValues\BoldTaggedValueSupport.pas', + BoldTemplate in 'Source\Common\Template\BoldTemplate.pas', + BoldTemplateExpander in 'Source\Common\Support\BoldTemplateExpander.pas', + BoldTextStream in 'Source\Common\IDE\BoldTextStream.pas', + BoldThread in 'Source\Common\SupportWin\BoldThread.pas', + BoldThreadedComObjectFactory in 'Source\Common\COM\BoldThreadedComObjectFactory.pas', + BoldThreadSafeLog in 'Source\Common\Logging\BoldThreadSafeLog.pas', + BoldThreadSafeQueue in 'Source\Common\Core\BoldThreadSafeQueue.pas', + BoldTrackBar in 'Source\BoldAwareGUI\BoldControls\BoldTrackBar.pas', + BoldTreeView in 'Source\BoldAwareGUI\BoldControls\BoldTreeView.pas', + BoldTreeViewConfig in 'Source\BoldAwareGUI\BoldControls\BoldTreeViewConfig.pas', + BoldTypeList in 'Source\ObjectSpace\BORepresentation\BoldTypeList.pas', + BoldTypeNameDictionary in 'Source\MoldModel\TypeNameDictionary\BoldTypeNameDictionary.pas', + BoldTypeNameEditor in 'Source\MoldModel\UtilsGUI\BoldTypeNameEditor.pas', + BoldTypeNameHandle in 'Source\MoldModel\Handles\BoldTypeNameHandle.pas', + BoldTypeNameHandleReg in 'Source\MoldModel\IDE\BoldTypeNameHandleReg.pas', + BoldTypeNameSelector in 'Source\ObjectSpace\UtilsGUI\BoldTypeNameSelector.pas', + BoldUDPBroadcasterReg in 'Source\Persistence\IDEUDP\BoldUDPBroadcasterReg.pas', + BoldUMLAbstractModelValidator in 'Source\UMLModel\Core\BoldUMLAbstractModelValidator.pas', + BoldUMLAddTV in 'Source\UMLModel\Editor\BoldUMLAddTV.pas', + BoldUMLAttributes in 'Source\UMLModel\Core\BoldUMLAttributes.pas', + BoldUMLBldLink in 'Source\UMLModel\ModelLinks\Bld\BoldUMLBldLink.pas', + BoldUMLConstraintEditor in 'Source\UMLModel\Editor\BoldUMLConstraintEditor.pas', + BoldUMLDelphiSupport in 'Source\Common\UML\BoldUMLDelphiSupport.pas', + BoldUMLModel in 'Source\UMLModel\Core\BoldUMLModel.pas', + BoldUMLModelConverter in 'Source\UMLModel\Core\BoldUMLModelConverter.pas', + BoldUMLModelDataModule in 'Source\UMLModel\Core\BoldUMLModelDataModule.pas', + BoldUMLModelEdit in 'Source\UMLModel\Editor\BoldUMLModelEdit.pas', + BoldUMLModelEditForm in 'Source\UMLModel\Editor\BoldUMLModelEditForm.pas', + BoldUMLModelEditPlugIn in 'Source\UMLModel\Plugins\BoldUMLModelEditPlugIn.pas', + BoldUMLModelEditReg in 'Source\UMLModel\Ide\BoldUMLModelEditReg.pas', + BoldUMLModelHandleReg in 'Source\UMLModel\Ide\BoldUMLModelHandleReg.pas', + BoldUMLModelLink in 'Source\UMLModel\ModelLinks\Core\BoldUMLModelLink.pas', + BoldUMLModelLinkSupport in 'Source\UMLModel\ModelLinks\Core\BoldUMLModelLinkSupport.pas', + BoldUMLModelStreamer in 'Source\UMLModel\Handles\BoldUMLModelStreamer.pas', + BoldUMLModelSupport in 'Source\UMLModel\Core\BoldUMLModelSupport.pas', + BoldUMLModelToEcoIIIGenerator in 'Source\UMLModel\Plugins\BoldUMLModelToEcoIIIGenerator.pas', + BoldUMLModelUpdater in 'Source\UMLModel\Core\BoldUMLModelUpdater.pas', + BoldUMLModelValidationForm in 'Source\UMLModel\Editor\BoldUMLModelValidationForm.pas', + BoldUMLModelValidator in 'Source\UMLModel\Core\BoldUMLModelValidator.pas', + BoldUMLNameTrimmer in 'Source\Samples\UMLPlugins\BoldUMLNameTrimmer.pas', + BoldUMLOCLEditor in 'Source\UMLModel\Editor\BoldUMLOCLEditor.pas', + BoldUMLOCLValidator in 'Source\UMLModel\Core\BoldUMLOCLValidator.pas', + BoldUMLPluginCallBacks in 'Source\UMLModel\Plugins\BoldUMLPluginCallBacks.pas', + BoldUMLPlugins in 'Source\UMLModel\Plugins\BoldUMLPlugins.pas', + BoldUMLRose98Link in 'Source\UMLModel\ModelLinks\Rose98\BoldUMLRose98Link.pas', + BoldUMLRose98Linkreg in 'Source\UMLModel\ModelLinks\Rose98\BoldUMLRose98Linkreg.pas', + BoldUMLRose98MappingUtils in 'Source\UMLModel\ModelLinks\Rose98\BoldUMLRose98MappingUtils.pas', + BoldUMLRose98Support in 'Source\UMLModel\ModelLinks\Rose98\BoldUMLRose98Support.pas', + BoldUMLTaggedValues in 'Source\Common\TaggedValues\BoldUMLTaggedValues.pas', + BoldUMLTaggedValuesEditor in 'Source\UMLModel\Editor\BoldUMLTaggedValuesEditor.pas', + BoldUMLTypes in 'Source\Common\UML\BoldUMLTypes.pas', + BoldUMLUsesEditorForm in 'Source\UMLModel\Editor\BoldUMLUsesEditorForm.pas', + BoldUMLUtils in 'Source\UMLModel\Core\BoldUMLUtils.pas', + BoldUMXMILinkreg in 'Source\UMLModel\ModelLinks\XMI\BoldUMXMILinkreg.pas', + BoldUndoActions in 'Source\Handles\Actions\BoldUndoActions.pas', + BoldUndoHandler in 'Source\ObjectSpace\Undo\BoldUndoHandler.pas', + BoldUndoInterfaces in 'Source\ObjectSpace\Interfaces\BoldUndoInterfaces.pas', + BoldUnloader in 'Source\ObjectSpace\Unloader\BoldUnloader.pas', + BoldUnloaderHandle in 'Source\Handles\UnLoader\BoldUnloaderHandle.pas', + BoldUpdatePrecondition in 'Source\Persistence\Core\BoldUpdatePrecondition.pas', + BoldUtils in 'Source\Common\Support\BoldUtils.pas', + BoldValueInterfaces in 'Source\ValueSpace\Interfaces\BoldValueInterfaces.pas', + BoldValueSpaceInterfaces in 'Source\ValueSpace\Interfaces\BoldValueSpaceInterfaces.pas', + BoldVariableDefinition in 'Source\Handles\Core\BoldVariableDefinition.pas', + BoldVariableHandle in 'Source\Handles\Core\BoldVariableHandle.pas', + BoldVariantControlPack in 'Source\BoldAwareGUI\ControlPacks\BoldVariantControlPack.pas', + BoldVclUtils in 'Source\ObjectSpace\IDE\AttributeWizard\BoldVclUtils.pas', + BoldViewerControlPack in 'Source\BoldAwareGUI\ControlPacks\BoldViewerControlPack.pas', + BoldWAClassInfo in 'Source\ObjectSpace\IDE\AttributeWizard\BoldWAClassInfo.pas', + BoldWACustomAttr in 'Source\ObjectSpace\IDE\AttributeWizard\BoldWACustomAttr.pas', + BoldWACustomAttrForm1 in 'Source\ObjectSpace\IDE\AttributeWizard\BoldWACustomAttrForm1.pas', + BoldWAdatamodule in 'Source\ObjectSpace\IDE\AttributeWizard\BoldWAdatamodule.pas', + BoldWAdmTemplates in 'Source\ObjectSpace\IDE\AttributeWizard\BoldWAdmTemplates.pas', + BoldWAInputFormUnit in 'Source\ObjectSpace\IDE\AttributeWizard\BoldWAInputFormUnit.pas', + BoldWAInterfaces in 'Source\ObjectSpace\IDE\AttributeWizard\BoldWAInterfaces.pas', + BoldWAMainForm in 'Source\ObjectSpace\IDE\AttributeWizard\BoldWAMainForm.pas', + BoldWAMethodInfo in 'Source\ObjectSpace\IDE\AttributeWizard\BoldWAMethodInfo.pas', + BoldWAStringGridManager in 'Source\ObjectSpace\IDE\AttributeWizard\BoldWAStringGridManager.pas', + BoldWASubClassForm1 in 'Source\ObjectSpace\IDE\AttributeWizard\BoldWASubClassForm1.pas', + BoldWAValueSetDlg in 'Source\ObjectSpace\IDE\AttributeWizard\BoldWAValueSetDlg.pas', + BoldWAValueSetForm1 in 'Source\ObjectSpace\IDE\AttributeWizard\BoldWAValueSetForm1.pas', + BoldWCodeInformer in 'Source\ObjectSpace\IDE\AttributeWizard\BoldWCodeInformer.pas', + BoldWebConnection in 'Source\Common\HTTP\BoldWebConnection.pas', + BoldWebConnectionReg in 'Source\Common\IDE\BoldWebConnectionReg.pas', + BoldWinINet in 'Source\Common\SupportWin\BoldWinINet.pas', + BoldWinUtils in 'Source\Common\SupportWin\BoldWinUtils.pas', + BoldWProjectWizard in 'Source\ObjectSpace\IDE\AttributeWizard\BoldWProjectWizard.pas', + BoldWScanner in 'Source\ObjectSpace\IDE\AttributeWizard\BoldWScanner.pas', + BoldWSimpleMenuWizard in 'Source\ObjectSpace\IDE\BoldWSimpleMenuWizard.pas', + BoldXCVTreeView in 'Source\BoldAwareGUI\BoldControls\BoldXCVTreeView.pas', + BoldXMLDispatcher in 'Source\Common\ConnectionHandlesCOM\BoldXMLDispatcher.pas', + BoldXMLDispatcherEditor in 'Source\Common\IDECOM\BoldXMLDispatcherEditor.pas', + BoldXMLDispatcherReg in 'Source\Common\IDECOM\BoldXMLDispatcherReg.pas', + BoldXMLDispatcherVB in 'Source\Common\ConnectionHandlesCOM\BoldXMLDispatcherVB.pas', BoldXMLDispatcherVBReg in 'Source\Common\IDECOM\BoldXMLDispatcherVBReg.pas', + BoldXMLProducers in 'Source\Handles\XML\BoldXMLProducers.pas', BoldXMLReg in 'Source\Handles\IDE\BoldXMLReg.pas', - BoldAFPPluggableReg in 'Source\BoldAwareGUI\FormGen\BoldAFPPluggableReg.pas', - BoldAwareGuiComReg in 'Source\ClientGuiCom\IDE\BoldAwareGuiComReg.pas', - BoldPersistenceHandleFireDACReg in 'Source\Persistence\FireDAC\BoldPersistenceHandleFireDACReg.pas', - BoldPersistenceHandleFireDAC in 'Source\Persistence\FireDAC\BoldPersistenceHandleFireDAC.pas', - BoldDatabaseAdapterFireDAC in 'Source\Persistence\FireDAC\BoldDatabaseAdapterFireDAC.pas', - BoldFireDACInterfaces in 'Source\Persistence\FireDAC\BoldFireDACInterfaces.pas', - BoldFireDACConsts in 'Source\Persistence\FireDAC\BoldFireDACConsts.pas', - BoldConstraintValidator in 'Source\Samples\ConstraintValidator\BoldConstraintValidator.pas', - BoldConstraintValidatorReg in 'Source\Samples\ConstraintValidator\BoldConstraintValidatorReg.pas', - BoldFormSaverActions in 'Source\Samples\FormSaver\BoldFormSaverActions.pas'; + BoldXMLRequests in 'Source\Common\SOAP\BoldXMLRequests.pas', + BoldXMLStreaming in 'Source\Common\Support\BoldXMLStreaming.pas', + FreeStandingValuesConst in 'Source\FreestandingValueSpace\Core\FreeStandingValuesConst.pas', + HandlesConst in 'Source\Handles\Core\HandlesConst.pas', + PersistenceConsts in 'Source\Persistence\Core\PersistenceConsts.pas', + PropagatorConsts in 'Source\Propagator\Common\PropagatorConsts.pas', + RationalRose2000_TLB in 'Source\Common\Rose2000\RationalRose2000_TLB.pas', + RationalRose98_TLB in 'Source\Common\Rose98\RationalRose98_TLB.pas', + UMLConsts in 'Source\UMLModel\Core\UMLConsts.pas', + ValueSpaceConst in 'Source\ValueSpace\Id\ValueSpaceConst.pas', + BoldAbstractExternalPersistenceController in 'Source\Persistence\ExternalPersistence\BoldAbstractExternalPersistenceController.pas', + BoldAbstractExternalPersistenceHandle in 'Source\Persistence\ExternalPersistence\BoldAbstractExternalPersistenceHandle.pas', + BoldAbstractPartiallyExternalPC in 'Source\Persistence\ExternalPersistence\BoldAbstractPartiallyExternalPC.pas', + BoldAbstractPartiallyExternalPH in 'Source\Persistence\ExternalPersistence\BoldAbstractPartiallyExternalPH.pas', + BoldExternalPersistenceConfigItemDataSet in 'Source\Persistence\ExternalPersistence\BoldExternalPersistenceConfigItemDataSet.pas', + BoldExternalPersistenceControllerConfig in 'Source\Persistence\ExternalPersistence\BoldExternalPersistenceControllerConfig.pas', + BoldExternalPersistenceControllerDataSet in 'Source\Persistence\ExternalPersistence\BoldExternalPersistenceControllerDataSet.pas', + BoldExternalPersistenceControllerEventDriven in 'Source\Persistence\ExternalPersistence\BoldExternalPersistenceControllerEventDriven.pas', + BoldExternalPersistenceControllerSQL in 'Source\Persistence\ExternalPersistence\BoldExternalPersistenceControllerSQL.pas', + BoldExternalPersistenceHandleDataSet in 'Source\Persistence\ExternalPersistence\BoldExternalPersistenceHandleDataSet.pas', + BoldExternalPersistenceHandleEventDriven in 'Source\Persistence\ExternalPersistence\BoldExternalPersistenceHandleEventDriven.pas', + BoldExternalPersistenceHandleSQL in 'Source\Persistence\ExternalPersistence\BoldExternalPersistenceHandleSQL.pas', + BoldExternalPersistenceHandleSQLPropEditor in 'Source\Persistence\ExternalPersistence\BoldExternalPersistenceHandleSQLPropEditor.pas', + BoldExternalPersistenceHandlesReg in 'Source\Persistence\ExternalPersistence\BoldExternalPersistenceHandlesReg.pas', + BoldExternalPersistenceSupport in 'Source\Persistence\ExternalPersistence\BoldExternalPersistenceSupport.pas', + ExPeConsts in 'Source\Persistence\ExternalPersistence\ExPeConsts.pas'; end. diff --git a/BoldDesignPackage.dproj b/BoldDesignPackage.dproj index 8e68937..20bfc0f 100644 --- a/BoldDesignPackage.dproj +++ b/BoldDesignPackage.dproj @@ -18,6 +18,11 @@ Base true
+ + true + Base + true + true Base @@ -47,7 +52,7 @@ Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;System;Xml;Data;Datasnap;Web;Soap;Winapi;$(DCC_Namespace) All BoldDesignPackage - $(BoldDelphi)\Source\UMLModel\Handles;$(BoldDelphi)\Source\Common\Subscription;$(BoldDelphi)\Source\Common\Include;$(BoldDelphi)\Source\Common\Core;$(BoldDelphi)\Source\Common\Support;$(BoldDelphi)\Source\Common\Queue;$(BoldDelphi)\Source\MoldModel\Handles;$(BoldDelphi)\Source\MoldModel\Core;$(BoldDelphi)\Source\Common\UML;$(BoldDelphi)\Source\MoldModel\TypeNameDictionary;$(BoldDelphi)\Source\Common\TaggedValues;$(BoldDelphi)\Source\ValueSpace\XMLStreaming;$(BoldDelphi)\Source\MoldModel\Bld;$(BoldDelphi)\Source\Common\Environment;$(BoldDelphi)\Source\Common\TaggedValues;$(BoldDelphi)\Source\Common\TaggedValues;$(BoldDelphi)\Source\Handles\Core;$(BoldDelphi)\Source\ObjectSpace\BORepresentation;$(BoldDelphi)\Source\ObjectSpace\RTModel;$(BoldDelphi)\Source\ObjectSpace\Core;$(BoldDelphi)\Source\ObjectSpace\Ocl;$(BoldDelphi)\Source\Persistence\Core;$(BoldDelphi)\Source\FreestandingValueSpace\Core;$(BoldDelphi)\Source\ValueSpace\Id;$(BoldDelphi)\Source\Common\MsXml;$(BoldDelphi)\Source\ValueSpace\Interfaces;$(BoldDelphi)\Source\ValueSpace\Condition;$(BoldDelphi)\Source\ValueSpace\Condition;$(BoldDelphi)\Source\Persistence\DB;$(BoldDelphi)\Source\PMapper\SQL;$(BoldDelphi)\Source\Common\Logging;$(BoldDelphi)\Source\ObjectSpace\Interfaces;$(BoldDelphi)\Source\ObjectSpace\PessimisticLocking;$(BoldDelphi)\Source\ObjectSpace\Undo;$(BoldDelphi)\Source\ObjectSpace\UtilsGUI;$(BoldDelphi)\Source\Common\Handles;$(BoldDelphi)\Source\Persistence\ObjectUpgrading;$(BoldDelphi)\Source\PMapper\Core;$(BoldDelphi)\Source\PMapper\Default;$(BoldDelphi)\Source\Common\UtilsGUI;$(BoldDelphi)\Source\Persistence\Propagation;$(BoldDelphi)\Source\UMLModel\Core;$(BoldDelphi)\Source\UMLModel\ModelLinks\Rose98;$(BoldDelphi)\Source\UMLModel\ModelLinks\Core;$(BoldDelphi)\Source\Common\Rose98;$(BoldDelphi)\Source\UMLModel\Editor;$(BoldDelphi)\Source\BoldAwareGUI\BoldControls;$(BoldDelphi)\Source\BoldAwareGUI\BoldControls;$(BoldDelphi)\Source\BoldAwareGUI\ControlPacks;$(BoldDelphi)\Source\BoldAwareGUI\Core;$(BoldDelphi)\Source\BoldAwareGUI\FormGen;$(BoldDelphi)\Source\UMLModel\Plugins;$(BoldDelphi)\Source\Common\IDE;$(BoldDelphi)\Source\Handles\Actions\;$(BoldDelphi)\Source\Persistence\IBX;$(BoldDelphi)\Source\Persistence\ExternalPersistence;$(BoldDelphi)\Source\BoldAwareGUI\IDE;$(BoldDelphi)\Source\ClientGuiCom\IDE;$(BoldDelphi)\Source\Handles\IDE;$(BoldDelphi)\Source\Handles\UnLoader;$(BoldDelphi)\Source\ObjectSpace\Unloader;$(BoldDelphi)\Source\MoldModel\UtilsGUI;$(BoldDelphi)\Source\Samples\FormSaver;$(BoldDelphi)\Source\Samples\NewObjectInterceptor;$(BoldDelphi)\Source\Samples\Actions;$(BoldDelphi)\Source\Samples\Misc;$(BoldDelphi)\Source\Samples\IDE;$(BoldDelphi)\Source\Samples\SystemDebugger;$(BoldDelphi)\Source\ClientHandlesCom\Core;$(BoldDelphi)\Source\ObjectSpace\COM;$(BoldDelphi)\Source\Common\COM;$(BoldDelphi)\Source\Common\ConnectionCOM;$(BoldDelphi)\Source\Common\Connection;$(BoldDelphi)\Source\Common\ConnectionHandlesCOM;$(BoldDelphi)\Source\UMLModel\ModelLinks\Bld;$(BoldDelphi)\Source\Common\ConnectionHandles;$(BoldDelphi)\Source\Common\IDECOM;$(BoldDelphi)\Source\UMLModel\ModelLinks\XMI;$(BoldDelphi)\Source\Persistence\File;$(BoldDelphi)\Source\Propagator\Common;$(BoldDelphi)\Source\ConcurrencyControl\Common;$(BoldDelphi)\Source\ValueSpace\ExternalEvents;$(BoldDelphi)\Source\Common\SupportWin;$(BoldDelphi)\Source\Persistence\DBExpress;$(BoldDelphi)\Source\Persistence\System;$(BoldDelphi)\Source\Persistence\UDPPropagator;$(BoldDelphi)\Source\Persistence\COM;$(BoldDelphi)\Source\Extensions\OLLE\Core;$(BoldDelphi)\Source\Extensions\OLLE\IDE;$(BoldDelphi)\Source\Persistence\SOAP;$(BoldDelphi)\Source\Common\SOAP;$(BoldDelphi)\Source\Persistence\HTTP;$(BoldDelphi)\Source\Propagator\COM;$(BoldDelphi)\Source\Propagator\IDECOM;$(BoldDelphi)\Source\Propagator\Enterprise;$(BoldDelphi)\Source\Common\HTTP;$(BoldDelphi)\Source\ConcurrencyControl\COM;$(BoldDelphi)\Source\ConcurrencyControl\IDECOM;$(BoldDelphi)\Source\Handles\PessimisticLocking;$(BoldDelphi)\Source\Handles\Manipulators;$(BoldDelphi)\Source\Handles\XML;$(BoldDelphi)\Source\Handles\COM;$(BoldDelphi)\Source\Handles\IDECOM;$(BoldDelphi)\Source\Handles\Actions;$(BoldDelphi)\Source\Samples\BoldCheckListBox;$(BoldDelphi)\Source\ClientGuiCom\BoldControls;$(BoldDelphi)\Source\ClientGuiCom\ControlPacks;$(BoldDelphi)\Source\ClientGuiCom\Core;$(DCC_UnitSearchPath) + $(BoldDelphi)\Source\BoldAwareGUI;$(BoldDelphi)\Source\BoldQAwareGUI;$(BoldDelphi)\Source\ClientGuiCom;$(BoldDelphi)\Source\ClientHandlesCom;$(BoldDelphi)\Source\Common;$(BoldDelphi)\Source\ConcurrencyControl;$(BoldDelphi)\Source\Extensions;$(BoldDelphi)\Source\FreestandingValueSpace;$(BoldDelphi)\Source\Handles;$(BoldDelphi)\Source\MoldModel;$(BoldDelphi)\Source\ObjectSpace;$(BoldDelphi)\Source\Persistence;$(BoldDelphi)\Source\PMapper;$(BoldDelphi)\Source\Propagator;$(BoldDelphi)\Source\Samples;$(BoldDelphi)\Source\UMLModel;$(BoldDelphi)\Source\Unassigned;$(BoldDelphi)\Source\ValueSpace;$(BoldDelphi)\Source\BoldAwareGUI\Actions;$(BoldDelphi)\Source\BoldAwareGUI\BoldControls;$(BoldDelphi)\Source\BoldAwareGUI\ControlPacks;$(BoldDelphi)\Source\BoldAwareGUI\Core;$(BoldDelphi)\Source\BoldAwareGUI\FormGen;$(BoldDelphi)\Source\BoldAwareGUI\IDE;$(BoldDelphi)\Source\BoldQAwareGUI\BoldControls;$(BoldDelphi)\Source\BoldQAwareGUI\ControlPacks;$(BoldDelphi)\Source\BoldQAwareGUI\Core;$(BoldDelphi)\Source\ClientGuiCom\BoldControls;$(BoldDelphi)\Source\ClientGuiCom\ControlPacks;$(BoldDelphi)\Source\ClientGuiCom\Core;$(BoldDelphi)\Source\ClientGuiCom\IDE;$(BoldDelphi)\Source\ClientHandlesCom\Core;$(BoldDelphi)\Source\ClientHandlesCom\IDE;$(BoldDelphi)\Source\Common\COM;$(BoldDelphi)\Source\Common\Connection;$(BoldDelphi)\Source\Common\ConnectionCOM;$(BoldDelphi)\Source\Common\ConnectionHandles;$(BoldDelphi)\Source\Common\ConnectionHandlesCOM;$(BoldDelphi)\Source\Common\Core;$(BoldDelphi)\Source\Common\Environment;$(BoldDelphi)\Source\Common\Handles;$(BoldDelphi)\Source\Common\HTTP;$(BoldDelphi)\Source\Common\IDE;$(BoldDelphi)\Source\Common\IDECOM;$(BoldDelphi)\Source\Common\Include;$(BoldDelphi)\Source\Common\Logging;$(BoldDelphi)\Source\Common\MsXml;$(BoldDelphi)\Source\Common\Queue;$(BoldDelphi)\Source\Common\Rose2000;$(BoldDelphi)\Source\Common\Rose98;$(BoldDelphi)\Source\Common\SOAP;$(BoldDelphi)\Source\Common\Subscription;$(BoldDelphi)\Source\Common\Support;$(BoldDelphi)\Source\Common\SupportWin;$(BoldDelphi)\Source\Common\TaggedValues;$(BoldDelphi)\Source\Common\Template;$(BoldDelphi)\Source\Common\UML;$(BoldDelphi)\Source\Common\UtilsGUI;$(BoldDelphi)\Source\ConcurrencyControl\COM;$(BoldDelphi)\Source\ConcurrencyControl\Common;$(BoldDelphi)\Source\ConcurrencyControl\IDECOM;$(BoldDelphi)\Source\Extensions\OLLE;$(BoldDelphi)\Source\Extensions\OLLE\Core;$(BoldDelphi)\Source\Extensions\OLLE\IDE;$(BoldDelphi)\Source\FreestandingValueSpace\Core;$(BoldDelphi)\Source\Handles\Actions;$(BoldDelphi)\Source\Handles\COM;$(BoldDelphi)\Source\Handles\Core;$(BoldDelphi)\Source\Handles\IDE;$(BoldDelphi)\Source\Handles\IDECOM;$(BoldDelphi)\Source\Handles\Manipulators;$(BoldDelphi)\Source\Handles\PessimisticLocking;$(BoldDelphi)\Source\Handles\UnLoader;$(BoldDelphi)\Source\Handles\XML;$(BoldDelphi)\Source\MoldModel\Bld;$(BoldDelphi)\Source\MoldModel\CodeGenerator;$(BoldDelphi)\Source\MoldModel\Core;$(BoldDelphi)\Source\MoldModel\Handles;$(BoldDelphi)\Source\MoldModel\IDE;$(BoldDelphi)\Source\MoldModel\TypeNameDictionary;$(BoldDelphi)\Source\MoldModel\UtilsGUI;$(BoldDelphi)\Source\ObjectSpace\BORepresentation;$(BoldDelphi)\Source\ObjectSpace\COM;$(BoldDelphi)\Source\ObjectSpace\Core;$(BoldDelphi)\Source\ObjectSpace\IDE;$(BoldDelphi)\Source\ObjectSpace\Interfaces;$(BoldDelphi)\Source\ObjectSpace\Ocl;$(BoldDelphi)\Source\ObjectSpace\PessimisticLocking;$(BoldDelphi)\Source\ObjectSpace\RTModel;$(BoldDelphi)\Source\ObjectSpace\Undo;$(BoldDelphi)\Source\ObjectSpace\Unloader;$(BoldDelphi)\Source\ObjectSpace\UtilsGUI;$(BoldDelphi)\Source\ObjectSpace\IDE\AttributeWizard;$(BoldDelphi)\Source\Persistence\ADO;$(BoldDelphi)\Source\Persistence\Advantage;$(BoldDelphi)\Source\Persistence\BDE;$(BoldDelphi)\Source\Persistence\COM;$(BoldDelphi)\Source\Persistence\Core;$(BoldDelphi)\Source\Persistence\DB;$(BoldDelphi)\Source\Persistence\DBExpress;$(BoldDelphi)\Source\Persistence\DBISAM;$(BoldDelphi)\Source\Persistence\DOA;$(BoldDelphi)\Source\Persistence\ExternalPersistence;$(BoldDelphi)\Source\Persistence\File;$(BoldDelphi)\Source\Persistence\FireDAC;$(BoldDelphi)\Source\Persistence\HTTP;$(BoldDelphi)\Source\Persistence\IBX;$(BoldDelphi)\Source\Persistence\IDE;$(BoldDelphi)\Source\Persistence\IDECOM;$(BoldDelphi)\Source\Persistence\IDEUDP;$(BoldDelphi)\Source\Persistence\ObjectUpgrading;$(BoldDelphi)\Source\Persistence\Propagation;$(BoldDelphi)\Source\Persistence\SOAP;$(BoldDelphi)\Source\Persistence\SQLDirect;$(BoldDelphi)\Source\Persistence\System;$(BoldDelphi)\Source\Persistence\UDPPropagator;$(BoldDelphi)\Source\Persistence\UniDAC;$(BoldDelphi)\Source\PMapper\Core;$(BoldDelphi)\Source\PMapper\DbEvolutor;$(BoldDelphi)\Source\PMapper\Default;$(BoldDelphi)\Source\PMapper\SQL;$(BoldDelphi)\Source\PMapper\Validator;$(BoldDelphi)\Source\Propagator\COM;$(BoldDelphi)\Source\Propagator\Common;$(BoldDelphi)\Source\Propagator\Enterprise;$(BoldDelphi)\Source\Propagator\IDECOM;$(BoldDelphi)\Source\Propagator\LowEnd;$(BoldDelphi)\Source\Samples\Actions;$(BoldDelphi)\Source\Samples\BoldCheckListBox;$(BoldDelphi)\Source\Samples\ConstraintValidator;$(BoldDelphi)\Source\Samples\FormSaver;$(BoldDelphi)\Source\Samples\IDE;$(BoldDelphi)\Source\Samples\Misc;$(BoldDelphi)\Source\Samples\ModelLoader;$(BoldDelphi)\Source\Samples\NewObjectInterceptor;$(BoldDelphi)\Source\Samples\SortingGrid;$(BoldDelphi)\Source\Samples\SystemComparer;$(BoldDelphi)\Source\Samples\SystemDebugger;$(BoldDelphi)\Source\Samples\UMLPlugins;$(BoldDelphi)\Source\Samples\Unicode;$(BoldDelphi)\Source\UMLModel\Core;$(BoldDelphi)\Source\UMLModel\Editor;$(BoldDelphi)\Source\UMLModel\Handles;$(BoldDelphi)\Source\UMLModel\Ide;$(BoldDelphi)\Source\UMLModel\ModelLinks;$(BoldDelphi)\Source\UMLModel\Plugins;$(BoldDelphi)\Source\UMLModel\ModelLinks\Bld;$(BoldDelphi)\Source\UMLModel\ModelLinks\Core;$(BoldDelphi)\Source\UMLModel\ModelLinks\ModelMaker;$(BoldDelphi)\Source\UMLModel\ModelLinks\Rose98;$(BoldDelphi)\Source\UMLModel\ModelLinks\XMI;$(BoldDelphi)\Source\UMLModel\ModelLinks\ModelMaker\Link;$(BoldDelphi)\Source\UMLModel\ModelLinks\ModelMaker\MMPlugin;$(BoldDelphi)\Source\UMLModel\ModelLinks\ModelMaker\Support;$(BoldDelphi)\Source\ValueSpace\Condition;$(BoldDelphi)\Source\ValueSpace\ExternalEvents;$(BoldDelphi)\Source\ValueSpace\Id;$(BoldDelphi)\Source\ValueSpace\Interfaces;$(BoldDelphi)\Source\ValueSpace\XMLStreaming;$(DCC_UnitSearchPath) 2077 CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments= true @@ -55,7 +60,7 @@ true true true - Bold 4.0 for Delphi + Bold for Delphi Design Package Bold_Delphi;$(DCC_Define) true @@ -65,6 +70,10 @@ true CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments= 1033 + vcl;IndySystem;IndyCore;vcldb;FireDAC;FireDACCommonDriver;FireDACCommon;FireDACPgDriver;$(DCC_UsePackage) + + + vcl;IndySystem;IndyCore;vcldb;FireDAC;FireDACCommonDriver;FireDACCommon;FireDACPgDriver;$(DCC_UsePackage) DEBUG;$(DCC_Define) @@ -95,54 +104,503 @@ + - + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + Cfg_2 Base @@ -164,6 +622,19 @@ BoldDesignPackage.dpk + Bold 4.0 for Delphi (VCL GUI) + Bold 4.0 for Delphi + Bold 4.0 for Delphi (Model editor) + Bold 4.0 for Delphi (FireDAC Support) + Bold 4.0 for Delphi (DBExpress Support) + Bold 4.0 for Delphi (COM Support) + Bold 4.0 for Delphi (External Persistence) + Bold 4.0 for Delphi (IBX Support) + Bold 4.0 for Delphi (Utils) + Bold 4.0 for Delphi (XMI Link) + Bold 4.0 for Delphi (UniDAC Support) + Bold 4.0 for Delphi (Object Lending Library Extension) + Attracs Components for Delphi 10.4 Sydney Microsoft Office 2000 Sample Automation Server Wrapper Components Microsoft Office XP Sample Automation Server Wrapper Components From cc91547853b659bf629989cd8d22d319f2cffd48 Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Sat, 22 May 2021 18:34:52 +0300 Subject: [PATCH 054/112] Implemented BoldOSSLog --- .../BoldObjectSpaceExternalEvents.pas | 89 +++++++++++++------ 1 file changed, 61 insertions(+), 28 deletions(-) diff --git a/Source/ValueSpace/ExternalEvents/BoldObjectSpaceExternalEvents.pas b/Source/ValueSpace/ExternalEvents/BoldObjectSpaceExternalEvents.pas index 9f8eddf..0e1d2c0 100644 --- a/Source/ValueSpace/ExternalEvents/BoldObjectSpaceExternalEvents.pas +++ b/Source/ValueSpace/ExternalEvents/BoldObjectSpaceExternalEvents.pas @@ -7,7 +7,8 @@ interface uses BoldID, - BoldDefaultID; + BoldDefaultID, + BoldLogHandler; type TBoldEventType = Char; @@ -30,19 +31,25 @@ TBoldObjectSpaceExternalEvent = class class function GetParameter(const Event: TBoldExternalEvent): String; class function GetEventType(const Event: TBoldExternalEvent): TBoldObjectSpaceSubscriptionType; public - class function EncodeExternalEvent(SubscriptionType: TBoldObjectSpaceSubscriptionType; const ClassName,MemberName, LockName: string; + class function EncodeExternalEvent(SubscriptionType: TBoldObjectSpaceSubscriptionType; const AClassName, AMemberName, ALockName: string; ObjectID: TBoldObjectID): String; class function DecodeExternalEvent(const Event: TBoldExternalEvent; - var Classname, MemberName, LockName: String; + var AClassname, MemberName, LockName: String; ObjectID: TBoldDefaultID): TBoldObjectSpaceSubscriptionType; end; +procedure BoldOSSLog(const s: string); +procedure BoldOSSLogFmt(const s: string; const Args: array of const); + +var + BoldOSSLogHandler: TBoldLogHandler; + implementation uses SysUtils, BoldDefs, - BoldRev; + BoldIsoDateTime; const SUBSCRIPTION_DELIMITER_CHAR = ':'; @@ -56,6 +63,18 @@ implementation EXTERNAL_EVENT_LOCKLOST = 'L'; EXTERNAL_EVENT_GOTLOCK = 'GotLocks'; +procedure BoldOSSLog(const s: string); +begin + if assigned(BoldOSSLogHandler) then + BoldOSSLogHandler.Log(AsISODateTimeMS(now)+':'+trim(s)); +end; + +procedure BoldOSSLogFmt(const s: string; const Args: array of const); +begin + if assigned(BoldOSSLogHandler) then + BoldOSSLogHandler.LogFmt(AsIsoDateTimeMs(now)+':'+ trim(s), Args); +end; + class function TBoldObjectSpaceExternalEvent.GetEventType(const Event: TBoldExternalEvent): TBoldObjectSpaceSubscriptionType; var ExternalEvent: char; @@ -112,44 +131,44 @@ class procedure TBoldObjectSpaceExternalEvent.GetID(const Event: TBoldExternalEv end; class function TBoldObjectSpaceExternalEvent.EncodeExternalEvent(SubscriptionType: TBoldObjectSpaceSubscriptionType; - const ClassName,MemberName, LockName: string; ObjectID: TBoldObjectID): String; + const AClassName, AMemberName, ALockName: string; ObjectID: TBoldObjectID): String; begin case SubscriptionType of bsClassChanged: Result := EXTERNAL_EVENT_CLASSCHANGED + SUBSCRIPTION_DELIMITER_CHAR + - ClassName; + AClassName; bsMemberChanged: Result := EXTERNAL_EVENT_MEMBERCHANGED + SUBSCRIPTION_DELIMITER_CHAR + - ClassName + + AClassName + CLASS_MEMBER_SEPARATOR + - MemberName + + AMemberName + SUBSCRIPTION_DELIMITER_CHAR + ObjectID.AsString; bsEmbeddedStateOfObjectChanged: Result := EXTERNAL_EVENT_EMBEDDEDSTATEOFOBJECTCHANGED + SUBSCRIPTION_DELIMITER_CHAR + - ClassName + + AClassName + SUBSCRIPTION_DELIMITER_CHAR + ObjectID.AsString; bsNonEmbeddedStateOfObjectChanged: Result := EXTERNAL_EVENT_NONEMBEDDEDSTATEOFOBJECTCHANGED + SUBSCRIPTION_DELIMITER_CHAR + - ClassName + + AClassName + CLASS_MEMBER_SEPARATOR + - MemberName + + AMemberName + SUBSCRIPTION_DELIMITER_CHAR + ObjectID.AsString; bsLockLost: Result := EXTERNAL_EVENT_LOCKLOST + SUBSCRIPTION_DELIMITER_CHAR + - LockName; + ALockName; bsGotLocks: Result := EXTERNAL_EVENT_GOTLOCK; bsObjectCreated: Result := EXTERNAL_EVENT_OBJECTCREATED + SUBSCRIPTION_DELIMITER_CHAR + - ClassName + + AClassName + SUBSCRIPTION_DELIMITER_CHAR + ObjectID.AsString; bsObjectDeleted: Result := EXTERNAL_EVENT_EMBEDDEDSTATEOFOBJECTCHANGED + SUBSCRIPTION_DELIMITER_CHAR + - ClassName + + AClassName + SUBSCRIPTION_DELIMITER_CHAR + ObjectID.AsString + PROPAGATOR_PARAMETER_DELIMITER_CHAR + @@ -160,7 +179,7 @@ class function TBoldObjectSpaceExternalEvent.EncodeExternalEvent(SubscriptionTyp end; class function TBoldObjectSpaceExternalEvent.DecodeExternalEvent(const Event: TBoldExternalEvent; - var Classname, MemberName, LockName: String; + var AClassname, MemberName, LockName: String; ObjectID: TBoldDefaultID): TBoldObjectSpaceSubscriptionType; var s: string; @@ -168,38 +187,54 @@ class function TBoldObjectSpaceExternalEvent.DecodeExternalEvent(const Event: TB begin Result := GetEventType(Event); case Result of - bsClassChanged: ClassName := Copy(Event, Length(EXTERNAL_EVENT_CLASSCHANGED + SUBSCRIPTION_DELIMITER_CHAR) + 1, MaxInt); + bsClassChanged: AClassName := Copy(Event, Length(EXTERNAL_EVENT_CLASSCHANGED + SUBSCRIPTION_DELIMITER_CHAR) + 1, MaxInt); bsObjectCreated: begin - ClassName := Copy(Event, Length(EXTERNAL_EVENT_OBJECTCREATED + SUBSCRIPTION_DELIMITER_CHAR) + 1, MaxInt); - ClassName := Copy(ClassName, 1, Pos(SUBSCRIPTION_DELIMITER_CHAR,ClassName) - 1); - GetID(Event, ObjectID, ClassName); + AClassName := Copy(Event, Length(EXTERNAL_EVENT_OBJECTCREATED + SUBSCRIPTION_DELIMITER_CHAR) + 1, MaxInt); + AClassName := Copy(AClassName, 1, Pos(SUBSCRIPTION_DELIMITER_CHAR,AClassName) - 1); + GetID(Event, ObjectID, AClassName); + BoldOSSLogFmt('Object %s.%s created', [AClassName, ObjectID.AsString]); end; bsMemberChanged: begin s := Copy(Event, pos(SUBSCRIPTION_DELIMITER_CHAR, Event) + 1, maxint); i := Pos(CLASS_MEMBER_SEPARATOR, s); - ClassName := Copy(s, 1, i-1); + AClassName := Copy(s, 1, i-1); MemberName := Copy(s, i+1, Pos(SUBSCRIPTION_DELIMITER_CHAR, s)-i-1); s := Copy(s, Pos(SUBSCRIPTION_DELIMITER_CHAR, s) + 1, MaxInt); ObjectID.AsInteger := StrToInt(s); + BoldOSSLogFmt('Member modified %s.%s.%s', [AClassName, MemberName, ObjectID.AsString]); end; bsObjectDeleted, bsEmbeddedStateOfObjectChanged: begin i := pos(SUBSCRIPTION_DELIMITER_CHAR, Event) + 1; - ClassName := Copy(Event, i, Pos(SUBSCRIPTION_DELIMITER_CHAR, Copy(Event, i, maxint)) - 1); - GetID(Event, ObjectID, ClassName); + AClassName := Copy(Event, i, Pos(SUBSCRIPTION_DELIMITER_CHAR, Copy(Event, i, maxint)) - 1); + GetID(Event, ObjectID, AClassName); + case bsObjectDeleted of + bsObjectDeleted: BoldOSSLogFmt('Object Deleted %s.%s', [AClassName, ObjectID.AsString]); + bsEmbeddedStateOfObjectChanged: BoldOSSLogFmt('EmbeddedStateOfObjectChanged %s.%s', [AClassName, ObjectID.AsString]); + end; + BoldOSSLogFmt('Object Deleted %s.%s', [AClassName, ObjectID.AsString]); end; bsNonEmbeddedStateOfObjectChanged: begin i := pos(SUBSCRIPTION_DELIMITER_CHAR, Event) + 1; s := Copy(Event, i, Pos(SUBSCRIPTION_DELIMITER_CHAR, Copy(Event, i, maxint)) - 1); - ClassName := Copy(s, 1, Pos(CLASS_MEMBER_SEPARATOR, s) - 1); + AClassName := Copy(s, 1, Pos(CLASS_MEMBER_SEPARATOR, s) - 1); MemberName := Copy(s, Pos(CLASS_MEMBER_SEPARATOR, s) +1, maxint); - GetID(Event, ObjectID, ClassName); + GetID(Event, ObjectID, AClassName); + BoldOSSLogFmt('Non Embedded state of object changed: Deleted %s.%s.%s', [AClassName, ObjectID.AsString, MemberName]); + end; + bsLockLost: + begin + LockName := Copy(Event, Length(EXTERNAL_EVENT_LOCKLOST + SUBSCRIPTION_DELIMITER_CHAR) + 1, MaxInt); + BoldOSSLogFmt('Lock Lost %s', [LockName]); + end; + bsGotLocks: + begin + LockName := Copy(Event, Length(EXTERNAL_EVENT_LOCKLOST + SUBSCRIPTION_DELIMITER_CHAR) + 1, MaxInt); + BoldOSSLogFmt('Locks placed %s', [LockName]); end; - bsLockLost: LockName := Copy(Event, Length(EXTERNAL_EVENT_LOCKLOST + SUBSCRIPTION_DELIMITER_CHAR) + 1, MaxInt); - bsGotLocks{, bsDBLock}: ; end; end; @@ -215,7 +250,5 @@ class function TBoldObjectSpaceExternalEvent.GetParameter(const Event: TBoldExte result := ''; end; -initialization - end. From bbc160b579914b9b3d705a7d1026a8b34fa93ee5 Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Sat, 22 May 2021 18:36:50 +0300 Subject: [PATCH 055/112] Updated SqlDir from ancient 80 to 260 --- BoldSQLDirect.dpk | 2 +- BoldSQLDirect.dproj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/BoldSQLDirect.dpk b/BoldSQLDirect.dpk index c8e2685..f23740c 100644 --- a/BoldSQLDirect.dpk +++ b/BoldSQLDirect.dpk @@ -33,7 +33,7 @@ requires vcl, vcldb, Bold, - SqlDir80; + SqlDir260; contains BoldDatabaseAdapterSQLDirect in 'Source\Persistence\SQLDirect\BoldDatabaseAdapterSQLDirect.pas', diff --git a/BoldSQLDirect.dproj b/BoldSQLDirect.dproj index 1fadfb3..b110b5b 100644 --- a/BoldSQLDirect.dproj +++ b/BoldSQLDirect.dproj @@ -88,7 +88,7 @@ - + From 86ff5130c4a5da2c3a53dc629ca6772ee268cedb Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Sat, 22 May 2021 18:45:57 +0300 Subject: [PATCH 056/112] TBoldSystemExtension now Subscribable. BoldList.Remove has param ARaiseIfNotFound. CreateTypedList and CreateRootClassList now have BoldSystem param. Clear Undo on System.discard. Add missing call to Prechange in TBoldAttribute.SetContentToNull - did not write to rollback. --- .../BORepresentation/BoldSystem.pas | 39 ++++++++++++------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/Source/ObjectSpace/BORepresentation/BoldSystem.pas b/Source/ObjectSpace/BORepresentation/BoldSystem.pas index d2639cd..d04af32 100644 --- a/Source/ObjectSpace/BORepresentation/BoldSystem.pas +++ b/Source/ObjectSpace/BORepresentation/BoldSystem.pas @@ -112,7 +112,7 @@ EBoldAccessNullValue = class(EBold); TBoldCreateApproximateObjectError = procedure(Obj: TBoldObject) of object; { TBoldSystemExtension } - TBoldSystemExtension = class(TBoldNonRefcountedObject) + TBoldSystemExtension = class(TBoldSubscribableNonRefCountedObject) private fSystem: TBoldSystem; public @@ -958,7 +958,7 @@ TBoldList = class(TBoldMember) procedure InsertNew(index: Integer); virtual; abstract; procedure Move(CurIndex, NewIndex: Integer); virtual; abstract; procedure MakeContentsImmutable; - procedure Remove(Item: TBoldElement); virtual; + procedure Remove(Item: TBoldElement; ARaiseIfNotFound: boolean = true); virtual; procedure RemoveByIndex(index: Integer); virtual; abstract; procedure Sort(CompareFunc: TBoldElementCompare; FirstIndex, LastIndex: Integer; SortMode: TBoldSortMode = BoldDefaultSortMode); overload; @@ -1091,8 +1091,8 @@ TBoldObjectList = class(TBoldList) function GetEnumerator: TBoldObjectListEnumerator; function GetLocatorEnumerator: TBoldObjectListLocatorEnumerator; constructor InternalCreateClassList(System: TBoldSystem; ListTypeInfo: TBoldListTypeInfo); - constructor CreateTypedList(ObjectClass: TBoldObjectClass); - constructor CreateRootClassList; + constructor CreateTypedList(ObjectClass: TBoldObjectClass; ABoldSystem: TBoldSystem = nil); + constructor CreateRootClassList(ABoldSystem: TBoldSystem = nil); procedure Add(BoldObject: TBoldObject); {$IFDEF BOLD_INLINE}inline;{$ENDIF} procedure AddList(List: TBoldList); override; procedure AddLocator(NewLocator: TBoldObjectLocator); @@ -1297,10 +1297,8 @@ TBoldLocatorHashIndex = class(TBoldHashIndex) public function FindLocatorByLocator(BoldObjectLocator: TBoldObjectLocator): TBoldObjectLocator; end; - {$ENDIF} - TBoldMemberDeriver = class({$IFDEF LightMemberDeriver}TBoldAbstractDeriver{$ELSE}TBoldEventPluggedDeriver{$ENDIF}) strict private fDerivedMember: TBoldMember; @@ -2417,6 +2415,8 @@ procedure TBoldSystem.Discard; DiscardTransient; if assigned(PessimisticLockHandler) then PessimisticLockHandler.ReleaseUnneededRegions; + if UndoHandlerInterface.Enabled then + UndoHandlerInterface.ClearAllUndoBlocks; end; procedure TBoldSystem.DefaultSubscribe(Subscriber: TBoldSubscriber; RequestedEvent: TBoldEvent = breReEvaluate); @@ -2627,7 +2627,7 @@ procedure TBoldSystem.ReceiveEventFromOwned(originator: TObject; else {$IFDEF BoldSystemBroadcastMemberEvents} if (originalEvent in beBroadcastMemberEvents) and ((Originator is TBoldObject) or (Originator is TBoldMember) and (TBoldMember(Originator).OwnedByObject)) then - Publisher.SendExtendedEvent(Originator, originalEvent, Args); + Publisher.SendExtendedEvent(Originator, originalEvent, Args); {$ENDIF} end; @@ -3359,7 +3359,6 @@ function TBoldObject.GetBoldMemberDeriver(Member: TBoldMember): TBoldMemberDeriv fDeriverArray[index] := Result; Member.HasDeriver := True; end; - end; function TBoldObject.SafeGetBoldMemberAssigned(Index: integer): Boolean; @@ -5889,7 +5888,7 @@ function TBoldAttribute.StringCompare(CompareType: TBoldCompareType; const s1, s ctAsString, ctCaseSensitive: Result := UnicodeCompareText(true, s1, s2); else - raise EBold.CreateFmt('Unsupported CompareType in StringCompare.', [ClassName]); + raise EBold.CreateFmt('%s.StringCompare Unsupported CompareType %s in StringCompare.', [ClassName, GetEnumName(TypeInfo(TBoldCompareType), Ord(CompareType))]); end; end; @@ -6060,6 +6059,7 @@ procedure TBoldAttribute.SetContentToNull; begin if not ContentIsNull then begin + PreChange; {$IFDEF NoNilAttributeExceptions} FreeContent; {$ENDIF} @@ -6814,15 +6814,18 @@ function TBoldList.HasDuplicates: boolean; end; end; -procedure TBoldList.Remove(Item: TBoldElement); +procedure TBoldList.Remove(Item: TBoldElement; ARaiseIfNotFound: boolean); var I: Integer; begin + if not mutable then + MutableError('Remove'); EnsureContentsCurrent; I := IndexOf(Item); if I <> -1 then RemoveByIndex(I) else + if ARaiseIfNotFound then raise EBold.CreateFmt('%s.Remove: Item not in list', [ClassName]); end; @@ -7838,13 +7841,16 @@ function TBoldObjectListLocatorEnumerator.GetCurrent: TBoldObjectLocator; { TBoldObjectList } -constructor TBoldObjectList.CreateTypedList(ObjectClass: TBoldObjectClass); +constructor TBoldObjectList.CreateTypedList(ObjectClass: TBoldObjectClass; ABoldSystem: TBoldSystem); var aSystem: TBoldSystem; ClassTypeInfo: TBoldClassTypeInfo; begin - inherited CreateWithOwner(nil); - aSystem := TBoldSystem.DefaultSystem; + inherited CreateWithOwner(ABoldSystem); + if Assigned(ABoldSystem) then + aSystem := ABoldSystem + else + aSystem := TBoldSystem.DefaultSystem; if not assigned(aSystem) then raise EBold.CreateFmt('%s.CreateTypedList: Can not find system', [classname]); ClassTypeInfo := aSystem.BoldSystemTypeInfo.TopSortedClasses.ItemsByObjectClass[ObjectClass]; @@ -7853,12 +7859,15 @@ constructor TBoldObjectList.CreateTypedList(ObjectClass: TBoldObjectClass); InitializeNonObjectOwned(ClassTypeInfo.ListTypeInfo); end; -constructor TBoldObjectList.CreateRootClassList; +constructor TBoldObjectList.CreateRootClassList(ABoldSystem: TBoldSystem); var aSystem: TBoldSystem; ClassTypeInfo: TBoldClassTypeInfo; begin - aSystem := TBoldSystem.DefaultSystem; + if Assigned(ABoldSystem) then + aSystem := ABoldSystem + else + aSystem := TBoldSystem.DefaultSystem; if not assigned(aSystem) then raise EBold.CreateFmt('%s.CreateRootClassList: Can not find system', [classname]); ClassTypeInfo := aSystem.BoldSystemTypeInfo.TopSortedClasses[0]; From ba862255af7e970ace07274705700bbd68bbe722 Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Sat, 22 May 2021 18:49:30 +0300 Subject: [PATCH 057/112] New TBoldSubscribableNonRefCountedObject. SubscribableObject is now TObject, since it can be anything. Added few debug asserts. Reduced beMaxSmallUser by 1, needs a test case. --- .../Common/Subscription/BoldSubscription.pas | 158 ++++++++++++++++-- 1 file changed, 141 insertions(+), 17 deletions(-) diff --git a/Source/Common/Subscription/BoldSubscription.pas b/Source/Common/Subscription/BoldSubscription.pas index 71704cf..0413be5 100644 --- a/Source/Common/Subscription/BoldSubscription.pas +++ b/Source/Common/Subscription/BoldSubscription.pas @@ -13,7 +13,8 @@ interface beMinSmallReserved = 0; beMaxSmallReserved = 27; beMinSmallUser = 28; - beMaxSmallUser = 30; + beMaxSmallUser = 29; + beBigEventFlag = 1 shl 30; beMaxEvent = 32767; beMinUser = 4096; beMaxUser = beMaxEvent; @@ -100,8 +101,6 @@ interface bqMayCommit = bqMinQuery + 4; {$ENDIF} bqMaxSubscription = bqMinQuery + 6; - const - beBigEventFlag = 1 shl 30; {$IFDEF BoldSystemBroadcastMemberEvents} beBroadcastMemberEvents = beValueEvents + [beCompleteModify] + beDirtyListEvents; @@ -184,7 +183,7 @@ TBoldPublisher = class(TBoldMemoryManagedObject) fSubscriptionArray: TBoldSubscriptionArray; fSubscriptionCount: integer; fPublisherFlags: TBoldPublisherFlags; - fSubscribableObject: TBoldSubscribableObject; + fSubscribableObject: TObject; fHoleCount: Integer; function GetHasSubscribers: Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure EnsureFreeSpace; {$IFDEF BOLD_INLINE} inline; {$ENDIF} @@ -222,7 +221,7 @@ TBoldPublisher = class(TBoldMemoryManagedObject) function HasMatchingSubscription(Subscriber: TBoldSubscriber): boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} procedure CancelSubscriptionTo(Subscriber: TBoldSubscriber); property HasSubscribers: Boolean read GetHasSubscribers; - property SubscribableObject : TBoldSubscribableObject read fSubscribableObject write fSubscribableObject; + property SubscribableObject : TObject read fSubscribableObject write fSubscribableObject; property SubscriptionCount: integer read fSubscriptionCount; property ContextString: string read GetContextString; property SubscriptionsAsText: string read GetSubscriptionsAsText; @@ -301,7 +300,7 @@ TBoldExtendedPassthroughSubscriber = class(TBoldPassthroughSubscriber) {---TBoldSubscribableObject---} TBoldSubscribableObject = class(TBoldFlaggedObject) - strict private + strict private fPublisher: TBoldPublisher; function GetHasSubscribers: Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} function GetPublisher: TBoldPublisher; {$IFDEF BOLD_INLINE} inline; {$ENDIF} @@ -377,7 +376,31 @@ TBoldSubscribablePersistent = class(TPersistent) property HasSubscribers: Boolean read GetHasSubscribers; property SubscriptionsAsText: string read GetSubscriptionsAsText; end; - + + TBoldSubscribableNonRefCountedObject = class(TBoldNonRefCountedObject) + strict private + fPublisher: TBoldPublisher; + function GetPublisher: TBoldPublisher; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetSubscriptionsAsText: string; + strict protected + function GetHasSubscribers: Boolean; virtual; + property Publisher: TBoldPublisher read GetPublisher; + procedure FreePublisher; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + public + destructor Destroy; override; + procedure AddSmallSubscription(Subscriber: TBoldSubscriber; + Events: TBoldSmallEventSet; RequestedEvent: TBoldRequestedEvent = beDefaultRequestedEvent); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure AddSubscription(Subscriber: TBoldSubscriber; + OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent = beDefaultRequestedEvent); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure SendEvent(Originator: TObject; OriginalEvent: TBoldEvent); {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure SendExtendedEvent(Originator: TObject; OriginalEvent: TBoldEvent; const Args: array of const); + {$IFNDEF BOLD_NO_QUERIES} + function SendQuery(Originator: TObject; OriginalEvent: TBoldEvent; const Args: array of const; Subscriber: TBoldSubscriber): Boolean; + {$ENDIF} + property HasSubscribers: Boolean read GetHasSubscribers; + property SubscriptionsAsText: string read GetSubscriptionsAsText; + end; + procedure BoldAddEventToPostNotifyQueue(Event: TNotifyEvent; Sender: TObject; Receiver: TObject); function BoldEventToString(aEvent: integer): string; @@ -520,7 +543,10 @@ procedure TBoldSubscription.ExtendEvents(Events: TBoldSmallEventSet); begin if (MatchCondition and beBigEventFlag) <> 0 then raise EBoldInternal.Create('TBoldSubscription.ExtendEvents called for big event'); - MatchCondition := Integer(TBoldSmallEventSet(MatchCondition) + Events); +{$IFDEF DEBUG} + if Integer(TBoldSmallEventSet(MatchCondition) + Events) <> MatchCondition then +{$ENDIF} + MatchCondition := Integer(TBoldSmallEventSet(MatchCondition) + Events); end; procedure TBoldSubscriber.ClearEntry(Index: integer); @@ -743,6 +769,9 @@ procedure TBoldPublisher.AddSmallSubscription(Subscriber: TBoldSubscriber; fSubscriptionArray[fSubscriptionCount].IndexInSubscriber := Subscriber.SubscriptionCount; fSubscriptionArray[fSubscriptionCount].RequestedEvent := RequestedEvent; fSubscriptionArray[fSubscriptionCount].MatchCondition := Integer(Events); +{$IFDEF DEBUG} + Assert(fSubscriptionArray[fSubscriptionCount].IsSmallEventSubscription); +{$ENDIF} Subscriber.AddToSubscriptions(self, fSubscriptionCount); Inc(fSubscriptionCount); end; @@ -787,6 +816,9 @@ procedure TBoldPublisher.AddSubscription(Subscriber: TBoldSubscriber; fSubscriptionArray[fSubscriptionCount].IndexInSubscriber := Subscriber.SubscriptionCount; fSubscriptionArray[fSubscriptionCount].RequestedEvent := RequestedEvent; fSubscriptionArray[fSubscriptionCount].MatchCondition := OriginalEvent or beBigEventFlag; +{$IFDEF DEBUG} + Assert(fSubscriptionArray[fSubscriptionCount].IsMatchingEvent(OriginalEvent)); +{$ENDIF} Subscriber.AddToSubscriptions(self, fSubscriptionCount); Inc(fSubscriptionCount); end; @@ -1024,9 +1056,12 @@ function TBoldSubscribableObject.GetHasSubscribers: Boolean; function TBoldSubscribableComponent.GetPublisher: TBoldPublisher; begin - if not assigned(fPublisher) then + if not Assigned(fPublisher) then + begin fPublisher := TBoldPublisher.Create; - result := fPublisher; + fPublisher.SubscribableObject := self; + end; + Result := fPublisher end; function TBoldSubscribableComponent.GetSubscriptionsAsText: string; @@ -1083,9 +1118,12 @@ function TBoldSubscribableComponent.SendQuery(Originator: TObject; OriginalEvent function TBoldSubscribablePersistent.GetPublisher: TBoldPublisher; begin - if not assigned(fPublisher) then + if not Assigned(fPublisher) then + begin fPublisher := TBoldPublisher.Create; - result := fPublisher; + fPublisher.SubscribableObject := self; + end; + Result := fPublisher end; function TBoldSubscribablePersistent.GetSubscriptionsAsText: string; @@ -1179,15 +1217,24 @@ function TBoldSubscriber.GetHandlesExtendedEvents: Boolean; function TBoldSubscriber.GetSubscriptionsAsText: string; var i,j: integer; + SubscribableObject: TObject; begin result := ''; j := 0; for I := 0 to Length(fSubscriptionArray) - 1 do - if Assigned(fSubscriptionArray[i].Publisher) and Assigned(fSubscriptionArray[i].Publisher.SubscribableObject) then - begin - result := result + IntToStr(j) + ':' + fSubscriptionArray[i].Publisher.SubscribableObject.ContextString + #13#10; - inc(j); - end; + if Assigned(fSubscriptionArray[i].Publisher) and Assigned(fSubscriptionArray[i].Publisher.SubscribableObject) then + begin + SubscribableObject := fSubscriptionArray[i].Publisher.SubscribableObject; + if fSubscriptionArray[i].Publisher.SubscribableObject is TBoldMemoryManagedObject + then + result := result + IntToStr(j) + ':' + TBoldMemoryManagedObject(fSubscriptionArray[i].Publisher.SubscribableObject).DebugInfo + #13#10 + else + if fSubscriptionArray[i].Publisher.SubscribableObject is TComponent then + result := result + IntToStr(j) + ':' + TComponent(fSubscriptionArray[i].Publisher.SubscribableObject).Name + #13#10 + else + result := result + IntToStr(j) + ':' + fSubscriptionArray[i].Publisher.SubscribableObject.ClassName + #13#10; + inc(j); + end; end; function TBoldSubscriber.HasMatchingSubscription( @@ -1306,6 +1353,83 @@ procedure InitDebugMethods; TBoldSubscribableComponent.Create(nil).SubscriptionsAsText; end; +{ TBoldSubscribableNonRefCountedObject } + +procedure TBoldSubscribableNonRefCountedObject.AddSmallSubscription( + Subscriber: TBoldSubscriber; Events: TBoldSmallEventSet; + RequestedEvent: TBoldRequestedEvent); +begin + Publisher.AddSmallSubscription(Subscriber, Events, RequestedEvent); +end; + +procedure TBoldSubscribableNonRefCountedObject.AddSubscription( + Subscriber: TBoldSubscriber; OriginalEvent: TBoldEvent; + RequestedEvent: TBoldRequestedEvent); +begin + Publisher.AddSubscription(Subscriber, OriginalEvent, RequestedEvent); +end; + +destructor TBoldSubscribableNonRefCountedObject.Destroy; +begin + FreePublisher; + inherited; +end; + +procedure TBoldSubscribableNonRefCountedObject.FreePublisher; +begin + if Assigned(fPublisher) then + begin + fPublisher.NotifySubscribersAndClearSubscriptions(Self); + FreeAndNil(fPublisher); + end; +end; + +function TBoldSubscribableNonRefCountedObject.GetHasSubscribers: Boolean; +begin + result := assigned(fPublisher) and Publisher.HasSubscribers; +end; + +function TBoldSubscribableNonRefCountedObject.GetPublisher: TBoldPublisher; +begin + if not Assigned(fPublisher) then + begin + fPublisher := TBoldPublisher.Create; + fPublisher.SubscribableObject := self; + end; + Result := fPublisher +end; + +function TBoldSubscribableNonRefCountedObject.GetSubscriptionsAsText: string; +begin + result := Publisher.SubscriptionsAsText; +end; + +procedure TBoldSubscribableNonRefCountedObject.SendEvent(Originator: TObject; + OriginalEvent: TBoldEvent); +begin + if Assigned(fPublisher) then + fPublisher.SendExtendedEvent(Originator, OriginalEvent, []); +end; + +procedure TBoldSubscribableNonRefCountedObject.SendExtendedEvent( + Originator: TObject; OriginalEvent: TBoldEvent; const Args: array of const); +begin + if Assigned(fPublisher) then + fPublisher.SendExtendedEvent(self, OriginalEvent, Args); +end; + +{$IFNDEF BOLD_NO_QUERIES} +function TBoldSubscribableNonRefCountedObject.SendQuery(Originator: TObject; + OriginalEvent: TBoldEvent; const Args: array of const; + Subscriber: TBoldSubscriber): Boolean; +begin + if Assigned(Originator) then + result := not Assigned(fPublisher) or fPublisher.SendQuery(Originator, OriginalEvent, Args, Subscriber) + else + result := not Assigned(fPublisher) or fPublisher.SendQuery(self, OriginalEvent, Args, Subscriber); +end; +{$ENDIF} + initialization G_PostNotifyQueue := TboldEventQueue.Create; InitDebugMethods; From 422b60ae60be46c93ab674ac32ba8b467e112ff6 Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Sat, 22 May 2021 19:27:28 +0300 Subject: [PATCH 058/112] UndoHandler is now subscribable and sends events. UndoBlocks now have timestamp and content properties. New convenience property CurrentUndoBlockHasChanges. Now merges undo blocks after updatedb. Default block name is now 'Undo' --- .../Interfaces/BoldUndoInterfaces.pas | 20 ++- Source/ObjectSpace/Undo/BoldUndoHandler.pas | 118 +++++++++++++----- 2 files changed, 103 insertions(+), 35 deletions(-) diff --git a/Source/ObjectSpace/Interfaces/BoldUndoInterfaces.pas b/Source/ObjectSpace/Interfaces/BoldUndoInterfaces.pas index 573d1c2..0409858 100644 --- a/Source/ObjectSpace/Interfaces/BoldUndoInterfaces.pas +++ b/Source/ObjectSpace/Interfaces/BoldUndoInterfaces.pas @@ -8,22 +8,33 @@ interface uses BoldValueSpaceInterfaces; +const +// from BoldSubscription + beUndoBlock = 60; + beRedoBlock = 61; + beUndoSetCheckpoint = 62; + beUndoChanged = 63; + type { forward declarations } IBoldUndoBlock = interface; IBoldUndoList = interface; IBoldUndoHandler = interface; - TBoldUndoState = (busNormal, busUndoing, busRedoing); + TBoldUndoState = (busNormal, busUndoing, busRedoing); IBoldUndoBlock = interface ['{F56612C3-7D33-4D60-9737-71ECE8E54D56}'] function GetName: string; function GetValueSpace: IBoldValueSpace; function GetContainsChanges: Boolean; + function GetContent: String; + function GetCreated: TDateTime; property Name: string read GetName; property ValueSpace: IBoldValueSpace read GetValueSpace; property ContainsChanges: Boolean read GetContainsChanges; + property Content: String read GetContent; + property Created: TDateTime read GetCreated; end; IBoldUndoList = interface @@ -63,16 +74,13 @@ interface procedure SetNamedCheckPoint(const CheckPointName: string); procedure SetCheckPoint; procedure ClearAllUndoBlocks; + function GetCurrentUndoBlockHasChanges: boolean; property UndoList: IBoldUndoList read GetUndoList; property RedoList: IBoldUndoList read GetRedoList; property Enabled: Boolean read GetEnabled write SetEnabled; + property CurrentUndoBlockHasChanges: boolean read GetCurrentUndoBlockHasChanges; end; - implementation -uses - BoldRev; - -initialization end. diff --git a/Source/ObjectSpace/Undo/BoldUndoHandler.pas b/Source/ObjectSpace/Undo/BoldUndoHandler.pas index 9cca03b..2202514 100644 --- a/Source/ObjectSpace/Undo/BoldUndoHandler.pas +++ b/Source/ObjectSpace/Undo/BoldUndoHandler.pas @@ -28,6 +28,7 @@ TBoldUndoBlock = class(TBoldNonRefCountedObject, IBoldUndoBlock) FName: string; FValueSpace: TBoldFreeStandingValueSpace; FContainsChanges: Boolean; + FCreated: TDateTime; procedure GetLinksToObject(const System: TBoldSystem; const ObjectId: TBoldObjectId; const OwnIndexInLinkClass: integer; const SingleLinkClassTypeInfo: TBoldClassTypeInfo; SingleLinkIds: TBoldObjectIdList); procedure AllIdsInClass(const System: TBoldSystem; const ClassTypeInfo: TBoldClassTypeInfo; IdList: TBoldObjectIdList); @@ -36,6 +37,8 @@ TBoldUndoBlock = class(TBoldNonRefCountedObject, IBoldUndoBlock) function GetName: string; {$IFDEF BOLD_INLINE} inline; {$ENDIF} function GetValueSpace: IBoldValueSpace; {$IFDEF BOLD_INLINE} inline; {$ENDIF} function GetContainsChanges: Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetContent: String; + function GetCreated: TDateTime; {$IFDEF BOLD_INLINE} inline; {$ENDIF} protected function HasObjectContentsForAnyObjectInList(const ObjectList: TBoldObjectList): Boolean; procedure HandleMember(const ObjectContents: IBoldObjectContents; MemberIndex: integer; const MemberValue: IBoldValue); @@ -53,6 +56,8 @@ TBoldUndoBlock = class(TBoldNonRefCountedObject, IBoldUndoBlock) property FSValueSpace: TBoldFreeStandingValueSpace read GetFSValueSpace write setFSVAlueSpace; property ValueSpace: IBoldValueSpace read GetValueSpace; property ContainsChanges: Boolean read GetContainsChanges; + property Created: TDateTime read GetCreated; + property Content: String read GetContent; end; TBoldUndoBlockList = class(TBoldNonRefCountedObject, IBoldUndoList) @@ -76,6 +81,7 @@ TBoldUndoBlockList = class(TBoldNonRefCountedObject, IBoldUndoList) function AssertedIndexOf(const BlockName: string): integer; procedure InternalRemoveBlock(const BlockName: string); overload; procedure InternalRemoveBlock(Block: TBoldUndoBlock); overload; + function GetIsEmpty: boolean; public procedure ApplytranslationList(IdTranslationList: TBoldIdTranslationList); constructor Create; @@ -97,6 +103,7 @@ TBoldUndoBlockList = class(TBoldNonRefCountedObject, IBoldUndoList) property Count: integer read GetCount; property CurrentBlock: TBoldUndoBlock read GetCurrentBlock; property ContainsChanges: Boolean read GetContainsChanges; + property IsEmpty: boolean read GetIsEmpty; end; TBoldUndoHandler = class(TBoldAbstractUndoHandler, IBoldUndoHandler) @@ -118,7 +125,10 @@ TBoldUndoHandler = class(TBoldAbstractUndoHandler, IBoldUndoHandler) function CanUndoBlock(const BlockName: string): Boolean; function CanRedoBlock(const BlockName: string):Boolean; function GetEnabled: Boolean; {$IFDEF BOLD_INLINE} inline; {$ENDIF} - procedure SetEnabled(value: Boolean); + procedure SetEnabled(value: Boolean); + function GetCurrentUndoBlock: TBoldUndoBlock; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetIsEmpty: boolean; + function GetCurrentUndoBlockHasChanges: boolean; public constructor Create(System: TBoldSystem); override; destructor Destroy; override; @@ -138,6 +148,7 @@ TBoldUndoHandler = class(TBoldAbstractUndoHandler, IBoldUndoHandler) property RedoBlocks: TBoldUndoBlockList read fRedoBlocks; property UndoState: TBoldUndoState read fUndoState write fUndoState; property Enabled: Boolean read GetEnabled write SetEnabled; + property CurrentUndoBlock: TBoldUndoBlock read GetCurrentUndoBlock; end; implementation @@ -149,7 +160,7 @@ implementation BoldDomainElement; const - cUnNamedBlockName = 'UnNamed'; + cUnNamedBlockName = 'Undo'; { TBoldUndoBlock } @@ -157,8 +168,9 @@ constructor TBoldUndoBlock.CreateNamedBlock(const BlockName: string; const FSVAl begin inherited Create; FContainsChanges := false; - FName := BlockName; FValueSpace := FSVAlueSpace; + FCreated := now; + FName := {FormatDateTime('hh:nn:ss', FCreated) + ' - ' + }BlockName; end; function TBoldUndoBlock.GetFSValueSpace: TBoldFreeStandingValueSpace; @@ -396,6 +408,29 @@ function TBoldUndoBlock.GetContainsChanges: Boolean; result := fContainsChanges; end; +function TBoldUndoBlock.GetContent: String; +var + i: integer; + List: TBoldObjectList; +begin + result := ''; + if FContainsChanges then + begin + List := TBoldObjectList.Create; + try + AddObjectsToList(TBoldSystem.DefaultSystem, List); + result := List.AsDebugCommaText(); + finally + List.free; + end; + end; +end; + +function TBoldUndoBlock.GetCreated: TDateTime; +begin + result := fCreated; +end; + procedure TBoldUndoBlock.ApplytranslationList( IdTranslationList: TBoldIdTranslationList); begin @@ -425,7 +460,7 @@ procedure TBoldUndoHandler.HandleMember(const ObjectContents: IBoldObjectContent if Enabled and (UndoState = busNormal) then begin RedoBlocks.Clear; - UndoBlocks.CurrentBlock.HandleMember(ObjectContents, MemberIndex, MemberValue); + CurrentUndoBlock.HandleMember(ObjectContents, MemberIndex, MemberValue); end; end; @@ -485,21 +520,8 @@ procedure TBoldUndoHandler.PrepareUpdate(const ObjectList: TBoldObjectList); else inc(i); end; -{$IFDEF MergeEmptyBlocks} - UndoBlocks.MergeAll; -{$ENDIF} -end; - -procedure TBoldUndoHandler.SetNamedCheckPoint(const CheckPointName: string); -begin - if Assigned(UndoBlocks.GetBlockByName(CheckPointName)) or Assigned(RedoBlocks.GetBlockByName(CheckPointName)) then - raise EBold.CreateFmt('%s.SetCheckPoint: An Undo/Redo block named %s is already defined', [Classname, CheckPointName]) -{$IFDEF MergeEmptyBlocks} - else if not (UndoBlocks.CurrentBlock.ContainsChanges) then - UndoBlocks.RenameBlock(UndoBlocks.CurrentBlock.BlockName, CheckPointName) -{$ENDIF} - else - UndoBlocks.AddBlock(CheckPointName); + UndoBlocks.MergeAll; // this was not original behavior + SendExtendedEvent(self, beUndoChanged, []); end; procedure TBoldUndoHandler.UndoBlock(const BlockName: string); @@ -509,6 +531,7 @@ procedure TBoldUndoHandler.UndoBlock(const BlockName: string); UndoState := busUndoing; try DoUndoInTransaction(BlockName, UndoBlocks, RedoBlocks); + SendExtendedEvent(self, beUndoBlock, [BlockName]); finally UndoState := busNormal; end; @@ -522,6 +545,7 @@ procedure TBoldUndoHandler.RedoBlock(const BlockName: string); UndoState := busRedoing; try DoUndoInTransaction(BlockName, RedoBlocks, UndoBlocks); + SendExtendedEvent(self, beRedoBlock, [BlockName]); finally UndoState := busNormal; end; @@ -536,7 +560,7 @@ procedure TBoldUndoHandler.RedoLatest; procedure TBoldUndoHandler.UndoLatest; begin if (UndoBlocks.Count > 0) then - UndoBlock(UndoBlocks.CurrentBlock.BlockName); + UndoBlock(CurrentUndoBlock.BlockName); end; procedure TBoldUndoHandler.HandleObject(const Obj: IBoldObjectContents; RegardAsExisting: Boolean); @@ -544,7 +568,7 @@ procedure TBoldUndoHandler.HandleObject(const Obj: IBoldObjectContents; RegardAs if Enabled and (UndoState = busNormal) then begin RedoBlocks.Clear; - UndoBlocks.CurrentBlock.HandleObject(Obj, RegardAsExisting); + CurrentUndoBlock.HandleObject(Obj, RegardAsExisting); end; end; procedure TBoldUndoHandler.DoUndo(UnDoValueSpace: TBoldFreeStandingValueSpace; @@ -853,11 +877,30 @@ function TBoldUndoHandler.CanUndoBlock(const BlockName: string): Boolean; Result := UnDoBlocks.CanMoveToTop(UndoBlocks.AssertedIndexOf(BlockName)); end; +function TBoldUndoHandler.GetCurrentUndoBlock: TBoldUndoBlock; +begin + if UndoBlocks.IsEmpty then + SetCheckPoint; + result := UndoBlocks.CurrentBlock; +end; + +function TBoldUndoHandler.GetCurrentUndoBlockHasChanges: boolean; +begin + result := false; + if not UndoBlocks.IsEmpty then + result := GetCurrentUndoBlock.ContainsChanges; +end; + function TBoldUndoHandler.GetEnabled: Boolean; begin result := fEnabled; end; +function TBoldUndoHandler.GetIsEmpty: boolean; +begin + result := UndoBlocks.Count = 0; +end; + function TBoldUndoHandler.GetRedoList: IBoldUndoList; begin Result := FRedoBlocks; @@ -881,7 +924,6 @@ function TBoldUndoHandler.GetUniqueBlockName(const SuggestedName: string): strin end; end; - {function TBoldUndoHandler.GetNonUndoableBlock: IBoldUndoBlock; begin Result := FNonUndoableBlock; @@ -895,15 +937,28 @@ procedure TBoldUndoHandler.ApplytranslationList( RedoBlocks.ApplytranslationList(IdTranslationList); end; +procedure TBoldUndoHandler.SetNamedCheckPoint(const CheckPointName: string); +begin + if Assigned(UndoBlocks.GetBlockByName(CheckPointName)) or Assigned(RedoBlocks.GetBlockByName(CheckPointName)) then + raise EBold.CreateFmt('%s.SetCheckPoint: An Undo/Redo block named %s is already defined', [Classname, CheckPointName]) + else if (not UndoBlocks.IsEmpty and not UndoBlocks.CurrentBlock.ContainsChanges) then + UndoBlocks.RenameBlock(CurrentUndoBlock.BlockName, CheckPointName) // reuse/rename if current block is empty + else + UndoBlocks.AddBlock(CheckPointName); + SendExtendedEvent(self, beUndoSetCheckpoint, [CheckPointName]); +end; + procedure TBoldUndoHandler.SetCheckPoint; begin - SetNamedCheckPoint(GetUniqueBlockName(cUnNamedBlockName)); + if UndoBlocks.IsEmpty or UndoBlocks.CurrentBlock.ContainsChanges then + SetNamedCheckPoint(GetUniqueBlockName(cUnNamedBlockName)); end; procedure TBoldUndoHandler.ClearAllUndoBlocks; begin FUndoBlocks.Clear; FRedoBlocks.Clear; + SendExtendedEvent(self, beUndoChanged, []); end; procedure TBoldUndoHandler.SetEnabled(value: Boolean); @@ -911,6 +966,7 @@ procedure TBoldUndoHandler.SetEnabled(value: Boolean); if fEnabled <> value then begin fEnabled := value; + SendExtendedEvent(self, beUndoChanged, []) end; end; @@ -1021,7 +1077,7 @@ procedure TBoldUndoBlockList.RenameBlock(const OldName, NewName: string); aBlock: TBoldUndoBlock; begin if Assigned(GetBlockByName(NewName)) then - raise EBold.Create('Can''t rename block'); + raise EBold.CreateFmt('Can''t rename block, %s already exists.', [NewName]); aBlock := AssertedBlockByName[OldName]; FList.Strings[IndexOf(OldName)] := NewName; aBlock.FName := NewName; @@ -1069,10 +1125,11 @@ function TBoldUndoBlockList.CanMergeBlock(CurIndex, function TBoldUndoBlockList.GetCurrentBlock: TBoldUndoBlock; begin Result := nil; - if (Count = 0) then +{ if (Count = 0) then Result := AddBlock(cUnNamedBlockName) - else if Count > 0 then - Result := FList.Objects[Count - 1] as TBoldUndoBlock; + else} + if Count > 0 then + Result := FList.Objects[Count - 1] as TBoldUndoBlock; end; function TBoldUndoBlockList.GetAssertedBlockByName( @@ -1101,6 +1158,11 @@ function TBoldUndoBlockList.GetItemByName(const Name: string): IBoldUndoBlock; result := BlockByName[Name] as IBoldUndoBlock; end; +function TBoldUndoBlockList.GetIsEmpty: boolean; +begin + result := Count = 0; +end; + function TBoldUndoBlockList.GetItem(Index: integer): IBoldUndoBlock; begin Result := BlockByIndex[Index] as IBoldUndoBlock ; @@ -1187,7 +1249,5 @@ function TBoldUndoBlockList.RemoveBlock(const BlockName: string): Boolean; InternalRemoveBlock(BlockName); end; -initialization - end. From 52ce751545a9d04c8ef15cac84936bcd48468e21 Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Sat, 22 May 2021 19:33:08 +0300 Subject: [PATCH 059/112] Updated BoldEventToString with new events --- .../Common/Subscription/BoldSubscription.pas | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/Source/Common/Subscription/BoldSubscription.pas b/Source/Common/Subscription/BoldSubscription.pas index 0413be5..2f739f7 100644 --- a/Source/Common/Subscription/BoldSubscription.pas +++ b/Source/Common/Subscription/BoldSubscription.pas @@ -91,6 +91,12 @@ interface boeMemberChanged = 57; beOssEvents = [boeClassChanged, boeEmbeddedStateOfObjectChanged, boeObjectCreated, boeObjectDeleted, boeNonEmbeddedStateOfObjectChanged, boeMemberChanged]; + // Undo Events + beUndoBlock = 60; + beRedoBlock = 61; + beUndoSetCheckpoint = 62; + beUndoChanged = 63; + bePrepareModify = 38; beCompleteModify = 39; bePrepareDelete = 41; @@ -439,6 +445,15 @@ function BoldEventToString(aEvent: integer): string; bePrepareDelete: result := 'bePrepareDelete'; breReSubscribe: result := 'breReSubscribe'; beServerSubscriberRemoved: result := 'beServerSubscriberRemoved'; + // Begin/EndUpdate, not yet in use + beBeginUpdate: result := 'beBeginUpdate'; + beEndUpdate: result := 'beEndUpdate'; + //DirtyList events + beObjectBecomingClean: result := 'beObjectBecomingClean'; + beObjectBecomingDirty: result := 'beObjectBecomingDirty'; + beMemberBecomingClean: result := 'beMemberBecomingClean'; + beMemberBecomingDirty: result := 'beMemberBecomingDirty'; + //Persistence events bpeStartFetch: result := 'bpeStartFetch'; bpeEndFetch: result := 'bpeEndFetch'; bpeStartUpdate: result := 'bpeStartUpdate'; @@ -453,6 +468,19 @@ function BoldEventToString(aEvent: integer): string; bpeFetchId: result := 'bpeFetchId'; bpeProgressStart: result := 'bpeProgressStart'; bpeProgressEnd: result := 'bpeProgressEnd'; + // OSS events + boeClassChanged: result := 'boeClassChanged'; + boeEmbeddedStateOfObjectChanged: result := 'boeEmbeddedStateOfObjectChanged'; + boeObjectCreated: result := 'boeObjectCreated'; + boeObjectDeleted: result := 'boeObjectDeleted'; + boeNonEmbeddedStateOfObjectChanged: result := 'boeNonEmbeddedStateOfObjectChanged'; + boeMemberChanged: result := 'boeMemberChanged'; + // Undo events + beUndoBlock: result := 'beUndoBlock'; + beRedoBlock: result := 'beRedoBlock'; + beUndoSetCheckpoint: result := 'beUndoSetCheckpoint'; + beUndoChanged: result := 'beUndoChanged'; + {$IFNDEF BOLD_NO_QUERIES} bqMayUpdate: result := 'bqMayUpdate'; bqMayModify: result := 'bqMayModify'; From ae15b9523e55dad869f4afa1ac0eea73ceb5c1a8 Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Sat, 22 May 2021 19:39:26 +0300 Subject: [PATCH 060/112] Updated Buildings demo --- examples/Delphi/Compound/Building/BldOwn.dpr | 4 +- examples/Delphi/Compound/Building/BldOwn.res | Bin 1992 -> 3308 bytes examples/Delphi/Compound/Building/Datamod.dfm | 242 +++++++++++++----- examples/Delphi/Compound/Building/Datamod.pas | 14 +- .../Delphi/Compound/Building/Mainform.dfm | 168 ++++++++---- .../Delphi/Compound/Building/Mainform.pas | 104 +++++++- .../Compound/Building/PersonAutoFormUnit.dfm | 107 +++++++- .../Compound/Building/PersonAutoFormUnit.pas | 13 +- 8 files changed, 513 insertions(+), 139 deletions(-) diff --git a/examples/Delphi/Compound/Building/BldOwn.dpr b/examples/Delphi/Compound/Building/BldOwn.dpr index a1ee31f..7be267b 100644 --- a/examples/Delphi/Compound/Building/BldOwn.dpr +++ b/examples/Delphi/Compound/Building/BldOwn.dpr @@ -7,8 +7,8 @@ program Bldown; uses Forms, - datamod in 'Datamod.pas' {DataModule1: TDataModule}, - mainform in 'Mainform.pas' {allform}, + Datamod in 'Datamod.pas' {DataModule1: TDataModule}, + Mainform in 'Mainform.pas' {allform}, PersonAutoFormUnit in 'PersonAutoFormUnit.pas' {PersonAutoForm}; {$R *.RES} diff --git a/examples/Delphi/Compound/Building/BldOwn.res b/examples/Delphi/Compound/Building/BldOwn.res index 6d50bf51e9294575accc4aa04858ab4fadb5e24d..5f4831f395c4f01207f47d40ea653ee7ed0417bf 100644 GIT binary patch literal 3308 zcmd^CO>f&q5M4C}Ql&^?0R`HdS)zxc07X(HWyz47x=vE4jhi4=-D9yLmo`y;nWX%I zqKNYg0^gcbeo2A+m>zm732q&~>(6!E&x|k~UcCPRKXpW9UDERs#PrLP-Sg?n-PI zYY}uAt`kTyctF7>FcYj_ODxu4S%r()zzQ&d*vcbiTjBSN_6~^VSMFe~Qs-%pv4Y zpPli2e#(WswQ|N=FV6U{7)iO9qd$4wlJ-)L`3ua2Twn?PBWOwdGl6}^pYztU62Iiz zhh~K@{W*QYYkYA=e7{xNpYl^V$F;_n^ZiQBpNnZrXbJf>4O#J@wvWJWpmY8q*&-YA zc{d`P^66JQW-Qc&sD=hnlx0~JqKX>igPWwPrB7zHwD^1-+&PLu<$z^*kihxebGi+u_3f>Z-Z2bE|KU8Ex?W^c zrl-+Bukqd>h*_Th3lg*YCdng~Z6$F~B-u`9&Ln`Vt?FeAF4^m#5-o;DM$Ka>i#?p~ zafMMY6dTo9&UR8C?g;8dP#nwfiVzpaDUtxJR!5yJ#x%m>R(Q?t=J>`C^(S zE@G5q8=1Qo6wEEAnbgqhuwA-mM0g$>87mxeUW{Ttsn7A6^hRcuDVQ^NnjvDdP-bj@ zilk@WqbxWGLbl6h8Ht>nN$(xOP^9t$cEG|}XcZ+C^Px)fQG9@yWb@4`$~4$;#eRpX zPs5zeMb&mepwAdC@(=VyUkCbZ%c8nb0x2qM5`@^x^)Wc7E{c6!xqYiSSWH2&&>VcK zY2!VnjP5EE7AA)Zic6F*%N6J<`7}+FtWf+UQ>r9Vb^<(p6itIyu&*?j_i$Soc|-MQ z)-g=ec2+ghvAddWxsFC1pJ|5C^B7~6XZgl2sxJL`8~W9&sV&E}dXqlY9Ip>*f8uF9 z*6}pjv2CN%as0kT1@&8QymvLTO*?+4$1KgUCVkDeZBv`jzN>lNzGqXLcA3?C7v{Ek zHMi+^SG(?NSL+$f)a;Jc*HEGpt!H_L-}MZSuD%PmXZSg&N155t^-QG0n literal 1992 zcmd^;O;1xn6o%hQ7rIeyB<@V_LK8G%Dl{e{@vDVE!dIlSB`Ao*Qrc1xH&T89VJB=@ z`y)*FF)rMhu4Lu-oSEKmp&E7N!fDUUoO{l^=Ub9u$hkmVPpvQK5_u0g887SYy_!vw z`nkl=BPgTrxy75Gua?ALtyVbLxk4=+9UUPsC+u+HU=MydMgRM9t{p{?tLI$q8&~I| z9OQPm9m6AZJG*UHcYDs{QLgQx!?ydt&C894wvQwK-pk<+;Z1H>roV-j$8Q^U+wHq( zH{b_*bu>Hp-k-f~m*88CTs;c!_uQW6*%N%v*E@2zZ){{*CjZT%EB@)~!+IWa?xLpj zSQDCtikjg}R(dXM8ZwIGUOyE!MH!7`)tR;4)GS@#Ygi-M0+)HsX@PxIPq|Ha3k%-f z7T2)mm8sn^J8RV*7Y8~mO*U76ur1zi# zKA1=2>cjgYI%}$F5&d^Wy$H8#pqlkKTi`X3jB_p_xkapVddtnYDtcvI0VlCr;_HT9 zczq-*LY$1^JFnI`dJf!iopMKUshwQ?sbH_*-NdXW7_RX4jcb)f>yj}4xEh{ymwydt`6{zx=I{huyN3t=9 z7xs()IAhXHtflRhv9#zjy2jbiYoblov@WAN)A7ZsY_TQzHZD}GJH|0GVwpZ2>!h#O zEO_f!d_%38sZ9M{oep##-%ewltyZ^Rzp8ueJGMb4?aeHG5xS*FZ!Dyu2=XWNk;PZ) znyXOL_Zq^t(BGCJ>kZ3lnVK5E0dKjhX*gBI0V-M00Npjj*F5Ji6)yPwF5MPmZ&{mA t#rH^p9P2r`wAoui%T~$n^S+)*wN9qe@@x|wDqqE$3YzJ8xsd&w{Q=rvOa%Y{ diff --git a/examples/Delphi/Compound/Building/Datamod.dfm b/examples/Delphi/Compound/Building/Datamod.dfm index 9b650db..5281177 100644 --- a/examples/Delphi/Compound/Building/Datamod.dfm +++ b/examples/Delphi/Compound/Building/Datamod.dfm @@ -7,7 +7,7 @@ object DataModule1: TDataModule1 Boldify.EnforceDefaultUMLCase = False Boldify.DefaultNavigableMultiplicity = '0..1' Boldify.DefaultNonNavigableMultiplicity = '0..*' - Left = 32 + Left = 56 Top = 8 Model = ( 'VERSION 19' @@ -344,60 +344,206 @@ object DataModule1: TDataModule1 OnMayModify = IsRichRendererMayModify OnSubscribe = IsRichRendererSubscribe OnGetAsCheckBoxState = IsRichRendererGetAsCheckBoxState - Left = 32 - Top = 96 + Left = 536 + Top = 16 end object IsRichFilter: TBoldFilter OnSubscribe = IsRichFilterSubscribe OnFilter = IsRichFilterFilter - Left = 32 - Top = 168 + Left = 464 + Top = 80 end object NameComparer: TBoldComparer OnSubscribe = NameComparerSubscribe OnCompare = NameComparerCompare - Left = 128 - Top = 168 + Left = 464 + Top = 16 end object NegativeRedRenderer: TBoldAsStringRenderer OnSetFont = NegativeRedRendererSetFont - Left = 248 - Top = 96 + Left = 536 + Top = 80 end object BoldSystemHandle1: TBoldSystemHandle IsDefault = True - AutoActivate = True SystemTypeInfoHandle = BoldSystemTypeInfoHandle1 Active = False PersistenceHandle = BoldPersistenceHandleDB1 - Left = 128 - Top = 8 + Left = 56 + Top = 64 end object BoldUMLRoseLink1: TBoldUMLRoseLink FileName = 'D:\bold\BfD\examples\Delphi\Compound\Building\Building.mdl' BoldModel = BoldModel1 - Left = 260 - Top = 164 + Left = 52 + Top = 188 end object BoldSystemTypeInfoHandle1: TBoldSystemTypeInfoHandle BoldModel = BoldModel1 - Left = 72 - Top = 248 + Left = 56 + Top = 128 end object BoldPlaceableAFP1: TBoldPlaceableAFP OnGetFormClass = BoldPlaceableAFP1GetFormClass OnRetrieveHandle = BoldPlaceableAFP1RetrieveHandle - Left = 248 - Top = 240 + Left = 520 + Top = 160 end object BoldPersistenceHandleDB1: TBoldPersistenceHandleDB BoldModel = BoldModel1 ClockLogGranularity = '0:0:0.0' - DatabaseAdapter = BoldDatabaseAdapterFireDAC1 - Left = 256 - Top = 24 + DatabaseAdapter = BoldDatabaseAdapterPostgres + Left = 224 + Top = 8 end - object BoldDatabaseAdapterFireDAC1: TBoldDatabaseAdapterFireDAC + object BoldDatabaseAdapterPostgres: TBoldDatabaseAdapterFireDAC + SQLDatabaseConfig.DefaultSystemMapper = '' + SQLDatabaseConfig.DefaultObjectMapper = '' + SQLDatabaseConfig.ColumnTypeForDate = 'DATE' + SQLDatabaseConfig.ColumnTypeForTime = 'TIME' + SQLDatabaseConfig.ColumnTypeForDateTime = 'TIMESTAMP' + SQLDatabaseConfig.ColumnTypeForBlob = 'BYTEA' + SQLDatabaseConfig.ColumnTypeForFloat = 'NUMERIC' + SQLDatabaseConfig.ColumnTypeForCurrency = 'NUMERIC' + SQLDatabaseConfig.ColumnTypeForString = 'VARCHAR(%d)' + SQLDatabaseConfig.ColumnTypeForUnicodeString = 'NVARCHAR(%d)' + SQLDatabaseConfig.ColumnTypeForText = 'VARCHAR(MAX)' + SQLDatabaseConfig.ColumnTypeForUnicodeText = 'NVARCHAR(MAX)' + SQLDatabaseConfig.ColumnTypeForInteger = 'INTEGER' + SQLDatabaseConfig.ColumnTypeForSmallInt = 'SMALLINT' + SQLDatabaseConfig.ColumnTypeForInt64 = 'BIGINT' + SQLDatabaseConfig.ColumnTypeForGUID = 'UUID' + SQLDatabaseConfig.CreateDatabaseTemplate = 'CREATE DATABASE %s' + SQLDatabaseConfig.DropColumnTemplate = 'ALTER TABLE DROP ' + SQLDatabaseConfig.DropTableTemplate = 'DROP TABLE ' + SQLDatabaseConfig.IndexInfoTemplate = + 'SELECT IND.NAME INDEXNAME, IND.IS_PRIMARY_KEY ISPRIMARY, IND.IS_' + + 'UNIQUE ISUNIQUE, COL.NAME COLUMNNAME FROM SYS.INDEXES IND INNER ' + + 'JOIN SYS.INDEX_COLUMNS IC ON IND.OBJECT_ID = IC.OBJECT_ID AND IN' + + 'D.INDEX_ID = IC.INDEX_ID INNER JOIN SYS.COLUMNS COL ON IC.OBJECT' + + '_ID = COL.OBJECT_ID AND IC.COLUMN_ID = COL.COLUMN_ID WHERE UPPER' + + '(OBJECT_NAME(IND.OBJECT_ID))=UPPER('#39''#39') ORDER BY INDEX' + + 'NAME, INDEX_COLUMN_ID' + SQLDatabaseConfig.DropIndexTemplate = 'DROP INDEX ' + SQLDatabaseConfig.EvolveDropsUnknownIndexes = True + SQLDatabaseConfig.MaxDbIdentifierLength = 63 + SQLDatabaseConfig.MaxIndexNameLength = 63 + SQLDatabaseConfig.BatchQuerySeparator = ';' + SQLDatabaseConfig.MultiRowInsertLimit = 1000 + SQLDatabaseConfig.SQLforNull = 'NULL' + SQLDatabaseConfig.SQLforNotNull = 'NOT NULL' + SQLDatabaseConfig.QuoteNonStringDefaultValues = False + SQLDatabaseConfig.SupportsConstraintsInCreateTable = True + SQLDatabaseConfig.SupportsStringDefaultValues = True + SQLDatabaseConfig.DBGenerationMode = dbgQuery + SQLDatabaseConfig.ReservedWords.Strings = ( + + 'ALL, ANALYSE, AND, ANY, ARRAY, AS, ASC, ASYMMETRIC, AUTHORIZATIO' + + 'N,' + + 'BETWEEN, BINARY, BOOLEAN, BOTH, CASE, CAST, CHAR, CHARACTER, CHE' + + 'CK,' + + 'CMIN, COALESCE, COLLATE, COLUMN, CONSTRAINT, CONVERT, CREATE, CR' + + 'OSS,' + 'CURRENT_DATE, CURRENT_ROLE, CURRENT_TIME, CURRENT_TIMESTAMP,' + 'CURRENT_USER, DEC, DECIMAL, DEFAULT, DEFERRABLE, SEC, ELSE, END,' + + 'EXCEPT, EXISTS, EXTRACT, FALSE, FLOAT, FOR, FOREIGN, FREEZE, FRO' + + 'M,' + + 'FULL, GRANT, GREATEST, GROUP, HAVING, ILIKE, IN, INITIALLY, INNE' + + 'R,' + + 'INOUT, INT, INTEGER, INTERSECT, INTERVAL, INTO, IS, ISNULL, JOIN' + + ',' + 'LEADING, LEAST, LEFT, LIKE, LIMIT, LOCALTIME, LOCALTIMESTAMP,' + 'NATIONAL, NATURAL, NCHAR, NEW, NONE, NOT, NOTNULL, NULL, NULLIF,' + + 'NUMERIC, OFF, OFFSET, OLD, ON, ONLY, OR, ORDER, OUT, OUTER, OVER' + + 'LAPS,' + 'OVERLAY, PLI, POSITION, PRECISION, PRIMARY, REAL, REFERENCES,' + 'RETURNING, RIGHT, ROW, SELECT, SESSION_USER, SETOF, SIMILAR,' + + 'SMALLINT, SOME, SUBSTRING, SYMMETRIC, TABLE, THEN, TIME, TIMESTA' + + 'MP,' + + 'TOP_LEVEL_COUNT, TRAILING, TREAT, TRIM, TRUE, UNION, UNIQUE, USE' + + 'R,' + 'USING, VALUES, VARCHAR, VERBOSE, WHEN, WHERE') + SQLDatabaseConfig.StoreEmptyStringsAsNULL = False + SQLDatabaseConfig.SystemTablePrefix = 'BOLD' + SQLDatabaseConfig.QuoteLeftBracketInLike = False + SQLDatabaseConfig.SqlScriptTerminator = ';' + SQLDatabaseConfig.SqlScriptCommentStart = '/* ' + SQLDatabaseConfig.SqlScriptCommentStop = ' */' + SQLDatabaseConfig.SqlScriptStartTransaction = 'START TRANSACTION' + SQLDatabaseConfig.SqlScriptCommitTransaction = 'COMMIT' + SQLDatabaseConfig.SqlScriptRollBackTransaction = 'ROLLBACK' + CustomIndexes = <> + Connection = FDConnectionPostgres + DatabaseEngine = dbePostgres + Left = 216 + Top = 208 + end + object FDConnectionSQLServer: TFDConnection + Params.Strings = ( + 'User_Name=sa' + 'Password=masterkey' + 'Server=DESKTOP-JJPVFK3' + 'OSAuthent=Yes' + 'ApplicationName=Enterprise/Architect/Ultimate' + 'Workstation=DESKTOP-JJPVFK3' + 'MARS=yes' + 'Database=Buildings' + 'DriverID=MSSQL') + TxOptions.Isolation = xiRepeatableRead + LoginPrompt = False + Left = 224 + Top = 128 + end + object BoldConstraintValidatorOnModify: TBoldConstraintValidator + StaticSystemHandle = BoldSystemHandle1 + Constraints = < + item + Context = 'Residential_Building' + Expression = 'residents->size <= capacity' + ErrorMessage = #39'Building capacity limit is '#39' + capacity.asString' + end> + ValidationMode = vmOnModify + Enabled = True + Left = 488 + Top = 320 + end + object BoldConstraintValidatorOnUpdate: TBoldConstraintValidator + StaticSystemHandle = BoldSystemHandle1 + Constraints = < + item + Context = 'Person' + Expression = + '(ownedBuildings->filterOnType(Residential_Building)->notEmpty'#13#10')' + + ' implies (home <> nil)'#13#10 + ErrorMessage = + 'name + '#39' can not be homeless while owning at least one non full ' + + 'residential building'#39 + end> + ValidationMode = vmPreUpdate + Enabled = True + Left = 488 + Top = 256 + end + object FDConnectionPostgres: TFDConnection + Params.Strings = ( + 'Password=masterkey' + 'Database=Buildings' + 'User_Name=postgres' + 'DriverID=PG') + TxOptions.Isolation = xiRepeatableRead + LoginPrompt = False + Left = 216 + Top = 256 + end + object BoldDatabaseAdapterSQLServer: TBoldDatabaseAdapterFireDAC SQLDatabaseConfig.DefaultSystemMapper = '' SQLDatabaseConfig.DefaultObjectMapper = '' SQLDatabaseConfig.IfTemplate = 'IF BEGIN END' @@ -519,55 +665,9 @@ object DataModule1: TDataModule1 SQLDatabaseConfig.SqlScriptCommitTransaction = 'COMMIT' SQLDatabaseConfig.SqlScriptRollBackTransaction = 'ROLLBACK' CustomIndexes = <> - Connection = FDConnection1 + Connection = FDConnectionPostgres DatabaseEngine = dbeSQLServer - Left = 384 - Top = 200 - end - object FDConnection1: TFDConnection - Params.Strings = ( - 'User_Name=sa' - 'Password=masterkey' - 'Server=DESKTOP-JJPVFK3' - 'OSAuthent=Yes' - 'ApplicationName=Enterprise/Architect/Ultimate' - 'Workstation=DESKTOP-JJPVFK3' - 'MARS=yes' - 'Database=Buildings' - 'DriverID=MSSQL') - TxOptions.Isolation = xiRepeatableRead - LoginPrompt = False - Left = 384 - Top = 256 - end - object BoldConstraintValidatorOnModify: TBoldConstraintValidator - StaticSystemHandle = BoldSystemHandle1 - Constraints = < - item - Context = 'Residential_Building' - Expression = 'residents->size <= capacity' - ErrorMessage = #39'Building capacity limit is '#39' + capacity.asString' - end> - ValidationMode = vmOnModify - Enabled = True - Left = 424 - Top = 56 - end - object BoldConstraintValidatorOnUpdate: TBoldConstraintValidator - StaticSystemHandle = BoldSystemHandle1 - Constraints = < - item - Context = 'Person' - Expression = - '(ownedBuildings->filterOnType(Residential_Building)->notEmpty'#13#10')' + - ' implies (home <> nil)'#13#10 - ErrorMessage = - 'name + '#39' can not be homeless while owning at least one non full ' + - 'residential building'#39 - end> - ValidationMode = vmPreUpdate - Enabled = True - Left = 424 - Top = 128 + Left = 224 + Top = 80 end end diff --git a/examples/Delphi/Compound/Building/Datamod.pas b/examples/Delphi/Compound/Building/Datamod.pas index fb387c2..019d7ab 100644 --- a/examples/Delphi/Compound/Building/Datamod.pas +++ b/examples/Delphi/Compound/Building/Datamod.pas @@ -43,7 +43,8 @@ interface FireDAC.DApt, BoldAbstractPropagatorHandle, BoldPropagatorHandleCOM, BoldPersistenceHandlePassthrough, BoldPersistenceHandlePTWithModel, BoldSnooperHandle, BoldAbstractDequeuer, - BoldExternalObjectSpaceEventHandler, BoldConstraintValidator; + BoldExternalObjectSpaceEventHandler, BoldConstraintValidator, FireDAC.Phys.PG, + FireDAC.Phys.PGDef; type TDataModule1 = class(TDataModule) @@ -57,10 +58,12 @@ TDataModule1 = class(TDataModule) BoldSystemTypeInfoHandle1: TBoldSystemTypeInfoHandle; BoldPlaceableAFP1: TBoldPlaceableAFP; BoldPersistenceHandleDB1: TBoldPersistenceHandleDB; - BoldDatabaseAdapterFireDAC1: TBoldDatabaseAdapterFireDAC; - FDConnection1: TFDConnection; + BoldDatabaseAdapterPostgres: TBoldDatabaseAdapterFireDAC; + FDConnectionSQLServer: TFDConnection; BoldConstraintValidatorOnModify: TBoldConstraintValidator; BoldConstraintValidatorOnUpdate: TBoldConstraintValidator; + FDConnectionPostgres: TFDConnection; + BoldDatabaseAdapterSQLServer: TBoldDatabaseAdapterFireDAC; function NameComparerCompare(item1, item2: TBoldElement): Integer; procedure NameComparerSubscribe(boldElement: TBoldElement; subscriber: TBoldSubscriber); function IsRichFilterFilter(element: TBoldElement): Boolean; @@ -165,7 +168,10 @@ procedure TDataModule1.BoldPlaceableAFP1GetFormClass(Element: TBoldElement; var procedure TDataModule1.BoldPlaceableAFP1RetrieveHandle(Form: TForm; var Result: TBoldReferenceHandle); begin if form is TPersonAutoForm then - result := TPersonAutoForm(form).brhPerson + begin + result := TPersonAutoForm(form).brhPerson; + TPersonAutoForm(form).BoldFormSaver1.SystemHandle := BoldSystemHandle1; + end else result := nil; end; diff --git a/examples/Delphi/Compound/Building/Mainform.dfm b/examples/Delphi/Compound/Building/Mainform.dfm index 5295418..76e938b 100644 --- a/examples/Delphi/Compound/Building/Mainform.dfm +++ b/examples/Delphi/Compound/Building/Mainform.dfm @@ -1,8 +1,8 @@ object allform: Tallform Left = 65 Top = 67 - ClientHeight = 575 - ClientWidth = 604 + ClientHeight = 576 + ClientWidth = 601 Color = clBtnFace Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText @@ -23,13 +23,6 @@ object allform: Tallform Height = 13 Caption = 'All Persons #:' end - object Label8: TLabel - Left = 32 - Top = 464 - Width = 30 - Height = 13 - Caption = 'Status' - end object PersonGroup: TGroupBox Left = 208 Top = 8 @@ -271,21 +264,13 @@ object allform: Tallform 87 53) end - object pbdbNotification: TProgressBar - Left = 8 - Top = 483 - Width = 105 - Height = 16 - Step = 1 - TabOrder = 5 - end object PageControl1: TPageControl Left = 3 Top = 224 Width = 593 Height = 225 ActivePage = tabResidentialBuilding - TabOrder = 6 + TabOrder = 5 object tabBuilding: TTabSheet Caption = 'Buildings' object bgrBuilding: TBoldGrid @@ -619,14 +604,14 @@ object allform: Tallform end end object GroupBox2: TGroupBox - Left = 393 - Top = 457 + Left = 134 + Top = 456 Width = 96 - Height = 105 - TabOrder = 7 + Height = 94 + TabOrder = 6 object btnUnDo: TButton - Left = 4 - Top = 35 + Left = 3 + Top = 34 Width = 88 Height = 25 Action = BoldUndoAction1 @@ -641,7 +626,7 @@ object allform: Tallform TabOrder = 1 end object btnCheckpoint: TButton - Left = 4 + Left = 3 Top = 3 Width = 88 Height = 29 @@ -650,15 +635,15 @@ object allform: Tallform end end object GroupBox3: TGroupBox - Left = 512 - Top = 457 - Width = 82 - Height = 105 - TabOrder = 8 + Left = 504 + Top = 456 + Width = 90 + Height = 95 + TabOrder = 7 object Button1: TButton Left = 3 Top = 34 - Width = 75 + Width = 84 Height = 25 Action = BoldActivateSystemAction1 TabOrder = 0 @@ -666,19 +651,11 @@ object allform: Tallform object Button2: TButton Left = 3 Top = 3 - Width = 75 + Width = 84 Height = 25 Action = BoldCreateDatabaseAction1 TabOrder = 1 end - object btnUpdateDB: TButton - Left = 3 - Top = 65 - Width = 75 - Height = 25 - Action = BoldUpdateDBAction1 - TabOrder = 2 - end end object BoldNavigator1: TBoldNavigator Left = 8 @@ -686,7 +663,7 @@ object allform: Tallform Width = 192 Height = 25 BoldHandle = blhAllPerson - TabOrder = 9 + TabOrder = 8 ImageIndices.nbFirst = -1 ImageIndices.nbPrior = -1 ImageIndices.nbNext = -1 @@ -701,20 +678,97 @@ object allform: Tallform end object StatusBar1: TStatusBar Left = 0 - Top = 556 - Width = 604 + Top = 557 + Width = 601 Height = 19 Action = BoldFailureDetectionAction1 Panels = <> SimplePanel = True + ExplicitWidth = 761 end - object ListBox1: TListBox - Left = 274 - Top = 456 - Width = 113 - Height = 89 - ItemHeight = 13 + object GroupBox4: TGroupBox + Left = 392 + Top = 455 + Width = 106 + Height = 96 + TabOrder = 10 + object Label8: TLabel + Left = 49 + Top = 61 + Width = 3 + Height = 13 + end + object pbdbNotification: TProgressBar + Left = 4 + Top = 75 + Width = 96 + Height = 16 + Step = 1 + TabOrder = 2 + end + object Button3: TButton + Left = 4 + Top = 34 + Width = 99 + Height = 25 + Action = BoldDiscardChangesAction1 + TabOrder = 0 + end + object Button5: TButton + Left = 4 + Top = 3 + Width = 98 + Height = 25 + Action = BoldUpdateDBAction1 + TabOrder = 1 + end + end + object GroupBox5: TGroupBox + Left = 236 + Top = 455 + Width = 133 + Height = 96 + Caption = 'Redo' TabOrder = 11 + object lbRedo: TListBox + Left = 2 + Top = 15 + Width = 129 + Height = 79 + Style = lbOwnerDrawFixed + Align = alClient + ItemHeight = 13 + TabOrder = 0 + OnDblClick = lbUndoDblClick + OnDrawItem = lbUndoDrawItem + end + end + object GroupBox6: TGroupBox + Left = 8 + Top = 455 + Width = 120 + Height = 96 + Caption = 'Undo' + TabOrder = 12 + object lbUndo: TListBox + Left = 2 + Top = 15 + Width = 116 + Height = 79 + Style = lbOwnerDrawFixed + Align = alClient + ItemHeight = 13 + TabOrder = 0 + OnDblClick = lbUndoDblClick + OnDrawItem = lbUndoDrawItem + end + end + object UndoSubscriber: TBoldPlaceableSubscriber + BoldHandle = DataModule1.BoldSystemHandle1 + OnReceive = UndoSubscriberReceive + OnSubscribeToElement = UndoSubscriberSubscribeToElement + Left = 304 + Top = 176 end object BuildingPopup: TPopupMenu OnPopup = PopupPopup @@ -852,15 +906,13 @@ object allform: Tallform end object BoldPersistenceProgressNotifier1: TBoldPersistenceProgressNotifier WinControl = StatusBar1 - MsgLabel = Label8 - ProgressBar = pbdbNotification AnimationInterval = 100 PersistenceHandle = DataModule1.BoldPersistenceHandleDB1 MsgFetchObjects = 'Fetching objects' MsgRetrieveIds = 'Retrieving object ids' MsgUpdateDatabase = 'Updating database' - Left = 120 - Top = 456 + Left = 112 + Top = 464 end object ActionList1: TActionList Left = 16 @@ -869,6 +921,7 @@ object allform: Tallform Category = 'Bold Actions' Caption = 'Open system' BoldSystemHandle = DataModule1.BoldSystemHandle1 + OnSystemOpened = BoldActivateSystemAction1SystemOpened OpenCaption = 'Open system' CloseCaption = 'Close system' SaveQuestion = 'There are dirty objects. Save them before exit?' @@ -884,6 +937,7 @@ object allform: Tallform Category = 'Bold Actions' Caption = 'Create DB' BoldSystemHandle = DataModule1.BoldSystemHandle1 + IgnoreUnknownTables = False end object BoldFailureDetectionAction1: TBoldFailureDetectionAction Category = 'Bold Actions' @@ -944,6 +998,11 @@ object allform: Tallform Category = 'Bold Actions' Caption = 'Log view' end + object BoldDiscardChangesAction1: TBoldDiscardChangesAction + Category = 'Bold Actions' + Caption = 'Discard changes' + BoldSystemHandle = DataModule1.BoldSystemHandle1 + end end object HighRentRenderer: TBoldAsStringRenderer OnSetFont = HighRentRendererSetFont @@ -965,6 +1024,9 @@ object allform: Tallform object UpdateDB1: TMenuItem Action = BoldUpdateDBAction1 end + object Discardchanges1: TMenuItem + Action = BoldDiscardChangesAction1 + end object Systemdebugger1: TMenuItem Action = BoldSystemDebuggerAction1 end diff --git a/examples/Delphi/Compound/Building/Mainform.pas b/examples/Delphi/Compound/Building/Mainform.pas index d90a8d4..e111c78 100644 --- a/examples/Delphi/Compound/Building/Mainform.pas +++ b/examples/Delphi/Compound/Building/Mainform.pas @@ -16,6 +16,8 @@ interface Grids, Actions, ActnList, + Types, + BoldSubscription, BoldElements, BoldSystem, @@ -38,12 +40,14 @@ interface BoldActions, BoldDBActions, BoldAFP, + BoldFormSaver, + BoldPlaceableSubscriber, BoldReferenceHandle, BoldNavigatorDefs, BoldDebugActions, BoldUndoActions, BoldCaptionController, - BoldAction; + BoldAction, BoldFormSaverActions; type Tallform = class(TForm) @@ -85,7 +89,6 @@ Tallform = class(TForm) bsrResidentsTotalAssets: TBoldAsStringRenderer; bsrAddress: TBoldAsStringRenderer; bgrPerson: TBoldGrid; - pbdbNotification: TProgressBar; PageControl1: TPageControl; tabBuilding: TTabSheet; tabResidentialBuilding: TTabSheet; @@ -121,7 +124,6 @@ Tallform = class(TForm) btnUnDo: TButton; btnRedo: TButton; GroupBox3: TGroupBox; - btnUpdateDB: TButton; BoldFailureDetectionAction1: TBoldFailureDetectionAction; BoldUndoAction1: TBoldUndoAction; BoldRedoAction1: TBoldRedoAction; @@ -153,8 +155,18 @@ Tallform = class(TForm) BoldCaptionController1: TBoldCaptionController; actChargeRent: TBoldAction; BoldLogFormAction1: TBoldLogFormAction; - ListBox1: TListBox; + BoldDiscardChangesAction1: TBoldDiscardChangesAction; + GroupBox4: TGroupBox; + Button3: TButton; + Button5: TButton; + Discardchanges1: TMenuItem; + pbdbNotification: TProgressBar; Label8: TLabel; + GroupBox5: TGroupBox; + lbRedo: TListBox; + GroupBox6: TGroupBox; + lbUndo: TListBox; + UndoSubscriber: TBoldPlaceableSubscriber; procedure newBuildingClick(Sender: TObject); procedure DeleteCurrentObject(Sender: TObject); procedure NewPersonClick(Sender: TObject); @@ -191,9 +203,18 @@ Tallform = class(TForm) procedure BoldModelEditorActionExecute(Sender: TObject); procedure actChargeRentExecute(Sender: TObject); procedure FormCreate(Sender: TObject); + procedure BoldActivateSystemAction1SystemOpened(Sender: TObject); + procedure lbUndoDblClick(Sender: TObject); + procedure lbUndoDrawItem(Control: TWinControl; Index: Integer; Rect: TRect; + State: TOwnerDrawState); + procedure UndoSubscriberSubscribeToElement(element: TBoldElement; + Subscriber: TBoldSubscriber); + procedure UndoSubscriberReceive(sender: TBoldPlaceableSubscriber; + Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: Integer); private { Private declarations } function CurrentBuildingHandle: TBoldListHandle; + procedure UpdateUndo; public { Public declarations } end; @@ -208,6 +229,7 @@ implementation BoldGUI, PersonAutoFormUnit, datamod, + BoldUndoInterfaces, BoldUMLModelEdit; {$R *.DFM} @@ -256,6 +278,21 @@ procedure Tallform.SingleItemRemove(Sender: TObject); TBoldObjectReference(BoldHandle.Value).BoldObject := nil; end; +procedure Tallform.UndoSubscriberReceive(sender: TBoldPlaceableSubscriber; + Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: Integer); +begin + UpdateUndo; +end; + +procedure Tallform.UndoSubscriberSubscribeToElement(element: TBoldElement; + Subscriber: TBoldSubscriber); +begin + TBoldSystem(Element).UndoHandler.AddSubscription(Subscriber, beUndoChanged, beUndoChanged); + TBoldSystem(Element).UndoHandler.AddSubscription(Subscriber, beUndoBlock, beUndoChanged); + TBoldSystem(Element).UndoHandler.AddSubscription(Subscriber, beRedoBlock, beUndoChanged); + TBoldSystem(Element).UndoHandler.AddSubscription(Subscriber, beUndoSetCheckpoint, beUndoChanged); +end; + procedure Tallform.PopupPopup(Sender: TObject); begin if (sender is TMenuItem) then @@ -281,7 +318,6 @@ procedure Tallform.FormCloseQuery(Sender: TObject; var CanClose: Boolean); procedure Tallform.FormCreate(Sender: TObject); begin Randomize; - datamodule1.BoldSystemHandle1.System.UndoHandlerInterface.Enabled := true; BoldCaptionController1.TrackControl := self; end; @@ -436,6 +472,36 @@ procedure Tallform.bsrResidentsTotalAssetsSubscribe(aFollower: TBoldFollower; end; end; +procedure Tallform.UpdateUndo; +var + i: integer; +begin + if not datamodule1.BoldSystemHandle1.Active then + exit; + if not datamodule1.BoldSystemHandle1.System.UndoHandlerInterface.Enabled then + exit; + lbUndo.Items.BeginUpdate; + lbUndo.Items.Clear; + lbRedo.Items.BeginUpdate; + lbRedo.Items.Clear; + with datamodule1.BoldSystemHandle1.System.UndoHandlerInterface do + try + for I := 0 to UndoList.Count-1 do + lbUndo.Items.Add(TimeToStr(UndoList[i].Created) + ':'+ UndoList[i].Name + ' ' + UndoList[i].Content); + lbUndo.ItemIndex := i; + for I := 0 to RedoList.Count-1 do + lbRedo.Items.Add(TimeToStr(RedoList[i].Created) + ':'+ RedoList[i].Name + ' ' + RedoList[i].Content); + finally + lbUndo.Items.EndUpdate; + lbRedo.Items.EndUpdate; + end; +end; + +procedure Tallform.BoldActivateSystemAction1SystemOpened(Sender: TObject); +begin + datamodule1.BoldSystemHandle1.System.UndoHandlerInterface.Enabled := true; +end; + procedure Tallform.BoldModelEditorActionExecute(Sender: TObject); begin BoldUMLModelEdit.UMLModelEditor.ShowEditFormForBoldModel(DataModule1.BoldModel1); @@ -509,6 +575,34 @@ procedure Tallform.HighRentRendererSetFont(aFollower: TBoldFollower; end; end; +procedure Tallform.lbUndoDblClick(Sender: TObject); +var + blockName: string; + i: integer; +begin + blockName := lbUndo.Items[lbUndo.ItemIndex]; + i := datamodule1.BoldSystemHandle1.System.UndoHandlerInterface.UndoList.IndexOf(blockName); + if i <> -1 then + datamodule1.BoldSystemHandle1.System.UndoHandlerInterface.UndoBlock(blockname) + else + begin + i := datamodule1.BoldSystemHandle1.System.UndoHandlerInterface.RedoList.IndexOf(blockName); + if i <> -1 then + datamodule1.BoldSystemHandle1.System.UndoHandlerInterface.RedoBlock(blockname); + end; +end; + +procedure Tallform.lbUndoDrawItem(Control: TWinControl; Index: Integer; + Rect: TRect; State: TOwnerDrawState); +begin + with (Control as TListBox) do + begin + if index = ItemIndex then + Canvas.Font.Color := clRed; + Canvas.TextOut(Rect.Left, Rect.Top, (Control as TListBox).Items[Index]); + end; +end; + end. diff --git a/examples/Delphi/Compound/Building/PersonAutoFormUnit.dfm b/examples/Delphi/Compound/Building/PersonAutoFormUnit.dfm index 0f486c3..1e49afe 100644 --- a/examples/Delphi/Compound/Building/PersonAutoFormUnit.dfm +++ b/examples/Delphi/Compound/Building/PersonAutoFormUnit.dfm @@ -2,8 +2,8 @@ object PersonAutoForm: TPersonAutoForm Left = 31 Top = 96 Caption = 'Person Detail' - ClientHeight = 380 - ClientWidth = 307 + ClientHeight = 559 + ClientWidth = 267 Color = clBtnFace Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText @@ -209,8 +209,78 @@ object PersonAutoForm: TPersonAutoForm BoldSelectChangeAction = bdcsSetValue TabOrder = 5 end + object BoldGrid1: TBoldGrid + Left = 8 + Top = 400 + Width = 249 + Height = 120 + AddNewAtEnd = False + BoldAutoColumns = False + BoldShowConstraints = False + BoldHandle = BoldCursorHandle1 + Columns = < + item + BoldProperties.Expression = '' + Color = clBtnFace + Font.Charset = DEFAULT_CHARSET + Font.Color = clWindowText + Font.Height = -11 + Font.Name = 'MS Sans Serif' + Font.Style = [] + LookUpProperties.Expression = '' + end + item + BoldProperties.Expression = '' + Font.Charset = DEFAULT_CHARSET + Font.Color = clWindowText + Font.Height = -11 + Font.Name = 'MS Sans Serif' + Font.Style = [] + LookUpProperties.Expression = '' + end> + DefaultRowHeight = 17 + EnableColAdjust = False + Font.Charset = DEFAULT_CHARSET + Font.Color = clWindowText + Font.Height = -11 + Font.Name = 'MS Sans Serif' + Font.Style = [] + ParentFont = False + TabOrder = 6 + TitleFont.Charset = DEFAULT_CHARSET + TitleFont.Color = clWindowText + TitleFont.Height = -11 + TitleFont.Name = 'Tahoma' + TitleFont.Style = [] + ColWidths = ( + 17 + 64) + end + object Button1: TButton + Left = 8 + Top = 526 + Width = 75 + Height = 25 + Action = BoldFormSaverApplyAction1 + TabOrder = 7 + end + object Button2: TButton + Left = 94 + Top = 526 + Width = 75 + Height = 25 + Action = BoldFormSaverOkAction1 + TabOrder = 8 + end + object Button3: TButton + Left = 182 + Top = 526 + Width = 75 + Height = 25 + Action = BoldFormSaverCancelAction1 + TabOrder = 9 + end object brhPerson: TBoldReferenceHandle - StaticSystemHandle = DataModule1.BoldSystemHandle1 StaticValueTypeName = 'Person' OnObjectDeleted = brhPersonObjectDeleted OnValueDestroyed = brhPersonObjectDeleted @@ -235,4 +305,35 @@ object PersonAutoForm: TPersonAutoForm Left = 24 Top = 240 end + object BoldFormSaver1: TBoldFormSaver + OnlyFirstDirty = False + Left = 208 + Top = 96 + end + object BoldCursorHandle1: TBoldCursorHandle + RootHandle = BoldFormSaver1 + Left = 120 + Top = 456 + end + object ActionList1: TActionList + Left = 208 + Top = 432 + object BoldFormSaverApplyAction1: TBoldFormSaverApplyAction + Category = 'Bold Actions' + Caption = '&Apply' + ShortCut = 16474 + BoldFormSaver = BoldFormSaver1 + end + object BoldFormSaverCancelAction1: TBoldFormSaverCancelAction + Category = 'Bold Actions' + Caption = '&Cancel' + BoldFormSaver = BoldFormSaver1 + end + object BoldFormSaverOkAction1: TBoldFormSaverOkAction + Category = 'Bold Actions' + Caption = '&Ok' + ShortCut = 16474 + BoldFormSaver = BoldFormSaver1 + end + end end diff --git a/examples/Delphi/Compound/Building/PersonAutoFormUnit.pas b/examples/Delphi/Compound/Building/PersonAutoFormUnit.pas index edcb18a..4149dfe 100644 --- a/examples/Delphi/Compound/Building/PersonAutoFormUnit.pas +++ b/examples/Delphi/Compound/Building/PersonAutoFormUnit.pas @@ -18,7 +18,8 @@ interface BoldGrid, StdCtrls, BoldCheckBox, - BoldEdit, BoldCaptionController, BoldComboBox; + BoldEdit, BoldCaptionController, BoldComboBox, BoldFormSaver, + BoldFormSaverActions, System.Actions, Vcl.ActnList, BoldHandleAction; type TPersonAutoForm = class(TForm) @@ -38,6 +39,16 @@ TPersonAutoForm = class(TForm) Label3: TLabel; Label6: TLabel; blhOwnedResidentialBuildings: TBoldListHandle; + BoldFormSaver1: TBoldFormSaver; + BoldGrid1: TBoldGrid; + BoldCursorHandle1: TBoldCursorHandle; + Button1: TButton; + Button2: TButton; + Button3: TButton; + ActionList1: TActionList; + BoldFormSaverApplyAction1: TBoldFormSaverApplyAction; + BoldFormSaverCancelAction1: TBoldFormSaverCancelAction; + BoldFormSaverOkAction1: TBoldFormSaverOkAction; procedure brhPersonObjectDeleted(Sender: TObject); procedure FormCreate(Sender: TObject); private From cc9d13ecd7fbf7edd1fc9fdd0d30714e2ddef826 Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Sat, 22 May 2021 20:32:24 +0300 Subject: [PATCH 061/112] Added LogOssAction and updated drop/exists db tempaltes --- examples/Delphi/Compound/Building/Datamod.dfm | 10 +++++++++- examples/Delphi/Compound/Building/Mainform.dfm | 11 +++++++++-- examples/Delphi/Compound/Building/Mainform.pas | 2 ++ 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/examples/Delphi/Compound/Building/Datamod.dfm b/examples/Delphi/Compound/Building/Datamod.dfm index 5281177..213f765 100644 --- a/examples/Delphi/Compound/Building/Datamod.dfm +++ b/examples/Delphi/Compound/Building/Datamod.dfm @@ -414,6 +414,10 @@ object DataModule1: TDataModule1 SQLDatabaseConfig.ColumnTypeForInt64 = 'BIGINT' SQLDatabaseConfig.ColumnTypeForGUID = 'UUID' SQLDatabaseConfig.CreateDatabaseTemplate = 'CREATE DATABASE %s' + SQLDatabaseConfig.DropDatabaseTemplate = 'DROP DATABASE %s' + SQLDatabaseConfig.DatabaseExistsTemplate = + 'select exists(SELECT datname FROM pg_catalog.pg_database WHERE l' + + 'ower(datname) = lower('#39'%s'#39'));' SQLDatabaseConfig.DropColumnTemplate = 'ALTER TABLE DROP ' SQLDatabaseConfig.DropTableTemplate = 'DROP TABLE ' SQLDatabaseConfig.IndexInfoTemplate = @@ -577,6 +581,10 @@ object DataModule1: TDataModule1 SQLDatabaseConfig.ColumnTypeForInt64 = 'BIGINT' SQLDatabaseConfig.ColumnTypeForGUID = 'UNIQUEIDENTIFIER' SQLDatabaseConfig.CreateDatabaseTemplate = 'CREATE DATABASE %s' + SQLDatabaseConfig.DropDatabaseTemplate = 'DROP DATABASE %s' + SQLDatabaseConfig.DatabaseExistsTemplate = + 'IF EXISTS (SELECT name FROM master.sys.databases WHERE name = N'#39 + + '%s'#39')' SQLDatabaseConfig.DropColumnTemplate = 'DECLARE @CONSTRAINTNAME NVARCHAR(200) SELECT @CONSTRAINTNAME=OD.' + 'NAME FROM SYSOBJECTS OT, SYSCOLUMNS C, SYSOBJECTS OD WHERE' + @@ -665,7 +673,7 @@ object DataModule1: TDataModule1 SQLDatabaseConfig.SqlScriptCommitTransaction = 'COMMIT' SQLDatabaseConfig.SqlScriptRollBackTransaction = 'ROLLBACK' CustomIndexes = <> - Connection = FDConnectionPostgres + Connection = FDConnectionSQLServer DatabaseEngine = dbeSQLServer Left = 224 Top = 80 diff --git a/examples/Delphi/Compound/Building/Mainform.dfm b/examples/Delphi/Compound/Building/Mainform.dfm index 76e938b..9f68953 100644 --- a/examples/Delphi/Compound/Building/Mainform.dfm +++ b/examples/Delphi/Compound/Building/Mainform.dfm @@ -684,7 +684,6 @@ object allform: Tallform Action = BoldFailureDetectionAction1 Panels = <> SimplePanel = True - ExplicitWidth = 761 end object GroupBox4: TGroupBox Left = 392 @@ -937,7 +936,8 @@ object allform: Tallform Category = 'Bold Actions' Caption = 'Create DB' BoldSystemHandle = DataModule1.BoldSystemHandle1 - IgnoreUnknownTables = False + IgnoreUnknownTables = True + DropExisting = True end object BoldFailureDetectionAction1: TBoldFailureDetectionAction Category = 'Bold Actions' @@ -974,6 +974,10 @@ object allform: Tallform Category = 'Bold Actions' Caption = 'Toggle SQL logs' end + object BoldLogOSSAction1: TBoldLogOSSAction + Category = 'Bold Actions' + Caption = 'Toggle OSS traffic logs' + end object BoldLogPMAction1: TBoldLogPMAction Category = 'Bold Actions' Caption = 'Toggle PMCalls logs' @@ -1057,6 +1061,9 @@ object allform: Tallform object oggleSQLlogs1: TMenuItem Action = BoldLogSQLAction1 end + object oggleOSStrafficlogs1: TMenuItem + Action = BoldLogOSSAction1 + end end end object BoldCaptionController1: TBoldCaptionController diff --git a/examples/Delphi/Compound/Building/Mainform.pas b/examples/Delphi/Compound/Building/Mainform.pas index e111c78..95afe30 100644 --- a/examples/Delphi/Compound/Building/Mainform.pas +++ b/examples/Delphi/Compound/Building/Mainform.pas @@ -167,6 +167,8 @@ Tallform = class(TForm) GroupBox6: TGroupBox; lbUndo: TListBox; UndoSubscriber: TBoldPlaceableSubscriber; + BoldLogOSSAction1: TBoldLogOSSAction; + oggleOSStrafficlogs1: TMenuItem; procedure newBuildingClick(Sender: TObject); procedure DeleteCurrentObject(Sender: TObject); procedure NewPersonClick(Sender: TObject); From f3b9cbe603ee5c0d11c2dd196e66c571b6f0f0bf Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Sun, 23 May 2021 13:18:17 +0300 Subject: [PATCH 062/112] Removed deprecated persistence handle --- Bold.dpk | 1 - .../DB/BoldPersistenceHandleDB_deprecated.pas | 189 ---------- .../FireDAC/BoldPersistenceHandleFireDAC.pas | 334 ------------------ .../BoldPersistenceHandleFireDACReg.pas | 5 +- .../UniDAC/BoldPersistenceHandleUniDAC.pas | 333 ----------------- .../UniDAC/BoldPersistenceHandleUniDACReg.pas | 4 - 6 files changed, 1 insertion(+), 865 deletions(-) delete mode 100644 Source/Persistence/DB/BoldPersistenceHandleDB_deprecated.pas delete mode 100644 Source/Persistence/FireDAC/BoldPersistenceHandleFireDAC.pas delete mode 100644 Source/Persistence/UniDAC/BoldPersistenceHandleUniDAC.pas diff --git a/Bold.dpk b/Bold.dpk index 957a5dd..e708ead 100644 --- a/Bold.dpk +++ b/Bold.dpk @@ -268,7 +268,6 @@ contains BoldDBActions in 'Source\Persistence\DB\BoldDBActions.pas', BoldDBInterfaces in 'Source\Persistence\DB\BoldDBInterfaces.pas', BoldPersistenceControllerDefault in 'Source\Persistence\DB\BoldPersistenceControllerDefault.pas', - BoldPersistenceHandleDB_deprecated in 'Source\Persistence\DB\BoldPersistenceHandleDB_deprecated.pas', BoldPersistenceHandleDB in 'Source\Persistence\DB\BoldPersistenceHandleDB.pas', BoldPersistenceHandleDBreg in 'Source\Persistence\DB\BoldPersistenceHandleDBreg.pas', BoldPersistenceHandleFile in 'Source\Persistence\File\BoldPersistenceHandleFile.pas', diff --git a/Source/Persistence/DB/BoldPersistenceHandleDB_deprecated.pas b/Source/Persistence/DB/BoldPersistenceHandleDB_deprecated.pas deleted file mode 100644 index 194b8b5..0000000 --- a/Source/Persistence/DB/BoldPersistenceHandleDB_deprecated.pas +++ /dev/null @@ -1,189 +0,0 @@ - -{ Global compiler directives } -{$include bold.inc} -unit BoldPersistenceHandleDB_deprecated; - -interface - -uses - Classes, - Dialogs, - Controls, - BoldPersistenceHandleDb, - BoldSQLDatabaseConfig, - BoldAbstractPersistenceHandleDB, BoldIndexCollection; - - -type - { forward declarations } - TBoldDBPersistenceHandle = class; - - { TBoldDBPersistenceHandle } - TBoldDBPersistenceHandle = class(TBoldAbstractPersistenceHandleDB) - private - fUserName: String; - fPassword: String; - fSQLDataBaseConfig: TBoldSQLDataBaseConfig; - fCustomIndexes: TBoldIndexCollection; - fDatabaseEngine: TBoldDataBaseEngine; - procedure SQLDatabaseConfigChanged(Sender: TObject); - procedure SetSQLDataBaseConfig(const Value: TBoldSQLDataBaseConfig); - procedure ReadEmptyStringMarker(Reader: TReader); - procedure ReadSystemTablePrefix(Reader: TReader); - function GetNewPersistenceHandle: TBoldPersistenceHandleDB; - procedure TransferPropertiesToNewPersistenceHandle(const Value: TBoldPersistenceHandleDB); - protected - procedure SetDataBaseEngine(const Value: TBoldDataBaseEngine); virtual; - procedure SetPassword(const Value: string); virtual; - procedure SetUserName(const Value: string); virtual; - function GetSQLDataBaseConfig: TBoldSQLDataBaseConfig; override; - function GetCustomIndexes: TBoldIndexCollection; override; - {$IFDEF T2H} - property EmptyStringMarker; - property SystemTablesPrefix; - {$ELSE} - procedure InternalTransferproperties(const target: TBoldPersistenceHandleDB); virtual; - function GetNewComponentName(Comp: Tcomponent; BaseName: string): String; - {$ENDIF} - procedure DefineProperties(Filer: TFiler); override; - public - constructor create(Owner: TComponent); override; - destructor destroy; override; - published - property Username: string read fusername write SetUserName; - property Password: string read fPassword write SetPassword; - property SQLDataBaseConfig: TBoldSQLDataBaseConfig read GetSQLDataBaseConfig write SetSQLDataBaseConfig; - property DatabaseEngine: TBoldDataBaseEngine read fDatabaseEngine write SetDataBaseEngine; - property __TransferPropertiesToNewPersistenceHandle: TBoldPersistenceHandleDB read GetNewPersistenceHandle write TransferPropertiesToNewPersistenceHandle; - end; - -implementation - -uses - SysUtils, - BoldPersistenceControllerDefault, - BoldPersistenceHandle; - -{ TBoldDBPersistenceHandle } - -constructor TBoldDBPersistenceHandle.create(Owner: TComponent); -begin - inherited; - fSQLDatabaseConfig := TBoldSQlDatabaseConfig.Create; -end; - -procedure TBoldDBPersistenceHandle.SetPassword(const Value: string); -begin - fPassword := Value; -end; - -procedure TBoldDBPersistenceHandle.SetUserName(const Value: string); -begin - fusername := Value; -end; - -destructor TBoldDBPersistenceHandle.destroy; -begin - FreeAndNil(fSQLDataBaseConfig); - inherited; -end; - -procedure TBoldDBPersistenceHandle.SQLDatabaseConfigChanged(Sender: TObject); -begin - if HasPersistenceController then - PersistenceControllerDefault.SQLDataBaseConfig.AssignConfig(SQLDataBaseConfig); -end; - -procedure TBoldDBPersistenceHandle.SetSQLDataBaseConfig(const Value: TBoldSQLDataBaseConfig); -begin - SQLDataBaseConfig.AssignConfig(Value); -end; - -procedure TBoldDBPersistenceHandle.SetDataBaseEngine(const Value: TBoldDataBaseEngine); -begin - if value <> fDatabaseEngine then - begin - if not (csLoading in ComponentState) then - SQLDatabaseConfig.InitializeDbEngineSettings(Value); - fDatabaseEngine := Value; - SQLDataBaseConfig.Engine := DatabaseEngine; - end; -end; - -function TBoldDBPersistenceHandle.GetSQLDataBaseConfig: TBoldSQLDataBaseConfig; -begin - if not assigned(fSQLDataBaseConfig) then - begin - fSQLDataBaseConfig := TBoldSQLDataBaseConfig.Create; - fSQLDataBaseConfig.OnChange := SQLDatabaseConfigChanged; - end; - result := fSQLDataBaseConfig; -end; - -procedure TBoldDBPersistenceHandle.DefineProperties(Filer: TFiler); -begin - inherited DefineProperties(Filer); - Filer.DefineProperty('EmptyStringMarker', ReadEmptyStringMarker, nil, True); - Filer.DefineProperty('SystemTablesPrefix', ReadSystemTablePrefix, nil, True); -end; - -procedure TBoldDBPersistenceHandle.ReadEmptyStringMarker(Reader: TReader); -begin - SQLDataBaseConfig.EmptyStringMarker := Reader.ReadString; -end; - -procedure TBoldDBPersistenceHandle.ReadSystemTablePrefix(Reader: TReader); -begin - SQLDataBaseConfig.SystemTablePrefix := Reader.ReadString; -end; - -function TBoldDBPersistenceHandle.GetNewPersistenceHandle: TBoldPersistenceHandleDB; -begin - result := nil; -end; - -procedure TBoldDBPersistenceHandle.TransferPropertiesToNewPersistenceHandle( - const Value: TBoldPersistenceHandleDB); -begin - if assigned(value) and - (MessageDlg(format('Do you want to transfer the settings to %s', [value.Name]), - mtConfirmation, [mbYes, mbNo], 0) = mrYes) then - begin - InternalTransferproperties(value); - Value.SQLDatabaseConfig.AssignConfig(SQLDataBaseConfig); - Value.ClockLogGranularity := ClockLogGranularity; - Value.EvolutionSupport := EvolutionSupport; - Value.UpgraderHandle := UpgraderHandle; - Value.OnGetCurrentTime := OnGetCurrentTime; - Value.BoldModel := BoldModel; - showmessage('All settings have been transferred to ' + value.Name); - end; -end; - -procedure TBoldDBPersistenceHandle.InternalTransferproperties(const target: TBoldPersistenceHandleDB); -begin -end; - -function TBoldDBPersistenceHandle.GetCustomIndexes: TBoldIndexCollection; -begin - if not assigned(fCustomIndexes) then - begin - fCustomIndexes := TBoldIndexCollection.Create(self); - end; - result := fCustomIndexes; -end; - -function TBoldDBPersistenceHandle.GetNewComponentName(Comp: Tcomponent; - BaseName: string): String; -var - i: integer; -begin - i := 1; - while assigned(comp.Owner.FindComponent(BaseName+IntToStr(i))) do - inc(i); - result := BaseName + inttostr(i); -end; - -initialization - -end. diff --git a/Source/Persistence/FireDAC/BoldPersistenceHandleFireDAC.pas b/Source/Persistence/FireDAC/BoldPersistenceHandleFireDAC.pas deleted file mode 100644 index 035d632..0000000 --- a/Source/Persistence/FireDAC/BoldPersistenceHandleFireDAC.pas +++ /dev/null @@ -1,334 +0,0 @@ -{ Global compiler directives } -{$include bold.inc} -unit BoldPersistenceHandleFireDAC; - -interface - -uses - Classes, - Dialogs, - - FireDAC.Comp.Client, - - - BoldDBInterfaces, - BoldFireDACInterfaces, - BoldPersistenceHandleDB, - BoldPersistenceHandleDB_deprecated; - -type - TBoldNetWorkProtocol = (bnwpLocal, bnwpTcpIP, bnwpNetBEUI, bnwpNovellSPX); - - TBoldPersistenceHandleFireDAC = class(TBoldDBPersistenceHandle) - private - fFDConnection: TFDConnection; - fOwnConnection: TFDConnection; - fConnectionAdapter: TBoldFireDACConnection; - fDataSource: string; - fProvider: string; - fPersistSecurityInfo: Boolean; - fNetWorkProtocol: TBoldNetWorkProtocol; - fHostName: string; - fInitialCatalog: string; - fExtendedProperties: TStringList; - procedure SetDataSource(const Value: string); - procedure SetProvider(const Value: string); - procedure SetPersistSecurityInfo(const Value: Boolean); - procedure SetNetWorkProtocol(const Value: TBoldNetWorkProtocol); - procedure SetHostName(const Value: string); - procedure SetInitialCatalog(const Value: string); - procedure SetExtendedProperties(const Value: TStringList); - procedure SetFDConnection(const Value: TFDConnection); - function getEffectiveConnection: TFDConnection; - protected - procedure AddExtendedProperties(Result: TStrings); virtual; - procedure UpdateInternalConnectionString; virtual; - procedure Notification(AComponent: TComponent; Operation: TOperation); override; - property EffectiveConnection: TFDConnection read getEffectiveConnection; - procedure SetPassword(const Value: string); override; - procedure SetUserName(const Value: string); override; - {$IFNDEF T2H} - procedure InternalTransferproperties(const target: TBoldPersistenceHandleDB); override; - {$ENDIF} - public - constructor Create(owner: TComponent); override; - destructor Destroy; override; - function GetDataBaseInterface: IBoldDatabase; override; - procedure Assign(Source: TPersistent); override; - published - property DataSource: string read FDataSource write SetDataSource; - property Provider: string read FProvider write SetProvider; - property PersistSecurityInfo: Boolean read FPersistSecurityInfo write SetPersistSecurityInfo; - property NetWorkProtocol: TBoldNetWorkProtocol read FNetWorkProtocol write SetNetWorkProtocol; - property HostName: string read FHostName write SetHostName; - property InitialCatalog: string read FInitialCatalog write SetInitialCatalog; - property ExtendedProperties: TStringList read fExtendedProperties write SetExtendedProperties; - property FDConnection: TFDConnection read fFDConnection write SetFDConnection; - end deprecated; - -const - BoldNetWorkProtocolStringRep: array[TBoldNetWorkProtocol] of string = ('', 'tcpip', 'netbeui', 'spx'); - -function BoldStringToNetworkProtocol(s: string): TBoldNetWorkProtocol; - -implementation - -uses - SysUtils, - BoldDefs, - BoldDatabaseAdapterFireDAC, - BoldUtils, - BoldFireDACConsts; - -function BoldStringToNetworkProtocol(s: string): TBoldNetWorkProtocol; -var - i: TBoldNetWorkProtocol; -begin - for i := low(BoldNetWorkProtocolStringRep) to high(BoldNetWorkProtocolStringRep) do - if CompareText(s, BoldNetWorkProtocolStringRep[i]) = 0 then - begin - Result := i; - exit; - end; - - Result := bnwpLocal; -end; - -{ TBoldPersistenceHandleFireDAC } - -procedure TBoldPersistenceHandleFireDAC.AddExtendedProperties( - Result: TStrings); -begin - if trim(DataSource) <> '' then - Result.Add('DSN=' + trim(DataSource)); // do not localize - if trim(HostName) <> '' then - Result.Add('Hostname=' + trim(HostName)); // do not localize - if trim(InitialCatalog) <> '' then - Result.Add('Initial Catalog=' + trim(InitialCatalog)); // do not localize - - Result.Add('NetworkProt=' + BoldNetWorkProtocolStringRep[NetWorkProtocol]); // do not localize - - Result.AddStrings(ExtendedProperties); -end; - -procedure TBoldPersistenceHandleFireDAC.Assign(Source: TPersistent); -begin - inherited; - if Source is TBoldPersistenceHandleFireDAC then - ExtendedProperties.Assign((Source as TBoldPersistenceHandleFireDAC).ExtendedProperties); -end; - -procedure TBoldPersistenceHandleFireDAC.UpdateInternalConnectionString; -const - BoolToStr: array[Boolean] of string = ('false', 'true'); -var - LExtendedProperties: TStringList; - ConnectionString: string; -begin - if Assigned(fOwnConnection) then - begin - LExtendedProperties := TStringList.Create; - AddExtendedProperties(LExtendedProperties); - - ConnectionString := format('Provider=%s;Persist Security Info=%s;Data Source=%s;Extended Properties=%s', // do not localize - [Provider, - BoolToStr[PersistSecurityInfo], - DataSource, - BoldSeparateStringList(LExtendedProperties, ';', '"', '"')]); - LExtendedProperties.Free; - fOwnConnection.ConnectionString := ConnectionString; - end; -end; - -constructor TBoldPersistenceHandleFireDAC.Create(owner: TComponent); -begin - inherited; - FHostName := ''; // do not localize - fExtendedProperties := TStringList.Create; -end; - -destructor TBoldPersistenceHandleFireDAC.Destroy; -begin - Active := False; - FreeAndNil(fOwnConnection); - FreeAndNil(fConnectionAdapter); - inherited; -end; - -procedure TBoldPersistenceHandleFireDAC.SetFDConnection( - const Value: TFDConnection); -begin - if fFDConnection <> Value then - begin - CheckInactive('SetDataBase'); // do not localize - if Assigned(fOwnConnection) then - begin - FreeAndNil(fOwnConnection); - FreeAndNil(fConnectionAdapter); - end; - fFDConnection := Value; - if Assigned(fFDConnection) then - fFDConnection.FreeNotification(Self); - end; -end; - -procedure TBoldPersistenceHandleFireDAC.SetDataSource(const Value: string); -begin - FDataSource := Value; - UpdateInternalConnectionString; -end; - -procedure TBoldPersistenceHandleFireDAC.SetExtendedProperties( - const Value: TStringList); -begin - fExtendedProperties.Assign(Value); - UpdateInternalConnectionString; -end; - -procedure TBoldPersistenceHandleFireDAC.SetHostName(const Value: string); -begin - FHostName := Value; - if trim(FHostName) = '' then - FHostName := ''; // do not localize - UpdateInternalConnectionString; -end; - -procedure TBoldPersistenceHandleFireDAC.SetInitialCatalog(const Value: string); -begin - FInitialCatalog := Value; - UpdateInternalConnectionString; -end; - -procedure TBoldPersistenceHandleFireDAC.SetNetWorkProtocol( - const Value: TBoldNetWorkProtocol); -begin - FNetWorkProtocol := Value; - UpdateInternalConnectionString; -end; - -procedure TBoldPersistenceHandleFireDAC.SetPersistSecurityInfo( - const Value: Boolean); -begin - FPersistSecurityInfo := Value; - UpdateInternalConnectionString; -end; - -procedure TBoldPersistenceHandleFireDAC.SetProvider(const Value: string); -begin - FProvider := Value; - UpdateInternalConnectionString; -end; - -procedure TBoldPersistenceHandleFireDAC.Notification(AComponent: TComponent; - Operation: TOperation); -begin - inherited; - if (AComponent = fFDConnection) and (Operation = opRemove) then - begin - if AComponent = EffectiveConnection then - begin - Active := False; - fConnectionAdapter := nil; - end; - fFDConnection := nil; - end; -end; - -function TBoldPersistenceHandleFireDAC.getEffectiveConnection: TFDConnection; -begin - if Assigned(fFDConnection) then - Result := fFDConnection - else - begin - if not Assigned(fOwnConnection) then - begin - fOwnConnection := TFDConnection.Create(nil); - UpdateInternalConnectionString; - end; - Result := fOwnConnection; - end; -end; - -procedure TBoldPersistenceHandleFireDAC.SetPassword(const Value: string); -begin - inherited; - UpdateInternalConnectionString; -end; - -procedure TBoldPersistenceHandleFireDAC.SetUserName(const Value: string); -begin - inherited; - UpdateInternalConnectionString; -end; - -function TBoldPersistenceHandleFireDAC.GetDataBaseInterface: IBoldDatabase; -begin - if not Assigned(fConnectionAdapter) then - fConnectionAdapter := TBoldFireDACConnection.Create(EffectiveConnection, SQLDataBaseConfig); - Result := fConnectionAdapter; -end; - -procedure TBoldPersistenceHandleFireDAC.InternalTransferproperties( - const target: TBoldPersistenceHandleDB); -const - BoolToStr: array[Boolean] of string = ('false', 'true'); -var - Adapter: tBoldDatabaseAdapterFireDAC; - DesInfo: longint; - LExtendedProperties: TStringList; - ConnectionString: string; -begin - inherited; - DesInfo := target.DesignInfo; - if not Assigned(target.DatabaseAdapter) then - begin - target.DatabaseAdapter := tBoldDatabaseAdapterFireDAC.Create(target.owner); - target.DatabaseAdapter.Name := GetNewComponentName(target.DatabaseAdapter, 'BoldDatabaseAdapterFireDAC'); // do not localize - LongRec(DesInfo).Lo := LongRec(DesInfo).Lo + 16; //set Left - LongRec(DesInfo).Hi := LongRec(DesInfo).Hi + 16; //Set Top; - target.DatabaseAdapter.DesignInfo := DesInfo; - showmessage(sCreatedNewAdapter); - end - else if not (target.DatabaseAdapter is tBoldDatabaseAdapterFireDAC) then - raise Exception.CreateFmt(sCanOnlyTransferToFireDACAdapter, [target.DatabaseAdapter.ClassName]); - - Adapter := target.DatabaseAdapter as TBoldDatabaseAdapterFireDAC; - if Assigned(fFDConnection) then - Adapter.Connection := FDConnection; - - if not Assigned(Adapter.Connection) then - begin - Adapter.Connection := TFDConnection.Create(target.owner); - Adapter.Connection.Name := GetNewComponentName(Adapter.Connection, 'FireDACDatabase'); // do not localize - showmessage(sCreatedNewDB); - LongRec(DesInfo).Lo := LongRec(DesInfo).Lo + 16; //set Left - LongRec(DesInfo).Hi := LongRec(DesInfo).Hi + 16; //Set Top; - Adapter.Connection.DesignInfo := DesInfo; - - try - LExtendedProperties := TStringList.Create; - AddExtendedProperties(LExtendedProperties); - - ConnectionString := format('Provider=%s;Persist Security Info=%s;Data Source=%s;Extended Properties=%s', // do not localize - [Provider, - BoolToStr[PersistSecurityInfo], - DataSource, - BoldSeparateStringList(LExtendedProperties, ';', '"', '"')]); - LExtendedProperties.Free; - Adapter.Connection.ConnectionString := ConnectionString; - except - on E: Exception do - begin - showmessage(sCouldNotTransferConnectionString + BOLDCRLF + BOLDCRLF + - E.Message + BOLDCRLF + BOLDCRLF + - sTransferManually); - Adapter.Connection.ConnectionString := ''; - - end; - end; - - end; -end; - -end. - diff --git a/Source/Persistence/FireDAC/BoldPersistenceHandleFireDACReg.pas b/Source/Persistence/FireDAC/BoldPersistenceHandleFireDACReg.pas index 1114616..21bac5c 100644 --- a/Source/Persistence/FireDAC/BoldPersistenceHandleFireDACReg.pas +++ b/Source/Persistence/FireDAC/BoldPersistenceHandleFireDACReg.pas @@ -14,14 +14,11 @@ implementation SysUtils, Classes, BoldDatabaseAdapterFireDAC, -// BoldPersistenceHandleFireDAC, BoldIDEConsts; procedure Register; begin - {$WARNINGS OFF} -// RegisterComponents(BOLDPAGENAME_DEPRECATED, [TBoldPersistenceHandleFireDAC]); - {$WARNINGS ON} + RegisterComponents(BOLDPAGENAME_PERSISTENCE, [TBoldDatabaseAdapterFireDAC]); end; diff --git a/Source/Persistence/UniDAC/BoldPersistenceHandleUniDAC.pas b/Source/Persistence/UniDAC/BoldPersistenceHandleUniDAC.pas deleted file mode 100644 index 8189003..0000000 --- a/Source/Persistence/UniDAC/BoldPersistenceHandleUniDAC.pas +++ /dev/null @@ -1,333 +0,0 @@ -{ Global compiler directives } -{$include bold.inc} -unit BoldPersistenceHandleUniDAC; - -interface - -uses - Classes, - DBAccess, - Uni, -// UniProvider, - Dialogs, - BoldDBInterfaces, - BoldUniDACInterfaces, - BoldPersistenceHandleDB, - BoldPersistenceHandleDB_deprecated; - -type - TBoldNetWorkProtocol = (bnwpLocal, bnwpTcpIP, bnwpNetBEUI, bnwpNovellSPX); - - TBoldPersistenceHandleUniDAC = class(TBoldDBPersistenceHandle) - private - fUniConnection: TUniConnection; - fOwnConnection: TUniConnection; - fConnectionAdapter: TBoldUniDACConnection; - fDataSource: string; - fProvider: string; - fPersistSecurityInfo: Boolean; - fNetWorkProtocol: TBoldNetWorkProtocol; - fHostName: string; - fInitialCatalog: string; - fExtendedProperties: TStringList; - procedure SetDataSource(const Value: string); - procedure SetProvider(const Value: string); - procedure SetPersistSecurityInfo(const Value: Boolean); - procedure SetNetWorkProtocol(const Value: TBoldNetWorkProtocol); - procedure SetHostName(const Value: string); - procedure SetInitialCatalog(const Value: string); - procedure SetExtendedProperties(const Value: TStringList); - procedure SetUniConnection(const Value: TUniConnection); - function getEffectiveConnection: TUniConnection; - protected - procedure AddExtendedProperties(Result: TStrings); virtual; - procedure UpdateInternalConnectionString; virtual; - procedure Notification(AComponent: TComponent; Operation: TOperation); override; - property EffectiveConnection: TUniConnection read getEffectiveConnection; - procedure SetPassword(const Value: string); override; - procedure SetUserName(const Value: string); override; - {$IFNDEF T2H} - procedure InternalTransferproperties(const target: TBoldPersistenceHandleDB); override; - {$ENDIF} - public - constructor Create(owner: TComponent); override; - destructor Destroy; override; - function GetDataBaseInterface: IBoldDatabase; override; - procedure Assign(Source: TPersistent); override; - published - property DataSource: string read FDataSource write SetDataSource; - property Provider: string read FProvider write SetProvider; - property PersistSecurityInfo: Boolean read FPersistSecurityInfo write SetPersistSecurityInfo; - property NetWorkProtocol: TBoldNetWorkProtocol read FNetWorkProtocol write SetNetWorkProtocol; - property HostName: string read FHostName write SetHostName; - property InitialCatalog: string read FInitialCatalog write SetInitialCatalog; - property ExtendedProperties: TStringList read fExtendedProperties write SetExtendedProperties; - property UniConnection: TUniConnection read fUniConnection write SetUniConnection; - end deprecated; - -const - BoldNetWorkProtocolStringRep: array[TBoldNetWorkProtocol] of string = ('', 'tcpip', 'netbeui', 'spx'); - -function BoldStringToNetworkProtocol(s: string): TBoldNetWorkProtocol; - -implementation - -uses - SysUtils, - BoldDefs, - BoldDatabaseAdapterUniDAC, - BoldUtils, - UniDACConsts; - -function BoldStringToNetworkProtocol(s: string): TBoldNetWorkProtocol; -var - i: TBoldNetWorkProtocol; -begin - for i := low(BoldNetWorkProtocolStringRep) to high(BoldNetWorkProtocolStringRep) do - if CompareText(s, BoldNetWorkProtocolStringRep[i]) = 0 then - begin - Result := i; - exit; - end; - - Result := bnwpLocal; -end; - -{ TBoldPersistenceHandleUniDAC } - -procedure TBoldPersistenceHandleUniDAC.AddExtendedProperties( - Result: TStrings); -begin - if trim(DataSource) <> '' then - Result.Add('DSN=' + trim(DataSource)); // do not localize - if trim(HostName) <> '' then - Result.Add('Hostname=' + trim(HostName)); // do not localize - if trim(InitialCatalog) <> '' then - Result.Add('Initial Catalog=' + trim(InitialCatalog)); // do not localize - - Result.Add('NetworkProt=' + BoldNetWorkProtocolStringRep[NetWorkProtocol]); // do not localize - - Result.AddStrings(ExtendedProperties); -end; - -procedure TBoldPersistenceHandleUniDAC.Assign(Source: TPersistent); -begin - inherited; - if Source is TBoldPersistenceHandleUniDAC then - ExtendedProperties.Assign((Source as TBoldPersistenceHandleUniDAC).ExtendedProperties); -end; - -procedure TBoldPersistenceHandleUniDAC.UpdateInternalConnectionString; -const - BoolToStr: array[Boolean] of string = ('false', 'true'); -var - LExtendedProperties: TStringList; - ConnectionString: string; -begin - if Assigned(fOwnConnection) then - begin - LExtendedProperties := TStringList.Create; - AddExtendedProperties(LExtendedProperties); - - ConnectionString := format('Provider=%s;Persist Security Info=%s;Data Source=%s;Extended Properties=%s', // do not localize - [Provider, - BoolToStr[PersistSecurityInfo], - DataSource, - BoldSeparateStringList(LExtendedProperties, ';', '"', '"')]); - LExtendedProperties.Free; - fOwnConnection.ConnectString := ConnectionString; - end; -end; - -constructor TBoldPersistenceHandleUniDAC.Create(owner: TComponent); -begin - inherited; - FHostName := ''; // do not localize - fExtendedProperties := TStringList.Create; -end; - -destructor TBoldPersistenceHandleUniDAC.Destroy; -begin - Active := False; - FreeAndNil(fOwnConnection); - FreeAndNil(fConnectionAdapter); - inherited; -end; - -procedure TBoldPersistenceHandleUniDAC.SetUniConnection( - const Value: TUniConnection); -begin - if fUniConnection <> Value then - begin - CheckInactive('SetDataBase'); // do not localize - if Assigned(fOwnConnection) then - begin - FreeAndNil(fOwnConnection); - FreeAndNil(fConnectionAdapter); - end; - fUniConnection := Value; - if Assigned(fUniConnection) then - fUniConnection.FreeNotification(Self); - end; -end; - -procedure TBoldPersistenceHandleUniDAC.SetDataSource(const Value: string); -begin - FDataSource := Value; - UpdateInternalConnectionString; -end; - -procedure TBoldPersistenceHandleUniDAC.SetExtendedProperties( - const Value: TStringList); -begin - fExtendedProperties.Assign(Value); - UpdateInternalConnectionString; -end; - -procedure TBoldPersistenceHandleUniDAC.SetHostName(const Value: string); -begin - FHostName := Value; - if trim(FHostName) = '' then - FHostName := ''; // do not localize - UpdateInternalConnectionString; -end; - -procedure TBoldPersistenceHandleUniDAC.SetInitialCatalog(const Value: string); -begin - FInitialCatalog := Value; - UpdateInternalConnectionString; -end; - -procedure TBoldPersistenceHandleUniDAC.SetNetWorkProtocol( - const Value: TBoldNetWorkProtocol); -begin - FNetWorkProtocol := Value; - UpdateInternalConnectionString; -end; - -procedure TBoldPersistenceHandleUniDAC.SetPersistSecurityInfo( - const Value: Boolean); -begin - FPersistSecurityInfo := Value; - UpdateInternalConnectionString; -end; - -procedure TBoldPersistenceHandleUniDAC.SetProvider(const Value: string); -begin - FProvider := Value; - UpdateInternalConnectionString; -end; - -procedure TBoldPersistenceHandleUniDAC.Notification(AComponent: TComponent; - Operation: TOperation); -begin - inherited; - if (AComponent = fUniConnection) and (Operation = opRemove) then - begin - if AComponent = EffectiveConnection then - begin - Active := False; - fConnectionAdapter := nil; - end; - fUniConnection := nil; - end; -end; - -function TBoldPersistenceHandleUniDAC.getEffectiveConnection: TUniConnection; -begin - if Assigned(fUniConnection) then - Result := fUniConnection - else - begin - if not Assigned(fOwnConnection) then - begin - fOwnConnection := TUniConnection.Create(nil); - UpdateInternalConnectionString; - end; - Result := fOwnConnection; - end; -end; - -procedure TBoldPersistenceHandleUniDAC.SetPassword(const Value: string); -begin - inherited; - UpdateInternalConnectionString; -end; - -procedure TBoldPersistenceHandleUniDAC.SetUserName(const Value: string); -begin - inherited; - UpdateInternalConnectionString; -end; - -function TBoldPersistenceHandleUniDAC.GetDataBaseInterface: IBoldDatabase; -begin - if not Assigned(fConnectionAdapter) then - fConnectionAdapter := TBoldUniDACConnection.Create(EffectiveConnection, SQLDataBaseConfig); - Result := fConnectionAdapter; -end; - -procedure TBoldPersistenceHandleUniDAC.InternalTransferproperties( - const target: TBoldPersistenceHandleDB); -const - BoolToStr: array[Boolean] of string = ('false', 'true'); -var - Adapter: tBoldDatabaseAdapterUniDAC; - DesInfo: longint; - LExtendedProperties: TStringList; - ConnectionString: string; -begin - inherited; - DesInfo := target.DesignInfo; - if not Assigned(target.DatabaseAdapter) then - begin - target.DatabaseAdapter := tBoldDatabaseAdapterUniDAC.Create(target.owner); - target.DatabaseAdapter.Name := GetNewComponentName(target.DatabaseAdapter, 'BoldDatabaseAdapterUniDAC'); // do not localize - LongRec(DesInfo).Lo := LongRec(DesInfo).Lo + 16; //set Left - LongRec(DesInfo).Hi := LongRec(DesInfo).Hi + 16; //Set Top; - target.DatabaseAdapter.DesignInfo := DesInfo; - showmessage(sCreatedNewAdapter); - end - else if not (target.DatabaseAdapter is tBoldDatabaseAdapterUniDAC) then - raise Exception.CreateFmt(sCanOnlyTransferToUniDACAdapter, [target.DatabaseAdapter.ClassName]); - - Adapter := target.DatabaseAdapter as TBoldDatabaseAdapterUniDAC; - if Assigned(fUniConnection) then - Adapter.Connection := UniConnection; - - if not Assigned(Adapter.Connection) then - begin - Adapter.Connection := TUniConnection.Create(target.owner); - Adapter.Connection.Name := GetNewComponentName(Adapter.Connection, 'UniDACDatabase'); // do not localize - showmessage(sCreatedNewDB); - LongRec(DesInfo).Lo := LongRec(DesInfo).Lo + 16; //set Left - LongRec(DesInfo).Hi := LongRec(DesInfo).Hi + 16; //Set Top; - Adapter.Connection.DesignInfo := DesInfo; - - try - LExtendedProperties := TStringList.Create; - AddExtendedProperties(LExtendedProperties); - - ConnectionString := format('Provider=%s;Persist Security Info=%s;Data Source=%s;Extended Properties=%s', // do not localize - [Provider, - BoolToStr[PersistSecurityInfo], - DataSource, - BoldSeparateStringList(LExtendedProperties, ';', '"', '"')]); - LExtendedProperties.Free; - Adapter.Connection.ConnectString := ConnectionString; - except - on E: Exception do - begin - showmessage(sCouldNotTransferConnectionString + BOLDCRLF + BOLDCRLF + - E.Message + BOLDCRLF + BOLDCRLF + - sTransferManually); - Adapter.Connection.ConnectString := ''; - - end; - end; - - end; -end; - -end. - diff --git a/Source/Persistence/UniDAC/BoldPersistenceHandleUniDACReg.pas b/Source/Persistence/UniDAC/BoldPersistenceHandleUniDACReg.pas index 176a25c..7472df0 100644 --- a/Source/Persistence/UniDAC/BoldPersistenceHandleUniDACReg.pas +++ b/Source/Persistence/UniDAC/BoldPersistenceHandleUniDACReg.pas @@ -14,14 +14,10 @@ implementation SysUtils, Classes, BoldDatabaseAdapterUniDAC, -// BoldPersistenceHandleUniDAC, BoldIDEConsts; procedure Register; begin - {$WARNINGS OFF} -// RegisterComponents(BOLDPAGENAME_DEPRECATED, [TBoldPersistenceHandleUniDAC]); - {$WARNINGS ON} RegisterComponents(BOLDPAGENAME_PERSISTENCE, [TBoldDatabaseAdapterUniDAC]); end; From a0f0b5007675e71babae0f1f891a75c4050aeaef Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Sun, 23 May 2021 13:19:42 +0300 Subject: [PATCH 063/112] Removed deprecated BoldVariableDefinition --- Source/Handles/IDE/BoldHandleReg.pas | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Handles/IDE/BoldHandleReg.pas b/Source/Handles/IDE/BoldHandleReg.pas index 5f4c607..bce545e 100644 --- a/Source/Handles/IDE/BoldHandleReg.pas +++ b/Source/Handles/IDE/BoldHandleReg.pas @@ -41,7 +41,7 @@ implementation BoldFilteredHandle, BoldSortedHandle, BoldReferenceHandle, - BoldVariableDefinition, +// BoldVariableDefinition, BoldOclRepository, BoldTypeNameSelector, BoldModelAwareComponentEditor, @@ -101,7 +101,7 @@ procedure RegisterComponentsOnPalette; RegisterComponents(BOLDPAGENAME_DEPRECATED, [ - TBoldVariableDefinition +// TBoldVariableDefinition ]); end; From cecad53375f68cb2f8b24ed0ad9b2ea04d739ab8 Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Sun, 23 May 2021 13:21:04 +0300 Subject: [PATCH 064/112] Unified Create/Drop/Exists database templates, use DatabaseNameMarker and added methods. --- Source/PMapper/SQL/BoldSQLDatabaseConfig.pas | 52 ++++++++++++++++++-- 1 file changed, 48 insertions(+), 4 deletions(-) diff --git a/Source/PMapper/SQL/BoldSQLDatabaseConfig.pas b/Source/PMapper/SQL/BoldSQLDatabaseConfig.pas index b422d3e..cd1ad7e 100644 --- a/Source/PMapper/SQL/BoldSQLDatabaseConfig.pas +++ b/Source/PMapper/SQL/BoldSQLDatabaseConfig.pas @@ -184,6 +184,9 @@ TBoldSQLDataBaseConfig = class(TPersistent) destructor Destroy; override; procedure Assign(Source: TPersistent); override; procedure AssignConfig(Source: TBoldSQLDataBaseConfig); + function GetCreateDatabaseQuery(const DatabaseName: String): String; + function GetDropDatabaseQuery(const DatabaseName: String): String; + function GetDatabaseExistsQuery(const DatabaseName: String): String; function GetDropColumnQuery(const TableName, columnName: String): String; function GetDropIndexQuery(const TableName, IndexName: String): String; function GetDropTableQuery(const TableName: String): String; @@ -282,6 +285,7 @@ implementation const EmptyMarker = ''; + DatabaseNameMarker = ''; TableNameMarker = ''; ColumnNameMarker = ''; IndexNameMarker = ''; @@ -627,6 +631,45 @@ function TBoldSQLDataBaseConfig.GetColumnTypeForUnicodeString( Result := Format(ColumnTypeForUnicodeText, [Size]); end; +function TBoldSQLDataBaseConfig.GetCreateDatabaseQuery( + const DatabaseName: String): String; +begin + Result := ''; + if CreateDatabaseTemplate <> '' then begin + Result := CreateDatabaseTemplate; + Result := StringReplace(result, DatabaseNameMarker, DatabaseName, [rfIgnoreCase, rfReplaceAll]); + end else begin + raise EBold.Create('Please set the template in the SQLDatabaseConfig ' + + 'for CreateDatabaseTemplate.'); + end; +end; + +function TBoldSQLDataBaseConfig.GetDatabaseExistsQuery( + const DatabaseName: String): String; +begin + Result := ''; + if DatabaseExistsTemplate <> '' then begin + Result := DatabaseExistsTemplate; + Result := StringReplace(result, DatabaseNameMarker, DatabaseName, [rfIgnoreCase, rfReplaceAll]); + end else begin + raise EBold.Create('Please set the template in the SQLDatabaseConfig ' + + 'for DatabaseExistsTemplate.'); + end; +end; + +function TBoldSQLDataBaseConfig.GetDropDatabaseQuery( + const DatabaseName: String): String; +begin + Result := ''; + if DropDatabaseTemplate <> '' then begin + Result := DropDatabaseTemplate; + Result := StringReplace(result, DatabaseNameMarker, DatabaseName, [rfIgnoreCase, rfReplaceAll]); + end else begin + raise EBold.Create('Please set the template in the SQLDatabaseConfig ' + + 'for DropDatabaseTemplate.'); + end; +end; + function TBoldSQLDataBaseConfig.GetDropColumnQuery(const TableName: string; const columnName: String): String; begin Result := ''; @@ -760,8 +803,8 @@ procedure TBoldSQLDataBaseConfig.SetInitialValues; fIgnoreMissingObjects := false; fAllowMetadataChangesInTransaction := true; fDBGenerationMode := dbgQuery; - fCreateDatabaseTemplate := 'CREATE DATABASE %s'; - fDropDatabaseTemplate := 'DROP DATABASE %s'; + fCreateDatabaseTemplate := 'CREATE DATABASE '; + fDropDatabaseTemplate := 'DROP DATABASE '; fDatabaseExistsTemplate := ''; fDropColumnTemplate := 'ALTER TABLE DROP '; fDropTableTemplate := 'DROP TABLE '; @@ -890,7 +933,7 @@ procedure TBoldSQLDataBaseConfig.InitializeDbEngineSettings(Engine: TBoldDatabas fMaxIndexNameLength := 63; fMaxDbIdentifierLength := 63; fMultiRowInsertLimit := 1000; - fDatabaseExistsTemplate := 'select exists(SELECT datname FROM pg_catalog.pg_database WHERE lower(datname) = lower(''%s''));'; + fDatabaseExistsTemplate := 'select exists(SELECT datname FROM pg_catalog.pg_database WHERE lower(datname) = lower(''''));'; // IndexInfoTemplate := 'select indexname from pg_indexes where tablename = '''''; // this is not complete IndexName, IsPrimary, IsUnique, ColumnName fReservedWords.Text := 'ALL, ANALYSE, AND, ANY, ARRAY, AS, ASC, ASYMMETRIC, AUTHORIZATION,'#10 + // do not localize 'BETWEEN, BINARY, BOOLEAN, BOTH, CASE, CAST, CHAR, CHARACTER, CHECK,'#10 + // do not localize @@ -927,7 +970,8 @@ procedure TBoldSQLDataBaseConfig.InitializeDbEngineSettings(Engine: TBoldDatabas fColumnTypeForDate := 'DATETIME'; // do not localize fColumnTypeForTime := 'DATETIME'; // do not localize fColumnTypeForDateTime := 'DATETIME'; // do not localize - fDatabaseExistsTemplate := 'IF EXISTS (SELECT name FROM master.sys.databases WHERE name = N''%s'')'; + fCreateDatabaseTemplate := 'USE MASTER;GO;CREATE DATABASE '; + fDatabaseExistsTemplate := 'IF EXISTS (SELECT name FROM master.sys.databases WHERE name = N'''')'; fColumnTypeForFloat := 'DECIMAL (28,10)'; // do not localize fColumnTypeForCurrency := 'DECIMAL (28,10)'; // do not localize fColumnTypeForText := 'VARCHAR(MAX)'; // do not localize From 9b9e78a9a528eb4c0a974cd9f9b9d8b8e3294171 Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Sun, 23 May 2021 13:22:29 +0300 Subject: [PATCH 065/112] Use new db templates --- .../FireDAC/BoldFireDACInterfaces.pas | 6 ++-- .../UniDAC/BoldUniDACInterfaces.pas | 28 ++++--------------- 2 files changed, 8 insertions(+), 26 deletions(-) diff --git a/Source/Persistence/FireDAC/BoldFireDACInterfaces.pas b/Source/Persistence/FireDAC/BoldFireDACInterfaces.pas index 74e5546..c4b5e7b 100644 --- a/Source/Persistence/FireDAC/BoldFireDACInterfaces.pas +++ b/Source/Persistence/FireDAC/BoldFireDACInterfaces.pas @@ -913,7 +913,7 @@ function TBoldFireDACConnection.DatabaseExists: boolean; FDConnection.Params.Database := ''; // need to clear this to connect succesfully vQuery := GetQuery; try - vQuery.SQLText := Format(SQLDataBaseConfig.DatabaseExistsTemplate , [vDatabaseName]); + vQuery.SQLText := SQLDataBaseConfig.GetDatabaseExistsQuery(vDatabaseName); vQuery.Open; result := vQuery.Fields[0].AsBoolean; finally @@ -939,7 +939,7 @@ procedure TBoldFireDACConnection.DropDatabase; vScript := TFDScript.Create(nil); sl := TStringList.Create; try - sl.Text := Format(SQLDataBaseConfig.DropDatabaseTemplate , [vDatabaseName]); + sl.Text := SQLDataBaseConfig.GetDropDatabaseQuery(vDatabaseName); vScript.Connection := FDConnection; vScript.ExecuteScript(sl); FDConnection.Close; @@ -984,7 +984,7 @@ procedure TBoldFireDACConnection.CreateDatabase(DropExisting: boolean = true); vScript := TFDScript.Create(nil); sl := TStringList.Create; try - sl.Text := Format(SQLDataBaseConfig.CreateDatabaseTemplate , [vDatabaseName]); + sl.Text := SQLDataBaseConfig.GetCreateDatabaseQuery(vDatabaseName); vScript.Connection := FDConnection; vScript.ExecuteScript(sl); FDConnection.Close; diff --git a/Source/Persistence/UniDAC/BoldUniDACInterfaces.pas b/Source/Persistence/UniDAC/BoldUniDACInterfaces.pas index 45c840c..edd0238 100644 --- a/Source/Persistence/UniDAC/BoldUniDACInterfaces.pas +++ b/Source/Persistence/UniDAC/BoldUniDACInterfaces.pas @@ -874,7 +874,7 @@ function TBoldUniDACConnection.DatabaseExists: boolean; vQuery := GetQuery; try (vQuery.Implementor as TUniQuery).Connection := UniConnection; - vQuery.SQLText := Format(SQLDataBaseConfig.DatabaseExistsTemplate, [vDatabaseName]); + vQuery.SQLText := SQLDataBaseConfig.GetDatabaseExistsQuery(vDatabaseName); vQuery.Open; result := vQuery.Fields[0].AsBoolean; finally @@ -961,39 +961,21 @@ procedure TBoldUniDACConnection.Close; procedure TBoldUniDACConnection.CreateDatabase; var - vQuery: IBoldExecQuery; vDatabaseName: string; vUniScript: TUniScript; - vIsInterbase: boolean; - vIsMSSQL: boolean; -const - cInterbase = 'InterBase'; - cMSSQL = 'SQL Server'; - cDropDatabaseSQL = 'Drop Database %s'; - cGenerateDatabaseSQL = 'Create Database %s'; - cGenerateDatabaseInterbaseSQL = 'Create Database ''%s'' user ''%s'' password ''%s'''; - cGenerateDatabaseSQLServer = 'USE master;' + BOLDCRLF + 'GO' + BOLDCRLF + ' Create Database %s'; begin vDatabaseName := LowerCase(UniConnection.Database); // UniConnection.Database := ''; // need to clear this to connect succesfully vUniScript := TUniScript.Create(nil); try vUniScript.Connection := UniConnection; - vIsInterbase := UniConnection.ProviderName = cInterBase; - vIsMSSQL := UniConnection.ProviderName = cMSSQL; - vUniScript.SQL.Text := Format(SQLDatabaseConfig.DropDatabaseTemplate, [vDatabaseName]); - if vIsMSSQL then - UniConnection.Database := 'master'; - try - vUniScript.Execute; - except - // ignore - end; + vUniScript.SQL.Text := SQLDataBaseConfig.GetCreateDatabaseQuery(vDatabaseName); + vUniScript.Execute; UniConnection.Close; finally + UniConnection.Close; vUniScript.free; - if vIsMSSQL then - UniConnection.Database := vDatabaseName; + UniConnection.Database := vDatabaseName; end; end; From aeb2421cbf260c6ca432da94cb4489cf6a73042d Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Sun, 23 May 2021 13:23:49 +0300 Subject: [PATCH 066/112] Cleaned up uses --- Source/Samples/Actions/BoldEditOCLAction.pas | 1 - Source/UMLModel/Editor/BoldUMLModelEditForm.pas | 6 ++---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/Source/Samples/Actions/BoldEditOCLAction.pas b/Source/Samples/Actions/BoldEditOCLAction.pas index 001aaa4..f112e90 100644 --- a/Source/Samples/Actions/BoldEditOCLAction.pas +++ b/Source/Samples/Actions/BoldEditOCLAction.pas @@ -45,7 +45,6 @@ implementation uses SysUtils, - BoldIDEConsts, BoldOclPropEditor, BoldDefs; diff --git a/Source/UMLModel/Editor/BoldUMLModelEditForm.pas b/Source/UMLModel/Editor/BoldUMLModelEditForm.pas index 2ec00c7..bb8b15a 100644 --- a/Source/UMLModel/Editor/BoldUMLModelEditForm.pas +++ b/Source/UMLModel/Editor/BoldUMLModelEditForm.pas @@ -764,7 +764,7 @@ implementation //BoldSystemDebuggerForm, BoldPMapperLists, BoldDefs, - BoldDefsDT, +// BoldDefsDT, BoldGUI, BoldQueue, BoldUMLUsesEditorForm, @@ -1331,7 +1331,7 @@ procedure TBoldModelEditFrm.FormCreate(Sender: TObject); SetCheckBoxHints; popTree.AutoHotkeys := maManual; - HelpFile := MODELEDITORHELPFILE; +// HelpFile := MODELEDITORHELPFILE; CutOrCopy := cckNone; @@ -2853,6 +2853,4 @@ procedure TBoldModelEditFrm.SetCheckBoxHints; TBoldCheckBox(Components[i]).Hint := StripHotkey(TBoldCheckBox(Components[i]).Caption); end; -initialization - end. From dff051088db109321ef94623dad27ee7df6df7cc Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Sun, 23 May 2021 13:24:55 +0300 Subject: [PATCH 067/112] Replaced BoldSoft with boldfordelphi link --- Source/Common/IDE/BoldDefsDT.pas | 5 ++--- Source/Common/IDE/BoldIDEMenus.pas | 9 +-------- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/Source/Common/IDE/BoldDefsDT.pas b/Source/Common/IDE/BoldDefsDT.pas index 66dc2b5..36ca6aa 100644 --- a/Source/Common/IDE/BoldDefsDT.pas +++ b/Source/Common/IDE/BoldDefsDT.pas @@ -18,9 +18,8 @@ interface ATTRIBUTEWIZARDHELPFILE = 'boldattributewizard.hlp'; MODELEDITORHELPFILE = 'boldmodeleditor.hlp'; - URLBoldSoft = 'http://www.boldsoft.com'; - URLBoldForDelphi = 'http://www.boldsoft.com'; - URLSupport = 'http://www.boldsoft.com'; + URLBoldForDelphi = 'http://www.boldfordelphi.com'; + URLSupport = 'http://www.forum.boldfordelphi.com'; GETTINGSTARTEDPATH = '\doc\frames\'; GETTINGSTARTEDDOCNAME = 'getting_started_f.html'; diff --git a/Source/Common/IDE/BoldIDEMenus.pas b/Source/Common/IDE/BoldIDEMenus.pas index 6106bbf..a9d2242 100644 --- a/Source/Common/IDE/BoldIDEMenus.pas +++ b/Source/Common/IDE/BoldIDEMenus.pas @@ -30,7 +30,6 @@ TBoldMenuExpert = class(TBoldExpert) {Menu Actions} procedure ActionAbout(Sender: TObject); procedure ActionHelp(Sender: TObject); - procedure ActionURLHome(Sender: TObject); procedure ActionURLBfD(Sender: TObject); {Properties} property BoldMenu: TMenuItem read fBoldMenu; @@ -88,11 +87,6 @@ procedure TBoldMenuExpert.ActionURLBfD(Sender: TObject); ShellExecute(0, 'open', URLBoldForDelphi, '', '', SW_SHOWMAXIMIZED); end; -procedure TBoldMenuExpert.ActionURLHome(Sender: TObject); -begin - ShellExecute(0, 'open', URLBoldSoft, '', '', SW_SHOWMAXIMIZED); -end; - function TBoldMenuExpert.AddMenuItem(aName, aCaption: string; aClickEvent: TNotifyEvent; first: Boolean = false): TMenuItem; begin if not IsInIDE then @@ -133,12 +127,11 @@ procedure TBoldMenuExpert.CreateBaseMenuItems; Inc(I); AddMenuItem('BoldURLDelimiterMenu', '-', nil); - AddMenuItem('BoldHomePageMenu', '&BoldSoft Home Page', ActionURLHome); AddMenuItem('BoldBfDHomePageMenu', 'Bold for &Delphi Home Page', ActionURLBfD); AddMenuItem('BoldHelpDelimiterMenu', '-', nil); AddMenuItem('BoldHelpMenu', '&Help', ActionHelp); AddMenuItem('BoldAboutDelimiterMenu', '-', nil); - AddMenuItem('BoldAboutMenu', '&About', ActionAbout); +// AddMenuItem('BoldAboutMenu', '&About', ActionAbout); MainMenu.Items.Insert(I, fBoldMenu); end; From e90a2b1fa570c2a0b2a51be704703d4b0a5b574e Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Sun, 23 May 2021 13:25:28 +0300 Subject: [PATCH 068/112] CreateDBAction now uses DropExisting param --- Source/Handles/Actions/BoldActions.pas | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Source/Handles/Actions/BoldActions.pas b/Source/Handles/Actions/BoldActions.pas index d6027e6..b1b33fe 100644 --- a/Source/Handles/Actions/BoldActions.pas +++ b/Source/Handles/Actions/BoldActions.pas @@ -95,6 +95,7 @@ TBoldCreateDatabaseAction = class(TBoldSystemHandleAction) private fOnSchemaGenerated: TNotifyEvent; fIgnoreUnknownTables: boolean; + fDropExisting: boolean; procedure SchemaGenerated; protected procedure GenerateSchema; @@ -104,7 +105,8 @@ TBoldCreateDatabaseAction = class(TBoldSystemHandleAction) procedure ExecuteTarget(Target: TObject); override; published property OnSchemaGenerated: TNotifyEvent read fOnSchemaGenerated write fOnSchemaGenerated; - property IgnoreUnknownTables: boolean read fIgnoreUnknownTables write fIgnoreUnknownTables; + property IgnoreUnknownTables: boolean read fIgnoreUnknownTables write fIgnoreUnknownTables default false; + property DropExisting: boolean read fDropExisting write fDropExisting default false; end; implementation @@ -333,7 +335,7 @@ procedure TBoldCreateDatabaseAction.GenerateSchema; begin Screen.Cursor := crHourGlass; try - BoldSystemHandle.PersistenceHandleDB.CreateDataBase; + BoldSystemHandle.PersistenceHandleDB.CreateDataBase(DropExisting); BoldSystemHandle.PersistenceHandleDB.CreateDataBaseSchema(IgnoreUnknownTables); finally Screen.Cursor := crDefault; From 49a0e0d46e3eb496149f5d5888b1e2bc1509ada7 Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Sun, 23 May 2021 13:33:35 +0300 Subject: [PATCH 069/112] Updated gitignore for Delphi file types --- .gitignore | 40 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index e0e4ceb..ba3acfa 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,39 @@ - +# Delphi compiler-generated binaries (safe to delete) +*.exe +*.dll +*.bpl +*.bpi +*.dcp +*.so +*.apk +*.drc +*.map +*.dres +*.rsm +*.tds *.dcu -*.~1~ -*.~2~ +*.lib +*.a +*.o +*.ocx + +# Delphi autogenerated files (duplicated info) +*.cfg +*.hpp +*Resource.rc + + +# Delphi local files (user-specific info) *.local -*.dsk *.identcache +*.projdata +*.tvsconfig +*.dsk + +# Delphi history and backups +__history/ +__recovery/ +*.~* + +# Castalia statistics file (since XE7 Castalia is distributed with Delphi) +*.stat \ No newline at end of file From 45faf2a9c7f16a34c95f5145e9db577064328f25 Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Sun, 23 May 2021 13:35:41 +0300 Subject: [PATCH 070/112] Turned on LightMemberDeriver and DebugInstanceCounter conditionals. --- Source/Common/Include/Bold.inc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Common/Include/Bold.inc b/Source/Common/Include/Bold.inc index 6ef4683..5a753e2 100644 --- a/Source/Common/Include/Bold.inc +++ b/Source/Common/Include/Bold.inc @@ -421,10 +421,10 @@ Illegal symbol combination {$DEFINE CompareToOldValues} // Debug addon to count instances per subclass of TBoldMemoryManagedObject -{.$DEFINE DebugInstanceCounter} +{$DEFINE DebugInstanceCounter} // It saves memory to use LightMemberDeriver, but FormSaver is not compatible with LightMemberDeriver -{.$DEFINE LightMemberDeriver} +{$DEFINE LightMemberDeriver} // Define to use string comparison for all attributes. This may be faster, it uses IBoldStringRepresentable // but assumes each value has distinct string representation. From fac6c99443a8765c0abab1a9b79c85a251e6d30e Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Sun, 23 May 2021 13:36:36 +0300 Subject: [PATCH 071/112] Removed copyright header --- Source/Persistence/FireDAC/BoldFireDACInterfaces.pas | 8 -------- 1 file changed, 8 deletions(-) diff --git a/Source/Persistence/FireDAC/BoldFireDACInterfaces.pas b/Source/Persistence/FireDAC/BoldFireDACInterfaces.pas index c4b5e7b..14d88c1 100644 --- a/Source/Persistence/FireDAC/BoldFireDACInterfaces.pas +++ b/Source/Persistence/FireDAC/BoldFireDACInterfaces.pas @@ -1,12 +1,4 @@ -///////////////////////////////////////////////////////// -// // -// Bold for Delphi // -// Copyright (c) 1996-2002 Boldsoft AB // -// (c) 2002-2005 Borland Software Corp // -// // -///////////////////////////////////////////////////////// - { Global compiler directives } {$include bold.inc} unit BoldFireDACInterfaces; From 519a7a982db8b35d34228a6cb977cfca2b9c14fd Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Sun, 23 May 2021 21:07:56 +0300 Subject: [PATCH 072/112] Reorganized packages, added BoldDevEx --- BoldAdditional.dpk | 211 + BoldAdditional.dproj | 1033 +++ BoldCore.dpk | 282 + BoldDesignPackage.dproj => BoldCore.dproj | 716 +- BoldDesignPackage.dpk | 540 -- BoldForDelphi.groupproj | 260 +- BoldUniDAC.dpk | 3 +- .../BoldDevex/BoldAFPCxGridProviderUnit.pas | 196 + .../BoldDevex/BoldToCxConverterForm.dfm | 112 + .../BoldDevex/BoldToCxConverterForm.pas | 55 + .../BoldDevex/BoldToCxConverterUnit.pas | 804 +++ .../BoldDevex/BoldToCxGridConverterUnit.pas | 106 + .../BoldDevex/cxBoldEditConsts.pas | 39 + .../BoldDevex/cxBoldEditRepositoryItems.pas | 134 + .../BoldAwareGUI/BoldDevex/cxBoldEditors.pas | 6369 +++++++++++++++++ .../BoldDevex/cxBoldExtLookupComboBox.pas | 1042 +++ .../BoldDevex/cxBoldLookupComboBox.pas | 655 ++ .../BoldDevex/cxBoldLookupEdit.pas | 804 +++ .../BoldAwareGUI/BoldDevex/cxBoldRegUnit.dcr | Bin 0 -> 24544 bytes .../BoldAwareGUI/BoldDevex/cxBoldRegUnit.pas | 344 + .../BoldDevex/cxGridBoldSupportUnit.pas | 6292 ++++++++++++++++ .../BoldDevex/cxLookupBoldGrid.pas | 629 ++ .../BoldAwareGUI/BoldDevex/dxBarBoldNav.pas | 515 ++ .../BoldAwareGUI/BoldDevex/dxBarBoldNav.res | Bin 0 -> 2996 bytes dclBold.dpk | 149 + dclBold.dproj | 975 +++ dclBoldDevEx.dpk | 56 + dclBoldDevEx.dproj | 878 +++ BoldFireDAC.dpk => dclBoldUniDAC.dpk | 18 +- BoldFireDAC.dproj => dclBoldUniDAC.dproj | 51 +- 30 files changed, 22004 insertions(+), 1264 deletions(-) create mode 100644 BoldAdditional.dpk create mode 100644 BoldAdditional.dproj create mode 100644 BoldCore.dpk rename BoldDesignPackage.dproj => BoldCore.dproj (65%) delete mode 100644 BoldDesignPackage.dpk create mode 100644 Source/BoldAwareGUI/BoldDevex/BoldAFPCxGridProviderUnit.pas create mode 100644 Source/BoldAwareGUI/BoldDevex/BoldToCxConverterForm.dfm create mode 100644 Source/BoldAwareGUI/BoldDevex/BoldToCxConverterForm.pas create mode 100644 Source/BoldAwareGUI/BoldDevex/BoldToCxConverterUnit.pas create mode 100644 Source/BoldAwareGUI/BoldDevex/BoldToCxGridConverterUnit.pas create mode 100644 Source/BoldAwareGUI/BoldDevex/cxBoldEditConsts.pas create mode 100644 Source/BoldAwareGUI/BoldDevex/cxBoldEditRepositoryItems.pas create mode 100644 Source/BoldAwareGUI/BoldDevex/cxBoldEditors.pas create mode 100644 Source/BoldAwareGUI/BoldDevex/cxBoldExtLookupComboBox.pas create mode 100644 Source/BoldAwareGUI/BoldDevex/cxBoldLookupComboBox.pas create mode 100644 Source/BoldAwareGUI/BoldDevex/cxBoldLookupEdit.pas create mode 100644 Source/BoldAwareGUI/BoldDevex/cxBoldRegUnit.dcr create mode 100644 Source/BoldAwareGUI/BoldDevex/cxBoldRegUnit.pas create mode 100644 Source/BoldAwareGUI/BoldDevex/cxGridBoldSupportUnit.pas create mode 100644 Source/BoldAwareGUI/BoldDevex/cxLookupBoldGrid.pas create mode 100644 Source/BoldAwareGUI/BoldDevex/dxBarBoldNav.pas create mode 100644 Source/BoldAwareGUI/BoldDevex/dxBarBoldNav.res create mode 100644 dclBold.dpk create mode 100644 dclBold.dproj create mode 100644 dclBoldDevEx.dpk create mode 100644 dclBoldDevEx.dproj rename BoldFireDAC.dpk => dclBoldUniDAC.dpk (52%) rename BoldFireDAC.dproj => dclBoldUniDAC.dproj (95%) diff --git a/BoldAdditional.dpk b/BoldAdditional.dpk new file mode 100644 index 0000000..d94d8a6 --- /dev/null +++ b/BoldAdditional.dpk @@ -0,0 +1,211 @@ +package BoldAdditional; + +{$R *.res} +{$IFDEF IMPLICITBUILDING This IFDEF should not be used by users} +{$ALIGN 8} +{$ASSERTIONS ON} +{$BOOLEVAL OFF} +{$DEBUGINFO OFF} +{$EXTENDEDSYNTAX ON} +{$IMPORTEDDATA ON} +{$IOCHECKS ON} +{$LOCALSYMBOLS ON} +{$LONGSTRINGS ON} +{$OPENSTRINGS ON} +{$OPTIMIZATION OFF} +{$OVERFLOWCHECKS OFF} +{$RANGECHECKS OFF} +{$REFERENCEINFO ON} +{$SAFEDIVIDE OFF} +{$STACKFRAMES ON} +{$TYPEDADDRESS OFF} +{$VARSTRINGCHECKS ON} +{$WRITEABLECONST OFF} +{$MINENUMSIZE 1} +{$IMAGEBASE $400000} +{$DEFINE DEBUG} +{$ENDIF IMPLICITBUILDING} +{$DESCRIPTION 'Bold for Delphi - Additional'} +{$LIBVERSION '27'} +{$RUNONLY} +{$IMPLICITBUILD OFF} + +requires + vcl, + vcldb, + vclx, + FireDac, + FireDACCommonDriver, + FireDACCommon, + FireDACPgDriver, + IndySystem, + IndyCore, + BoldCore; + +contains + BoldAbstractComClientPersistenceHandles in 'Source\Persistence\COM\BoldAbstractComClientPersistenceHandles.pas', + BoldAbstractComPersistenceControllerProxy in 'Source\Persistence\COM\BoldAbstractComPersistenceControllerProxy.pas', + BoldAction in 'Source\BoldAwareGUI\Actions\BoldAction.pas', + BoldAFP in 'Source\BoldAwareGUI\FormGen\BoldAFP.pas', + BoldAFPDefault in 'Source\BoldAwareGUI\FormGen\BoldAFPDefault.pas', + BoldAFPPluggable in 'Source\BoldAwareGUI\FormGen\BoldAFPPluggable.pas', + BoldAFPUser in 'Source\BoldAwareGUI\FormGen\BoldAFPUser.pas', + BoldApartmentThread in 'Source\Common\COM\BoldApartmentThread.pas', + BoldCaptionController in 'Source\BoldAwareGUI\BoldControls\BoldCaptionController.pas', + BoldCheckBox in 'Source\BoldAwareGUI\BoldControls\BoldCheckBox.pas', + BoldCheckboxStateControlPack in 'Source\BoldAwareGUI\ControlPacks\BoldCheckboxStateControlPack.pas', + BoldCheckListBox in 'Source\Samples\BoldCheckListBox\BoldCheckListBox.pas', + BoldComAdapter in 'Source\Common\COM\BoldComAdapter.pas', + BoldComboBox in 'Source\BoldAwareGUI\BoldControls\BoldComboBox.pas', + BoldComClient in 'Source\Common\ConnectionCOM\BoldComClient.pas', + BoldComClientElementHandles in 'Source\Handles\COM\BoldComClientElementHandles.pas', + BoldComClientHandles in 'Source\Common\ConnectionHandlesCOM\BoldComClientHandles.pas', + BoldComConnection in 'Source\Common\ConnectionCOM\BoldComConnection.pas', + BoldComConst in 'Source\Common\COM\BoldComConst.pas', + BoldComEventQueue in 'Source\Common\COM\BoldComEventQueue.pas', + BoldComObj in 'Source\Common\COM\BoldComObj.pas', + BoldComObjectSpace in 'Source\ObjectSpace\COM\BoldComObjectSpace.pas', + BoldComObjectSpace_TLB in 'Source\ObjectSpace\COM\BoldComObjectSpace_TLB.pas', + BoldComObjectSpaceAdapters in 'Source\ObjectSpace\COM\BoldComObjectSpaceAdapters.pas', + BoldComponentValidatorCom in 'Source\ObjectSpace\COM\BoldComponentValidatorCom.pas', + BoldComServer in 'Source\Common\ConnectionCOM\BoldComServer.pas', + BoldComServerElementHandleFactory in 'Source\Handles\COM\BoldComServerElementHandleFactory.pas', + BoldComServerElementHandles in 'Source\Handles\COM\BoldComServerElementHandles.pas', + BoldComServerHandles in 'Source\Common\ConnectionHandlesCOM\BoldComServerHandles.pas', + BoldComThreads in 'Source\Common\COM\BoldComThreads.pas', + BoldComUtils in 'Source\Common\COM\BoldComUtils.pas', + BoldConstraintValidator in 'Source\Samples\ConstraintValidator\BoldConstraintValidator.pas', + BoldControllerListControlPack in 'Source\BoldAwareGUI\ControlPacks\BoldControllerListControlPack.pas', + BoldControlPack in 'Source\BoldAwareGUI\ControlPacks\BoldControlPack.pas', + BoldCustomCheckListBox in 'Source\Samples\BoldCheckListBox\BoldCustomCheckListBox.pas', + BoldDatabaseAdapterFireDAC in 'Source\Persistence\FireDAC\BoldDatabaseAdapterFireDAC.pas', + BoldDateTimeControlPack in 'Source\BoldAwareGUI\ControlPacks\BoldDateTimeControlPack.pas', + BoldDbPlugins in 'Source\UMLModel\Plugins\BoldDbPlugins.pas', + BoldDebugActions in 'Source\Samples\Actions\BoldDebugActions.pas', + BoldDerivationExpressionsEditor in 'Source\UMLModel\Editor\BoldDerivationExpressionsEditor.pas', + BoldDragDropTarget in 'Source\BoldAwareGUI\BoldControls\BoldDragDropTarget.pas', + BoldDragObject in 'Source\UMLModel\Editor\BoldDragObject.pas', + BoldEdit in 'Source\BoldAwareGUI\BoldControls\BoldEdit.pas', + BoldEditOCLAction in 'Source\Samples\Actions\BoldEditOCLAction.pas', + BoldElementHandleFollower in 'Source\BoldAwareGUI\ControlPacks\BoldElementHandleFollower.pas', + BoldEnvironmentIDE in 'Source\Common\Environment\BoldEnvironmentIDE.pas', + BoldExceptionHandlers in 'Source\BoldAwareGUI\Core\BoldExceptionHandlers.pas', + BoldFireDACConsts in 'Source\Persistence\FireDAC\BoldFireDACConsts.pas', + BoldFireDACInterfaces in 'Source\Persistence\FireDAC\BoldFireDACInterfaces.pas', + BoldFloatControlPack in 'Source\BoldAwareGUI\ControlPacks\BoldFloatControlPack.pas', + BoldFormSaver in 'Source\Samples\FormSaver\BoldFormSaver.pas', + BoldFormSaverActions in 'Source\Samples\FormSaver\BoldFormSaverActions.pas', + BoldGen in 'Source\MoldModel\CodeGenerator\BoldGen.pas', + BoldGeneratorTemplates in 'Source\MoldModel\CodeGenerator\BoldGeneratorTemplates.pas', + BoldGeneratorTemplatesCPP in 'Source\MoldModel\CodeGenerator\BoldGeneratorTemplatesCPP.pas', + BoldGeneratorTemplatesDelphi in 'Source\MoldModel\CodeGenerator\BoldGeneratorTemplatesDelphi.pas', + BoldGenericListControlPack in 'Source\BoldAwareGUI\ControlPacks\BoldGenericListControlPack.pas', + BoldGrid in 'Source\BoldAwareGUI\BoldControls\BoldGrid.pas', + BoldGridRTColEditor in 'Source\BoldAwareGUI\BoldControls\BoldGridRTColEditor.pas', + BoldGUI in 'Source\BoldAwareGUI\Core\BoldGUI.pas', + BoldGuiResourceStrings in 'Source\BoldAwareGUI\Core\BoldGuiResourceStrings.pas', + BoldHTTPClientPersistenceHandle in 'Source\Persistence\HTTP\BoldHTTPClientPersistenceHandle.pas', + BoldHTTPPersistenceControllerClient in 'Source\Persistence\HTTP\BoldHTTPPersistenceControllerClient.pas', + BoldHTTPServerPersistenceHandlePassthrough in 'Source\Persistence\HTTP\BoldHTTPServerPersistenceHandlePassthrough.pas', + BoldImage in 'Source\BoldAwareGUI\BoldControls\BoldImage.pas', + BoldImageBitmap in 'Source\BoldAwareGUI\BoldControls\BoldImageBitmap.pas', + BoldImageJPEG in 'Source\BoldAwareGUI\BoldControls\BoldImageJPEG.pas', + BoldLabel in 'Source\BoldAwareGUI\BoldControls\BoldLabel.pas', + BoldListBox in 'Source\BoldAwareGUI\BoldControls\BoldListBox.pas', + BoldListControlPack in 'Source\BoldAwareGUI\ControlPacks\BoldListControlPack.pas', + BoldListHandleFollower in 'Source\BoldAwareGUI\ControlPacks\BoldListHandleFollower.pas', + BoldListListControlPack in 'Source\BoldAwareGUI\ControlPacks\BoldListListControlPack.pas', + BoldLockManagerAdminHandleCom in 'Source\ConcurrencyControl\COM\BoldLockManagerAdminHandleCom.pas', + BoldLockManagerHandleCom in 'Source\ConcurrencyControl\COM\BoldLockManagerHandleCom.pas', + BoldLockUtils in 'Source\Samples\Misc\BoldLockUtils.pas', + BoldMemo in 'Source\BoldAwareGUI\BoldControls\BoldMemo.pas', + BoldMLRenderers in 'Source\BoldAwareGUI\ControlPacks\BoldMLRenderers.pas', + BoldModel in 'Source\UMLModel\Handles\BoldModel.pas', + BoldModelLoader in 'Source\Samples\ModelLoader\BoldModelLoader.pas', + BoldModelOCLValidatorPlugIn in 'Source\UMLModel\Plugins\BoldModelOCLValidatorPlugIn.pas', + BoldNavigator in 'Source\BoldAwareGUI\BoldControls\BoldNavigator.pas', + BoldNewObjectInterceptor in 'Source\Samples\NewObjectInterceptor\BoldNewObjectInterceptor.pas', + BoldNodeControlPack in 'Source\BoldAwareGUI\ControlPacks\BoldNodeControlPack.pas', + BoldNumericControlPack in 'Source\BoldAwareGUI\ControlPacks\BoldNumericControlPack.pas', + BoldObjectRetriever in 'Source\Samples\Misc\BoldObjectRetriever.pas', + BoldPageControl in 'Source\BoldAwareGUI\BoldControls\BoldPageControl.pas', + BoldPersistenceControllerSOAPAdapterCore in 'Source\Persistence\SOAP\BoldPersistenceControllerSOAPAdapterCore.pas', + BoldPersistenceOperationXMLStreaming in 'Source\Persistence\SOAP\BoldPersistenceOperationXMLStreaming.pas', + BoldProgressBar in 'Source\BoldAwareGUI\BoldControls\BoldProgressBar.pas', + BoldPropagatorHandleCOM in 'Source\Propagator\COM\BoldPropagatorHandleCOM.pas', + BoldPropagatorUtils in 'Source\Persistence\Propagation\BoldPropagatorUtils.pas', + BoldPropertiesController in 'Source\BoldAwareGUI\BoldControls\BoldPropertiesController.pas', + BoldRichEdit in 'Source\BoldAwareGUI\BoldControls\BoldRichEdit.pas', + BoldRose2000Support in 'Source\Common\Rose2000\BoldRose2000Support.pas', + BoldRose98ptyCreator in 'Source\UMLModel\ModelLinks\Rose98\BoldRose98ptyCreator.pas', + BoldRose98Support in 'Source\Common\Rose98\BoldRose98Support.pas', + BoldRose98TaggedValues in 'Source\UMLModel\ModelLinks\Rose98\BoldRose98TaggedValues.pas', + BoldSelectionListBox in 'Source\Samples\BoldCheckListBox\BoldSelectionListBox.pas', + BoldSOAPClientPersistenceHandles in 'Source\Persistence\SOAP\BoldSOAPClientPersistenceHandles.pas', + BoldSOAPPersistenceControllerProxy in 'Source\Persistence\SOAP\BoldSOAPPersistenceControllerProxy.pas', + BoldSOAPPersistenceControllerStub in 'Source\Persistence\SOAP\BoldSOAPPersistenceControllerStub.pas', + BoldSOAPServerPersistenceHandles in 'Source\Persistence\SOAP\BoldSOAPServerPersistenceHandles.pas', + BoldStringControlPack in 'Source\BoldAwareGUI\ControlPacks\BoldStringControlPack.pas', + BoldStringsPropertyController in 'Source\BoldAwareGUI\BoldControls\BoldStringsPropertyController.pas', + BoldSystemComparer in 'Source\Samples\SystemComparer\BoldSystemComparer.pas', + BoldSystemDebuggerForm in 'Source\Samples\SystemDebugger\BoldSystemDebuggerForm.pas', + BoldThreadedComObjectFactory in 'Source\Common\COM\BoldThreadedComObjectFactory.pas', + BoldTrackBar in 'Source\BoldAwareGUI\BoldControls\BoldTrackBar.pas', + BoldTreeView in 'Source\BoldAwareGUI\BoldControls\BoldTreeView.pas', + BoldTreeViewConfig in 'Source\BoldAwareGUI\BoldControls\BoldTreeViewConfig.pas', + BoldUMLAbstractModelValidator in 'Source\UMLModel\Core\BoldUMLAbstractModelValidator.pas', + BoldUMLAddTV in 'Source\UMLModel\Editor\BoldUMLAddTV.pas', + BoldUMLAttributes in 'Source\UMLModel\Core\BoldUMLAttributes.pas', + BoldUMLBldLink in 'Source\UMLModel\ModelLinks\Bld\BoldUMLBldLink.pas', + BoldUMLConstraintEditor in 'Source\UMLModel\Editor\BoldUMLConstraintEditor.pas', + BoldUMLModel in 'Source\UMLModel\Core\BoldUMLModel.pas', + BoldUMLModelConverter in 'Source\UMLModel\Core\BoldUMLModelConverter.pas', + BoldUMLModelDataModule in 'Source\UMLModel\Core\BoldUMLModelDataModule.pas', + BoldUMLModelEdit in 'Source\UMLModel\Editor\BoldUMLModelEdit.pas', + BoldUMLModelEditForm in 'Source\UMLModel\Editor\BoldUMLModelEditForm.pas', + BoldUMLModelEditPlugIn in 'Source\UMLModel\Plugins\BoldUMLModelEditPlugIn.pas', + BoldUMLModelLink in 'Source\UMLModel\ModelLinks\Core\BoldUMLModelLink.pas', + BoldUMLModelLinkSupport in 'Source\UMLModel\ModelLinks\Core\BoldUMLModelLinkSupport.pas', + BoldUMLModelStreamer in 'Source\UMLModel\Handles\BoldUMLModelStreamer.pas', + BoldUMLModelSupport in 'Source\UMLModel\Core\BoldUMLModelSupport.pas', + BoldUMLModelToEcoIIIGenerator in 'Source\UMLModel\Plugins\BoldUMLModelToEcoIIIGenerator.pas', + BoldUMLModelUpdater in 'Source\UMLModel\Core\BoldUMLModelUpdater.pas', + BoldUMLModelValidationForm in 'Source\UMLModel\Editor\BoldUMLModelValidationForm.pas', + BoldUMLModelValidator in 'Source\UMLModel\Core\BoldUMLModelValidator.pas', + BoldUMLNameTrimmer in 'Source\Samples\UMLPlugins\BoldUMLNameTrimmer.pas', + BoldUMLOCLEditor in 'Source\UMLModel\Editor\BoldUMLOCLEditor.pas', + BoldUMLOCLValidator in 'Source\UMLModel\Core\BoldUMLOCLValidator.pas', + BoldUMLPluginCallBacks in 'Source\UMLModel\Plugins\BoldUMLPluginCallBacks.pas', + BoldUMLPlugins in 'Source\UMLModel\Plugins\BoldUMLPlugins.pas', + BoldUMLRose98Link in 'Source\UMLModel\ModelLinks\Rose98\BoldUMLRose98Link.pas', + BoldUMLRose98MappingUtils in 'Source\UMLModel\ModelLinks\Rose98\BoldUMLRose98MappingUtils.pas', + BoldUMLRose98Support in 'Source\UMLModel\ModelLinks\Rose98\BoldUMLRose98Support.pas', + BoldUMLTaggedValuesEditor in 'Source\UMLModel\Editor\BoldUMLTaggedValuesEditor.pas', + BoldUMLUsesEditorForm in 'Source\UMLModel\Editor\BoldUMLUsesEditorForm.pas', + BoldUMLUtils in 'Source\UMLModel\Core\BoldUMLUtils.pas', + BoldVariantControlPack in 'Source\BoldAwareGUI\ControlPacks\BoldVariantControlPack.pas', + BoldViewerControlPack in 'Source\BoldAwareGUI\ControlPacks\BoldViewerControlPack.pas', + BoldWebConnection in 'Source\Common\HTTP\BoldWebConnection.pas', + BoldXCVTreeView in 'Source\BoldAwareGUI\BoldControls\BoldXCVTreeView.pas', + BoldXMLDispatcher in 'Source\Common\ConnectionHandlesCOM\BoldXMLDispatcher.pas', + BoldXMLDispatcherVB in 'Source\Common\ConnectionHandlesCOM\BoldXMLDispatcherVB.pas', + RationalRose2000_TLB in 'Source\Common\Rose2000\RationalRose2000_TLB.pas', + RationalRose98_TLB in 'Source\Common\Rose98\RationalRose98_TLB.pas', + UMLConsts in 'Source\UMLModel\Core\UMLConsts.pas', + BoldAbstractExternalPersistenceController in 'Source\Persistence\ExternalPersistence\BoldAbstractExternalPersistenceController.pas', + BoldAbstractExternalPersistenceHandle in 'Source\Persistence\ExternalPersistence\BoldAbstractExternalPersistenceHandle.pas', + BoldAbstractPartiallyExternalPC in 'Source\Persistence\ExternalPersistence\BoldAbstractPartiallyExternalPC.pas', + BoldAbstractPartiallyExternalPH in 'Source\Persistence\ExternalPersistence\BoldAbstractPartiallyExternalPH.pas', + BoldExternalPersistenceConfigItemDataSet in 'Source\Persistence\ExternalPersistence\BoldExternalPersistenceConfigItemDataSet.pas', + BoldExternalPersistenceControllerConfig in 'Source\Persistence\ExternalPersistence\BoldExternalPersistenceControllerConfig.pas', + BoldExternalPersistenceControllerDataSet in 'Source\Persistence\ExternalPersistence\BoldExternalPersistenceControllerDataSet.pas', + BoldExternalPersistenceControllerEventDriven in 'Source\Persistence\ExternalPersistence\BoldExternalPersistenceControllerEventDriven.pas', + BoldExternalPersistenceControllerSQL in 'Source\Persistence\ExternalPersistence\BoldExternalPersistenceControllerSQL.pas', + BoldExternalPersistenceHandleDataSet in 'Source\Persistence\ExternalPersistence\BoldExternalPersistenceHandleDataSet.pas', + BoldExternalPersistenceHandleEventDriven in 'Source\Persistence\ExternalPersistence\BoldExternalPersistenceHandleEventDriven.pas', + BoldExternalPersistenceHandleSQL in 'Source\Persistence\ExternalPersistence\BoldExternalPersistenceHandleSQL.pas', + BoldExternalPersistenceHandleSQLPropEditor in 'Source\Persistence\ExternalPersistence\BoldExternalPersistenceHandleSQLPropEditor.pas', + BoldExternalPersistenceSupport in 'Source\Persistence\ExternalPersistence\BoldExternalPersistenceSupport.pas', + ExPeConsts in 'Source\Persistence\ExternalPersistence\ExPeConsts.pas'; + +end. diff --git a/BoldAdditional.dproj b/BoldAdditional.dproj new file mode 100644 index 0000000..73c8161 --- /dev/null +++ b/BoldAdditional.dproj @@ -0,0 +1,1033 @@ + + + {4605ECDE-EC4C-4939-876E-5D5A4A731127} + BoldAdditional.dpk + 19.2 + None + True + Debug + Win32 + 3 + Package + + + true + + + true + Base + true + + + true + Base + true + + + true + Base + true + + + true + Cfg_1 + true + true + + + true + Cfg_1 + true + true + + + true + Base + true + + + .\$(Platform)\$(Config) + .\$(Platform)\$(Config) + false + false + false + false + false + true + true + System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;System;Xml;Data;Datasnap;Web;Soap;Winapi;$(DCC_Namespace) + All + BoldAdditional + true + $(BoldDelphi)\Source\Common\Include;$(DCC_UnitSearchPath) + 2077 + CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments= + true + + + Debug + true + 1033 + + + Debug + true + 1033 + + + DEBUG;$(DCC_Define) + true + false + true + true + true + Bold Runtime Package + 27 + + + false + true + 1033 + Bold for Delphi - Additional + + + true + 1033 + + + false + RELEASE;$(DCC_Define) + 0 + 0 + + + + MainSource + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Cfg_2 + Base + + + Base + + + Cfg_1 + Base + + + + Delphi.Personality.12 + Package + + + + BoldAdditional.dpk + + + Bold For Delphi - Core + Attracs Components for Delphi 10.4 Sydney + Microsoft Office 2000 Sample Automation Server Wrapper Components + Microsoft Office XP Sample Automation Server Wrapper Components + + + + + + true + + + + + true + + + + + true + + + + + BoldAdditional.bpl + true + + + + + 1 + + + 0 + + + + + classes + 1 + + + classes + 1 + + + + + res\xml + 1 + + + res\xml + 1 + + + + + library\lib\armeabi-v7a + 1 + + + + + library\lib\armeabi + 1 + + + library\lib\armeabi + 1 + + + + + library\lib\armeabi-v7a + 1 + + + + + library\lib\mips + 1 + + + library\lib\mips + 1 + + + + + library\lib\armeabi-v7a + 1 + + + library\lib\arm64-v8a + 1 + + + + + library\lib\armeabi-v7a + 1 + + + + + res\drawable + 1 + + + res\drawable + 1 + + + + + res\values + 1 + + + res\values + 1 + + + + + res\values-v21 + 1 + + + res\values-v21 + 1 + + + + + res\values + 1 + + + res\values + 1 + + + + + res\drawable + 1 + + + res\drawable + 1 + + + + + res\drawable-xxhdpi + 1 + + + res\drawable-xxhdpi + 1 + + + + + res\drawable-xxxhdpi + 1 + + + res\drawable-xxxhdpi + 1 + + + + + res\drawable-ldpi + 1 + + + res\drawable-ldpi + 1 + + + + + res\drawable-mdpi + 1 + + + res\drawable-mdpi + 1 + + + + + res\drawable-hdpi + 1 + + + res\drawable-hdpi + 1 + + + + + res\drawable-xhdpi + 1 + + + res\drawable-xhdpi + 1 + + + + + res\drawable-mdpi + 1 + + + res\drawable-mdpi + 1 + + + + + res\drawable-hdpi + 1 + + + res\drawable-hdpi + 1 + + + + + res\drawable-xhdpi + 1 + + + res\drawable-xhdpi + 1 + + + + + res\drawable-xxhdpi + 1 + + + res\drawable-xxhdpi + 1 + + + + + res\drawable-xxxhdpi + 1 + + + res\drawable-xxxhdpi + 1 + + + + + res\drawable-small + 1 + + + res\drawable-small + 1 + + + + + res\drawable-normal + 1 + + + res\drawable-normal + 1 + + + + + res\drawable-large + 1 + + + res\drawable-large + 1 + + + + + res\drawable-xlarge + 1 + + + res\drawable-xlarge + 1 + + + + + res\values + 1 + + + res\values + 1 + + + + + 1 + + + 1 + + + 0 + + + + + 1 + .framework + + + 1 + .framework + + + 0 + + + + + 1 + .dylib + + + 1 + .dylib + + + 0 + .dll;.bpl + + + + + 1 + .dylib + + + 1 + .dylib + + + 1 + .dylib + + + 1 + .dylib + + + 1 + .dylib + + + 0 + .bpl + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + 1 + + + 1 + + + + + ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF + 1 + + + ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF + 1 + + + + + + + + 1 + + + 1 + + + 1 + + + + + + + + Contents\Resources + 1 + + + Contents\Resources + 1 + + + + + library\lib\armeabi-v7a + 1 + + + library\lib\arm64-v8a + 1 + + + 1 + + + 1 + + + 1 + + + 1 + + + 1 + + + 1 + + + 0 + + + + + library\lib\armeabi-v7a + 1 + + + + + 1 + + + 1 + + + + + Assets + 1 + + + Assets + 1 + + + + + Assets + 1 + + + Assets + 1 + + + + + + + + + + + + + + + True + True + + + 12 + + + + + diff --git a/BoldCore.dpk b/BoldCore.dpk new file mode 100644 index 0000000..6da3be7 --- /dev/null +++ b/BoldCore.dpk @@ -0,0 +1,282 @@ +package BoldCore; + +{$R *.res} +{$IFDEF IMPLICITBUILDING This IFDEF should not be used by users} +{$ALIGN 8} +{$ASSERTIONS ON} +{$BOOLEVAL OFF} +{$DEBUGINFO OFF} +{$EXTENDEDSYNTAX ON} +{$IMPORTEDDATA ON} +{$IOCHECKS ON} +{$LOCALSYMBOLS ON} +{$LONGSTRINGS ON} +{$OPENSTRINGS ON} +{$OPTIMIZATION OFF} +{$OVERFLOWCHECKS OFF} +{$RANGECHECKS OFF} +{$REFERENCEINFO ON} +{$SAFEDIVIDE OFF} +{$STACKFRAMES ON} +{$TYPEDADDRESS OFF} +{$VARSTRINGCHECKS ON} +{$WRITEABLECONST OFF} +{$MINENUMSIZE 1} +{$IMAGEBASE $400000} +{$DEFINE DEBUG} +{$ENDIF IMPLICITBUILDING} +{$DESCRIPTION 'Bold For Delphi - Core'} +{$LIBVERSION '27'} +{$RUNONLY} +{$IMPLICITBUILD OFF} + +requires + vcl, + vcldb; + +contains + BoldSystem in 'Source\ObjectSpace\BORepresentation\BoldSystem.pas', + BoldAttributes in 'Source\ObjectSpace\BORepresentation\BoldAttributes.pas', + BoldDerivedValueSet in 'Source\ObjectSpace\BORepresentation\BoldDerivedValueSet.pas', + BoldDomainElement in 'Source\ObjectSpace\BORepresentation\BoldDomainElement.pas', + BoldElementList in 'Source\ObjectSpace\BORepresentation\BoldElementList.pas', + BoldExternalObjectSpaceEventHandler in 'Source\ObjectSpace\BORepresentation\BoldExternalObjectSpaceEventHandler.pas', + BoldLinks in 'Source\ObjectSpace\BORepresentation\BoldLinks.pas', + BoldMLAttributes in 'Source\ObjectSpace\BORepresentation\BoldMLAttributes.pas', + BoldObjectListControllers in 'Source\ObjectSpace\BORepresentation\BoldObjectListControllers.pas', + BoldObjectSpaceLists in 'Source\ObjectSpace\BORepresentation\BoldObjectSpaceLists.pas', + BoldOptimisticLockingSupport in 'Source\ObjectSpace\BORepresentation\BoldOptimisticLockingSupport.pas', + BoldSystemOldValuehandler in 'Source\ObjectSpace\BORepresentation\BoldSystemOldValuehandler.pas', + BoldSystemPersistenceHandler in 'Source\ObjectSpace\BORepresentation\BoldSystemPersistenceHandler.pas', + BoldTypeList in 'Source\ObjectSpace\BORepresentation\BoldTypeList.pas', + BoldCoreConsts in 'Source\ObjectSpace\Core\BoldCoreConsts.pas', + BoldElements in 'Source\ObjectSpace\Core\BoldElements.pas', + BoldMetaElementList in 'Source\ObjectSpace\Core\BoldMetaElementList.pas', + BoldUndoInterfaces in 'Source\ObjectSpace\Interfaces\BoldUndoInterfaces.pas', + BoldOcl in 'Source\ObjectSpace\Ocl\BoldOcl.pas', + BoldOclClasses in 'Source\ObjectSpace\Ocl\BoldOclClasses.pas', + BoldOclError in 'Source\ObjectSpace\Ocl\BoldOclError.pas', + BoldOclEvaluator in 'Source\ObjectSpace\Ocl\BoldOclEvaluator.pas', + BoldOclLightWeightNodeMaker in 'Source\ObjectSpace\Ocl\BoldOclLightWeightNodeMaker.pas', + BoldOclLightWeightNodes in 'Source\ObjectSpace\Ocl\BoldOclLightWeightNodes.pas', + BoldOclRTDebug in 'Source\ObjectSpace\Ocl\BoldOclRTDebug.pas', + BoldOclSemantics in 'Source\ObjectSpace\Ocl\BoldOclSemantics.pas', + BoldOclSymbolImplementations in 'Source\ObjectSpace\Ocl\BoldOclSymbolImplementations.pas', + BoldORed in 'Source\ObjectSpace\Ocl\BoldORed.pas', + BoldSSExcept in 'Source\ObjectSpace\Ocl\BoldSSExcept.pas', + BoldSSLexU in 'Source\ObjectSpace\Ocl\BoldSSLexU.pas', + BoldSSYaccU in 'Source\ObjectSpace\Ocl\BoldSSYaccU.pas', + BoldLockHandler in 'Source\ObjectSpace\PessimisticLocking\BoldLockHandler.pas', + BoldLockHolder in 'Source\ObjectSpace\PessimisticLocking\BoldLockHolder.pas', + BoldLockRegions in 'Source\ObjectSpace\PessimisticLocking\BoldLockRegions.pas', + BoldRegionDefinitionParser in 'Source\ObjectSpace\PessimisticLocking\BoldRegionDefinitionParser.pas', + BoldRegionDefinitions in 'Source\ObjectSpace\PessimisticLocking\BoldRegionDefinitions.pas', + BoldGeneratedCodeDictionary in 'Source\ObjectSpace\RTModel\BoldGeneratedCodeDictionary.pas', + BoldMemberTypeDictionary in 'Source\ObjectSpace\RTModel\BoldMemberTypeDictionary.pas', + BoldSystemRT in 'Source\ObjectSpace\RTModel\BoldSystemRT.pas', + BoldUndoHandler in 'Source\ObjectSpace\Undo\BoldUndoHandler.pas', + BoldUnloader in 'Source\ObjectSpace\Unloader\BoldUnloader.pas', + BoldComponentValidator in 'Source\ObjectSpace\UtilsGUI\BoldComponentValidator.pas', + BoldOCLGraphicRTDebug in 'Source\ObjectSpace\UtilsGUI\BoldOCLGraphicRTDebug.pas', + BoldOclPropEditor in 'Source\ObjectSpace\UtilsGUI\BoldOclPropEditor.pas', + BoldTypeNameSelector in 'Source\ObjectSpace\UtilsGUI\BoldTypeNameSelector.pas', + BoldClient in 'Source\Common\Connection\BoldClient.pas', + BoldServer in 'Source\Common\Connection\BoldServer.pas', + BoldClientHandles in 'Source\Common\ConnectionHandles\BoldClientHandles.pas', + BoldServerHandles in 'Source\Common\ConnectionHandles\BoldServerHandles.pas', + BoldAggeregates in 'Source\Common\Core\BoldAggeregates.pas', + BoldBase in 'Source\Common\Core\BoldBase.pas', + BoldCommonConst in 'Source\Common\Core\BoldCommonConst.pas', + BoldContainers in 'Source\Common\Core\BoldContainers.pas', + BoldDefs in 'Source\Common\Core\BoldDefs.pas', + BoldStreams in 'Source\Common\Core\BoldStreams.pas', + BoldThreadSafeQueue in 'Source\Common\Core\BoldThreadSafeQueue.pas', + BoldEnvironment in 'Source\Common\Environment\BoldEnvironment.pas', + BoldEnvironmentVCL in 'Source\Common\Environment\BoldEnvironmentVCL.pas', + BoldHandle in 'Source\Common\Handles\BoldHandle.pas', + BoldDataBlock in 'Source\Common\HTTP\BoldDataBlock.pas', + BoldLogForm in 'Source\Common\Logging\BoldLogForm.pas', + BoldLogHandler in 'Source\Common\Logging\BoldLogHandler.pas', + BoldLogHandlerForm in 'Source\Common\Logging\BoldLogHandlerForm.pas', + BoldLogHandlerSimple in 'Source\Common\Logging\BoldLogHandlerSimple.pas', + BoldLogReceiverInterface in 'Source\Common\Logging\BoldLogReceiverInterface.pas', + BoldSmallLogFrame in 'Source\Common\Logging\BoldSmallLogFrame.pas', + BoldThreadSafeLog in 'Source\Common\Logging\BoldThreadSafeLog.pas', + Bold_MSXML_TLB in 'Source\Common\MsXml\Bold_MSXML_TLB.pas', + BoldAbstractDequeuer in 'Source\Common\Queue\BoldAbstractDequeuer.pas', + BoldEventQueue in 'Source\Common\Queue\BoldEventQueue.pas', + BoldQueue in 'Source\Common\Queue\BoldQueue.pas', + BoldSOAP_TLB in 'Source\Common\SOAP\BoldSOAP_TLB.pas', + BoldSOAP2_TLB in 'Source\Common\SOAP\BoldSOAP2_TLB.pas', + BoldXMLRequests in 'Source\Common\SOAP\BoldXMLRequests.pas', + BoldDeriver in 'Source\Common\Subscription\BoldDeriver.pas', + BoldSubscribableCollection in 'Source\Common\Subscription\BoldSubscribableCollection.pas', + BoldSubscription in 'Source\Common\Subscription\BoldSubscription.pas', + BoldBase64 in 'Source\Common\Support\BoldBase64.pas', + BoldCollections in 'Source\Common\Support\BoldCollections.pas', + BoldIndexCollection in 'Source\Common\Support\BoldIndexCollection.pas', + BoldCommonBitmaps in 'Source\Common\Support\BoldCommonBitmaps.pas', + BoldControlPackDefs in 'Source\Common\Support\BoldControlPackDefs.pas', + BoldControlsDefs in 'Source\Common\Support\BoldControlsDefs.pas', + BoldDirectoryTraverser in 'Source\Common\Support\BoldDirectoryTraverser.pas', + BoldExternalizedReferences in 'Source\Common\Support\BoldExternalizedReferences.pas', + BoldFileHandler in 'Source\Common\Support\BoldFileHandler.pas', + BoldGuard in 'Source\Common\Support\BoldGuard.pas', + BoldGUIDUtils in 'Source\Common\Support\BoldGUIDUtils.pas', + BoldHashIndexes in 'Source\Common\Support\BoldHashIndexes.pas', + BoldIndex in 'Source\Common\Support\BoldIndex.pas', + BoldIndexableList in 'Source\Common\Support\BoldIndexableList.pas', + BoldIsoDateTime in 'Source\Common\Support\BoldIsoDateTime.pas', + BoldLoggableCriticalSection in 'Source\Common\Support\BoldLoggableCriticalSection.pas', + BoldMath in 'Source\Common\Support\BoldMath.pas', + BoldMemoryManager in 'Source\Common\Support\BoldMemoryManager.pas', + BoldNamedValueList in 'Source\Common\Support\BoldNamedValueList.pas', + BoldNavigatorDefs in 'Source\Common\Support\BoldNavigatorDefs.pas', + BoldPerformanceCounter in 'Source\Common\Support\BoldPerformanceCounter.pas', + BoldPriorityQueue in 'Source\Common\Support\BoldPriorityQueue.pas', + BoldRegistry in 'Source\Common\Support\BoldRegistry.pas', + BoldRev in 'Source\Common\Support\BoldRev.pas', + BoldSharedStrings in 'Source\Common\Support\BoldSharedStrings.pas', + BoldSorter in 'Source\Common\Support\BoldSorter.pas', + BoldStringList in 'Source\Common\Support\BoldStringList.pas', + BoldSupportConst in 'Source\Common\Support\BoldSupportConst.pas', + BoldTemplateExpander in 'Source\Common\Support\BoldTemplateExpander.pas', + BoldUtils in 'Source\Common\Support\BoldUtils.pas', + BoldXMLStreaming in 'Source\Common\Support\BoldXMLStreaming.pas', + BoldThread in 'Source\Common\SupportWin\BoldThread.pas', + BoldWinINet in 'Source\Common\SupportWin\BoldWinINet.pas', + BoldWinUtils in 'Source\Common\SupportWin\BoldWinUtils.pas', + BoldDefaultTaggedValues in 'Source\Common\TaggedValues\BoldDefaultTaggedValues.pas', + BoldTaggedValueList in 'Source\Common\TaggedValues\BoldTaggedValueList.pas', + BoldTaggedValueSupport in 'Source\Common\TaggedValues\BoldTaggedValueSupport.pas', + BoldUMLTaggedValues in 'Source\Common\TaggedValues\BoldUMLTaggedValues.pas', + BoldTemplate in 'Source\Common\Template\BoldTemplate.pas', + BoldUMLDelphiSupport in 'Source\Common\UML\BoldUMLDelphiSupport.pas', + BoldUMLTypes in 'Source\Common\UML\BoldUMLTypes.pas', + BoldCursorGuard in 'Source\Common\UtilsGUI\BoldCursorGuard.pas', + BoldQueryUserDlg in 'Source\Common\UtilsGUI\BoldQueryUserDlg.pas', + BoldAbstractLockManagerAdminHandle in 'Source\ConcurrencyControl\Common\BoldAbstractLockManagerAdminHandle.pas', + BoldAbstractLockManagerHandle in 'Source\ConcurrencyControl\Common\BoldAbstractLockManagerHandle.pas', + BoldLockingDefs in 'Source\ConcurrencyControl\Common\BoldLockingDefs.pas', + BoldFreeStandingValueFactories in 'Source\FreestandingValueSpace\Core\BoldFreeStandingValueFactories.pas', + BoldFreeStandingValues in 'Source\FreestandingValueSpace\Core\BoldFreeStandingValues.pas', + FreeStandingValuesConst in 'Source\FreestandingValueSpace\Core\FreeStandingValuesConst.pas', + BoldActionDefs in 'Source\Handles\Actions\BoldActionDefs.pas', + BoldActions in 'Source\Handles\Actions\BoldActions.pas', + BoldHandleAction in 'Source\Handles\Actions\BoldHandleAction.pas', + BoldListActions in 'Source\Handles\Actions\BoldListActions.pas', + BoldUndoActions in 'Source\Handles\Actions\BoldUndoActions.pas', + BoldAbstractListHandle in 'Source\Handles\Core\BoldAbstractListHandle.pas', + BoldCursorHandle in 'Source\Handles\Core\BoldCursorHandle.pas', + BoldDerivedHandle in 'Source\Handles\Core\BoldDerivedHandle.pas', + BoldExpressionHandle in 'Source\Handles\Core\BoldExpressionHandle.pas', + BoldFilteredHandle in 'Source\Handles\Core\BoldFilteredHandle.pas', + BoldHandles in 'Source\Handles\Core\BoldHandles.pas', + BoldListHandle in 'Source\Handles\Core\BoldListHandle.pas', + BoldOclRepository in 'Source\Handles\Core\BoldOclRepository.pas', + BoldOclVariables in 'Source\Handles\Core\BoldOclVariables.pas', + BoldOSSMessage in 'Source\ObjectSpace\BORepresentation\BoldOSSMessage.pas', + BoldPlaceableSubscriber in 'Source\Handles\Core\BoldPlaceableSubscriber.pas', + BoldReferenceHandle in 'Source\Handles\Core\BoldReferenceHandle.pas', + BoldRootedHandles in 'Source\Handles\Core\BoldRootedHandles.pas', + BoldSortedHandle in 'Source\Handles\Core\BoldSortedHandle.pas', + BoldSQLHandle in 'Source\Handles\Core\BoldSQLHandle.pas', + BoldRawSQLHandle in 'Source\Handles\Core\BoldRawSQLHandle.pas', + BoldSystemHandle in 'Source\Handles\Core\BoldSystemHandle.pas', + BoldVariableDefinition in 'Source\Handles\Core\BoldVariableDefinition.pas', + BoldVariableHandle in 'Source\Handles\Core\BoldVariableHandle.pas', + HandlesConst in 'Source\Handles\Core\HandlesConst.pas', + BoldManipulators in 'Source\Handles\Manipulators\BoldManipulators.pas', + BoldLockingHandles in 'Source\Handles\PessimisticLocking\BoldLockingHandles.pas', + BoldUnloaderHandle in 'Source\Handles\UnLoader\BoldUnloaderHandle.pas', + BoldXMLProducers in 'Source\Handles\XML\BoldXMLProducers.pas', + BoldBld in 'Source\MoldModel\Bld\BoldBld.pas', + BoldMeta in 'Source\MoldModel\Core\BoldMeta.pas', + BoldMetaSupport in 'Source\MoldModel\Core\BoldMetaSupport.pas', + BoldMoldConsts in 'Source\MoldModel\Core\BoldMoldConsts.pas', + BoldNameExpander in 'Source\MoldModel\Core\BoldNameExpander.pas', + BoldAbstractModel in 'Source\MoldModel\Handles\BoldAbstractModel.pas', + BoldTypeNameHandle in 'Source\MoldModel\Handles\BoldTypeNameHandle.pas', + BoldTypeNameDictionary in 'Source\MoldModel\TypeNameDictionary\BoldTypeNameDictionary.pas', + BoldTypeNameEditor in 'Source\MoldModel\UtilsGUI\BoldTypeNameEditor.pas', + BoldAbstractSnooper in 'Source\Persistence\Core\BoldAbstractSnooper.pas', + BoldPersistenceController in 'Source\Persistence\Core\BoldPersistenceController.pas', + BoldPersistenceHandle in 'Source\Persistence\Core\BoldPersistenceHandle.pas', + BoldPersistenceHandlePassthrough in 'Source\Persistence\Core\BoldPersistenceHandlePassthrough.pas', + BoldPersistenceHandlePTWithModel in 'Source\Persistence\Core\BoldPersistenceHandlePTWithModel.pas', + BoldPersistenceNotifier in 'Source\Persistence\Core\BoldPersistenceNotifier.pas', + BoldUpdatePrecondition in 'Source\Persistence\Core\BoldUpdatePrecondition.pas', + PersistenceConsts in 'Source\Persistence\Core\PersistenceConsts.pas', + BoldAbstractDatabaseAdapter in 'Source\Persistence\DB\BoldAbstractDatabaseAdapter.pas', + BoldAbstractPersistenceHandleDB in 'Source\Persistence\DB\BoldAbstractPersistenceHandleDB.pas', + BoldDBActions in 'Source\Persistence\DB\BoldDBActions.pas', + BoldDBInterfaces in 'Source\Persistence\DB\BoldDBInterfaces.pas', + BoldPersistenceControllerDefault in 'Source\Persistence\DB\BoldPersistenceControllerDefault.pas', + BoldPersistenceHandleDB in 'Source\Persistence\DB\BoldPersistenceHandleDB.pas', + BoldPersistenceHandleFile in 'Source\Persistence\File\BoldPersistenceHandleFile.pas', + BoldPersistenceHandleFileXML in 'Source\Persistence\File\BoldPersistenceHandleFileXML.pas', + BoldAbstractObjectUpgraderHandle in 'Source\Persistence\ObjectUpgrading\BoldAbstractObjectUpgraderHandle.pas', + BoldBatchUpgrader in 'Source\Persistence\ObjectUpgrading\BoldBatchUpgrader.pas', + BoldObjectUpgrader in 'Source\Persistence\ObjectUpgrading\BoldObjectUpgrader.pas', + BoldObjectUpgraderHandle in 'Source\Persistence\ObjectUpgrading\BoldObjectUpgraderHandle.pas', + BoldIDAdder in 'Source\Persistence\Propagation\BoldIDAdder.pas', + BoldIDAdderHandle in 'Source\Persistence\Propagation\BoldIDAdderHandle.pas', + BoldListenerCOM in 'Source\Persistence\Propagation\BoldListenerCOM.pas', + BoldListenerHandle in 'Source\Persistence\Propagation\BoldListenerHandle.pas', + BoldListenerThread in 'Source\Persistence\Propagation\BoldListenerThread.pas', + BoldPersistenceControllerPassthrough in 'Source\Persistence\Propagation\BoldPersistenceControllerPassthrough.pas', + BoldSnooper in 'Source\Persistence\Propagation\BoldSnooper.pas', + BoldSnooperHandle in 'Source\Persistence\Propagation\BoldSnooperHandle.pas', + BoldPersistenceControllerSystem in 'Source\Persistence\System\BoldPersistenceControllerSystem.pas', + BoldPersistenceHandleSystem in 'Source\Persistence\System\BoldPersistenceHandleSystem.pas', + BoldAbstractObjectUpgrader in 'Source\PMapper\Core\BoldAbstractObjectUpgrader.pas', + BoldPMapper in 'Source\PMapper\Core\BoldPMapper.pas', + BoldPMapperLists in 'Source\PMapper\Core\BoldPMapperLists.pas', + BoldPMappers in 'Source\PMapper\Core\BoldPMappers.pas', + BoldPMConsts in 'Source\PMapper\Core\BoldPMConsts.pas', + BoldPSDescriptions in 'Source\PMapper\Core\BoldPSDescriptions.pas', + BoldPSParams in 'Source\PMapper\Core\BoldPSParams.pas', + BoldDbEvolutor in 'Source\PMapper\DbEvolutor\BoldDbEvolutor.pas', + BoldDbEvolutorForm in 'Source\PMapper\DbEvolutor\BoldDbEvolutorForm.pas', + BoldDbEvolutorScript in 'Source\PMapper\DbEvolutor\BoldDbEvolutorScript.pas', + BoldCustomBlobMapper in 'Source\PMapper\Default\BoldCustomBlobMapper.pas', + BoldMappingInfo in 'Source\PMapper\Default\BoldMappingInfo.pas', + BoldPMappersAttributeDefault in 'Source\PMapper\Default\BoldPMappersAttributeDefault.pas', + BoldPMappersDefault in 'Source\PMapper\Default\BoldPMappersDefault.pas', + BoldPMappersLinkDefault in 'Source\PMapper\Default\BoldPMappersLinkDefault.pas', + BoldPSDescriptionsDefault in 'Source\PMapper\Default\BoldPSDescriptionsDefault.pas', + BoldPSParamsDefault in 'Source\PMapper\Default\BoldPSParamsDefault.pas', + BoldPMappersSQL in 'Source\PMapper\SQL\BoldPMappersSQL.pas', + BoldPSDescriptionsSQL in 'Source\PMapper\SQL\BoldPSDescriptionsSQL.pas', + BoldPSParamsSQL in 'Source\PMapper\SQL\BoldPSParamsSQL.pas', + BoldSQLDatabaseConfig in 'Source\PMapper\SQL\BoldSQLDatabaseConfig.pas', + BoldSQLMappingInfo in 'Source\PMapper\SQL\BoldSQLMappingInfo.pas', + BoldSqlNodeMaker in 'Source\PMapper\SQL\BoldSqlNodeMaker.pas', + BoldSqlNodes in 'Source\PMapper\SQL\BoldSqlNodes.pas', + BoldSqlNodesResolver in 'Source\PMapper\SQL\BoldSqlNodesResolver.pas', + BoldSQLQuery in 'Source\PMapper\SQL\BoldSQLQuery.pas', + BoldSqlQueryGenerator in 'Source\PMapper\SQL\BoldSqlQueryGenerator.pas', + BoldSqlSymbols in 'Source\PMapper\SQL\BoldSqlSymbols.pas', + BoldDbDataValidator in 'Source\PMapper\Validator\BoldDbDataValidator.pas', + BoldDbStructureValidator in 'Source\PMapper\Validator\BoldDbStructureValidator.pas', + BoldDbValidator in 'Source\PMapper\Validator\BoldDbValidator.pas', + BoldAbstractPropagatorHandle in 'Source\Propagator\Common\BoldAbstractPropagatorHandle.pas', + BoldLockingSupportInterfaces_TLB in 'Source\Propagator\Common\BoldLockingSupportInterfaces_TLB.pas', + BoldPropagatorInterfaces_TLB in 'Source\Propagator\Common\BoldPropagatorInterfaces_TLB.pas', + BoldObjectMarshaler in 'Source\Propagator\Common\BoldObjectMarshaler.pas', + BoldPropagatorConstants in 'Source\Propagator\Common\BoldPropagatorConstants.pas', + BoldPropagatorGUIDs in 'Source\Propagator\Common\BoldPropagatorGUIDs.pas', + PropagatorConsts in 'Source\Propagator\Common\PropagatorConsts.pas', + BoldCondition in 'Source\ValueSpace\Condition\BoldCondition.pas', + BoldObjectSpaceExternalEvents in 'Source\ValueSpace\ExternalEvents\BoldObjectSpaceExternalEvents.pas', + BoldDefaultId in 'Source\ValueSpace\Id\BoldDefaultId.pas', + BoldGlobalId in 'Source\ValueSpace\Id\BoldGlobalId.pas', + BoldId in 'Source\ValueSpace\Id\BoldId.pas', + BoldStringId in 'Source\ValueSpace\Id\BoldStringId.pas', + ValueSpaceConst in 'Source\ValueSpace\Id\ValueSpaceConst.pas', + BoldValueInterfaces in 'Source\ValueSpace\Interfaces\BoldValueInterfaces.pas', + BoldValueSpaceInterfaces in 'Source\ValueSpace\Interfaces\BoldValueSpaceInterfaces.pas', + BoldDefaultStreamNames in 'Source\ValueSpace\XMLStreaming\BoldDefaultStreamNames.pas', + BoldDefaultXMLStreaming in 'Source\ValueSpace\XMLStreaming\BoldDefaultXMLStreaming.pas'; + +end. diff --git a/BoldDesignPackage.dproj b/BoldCore.dproj similarity index 65% rename from BoldDesignPackage.dproj rename to BoldCore.dproj index 20bfc0f..f876964 100644 --- a/BoldDesignPackage.dproj +++ b/BoldCore.dproj @@ -1,13 +1,13 @@  - {BA681BD2-4AA5-4AB0-8850-FFE2B8AAC9E0} - BoldDesignPackage.dpk + {4BC34884-BFF5-402F-81A4-0063B51D2F4F} + BoldCore.dpk 19.2 None True Debug Win32 - 1 + 3 Package @@ -34,11 +34,23 @@ true true + + true + Cfg_1 + true + true + true Base true + + true + Cfg_2 + true + true + .\$(Platform)\$(Config) .\$(Platform)\$(Config) @@ -49,31 +61,28 @@ false true true - Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;System;Xml;Data;Datasnap;Web;Soap;Winapi;$(DCC_Namespace) + System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;Winapi;System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace) All - BoldDesignPackage - $(BoldDelphi)\Source\BoldAwareGUI;$(BoldDelphi)\Source\BoldQAwareGUI;$(BoldDelphi)\Source\ClientGuiCom;$(BoldDelphi)\Source\ClientHandlesCom;$(BoldDelphi)\Source\Common;$(BoldDelphi)\Source\ConcurrencyControl;$(BoldDelphi)\Source\Extensions;$(BoldDelphi)\Source\FreestandingValueSpace;$(BoldDelphi)\Source\Handles;$(BoldDelphi)\Source\MoldModel;$(BoldDelphi)\Source\ObjectSpace;$(BoldDelphi)\Source\Persistence;$(BoldDelphi)\Source\PMapper;$(BoldDelphi)\Source\Propagator;$(BoldDelphi)\Source\Samples;$(BoldDelphi)\Source\UMLModel;$(BoldDelphi)\Source\Unassigned;$(BoldDelphi)\Source\ValueSpace;$(BoldDelphi)\Source\BoldAwareGUI\Actions;$(BoldDelphi)\Source\BoldAwareGUI\BoldControls;$(BoldDelphi)\Source\BoldAwareGUI\ControlPacks;$(BoldDelphi)\Source\BoldAwareGUI\Core;$(BoldDelphi)\Source\BoldAwareGUI\FormGen;$(BoldDelphi)\Source\BoldAwareGUI\IDE;$(BoldDelphi)\Source\BoldQAwareGUI\BoldControls;$(BoldDelphi)\Source\BoldQAwareGUI\ControlPacks;$(BoldDelphi)\Source\BoldQAwareGUI\Core;$(BoldDelphi)\Source\ClientGuiCom\BoldControls;$(BoldDelphi)\Source\ClientGuiCom\ControlPacks;$(BoldDelphi)\Source\ClientGuiCom\Core;$(BoldDelphi)\Source\ClientGuiCom\IDE;$(BoldDelphi)\Source\ClientHandlesCom\Core;$(BoldDelphi)\Source\ClientHandlesCom\IDE;$(BoldDelphi)\Source\Common\COM;$(BoldDelphi)\Source\Common\Connection;$(BoldDelphi)\Source\Common\ConnectionCOM;$(BoldDelphi)\Source\Common\ConnectionHandles;$(BoldDelphi)\Source\Common\ConnectionHandlesCOM;$(BoldDelphi)\Source\Common\Core;$(BoldDelphi)\Source\Common\Environment;$(BoldDelphi)\Source\Common\Handles;$(BoldDelphi)\Source\Common\HTTP;$(BoldDelphi)\Source\Common\IDE;$(BoldDelphi)\Source\Common\IDECOM;$(BoldDelphi)\Source\Common\Include;$(BoldDelphi)\Source\Common\Logging;$(BoldDelphi)\Source\Common\MsXml;$(BoldDelphi)\Source\Common\Queue;$(BoldDelphi)\Source\Common\Rose2000;$(BoldDelphi)\Source\Common\Rose98;$(BoldDelphi)\Source\Common\SOAP;$(BoldDelphi)\Source\Common\Subscription;$(BoldDelphi)\Source\Common\Support;$(BoldDelphi)\Source\Common\SupportWin;$(BoldDelphi)\Source\Common\TaggedValues;$(BoldDelphi)\Source\Common\Template;$(BoldDelphi)\Source\Common\UML;$(BoldDelphi)\Source\Common\UtilsGUI;$(BoldDelphi)\Source\ConcurrencyControl\COM;$(BoldDelphi)\Source\ConcurrencyControl\Common;$(BoldDelphi)\Source\ConcurrencyControl\IDECOM;$(BoldDelphi)\Source\Extensions\OLLE;$(BoldDelphi)\Source\Extensions\OLLE\Core;$(BoldDelphi)\Source\Extensions\OLLE\IDE;$(BoldDelphi)\Source\FreestandingValueSpace\Core;$(BoldDelphi)\Source\Handles\Actions;$(BoldDelphi)\Source\Handles\COM;$(BoldDelphi)\Source\Handles\Core;$(BoldDelphi)\Source\Handles\IDE;$(BoldDelphi)\Source\Handles\IDECOM;$(BoldDelphi)\Source\Handles\Manipulators;$(BoldDelphi)\Source\Handles\PessimisticLocking;$(BoldDelphi)\Source\Handles\UnLoader;$(BoldDelphi)\Source\Handles\XML;$(BoldDelphi)\Source\MoldModel\Bld;$(BoldDelphi)\Source\MoldModel\CodeGenerator;$(BoldDelphi)\Source\MoldModel\Core;$(BoldDelphi)\Source\MoldModel\Handles;$(BoldDelphi)\Source\MoldModel\IDE;$(BoldDelphi)\Source\MoldModel\TypeNameDictionary;$(BoldDelphi)\Source\MoldModel\UtilsGUI;$(BoldDelphi)\Source\ObjectSpace\BORepresentation;$(BoldDelphi)\Source\ObjectSpace\COM;$(BoldDelphi)\Source\ObjectSpace\Core;$(BoldDelphi)\Source\ObjectSpace\IDE;$(BoldDelphi)\Source\ObjectSpace\Interfaces;$(BoldDelphi)\Source\ObjectSpace\Ocl;$(BoldDelphi)\Source\ObjectSpace\PessimisticLocking;$(BoldDelphi)\Source\ObjectSpace\RTModel;$(BoldDelphi)\Source\ObjectSpace\Undo;$(BoldDelphi)\Source\ObjectSpace\Unloader;$(BoldDelphi)\Source\ObjectSpace\UtilsGUI;$(BoldDelphi)\Source\ObjectSpace\IDE\AttributeWizard;$(BoldDelphi)\Source\Persistence\ADO;$(BoldDelphi)\Source\Persistence\Advantage;$(BoldDelphi)\Source\Persistence\BDE;$(BoldDelphi)\Source\Persistence\COM;$(BoldDelphi)\Source\Persistence\Core;$(BoldDelphi)\Source\Persistence\DB;$(BoldDelphi)\Source\Persistence\DBExpress;$(BoldDelphi)\Source\Persistence\DBISAM;$(BoldDelphi)\Source\Persistence\DOA;$(BoldDelphi)\Source\Persistence\ExternalPersistence;$(BoldDelphi)\Source\Persistence\File;$(BoldDelphi)\Source\Persistence\FireDAC;$(BoldDelphi)\Source\Persistence\HTTP;$(BoldDelphi)\Source\Persistence\IBX;$(BoldDelphi)\Source\Persistence\IDE;$(BoldDelphi)\Source\Persistence\IDECOM;$(BoldDelphi)\Source\Persistence\IDEUDP;$(BoldDelphi)\Source\Persistence\ObjectUpgrading;$(BoldDelphi)\Source\Persistence\Propagation;$(BoldDelphi)\Source\Persistence\SOAP;$(BoldDelphi)\Source\Persistence\SQLDirect;$(BoldDelphi)\Source\Persistence\System;$(BoldDelphi)\Source\Persistence\UDPPropagator;$(BoldDelphi)\Source\Persistence\UniDAC;$(BoldDelphi)\Source\PMapper\Core;$(BoldDelphi)\Source\PMapper\DbEvolutor;$(BoldDelphi)\Source\PMapper\Default;$(BoldDelphi)\Source\PMapper\SQL;$(BoldDelphi)\Source\PMapper\Validator;$(BoldDelphi)\Source\Propagator\COM;$(BoldDelphi)\Source\Propagator\Common;$(BoldDelphi)\Source\Propagator\Enterprise;$(BoldDelphi)\Source\Propagator\IDECOM;$(BoldDelphi)\Source\Propagator\LowEnd;$(BoldDelphi)\Source\Samples\Actions;$(BoldDelphi)\Source\Samples\BoldCheckListBox;$(BoldDelphi)\Source\Samples\ConstraintValidator;$(BoldDelphi)\Source\Samples\FormSaver;$(BoldDelphi)\Source\Samples\IDE;$(BoldDelphi)\Source\Samples\Misc;$(BoldDelphi)\Source\Samples\ModelLoader;$(BoldDelphi)\Source\Samples\NewObjectInterceptor;$(BoldDelphi)\Source\Samples\SortingGrid;$(BoldDelphi)\Source\Samples\SystemComparer;$(BoldDelphi)\Source\Samples\SystemDebugger;$(BoldDelphi)\Source\Samples\UMLPlugins;$(BoldDelphi)\Source\Samples\Unicode;$(BoldDelphi)\Source\UMLModel\Core;$(BoldDelphi)\Source\UMLModel\Editor;$(BoldDelphi)\Source\UMLModel\Handles;$(BoldDelphi)\Source\UMLModel\Ide;$(BoldDelphi)\Source\UMLModel\ModelLinks;$(BoldDelphi)\Source\UMLModel\Plugins;$(BoldDelphi)\Source\UMLModel\ModelLinks\Bld;$(BoldDelphi)\Source\UMLModel\ModelLinks\Core;$(BoldDelphi)\Source\UMLModel\ModelLinks\ModelMaker;$(BoldDelphi)\Source\UMLModel\ModelLinks\Rose98;$(BoldDelphi)\Source\UMLModel\ModelLinks\XMI;$(BoldDelphi)\Source\UMLModel\ModelLinks\ModelMaker\Link;$(BoldDelphi)\Source\UMLModel\ModelLinks\ModelMaker\MMPlugin;$(BoldDelphi)\Source\UMLModel\ModelLinks\ModelMaker\Support;$(BoldDelphi)\Source\ValueSpace\Condition;$(BoldDelphi)\Source\ValueSpace\ExternalEvents;$(BoldDelphi)\Source\ValueSpace\Id;$(BoldDelphi)\Source\ValueSpace\Interfaces;$(BoldDelphi)\Source\ValueSpace\XMLStreaming;$(DCC_UnitSearchPath) + BoldCore + $(BoldDelphi)\Source\Common\Include;$(DCC_UnitSearchPath) 2077 CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments= - true - true - true - true - true - Bold for Delphi Design Package - Bold_Delphi;$(DCC_Define) - true + Bold For Delphi - Core + true + 27 + true - System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) Debug true - CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments= 1033 - vcl;IndySystem;IndyCore;vcldb;FireDAC;FireDACCommonDriver;FireDACCommon;FireDACPgDriver;$(DCC_UsePackage) + vcl;vcldb;$(DCC_UsePackage) - vcl;IndySystem;IndyCore;vcldb;FireDAC;FireDACCommonDriver;FireDACCommon;FireDACPgDriver;$(DCC_UsePackage) + vcl;vcldb;$(DCC_UsePackage) + Debug + true + 1033 DEBUG;$(DCC_Define) @@ -88,369 +97,241 @@ true 1033 + + true + 1033 + false RELEASE;$(DCC_Define) 0 0 + + true + 1033 + MainSource - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - + + + + + + + + + + + - - - - + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + + + + + + + - - - - - - - - + + + + + + + + + + + + + - - - - - + + + + + + + + + - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -458,149 +339,27 @@ - - - - - + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + Cfg_2 Base @@ -619,21 +378,10 @@ - BoldDesignPackage.dpk + BoldCore.dpk - Bold 4.0 for Delphi (VCL GUI) - Bold 4.0 for Delphi - Bold 4.0 for Delphi (Model editor) - Bold 4.0 for Delphi (FireDAC Support) - Bold 4.0 for Delphi (DBExpress Support) - Bold 4.0 for Delphi (COM Support) - Bold 4.0 for Delphi (External Persistence) - Bold 4.0 for Delphi (IBX Support) - Bold 4.0 for Delphi (Utils) - Bold 4.0 for Delphi (XMI Link) - Bold 4.0 for Delphi (UniDAC Support) - Bold 4.0 for Delphi (Object Lending Library Extension) + Bold For Delphi - Core Attracs Components for Delphi 10.4 Sydney Microsoft Office 2000 Sample Automation Server Wrapper Components Microsoft Office XP Sample Automation Server Wrapper Components @@ -655,9 +403,9 @@ true - + - BoldDesignPackage.bpl + BoldCore.bpl true @@ -1356,7 +1104,7 @@ True - False + True 12 diff --git a/BoldDesignPackage.dpk b/BoldDesignPackage.dpk deleted file mode 100644 index 5f12634..0000000 --- a/BoldDesignPackage.dpk +++ /dev/null @@ -1,540 +0,0 @@ -package BoldDesignPackage; - -{$R *.res} -{$IFDEF IMPLICITBUILDING This IFDEF should not be used by users} -{$ALIGN 8} -{$ASSERTIONS ON} -{$BOOLEVAL OFF} -{$DEBUGINFO OFF} -{$EXTENDEDSYNTAX ON} -{$IMPORTEDDATA ON} -{$IOCHECKS ON} -{$LOCALSYMBOLS ON} -{$LONGSTRINGS ON} -{$OPENSTRINGS ON} -{$OPTIMIZATION OFF} -{$OVERFLOWCHECKS ON} -{$RANGECHECKS ON} -{$REFERENCEINFO ON} -{$SAFEDIVIDE OFF} -{$STACKFRAMES ON} -{$TYPEDADDRESS OFF} -{$VARSTRINGCHECKS ON} -{$WRITEABLECONST OFF} -{$MINENUMSIZE 1} -{$IMAGEBASE $400000} -{$DEFINE DEBUG} -{$DEFINE Bold_Delphi} -{$ENDIF IMPLICITBUILDING} -{$DESCRIPTION 'Bold for Delphi Design Package'} -{$DESIGNONLY} -{$IMPLICITBUILD ON} - -requires - vcl, - vcldb, - DesignIDE, - FireDac, - FireDACCommonDriver, - FireDACCommon, - FireDACPgDriver, - IndySystem, - IndyCore; - -contains - Bold_MSXML_TLB in 'Source\Common\MsXml\Bold_MSXML_TLB.pas', - BoldAbstractComClientPersistenceHandles in 'Source\Persistence\COM\BoldAbstractComClientPersistenceHandles.pas', - BoldAbstractComPersistenceControllerProxy in 'Source\Persistence\COM\BoldAbstractComPersistenceControllerProxy.pas', - BoldAbstractDatabaseAdapter in 'Source\Persistence\DB\BoldAbstractDatabaseAdapter.pas', - BoldAbstractDequeuer in 'Source\Common\Queue\BoldAbstractDequeuer.pas', - BoldAbstractListHandle in 'Source\Handles\Core\BoldAbstractListHandle.pas', - BoldAbstractLockManagerAdminHandle in 'Source\ConcurrencyControl\Common\BoldAbstractLockManagerAdminHandle.pas', - BoldAbstractLockManagerHandle in 'Source\ConcurrencyControl\Common\BoldAbstractLockManagerHandle.pas', - BoldAbstractModel in 'Source\MoldModel\Handles\BoldAbstractModel.pas', - BoldAbstractObjectUpgrader in 'Source\PMapper\Core\BoldAbstractObjectUpgrader.pas', - BoldAbstractObjectUpgraderHandle in 'Source\Persistence\ObjectUpgrading\BoldAbstractObjectUpgraderHandle.pas', - BoldAbstractPersistenceHandleDB in 'Source\Persistence\DB\BoldAbstractPersistenceHandleDB.pas', - BoldAbstractPropagatorHandle in 'Source\Propagator\Common\BoldAbstractPropagatorHandle.pas', - BoldAbstractPropertyEditors in 'Source\Common\IDE\BoldAbstractPropertyEditors.pas', - BoldAbstractSnooper in 'Source\Persistence\Core\BoldAbstractSnooper.pas', - BoldAction in 'Source\BoldAwareGUI\Actions\BoldAction.pas', - BoldActionDefs in 'Source\Handles\Actions\BoldActionDefs.pas', - BoldActions in 'Source\Handles\Actions\BoldActions.pas', - BoldAFP in 'Source\BoldAwareGUI\FormGen\BoldAFP.pas', - BoldAFPDefault in 'Source\BoldAwareGUI\FormGen\BoldAFPDefault.pas', - BoldAFPPluggable in 'Source\BoldAwareGUI\FormGen\BoldAFPPluggable.pas', - BoldAFPPluggableReg in 'Source\BoldAwareGUI\FormGen\BoldAFPPluggableReg.pas', - BoldAFPUser in 'Source\BoldAwareGUI\FormGen\BoldAFPUser.pas', - BoldAggeregates in 'Source\Common\Core\BoldAggeregates.pas', - BoldApartmentThread in 'Source\Common\COM\BoldApartmentThread.pas', - BoldAttributes in 'Source\ObjectSpace\BORepresentation\BoldAttributes.pas', - BoldAttributeWizard in 'Source\ObjectSpace\IDE\AttributeWizard\BoldAttributeWizard.pas', - BoldAwareGuiComReg in 'Source\ClientGuiCom\IDE\BoldAwareGuiComReg.pas', - BoldAwareGuiReg in 'Source\BoldAwareGUI\IDE\BoldAwareGuiReg.pas', - BoldBase in 'Source\Common\Core\BoldBase.pas', - BoldBase64 in 'Source\Common\Support\BoldBase64.pas', - BoldBatchUpgrader in 'Source\Persistence\ObjectUpgrading\BoldBatchUpgrader.pas', - BoldBld in 'Source\MoldModel\Bld\BoldBld.pas', - BoldCaptionController in 'Source\BoldAwareGUI\BoldControls\BoldCaptionController.pas', - BoldCheckBox in 'Source\BoldAwareGUI\BoldControls\BoldCheckBox.pas', - BoldCheckboxStateControlPack in 'Source\BoldAwareGUI\ControlPacks\BoldCheckboxStateControlPack.pas', - BoldCheckListBox in 'Source\Samples\BoldCheckListBox\BoldCheckListBox.pas', - BoldCheckListBoxReg in 'Source\Samples\BoldCheckListBox\BoldCheckListBoxReg.pas', - BoldClient in 'Source\Common\Connection\BoldClient.pas', - BoldClientHandles in 'Source\Common\ConnectionHandles\BoldClientHandles.pas', - BoldCodePlugins in 'Source\UMLModel\Plugins\BoldCodePlugins.pas', - BoldCollections in 'Source\Common\Support\BoldCollections.pas', - BoldComAdapter in 'Source\Common\COM\BoldComAdapter.pas', - BoldComboBox in 'Source\BoldAwareGUI\BoldControls\BoldComboBox.pas', - BoldComboBoxPropertyEditors in 'Source\BoldAwareGUI\IDE\BoldComboBoxPropertyEditors.pas', - BoldComClient in 'Source\Common\ConnectionCOM\BoldComClient.pas', - BoldComClientElementHandles in 'Source\Handles\COM\BoldComClientElementHandles.pas', - BoldComClientHandles in 'Source\Common\ConnectionHandlesCOM\BoldComClientHandles.pas', - BoldComConnection in 'Source\Common\ConnectionCOM\BoldComConnection.pas', - BoldComConst in 'Source\Common\COM\BoldComConst.pas', - BoldComEditors in 'Source\Common\IDECOM\BoldComEditors.pas', - BoldComElementHandleReg in 'Source\Handles\IDECOM\BoldComElementHandleReg.pas', - BoldComEventQueue in 'Source\Common\COM\BoldComEventQueue.pas', - BoldCommonBitmaps in 'Source\Common\Support\BoldCommonBitmaps.pas', - BoldCommonConst in 'Source\Common\Core\BoldCommonConst.pas', - BoldComObj in 'Source\Common\COM\BoldComObj.pas', - BoldComObjectSpace in 'Source\ObjectSpace\COM\BoldComObjectSpace.pas', - BoldComObjectSpace_TLB in 'Source\ObjectSpace\COM\BoldComObjectSpace_TLB.pas', - BoldComObjectSpaceAdapters in 'Source\ObjectSpace\COM\BoldComObjectSpaceAdapters.pas', - BoldComPersistenceHandleReg in 'Source\Persistence\IDECOM\BoldComPersistenceHandleReg.pas', - BoldComponentValidator in 'Source\ObjectSpace\UtilsGUI\BoldComponentValidator.pas', - BoldComponentValidatorCom in 'Source\ObjectSpace\COM\BoldComponentValidatorCom.pas', - BoldComponentValidatorIDE in 'Source\ObjectSpace\IDE\BoldComponentValidatorIDE.pas', - BoldComReg in 'Source\Common\IDECOM\BoldComReg.pas', - BoldComServer in 'Source\Common\ConnectionCOM\BoldComServer.pas', - BoldComServerElementHandleFactory in 'Source\Handles\COM\BoldComServerElementHandleFactory.pas', - BoldComServerElementHandles in 'Source\Handles\COM\BoldComServerElementHandles.pas', - BoldComServerHandles in 'Source\Common\ConnectionHandlesCOM\BoldComServerHandles.pas', - BoldComThreads in 'Source\Common\COM\BoldComThreads.pas', - BoldComUtils in 'Source\Common\COM\BoldComUtils.pas', - BoldConcurrencyControlReg in 'Source\ConcurrencyControl\IDECOM\BoldConcurrencyControlReg.pas', - BoldCondition in 'Source\ValueSpace\Condition\BoldCondition.pas', - BoldConstraintValidator in 'Source\Samples\ConstraintValidator\BoldConstraintValidator.pas', - BoldConstraintValidatorReg in 'Source\Samples\ConstraintValidator\BoldConstraintValidatorReg.pas', - BoldContainers in 'Source\Common\Core\BoldContainers.pas', - BoldControllerListControlPack in 'Source\BoldAwareGUI\ControlPacks\BoldControllerListControlPack.pas', - BoldControlPack in 'Source\BoldAwareGUI\ControlPacks\BoldControlPack.pas', - BoldControlPackDefs in 'Source\Common\Support\BoldControlPackDefs.pas', - BoldControlPackPropertyEditors in 'Source\BoldAwareGUI\IDE\BoldControlPackPropertyEditors.pas', - BoldControlsDefs in 'Source\Common\Support\BoldControlsDefs.pas', - BoldCoreConsts in 'Source\ObjectSpace\Core\BoldCoreConsts.pas', - BoldCursorGuard in 'Source\Common\UtilsGUI\BoldCursorGuard.pas', - BoldCursorHandle in 'Source\Handles\Core\BoldCursorHandle.pas', - BoldCustomBlobMapper in 'Source\PMapper\Default\BoldCustomBlobMapper.pas', - BoldCustomCheckListBox in 'Source\Samples\BoldCheckListBox\BoldCustomCheckListBox.pas', - BoldDatabaseAdapterFireDAC in 'Source\Persistence\FireDAC\BoldDatabaseAdapterFireDAC.pas', - BoldDataBlock in 'Source\Common\HTTP\BoldDataBlock.pas', - BoldDateTimeControlPack in 'Source\BoldAwareGUI\ControlPacks\BoldDateTimeControlPack.pas', - BoldDBActions in 'Source\Persistence\DB\BoldDBActions.pas', - BoldDbDataValidator in 'Source\PMapper\Validator\BoldDbDataValidator.pas', - BoldDbEvolutor in 'Source\PMapper\DbEvolutor\BoldDbEvolutor.pas', - BoldDbEvolutorForm in 'Source\PMapper\DbEvolutor\BoldDbEvolutorForm.pas', - BoldDbEvolutorScript in 'Source\PMapper\DbEvolutor\BoldDbEvolutorScript.pas', - BoldDBInterfaces in 'Source\Persistence\DB\BoldDBInterfaces.pas', - BoldDbPlugins in 'Source\UMLModel\Plugins\BoldDbPlugins.pas', - BoldDbStructureValidator in 'Source\PMapper\Validator\BoldDbStructureValidator.pas', - BoldDbValidator in 'Source\PMapper\Validator\BoldDbValidator.pas', - BoldDebugActions in 'Source\Samples\Actions\BoldDebugActions.pas', - BoldDefaultId in 'Source\ValueSpace\Id\BoldDefaultId.pas', - BoldDefaultStreamNames in 'Source\ValueSpace\XMLStreaming\BoldDefaultStreamNames.pas', - BoldDefaultTaggedValues in 'Source\Common\TaggedValues\BoldDefaultTaggedValues.pas', - BoldDefaultXMLStreaming in 'Source\ValueSpace\XMLStreaming\BoldDefaultXMLStreaming.pas', - BoldDefs in 'Source\Common\Core\BoldDefs.pas', - BoldDefsDT in 'Source\Common\IDE\BoldDefsDT.pas', - BoldDerivationExpressionsEditor in 'Source\UMLModel\Editor\BoldDerivationExpressionsEditor.pas', - BoldDerivedHandle in 'Source\Handles\Core\BoldDerivedHandle.pas', - BoldDerivedValueSet in 'Source\ObjectSpace\BORepresentation\BoldDerivedValueSet.pas', - BoldDeriver in 'Source\Common\Subscription\BoldDeriver.pas', - BoldDirectoryTraverser in 'Source\Common\Support\BoldDirectoryTraverser.pas', - BoldDomainElement in 'Source\ObjectSpace\BORepresentation\BoldDomainElement.pas', - BoldDragDropTarget in 'Source\BoldAwareGUI\BoldControls\BoldDragDropTarget.pas', - BoldDragObject in 'Source\UMLModel\Editor\BoldDragObject.pas', - BoldEdit in 'Source\BoldAwareGUI\BoldControls\BoldEdit.pas', - BoldEditOCLAction in 'Source\Samples\Actions\BoldEditOCLAction.pas', - BoldEditOCLActionPropEditor in 'Source\Samples\IDE\BoldEditOCLActionPropEditor.pas', - BoldElementHandleFollower in 'Source\BoldAwareGUI\ControlPacks\BoldElementHandleFollower.pas', - BoldElementList in 'Source\ObjectSpace\BORepresentation\BoldElementList.pas', - BoldElements in 'Source\ObjectSpace\Core\BoldElements.pas', - BoldEnvironment in 'Source\Common\Environment\BoldEnvironment.pas', - BoldEnvironmentIDE in 'Source\Common\Environment\BoldEnvironmentIDE.pas', - BoldEnvironmentVCL in 'Source\Common\Environment\BoldEnvironmentVCL.pas', - BoldEventQueue in 'Source\Common\Queue\BoldEventQueue.pas', - BoldExceptionHandlers in 'Source\BoldAwareGUI\Core\BoldExceptionHandlers.pas', - BoldExpert in 'Source\Common\IDE\BoldExpert.pas', - BoldExpertMenus in 'Source\Common\IDE\BoldExpertMenus.pas', - BoldExpressionHandle in 'Source\Handles\Core\BoldExpressionHandle.pas', - BoldExternalizedReferences in 'Source\Common\Support\BoldExternalizedReferences.pas', - BoldExternalObjectSpaceEventHandler in 'Source\ObjectSpace\BORepresentation\BoldExternalObjectSpaceEventHandler.pas', - BoldExternalObjectSpaceEventHandlerReg in 'Source\ObjectSpace\IDE\BoldExternalObjectSpaceEventHandlerReg.pas', - BoldFileHandler in 'Source\Common\Support\BoldFileHandler.pas', - BoldFilteredHandle in 'Source\Handles\Core\BoldFilteredHandle.pas', - BoldFireDACConsts in 'Source\Persistence\FireDAC\BoldFireDACConsts.pas', - BoldFireDACInterfaces in 'Source\Persistence\FireDAC\BoldFireDACInterfaces.pas', - BoldFloatControlPack in 'Source\BoldAwareGUI\ControlPacks\BoldFloatControlPack.pas', - BoldFormSaver in 'Source\Samples\FormSaver\BoldFormSaver.pas', - BoldFormSaverActions in 'Source\Samples\FormSaver\BoldFormSaverActions.pas', - BoldFreeStandingValueFactories in 'Source\FreestandingValueSpace\Core\BoldFreeStandingValueFactories.pas', - BoldFreeStandingValues in 'Source\FreestandingValueSpace\Core\BoldFreeStandingValues.pas', - BoldGen in 'Source\MoldModel\CodeGenerator\BoldGen.pas', - BoldGeneratedCodeDictionary in 'Source\ObjectSpace\RTModel\BoldGeneratedCodeDictionary.pas', - BoldGeneratorTemplates in 'Source\MoldModel\CodeGenerator\BoldGeneratorTemplates.pas', - BoldGeneratorTemplatesCPP in 'Source\MoldModel\CodeGenerator\BoldGeneratorTemplatesCPP.pas', - BoldGeneratorTemplatesDelphi in 'Source\MoldModel\CodeGenerator\BoldGeneratorTemplatesDelphi.pas', - BoldGenericListControlPack in 'Source\BoldAwareGUI\ControlPacks\BoldGenericListControlPack.pas', - BoldGlobalId in 'Source\ValueSpace\Id\BoldGlobalId.pas', - BoldGrid in 'Source\BoldAwareGUI\BoldControls\BoldGrid.pas', - BoldGridPropertyEditors in 'Source\BoldAwareGUI\IDE\BoldGridPropertyEditors.pas', - BoldGridRTColEditor in 'Source\BoldAwareGUI\BoldControls\BoldGridRTColEditor.pas', - BoldGuard in 'Source\Common\Support\BoldGuard.pas', - BoldGUI in 'Source\BoldAwareGUI\Core\BoldGUI.pas', - BoldGUIDUtils in 'Source\Common\Support\BoldGUIDUtils.pas', - BoldGuiResourceStrings in 'Source\BoldAwareGUI\Core\BoldGuiResourceStrings.pas', - BoldHandle in 'Source\Common\Handles\BoldHandle.pas', - BoldHandleAction in 'Source\Handles\Actions\BoldHandleAction.pas', - BoldHandleComReg in 'Source\ClientHandlesCom\IDE\BoldHandleComReg.pas', - BoldHandlePropEditor in 'Source\Handles\IDE\BoldHandlePropEditor.pas', - BoldHandleReg in 'Source\Handles\IDE\BoldHandleReg.pas', - BoldHandles in 'Source\Handles\Core\BoldHandles.pas', - BoldHandlesPropagationReg in 'Source\Persistence\IDE\BoldHandlesPropagationReg.pas', - BoldHashIndexes in 'Source\Common\Support\BoldHashIndexes.pas', - BoldHTTPClientPersistenceHandle in 'Source\Persistence\HTTP\BoldHTTPClientPersistenceHandle.pas', - BoldHTTPClientPersistenceHandleReg in 'Source\Persistence\IDECOM\BoldHTTPClientPersistenceHandleReg.pas', - BoldHTTPPersistenceControllerClient in 'Source\Persistence\HTTP\BoldHTTPPersistenceControllerClient.pas', - BoldHTTPServerPersistenceHandlePassthrough in 'Source\Persistence\HTTP\BoldHTTPServerPersistenceHandlePassthrough.pas', - BoldHTTPServerPersistenceHandlePassthroughReg in 'Source\Persistence\IDECOM\BoldHTTPServerPersistenceHandlePassthroughReg.pas', - BoldId in 'Source\ValueSpace\Id\BoldId.pas', - BoldIDAdder in 'Source\Persistence\Propagation\BoldIDAdder.pas', - BoldIDAdderHandle in 'Source\Persistence\Propagation\BoldIDAdderHandle.pas', - BoldIDEConsts in 'Source\Common\IDE\BoldIDEConsts.pas', - BoldIDEMenus in 'Source\Common\IDE\BoldIDEMenus.pas', - BoldIDESupport in 'Source\Common\IDE\BoldIDESupport.pas', - BoldImage in 'Source\BoldAwareGUI\BoldControls\BoldImage.pas', - BoldImageBitmap in 'Source\BoldAwareGUI\BoldControls\BoldImageBitmap.pas', - BoldImageJPEG in 'Source\BoldAwareGUI\BoldControls\BoldImageJPEG.pas', - BoldIndex in 'Source\Common\Support\BoldIndex.pas', - BoldIndexableList in 'Source\Common\Support\BoldIndexableList.pas', - BoldIndexCollection in 'Source\Common\Support\BoldIndexCollection.pas', - BoldIsoDateTime in 'Source\Common\Support\BoldIsoDateTime.pas', - BoldLabel in 'Source\BoldAwareGUI\BoldControls\BoldLabel.pas', - BoldLinks in 'Source\ObjectSpace\BORepresentation\BoldLinks.pas', - BoldListActions in 'Source\Handles\Actions\BoldListActions.pas', - BoldListBox in 'Source\BoldAwareGUI\BoldControls\BoldListBox.pas', - BoldListControlPack in 'Source\BoldAwareGUI\ControlPacks\BoldListControlPack.pas', - BoldListenerCOM in 'Source\Persistence\Propagation\BoldListenerCOM.pas', - BoldListenerHandle in 'Source\Persistence\Propagation\BoldListenerHandle.pas', - BoldListenerThread in 'Source\Persistence\Propagation\BoldListenerThread.pas', - BoldListHandle in 'Source\Handles\Core\BoldListHandle.pas', - BoldListHandleFollower in 'Source\BoldAwareGUI\ControlPacks\BoldListHandleFollower.pas', - BoldListListControlPack in 'Source\BoldAwareGUI\ControlPacks\BoldListListControlPack.pas', - BoldLockHandler in 'Source\ObjectSpace\PessimisticLocking\BoldLockHandler.pas', - BoldLockHolder in 'Source\ObjectSpace\PessimisticLocking\BoldLockHolder.pas', - BoldLockingDefs in 'Source\ConcurrencyControl\Common\BoldLockingDefs.pas', - BoldLockingHandles in 'Source\Handles\PessimisticLocking\BoldLockingHandles.pas', - BoldLockingReg in 'Source\Handles\IDE\BoldLockingReg.pas', - BoldLockingSupportInterfaces_TLB in 'Source\Propagator\Common\BoldLockingSupportInterfaces_TLB.pas', - BoldLockManagerAdminHandleCom in 'Source\ConcurrencyControl\COM\BoldLockManagerAdminHandleCom.pas', - BoldLockManagerHandleCom in 'Source\ConcurrencyControl\COM\BoldLockManagerHandleCom.pas', - BoldLockRegions in 'Source\ObjectSpace\PessimisticLocking\BoldLockRegions.pas', - BoldLockUtils in 'Source\Samples\Misc\BoldLockUtils.pas', - BoldLogForm in 'Source\Common\Logging\BoldLogForm.pas', - BoldLoggableCriticalSection in 'Source\Common\Support\BoldLoggableCriticalSection.pas', - BoldLogHandler in 'Source\Common\Logging\BoldLogHandler.pas', - BoldLogHandlerForm in 'Source\Common\Logging\BoldLogHandlerForm.pas', - BoldLogHandlerSimple in 'Source\Common\Logging\BoldLogHandlerSimple.pas', - BoldLogReceiverInterface in 'Source\Common\Logging\BoldLogReceiverInterface.pas', - BoldManipulatorReg in 'Source\Handles\IDE\BoldManipulatorReg.pas', - BoldManipulators in 'Source\Handles\Manipulators\BoldManipulators.pas', - BoldMappingInfo in 'Source\PMapper\Default\BoldMappingInfo.pas', - BoldMath in 'Source\Common\Support\BoldMath.pas', - BoldMemberTypeDictionary in 'Source\ObjectSpace\RTModel\BoldMemberTypeDictionary.pas', - BoldMemo in 'Source\BoldAwareGUI\BoldControls\BoldMemo.pas', - BoldMemoryManager in 'Source\Common\Support\BoldMemoryManager.pas', - BoldMeta in 'Source\MoldModel\Core\BoldMeta.pas', - BoldMetaElementList in 'Source\ObjectSpace\Core\BoldMetaElementList.pas', - BoldMetaSupport in 'Source\MoldModel\Core\BoldMetaSupport.pas', - BoldMLAttributes in 'Source\ObjectSpace\BORepresentation\BoldMLAttributes.pas', - BoldMLRenderers in 'Source\BoldAwareGUI\ControlPacks\BoldMLRenderers.pas', - BoldModel in 'Source\UMLModel\Handles\BoldModel.pas', - BoldModelAwareComponentEditor in 'Source\Common\IDE\BoldModelAwareComponentEditor.pas', - BoldModelLoader in 'Source\Samples\ModelLoader\BoldModelLoader.pas', - BoldModelOCLValidatorPlugIn in 'Source\UMLModel\Plugins\BoldModelOCLValidatorPlugIn.pas', - BoldModelReg in 'Source\MoldModel\IDE\BoldModelReg.pas', - BoldMoldConsts in 'Source\MoldModel\Core\BoldMoldConsts.pas', - BoldNamedValueList in 'Source\Common\Support\BoldNamedValueList.pas', - BoldNameExpander in 'Source\MoldModel\Core\BoldNameExpander.pas', - BoldNavigator in 'Source\BoldAwareGUI\BoldControls\BoldNavigator.pas', - BoldNavigatorDefs in 'Source\Common\Support\BoldNavigatorDefs.pas', - BoldNewObjectInterceptor in 'Source\Samples\NewObjectInterceptor\BoldNewObjectInterceptor.pas', - BoldNodeControlPack in 'Source\BoldAwareGUI\ControlPacks\BoldNodeControlPack.pas', - BoldNodeDescriptionEditor in 'Source\BoldAwareGUI\IDE\BoldNodeDescriptionEditor.pas', - BoldNumericControlPack in 'Source\BoldAwareGUI\ControlPacks\BoldNumericControlPack.pas', - BoldObjectListControllers in 'Source\ObjectSpace\BORepresentation\BoldObjectListControllers.pas', - BoldObjectMarshaler in 'Source\Propagator\Common\BoldObjectMarshaler.pas', - BoldObjectNamePropertyEditor in 'Source\Common\IDECOM\BoldObjectNamePropertyEditor.pas', - BoldObjectRetriever in 'Source\Samples\Misc\BoldObjectRetriever.pas', - BoldObjectSpaceExternalEvents in 'Source\ValueSpace\ExternalEvents\BoldObjectSpaceExternalEvents.pas', - BoldObjectSpaceLists in 'Source\ObjectSpace\BORepresentation\BoldObjectSpaceLists.pas', - BoldObjectUpgrader in 'Source\Persistence\ObjectUpgrading\BoldObjectUpgrader.pas', - BoldObjectUpgraderHandle in 'Source\Persistence\ObjectUpgrading\BoldObjectUpgraderHandle.pas', - BoldObjectUpgraderHandleReg in 'Source\Persistence\IDE\BoldObjectUpgraderHandleReg.pas', - BoldOcl in 'Source\ObjectSpace\Ocl\BoldOcl.pas', - BoldOclClasses in 'Source\ObjectSpace\Ocl\BoldOclClasses.pas', - BoldOclError in 'Source\ObjectSpace\Ocl\BoldOclError.pas', - BoldOclEvaluator in 'Source\ObjectSpace\Ocl\BoldOclEvaluator.pas', - BoldOCLGraphicRTDebug in 'Source\ObjectSpace\UtilsGUI\BoldOCLGraphicRTDebug.pas', - BoldOclLightWeightNodeMaker in 'Source\ObjectSpace\Ocl\BoldOclLightWeightNodeMaker.pas', - BoldOclLightWeightNodes in 'Source\ObjectSpace\Ocl\BoldOclLightWeightNodes.pas', - BoldOclPropEditor in 'Source\ObjectSpace\UtilsGUI\BoldOclPropEditor.pas', - BoldOclRepository in 'Source\Handles\Core\BoldOclRepository.pas', - BoldOclRTDebug in 'Source\ObjectSpace\Ocl\BoldOclRTDebug.pas', - BoldOclSemantics in 'Source\ObjectSpace\Ocl\BoldOclSemantics.pas', - BoldOclSymbolImplementations in 'Source\ObjectSpace\Ocl\BoldOclSymbolImplementations.pas', - BoldOclVariables in 'Source\Handles\Core\BoldOclVariables.pas', - BoldOLLEHandlesReg in 'Source\Extensions\OLLE\IDE\BoldOLLEHandlesReg.pas', - BoldOptimisticLockingSupport in 'Source\ObjectSpace\BORepresentation\BoldOptimisticLockingSupport.pas', - BoldORed in 'Source\ObjectSpace\Ocl\BoldORed.pas', - BoldOSSMessage in 'Source\ObjectSpace\BORepresentation\BoldOSSMessage.pas', - BoldOTACodeGen in 'Source\ObjectSpace\IDE\AttributeWizard\BoldOTACodeGen.pas', - BoldOTAFileHandler in 'Source\Common\IDE\BoldOTAFileHandler.pas', - BoldOTASupport in 'Source\Common\IDE\BoldOTASupport.pas', - BoldPageControl in 'Source\BoldAwareGUI\BoldControls\BoldPageControl.pas', - BoldPerformanceCounter in 'Source\Common\Support\BoldPerformanceCounter.pas', - BoldPersistenceController in 'Source\Persistence\Core\BoldPersistenceController.pas', - BoldPersistenceControllerDefault in 'Source\Persistence\DB\BoldPersistenceControllerDefault.pas', - BoldPersistenceControllerPassthrough in 'Source\Persistence\Propagation\BoldPersistenceControllerPassthrough.pas', - BoldPersistenceControllerSOAPAdapterCore in 'Source\Persistence\SOAP\BoldPersistenceControllerSOAPAdapterCore.pas', - BoldPersistenceControllerSystem in 'Source\Persistence\System\BoldPersistenceControllerSystem.pas', - BoldPersistenceHandle in 'Source\Persistence\Core\BoldPersistenceHandle.pas', - BoldPersistenceHandleDB in 'Source\Persistence\DB\BoldPersistenceHandleDB.pas', - BoldPersistenceHandleDB_deprecated in 'Source\Persistence\DB\BoldPersistenceHandleDB_deprecated.pas', - BoldPersistenceHandleDBreg in 'Source\Persistence\DB\BoldPersistenceHandleDBreg.pas', - BoldPersistenceHandleFile in 'Source\Persistence\File\BoldPersistenceHandleFile.pas', - BoldPersistenceHandleFileReg in 'Source\Persistence\IDE\BoldPersistenceHandleFileReg.pas', - BoldPersistenceHandleFileXML in 'Source\Persistence\File\BoldPersistenceHandleFileXML.pas', - BoldPersistenceHandleFireDAC in 'Source\Persistence\FireDAC\BoldPersistenceHandleFireDAC.pas', - BoldPersistenceHandleFireDACReg in 'Source\Persistence\FireDAC\BoldPersistenceHandleFireDACReg.pas', - BoldPersistenceHandlePassthrough in 'Source\Persistence\Core\BoldPersistenceHandlePassthrough.pas', - BoldPersistenceHandlePTWithModel in 'Source\Persistence\Core\BoldPersistenceHandlePTWithModel.pas', - BoldPersistenceHandleReg in 'Source\Persistence\IDE\BoldPersistenceHandleReg.pas', - BoldPersistenceHandleSystem in 'Source\Persistence\System\BoldPersistenceHandleSystem.pas', - BoldPersistenceHandleSystemReg in 'Source\Persistence\IDE\BoldPersistenceHandleSystemReg.pas', - BoldPersistenceNotifier in 'Source\Persistence\Core\BoldPersistenceNotifier.pas', - BoldPersistenceNotifierReg in 'Source\Persistence\IDE\BoldPersistenceNotifierReg.pas', - BoldPersistenceOperationXMLStreaming in 'Source\Persistence\SOAP\BoldPersistenceOperationXMLStreaming.pas', - BoldPlaceableSubscriber in 'Source\Handles\Core\BoldPlaceableSubscriber.pas', - BoldPMapper in 'Source\PMapper\Core\BoldPMapper.pas', - BoldPMapperLists in 'Source\PMapper\Core\BoldPMapperLists.pas', - BoldPMappers in 'Source\PMapper\Core\BoldPMappers.pas', - BoldPMappersAttributeDefault in 'Source\PMapper\Default\BoldPMappersAttributeDefault.pas', - BoldPMappersDefault in 'Source\PMapper\Default\BoldPMappersDefault.pas', - BoldPMappersLinkDefault in 'Source\PMapper\Default\BoldPMappersLinkDefault.pas', - BoldPMappersSQL in 'Source\PMapper\SQL\BoldPMappersSQL.pas', - BoldPMConsts in 'Source\PMapper\Core\BoldPMConsts.pas', - BoldPriorityQueue in 'Source\Common\Support\BoldPriorityQueue.pas', - BoldProgressBar in 'Source\BoldAwareGUI\BoldControls\BoldProgressBar.pas', - BoldPropagatorConstants in 'Source\Propagator\Common\BoldPropagatorConstants.pas', - BoldPropagatorGUIDs in 'Source\Propagator\Common\BoldPropagatorGUIDs.pas', - BoldPropagatorHandleCOM in 'Source\Propagator\COM\BoldPropagatorHandleCOM.pas', - BoldPropagatorHandleCOMReg in 'Source\Propagator\IDECOM\BoldPropagatorHandleCOMReg.pas', - BoldPropagatorInterfaces_TLB in 'Source\Propagator\Common\BoldPropagatorInterfaces_TLB.pas', - BoldPropagatorUtils in 'Source\Persistence\Propagation\BoldPropagatorUtils.pas', - BoldPropertiesController in 'Source\BoldAwareGUI\BoldControls\BoldPropertiesController.pas', - BoldPropertiesControllerPropertyEditors in 'Source\BoldAwareGUI\IDE\BoldPropertiesControllerPropertyEditors.pas', - BoldPropertyEditors in 'Source\Common\IDE\BoldPropertyEditors.pas', - BoldPSDescriptions in 'Source\PMapper\Core\BoldPSDescriptions.pas', - BoldPSDescriptionsDefault in 'Source\PMapper\Default\BoldPSDescriptionsDefault.pas', - BoldPSDescriptionsSQL in 'Source\PMapper\SQL\BoldPSDescriptionsSQL.pas', - BoldPSParams in 'Source\PMapper\Core\BoldPSParams.pas', - BoldPSParamsDefault in 'Source\PMapper\Default\BoldPSParamsDefault.pas', - BoldPSParamsSQL in 'Source\PMapper\SQL\BoldPSParamsSQL.pas', - BoldQueryUserDlg in 'Source\Common\UtilsGUI\BoldQueryUserDlg.pas', - BoldQueue in 'Source\Common\Queue\BoldQueue.pas', - BoldRawSQLHandle in 'Source\Handles\Core\BoldRawSQLHandle.pas', - BoldReferenceHandle in 'Source\Handles\Core\BoldReferenceHandle.pas', - BoldReg in 'Source\Common\IDE\BoldReg.pas', - BoldRegionDefinitionParser in 'Source\ObjectSpace\PessimisticLocking\BoldRegionDefinitionParser.pas', - BoldRegionDefinitions in 'Source\ObjectSpace\PessimisticLocking\BoldRegionDefinitions.pas', - BoldRegistry in 'Source\Common\Support\BoldRegistry.pas', - BoldRev in 'Source\Common\Support\BoldRev.pas', - BoldRichEdit in 'Source\BoldAwareGUI\BoldControls\BoldRichEdit.pas', - BoldRootedHandles in 'Source\Handles\Core\BoldRootedHandles.pas', - BoldRose2000Support in 'Source\Common\Rose2000\BoldRose2000Support.pas', - BoldRose98ptyCreator in 'Source\UMLModel\ModelLinks\Rose98\BoldRose98ptyCreator.pas', - BoldRose98Support in 'Source\Common\Rose98\BoldRose98Support.pas', - BoldRose98TaggedValues in 'Source\UMLModel\ModelLinks\Rose98\BoldRose98TaggedValues.pas', - BoldSamplesReg in 'Source\Samples\IDE\BoldSamplesReg.pas', - BoldSelectionListBox in 'Source\Samples\BoldCheckListBox\BoldSelectionListBox.pas', - BoldSelectionListBoxReg in 'Source\Samples\BoldCheckListBox\BoldSelectionListBoxReg.pas', - BoldServer in 'Source\Common\Connection\BoldServer.pas', - BoldServerHandles in 'Source\Common\ConnectionHandles\BoldServerHandles.pas', - BoldSharedStrings in 'Source\Common\Support\BoldSharedStrings.pas', - BoldSmallLogFrame in 'Source\Common\Logging\BoldSmallLogFrame.pas', - BoldSnooper in 'Source\Persistence\Propagation\BoldSnooper.pas', - BoldSnooperHandle in 'Source\Persistence\Propagation\BoldSnooperHandle.pas', - BoldSOAP_TLB in 'Source\Common\SOAP\BoldSOAP_TLB.pas', - BoldSOAP2_TLB in 'Source\Common\SOAP\BoldSOAP2_TLB.pas', - BoldSOAPClientPersistenceHandles in 'Source\Persistence\SOAP\BoldSOAPClientPersistenceHandles.pas', - BoldSOAPPersistenceControllerProxy in 'Source\Persistence\SOAP\BoldSOAPPersistenceControllerProxy.pas', - BoldSOAPPersistenceControllerStub in 'Source\Persistence\SOAP\BoldSOAPPersistenceControllerStub.pas', - BoldSOAPServerPersistenceHandles in 'Source\Persistence\SOAP\BoldSOAPServerPersistenceHandles.pas', - BoldSortedHandle in 'Source\Handles\Core\BoldSortedHandle.pas', - BoldSorter in 'Source\Common\Support\BoldSorter.pas', - BoldSQLDatabaseConfig in 'Source\PMapper\SQL\BoldSQLDatabaseConfig.pas', - BoldSQLHandle in 'Source\Handles\Core\BoldSQLHandle.pas', - BoldSQLMappingInfo in 'Source\PMapper\SQL\BoldSQLMappingInfo.pas', - BoldSqlNodeMaker in 'Source\PMapper\SQL\BoldSqlNodeMaker.pas', - BoldSqlNodes in 'Source\PMapper\SQL\BoldSqlNodes.pas', - BoldSqlNodesResolver in 'Source\PMapper\SQL\BoldSqlNodesResolver.pas', - BoldSQLQuery in 'Source\PMapper\SQL\BoldSQLQuery.pas', - BoldSqlQueryGenerator in 'Source\PMapper\SQL\BoldSqlQueryGenerator.pas', - BoldSqlSymbols in 'Source\PMapper\SQL\BoldSqlSymbols.pas', - BoldSSExcept in 'Source\ObjectSpace\Ocl\BoldSSExcept.pas', - BoldSSLexU in 'Source\ObjectSpace\Ocl\BoldSSLexU.pas', - BoldSSYaccU in 'Source\ObjectSpace\Ocl\BoldSSYaccU.pas', - BoldStreams in 'Source\Common\Core\BoldStreams.pas', - BoldStringControlPack in 'Source\BoldAwareGUI\ControlPacks\BoldStringControlPack.pas', - BoldStringId in 'Source\ValueSpace\Id\BoldStringId.pas', - BoldStringList in 'Source\Common\Support\BoldStringList.pas', - BoldStringsPropertyController in 'Source\BoldAwareGUI\BoldControls\BoldStringsPropertyController.pas', - BoldSubscribableCollection in 'Source\Common\Subscription\BoldSubscribableCollection.pas', - BoldSubscription in 'Source\Common\Subscription\BoldSubscription.pas', - BoldSupportConst in 'Source\Common\Support\BoldSupportConst.pas', - BoldSystem in 'Source\ObjectSpace\BORepresentation\BoldSystem.pas', - BoldSystemComparer in 'Source\Samples\SystemComparer\BoldSystemComparer.pas', - BoldSystemDebuggerForm in 'Source\Samples\SystemDebugger\BoldSystemDebuggerForm.pas', - BoldSystemHandle in 'Source\Handles\Core\BoldSystemHandle.pas', - BoldSystemOldValuehandler in 'Source\ObjectSpace\BORepresentation\BoldSystemOldValuehandler.pas', - BoldSystemPersistenceHandler in 'Source\ObjectSpace\BORepresentation\BoldSystemPersistenceHandler.pas', - BoldSystemRT in 'Source\ObjectSpace\RTModel\BoldSystemRT.pas', - BoldTaggedValueList in 'Source\Common\TaggedValues\BoldTaggedValueList.pas', - BoldTaggedValueSupport in 'Source\Common\TaggedValues\BoldTaggedValueSupport.pas', - BoldTemplate in 'Source\Common\Template\BoldTemplate.pas', - BoldTemplateExpander in 'Source\Common\Support\BoldTemplateExpander.pas', - BoldTextStream in 'Source\Common\IDE\BoldTextStream.pas', - BoldThread in 'Source\Common\SupportWin\BoldThread.pas', - BoldThreadedComObjectFactory in 'Source\Common\COM\BoldThreadedComObjectFactory.pas', - BoldThreadSafeLog in 'Source\Common\Logging\BoldThreadSafeLog.pas', - BoldThreadSafeQueue in 'Source\Common\Core\BoldThreadSafeQueue.pas', - BoldTrackBar in 'Source\BoldAwareGUI\BoldControls\BoldTrackBar.pas', - BoldTreeView in 'Source\BoldAwareGUI\BoldControls\BoldTreeView.pas', - BoldTreeViewConfig in 'Source\BoldAwareGUI\BoldControls\BoldTreeViewConfig.pas', - BoldTypeList in 'Source\ObjectSpace\BORepresentation\BoldTypeList.pas', - BoldTypeNameDictionary in 'Source\MoldModel\TypeNameDictionary\BoldTypeNameDictionary.pas', - BoldTypeNameEditor in 'Source\MoldModel\UtilsGUI\BoldTypeNameEditor.pas', - BoldTypeNameHandle in 'Source\MoldModel\Handles\BoldTypeNameHandle.pas', - BoldTypeNameHandleReg in 'Source\MoldModel\IDE\BoldTypeNameHandleReg.pas', - BoldTypeNameSelector in 'Source\ObjectSpace\UtilsGUI\BoldTypeNameSelector.pas', - BoldUDPBroadcasterReg in 'Source\Persistence\IDEUDP\BoldUDPBroadcasterReg.pas', - BoldUMLAbstractModelValidator in 'Source\UMLModel\Core\BoldUMLAbstractModelValidator.pas', - BoldUMLAddTV in 'Source\UMLModel\Editor\BoldUMLAddTV.pas', - BoldUMLAttributes in 'Source\UMLModel\Core\BoldUMLAttributes.pas', - BoldUMLBldLink in 'Source\UMLModel\ModelLinks\Bld\BoldUMLBldLink.pas', - BoldUMLConstraintEditor in 'Source\UMLModel\Editor\BoldUMLConstraintEditor.pas', - BoldUMLDelphiSupport in 'Source\Common\UML\BoldUMLDelphiSupport.pas', - BoldUMLModel in 'Source\UMLModel\Core\BoldUMLModel.pas', - BoldUMLModelConverter in 'Source\UMLModel\Core\BoldUMLModelConverter.pas', - BoldUMLModelDataModule in 'Source\UMLModel\Core\BoldUMLModelDataModule.pas', - BoldUMLModelEdit in 'Source\UMLModel\Editor\BoldUMLModelEdit.pas', - BoldUMLModelEditForm in 'Source\UMLModel\Editor\BoldUMLModelEditForm.pas', - BoldUMLModelEditPlugIn in 'Source\UMLModel\Plugins\BoldUMLModelEditPlugIn.pas', - BoldUMLModelEditReg in 'Source\UMLModel\Ide\BoldUMLModelEditReg.pas', - BoldUMLModelHandleReg in 'Source\UMLModel\Ide\BoldUMLModelHandleReg.pas', - BoldUMLModelLink in 'Source\UMLModel\ModelLinks\Core\BoldUMLModelLink.pas', - BoldUMLModelLinkSupport in 'Source\UMLModel\ModelLinks\Core\BoldUMLModelLinkSupport.pas', - BoldUMLModelStreamer in 'Source\UMLModel\Handles\BoldUMLModelStreamer.pas', - BoldUMLModelSupport in 'Source\UMLModel\Core\BoldUMLModelSupport.pas', - BoldUMLModelToEcoIIIGenerator in 'Source\UMLModel\Plugins\BoldUMLModelToEcoIIIGenerator.pas', - BoldUMLModelUpdater in 'Source\UMLModel\Core\BoldUMLModelUpdater.pas', - BoldUMLModelValidationForm in 'Source\UMLModel\Editor\BoldUMLModelValidationForm.pas', - BoldUMLModelValidator in 'Source\UMLModel\Core\BoldUMLModelValidator.pas', - BoldUMLNameTrimmer in 'Source\Samples\UMLPlugins\BoldUMLNameTrimmer.pas', - BoldUMLOCLEditor in 'Source\UMLModel\Editor\BoldUMLOCLEditor.pas', - BoldUMLOCLValidator in 'Source\UMLModel\Core\BoldUMLOCLValidator.pas', - BoldUMLPluginCallBacks in 'Source\UMLModel\Plugins\BoldUMLPluginCallBacks.pas', - BoldUMLPlugins in 'Source\UMLModel\Plugins\BoldUMLPlugins.pas', - BoldUMLRose98Link in 'Source\UMLModel\ModelLinks\Rose98\BoldUMLRose98Link.pas', - BoldUMLRose98Linkreg in 'Source\UMLModel\ModelLinks\Rose98\BoldUMLRose98Linkreg.pas', - BoldUMLRose98MappingUtils in 'Source\UMLModel\ModelLinks\Rose98\BoldUMLRose98MappingUtils.pas', - BoldUMLRose98Support in 'Source\UMLModel\ModelLinks\Rose98\BoldUMLRose98Support.pas', - BoldUMLTaggedValues in 'Source\Common\TaggedValues\BoldUMLTaggedValues.pas', - BoldUMLTaggedValuesEditor in 'Source\UMLModel\Editor\BoldUMLTaggedValuesEditor.pas', - BoldUMLTypes in 'Source\Common\UML\BoldUMLTypes.pas', - BoldUMLUsesEditorForm in 'Source\UMLModel\Editor\BoldUMLUsesEditorForm.pas', - BoldUMLUtils in 'Source\UMLModel\Core\BoldUMLUtils.pas', - BoldUMXMILinkreg in 'Source\UMLModel\ModelLinks\XMI\BoldUMXMILinkreg.pas', - BoldUndoActions in 'Source\Handles\Actions\BoldUndoActions.pas', - BoldUndoHandler in 'Source\ObjectSpace\Undo\BoldUndoHandler.pas', - BoldUndoInterfaces in 'Source\ObjectSpace\Interfaces\BoldUndoInterfaces.pas', - BoldUnloader in 'Source\ObjectSpace\Unloader\BoldUnloader.pas', - BoldUnloaderHandle in 'Source\Handles\UnLoader\BoldUnloaderHandle.pas', - BoldUpdatePrecondition in 'Source\Persistence\Core\BoldUpdatePrecondition.pas', - BoldUtils in 'Source\Common\Support\BoldUtils.pas', - BoldValueInterfaces in 'Source\ValueSpace\Interfaces\BoldValueInterfaces.pas', - BoldValueSpaceInterfaces in 'Source\ValueSpace\Interfaces\BoldValueSpaceInterfaces.pas', - BoldVariableDefinition in 'Source\Handles\Core\BoldVariableDefinition.pas', - BoldVariableHandle in 'Source\Handles\Core\BoldVariableHandle.pas', - BoldVariantControlPack in 'Source\BoldAwareGUI\ControlPacks\BoldVariantControlPack.pas', - BoldVclUtils in 'Source\ObjectSpace\IDE\AttributeWizard\BoldVclUtils.pas', - BoldViewerControlPack in 'Source\BoldAwareGUI\ControlPacks\BoldViewerControlPack.pas', - BoldWAClassInfo in 'Source\ObjectSpace\IDE\AttributeWizard\BoldWAClassInfo.pas', - BoldWACustomAttr in 'Source\ObjectSpace\IDE\AttributeWizard\BoldWACustomAttr.pas', - BoldWACustomAttrForm1 in 'Source\ObjectSpace\IDE\AttributeWizard\BoldWACustomAttrForm1.pas', - BoldWAdatamodule in 'Source\ObjectSpace\IDE\AttributeWizard\BoldWAdatamodule.pas', - BoldWAdmTemplates in 'Source\ObjectSpace\IDE\AttributeWizard\BoldWAdmTemplates.pas', - BoldWAInputFormUnit in 'Source\ObjectSpace\IDE\AttributeWizard\BoldWAInputFormUnit.pas', - BoldWAInterfaces in 'Source\ObjectSpace\IDE\AttributeWizard\BoldWAInterfaces.pas', - BoldWAMainForm in 'Source\ObjectSpace\IDE\AttributeWizard\BoldWAMainForm.pas', - BoldWAMethodInfo in 'Source\ObjectSpace\IDE\AttributeWizard\BoldWAMethodInfo.pas', - BoldWAStringGridManager in 'Source\ObjectSpace\IDE\AttributeWizard\BoldWAStringGridManager.pas', - BoldWASubClassForm1 in 'Source\ObjectSpace\IDE\AttributeWizard\BoldWASubClassForm1.pas', - BoldWAValueSetDlg in 'Source\ObjectSpace\IDE\AttributeWizard\BoldWAValueSetDlg.pas', - BoldWAValueSetForm1 in 'Source\ObjectSpace\IDE\AttributeWizard\BoldWAValueSetForm1.pas', - BoldWCodeInformer in 'Source\ObjectSpace\IDE\AttributeWizard\BoldWCodeInformer.pas', - BoldWebConnection in 'Source\Common\HTTP\BoldWebConnection.pas', - BoldWebConnectionReg in 'Source\Common\IDE\BoldWebConnectionReg.pas', - BoldWinINet in 'Source\Common\SupportWin\BoldWinINet.pas', - BoldWinUtils in 'Source\Common\SupportWin\BoldWinUtils.pas', - BoldWProjectWizard in 'Source\ObjectSpace\IDE\AttributeWizard\BoldWProjectWizard.pas', - BoldWScanner in 'Source\ObjectSpace\IDE\AttributeWizard\BoldWScanner.pas', - BoldWSimpleMenuWizard in 'Source\ObjectSpace\IDE\BoldWSimpleMenuWizard.pas', - BoldXCVTreeView in 'Source\BoldAwareGUI\BoldControls\BoldXCVTreeView.pas', - BoldXMLDispatcher in 'Source\Common\ConnectionHandlesCOM\BoldXMLDispatcher.pas', - BoldXMLDispatcherEditor in 'Source\Common\IDECOM\BoldXMLDispatcherEditor.pas', - BoldXMLDispatcherReg in 'Source\Common\IDECOM\BoldXMLDispatcherReg.pas', - BoldXMLDispatcherVB in 'Source\Common\ConnectionHandlesCOM\BoldXMLDispatcherVB.pas', - BoldXMLDispatcherVBReg in 'Source\Common\IDECOM\BoldXMLDispatcherVBReg.pas', - BoldXMLProducers in 'Source\Handles\XML\BoldXMLProducers.pas', - BoldXMLReg in 'Source\Handles\IDE\BoldXMLReg.pas', - BoldXMLRequests in 'Source\Common\SOAP\BoldXMLRequests.pas', - BoldXMLStreaming in 'Source\Common\Support\BoldXMLStreaming.pas', - FreeStandingValuesConst in 'Source\FreestandingValueSpace\Core\FreeStandingValuesConst.pas', - HandlesConst in 'Source\Handles\Core\HandlesConst.pas', - PersistenceConsts in 'Source\Persistence\Core\PersistenceConsts.pas', - PropagatorConsts in 'Source\Propagator\Common\PropagatorConsts.pas', - RationalRose2000_TLB in 'Source\Common\Rose2000\RationalRose2000_TLB.pas', - RationalRose98_TLB in 'Source\Common\Rose98\RationalRose98_TLB.pas', - UMLConsts in 'Source\UMLModel\Core\UMLConsts.pas', - ValueSpaceConst in 'Source\ValueSpace\Id\ValueSpaceConst.pas', - BoldAbstractExternalPersistenceController in 'Source\Persistence\ExternalPersistence\BoldAbstractExternalPersistenceController.pas', - BoldAbstractExternalPersistenceHandle in 'Source\Persistence\ExternalPersistence\BoldAbstractExternalPersistenceHandle.pas', - BoldAbstractPartiallyExternalPC in 'Source\Persistence\ExternalPersistence\BoldAbstractPartiallyExternalPC.pas', - BoldAbstractPartiallyExternalPH in 'Source\Persistence\ExternalPersistence\BoldAbstractPartiallyExternalPH.pas', - BoldExternalPersistenceConfigItemDataSet in 'Source\Persistence\ExternalPersistence\BoldExternalPersistenceConfigItemDataSet.pas', - BoldExternalPersistenceControllerConfig in 'Source\Persistence\ExternalPersistence\BoldExternalPersistenceControllerConfig.pas', - BoldExternalPersistenceControllerDataSet in 'Source\Persistence\ExternalPersistence\BoldExternalPersistenceControllerDataSet.pas', - BoldExternalPersistenceControllerEventDriven in 'Source\Persistence\ExternalPersistence\BoldExternalPersistenceControllerEventDriven.pas', - BoldExternalPersistenceControllerSQL in 'Source\Persistence\ExternalPersistence\BoldExternalPersistenceControllerSQL.pas', - BoldExternalPersistenceHandleDataSet in 'Source\Persistence\ExternalPersistence\BoldExternalPersistenceHandleDataSet.pas', - BoldExternalPersistenceHandleEventDriven in 'Source\Persistence\ExternalPersistence\BoldExternalPersistenceHandleEventDriven.pas', - BoldExternalPersistenceHandleSQL in 'Source\Persistence\ExternalPersistence\BoldExternalPersistenceHandleSQL.pas', - BoldExternalPersistenceHandleSQLPropEditor in 'Source\Persistence\ExternalPersistence\BoldExternalPersistenceHandleSQLPropEditor.pas', - BoldExternalPersistenceHandlesReg in 'Source\Persistence\ExternalPersistence\BoldExternalPersistenceHandlesReg.pas', - BoldExternalPersistenceSupport in 'Source\Persistence\ExternalPersistence\BoldExternalPersistenceSupport.pas', - ExPeConsts in 'Source\Persistence\ExternalPersistence\ExPeConsts.pas'; - -end. diff --git a/BoldForDelphi.groupproj b/BoldForDelphi.groupproj index 725adb4..026fd37 100644 --- a/BoldForDelphi.groupproj +++ b/BoldForDelphi.groupproj @@ -3,64 +3,25 @@ {DFD5A34D-3F28-461E-9001-16DFEADD40A9} - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -71,194 +32,77 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - + - + diff --git a/BoldUniDAC.dpk b/BoldUniDAC.dpk index 4a5296d..94a9071 100644 --- a/BoldUniDAC.dpk +++ b/BoldUniDAC.dpk @@ -40,7 +40,6 @@ contains BoldPersistenceHandleUniDACReg in 'Source\Persistence\UniDAC\BoldPersistenceHandleUniDACReg.pas', BoldUniDACInterfaces in 'Source\Persistence\UniDAC\BoldUniDACInterfaces.pas', UniDACConsts in 'Source\Persistence\UniDAC\UniDACConsts.pas', - BoldDatabaseAdapterUniDAC in 'Source\Persistence\UniDAC\BoldDatabaseAdapterUniDAC.pas', - BoldPersistenceHandleUniDAC in 'Source\Persistence\UniDAC\BoldPersistenceHandleUniDAC.pas'; + BoldDatabaseAdapterUniDAC in 'Source\Persistence\UniDAC\BoldDatabaseAdapterUniDAC.pas'; end. diff --git a/Source/BoldAwareGUI/BoldDevex/BoldAFPCxGridProviderUnit.pas b/Source/BoldAwareGUI/BoldDevex/BoldAFPCxGridProviderUnit.pas new file mode 100644 index 0000000..758ac61 --- /dev/null +++ b/Source/BoldAwareGUI/BoldDevex/BoldAFPCxGridProviderUnit.pas @@ -0,0 +1,196 @@ +unit BoldAFPCxGridProviderUnit; + +interface + +uses + cxGrid, + cxGridBoldSupportUnit, + BoldAFPDefault, + BoldAFP, + BoldAbstractListHandle; + +type + TBoldCxGridFormProviderForList = class(TBoldDefaultFormProvider) + private + fGrid: TcxGrid; + fListHandle: TBoldAbstractListHandle; + function GetlistHandle: TBoldAbstractListHandle; + protected + procedure EnsureHandle; override; + procedure PreEnsureComponents; override; + property Grid: TcxGrid read fGrid; + property ListHandle: TBoldAbstractListHandle read GetlistHandle; + end; + + TBoldCxGridObjectAutoFormProvider = class(TBoldDefaultObjectAutoFormProvider) + protected + procedure EnsureMultiRoleMemberControls; override; + end; + +implementation + +uses + BoldElements, + BoldReferenceHandle, + BoldListHandle, + BoldSystemRT, +// BoldNavigator, + BoldSystem, + Controls, + ComCtrls, + SysUtils, + cxGridCustomPopupMenu, + cxGridPopupMenu; + +const + BOXMARGIN = 8; + BOXSPACING = 2; + CONTROLMARGIN = 10; + LISTBOXLABELHEIGHT = 18; + MAXFORMHEIGHT = 450; + MINFORMHEIGHT = 150; + EDITHEIGHT = 20; + EDITWIDTH = 121; + LISTBOXHEIGHT = 97; + LISTBOXWIDTH = 121; + PANELHEIGHT = 35; + +{ TBoldCxGridFormProviderForList } + +procedure TBoldCxGridFormProviderForList.EnsureHandle; +var + DesignTimeContext: TBoldElementTypeInfo; +begin + BoldHandle := TBoldReferenceHandle.Create(Form); + DesignTimeContext := Element.BoldType; + if DesignTimeContext is TBoldListTypeInfo then + DesignTimeContext := (DesignTimeContext as TBoldListTypeInfo).ListElementTypeInfo; + BoldHandle.StaticValueTypeName := DesignTimeContext.ExpressionName; + BoldHandle.OnObjectDeleted := DefaultReceiveObjectGone; + BoldHandle.OnValueDestroyed := DefaultReceiveObjectGone; + inherited; +end; + +function TBoldCxGridFormProviderForList.GetlistHandle: TBoldAbstractListHandle; +begin + if not assigned(fListHandle) then + begin + fListHandle := TBoldListHandle.Create(Form); + fListHandle.RootHandle := BoldHandle; + end; + Result := fListHandle; +end; + +procedure TBoldCxGridFormProviderForList.PreEnsureComponents; +var + lcxGridBoldTableView: TcxGridBoldTableView; + lcxGridPopupMenu: TcxGridPopupMenu; +begin + inherited; + fGrid := TcxGrid.Create(Form); + with fGrid do + begin + Name := 'Grid'; // do not localize + fGrid.Levels.Add; + lcxGridBoldTableView := fGrid.CreateView(TcxGridBoldTableView) as TcxGridBoldTableView; + lcxGridBoldTableView.OptionsBehavior.ImmediateEditor := false; + lcxGridBoldTableView.OptionsBehavior.IncSearch := true; + Levels[0].GridView := lcxGridBoldTableView; + lcxGridBoldTableView.OptionsSelection.MultiSelect := true; + lcxGridBoldTableView.DataController.BoldAutoColumns := true; + lcxGridBoldTableView.DataController.BoldHandle := ListHandle; + + lcxGridPopupMenu := TcxGridPopupMenu.Create(Form); + lcxGridPopupMenu.Grid := fGrid; + +// BoldShowConstraints := BoldShowConstraintsInAutoFormGrids; +// BoldAutoColumns := True; + + Align := alClient; + Parent := Target; + end; + +{ with TBoldNavigator.Create(Form) do + begin + Parent := Target; + Align := alBottom; + Boldhandle := ListHandle; + name := 'BoldNavigator'; // do not localize + end; +} + Form.Caption := Element.BoldType.ModelName; + ListHandle.Name := 'BoldListHandle'; // do not localize +end; + +{ TBoldCxGridObjectAutoFormProvider } + +procedure TBoldCxGridObjectAutoFormProvider.EnsureMultiRoleMemberControls; +var + i: integer; + Member: TBoldMemberRTInfo; + ListHandle: TBoldListHandle; + lGrid: TcxGrid; + lView: TcxGridBoldTableView; + TabSheet: TTabSheet; + DesInfo: longint; + ValueType: TBoldElementTypeInfo; +// Navigator: TBoldNavigator; +begin + for i := 0 to MemberRTInfoList.Count - 1 do + begin + Member := MemberRTInfoList[i]; + if Member.IsMultiRole then + begin + if MemberShouldBeDisplayed(Member) then + begin + TabSheet := CreateTabSheet(Member.ModelName, MakeComponentName('Tab', ClassTypeInfo, Member)); // do not localize + + listHandle := TBoldListHandle.Create(TabSheet); // must be tabsheet for "ActivateTabSheetHandle" to work + ListHandle.Enabled := False; + TabSheet.OnShow := ActivateTabSheetHandle; + + LongRec(desinfo).Lo := CONTROLMARGIN; //set Left + LongRec(desinfo).Hi := CONTROLMARGIN; //Set Top; + listHandle.DesignInfo := desInfo; + listHandle.RootHandle := BoldHandle; + listHandle.Expression := Member.ExpressionName; + listHandle.MutableListExpression := Member.ExpressionName; + listHandle.Name := MakeComponentName('Handle', ClassTypeInfo, Member); // do not localize + ValueType := Member.BoldType; + if ValueType is TBoldListTypeInfo then + ValueType := (ValueType as TBoldListTypeInfo).ListElementTypeInfo; + listHandle.RootTypeName := ValueType.ExpressionName; + listHandle.StaticSystemHandle := self.BoldHandle.StaticSystemHandle; + + lGrid := TcxGrid.Create(TabSheet); + lGrid.Name := MakeComponentName('Grid', ClassTypeInfo, Member); // do not localize + lGrid.Levels.Add; + lView := lGrid.CreateView(TcxGridBoldTableView) as TcxGridBoldTableView; + lView.OptionsBehavior.ImmediateEditor := false; + lView.OptionsBehavior.IncSearch := true; + lGrid.Levels[0].GridView := lView; + lView.DataController.BoldHandle := ListHandle; + lView.DataController.BoldAutoColumns := True; + lView.OptionsSelection.MultiSelect := true; + lGrid.Align := alClient; + lGrid.Parent := TabSheet; + +{ Navigator := TBoldNavigator.Create(Form); + NAvigator.align := alBottom; + Navigator.BoldHandle := ListHandle; + Navigator.Parent := TabSheet; +} + end; + end; + end; +end; + +initialization + AutoFormProviderRegistry.RegisterListProvider(bvtClass, TBoldObjectList, TBoldCxGridFormProviderForList); + AutoFormProviderRegistry.RegisterProvider(bvtClass, TBoldObject, TBoldCxGridObjectAutoFormProvider); + +finalization + AutoFormProviderRegistry.UnregisterProvider(TBoldDefaultObjectListAutoFormProvider); + AutoFormProviderRegistry.UnregisterProvider(TBoldCxGridObjectAutoFormProvider); + +end. diff --git a/Source/BoldAwareGUI/BoldDevex/BoldToCxConverterForm.dfm b/Source/BoldAwareGUI/BoldDevex/BoldToCxConverterForm.dfm new file mode 100644 index 0000000..fd40553 --- /dev/null +++ b/Source/BoldAwareGUI/BoldDevex/BoldToCxConverterForm.dfm @@ -0,0 +1,112 @@ +object frmBoldToCxConverter: TfrmBoldToCxConverter + Left = 0 + Top = 0 + Caption = 'Select Components' + ClientHeight = 598 + ClientWidth = 763 + Color = clBtnFace + Font.Charset = DEFAULT_CHARSET + Font.Color = clWindowText + Font.Height = -11 + Font.Name = 'Tahoma' + Font.Style = [] + OldCreateOrder = False + PixelsPerInch = 96 + TextHeight = 13 + object DetectedComponentsGrid: TcxGrid + Left = 0 + Top = 0 + Width = 763 + Height = 392 + Align = alClient + TabOrder = 0 + object tv: TcxGridTableView + Navigator.Buttons.CustomButtons = <> + ScrollbarAnnotations.CustomAnnotations = <> + OnSelectionChanged = tvSelectionChanged + DataController.Summary.DefaultGroupSummaryItems = <> + DataController.Summary.FooterSummaryItems = <> + DataController.Summary.SummaryGroups = <> + OptionsCustomize.ColumnFiltering = False + OptionsCustomize.ColumnGrouping = False + OptionsCustomize.ColumnHidingOnGrouping = False + OptionsCustomize.ColumnHorzSizing = False + OptionsCustomize.ColumnMoving = False + OptionsCustomize.ColumnSorting = False + OptionsSelection.CellSelect = False + OptionsSelection.MultiSelect = True + OptionsSelection.HideFocusRectOnExit = False + object tvColumn1: TcxGridColumn + Caption = 'Component' + Width = 209 + end + object tvColumn2: TcxGridColumn + Caption = 'Type' + Width = 132 + end + object tvColumn3: TcxGridColumn + Caption = 'Ocl Type' + Width = 211 + end + object tvColumn4: TcxGridColumn + Caption = 'Convert to' + Width = 186 + end + end + object DetectedComponentsGridLevel1: TcxGridLevel + GridView = tv + end + end + object Panel1: TPanel + Left = 0 + Top = 558 + Width = 763 + Height = 40 + Align = alBottom + TabOrder = 1 + DesignSize = ( + 763 + 40) + object cxCancelButton: TcxButton + Left = 680 + Top = 7 + Width = 75 + Height = 25 + Anchors = [akRight, akBottom] + Cancel = True + Caption = 'Cancel' + ModalResult = 2 + TabOrder = 0 + OnClick = cxCancelButtonClick + end + object cxConvert: TcxButton + Left = 562 + Top = 7 + Width = 110 + Height = 25 + Anchors = [akRight, akBottom] + Caption = 'Convert Selected' + Enabled = False + ModalResult = 1 + TabOrder = 1 + end + object cxRemoveAfterConvertionCheckbox: TcxCheckBox + Left = 9 + Top = 11 + Anchors = [akLeft, akBottom] + Caption = 'Remove old components after convertion' + State = cbsChecked + TabOrder = 2 + end + end + object cxMemoLog: TcxMemo + Left = 0 + Top = 392 + Align = alBottom + Properties.ReadOnly = True + Properties.ScrollBars = ssVertical + TabOrder = 2 + Height = 166 + Width = 763 + end +end diff --git a/Source/BoldAwareGUI/BoldDevex/BoldToCxConverterForm.pas b/Source/BoldAwareGUI/BoldDevex/BoldToCxConverterForm.pas new file mode 100644 index 0000000..b1ac6e6 --- /dev/null +++ b/Source/BoldAwareGUI/BoldDevex/BoldToCxConverterForm.pas @@ -0,0 +1,55 @@ +unit BoldToCxConverterForm; + +interface + +uses + Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, + Dialogs, cxGraphics, cxControls, cxLookAndFeels, cxLookAndFeelPainters, + cxCustomData, cxFilter, + cxData, cxDataStorage, cxEdit, cxDropDownEdit, Menus, cxContainer, cxCheckBox, + StdCtrls, cxButtons, cxGridCustomTableView, cxGridTableView, cxGridCustomView, + cxClasses, cxGridLevel, cxGrid, cxNavigator, cxStyles, ExtCtrls, + cxTextEdit, cxMemo, dxDateRanges, dxScrollbarAnnotations; + +type + TfrmBoldToCxConverter = class(TForm) + DetectedComponentsGrid: TcxGrid; + DetectedComponentsGridLevel1: TcxGridLevel; + tv: TcxGridTableView; + tvColumn1: TcxGridColumn; + tvColumn2: TcxGridColumn; + tvColumn3: TcxGridColumn; + tvColumn4: TcxGridColumn; + cxConvert: TcxButton; + cxCancelButton: TcxButton; + cxRemoveAfterConvertionCheckbox: TcxCheckBox; + Panel1: TPanel; + cxMemoLog: TcxMemo; + procedure cxCancelButtonClick(Sender: TObject); + procedure tvSelectionChanged(Sender: TcxCustomGridTableView); + private + { Private declarations } + public + { Public declarations } + end; + +var + frmBoldToCxConverter: TfrmBoldToCxConverter; + +implementation + +{$R *.dfm} + +procedure TfrmBoldToCxConverter.cxCancelButtonClick(Sender: TObject); +begin + Self.Close; +end; + +procedure TfrmBoldToCxConverter.tvSelectionChanged( + Sender: TcxCustomGridTableView); +begin + cxConvert.Enabled := tv.Controller.SelectedRecordCount > 0; + cxConvert.Caption := Format('Convert %d Selected', [tv.Controller.SelectedRecordCount]); +end; + +end. diff --git a/Source/BoldAwareGUI/BoldDevex/BoldToCxConverterUnit.pas b/Source/BoldAwareGUI/BoldDevex/BoldToCxConverterUnit.pas new file mode 100644 index 0000000..228b6d2 --- /dev/null +++ b/Source/BoldAwareGUI/BoldDevex/BoldToCxConverterUnit.pas @@ -0,0 +1,804 @@ +unit BoldToCxConverterUnit; + +interface + +uses + Classes, + Controls, + SysUtils, + BoldEdit, + BoldVariantControlPack, + BoldStringControlPack, + BoldComboBox, + BoldGrid, + BoldMemo, + BoldLabel, + Buttons, + cxBoldEditors, + cxGridBoldSupportUnit, + cxGridPopupMenu, + BoldToCxConverterForm, + BoldCaptionController, + BoldPropertiesController, + StdCtrls, + cxGridCustomTableView, + cxTextEdit, + cxLabel, + cxGroupBox, + cxButtons, + cxMemo, + TypInfo; + +type + TBoldToCxConverter = class(TComponent) + private + fBoldToCxConverterForm : TfrmBoldToCxConverter; + fBoldComponents : TStringList; + fLog: TStringList; + + function ConvertGrid(aBoldGrid : TBoldGrid): Boolean; + procedure CopyBoldColumn(aBoldColumn : TBoldGridColumn; aCxGridBoldColumn : TCxGridBoldColumn); + procedure CountNumberOfBoldComponents(var vBoldComponentCount: Integer; AOwner: TComponent); + procedure FoundBoldComponent(aComponent: TComponent); + procedure FoundTBoldGrid(aGrid: TBoldGrid); + procedure FoundTBoldEdit(aEdit: TBoldEdit); + procedure FoundTBoldMemo(aMemo: TBoldMemo); + procedure FoundTBoldLabel(aLabel: TBoldLabel); + procedure FoundTBoldComboBox(aComboBox : TBoldComboBox); + procedure FoundTEdit(aEdit: TEdit); + procedure FoundTLabel(aLabel: TLabel); + procedure FoundTMemo(aMemo: TMemo); + procedure FoundTGroupBox(aBox: TGroupBox); + procedure FoundTSpeedButton(aButton: TSpeedButton); + function ConvertTBoldEdit(aBoldEdit: TBoldEdit): Boolean; + function ConvertTBoldEditToDateEdit(aBoldEdit: TBoldEdit): Boolean; + function ConvertTBoldMemo(aBoldMemo: TBoldMemo): Boolean; + function ConvertTBoldLabel(aBoldLabel: TBoldLabel): Boolean; + function ConvertTBoldComboBox(aBoldComboBox: TBoldComboBox): Boolean; + function ConvertTEdit(aEdit: TEdit): Boolean; + function ConvertTMemo(aMemo: TMemo): Boolean; + function ConvertTLabel(aLabel: TLabel): Boolean; + function ConvertTGroupBox(aBox: TGroupBox): Boolean; + function ConvertTSpeedButton(aButton: TSpeedButton): Boolean; + procedure CopyPublishedProperties(FromControl, ToControl: TControl); + procedure CopyFollowerProperties(FromFollower: TBoldStringFollowerController; ToFollower: TBoldVariantFollowerController); + procedure CopyBoldComboListControllerProperties(FromComboListController: BoldComboBox.TBoldComboListController; ToComboListController: cxBoldEditors.TBoldComboListController); + procedure CheckEvents(AEventList: array of string; AObject: TObject); + function TryRename(aComponent: TComponent): Boolean; + protected + function GridController : TcxGridDataController; + public + constructor Create(AOwner : TComponent); override; + destructor Destroy;override; + { Public declarations } + published + { Published declarations } + end; + +const + Ctrlf = #13#10; + +// cTControlEvents: array[0..9] of string = ('OnAlignPosition', 'OnDockDrop', 'OnDockOver', 'OnEnter', 'OnExit', 'OnGetSiteInfo', 'OnKeyDown', 'OnKeyPress', 'OnKeyUp', 'OnUnDock'); +// cTWinControlEvents: array[0..10] of string = ('OnAlignInsertBefore', 'OnAlignPosition', 'OnDockDrop', 'OnDockOver', 'OnEnter', 'OnExit', 'OnGetSiteInfo', 'OnKeyDown', 'OnKeyPress', 'OnKeyUp', 'OnUnDock'); +{ cTEditEvents: array[0..20] of String = ('OnChange', 'OnClick', 'OnContextPopup', 'OnDblClick', 'OnDragDrop', 'OnDragOver', 'OnEndDock', + 'OnEndDrag', 'OnEnter', 'OnExit', 'OnKeyDown', 'OnKeyPress', 'OnKeyUp', 'OnMouseActivate', 'OnMouseDown', + 'OnMouseEnter', 'OnMouseLeave', 'OnMouseMove', 'OnMouseUp', 'OnStartDock', 'OnStartDrag'); + cTLabelEvents: array[0..14] of String = ('OnClick', 'OnContextPopup', 'OnDblClick', 'OnDragDrop', 'OnDragOver', 'OnEndDock', 'OnEndDrag', + 'OnMouseActivate', 'OnMouseDown', 'OnMouseMove', 'OnMouseUp', 'OnMouseEnter', 'OnMouseLeave', 'OnStartDock', 'OnStartDrag'); + cTMemoEvents: array[0..20] of String = ('OnChange', 'OnClick', 'OnContextPopup', 'OnDblClick', 'OnDragDrop', 'OnDragOver', 'OnEndDock', 'OnEndDrag', + 'OnEnter', 'OnExit', 'OnKeyDown', 'OnKeyPress', 'OnKeyUp', 'OnMouseActivate', 'OnMouseDown', 'OnMouseEnter', + 'OnMouseLeave', 'OnMouseMove', 'OnMouseUp', 'OnStartDock', 'OnStartDrag'); + cTGroupBoxEvents: array[0..22] of String = ('OnAlignInsertBefore', 'OnAlignPosition', 'OnClick', 'OnContextPopup', 'OnDblClick', 'OnDragDrop', 'OnDockDrop', + 'OnDockOver', 'OnDragOver', 'OnEndDock', 'OnEndDrag', 'OnEnter', 'OnExit', 'OnGetSiteInfo', 'OnMouseActivate', + 'OnMouseDown', 'OnMouseEnter', 'OnMouseLeave', 'OnMouseMove', 'OnMouseUp', 'OnStartDock', 'OnStartDrag', 'OnUnDock'); + cTSpeedButtonEvents: array[0..7] of String = ('OnClick', 'OnDblClick', 'OnMouseActivate', 'OnMouseDown', 'OnMouseEnter', 'OnMouseLeave', 'OnMouseMove', 'OnMouseUp');} + + cEvents: array[0..32] of String = ('OnAlignInsertBefore', 'OnAlignPosition', 'OnCanResize', 'OnChange', 'OnClick', 'OnConstrainedResize', 'OnContextPopup', + 'OnDblClick', 'OnDockDrop', 'OnDockOver', 'OnDragDrop', 'OnDragOver', 'OnEndDock', 'OnEndDrag', 'OnEnter', 'OnExit', + 'OnGetSiteInfo', 'OnKeyDown', 'OnKeyPress', 'OnKeyUp', 'OnMouseActivate', 'OnMouseDown', 'OnMouseEnter', 'OnMouseLeave', + 'OnMouseMove', 'OnMouseUp', 'OnMouseWheel', 'OnMouseWheelDown', 'OnMouseWheelUp', 'OnResize', 'OnStartDock', 'OnStartDrag', 'OnUnDock'); + +procedure Register; + +implementation +uses Dialogs, cxGrid,Forms, BoldElements, CxEdit, CxGridLevel; + +procedure Register; +begin + RegisterComponents('AT Core', [TBoldToCxConverter]); +end; + +{ TBoldToCxGridConverter } + +constructor TBoldToCxConverter.Create(AOwner: TComponent); +var + vBoldComponentCount : Integer; + I,j : Integer; + vComponent: TComponent; + res: Boolean; +begin + inherited; + fBoldComponents := TStringList.Create; + fLog := TStringList.Create; + Application.CreateForm(TfrmBoldToCxConverter,fBoldToCxConverterForm); + CountNumberOfBoldComponents(vBoldComponentCount, AOwner); + GridController.RecordCount := vBoldComponentCount; + + for I := 0 to AOwner.ComponentCount - 1 do + begin + vComponent := AOwner.Components[I]; + // TODO + if (vComponent is TBoldGrid) then FoundTBoldGrid(vComponent as TBoldGrid); + if (vComponent is TBoldEdit) then FoundTBoldEdit(vComponent as TBoldEdit); + if (vComponent is TBoldMemo) then FoundTBoldMemo(vComponent as TBoldMemo); + if (vComponent is TBoldLabel) then FoundTBoldLabel(vComponent as TBoldLabel); + if (vComponent is TBoldComboBox) then FoundTBoldComboBox(vComponent as TBoldComboBox); + if (vComponent is TEdit) then FoundTEdit(vComponent as TEdit); + if (vComponent is TLabel) then FoundTLabel(vComponent as TLabel); + if (vComponent is TMemo) then FoundTMemo(vComponent as TMemo); + if (vComponent is TGroupBox) then FoundTGroupBox(vComponent as TGroupBox); + if (vComponent is TSpeedButton) then FoundTSpeedButton(vComponent as TSpeedButton); + + if (vComponent is TBoldCaptionController) then fLog.Add('Achtung: Form enthält einen TBoldCaptionController'); + if (vComponent is TBoldPropertiesController) then fLog.Add('Achtung: Form enthält einen TBoldPropertiesController'); + end; + + if fLog.Count > 0 then + fBoldToCxConverterForm.cxMemoLog.Lines.AddStrings(fLog); + + if fBoldToCxConverterForm.ShowModal = mrOK then + begin + for j := GridController.RecordCount - 1 downto 0 do + if not GridController.IsRowSelected(j) then + fBoldComponents.Delete(fBoldComponents.IndexOf(GridController.GetValue(j,0))); + for I := fBoldComponents.Count - 1 downto 0 do + begin + vComponent := fBoldComponents.Objects[I] as TComponent; + res := false; + // TODO + if vComponent is TBoldGrid then res := ConvertGrid(vComponent as TBoldGrid); + if vComponent is TBoldMemo then res := ConvertTBoldMemo(vComponent as TBoldMemo); + if vComponent is TBoldLabel then res := ConvertTBoldLabel(vComponent as TBoldLabel); + if vComponent is TEdit then res := ConvertTEdit(vComponent as TEdit); + if vComponent is TMemo then res := ConvertTMemo(vComponent as TMemo); + if vComponent is TLabel then res := ConvertTLabel(vComponent as TLabel); + if vComponent is TGroupBox then res := ConvertTGroupBox(vComponent as TGroupBox); + if vComponent is TSpeedButton then res := ConvertTSpeedButton(vComponent as TSpeedButton); + if vComponent is TBoldEdit then + begin + if GridController.Values[I,3] = 'TcxBoldDateEdit' then + res := ConvertTBoldEditToDateEdit(vComponent as TBoldEdit) + else + res := ConvertTBoldEdit(vComponent as TBoldEdit) + end; + if vComponent is TBoldComboBox then res := ConvertTBoldComboBox(vComponent as TBoldComboBox); + + // Altes Component löschen + if res and fBoldToCxConverterForm.cxRemoveAfterConvertionCheckbox.Checked then + vComponent.Free; + end; + end; +end; + +destructor TBoldToCxConverter.Destroy; +begin + fBoldToCxConverterForm.Close; + fBoldToCxConverterForm.Free; + fBoldComponents.Free; + fLog.Free; + inherited; +end; + +procedure TBoldToCxConverter.FoundBoldComponent(aComponent : TComponent); +begin + fBoldComponents.AddObject(aComponent.Name,aComponent); + GridController.Values[fBoldComponents.Count - 1, 0] := aComponent.Name; + GridController.Values[fBoldComponents.Count - 1, 1] := aComponent.ClassName; +end; + +procedure TBoldToCxConverter.FoundTBoldComboBox(aComboBox: TBoldComboBox); +begin + FoundBoldComponent(aComboBox); + GridController.Values[fBoldComponents.Count - 1, 3] := 'TcxBoldComboBox'; +end; + +procedure TBoldToCxConverter.FoundTBoldGrid(aGrid : TBoldGrid); +begin + FoundBoldComponent(aGrid); + GridController.Values[fBoldComponents.Count - 1, 3] := 'TcxGridBoldTableView'; +end; + +procedure TBoldToCxConverter.FoundTBoldLabel(aLabel: TBoldLabel); +begin + CheckEvents(cEvents, aLabel); + FoundBoldComponent(aLabel); + GridController.Values[fBoldComponents.Count - 1, 3] := 'TcxBoldLabel'; +end; + +procedure TBoldToCxConverter.FoundTBoldMemo(aMemo: TBoldMemo); +begin + CheckEvents(cEvents, aMemo); + FoundBoldComponent(aMemo); + GridController.Values[fBoldComponents.Count - 1, 3] := 'TcxBoldMemo'; +end; + +procedure TBoldToCxConverter.FoundTEdit(aEdit: TEdit); +begin + CheckEvents(cEvents, aEdit); + FoundBoldComponent(aEdit); + GridController.Values[fBoldComponents.Count - 1, 3] := 'TcxTextEdit'; +end; + +procedure TBoldToCxConverter.FoundTGroupBox(aBox: TGroupBox); +begin + CheckEvents(cEvents, aBox); + FoundBoldComponent(aBox); + GridController.Values[fBoldComponents.Count - 1, 3] := 'TcxGroupBox'; +end; + +procedure TBoldToCxConverter.FoundTLabel(aLabel: TLabel); +begin + CheckEvents(cEvents, aLabel); + FoundBoldComponent(aLabel); + GridController.Values[fBoldComponents.Count - 1, 3] := 'TcxLabel'; +end; + +procedure TBoldToCxConverter.FoundTMemo(aMemo: TMemo); +begin + CheckEvents(cEvents, aMemo); + FoundBoldComponent(aMemo); + GridController.Values[fBoldComponents.Count - 1, 3] := 'TcxMemo'; +end; + +procedure TBoldToCxConverter.FoundTSpeedButton(aButton: TSpeedButton); +begin + CheckEvents(cEvents, aButton); + FoundBoldComponent(aButton); + GridController.Values[fBoldComponents.Count - 1, 3] := 'TcxButton'; +end; + +procedure TBoldToCxConverter.FoundTBoldEdit(aEdit : TBoldEdit); +var + ExpressionType: TBoldElementTypeInfo; + vProposedComponent: string; +begin + CheckEvents(cEvents, aEdit); + ExpressionType := nil; + FoundBoldComponent(aEdit); + vProposedComponent := 'Unknown'; + + if Assigned(aEdit.BoldHandle) and Assigned(aEdit.BoldHandle.BoldType) and Assigned(aEdit.BoldHandle.BoldType.Evaluator) then + ExpressionType := aEdit.BoldHandle.BoldType.Evaluator.ExpressionType(aEdit.BoldProperties.expression,aEdit.BoldHandle.BoldType,false); + + if Assigned(ExpressionType) then + begin + GridController.Values[fBoldComponents.Count - 1, 2] := ExpressionType.DelphiName; + + if ExpressionType.DelphiName = 'TBADateTime' then + vProposedComponent := 'TcxBoldDateEdit' + else if ExpressionType.DelphiName = 'TBABoolean' then + vProposedComponent := 'TcxBoldCheckBox' + else + vProposedComponent := 'TcxBoldTextEdit'; + end; + GridController.Values[fBoldComponents.Count - 1, 3] := vProposedComponent; +end; + +function TBoldToCxConverter.GridController: TcxGridDataController; +begin + Result := fBoldToCxConverterForm.tv.DataController; +end; + +function TBoldToCxConverter.TryRename(aComponent: TComponent): Boolean; +begin + try + ValidateRename(aComponent, aComponent.Name, 'old' + aComponent.Name); + result := true; + except + on e: Exception do begin + ShowMessage(Format('%s (%s): %s', [aComponent.Name, aComponent.ClassName, e.Message])); + result := false; + end; + end; +end; + +procedure TBoldToCxConverter.CountNumberOfBoldComponents(var vBoldComponentCount: Integer; AOwner: TComponent); +var + I: Integer; + vComponent: TComponent; +begin + vBoldComponentCount := 0; + for I := 0 to AOwner.ComponentCount - 1 do + begin + vComponent := AOwner.Components[I]; + // TODO + if (vComponent is TBoldGrid) or (vComponent is TBoldEdit) or (vComponent is TBoldComboBox) or (vComponent is TBoldMemo) or (vComponent is TBoldLabel) + or (vComponent is TEdit) or (vComponent is TLabel) or (vComponent is TMemo) or (vComponent is TGroupBox) or (vComponent is TSpeedButton) + then + Inc(vBoldComponentCount); + end; +end; + +procedure TBoldToCxConverter.CopyBoldColumn(aBoldColumn: TBoldGridColumn;aCxGridBoldColumn: TCxGridBoldColumn); +begin + aCxGridBoldColumn.DataBinding.BoldProperties.Expression := aBoldColumn.BoldProperties.Expression; + aCxGridBoldColumn.Caption := aBoldColumn.Title.Caption; + aCxGridBoldColumn.name := 'Column' + IntToStr(aCxGridBoldColumn.Index); + if aBoldColumn.BoldProperties.Expression <> '' then + try + aCxGridBoldColumn.name := 'col' + AnsiUpperCase(aBoldColumn.BoldProperties.Expression[1]) + Copy(aBoldColumn.BoldProperties.Expression, 2, 1000); + except + // ignore rename attept + end; +end; + +procedure TBoldToCxConverter.CopyBoldComboListControllerProperties(FromComboListController : BoldComboBox.TBoldComboListController; ToComboListController: cxBoldEditors.TBoldComboListController); +begin + with FromComboListController do + begin + ToComboListController.DragMode := DragMode; + ToComboListController.DropMode := DropMode; + ToComboListController.NilElementMode := NilElementMode; + end; + +end; + +procedure TBoldToCxConverter.CheckEvents(AEventList: array of string; AObject: TObject); +var + i: Integer; + method: TMethod; + str, name: String; +begin + str := ''; + for i := Low(AEventList) to High(AEventList) do begin + if TypInfo.IsPublishedProp(AObject, AEventList[i]) then begin + method := TypInfo.GetMethodProp(AObject, AEventList[i]); + if method.Data <> nil then begin + name := TObject(Method.Data).MethodName(Method.Code); + str := str + Format('%s=%s; ', [AEventList[i], name]); + end; + end; + end; + if str <> '' then + fLog.Add(Format('Events von %s (%s): %s', [(AObject as TComponent).Name, AObject.ClassName, str])); +end; + +function TBoldToCxConverter.ConvertGrid(aBoldGrid : TBoldGrid): Boolean; +var + vCxGrid : TCxGrid; + vCxLevel: TCxGridLevel; + vCxGridBoldTableView : TcxGridBoldTableView; + vCol : Integer; +begin + result := false; + if not TryRename(aBoldGrid) then Exit; + vCxGrid := TcxGrid.Create(aBoldGrid.Owner); + CopyPublishedProperties (aBoldGrid,vCxGrid); + + vCxGridBoldTableView := vCxGrid.CreateView(TcxGridBoldTableView) as TcxGridBoldTableView; + vCxGridBoldTableView.Name := vCxGrid.Name + 'BoldTableView'; + + vCxGridBoldTableView.DataController.BoldHandle := aBoldGrid.BoldHandle; + if vCxGrid.Levels.Count = 0 then + vCxLevel := vCxGrid.Levels.Add + else + vCxLevel := vCxGrid.Levels[0]; + vCxLevel.GridView := vCxGridBoldTableView; + vCxGridBoldTableView.OptionsData.Editing := False; + vCxGridBoldTableView.OptionsView.GroupByBox := False; + vCxGridBoldTableView.OptionsBehavior.CellHints := True; + vCxGridBoldTableView.OptionsSelection.CellSelect := False; + + for vCol := 1 to aBoldGrid.ColCount - 1 do + CopyBoldColumn(aBoldGrid.Columns[vCol],vCxGridBoldTableView.CreateItem as TcxGridBoldColumn ); + result := true; +end; + +function TBoldToCxConverter.ConvertTEdit(aEdit: TEdit): Boolean; +var + vCxEdit : TcxTextEdit; +begin + result := false; + if not TryRename(aEdit) then Exit; + vCxEdit := TcxTextEdit.Create(aEdit.Owner); + vCxEdit.Autosize := aEdit.Autosize; + CopyPublishedProperties(aEdit, vCxEdit); + + vCxEdit.Properties.AutoSelect := aEdit.AutoSelect; + vCXEdit.Style.BorderStyle := ebsFlat; //ABoldEdit.BorderStyle; + vCxEdit.Properties.CharCase := aEdit.CharCase; + vCXEdit.Style.Color := aEdit.Color; + vCxEdit.DragCursor := aEdit.DragCursor; + vCxEdit.DragKind := aEdit.DragKind; + vCxEdit.DragMode := aEdit.DragMode; + vCxEdit.Style.Font := aEdit.Font; + vCxEdit.ParentColor := aEdit.ParentColor; //?? + vCxEdit.ParentFont := aEdit.ParentFont; //?? + vCxEdit.Properties.PasswordChar := aEdit.PasswordChar; + vCxEdit.PopupMenu := aEdit.PopupMenu; + vCxEdit.TabOrder := aEdit.TabOrder; + vCxEdit.TabStop := aEdit.TabStop; + + vCxEdit.Text := aEdit.Text; + if aEdit.ReadOnly then + vCxEdit.Properties.ReadOnly := aEdit.ReadOnly; + if aEdit.MaxLength <> 0 then + vCxEdit.Properties.MaxLength := aEdit.MaxLength; + result := true; +end; + +function TBoldToCxConverter.ConvertTGroupBox(aBox: TGroupBox): Boolean; +var + vCxEdit : TcxGroupBox; + i: Integer; +begin + result := false; + if not TryRename(aBox) then Exit; + vCxEdit := TcxGroupBox.Create(aBox.Owner); + CopyPublishedProperties(aBox, vCxEdit); + + vCXEdit.Style.BorderStyle := ebsFlat; //ABoldEdit.BorderStyle; + vCXEdit.Style.Color := aBox.Color; + vCxEdit.DragCursor := aBox.DragCursor; + vCxEdit.DragKind := aBox.DragKind; + vCxEdit.DragMode := aBox.DragMode; + vCxEdit.Style.Font := aBox.Font; + vCxEdit.ParentColor := aBox.ParentColor; //?? + vCxEdit.ParentFont := aBox.ParentFont; //?? + vCxEdit.PopupMenu := aBox.PopupMenu; + vCxEdit.TabOrder := aBox.TabOrder; + vCxEdit.TabStop := aBox.TabStop; + + vCxEdit.Caption := aBox.Caption; + + for i := aBox.ControlCount - 1 downto 0 do + (aBox.Controls[i] as TControl).Parent := vCxEdit; + result := true; +end; + +function TBoldToCxConverter.ConvertTLabel(aLabel: TLabel): Boolean; +var + vCxEdit : TcxLabel; +begin + result := false; + if not TryRename(aLabel) then Exit; + vCxEdit := TcxLabel.Create(aLabel.Owner); + vCxEdit.Properties.WordWrap := aLabel.WordWrap; + vCxEdit.Autosize := aLabel.Autosize; + CopyPublishedProperties(aLabel, vCxEdit); + + vCXEdit.Style.BorderStyle := ebsNone; + vCXEdit.Style.Color := aLabel.Color; + vCxEdit.DragCursor := aLabel.DragCursor; + vCxEdit.DragKind := aLabel.DragKind; + vCxEdit.DragMode := aLabel.DragMode; + vCxEdit.Style.Font := aLabel.Font; + vCxEdit.ParentColor := aLabel.ParentColor; //?? + vCxEdit.ParentFont := aLabel.ParentFont; //?? + vCxEdit.PopupMenu := aLabel.PopupMenu; + + vCxEdit.Caption := aLabel.Caption; + vCxEdit.Properties.Alignment.Horz := aLabel.Alignment; + case aLabel.Layout of + tlTop: vCxEdit.Properties.Alignment.Vert := taTopJustify; + tlCenter: vCxEdit.Properties.Alignment.Vert := taVCenter; + tlBottom: vCxEdit.Properties.Alignment.Vert := taBottomJustify; + end; + + vCxEdit.Transparent := True; + result := true; +end; + +function TBoldToCxConverter.ConvertTMemo(aMemo: TMemo): Boolean; +var + vCxEdit : TcxMemo; +begin + result := false; + if not TryRename(aMemo) then Exit; + vCxEdit := TcxMemo.Create(aMemo.Owner); + CopyPublishedProperties(aMemo, vCxEdit); + + vCXEdit.Style.BorderStyle := ebsFlat; + vCXEdit.Style.Color := aMemo.Color; + vCxEdit.DragCursor := aMemo.DragCursor; + vCxEdit.DragKind := aMemo.DragKind; + vCxEdit.DragMode := aMemo.DragMode; + vCxEdit.Style.Font := aMemo.Font; + vCxEdit.ParentColor := aMemo.ParentColor; //?? + vCxEdit.ParentFont := aMemo.ParentFont; //?? + vCxEdit.PopupMenu := aMemo.PopupMenu; + if aMemo.ReadOnly then + vCxEdit.Properties.ReadOnly := aMemo.ReadOnly; + vCxEdit.TabOrder := aMemo.TabOrder; + vCxEdit.TabStop := aMemo.TabStop; + + vCxEdit.Lines := aMemo.Lines; + vCxEdit.Properties.ScrollBars := aMemo.ScrollBars; + vCxEdit.Properties.WantReturns := aMemo.WantReturns; + vCxEdit.Properties.WantTabs := aMemo.WantTabs; + vCxEdit.Properties.WordWrap := aMemo.WordWrap; + result := true; +end; + +function TBoldToCxConverter.ConvertTSpeedButton(aButton: TSpeedButton): Boolean; +var + vCxEdit : TcxButton; +begin + result := false; + if not TryRename(aButton) then Exit; + vCxEdit := TcxButton.Create(aButton.Owner); + CopyPublishedProperties(aButton, vCxEdit); + + vCxEdit.ParentFont := aButton.ParentFont; //?? + vCxEdit.PopupMenu := aButton.PopupMenu; + vCxEdit.Caption := aButton.Caption; + if aButton.Glyph <> nil then + vCxEdit.Glyph.SetBitmap(aButton.Glyph); + vCxEdit.TabStop := false; + vCxEdit.SpeedButtonOptions.CanBeFocused := false; + if aButton.Action <> nil then + vCxEdit.Action := aButton.Action; + result := true; +end; + +procedure TBoldToCxConverter.CopyPublishedProperties(FromControl, ToControl : TControl); +var + OldName : string; +begin + + with FromControl do + begin + ToControl.Align := Align; + ToControl.AlignWithMargins := AlignWithMargins; + ToControl.Anchors := Anchors; + ToControl.Constraints := Constraints; + ToControl.Cursor := Cursor; + ToControl.Height := Height; + ToControl.HelpContext := HelpContext; + ToControl.HelpKeyword := HelpKeyword; + ToControl.HelpType := HelpType; + ToControl.Hint := Hint; + ToControl.Left := Left; + ToControl.Margins := Margins; + ToControl.Parent := Parent; + ToControl.Tag := Tag; + ToControl.Top := Top; + ToControl.Width := Width; + ToControl.Enabled := Enabled; + ToControl.ShowHint := ShowHint; + ToControl.Visible := Visible; + + OldName := Name; + Name := 'old' + Name; + end; + ToControl.Name := OldName; + +end; + +function TBoldToCxConverter.ConvertTBoldEdit(aBoldEdit : TBoldEdit): Boolean; +var + vCxBoldEdit : TcxBoldTextEdit; +begin + result := false; + if not TryRename(aBoldEdit) then Exit; + vCxBoldEdit := TcxBoldTextEdit.Create(aBoldEdit.Owner); + CopyPublishedProperties(aBoldEdit, vCxBoldEdit); + vCxBoldEdit.DataBinding.BoldHandle := aBoldEdit.BoldHandle; + vCxBoldEdit.DataBinding.BoldProperties.Expression := aBoldEdit.BoldProperties.Expression; + CopyFollowerProperties(aBoldEdit.BoldProperties,vCxBoldEdit.DataBinding.BoldProperties); + + vCxBoldEdit.Properties.Alignment.Horz := aBoldEdit.Alignment; + vCxBoldEdit.Properties.AutoSelect := aBoldEdit.AutoSelect; + vCxBoldEdit.Autosize := aBoldEdit.Autosize; + vCXBoldEdit.Style.BorderStyle := ebsFlat; //ABoldEdit.BorderStyle; + vCxBoldEdit.Properties.CharCase := aBoldEdit.CharCase; + vCXBoldEdit.Style.Color := aBoldEdit.Color; + vCxBoldEdit.DragCursor := aBoldEdit.DragCursor; + vCxBoldEdit.DragKind := aBoldEdit.DragKind; + vCxBoldEdit.DragMode := aBoldEdit.DragMode; + vCxBoldEdit.Style.Font := aBoldEdit.Font; + vCxBoldEdit.ParentColor := aBoldEdit.ParentColor; //?? + vCxBoldEdit.ParentFont := aBoldEdit.ParentFont; //?? + vCxBoldEdit.Properties.PasswordChar := aBoldEdit.PasswordChar; + + vCxBoldEdit.PopupMenu := aBoldEdit.PopupMenu; + if aBoldEdit.ReadOnly then + vCxBoldEdit.Properties.ReadOnly := aBoldEdit.ReadOnly; + if aBoldEdit.MaxLength <> 0 then + vCxBoldEdit.Properties.MaxLength := aBoldEdit.MaxLength; + vCxBoldEdit.TabOrder := aBoldEdit.TabOrder; + vCxBoldEdit.TabStop := aBoldEdit.TabStop; + vCxBoldEdit.Text := ''; + result := true; +end; + +function TBoldToCxConverter.ConvertTBoldEditToDateEdit(aBoldEdit : TBoldEdit): Boolean; +var + vCxBoldDateEdit : TcxBoldDateEdit; +begin + result := false; + if not TryRename(aBoldEdit) then Exit; + vCxBoldDateEdit := TcxBoldDateEdit.Create(aBoldEdit.Owner); + CopyPublishedProperties(aBoldEdit, vCxBoldDateEdit); + vCxBoldDateEdit.DataBinding.BoldHandle := aBoldEdit.BoldHandle; + vCxBoldDateEdit.DataBinding.BoldProperties.Expression := aBoldEdit.BoldProperties.Expression; + CopyFollowerProperties(aBoldEdit.BoldProperties,vCxBoldDateEdit.DataBinding.BoldProperties); + + vCxBoldDateEdit.Properties.Alignment.Horz := aBoldEdit.Alignment; + vCxBoldDateEdit.Properties.AutoSelect := aBoldEdit.AutoSelect; + vCxBoldDateEdit.Autosize := aBoldEdit.Autosize; + vCxBoldDateEdit.Style.BorderStyle := ebsFlat; //ABoldEdit.BorderStyle; + vCxBoldDateEdit.Properties.CharCase := aBoldEdit.CharCase; + vCxBoldDateEdit.Style.Color := aBoldEdit.Color; + vCxBoldDateEdit.DragCursor := aBoldEdit.DragCursor; + vCxBoldDateEdit.DragKind := aBoldEdit.DragKind; + vCxBoldDateEdit.DragMode := aBoldEdit.DragMode; + vCxBoldDateEdit.Style.Font := aBoldEdit.Font; + vCxBoldDateEdit.ParentColor := aBoldEdit.ParentColor; //?? + vCxBoldDateEdit.ParentFont := aBoldEdit.ParentFont; //?? + vCxBoldDateEdit.Properties.PasswordChar := aBoldEdit.PasswordChar; + + vCxBoldDateEdit.PopupMenu := aBoldEdit.PopupMenu; + if aBoldEdit.ReadOnly then + vCxBoldDateEdit.Properties.ReadOnly := aBoldEdit.ReadOnly; + if aBoldEdit.MaxLength <> 0 then + vCxBoldDateEdit.Properties.MaxLength := aBoldEdit.MaxLength; + vCxBoldDateEdit.TabOrder := aBoldEdit.TabOrder; + vCxBoldDateEdit.TabStop := aBoldEdit.TabStop; + result := true; +end; + + +function TBoldToCxConverter.ConvertTBoldLabel(aBoldLabel: TBoldLabel): Boolean; +var + vCxEdit : TcxBoldLabel; +begin + result := false; + if not TryRename(aBoldLabel) then Exit; + vCxEdit := TcxBoldLabel.Create(aBoldLabel.Owner); + vCxEdit.Properties.WordWrap := aBoldLabel.WordWrap; + vCxEdit.Autosize := aBoldLabel.Autosize; + CopyPublishedProperties(aBoldLabel, vCxEdit); + + vCxEdit.DataBinding.BoldHandle := aBoldLabel.BoldHandle; + vCxEdit.DataBinding.BoldProperties.Expression := aBoldLabel.BoldProperties.Expression; + CopyFollowerProperties(aBoldLabel.BoldProperties,vCxEdit.DataBinding.BoldProperties); + + vCXEdit.Style.BorderStyle := ebsNone; + vCXEdit.Style.Color := aBoldLabel.Color; + vCxEdit.DragCursor := aBoldLabel.DragCursor; + vCxEdit.DragKind := aBoldLabel.DragKind; + vCxEdit.DragMode := aBoldLabel.DragMode; + vCxEdit.Style.Font := aBoldLabel.Font; + vCxEdit.ParentColor := aBoldLabel.ParentColor; //?? + vCxEdit.ParentFont := aBoldLabel.ParentFont; //?? + vCxEdit.PopupMenu := aBoldLabel.PopupMenu; + + vCxEdit.Caption := aBoldLabel.Caption; + vCxEdit.Properties.Alignment.Horz := aBoldLabel.Alignment; + case aBoldLabel.Layout of + tlTop: vCxEdit.Properties.Alignment.Vert := taTopJustify; + tlCenter: vCxEdit.Properties.Alignment.Vert := taVCenter; + tlBottom: vCxEdit.Properties.Alignment.Vert := taBottomJustify; + end; + + vCxEdit.Transparent := True; + result := true; +end; + +function TBoldToCxConverter.ConvertTBoldMemo(aBoldMemo: TBoldMemo): Boolean; +var + vCxEdit : TcxBoldMemo; +begin + result := false; + if not TryRename(aBoldMemo) then Exit; + vCxEdit := TcxBoldMemo.Create(aBoldMemo.Owner); + CopyPublishedProperties(aBoldMemo, vCxEdit); + vCxEdit.DataBinding.BoldHandle := aBoldMemo.BoldHandle; + vCxEdit.DataBinding.BoldProperties.Expression := aBoldMemo.BoldProperties.Expression; + CopyFollowerProperties(aBoldMemo.BoldProperties,vCxEdit.DataBinding.BoldProperties); + + vCXEdit.Style.BorderStyle := ebsFlat; + vCXEdit.Style.Color := aBoldMemo.Color; + vCxEdit.DragCursor := aBoldMemo.DragCursor; + vCxEdit.DragKind := aBoldMemo.DragKind; + vCxEdit.DragMode := aBoldMemo.DragMode; + vCxEdit.Style.Font := aBoldMemo.Font; + vCxEdit.ParentColor := aBoldMemo.ParentColor; //?? + vCxEdit.ParentFont := aBoldMemo.ParentFont; //?? + vCxEdit.PopupMenu := aBoldMemo.PopupMenu; + if aBoldMemo.ReadOnly then + vCxEdit.Properties.ReadOnly := aBoldMemo.ReadOnly; + vCxEdit.TabOrder := aBoldMemo.TabOrder; + vCxEdit.TabStop := aBoldMemo.TabStop; + + vCxEdit.Lines := aBoldMemo.Lines; + vCxEdit.Properties.ScrollBars := aBoldMemo.ScrollBars; + vCxEdit.Properties.WantReturns := aBoldMemo.WantReturns; + vCxEdit.Properties.WantTabs := aBoldMemo.WantTabs; + vCxEdit.Properties.WordWrap := aBoldMemo.WordWrap; + result := true; +end; + +procedure TBoldToCxConverter.CopyFollowerProperties(FromFollower : TBoldStringFollowerController; ToFollower : TBoldVariantFollowerController); +begin + with FromFollower do + begin + ToFollower.Expression := Expression; + ToFollower.ApplyPolicy := ApplyPolicy; + ToFollower.CleanOnEqual := CleanOnEqual; + ToFollower.DragMode := DragMode; + ToFollower.DropMode := DropMode; + ToFollower.NilRepresentation := NilStringRepresentation; + ToFollower.Representation := Representation; + ToFollower.Variables := Variables; + //Renderer One is variant and the other stringrenderer + end; +end; + +function TBoldToCxConverter.ConvertTBoldComboBox(aBoldComboBox : TBoldComboBox): Boolean; +var + vCxBoldComboBox : TcxBoldComboBox; +begin + result := false; + if not TryRename(aBoldComboBox) then Exit; + vCxBoldComboBox := TcxBoldComboBox.Create(aBoldComboBox.Owner); + CopyPublishedProperties (aBoldComboBox, vCxBoldComboBox); + CopyFollowerProperties(aBoldComboBox.BoldProperties,vCxBoldComboBox.DataBinding.BoldProperties); + CopyBoldComboListControllerProperties(aBoldComboBox.BoldListProperties, vCxBoldComboBox.Properties.BoldLookupListProperties); + + vCxBoldComboBox.DataBinding.BoldHandle := aBoldComboBox.BoldHandle; + CopyFollowerProperties(aBoldComboBox.BoldRowProperties, vCxBoldComboBox.Properties.BoldRowProperties); + vCxBoldComboBox.Properties.BoldLookupListHandle := aBoldComboBox.BoldListHandle; + + vCxBoldComboBox.Properties.Alignment.Horz := aBoldComboBox.Alignment; + vCxBoldComboBox.AlignWithMargins := ABoldComboBox.AlignWithMargins; + //vCxBoldComboBox.Properties.AutoSelect := aBoldComboBox.AutoSelect; + //vCxBoldComboBox.Autosize := aBoldComboBox.Autosize; + vCXBoldComboBox.Style.BorderStyle := ebsFlat; //ABoldComboBox.BorderStyle; + vCxBoldComboBox.Properties.CharCase := aBoldComboBox.CharCase; + vCXBoldComboBox.Style.Color := aBoldComboBox.Color; + vCxBoldComboBox.DragCursor := aBoldComboBox.DragCursor; + vCxBoldComboBox.DragKind := aBoldComboBox.DragKind; + vCxBoldComboBox.DragMode := aBoldComboBox.DragMode; + vCxBoldComboBox.Style.Font := aBoldComboBox.Font; + vCxBoldComboBox.ParentColor := aBoldComboBox.ParentColor; + // vCxBoldComboBox.ParentCtl3D := aBoldComboBox.ParentCtl3D; + //MaxLength + vCxBoldComboBox.ParentFont := aBoldComboBox.ParentFont; + vCxBoldComboBox.ParentShowHint := aBoldComboBox.ParentShowHint; + //vCxBoldComboBox.Properties.PasswordChar := aBoldComboBox.PasswordChar; + + vCxBoldComboBox.PopupMenu := aBoldComboBox.PopupMenu; + if aBoldComboBox.ReadOnly then + vCxBoldComboBox.Properties.ReadOnly := aBoldComboBox.ReadOnly; + vCxBoldComboBox.TabOrder := aBoldComboBox.TabOrder; + vCxBoldComboBox.TabStop := aBoldComboBox.TabStop; + vCxBoldComboBox.Properties.BoldSelectChangeAction := aBoldComboBox.BoldSelectChangeAction; + vCxBoldComboBox.Properties.BoldSetValueExpression := aBoldComboBox.BoldSetValueExpression; + + vCXBoldCombobox.Properties.OnChange := aBoldComboBox.OnChange; + vCXBoldCombobox.OnClick := aBoldComboBox.OnClick; + vCXBoldCombobox.OnContextPopup := aBoldComboBox.OnContextPopup; + vCXBoldCombobox.OnDblClick := aBoldComboBox.OnDblClick; + vCXBoldCombobox.OnDragDrop := aBoldComboBox.OnDragDrop; + vCXBoldCombobox.OnDragOver := aBoldComboBox.OnDragOver; + //vCXBoldCombobox.Properties.OnDrawItem := aBoldComboBox.OnDrawItem; + //vCXBoldCombobox.OnDropDown := ???? + vCXBoldCombobox.OnEndDock := aBoldComboBox.OnEndDock; + vCXBoldCombobox.OnEndDrag := aBoldComboBox.OnEndDrag; + vCXBoldCombobox.OnEnter := aBoldComboBox.OnEnter; + vCXBoldCombobox.OnExit := aBoldComboBox.OnExit; + vCXBoldCombobox.OnKeyDown := aBoldComboBox.OnKeyDown; + vCXBoldCombobox.OnKeyPress := aBoldComboBox.OnKeyPress; + vCXBoldCombobox.OnKeyUp := aBoldComboBox.OnKeyUp; + //vCXBoldCombobox.Properties.OnMeasureItem := aBoldComboBox.OnMeasureItem; + //vCXBoldCombobox.Properties.OnSelectChanged := aBoldComboBox.OnSelectChanged; + vCXBoldCombobox.OnStartDock := aBoldComboBox.OnStartDock; + vCXBoldCombobox.OnStartDrag := aBoldComboBox.OnStartDrag; + vCXBoldCombobox.PopupMenu := aBoldComboBox.PopupMenu; + + result := true; +end; + +end. diff --git a/Source/BoldAwareGUI/BoldDevex/BoldToCxGridConverterUnit.pas b/Source/BoldAwareGUI/BoldDevex/BoldToCxGridConverterUnit.pas new file mode 100644 index 0000000..7d563e1 --- /dev/null +++ b/Source/BoldAwareGUI/BoldDevex/BoldToCxGridConverterUnit.pas @@ -0,0 +1,106 @@ +unit BoldToCxGridConverterUnit; + +interface + +uses + BoldGrid, + Classes, + cxGridBoldSupportUnit, + cxGridPopupMenu, + SysUtils; + +type + TBoldToCxGridConverter = class(TComponent) + private + procedure ConvertGrid(aBoldGrid : TBoldGrid); + procedure CopyBoldColumn(aBoldColumn : TBoldGridColumn; aCxGridBoldColumn : TCxGridBoldColumn); + protected + { Protected declarations } + public + constructor Create(AOwner : TComponent); override; + { Public declarations } + published + { Published declarations } + end; + +const + Ctrlf = #13#10; + +procedure Register; + +implementation +uses Dialogs, cxGrid; + +procedure Register; +begin + RegisterComponents('AT Core', [TBoldToCxGridConverter]); +end; + +{ TBoldToCxGridConverter } + +procedure TBoldToCxGridConverter.CopyBoldColumn(aBoldColumn: TBoldGridColumn;aCxGridBoldColumn: TCxGridBoldColumn); +begin + aCxGridBoldColumn.DataBinding.BoldProperties.Expression := aBoldColumn.BoldProperties.Expression; + aCxGridBoldColumn.Caption := aBoldColumn.Title.Caption; + try + aCxGridBoldColumn.name := 'col' + AnsiUpperCase(aBoldColumn.BoldProperties.Expression[1]) + Copy(aBoldColumn.BoldProperties.Expression, 2, 1000); + except + aCxGridBoldColumn.name := 'Column' + IntToStr(aCxGridBoldColumn.Index); + end; +end; + +constructor TBoldToCxGridConverter.Create(AOwner: TComponent); +var + I : Integer; + vGrid : TBoldGrid; +begin + inherited; + for I := 0 to AOwner.ComponentCount - 1 do + begin + if AOwner.Components[I] is TBoldGrid then + begin + vGrid := AOwner.Components[I] as TBoldGrid; + if MessageDlg('Convert ' + vGrid.Name + ' into a cxBoldGrid ?',mtWarning,[mbYes,mbNo],0) = 6 then + ConvertGrid(vGrid); + end; + end; +end; + + +procedure TBoldToCxGridConverter.ConvertGrid(aBoldGrid : TBoldGrid); +var + vCxGrid : TCxGrid; + vCxGridBoldTableView : TcxGridBoldTableView; + vCol : Integer; +begin + + vCxGrid := TcxGrid.Create(aBoldGrid.Owner); + vCxGrid.Name := 'cx'+ aBoldGrid.Name; + vCxGrid.Parent := aBoldGrid.Parent; + vCxGrid.Left := aBoldGrid.Left; + vCxGrid.Top := aBoldGrid.Top; + vCxGrid.Width := aBoldGrid.Width; + vCxGrid.Height := aBoldGrid.Height; + vCxGrid.Align := aBoldGrid.Align; + vCxGrid.Anchors := aBoldGrid.Anchors; + + vCxGridBoldTableView := vCxGrid.CreateView(TcxGridBoldTableView) as TcxGridBoldTableView; + vCxGridBoldTableView.Name := vCxGrid.Name + 'BoldTableView'; + + vCxGridBoldTableView.DataController.BoldHandle := aBoldGrid.BoldHandle; + vCxGrid.Levels[0].GridView := vCxGridBoldTableView; + vCxGridBoldTableView.OptionsData.Editing := False; + vCxGridBoldTableView.OptionsView.GroupByBox := False; + vCxGridBoldTableView.OptionsBehavior.CellHints := True; + vCxGridBoldTableView.OptionsSelection.CellSelect := False; + + for vCol := 1 to aBoldGrid.ColCount - 1 do + CopyBoldColumn(aBoldGrid.Columns[vCol],vCxGridBoldTableView.CreateItem as TcxGridBoldColumn ); + + ShowMessage('Successfully converted ' + aBoldGrid.name + ' into a TcxBoldGrid' + CtrLf + + 'Remember to remove old boldgrid and this converter component.' + Ctrlf + + 'Add a TcxGridPopupMenu component if you want to use menus on the grids header.'); + +end; + +end. diff --git a/Source/BoldAwareGUI/BoldDevex/cxBoldEditConsts.pas b/Source/BoldAwareGUI/BoldDevex/cxBoldEditConsts.pas new file mode 100644 index 0000000..28bccf8 --- /dev/null +++ b/Source/BoldAwareGUI/BoldDevex/cxBoldEditConsts.pas @@ -0,0 +1,39 @@ +unit cxBoldEditConsts; + +interface + +// v2.03 - 25 Jan 2011 2007-2011 Daniel Mauric + +resourcestring + scxSBoldEditRepositoryTextItem = 'BoldTextEdit|Represents a Bold aware single line text editor'; + scxSBoldComboBoxRepositoryTextItem = 'BoldComboBox|Represents a Bold aware combo box editor'; + scxSBoldLookupComboBoxRepositoryTextItem = 'BoldLookupComboBox|Represents a Bold aware lookup combo box editor'; + scxSBoldExtLookupComboBoxRepositoryTextItem = 'BoldExtLookupComboBox|Represents a Bold aware lookup combo using grid as its drop down control'; + +implementation + +uses + dxCore; + +procedure AddEditorsResourceStringNames(AProduct: TdxProductResourceStrings); + + procedure InternalAdd(const AResourceStringName: string; AAdress: Pointer); + begin + AProduct.Add(AResourceStringName, AAdress); + end; + +begin + InternalAdd('scxSBoldEditRepositoryTextItem', @scxSBoldEditRepositoryTextItem); + InternalAdd('scxSBoldComboBoxRepositoryTextItem', @scxSBoldComboBoxRepositoryTextItem); + InternalAdd('scxSBoldLookupComboBoxRepositoryTextItem', @scxSBoldLookupComboBoxRepositoryTextItem); + InternalAdd('scxSBoldExtLookupComboBoxRepositoryTextItem', @scxSBoldExtLookupComboBoxRepositoryTextItem); +end; + + +initialization + dxResourceStringsRepository.RegisterProduct('Bold ExpressEditors Library', @AddEditorsResourceStringNames); + +finalization + dxResourceStringsRepository.UnRegisterProduct('Bold ExpressEditors Library'); + +end. diff --git a/Source/BoldAwareGUI/BoldDevex/cxBoldEditRepositoryItems.pas b/Source/BoldAwareGUI/BoldDevex/cxBoldEditRepositoryItems.pas new file mode 100644 index 0000000..e6a1b1c --- /dev/null +++ b/Source/BoldAwareGUI/BoldDevex/cxBoldEditRepositoryItems.pas @@ -0,0 +1,134 @@ +unit cxBoldEditRepositoryItems; + +interface + +// v2.03 - 25 Jan 2011 2007-2011 Daniel Mauric + +uses + cxEdit, + cxBoldEditors, + cxBoldExtLookupComboBox, + cxBoldLookupComboBox; + +type + TcxEditRepositoryBoldStringItem = class(TcxEditRepositoryItem) + private + function GetProperties: TcxBoldTextEditProperties; + procedure SetProperties(Value: TcxBoldTextEditProperties); + public + class function GetEditPropertiesClass: TcxCustomEditPropertiesClass; override; + published + property Properties: TcxBoldTextEditProperties read GetProperties write SetProperties; + end; + + TcxEditRepositoryBoldComboBoxItem = class(TcxEditRepositoryItem) + private + function GetProperties: TcxBoldComboBoxProperties; + procedure SetProperties(Value: TcxBoldComboBoxProperties); + public + class function GetEditPropertiesClass: TcxCustomEditPropertiesClass; override; + published + property Properties: TcxBoldComboBoxProperties read GetProperties write SetProperties; + end; + + TcxEditRepositoryBoldLookupComboBoxItem = class(TcxEditRepositoryItem) + private + function GetProperties: TcxBoldLookupComboBoxProperties; + procedure SetProperties(Value: TcxBoldLookupComboBoxProperties); + public + class function GetEditPropertiesClass: TcxCustomEditPropertiesClass; override; + published + property Properties: TcxBoldLookupComboBoxProperties read GetProperties write SetProperties; + end; + + TcxEditRepositoryBoldExtLookupComboBoxItem = class(TcxEditRepositoryItem) + private + function GetProperties: TcxBoldExtLookupComboBoxProperties; + procedure SetProperties(Value: TcxBoldExtLookupComboBoxProperties); + public + class function GetEditPropertiesClass: TcxCustomEditPropertiesClass; override; + published + property Properties: TcxBoldExtLookupComboBoxProperties read GetProperties write SetProperties; + end; + +implementation + +uses + Classes; + +{ TcxEditRepositoryBoldStringItem } + +class function TcxEditRepositoryBoldStringItem.GetEditPropertiesClass: TcxCustomEditPropertiesClass; +begin + Result := TcxBoldTextEditProperties; +end; + +function TcxEditRepositoryBoldStringItem.GetProperties: TcxBoldTextEditProperties; +begin + Result := inherited Properties as TcxBoldTextEditProperties; +end; + +procedure TcxEditRepositoryBoldStringItem.SetProperties( + Value: TcxBoldTextEditProperties); +begin + inherited Properties := Value; +end; + +{ TcxEditRepositoryBoldComboBoxItem } + +class function TcxEditRepositoryBoldComboBoxItem.GetEditPropertiesClass: TcxCustomEditPropertiesClass; +begin + Result := TcxBoldComboBoxProperties; +end; + +function TcxEditRepositoryBoldComboBoxItem.GetProperties: TcxBoldComboBoxProperties; +begin + Result := inherited Properties as TcxBoldComboBoxProperties; +end; + +procedure TcxEditRepositoryBoldComboBoxItem.SetProperties( + Value: TcxBoldComboBoxProperties); +begin + inherited Properties := Value; +end; + +{ TcxEditRepositoryBoldLookupComboBoxItem } + +class function TcxEditRepositoryBoldLookupComboBoxItem.GetEditPropertiesClass: TcxCustomEditPropertiesClass; +begin + result := TcxBoldLookupComboBoxProperties; +end; + +function TcxEditRepositoryBoldLookupComboBoxItem.GetProperties: TcxBoldLookupComboBoxProperties; +begin + Result := inherited Properties as TcxBoldLookupComboBoxProperties; +end; + +procedure TcxEditRepositoryBoldLookupComboBoxItem.SetProperties( + Value: TcxBoldLookupComboBoxProperties); +begin + inherited Properties := Value; +end; + +{ TcxEditRepositoryBoldExtLookupComboBoxItem } + +class function TcxEditRepositoryBoldExtLookupComboBoxItem.GetEditPropertiesClass: TcxCustomEditPropertiesClass; +begin + result := TcxBoldExtLookupComboBoxProperties; +end; + +function TcxEditRepositoryBoldExtLookupComboBoxItem.GetProperties: TcxBoldExtLookupComboBoxProperties; +begin + Result := inherited Properties as TcxBoldExtLookupComboBoxProperties; +end; + +procedure TcxEditRepositoryBoldExtLookupComboBoxItem.SetProperties( + Value: TcxBoldExtLookupComboBoxProperties); +begin + inherited Properties := Value; +end; + +initialization + RegisterClasses([TcxEditRepositoryBoldStringItem, TcxEditRepositoryBoldComboBoxItem, TcxEditRepositoryBoldLookupComboBoxItem, TcxEditRepositoryBoldExtLookupComboBoxItem]); + +end. diff --git a/Source/BoldAwareGUI/BoldDevex/cxBoldEditors.pas b/Source/BoldAwareGUI/BoldDevex/cxBoldEditors.pas new file mode 100644 index 0000000..e7fff10 --- /dev/null +++ b/Source/BoldAwareGUI/BoldDevex/cxBoldEditors.pas @@ -0,0 +1,6369 @@ +unit cxBoldEditors; + +{$ASSERTIONS ON} +{$INCLUDE Bold.inc} + +{$DEFINE Constraints} + +{.$DEFINE BoldDevExLog} + +{.$DEFINE LOGCHANGES} + +(* + cxBoldEditors v2.60 - 26 July 2017 + 2007-2017 Daniel Mauric +*) + +interface + +uses + Classes, + SysUtils, + + cxClasses, + cxControls, + cxEdit, + cxTextEdit, + cxDropDownEdit, + cxCalendar, + cxTimeEdit, + cxMemo, + cxCurrencyEdit, + cxMaskEdit, + cxCheckBox, + cxSpinEdit, + cxButtonEdit, + cxHyperLinkEdit, + cxProgressBar, + cxBarEditItem, + dxBar, + cxContainer, + {$IFDEF DevExScheduler} + cxDateNavigator, + {$ENDIF} + cxLabel, + cxImage, + cxRichEdit, + cxCheckListBox, + cxListBox, + cxListView, ComCtrls, + cxDataUtils, + + cxLookAndFeelPainters, // for TcxCheckBoxState = (cbsUnchecked, cbsChecked, cbsGrayed); + StdCtrls, // for TCheckBoxState = (cbUnchecked, cbChecked, cbGrayed); + cxGraphics, + Controls,// for TCaption + Messages, // for TMessage + Windows, + + BoldSubscription, + BoldVariantControlPack, + BoldCheckboxStateControlPack, + BoldControllerListControlPack, + BoldElementHandleFollower, + BoldControlPack, + BoldHandles, + BoldElements, + BoldControlPackDefs, + BoldSystem, + BoldSystemRT, + BoldListHandleFollower, + BoldListListControlPack, + BoldControlsDefs, + BoldDefs, + BoldAbstractListHandle, + BoldComponentvalidator; + +type + TcxCustomBoldEditDefaultValuesProvider = class; + TcxBoldEditDataBinding = class; + TBoldComboListController = class; + TcxCustomBoldTextEditProperties = class; + TcxBoldTextEditProperties = class; + TcxBoldTextEdit = class; + TcxBoldDateEdit = class; + + IcxBoldEditProperties = Interface + ['{D50859F1-F550-4CE6-84DE-5074921512E5}'] + procedure SetStoredValue(aValue: Variant; aBoldHandle: TBoldElementHandle; aEdit: TcxCustomEdit; aFollower: TBoldFollower; var aDone: boolean); + function BoldElementToEditValue(aFollower: TBoldFollower; aElement: TBoldElement; aEdit: TcxCustomEdit): variant; + function CanEdit(aBoldHandle: TBoldElementHandle; aFollower: TBoldFollower): boolean; + end; + + TBoldComboListController = class(TBoldAbstractListAsFollowerListController) + published + property NilElementMode; + end; + + TcxCustomBoldTextEditProperties = class(TcxCustomTextEditProperties, IcxBoldEditProperties, IBoldValidateableComponent) + private + fListHandleFollower: TBoldListHandleFollower; + fBoldListProperties: TBoldAbstractListAsFollowerListController; // TBoldComboListController; + fBoldRowProperties: TBoldVariantFollowerController; + fBoldSelectChangeAction: TBoldComboSelectChangeAction; + fBoldSetValueExpression: TBoldExpression; + function GetBoldListHandle: TBoldAbstractListHandle; + function GetListFollower: TBoldFollower; + procedure SetBoldListHandle(const Value: TBoldAbstractListHandle); + procedure SetBoldListProperties(const Value: TBoldAbstractListAsFollowerListController); + procedure SetRowProperties(const Value: TBoldVariantFollowerController); + function GetContextForBoldRowProperties: TBoldElementTypeInfo; + procedure SetBoldSelectChangeAction(Value: TBoldComboSelectChangeAction); + // IBoldValidateableComponent + function ValidateComponent(ComponentValidator: TBoldComponentValidator; NamePrefix: string): Boolean; + // IcxBoldEditProperties + procedure SetStoredValue(aValue: Variant; aBoldHandle: TBoldElementHandle; aEdit: TcxCustomEdit; aFollower: TBoldFollower; var aDone: boolean); + function BoldElementToEditValue(aFollower: TBoldFollower; aElement: TBoldElement; aEdit: TcxCustomEdit): variant; + function CanEdit(aBoldHandle: TBoldElementHandle; aFollower: TBoldFollower): boolean; + procedure SetBoldSetValueExpression(const Value: TBoldExpression); + protected + function IsNilRepresentation(AValue: Variant): boolean; + procedure _InsertItem(Index: Integer; Follower: TBoldFollower); + procedure _ReplaceItem(Index: Integer; Follower: TBoldFollower); + procedure _DeleteItem(Index: Integer; OwningFollower: TBoldFollower); + procedure _RowAfterMakeUptoDate(Follower: TBoldFollower); + procedure _BeforeMakeUptoDate(Follower: TBoldFollower); + procedure _AfterMakeUptoDate(Follower: TBoldFollower); + property BoldLookupListHandle: TBoldAbstractListHandle read GetBoldListHandle write SetBoldListHandle; + property BoldLookupListProperties: TBoldAbstractListAsFollowerListController read fBoldListProperties write SetBoldListProperties; + property BoldRowProperties: TBoldVariantFollowerController read fBoldRowProperties write SetRowProperties; + property BoldSelectChangeAction: TBoldComboSelectChangeAction read fBoldSelectChangeAction write SetBoldSelectChangeAction default bdcsSetValue; + property BoldSetValueExpression: TBoldExpression read fBoldSetValueExpression write SetBoldSetValueExpression; + public + constructor Create(AOwner: TPersistent); override; + destructor Destroy; override; + class function GetContainerClass: TcxContainerClass; override; + function IsEditValueValid(var EditValue: TcxEditValue; AEditFocused: Boolean): Boolean; override; + property LookupListFollower: TBoldFollower read GetListFollower; + end; + + TcxBoldComboBoxProperties = class(TcxCustomComboBoxProperties, IcxBoldEditProperties, IBoldValidateableComponent) + private + fListHandleFollower: TBoldListHandleFollower; + fBoldListProperties: TBoldComboListController; + fBoldRowProperties: TBoldVariantFollowerController; + fBoldSelectChangeAction: TBoldComboSelectChangeAction; + fBoldSetValueExpression: TBoldExpression; + function GetBoldListHandle: TBoldAbstractListHandle; + function GetListFollower: TBoldFollower; + procedure SetBoldListHandle(const Value: TBoldAbstractListHandle); + procedure SetBoldListProperties(const Value: TBoldComboListController); + procedure SetRowProperties(const Value: TBoldVariantFollowerController); + function GetContextForBoldRowProperties: TBoldElementTypeInfo; + procedure SetBoldSelectChangeAction(Value: TBoldComboSelectChangeAction); + // IBoldValidateableComponent + function ValidateComponent(ComponentValidator: TBoldComponentValidator; NamePrefix: string): Boolean; + // IcxBoldEditProperties + procedure SetStoredValue(aValue: Variant; aBoldHandle: TBoldElementHandle; aEdit: TcxCustomEdit; aFollower: TBoldFollower; var aDone: boolean); + function BoldElementToEditValue(aFollower: TBoldFollower; aElement: TBoldElement; aEdit: TcxCustomEdit): variant; + function CanEdit(aBoldHandle: TBoldElementHandle; aFollower: TBoldFollower): boolean; + procedure SetBoldSetValueExpression(const Value: TBoldExpression); + protected + procedure _InsertItem(Index: Integer; Follower: TBoldFollower); + procedure _ReplaceItem(Index: Integer; Follower: TBoldFollower); + procedure _DeleteItem(Index: Integer; OwningFollower: TBoldFollower); + procedure _RowAfterMakeUptoDate(Follower: TBoldFollower); + procedure _BeforeMakeUptoDate(Follower: TBoldFollower); + procedure _AfterMakeUptoDate(Follower: TBoldFollower); + function GetAlwaysPostEditValue: Boolean; override; + public + constructor Create(AOwner: TPersistent); override; + destructor Destroy; override; + procedure Assign(Source: TPersistent); override; + class function GetContainerClass: TcxContainerClass; override; + function IsEditValueValid(var EditValue: TcxEditValue; AEditFocused: Boolean): Boolean; override; + function IsDisplayValueValid(var DisplayValue: TcxEditValue; AEditFocused: Boolean): Boolean; override; + property LookupListFollower: TBoldFollower read GetListFollower; + published + property BoldLookupListHandle: TBoldAbstractListHandle read GetBoldListHandle write SetBoldListHandle; + property BoldLookupListProperties: TBoldComboListController read fBoldListProperties write SetBoldListProperties; + property BoldRowProperties: TBoldVariantFollowerController read fBoldRowProperties write SetRowProperties; + property BoldSelectChangeAction: TBoldComboSelectChangeAction read fBoldSelectChangeAction write SetBoldSelectChangeAction default bdcsSetValue; + property BoldSetValueExpression: TBoldExpression read fBoldSetValueExpression write SetBoldSetValueExpression; + + property Alignment; + property AssignedValues; + property AutoSelect; + property BeepOnError; + property ButtonGlyph; + property CaseInsensitive; + property CharCase; + property ClearKey; + property DropDownAutoWidth; + property DropDownListStyle; + property DropDownRows; + property DropDownSizeable; + property DropDownWidth; + property HideSelection; + property IgnoreMaskBlank; + property ImeMode; + property ImeName; + property ImmediateDropDown; +// property ImmediatePost; + property ImmediateUpdateText; + property IncrementalSearch; + property ItemHeight; + property MaskKind; + property EditMask; + property MaxLength; + property OEMConvert; + property PopupAlignment; + property PostPopupValueOnTab; + property ReadOnly; + property Revertable; +// property Sorted; + property UseLeftAlignmentOnEditing; + property ValidateOnEnter; + property ValidationOptions; + property OnChange; + property OnCloseUp; + property OnDrawItem; + property OnEditValueChanged; + property OnInitPopup; + property OnMeasureItem; + property OnNewLookupDisplayText; + property OnPopup; + property OnValidate; + end; + + TcxSingleLinkEditProperties = class(TcxCustomHyperLinkEditProperties {TcxCustomHyperLinkEditProperties}) + published + property Alignment; + property AssignedValues; +// property AutoComplete; // deprecated + property AutoSelect; + property ClearKey; + property ImeMode; + property ImeName; + property IncrementalSearch; + property LinkColor; + property LookupItems; +// property LookupItemsSorted; +// property Prefix; + property ReadOnly; + property StartKey; + property SingleClick; + property UseLeftAlignmentOnEditing; +// property UsePrefix; + property ValidateOnEnter; + property ValidationOptions; + property OnChange; + property OnEditValueChanged; + property OnStartClick; + property OnValidate; + end; + + + TcxBoldTextEditProperties = class(TcxCustomBoldTextEditProperties) + published + property BoldLookupListHandle; + property BoldLookupListProperties; + property BoldRowProperties; + property BoldSelectChangeAction; + property BoldSetValueExpression; + property Alignment; + property AssignedValues; + property AutoSelect; + property BeepOnError; + property CharCase; + property ClearKey; + property EchoMode; + property HideSelection; + property ImeMode; + property ImeName; + property IncrementalSearch; + property OEMConvert; + property PasswordChar; + property ReadOnly; + property UseLeftAlignmentOnEditing; + + property ValidateOnEnter; + property ValidationOptions; + property OnChange; + property OnEditValueChanged; + property OnNewLookupDisplayText; + property OnValidate; + end; + + TcxCustomBoldEditDefaultValuesProvider = class(TcxCustomEditDefaultValuesProvider) + private + fBoldHandleFollower: TBoldAbstractHandleFollower; // handle follower is needed if we end up needing to access follower + fBoldProperties: TBoldFollowerController; +// fcxBoldEditDataBinding: TcxBoldEditDataBinding; + +// TODO: Place subscriptions instead of FreeNotification +// procedure FreeNotification(Sender: TComponent); + + function GetFollower: TBoldFollower; +// procedure SetBoldHandle(const Value: TBoldElementHandle); + procedure SetBoldProperties(const Value: TBoldFollowerController); + procedure SetHandleFollower(const Value: TBoldAbstractHandleFollower); + function GetBoldHandle: TBoldElementHandle; + protected + function GetBoldElementTypeInfo: TBoldElementTypeInfo; +// property DataBinding: TcxBoldEditDataBinding read fcxBoldEditDataBinding; + public + constructor Create(AOwner: TPersistent); override; + destructor Destroy; override; +// function CanSetEditMode: Boolean; override; + function DefaultAlignment: TAlignment; override; + function DefaultBlobKind: TcxBlobKind; override; + function DefaultCanModify: Boolean; override; +// function DefaultDisplayFormat: string; override; +// function DefaultEditFormat: string; override; +// function DefaultEditMask: string; override; + function DefaultIsFloatValue: Boolean; override; + function DefaultMaxLength: Integer; override; +// function DefaultMaxValue: Double; override; +// function DefaultMinValue: Double; override; +// function DefaultPrecision: Integer; override; +// function DefaultReadOnly: Boolean; override; +// function DefaultRequired: Boolean; override; + function IsBlob: Boolean; override; + function IsCurrency: Boolean; override; + function IsDataAvailable: Boolean; override; +// function IsDataStorage: Boolean; override; +// function IsDisplayFormatDefined(AIsCurrencyValueAccepted: Boolean): Boolean; override; +// function IsOnGetTextAssigned: Boolean; override; +// function IsOnSetTextAssigned: Boolean; override; + function IsValidChar(AChar: Char): Boolean; override; + + property Follower: TBoldFollower read GetFollower; + property BoldHandle: TBoldElementHandle read GetBoldHandle{ write SetBoldHandle}; + property BoldProperties: TBoldFollowerController read fBoldProperties write SetBoldProperties; + property BoldHandleFollower: TBoldAbstractHandleFollower read fBoldHandleFollower write SetHandleFollower; + end; + + TcxBoldEditDataBinding = class(TcxEditDataBinding) + private + fInternalChange: integer; + fBoldHandleFollower: TBoldElementHandleFollower; + fCurrentElementType: TBoldElementTypeInfo; + fBoldFollowerController: TBoldFollowerController; + fValueOrDefinitionInvalid: boolean; + fBrokenConstraints: TStringList; + fShowHintIfCaptionDoesntFit: boolean; + procedure SetBoldHandle(const Value: TBoldElementHandle); + function GetFollower: TBoldFollower; + function GetBoldHandle: TBoldElementHandle; + function GetDefaultValuesProvider: TcxCustomBoldEditDefaultValuesProvider; + + procedure SetBoldProperties(const Value: TBoldVariantFollowerController); + function GetBoldProperties: TBoldVariantFollowerController; + +{$IFDEF Constraints} + procedure SubscribeToConstraints(aElement: TBoldElement); +{$ENDIF} + function GetValueOrDefinitionInvalid: boolean; + procedure SetValueOrDefinitionInvalid(const Value: boolean); + function GetIsInInternalChange: boolean; + function GetBrokenConstraints: TStringList; + function GetHasBrokenConstraints: boolean; + protected + // IBoldOCLComponent + function GetContextType: TBoldElementTypeInfo; + procedure SetExpression(const Value: TBoldExpression); + function GetVariableList: TBoldExternalVariableList; + function GetExpression: TBoldExpression; + + // IBoldValidateableComponent + function ValidateComponent(ComponentValidator: TBoldComponentValidator; NamePrefix: string): Boolean; + + procedure _AfterMakeUptoDate(Follower: TBoldFollower); virtual; + + function ValidateTypeConforms(aExpressionType: TBoldElementTypeInfo): string; virtual; + + function MayModify: boolean; virtual; + procedure TypeMayHaveChanged; + procedure DoChanged; virtual; + + property BoldFollowerController: TBoldFollowerController read fBoldFollowerController; + + procedure InternalSetValue(const aValue: TcxEditValue); virtual; + function InternalGetValue(Follower: TBoldFollower): Variant; + function ImmediatePost: boolean; virtual; + + procedure ValidateDisplayValue(var ADisplayValue: TcxEditValue; var AErrorText: TCaption; var AError: Boolean); + + function HandleApplyException(E: Exception; Elem: TBoldElement; var Discard: Boolean): Boolean; + procedure DefaultValuesChanged; override; + function GetModified: Boolean; override; + function GetStoredValue: TcxEditValue; override; + function IsRefreshDisabled: Boolean; + procedure Reset; override; + procedure SetStoredValue(const Value: TcxEditValue); override; + procedure DataChanged; virtual; + procedure DataSetChange; virtual; + procedure EditingChanged; virtual; + function IsLookupControl: Boolean; virtual; + procedure UpdateData; virtual; + property DefaultValuesProvider: TcxCustomBoldEditDefaultValuesProvider read GetDefaultValuesProvider; + procedure DoEnter; virtual; + procedure DoExit; virtual; + property ValueOrDefinitionInvalid: boolean read GetValueOrDefinitionInvalid write SetValueOrDefinitionInvalid; + property BrokenConstraints: TStringList read GetBrokenConstraints; + property HasBrokenConstraints: boolean read GetHasBrokenConstraints; + public + constructor Create(AEdit: TcxCustomEdit); override; + destructor Destroy; override; + procedure Assign(Source: TPersistent); override; + function CanCheckEditorValue: Boolean; override; + function CanModify: Boolean; override; + function CanPostEditorValue: Boolean; override; + function ExecuteAction(Action: TBasicAction): Boolean; override; + class function GetDefaultValuesProviderClass: TcxCustomEditDefaultValuesProviderClass; override; + procedure SetModified; override; + function UpdateAction(Action: TBasicAction): Boolean; override; + procedure UpdateDisplayValue; override; + property Follower: TBoldFollower read GetFollower; + property IsInInternalChange: boolean read GetIsInInternalChange; + published + property BoldHandle: TBoldElementHandle read GetBoldHandle write SetBoldHandle; +// property BoldHandleFollower: TBoldElementHandleFollower read fBoldHandleFollower write SetBoldHandleFollower; +// property BoldProperties: TBoldVariantFollowerController read fBoldProperties write SetBoldProperties; + property BoldProperties: TBoldVariantFollowerController read GetBoldProperties write SetBoldProperties; + property ShowHintIfCaptionDoesntFit: boolean read fShowHintIfCaptionDoesntFit write fShowHintIfCaptionDoesntFit default false; + end; + + TcxBoldTextEditDataBinding = class(TcxBoldEditDataBinding) + end; + + TcxBoldDateTimeEditDataBinding = class(TcxBoldEditDataBinding) + protected + function ValidateTypeConforms(aExpressionType: TBoldElementTypeInfo): string; override; + end; + + TcxBoldTimeEditDataBinding = class(TcxBoldEditDataBinding) + protected + function ValidateTypeConforms(aExpressionType: TBoldElementTypeInfo): string; override; + end; + + TcxBoldCheckBoxEditDataBinding = class(TcxBoldEditDataBinding) + protected + function ValidateTypeConforms(aExpressionType: TBoldElementTypeInfo): string; override; + function ImmediatePost: boolean; override; + public + function MayModify: boolean; override; // TODO: move this up to TcxBoldEditDataBinding + end; + + TcxBoldNumericEditDataBinding = class(TcxBoldEditDataBinding) + protected + function ValidateTypeConforms(aExpressionType: TBoldElementTypeInfo): string; override; + end; + + TcxBoldFloatEditDataBinding = class(TcxBoldEditDataBinding) + protected + function ValidateTypeConforms(aExpressionType: TBoldElementTypeInfo): string; override; + end; + + TcxBoldCurrencyEditDataBinding = class(TcxBoldEditDataBinding) + protected + function ValidateTypeConforms(aExpressionType: TBoldElementTypeInfo): string; override; + end; + + TcxBoldBlobEditDataBinding = class(TcxBoldEditDataBinding) + protected + function ValidateTypeConforms(aExpressionType: TBoldElementTypeInfo): string; override; + end; + + TcxBoldComboBoxEditDataBinding = class(TcxBoldTextEditDataBinding) + protected + function GetModified: Boolean; override; + function ImmediatePost: boolean; override; + public + constructor Create(AEdit: TcxCustomEdit); override; + end; + + TcxBoldTextEdit = class(TcxCustomTextEdit, IBoldValidateableComponent, IBoldOCLComponent) + private + function GetActiveProperties: TcxBoldTextEditProperties; + function GetProperties: TcxBoldTextEditProperties; + procedure SetProperties(Value: TcxBoldTextEditProperties); + function GetDataBinding: TcxBoldTextEditDataBinding; + procedure SetDataBinding(Value: TcxBoldTextEditDataBinding); + protected + class function GetDataBindingClass: TcxEditDataBindingClass; override; + function ValidateKeyDown(var Key: Word; Shift: TShiftState): Boolean; override; + function ValidateKeyPress(var Key: Char): Boolean; override; + procedure DoValidateDisplayValue(var ADisplayValue: TcxEditValue; var AErrorText: TCaption; var AError: Boolean); override; + procedure DoOnChange; override; + procedure DoChange; override; + procedure Paint; override; + public + class function GetPropertiesClass: TcxCustomEditPropertiesClass; override; + property ActiveProperties: TcxBoldTextEditProperties read GetActiveProperties; + procedure DoEnter; override; + procedure DoExit; override; + published + property DataBinding: TcxBoldTextEditDataBinding read GetDataBinding write SetDataBinding implements IBoldValidateableComponent, IBoldOCLComponent; + property Properties: TcxBoldTextEditProperties read GetProperties write SetProperties; + property Anchors; + property AutoSize; + property BeepOnEnter; + property Constraints; + property DragCursor; + property DragKind; + property DragMode; + property Enabled; + property ImeMode; + property ImeName; + property ParentColor; + property ParentFont; + property ParentShowHint; + property PopupMenu; + property ShowHint; + property Style; + property StyleDisabled; + property StyleFocused; + property StyleHot; + property TabOrder; + property TabStop; +{$IFDEF DELPHI12} + property TextHint; +{$ENDIF} + property Visible; + property OnClick; +{$IFDEF DELPHI5} + property OnContextPopup; +{$ENDIF} + property OnDblClick; + property OnDragDrop; + property OnDragOver; + property OnEditing; + property OnEndDrag; + property OnEnter; + property OnExit; + property OnKeyDown; + property OnKeyPress; + property OnKeyUp; + property OnMouseDown; + property OnMouseEnter; + property OnMouseLeave; + property OnMouseMove; + property OnMouseUp; + property OnStartDrag; + property OnEndDock; + property OnStartDock; + end; +{ + TcxCustomBoldDateEditProperties = class(TcxCustomDateEditProperties) + end; + + TcxBoldDateEditProperties = class(TcxCustomBoldDateEditProperties) + end; +} + + TcxBoldDateEdit = class(TcxCustomDateEdit, IBoldValidateableComponent, IBoldOCLComponent) + private + function GetActiveProperties: TcxDateEditProperties; + function GetProperties: TcxDateEditProperties; + procedure SetProperties(Value: TcxDateEditProperties); + function GetDataBinding: TcxBoldDateTimeEditDataBinding; + procedure SetDataBinding(Value: TcxBoldDateTimeEditDataBinding); + protected + class function GetDataBindingClass: TcxEditDataBindingClass; override; + function ValidateKeyDown(var Key: Word; Shift: TShiftState): Boolean; override; + function ValidateKeyPress(var Key: Char): Boolean; override; + procedure DoChange; override; + procedure DoOnChange; override; + function CanDropDown: Boolean; override; + procedure Paint; override; + procedure HidePopup(Sender: TcxControl; AReason: TcxEditCloseUpReason); override; + procedure DoValidateDisplayValue(var ADisplayValue: TcxEditValue; var AErrorText: TCaption; var AError: Boolean); override; + public + class function GetPropertiesClass: TcxCustomEditPropertiesClass; override; + property ActiveProperties: TcxDateEditProperties read GetActiveProperties; + procedure DoEnter; override; + procedure DoExit; override; + published + property DataBinding: TcxBoldDateTimeEditDataBinding read GetDataBinding write SetDataBinding implements IBoldValidateableComponent, IBoldOCLComponent; + property Properties: TcxDateEditProperties read GetProperties write SetProperties; + property Anchors; + property AutoSize; + property BeepOnEnter; +// property BiDiMode; + property Constraints; + property DragCursor; + property DragKind; +// property Date; + property DragMode; +// property EditValue; + property Enabled; + property ImeMode; + property ImeName; +// property ParentBiDiMode; + property ParentColor; + property ParentFont; + property ParentShowHint; + property PopupMenu; + property ShowHint; + property Style; + property StyleDisabled; + property StyleFocused; + property StyleHot; + property TabOrder; + property TabStop default True; +{$IFDEF DELPHI12} + property TextHint; +{$ENDIF} + property Visible; + property OnClick; + {$IFDEF DELPHI5} + property OnContextPopup; + {$ENDIF} + property OnDblClick; + property OnDragDrop; + property OnDragOver; + property OnEditing; + property OnEndDock; + property OnEndDrag; + property OnEnter; + property OnExit; + property OnKeyDown; + property OnKeyPress; + property OnKeyUp; + property OnMouseDown; + property OnMouseMove; + property OnMouseUp; + property OnStartDrag; + property OnStartDock; + end; + + TcxBoldMemo = class(TcxCustomMemo, IBoldValidateableComponent, IBoldOCLComponent) + private + function GetActiveProperties: TcxMemoProperties; + function GetDataBinding: TcxBoldTextEditDataBinding; + function GetProperties: TcxMemoProperties; + procedure SetDataBinding(Value: TcxBoldTextEditDataBinding); + procedure SetProperties(Value: TcxMemoProperties); + protected + class function GetDataBindingClass: TcxEditDataBindingClass; override; + procedure DoChange; override; + procedure Paint; override; + procedure DoValidateDisplayValue(var ADisplayValue: TcxEditValue; var AErrorText: TCaption; var AError: Boolean); override; + public + class function GetPropertiesClass: TcxCustomEditPropertiesClass; override; + property ActiveProperties: TcxMemoProperties read GetActiveProperties; + procedure DoEnter; override; + procedure DoExit; override; + published + property Align; + property Anchors; + property Constraints; + property DataBinding: TcxBoldTextEditDataBinding read GetDataBinding write SetDataBinding implements IBoldValidateableComponent, IBoldOCLComponent; + property DragCursor; + property DragKind; + property DragMode; + property Enabled; + property ImeMode; + property ImeName; + property ParentColor; + property ParentFont; + property ParentShowHint; + property PopupMenu; + property Properties: TcxMemoProperties read GetProperties write SetProperties; + property ShowHint; + property Style; + property StyleDisabled; + property StyleFocused; + property StyleHot; + property TabOrder; + property TabStop; +{$IFDEF DELPHI12} + property TextHint; +{$ENDIF} + property Visible; + property OnClick; + property OnContextPopup; + property OnDblClick; + property OnDragDrop; + property OnDragOver; + property OnEditing; + property OnEndDock; + property OnEndDrag; + property OnEnter; + property OnExit; + property OnKeyDown; + property OnKeyPress; + property OnKeyUp; + property OnMouseDown; + property OnMouseEnter; + property OnMouseLeave; + property OnMouseMove; + property OnMouseUp; + property OnStartDock; + property OnStartDrag; + end; + + TcxBoldTimeEdit = class(TcxCustomTimeEdit, IBoldValidateableComponent, IBoldOCLComponent) + private + function GetActiveProperties: TcxTimeEditProperties; + function GetDataBinding: TcxBoldTimeEditDataBinding; + function GetProperties: TcxTimeEditProperties; + procedure SetDataBinding(Value: TcxBoldTimeEditDataBinding); + procedure SetProperties(Value: TcxTimeEditProperties); + protected + class function GetDataBindingClass: TcxEditDataBindingClass; override; + procedure DoChange; override; + function ValidateKeyDown(var Key: Word; Shift: TShiftState): Boolean; override; + function ValidateKeyPress(var Key: Char): Boolean; override; + procedure DoValidateDisplayValue(var ADisplayValue: TcxEditValue; var AErrorText: TCaption; var AError: Boolean); override; + procedure Paint; override; + public + class function GetPropertiesClass: TcxCustomEditPropertiesClass; override; + property ActiveProperties: TcxTimeEditProperties read GetActiveProperties; + procedure DoEnter; override; + procedure DoExit; override; + published + property Anchors; + property AutoSize; + property BeepOnEnter; + property Constraints; + property DataBinding: TcxBoldTimeEditDataBinding read GetDataBinding write SetDataBinding implements IBoldValidateableComponent, IBoldOCLComponent; + property DragCursor; + property DragKind; + property DragMode; + property Enabled; + property ImeMode; + property ImeName; + property ParentColor; + property ParentFont; + property ParentShowHint; + property PopupMenu; + property Properties: TcxTimeEditProperties read GetProperties write SetProperties; + property ShowHint; + property Style; + property StyleDisabled; + property StyleFocused; + property StyleHot; + property TabOrder; + property TabStop; +{$IFDEF DELPHI12} + property TextHint; +{$ENDIF} + property Visible; + property OnClick; + property OnContextPopup; + property OnDblClick; + property OnDragDrop; + property OnDragOver; + property OnEditing; + property OnEndDock; + property OnEndDrag; + property OnEnter; + property OnExit; + property OnKeyDown; + property OnKeyPress; + property OnKeyUp; + property OnMouseDown; + property OnMouseEnter; + property OnMouseLeave; + property OnMouseMove; + property OnMouseUp; + property OnStartDock; + property OnStartDrag; + end; + + TcxBoldCurrencyEdit = class(TcxCustomCurrencyEdit, IBoldValidateableComponent, IBoldOCLComponent) + private + function GetActiveProperties: TcxCurrencyEditProperties; + function GetDataBinding: TcxBoldCurrencyEditDataBinding; + function GetProperties: TcxCurrencyEditProperties; + procedure SetDataBinding(Value: TcxBoldCurrencyEditDataBinding); + procedure SetProperties(Value: TcxCurrencyEditProperties); + protected + class function GetDataBindingClass: TcxEditDataBindingClass; override; + procedure DoValidateDisplayValue(var ADisplayValue: TcxEditValue; var AErrorText: TCaption; var AError: Boolean); override; + procedure DoChange; override; + procedure Paint; override; + public + class function GetPropertiesClass: TcxCustomEditPropertiesClass; override; + property ActiveProperties: TcxCurrencyEditProperties read GetActiveProperties; + procedure DoEnter; override; + procedure DoExit; override; + published + property Anchors; + property AutoSize; + property BeepOnEnter; + property Constraints; + property DataBinding: TcxBoldCurrencyEditDataBinding read GetDataBinding write SetDataBinding implements IBoldValidateableComponent, IBoldOCLComponent; + property DragCursor; + property DragKind; + property DragMode; + property Enabled; + property ImeMode; + property ImeName; + property ParentColor; + property ParentFont; + property ParentShowHint; + property PopupMenu; + property Properties: TcxCurrencyEditProperties read GetProperties write SetProperties; + property ShowHint; + property Style; + property StyleDisabled; + property StyleFocused; + property StyleHot; + property TabOrder; + property TabStop; +{$IFDEF DELPHI12} + property TextHint; +{$ENDIF} + property Visible; + property OnClick; + property OnContextPopup; + property OnDblClick; + property OnEditing; + property OnEndDock; + property OnEnter; + property OnExit; + property OnKeyDown; + property OnKeyPress; + property OnKeyUp; + property OnMouseDown; + property OnMouseMove; + property OnMouseUp; + property OnStartDock; + end; + + TcxBoldMaskEdit = class(TcxCustomMaskEdit, IBoldValidateableComponent, IBoldOCLComponent) + private + function GetActiveProperties: TcxMaskEditProperties; + function GetDataBinding: TcxBoldTextEditDataBinding; + function GetProperties: TcxMaskEditProperties; + procedure SetDataBinding(Value: TcxBoldTextEditDataBinding); + procedure SetProperties(Value: TcxMaskEditProperties); + protected + class function GetDataBindingClass: TcxEditDataBindingClass; override; + function SupportsSpelling: Boolean; override; + procedure DoValidateDisplayValue(var ADisplayValue: TcxEditValue; var AErrorText: TCaption; var AError: Boolean); override; + procedure Paint; override; + public + class function GetPropertiesClass: TcxCustomEditPropertiesClass; override; + property ActiveProperties: TcxMaskEditProperties read GetActiveProperties; + procedure DoEnter; override; + procedure DoExit; override; + published + property Anchors; + property AutoSize; + property BeepOnEnter; + property Constraints; + property DataBinding: TcxBoldTextEditDataBinding read GetDataBinding write SetDataBinding implements IBoldValidateableComponent, IBoldOCLComponent; + property DragCursor; + property DragKind; + property DragMode; + property Enabled; + property ImeMode; + property ImeName; + property ParentColor; + property ParentFont; + property ParentShowHint; + property PopupMenu; + property Properties: TcxMaskEditProperties read GetProperties write SetProperties; + property ShowHint; + property Style; + property StyleDisabled; + property StyleFocused; + property StyleHot; + property TabOrder; + property TabStop; +{$IFDEF DELPHI12} + property TextHint; +{$ENDIF} + property Visible; + property OnClick; + property OnContextPopup; + property OnDblClick; + property OnDragDrop; + property OnDragOver; + property OnEditing; + property OnEndDrag; + property OnEnter; + property OnExit; + property OnKeyDown; + property OnKeyPress; + property OnKeyUp; + property OnMouseDown; + property OnMouseEnter; + property OnMouseLeave; + property OnMouseMove; + property OnMouseUp; + property OnStartDrag; + property OnEndDock; + property OnStartDock; + end; + + TcxBoldCheckBox = class(TcxCustomCheckBox, IBoldValidateableComponent, IBoldOCLComponent) + private + function GetActiveProperties: TcxCheckBoxProperties; + function GetDataBinding: TcxBoldCheckBoxEditDataBinding; + function GetProperties: TcxCheckBoxProperties; + procedure SetDataBinding(Value: TcxBoldCheckBoxEditDataBinding); + procedure SetProperties(Value: TcxCheckBoxProperties); + protected + class function GetDataBindingClass: TcxEditDataBindingClass; override; + procedure DoValidateDisplayValue(var ADisplayValue: TcxEditValue; var AErrorText: TCaption; var AError: Boolean); override; + procedure Toggle; override; + procedure Paint; override; + procedure Initialize; override; + procedure DoChange; override; + public + class function GetPropertiesClass: TcxCustomEditPropertiesClass; override; + property ActiveProperties: TcxCheckBoxProperties read GetActiveProperties; + procedure DoEnter; override; + procedure DoExit; override; + property Checked; + published + property Action; + property Align; + property Anchors; + property AutoSize; + property Caption; + property Constraints; + property DataBinding: TcxBoldCheckBoxEditDataBinding read GetDataBinding write SetDataBinding implements IBoldValidateableComponent, IBoldOCLComponent; + property DragCursor; + property DragKind; + property DragMode; + property Enabled; + property ParentBackground; + property ParentColor; + property ParentFont; + property ParentShowHint; + property PopupMenu; + property Properties: TcxCheckBoxProperties read GetProperties write SetProperties; + property ShowHint; + property Style; + property StyleDisabled; + property StyleFocused; + property StyleHot; + property TabOrder; + property TabStop; + property Transparent; +// property TextHint; + property Visible; + property OnClick; + property OnContextPopup; + property OnDragDrop; + property OnDragOver; + property OnEditing; + property OnEndDrag; + property OnEnter; + property OnExit; + property OnKeyDown; + property OnKeyPress; + property OnKeyUp; + property OnMouseDown; + property OnMouseEnter; + property OnMouseLeave; + property OnMouseMove; + property OnMouseUp; + property OnStartDrag; + property OnEndDock; + property OnStartDock; + end; + + TcxBoldComboBox = class(TcxCustomComboBox, IBoldValidateableComponent, IBoldOCLComponent) + private + function GetActiveProperties: TcxBoldComboBoxProperties; + function GetDataBinding: TcxBoldComboBoxEditDataBinding; + function GetProperties: TcxBoldComboBoxProperties; + procedure SetDataBinding(Value: TcxBoldComboBoxEditDataBinding); + procedure SetProperties(Value: TcxBoldComboBoxProperties); + protected + class function GetDataBindingClass: TcxEditDataBindingClass; override; + procedure DoValidateDisplayValue(var ADisplayValue: TcxEditValue; var AErrorText: TCaption; var AError: Boolean); override; + function SupportsSpelling: Boolean; override; + function CanDropDown: Boolean; override; + procedure Paint; override; + public + class function GetPropertiesClass: TcxCustomEditPropertiesClass; override; + property ActiveProperties: TcxBoldComboBoxProperties read GetActiveProperties; + procedure DoEnter; override; + procedure DoExit; override; + property ItemIndex; + published + property Anchors; + property AutoSize; + property BeepOnEnter; + property Constraints; + property DataBinding: TcxBoldComboBoxEditDataBinding read GetDataBinding write SetDataBinding implements IBoldValidateableComponent, IBoldOCLComponent; + property DragCursor; + property DragKind; + property DragMode; + property Enabled; + property ImeMode; + property ImeName; + property ParentColor; + property ParentFont; + property ParentShowHint; + property PopupMenu; + property Properties: TcxBoldComboBoxProperties read GetProperties write SetProperties; + property ShowHint; + property Style; + property StyleDisabled; + property StyleFocused; + property StyleHot; + property TabOrder; + property TabStop; +{$IFDEF DELPHI12} + property TextHint; +{$ENDIF} + property Visible; + property OnClick; + property OnContextPopup; + property OnDblClick; + property OnDragDrop; + property OnDragOver; + property OnEditing; + property OnEndDrag; + property OnEnter; + property OnExit; + property OnKeyDown; + property OnKeyPress; + property OnKeyUp; + property OnMouseDown; + property OnMouseEnter; + property OnMouseLeave; + property OnMouseMove; + property OnMouseUp; + property OnStartDrag; + property OnEndDock; + property OnStartDock; + end; + + // perhaps use TBoldIntegerFollowerController ? + TcxBoldSpinEdit = class(TcxCustomSpinEdit, IBoldValidateableComponent, IBoldOCLComponent) + private + function GetActiveProperties: TcxSpinEditProperties; + function GetProperties: TcxSpinEditProperties; + function GetDataBinding: TcxBoldNumericEditDataBinding; + procedure SetDataBinding(Value: TcxBoldNumericEditDataBinding); + procedure SetProperties(Value: TcxSpinEditProperties); + protected + class function GetDataBindingClass: TcxEditDataBindingClass; override; + procedure DoValidateDisplayValue(var ADisplayValue: TcxEditValue; var AErrorText: TCaption; var AError: Boolean); override; + procedure Paint; override; + public + class function GetPropertiesClass: TcxCustomEditPropertiesClass; override; + property ActiveProperties: TcxSpinEditProperties read GetActiveProperties; + procedure DoEnter; override; + procedure DoExit; override; + property Value; + published + property Anchors; + property AutoSize; + property BeepOnEnter; + property Constraints; + property DataBinding: TcxBoldNumericEditDataBinding read GetDataBinding write SetDataBinding implements IBoldValidateableComponent, IBoldOCLComponent; + property DragCursor; + property DragKind; + property DragMode; + property Enabled; + property ImeMode; + property ImeName; + property ParentColor; + property ParentFont; + property ParentShowHint; + property PopupMenu; + property Properties: TcxSpinEditProperties read GetProperties write SetProperties; + property ShowHint; + property Style; + property StyleDisabled; + property StyleFocused; + property StyleHot; + property TabOrder; + property TabStop; +{$IFDEF DELPHI12} + property TextHint; +{$ENDIF} + property Visible; + property OnClick; + property OnContextPopup; + property OnDblClick; + property OnDragDrop; + property OnDragOver; + property OnEditing; + property OnEndDock; + property OnEndDrag; + property OnEnter; + property OnExit; + property OnKeyDown; + property OnKeyPress; + property OnKeyUp; + property OnMouseDown; + property OnMouseEnter; + property OnMouseLeave; + property OnMouseMove; + property OnMouseUp; + property OnStartDock; + property OnStartDrag; + end; + + TcxBoldButtonEdit = class(TcxCustomButtonEdit, IBoldValidateableComponent, IBoldOCLComponent) + private + function GetActiveProperties: TcxButtonEditProperties; + function GetDataBinding: TcxBoldTextEditDataBinding; + function GetProperties: TcxButtonEditProperties; + procedure SetDataBinding(Value: TcxBoldTextEditDataBinding); + procedure SetProperties(Value: TcxButtonEditProperties); + protected + class function GetDataBindingClass: TcxEditDataBindingClass; override; + procedure DoValidateDisplayValue(var ADisplayValue: TcxEditValue; var AErrorText: TCaption; var AError: Boolean); override; + procedure Paint; override; + public + class function GetPropertiesClass: TcxCustomEditPropertiesClass; override; + property ActiveProperties: TcxButtonEditProperties read GetActiveProperties; + procedure DoEnter; override; + procedure DoExit; override; + published + property Anchors; + property AutoSize; + property BeepOnEnter; + property Constraints; + property DataBinding: TcxBoldTextEditDataBinding read GetDataBinding write SetDataBinding implements IBoldValidateableComponent, IBoldOCLComponent; + property DragCursor; + property DragKind; + property DragMode; + property Enabled; + property ImeMode; + property ImeName; + property ParentColor; + property ParentFont; + property ParentShowHint; + property PopupMenu; + property Properties: TcxButtonEditProperties read GetProperties write SetProperties; + property ShowHint; + property Style; + property StyleDisabled; + property StyleFocused; + property StyleHot; + property TabOrder; + property TabStop; +{$IFDEF DELPHI12} + property TextHint; +{$ENDIF} + property Visible; + property OnClick; + property OnContextPopup; + property OnDblClick; + property OnDragDrop; + property OnDragOver; + property OnEditing; + property OnEndDrag; + property OnEnter; + property OnExit; + property OnKeyDown; + property OnKeyPress; + property OnKeyUp; + property OnMouseDown; + property OnMouseEnter; + property OnMouseLeave; + property OnMouseMove; + property OnMouseUp; + property OnStartDrag; + property OnEndDock; + property OnStartDock; + end; + + TcxBoldHyperLinkEdit = class(TcxCustomHyperLinkEdit, IBoldValidateableComponent, IBoldOCLComponent) + private + function GetActiveProperties: TcxHyperLinkEditProperties; + function GetDataBinding: TcxBoldTextEditDataBinding; + function GetProperties: TcxHyperLinkEditProperties; + procedure SetDataBinding(Value: TcxBoldTextEditDataBinding); + procedure SetProperties(Value: TcxHyperLinkEditProperties); + protected + class function GetDataBindingClass: TcxEditDataBindingClass; override; + procedure DoValidateDisplayValue(var ADisplayValue: TcxEditValue; var AErrorText: TCaption; var AError: Boolean); override; + procedure Paint; override; + public + class function GetPropertiesClass: TcxCustomEditPropertiesClass; override; + property ActiveProperties: TcxHyperLinkEditProperties read GetActiveProperties; + procedure DoEnter; override; + procedure DoExit; override; + published + property Anchors; + property AutoSize; + property BeepOnEnter; + property Constraints; + property DataBinding: TcxBoldTextEditDataBinding read GetDataBinding write SetDataBinding implements IBoldValidateableComponent, IBoldOCLComponent; + property DragCursor; + property DragKind; + property DragMode; + property Enabled; + property ImeMode; + property ImeName; + property ParentColor; + property ParentFont; + property ParentShowHint; + property PopupMenu; + property Properties: TcxHyperLinkEditProperties read GetProperties write SetProperties; + property ShowHint; + property Style; + property StyleDisabled; + property StyleFocused; + property StyleHot; + property TabOrder; + property TabStop; +{$IFDEF DELPHI12} + property TextHint; +{$ENDIF} + property Visible; + property OnClick; + property OnContextPopup; + property OnDblClick; + property OnEditing; + property OnEndDock; + property OnEnter; + property OnExit; + property OnKeyDown; + property OnKeyPress; + property OnKeyUp; + property OnMouseDown; + property OnMouseMove; + property OnMouseUp; + property OnStartDock; + end; + + TcxBoldProgressBar = class(TcxCustomProgressBar, IBoldValidateableComponent, IBoldOCLComponent) + private + function GetActiveProperties: TcxProgressBarProperties; + function GetDataBinding: TcxBoldNumericEditDataBinding; + procedure SetDataBinding(Value: TcxBoldNumericEditDataBinding); + function GetProperties: TcxProgressBarProperties; + procedure SetProperties(Value: TcxProgressBarProperties); + protected + class function GetDataBindingClass: TcxEditDataBindingClass; override; + procedure Initialize; override; + procedure Paint; override; + public + class function GetPropertiesClass: TcxCustomEditPropertiesClass; override; + property ActiveProperties: TcxProgressBarProperties read GetActiveProperties; + published + property Align; + property Anchors; + property AutoSize; + property Constraints; + property DataBinding: TcxBoldNumericEditDataBinding read GetDataBinding write SetDataBinding implements IBoldValidateableComponent, IBoldOCLComponent; + property DragCursor; + property DragKind; + property DragMode; + property Enabled; + property ParentColor; + property ParentFont; + property ParentShowHint; + property PopupMenu; + property Properties: TcxProgressBarProperties read GetProperties write SetProperties; + property ShowHint; + property Style; + property StyleDisabled; + property StyleFocused; + property StyleHot; + property TabOrder; + property TabStop; + property Transparent; + property Visible; + property OnContextPopup; + property OnDragDrop; + property OnDragOver; + property OnEndDock; + property OnEndDrag; + property OnEnter; + property OnExit; + property OnKeyDown; + property OnKeyPress; + property OnKeyUp; + property OnMouseDown; + property OnMouseEnter; + property OnMouseLeave; + property OnMouseMove; + property OnMouseUp; + property OnStartDock; + property OnStartDrag; + end; + + TcxBarBoldEditItem = class(TcxCustomBarEditItem) + private + fInternalChange: integer; + fBoldHandleFollower: TBoldElementHandleFollower; + fBoldProperties: TBoldVariantFollowerController; + procedure SetBoldHandle(const Value: TBoldElementHandle); + function GetFollower: TBoldFollower; + function GetBoldHandle: TBoldElementHandle; + procedure SetBoldProperties(const Value: TBoldVariantFollowerController); + protected + function GetContextType: TBoldElementTypeInfo; + procedure _AfterMakeUptoDate(Follower: TBoldFollower); +// function CanEdit: Boolean; override; +// procedure DoEditValueChanged(Sender: TObject); override; + procedure EditValueChanged(Sender: TObject); + procedure EditExit(Sender: TObject); + function GetControlClass(AIsVertical: Boolean): TdxBarItemControlClass; override; + + procedure KeyPress(var Key: Char); override; + + procedure DoEnter; override; + procedure DoExit; override; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + property Follower: TBoldFollower read GetFollower; + published + property BoldHandle: TBoldElementHandle read GetBoldHandle write SetBoldHandle; + property BoldProperties: TBoldVariantFollowerController read fBoldProperties write SetBoldProperties; + property CanSelect; +// property EditValue; + property Height; + property Properties; + property RepositoryItem; + property StyleEdit; +// property TextHint; + end; + + TcxBarBoldEditItemControl = class(TcxBarEditItemControl) + private + protected +// procedure DoPostEditValue(Sender: TObject); override; +// procedure DoValidate(Sender: TObject; var DisplayValue: TcxEditValue; +// var ErrorText: TCaption; var Error: Boolean); override; + procedure RestoreDisplayValue; override; + procedure StoreDisplayValue; override; +// procedure DoPaint(ARect: TRect; PaintType: TdxBarPaintType); override; + public + end; + +{$IFDEF DevExScheduler} + TcxBoldDateNavigator = class(TcxCustomDateNavigator, IBoldValidateableComponent) + private + fInternalChange: integer; + fBoldStartHandleFollower: TBoldElementHandleFollower; + fBoldEndHandleFollower: TBoldElementHandleFollower; + fBoldStartProperties: TBoldVariantFollowerController; + fBoldEndProperties: TBoldVariantFollowerController; +// fValueOrDefinitionInvalid: boolean; + function GetStartFollower: TBoldFollower; + function GetEndFollower: TBoldFollower; + procedure SetBoldStartProperties(const Value: TBoldVariantFollowerController); + procedure SetBoldEndProperties(const Value: TBoldVariantFollowerController); + function GetBoldEndHandle: TBoldElementHandle; + function GetBoldStartHandle: TBoldElementHandle; + procedure SetBoldEndHandle(const Value: TBoldElementHandle); + procedure SetBoldStartHandle(const Value: TBoldElementHandle); + procedure _AfterMakeUptoDate(Follower: TBoldFollower); + + procedure ValidateSelf; + + // IBoldValidateableComponent + function ValidateComponent(ComponentValidator: TBoldComponentValidator; NamePrefix: string): Boolean; + protected + function GetStartContextType: TBoldElementTypeInfo; + function GetEndContextType: TBoldElementTypeInfo; +// function CanSelectPeriod: Boolean; // overriden to return false, as we don't support range + procedure DateNavigatorSelectionChanged; override; +// procedure DoSelectionChangedEvent; override; + procedure Loaded; override; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + property StartFollower: TBoldFollower read GetStartFollower; + property EndFollower: TBoldFollower read GetEndFollower; + published + property BoldStartHandle: TBoldElementHandle read GetBoldStartHandle write SetBoldStartHandle; + property BoldStartProperties: TBoldVariantFollowerController read fBoldStartProperties write SetBoldStartProperties; + property BoldEndHandle: TBoldElementHandle read GetBoldEndHandle write SetBoldEndHandle; + property BoldEndProperties: TBoldVariantFollowerController read fBoldEndProperties write SetBoldEndProperties; + property Align; + property Anchors; + property BorderStyle; + property Constraints; + property DragCursor; + property DragKind; + property DragMode; + property Enabled; + property FirstWeekOfYear; + property Font; + property HolidayColor; + property LookAndFeel; + property ParentFont; + property ParentShowHint; + property PopupMenu; + property Scheduler; + property SelectPeriod; + property ShowDatesContainingEventsInBold; + property ShowDatesContainingHolidaysInColor; + property ShowWeekNumbers; + property StartOfWeek; + property Storage; + property Styles; + property TabOrder; + property TabStop; + property UnlimitedSelection; + property Visible; + + property OnClick; + {$IFDEF DELPHI5} + property OnContextPopup; + {$ENDIF} + property OnCustomDrawBackground; + property OnCustomDrawContent; + property OnCustomDrawDayCaption; + property OnCustomDrawDayNumber; + property OnCustomDrawHeader; + property OnPeriodChanged; + property OnSelectionChanged; + property OnShowDateHint; + property OnDblClick; + property OnDragDrop; + property OnDragOver; + property OnEndDock; + property OnEndDrag; + property OnEnter; + property OnExit; + property OnKeyDown; + property OnKeyPress; + property OnKeyUp; + property OnMouseDown; + property OnMouseEnter; + property OnMouseLeave; + property OnMouseMove; + property OnMouseUp; + property OnMouseWheel; + property OnMouseWheelDown; + property OnMouseWheelUp; + property OnResize; + property OnStartDock; + property OnStartDrag; + end; +{$ENDIF} + + { TcxBoldLabel } + + TcxBoldLabel = class(TcxCustomLabel, IBoldValidateableComponent, IBoldOCLComponent) + private + function GetActiveProperties: TcxLabelProperties; + function GetDataBinding: TcxBoldTextEditDataBinding; + function GetProperties: TcxLabelProperties; + procedure SetDataBinding(Value: TcxBoldTextEditDataBinding); + procedure SetProperties(Value: TcxLabelProperties); + protected + class function GetDataBindingClass: TcxEditDataBindingClass; override; + procedure Initialize; override; + procedure SetEditAutoSize(Value: Boolean); override; + procedure Paint; override; + public + class function GetPropertiesClass: TcxCustomEditPropertiesClass; override; + property ActiveProperties: TcxLabelProperties read GetActiveProperties; + published + property Align; + property Anchors; + property AutoSize {default False}; + property Constraints; + property DataBinding: TcxBoldTextEditDataBinding read GetDataBinding write SetDataBinding implements IBoldValidateableComponent, IBoldOCLComponent; + property DragCursor; + property DragKind; + property DragMode; + property Enabled; + property ImeMode; + property ImeName; + property ParentColor; + property ParentFont; + property ParentShowHint; + property PopupMenu; + property Properties: TcxLabelProperties read GetProperties + write SetProperties; + property ShowHint; + property Style; + property StyleDisabled; + property StyleFocused; + property StyleHot; + property TabOrder; + property TabStop; + property Transparent; + property Visible; + property OnClick; + property OnContextPopup; + property OnDragDrop; + property OnDragOver; + property OnEndDock; + property OnEndDrag; + property OnEnter; + property OnExit; + property OnKeyDown; + property OnKeyPress; + property OnKeyUp; + property OnMouseDown; + property OnMouseEnter; + property OnMouseLeave; + property OnMouseMove; + property OnMouseUp; + property OnStartDock; + property OnStartDrag; + end; + + TcxBoldImage = class(TcxCustomImage, IBoldValidateableComponent, IBoldOCLComponent) + private + function GetActiveProperties: TcxImageProperties; + function GetDataBinding: TcxBoldBlobEditDataBinding; + function GetProperties: TcxImageProperties; + procedure SetDataBinding(Value: TcxBoldBlobEditDataBinding); + procedure SetProperties(Value: TcxImageProperties); +// function GetViewer: TBoldAbstractViewAdapter; +// procedure SetViewer(Value: TBoldAbstractViewAdapter); + protected + class function GetDataBindingClass: TcxEditDataBindingClass; override; + procedure Initialize; override; + procedure Paint; override; + public + class function GetPropertiesClass: TcxCustomEditPropertiesClass; override; + property ActiveProperties: TcxImageProperties read GetActiveProperties; +// property Viewer: TBoldAbstractViewAdapter read GetViewer write SetViewer; + published + property Align; + property Anchors; + property AutoSize; + property Constraints; + property DataBinding: TcxBoldBlobEditDataBinding read GetDataBinding write SetDataBinding implements IBoldValidateableComponent, IBoldOCLComponent; + property DragCursor; + property DragKind; + property DragMode; + property Enabled; + property ParentColor; + property PopupMenu; + property Properties: TcxImageProperties read GetProperties write SetProperties; + property ShowHint; + property Style; + property StyleDisabled; + property StyleFocused; + property StyleHot; + property TabOrder; + property TabStop; + property Visible; + property OnClick; + property OnContextPopup; + property OnDblClick; + property OnDragDrop; + property OnDragOver; + property OnEditing; + property OnEndDock; + property OnEndDrag; + property OnEnter; + property OnExit; + property OnGetGraphicClass; + property OnKeyDown; + property OnKeyPress; + property OnKeyUp; + property OnMouseDown; + property OnMouseMove; + property OnMouseUp; + property OnStartDock; + property OnStartDrag; + end; + + TcxBoldRichEdit = class(TcxCustomRichEdit, IBoldValidateableComponent, IBoldOCLComponent) + private + function GetActiveProperties: TcxRichEditProperties; + function GetDataBinding: TcxBoldTextEditDataBinding; + function GetProperties: TcxRichEditProperties; + procedure SetDataBinding(Value: TcxBoldTextEditDataBinding); + procedure SetProperties(Value: TcxRichEditProperties); + protected + procedure EditingChanged; override; + class function GetDataBindingClass: TcxEditDataBindingClass; override; + procedure DoValidateDisplayValue(var ADisplayValue: TcxEditValue; var AErrorText: TCaption; var AError: Boolean); override; + function RealReadOnly: Boolean; override; + procedure Paint; override; + public + class function GetPropertiesClass: TcxCustomEditPropertiesClass; override; + property ActiveProperties: TcxRichEditProperties read GetActiveProperties; + published + property Align; + property Anchors; + property Constraints; + property DataBinding: TcxBoldTextEditDataBinding read GetDataBinding write SetDataBinding implements IBoldValidateableComponent, IBoldOCLComponent; + property DragCursor; + property DragKind; + property DragMode; + property Enabled; + property ImeMode; + property ImeName; + property ParentColor; + property ParentFont; + property ParentShowHint; + property PopupMenu; + property Properties: TcxRichEditProperties read GetProperties + write SetProperties; + property ShowHint; + property Style; + property StyleDisabled; + property StyleFocused; + property StyleHot; + property TabOrder; + property TabStop; + property Visible; + property OnClick; + property OnContextPopup; + property OnDblClick; + property OnDragDrop; + property OnDragOver; + property OnEditing; + property OnEndDock; + property OnEndDrag; + property OnEnter; + property OnExit; + property OnKeyDown; + property OnKeyPress; + property OnKeyUp; + property OnMouseDown; + property OnMouseEnter; + property OnMouseLeave; + property OnMouseMove; + property OnMouseUp; + property OnMouseWheel; + property OnMouseWheelDown; + property OnMouseWheelUp; + property OnStartDock; + property OnStartDrag; + end; + + TcxBoldListBox = class(TcxListBox, IBoldValidateableComponent) + private + fInternalUpdate: boolean; + fListHandleFollower: TBoldListHandleFollower; + fBoldListProperties: TBoldListAsFollowerListController; + fBoldRowProperties: TBoldVariantFollowerController; + function GetBoldListHandle: TBoldAbstractListHandle; + procedure SetBoldListHandle(const Value: TBoldAbstractListHandle); + procedure SetBoldListProperties( + const Value: TBoldListAsFollowerListController); + procedure SetRowProperties( + const Value: TBoldVariantFollowerController); + function GetBoldHandleIndexLock: Boolean; + procedure SetBoldHandleIndexLock(const Value: Boolean); + function GetFollower: TBoldFollower; + function GetMutableList: TBoldList; + procedure SyncSelection; + // IBoldValidateableComponent + function ValidateComponent(ComponentValidator: TBoldComponentValidator; NamePrefix: string): Boolean; + protected + procedure WndProc(var Message: TMessage); override; + procedure DblClick; override; + procedure Loaded; override; + procedure _InsertItem(Index: Integer; Follower: TBoldFollower); + procedure _ReplaceItem(Index: Integer; Follower: TBoldFollower); + procedure _DeleteItem(Index: Integer; OwningFollower: TBoldFollower); + procedure _RowAfterMakeUptoDate(Follower: TBoldFollower); + procedure _BeforeMakeUptoDate(Follower: TBoldFollower); + procedure _AfterMakeUptoDate(Follower: TBoldFollower); + + function DrawItem(ACanvas: TcxCanvas; AIndex: Integer; const ARect: TRect; + AState: TOwnerDrawState): Boolean; override; + procedure DefaultSetFontAndColor(Index: integer); virtual; + + procedure DoStartDrag(var DragObject: TDragObject); override; + procedure DoEndDrag(Target: TObject; X, Y: Integer); override; + procedure DragOver(Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean); override; + + function GetListFollower: TBoldFollower; + function GetContextForBoldRowProperties: TBoldElementTypeInfo; + property Follower: TBoldFollower read GetFollower; + property MutableList: TBoldList read GetMutableList; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + procedure DefaultDrawItem(Index: integer; aRect: TRect); virtual; + procedure DragDrop(Source: TObject; X, Y: Integer); override; + published +// property DataBinding: TcxBoldDataBinding read GetDataBinding write SetDataBinding implements IBoldValidateableComponent, IBoldOCLComponent; + property BoldListHandle: TBoldAbstractListHandle read GetBoldListHandle write SetBoldListHandle; + property BoldListProperties: TBoldListAsFollowerListController read fBoldListProperties write SetBoldListProperties; + property BoldRowProperties: TBoldVariantFollowerController read fBoldRowProperties write SetRowProperties; + property BoldHandleIndexLock: Boolean read GetBoldHandleIndexLock write SetBoldHandleIndexLock default true; + end; + + + TcxBoldCustomCheckListBox = class(TcxCustomCheckListBox, IBoldValidateableComponent) + private + fInternalUpdate: boolean; + fListHandleFollower: TBoldListHandleFollower; + fBoldListProperties: TBoldAbstractListAsFollowerListController; + fBoldRowProperties: TBoldVariantFollowerController; + FUpdateCount: Integer; // for Items + fBoldRowCheckBoxProperties: TBoldCheckBoxStateFollowerController; + fControllerList: TBoldControllerList; + + function GetBoldListHandle: TBoldAbstractListHandle; + procedure SetBoldListHandle(const Value: TBoldAbstractListHandle); + procedure SetBoldListProperties( + const Value: TBoldAbstractListAsFollowerListController); + procedure SetRowProperties( + const Value: TBoldVariantFollowerController); + function GetBoldHandleIndexLock: Boolean; + procedure SetBoldHandleIndexLock(const Value: Boolean); + function GetFollower: TBoldFollower; + procedure SetBoldRowCheckBoxProperties(const Value: TBoldCheckBoxStateFollowerController); + // IBoldValidateableComponent + function ValidateComponent(ComponentValidator: TBoldComponentValidator; NamePrefix: string): Boolean; virtual; abstract; + protected + procedure WndProc(var Message: TMessage); override; + procedure SyncSelection; + function GetInnerCheckListBoxClass: TcxCustomInnerCheckListBoxClass; override; + + procedure Loaded; override; + + function GetContextType: TBoldElementTypeInfo; + procedure _DisplayCheckBox(Follower: TBoldFollower); + procedure _DisplayString(Follower: TBoldFollower); + procedure _ListInsertItem(Index: integer; Follower: TBoldFollower); + procedure _ReplaceItem(Index: Integer; Follower: TBoldFollower); + procedure _ListDeleteItem(Index: integer; Follower: TBoldFollower); + procedure _ListBeforeMakeUpToDate(Follower: TBoldFollower); + procedure _ListAfterMakeUpToDate(Follower: TBoldFollower); + property BoldRowCheckBoxProperties: TBoldCheckBoxStateFollowerController read fBoldRowCheckBoxProperties write SetBoldRowCheckBoxProperties; + property Follower: TBoldFollower read GetFollower; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; +// procedure DefaultDrawItem(Index: integer; aRect: TRect); virtual; +// procedure DragDrop(Source: TObject; X, Y: Integer); override; + published + property BoldListHandle: TBoldAbstractListHandle read GetBoldListHandle write SetBoldListHandle; + property BoldListProperties: TBoldAbstractListAsFollowerListController read fBoldListProperties write SetBoldListProperties; + property BoldRowProperties: TBoldVariantFollowerController read fBoldRowProperties write SetRowProperties; + property BoldHandleIndexLock: Boolean read GetBoldHandleIndexLock write SetBoldHandleIndexLock default true; + + property Align; + property AllowDblClickToggle; + property AllowGrayed; + property Anchors; + property AutoComplete; + property AutoCompleteDelay; + property BiDiMode; + property Columns; + property Constraints; + property DragCursor; + property DragKind; + property DragMode; + property EditValueFormat; + property Enabled; + property Glyph; + property GlyphCount; + property Images; + property ImageLayout; + property ImeMode; + property ImeName; + property IntegralHeight; +// property Items; + property ParentBiDiMode; + property ParentColor; + property ParentFont; + property ParentShowHint; + property PopupMenu; + property ReadOnly; + property ScrollWidth; + property ShowChecks; + property ShowHint; + property Sorted; + property Style; + property StyleDisabled; + property StyleFocused; + property StyleHot; + property TabOrder; + property TabStop; + property TabWidth; + property Visible; + property OnCheckStatesToEditValue; + property OnClick; + property OnClickCheck; + property OnCompare; + property OnContextPopup; + property OnDblClick; + property OnDragDrop; + property OnDragOver; + property OnDrawItem; + property OnEditValueToCheckStates; + property OnEndDock; + property OnEndDrag; + property OnEnter; + property OnExit; + property OnKeyDown; + property OnKeyPress; + property OnKeyUp; + property OnMeasureItem; + property OnMouseDown; + property OnMouseMove; + property OnMouseUp; + property OnStartDock; + property OnStartDrag; + end; + + TcxBoldCheckListBox = class(TcxBoldCustomCheckListBox{, IBoldValidateableComponent, IBoldOCLComponent}) + private + // IBoldValidateableComponent + function ValidateComponent(ComponentValidator: TBoldComponentValidator; NamePrefix: string): Boolean; override; + published + property BoldRowCheckBoxProperties; + end; + + +const + beSelectionHandleChanged = 400; + +type + TcxBoldSelectionCheckListBox = class(TcxBoldCustomCheckListBox{, IBoldValidateableComponent, IBoldOCLComponent}) + private + fCheckBoxRenderer: TBoldAsCheckBoxStateRenderer; + fPublisher: TBoldPublisher; + fBoldSelectionHandle: TBoldAbstractListHandle; + function GetAsCheckBoxState(aFollower: TBoldFollower): TCheckBoxState; + procedure SetAsCheckBoxState(aFollower: TBoldFollower; newValue: TCheckBoxState); + procedure OnSubscribe(aFollower: TBoldFollower; Subscriber: TBoldSubscriber); + procedure SetSelectionHandle(const Value: TBoldAbstractListHandle); + // IBoldValidateableComponent + function ValidateComponent(ComponentValidator: TBoldComponentValidator; NamePrefix: string): Boolean; override; + protected + procedure Notification(AComponent: TComponent; Operation: TOperation); override; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + published + property BoldSelectionHandle: TBoldAbstractListHandle read fBoldSelectionHandle write SetSelectionHandle; + end; + + TcxBoldListView = class(TcxCustomListView{, IBoldValidateableComponent, IBoldOCLComponent}) + private + fListHandleFollower: TBoldListHandleFollower; + fBoldProperties: TBoldAbstractListAsFollowerListController; + fBoldRowProperties: TBoldVariantFollowerController; + FUpdateCount: Integer; + function GetContextType: TBoldElementTypeInfo; + function GetBoldHandle: TBoldAbstractListHandle; + procedure SetBoldHandle(value: TBoldAbstractListHandle); + function GetFollower: TBoldFollower; + procedure SetBoldProperties(Value: TBoldAbstractListAsFollowerListController); + procedure SetRowProperties(const Value: TBoldVariantFollowerController); + function GetBoldHandleIndexLock: Boolean; + procedure SetBoldHandleIndexLock(Value: Boolean); + function GetBoldList: TBoldList; + function GetCurrentBoldElement: TBoldElement; + function GetCurrentBoldObject: TBoldObject; + protected + procedure _BeforeMakeUptoDate(Follower: TBoldFollower); + procedure _AfterMakeUptoDate(Follower: TBoldFollower); + procedure _InsertItem(Index: Integer; Follower: TBoldFollower); + procedure _ReplaceItem(Index: Integer; Follower: TBoldFollower); + procedure _DeleteItem(index: Integer; OwningFollower: TBoldFollower); + procedure _RowAfterMakeUptoDate(Follower: TBoldFollower); + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + property Follower: TBoldFollower read GetFollower; + property ListViewCanvas; + property BoldList: TBoldList read GetBoldList; + property CurrentBoldObject: TBoldObject read GetCurrentBoldObject; + property CurrentBoldElement: TBoldElement read GetCurrentBoldElement; + published + property BoldHandle: TBoldAbstractListHandle read GetBoldHandle write SetBoldHandle; + property BoldHandleIndexLock: Boolean read GetBoldHandleIndexLock write SetBoldHandleIndexLock default true; + property BoldProperties: TBoldAbstractListAsFollowerListController read fBoldProperties write SetBoldProperties; + property BoldRowProperties: TBoldVariantFollowerController read fBoldRowProperties write SetRowProperties; + + property Align; + property AllocBy default 0; + property Anchors; + property BiDiMode; + property Checkboxes; + property ColumnClick default True; + property Columns; + property Constraints; + property DragCursor; + property DragKind; + property DragMode; + property Enabled; + property HideSelection default True; + property HotTrack default False; + property HoverTime default -1; + property IconOptions; + {$IFDEF DELPHI6} + property ItemIndex; + {$ENDIF} +// property Items; + property LargeImages; + property MultiSelect default False; + property OwnerData default False; + property OwnerDraw default False; + property ParentBiDiMode; + property ParentColor default False; + property ParentFont; + property ParentShowHint; + property PopupMenu; + property ReadOnly default False; + property RowSelect default False; + property ShowColumnHeaders default True; + property ShowHint; + property ShowWorkAreas default False; + property SmallImages; + property SortType default stNone; + property StateImages; + property Style; + property StyleDisabled; + property StyleFocused; + property StyleHot; + property TabOrder; + property TabStop; + property ViewStyle default vsIcon; + property Visible; + property OnAdvancedCustomDraw; + property OnAdvancedCustomDrawItem; + property OnAdvancedCustomDrawSubItem; + property OnCancelEdit; + property OnChange; + property OnChanging; + property OnClick; + property OnColumnClick; + property OnColumnDragged; + property OnColumnRightClick; + property OnCompare; + property OnContextPopup; + {$IFDEF DELPHI6} + property OnCreateItemClass; + {$ENDIF} + property OnCustomDraw; + property OnCustomDrawItem; + property OnCustomDrawSubItem; + property OnData; + property OnDataFind; + property OnDataHint; + property OnDataStateChange; + property OnDblClick; + property OnDeletion; + property OnDragDrop; + property OnDragOver; + property OnDrawItem; + property OnEdited; + property OnEditing; + property OnEndDock; + property OnEndDrag; + property OnEnter; + property OnExit; + property OnGetImageIndex; + property OnGetSubItemImage; + property OnInfoTip; + property OnInsert; + property OnKeyDown; + property OnKeyPress; + property OnKeyUp; + property OnMouseDown; + property OnMouseMove; + property OnMouseUp; + property OnSelectItem; + property OnStartDock; + property OnStartDrag; + end; + +{$IFDEF BoldDevExLog} + TcxBoldEditorsLogProc = procedure(aMessage: string; aCategory: string = '') of object; +{$ENDIF} + +{$IFDEF BoldDevExLog} +var + cxBoldEditorsLogProc: TcxBoldEditorsLogProc; +{$ENDIF} + +procedure InternalComboSetValue( + aBoldHandle: TBoldElementHandle; + aFollower: TBoldFollower; + aSelectedElement: TBoldElement; + aBoldSelectChangeAction: TBoldComboSelectChangeAction; + aBoldSetValueExpression: TBoldExpression; + aListHandle: TBoldAbstractListHandle; + aValue: Variant); + +procedure _ValidateEdit(aEdit: TcxCustomEdit); + +implementation + +uses + Types, +{$IFDEF BOLD_DELPHI16_OR_LATER}UiTypes,{$ENDIF} + BoldAttributes, + BoldBase, + Variants, + Graphics, + BoldQueue, + BoldEnvironment, + cxFilterControlUtils, + cxBoldEditConsts, + BoldReferenceHandle, + BoldValueInterfaces, + cxDateUtils, + {$IFDEF DevExScheduler} + cxSchedulerDateNavigator, + {$ENDIF} + BoldLogHandler, + BoldCoreConsts, + BoldDomainElement, + BoldOCL, + BoldGuard, + BoldAFP, + BoldGUI, + BoldGuiResourceStrings, + BoldMetaElementList, + BoldHashIndexes, + BoldIndex, + BoldIndexableList, + Forms, dxMessages; + +type + TcxCustomEditAccess = class(TcxCustomEdit); + TBoldFollowerControllerAccess = class(TBoldFollowerController); + TBoldElementHandleAccess = class(TBoldElementHandle); + TcxEditValidateInfoAccess = class(TcxEditValidateInfo); + +{$IFDEF BoldDevExLog} +procedure _Log(aMessage: string; aCategory: string = ''); +begin + if Assigned(cxBoldEditorsLogProc) then + cxBoldEditorsLogProc(aMessage, aCategory); +end; +{$ENDIF} + +procedure _ValidateEdit(aEdit: TcxCustomEdit); +var + lBoldValidateableComponent: IBoldValidateableComponent; + + procedure InternalValidate; + var + lBoldComponentValidator: TBoldComponentValidator; + begin + lBoldComponentValidator := TBoldComponentValidator.Create; + try + lBoldValidateableComponent.ValidateComponent(lBoldComponentValidator, aEdit.Name); + finally + lBoldComponentValidator.free; + end; + end; + +var + lcxBoldEditDataBinding: TcxBoldEditDataBinding; + lValue: Variant; + lFollower: TBoldFollower; + s: string; + lContext: TBoldElementTypeInfo; + lEvaluator: TBoldOCL; + lBoldMemberRTInfo: TBoldMemberRTInfo; + lExpression: string; +begin + if Supports(aEdit, IBoldValidateableComponent, lBoldValidateableComponent) then + begin + InternalValidate; + + lcxBoldEditDataBinding := TcxCustomEditAccess(aEdit).DataBinding as TcxBoldEditDataBinding; + lContext := lcxBoldEditDataBinding.GetContextType; + if not Assigned(lcxBoldEditDataBinding.BoldHandle) then + lValue := '< no handle >' + else + if (lContext = nil) then + lValue := '< no context >' + else + if Assigned(lcxBoldEditDataBinding.Follower) then + begin + lFollower := lcxBoldEditDataBinding.Follower; + lEvaluator := lContext.Evaluator as TBoldOCL; + lExpression := TBoldFollowerControllerAccess(lFollower.Controller).Expression; + lBoldMemberRTInfo := lEvaluator.RTInfo(lExpression, lContext, false, lFollower.Controller.VariableList); + if Assigned(lBoldMemberRTInfo) then + lValue := lBoldMemberRTInfo.AsString + else + begin + lContext := lEvaluator.ExpressionType(lExpression, lContext, false, lFollower.Controller.VariableList); + if Assigned(lContext) then + lValue := lContext.AsString; + end; + end; + if VarIsNull(lValue) or (lValue = '') then + lValue := TBoldFollowerControllerAccess(lcxBoldEditDataBinding.BoldFollowerController).Expression; + +// TcxCustomEditAccess(aEdit).SetInternalEditValue(lValue); + TcxCustomEditAccess(aEdit).SetInternalDisplayValue(lValue); + + if aEdit.name <> '' then + s := '_ValidateEdit ' + aEdit.name + ':' + lValue + else + s := '_ValidateEdit ' + aEdit.ClassName + ':' + lValue; + + OutPutDebugString(PChar(S)); + end + else + if Supports(aEdit.ActiveProperties, IBoldValidateableComponent, lBoldValidateableComponent) then + InternalValidate; +end; + +procedure InternalComboSetValue( + aBoldHandle: TBoldElementHandle; + aFollower: TBoldFollower; + aSelectedElement: TBoldElement; + aBoldSelectChangeAction: TBoldComboSelectChangeAction; + aBoldSetValueExpression: TBoldExpression; + aListHandle: TBoldAbstractListHandle; + aValue: Variant); + +var + ElementToAssignTo: TBoldElement; + lValue: Variant; + lOldValue: IBoldValue; + lHasOldValue: boolean; + + procedure InternalSetValue(); + begin + if not ElementToAssignTo.Mutable then + begin + SetBoldLastFailureReason(TBoldFailureReason.CreateFmt('Element %s is immutable', [ElementToAssignTo.displayName], ElementToAssignTo)); + exit; + end + else + if (elementToAssignTo is TBoldMember) then + begin + if not TBoldMember(ElementToAssignTo).CanModify then + begin + exit; + end; + if elementToAssignTo is TBoldObjectReference then + begin + if not ElementToAssignTo.IsEqual(aSelectedElement) then + begin + ElementToAssignTo.Assign(aSelectedElement); + end; + end + else + // if elementToAssignTo is TBoldAttribute then + begin + lValue := Null; + if Assigned(aSelectedElement) then + lValue := aSelectedElement.AsVariant; + ElementToAssignTo.AsVariant := lValue; + // (aFollower.Controller as TBoldVariantFollowerController).MayHaveChanged(lValue, aFollower); + end; + end; + end; + +var + FailureReason: TBoldFailureReason; + Discard: Boolean; + Handled: Boolean; +begin + try + BoldClearLastFailure; + try + case aBoldSelectChangeAction of + bdcsNone:; + bdscSetText: + (aFollower.Controller as TBoldVariantFollowerController).MayHaveChanged(aValue, aFollower); + bdcsSetReference: + if Assigned(aBoldHandle) and aBoldHandle.CanSetValue then + TBoldElementHandleAccess(aBoldHandle).SetValue(aSelectedElement); + bdcsSetListIndex: + begin + aFollower.DiscardChange; + if assigned(aListHandle) then + aListHandle.CurrentIndex := aListHandle.List.IndexOf(aSelectedElement); + end; + bdcsSetValue: + begin + if not (Assigned(aFollower.Element)) then + exit; + if trim(aBoldSetValueExpression) <> '' then + ElementToAssignTo := aFollower.Element.EvaluateExpressionAsDirectElement(aBoldSetValueExpression, TBoldFollowerControllerAccess(aFollower.Controller).VariableList) + else + begin + ElementToAssignTo := aFollower.Value; + end; + if assigned(ElementToAssignTo) then + InternalSetValue(); + end; + end; + finally + FailureReason := GetBoldLastFailureReason; + if assigned(FailureReason) then + BoldRaiseLastFailure(nil, '', 'InternalComboSetValue failed.'); + end; + except + on E: Exception do + begin + Handled := assigned(aFollower.Controller) and TBoldFollowerControllerAccess(aFollower.Controller).DoApplyException(E, ElementToAssignTo, Discard); + if Discard then + aFollower.DiscardChange; + if not Handled then + raise; + end; + end; +end; + +{ TcxBoldTextEditProperties } + +procedure TcxCustomBoldTextEditProperties._DeleteItem(Index: Integer; + OwningFollower: TBoldFollower); +begin + if not LookupItems.Updating then + LookupItems.BeginUpdate; + LookupItems.Delete(index); +end; + +procedure TcxCustomBoldTextEditProperties._InsertItem(Index: Integer; Follower: TBoldFollower); +begin + Assert(Assigned(Follower)); + if not LookupItems.Updating then + LookupItems.BeginUpdate; + Follower.EnsureDisplayable; + LookupItems.Insert(Index, VarToStr(TBoldVariantFollowerController(Follower.Controller).GetAsVariant(Follower))); +end; + +procedure TcxCustomBoldTextEditProperties._ReplaceItem(Index: Integer; + Follower: TBoldFollower); +begin + if not LookupItems.Updating then + LookupItems.BeginUpdate; + Follower.EnsureDisplayable; + LookupItems.Strings[Index] := VarToStr(TBoldVariantFollowerController(Follower.Controller).GetAsVariant(Follower)); +end; + +procedure TcxCustomBoldTextEditProperties._RowAfterMakeUptoDate( + Follower: TBoldFollower); +var + index: Integer; + NewValue: String; +begin +{ OutputDebugString('TcxCustomBoldTextEditProperties._RowAfterMakeUptoDate'); + if (Owner is TcxCustomEdit) and TcxCustomEdit(Owner).IsDesigning then + begin + ValidateEdit(TcxCustomEdit(Owner)); + end; +} + index := Follower.index; + if (index > -1) and (index < LookupItems.Count) then + begin + NewValue := VarToStr(TBoldVariantFollowerController(Follower.Controller).GetAsVariant(Follower)); + if LookupItems[index] <> NewValue then + LookupItems[index] := NewValue; + end; +// LookupDataChanged(self); + // forces a redisplay of the edit-area, the windows component might go blank if the active row is removed and then reinserted +// fBoldHandleFollower.Follower.MarkValueOutOfDate; // do we really need this here ? Danny +end; + +function TcxCustomBoldTextEditProperties.GetBoldListHandle: TBoldAbstractListHandle; +begin + Result := fListHandleFollower.BoldHandle; +end; + +function TcxCustomBoldTextEditProperties.GetContextForBoldRowProperties: TBoldElementTypeInfo; +begin + if assigned(BoldLookupListHandle) then + result := BoldLookupListHandle.StaticBoldType + else + result := nil; +end; + +function TcxCustomBoldTextEditProperties.GetListFollower: TBoldFollower; +begin + Result := fListHandleFollower.Follower; +end; + +function TcxCustomBoldTextEditProperties.IsEditValueValid( + var EditValue: TcxEditValue; AEditFocused: Boolean): Boolean; +begin + result := inherited IsEditValueValid(EditValue, AEditFocused) or IsNilRepresentation(EditValue); +end; + +function TcxCustomBoldTextEditProperties.IsNilRepresentation( + AValue: Variant): boolean; +begin + result := UseLookupData and cxEditVarEquals(AValue, BoldRowProperties.NilRepresentation); +end; + +procedure TcxCustomBoldTextEditProperties.SetBoldListHandle( + const Value: TBoldAbstractListHandle); +begin + fListHandleFollower.BoldHandle := value; +end; + +procedure TcxCustomBoldTextEditProperties.SetBoldListProperties( + const Value: TBoldAbstractListAsFollowerListController); +begin + fBoldListProperties.Assign(Value); +end; +{ +procedure TcxCustomBoldTextEditProperties.SetBoldSelectChangeAction( + const Value: TBoldComboSelectChangeAction); +begin + fBoldSelectChangeAction := Value; +end; +} +procedure TcxCustomBoldTextEditProperties.SetRowProperties( + const Value: TBoldVariantFollowerController); +begin + fBoldRowProperties.Assign(Value); +end; + +constructor TcxCustomBoldTextEditProperties.Create(AOwner: TPersistent); + +begin + inherited; + fBoldRowProperties := TBoldVariantFollowerController.Create(Owner as TComponent); + fBoldRowProperties.AfterMakeUptoDate := _RowAfterMakeUptoDate; + fBoldRowProperties.OnGetContextType := GetContextForBoldRowProperties; + fBoldListProperties := TBoldAbstractListAsFollowerListController.Create((Owner as TComponent), fBoldRowProperties); + with fBoldListProperties do + begin + OnAfterInsertItem := _InsertItem; + OnAfterDeleteItem := _DeleteItem; + OnReplaceitem := _ReplaceItem; + BeforeMakeUptoDate := _BeforeMakeUptoDate; + AfterMakeUptoDate := _AfterMakeUptoDate; + end; + fListHandleFollower := TBoldListHandleFollower.Create((Owner as TComponent).owner , fBoldListProperties); + BoldSelectChangeAction := bdcsSetValue; +end; + +destructor TcxCustomBoldTextEditProperties.Destroy; +begin + FreeAndNil(fListHandleFollower); + FreeAndNil(fBoldListProperties); + FreeAndNil(fBoldRowProperties); + inherited; +end; + +procedure TcxCustomBoldTextEditProperties._AfterMakeUptoDate( + Follower: TBoldFollower); +begin + fBoldRowProperties.AfterMakeUptoDate := _RowAfterMakeUptoDate; + if LookupItems.Updating then + LookupItems.EndUpdate; +end; + +procedure TcxCustomBoldTextEditProperties._BeforeMakeUptoDate( + Follower: TBoldFollower); +begin + fBoldRowProperties.AfterMakeUptoDate := nil; +end; + + +{ TcxBoldEditDataBinding } + +constructor TcxBoldEditDataBinding.Create(AEdit: TcxCustomEdit); +begin + inherited Create(AEdit); +// DefaultValuesProvider.fcxBoldEditDataBinding := self; + fBoldFollowerController:= TBoldVariantFollowerController.Create(AEdit); +// fBoldProperties := TBoldVariantFollowerController.Create(AEdit); + BoldFollowerController.AfterMakeUptoDate := _AfterMakeUptoDate; + BoldFollowerController.OnGetContextType := GetContextType; + BoldFollowerController.OnApplyException := HandleApplyException; + fBoldHandleFollower := TBoldElementHandleFollower.Create(AEdit.Owner, BoldFollowerController); + + DefaultValuesProvider.BoldProperties := BoldFollowerController; + DefaultValuesProvider.BoldHandleFollower := fBoldHandleFollower; +{ if AEdit.InnerControl <> nil then + FDataLink.Control := AEdit.InnerControl + else + FDataLink.Control := AEdit; +} +end; + +destructor TcxBoldEditDataBinding.Destroy; +begin + case BoldFollowerController.ApplyPolicy of + bapChange, bapExit: try + Follower.Apply; + except + Follower.DiscardChange; + end; + bapDemand: Follower.DiscardChange; + end; + FreeAndNil(fBrokenConstraints); + FreeAndNil(fBoldHandleFollower); + FreeAndNil(fBoldFollowerController); + Edit.ViewInfo.OnPaint := nil; + inherited Destroy; +end; + +function TcxBoldEditDataBinding.GetBoldHandle: TBoldElementHandle; +begin + Result := fBoldHandleFollower.BoldHandle +end; + +function TcxBoldEditDataBinding.GetFollower: TBoldFollower; +begin + Result := fBoldHandleFollower.Follower +end; + +function TcxBoldEditDataBinding.GetHasBrokenConstraints: boolean; +begin + result := Assigned(fBrokenConstraints) and (BrokenConstraints.Count > 0); +end; + +function TcxBoldEditDataBinding.GetIsInInternalChange: boolean; +begin + result := fInternalChange > 0; +end; + +procedure TcxBoldEditDataBinding.SetBoldHandle( + const Value: TBoldElementHandle); +begin +// if not (Edit.IsLoading) then + begin + fBoldHandleFollower.BoldHandle := value; + DefaultValuesProvider.fBoldHandleFollower := fBoldHandleFollower; + if (Edit.IsDesigning) and not (Edit.IsLoading) then + begin + _ValidateEdit(Edit); + end; +// DefaultValuesProvider.BoldHandle := value; +// DefaultValuesProvider.BoldProperties := BoldProperties; + end; +end; + +procedure TcxBoldEditDataBinding.Assign(Source: TPersistent); +begin + if Source is TcxBoldEditDataBinding then + begin + // TODO: what about HandleFollower ? + BoldHandle := TcxBoldEditDataBinding(Source).BoldHandle; + fBoldFollowerController := TcxBoldEditDataBinding(Source).BoldFollowerController; + DataChanged; // ? + end; + inherited Assign(Source); +end; + +function TcxBoldEditDataBinding.ImmediatePost: boolean; +begin + result := BoldFollowerController.ApplyPolicy = bapChange; +end; + +function TcxBoldEditDataBinding.CanCheckEditorValue: Boolean; +begin + result := inherited CanCheckEditorValue; +end; + +function TcxBoldEditDataBinding.CanPostEditorValue: Boolean; +begin + Result := IsDataAvailable and (fInternalChange = 0) and not FEdit.ActiveProperties.ReadOnly and Modified; +// Result := Editing and Edit.IsFocused; //or (BoldProperties.ApplyPolicy = bapExit); +// result := false; // inherited CanPostEditorValue; +// Result := Editing and DataLink.FModified; +end; + +procedure TcxBoldEditDataBinding.DataChanged; +begin + inherited; +end; + +procedure TcxBoldEditDataBinding.DataSetChange; +begin + inherited; +end; + +procedure TcxBoldEditDataBinding.DefaultValuesChanged; +begin + inherited DefaultValuesChanged; +end; + +procedure TcxBoldEditDataBinding.EditingChanged; +begin + TcxCustomEditAccess(Edit).EditingChanged; +end; + +function TcxBoldEditDataBinding.ExecuteAction( + Action: TBasicAction): Boolean; +begin + result := inherited ExecuteAction(Action); +end; + +function TcxBoldEditDataBinding.GetDefaultValuesProvider: TcxCustomBoldEditDefaultValuesProvider; +begin + Result := TcxCustomBoldEditDefaultValuesProvider(IDefaultValuesProvider.GetInstance); +end; + +class function TcxBoldEditDataBinding.GetDefaultValuesProviderClass: TcxCustomEditDefaultValuesProviderClass; +begin + result := TcxCustomBoldEditDefaultValuesProvider; +end; + +type + TcxCustomTextEditAccess = class(TcxTextEdit); + +function TcxBoldEditDataBinding.GetModified: Boolean; +var + lcxBoldEditProperties: IcxBoldEditProperties; + lValue: Variant; + lEditValue: variant; +// lElement: TBoldElement; +begin + if not IsDataAvailable or FEdit.ActiveProperties.ReadOnly then + begin + result := false; + end + else + begin + if Supports(Edit.ActiveProperties, IcxBoldEditProperties, lcxBoldEditProperties) then + begin + if Edit is TcxCustomComboBox then + lEditValue := TcxCustomComboBox(Edit).ILookupData.CurrentKey + else + lEditValue := Edit.EditValue; + lValue := lcxBoldEditProperties.BoldElementToEditValue(Follower, Follower.Element, Edit); +// result := (Follower.AssertedController.EffectiveRenderer as TBoldAsVariantRenderer).IsChanged(Follower, lValue); + result := not cxEditVarEquals(lEditValue, lValue); + end + else + begin + result := (TBoldFollowerControllerAccess(Follower.AssertedController).EffectiveRenderer as TBoldAsVariantRenderer).IsChanged(Follower, Edit.EditValue); + end; + end; +end; + +function TcxBoldEditDataBinding.GetStoredValue: TcxEditValue; +begin + Assert(assigned(Follower)); + result := ((Follower.Controller) as TBoldVariantFollowerController).GetAsVariant(Follower); +end; + +function TcxBoldEditDataBinding.IsLookupControl: Boolean; +begin + result := false; // inherited IsLookupControl; +end; + +function TcxBoldEditDataBinding.IsRefreshDisabled: Boolean; +begin + result := false; // inherited IsRefreshDisabled; +end; + +procedure TcxBoldEditDataBinding.Reset; +begin + inc(fInternalChange); + try + case BoldFollowerController.ApplyPolicy of + bapChange : + begin +// Follower.UndoChange; + end; + bapExit, bapDemand: Follower.DiscardChange; + end; + inherited; +// Follower.Display; +// TBoldQueueable.DisplayAll; + finally + dec(fInternalChange); + Edit.LockClick(False); + end; +end; + +procedure TcxBoldEditDataBinding.SetModified; +begin + if (fInternalChange = 0) and Editing then + begin + inherited; + end; +end; + +procedure TcxBoldEditDataBinding.SetStoredValue(const Value: TcxEditValue); +var + lIcxBoldEditProperties: IcxBoldEditProperties; + lDone: Boolean; +begin + lDone := false; + if Supports(Edit.ActiveProperties, IcxBoldEditProperties, lIcxBoldEditProperties) then + begin + lIcxBoldEditProperties.SetStoredValue(Value, BoldHandle, Edit, Follower, lDone); + end; + if not lDone then + begin + InternalSetValue(Value); + end; + TBoldQueueable.DisplayAll; +// Follower.Apply; + inherited; +end; + +function TcxBoldEditDataBinding.UpdateAction( + Action: TBasicAction): Boolean; +begin + result := inherited UpdateAction(Action); +end; + +procedure TcxBoldEditDataBinding.UpdateData; +begin + inherited; +end; + +procedure TcxBoldEditDataBinding.UpdateDisplayValue; +begin + Edit.LockClick(True); + inc(fInternalChange); + try + inherited UpdateDisplayValue; + finally + dec(fInternalChange); + Edit.LockClick(False); + end; + if Edit.IsDesigning and not Edit.IsLoading then + begin + _ValidateEdit(Edit); + end; +end; + +type + TcxCustomTextEditPropertiesAccess = class(TcxCustomTextEditProperties) + end; + +procedure TcxBoldEditDataBinding._AfterMakeUptoDate( + Follower: TBoldFollower); +var + lValue: Variant; +// lcxBoldComboBoxProperties: TcxBoldComboBoxProperties; + lElement: TBoldElement; +// WasModified: boolean; + ASize: TSize; + AViewData: TcxCustomEditViewData; + AEditSizeProperties: TcxEditSizeProperties; +begin + if fInternalChange > 0 then + begin + {$IFDEF BoldDevExLog} + Assert(assigned(self)); + _Log('TcxBoldEditDataBinding._AfterMakeUptoDate: fInternalChange ' + Edit.Name, className); + {$ENDIF} + {$IFDEF Constraints} + SubscribeToConstraints(Follower.Value); + {$ENDIF} + exit; + end; +// WasModified := Edit.ModifiedAfterEnter or Edit.EditModified; + Edit.LockClick(True); + inc(fInternalChange); + try + // this is not really the perfect place for setting ImmediatePost + Edit.ActiveProperties.ImmediatePost := ImmediatePost; + lValue := null; + if Edit.IsDesigning then + begin + _ValidateEdit(Edit); + end + else + begin + TypeMayHaveChanged; + {$IFDEF Constraints} + lElement := Follower.Value; + SubscribeToConstraints(lElement); + {$ENDIF} + lValue := InternalGetValue(Follower); + if Edit.ModifiedAfterEnter and not Edit.IsPosting then + Edit.Reset; + if not cxEditVarEquals(Edit.EditValue, lValue) then + begin + TcxCustomEditAccess(Edit).SetInternalEditValue(lValue); + end; + if ShowHintIfCaptionDoesntFit then + begin + AViewData := TcxCustomEditViewData(TcxCustomEditAccess(Edit).CreateViewData); + try + TcxCustomEditAccess(Edit).PopulateSizeProperties(AEditSizeProperties); + ASize := AViewData.GetEditSize(cxScreenCanvas, lValue, AEditSizeProperties, edit.ViewInfo); + if ASize.cx > Edit.Width then + begin + Edit.Hint := VarToStr(lValue); + Edit.ShowHint := true; + end + else + begin + Edit.Hint := ''; + Edit.ShowHint := false; + end; + finally + FreeAndNil(AViewData); + end; + end; + end; + finally + ValueOrDefinitionInvalid := false; + try + if Assigned(Edit.ViewInfo) and Assigned(Edit.ViewInfo.ErrorData) and TcxEditValidateInfoAccess(Edit.ViewInfo.ErrorData).IsError then + begin + ValueOrDefinitionInvalid := not Edit.ValidateEdit(false); + end; + finally +// TcxCustomTextEditAccess(Edit).ResetEditValue; + Edit.LockClick(False); + dec(fInternalChange); + if Edit.IsFocused and not Edit.EditModified then + Edit.SelectAll + end; + end; +end; + +function TcxBoldEditDataBinding.InternalGetValue(Follower: TBoldFollower): Variant; +var + lElement: TBoldElement; + lIcxBoldEditProperties: IcxBoldEditProperties; +begin + result := Null; + lElement := Follower.Value; +{ if (Edit.ActiveProperties is TcxBoldComboBoxProperties) then + begin + lcxBoldComboBoxProperties := (Edit.ActiveProperties as TcxBoldComboBoxProperties); + if (Edit is TcxCustomComboBox) and Assigned(TcxCustomComboBox(Edit).ILookupData.ActiveControl) then + begin + TcxCustomEditListBox(TcxCustomComboBox(Edit).ILookupData.ActiveControl).ItemIndex := lcxBoldComboBoxProperties.LookupListFollower.CurrentIndex; + end; + end; +} + if Supports(Edit.ActiveProperties, IcxBoldEditProperties, lIcxBoldEditProperties) then + result := lIcxBoldEditProperties.BoldElementToEditValue(Follower, lElement, Edit) + else + result := TBoldVariantFollowerController(Follower.Controller).GetAsVariant(Follower); + if VarIsEmpty(result) then + result := Null; +end; + +function TcxBoldEditDataBinding.GetBrokenConstraints: TStringList; +begin + if not Assigned(fBrokenConstraints) then + fBrokenConstraints := TStringList.Create; + result := fBrokenConstraints; +end; + +function TcxBoldEditDataBinding.GetContextType: TBoldElementTypeInfo; +begin + if assigned(BoldHandle) then + result := BoldHandle.StaticBoldType + else + result := nil; +end; + +function TcxBoldEditDataBinding.CanModify: Boolean; +begin + result := inherited CanModify and MayModify; +end; + +procedure TcxBoldEditDataBinding.TypeMayHaveChanged; +begin +// Edit.IsDesigning +// BoldEffectiveEnvironment.RunningInIDE or + if not Assigned(BoldHandle) or not Assigned(BoldHandle.Value) then + Exit; // only update at runtime if there are values, avoids update on every UML model change. + if fCurrentElementType <> BoldHandle.BoldType then + begin + fCurrentElementType := BoldHandle.BoldType; + if Edit is TcxCustomTextEdit then + TcxCustomTextEditAccess(Edit).LockLookupDataTextChanged; + try + TcxCustomEditAccess(Edit).PropertiesChanged(nil); + finally + if Edit is TcxCustomTextEdit then + TcxCustomTextEditAccess(Edit).UnlockLookupDataTextChanged; + end; + end; +end; + +function TcxBoldEditDataBinding.MayModify: boolean; +var + lcxBoldEditProperties: IcxBoldEditProperties; +begin + result := BoldFollowerController.MayModify(Follower); + if result and Supports(Edit.ActiveProperties, IcxBoldEditProperties, lcxBoldEditProperties) then + begin + result := lcxBoldEditProperties.CanEdit(BoldHandle, Follower); + end; +end; + +procedure TcxBoldEditDataBinding.DoChanged; +begin + if Editing and (fInternalChange = 0) then + begin + inc(fInternalChange); + try + InternalSetValue(Edit.EditingValue); + if ImmediatePost then + Follower.Apply; + Follower.EnsureDisplayable; + finally + dec(fInternalChange); + end; + end; +end; + +procedure TcxBoldEditDataBinding.DoEnter; +begin + if (Follower.State = bfsDirty) then + Edit.ModifiedAfterEnter := true; +end; + +procedure TcxBoldEditDataBinding.DoExit; +begin + if (Follower.State = bfsDirty) and (Follower.Controller.ApplyPolicy <> bapDemand) then + try + Follower.Apply; + except + Follower.DiscardChange; + end; +end; + +{$IFDEF Constraints} +procedure TcxBoldEditDataBinding.SubscribeToConstraints( + aElement: TBoldElement); +var + s: string; + lIE: TBoldIndirectElement; + lConstraintList: TBoldList; +const + ECM_FIRST = $1500; + EM_SETCUEBANNER = ECM_FIRST + 1; + + procedure EvaluateConstraints(AElement: TBoldElement); + var + i: integer; + begin + lIE := TBoldIndirectElement.Create; + try + aElement.EvaluateAndSubscribeToExpression('constraints->select(c|not c)', Follower.Subscriber, lIe); + lConstraintList := lIE.Value as TBoldList; + for i := 0 to lConstraintList.Count - 1 do + BrokenConstraints.AddObject(lConstraintList[i].StringRepresentation[11], lConstraintList[i]); + if HasBrokenConstraints then + if Assigned(Edit) and Assigned(TcxCustomEditAccess(Edit).InnerEdit) then + begin + s := BrokenConstraints.Text; + SendMessage(TcxCustomEditAccess(Edit).InnerEdit.Control.Handle, EM_SETCUEBANNER, 1, LParam(PWideChar(WideString(s)))); + end; + finally + lIE.free; + end; + end; + +begin + FreeAndNil(fBrokenConstraints); + if not Assigned(aElement) then + exit; + if ((aElement is TBoldMember) and (Assigned(TBoldMember(aElement).BoldMemberRTinfo)) and + ((TBoldMember(aElement).BoldMemberRTinfo.ConstraintCount > 0) +// or (TBoldMember(aElement).OwningObject.BoldClassTypeInfo.ConstraintCount > 0) + )) or + (aElement is TBoldObject) and (TBoldObject(aElement).BoldClassTypeInfo.ConstraintCount > 0) or + (aElement is TBoldSystem) and (TBoldSystem(aElement).BoldSystemTypeInfo.ConstraintCount > 0 ) then + begin + EvaluateConstraints(AElement); + end; +end; +{$ENDIF} + +function TcxBoldEditDataBinding.ValidateComponent( + ComponentValidator: TBoldComponentValidator; + NamePrefix: string): Boolean; +var + lContext: TBoldElementTypeInfo; + lExpressionType: TBoldElementTypeInfo; + lBoldValidateableComponent: IBoldValidateableComponent; + s: string; +begin + lContext := GetContextType; + result := Assigned(lContext); + if not result then + begin + BoldLog.LogFmt(sNoContext, [Edit.Name]) + end + else + begin + result := ComponentValidator.ValidateExpressionInContext( + TBoldFollowerControllerAccess(BoldFollowerController).Expression, + lContext, + format('%s %s.Expression', [NamePrefix, Edit.Name]), TBoldFollowerControllerAccess(BoldFollowerController).VariableList) and result; // do not localize + + if result then + begin + lExpressionType := lContext.Evaluator.ExpressionType(TBoldFollowerControllerAccess(BoldFollowerController).Expression, lContext, false, TBoldFollowerControllerAccess(BoldFollowerController).VariableList); + if Assigned(lExpressionType) then + begin + s := ValidateTypeConforms(lExpressionType); + if s <> '' then + begin + result := false; + BoldLog.Log('*** ' + s + ' in ' + Edit.Name); + end; + end; + end; + end; + if Supports(Edit.ActiveProperties, IBoldValidateableComponent, lBoldValidateableComponent) then + begin + result := lBoldValidateableComponent.ValidateComponent(ComponentValidator, NamePrefix) and result; + end; + ValueOrDefinitionInvalid := not result; +end; + +function TcxBoldEditDataBinding.ValidateTypeConforms( + aExpressionType: TBoldElementTypeInfo): string; +begin + result := ''; +end; + +function TcxBoldEditDataBinding.GetValueOrDefinitionInvalid: boolean; +begin + result := fValueOrDefinitionInvalid; +end; + +procedure TcxBoldEditDataBinding.SetValueOrDefinitionInvalid( + const Value: boolean); +begin + if fValueOrDefinitionInvalid <> Value then + begin + fValueOrDefinitionInvalid := Value; +// Edit.Refresh; +// Edit.Invalidate; + Edit.Repaint; + end; +end; + +function TcxBoldEditDataBinding.GetBoldProperties: TBoldVariantFollowerController; +begin + result := BoldFollowerController as TBoldVariantFollowerController; +end; + +procedure TcxBoldEditDataBinding.InternalSetValue( + const aValue: TcxEditValue); +begin + {$IFDEF BoldDevExLog} + if Follower.State = bfsSubscriptionOutOfDate then + begin + _Log('TcxBoldEditDataBinding.InternalSetValue, Follower.State = bfsSubscriptionOutOfDate', 'Follower debug'); + end; + {$ENDIF} + BoldProperties.MayHaveChanged(aValue, Follower); +end; + +procedure TcxBoldEditDataBinding.SetBoldProperties( + const Value: TBoldVariantFollowerController); +begin + BoldFollowerController.Assign(Value); +end; + +function TcxBoldEditDataBinding.GetExpression: TBoldExpression; +begin + result := BoldProperties.Expression; +end; + +function TcxBoldEditDataBinding.GetVariableList: TBoldExternalVariableList; +begin + result := BoldProperties.VariableList; +end; + +function TcxBoldEditDataBinding.HandleApplyException(E: Exception; + Elem: TBoldElement; var Discard: Boolean): Boolean; +begin + result := false; + if Edit.IsDestroying then + exit; + if Assigned(Edit.ActiveProperties) then + result := not (evoRaiseException in Edit.ActiveProperties.ValidationOptions); + if not TcxCustomEditAccess(Edit).IsEditValidated then + Edit.ValidateEdit(false); +end; + +procedure TcxBoldEditDataBinding.SetExpression(const Value: TBoldExpression); +begin + BoldProperties.Expression := Value; +end; + +procedure TcxBoldEditDataBinding.ValidateDisplayValue(var ADisplayValue: TcxEditValue; var AErrorText: TCaption; var AError: Boolean); + + procedure AddMessage(const s: string); + begin + if AErrorText <> '' then + AErrorText := AErrorText + BOLDCRLF + s + else + AErrorText := s; + end; +begin + if not AError then + AErrorText := ''; + BoldClearLastFailure; + if not BoldProperties.ValidateVariant(ADisplayValue, Follower) then + begin + AError := true; + if (BoldSystem.GetBoldLastFailureReason <> nil) then + AddMessage(BoldSystem.GetBoldLastFailureReason.Reason); + end; + if HasBrokenConstraints then + begin + AError := true; + AddMessage(BrokenConstraints.text); + end; + ValueOrDefinitionInvalid := AError; +end; + +{ TcxBoldTextEdit } + +class function TcxBoldTextEdit.GetPropertiesClass: TcxCustomEditPropertiesClass; +begin + Result := TcxBoldTextEditProperties; +end; + +function TcxBoldTextEdit.GetActiveProperties: TcxBoldTextEditProperties; +begin + Result := TcxBoldTextEditProperties(InternalGetActiveProperties); +// FProperties.ValidateOnEnter := true; +end; + +function TcxBoldTextEdit.GetProperties: TcxBoldTextEditProperties; +begin + Result := TcxBoldTextEditProperties(FProperties); +// FProperties.ImmediatePost := true; +// FProperties.ValidateOnEnter := true; +end; + +procedure TcxBoldTextEdit.SetProperties( + Value: TcxBoldTextEditProperties); +begin + FProperties.Assign(Value); +end; + +class function TcxBoldTextEdit.GetDataBindingClass: TcxEditDataBindingClass; +begin + Result := TcxBoldTextEditDataBinding; +end; + +function TcxBoldTextEdit.GetDataBinding: TcxBoldTextEditDataBinding; +begin + Result := FDataBinding as TcxBoldTextEditDataBinding; +end; + +procedure TcxBoldTextEdit.SetDataBinding( + Value: TcxBoldTextEditDataBinding); +begin + FDataBinding.Assign(Value); +end; + +function TcxBoldTextEdit.ValidateKeyDown(var Key: Word; + Shift: TShiftState): Boolean; +begin + result := DataBinding.IsDataAvailable and inherited ValidateKeyDown(Key, Shift); +end; + +function TcxBoldTextEdit.ValidateKeyPress(var Key: Char): Boolean; +begin + result := DataBinding.MayModify and inherited ValidateKeyPress(Key); + if not result then + Key := #0 + else + begin + if (Key = #13) and (DataBinding.Follower.Controller.ApplyPolicy <> bapDemand) then + begin + DataBinding.Follower.Apply; + SelectAll; + end; + end; +end; + +procedure TcxBoldTextEdit.DoOnChange; +begin + inherited; + PostEditValue; +end; + +procedure TcxBoldTextEdit.DoValidateDisplayValue( + var ADisplayValue: TcxEditValue; var AErrorText: TCaption; + var AError: Boolean); +begin + inherited; + if Assigned(DataBinding) then + DataBinding.ValidateDisplayValue(ADisplayValue, AErrorText, AError); +end; + +procedure TcxBoldTextEdit.DoChange; +begin + inherited; + DataBinding.DoChanged; +end; + +procedure TcxBoldTextEdit.DoEnter; +begin + inherited; + DataBinding.DoEnter; +end; + +procedure TcxBoldTextEdit.DoExit; +begin + inherited; + DataBinding.DoExit; +end; +{ +function TcxBoldTextEdit.ValidateComponent( + ComponentValidator: TBoldComponentValidator; + NamePrefix: string): Boolean; +begin + result := DataBinding.ValidateComponent(ComponentValidator, NamePrefix); + result := GetActiveProperties.ValidateComponent(ComponentValidator, NamePrefix) and result; +end; +} +procedure TcxBoldTextEdit.Paint; +begin + inherited Paint; + if DataBinding.ValueOrDefinitionInvalid then + Canvas.FrameRect(Bounds, clRed, 2 - Ord(IsNativeStyle)); +end; + +{ TcxCustomBoldEditDefaultValuesProvider } + +function TcxCustomBoldEditDefaultValuesProvider.GetBoldElementTypeInfo: TBoldElementTypeInfo; +begin + if Assigned({DataBinding.}BoldHandle)then + result := {DataBinding.}BoldHandle.StaticBoldType + else + result := nil; +end; + +function TcxCustomBoldEditDefaultValuesProvider.IsDataAvailable: Boolean; +begin + Result := ({DataBinding.}BoldHandle <> nil) {and (DataBinding.BoldHandle.Value <> nil)}; +end; + +function TcxCustomBoldEditDefaultValuesProvider.DefaultAlignment: TAlignment; +var + lElement: TBoldElement; +begin + Result := taLeftJustify; + if IsDataAvailable then + begin + lElement := Follower.Value; + if (lElement is TBAMoment) or (lElement is TBANumeric) then + result := taRightJustify; + end; +end; + +function TcxCustomBoldEditDefaultValuesProvider.DefaultBlobKind: TcxBlobKind; +var + lElement: TBoldElement; +begin + Result := cxEdit.bkNone; + lElement := Follower.Value; + if (lElement is TBABlob) then + begin + if (lElement is TBABlobImageBMP) or (lElement is TBABlobImageJPEG) then + Result := bkGraphic + else + if (lElement is TBATypedBlob) then + begin + Result := bkBlob; +// TcxBlobKind = (bkNone, bkBlob, bkGraphic, bkMemo, bkOle); +{ + MIME decode to see what type it is + (Follower.Value as TBATypedBlob).ContentType +} + end + else + end; +end; + +function TcxCustomBoldEditDefaultValuesProvider.DefaultCanModify: Boolean; +begin +// TODO: 'not Assigned(Follower.Element)' is a temp workaround for cases where Value is nil and hence not allowed to be modified as per TBoldRenderer.DefaultMayModify +// Follower here can be list(lookup) follower instead of single editing follower, so we can't use it for MayModify + Result := not DefaultReadOnly and IsDataAvailable {and (Follower.Controller.MayModify(Follower) or not Assigned(Follower.Element))} {DataBinding.MayModify}; +end; + +function TcxCustomBoldEditDefaultValuesProvider.DefaultIsFloatValue: Boolean; +var + lElement: TBoldElement; +begin + lElement := nil; + if Assigned(Follower) then + lElement := Follower.Value; + result := (lElement is TBAFloat) or (lElement is TBACurrency); +end; + +function TcxCustomBoldEditDefaultValuesProvider.DefaultMaxLength: Integer; +var + lElement: TBoldElement; +begin + result := 0; + if not Assigned(fBoldHandleFollower) then + exit; + lElement := Follower.Value; + if (lElement is TBAString) and Assigned(TBAString(lElement).BoldAttributeRTInfo) then + begin + result := TBAString(lElement).BoldAttributeRTInfo.Length; + if result < 1 then + Result := inherited DefaultMaxLength; + end + else + Result := inherited DefaultMaxLength; +end; + +function TcxCustomBoldEditDefaultValuesProvider.IsBlob: Boolean; +var + lElement: TBoldElement; +begin + result := IsDataAvailable; + if result then + begin + lElement := Follower.Value; + result := (lElement is TBABlob); + end; +end; + +function TcxCustomBoldEditDefaultValuesProvider.IsCurrency: Boolean; +var + lElement: TBoldElement; +begin + result := IsDataAvailable; + if result then + begin + lElement := Follower.Value; + result := (lElement is TBACurrency); + end; +end; + +function TcxCustomBoldEditDefaultValuesProvider.IsValidChar( + AChar: Char): Boolean; +begin + result := inherited IsValidChar(AChar); + if result and (BoldProperties is TBoldVariantFollowerController) then + result := TBoldVariantFollowerController(BoldProperties).ValidateCharacter(AChar, Follower); +end; + +{function TcxCustomBoldEditDefaultValuesProvider.GetFollower: TBoldFollower; +begin + Result := DataBinding.Follower; +end;} + +function TcxCustomBoldEditDefaultValuesProvider.GetFollower: TBoldFollower; +begin + if Assigned(BoldHandleFollower) then + result := BoldHandleFollower.Follower + else + result := nil; +end; +(* +procedure TcxCustomBoldEditDefaultValuesProvider.SetBoldHandle( + const Value: TBoldElementHandle); +begin + self.BoldHandleFollower.BoldHandle := Value; +// TODO: Place subscriptions instead of free notifications +{ + if BoldHandle <> Value then + begin + if BoldHandle <> nil then + FFreeNotifier.RemoveSender(BoldHandle); + BoldHandle := Value; + if BoldHandle <> nil then + FFreeNotifier.AddSender(BoldHandle); + end; +} +end; +*) +procedure TcxCustomBoldEditDefaultValuesProvider.SetBoldProperties( + const Value: TBoldFollowerController); +begin + fBoldProperties := Value; +// TODO: Place subscriptions instead of free notifications +{ + if fBoldProperties <> Value then + begin + if fBoldProperties <> nil then + FFreeNotifier.RemoveSender(fBoldProperties); + fBoldProperties := Value; + if fBoldProperties <> nil then + FFreeNotifier.AddSender(fBoldProperties); + end; +} +end; + +procedure TcxCustomBoldEditDefaultValuesProvider.SetHandleFollower( + const Value: TBoldAbstractHandleFollower); +begin + fBoldHandleFollower := Value; +// TODO: Place subscriptions instead of free notifications +{ + if fBoldHandleFollower <> Value then + begin + if fBoldHandleFollower <> nil then + FFreeNotifier.RemoveSender(fBoldHandleFollower); + fBoldHandleFollower := Value; + if fBoldHandleFollower <> nil then + FFreeNotifier.AddSender(fBoldHandleFollower); + end; +} +end; + +function TcxCustomBoldEditDefaultValuesProvider.GetBoldHandle: TBoldElementHandle; +begin + if Assigned(BoldHandleFollower) then + result := BoldHandleFollower.BoldHandle + else + result := nil; +end; + +constructor TcxCustomBoldEditDefaultValuesProvider.Create( + AOwner: TPersistent); +begin + inherited; + +end; + +destructor TcxCustomBoldEditDefaultValuesProvider.Destroy; +begin + + inherited; +end; + +{ TcxBoldFloatEditDataBinding } + +function TcxBoldFloatEditDataBinding.ValidateTypeConforms( + aExpressionType: TBoldElementTypeInfo): string; +var + lFloatTypeInfo: TBoldAttributeTypeInfo; + lCurrencyTypeInfo: TBoldAttributeTypeInfo; +begin + result := ''; + with (aExpressionType.SystemTypeInfo as TBoldSystemTypeInfo) do + begin + lCurrencyTypeInfo := AttributeTypeInfoByExpressionName['Currency']; // do not localize + lFloatTypeInfo := AttributeTypeInfoByExpressionName['Float']; // do not localize + end; + if not aExpressionType.ConformsTo(lCurrencyTypeInfo) and not aExpressionType.ConformsTo(lFloatTypeInfo) then + result := Format(sPossiblyBadConformance, [aExpressionType.ModelName , lFloatTypeInfo.ModelName]); +end; + +{ TcxBoldDateTimeEditDataBinding } + +function TcxBoldDateTimeEditDataBinding.ValidateTypeConforms( + aExpressionType: TBoldElementTypeInfo): string; +var + lDateTimeTypeInfo: TBoldAttributeTypeInfo; + lDateTypeInfo: TBoldAttributeTypeInfo; +begin + result := ''; + with (aExpressionType.SystemTypeInfo as TBoldSystemTypeInfo) do + begin + lDateTimeTypeInfo := AttributeTypeInfoByExpressionName['DateTime']; // do not localize + lDateTypeInfo := AttributeTypeInfoByExpressionName['Date']; // do not localize + end; + if not (aExpressionType.ConformsTo(lDateTimeTypeInfo) or aExpressionType.ConformsTo(lDateTypeInfo)) then + result := Format(sPossiblyBadConformance, [aExpressionType.ModelName , lDateTimeTypeInfo.ModelName + ' nor ' + lDateTypeInfo.ModelName]); +end; + +{ TcxBoldDateEdit } + +function TcxBoldDateEdit.CanDropDown: Boolean; +begin + result := inherited CanDropDown and DataBinding.IsDataAvailable; +end; + +procedure TcxBoldDateEdit.DoChange; +begin + inherited; + DataBinding.DoChanged; +end; + +procedure TcxBoldDateEdit.DoEnter; +begin + inherited; + DataBinding.DoEnter; +end; + +procedure TcxBoldDateEdit.DoExit; +begin + inherited; + DataBinding.DoExit; +end; + +procedure TcxBoldDateEdit.DoOnChange; +begin + inherited; + if not DataBinding.IsInInternalChange then + PostEditValue; +end; + +procedure TcxBoldDateEdit.DoValidateDisplayValue( + var ADisplayValue: TcxEditValue; var AErrorText: TCaption; + var AError: Boolean); +begin + inherited; + if Assigned(DataBinding) then + DataBinding.ValidateDisplayValue(ADisplayValue, AErrorText, AError); +end; + +{ TcxBoldDateEdit } + +function TcxBoldDateEdit.GetActiveProperties: TcxDateEditProperties; +begin + Result := TcxDateEditProperties(InternalGetActiveProperties); +end; + +function TcxBoldDateEdit.GetDataBinding: TcxBoldDateTimeEditDataBinding; +begin + Result := TcxBoldDateTimeEditDataBinding(FDataBinding); +end; + +class function TcxBoldDateEdit.GetDataBindingClass: TcxEditDataBindingClass; +begin + Result := TcxBoldDateTimeEditDataBinding; +end; + +function TcxBoldDateEdit.GetProperties: TcxDateEditProperties; +begin + Result := TcxDateEditProperties(FProperties); +end; + +class function TcxBoldDateEdit.GetPropertiesClass: TcxCustomEditPropertiesClass; +begin + Result := TcxDateEditProperties; +end; + +procedure TcxBoldDateEdit.HidePopup(Sender: TcxControl; + AReason: TcxEditCloseUpReason); +begin + inherited; +// this will post the value when the calednar popup is closed with ok or enter +// the idea being to post the value even if using bapExit + if AReason = crEnter then + begin + DataBinding.InternalSetValue(EditingValue); + if (DataBinding.BoldFollowerController.ApplyPolicy <> bapDemand) and (DataBinding.Follower.State = bfsDirty) then + DataBinding.Follower.Apply; + end; +end; + +procedure TcxBoldDateEdit.Paint; +begin + inherited Paint; + if DataBinding.ValueOrDefinitionInvalid then + Canvas.FrameRect(Bounds, clRed, 2 - Ord(IsNativeStyle)); +end; + +procedure TcxBoldDateEdit.SetDataBinding( + Value: TcxBoldDateTimeEditDataBinding); +begin + FDataBinding.Assign(Value); +end; + +procedure TcxBoldDateEdit.SetProperties( + Value: TcxDateEditProperties); +begin + FProperties.Assign(Value); +end; + +function TcxBoldDateEdit.ValidateKeyDown(var Key: Word; + Shift: TShiftState): Boolean; +begin + result := DataBinding.IsDataAvailable and inherited ValidateKeyDown(Key, Shift); +end; + +function TcxBoldDateEdit.ValidateKeyPress(var Key: Char): Boolean; +begin + result := DataBinding.MayModify and inherited ValidateKeyPress(Key); + if not result then + Key := #0 + else + begin + if (Key = #13) and (DataBinding.Follower.Controller.ApplyPolicy <> bapDemand) then + begin + DataBinding.Follower.Apply; + SelectAll; + end; + end; +end; + +{ TcxBoldMemo } + +procedure TcxBoldMemo.DoChange; +begin + inherited; + DataBinding.DoChanged; +end; + +procedure TcxBoldMemo.DoEnter; +begin + inherited; + DataBinding.DoEnter; +end; + +procedure TcxBoldMemo.DoExit; +begin + inherited; + DataBinding.DoExit; +end; + +procedure TcxBoldMemo.DoValidateDisplayValue(var ADisplayValue: TcxEditValue; + var AErrorText: TCaption; var AError: Boolean); +begin + inherited; + if Assigned(DataBinding) then + DataBinding.ValidateDisplayValue(ADisplayValue, AErrorText, AError); +end; + +function TcxBoldMemo.GetActiveProperties: TcxMemoProperties; +begin + Result := TcxMemoProperties(InternalGetActiveProperties); +end; + +function TcxBoldMemo.GetDataBinding: TcxBoldTextEditDataBinding; +begin + Result := TcxBoldTextEditDataBinding(FDataBinding); +end; + +class function TcxBoldMemo.GetDataBindingClass: TcxEditDataBindingClass; +begin + result := TcxBoldTextEditDataBinding; +end; + +function TcxBoldMemo.GetProperties: TcxMemoProperties; +begin + Result := TcxMemoProperties(FProperties); +end; + +class function TcxBoldMemo.GetPropertiesClass: TcxCustomEditPropertiesClass; +begin + Result := TcxMemoProperties; +end; + +procedure TcxBoldMemo.Paint; +begin + inherited Paint; + if DataBinding.ValueOrDefinitionInvalid then + Canvas.FrameRect(Bounds, clRed, 2 - Ord(IsNativeStyle)); +end; + +procedure TcxBoldMemo.SetDataBinding(Value: TcxBoldTextEditDataBinding); +begin + FDataBinding.Assign(Value); +end; + +procedure TcxBoldMemo.SetProperties(Value: TcxMemoProperties); +begin + FProperties.Assign(Value); +end; + +{ TcxBoldTimeEdit } + +procedure TcxBoldTimeEdit.DoChange; +begin + inherited; + DataBinding.DoChanged; +end; + +procedure TcxBoldTimeEdit.DoEnter; +begin + inherited; + DataBinding.DoEnter; +end; + +procedure TcxBoldTimeEdit.DoExit; +begin + inherited; + DataBinding.DoExit; +end; + +procedure TcxBoldTimeEdit.DoValidateDisplayValue( + var ADisplayValue: TcxEditValue; var AErrorText: TCaption; + var AError: Boolean); +begin + inherited; + if Assigned(DataBinding) then + DataBinding.ValidateDisplayValue(ADisplayValue, AErrorText, AError); +end; + +function TcxBoldTimeEdit.GetActiveProperties: TcxTimeEditProperties; +begin + Result := TcxTimeEditProperties(InternalGetActiveProperties); +end; + +function TcxBoldTimeEdit.GetDataBinding: TcxBoldTimeEditDataBinding; +begin + Result := TcxBoldTimeEditDataBinding(FDataBinding); +end; + +class function TcxBoldTimeEdit.GetDataBindingClass: TcxEditDataBindingClass; +begin + result := TcxBoldTimeEditDataBinding; +end; + +function TcxBoldTimeEdit.GetProperties: TcxTimeEditProperties; +begin + Result := TcxTimeEditProperties(FProperties); +end; + +class function TcxBoldTimeEdit.GetPropertiesClass: TcxCustomEditPropertiesClass; +begin + Result := TcxTimeEditProperties; +end; + +procedure TcxBoldTimeEdit.Paint; +begin + inherited Paint; + if DataBinding.ValueOrDefinitionInvalid then + Canvas.FrameRect(Bounds, clRed, 2 - Ord(IsNativeStyle)); +end; + +procedure TcxBoldTimeEdit.SetDataBinding( + Value: TcxBoldTimeEditDataBinding); +begin + FDataBinding.Assign(Value); +end; + +procedure TcxBoldTimeEdit.SetProperties(Value: TcxTimeEditProperties); +begin + FProperties.Assign(Value); +end; + +function TcxBoldTimeEdit.ValidateKeyDown(var Key: Word; + Shift: TShiftState): Boolean; +begin + result := DataBinding.IsDataAvailable and inherited ValidateKeyDown(Key, Shift); +end; + +function TcxBoldTimeEdit.ValidateKeyPress(var Key: Char): Boolean; +begin + result := DataBinding.MayModify and inherited ValidateKeyPress(Key); + if not result then + Key := #0 + else + begin + if (Key = #13) and (DataBinding.Follower.Controller.ApplyPolicy <> bapDemand) then + begin + DataBinding.Follower.Apply; + SelectAll; + end; + end; +end; + +{ TcxBoldCurrencyEdit } + +procedure TcxBoldCurrencyEdit.DoEnter; +begin + inherited; + DataBinding.DoEnter; +end; + +procedure TcxBoldCurrencyEdit.DoExit; +begin + inherited; + DataBinding.DoExit; +end; + +procedure TcxBoldCurrencyEdit.DoValidateDisplayValue( + var ADisplayValue: TcxEditValue; var AErrorText: TCaption; + var AError: Boolean); +begin + inherited; + if Assigned(DataBinding) then + DataBinding.ValidateDisplayValue(ADisplayValue, AErrorText, AError); +end; + +function TcxBoldCurrencyEdit.GetActiveProperties: TcxCurrencyEditProperties; +begin + Result := TcxCurrencyEditProperties(InternalGetActiveProperties); +end; + +function TcxBoldCurrencyEdit.GetDataBinding: TcxBoldCurrencyEditDataBinding; +begin + Result := TcxBoldCurrencyEditDataBinding(FDataBinding); +end; + +class function TcxBoldCurrencyEdit.GetDataBindingClass: TcxEditDataBindingClass; +begin + Result := TcxBoldCurrencyEditDataBinding; +end; + +function TcxBoldCurrencyEdit.GetProperties: TcxCurrencyEditProperties; +begin + Result := TcxCurrencyEditProperties(FProperties); +end; + +class function TcxBoldCurrencyEdit.GetPropertiesClass: TcxCustomEditPropertiesClass; +begin + Result := TcxCurrencyEditProperties; +end; + +procedure TcxBoldCurrencyEdit.Paint; +begin + inherited Paint; + if DataBinding.ValueOrDefinitionInvalid then + Canvas.FrameRect(Bounds, clRed, 2 - Ord(IsNativeStyle)); +end; + +procedure TcxBoldCurrencyEdit.SetDataBinding( + Value: TcxBoldCurrencyEditDataBinding); +begin + FDataBinding.Assign(Value); +end; + +procedure TcxBoldCurrencyEdit.SetProperties( + Value: TcxCurrencyEditProperties); +begin + FProperties.Assign(Value); +end; + +procedure TcxBoldCurrencyEdit.DoChange; +begin + inherited; + DataBinding.DoChanged; +end; + +{ TcxBoldTextEditDataBinding } +{ +procedure TcxBoldTextEditDataBinding.InternalSetValue( + const aValue: TcxEditValue); +begin + if VarIsNull(aValue) then + BoldProperties.MayHaveChanged('', Follower) + else + BoldProperties.MayHaveChanged(aValue, Follower); +end; +} +{ TcxBoldMaskEdit } + +procedure TcxBoldMaskEdit.DoEnter; +begin + inherited; + DataBinding.DoEnter; +end; + +procedure TcxBoldMaskEdit.DoExit; +begin + inherited; + DataBinding.DoExit; +end; + +procedure TcxBoldMaskEdit.DoValidateDisplayValue( + var ADisplayValue: TcxEditValue; var AErrorText: TCaption; + var AError: Boolean); +begin + inherited; + if Assigned(DataBinding) then + DataBinding.ValidateDisplayValue(ADisplayValue, AErrorText, AError); +end; + +function TcxBoldMaskEdit.GetActiveProperties: TcxMaskEditProperties; +begin + Result := TcxMaskEditProperties(InternalGetActiveProperties); +end; + +function TcxBoldMaskEdit.GetDataBinding: TcxBoldTextEditDataBinding; +begin + Result := TcxBoldTextEditDataBinding(FDataBinding); +end; + +class function TcxBoldMaskEdit.GetDataBindingClass: TcxEditDataBindingClass; +begin + Result := TcxBoldTextEditDataBinding; +end; + +function TcxBoldMaskEdit.GetProperties: TcxMaskEditProperties; +begin + Result := TcxMaskEditProperties(FProperties); +end; + +class function TcxBoldMaskEdit.GetPropertiesClass: TcxCustomEditPropertiesClass; +begin + Result := TcxMaskEditProperties; +end; + +procedure TcxBoldMaskEdit.Paint; +begin + inherited Paint; + if DataBinding.ValueOrDefinitionInvalid then + Canvas.FrameRect(Bounds, clRed, 2 - Ord(IsNativeStyle)); +end; + +procedure TcxBoldMaskEdit.SetDataBinding( + Value: TcxBoldTextEditDataBinding); +begin + FDataBinding.Assign(Value); +end; + +procedure TcxBoldMaskEdit.SetProperties(Value: TcxMaskEditProperties); +begin + FProperties.Assign(Value); +end; + +function TcxBoldMaskEdit.SupportsSpelling: Boolean; +begin + Result := IsTextInputMode; +end; + +{ TcxBoldCheckBoxEditDataBinding } + + +function TcxBoldCheckBoxEditDataBinding.MayModify: boolean; +begin + result := inherited MayModify; //and (fCurrentElementType is TBoldAttributeTypeInfo) and TBoldAttributeTypeInfo(fCurrentElementType).AttributeClass.InheritsFrom(TBABoolean); +end; + + +function TcxBoldCheckBoxEditDataBinding.ValidateTypeConforms( + aExpressionType: TBoldElementTypeInfo): string; +var + lBooleanTypeInfo: TBoldAttributeTypeInfo; +begin + result := ''; + with (aExpressionType.SystemTypeInfo as TBoldSystemTypeInfo) do + begin + lBooleanTypeInfo := AttributeTypeInfoByExpressionName['Boolean']; // do not localize + end; + if not aExpressionType.ConformsTo(lBooleanTypeInfo) then + result := Format(sPossiblyBadConformance, [aExpressionType.ModelName , lBooleanTypeInfo.ModelName]); +end; + +function TcxBoldCheckBoxEditDataBinding.ImmediatePost: boolean; +begin + result := true; +end; + +{ TcxBoldCheckBox } + +procedure TcxBoldCheckBox.DoChange; +begin + inherited; + DataBinding.DoChanged; +end; + +procedure TcxBoldCheckBox.DoEnter; +begin + inherited; + DataBinding.DoEnter; +end; + +procedure TcxBoldCheckBox.DoExit; +begin + inherited; + DataBinding.DoExit; +end; + +procedure TcxBoldCheckBox.DoValidateDisplayValue( + var ADisplayValue: TcxEditValue; var AErrorText: TCaption; + var AError: Boolean); +begin + inherited; + ADisplayValue := EditingValue; + if Assigned(DataBinding) then + DataBinding.ValidateDisplayValue(ADisplayValue, AErrorText, AError); +end; + +function TcxBoldCheckBox.GetActiveProperties: TcxCheckBoxProperties; +begin + Result := TcxCheckBoxProperties(InternalGetActiveProperties); +end; + +function TcxBoldCheckBox.GetDataBinding: TcxBoldCheckBoxEditDataBinding; +begin + Result := FDataBinding as TcxBoldCheckBoxEditDataBinding; +end; + +class function TcxBoldCheckBox.GetDataBindingClass: TcxEditDataBindingClass; +begin + result := TcxBoldCheckBoxEditDataBinding; +end; + +function TcxBoldCheckBox.GetProperties: TcxCheckBoxProperties; +begin + Result := TcxCheckBoxProperties(FProperties); +end; + +class function TcxBoldCheckBox.GetPropertiesClass: TcxCustomEditPropertiesClass; +begin + Result := TcxCheckBoxProperties; +end; + +procedure TcxBoldCheckBox.Initialize; +begin + inherited; + if IsDesigning and not IsLoading then + begin + _ValidateEdit(self); + end; +end; + +procedure TcxBoldCheckBox.Paint; +begin + inherited; + if DataBinding.ValueOrDefinitionInvalid then + Canvas.FrameRect(Bounds, clRed, 3); +end; + +procedure TcxBoldCheckBox.SetDataBinding( + Value: TcxBoldCheckBoxEditDataBinding); +begin + FDataBinding.Assign(Value); +end; + +procedure TcxBoldCheckBox.SetProperties(Value: TcxCheckBoxProperties); +begin + FProperties.Assign(Value); +end; + +procedure TcxBoldCheckBox.Toggle; +begin + // this is a bit hacky, would be better if we can set it somewhere once + FProperties.ImmediatePost := DataBinding.ImmediatePost; + if CanModify and (DataBinding.MayModify) and Assigned(DataBinding.Follower.Element) then + begin + inherited Toggle; + DataBinding.Follower.Apply; + end; +end; + +{ TcxBoldComboBoxProperties } + +procedure TcxBoldComboBoxProperties._DeleteItem(Index: Integer; + OwningFollower: TBoldFollower); +begin + if not Items.Updating then + Items.BeginUpdate; + Items.Delete(index); +end; + +procedure TcxBoldComboBoxProperties._InsertItem(Index: Integer; Follower: TBoldFollower); +begin + if not Items.Updating then + Items.BeginUpdate; + if Assigned(Follower) then + begin + Follower.EnsureDisplayable; + Items.Insert(Follower.Index, VarToStr(TBoldVariantFollowerController(Follower.Controller).GetAsVariant(Follower))); + end + else + begin + Items.Insert(Index, VarToStr(BoldRowProperties.NilRepresentation)); + end; +end; + +procedure TcxBoldComboBoxProperties._ReplaceItem(Index: Integer; + Follower: TBoldFollower); +begin + if not Items.Updating then + Items.BeginUpdate; + Follower.EnsureDisplayable; + Items.Strings[Index] := VarToStr(TBoldVariantFollowerController(Follower.Controller).GetAsVariant(Follower)); +end; + +procedure TcxBoldComboBoxProperties._RowAfterMakeUptoDate( + Follower: TBoldFollower); +var + index: Integer; + NewValue: String; +begin + index := Follower.index; + if (index > -1) and (index < Items.Count) then + begin + NewValue := VarToStr(TBoldVariantFollowerController(Follower.Controller).GetAsVariant(Follower)); + if NewValue <> Items[index] then + Items[index] := NewValue; + end; +// LookupDataChanged(self); + // forces a redisplay of the edit-area, the windows component might go blank if the active row is removed and then reinserted +// fBoldHandleFollower.Follower.MarkValueOutOfDate; // do we really need this here ? Danny +end; + +procedure TcxBoldComboBoxProperties._AfterMakeUptoDate( + Follower: TBoldFollower); +begin + fBoldRowProperties.AfterMakeUptoDate := _RowAfterMakeUptoDate; + if Items.Updating then + Items.EndUpdate; +end; + +procedure TcxBoldComboBoxProperties._BeforeMakeUptoDate( + Follower: TBoldFollower); +begin + fBoldRowProperties.AfterMakeUptoDate := nil; +end; + +constructor TcxBoldComboBoxProperties.Create(AOwner: TPersistent); +var + lMatchObject: TComponent; +// lBoldAwareViewItem: IBoldAwareViewItem; +begin + inherited; + if aOwner is TComponent then + lMatchObject := aOwner as TComponent + else + lMatchObject := nil; + fBoldRowProperties := TBoldVariantFollowerController.Create(lMatchObject); + fBoldRowProperties.AfterMakeUptoDate := _RowAfterMakeUptoDate; + fBoldRowProperties.OnGetContextType := GetContextForBoldRowProperties; + fBoldListProperties := TBoldComboListController.Create(lMatchObject, fBoldRowProperties); + with fBoldListProperties do + begin + OnAfterInsertItem := _InsertItem; + OnAfterDeleteItem := _DeleteItem; + OnReplaceitem := _ReplaceItem; + BeforeMakeUptoDate := _BeforeMakeUptoDate; + AfterMakeUptoDate := _AfterMakeUptoDate; + end; + fListHandleFollower := TBoldListHandleFollower.Create(Owner, fBoldListProperties); + ImmediatePost := false; + BoldSelectChangeAction := bdcsSetValue; +// if aOwner.GetInterface(IBoldAwareViewItem, lBoldAwareViewItem) then +// BoldSetValueExpression := lBoldAwareViewItem.DataBinding.BoldProperties.Expression; +end; + +destructor TcxBoldComboBoxProperties.Destroy; +begin + FreeAndNil(fListHandleFollower); + FreeAndNil(fBoldListProperties); + FreeAndNil(fBoldRowProperties); + inherited; +end; + +function TcxBoldComboBoxProperties.GetBoldListHandle: TBoldAbstractListHandle; +begin + Result := fListHandleFollower.BoldHandle; +end; + +function TcxBoldComboBoxProperties.GetContextForBoldRowProperties: TBoldElementTypeInfo; +begin + if assigned(BoldLookupListHandle) then + result := BoldLookupListHandle.StaticBoldType + else + result := nil; +end; + +function TcxBoldComboBoxProperties.GetListFollower: TBoldFollower; +begin + Result := fListHandleFollower.Follower; +end; + +function TcxBoldComboBoxProperties.IsDisplayValueValid( + var DisplayValue: TcxEditValue; AEditFocused: Boolean): Boolean; +begin +// result := cxEditVarEquals(DisplayValue, BoldRowProperties.NilRepresentation) or inherited IsDisplayValueValid(DisplayValue, AEditFocused) + if not VarIsNull(BoldRowProperties.NilRepresentation) and cxEditVarEquals(DisplayValue, BoldRowProperties.NilRepresentation) then + result := true + else + result := inherited IsDisplayValueValid(DisplayValue, AEditFocused); +end; + +function TcxBoldComboBoxProperties.IsEditValueValid(var EditValue: TcxEditValue; + AEditFocused: Boolean): Boolean; +begin +// result := inherited IsEditValueValid(EditValue, AEditFocused) or cxEditVarEquals(EditValue, BoldRowProperties.NilRepresentation); + result := inherited IsEditValueValid(EditValue, AEditFocused); + if not result then + result := cxEditVarEquals(EditValue, BoldRowProperties.NilRepresentation); +end; + +procedure TcxBoldComboBoxProperties.SetBoldListHandle( + const Value: TBoldAbstractListHandle); +begin + fListHandleFollower.BoldHandle := value; +end; + +procedure TcxBoldComboBoxProperties.SetBoldListProperties( + const Value: TBoldComboListController); +begin + fBoldListProperties.Assign(Value); +end; + +procedure TcxBoldComboBoxProperties.SetRowProperties( + const Value: TBoldVariantFollowerController); +begin + fBoldRowProperties.Assign(Value); +end; + +procedure TcxBoldComboBoxProperties.SetBoldSelectChangeAction( + Value: TBoldComboSelectChangeAction); +begin +// if (Value = bdcsSetReference) and assigned(BoldHandle) and not BoldHandle.CanSetValue then +// raise EBold.Create(sChangeActionCannotBeSetReference); + fBoldSelectChangeAction := Value; +end; + +procedure TcxBoldComboBoxProperties.SetStoredValue( + aValue: Variant; + aBoldHandle: TBoldElementHandle; + aEdit: TcxCustomEdit; + aFollower: TBoldFollower; + var aDone: boolean); +var + LocalSelectedElement: TBoldElement; + lItemIndex: Integer; +begin + Assert(aEdit is TcxCustomComboBox); + lItemIndex := (aEdit as TcxCustomComboBox).ItemIndex; + if lItemIndex = -1 then + begin + // if DropDownListStyle = lsEditList then we might want to let default handling make modifications + // on other cases we set aDone := true as we're sure that with a fixed list item that isn't in the list won't make changes. + if DropDownListStyle <> lsEditList then + aDone := true; + exit; + end + else + begin + if ((lItemIndex = LookupListFollower.SubFollowerCount-1) and (BoldLookupListProperties.NilElementMode = neAddLast)) + or ((lItemIndex = 0) and (BoldLookupListProperties.NilElementMode = neInsertFirst)) then + begin + LocalSelectedElement := nil + end + else + begin + if (BoldLookupListProperties.NilElementMode = neInsertFirst) then + dec(lItemIndex); + LocalSelectedElement := BoldLookupListHandle.List[lItemIndex]; + end; + end; + InternalComboSetValue(aBoldHandle, aFollower, LocalSelectedElement, BoldSelectChangeAction, BoldSetValueExpression, BoldLookupListHandle, aValue); + aDone := true; +end; + +class function TcxBoldComboBoxProperties.GetContainerClass: TcxContainerClass; +begin + result := inherited GetContainerClass; +// result := TcxBoldComboBox; +end; + +function TcxBoldComboBoxProperties.GetAlwaysPostEditValue: Boolean; +begin + result := false; +end; + +function TcxBoldComboBoxProperties.ValidateComponent( + ComponentValidator: TBoldComponentValidator; + NamePrefix: string): Boolean; +var + lContext: TBoldElementTypeInfo; + lName: string; + lcxBoldEditDataBinding: TcxBoldEditDataBinding; +begin + result := true; + if (Owner is TComponent) and (TComponent(Owner).Name <> '') then + lName := TComponent(Owner).Name + else + if Assigned(Owner) then + lName := Owner.ClassName + else + lName := ClassName; + +// OutPutDebugString(PChar(lName)); + + lContext := GetContextForBoldRowProperties; + if assigned(lContext) then + begin + result := ComponentValidator.ValidateExpressionInContext( + BoldRowProperties.Expression, + lContext, + format('%s %s.BoldRowProperties.Expression', [NamePrefix, lName]), BoldRowProperties.VariableList) and result; // do not localize + + if (BoldSelectChangeAction = bdcsSetValue) and (Owner is TcxCustomEdit) then + begin + lcxBoldEditDataBinding := TcxCustomEditAccess(TcxCustomEdit(Owner)).DataBinding as TcxBoldEditDataBinding; + lContext := lcxBoldEditDataBinding.GetContextType; + result := ComponentValidator.ValidateExpressionInContext( + BoldSetValueExpression, + lContext, + format('%s %s.BoldSetValueExpression', [NamePrefix, lName]), + lcxBoldEditDataBinding.BoldProperties.VariableList) and result; // do not localize + end; + end; +end; + +function TcxBoldComboBoxProperties.BoldElementToEditValue( + aFollower: TBoldFollower; aElement: TBoldElement; aEdit: TcxCustomEdit): variant; +begin + result := BoldRowProperties.GetAsVariant(aFollower); +end; + +procedure TcxBoldComboBoxProperties.Assign(Source: TPersistent); +begin + if Source is TcxBoldComboBoxProperties then + begin + BeginUpdate; + try + BoldLookupListHandle := TcxBoldComboBoxProperties(Source).BoldLookupListHandle; + BoldLookupListProperties := TcxBoldComboBoxProperties(Source).BoldLookupListProperties; + BoldRowProperties := TcxBoldComboBoxProperties(Source).BoldRowProperties; + BoldSetValueExpression := TcxBoldComboBoxProperties(Source).BoldSetValueExpression; + BoldSelectChangeAction := TcxBoldComboBoxProperties(Source).BoldSelectChangeAction; + inherited Assign(Source); + + +// (FIDefaultValuesProvider.GetInstance as TcxCustomBoldEditDefaultValuesProvider).BoldHandleFollower := (TcxBoldComboBoxProperties(Source).FIDefaultValuesProvider.GetInstance as TcxCustomBoldEditDefaultValuesProvider).BoldHandleFollower; +// (FIDefaultValuesProvider.GetInstance as TcxCustomBoldEditDefaultValuesProvider).BoldProperties := (TcxBoldComboBoxProperties(Source).FIDefaultValuesProvider.GetInstance as TcxCustomBoldEditDefaultValuesProvider).BoldProperties; + + TBoldQueueable.DisplayAll; + finally + EndUpdate; + end + end + else + inherited Assign(Source); +end; + +function TcxBoldComboBoxProperties.CanEdit(aBoldHandle: TBoldElementHandle; + aFollower: TBoldFollower): boolean; +begin + result := (LookupListFollower.SubFollowerCount > 0) or (DropDownListStyle = lsEditList); +end; + +procedure TcxBoldComboBoxProperties.SetBoldSetValueExpression( + const Value: TBoldExpression); +begin + fBoldSetValueExpression := Value; + if Owner is TcxCustomEdit and (TcxCustomEdit(Owner).IsDesigning) and not (TcxCustomEdit(Owner).IsLoading) then + begin + _ValidateEdit(TcxCustomEdit(Owner)); + end; +end; + +{ TcxBoldComboBox } + +function TcxBoldComboBox.CanDropDown: Boolean; +var + lElementToAssignTo: TBoldElement; +begin + result := inherited CanDropDown and DataBinding.IsDataAvailable; + if result then + begin + case ActiveProperties.BoldSelectChangeAction of + bdcsSetValue: + begin + if (Assigned(DataBinding.Follower.Element)) then + begin + if trim(ActiveProperties.BoldSetValueExpression) <> '' then + begin + lElementToAssignTo := DataBinding.Follower.Element.EvaluateExpressionAsDirectElement(ActiveProperties.BoldSetValueExpression, TBoldFollowerControllerAccess(DataBinding.Follower.Controller).VariableList); + result := assigned(lElementToAssignTo) and lElementToAssignTo.Mutable; + end; + end + else + result := false; + end; + end; + end; +end; + +procedure TcxBoldComboBox.DoEnter; +begin + inherited; + DataBinding.DoEnter; +end; + +procedure TcxBoldComboBox.DoExit; +begin + inherited; + DataBinding.DoExit; +end; + +procedure TcxBoldComboBox.DoValidateDisplayValue( + var ADisplayValue: TcxEditValue; var AErrorText: TCaption; + var AError: Boolean); +begin + inherited; + if Assigned(DataBinding) then + DataBinding.ValidateDisplayValue(ADisplayValue, AErrorText, AError); +end; + +function TcxBoldComboBox.GetActiveProperties: TcxBoldComboBoxProperties; +begin + Result := TcxBoldComboBoxProperties(InternalGetActiveProperties); +end; + +function TcxBoldComboBox.GetDataBinding: TcxBoldComboBoxEditDataBinding; +begin + Result := TcxBoldComboBoxEditDataBinding(FDataBinding); +end; + +class function TcxBoldComboBox.GetDataBindingClass: TcxEditDataBindingClass; +begin + result := TcxBoldComboBoxEditDataBinding; //TcxBoldTextEditDataBinding; +end; + +function TcxBoldComboBox.GetProperties: TcxBoldComboBoxProperties; +begin + Result := TcxBoldComboBoxProperties(FProperties); +end; + +class function TcxBoldComboBox.GetPropertiesClass: TcxCustomEditPropertiesClass; +begin + result := TcxBoldComboBoxProperties; +end; + +procedure TcxBoldComboBox.Paint; +begin + inherited Paint; + if DataBinding.ValueOrDefinitionInvalid then + Canvas.FrameRect(Bounds, clRed, 2 - Ord(IsNativeStyle)); +end; + +procedure TcxBoldComboBox.SetDataBinding( + Value: TcxBoldComboBoxEditDataBinding); +begin + FDataBinding.Assign(Value); +end; + +procedure TcxBoldComboBox.SetProperties(Value: TcxBoldComboBoxProperties); +begin + FProperties.Assign(Value); +end; + +function TcxBoldComboBox.SupportsSpelling: Boolean; +begin + Result := IsTextInputMode; +end; +{ +function TcxBoldComboBox.ValidateComponent( + ComponentValidator: TBoldComponentValidator; + NamePrefix: string): Boolean; +begin + result := DataBinding.ValidateComponent(ComponentValidator, NamePrefix); + result := GetActiveProperties.ValidateComponent(ComponentValidator, NamePrefix) and result; +end; +} +{ TcxBoldSpinEdit } + +procedure TcxBoldSpinEdit.DoEnter; +begin + inherited; + DataBinding.DoEnter; +end; + +procedure TcxBoldSpinEdit.DoExit; +begin + inherited; + DataBinding.DoExit; +end; + +procedure TcxBoldSpinEdit.DoValidateDisplayValue( + var ADisplayValue: TcxEditValue; var AErrorText: TCaption; + var AError: Boolean); +begin + inherited; + if Assigned(DataBinding) then + DataBinding.ValidateDisplayValue(ADisplayValue, AErrorText, AError); +end; + +function TcxBoldSpinEdit.GetActiveProperties: TcxSpinEditProperties; +begin + Result := TcxSpinEditProperties(InternalGetActiveProperties); +end; + +function TcxBoldSpinEdit.GetDataBinding: TcxBoldNumericEditDataBinding; +begin + Result := TcxBoldNumericEditDataBinding(FDataBinding); +end; + +class function TcxBoldSpinEdit.GetDataBindingClass: TcxEditDataBindingClass; +begin + Result := TcxBoldNumericEditDataBinding; +end; + +function TcxBoldSpinEdit.GetProperties: TcxSpinEditProperties; +begin + Result := TcxSpinEditProperties(FProperties); +end; + +class function TcxBoldSpinEdit.GetPropertiesClass: TcxCustomEditPropertiesClass; +begin + Result := TcxSpinEditProperties; +end; + +procedure TcxBoldSpinEdit.Paint; +begin + inherited Paint; + if DataBinding.ValueOrDefinitionInvalid then + Canvas.FrameRect(Bounds, clRed, 2 - Ord(IsNativeStyle)); +end; + +procedure TcxBoldSpinEdit.SetDataBinding( + Value: TcxBoldNumericEditDataBinding); +begin + FDataBinding.Assign(Value); +end; + +procedure TcxBoldSpinEdit.SetProperties(Value: TcxSpinEditProperties); +begin + FProperties.Assign(Value); +end; + +{ TcxBoldButtonEdit } + +procedure TcxBoldButtonEdit.DoEnter; +begin + inherited; + DataBinding.DoEnter; +end; + +procedure TcxBoldButtonEdit.DoExit; +begin + inherited; + DataBinding.DoExit; +end; + +procedure TcxBoldButtonEdit.DoValidateDisplayValue( + var ADisplayValue: TcxEditValue; var AErrorText: TCaption; + var AError: Boolean); +begin + inherited; + if Assigned(DataBinding) then + DataBinding.ValidateDisplayValue(ADisplayValue, AErrorText, AError); +end; + +function TcxBoldButtonEdit.GetActiveProperties: TcxButtonEditProperties; +begin + Result := TcxButtonEditProperties(InternalGetActiveProperties); +end; + +function TcxBoldButtonEdit.GetDataBinding: TcxBoldTextEditDataBinding; +begin + Result := TcxBoldTextEditDataBinding(FDataBinding); +end; + +class function TcxBoldButtonEdit.GetDataBindingClass: TcxEditDataBindingClass; +begin + Result := TcxBoldTextEditDataBinding; +end; + +function TcxBoldButtonEdit.GetProperties: TcxButtonEditProperties; +begin + Result := TcxButtonEditProperties(FProperties); +end; + +class function TcxBoldButtonEdit.GetPropertiesClass: TcxCustomEditPropertiesClass; +begin + Result := TcxButtonEditProperties; +end; + +procedure TcxBoldButtonEdit.Paint; +begin + inherited Paint; + if DataBinding.ValueOrDefinitionInvalid then + Canvas.FrameRect(Bounds, clRed, 2 - Ord(IsNativeStyle)); +end; + +procedure TcxBoldButtonEdit.SetDataBinding( + Value: TcxBoldTextEditDataBinding); +begin + FDataBinding.Assign(Value); +end; + +procedure TcxBoldButtonEdit.SetProperties(Value: TcxButtonEditProperties); +begin + FProperties.Assign(Value); +end; + +{ TcxBoldHyperLinkEdit } + +procedure TcxBoldHyperLinkEdit.DoEnter; +begin + inherited; + DataBinding.DoEnter; +end; + +procedure TcxBoldHyperLinkEdit.DoExit; +begin + inherited; + DataBinding.DoExit; +end; + +procedure TcxBoldHyperLinkEdit.DoValidateDisplayValue( + var ADisplayValue: TcxEditValue; var AErrorText: TCaption; + var AError: Boolean); +begin + inherited; + if Assigned(DataBinding) then + DataBinding.ValidateDisplayValue(ADisplayValue, AErrorText, AError); +end; + +function TcxBoldHyperLinkEdit.GetActiveProperties: TcxHyperLinkEditProperties; +begin + Result := TcxHyperLinkEditProperties(InternalGetActiveProperties); +end; + +function TcxBoldHyperLinkEdit.GetDataBinding: TcxBoldTextEditDataBinding; +begin + Result := TcxBoldTextEditDataBinding(FDataBinding); +end; + +class function TcxBoldHyperLinkEdit.GetDataBindingClass: TcxEditDataBindingClass; +begin + Result := TcxBoldTextEditDataBinding; +end; + +function TcxBoldHyperLinkEdit.GetProperties: TcxHyperLinkEditProperties; +begin + Result := TcxHyperLinkEditProperties(FProperties); +end; + +class function TcxBoldHyperLinkEdit.GetPropertiesClass: TcxCustomEditPropertiesClass; +begin + Result := TcxHyperLinkEditProperties; +end; + +procedure TcxBoldHyperLinkEdit.Paint; +begin + inherited Paint; + if DataBinding.ValueOrDefinitionInvalid then + Canvas.FrameRect(Bounds, clRed, 2 - Ord(IsNativeStyle)); +end; + +procedure TcxBoldHyperLinkEdit.SetDataBinding( + Value: TcxBoldTextEditDataBinding); +begin + FDataBinding.Assign(Value); +end; + +procedure TcxBoldHyperLinkEdit.SetProperties( + Value: TcxHyperLinkEditProperties); +begin + FProperties.Assign(Value); +end; + +{ TcxBoldProgressBar } + +function TcxBoldProgressBar.GetActiveProperties: TcxProgressBarProperties; +begin + Result := TcxProgressBarProperties(InternalGetActiveProperties); +end; + +function TcxBoldProgressBar.GetDataBinding: TcxBoldNumericEditDataBinding; +begin + Result := TcxBoldNumericEditDataBinding(FDataBinding); +end; + +class function TcxBoldProgressBar.GetDataBindingClass: TcxEditDataBindingClass; +begin + Result := TcxBoldNumericEditDataBinding; +end; + +function TcxBoldProgressBar.GetProperties: TcxProgressBarProperties; +begin + Result := TcxProgressBarProperties(FProperties); +end; + +class function TcxBoldProgressBar.GetPropertiesClass: TcxCustomEditPropertiesClass; +begin + Result := TcxProgressBarProperties; +end; + +procedure TcxBoldProgressBar.Initialize; +begin + inherited; + if IsDesigning and not IsLoading then + begin + _ValidateEdit(self); + end; +end; + +procedure TcxBoldProgressBar.Paint; +begin + inherited Paint; + if DataBinding.ValueOrDefinitionInvalid then + Canvas.FrameRect(Bounds, clRed, 2 - Ord(IsNativeStyle)); +end; + +procedure TcxBoldProgressBar.SetDataBinding( + Value: TcxBoldNumericEditDataBinding); +begin + FDataBinding.Assign(Value); +end; + +procedure TcxBoldProgressBar.SetProperties( + Value: TcxProgressBarProperties); +begin + FProperties.Assign(Value); +end; + +{ TcxBarBoldEditItem } + +procedure TcxBarBoldEditItem._AfterMakeUptoDate(Follower: TBoldFollower); +var + lValue: variant;//string; + lElement: TBoldElement; + lIcxBoldEditProperties: IcxBoldEditProperties; +begin +// lValue := BoldProperties.GetAsVariant(Follower); + if fInternalChange = 0 then + begin + lElement := Follower.Value; + if Supports(Properties, IcxBoldEditProperties, lIcxBoldEditProperties) then + begin +// if Assigned(lElement) then + lValue := lIcxBoldEditProperties.BoldElementToEditValue(Follower, lElement, nil); + end + else + begin + lValue := TBoldVariantFollowerController(Follower.Controller).GetAsVariant(Follower); + if VarIsEmpty(lValue) then + lValue := Null; + end; + + inc(fInternalChange); + try + if not cxEditVarEquals(EditValue, lValue) then + EditValue := lValue; + finally + dec(fInternalChange); + end; + end; +end; + +{ +function TcxBarBoldEditItem.CanEdit: Boolean; +begin + result := inherited CanEdit; +end; +} +{ +procedure TcxBarBoldEditItem.DoEditValueChanged(Sender: TObject); +begin + inherited; + +end; +} +constructor TcxBarBoldEditItem.Create(AOwner: TComponent); +begin + inherited; + fBoldProperties := TBoldVariantFollowerController.Create(Self); + fBoldProperties.AfterMakeUptoDate := _AfterMakeUptoDate; + fBoldProperties.OnGetContextType := GetContextType; + fBoldHandleFollower := TBoldElementHandleFollower.Create(Owner, fBoldProperties); +// self.OnChange := EditValueChanged; +// self.OnEnter := EditEnter; + self.OnExit := EditExit; +end; + +destructor TcxBarBoldEditItem.Destroy; +begin + case BoldProperties.ApplyPolicy of + bapChange, bapExit: try + Follower.Apply; + except + Follower.DiscardChange; + end; + bapDemand: Follower.DiscardChange; + end; + FreeAndNil(fBoldHandleFollower); + FreeAndNil(fBoldProperties); + inherited; +end; + +function TcxBarBoldEditItem.GetBoldHandle: TBoldElementHandle; +begin + Result := fBoldHandleFollower.BoldHandle; +end; + +function TcxBarBoldEditItem.GetContextType: TBoldElementTypeInfo; +begin + if assigned(BoldHandle) then + result := BoldHandle.StaticBoldType + else + result := nil; +end; + +function TcxBarBoldEditItem.GetFollower: TBoldFollower; +begin + Result := fBoldHandleFollower.Follower; +end; + +procedure TcxBarBoldEditItem.SetBoldHandle( + const Value: TBoldElementHandle); +begin + fBoldHandleFollower.BoldHandle := value; +end; + +procedure TcxBarBoldEditItem.SetBoldProperties( + const Value: TBoldVariantFollowerController); +begin + fBoldProperties.Assign(Value); +end; + +procedure TcxBarBoldEditItem.EditValueChanged(Sender: TObject); +var + lIcxBoldEditProperties: IcxBoldEditProperties; + lDone: Boolean; + lEdit: TcxCustomEdit; +begin + if fInternalChange = 0 then + begin + lDone := false; + lEdit := Sender as TcxCustomEdit; + if Supports(Properties, IcxBoldEditProperties, lIcxBoldEditProperties) then + begin + lIcxBoldEditProperties.SetStoredValue(Null, BoldHandle, lEdit, Follower, lDone); + end; + if not lDone then + begin + if VarIsNull(EditValue) then + BoldProperties.MayHaveChanged('', Follower) + else + BoldProperties.MayHaveChanged(EditValue, Follower); + end; + TBoldQueueable.DisplayAll; + end; +end; + +procedure TcxBarBoldEditItem.EditExit(Sender: TObject); +begin + if (Follower.Controller.ApplyPolicy <> bapDemand) then + Follower.Apply; +end; + +class function TcxCustomBoldTextEditProperties.GetContainerClass: TcxContainerClass; +begin + result := inherited GetContainerClass; +// result := TcxBoldTextEdit; +end; + +procedure TcxBarBoldEditItem.DoEnter; +begin + inherited; + +end; + +procedure TcxBarBoldEditItem.DoExit; +begin + inherited; +end; + +function TcxBarBoldEditItem.GetControlClass( + AIsVertical: Boolean): TdxBarItemControlClass; +begin + if AIsVertical then + Result := inherited GetControlClass(AIsVertical) + else + Result := TcxBarBoldEditItemControl; +end; + +procedure TcxBarBoldEditItem.KeyPress(var Key: Char); +begin + inherited; + if (not Follower.Controller.MayModify(Follower)) or (not BoldProperties.ValidateCharacter(Key, Follower)) then + Key := #0; +end; + +{ TcxBarBoldEditItemControl } +{ +procedure TcxBarBoldEditItemControl.DoPostEditValue(Sender: TObject); +begin + inherited; + +end; + +procedure TcxBarBoldEditItemControl.DoValidate(Sender: TObject; + var DisplayValue: TcxEditValue; var ErrorText: TCaption; + var Error: Boolean); +begin + inherited; +// Error := Error or not (Item as TcxBarBoldEditItem).BoldProperties.ValidateString(DisplayValue, (Item as TcxBarBoldEditItem).Follower); +// if Error then +// Errortext := '+' + Errortext; +// (Item as TcxBarBoldEditItem).EditValueChanged(sender as TcxCustomEdit); +end; +} +//type +// TcxCustomDropDownEditPropertiesAccess = Class(TcxCustomDropDownEditProperties); + +procedure TcxBarBoldEditItemControl.RestoreDisplayValue; +begin + inherited; +// if Properties is TcxCustomDropDownEditProperties then +// TcxCustomDropDownEditPropertiesAccess(Properties).AlwaysPostEditValue := true; + Properties.ImmediatePost := true; +end; + +procedure TcxBarBoldEditItemControl.StoreDisplayValue; +begin + inherited; + (Item as TcxBarBoldEditItem).EditValueChanged(Edit); +// if Edit is TcxCustomComboBox then +end; + +function TcxCustomBoldTextEditProperties.ValidateComponent( + ComponentValidator: TBoldComponentValidator; + NamePrefix: string): Boolean; +var + lContext: TBoldElementTypeInfo; + lName: string; +begin + result := true; + if (Owner is TComponent) and (TComponent(Owner).Name <> '') then + lName := TComponent(Owner).Name + else + lName := ClassName; + if Assigned(BoldLookupListHandle) then + begin + lContext := GetContextForBoldRowProperties; + if not Assigned(lContext) then + BoldLog.LogFmt(sNoContext, [lName]) + else + begin + result := ComponentValidator.ValidateExpressionInContext( + BoldRowProperties.Expression, + lContext, + format('%s %s.BoldRowProperties.Expression', [NamePrefix, lName]), + BoldRowProperties.VariableList ) and result; // do not localize + end; + end; +end; + +{ TcxBoldDateNavigator } + +{$IFDEF DevExScheduler} + +procedure TcxBoldDateNavigator._AfterMakeUptoDate(Follower: TBoldFollower); +var + lValue: variant;//string; + lElement: TBoldElement; + i,j: integer; + lBoldComponentValidator: TBoldComponentValidator; +begin + if IsDesigning then + begin + lBoldComponentValidator := TBoldComponentValidator.Create; + try + ValidateComponent(lBoldComponentValidator, Name); + finally + lBoldComponentValidator.free; + end; + exit; + end; + lElement := Follower.Value; + if Assigned(lElement) then + lValue := lElement.AsVariant + else + lValue := Null; + InnerDateNavigator.EventOperations.ReadOnly := not Assigned(lElement); + inc(fInternalChange); + try + if Follower = StartFollower then + begin + if VarIsNull(lValue) or (lValue = 0) then + begin + if (self.Date <> NullDate) then + begin + SelectedDays.Clear; + DateNavigator.Refresh; + end + end + else + begin + if lValue <> self.Date then + self.Date := lValue; + end; + end + else + begin + if not VarIsNull(lValue) and (lValue <> 0) and (lValue <> RealLastDate) and (self.date <> NullDate) then + begin + j := Trunc(self.date); + SelectedDays.Clear; + for i := j to lValue do + SelectedDays.Add(i); + DateNavigator.Refresh; + end; + end; + finally + dec(fInternalChange); + end; +end; + +constructor TcxBoldDateNavigator.Create(AOwner: TComponent); +begin + inherited; +// fBoldProperties := TBoldVariantFollowerController.Create(Self); +// fBoldProperties.AfterMakeUptoDate := _AfterMakeUptoDate; +// fBoldProperties.OnGetContextType := GetContextType; + + fBoldStartProperties := TBoldVariantFollowerController.Create(Self); + fBoldStartProperties.AfterMakeUptoDate := _AfterMakeUptoDate; + fBoldStartProperties.OnGetContextType := GetStartContextType; + + fBoldEndProperties := TBoldVariantFollowerController.Create(Self); + fBoldEndProperties.AfterMakeUptoDate := _AfterMakeUptoDate; + fBoldEndProperties.OnGetContextType := GetEndContextType; + + fBoldStartHandleFollower := TBoldElementHandleFollower.Create(AOwner, fBoldStartProperties); + fBoldEndHandleFollower := TBoldElementHandleFollower.Create(AOwner, fBoldEndProperties); + + if IsDesigning and not isLoading then + ValidateSelf; +end; + +procedure TcxBoldDateNavigator.DateNavigatorSelectionChanged; +begin + inherited; + if (fInternalChange = 0) {and Assigned(Follower) and Follower.Controller.MayModify(Follower)} then + begin + if Assigned(StartFollower) and StartFollower.Controller.MayModify(StartFollower) then + BoldStartProperties.MayHaveChanged(self.date, StartFollower); + if Assigned(EndFollower) and EndFollower.Controller.MayModify(EndFollower) then + BoldEndProperties.MayHaveChanged(self.RealLastDate, EndFollower); + end; +end; +{ +procedure TcxBoldDateNavigator.DoSelectionChangedEvent; +begin + inherited; + BoldProperties.MayHaveChanged(DateToStr(self.date), Follower); +end; +} +destructor TcxBoldDateNavigator.Destroy; +begin + case BoldStartProperties.ApplyPolicy of + bapChange, bapExit: try + StartFollower.Apply; + except + StartFollower.DiscardChange; + end; + bapDemand: StartFollower.DiscardChange; + end; + case BoldEndProperties.ApplyPolicy of + bapChange, bapExit: try + EndFollower.Apply; + except + EndFollower.DiscardChange; + end; + bapDemand: EndFollower.DiscardChange; + end; + FreeAndNil(fBoldStartHandleFollower); + FreeAndNil(fBoldEndHandleFollower); + FreeAndNil(fBoldStartProperties); + FreeAndNil(fBoldEndProperties); + inherited; +end; + + +function TcxBoldDateNavigator.GetBoldEndHandle: TBoldElementHandle; +begin + Result := fBoldEndHandleFollower.BoldHandle; +end; + +function TcxBoldDateNavigator.GetEndContextType: TBoldElementTypeInfo; +begin + if assigned(BoldEndHandle) then + result := BoldEndHandle.StaticBoldType + else + result := nil; +end; + +function TcxBoldDateNavigator.GetEndFollower: TBoldFollower; +begin + result := fBoldEndHandleFollower.Follower; +end; + +function TcxBoldDateNavigator.GetBoldStartHandle: TBoldElementHandle; +begin + Result := fBoldStartHandleFollower.BoldHandle; +end; + +function TcxBoldDateNavigator.GetStartContextType: TBoldElementTypeInfo; +begin + if assigned(BoldStartHandle) then + result := BoldStartHandle.StaticBoldType + else + result := nil; +end; + +function TcxBoldDateNavigator.GetStartFollower: TBoldFollower; +begin + result := fBoldStartHandleFollower.Follower; +end; + +{procedure TcxBoldDateNavigator.SetBoldProperties( + const Value: TBoldVariantFollowerController); +begin + fBoldProperties.Assign(Value); +end;} + +procedure TcxBoldDateNavigator.SetBoldEndHandle( + const Value: TBoldElementHandle); +begin + fBoldEndHandleFollower.BoldHandle := value; +end; + +procedure TcxBoldDateNavigator.SetBoldEndProperties( + const Value: TBoldVariantFollowerController); +begin + fBoldEndProperties.Assign(Value); +end; + +procedure TcxBoldDateNavigator.SetBoldStartHandle( + const Value: TBoldElementHandle); +begin + fBoldStartHandleFollower.BoldHandle := value; +end; + +procedure TcxBoldDateNavigator.SetBoldStartProperties( + const Value: TBoldVariantFollowerController); +begin + fBoldStartProperties.Assign(Value); +end; + +type TcxInnerDateNavigatorAccess = class(TcxInnerDateNavigator); + +function TcxBoldDateNavigator.ValidateComponent( + ComponentValidator: TBoldComponentValidator; + NamePrefix: string): Boolean; +var + lContext: TBoldElementTypeInfo; + lExpressionType: TBoldElementTypeInfo; + lDateTimeTypeInfo: TBoldAttributeTypeInfo; + lDateTypeInfo: TBoldAttributeTypeInfo; +// s: string; +begin +// OutPutDebugString(PChar('TcxBoldDateNavigator.ValidateComponent start')); + lContext := GetStartContextType; + result := Assigned(lContext); + if not result then + begin + BoldLog.LogFmt(sNoContext, [Name]) + end + else + begin + with (lContext.SystemTypeInfo as TBoldSystemTypeInfo) do + begin + lDateTimeTypeInfo := AttributeTypeInfoByExpressionName['DateTime']; // do not localize + lDateTypeInfo := AttributeTypeInfoByExpressionName['Date']; // do not localize + end; + result := ComponentValidator.ValidateExpressionInContext( + TBoldFollowerControllerAccess(BoldStartProperties).Expression, + lContext, + format('%s %s.Expression', [NamePrefix, Name]), + BoldStartProperties.VariableList); // do not localize + + if result then + begin + lExpressionType := lContext.Evaluator.ExpressionType(TBoldFollowerControllerAccess(BoldStartProperties).Expression, lContext, false, TBoldFollowerControllerAccess(BoldStartProperties).VariableList); + if not (lExpressionType.ConformsTo(lDateTimeTypeInfo) or lExpressionType.ConformsTo(lDateTypeInfo)) then + begin + result := false; + BoldLog.LogFmt(sPossiblyBadConformance, [lExpressionType.ModelName , lDateTimeTypeInfo.ModelName + ' nor ' + lDateTypeInfo.ModelName]); + end; + end; + + lContext := GetEndContextType; + if Assigned(lContext) then + begin + result := ComponentValidator.ValidateExpressionInContext( + TBoldFollowerControllerAccess(BoldEndProperties).Expression, + lContext, + format('%s %s.Expression', [NamePrefix, Name]), + BoldEndProperties.VariableList) and result; // do not localize + + if result then + begin + lExpressionType := lContext.Evaluator.ExpressionType(TBoldFollowerControllerAccess(BoldEndProperties).Expression, lContext, false, TBoldFollowerControllerAccess(BoldEndProperties).VariableList); + if not (lExpressionType.ConformsTo(lDateTimeTypeInfo) or lExpressionType.ConformsTo(lDateTypeInfo)) then + begin + result := false; + BoldLog.LogFmt(sPossiblyBadConformance, [lExpressionType.ModelName , lDateTimeTypeInfo.ModelName + ' nor ' + lDateTypeInfo.ModelName]); + end; + end; + end; + end; +// fValueOrDefinitionInvalid := not result; +// s := 'TcxBoldDateNavigator.ValidateComponent:' + BoolToStr(result, true); +// OutPutDebugString(PChar(S)); +end; + +procedure TcxBoldDateNavigator.Loaded; +begin + inherited; + if IsDesigning then + ValidateSelf; +end; + +procedure TcxBoldDateNavigator.ValidateSelf; +var + lBoldComponentValidator: TBoldComponentValidator; +begin + if IsDesigning then + begin + lBoldComponentValidator := TBoldComponentValidator.Create; + try + ValidateComponent(lBoldComponentValidator, Name); + finally + lBoldComponentValidator.free; + end; + end; +end; + +{$ENDIF} + +{ TcxBoldLabel } + +function TcxBoldLabel.GetActiveProperties: TcxLabelProperties; +begin + Result := TcxLabelProperties(InternalGetActiveProperties); +end; + +function TcxBoldLabel.GetDataBinding: TcxBoldTextEditDataBinding; +begin + Result := FDataBinding as TcxBoldTextEditDataBinding; +end; + +class function TcxBoldLabel.GetDataBindingClass: TcxEditDataBindingClass; +begin + Result := TcxBoldTextEditDataBinding; +end; + +function TcxBoldLabel.GetProperties: TcxLabelProperties; +begin + Result := TcxLabelProperties(FProperties); +end; + +class function TcxBoldLabel.GetPropertiesClass: TcxCustomEditPropertiesClass; +begin + Result := TcxLabelProperties; +end; + +procedure TcxBoldLabel.Initialize; +begin + inherited Initialize; +// AutoSize := False; + if IsDesigning and not IsLoading then + begin + _ValidateEdit(self); + end; +end; + +procedure TcxBoldLabel.Paint; +begin + inherited; + if DataBinding.ValueOrDefinitionInvalid then +// ViewInfo.TextColor := clRed; + Canvas.FrameRect(Bounds, clRed, 3); +end; + +procedure TcxBoldLabel.SetDataBinding(Value: TcxBoldTextEditDataBinding); +begin + FDataBinding.Assign(Value); +end; + +procedure TcxBoldLabel.SetEditAutoSize(Value: Boolean); +begin + inherited; + +end; + +procedure TcxBoldLabel.SetProperties(Value: TcxLabelProperties); +begin + FProperties.Assign(Value); +end; + +{ TcxBoldImage } + +function TcxBoldImage.GetActiveProperties: TcxImageProperties; +begin + Result := TcxImageProperties(InternalGetActiveProperties); +end; + +function TcxBoldImage.GetDataBinding: TcxBoldBlobEditDataBinding; +begin + Result := FDataBinding as TcxBoldBlobEditDataBinding; +end; + +class function TcxBoldImage.GetDataBindingClass: TcxEditDataBindingClass; +begin + result := TcxBoldBlobEditDataBinding; +end; + +function TcxBoldImage.GetProperties: TcxImageProperties; +begin + Result := TcxImageProperties(FProperties); +end; + +class function TcxBoldImage.GetPropertiesClass: TcxCustomEditPropertiesClass; +begin + Result := TcxImageProperties; +end; + +procedure TcxBoldImage.Initialize; +begin + inherited; + if IsDesigning and not IsLoading then + begin + _ValidateEdit(self); + end; +end; + +procedure TcxBoldImage.Paint; +begin + inherited Paint; + if DataBinding.ValueOrDefinitionInvalid then + Canvas.FrameRect(Bounds, clRed, 2 - Ord(IsNativeStyle)); +end; + +procedure TcxBoldImage.SetDataBinding(Value: TcxBoldBlobEditDataBinding); +begin + FDataBinding.Assign(Value); +end; + +procedure TcxBoldImage.SetProperties(Value: TcxImageProperties); +begin + FProperties.Assign(Value); +end; + +{ TcxBoldRichEdit } + +procedure TcxBoldRichEdit.DoValidateDisplayValue( + var ADisplayValue: TcxEditValue; var AErrorText: TCaption; + var AError: Boolean); +begin + inherited; + if Assigned(DataBinding) then + DataBinding.ValidateDisplayValue(ADisplayValue, AErrorText, AError); +end; + +procedure TcxBoldRichEdit.EditingChanged; +begin + inherited; + +end; + +function TcxBoldRichEdit.GetActiveProperties: TcxRichEditProperties; +begin + Result := TcxRichEditProperties(InternalGetActiveProperties); +end; + +function TcxBoldRichEdit.GetDataBinding: TcxBoldTextEditDataBinding; +begin + Result := FDataBinding as TcxBoldTextEditDataBinding; +end; + +class function TcxBoldRichEdit.GetDataBindingClass: TcxEditDataBindingClass; +begin + Result := TcxBoldTextEditDataBinding; +end; + +function TcxBoldRichEdit.GetProperties: TcxRichEditProperties; +begin + Result := TcxRichEditProperties(FProperties); +end; + +class function TcxBoldRichEdit.GetPropertiesClass: TcxCustomEditPropertiesClass; +begin + Result := TcxRichEditProperties; +end; + +procedure TcxBoldRichEdit.Paint; +begin + inherited Paint; + if DataBinding.ValueOrDefinitionInvalid then + Canvas.FrameRect(Bounds, clRed, 2 - Ord(IsNativeStyle)); +end; + +function TcxBoldRichEdit.RealReadOnly: Boolean; +begin + Result := inherited RealReadOnly or not DataBinding.Editing; +end; + +procedure TcxBoldRichEdit.SetDataBinding( + Value: TcxBoldTextEditDataBinding); +begin + FDataBinding.Assign(Value); +end; + +procedure TcxBoldRichEdit.SetProperties(Value: TcxRichEditProperties); +begin + FProperties.Assign(Value); +end; + +{ TcxBoldComboBoxEditDataBinding } + +constructor TcxBoldComboBoxEditDataBinding.Create(AEdit: TcxCustomEdit); +begin + inherited; + Assert(TcxCustomEditAccess(AEdit).Properties is TcxBoldComboBoxProperties); + fBoldHandleFollower.PrioritizedQueuable := TcxBoldComboBoxProperties(TcxCustomEditAccess(AEdit).Properties).fListHandleFollower; + fBoldHandleFollower.StronglyDependedOfPrioritized := true; +end; + +function TcxBoldComboBoxEditDataBinding.GetModified: Boolean; +var +// lcxCustomTextEditAccess: TcxCustomTextEditAccess; + lItemIndex: integer; + lCount: integer; + lOriginalElement, lNewElement: TBoldElement; + lcxBoldComboBox: TcxBoldComboBox; +begin + if not IsDataAvailable or FEdit.ActiveProperties.ReadOnly or (TcxCustomTextEditAccess(Edit).ILookupData.ActiveControl = nil) then + begin + result := false; + exit; + end; + result := not cxEditVarEquals(Edit.EditValue, StoredValue); //not ((VarType(Edit.EditValue) = VarType(StoredValue)) and VarSameValue(StoredValue, Edit.EditValue)); + if result and ((VarIsNull(Edit.EditValue) and VarIsStr(StoredValue) and (StoredValue = '')) + or (VarIsNull(StoredValue) and VarIsStr(Edit.EditValue) and (Edit.EditValue = ''))) then + result := false; +// if not result then + begin + lcxBoldComboBox := Edit as TcxBoldComboBox; + lOriginalElement := lcxBoldComboBox.DataBinding.Follower.Value; + if lOriginalElement is TBoldObjectReference then + lOriginalElement := TBoldObjectReference(lOriginalElement).BoldObject; +// lItemIndex := TcxCustomTextEditAccess(Edit).ItemIndex; + lCount := lcxBoldComboBox.ActiveProperties.LookupListFollower.SubFollowerCount-1; + lItemIndex := TcxCustomEditListBox(TcxCustomTextEditAccess(Edit).ILookupData.ActiveControl).itemIndex; + + if ((lItemIndex = lCount) and (lcxBoldComboBox.ActiveProperties.BoldLookupListProperties.NilElementMode = neAddLast)) + or ((lItemIndex = 0) and (lcxBoldComboBox.ActiveProperties.BoldLookupListProperties.NilElementMode = neInsertFirst)) + then + begin + Result := lOriginalElement <> nil; + exit; + end; + if lItemIndex <> -1 then + begin + // lcxBoldComboBox.ActiveProperties.BoldLookupListProperties.ListIndexToIndex(lItemIndex); + if (lcxBoldComboBox.ActiveProperties.BoldLookupListProperties.NilElementMode = neInsertFirst) then + Dec(lItemIndex); + lNewElement := lcxBoldComboBox.ActiveProperties.BoldLookupListHandle.List[lItemIndex]; + Result := lOriginalElement <> lNewElement; + end + else + begin + if not ((lcxBoldComboBox.Properties.BoldSelectChangeAction in [bdcsSetValue,bdscSetText]) and (lOriginalElement is TBoldAttribute)) then + result := false; + end; + end; +end; + +function TcxBoldComboBoxEditDataBinding.ImmediatePost: boolean; +begin + result := true; +end; + +{ TcxBoldIntegerEditDataBinding } + +function TcxBoldNumericEditDataBinding.ValidateTypeConforms( + aExpressionType: TBoldElementTypeInfo): string; +var + lNumericTypeInfo: TBoldAttributeTypeInfo; +begin + result := ''; + with (aExpressionType.SystemTypeInfo as TBoldSystemTypeInfo) do + begin + lNumericTypeInfo := AttributeTypeInfoByExpressionName['Numeric']; // do not localize + end; + if not aExpressionType.ConformsTo(lNumericTypeInfo) then + result := Format(sPossiblyBadConformance, [aExpressionType.ModelName , lNumericTypeInfo.ModelName]); +end; + +{ TcxBoldBlobEditDataBinding } + +function TcxBoldBlobEditDataBinding.ValidateTypeConforms( + aExpressionType: TBoldElementTypeInfo): string; +var + lBlobTypeInfo: TBoldAttributeTypeInfo; +begin + result := ''; + with (aExpressionType.SystemTypeInfo as TBoldSystemTypeInfo) do + begin + lBlobTypeInfo := AttributeTypeInfoByExpressionName['Blob']; // do not localize + end; + if not aExpressionType.ConformsTo(lBlobTypeInfo) then + result := Format(sPossiblyBadConformance, [aExpressionType.ModelName , lBlobTypeInfo.ModelName]); +end; + +{ TcxBoldTimeEditDataBinding } + +function TcxBoldTimeEditDataBinding.ValidateTypeConforms( + aExpressionType: TBoldElementTypeInfo): string; +var + lDateTimeTypeInfo: TBoldAttributeTypeInfo; + lTimeTypeInfo: TBoldAttributeTypeInfo; +begin + result := ''; + with (aExpressionType.SystemTypeInfo as TBoldSystemTypeInfo) do + begin + lDateTimeTypeInfo := AttributeTypeInfoByExpressionName['DateTime']; // do not localize + lTimeTypeInfo := AttributeTypeInfoByExpressionName['Time']; // do not localize + end; + if not (aExpressionType.ConformsTo(lDateTimeTypeInfo) or aExpressionType.ConformsTo(lTimeTypeInfo)) then + result := Format(sPossiblyBadConformance, [aExpressionType.ModelName , lDateTimeTypeInfo.ModelName + ' nor ' + lTimeTypeInfo.ModelName]); +end; + +function TcxCustomBoldTextEditProperties.BoldElementToEditValue( + aFollower: TBoldFollower; aElement: TBoldElement; + aEdit: TcxCustomEdit): variant; +begin + result := BoldRowProperties.GetAsVariant(aFollower); +end; + +procedure TcxCustomBoldTextEditProperties.SetBoldSelectChangeAction( + Value: TBoldComboSelectChangeAction); +begin + fBoldSelectChangeAction := Value; +end; + +procedure TcxCustomBoldTextEditProperties.SetStoredValue(aValue: Variant; + aBoldHandle: TBoldElementHandle; aEdit: TcxCustomEdit; + aFollower: TBoldFollower; var aDone: boolean); +var + LocalSelectedElement: TBoldElement; + lItemIndex: Integer; +begin + lItemIndex := -1; + if Assigned(TcxTextEdit(aEdit).ILookupData) then + lItemIndex := TcxTextEdit(aEdit).ILookupData.CurrentKey; + if lItemIndex = -1 then + begin + aDone := false; + exit; + end + else + begin +{ if ((lItemIndex = LookupListFollower.SubFollowerCount-1) and (BoldLookupListProperties.NilElementMode = neAddLast)) + or ((lItemIndex = 0) and (BoldLookupListProperties.NilElementMode = neInsertFirst)) then + begin + LocalSelectedElement := nil + end + else + begin + if (BoldLookupListProperties.NilElementMode = neInsertFirst) then + dec(lItemIndex); +} + LocalSelectedElement := BoldLookupListHandle.List[lItemIndex]; +// end; + end; + InternalComboSetValue(aBoldHandle, aFollower, LocalSelectedElement, BoldSelectChangeAction, BoldSetValueExpression, BoldLookupListHandle, aValue); + aDone := true; +end; + +function TcxCustomBoldTextEditProperties.CanEdit( + aBoldHandle: TBoldElementHandle; aFollower: TBoldFollower): boolean; +begin + result := true; +end; + +procedure TcxCustomBoldTextEditProperties.SetBoldSetValueExpression( + const Value: TBoldExpression); +begin + fBoldSetValueExpression := Value; + if Owner is TcxCustomEdit and (TcxCustomEdit(Owner).IsDesigning) and not (TcxCustomEdit(Owner).IsLoading) then + begin + _ValidateEdit(TcxCustomEdit(Owner)); + end; +end; + +{ TcxBoldCurrencyEditDataBinding } + +function TcxBoldCurrencyEditDataBinding.ValidateTypeConforms( + aExpressionType: TBoldElementTypeInfo): string; +var + lCurrencyTypeInfo: TBoldAttributeTypeInfo; + lFloatTypeInfo: TBoldAttributeTypeInfo; +begin + result := ''; + with (aExpressionType.SystemTypeInfo as TBoldSystemTypeInfo) do + begin + lCurrencyTypeInfo := AttributeTypeInfoByExpressionName['Currency']; // do not localize + lFloatTypeInfo := AttributeTypeInfoByExpressionName['Float']; // do not localize + end; + if not aExpressionType.ConformsTo(lCurrencyTypeInfo) and not aExpressionType.ConformsTo(lFloatTypeInfo) then + result := Format(sPossiblyBadConformance, [aExpressionType.ModelName , lCurrencyTypeInfo.ModelName]); +end; + +{ TcxBoldListBox } + +procedure TcxBoldListBox._DeleteItem(Index: Integer; + OwningFollower: TBoldFollower); +begin + if not (ListStyle in [lbVirtual, lbVirtualOwnerDraw]) then + begin + if not Items.Updating then + Items.BeginUpdate; + Items.Delete(index); + end; +end; + +procedure TcxBoldListBox._InsertItem(Index: Integer; Follower: TBoldFollower); +begin + Assert(Assigned(Follower)); + if not Items.Updating then + Items.BeginUpdate; + Follower.EnsureDisplayable; + if not (ListStyle in [lbVirtual, lbVirtualOwnerDraw]) then + Items.Insert(Follower.Index, VarToStr(TBoldVariantFollowerController(Follower.Controller).GetAsVariant(Follower))) +end; + +procedure TcxBoldListBox._ReplaceItem(Index: Integer; Follower: TBoldFollower); +begin + if not Items.Updating then + Items.BeginUpdate; + Follower.EnsureDisplayable; + if not (ListStyle in [lbVirtual, lbVirtualOwnerDraw]) then + Items.Strings[Index] := VarToStr(TBoldVariantFollowerController(Follower.Controller).GetAsVariant(Follower)); +end; + +procedure TcxBoldListBox._RowAfterMakeUptoDate(Follower: TBoldFollower); +var + index: Integer; + s: string; +begin + index := Follower.index; + if (index > -1) and (index < Items.Count) then + begin + s := VarToStr(TBoldVariantFollowerController(Follower.Controller).GetAsVariant(Follower)); + if s <> Items[index] then + Items[index] := s; + end; +end; + +procedure TcxBoldListBox._AfterMakeUptoDate(Follower: TBoldFollower); +begin + fBoldRowProperties.AfterMakeUptoDate := _RowAfterMakeUptoDate; + if not fInternalUpdate then + begin + if ListStyle in [lbVirtual, lbVirtualOwnerDraw] then + Count := self.Follower.SubFollowerCount; + ItemIndex := Follower.CurrentIndex; + if MultiSelect then + ClearSelection; + if ItemIndex <> -1 then + Selected[ItemIndex] := true; + end; + SyncSelection; + if Items.Updating then + Items.EndUpdate; +end; + +procedure TcxBoldListBox._BeforeMakeUptoDate(Follower: TBoldFollower); +begin + fBoldRowProperties.AfterMakeUptoDate := nil; + if assigned(BoldListHandle) and assigned(BoldListHandle.list) then + BoldListHandle.list.EnsureRange(0, BoldListHandle.list.Count-1); +end; + +function TcxBoldListBox.GetBoldListHandle: TBoldAbstractListHandle; +begin + Result := fListHandleFollower.BoldHandle; +end; + +procedure TcxBoldListBox.SetBoldListHandle( + const Value: TBoldAbstractListHandle); +begin + fListHandleFollower.BoldHandle := value; +end; + +procedure TcxBoldListBox.SetBoldListProperties( + const Value: TBoldListAsFollowerListController); +begin + fBoldListProperties.Assign(Value); +end; + +procedure TcxBoldListBox.SetRowProperties( + const Value: TBoldVariantFollowerController); +begin + fBoldRowProperties.Assign(Value); +end; + +function TcxBoldListBox.GetListFollower: TBoldFollower; +begin + Result := fListHandleFollower.Follower; +end; + +constructor TcxBoldListBox.Create(AOwner: TComponent); +begin + inherited; + fBoldRowProperties := TBoldVariantFollowerController.Create(AOwner); + fBoldRowProperties.AfterMakeUptoDate := _RowAfterMakeUptoDate; + fBoldRowProperties.OnGetContextType := GetContextForBoldRowProperties; + fBoldListProperties := TBoldListAsFollowerListController.Create(AOwner, fBoldRowProperties); + with fBoldListProperties do + begin + OnAfterInsertItem := _InsertItem; + OnAfterDeleteItem := _DeleteItem; + OnReplaceitem := _ReplaceItem; + BeforeMakeUptoDate := _BeforeMakeUptoDate; + AfterMakeUptoDate := _AfterMakeUptoDate; + end; + fListHandleFollower := TBoldListHandleFollower.Create(Owner, fBoldListProperties); +end; + +destructor TcxBoldListBox.Destroy; +begin + FreeAndNil(fListHandleFollower); + FreeAndNil(fBoldListProperties); + FreeAndNil(fBoldRowProperties); + inherited; +end; + +function TcxBoldListBox.GetContextForBoldRowProperties: TBoldElementTypeInfo; +begin + if assigned(BoldListHandle) then + result := BoldListHandle.StaticBoldType + else + result := nil; +end; + +function TcxBoldListBox.GetBoldHandleIndexLock: Boolean; +begin + Result := fListHandleFollower.HandleIndexLock; +end; + +procedure TcxBoldListBox.SetBoldHandleIndexLock(const Value: Boolean); +begin + fListHandleFollower.HandleIndexLock := Value; +end; + +procedure TcxBoldListBox.WndProc(var Message: TMessage); +begin + inherited; + if (InnerListBox <> nil) and not IsDestroying and + ((Message.Msg = WM_CTLCOLORLISTBOX) or (Message.Msg = WM_COMMAND) and (Message.WParamHi = LBN_SELCHANGE)) and (Follower.CurrentIndex <> ItemIndex) then + begin + fListHandleFollower.SetFollowerIndex(ItemIndex); + fInternalUpdate := true; + try + TBoldQueueable.DisplayAll; + finally + fInternalUpdate := false; + end; + end; +end; + +procedure TcxBoldListBox.DblClick; +var + lAutoForm: TForm; + lElement: TBoldElement; +begin + inherited; + if fBoldListProperties.DefaultDblClick and Assigned(Follower.CurrentSubFollower) and Assigned(Follower.CurrentSubFollower.Element) then + begin + lElement := Follower.CurrentSubFollower.Element; + lAutoForm := AutoFormProviderRegistry.FormForElement(lElement); + if assigned(lAutoForm) then + begin + lAutoForm.Show; + end + end; +end; + +function TcxBoldListBox.GetFollower: TBoldFollower; +begin + if Assigned(fListHandleFollower) then + result := fListHandleFollower.Follower + else + result := nil; +end; + +procedure TcxBoldListBox.Loaded; +begin + inherited; + Items.Clear; + DragMode := dmAutomatic; +end; + +procedure TcxBoldListBox.DoEndDrag(Target: TObject; X, Y: Integer); +begin + BoldListProperties.EndDrag; + inherited DoEndDrag(Target, X, Y); +end; + +procedure TcxBoldListBox.DoStartDrag(var DragObject: TDragObject); +begin + SyncSelection; + BoldListProperties.StartDrag(Follower); + inherited DoStartDrag(DragObject); +end; + +procedure TcxBoldListBox.DragOver(Source: TObject; X, Y: Integer; + State: TDragState; var Accept: Boolean); +begin + if Assigned(OnDragOver) + or (BoldListProperties.DropMode = bdpNone) + or ((Source = Self) and (not BoldListProperties.InternalDrag)) then + inherited DragOver(Source, X, Y, State, Accept) + else + Accept := BoldListProperties.DragOver(Follower, MutableList, ItemAtPos(Point(X, Y), False)); +end; + +procedure TcxBoldListBox.DragDrop(Source: TObject; X, Y: Integer); +begin + if Assigned(OnDragDrop) then + begin + if BoldGuiHandler.ActivateTargetFormOnDrop then + BoldGUIHandler.TryToFocusHostingForm(self); + inherited DragDrop(Source, X, Y); + end + else + BoldListProperties.DragDrop(Follower, MutableList, ItemAtPos(Point(X, Y), False)); +end; + +function TcxBoldListBox.DrawItem(ACanvas: TcxCanvas; AIndex: Integer; + const ARect: TRect; AState: TOwnerDrawState): Boolean; +begin + DefaultSetFontAndColor(AIndex); + Result := inherited DrawItem(ACanvas, AIndex, ARect, AState); +end; + +procedure TcxBoldListBox.DefaultDrawItem(Index: integer; aRect: TRect); +begin + BoldRowProperties.DrawOnCanvas(Follower.SubFollowers[index], Canvas.Canvas, aRect, taLeftJustify, Point(2,0)); +end; + +procedure TcxBoldListBox.DefaultSetFontAndColor(Index: integer); +var + ec: tColor; + SubFollower: TBoldFollower; +begin + BoldRowProperties.SetFont(InnerListBox.Canvas.Font, InnerListBox.Canvas.Font, Follower.SubFollowers[index]); + BoldRowProperties.SetColor(ec, InnerListBox.Canvas.Brush.Color, Follower.SubFollowers[index]); + InnerListBox.Canvas.Brush.Color := ec; + SubFollower := Follower.SubFollowers[index]; + if assigned(Subfollower) and Subfollower.Selected then + with InnerListBox.Canvas do + begin + Brush.Color := clHighlight; + Font.Color := clHighlightText; + end; +end; + +function TcxBoldListBox.GetMutableList: TBoldList; +begin + if assigned(BoldListHandle) then + result := BoldListHandle.MutableList + else + result := nil; +end; + +procedure TcxBoldListBox.SyncSelection; +var + i: integer; +begin + BoldListProperties.SelectAll(Follower, False); + if multiselect then + begin + if SelCount > 0 then + begin + for i := 0 to Count - 1 do + begin + BoldListProperties.SetSelected(Follower, i, Selected[i]); + end; + end; + end + else + begin + if ItemIndex <> -1 then + BoldListProperties.SetSelected(Follower, ItemIndex, true); + end; + if Assigned(BoldListHandle) and (BoldListHandle.CurrentIndex <> ItemIndex) then + begin + BoldListHandle.CurrentIndex := ItemIndex; + TBoldQueueable.DisplayAll; + end; +end; + +function TcxBoldListBox.ValidateComponent( + ComponentValidator: TBoldComponentValidator; + NamePrefix: string): Boolean; +var + lContext: TBoldElementTypeInfo; +begin + result := false; + lContext := GetContextForBoldRowProperties; + if assigned(lContext) then + begin + result := ComponentValidator.ValidateExpressionInContext( + BoldRowProperties.Expression, + lContext, + format('%s %s.BoldRowProperties.Expression', [NamePrefix, Name]), BoldRowProperties.VariableList); // do not localize + end; +end; + +{ TcxBoldListView } + +procedure TcxBoldListView._BeforeMakeUptoDate(Follower: TBoldFollower); +begin + // Will fetch all + if assigned(BoldHandle) and assigned(Boldhandle.list) then + BoldHandle.list.EnsureRange(0, BoldHandle.list.Count-1); +end; + +procedure TcxBoldListView._AfterMakeUptoDate(Follower: TBoldFollower); +begin + ItemIndex := Follower.CurrentIndex; + if ItemIndex = -1 then + fBoldProperties.SelectAll(Follower, False) + else + ; + if FUpdateCount > 0 then + begin + dec(FUpdateCount); + Items.EndUpdate; + end; +end; + +procedure TcxBoldListView._InsertItem(Index: Integer; Follower: TBoldFollower); +var + lItem: TListItem; +begin + Assert(Assigned(Follower)); + if FUpdateCount = 0 then + begin + inc(FUpdateCount); + Items.BeginUpdate; + end; + Follower.EnsureDisplayable; + lItem := Items.Insert(Follower.Index); + lItem.Caption := VarToStr(TBoldVariantFollowerController(Follower.Controller).GetAsVariant(Follower)); + lItem.ImageIndex := 0; +end; + +procedure TcxBoldListView._DeleteItem(index: Integer; + OwningFollower: TBoldFollower); +begin + if FUpdateCount = 0 then + begin + inc(FUpdateCount); + Items.BeginUpdate; + end; + Items.Delete(index); +end; + +procedure TcxBoldListView._ReplaceItem(Index: Integer; Follower: TBoldFollower); +begin + if FUpdateCount = 0 then + begin + inc(FUpdateCount); + Items.BeginUpdate; + end; + Follower.EnsureDisplayable; + items[Index].Caption := VarToStr(TBoldVariantFollowerController(Follower.Controller).GetAsVariant(Follower)); +end; + +procedure TcxBoldListView._RowAfterMakeUptoDate(Follower: TBoldFollower); +var + NewValue: string; +begin + NewValue := VarToStr(TBoldVariantFollowerController(Follower.Controller).GetAsVariant(Follower)); + if Items[Follower.index].Caption <> NewValue then + Items[Follower.index].Caption := NewValue; +end; + +function TcxBoldListView.GetBoldHandle: TBoldAbstractListHandle; +begin + Result := fListHandleFollower.BoldHandle; +end; + +function TcxBoldListView.GetBoldHandleIndexLock: Boolean; +begin + Result := fListHandleFollower.HandleIndexLock; +end; + +function TcxBoldListView.GetBoldList: TBoldList; +begin + //CHECKME We may have to remove this because the list is not necessarily equal with the rendered list!!! /FH + if Assigned(BoldHandle) then + Result := BoldHandle.List + else + Result := nil; +end; + +function TcxBoldListView.GetContextType: TBoldElementTypeInfo; +begin + if assigned(BoldHandle) then + result := BoldHandle.StaticBoldType + else + result := nil; +end; + +function TcxBoldListView.GetCurrentBoldElement: TBoldElement; +var + Subfollower: TBoldFollower; +begin + Result := nil; + if ItemIndex <> -1 then + begin + SubFollower := Follower.SubFollowers[ItemIndex]; + if assigned(SubFollower) then + Result := Subfollower.Element; + end; +end; + +function TcxBoldListView.GetCurrentBoldObject: TBoldObject; +begin + if CurrentBoldElement is TBoldObject then + Result := CurrentBoldElement as TBoldObject + else + Result := nil; +end; + +function TcxBoldListView.GetFollower: TBoldFollower; +begin + Result := fListHandleFollower.Follower; +end; + +procedure TcxBoldListView.SetBoldHandle(value: TBoldAbstractListHandle); +begin + fListHandleFollower.BoldHandle := value; +end; + +procedure TcxBoldListView.SetBoldHandleIndexLock(Value: Boolean); +begin + fListHandleFollower.HandleIndexLock := Value; +end; + +procedure TcxBoldListView.SetBoldProperties( + Value: TBoldAbstractListAsFollowerListController); +begin + fBoldProperties.Assign(Value); +end; + +procedure TcxBoldListView.SetRowProperties( + const Value: TBoldVariantFollowerController); +begin + fBoldRowProperties.Assign(Value); +end; + +constructor TcxBoldListView.Create(AOwner: TComponent); +begin + inherited Create(AOwner); + fBoldRowProperties := TBoldVariantFollowerController.Create(Self); + fBoldRowProperties.AfterMakeUptoDate := _RowAfterMakeUptoDate; + fBoldRowProperties.OnGetContextType := GetContextType; + fBoldProperties := TBoldAbstractListAsFollowerListController.Create(Self, fBoldRowProperties); + with fBoldProperties do + begin + OnAfterInsertItem := _InsertItem; + OnAfterDeleteItem := _DeleteItem; + OnReplaceitem := _ReplaceItem; + BeforeMakeUptoDate := _BeforeMakeUptoDate; + AfterMakeUptoDate := _AfterMakeUptoDate; + end; + fListHandleFollower := TBoldListHandleFollower.Create(Owner, fBoldProperties); + DragMode := dmAutomatic; + ViewStyle := vsIcon; +end; + +destructor TcxBoldListView.Destroy; +begin + FreeAndNil(fListHandleFollower); + FreeAndNil(fBoldProperties); + FreeAndNil(fBoldRowProperties); + inherited Destroy; +end; +(* +{ TcxBoldListBox } + +function TcxBoldListBox.GetDataBinding: TcxBoldDataBinding; +begin + Result := TcxBoldDataBinding(FDataBinding); +end; + +function TcxBoldListBox.GetDataBindingClass: TcxCustomDataBindingClass; +begin + result := TcxBoldDataBinding; +end; + +procedure TcxBoldListBox.SetDataBinding(Value: TcxBoldDataBinding); +begin + FDataBinding.Assign(Value); +end; +*) + +{ TcxBoldCustomCheckListBox } + +constructor TcxBoldCustomCheckListBox.Create(AOwner: TComponent); +begin + inherited; + fBoldRowProperties := TBoldVariantFollowerController.Create(self); + fBoldRowProperties.OnGetContextType := GetContextType; + fBoldRowCheckBoxProperties := TBoldCheckBoxStateFollowerController.Create(self); + fBoldRowCheckBoxProperties.OnGetContextType := GetContextType; + + fControllerList := TBoldControllerList.Create(self); + fControllerList.Add(fBoldRowCheckBoxProperties); + fControllerLIst.Add(fBoldRowProperties); + + fBoldRowProperties.AfterMakeUptoDate := _DisplayString; + fBoldRowCheckBoxProperties.AfterMakeUpToDate := _DisplayCheckBox; + + fBoldListProperties := TBoldAbstractListAsFollowerListController.Create(self, fControllerList); + fBoldListProperties.OnGetContextType := GetContextType; + fBoldListProperties.AfterMakeUptoDate := _ListAfterMakeUpToDate; + fBoldListProperties.BeforeMakeUptoDate := _ListBeforeMakeUpToDate; + fBoldlistProperties.OnAfterInsertItem := _ListInsertItem; + fBoldListProperties.OnAfterDeleteItem := _ListDeleteItem; + fBoldListProperties.OnReplaceitem := _ReplaceItem; +// fBoldListProperties.DefaultDblClick := false; + fListHandleFollower := TBoldListHandleFollower.Create(AOwner, fBoldListProperties); +end; + +destructor TcxBoldCustomCheckListBox.Destroy; +begin + FreeAndNil(fListHandleFollower); + FreeAndNil(fBoldListProperties); + FreeAndNil(fControllerList); + inherited; +end; + +function TcxBoldCustomCheckListBox.GetBoldHandleIndexLock: Boolean; +begin + Result := fListHandleFollower.HandleIndexLock; +end; + +function TcxBoldCustomCheckListBox.GetBoldListHandle: TBoldAbstractListHandle; +begin + Result := fListHandleFollower.BoldHandle; +end; + +function TcxBoldCustomCheckListBox.GetContextType: TBoldElementTypeInfo; +begin + if Assigned(BoldListHandle) then + result := BoldListHandle.StaticBoldType + else + result := nil; +end; + +function TcxBoldCustomCheckListBox.GetFollower: TBoldFollower; +begin + result := fListHandleFollower.Follower; +end; + +type + TcxBoldCustomInnerCheckListBox = class(TcxCustomInnerCheckListBox) + protected + procedure DoClickCheck(const AIndex: Integer; const OldState, NewState: TcxCheckBoxState); override; + end; + +{ TcxBoldCustomInnerCheckListBox } + +const + CHECKBOXFOLLOWER_INDEX = 0; + STRINGFOLLOWER_INDEX = 1; + +procedure TcxBoldCustomInnerCheckListBox.DoClickCheck( + const AIndex: Integer; const OldState, NewState: TcxCheckBoxState); +var + CheckBoxFollower: TBoldFollower; + lOwningCheckListBox: TcxBoldCustomCheckListBox; +begin + lOwningCheckListBox := (fContainer as TcxBoldCustomCheckListBox); + if not (csDesigning in ComponentState) and (ItemIndex <> - 1) then + begin + CheckBoxFollower := lOwningCheckListBox.fListHandleFollower.Follower.SubFollowers[AIndex].SubFollowers[CHECKBOXFOLLOWER_INDEX]; + TBoldCheckBoxStateFollowerController(CheckBoxFollower.Controller).SetAsCheckBoxState(TCheckBoxState(NewState), CheckBoxFollower); + lOwningCheckListBox.fListHandleFollower.SetFollowerIndex(AIndex); + end; + inherited; +end; + +function TcxBoldCustomCheckListBox.GetInnerCheckListBoxClass: TcxCustomInnerCheckListBoxClass; +begin + result := TcxBoldCustomInnerCheckListBox; +end; + +procedure TcxBoldCustomCheckListBox.Loaded; +begin + inherited; + Items.Clear; + DragMode := dmAutomatic; +end; + +procedure TcxBoldCustomCheckListBox.SetBoldHandleIndexLock( + const Value: Boolean); +begin + fListHandleFollower.HandleIndexLock := Value; +end; + +procedure TcxBoldCustomCheckListBox.SetBoldListHandle( + const Value: TBoldAbstractListHandle); +begin + fListHandleFollower.BoldHandle := value; +end; + +procedure TcxBoldCustomCheckListBox.SetBoldListProperties( + const Value: TBoldAbstractListAsFollowerListController); +begin + FBoldListProperties.Assign(Value); +end; + +procedure TcxBoldCustomCheckListBox.SetBoldRowCheckBoxProperties( + const Value: TBoldCheckBoxStateFollowerController); +begin + fBoldRowCheckBoxProperties.Assign(Value); +end; + +procedure TcxBoldCustomCheckListBox.SetRowProperties( + const Value: TBoldVariantFollowerController); +begin + fBoldRowProperties.Assign(Value); +end; + +procedure TcxBoldCustomCheckListBox.SyncSelection; +var + i: integer; +begin + BoldListProperties.SelectAll(Follower, False); + if InnerCheckListBox.multiselect then + begin + if InnerCheckListBox.SelCount > 0 then + begin + for i := 0 to Count - 1 do + begin + BoldListProperties.SetSelected(Follower, i, Selected[i]); + end; + end + end + else + begin + if ItemIndex <> -1 then + BoldListProperties.SetSelected(Follower, ItemIndex, true) + end; +end; + +procedure TcxBoldCustomCheckListBox.WndProc(var Message: TMessage); +begin + inherited; + if (InnerCheckListBox <> nil) and (Message.Msg = WM_COMMAND) and (Message.WParamHi = LBN_SELCHANGE) then + begin + fListHandleFollower.SetFollowerIndex(ItemIndex); + fInternalUpdate := true; + try + TBoldQueueable.DisplayAll; + finally + fInternalUpdate := false; + end; + end; +end; + +procedure TcxBoldCustomCheckListBox._DisplayCheckBox( + Follower: TBoldFollower); +var + index: integer; +begin + index := Follower.OwningFollower.index; + if (index > -1) and (index < Items.Count) then + begin + Items[Index].State := TcxCheckBoxState(TBoldCheckBoxStateFollowerController(Follower.Controller).GetCurrentAsCheckBoxState(Follower)); + end; +end; + +procedure TcxBoldCustomCheckListBox._DisplayString( + Follower: TBoldFollower); +var + index: integer; +begin + index := Follower.OwningFollower.index; + if (index > -1) and (index < Items.Count) then + begin + Items[Index].Text := VarToStr(TBoldVariantFollowerController(Follower.Controller).GetAsVariant(Follower)); + end; +end; + +procedure TcxBoldCustomCheckListBox._ListAfterMakeUpToDate( + Follower: TBoldFollower); +var + lIndex: integer; +begin +// fBoldRowProperties.AfterMakeUptoDate := _RowAfterMakeUptoDate; + if FUpdateCount > 0 then + begin + dec(FUpdateCount); + Items.EndUpdate; + end; + if not fInternalUpdate then + begin + lIndex := Follower.CurrentIndex; + ItemIndex := lIndex; + if self.InnerCheckListBox.MultiSelect then + InnerCheckListBox.ClearSelection; + if lIndex <> -1 then + Selected[lIndex] := true; + end; + SyncSelection; +end; + +procedure TcxBoldCustomCheckListBox._ListBeforeMakeUpToDate( + Follower: TBoldFollower); +begin + // will fetch all + if Assigned(BoldListHandle) and Assigned(BoldListHandle.List) then + BoldListHandle.List.EnsureRange(0, BoldListHandle.List.Count - 1); +end; + +procedure TcxBoldCustomCheckListBox._ListDeleteItem(Index: integer; + Follower: TBoldFollower); +begin + if FUpdateCount = 0 then + begin + inc(FUpdateCount); + Items.BeginUpdate; + end; + Items.Delete(Index); +end; + +procedure TcxBoldCustomCheckListBox._ListInsertItem(Index: Integer; Follower: TBoldFollower); +var + lCheckListBoxItem: TcxCheckListBoxItem; +begin + if FUpdateCount = 0 then + begin + inc(FUpdateCount); + Items.BeginUpdate; + end; + Assert(Assigned(Follower)); + lCheckListBoxItem := Items.Insert(Follower.Index) as TcxCheckListBoxItem; + if Assigned(Follower) then + begin + Follower.EnsureDisplayable; + if Assigned(Follower.Value) then + lCheckListBoxItem.Text := VarToStr(TBoldVariantFollowerController(Follower.Controller).GetAsVariant(Follower)); + end; +end; + +procedure TcxBoldCustomCheckListBox._ReplaceItem(Index: Integer; + Follower: TBoldFollower); +begin + if FUpdateCount = 0 then + begin + inc(FUpdateCount); + Items.BeginUpdate; + end; + Follower.EnsureDisplayable; + Items[Index].Text := VarToStr(TBoldVariantFollowerController(Follower.Controller).GetAsVariant(Follower)); +end; + +{ TcxBoldSelectionCheckListBox } + +constructor TcxBoldSelectionCheckListBox.Create(AOwner: TComponent); +begin + inherited; + fPublisher := TBoldPublisher.Create; +{ + TBoldGetAsCheckBoxState = function (Element: TBoldElement; Representation: TBoldRepresentation; Expression: TBoldExpression): TCheckBoxState of object; + TBoldSetAsCheckBoxState = procedure (Element: TBoldElement; newValue: TCheckBoxState; Representation: TBoldRepresentation; Expression: TBoldExpression) of object; +} + fCheckBoxRenderer := TBoldAsCheckBoxStateRenderer.Create(self); + fCheckBoxRenderer.OnGetAsCheckBoxState := GetAsCheckBoxState; + fCheckBoxRenderer.OnSetAsCheckBoxState := SetAsCheckBoxState; + fCheckBoxRenderer.OnSubscribe := OnSubscribe; + BoldRowCheckBoxProperties.Renderer := fCheckBoxRenderer; +end; + +destructor TcxBoldSelectionCheckListBox.Destroy; +begin + fPublisher.NotifySubscribersAndClearSubscriptions(self); + FreeAndNil(fPublisher); + inherited; +end; + +function TcxBoldSelectionCheckListBox.GetAsCheckBoxState( + aFollower: TBoldFollower + ): TCheckBoxState; +begin + if Assigned(BoldSelectionHandle) then + begin + if (BoldSelectionHandle.List.IndexOf(aFollower.Element) <> -1 ) then + Result := cbChecked + else + Result := cbUnChecked; + end + else + Result := cbGrayed; +end; + +procedure TcxBoldSelectionCheckListBox.SetAsCheckBoxState( + aFollower: TBoldFollower; newValue: TCheckBoxState); +var + lElement: TBoldElement; +begin + lElement := aFollower.Element; + if Assigned(BoldSelectionHandle) then + begin + case newValue of + cbChecked: BoldSelectionHandle.MutableList.Add(lElement); + cbUnChecked: if (BoldSelectionHandle.List.IndexOf(lElement) <> -1) then BoldSelectionHandle.MutableList.Remove(lElement); + cbGrayed: ; + end; + end; +end; + +procedure TcxBoldSelectionCheckListBox.Notification(AComponent: TComponent; + Operation: TOperation); +begin + inherited; + if (AComponent = BoldSelectionHandle) and (Operation = opRemove) then + BoldSelectionHandle := nil; +end; + +procedure TcxBoldSelectionCheckListBox.OnSubscribe( + aFollower: TBoldFollower; Subscriber: TBoldSubscriber); +begin + if Assigned(BoldSelectionHandle) then + begin + BoldSelectionHandle.AddSmallSubscription(Subscriber, [beValueIdentityChanged, beDestroying], breReSubscribe); + if Assigned(BoldSelectionHandle.List) then + BoldSelectionHandle.List.DefaultSubscribe(Subscriber); + end; + fPublisher.AddSubscription(Subscriber, beSelectionHandleChanged, breReSubscribe); +end; + +procedure TcxBoldSelectionCheckListBox.SetSelectionHandle( + const Value: TBoldAbstractListHandle); +begin + if (fBoldSelectionHandle <> Value) then + begin + fBoldSelectionHandle := Value; + fPublisher.SendExtendedEvent(self, beSelectionHandleChanged, []); + end; +end; + +function TcxBoldSelectionCheckListBox.ValidateComponent( + ComponentValidator: TBoldComponentValidator; + NamePrefix: string): Boolean; +var + lContext: TBoldElementTypeInfo; +begin + result := false; + lContext := GetContextType; + if assigned(lContext) then + begin + result := ComponentValidator.ValidateExpressionInContext( + BoldRowProperties.Expression, + lContext, + format('%s %s.BoldRowProperties.Expression', [NamePrefix, Name]), BoldRowProperties.VariableList); // do not localize + end; +end; + +{ TcxBoldCheckListBox } + +function TcxBoldCheckListBox.ValidateComponent( + ComponentValidator: TBoldComponentValidator; + NamePrefix: string): Boolean; +var + lContext: TBoldElementTypeInfo; +begin + result := false; + lContext := GetContextType; + if assigned(lContext) then + begin + result := ComponentValidator.ValidateExpressionInContext( + BoldRowProperties.Expression, + lContext, + format('%s %s.BoldRowProperties.Expression', [NamePrefix, Name]), BoldRowProperties.VariableList); // do not localize + result := ComponentValidator.ValidateExpressionInContext( + BoldRowCheckBoxProperties.Expression, + lContext, + format('%s %s.BoldRowProperties.Expression', [NamePrefix, Name]), BoldRowCheckBoxProperties.VariableList) and result; // do not localize + end; +end; + +initialization + GetRegisteredEditProperties.Register(TcxBoldTextEditProperties, scxSBoldEditRepositoryTextItem); + GetRegisteredEditProperties.Register(TcxBoldComboBoxProperties, scxSBoldComboBoxRepositoryTextItem); + FilterEditsController.Register(TcxBoldTextEditProperties, TcxFilterTextEditHelper); + FilterEditsController.Register(TcxBoldComboBoxProperties, TcxFilterComboBoxHelper); + dxBarRegisterItem(TcxBarBoldEditItem, TcxBarEditItemControl, True); +// BarDesignController.RegisterBarControlEditor(TcxItemsEditorEx); + + +finalization + dxBarUnregisterItem(TcxBarBoldEditItem); + FilterEditsController.Unregister(TcxBoldTextEditProperties, TcxFilterTextEditHelper); + FilterEditsController.Unregister(TcxBoldComboBoxProperties, TcxFilterComboBoxHelper); + GetRegisteredEditProperties.UnRegister(TcxBoldTextEditProperties); + GetRegisteredEditProperties.UnRegister(TcxBoldComboBoxProperties); +// BarDesignController.UnregisterBarControlEditor(TcxItemsEditorEx); + +end. diff --git a/Source/BoldAwareGUI/BoldDevex/cxBoldExtLookupComboBox.pas b/Source/BoldAwareGUI/BoldDevex/cxBoldExtLookupComboBox.pas new file mode 100644 index 0000000..f8fc6ca --- /dev/null +++ b/Source/BoldAwareGUI/BoldDevex/cxBoldExtLookupComboBox.pas @@ -0,0 +1,1042 @@ +unit cxBoldExtLookupComboBox; + +{$I cxVer.inc} + +// v2.03 - 25 Jan 2011 2007-2011 Daniel Mauric + +interface + +uses +{$IFDEF DELPHI6} + Variants, +{$ENDIF} + Windows, Classes, Controls, + Graphics, Messages, SysUtils, cxClasses, + cxContainer, cxControls, cxCustomData, + cxBoldLookupEdit, + cxEditConsts, cxGrid, cxGridCustomTableView, cxEdit, + cxGridCustomView, cxGridStrs, cxGridTableView, cxLookAndFeels, cxLookupEdit, + + BoldElements, + cxBoldEditors, + cxGridBoldSupportUnit, + BoldControlPack, + BoldHandles, + BoldComponentValidator; + +type + { TcxBoldExtLookupGrid } + + TcxBoldExtLookupGrid = class(TcxGrid) + private + FEditable: Boolean; + FMousePos: TPoint; + FPopupMouseMoveLocked: Boolean; + FPrevOnKeyDown: TKeyEvent; + FPrevOnMouseDown: TMouseEvent; + FPrevOnMouseMove: TMouseMoveEvent; + FPrevOnMouseUp: TMouseEvent; + FRowPressed: Boolean; + FOnCloseUp: TcxLookupGridCloseUpEvent; + function GetView: TcxCustomGridTableView; + procedure ViewKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); + procedure ViewMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); + procedure ViewMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); + procedure ViewMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); + protected + procedure DoCancelMode; override; + procedure DoCloseUp(AAccept: Boolean); virtual; + function IsDataRow(AHitTest: TcxCustomGridHitTest): Boolean; + property Editable: Boolean read FEditable write FEditable; + property PopupMouseMoveLocked: Boolean read FPopupMouseMoveLocked write FPopupMouseMoveLocked; + property OnCloseUp: TcxLookupGridCloseUpEvent read FOnCloseUp write FOnCloseUp; + public + property View: TcxCustomGridTableView read GetView; + end; + + { TcxCustomBoldExtLookupComboBoxProperties } + + TcxCustomBoldExtLookupComboBoxProperties = class(TcxCustomBoldLookupEditProperties); + + { TcxBoldExtLookupComboBoxProperties } + + TcxBoldExtLookupComboBoxProperties = class(TcxCustomBoldExtLookupComboBoxProperties) + private + FAutoSearchOnPopup: Boolean; + FDestroying: Boolean; + FFocusPopup: Boolean; + FGrid: TcxBoldExtLookupGrid; + FInCheckListFieldItem: Boolean; + FListFieldItem: TcxCustomGridTableItem; + FPrevColumnFiltering: Boolean; + FPrevColumnsQuickCustomization: Boolean; + FPrevPullFocusing: Boolean; + FPrevImmediateEditor: Boolean; + FPrevIncSearch: Boolean; + FPrevMultiSelect: Boolean; + FView: TcxCustomGridTableView; + function GetGrid: TcxBoldExtLookupGrid; +// function GetGridMode: Boolean; + function GetListFieldIndex: Integer; + function GetListFieldItem: TcxCustomGridTableItem; +// procedure SetGridMode(Value: Boolean); + procedure SetListFieldItem(Value: TcxCustomGridTableItem); + procedure SetView(Value: TcxCustomGridTableView); + protected + // IcxBoldEditProperties + procedure SetStoredValue(aValue: Variant; aBoldHandle: TBoldElementHandle; aEdit: TcxCustomEdit; aFollower: TBoldFollower; var aDone: boolean); override; + function CanEdit(aBoldHandle: TBoldElementHandle; aFollower: TBoldFollower): boolean; override; + + procedure CheckListFieldItem; + procedure DeinitializeDataController; override; + procedure FreeNotification(Sender: TComponent); override; + function GetIncrementalFiltering: Boolean; override; + function GetListIndex: Integer; override; + procedure InitializeDataController; override; + procedure LinkView(AView: TcxCustomGridTableView); + function PopupWindowCapturesFocus: Boolean; override; + procedure UnlinkView(AView: TcxCustomGridTableView); + // LookupGrid methods + function GetLookupGridActiveControl: TWinControl; override; + function GetLookupGridCanResize: Boolean; override; + function GetLookupGridColumnCount: Integer; override; + function GetLookupGridControl: TWinControl; override; + function GetLookupGridDataController: TcxCustomDataController; override; + function GetLookupGridVisualAreaPreferredWidth: Integer; override; + function GetLookupGridNearestPopupHeight(AHeight: Integer): Integer; override; + function GetLookupGridPopupHeight(ADropDownRowCount: Integer): Integer; override; + function IsLookupGridMouseOverList(const P: TPoint): Boolean; override; + procedure LookupGridDeinitialize; override; + procedure LookupGridDroppedDown(const AFindStr: string); override; + procedure LookupGridInitEvents(AOnClick, AOnFocusedRowChanged: TNotifyEvent; + AOnCloseUp: TcxLookupGridCloseUpEvent); override; + procedure LookupGridInitialize; override; + procedure LookupGridInitLookAndFeel(ALookAndFeel: TcxLookAndFeel; + AColor: TColor; AFont: TFont); override; + procedure LookupGridLockMouseMove; override; + procedure LookupGridMakeFocusedRowVisible; override; + procedure LookupGridUnlockMouseMove; override; + + procedure BoldLookupGridBeginUpdate; override; + procedure BoldLookupGridEndUpdate; override; + + // DBLookupGrid methods +{ + procedure DBLookupGridBeginUpdate; override; + procedure DBLookupGridCheckColumnByFieldName(const AFieldName: string); override; + procedure DBLookupGridCreateColumnsByFieldNames(const AFieldNames: string); override; + procedure DBLookupGridEndUpdate; override; + function GetDBLookupGridColumnField(AIndex: Integer): TField; override; + function GetDBLookupGridColumnFieldName(AIndex: Integer): string; override; + function GetDBLookupGridColumnIndexByFieldName(const AFieldName: string): Integer; override; +} + function GetBoldLookupGridDataController: TcxBoldDataController; override; + public + constructor Create(AOwner: TPersistent); override; + destructor Destroy; override; + procedure Assign(Source: TPersistent); override; + class function GetContainerClass: TcxContainerClass; override; + class function IsViewSupported(Value: TcxCustomGridTableView): Boolean; + property Grid: TcxBoldExtLookupGrid read GetGrid; + property ListFieldIndex: Integer read GetListFieldIndex; + published + property BoldSelectChangeAction; + property BoldSetValueExpression; + + property Alignment; + property AssignedValues; + property AutoSearchOnPopup: Boolean read FAutoSearchOnPopup write FAutoSearchOnPopup default True; + property AutoSelect; + property ButtonGlyph; + property CaseSensitiveSearch; + property CharCase; + property ClearKey; + property DropDownAutoSize; + property DropDownHeight; + property DropDownListStyle; + property DropDownRows; + property DropDownSizeable; + property DropDownWidth; + property FocusPopup: Boolean read FFocusPopup write FFocusPopup default False; +// property GridMode: Boolean read GetGridMode write SetGridMode default False; + property HideSelection; + property ImeMode; + property ImeName; + property ImmediateDropDown; +// property ImmediatePost; + property IncrementalFiltering; + property IncrementalFilteringOptions; + property View: TcxCustomGridTableView read FView write SetView; // before +// property KeyFieldNames; + property ListFieldItem: TcxCustomGridTableItem read GetListFieldItem write SetListFieldItem; + property MaxLength; + property OEMConvert; + property PopupAlignment; + property PostPopupValueOnTab; + property ReadOnly; + property Revertable; + property UseLeftAlignmentOnEditing; + property ValidateOnEnter; + property OnChange; + property OnCloseUp; + property OnEditValueChanged; + property OnInitPopup; + property OnNewLookupDisplayText; + property OnPopup; + property OnValidate; + end; + + { TcxCustomBoldExtLookupComboBox } + + TcxCustomBoldExtLookupComboBox = class(TcxCustomBoldLookupEdit) + private + function GetActiveProperties: TcxBoldExtLookupComboBoxProperties; + function GetProperties: TcxBoldExtLookupComboBoxProperties; + procedure SetProperties(Value: TcxBoldExtLookupComboBoxProperties); + protected + function CanDropDown: Boolean; override; + public + class function GetPropertiesClass: TcxCustomEditPropertiesClass; override; + property ActiveProperties: TcxBoldExtLookupComboBoxProperties + read GetActiveProperties; + property EditValue; + property Properties: TcxBoldExtLookupComboBoxProperties read GetProperties + write SetProperties; + property Text; + end; + + { TcxBoldNBExtLookupComboBox } + + TcxBoldNBExtLookupComboBox = class(TcxCustomBoldExtLookupComboBox) + published + property Anchors; + property AutoSize; + property BeepOnEnter; + property Constraints; + property DragCursor; + property DragKind; + property DragMode; + property Enabled; + property ImeMode; + property ImeName; + property ParentColor; + property ParentFont; + property ParentShowHint; + property PopupMenu; + property Properties; + property EditValue; + property ShowHint; + property Style; + property StyleDisabled; + property StyleFocused; + property StyleHot; + property TabOrder; + property TabStop; + property Visible; + property OnClick; + property OnContextPopup; + property OnDblClick; + property OnEditing; + property OnEnter; + property OnExit; + property OnKeyDown; + property OnKeyPress; + property OnKeyUp; + property OnMouseDown; + property OnMouseMove; + property OnMouseUp; + end; + + { TcxBoldExtLookupComboBox } + + TcxBoldExtLookupComboBox = class(TcxCustomBoldExtLookupComboBox, IBoldValidateableComponent, IBoldOCLComponent) + private + function GetDataBinding: TcxBoldTextEditDataBinding; + procedure SetDataBinding(Value: TcxBoldTextEditDataBinding); +// procedure CMGetDataLink(var Message: TMessage); message CM_GETDATALINK; + protected + class function GetDataBindingClass: TcxEditDataBindingClass; override; + procedure Initialize; override; + procedure Paint; override; + published + property Anchors; + property AutoSize; + property BeepOnEnter; + property Constraints; + property DragCursor; + property DragKind; + property DataBinding: TcxBoldTextEditDataBinding read GetDataBinding write SetDataBinding implements IBoldValidateableComponent, IBoldOCLComponent; + property DragMode; + property Enabled; + property ImeMode; + property ImeName; + property ParentColor; + property ParentFont; + property ParentShowHint; + property PopupMenu; + property Properties; + property ShowHint; + property Style; + property StyleDisabled; + property StyleFocused; + property StyleHot; + property TabOrder; + property TabStop; + property Visible; + property OnClick; + property OnContextPopup; + property OnDblClick; + property OnEditing; + property OnEnter; + property OnExit; + property OnKeyDown; + property OnKeyPress; + property OnKeyUp; + property OnMouseDown; + property OnMouseMove; + property OnMouseUp; + end; + + { TcxEditRepositoryExtLookupComboBoxItem } + + TcxEditRepositoryExtLookupComboBoxItem = class(TcxEditRepositoryItem) + private + function GetProperties: TcxBoldExtLookupComboBoxProperties; + procedure SetProperties(Value: TcxBoldExtLookupComboBoxProperties); + public + class function GetEditPropertiesClass: TcxCustomEditPropertiesClass; override; + published + property Properties: TcxBoldExtLookupComboBoxProperties read GetProperties write SetProperties; + end; + +implementation + +uses + Types, + cxGridFilterHelpers, + BoldSystem, + cxDropDownEdit; + +type + TcxCustomGridTableOptionsBehaviorAccess = class(TcxCustomGridTableOptionsBehavior); + TcxCustomGridTableOptionsViewAccess = class(TcxCustomGridTableOptionsView); + +{ TcxBoldExtLookupGrid } + +procedure TcxBoldExtLookupGrid.DoCancelMode; +begin + FRowPressed := False; + inherited; +end; + +procedure TcxBoldExtLookupGrid.DoCloseUp(AAccept: Boolean); +begin + if AAccept then + View.DataController.SyncSelected(True); + if Assigned(FOnCloseUp) then FOnCloseUp(Self, AAccept); +end; + +function TcxBoldExtLookupGrid.IsDataRow(AHitTest: TcxCustomGridHitTest): Boolean; +begin + Result := (AHitTest is TcxGridRecordHitTest) and + TcxGridRecordHitTest(AHitTest).GridRecord.IsData; +end; + +function TcxBoldExtLookupGrid.GetView: TcxCustomGridTableView; +begin + Result := Levels[0].GridView as TcxCustomGridTableView; +end; + +procedure TcxBoldExtLookupGrid.ViewKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); +begin + if Assigned(FPrevOnKeyDown) then + FPrevOnKeyDown(Self, Key, Shift); + if (View = nil) then Exit; + case Key of + VK_RETURN: + if not Editable or not View.OptionsData.Editing or (ssCtrl in Shift) then + begin + if View.DataController.IsEditing then + View.DataController.Post; + DoCloseUp(View.DataController.FocusedRowIndex <> -1); + end; + VK_ESCAPE: + if Editable and not View.DataController.IsEditing then + DoCloseUp(False); + end; +end; + +procedure TcxBoldExtLookupGrid.ViewMouseDown(Sender: TObject; Button: TMouseButton; + Shift: TShiftState; X, Y: Integer); +var + AHitTest: TcxCustomGridHitTest; +begin + if Assigned(FPrevOnMouseDown) then + FPrevOnMouseDown(Sender, Button, Shift, X, Y); + AHitTest := View.ViewInfo.GetHitTest(X, Y); + if (Button = mbLeft) and IsDataRow(AHitTest) then + begin + if Editable then + begin + if ssDouble in Shift then + DoCloseUp(True); + end + else + FRowPressed := True; + end; +end; + +procedure TcxBoldExtLookupGrid.ViewMouseMove(Sender: TObject; Shift: TShiftState; + X, Y: Integer); +var + AHitTest: TcxCustomGridHitTest; +begin + if Assigned(FPrevOnMouseMove) then + FPrevOnMouseMove(Sender, Shift, X, Y); + if not MouseCapture and PopupMouseMoveLocked then + begin + PopupMouseMoveLocked := False; + Exit; + end; + // Hot Track + if (View = nil) or Editable then Exit; + AHitTest := View.ViewInfo.GetHitTest(X, Y); + if IsDataRow(AHitTest) and ((FMousePos.X <> X) or (FMousePos.Y <> Y)) then + begin + FMousePos.X := X; + FMousePos.Y := Y; + TcxGridRecordHitTest(AHitTest).GridRecord.Focused := True; + end; +end; + +procedure TcxBoldExtLookupGrid.ViewMouseUp(Sender: TObject; Button: TMouseButton; + Shift: TShiftState; X, Y: Integer); +var + AHitTest: TcxCustomGridHitTest; +begin + if Assigned(FPrevOnMouseUp) then + FPrevOnMouseUp(Sender, Button, Shift, X, Y); + AHitTest := View.ViewInfo.GetHitTest(X, Y); + if (Button = mbLeft) and FRowPressed then + DoCloseUp(IsDataRow(AHitTest)); + FRowPressed := False; +end; + +{ TcxBoldExtLookupComboBoxProperties } + +constructor TcxBoldExtLookupComboBoxProperties.Create(AOwner: TPersistent); +begin + inherited Create(AOwner); + FAutoSearchOnPopup := True; +end; + +destructor TcxBoldExtLookupComboBoxProperties.Destroy; +begin + FDestroying := True; + ListFieldItem := nil; + View := nil; + FreeAndNil(FGrid); + inherited Destroy; +end; + +procedure TcxBoldExtLookupComboBoxProperties.Assign(Source: TPersistent); +begin + if Source is TcxBoldExtLookupComboBoxProperties then + begin + BeginUpdate; + try + AutoSearchOnPopup := TcxBoldExtLookupComboBoxProperties(Source).AutoSearchOnPopup; + FocusPopup := TcxBoldExtLookupComboBoxProperties(Source).FocusPopup; + View := nil; //? +// GridMode := TcxBoldExtLookupComboBoxProperties(Source).GridMode; + View := TcxBoldExtLookupComboBoxProperties(Source).View; + inherited Assign(Source); + ListFieldItem := TcxBoldExtLookupComboBoxProperties(Source).ListFieldItem; + finally + EndUpdate; + end + end + else + inherited Assign(Source); +end; + +class function TcxBoldExtLookupComboBoxProperties.GetContainerClass: TcxContainerClass; +begin + Result := TcxBoldNBExtLookupComboBox; +end; + +class function TcxBoldExtLookupComboBoxProperties.IsViewSupported(Value: TcxCustomGridTableView): Boolean; +begin + Result := Value.CanBeLookupList and + (TcxCustomGridView(Value).DataController is TcxBoldDataController); +end; + +procedure TcxBoldExtLookupComboBoxProperties.CheckListFieldItem; +begin + FInCheckListFieldItem := True; + try + if (View <> nil) and (ListFieldItem <> nil) and + (View.IndexOfItem(ListFieldItem) = -1) then + ListFieldItem := nil; + finally + FInCheckListFieldItem := False; + end; +end; + +procedure TcxBoldExtLookupComboBoxProperties.DeinitializeDataController; +begin + inherited DeinitializeDataController; + if DataController <> nil then + DataController.RemoveDataChangeRefCount; +end; + +procedure TcxBoldExtLookupComboBoxProperties.FreeNotification(Sender: TComponent); +begin + inherited FreeNotification(Sender); + if Sender = ListFieldItem then + ListFieldItem := nil; + if Sender = View then + View := nil; +end; + +function TcxBoldExtLookupComboBoxProperties.GetIncrementalFiltering: Boolean; +begin + if FocusPopup then + Result := False + else + Result := inherited GetIncrementalFiltering; +end; + +function TcxBoldExtLookupComboBoxProperties.GetListIndex: Integer; +begin + Result := Self.ListFieldIndex; +end; + +procedure TcxBoldExtLookupComboBoxProperties.InitializeDataController; +begin + inherited InitializeDataController; + if DataController <> nil then + DataController.AddDataChangeRefCount; +end; + +procedure TcxBoldExtLookupComboBoxProperties.LinkView(AView: TcxCustomGridTableView); +begin + CheckListFieldItem; + FreeNotificator.AddSender(AView); + InitializeDataController; +end; + +function TcxBoldExtLookupComboBoxProperties.PopupWindowCapturesFocus: Boolean; +begin + Result := FocusPopup; +end; + +procedure TcxBoldExtLookupComboBoxProperties.UnlinkView(AView: TcxCustomGridTableView); +begin + DeinitializeDataController; + FreeNotificator.RemoveSender(AView); +end; + +// LookupGrid methods + +function TcxBoldExtLookupComboBoxProperties.GetLookupGridActiveControl: TWinControl; +begin + if View <> nil then + Result := View.Site + else + Result := inherited GetLookupGridActiveControl; +end; + +function TcxBoldExtLookupComboBoxProperties.GetLookupGridCanResize: Boolean; +begin + if View <> nil then + Result := not TcxCustomGridTableOptionsViewAccess(View.OptionsView).CellAutoHeight + else + Result := False; +end; + +function TcxBoldExtLookupComboBoxProperties.GetLookupGridColumnCount: Integer; +begin + if View <> nil then + Result := View.ItemCount + else + Result := 0; +end; + +function TcxBoldExtLookupComboBoxProperties.GetLookupGridControl: TWinControl; +begin + Result := Grid; +end; + +function TcxBoldExtLookupComboBoxProperties.GetLookupGridDataController: TcxCustomDataController; +begin + if View <> nil then + Result := View.DataController + else + Result := nil; +end; + +function TcxBoldExtLookupComboBoxProperties.GetLookupGridVisualAreaPreferredWidth: Integer; +begin + Result := 0; + if View <> nil then + View.ViewInfo.GetWidth(Point(MaxInt, MaxInt), Result); +end; + +function TcxBoldExtLookupComboBoxProperties.GetLookupGridNearestPopupHeight(AHeight: Integer): Integer; +begin + if View <> nil then + Result := View.ViewInfo.GetNearestPopupHeight(AHeight, FocusPopup) + else + Result := AHeight; +end; + +function TcxBoldExtLookupComboBoxProperties.GetLookupGridPopupHeight(ADropDownRowCount: Integer): Integer; +begin + if View <> nil then + begin + if FocusPopup and (ADropDownRowCount < 2) then // TODO: Check New Item Row + ADropDownRowCount := 2; + Result := View.ViewInfo.GetPopupHeight(ADropDownRowCount); + end + else + Result := 0; +end; + +function TcxBoldExtLookupComboBoxProperties.IsLookupGridMouseOverList(const P: TPoint): Boolean; +var + AHitTest: TcxCustomGridHitTest; +begin + Result := False; + if View <> nil then + begin + AHitTest := View.ViewInfo.GetHitTest(P); + Result := AHitTest is TcxGridRecordHitTest; + end; +end; + +procedure TcxBoldExtLookupComboBoxProperties.LookupGridDeinitialize; +begin + Grid.Levels[0].GridView := nil; + // restore options + if (View <> nil) and not (csDestroying in View.ComponentState) then + begin + TcxCustomGridTableOptionsBehaviorAccess(View.OptionsBehavior).PullFocusing := FPrevPullFocusing; + View.OptionsSelection.MultiSelect := FPrevMultiSelect; + View.OptionsBehavior.ImmediateEditor := FPrevImmediateEditor; + if View is TcxGridTableView then + begin + TcxGridTableView(View).OptionsCustomize.ColumnFiltering := FPrevColumnFiltering; + TcxGridTableView(View).OptionsCustomize.ColumnsQuickCustomization := FPrevColumnsQuickCustomization; + end; + View.OptionsBehavior.IncSearch := FPrevIncSearch; + View.OnKeyDown := Grid.FPrevOnKeyDown; + View.OnMouseDown := Grid.FPrevOnMouseDown; + View.OnMouseMove := Grid.FPrevOnMouseMove; + View.OnMouseUp := Grid.FPrevOnMouseUp; + end; +end; + +procedure TcxBoldExtLookupComboBoxProperties.LookupGridDroppedDown(const AFindStr: string); +begin + // Init Inc Search + // TODO: !!! + if FocusPopup and AutoSearchOnPopup and (ListFieldItem <> nil) then + begin + ListFieldItem.Focused := True; + View.DataController.Search.Locate(ListFieldItem.Index, AFindStr); + end; +end; + +procedure TcxBoldExtLookupComboBoxProperties.LookupGridInitEvents(AOnClick, AOnFocusedRowChanged: TNotifyEvent; + AOnCloseUp: cxLookupEdit.TcxLookupGridCloseUpEvent); +begin + Grid.OnClick := AOnClick; // not impl + if View <> nil then + begin +// View.OnFocusedRecordChanged := AOnFocusedRowChanged; + Grid.OnCloseUp := AOnCloseUp; + end; +end; + +procedure TcxBoldExtLookupComboBoxProperties.LookupGridInitialize; +begin + if View = nil then + Exit; + // save options + FPrevPullFocusing := TcxCustomGridTableOptionsBehaviorAccess(View.OptionsBehavior).PullFocusing; + TcxCustomGridTableOptionsBehaviorAccess(View.OptionsBehavior).PullFocusing := True; + FPrevMultiSelect := View.OptionsSelection.MultiSelect; + View.OptionsSelection.MultiSelect := False; + FPrevImmediateEditor := View.OptionsBehavior.ImmediateEditor; + View.OptionsBehavior.ImmediateEditor := False; + if View is TcxGridTableView then + begin + FPrevColumnFiltering := TcxGridTableView(View).OptionsCustomize.ColumnFiltering; + FPrevColumnsQuickCustomization := TcxGridTableView(View).OptionsCustomize.ColumnsQuickCustomization; + if not FocusPopup then + begin + TcxGridTableView(View).OptionsCustomize.ColumnFiltering := False; + TcxGridTableView(View).OptionsCustomize.ColumnsQuickCustomization := False; + end; + end; + + Grid.FPrevOnKeyDown := View.OnKeyDown; + View.OnKeyDown := Grid.ViewKeyDown; + + Grid.FPrevOnMouseDown := View.OnMouseDown; + View.OnMouseDown := Grid.ViewMouseDown; + + Grid.FMousePos := Point(-1, -1); + Grid.FPrevOnMouseMove := View.OnMouseMove; + View.OnMouseMove := Grid.ViewMouseMove; + + Grid.FPrevOnMouseUp := View.OnMouseUp; + View.OnMouseUp := Grid.ViewMouseUp; + + Grid.Editable := FocusPopup; + Grid.Levels[0].GridView := View; + + FPrevIncSearch := View.OptionsBehavior.IncSearch; + if FocusPopup and AutoSearchOnPopup then + View.OptionsBehavior.IncSearch := True; + View.DataController.Search.Cancel; +end; + +procedure TcxBoldExtLookupComboBoxProperties.LookupGridInitLookAndFeel(ALookAndFeel: TcxLookAndFeel; + AColor: TColor; AFont: TFont); +begin + Grid.LookAndFeel.MasterLookAndFeel := ALookAndFeel; + Grid.Color := AColor; + Grid.Font := AFont; +end; + +procedure TcxBoldExtLookupComboBoxProperties.LookupGridLockMouseMove; +begin + Grid.PopupMouseMoveLocked := True; +end; + +procedure TcxBoldExtLookupComboBoxProperties.LookupGridMakeFocusedRowVisible; +begin + if View <> nil then + View.Controller.MakeFocusedRecordVisible; +end; + +procedure TcxBoldExtLookupComboBoxProperties.LookupGridUnlockMouseMove; +begin + Grid.MouseCapture := False; + Grid.PopupMouseMoveLocked := False; +end; + +// DBLookupGrid methods +{ +procedure TcxBoldExtLookupComboBoxProperties.DBLookupGridBeginUpdate; +begin + if View <> nil then View.BeginUpdate; +end; + +procedure TcxBoldExtLookupComboBoxProperties.DBLookupGridCheckColumnByFieldName(const AFieldName: string); +begin + if (View <> nil) and (DataController <> nil) then + begin + if (AFieldName <> '') and (DataController.GetItemByFieldName(AFieldName) = nil) then + with View.CreateItem do + begin + Index := 0; + DataController.ChangeFieldName(Index, AFieldName); + end; + end; +end; + +procedure TcxBoldExtLookupComboBoxProperties.DBLookupGridCreateColumnsByFieldNames(const AFieldNames: string); +var + I: Integer; + AFieldNamesList: TStrings; +begin + if View <> nil then + begin + View.ClearItems; + AFieldNamesList := TStringList.Create; + try + GetFieldNames(AFieldNames, AFieldNamesList); + View.BeginUpdate; + try + for I := 0 to AFieldNamesList.Count - 1 do + DataController.ChangeFieldName(View.CreateItem.Index, AFieldNamesList[I]); + finally + View.EndUpdate; + end; + finally + AFieldNamesList.Free; + end; + end; +end; + +procedure TcxBoldExtLookupComboBoxProperties.DBLookupGridEndUpdate; +begin + if View <> nil then View.EndUpdate; +end; + +function TcxBoldExtLookupComboBoxProperties.GetDBLookupGridColumnField(AIndex: Integer): TField; +begin + if DataController <> nil then + Result := DataController.GetItemField(AIndex) + else + Result := nil; +end; + +function TcxBoldExtLookupComboBoxProperties.GetDBLookupGridColumnFieldName(AIndex: Integer): string; +begin + if DataController <> nil then + Result := DataController.GetItemFieldName(AIndex) + else + Result := ''; +end; + +function TcxBoldExtLookupComboBoxProperties.GetDBLookupGridColumnIndexByFieldName(const AFieldName: string): Integer; +var + AItem: TcxCustomGridTableItem; +begin + if DataController <> nil then + begin + AItem := TcxCustomGridTableItem(DataController.GetItemByFieldName(AFieldName)); + Result := AItem.Index; + end + else + Result := -1; +end; + +function TcxBoldExtLookupComboBoxProperties.GetDBLookupGridDataController: TcxDBDataController; +begin + Result := TcxDBDataController(GetLookupGridDataController); +end; +} +function TcxBoldExtLookupComboBoxProperties.GetGrid: TcxBoldExtLookupGrid; + + procedure CreateGrid; + begin + FGrid := TcxBoldExtLookupGrid.Create(nil); + FGrid.IsPopupControl := True; + FGrid.BorderStyle := cxcbsNone; + FGrid.Levels.Add; + end; + +begin + if (FGrid = nil) and not FDestroying then + CreateGrid; + Result := FGrid; +end; + +{function TcxBoldExtLookupComboBoxProperties.GetGridMode: Boolean; +begin + Result := inherited IsUseLookupList; +end;} + +function TcxBoldExtLookupComboBoxProperties.GetListFieldIndex: Integer; +var + AItem: TcxCustomGridTableItem; +begin + if IsDefinedByLookup then + Result := GetDisplayColumnIndex + else + begin + AItem := ListFieldItem; + if AItem <> nil then + Result := AItem.Index + else + Result := -1; + end; +end; + +function TcxBoldExtLookupComboBoxProperties.GetListFieldItem: TcxCustomGridTableItem; +begin + if IsDefinedByLookup then + Result := nil + else + Result := FListFieldItem; +end; + +{procedure TcxBoldExtLookupComboBoxProperties.SetGridMode(Value: Boolean); +begin + inherited IsUseLookupList := Value; +end;} + +procedure TcxBoldExtLookupComboBoxProperties.SetListFieldItem(Value: TcxCustomGridTableItem); +begin + if (View <> nil) and (View.IndexOfItem(Value) = -1) then + Value := nil; + if FListFieldItem <> Value then + begin + if FListFieldItem <> nil then + FreeNotificator.RemoveSender(FListFieldItem); + FListFieldItem := Value; + if FListFieldItem <> nil then + FreeNotificator.AddSender(FListFieldItem); + if not FInCheckListFieldItem then + Changed; + end; +end; + +procedure TcxBoldExtLookupComboBoxProperties.SetView(Value: TcxCustomGridTableView); +begin + if (Value <> nil) and not IsViewSupported(Value) then Exit; + if FView <> Value then + begin + if FView <> nil then + UnlinkView(FView); + FView := Value; + if FView <> nil then + LinkView(FView); + Changed; + end; +end; + +function TcxBoldExtLookupComboBoxProperties.GetBoldLookupGridDataController: TcxBoldDataController; +begin + Result := TcxBoldDataController(GetLookupGridDataController); +end; + +procedure TcxBoldExtLookupComboBoxProperties.SetStoredValue( + aValue: Variant; aBoldHandle: TBoldElementHandle; aEdit: TcxCustomEdit; aFollower: TBoldFollower; var aDone: boolean); +var + lItemIndex: Integer; + lSelectedElement: TBoldElement; +begin +// inherited; +// Assert(aEdit is TcxCustomComboBox, 'TcxBoldLookupComboBoxProperties.SetStoredValue: aEdit is not TcxCustomComboBox;' + aEdit.classname); + +// lItemIndex := (aEdit as TcxCustomComboBox).ItemIndex; +// if TcxCustomComboBox(aEdit).ILookupData.CurrentKey <> null then + if (not VarIsNull(aValue)) and (aValue <> -1) then + begin + lItemIndex := aValue; //TcxCustomComboBox(aEdit).ILookupData.CurrentKey; + + lSelectedElement := GetBoldLookupGridDataController.BoldHandle.List[lItemIndex]; + InternalComboSetValue(aBoldHandle, aFollower, lSelectedElement, BoldSelectChangeAction, BoldSetValueExpression, DataController.BoldHandle, aValue); +{ + Assert(aEdit.EditingValue = aEdit.EditValue); + i := aEdit.EditingValue; + Assert(DataController.CurrentIndex = i); +// (DataController.Follower.Element as TBoldList)[i]. + aFollower.Element.Assign(DataController.CurrentBoldObject); +} + end; + aDone := true; +end; + +procedure TcxBoldExtLookupComboBoxProperties.BoldLookupGridBeginUpdate; +begin + if View <> nil then View.BeginUpdate; +end; + +procedure TcxBoldExtLookupComboBoxProperties.BoldLookupGridEndUpdate; +begin + if View <> nil then View.EndUpdate; +end; + +function TcxBoldExtLookupComboBoxProperties.CanEdit( + aBoldHandle: TBoldElementHandle; aFollower: TBoldFollower): boolean; +begin + result := GetBoldLookupGridDataController.RecordCount > 0; +end; + +{ TcxCustomBoldExtLookupComboBox } + +class function TcxCustomBoldExtLookupComboBox.GetPropertiesClass: TcxCustomEditPropertiesClass; +begin + Result := TcxBoldExtLookupComboBoxProperties; +end; + +function TcxCustomBoldExtLookupComboBox.CanDropDown: Boolean; +begin + if ActiveProperties.FocusPopup then + Result := True + else + Result := inherited CanDropDown; +end; + +function TcxCustomBoldExtLookupComboBox.GetActiveProperties: TcxBoldExtLookupComboBoxProperties; +begin + Result := TcxBoldExtLookupComboBoxProperties(InternalGetActiveProperties); +end; + +function TcxCustomBoldExtLookupComboBox.GetProperties: TcxBoldExtLookupComboBoxProperties; +begin + Result := TcxBoldExtLookupComboBoxProperties(FProperties); +end; + +procedure TcxCustomBoldExtLookupComboBox.SetProperties(Value: TcxBoldExtLookupComboBoxProperties); +begin + FProperties.Assign(Value); +end; + +{ TcxBoldExtLookupComboBox } + +class function TcxBoldExtLookupComboBox.GetDataBindingClass: TcxEditDataBindingClass; +begin + Result := TcxBoldLookupEditDataBinding; +end; + +function TcxBoldExtLookupComboBox.GetDataBinding: TcxBoldTextEditDataBinding; +begin + Result := TcxBoldTextEditDataBinding(FDataBinding); +end; + +procedure TcxBoldExtLookupComboBox.SetDataBinding(Value: TcxBoldTextEditDataBinding); +begin + FDataBinding.Assign(Value); +end; +{ +procedure TcxBoldExtLookupComboBox.CMGetDataLink(var Message: TMessage); +begin + Message.Result := Integer(GetcxDBEditDataLink(Self)); +end; +} + +type + TcxBoldTextEditDataBindingAccess = class(TcxBoldTextEditDataBinding); + +procedure TcxBoldExtLookupComboBox.Paint; +begin + inherited Paint; + if TcxBoldTextEditDataBindingAccess(DataBinding).ValueOrDefinitionInvalid then + Canvas.FrameRect(Bounds, clRed, 2 - Ord(IsNativeStyle)); +end; + +procedure TcxBoldExtLookupComboBox.Initialize; +begin + inherited; + if IsDesigning and not IsLoading then + begin + _ValidateEdit(self); + end; +end; + +{ TcxEditRepositoryExtLookupComboBoxItem } + +class function TcxEditRepositoryExtLookupComboBoxItem.GetEditPropertiesClass: TcxCustomEditPropertiesClass; +begin + Result := TcxBoldExtLookupComboBoxProperties; +end; + +function TcxEditRepositoryExtLookupComboBoxItem.GetProperties: TcxBoldExtLookupComboBoxProperties; +begin + Result := inherited Properties as TcxBoldExtLookupComboBoxProperties; +end; + +procedure TcxEditRepositoryExtLookupComboBoxItem.SetProperties(Value: TcxBoldExtLookupComboBoxProperties); +begin + inherited Properties := Value; +end; + +// TODO: rename TcxEditRepositoryExtLookupComboBoxItem to something unique +{ +initialization + RegisterClasses([TcxEditRepositoryExtLookupComboBoxItem]); + GetRegisteredEditProperties.Register(TcxBoldExtLookupComboBoxProperties, + cxSEditRepositoryExtLookupComboBoxItem); + +finalization + GetRegisteredEditProperties.Unregister(TcxBoldExtLookupComboBoxProperties); +} +end. diff --git a/Source/BoldAwareGUI/BoldDevex/cxBoldLookupComboBox.pas b/Source/BoldAwareGUI/BoldDevex/cxBoldLookupComboBox.pas new file mode 100644 index 0000000..6cff4b4 --- /dev/null +++ b/Source/BoldAwareGUI/BoldDevex/cxBoldLookupComboBox.pas @@ -0,0 +1,655 @@ +unit cxBoldLookupComboBox; + +{$I cxVer.inc} + +// v2.03 - 25 Jan 2011 2007-2011 Daniel Mauric + +interface + +uses +{$IFDEF DELPHI6} + Variants, +{$ENDIF} + Windows, Messages, SysUtils, Classes, Controls, Graphics, + cxClasses, cxContainer, cxCustomData, cxDataStorage, + cxLookAndFeels, cxEdit, + cxEditConsts, cxDropDownEdit, + cxLookupEdit, + cxBoldLookupEdit, + cxLookupGrid, + cxLookupBoldGrid, + cxFilterControlUtils, + + cxGridBoldSupportUnit, + cxBoldEditors, + + BoldListHandleFollower, + BoldComboBox, // TODO: it's only neede for TBoldComboListController, perhaps we can replace it + BoldControlPack, +// BoldStringControlPack, + BoldAbstractListHandle, + BoldElements, + BoldHandles, + BoldComponentValidator; + +type + { TcxBoldLookupComboBoxProperties } + + TcxBoldLookupComboBoxProperties = class(TcxCustomBoldLookupEditProperties) + private + FGrid: TcxCustomLookupBoldGrid; + function GetBoldListHandle: TBoldAbstractListHandle; + function GetGrid: TcxCustomLookupBoldGrid; +// function GetGridMode: Boolean; + function GetListColumns: TcxLookupBoldGridColumns; + function GetListOptions: TcxLookupBoldGridOptions; +// function GetListSource: TDataSource; + function GetOnSortingChanged: TNotifyEvent; +// procedure SetGridMode(Value: Boolean); + procedure SetListColumns(Value: TcxLookupBoldGridColumns); + procedure SetListOptions(Value: TcxLookupBoldGridOptions); +// procedure SetListSource(Value: TDataSource); + procedure SetOnSortingChanged(Value: TNotifyEvent); + procedure SetBoldListHandle(const Value: TBoldAbstractListHandle); + protected + function GetLookupGridClass: TcxCustomLookupBoldGridClass; virtual; + procedure ListOptionsChanged(Sender: TObject); virtual; + // LookupGrid methods + function GetLookupGridColumnCount: Integer; override; + function GetLookupGridControl: TWinControl; override; + function GetLookupGridDataController: TcxCustomDataController; override; + function GetLookupGridVisualAreaPreferredWidth: Integer; override; + function GetLookupGridNearestPopupHeight(AHeight: Integer): Integer; override; + function GetLookupGridPopupHeight(ADropDownRowCount: Integer): Integer; override; + function IsLookupGridMouseOverList(const P: TPoint): Boolean; override; + procedure LookupGridInitEvents(AOnClick, AOnFocusedRowChanged: TNotifyEvent; + AOnCloseUp: cxLookupEdit.TcxLookupGridCloseUpEvent); override; + procedure LookupGridInitLookAndFeel(ALookAndFeel: TcxLookAndFeel; AColor: TColor; AFont: TFont); override; + procedure LookupGridLockMouseMove; override; + procedure LookupGridMakeFocusedRowVisible; override; + procedure LookupGridUnlockMouseMove; override; + // BoldLookupGrid methods + procedure BoldLookupGridBeginUpdate; override; +// procedure BoldLookupGridCheckColumnByFieldName(const AFieldName: string); override; +// procedure BoldLookupGridCreateColumnsByFieldNames(const AFieldNames: string); override; + procedure BoldLookupGridEndUpdate; override; +// function GetBoldLookupGridColumnField(AIndex: Integer): TField; override; +// function GetBoldLookupGridColumnFieldName(AIndex: Integer): string; override; +// function GetBoldLookupGridColumnIndexByFieldName(const AFieldName: string): Integer; override; + function GetBoldLookupGridDataController: TcxBoldDataController; override; + procedure SetStoredValue(aValue: Variant; aBoldHandle: TBoldElementHandle; aEdit: TcxCustomEdit; aFollower: TBoldFollower; var aDone: boolean); override; + function CanEdit(aBoldHandle: TBoldElementHandle; aFollower: TBoldFollower): boolean; override; + public + constructor Create(AOwner: TPersistent); override; + destructor Destroy; override; + procedure Assign(Source: TPersistent); override; + class function GetContainerClass: TcxContainerClass; override; + property Grid: TcxCustomLookupBoldGrid read GetGrid; +// property LookupListFollower: TBoldFollower read GetListFollower; + published + property BoldLookupListHandle: TBoldAbstractListHandle read GetBoldListHandle write SetBoldListHandle; +// property BoldLookupListProperties: TBoldComboListController read fBoldListProperties write SetBoldListProperties; +// property BoldRowProperties: TBoldStringFollowerController read fBoldRowProperties write SetRowProperties; + + property BoldSelectChangeAction; + property BoldSetValueExpression; + + property Alignment; + property AutoSelect; + property AssignedValues; + property ButtonGlyph; + property CaseSensitiveSearch; + property CharCase; + property ClearKey; + property DropDownAutoSize; + property DropDownHeight; + property DropDownListStyle; + property DropDownRows; + property DropDownSizeable; + property DropDownWidth; +// property GridMode: Boolean read GetGridMode write SetGridMode default False; + property HideSelection; + property ImeMode; + property ImeName; + property ImmediateDropDown; +// property ImmediatePost; + property IncrementalFiltering; + property IncrementalFilteringOptions; +// property KeyFieldNames; + property ListColumns: TcxLookupBoldGridColumns read GetListColumns write SetListColumns; +// property ListFieldNames; + property ListFieldIndex; + property ListOptions: TcxLookupBoldGridOptions read GetListOptions write SetListOptions; +// property ListSource: TDataSource read GetListSource write SetListSource; + property MaxLength; + property OEMConvert; + property PopupAlignment; + property PostPopupValueOnTab; + property ReadOnly; + property Revertable; + property UseLeftAlignmentOnEditing; + property ValidateOnEnter; + property OnChange; + property OnCloseUp; + property OnEditValueChanged; + property OnInitPopup; + property OnNewLookupDisplayText; + property OnPopup; + property OnSortingChanged: TNotifyEvent read GetOnSortingChanged write SetOnSortingChanged; + property OnValidate; + end; + + { TcxCustomBoldLookupComboBox } + + TcxCustomBoldLookupComboBox = class(TcxCustomBoldLookupEdit) + private + function GetProperties: TcxBoldLookupComboBoxProperties; + function GetActiveProperties: TcxBoldLookupComboBoxProperties; + procedure SetProperties(Value: TcxBoldLookupComboBoxProperties); + public + class function GetPropertiesClass: TcxCustomEditPropertiesClass; override; + property ActiveProperties: TcxBoldLookupComboBoxProperties + read GetActiveProperties; + property EditValue; + property Properties: TcxBoldLookupComboBoxProperties read GetProperties + write SetProperties; + property Text; + end; + + { TcxBoldLookupComboBox } + + TcxBoldNBLookupComboBox = class(TcxCustomBoldLookupComboBox) + published + property Anchors; + property AutoSize; + property BeepOnEnter; + property Constraints; + property DragCursor; + property DragKind; + property DragMode; + property Enabled; + property ImeMode; + property ImeName; + property ParentColor; + property ParentFont; + property ParentShowHint; + property PopupMenu; + property Properties; + property EditValue; + property ShowHint; + property Style; + property StyleDisabled; + property StyleFocused; + property StyleHot; + property TabOrder; + property TabStop; + property Visible; + property OnClick; +{$IFDEF DELPHI5} + property OnContextPopup; +{$ENDIF} + property OnDblClick; + property OnEditing; + property OnEnter; + property OnExit; + property OnKeyDown; + property OnKeyPress; + property OnKeyUp; + property OnMouseDown; + property OnMouseMove; + property OnMouseUp; + end; + + { TcxBoldLookupComboBox } + + TcxBoldLookupComboBox = class(TcxCustomBoldLookupComboBox, IBoldValidateableComponent, IBoldOCLComponent) + private + function GetDataBinding: TcxBoldTextEditDataBinding; + procedure SetDataBinding(Value: TcxBoldTextEditDataBinding); +// procedure CMGetDataLink(var Message: TMessage); message CM_GETDATALINK; + protected + class function GetDataBindingClass: TcxEditDataBindingClass; override; + procedure Initialize; override; + procedure Paint; override; + published + property Anchors; + property AutoSize; + property BeepOnEnter; + property Constraints; + property DragCursor; + property DragKind; + property DataBinding: TcxBoldTextEditDataBinding read GetDataBinding write SetDataBinding implements IBoldValidateableComponent, IBoldOCLComponent; + property DragMode; + property Enabled; + property ImeMode; + property ImeName; + property ParentColor; + property ParentFont; + property ParentShowHint; + property PopupMenu; + property Properties; + property ShowHint; + property Style; + property StyleDisabled; + property StyleFocused; + property StyleHot; + property TabOrder; + property TabStop; + property Visible; + property OnClick; +{$IFDEF DELPHI5} + property OnContextPopup; +{$ENDIF} + property OnDblClick; + property OnEditing; + property OnEnter; + property OnExit; + property OnKeyDown; + property OnKeyPress; + property OnKeyUp; + property OnMouseDown; + property OnMouseMove; + property OnMouseUp; + end; + + { TcxBoldFilterLookupComboBoxHelper } + + TcxBoldFilterLookupComboBoxHelper = class(TcxFilterComboBoxHelper) + protected + class function IsIDefaultValuesProviderNeeded( + AEditProperties: TcxCustomEditProperties): Boolean; override; + public + class function GetFilterEditClass: TcxCustomEditClass; override; + class procedure GetFilterValue(AEdit: TcxCustomEdit; AEditProperties: TcxCustomEditProperties; + var V: Variant; var S: TCaption); override; + class function GetSupportedFilterOperators( + AProperties: TcxCustomEditProperties; + AValueTypeClass: TcxValueTypeClass; + AExtendedSet: Boolean = False): TcxFilterControlOperators; override; + class procedure InitializeProperties(AProperties, + AEditProperties: TcxCustomEditProperties; AHasButtons: Boolean); override; + class function IsValueValid(AValueTypeClass: TcxValueTypeClass; + var Value: Variant): Boolean; override; + end; + +implementation + +uses + cxTextEdit, + + BoldSystem, + BoldQueue; + +type + TControlAccess = class(TControl); + +{ TcxBoldLookupComboBoxProperties } + +constructor TcxBoldLookupComboBoxProperties.Create(AOwner: TPersistent); +//var +// lMatchObject: TComponent; +begin + inherited Create(AOwner); +{ if aOwner is TComponent then + lMatchObject := aOwner as TComponent + else + lMatchObject := nil; +} + FGrid := GetLookupGridClass.Create(nil); + FGrid.IsPopupControl := True; + FGrid.Options.OnChanged := ListOptionsChanged; + InitializeDataController; +end; + +destructor TcxBoldLookupComboBoxProperties.Destroy; +begin + DeinitializeDataController; + FGrid.Free; + FGrid := nil; + inherited Destroy; +end; + +procedure TcxBoldLookupComboBoxProperties.Assign(Source: TPersistent); +begin + if Source is TcxBoldLookupComboBoxProperties then + begin + BeginUpdate; + try +// GridMode := TcxBoldLookupComboBoxProperties(Source).GridMode; + ListOptions := TcxBoldLookupComboBoxProperties(Source).ListOptions; + if not IsDefinedByLookup then + begin + BoldSetValueExpression := TcxBoldLookupComboBoxProperties(Source).BoldSetValueExpression; + BoldSelectChangeAction := TcxBoldLookupComboBoxProperties(Source).BoldSelectChangeAction; + BoldLookupListHandle := TcxBoldLookupComboBoxProperties(Source).BoldLookupListHandle; +// ListSource := TcxBoldLookupComboBoxProperties(Source).ListSource; + ListColumns := TcxBoldLookupComboBoxProperties(Source).ListColumns; + end; + OnSortingChanged := TcxBoldLookupComboBoxProperties(Source).OnSortingChanged; + inherited Assign(Source); + if IsDefinedByLookup then + ListColumns := TcxBoldLookupComboBoxProperties(Source).ListColumns; + // DisplayAll is needed to make sure DataController is up to date, + // otherwise it will get updated in next onIdle and by then it will be too late and it will be interpreted as a modification + TBoldQueueable.DisplayAll; + finally + EndUpdate; + end + end + else + inherited Assign(Source); +end; + +class function TcxBoldLookupComboBoxProperties.GetContainerClass: TcxContainerClass; +begin + Result := TcxBoldLookupComboBox; +end; + +function TcxBoldLookupComboBoxProperties.GetLookupGridClass: TcxCustomLookupBoldGridClass; +begin + Result := TcxCustomLookupBoldGrid; +end; + +procedure TcxBoldLookupComboBoxProperties.ListOptionsChanged(Sender: TObject); +begin + Changed; +end; + +// LookupGrid + +function TcxBoldLookupComboBoxProperties.GetLookupGridColumnCount: Integer; +begin + Result := ListColumns.Count; +end; + +function TcxBoldLookupComboBoxProperties.GetLookupGridControl: TWinControl; +begin + Result := Grid; +end; + +function TcxBoldLookupComboBoxProperties.GetLookupGridDataController: TcxCustomDataController; +begin + Result := Grid.DataController; +end; + +function TcxBoldLookupComboBoxProperties.GetLookupGridVisualAreaPreferredWidth: Integer; +var + I: Integer; +begin + Result := 0; + for I := 0 to ListColumns.Count - 1 do + Inc(Result, ListColumns[I].Width); +end; + +function TcxBoldLookupComboBoxProperties.GetLookupGridNearestPopupHeight( + AHeight: Integer): Integer; +begin + Result := Grid.GetNearestPopupHeight(AHeight); +end; + +function TcxBoldLookupComboBoxProperties.GetLookupGridPopupHeight(ADropDownRowCount: Integer): Integer; +begin + Result := Grid.GetPopupHeight(ADropDownRowCount); +end; + +function TcxBoldLookupComboBoxProperties.IsLookupGridMouseOverList(const P: TPoint): Boolean; +begin + Result := Grid.IsMouseOverList(P); +end; + +procedure TcxBoldLookupComboBoxProperties.LookupGridInitEvents(AOnClick, AOnFocusedRowChanged: TNotifyEvent; + AOnCloseUp: cxLookupEdit.TcxLookupGridCloseUpEvent); +begin + Grid.OnClick := AOnClick; + Grid.OnFocusedRowChanged := AOnFocusedRowChanged; + Grid.OnCloseUp := AOnCloseUp; +end; + +procedure TcxBoldLookupComboBoxProperties.LookupGridInitLookAndFeel(ALookAndFeel: TcxLookAndFeel; + AColor: TColor; AFont: TFont); +begin + Grid.LookAndFeel.MasterLookAndFeel := ALookAndFeel; + Grid.Color := AColor; + Grid.Font := AFont; +end; + +procedure TcxBoldLookupComboBoxProperties.LookupGridLockMouseMove; +begin + Grid.LockPopupMouseMove; +end; + +procedure TcxBoldLookupComboBoxProperties.LookupGridMakeFocusedRowVisible; +begin + Grid.MakeFocusedRowVisible; +end; + +procedure TcxBoldLookupComboBoxProperties.LookupGridUnlockMouseMove; +begin + TControlAccess(Grid).MouseCapture := False; +end; + +// BoldLookupGrid + +procedure TcxBoldLookupComboBoxProperties.BoldLookupGridBeginUpdate; +begin + Grid.BeginUpdate; +end; + +procedure TcxBoldLookupComboBoxProperties.BoldLookupGridEndUpdate; +begin + Grid.EndUpdate; +end; + +function TcxBoldLookupComboBoxProperties.GetBoldLookupGridDataController: TcxBoldDataController; +begin + if Grid <> nil then + Result := Grid.DataController + else + Result := nil; +end; + +function TcxBoldLookupComboBoxProperties.GetGrid: TcxCustomLookupBoldGrid; +begin + Result := FGrid; +end; + +{function TcxBoldLookupComboBoxProperties.GetGridMode: Boolean; +begin + Result := inherited IsUseLookupList; +end;} + +function TcxBoldLookupComboBoxProperties.GetListColumns: TcxLookupBoldGridColumns; +begin + Result := Grid.Columns; +end; + +function TcxBoldLookupComboBoxProperties.GetListOptions: TcxLookupBoldGridOptions; +begin + Result := Grid.Options; +end; + +function TcxBoldLookupComboBoxProperties.GetOnSortingChanged: TNotifyEvent; +begin + Result := Grid.DataController.OnSortingChanged; +end; + +{procedure TcxBoldLookupComboBoxProperties.SetGridMode(Value: Boolean); +begin + inherited IsUseLookupList := Value; +end;} + +procedure TcxBoldLookupComboBoxProperties.SetListColumns(Value: TcxLookupBoldGridColumns); +begin + Grid.Columns := Value; // TODO: recreate? + CheckLookupColumn; + CheckDisplayColumnIndex; +end; + +procedure TcxBoldLookupComboBoxProperties.SetListOptions(Value: TcxLookupBoldGridOptions); +begin + Grid.Options := Value; +end; + +procedure TcxBoldLookupComboBoxProperties.SetOnSortingChanged(Value: TNotifyEvent); +begin + Grid.DataController.OnSortingChanged := Value; +end; + +function TcxBoldLookupComboBoxProperties.GetBoldListHandle: TBoldAbstractListHandle; +begin + result := DataController.BoldHandle; +end; + +procedure TcxBoldLookupComboBoxProperties.SetBoldListHandle( + const Value: TBoldAbstractListHandle); +begin + DataController.BoldHandle := Value; +end; + +procedure TcxBoldLookupComboBoxProperties.SetStoredValue( + aValue: Variant; aBoldHandle: TBoldElementHandle; aEdit: TcxCustomEdit; aFollower: TBoldFollower; var aDone: boolean); +var + lItemIndex: Integer; + lSelectedElement: TBoldElement; +begin +// inherited; + +// if TcxCustomComboBox(aEdit).ILookupData.CurrentKey <> null then + if (not VarIsNull(aValue)) and (aValue <> -1) then + begin + lItemIndex := aValue; //(aEdit as TcxCustomComboBox).ItemIndex; + lSelectedElement := DataController.BoldHandle.List[lItemIndex]; //(DataController.Follower.Element as TBoldList)[lItemIndex]; + + InternalComboSetValue(aBoldHandle, aFollower, lSelectedElement, BoldSelectChangeAction, BoldSetValueExpression, BoldLookupListHandle, AValue); + // aEdit.EditModified := false + end; + aDone := true; +end; + +function TcxBoldLookupComboBoxProperties.CanEdit( + aBoldHandle: TBoldElementHandle; aFollower: TBoldFollower): boolean; +begin + result := Assigned(BoldLookupListHandle) and (BoldLookupListHandle.Count > 0); +end; + +{ TcxCustomBoldLookupComboBox } + +class function TcxCustomBoldLookupComboBox.GetPropertiesClass: TcxCustomEditPropertiesClass; +begin + Result := TcxBoldLookupComboBoxProperties; +end; + +function TcxCustomBoldLookupComboBox.GetProperties: TcxBoldLookupComboBoxProperties; +begin + Result := TcxBoldLookupComboBoxProperties(FProperties); +end; + +function TcxCustomBoldLookupComboBox.GetActiveProperties: TcxBoldLookupComboBoxProperties; +begin + Result := TcxBoldLookupComboBoxProperties(InternalGetActiveProperties); +end; + +procedure TcxCustomBoldLookupComboBox.SetProperties(Value: TcxBoldLookupComboBoxProperties); +begin + FProperties.Assign(Value); +end; + +{ TcxBoldLookupComboBox } + +class function TcxBoldLookupComboBox.GetDataBindingClass: TcxEditDataBindingClass; +begin + Result := TcxBoldLookupEditDataBinding; +end; + +function TcxBoldLookupComboBox.GetDataBinding: TcxBoldTextEditDataBinding; +begin + Result := TcxBoldTextEditDataBinding(FDataBinding); +end; + +procedure TcxBoldLookupComboBox.SetDataBinding(Value: TcxBoldTextEditDataBinding); +begin + FDataBinding.Assign(Value); +end; + +{procedure TcxBoldLookupComboBox.CMGetDataLink(var Message: TMessage); +begin + Message.Result := Integer(GetcxDBEditDataLink(Self)); +end;} + +type + TcxBoldTextEditDataBindingAccess = class(TcxBoldTextEditDataBinding); + +procedure TcxBoldLookupComboBox.Paint; +begin + inherited Paint; + if TcxBoldTextEditDataBindingAccess(DataBinding).ValueOrDefinitionInvalid then + Canvas.FrameRect(Bounds, clRed, 2 - Ord(IsNativeStyle)); +end; + +procedure TcxBoldLookupComboBox.Initialize; +begin + inherited; + if IsDesigning and not IsLoading then + begin + _ValidateEdit(self); + end; +end; + +{ TcxBoldFilterLookupComboBoxHelper } + +class function TcxBoldFilterLookupComboBoxHelper.GetFilterEditClass: TcxCustomEditClass; +begin + Result := TcxBoldLookupComboBox; +end; + +class procedure TcxBoldFilterLookupComboBoxHelper.GetFilterValue(AEdit: TcxCustomEdit; + AEditProperties: TcxCustomEditProperties; var V: Variant; var S: TCaption); +begin + V := AEdit.EditValue; + S := TcxCustomTextEdit(AEdit).ILookupData.GetDisplayText(V); +end; + +class function TcxBoldFilterLookupComboBoxHelper.GetSupportedFilterOperators( + AProperties: TcxCustomEditProperties; + AValueTypeClass: TcxValueTypeClass; + AExtendedSet: Boolean = False): TcxFilterControlOperators; +begin + Result := [fcoEqual, fcoNotEqual, fcoBlanks, fcoNonBlanks]; +end; + +class procedure TcxBoldFilterLookupComboBoxHelper.InitializeProperties(AProperties, + AEditProperties: TcxCustomEditProperties; AHasButtons: Boolean); +begin + inherited InitializeProperties(AProperties, AEditProperties, AHasButtons); + with TcxCustomLookupEditProperties(AProperties) do + begin + DropDownAutoSize := True; + DropDownListStyle := lsFixedList; + DropDownSizeable := True; + IncrementalFiltering := True; + end; +end; + +class function TcxBoldFilterLookupComboBoxHelper.IsValueValid(AValueTypeClass: TcxValueTypeClass; + var Value: Variant): Boolean; +begin + Result := True; +end; + +class function TcxBoldFilterLookupComboBoxHelper.IsIDefaultValuesProviderNeeded( + AEditProperties: TcxCustomEditProperties): Boolean; +begin + Result := TcxCustomBoldLookupEditProperties(AEditProperties).IsDefinedByLookup; +end; + +initialization +// scxSEditRepositoryLookupComboBoxItem = 'LookupComboBox|Represents a lookup combo box control'; +// InternalAdd('scxSEditRepositoryLookupComboBoxItem', @scxSEditRepositoryLookupComboBoxItem); +// TODO: extract sting to a resourcestring like above + GetRegisteredEditProperties.Register(TcxBoldLookupComboBoxProperties, 'BoldLookupComboBox|Represents a bold aware lookup combo box control'); + FilterEditsController.Register(TcxBoldLookupComboBoxProperties, TcxBoldFilterLookupComboBoxHelper); + +finalization + FilterEditsController.Unregister(TcxBoldLookupComboBoxProperties, TcxBoldFilterLookupComboBoxHelper); + +end. diff --git a/Source/BoldAwareGUI/BoldDevex/cxBoldLookupEdit.pas b/Source/BoldAwareGUI/BoldDevex/cxBoldLookupEdit.pas new file mode 100644 index 0000000..549049c --- /dev/null +++ b/Source/BoldAwareGUI/BoldDevex/cxBoldLookupEdit.pas @@ -0,0 +1,804 @@ +unit cxBoldLookupEdit; + +interface + +// v2.03 - 25 Jan 2011 2007-2011 Daniel Mauric + +uses + classes, + cxLookupEdit, + cxDataStorage, + cxClasses, + cxEdit, + cxContainer, + cxBoldEditors, + cxGridBoldSupportUnit, + dxCoreClasses, + + BoldElements, + BoldControlPack, + BoldControlsDefs, + BoldDefs, + BoldHandles, + BoldComponentValidator; + +type + TcxCustomBoldLookupEditProperties = class; + + { TcxCustomBoldLookupEditLookupData } + + TcxCustomBoldLookupEditLookupData = class(TcxCustomLookupEditLookupData) + private +// fCurrentElement: TBoldElement; // ? + function GetDataController: TcxBoldDataController; + function GetProperties: TcxCustomBoldLookupEditProperties; + protected + procedure DoSetCurrentKey(ARecordIndex: Integer); override; + procedure DoSyncGrid; override; + property DataController: TcxBoldDataController read GetDataController; + property Properties: TcxCustomBoldLookupEditProperties read GetProperties; + end; + + { TcxCustomBoldLookupEditProperties } + + TcxCustomBoldLookupEditProperties = class(TcxCustomLookupEditProperties, IcxBoldEditProperties, IBoldValidateableComponent) + private +// FCachedLookupSource: TDataSource; + FCaseSensitiveSearch: Boolean; + FLockGridModeCount: Integer; +// FLookupField: TField; +// FLookupList: TcxLookupList; +// FLookupSource: TDataSource; +// FSyncLookup: Boolean; + fBoldSelectChangeAction: TBoldComboSelectChangeAction; + fBoldSetValueExpression: TBoldExpression; +// function GetIsUseLookupList: Boolean; +// function GetKeyFieldNames: string; +// function GetListField: TField; + function GetListFieldIndex: Integer; +// function GetListFieldNames: string; +// procedure SetIsUseLookupList(Value: Boolean); + procedure SetBoldSelectChangeAction( + const Value: TBoldComboSelectChangeAction); +// procedure SetKeyFieldNames(const Value: string); + procedure SetListFieldIndex(Value: Integer); + procedure SetBoldSetValueExpression(const Value: TBoldExpression); +// procedure SetListFieldNames(const Value: string); + protected + // IcxBoldEditProperties + procedure SetStoredValue(aValue: Variant; aBoldHandle: TBoldElementHandle; aEdit: TcxCustomEdit; aFollower: TBoldFollower; var aDone: boolean); virtual; + function BoldElementToEditValue(aFollower: TBoldFollower; aElement: TBoldElement; aEdit: TcxCustomEdit): variant; + function CanEdit(aBoldHandle: TBoldElementHandle; aFollower: TBoldFollower): boolean; virtual; + // IBoldValidateableComponent + function ValidateComponent(ComponentValidator: TBoldComponentValidator; NamePrefix: string): Boolean; + // BoldLookupGrid methods + procedure BoldLookupGridBeginUpdate; virtual; +// procedure BoldLookupGridCheckColumnByFieldName(const AFieldName: string); virtual; // if a column does not exist, then create it with zero index +// procedure BoldLookupGridCreateColumnsByFieldNames(const AFieldNames: string); virtual; + procedure BoldLookupGridEndUpdate; virtual; +// function GetBoldLookupGridColumnField(AIndex: Integer): TField; virtual; +// function GetBoldLookupGridColumnFieldName(AIndex: Integer): string; virtual; +// function GetBoldLookupGridColumnIndexByFieldName(const AFieldName: string): Integer; virtual; + function GetBoldLookupGridDataController: TcxBoldDataController; virtual; + + function CanDisplayArbitraryEditValue: Boolean; + procedure CheckLookup; virtual; + procedure CheckLookupColumn; virtual; +// procedure CheckLookupList; + procedure DefaultValuesProviderDestroyed; override; + procedure DefineByLookupError; + procedure DoChanged; override; + function GetAlwaysPostEditValue: Boolean; override; + function FindByText(AItemIndex: Integer; const AText: string; APartialCompare: Boolean): Integer; override; + function GetDisplayColumnIndex: Integer; override; + function GetDisplayLookupText(const AKey: TcxEditValue): string; override; + function GetDefaultHorzAlignment: TAlignment; override; + function GetDefaultMaxLength: Integer; override; + function GetIncrementalFiltering: Boolean; override; + function GetKeyByRecordIndex(ARecordIndex: Integer): Variant; + class function GetLookupDataClass: TcxInterfacedPersistentClass; override; +// function GetLookupResultFieldName: string; + function GetNullKey: Variant; override; + function GetRecordIndexByKey(const AKey: Variant): Integer; + function IsPickMode: Boolean; override; + procedure LockDataChanged; override; + procedure LookupSourceFreeNotification(Sender: TComponent); virtual; + procedure SetDisplayColumnIndex(Value: Integer); override; +// procedure SetLookupField(ALookupField: TField); + procedure UnlockDataChanged; override; +// property InSyncLookup: Boolean read FSyncLookup; +// property IsUseLookupList: Boolean read GetIsUseLookupList write SetIsUseLookupList; + public + constructor Create(AOwner: TPersistent); override; + destructor Destroy; override; + procedure Assign(Source: TPersistent); override; + class function GetContainerClass: TcxContainerClass; override; +// function GetDataField: TField; +// function GetEditValueSource(AEditFocused: Boolean): TcxDataEditValueSource; override; +// function GetLookupField: TField; +// function IsLookupField: Boolean; override; + procedure PrepareDisplayValue(const AEditValue: TcxEditValue; + var DisplayValue: TcxEditValue; AEditFocused: Boolean); override; + property CaseSensitiveSearch: Boolean read FCaseSensitiveSearch + write FCaseSensitiveSearch default False; + property DataController: TcxBoldDataController read GetBoldLookupGridDataController; +// property KeyFieldNames: string read GetKeyFieldNames write SetKeyFieldNames; +// property ListField: TField read GetListField; +// property ListFieldNames: string read GetListFieldNames write SetListFieldNames stored False; + property ListFieldIndex: Integer read GetListFieldIndex write SetListFieldIndex default 0; + +// property BoldRowProperties: TBoldStringFollowerController read fBoldRowProperties write SetRowProperties; + property BoldSelectChangeAction: TBoldComboSelectChangeAction read fBoldSelectChangeAction write SetBoldSelectChangeAction default bdcsSetValue; + property BoldSetValueExpression: TBoldExpression read fBoldSetValueExpression write SetBoldSetValueExpression; + end; + + { TcxCustomBoldLookupEdit } + + TcxCustomBoldLookupEdit = class(TcxCustomLookupEdit) + private + function GetProperties: TcxCustomBoldLookupEditProperties; + function GetActiveProperties: TcxCustomBoldLookupEditProperties; + procedure SetProperties(Value: TcxCustomBoldLookupEditProperties); + protected + function GetClearValue: TcxEditValue; override; + function IsValidChar(AChar: Char): Boolean; override; + function ItemIndexToLookupKey(AItemIndex: Integer): TcxEditValue; override; + function LookupKeyToEditValue(const AKey: TcxEditValue): TcxEditValue; override; +// function LookupKeyToItemIndex(const AKey: TcxEditValue): Integer; override; + procedure PopupWindowClosed(Sender: TObject); override; + procedure PrepareDisplayValue(const AEditValue: TcxEditValue; + var DisplayValue: TcxEditValue; AEditFocused: Boolean); override; + public + class function GetPropertiesClass: TcxCustomEditPropertiesClass; override; + property ActiveProperties: TcxCustomBoldLookupEditProperties + read GetActiveProperties; + property Properties: TcxCustomBoldLookupEditProperties read GetProperties + write SetProperties; + end; + + { TcxBoldLookupEditDataBinding } + + TcxBoldLookupEditDataBinding = class(TcxBoldTextEditDataBinding) + protected + function IsLookupControl: Boolean; override; + end; + +implementation + +uses +{$IFDEF DELPHI6} + VDBConsts, +{$ENDIF} + Contnrs, + cxDropDownEdit, + Variants, + SysUtils, + + BoldSystem; + +{ TcxCustomBoldLookupEditLookupData } + +procedure TcxCustomBoldLookupEditLookupData.DoSetCurrentKey(ARecordIndex: Integer); +begin + FCurrentKey := Properties.GetKeyByRecordIndex(ARecordIndex); +end; + +type + TcxCustomEditAccess = Class(TcxCustomEdit) + end; + +procedure TcxCustomBoldLookupEditLookupData.DoSyncGrid; +var + lcxBoldEditDataBinding: TcxBoldEditDataBinding; + lBoldElement: TBoldElement; +begin + if Edit is TcxCustomEdit and (TcxCustomEditAccess(Edit).DataBinding is TcxBoldEditDataBinding) then + begin + lcxBoldEditDataBinding := TcxCustomEditAccess(Edit).DataBinding as TcxBoldEditDataBinding; + lBoldElement := lcxBoldEditDataBinding.Follower.Element; + if Assigned(DataController) and Assigned(lBoldElement) and (DataController.Follower.Element is TBoldList) then + begin + Properties.LockDataChanged; + try + DataController.RecNo := (DataController.Follower.Element as TBoldList).IndexOf(lBoldElement); + finally + Properties.UnlockDataChanged; + end; + end; + end; +// DataController.Follower.Element. +{ if DataController <> nil then + try + Properties.LockDataChanged; + try + DataController.LocateByKey(GetCurrentKey); + finally + Properties.UnlockDataChanged; + end; + except + on EVariantError do; + on EDatabaseError do; + end; +} +end; + +function TcxCustomBoldLookupEditLookupData.GetDataController: TcxBoldDataController; +begin + Result := Properties.DataController; +end; + +function TcxCustomBoldLookupEditLookupData.GetProperties: TcxCustomBoldLookupEditProperties; +begin + Result := TcxCustomBoldLookupEditProperties(inherited Properties); +end; + +{ TcxCustomBoldLookupEditProperties } + +constructor TcxCustomBoldLookupEditProperties.Create(AOwner: TPersistent); +begin + inherited; + BoldSelectChangeAction := bdcsSetValue; +end; + +destructor TcxCustomBoldLookupEditProperties.Destroy; +begin +// SetLookupField(nil); +// FLookupList.Free; +// FLookupList := nil; +// FreeAndNil(FCachedLookupSource); + inherited Destroy; +end; + +procedure TcxCustomBoldLookupEditProperties.Assign(Source: TPersistent); +begin + if Source is TcxCustomBoldLookupEditProperties then + begin + BeginUpdate; + try + inherited Assign(Source); + CaseSensitiveSearch := TcxCustomBoldLookupEditProperties(Source).CaseSensitiveSearch; +// if not IsDefinedByLookup then +// KeyFieldNames := TcxCustomBoldLookupEditProperties(Source).KeyFieldNames; + finally + EndUpdate; + end + end + else + inherited Assign(Source); +end; + +class function TcxCustomBoldLookupEditProperties.GetContainerClass: TcxContainerClass; +begin +// result := inherited GetContainerClass; + Result := TcxCustomBoldLookupEdit; +end; +{ +function TcxCustomBoldLookupEditProperties.GetDataField: TField; +var + ADefaultValuesProvider: TcxCustomEditDefaultValuesProvider; +begin + Result := nil; + if IDefaultValuesProvider <> nil then + begin + ADefaultValuesProvider := TcxCustomEditDefaultValuesProvider(IDefaultValuesProvider.GetInstance); + if ADefaultValuesProvider is TcxCustomDBEditDefaultValuesProvider then + Result := TcxCustomDBEditDefaultValuesProvider(ADefaultValuesProvider).Field; + end; +end; +} +{ +function TcxCustomBoldLookupEditProperties.GetEditValueSource(AEditFocused: Boolean): TcxDataEditValueSource; +begin + if GetLookupField <> nil then + begin + if AEditFocused then + Result := evsKey + else + Result := evsText; + end + else + Result := inherited GetEditValueSource(AEditFocused); +end; +} +{ +function TcxCustomBoldLookupEditProperties.GetLookupField: TField; +begin + Result := GetDataField; + if (Result <> nil) and (not Result.Lookup or (csDestroying in Result.ComponentState)) then + Result := nil; +end; + +function TcxCustomBoldLookupEditProperties.IsLookupField: Boolean; +begin + Result := GetLookupField <> nil; +end; +} +procedure TcxCustomBoldLookupEditProperties.PrepareDisplayValue( + const AEditValue: TcxEditValue; var DisplayValue: TcxEditValue; + AEditFocused: Boolean); +var + lRecordIndex, lItemIndex: integer; +begin + lRecordIndex := GetRecordIndexByKey(AEditValue); + lItemIndex := GetListIndex; + if (lItemIndex <> -1) and (lRecordIndex <> -1) then + begin + DisplayValue := DataController.Values[lRecordIndex, lItemIndex]; + if VarIsNull(DisplayValue) then + begin + DisplayValue := DataController.Values[lRecordIndex, lItemIndex]; + if VarIsNull(DisplayValue) then + DisplayValue := ''; + end; + end + else + inherited PrepareDisplayValue(AEditValue, DisplayValue, AEditFocused); +end; + +procedure TcxCustomBoldLookupEditProperties.BoldLookupGridBeginUpdate; +begin +end; +{ +procedure TcxCustomBoldLookupEditProperties.BoldLookupGridCheckColumnByFieldName(const AFieldName: string); +begin +end; + +procedure TcxCustomBoldLookupEditProperties.BoldLookupGridCreateColumnsByFieldNames(const AFieldNames: string); +begin +end; +} +procedure TcxCustomBoldLookupEditProperties.BoldLookupGridEndUpdate; +begin +end; +{ +function TcxCustomBoldLookupEditProperties.GetBoldLookupGridColumnField(AIndex: Integer): TField; +begin + Result := nil; +end; +} +{ +function TcxCustomBoldLookupEditProperties.GetBoldLookupGridColumnFieldName(AIndex: Integer): string; +begin + Result := ''; +end; + +function TcxCustomBoldLookupEditProperties.GetBoldLookupGridColumnIndexByFieldName(const AFieldName: string): Integer; +begin + Result := -1; +end; +} +function TcxCustomBoldLookupEditProperties.GetAlwaysPostEditValue: Boolean; +begin + result := true; +end; + +function TcxCustomBoldLookupEditProperties.GetBoldLookupGridDataController: TcxBoldDataController; +begin + Result := nil; +end; + +function TcxCustomBoldLookupEditProperties.CanDisplayArbitraryEditValue: Boolean; +//var +// AKeyField: TField; +begin + Result := DropDownListStyle = lsEditList; +{ + Result := False; // TODO: method in DataController? + if (KeyFieldNames <> '') and not IsMultipleFieldNames(KeyFieldNames) and + (DataController <> nil) and (DataController.DataSet <> nil) then + begin + AKeyField := DataController.DataSet.FindField(KeyFieldNames); + if AKeyField <> nil then + Result := (AKeyField = GetListField) and + ((DropDownListStyle = lsEditList) or (AKeyField is TStringField)); + end; +} +end; + +procedure TcxCustomBoldLookupEditProperties.CheckLookup; +begin +// Assert(false); +// SetLookupField(GetLookupField); +// CheckListSource; +end; + +procedure TcxCustomBoldLookupEditProperties.CheckLookupColumn; +//var +// AFieldName: string; +begin +// Assert(false); +// AFieldName := GetLookupResultFieldName; +// if AFieldName <> '' then +// BoldLookupGridCheckColumnByFieldName(AFieldName); +end; + +{procedure TcxCustomBoldLookupEditProperties.CheckLookupList; +begin + if FLookupList <> nil then + FLookupList.Clear; +// if (DataController <> nil) then +// DataController.DataModeController.GridMode := IsUseLookupList; +end;} + +procedure TcxCustomBoldLookupEditProperties.DefaultValuesProviderDestroyed; +begin + inherited DefaultValuesProviderDestroyed; + BeginUpdate; + try + Changed; + finally + EndUpdate(False); + end; +end; + +procedure TcxCustomBoldLookupEditProperties.DefineByLookupError; +begin + Assert(false); +// DatabaseError(SPropDefByLookup); +end; + +procedure TcxCustomBoldLookupEditProperties.DoChanged; +begin +// CheckLookupList; + CheckLookup; + CheckLookupColumn; + inherited; + + if (owner is TcxCustomEdit) and TcxCustomEdit(owner).IsDesigning and not TcxCustomEdit(owner).IsLoading and Assigned(TcxCustomEditAccess(owner).FDataBinding) then + begin + _ValidateEdit(TcxCustomEdit(owner)); + end; +end; + +function TcxCustomBoldLookupEditProperties.IsPickMode: Boolean; +begin + Result := (DropDownListStyle = lsEditList) and CanDisplayArbitraryEditValue; +end; + +procedure TcxCustomBoldLookupEditProperties.LockDataChanged; +begin + inherited LockDataChanged; + // TODO: if GridMode + if (DataController <> nil) and DataController.IsGridMode then + Inc(FLockGridModeCount); + if FLockGridModeCount <> 0 then + DataController.LockGridModeNotify; +end; + +procedure TcxCustomBoldLookupEditProperties.LookupSourceFreeNotification(Sender: TComponent); +begin + CheckLookup; +end; + +procedure TcxCustomBoldLookupEditProperties.SetDisplayColumnIndex(Value: Integer); +begin + if IsDefinedByLookup then + DefineByLookupError; + inherited SetDisplayColumnIndex(Value); +end; + +procedure TcxCustomBoldLookupEditProperties.UnlockDataChanged; +begin + if FLockGridModeCount <> 0 then + begin + if DataController <> nil then + DataController.UnlockGridModeNotify; + Dec(FLockGridModeCount); + end; + inherited UnlockDataChanged; +end; + +function TcxCustomBoldLookupEditProperties.FindByText(AItemIndex: Integer; + const AText: string; APartialCompare: Boolean): Integer; + +{ function GetLocateOptions: TLocateOptions; + begin + Result := []; + if not CaseSensitiveSearch then + Include(Result, loCaseInsensitive); + if APartialCompare then + Result := Result + [loPartialKey]; + end; + + function GetLocateValue: Variant; + begin + Result := AText; + // TDataSet.Locate does not work with empty strings passed as key values for numeric fields + if (AText = '') and not (DataController.GetItemField(AItemIndex) is TStringField) then + Result := Null; + end; +} +//var +// ADataSet: TDataSet; +// AListFieldName: string; +begin +// if not IsUseLookupList then + begin + Result := inherited FindByText(AItemIndex, AText, APartialCompare); + Exit; + end; + Result := DataController.GetFocusedRecordIndex; +{ + Result := -1; + LockDataChanged; + try +// ADataSet := DataController.DataSet; + AListFieldName := DataController.GetItemFieldName(AItemIndex); + try +// if (ADataSet <> nil) and ADataSet.Active and (AItemIndex <> -1) and +// ADataSet.Locate(AListFieldName, GetLocateValue, GetLocateOptions) then + Result := DataController.GetFocusedRecordIndex; + except + on EDatabaseError do; + on EVariantError do; + end; + finally + UnlockDataChanged; + end; +} +end; + +function TcxCustomBoldLookupEditProperties.GetDisplayColumnIndex: Integer; +begin + Result := inherited GetDisplayColumnIndex; +end; + +function TcxCustomBoldLookupEditProperties.GetDisplayLookupText(const AKey: TcxEditValue): string; +var + ARecordIndex: Integer; + AItemIndex: Integer; +begin + Result := ''; + AItemIndex := GetListIndex; + if (AItemIndex <> -1) and (DataController <> nil) then + begin + ARecordIndex := GetRecordIndexByKey(AKey); + if (ARecordIndex <> -1) then + Result := DataController.DisplayTexts[ARecordIndex, AItemIndex] + end + else + begin + if VarIsStr(AKey) then + Result := AKey + else + Result := inherited GetDisplayLookupText(AKey); + end; +end; + +function TcxCustomBoldLookupEditProperties.GetDefaultHorzAlignment: TAlignment; +begin + Result := inherited GetDefaultHorzAlignment; +end; + +function TcxCustomBoldLookupEditProperties.GetDefaultMaxLength: Integer; +begin + Result := inherited GetDefaultMaxLength; +end; + +function TcxCustomBoldLookupEditProperties.GetIncrementalFiltering: Boolean; +begin + Result := inherited GetIncrementalFiltering; +end; + +class function TcxCustomBoldLookupEditProperties.GetLookupDataClass: TcxInterfacedPersistentClass; +begin + Result := TcxCustomBoldLookupEditLookupData; +end; + +function TcxCustomBoldLookupEditProperties.GetNullKey: Variant; +begin + Result := Null; +end; + +function TcxCustomBoldLookupEditProperties.GetRecordIndexByKey(const AKey: Variant): Integer; +begin + if VarIsNull(AKey) or VarIsEmpty(AKey) or not VarIsType(AKey, varInteger) or (AKey >= DataController.RecordCount) then +// or VarIsType(AKey, varSmallint) or VarIsType(AKey, varShortInt) or VarIsType(AKey, varInt64)) then + result := -1 + else + Result := AKey; +end; + +{function TcxCustomBoldLookupEditProperties.GetIsUseLookupList: Boolean; +begin + Result := FLookupList <> nil; +end;} + +{procedure TcxCustomBoldLookupEditProperties.SetIsUseLookupList(Value: Boolean); +begin + if (FLookupList <> nil) <> Value then + begin + if Value then + begin + FLookupList := TcxLookupList.Create; + end + else + begin + FLookupList.Free; + FLookupList := nil; + end; + Changed; + end; +end;} + +function TcxCustomBoldLookupEditProperties.GetKeyByRecordIndex( + ARecordIndex: Integer): Variant; +begin + if (ARecordIndex <> -1) and (DataController <> nil) then + Result := DataController.GetRecordId(ARecordIndex) + else + Result := Null; +end; + +procedure TcxCustomBoldLookupEditProperties.SetStoredValue( + aValue: Variant; aBoldHandle: TBoldElementHandle; aEdit: TcxCustomEdit; aFollower: TBoldFollower; var aDone: boolean); +begin +// TODO: nothing to do here, subclasse will override, perhaps even make this abstract ? +end; + +procedure TcxCustomBoldLookupEditProperties.SetBoldSelectChangeAction( + const Value: TBoldComboSelectChangeAction); +begin + fBoldSelectChangeAction := Value; +end; + +function TcxCustomBoldLookupEditProperties.GetListFieldIndex: Integer; +begin + Result := inherited DisplayColumnIndex; +end; + +procedure TcxCustomBoldLookupEditProperties.SetListFieldIndex( + Value: Integer); +begin + inherited DisplayColumnIndex := Value; +end; + +function TcxCustomBoldLookupEditProperties.BoldElementToEditValue( + aFollower: TBoldFollower; aElement: TBoldElement; aEdit: TcxCustomEdit): variant; +var + lBoldList: TBoldList; +begin + result := Null; // used to be -1 + if Assigned(DataController) and Assigned(DataController.BoldHandle) and Assigned(aElement) then + begin + lBoldList := DataController.BoldHandle.List; + if Assigned(lBoldList) then + begin + if aElement is TBoldObjectReference then + result := lBoldList.IndexOf( TBoldObjectReference(aElement).BoldObject ) + else + result := lBoldList.IndexOf(aElement); + end; + end; +end; + +type + TcxBoldEditDataBindingAccess = class(TcxBoldEditDataBinding); + TBoldFollowerControllerAccess = class(TBoldFollowerController); + +function TcxCustomBoldLookupEditProperties.ValidateComponent( + ComponentValidator: TBoldComponentValidator; + NamePrefix: string): Boolean; +var + lContext: TBoldElementTypeInfo; + lName: string; + lcxBoldEditDataBinding: TcxBoldEditDataBinding; +begin + if (Owner is TComponent) and (TComponent(Owner).Name <> '') then + lName := TComponent(Owner).Name + else + lName := ClassName; + + result := Assigned(DataController); + if Assigned(DataController) then + begin + lContext := DataController.GetHandleStaticType; + if assigned(lContext) then + begin + result := ComponentValidator.ValidateExpressionInContext( + TBoldFollowerControllerAccess(DataController.BoldProperties).Expression, + lContext, + format('%s %s.BoldProperties.Expression', [NamePrefix, lName]), DataController.BoldProperties.VariableList) and result; // do not localize + if (BoldSelectChangeAction = bdcsSetValue) and (Owner is TcxCustomEdit) then + begin + lcxBoldEditDataBinding := TcxCustomEditAccess(TcxCustomEdit(Owner)).DataBinding as TcxBoldEditDataBinding; + lContext := TcxBoldEditDataBindingAccess(lcxBoldEditDataBinding).GetContextType; + result := ComponentValidator.ValidateExpressionInContext( + BoldSetValueExpression, + lContext, + format('%s %s.BoldSetValueExpression', [NamePrefix, lName]), + lcxBoldEditDataBinding.BoldProperties.VariableList) and result; // do not localize + end; + end; + end; +end; + +function TcxCustomBoldLookupEditProperties.CanEdit( + aBoldHandle: TBoldElementHandle; aFollower: TBoldFollower): boolean; +begin + result := false; +end; + +procedure TcxCustomBoldLookupEditProperties.SetBoldSetValueExpression( + const Value: TBoldExpression); +begin + fBoldSetValueExpression := Value; + if Owner is TcxCustomEdit and (TcxCustomEdit(Owner).IsDesigning) and not (TcxCustomEdit(Owner).IsLoading) then + begin + _ValidateEdit(TcxCustomEdit(Owner)); + end; +end; + +{ TcxCustomBoldLookupEdit } + +class function TcxCustomBoldLookupEdit.GetPropertiesClass: TcxCustomEditPropertiesClass; +begin + Result := TcxCustomBoldLookupEditProperties; +end; + +function TcxCustomBoldLookupEdit.GetClearValue: TcxEditValue; +begin + Result := inherited GetClearValue; +end; + +function TcxCustomBoldLookupEdit.IsValidChar(AChar: Char): Boolean; +begin + Result := True; +end; + +function TcxCustomBoldLookupEdit.ItemIndexToLookupKey(AItemIndex: Integer): TcxEditValue; +begin + Assert(false); +end; + +function TcxCustomBoldLookupEdit.LookupKeyToEditValue(const AKey: TcxEditValue): TcxEditValue; +begin + Result := AKey; +end; + +{function TcxCustomBoldLookupEdit.LookupKeyToItemIndex(const AKey: TcxEditValue): Integer; +begin + Assert(false); +end;} + +procedure TcxCustomBoldLookupEdit.PopupWindowClosed(Sender: TObject); +begin +// if ActiveProperties.DataController.DataModeController.SyncMode then + ILookupData.CurrentKey := EditValue; + inherited PopupWindowClosed(Sender); +end; + +procedure TcxCustomBoldLookupEdit.PrepareDisplayValue( + const AEditValue: TcxEditValue; var DisplayValue: TcxEditValue; + AEditFocused: Boolean); +begin + if (ActiveProperties.DropDownListStyle <> lsEditList) and not Focused and + ActiveProperties.CanDisplayArbitraryEditValue then + DisplayValue := VarToStr(AEditValue) + else + ActiveProperties.PrepareDisplayValue(AEditValue, DisplayValue, AEditFocused); +end; + +function TcxCustomBoldLookupEdit.GetProperties: TcxCustomBoldLookupEditProperties; +begin + Result := TcxCustomBoldLookupEditProperties(FProperties); +end; + +function TcxCustomBoldLookupEdit.GetActiveProperties: TcxCustomBoldLookupEditProperties; +begin + Result := TcxCustomBoldLookupEditProperties(InternalGetActiveProperties); +end; + +procedure TcxCustomBoldLookupEdit.SetProperties(Value: TcxCustomBoldLookupEditProperties); +begin + FProperties.Assign(Value); +end; + +{ TcxBoldLookupEditDataBinding } + +function TcxBoldLookupEditDataBinding.IsLookupControl: Boolean; +begin + Result := True; +end; + +end. diff --git a/Source/BoldAwareGUI/BoldDevex/cxBoldRegUnit.dcr b/Source/BoldAwareGUI/BoldDevex/cxBoldRegUnit.dcr new file mode 100644 index 0000000000000000000000000000000000000000..665ec51cc571b9f83531678d0f916a89aaf32a4d GIT binary patch literal 24544 zcmeI4UyLNhdBDFjo9v#f&9X5k*(dE?>CoNg?NBzB^N@$KZxDwJ94uTyvawad$~sRh zQY??3LPf!1{6r*B1lpI1Zk2~bfGwG9B9v^s1$Ya@yL2I6OHj>uGAVLv7E>z^*jkzrgBpTFY0O27vp#whV8QMUi( zuSui@2dppwA|w$jU;x27@DLzE5^(|sEbzy92oNFZ&cJ{L2Oa`MNFs<53|MgBAwYyg zA_WXsaNr?8ge1aOk^u`2JOqf4#0tq21Nw2`AwYyw4$T;r794m85FwSrwuYqz2Oa`M zNad6`!_tBS4*?>ia=N@>X~BVq01;9-mBFyI;J`zG2&tUrXjocs;2}VSl(WDl!_tBS z4*?=1@f^Pw1A62R^b;ULDp_L;OA8J>1c;DIwpqi{f&&i$BBYX~&akxLz(artsbse| zEG;Ud`9G zR9u^E?5JGAS{55U|Az6A8vSImL5V)p^S=qY;UIp!K^?u;H!+2^Wj`gp94SGX=sEt{ zk%7L6p7rv6OJ5%bcI5qb{N^aGTsd;26`$x6bvlo<;-i|F&=uHe$IohAp?cysK}`(o z9Fg}Y^G7CFuMmh|t7YxV6^swAj^CL}TS>ws{(UyKT z>#OQK@jsXKB!YC-`VI*~ubcIHnzq@a-}%mWCc59~cDvKJKKtymlUtp8^>nE9=Co)Y zTDBO^!!OB2Y8?-efA`6q(viE7OSsYb*rfe>mz#CESxj%{Q(T|tl3%<0o8J5od2(`U zG>%uJRoS-WW0tR-k0r$=zqYnCGfF;g{jh^v>pPlDB_B(il8;+I)UB_Tj|bh0=gGfw z^5vWAUesgxIf9;inJxxq^zItS{A=WGuIfhCdwL+VBFp8%n8|X^!|g1WJgl-@?!{uK z+>2$upHv=p^r{-G@1NsdT;y{n_u@JE{hRoH{E&N%oZ8j<=skq(85zjccGkal>g;=` zYPovvz3S{hK0B08RRftQjqLS`sN?6nJe%#;d0FgSbgOF{V8`-Tm7QkMJ_hs=B?v2w`|VRFMQ#a$G$LmN0yOpd2AtP z{bpKN_>)^6OId&QmOJiP__ggUzmpbbYy&ObuXKK@^u`|y$8qc!kZ}%n_T1i+OH1EHJ^Q< zUi`IRynMOhTl`{M?sP8jy>7kNE4sFm^RU>zk$&;FNYQwidM|h1y|gw;xY2nxl3$uD zB~ZQ%0`le3_@ltuN3Rk0(|0=i>o1JO-_~=%E;N40yKHlqcj)Ujp>8`YKdZV!3T{WEc#(N+W5g;f1cfza&&j1gIwx6 zyREh&ZGP3~Hb3N>p&m6>M76%{YE@Dmwh$mcHqY;EOcv-)}(N;A7MnQI3s@AMvH zn1Tj#EjMv?x~i8M)&KX#9fSBPe?)ywN^L*aH;SEMy>Yv4w-x=c-ncz%caxsM7z1gp z`&YE(fnIk|RTosB>l@W&J>Fd3s5;bR(KjO)^hF#zPV^u(M(sbj3Gy&k7C+k0NLwLy zN0mOQea950hGPw0hB8|W#uu{Q=X1Q<)A*(Ce?!L?w9aUAuJ4_T@*usL+M{{#u)Y|Q zI(sl+!GVVW5t0bs!#OF2y5eDd@o-Mc$1x{GYaQcZP}kWbaQE#O_QY!bQpc;Rwd|71 z&)Q_gcT($q2*aRS{-a+TF`uKaW&JR6jyJGVo6pL|t}fTAHC;7{y}Um)rS`Q_P(t2> zm^nS{x0$Cgs&CIRQM+~gR(&xmYkj-ExK;&~@{5+RL^{x6MsinTCCu(ne)Mc_t zjz3I)V`mck!#OGB<|j~J)G@b*^T^u`uP+`@&G?Xd1m|_Ek68PH>ptSn`-PkhtW7s=^KPTxeoAZDB~F&fy)Df`sZP%HdcKU+ zFoM^c@}aO7km^Sp@*f+2E1Q4* zfV}wp-^llVvLk=B@gvI1zhsNtGpmbVxmX94fAdrhr&V4kVO;KX&Ye1S`)S>5;hATi zzI5r*>4%n=zrB!01#Un6&^M8ve)^ebp83J)hkLzmFPyraHR!wF{Px17OHV)j^bbxi zs$AR8acX(-Pv0iw1f5=do6LSAuQ+}2jYht7`l|!^4^F=|kT0Fys^!ltEPTGm7ay3# zRFPkvoju0&@`l=f<)1(EdE~dAfByM@d-;0{$Zx#<`s@F>Fndg8-BV7%MP`&SPpreq zD1HB(JQrR2hMO7b2j%7sX^*!G(ydKxHhFE3(dgYp(oc~^<*DAb$SzGTWa({B`CSfH z*6ZvKbfXb~<;dUU#Z<{?O<4c<%|dpWEZTJWa9H9-q$b z@%``3d+7bYz&NUoZu^GQhyQieCxyKg6In~^kEqKFpL8a0U{)^R=|J- z2Oa`MNP-FsSa9GWK!hYj2Ll!ycnA<738uh+1qU7iL`XdQBVfRS0}lZrB>G+i3|MgB zAwYyA>>dnQaG;+65fab-2pF*7z(artiD!QV3|MgBAwY!0vp)g`EI9BGAVSL5nP(>+ zL!QXqdk7FA@$8R)0SgX11c;D$_D8^g1qU7iL`Z@OFkr!fhX4_husIm8;J`xw{iM>p zXADaV4m<>ikV@B|H7qSS@DLzED&2z4u(aU7Lx2dWbQyZX(t-mI0V1T*ofr&D3l2O4 zh>*BP1q@hl;Ng>eF6hLG6RWFB8Wx9vX8ehj6IwH>$|y+rT|7X)r26iOrZZx&Ttz>> zK5l0%>*vSp*ZRTsjd0EQ8wc2#Z-+A+CPDYh6;i?qVP1b$R6p#4Strcv&-$4wSJsAo zFfDuf0MMY%MrXQqvz_^o=YlqJP&;Qwp7YVPOq|UjKj+i*{mied)73&!2<<+bc~$Q- zX1B8Rz)~HZ_`^P!m5q&wm13qfX1BVEjk9MPef^s zD`$?4>HB>(bZn<_HY|yM20JfeXm9*88&iD@&Cl(zb7rI8?~~HGww)d9^!vEE{`yFK z^egLAY%uxaa@!92DN=uCdHIDi18<}5LJyuhq=e$L^mo*66`!TQ^VjdUvg_K%zhzm?S!6C`Hzc~;`DOgylZT~ym|sU7xO^n>SF*VeM% z(w%1e*>UArIr_f|>bFMQ(GN;9!{j1s^m&h_ze`8Gwa>Es)WE@gUHi1Pjx;%;OP{|~ zZdC$42rCO=ZA>0}lZrB-&E~1}r%65FkPlRA9h@0}lZrB-&E~1}r%65FkRr zF9{g1;J`zG2noL=V8DU{4*?=1{E~nH3l2O4h>(Qcg8>T;^b;ULqCF*Gz=8u00U{*Y zQvwDoIPef4LZUq-V8DU{4*?>ie4TlA;xXij?7fEo5fbew0Rt8scnA<7(Vh}8V8MZh z01*=HDFFi(9C!#2Aqks<0SgX11kg_sOoIUn4m<>ikc8cW0SgX11c;C%IspR~9C!#2 zAxZQC1}r%65FkR57z7MhaNr?8gv326V8DU{4=6x%G8*kIU@fwxtTsL}2wKdi8haVxdH_0EQ@o|w>v>&QD8 zu(OJtqHnde)DFon`hm~NR@Tr{kr(aCnwPcLcQxnn&`&wx=7s-9_0tPHN@DLzE!WRh` zu;9Q$fCvd+Bw)aT0}lZrBz%#80SgX11c;FEMFIvaIPef4LK1cl2K2}s=qEsgB;E)Z zu;9Q$fCvd+Bw)aT0}lZrBz%#80SgX11c;FEMFIvaIPef4Lc$jb7_i{LLx2bgUnF3_ zf&&i$A|!l~fB_2*JOqf4gw4T#1qU7i=qKTe1PoYk;2}VSgf9{>V8MZh01*%X`0aUF{r)5Br}TJN+wmV!b(yfW+MdU+88xw*(?k4WpP;JyW!Bqj zqZXoJBS+Ss=2)BSqgkq->TnN@_X!p+rSB)vXX&+Fb$#y)I&4!N`YMZWa)4J#0U{*v zTxW;Ain3lP>xHtOvvKIFD2cc(_6g`)-F5?!?jf06qre)5Nu7Y3^_Xeq;j(&?zeTTa z*&BvzE5}z|y=$aV{Q>c{Xs*LZ{8C_RZ&^JDSJR1&Ch}hW(0psZt<%s>&(K%pt(yI| ze3h2qLp#Iqt9JahuWH9{`yP$oq`&Q}h|d9(^EnznA74KIZC|BH9N1}`63?7rLDA3} zzsgUpH7;q;rWz<};o#?$_VZBJnqyItV2+f8=x?5?HTdhbpaNeO{2~JPYmBVmn$gQf zud4h{uP*&Nm|)5jJ?4S3t`7UYTSDJ2x0&BZ#|z7NUtIlMQnkzbeFpk0=Umj6noVy$ zQ6@s2&$8-y-<`&3^zHa6`<#Mev&t`KOwmX8!5L-=bqjvzgM5QgWJRtImRzE55JWs4(3UMn~#?~$#cISU+F%+(|x?^ z?oRL3S3Asn+ec6Qs?u}6$4<3_VsHG%^iXU2bsp+|OCHvC2Jf5Lt@E(#x5>i`#4mG* zyWi;W-oc{p@ovH=>paxw26x8aO(-49&Zpb&Ce%8kzB_Wf&iEiXr~UEgs4d=2KfJyb zt$E8`lfUg+ nil then + GetGridViewItemNames(AGridView, Proc); +end; + +function TcxCustomGridTableItemProperty.GetGridView: TcxCustomGridView; +var + I: Integer; +begin + Result := InternalGetGridView(GetComponent(0)); + for I := 1 to PropCount - 1 do + if InternalGetGridView(GetComponent(I)) <> Result then + begin + Result := nil; + Break; + end; +end; + +procedure TcxCustomGridTableItemProperty.GetGridViewItemNames(AGridView: TcxCustomGridView; + Proc: TGetStrProc); +var + I: Integer; +begin + if AGridView is TcxCustomGridTableView then + with AGridView as TcxCustomGridTableView do + for I := 0 to ItemCount - 1 do + Proc(Designer.GetComponentName(Items[I])); +end; + +type + TcxExtLookupComboBoxPropertiesItemColumnProperty = class(TcxCustomGridTableItemProperty) + protected + function InternalGetGridView(APersistent: TPersistent): TcxCustomGridView; override; + end; + + TcxExtLookupComboBoxPropertiesViewProperty = class(TComponentProperty) + private + FProc: TGetStrProc; + procedure CheckComponent(const Value: string); + public + procedure GetValues(Proc: TGetStrProc); override; + end; + +(* + TBoldOCLExpressionForSetValueExpression = class(TBoldOCLExpressionProperty) + protected + function GetContextType(Component: TPersistent): TBoldElementTypeInfo; override; + end; + +{ TBoldOCLExpressionForSetValueExpression } + + +function TBoldOCLExpressionForSetValueExpression.GetContextType( + Component: TPersistent): TBoldElementTypeInfo; +var + lBoldElementHandle: TBoldElementHandle; +begin + if Component is TcxBarBoldEditItem then + lBoldElementHandle := (Component as TcxBarBoldEditItem).BoldHandle + else + if component is TcxCustomEdit and (TcxCustomEditAccess(component).DataBinding is TcxBoldEditDataBinding) then + lBoldElementHandle := (TcxCustomEditAccess(component).DataBinding as TcxBoldEditDataBinding).BoldHandle + else + if component is TcxBoldComboBoxProperties then + begin + raise EBold.CreateFmt('Unsuported component %s.', [(component as TcxBoldComboBoxProperties).Owner.Classname]); + end + else + raise EBold.CreateFmt('Unsuported component %s.', [Component.ClassName]); + + if Assigned(lBoldElementHandle) then + Result := lBoldElementHandle.StaticBoldType + else + Result := nil +end; +*) +{ TdxBoldItemEditor } + +class function TdxBoldItemEditor.GetAddedItemClass( + const AAddedItemName: string): TdxBarItemClass; +begin + Result := TcxBarBoldEditItem; +end; + +class function TdxBoldItemEditor.GetPopupItemCaption: string; +begin + Result := 'Add BoldItem';//dxSBAR_CP_ADDBUTTON; +end; + + +procedure RegisterEditRepositoryItems; +begin + RegisterEditRepositoryItem(TcxEditRepositoryBoldStringItem, scxSBoldEditRepositoryTextItem); + RegisterEditRepositoryItem(TcxEditRepositoryBoldComboBoxItem, scxSBoldComboBoxRepositoryTextItem); + RegisterEditRepositoryItem(TcxEditRepositoryBoldLookupComboBoxItem, scxSBoldLookupComboBoxRepositoryTextItem); + RegisterEditRepositoryItem(TcxEditRepositoryBoldExtLookupComboBoxItem, scxSBoldExtLookupComboBoxRepositoryTextItem); +end; + +{type + TBoldOCLExpressionForDataBindingDefinitionProperty = class(TBoldOCLExpressionProperty) + protected + function GetContextType(Component: TPersistent): TBoldElementTypeInfo; override; + function GetVariableList(Component: TPersistent): TBoldExternalVariableList; override; + end;} + +procedure Register; +begin +{$IFDEF DELPHI9} + ForceDemandLoadState(dlDisable); +{$ENDIF} + RegisterNoIcon([TcxBarBoldEditItem]); + + RegisterComponents('Express BoldEditors', [TdxBarBoldNavigator, TcxBoldTextEdit, TcxBoldDateEdit, + TcxBoldTimeEdit, TcxBoldMemo, TcxBoldCurrencyEdit, TcxBoldMaskEdit, TcxBoldCheckBox, TcxBoldComboBox, + TcxBoldSpinEdit, TcxBoldButtonEdit, TcxBoldHyperLinkEdit, TcxBoldProgressBar, + {$IFDEF DevExScheduler} + TcxBoldDateNavigator, + {$ENDIF} + TcxBoldLabel, TcxBoldImage, TcxBoldRichEdit, + TcxBoldListBox, TcxBoldCheckListBox, TcxBoldSelectionCheckListBox, TcxBoldListView, + TcxBoldExtLookupComboBox, TcxBoldLookupComboBox, TcxBoldNBLookupComboBox, TcxBoldNBExtLookupComboBox, + TBoldToCxConverter]); + + RegisterNoIcon([TdxBarBoldNavButton]); + + RegisterPropertyEditor(TypeInfo(TdxBarBoldNavigator), TdxBarBoldNavButton, 'BarBoldNavigator', nil); +// RegisterPropertyEditor(TypeInfo(String), TcxBoldComboBoxProperties, 'BoldSetValueExpression', TBoldOCLExpressionForSetValueExpression); + + BarDesignController.RegisterBarControlEditor(TdxBoldItemEditor); + RegisterEditRepositoryItems; + + RegisterPropertyEditor(TypeInfo(TBoldElementHandle), TPersistent, 'BoldHandle', TBoldComponentPropertyIndicateMissing); + RegisterPropertyEditor(TypeInfo(TBoldExpression), TcxBoldComboBoxProperties, 'BoldSetValueExpression', TBoldOCLExpressionForCxBoldPropertiesSetValueExpression); + RegisterPropertyEditor(TypeInfo(TBoldExpression), TcxCustomBoldLookupEditProperties, 'BoldSetValueExpression', TBoldOCLExpressionForCxBoldPropertiesSetValueExpression); + RegisterPropertyEditor(TypeInfo(TcxCustomGridTableItem), TcxBoldExtLookupComboBoxProperties, 'ListFieldItem', TcxExtLookupComboBoxPropertiesItemColumnProperty); + RegisterPropertyEditor(TypeInfo(TcxCustomGridTableView), TcxBoldExtLookupComboBoxProperties, 'View', TcxExtLookupComboBoxPropertiesViewProperty); + + {GUI Component editors} + RegisterComponentEditor(TcxBoldTextEdit, TBoldOCLComponentEditor); + RegisterComponentEditor(TcxBoldDateEdit, TBoldOCLComponentEditor); + RegisterComponentEditor(TcxBoldTimeEdit, TBoldOCLComponentEditor); + RegisterComponentEditor(TcxBoldMemo, TBoldOCLComponentEditor); + RegisterComponentEditor(TcxBoldCurrencyEdit, TBoldOCLComponentEditor); + RegisterComponentEditor(TcxBoldMaskEdit, TBoldOCLComponentEditor); + RegisterComponentEditor(TcxBoldCheckBox, TBoldOCLComponentEditor); + RegisterComponentEditor(TcxBoldComboBox, TBoldOCLComponentEditor); + RegisterComponentEditor(TcxBoldSpinEdit, TBoldOCLComponentEditor); + RegisterComponentEditor(TcxBoldButtonEdit, TBoldOCLComponentEditor); + RegisterComponentEditor(TcxBoldHyperLinkEdit, TBoldOCLComponentEditor); + RegisterComponentEditor(TcxBoldProgressBar, TBoldOCLComponentEditor); + RegisterComponentEditor(TcxBoldLabel, TBoldOCLComponentEditor); + RegisterComponentEditor(TcxBoldImage, TBoldOCLComponentEditor); + RegisterComponentEditor(TcxBoldRichEdit, TBoldOCLComponentEditor); + RegisterComponentEditor(TcxBoldExtLookupComboBox, TBoldOCLComponentEditor); + RegisterComponentEditor(TcxBoldLookupComboBox, TBoldOCLComponentEditor); +end; + + +{ TBoldOCLExpressionForDataBindingDefinitionProperty } +{ +function TBoldOCLExpressionForDataBindingDefinitionProperty.GetContextType( + Component: TPersistent): TBoldElementTypeInfo; +begin + EnsureComponentType(Component, TBoldDataBindingDefinition); + Result := (Component as TBoldDataBindingDefinition).ContextType; +end; + +function TBoldOCLExpressionForDataBindingDefinitionProperty.GetVariableList( + Component: TPersistent): TBoldExternalVariableList; +begin + EnsureComponentType(Component, TBoldDataBindingDefinition); + Result := (Component as TBoldDataBindingDefinition).VariableList; +end; +} + +{ TBoldOCLExpressionForCxBoldPropertiesSetValueExpression } + +function TBoldOCLExpressionForCxBoldPropertiesSetValueExpression.GetContextType( + Component: TPersistent): TBoldElementTypeInfo; +var + lcxBoldComboBoxProperties: TcxBoldComboBoxProperties; + lBoldAwareViewItem: IBoldAwareViewItem; + lcxBoldComboBox: TcxBoldComboBox; + lcxBoldDataController: TcxBoldDataController; + lcxCustomBoldLookupEditProperties: TcxCustomBoldLookupEditProperties; + lcxBoldEditDataBinding: TcxBoldEditDataBinding; +begin + result := nil; + if Component is TcxBoldComboBoxProperties then + begin +// ShowMessage(lcxBoldComboBoxProperties.GetContainerClass.ClassName); +// ShowMessage(lcxBoldComboBoxProperties.Owner.ClassName); + lcxBoldComboBoxProperties := Component as TcxBoldComboBoxProperties; + if (lcxBoldComboBoxProperties.Owner is TcxCustomGridTableItem) and lcxBoldComboBoxProperties.Owner.GetInterface(IBoldAwareViewItem, lBoldAwareViewItem) then + begin + lcxBoldDataController := (TcxCustomGridTableItem(lcxBoldComboBoxProperties.Owner).DataBinding.DataController as TcxBoldDataController); + if Assigned(lcxBoldDataController.BoldHandle) then + result := lcxBoldDataController.BoldHandle.StaticBoldType; + end + else + if lcxBoldComboBoxProperties.Owner is TcxBoldComboBox then + begin + lcxBoldComboBox := lcxBoldComboBoxProperties.Owner as TcxBoldComboBox; + if Assigned(lcxBoldComboBox.DataBinding.BoldHandle) then + result := lcxBoldComboBox.DataBinding.BoldHandle.StaticBoldType; + end + else + if lcxBoldComboBoxProperties.Owner is TcxEditRepositoryItem then + begin + raise Exception.Create('OCL Editor is not available, repository items do not have a context.'); + end + else + raise Exception.Create('Unknown context: ' + lcxBoldComboBoxProperties.Owner.ClassName ); +{ if Assigned(lcxBoldComboBoxProperties.BoldLookupListHandle) then + result := lcxBoldComboBoxProperties.BoldLookupListHandle.StaticBoldType; +} + end + else + if component is TcxCustomBoldLookupEditProperties then + begin + lcxCustomBoldLookupEditProperties := component as TcxCustomBoldLookupEditProperties; + if (lcxCustomBoldLookupEditProperties.Owner is TcxCustomBoldLookupEdit) and (TcxCustomBoldLookupEditAccess(lcxCustomBoldLookupEditProperties.Owner).DataBinding is TcxBoldEditDataBinding) then + begin + lcxBoldEditDataBinding := TcxBoldEditDataBinding(TcxCustomEditAccess(lcxCustomBoldLookupEditProperties.Owner).DataBinding); + if Assigned(lcxBoldEditDataBinding.BoldHandle) then + result := lcxBoldEditDataBinding.BoldHandle.StaticBoldType; + end + else + raise Exception.Create('Unknown context: ' + lcxCustomBoldLookupEditProperties.Owner.ClassName ); + end + else + Assert(false); +// raise EBold.CreateFmt(sComponentNotComboBox, [ClassName]); +end; + +{ TcxExtLookupComboBoxPropertiesItemColumnProperty } + +function TcxExtLookupComboBoxPropertiesItemColumnProperty.InternalGetGridView( + APersistent: TPersistent): TcxCustomGridView; +var + AProperties: TcxBoldExtLookupComboBoxProperties; +begin + AProperties := APersistent as TcxBoldExtLookupComboBoxProperties; + Result := AProperties.View; +end; + +{ TcxExtLookupComboBoxPropertiesViewProperty } + +procedure TcxExtLookupComboBoxPropertiesViewProperty.CheckComponent( + const Value: string); +var + AView: TcxCustomGridTableView; +begin + AView := TcxCustomGridTableView(Designer.GetComponent(Value)); + if (AView <> nil) and TcxBoldExtLookupComboBoxProperties.IsViewSupported(AView) then + FProc(Value); +end; + +procedure TcxExtLookupComboBoxPropertiesViewProperty.GetValues( + Proc: TGetStrProc); +begin + FProc := Proc; + inherited GetValues(CheckComponent); +end; + +end. diff --git a/Source/BoldAwareGUI/BoldDevex/cxGridBoldSupportUnit.pas b/Source/BoldAwareGUI/BoldDevex/cxGridBoldSupportUnit.pas new file mode 100644 index 0000000..321e6a5 --- /dev/null +++ b/Source/BoldAwareGUI/BoldDevex/cxGridBoldSupportUnit.pas @@ -0,0 +1,6292 @@ +unit cxGridBoldSupportUnit; + + +{$ASSERTIONS ON} +{$INCLUDE Bold.inc} + +{$DEFINE DelayOnFocusedRecordChange} + +{.$DEFINE IEJpegImage} +{.$DEFINE DefaultDragMode} +{.$DEFINE FireAfterLoadOnChangeOnly} +{$DEFINE CenterResultOnIncSearch} + +{.$DEFINE BoldDevExLog} + +(* + cxGrid Bold aware components v2.7 - Oct 2018 + for ExpressQuantumGrid 6 + + 2007-2018 Daniel Mauric + + features + - on demand fetching + - appropriate column properties for each BoldAttribute, including ComboBoxProperties with possible values for TBAValueSet + - smart drag & drop support, across views and within single view if list is ordered, etc... + - constraint column with hints that contain broken constraints messages + - implements IBoldValidateableComponent + - global var cxBoldDataSourceClass allows to plugin a custom TcxBoldDataSource subclass + + non bold related features + - ctrl+home and ctrl+end go to top and bottom of the list, respectively + - ctrl+numeric plus toggles ApplyBestFit for the visible range of records + + known issues + - Drag drop is currently not supported in the CardView + - Master detail views only supported when connected to BoldListHandles + +*) + +interface + +uses + Classes, + Controls, + Types, + Messages, + Contnrs, + + cxGridCustomTableView, + cxCustomData, + cxGridCustomView, + cxGridTableView, + cxStorage, + cxDataStorage, + cxData, + cxDataUtils, + cxEdit, + cxDropDownEdit, + cxGridCardView, +// cxGridChartView, + cxGridBandedTableView, + cxGridLayoutView, + cxFilter, + cxGraphics, + + BoldSystem, + BoldEnvironmentVCL, // Make sure VCL environement loaded, and finalized after + BoldComponentvalidator, + BoldSystemRT, + BoldControlPack, +// BoldStringControlPack, + BoldVariantControlPack, + BoldListHandleFollower, + BoldListListControlPack, + BoldControllerListControlPack, + BoldAbstractListHandle, + BoldElements, + BoldSubscription, + + cxBoldEditors; // for IcxBoldEditProperties, perhaps extract that class to another unit later on and use that instead + +type + TcxGridBoldTableView = class; + TcxGridBoldColumn = class; + TcxGridItemBoldDataBinding = class; + TcxBoldDataController = class; + TcxGridBoldDataController = class; + TcxBoldDataSource = class; + TcxGridBoldTableController = class; + TcxGridBoldCardView = class; +(* + TcxBoldGridChartView = class; + TcxGridBoldChartDataController = class; + TcxGridBoldChartCategories = class; + TcxGridBoldChartDataGroup = class; + TcxGridBoldChartSeries = class; +*) + TcxGridBoldBandedTableView = class; + TcxGridBoldBandedColumn = class; + TcxGridBoldBandedTableController = class; + TcxBoldDataControllerSearch = class; + TcxBoldCustomDataProvider = class; + TcxGridBoldEditingController = class; + + TcxGridBoldLayoutView = class; + TcxGridBoldLayoutViewItem = class; + + TBoldCxGridVariantFollowerController = class; + + IBoldAwareViewItem = interface + ['{187C2B47-FD11-4A01-9340-6BC608B6FF38}'] + function GetBoldProperties: TBoldVariantFollowerController; + property BoldProperties: TBoldVariantFollowerController read GetBoldProperties; + end; + + IBoldAwareView = interface + ['{51A80761-FCA5-4D4E-8585-907B8C08C404}'] + function GetDataController: TcxGridBoldDataController; + procedure SetDataController(Value: TcxGridBoldDataController); + property DataController: TcxGridBoldDataController read GetDataController write SetDataController; + function GetItemCount: Integer; + property ItemCount: Integer read GetItemCount; + function GetItem(Index: Integer): IBoldAwareViewItem; + property Items[Index: Integer]: IBoldAwareViewItem read GetItem; default; + function GetSelection: TBoldList; + property Selection: TBoldList read GetSelection; + procedure DoSelectionChanged; + procedure ClearItems; + + function GetCurrentBoldObject: TBoldObject; + function GetCurrentIndex: integer; + function GetCurrentElement: TBoldElement; + + property CurrentBoldObject: TBoldObject read GetCurrentBoldObject; + property CurrentElement: TBoldElement read GetCurrentElement; + property CurrentIndex: integer read GetCurrentIndex; + end; + + TBoldCxGridVariantFollowerController = class(TBoldVariantFollowerController) + protected + fcxGridItemBoldDataBinding: TcxGridItemBoldDataBinding; + public + function SubFollowersActive: boolean; override; + constructor Create(aOwningComponent: TComponent); reintroduce; + end; + + TcxGridBoldDefaultValuesProvider = class(TcxCustomBoldEditDefaultValuesProvider) + public + function DefaultCanModify: Boolean; override; + function IsDisplayFormatDefined(AIsCurrencyValueAccepted: Boolean): Boolean; override; + end; + + + TcxBoldDataSource = class(TcxCustomDataSource) + private + fBoldDataController: TcxBoldDataController; + fIsBoldInitiatedChange: boolean; + protected + function GetRecordCount: Integer; override; + function GetValue(ARecordHandle: TcxDataRecordHandle; + AItemHandle: TcxDataItemHandle): Variant; override; + procedure SetValue(ARecordHandle: TcxDataRecordHandle; + AItemHandle: TcxDataItemHandle; const AValue: Variant); override; + function GetItemHandle(AItemIndex: Integer): TcxDataItemHandle; override; + function GetRecordHandle(ARecordIndex: Integer): TcxDataRecordHandle; override; + function IsRecordIdSupported: Boolean; override; + function GetRecordId(ARecordHandle: TcxDataRecordHandle): Variant; override; + function GetDetailHasChildren(ARecordIndex, ARelationIndex: Integer): Boolean; override; + procedure LoadRecordHandles; override; + procedure CustomSort; override; + function CustomSortElementCompare(Item1, Item2: TBoldElement): integer; + function IsCustomSorting: Boolean; override; + public + constructor Create(aBoldDataController: TcxBoldDataController); virtual; + destructor Destroy; override; + procedure DeleteRecord(ARecordHandle: TcxDataRecordHandle); override; + function GetRecordHandleByIndex(ARecordIndex: Integer): TcxDataRecordHandle; override; + end; + + TcxBoldCustomDataControllerInfo = class(TcxCustomDataControllerInfo) + protected + procedure DoSort; override; + procedure DoFilter; override; + end; + + TcxBoldDataSummary = class(TcxDataSummary) + protected +{$IFDEF BOLD_DELPHI16_OR_LATER} + procedure CalculateSummary(ASummaryItems: TcxDataSummaryItems; ABeginIndex, AEndIndex: Integer; + var ACountValues: TcxDataSummaryCountValues; var ASummaryValues: TcxDataSummaryValues); override; +{$ELSE} + procedure CalculateSummary(ASummaryItems: TcxDataSummaryItems; ABeginIndex, AEndIndex: Integer; + var ACountValues: TcxDataSummaryCountValues; var ASummaryValues: TcxDataSummaryValues; var SummaryValues: Variant); override; +{$ENDIF} + end; + + TcxGridUserQueryEvent = procedure (Sender: TObject; var Allow: boolean) of object; + + TcxBoldDataController = class(TcxCustomDataController) + private + fBoldHandleFollower: TBoldListHandleFollower; + fBoldProperties: TBoldListAsFollowerListController; + fBoldColumnsProperties: TBoldControllerList; + fSubscriber: TBoldPassthroughSubscriber; + FSkipMakeCellUptoDate: integer; + FSkipSyncFocusedRecord: integer; + fInDelayScrollUpdate: boolean; + fCurrentListElementType: TBoldElementTypeInfo; + fSelection: TBoldList; + fBoldAutoColumns: Boolean; + fDataChanged: boolean; + fInvalidating: boolean; + fFetchedAll: boolean; + fInternalLoading: boolean; +// fBeforeLoad: TNotifyEvent; + fAfterLoad: TNotifyEvent; + fLoadAll: boolean; + fSkipCancel: boolean; + fOnDelete: TNotifyEvent; + fOnInsert: TNotifyEvent; + fCanInsert: TcxGridUserQueryEvent; + fCanDelete: TcxGridUserQueryEvent; + FUseDelayedScrollUpdate: boolean; + fClearColumnsOnTypeChange: boolean; + fStoredRecordIndex: integer; + fRedrawGrid: boolean; + fRecalcSummary: boolean; +{$IFDEF DelayOnFocusedRecordChange} + fFocusChanged: boolean; + fPrevFocusedRecordIndex: integer; + fFocusedRecordIndex: integer; + fPrevFocusedDataRecordIndex: integer; + fFocusedDataRecordIndex: integer; + fNewItemRecordFocusingChanged: boolean; +{$ENDIF} + function GetRecNo: Integer; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure SetRecNo(const Value: Integer); + function GetBoldHandle: TBoldAbstractListHandle; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetBoldHandleIndexLock: Boolean; + procedure SetBoldHandle(const Value: TBoldAbstractListHandle); + procedure SetBoldHandleIndexLock(const Value: Boolean); + procedure SetController(const Value: TBoldListAsFollowerListController); + function GetRowFollower(DataRow: Integer): TBoldFollower; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetFollower: TBoldFollower; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetCellFollower(ARecordIndex, AItemIndex: Integer): TBoldFollower; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetSelection: TBoldList; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + function GetBoldList: TBoldList; {$IFDEF BOLD_INLINE} inline; {$ENDIF} + procedure SetDataChanged(const Value: boolean); + procedure FindMinMaxIndex(ListA, ListB: TBoldList; var AFrom, ATo: integer); + procedure Receive(Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent); + function GetHasCellFollower(ARecordIndex, AItemIndex: Integer): boolean; + procedure EnsureEventQueued; + protected + function GetDataProviderClass: TcxCustomDataProviderClass; override; + function GetSearchClass: TcxDataControllerSearchClass; override; + function CreateDataControllerInfo: TcxCustomDataControllerInfo; override; + function IsDataLinked: Boolean; + function IsSmartRefresh: Boolean; override; + function GetCurrentBoldObject: TBoldObject; + function GetCurrentIndex: integer; + function GetCurrentElement: TBoldElement; + procedure ProcessQueueEvent(Sender: TObject); virtual; + procedure BeforeSorting; override; + function BoldSetValue(AItemHandle: TcxDataItemHandle; ACellFollower: TBoldFollower; const AValue: variant): boolean; virtual; + function RequiresAllRecords: boolean; overload; virtual; + function RequiresAllRecords(AItem: TObject): boolean; overload; virtual; + procedure SelectionChanged; virtual; + procedure FilterChanged; override; + function FindItemByData(AData: Integer): TObject; + function GetItemData(AItem: TObject): Integer; virtual; abstract; + function BoldPropertiesFromItem(aIndex: integer): TBoldVariantFollowerController; + procedure _InsertRow(index: Integer; Follower: TBoldFollower); virtual; + procedure _DeleteRow(index: Integer; owningFollower: TBoldFollower); virtual; + procedure _ReplaceRow(index: Integer; AFollower: TBoldFollower); virtual; + procedure _BeforeMakeListUpToDate(Follower: TBoldFollower); virtual; + procedure _AfterMakeListUptoDate(Follower: TBoldFollower); virtual; + procedure _AfterMakeCellUptoDate(Follower: TBoldFollower); virtual; + function GetHandleListElementType: TBoldElementTypeInfo; + function TypeMayHaveChanged: boolean; + procedure TypeChanged(aNewType, aOldType: TBoldElementTypeInfo); virtual; + procedure BeginDelayScrollUpdate; + procedure EndDelayScrollUpdate; + procedure DisplayFollowers; virtual; + function MainFollowerNeedsDisplay: boolean; + function EnsureFollower(ARecordIndex, AItemIndex: integer): boolean; + property BoldHandleIndexLock: Boolean read GetBoldHandleIndexLock write SetBoldHandleIndexLock default true; + property HasCellFollower[ARecordIndex, AItemIndex: Integer]: boolean read GetHasCellFollower; + property BoldAutoColumns: Boolean read fBoldAutoColumns write fBoldAutoColumns default false; + property BoldColumnsProperties: TBoldControllerList read fBoldColumnsProperties; + property DataHasChanged: boolean read fDataChanged write SetDataChanged; + property SkipMakeCellUptoDate: integer read FSkipMakeCellUptoDate; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + function InDelayScrollUpdate: boolean; + function IsProviderMode: Boolean; override; + function GetRecordCount: Integer; override; + procedure Cancel; override; + procedure AdjustActiveRange(aList: TBoldList = nil; aItem: integer = -1); overload; virtual; + procedure AdjustActiveRange(aRecordIndex: integer; aItem: integer = -1); overload; + procedure PreFetchColumns(aList: TBoldList = nil; aItem: integer = -1); virtual; + function GetHandleStaticType: TBoldElementTypeInfo; + function GetCurrentDetailDataController(ARelationIndex: integer = 0): TcxBoldDataController; + function CreateList: TBoldList; + property BoldProperties: TBoldListAsFollowerListController read fBoldProperties write SetController; + property BoldHandle: TBoldAbstractListHandle read GetBoldHandle write SetBoldHandle; + property BoldHandleFollower: TBoldListHandleFollower read fBoldHandleFollower; + property RecNo: Integer read GetRecNo write SetRecNo; // Sequenced + property Follower: TBoldFollower read GetFollower; + property CurrentBoldObject: TBoldObject read GetCurrentBoldObject; + property CurrentElement: TBoldElement read GetCurrentElement; + property CurrentIndex: integer read GetCurrentIndex; +// property OnBeforeLoad: TNotifyEvent read fBeforeLoad write fBeforeLoad; + property OnAfterLoad: TNotifyEvent read fAfterLoad write fAfterLoad; + property LoadAll: boolean read fLoadAll write fLoadAll default false; + property Selection: TBoldList read GetSelection; + property BoldList: TBoldList read GetBoldList; + property CellFollowers[ARecordIndex, AItemIndex: Integer]: TBoldFollower read GetCellFollower; + published + property OnInsert: TNotifyEvent read fOnInsert write fOnInsert; + property OnDelete: TNotifyEvent read fOnDelete write fOnDelete; + property CanInsert: TcxGridUserQueryEvent read fCanInsert write fCanInsert; + property CanDelete: TcxGridUserQueryEvent read fCanDelete write fCanDelete; + property UseDelayedScrollUpdate: boolean read FUseDelayedScrollUpdate write FUseDelayedScrollUpdate default true; + property ClearColumnsOnTypeChange: boolean read fClearColumnsOnTypeChange write fClearColumnsOnTypeChange default true; + end; + + TcxGridBoldDataController = class(TcxBoldDataController, IcxCustomGridDataController, IcxGridDataController) + private + FPrevScrollBarPos: Integer; + fCreatingColumns: boolean; + fInternalChange: boolean; + fTriggerAfterLoad: boolean; + function GetController: TcxCustomGridTableController; + function GetGridViewValue: TcxCustomGridTableView; + procedure ConstraintColumnCustomDrawCell(Sender: TcxCustomGridTableView; + ACanvas: TcxCanvas; AViewInfo: TcxGridTableDataCellViewInfo; var ADone: Boolean); + procedure ColumnCustomDrawCell(Sender: TcxCustomGridTableView; + ACanvas: TcxCanvas; AViewInfo: TcxGridTableDataCellViewInfo; var ADone: Boolean); + protected + function GetSummaryItemClass: TcxDataSummaryItemClass; override; + function GetSummaryGroupItemLinkClass: TcxDataSummaryGroupItemLinkClass; override; + + procedure CheckDataSetCurrent; override; // used to get CurrentIndex (ie. current record after change) + procedure GetCellHint(Sender: TcxCustomGridTableItem; ARecord: TcxCustomGridRecord; + ACellViewInfo: TcxGridTableDataCellViewInfo; const AMousePos: TPoint; + var AHintText: TCaption; var AIsHintMultiLine: Boolean; var AHintTextRect: TRect); + procedure SelectionChanged; override; + procedure ProcessQueueEvent(Sender: TObject); override; + procedure DisplayFollowers; override; + function DoEditing(AItem: TcxCustomGridTableItem): Boolean; + function BoldSetValue(AItemHandle: TcxDataItemHandle; ACellFollower: TBoldFollower; const AValue: variant): boolean; override; + + function GetOwnerOrView: TComponent; + { IcxCustomGridDataController } + procedure AssignData(ADataController: TcxCustomDataController); + procedure DeleteAllItems; + procedure GetFakeComponentLinks(AList: TList); + function GetGridView: TcxCustomGridView; + function HasAllItems: Boolean; + function IsDataChangeable: Boolean; + function IsDataLinked: Boolean; + function SupportsCreateAllItems: Boolean; + + { IcxGridDataController } + procedure CheckGridModeBufferCount; + function DoScroll(AForward: Boolean): Boolean; + function DoScrollPage(AForward: Boolean): Boolean; + //function GetFilterPropertyValue(const AName: string; var AValue: Variant): Boolean; + function GetItemDataBindingClass: TcxGridItemDataBindingClass; + function GetItemDefaultValuesProviderClass: TcxCustomEditDefaultValuesProviderClass; + function GetNavigatorIsBof: Boolean; + function GetNavigatorIsEof: Boolean; + function GetScrollBarPos: Integer; + function GetScrollBarRecordCount: Integer; + //function SetFilterPropertyValue(const AName: string; const AValue: Variant): Boolean; + function SetScrollBarPos(Value: Integer): Boolean; + function SupportsScrollBarParams: Boolean; virtual; + function GetItemData(AItem: TObject): Integer; override; + function RequiresAllRecords: boolean; overload; override; + function RequiresAllRecords(AItem: TObject): boolean; overload; override; + function CanSelectRow(ARowIndex: Integer): Boolean; override; + function CompareByField(ARecordIndex1, ARecordIndex2: Integer; + AField: TcxCustomDataField; AMode: TcxDataControllerComparisonMode): Integer; override; + procedure DoValueTypeClassChanged(AItemIndex: Integer); override; + procedure FilterChanged; override; + function GetDefaultActiveRelationIndex: Integer; override; + function GetFilterDisplayText(ARecordIndex, AItemIndex: Integer): string; override; + function GetItemID(AItem: TObject): Integer; override; +// function GetItemData(AItem: TObject): Integer; virtual; + function GetSortingBySummaryEngineClass: TcxSortingBySummaryEngineClass; override; + function GetSummaryClass: TcxDataSummaryClass; override; + { Bold methods } + procedure _BeforeMakeListUpToDate(Follower: TBoldFollower); override; + procedure _AfterMakeListUptoDate(Follower: TBoldFollower); override; + procedure _AfterMakeCellUptoDate(Follower: TBoldFollower); override; + procedure TypeChanged(aNewType, aOldType: TBoldElementTypeInfo); override; + procedure ConnectEvents(AConnect: boolean); + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + procedure CreateAllItems(AMissingItemsOnly: Boolean); + procedure EnsureConstraintColumn; + function GetItemByExpression(const AExpression: string): TObject; + function GetItem(Index: Integer): TObject; override; + procedure ChangeValueTypeClass(AItemIndex: Integer; AValueTypeClass: TcxValueTypeClass); override; + procedure DoStartDrag(Sender: TObject; var DragObject: TDragObject); + procedure DoDragOver(Sender, Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean); + procedure DoDragDrop(Sender, Source: TObject; X, Y: Integer); + procedure DoEndDrag(Sender, Target: TObject; X, Y: Integer); + function CreateItem(aGridView: TcxCustomGridTableView; const aExpression, aCaption, aValueType, aName: string): TcxCustomGridTableItem; + procedure BeginFullUpdate; override; + procedure EndFullUpdate; override; + function CreateDetailLinkObject(ARelation: TcxCustomDataRelation; + ARecordIndex: Integer): TObject; override; + procedure FocusControl(AItemIndex: Integer; var Done: Boolean); override; + function GetDetailDataControllerByLinkObject(ALinkObject: TObject): TcxCustomDataController; override; + function GetDisplayText(ARecordIndex, AItemIndex: Integer): string; override; + function GetFilterDataValue(ARecordIndex: Integer; AField: TcxCustomDataField): Variant; override; + function GetFilterItemFieldCaption(AItem: TObject): string; override; + function GetItemSortByDisplayText(AItemIndex: Integer; ASortByDisplayText: Boolean): Boolean; override; + function GetItemValueSource(AItemIndex: Integer): TcxDataEditValueSource; override; + procedure UpdateData; override; + procedure ReloadStorage; + procedure AdjustActiveRange(aList: TBoldList = nil; aItem: integer = -1); override; + procedure CollectVisibleRecords(var aList: TBoldList); + procedure PreFetchColumns(AList: TBoldList; AItem: integer = -1); override; +// procedure DoGroupingChanged; override; +// procedure DoSortingChanged; override; + // Master-Detail: Grid Notifications + procedure SetMasterRelation(AMasterRelation: TcxCustomDataRelation; AMasterRecordIndex: Integer); override; + procedure SetValueTypeAndProperties(aMember: TBoldMemberRtInfo; aItem: TcxCustomGridTableItem; aChangeProperties: boolean = true); overload; + procedure SetValueTypeAndProperties(aElementTypeInfo: TBoldElementTypeInfo; aItem: TcxCustomGridTableItem; aChangeProperties: boolean = true); overload; + procedure ForEachRow(ASelectedRows: Boolean; AProc: TcxDataControllerEachRowProc); override; + property GridView: TcxCustomGridTableView read GetGridViewValue; + property Controller: TcxCustomGridTableController read GetController; + published + property BoldProperties; + property BoldHandle; + property BoldHandleIndexLock; + property BoldAutoColumns; +// property OnBeforeLoad; + property OnAfterLoad; + property LoadAll; + + property Filter; + property Options; + property Summary; + property OnAfterCancel; + property OnAfterDelete; + property OnAfterInsert; + property OnAfterPost; + property OnBeforeCancel; + property OnBeforeDelete; + property OnBeforeInsert; + property OnBeforePost; + property OnNewRecord; + property OnCompare; + property OnDataChanged; + property OnDetailCollapsing; + property OnDetailCollapsed; + property OnDetailExpanding; + property OnDetailExpanded; + property OnFilterRecord; + property OnGroupingChanged; + property OnRecordChanged; + property OnSortingChanged; + end; + + TcxGridItemBoldDataBinding = class(TcxGridItemDataBinding) + private + fBoldProperties: TBoldVariantFollowerController; + fSubscriber: TBoldPassthroughSubscriber; + procedure Receive(Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent); + function GetDataController: TcxGridBoldDataController; + function GetBoldProperties: TBoldVariantFollowerController; + procedure SetBoldProperties(Value: TBoldVariantFollowerController); + protected + function GetDefaultValueTypeClass: TcxValueTypeClass; override; + procedure Init; override; + procedure Remove; + public + constructor Create(AItem: TcxCustomGridTableItem); override; + destructor Destroy; override; + procedure Assign(Source: TPersistent); override; + property DataController: TcxGridBoldDataController read GetDataController; + published + property BoldProperties: TBoldVariantFollowerController read GetBoldProperties write SetBoldProperties; + end; + + TcxGridBoldColumn = class(TcxGridColumn, IBoldAwareViewItem, IcxStoredObject) + private + function GetDataBinding: TcxGridItemBoldDataBinding; + procedure SetDataBinding(Value: TcxGridItemBoldDataBinding); + protected + // IcxStoredObject + function GetProperties(AProperties: TStrings): Boolean; + procedure GetPropertyValue(const AName: string; var AValue: Variant); override; + procedure SetPropertyValue(const AName: string; const AValue: Variant); override; + function CalculateBestFitWidth: Integer; override; + procedure VisibleChanged; override; + public + destructor Destroy; override; + published + property DataBinding: TcxGridItemBoldDataBinding read GetDataBinding write SetDataBinding implements IBoldAwareViewItem; + end; + + TcxBoldDataControllerSearch = class(TcxDataControllerSearch) + public + // the sole purpose of these overrides is to ensure range (fetch in 1 pass) +{$IFDEF BOLD_DELPHI25_OR_LATER} + function Locate(AItemIndex: Integer; const ASubText: string; AIsAnywhere: Boolean = False; ASyncSelection: Boolean = True): Boolean; override; + function LocateNext(AForward: Boolean; AIsAnywhere: Boolean = False; ASyncSelection: Boolean = True): Boolean; override; +{$ELSE} + function Locate(AItemIndex: Integer; const ASubText: string; AIsAnywhere: Boolean = False): Boolean; override; + function LocateNext(AForward: Boolean; AIsAnywhere: Boolean = False): Boolean; override; +{$ENDIF} + end; + + TcxGridBoldCardsViewInfo = class(TcxGridCardsViewInfo) + protected + end; + + TcxGridBoldCardViewViewInfo = class(TcxGridCardViewViewInfo) + protected + function GetSiteClass: TcxGridSiteClass; override; + function GetRecordsViewInfoClass: TcxCustomGridRecordsViewInfoClass; override; + end; + + TcxGridBoldCardView = class(TcxGridCardView, IBoldAwareView, IBoldValidateableComponent) + private + function GetDataController: TcxGridBoldDataController; + procedure SetDataController(Value: TcxGridBoldDataController); + // IBoldValidateableComponent + function ValidateComponent(ComponentValidator: TBoldComponentValidator; NamePrefix: string): Boolean; + // IBoldAwareView + function GetItemCount: Integer; + function GetItem(Index: Integer): IBoldAwareViewItem; + function GetSelection: TBoldList; + function GetCurrentBoldObject: TBoldObject; + function GetCurrentIndex: integer; + function GetCurrentElement: TBoldElement; + protected + function GetDataControllerClass: TcxCustomDataControllerClass; override; + function GetControllerClass: TcxCustomGridControllerClass; override; + function GetItemClass: TcxCustomGridTableItemClass; override; + function DoEditing(AItem: TcxCustomGridTableItem): Boolean; override; + function DoCellDblClick(ACellViewInfo: TcxGridTableDataCellViewInfo; + AButton: TMouseButton; AShift: TShiftState): Boolean; override; + procedure DoSelectionChanged; override; + function GetViewInfoClass: TcxCustomGridViewInfoClass; override; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + property Items[Index: Integer]: IBoldAwareViewItem read GetItem; default; + property ItemCount: Integer read GetItemCount; + property Selection: TBoldList read GetSelection; + property CurrentBoldObject: TBoldObject read GetCurrentBoldObject; + property CurrentElement: TBoldElement read GetCurrentElement; + property CurrentIndex: integer read GetCurrentIndex; + published + property DataController: TcxGridBoldDataController read GetDataController write SetDataController; + end; + + TcxGridBoldCardViewRow = class(TcxGridCardViewRow, IBoldAwareViewItem) + private + function GetDataBinding: TcxGridItemBoldDataBinding; + procedure SetDataBinding(Value: TcxGridItemBoldDataBinding); + protected + // IcxStoredObject + {function GetStoredProperties(AProperties: TStrings): Boolean; override; + procedure GetPropertyValue(const AName: string; var AValue: Variant); override; + procedure SetPropertyValue(const AName: string; const AValue: Variant); override;} + function CalculateBestFitWidth: Integer; override; + procedure VisibleChanged; override; + public + destructor Destroy; override; + published + property DataBinding: TcxGridItemBoldDataBinding read GetDataBinding write SetDataBinding implements IBoldAwareViewItem; + end; +(* + TcxGridBoldChartDataController = class(TcxBoldDataController, {TcxGridBoldDataController} IcxCustomGridDataController, + IcxGridChartViewItemsProvider) + private + { IcxGridChartViewItemsProvider } + function IcxGridChartViewItemsProvider.GetItem = GetChartItem; + function GetChartItem(AItemClass: TcxGridChartItemClass; AIndex: Integer): TcxGridChartItem; + procedure GetItemCaptions(AItemClass: TcxGridChartItemClass; ACaptions: TStringList); + procedure InitItem(AItem: TcxGridChartItem; AIndex: Integer); + procedure GetValidValueFields(AItemClass: TcxGridChartItemClass; AFields: TList); + { IcxCustomGridDataController } + procedure AssignData(ADataController: TcxCustomDataController); + procedure CreateAllItems(AMissingItemsOnly: Boolean); + procedure DeleteAllItems; + procedure GetFakeComponentLinks(AList: TList); + function HasAllItems: Boolean; + function IsDataChangeable: Boolean; + function SupportsCreateAllItems: Boolean; + published + property Options; +// property OnAfterSummary: TcxAfterSummaryEvent read GetOnAfterSummary write SetOnAfterSummary; + property OnCompare; + property OnDataChanged; + property OnFilterRecord; +// property OnSummary: TcxSummaryEvent read GetOnSummary write SetOnSummary; + end; + + TcxGridBoldChartItemDataBinding = class(TcxGridChartItemDataBinding) + private + fBoldProperties: TBoldVariantFollowerController; + procedure SetBoldProperties(Value: TBoldVariantFollowerController); + function GetDataController: TcxGridBoldChartDataController; + public + constructor Create(AGridView: TcxGridChartView; AIsValue: Boolean; + ADefaultValueTypeClass: TcxValueTypeClass); override; + destructor Destroy; override; + procedure Assign(Source: TPersistent); override; + property DataController: TcxGridBoldChartDataController read GetDataController; + property BoldProperties: TBoldVariantFollowerController read fBoldProperties write SetBoldProperties; + end; + + TcxGridBoldChartCategories = class(TcxGridChartCategories) + private + function GetDataBinding: TcxGridBoldChartItemDataBinding; + procedure SetDataBinding(Value: TcxGridBoldChartItemDataBinding); + published + property DataBinding: TcxGridBoldChartItemDataBinding read GetDataBinding write SetDataBinding; + end; + + TcxGridBoldChartDataGroup = class(TcxGridChartDataGroup) + private + function GetDataBinding: TcxGridBoldChartItemDataBinding; + procedure SetDataBinding(Value: TcxGridBoldChartItemDataBinding); + published + property DataBinding: TcxGridBoldChartItemDataBinding read GetDataBinding write SetDataBinding; + end; + + TcxGridBoldChartSeries = class(TcxGridChartSeries) + private + function GetDataBinding: TcxGridBoldChartItemDataBinding; + procedure SetDataBinding(Value: TcxGridBoldChartItemDataBinding); + published + property DataBinding: TcxGridBoldChartItemDataBinding read GetDataBinding write SetDataBinding; + end; + + TcxBoldGridChartView = class(TcxGridChartView, IBoldAwareView, IBoldValidateableComponent) + private + function GetCategories: TcxGridBoldChartCategories; + function GetDataController: TcxGridBoldChartDataController; + function GetDataGroup(Index: Integer): TcxGridBoldChartDataGroup; + function GetSeries(Index: Integer): TcxGridBoldChartSeries; + procedure SetCategories(Value: TcxGridBoldChartCategories); + procedure SetDataController(Value: TcxGridBoldChartDataController); + procedure SetDataGroup(Index: Integer; Value: TcxGridBoldChartDataGroup); + procedure SetSeries(Index: Integer; Value: TcxGridBoldChartSeries); + procedure ClearItems; + // IBoldValidateableComponent + function ValidateComponent(ComponentValidator: TBoldComponentValidator; NamePrefix: String): Boolean; + // IBoldAwareView + function GetItemCount: Integer; + function GetItem(Index: Integer): IBoldAwareViewItem; + function GetSelection: TBoldList; + property Selection: TBoldList read GetSelection; + protected + function GetCategoriesClass: TcxGridChartCategoriesClass; override; + function GetDataControllerClass: TcxCustomDataControllerClass; override; + function GetItemDataBindingClass: TcxGridChartItemDataBindingClass; override; + + function FindItemByFieldName(AItemClass: TcxGridChartItemClass; const AFieldName: string): TcxGridChartItem; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + property Items[Index: Integer]: IBoldAwareViewItem read GetItem; default; + property ItemCount: Integer read GetItemCount; + + function CreateDataGroup: TcxGridBoldChartDataGroup; + function FindDataGroupByFieldName(const AFieldName: string): TcxGridBoldChartDataGroup; + function GetDataGroupClass: TcxGridChartDataGroupClass; override; + property DataGroups[Index: Integer]: TcxGridBoldChartDataGroup read GetDataGroup write SetDataGroup; + + function CreateSeries: TcxGridBoldChartSeries; + function FindSeriesByFieldName(const AFieldName: string): TcxGridBoldChartSeries; + function GetSeriesClass: TcxGridChartSeriesClass; override; + property Series[Index: Integer]: TcxGridBoldChartSeries read GetSeries write SetSeries; + published + property Categories: TcxGridBoldChartCategories read GetCategories write SetCategories; + property DataController: TcxGridBoldChartDataController read GetDataController write SetDataController; + end; +*) + + TcxGridBoldBandedColumn = class(TcxGridBandedColumn, IBoldAwareViewItem {,IcxStoredObject}) + private + function GetDataBinding: TcxGridItemBoldDataBinding; + procedure SetDataBinding(Value: TcxGridItemBoldDataBinding); +// procedure HyperLinkClick(Sender: TObject); + protected + // IcxStoredObject +// function GetProperties(AProperties: TStrings): Boolean; +// procedure GetPropertyValue(const AName: string; var AValue: Variant); override; +// procedure SetPropertyValue(const AName: string; const AValue: Variant); override; + function CalculateBestFitWidth: Integer; override; + procedure VisibleChanged; override; + public + destructor Destroy; override; + published + property DataBinding: TcxGridItemBoldDataBinding read GetDataBinding write SetDataBinding implements IBoldAwareViewItem; + end; + + TcxGridBoldBandedRowsViewInfo = class(TcxGridBandedRowsViewInfo) + protected + end; + + TcxGridBoldBandedTableViewInfo = class(TcxGridBandedTableViewInfo) + protected + function GetRecordsViewInfoClass: TcxCustomGridRecordsViewInfoClass; override; + function GetSiteClass: TcxGridSiteClass; override; + procedure Calculate; override; + end; + + TcxGridBoldBandedTableView = class(TcxGridBandedTableView, IBoldAwareView, IBoldValidateableComponent) + private + FPrevFocusedRecordIndex: integer; + FPrevFocusedDataRecordIndex: integer; + procedure HookDragDrop; + function GetDataController: TcxGridBoldDataController; + procedure SetDataController(Value: TcxGridBoldDataController); + // IBoldValidateableComponent + function ValidateComponent(ComponentValidator: TBoldComponentValidator; NamePrefix: string): Boolean; + // IBoldAwareView + function GetItemCount: Integer; + function GetItem(Index: Integer): IBoldAwareViewItem; + function GetSelection: TBoldList; + function GetCurrentBoldObject: TBoldObject; + function GetCurrentIndex: integer; + function GetCurrentElement: TBoldElement; + protected + function GetDataControllerClass: TcxCustomDataControllerClass; override; + function GetControllerClass: TcxCustomGridControllerClass; override; + function GetItemClass: TcxCustomGridTableItemClass; override; + function DoCellDblClick(ACellViewInfo: TcxGridTableDataCellViewInfo; + AButton: TMouseButton; AShift: TShiftState): Boolean; override; + function DoEditing(AItem: TcxCustomGridTableItem): Boolean; override; + procedure DoSelectionChanged; override; + function GetViewInfoClass: TcxCustomGridViewInfoClass; override; + procedure DoChanged(AChangeKind: TcxGridViewChangeKind); override; + procedure DoFocusedRecordChanged(APrevFocusedRecordIndex, AFocusedRecordIndex, + APrevFocusedDataRecordIndex, AFocusedDataRecordIndex: Integer; + ANewItemRecordFocusingChanged: Boolean); override; +{$IFDEF DelayOnFocusedRecordChange} + procedure InheritedDoFocusedRecordChanged(APrevFocusedRecordIndex, AFocusedRecordIndex, // a bit ugly + APrevFocusedDataRecordIndex, AFocusedDataRecordIndex: Integer; + ANewItemRecordFocusingChanged: Boolean); +{$ENDIF} + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + property Items[Index: Integer]: IBoldAwareViewItem read GetItem; default; + property ItemCount: Integer read GetItemCount; + property Selection: TBoldList read GetSelection; + property CurrentBoldObject: TBoldObject read GetCurrentBoldObject; + property CurrentElement: TBoldElement read GetCurrentElement; + property CurrentIndex: integer read GetCurrentIndex; + published + property DataController: TcxGridBoldDataController read GetDataController write SetDataController; + end; + + TcxBoldGridSite = class(TcxGridSite) + protected + procedure WndProc(var Message: TMessage); override; + end; + + TLinkClickEvent = procedure(Sender: TObject; aElement: TBoldElement) of object; + + TcxBoldGridRowsViewInfo = class(TcxGridRowsViewInfo) + protected + end; + + TcxGridBoldTableViewInfo = class(TcxGridTableViewInfo) + protected + function GetRecordsViewInfoClass: TcxCustomGridRecordsViewInfoClass; override; + function GetSiteClass: TcxGridSiteClass; override; + procedure Calculate; override; + end; + + TcxGridBoldTableView = class(TcxGridTableView, IBoldAwareView, IBoldValidateableComponent) + private + fOnLinkClick: TLinkClickEvent; + FPrevFocusedRecordIndex: integer; + FPrevFocusedDataRecordIndex: integer; + procedure HookDragDrop; + function GetDataController: TcxGridBoldDataController; + procedure SetDataController(Value: TcxGridBoldDataController); + function GetSelection: TBoldList; + function GetCurrentBoldObject: TBoldObject; + function GetCurrentIndex: integer; + function GetCurrentElement: TBoldElement; + // IBoldValidateableComponent + function ValidateComponent(ComponentValidator: TBoldComponentValidator; NamePrefix: string): Boolean; + // IBoldAwareView + function GetItemCount: Integer; + function GetItem(Index: Integer): IBoldAwareViewItem; + function GetFake: TNotifyEvent; + procedure SetFake(const Value: TNotifyEvent); + protected + // IcxStoredObject + function GetProperties(AProperties: TStrings): Boolean; override; + procedure GetPropertyValue(const AName: string; var AValue: Variant); override; + procedure SetPropertyValue(const AName: string; const AValue: Variant); override; + + function GetDataControllerClass: TcxCustomDataControllerClass; override; + function GetControllerClass: TcxCustomGridControllerClass; override; + function GetItemClass: TcxCustomGridTableItemClass; override; + function DoEditing(AItem: TcxCustomGridTableItem): Boolean; override; + procedure DoEditKeyPress(AItem: TcxCustomGridTableItem; AEdit: TcxCustomEdit; + var Key: Char); override; + function DoCellDblClick(ACellViewInfo: TcxGridTableDataCellViewInfo; + AButton: TMouseButton; AShift: TShiftState): Boolean; override; + procedure DoSelectionChanged; override; + procedure DoChanged(AChangeKind: TcxGridViewChangeKind); override; + procedure DoFocusedRecordChanged(APrevFocusedRecordIndex, AFocusedRecordIndex, + APrevFocusedDataRecordIndex, AFocusedDataRecordIndex: Integer; + ANewItemRecordFocusingChanged: Boolean); override; +{$IFDEF DelayOnFocusedRecordChange} + procedure InheritedDoFocusedRecordChanged(APrevFocusedRecordIndex, AFocusedRecordIndex, // a bit ugly + APrevFocusedDataRecordIndex, AFocusedDataRecordIndex: Integer; + ANewItemRecordFocusingChanged: Boolean); +{$ENDIF} + procedure DoItemsAssigned; override; + function GetViewInfoClass: TcxCustomGridViewInfoClass; override; + procedure DoCustomDrawCell(ACanvas: TcxCanvas; AViewInfo: TcxGridTableDataCellViewInfo; + var ADone: Boolean); override; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + property Items[Index: Integer]: IBoldAwareViewItem read GetItem; default; + property ItemCount: Integer read GetItemCount; + property Selection: TBoldList read GetSelection; + property CurrentBoldObject: TBoldObject read GetCurrentBoldObject; + property CurrentElement: TBoldElement read GetCurrentElement; + property CurrentIndex: integer read GetCurrentIndex; + published + property DataController: TcxGridBoldDataController read GetDataController write SetDataController; + property DragMode; + property OnDelete: TNotifyEvent read GetFake write SetFake; + property OnInsert: TNotifyEvent read GetFake write SetFake; + + property OnLinkClick: TLinkClickEvent read fOnLinkClick write fOnLinkClick; + end; + + TcxGridBoldLayoutView = class(TcxGridLayoutView, IBoldAwareView, IBoldValidateableComponent) + private + function GetDataController: TcxGridBoldDataController; +// function GetItem(Index: Integer): TcxGridBoldLayoutViewItem; + procedure SetDataController(Value: TcxGridBoldDataController); +// procedure SetItem(Index: Integer; Value: TcxGridBoldLayoutViewItem); + // IBoldValidateableComponent + function ValidateComponent(ComponentValidator: TBoldComponentValidator; NamePrefix: string): Boolean; + // IBoldAwareView + function GetItemCount: Integer; + function GetItem(Index: Integer): IBoldAwareViewItem; + function GetSelection: TBoldList; + function GetCurrentBoldObject: TBoldObject; + function GetCurrentIndex: integer; + function GetCurrentElement: TBoldElement; + protected + function GetDataControllerClass: TcxCustomDataControllerClass; override; + function GetItemClass: TcxCustomGridTableItemClass; override; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + function CreateItem: TcxGridBoldLayoutViewItem; +// property Items[Index: Integer]: TcxGridBoldLayoutViewItem read GetItem write SetItem; + property Items[Index: Integer]: IBoldAwareViewItem read GetItem; default; + property ItemCount: Integer read GetItemCount; + property Selection: TBoldList read GetSelection; + property CurrentBoldObject: TBoldObject read GetCurrentBoldObject; + property CurrentElement: TBoldElement read GetCurrentElement; + property CurrentIndex: integer read GetCurrentIndex; + published + property DataController: TcxGridBoldDataController read GetDataController write SetDataController; + end; + + TcxGridBoldLayoutViewItem = class(TcxGridLayoutViewItem, IBoldAwareViewItem) + private + function GetDataBinding: TcxGridItemBoldDataBinding; + procedure SetDataBinding(Value: TcxGridItemBoldDataBinding); + public + destructor Destroy; override; + published + property DataBinding: TcxGridItemBoldDataBinding read GetDataBinding write SetDataBinding implements IBoldAwareViewItem; + end; + + + TcxBoldCustomDataProvider = class(TcxCustomDataProvider) + protected + function GetValue(ARecordIndex: Integer; AField: TcxCustomDataField): Variant; override; + procedure SetValue(ARecordIndex: Integer; AField: TcxCustomDataField; const Value: Variant); override; + function CanInsert: Boolean; override; + function CanDelete: Boolean; override; + procedure DeleteRecords(AList: TList); override; + function SetEditValue(ARecordIndex: Integer; AField: TcxCustomDataField; const AValue: Variant; AEditValueSource: TcxDataEditValueSource): Boolean; override; + function IsActiveDataSet: Boolean; override; + end; + + TcxGridBoldTableController = class(TcxGridTableController) + protected +{ procedure FocusedRecordChanged(APrevFocusedRecordIndex, AFocusedRecordIndex, + APrevFocusedDataRecordIndex, AFocusedDataRecordIndex: Integer; + ANewItemRecordFocusingChanged: Boolean); override; +} + function GetEditingControllerClass: TcxGridEditingControllerClass; override; + public + procedure DoKeyDown(var Key: Word; Shift: TShiftState); override; + procedure KeyDown(var Key: Word; Shift: TShiftState); override; + procedure KeyUp(var Key: Word; Shift: TShiftState); override; + end; + + TcxGridBoldBandedTableController = class(TcxGridBandedTableController) + protected + function GetEditingControllerClass: TcxGridEditingControllerClass; override; + public + procedure DoKeyDown(var Key: Word; Shift: TShiftState); override; + procedure KeyDown(var Key: Word; Shift: TShiftState); override; + procedure KeyUp(var Key: Word; Shift: TShiftState); override; + end; + + TcxGridBoldEditingController = class(TcxGridTableEditingController) + protected + procedure DoEditKeyDown(var Key: Word; Shift: TShiftState); override; + procedure EditChanged(Sender: TObject); override; + procedure EditExit(Sender: TObject); override; + public + procedure HideEdit(Accept: Boolean); override; + end; + + TcxGridBoldCardViewController = class(TcxGridCardViewController) + protected + function GetEditingControllerClass: TcxGridEditingControllerClass; override; +// procedure DoEditKeyDown(var Key: Word; Shift: TShiftState); override; +// procedure EditChanged(Sender: TObject); override; + public + end; + + TcxGridBoldCardEditingController = class(TcxGridEditingController) + protected +// procedure DoEditKeyDown(var Key: Word; Shift: TShiftState); override; + procedure EditChanged(Sender: TObject); override; +// procedure EditExit(Sender: TObject); override; + public +// procedure HideEdit(Accept: Boolean); override; + end; + + + TcxBoldDataSourceClass = class of TcxBoldDataSource; +{$IFDEF BoldDevExLog} + TcxBoldGridLogProc = procedure(aMessage: string; aCategory: string = '') of object; +{$ENDIF} + +var + cxBoldDataSourceClass: TcxBoldDataSourceClass = TcxBoldDataSource; +{$IFDEF BoldDevExLog} + cxBoldGridLogProc: TcxBoldGridLogProc; +{$ENDIF} + +{$IFDEF BoldDevExLog} +procedure _Log(aMessage: string; aCategory: string = ''); +{$ENDIF} + +implementation + +uses + Dialogs, + Forms, + Graphics, + Math, + SysUtils, + Variants, + Windows, +{$IFDEF BOLD_DELPHI16_OR_LATER}UiTypes,{$ENDIF} + + BoldAFP, + BoldAttributes, + BoldBase, + BoldCommonBitmaps, + BoldControlPackDefs, + BoldDefs, + BoldDerivedValueSet, + BoldElementList, + BoldEnvironment, + BoldGui, + BoldId, + BoldListControlPack, + BoldListHandle, + BoldMLAttributes, + BoldOcl, + BoldQueue, + BoldReferenceHandle, + BoldSystemPersistenceHandler, + BoldValueSpaceInterfaces, + + cxCalendar, + cxCheckBox, + cxClasses, + cxControls, + cxCurrencyEdit, + cxFilterConsts, + cxFilterControlUtils, + cxGridCommon, + cxGridLevel, + cxGridRows, + cxHyperLinkEdit, + cxImage, + cxSpinEdit, + cxTextEdit, + cxTimeEdit, + +{$IFDEF SpanFetch} + AttracsSpanFetchManager, +{$ENDIF} + BoldGuard, TypInfo; + +const + cOCLConstraint = 'constraints->select(c|not c)->size = 0'; + beSystemDestroying = 100; + beSelectionDestroying = 101; + +type + EcxGridBoldSupport = class(Exception); + TcxCustomDataControllerAccess = class(TcxCustomDataController); + TcxGridTableControllerAccess = class(TcxGridTableController); + TBoldListHandleFollowerAccess = class(TBoldListHandleFollower); + TBoldFollowerAccess = class(TBoldFollower); + TBoldFollowerControllerAccess = class(TBoldFollowerController); + TcxCustomGridTableItemAccess = class(TcxCustomGridTableItem); + TcxGridLevelAccess = class(TcxGridLevel); + TcxCustomDataProviderAccess = class(TcxCustomDataProvider); + TcxCustomGridRecordAccess = class(TcxCustomGridRecord); + TcxCustomGridTableViewAccess = class(TcxCustomGridTableView); + TcxCustomDataControllerInfoAccess = class(TcxCustomDataControllerInfo); + TBoldQueueableAccess = class(TBoldQueueable); + +{$IFDEF BoldDevExLog} +procedure _Log(aMessage: string; aCategory: string = ''); +begin + if Assigned(cxBoldGridLogProc) then + cxBoldGridLogProc(aMessage, aCategory); +end; +{$ENDIF} + +function InternalSetValue(aFollower: TBoldFollower; const AValue: Variant): boolean; +var + lController: TBoldVariantFollowerController; +begin + result := false; + lController := aFollower.Controller as TBoldVariantFollowerController; + if VarIsNull(aValue) then + lController.MayHaveChanged('', aFollower) + else + lController.MayHaveChanged(aValue, aFollower); +end; + +{ TcxGridBoldDataController } + +procedure TcxGridBoldDataController.SetValueTypeAndProperties( + aElementTypeInfo: TBoldElementTypeInfo; aItem: TcxCustomGridTableItem; + aChangeProperties: boolean); +var + lAttributeClass: TClass; + lValueType: string; + lBAValueSet: TBAValueSet; + lBoldAttributeTypeInfo: TBoldAttributeTypeInfo; + i: integer; +begin + lValueType := 'String'; + if aElementTypeInfo is TBoldAttributeTypeInfo then + begin + lBoldAttributeTypeInfo := TBoldAttributeTypeInfo(aElementTypeInfo); + lAttributeClass := lBoldAttributeTypeInfo.AttributeClass; + if not Assigned(lAttributeClass) then + begin + raise EcxGridBoldSupport.Create('Custom attribute ' + aElementTypeInfo.ModelName + ' is not installed in IDE.'); + end; + // Blob, ValueSet and Associations map to string + if lAttributeClass.InheritsFrom(TBAString) then + begin + lValueType := 'String'; + if aChangeProperties then + aItem.PropertiesClass := TcxTextEditProperties; + end + else + if lAttributeClass.InheritsFrom(TBATime) then + begin + lValueType := 'DateTime'; + if aChangeProperties then + begin + aItem.PropertiesClass := TcxTimeEditProperties; + (aItem.Properties as TcxTimeEditProperties).Alignment.Horz := taRightJustify; + end; + end + else + if lAttributeClass.InheritsFrom(TBAMoment) then + begin + lValueType := 'DateTime'; + if aChangeProperties then + begin + aItem.PropertiesClass := TcxDateEditProperties; + (aItem.Properties as TcxDateEditProperties).Alignment.Horz := taRightJustify; + end; + end + else + if lAttributeClass.InheritsFrom(TBABoolean) then + begin + lValueType := 'Boolean'; + if aChangeProperties then + aItem.PropertiesClass := TcxCheckBoxProperties; + end + else + if lAttributeClass.InheritsFrom(TBACurrency) then + begin + lValueType := 'Currency'; + if aChangeProperties then + begin + aItem.PropertiesClass := TcxCurrencyEditProperties; + (aItem.Properties as TcxCurrencyEditProperties).Alignment.Horz := taRightJustify; + end; + end + else + if lAttributeClass.InheritsFrom(TBANumeric) then + begin + if aChangeProperties then + begin + aItem.PropertiesClass := TcxSpinEditProperties; + (aItem.properties as TcxSpinEditProperties).SpinButtons.Visible := false; + (aItem.Properties as TcxSpinEditProperties).Alignment.Horz := taRightJustify; + (aItem.Properties as TcxSpinEditProperties).Increment := 0; + (aItem.Properties as TcxSpinEditProperties).LargeIncrement := 0; + end; + if lAttributeClass.InheritsFrom(TBAFloat) then + begin + lValueType := 'Float'; + if aItem.properties is TcxSpinEditProperties then + (aItem.properties as TcxSpinEditProperties).ValueType := vtFloat; + end + else + if lAttributeClass.InheritsFrom(TBASMallInt) then + begin + lValueType := 'Smallint'; + if aItem.properties is TcxSpinEditProperties then + (aItem.properties as TcxSpinEditProperties).ValueType := vtInt; + end + else + if lAttributeClass.InheritsFrom(TBAWord) then + begin + lValueType := 'Word'; + if aItem.properties is TcxSpinEditProperties then + (aItem.properties as TcxSpinEditProperties).ValueType := vtInt; + end + else + if lAttributeClass.InheritsFrom(TBAInteger) then + begin + lValueType := 'Integer'; + if aItem.properties is TcxSpinEditProperties then + (aItem.properties as TcxSpinEditProperties).ValueType := vtInt; + end; + end + else + {$IFDEF IEJpegImage} + if lAttributeClass.InheritsFrom(TBABlobImageJPEG) then + begin + lValueType := ''; + if aChangeProperties then + begin + aItem.PropertiesClass := TcxImageProperties; + (aItem.properties as TcxImageProperties).GraphicClassName := 'TIEJpegImage'; + end; + end + else + {$ENDIF} + if lAttributeClass.InheritsFrom(TBABlobImageBMP) or lAttributeClass.InheritsFrom(TBABlobImageJPEG) then + begin + lValueType := ''; + if aChangeProperties then + aItem.PropertiesClass := TcxImageProperties; + end + else + if aChangeProperties and lAttributeClass.InheritsFrom(TBAValueSet) then + begin + if lAttributeClass.InheritsFrom(TBALanguage) or lAttributeClass.InheritsFrom(TBADerivedValueSetValueList) and GridView.IsDesigning then + begin + MessageDlg(Format('Combo values for ''%s'' can only be fetched at run time', [aElementTypeInfo.expressionName]), mtError, [mbOk], 0); + end + else + begin + lBAValueSet := TBoldMemberFactory.CreateMemberFromBoldType(aElementTypeInfo) as TBAValueSet; + try + aItem.PropertiesClass := TcxComboBoxProperties; + (aItem.Properties as TcxComboBoxProperties).Items.Clear; + for i := 0 to lBAValueSet.Values.Count - 1 do + begin + (aItem.Properties as TcxComboBoxProperties).Items.Add(lBAValueSet.Values[i].AsString); + end; + (aItem.Properties as TcxComboBoxProperties).DropDownListStyle := lsEditFixedList; + (aItem.Properties as TcxComboBoxProperties).DropDownRows := lBAValueSet.Values.Count; + finally + lBAValueSet.Free; + end; + end; + end; + end; + aItem.DataBinding.ValueType := lValueType; +end; + +procedure TcxGridBoldDataController.SetValueTypeAndProperties(aMember: TBoldMemberRtInfo; aItem: TcxCustomGridTableItem; aChangeProperties: boolean); +begin + SetValueTypeAndProperties(aMember.boldType, aItem); +end; + +procedure TcxGridBoldDataController.ChangeValueTypeClass(AItemIndex: Integer; + AValueTypeClass: TcxValueTypeClass); +begin + // this code is copied from inherited TcxCustomDataController.ChangeValueTypeClass and RestructData is commented out + // Commenting out RestructData causes other problems. + // Probably it has to be only called once, not for each item. That should be implemented + CheckItemRange(AItemIndex); + if GetItemValueTypeClass(AItemIndex) <> AValueTypeClass then + begin + Fields[AItemIndex].ValueTypeClass := AValueTypeClass; +// if {IsProviderMode and} not TcxCustomGridTableViewAccess(GridView).IsAssigningItems then +// RestructData; + DataControllerInfo.UpdateField(Fields[AItemIndex]); + DoValueTypeClassChanged(AItemIndex); + end; +end; + +procedure TcxGridBoldDataController.CheckDataSetCurrent; +var + i: integer; + lChanged: boolean; + lState : TKeyboardState; +begin + inherited; + if Assigned(BoldHandle) and Assigned(CustomDataSource) and (FSkipSyncFocusedRecord = 0) and not (csDestroying in GridView.ComponentState) then + begin + i := FocusedRecordIndex; + if (i >= RecordCount) then + begin + FocusedRecordIndex := -1; + i := -1; + end; + lChanged := (i <> Follower.CurrentIndex) {or (i <> BoldHandle.CurrentIndex)}; + if not lChanged and (i <> BoldHandle.CurrentIndex) then + lChanged := true; + + if lChanged then + begin + {$IFDEF BoldDevExLog} + if GridView <> nil then + _Log(GridView.Name + ':CheckDataSetCurrent', className) + else + _Log(':CheckDataSetCurrent', className); + {$ENDIF} + ConnectEvents(false); + inc(FSkipMakeCellUptoDate); + BeginUpdate; + try +// TBoldQueueable.DisplayAll; + fBoldHandleFollower.SetFollowerIndex(i); + GetKeyboardState(lState); + if i <> -1 then + begin + i := GetRowIndexByRecordIndex(i, false); + end; + if not (((lState[VK_CONTROL] and 128) <> 0) or ((lState[VK_SHIFT] and 128) <> 0)) and ((i = -1) or not IsRowSelected(i)) then + begin + Controller.ClearSelection; + if Assigned(Controller.FocusedRecord) and not MultiSelect then + Controller.FocusedRecord.Selected := true; + end; + finally + DisplayFollowers; + ConnectEvents(True); + dec(FSkipMakeCellUptoDate); + SelectionChanged; + EndUpdate; + end; + end; + end; +end; + +procedure TcxGridBoldDataController.ConnectEvents(AConnect: boolean); +var + i: integer; +begin + for i := 0 to ItemCount - 1 do + begin + if AConnect then + BoldPropertiesFromItem(i).AfterMakeUptoDate := _AfterMakeCellUptoDate + else + BoldPropertiesFromItem(i).AfterMakeUptoDate := nil; + end; + if AConnect then + begin + fBoldProperties.AfterMakeUptoDate := _AfterMakeListUptoDate; + fBoldProperties.BeforeMakeUptoDate := _BeforeMakeListUptoDate; + fBoldProperties.OnAfterInsertItem := _InsertRow; + fBoldProperties.OnAfterDeleteItem := _DeleteRow; + fBoldProperties.OnReplaceitem := _ReplaceRow + end + else + begin + fBoldProperties.AfterMakeUptoDate := nil; + fBoldProperties.BeforeMakeUptoDate := nil; + fBoldProperties.OnAfterInsertItem := nil; + fBoldProperties.OnAfterDeleteItem := nil; + fBoldProperties.OnReplaceitem := nil; + end; +end; + +procedure TcxGridBoldDataController.ConstraintColumnCustomDrawCell( + Sender: TcxCustomGridTableView; ACanvas: TcxCanvas; + AViewInfo: TcxGridTableDataCellViewInfo; var ADone: Boolean); +var + ARect: TRect; + lConstraintBitmap: Graphics.TBitmap; + lValue: Variant; +begin + if AViewInfo is TcxGridCardRowCaptionViewInfo then exit; + with AViewInfo do + begin + ARect := Bounds; +// ACanvas.Brush.Style := bsClear; + ACanvas.FillRect(ARect, ACanvas.Brush.Color); + if AViewInfo.RecordViewInfo.Index = -1 then + begin + // draw nothing + end + else + begin + lValue := Value; + if not VarIsNull(lValue) and lValue then + lConstraintBitmap := bmpBoldGridConstraint_true + else + lConstraintBitmap := bmpBoldGridConstraint_false; + lConstraintBitmap.Transparent := true; + ACanvas.Draw(ARect.Left + 4, ARect.Top + 4, lConstraintBitmap); + end; + end; + ADone := true; +end; + +procedure TcxGridBoldDataController.ColumnCustomDrawCell( + Sender: TcxCustomGridTableView; ACanvas: TcxCanvas; + AViewInfo: TcxGridTableDataCellViewInfo; var ADone: Boolean); +var + lBoldVariantFollowerController: TBoldVariantFollowerController; + lColor: TColor; + lCellFollower: TBoldFollower; +begin + inc(FSkipMakeCellUptoDate); + try + if not AViewInfo.RecordViewInfo.Focused then + begin + lCellFollower := CellFollowers[AViewInfo.RecordViewInfo.GridRecord.RecordIndex, AViewInfo.Item.Id]; + if Assigned(lCellFollower) then + begin + lBoldVariantFollowerController := lCellFollower.Controller as TBoldVariantFollowerController; + lBoldVariantFollowerController.SetColor(lColor, ACanvas.Brush.Color, lCellFollower); + lBoldVariantFollowerController.SetFont(ACanvas.Font, ACanvas.Font, lCellFollower); + if LColor > -1 then + ACanvas.Brush.Color := lColor; + end; + end; + finally + dec(FSkipMakeCellUptoDate); + end; +end; + +procedure TcxGridBoldDataController.GetCellHint(Sender: TcxCustomGridTableItem; ARecord: TcxCustomGridRecord; + ACellViewInfo: TcxGridTableDataCellViewInfo; const AMousePos: TPoint; + var AHintText: TCaption; var AIsHintMultiLine: Boolean; var AHintTextRect: TRect); +var + lIE: TBoldIndirectElement; +begin + if VarIsType(ACellViewInfo.Value, varBoolean) and (not ACellViewInfo.Value) then +// if (not VarIsNull(ACellViewInfo.Value)) and (not ACellViewInfo.Value) then + begin + lIE := TBoldIndirectElement.Create; + try + Follower.SubFollowers[ARecord.RecordIndex].Element.EvaluateExpression('constraints->select(c|not c)', lIE); + AHintText := (lIE.Value as TBoldList).AsCommaText(false, 11); + finally + lIE.free; + end; + end; +end; + +procedure TcxGridBoldDataController.CreateAllItems( + AMissingItemsOnly: Boolean); + +function ClassTypeHasConstraints(aBoldClassTypeInfo: TBoldClassTypeInfo): boolean; +var + lBoldClassTypeInfo: TBoldClassTypeInfo; +begin + lBoldClassTypeInfo := aBoldClassTypeInfo; + repeat + // BoldClassTypeInfo.ConstraintCount doesn't include inherited constraints so we have to iterate + result := lBoldClassTypeInfo.ConstraintCount > 0; + lBoldClassTypeInfo := lBoldClassTypeInfo.SuperClassTypeInfo; + until result or (lBoldClassTypeInfo = nil); +end; + +var + I: Integer; + lListElementType: TBoldElementTypeInfo; + lClasstypeInfo: TBoldClassTypeInfo; + lMember: TBoldMemberRtInfo; + lcxCustomGridTableItem: TcxCustomGridTableItem; +begin + if (BoldHandle = nil) or (BoldHandle.ListElementType = nil) then Exit; + ShowHourglassCursor; + fCreatingColumns := true; + try + GridView.BeginUpdate; + BeginUpdateFields; + try + lListElementType := BoldHandle.ListElementType; + if (lListElementType is TBoldClassTypeInfo) then + begin + lClassTypeInfo := lListElementType as TBoldClassTypeInfo; + if ClassTypeHasConstraints(lClassTypeInfo) and (not AMissingItemsOnly or (GetItemByExpression(cOCLConstraint) = nil)) then + begin + // create constraint column + EnsureConstraintColumn; + end; + if (lClassTypeInfo.DefaultStringRepresentation <> '') and (lClassTypeInfo.AllMembers.Count = 0) then + begin + if not AMissingItemsOnly or (GetItemByExpression('') = nil) then + begin + CreateItem(GridView, '', lClassTypeInfo.ModelName, 'String', 'DefaultStringRepresentation'); + end; + end; + for i := 0 to lClassTypeInfo.AllMembers.Count - 1 do + begin + lMember := lClassTypeInfo.AllMembers[I]; + if (lMember.IsAttribute or (lMember.IsSingleRole and TBoldRoleRTInfo(lMember).IsNavigable)) and not lMember.DelayedFetch then + begin + if not AMissingItemsOnly or (GetItemByExpression(lMember.ExpressionName) = nil) then + begin + lcxCustomGridTableItem := CreateItem(GridView, lMember.ExpressionName, lMember.ModelName, 'String', lMember.ModelName); + if lMember.IsSingleRole then + begin + lcxCustomGridTableItem.DataBinding.ValueType := 'String'; + end + else + begin + SetValueTypeAndProperties(lMember, lcxCustomGridTableItem); + end; + end; + end; + end; + end + else if (lListElementType is TBoldAttributeTypeInfo) then + begin + if not AMissingItemsOnly or (GetItemByExpression('') = nil) then + begin + CreateItem(GridView, '', TBoldAttributeTypeInfo(lListElementType).ModelName, 'String', TBoldAttributeTypeInfo(lListElementType).ModelName); + end; + end + else if (lListElementType is TBoldListTypeInfo) then + begin + if not AMissingItemsOnly or (GetItemByExpression('') = nil) then + begin + CreateItem(GridView, '', 'ClassName', 'String', 'ClassName'); + end; + end; + if (GridView.ItemCount = 0) or ((GridView.ItemCount = 1) and ((GridView.Items[0] as IBoldAwareViewItem).BoldProperties.expression = cOCLConstraint)) then + begin + CreateItem(GridView, '', lListElementType.asString, 'String', lListElementType.asString); + end; + finally + EndUpdateFields; + GridView.EndUpdate; + end; + finally + HideHourglassCursor; + fCreatingColumns := false; + end; +end; + +{ +procedure TcxGridBoldDataController.DoGroupingChanged; +begin + inherited; + +end; + +procedure TcxGridBoldDataController.DoSortingChanged; +begin + inherited; + +end; +} + +function TcxGridBoldDataController.GetController: TcxCustomGridTableController; +begin + Result := GridView.Controller; +end; + +function TcxGridBoldDataController.GetGridViewValue: TcxCustomGridTableView; +begin + result := TcxCustomGridTableView(GetGridView); +end; + +function TcxGridBoldDataController.GetItem(Index: Integer): TObject; +begin + Result := GridView.Items[Index]; +end; + +function TcxGridBoldDataController.GetItemByExpression( + const aExpression: string): TObject; +var + I: Integer; +begin + Result := nil; + for I := 0 to ItemCount - 1 do + begin + if AnsiCompareText(BoldPropertiesFromItem(i).Expression, aExpression) = 0 then + begin + Result := GetItem(I); + Break; + end; + end; +end; + +function TcxGridBoldDataController.GetItemData(AItem: TObject): Integer; +begin + if AItem is TcxCustomGridTableItem then + Result := Integer(TcxCustomGridTableItem(AItem).DataBinding.Data) + else + Result := -1; +end; + +function TcxGridBoldDataController.GetItemDataBindingClass: TcxGridItemDataBindingClass; +begin + Result := TcxGridItemBoldDataBinding; +end; + +function TcxGridBoldDataController.HasAllItems: Boolean; +begin + result := false; +end; + +function TcxGridBoldDataController.SupportsCreateAllItems: Boolean; +begin + result := true; +end; + +procedure TcxGridBoldDataController.ForEachRow(ASelectedRows: Boolean; + AProc: TcxDataControllerEachRowProc); +var + i: integer; + lList: TBoldList; + IsObjectList: boolean; + lWholeList: TBoldList; + lGuard: IBoldGuard; +begin + if ASelectedRows then + begin + if GetSelectedCount > 0 then + begin + lWholeList := BoldList; + lGuard := TBoldGuard.Create(lList); + lList := CreateList; + lList.DuplicateMode := bldmAllow; + lList.Capacity := GetSelectedCount; + IsObjectList := (lList is TBoldObjectList) and (lWholeList is TBoldObjectList); + for i := 0 to GetSelectedCount - 1 do // or Controller.SelectedRecordCount ? + begin + if IsObjectList then + TBoldObjectList(lList).AddLocator( TBoldObjectList(lWholeList).Locators[Controller.SelectedRecords[i].RecordIndex] ) + else + lList.Add(lWholeList[Controller.SelectedRecords[i].RecordIndex]); + end; + AdjustActiveRange(lList); + end; + end + else + begin + AdjustActiveRange; + end; + inherited; +end; + +procedure TcxGridBoldDataController.SetMasterRelation( + AMasterRelation: TcxCustomDataRelation; AMasterRecordIndex: Integer); +var + lReferenceHandle: TBoldReferenceHandle; + lListHandle: TBoldListHandle; + lGridLevel: TcxGridLevel; + lPatternView: IBoldAwareView; + lMasterElement: TBoldElement; + lBoldAwareView: IBoldAwareView; +begin + if Assigned(AMasterRelation) and (AMasterRelation.Item is TcxGridLevel) then + begin + lGridLevel := (AMasterRelation.Item as TcxGridLevel); + if lGridLevel.GridView.IsPattern and (lGridLevel.GridView <> GridView) then + begin + lBoldAwareView := lGridLevel.GridView.MasterGridView as IBoldAwareView; + Assert(lBoldAwareView.DataController.BoldHandle.List.count > AMasterRecordIndex); + lBoldAwareView.DataController.BoldHandle.CurrentIndex := AMasterRecordIndex; + lMasterElement := lBoldAwareView.DataController.BoldHandle.Value; + lPatternView := (lGridLevel.GridView as IBoldAwareView); + lReferenceHandle := TBoldReferenceHandle.Create(GetOwnerOrView); + lReferenceHandle.Value := lMasterElement; + lListHandle := TBoldListHandle.Create(GetOwnerOrView); + lListHandle.RootHandle := lReferenceHandle; + if Assigned(lPatternView.DataController.BoldHandle) and (lPatternView.DataController.BoldHandle is TBoldListHandle) then + begin + lListHandle.expression := (lPatternView.DataController.BoldHandle as TBoldListHandle).Expression; + lListHandle.mutableListexpression := (lPatternView.DataController.BoldHandle as TBoldListHandle).mutableListexpression; + lListHandle.name := CreateUniqueName(GetOwnerOrView, GridView, lListHandle, '', 'md_' + lPatternView.DataController.BoldHandle.name); + end; + BoldAutoColumns := false; // lPatternView.DataController.BoldAutoColumns; + BoldHandle := lListHandle; + GridView.Name := CreateUniqueName(GetOwnerOrView, GetOwnerOrView, GridView, '', lGridLevel.GridView.Name); + end; + end; + inherited; +end; + +type + TcxCustomGridTableControllerHack = class(TcxCustomGridTableController); + +procedure TcxGridBoldDataController.SelectionChanged; +var + i, j: integer; + lSelectedIndex: integer; + lFollower: TBoldFollower; + lCount: integer; + lList: TBoldList; + lIndex: integer; +// lBoldAwareView: IBoldAwareView; + lSelection: TBoldList; + lRecordCount: integer; +begin + {$IFDEF BoldDevExLog} + _Log(GridView.Name + ':DoSelectionChanged', className); + {$ENDIF} +// GridView.GetInterface(IBoldAwareView, lBoldAwareView); + lSelection := fSelection;// lBoldAwareView.Selection; + if Assigned(lSelection) then + lSelection.Clear; + lFollower := Follower; + j := Controller.SelectedRecordCount; + if Assigned(BoldHandle) and Assigned(Follower.Element) and (lFollower.Element is TBoldObjectList) then + begin + lList := BoldList; + if (j > 0) and (j >= lList.Count) then + begin + if Assigned(lSelection) then + lSelection.AddList(lList); + BoldProperties.SelectAll(lFollower, true); + end + else + begin + lCount := lList.count; + lRecordCount := TcxCustomGridTableControllerHack(GridView.Controller).ViewData.RecordCount; + BoldProperties.SelectAll(lFollower, false); + for i := 0 to j - 1 do + begin + lIndex := GetSelectedRowIndex(i); + if lIndex < lRecordCount then + begin + lSelectedIndex := Controller.SelectedRecords[i].RecordIndex; + if lSelectedIndex < lCount then + begin + if Assigned(lSelection) then + lSelection.Add(lList[lSelectedIndex]); + BoldProperties.SetSelected(lFollower, lSelectedIndex, true); + end; + end; + end; + end; + if not MultiSelect and (Follower.SubFollowerCount > 0) and (Follower.CurrentIndex <> -1) and (Follower.CurrentIndex < Follower.SubFollowerCount) then + begin + if Assigned(lSelection) and Assigned(Follower.CurrentSubFollower) then + lSelection.Add(Follower.CurrentSubFollower.Element); + BoldProperties.SetSelected(lFollower, Follower.CurrentIndex, true); + end; + end + else + begin + if Assigned(lSelection) then + lSelection.Clear; + BoldProperties.SelectAll(lFollower, false); + end; + {$IFDEF DisplayAll} +// TBoldQueueable.DisplayAll; + {$ENDIF} +end; + +function TcxGridBoldDataController.DoEditing(AItem: TcxCustomGridTableItem): Boolean; +var + lRecord: integer; + lFollower: TBoldFollower; + lIcxBoldEditProperties: IcxBoldEditProperties; +begin + lRecord := RecNo; + Assert(lRecord <> -1, 'lRecord <> -1'); + lFollower := CellFollowers[lRecord, AItem.ID]; + if not Assigned(lFollower) then + begin + TBoldQueueable.DisplayAll; + lFollower := CellFollowers[lRecord, AItem.ID]; +// Assert(Assigned(lFollower)); + end; + result := Assigned(lFollower); + if Assigned(lFollower) then + begin + lFollower.EnsureDisplayable; + result := lFollower.Controller.MayModify(lFollower); + Assert(AItem.GetProperties <> nil); + if Supports(AItem.GetProperties, IcxBoldEditProperties, lIcxBoldEditProperties) then + begin + result := lIcxBoldEditProperties.CanEdit(BoldHandle, lFollower); + end + end; +end; + +procedure TcxGridBoldDataController.AssignData( + ADataController: TcxCustomDataController); +begin +end; + +procedure TcxGridBoldDataController.CheckGridModeBufferCount; +begin +// UpdateGridModeBufferCount; +end; + +procedure TcxGridBoldDataController.DeleteAllItems; +begin + GridView.ClearItems; +end; + +function TcxGridBoldDataController.DoScroll(AForward: Boolean): Boolean; +begin + Result := SupportsScrollBarParams; + if Result then + if AForward then + Controller.GoToNext(False, False) + else + Controller.GoToPrev(False, False); +end; + +function TcxGridBoldDataController.DoScrollPage( + AForward: Boolean): Boolean; +begin + Result := SupportsScrollBarParams; + if Result then + if AForward then + TcxCustomGridTableControllerAccess.FocusNextPage(Controller, False) + else + TcxCustomGridTableControllerAccess.FocusPrevPage(Controller, False); +end; + +procedure TcxGridBoldDataController.GetFakeComponentLinks(AList: TList); +begin + if (BoldHandle <> nil) and (BoldHandle.Owner <> GetOwnerOrView) and + (AList.IndexOf(BoldHandle.Owner) = -1) then + AList.Add(BoldHandle.Owner); +end; + +function TcxGridBoldDataController.GetGridView: TcxCustomGridView; +begin + Result := TcxCustomGridView(GetOwner); +end; + +function TcxGridBoldDataController.GetItemDefaultValuesProviderClass: TcxCustomEditDefaultValuesProviderClass; +begin +// Result := TcxGridDefaultValuesProvider; + Result := TcxGridBoldDefaultValuesProvider; +end; + +function TcxGridBoldDataController.GetNavigatorIsBof: Boolean; +begin + Result := GridView.Controller.IsStart; +end; + +function TcxGridBoldDataController.GetNavigatorIsEof: Boolean; +begin + Result := GridView.Controller.IsFinish; +end; + +function TcxGridBoldDataController.GetScrollBarPos: Integer; +begin + if SupportsScrollBarParams then + if dceInsert in EditState then + Result := FPrevScrollBarPos + else + Result := RecNo - 1 + else + Result := -1; + FPrevScrollBarPos := Result; +end; + +function TcxGridBoldDataController.GetScrollBarRecordCount: Integer; +begin +// TODO see how to properly replace DataSetRecordCount, perhaps add BoldHandleRecordCount + if SupportsScrollBarParams then + Result := {DataSetRecordCount +} GridView.ViewInfo.VisibleRecordCount - 1 + else + Result := -1; +end; + +function TcxGridBoldDataController.CreateItem( + aGridView: TcxCustomGridTableView; const aExpression, aCaption, aValueType, + aName: string): TcxCustomGridTableItem; +begin + result := aGridView.CreateItem; + (result as IBoldAwareViewItem).BoldProperties.Expression := aExpression; + result.DataBinding.ValueType := aValueType; + result.Caption := aCaption; + result.Name := CreateUniqueName(GetOwnerOrView, GridView, result, ScxGridPrefixName, aName); +end; + +function TcxGridBoldDataController.IsDataChangeable: Boolean; +begin + Result := False; +end; + +function TcxGridBoldDataController.IsDataLinked: Boolean; +begin + Result := BoldHandle <> nil; +end; + +procedure TcxGridBoldDataController.PreFetchColumns(AList: TBoldList; aItem: integer); + + procedure Prefetch(FetchList: TBoldList; const AOcl: String; AVariableList: TBoldExternalVariableList); +{$IFNDEF SpanFetch} + var + IE: TBoldIndirectElement; + const + cCollectOcl = 'self->collect(%s)'; +{$ENDIF} + begin + try + {$IFDEF SpanFetch} + FetchOclSpan(FetchList, AOcl, AVariableList); + {$ELSE} + IE := TBoldIndirectElement.Create; + try + with BoldHandle.StaticSystemHandle.System.Evaluator do + begin + if Assigned(ExpressionType(AOCL, FetchList.BoldType, false, AVariableList)) then + Evaluate(AOcl, FetchList, nil, false, IE, false, AVariableList) + else + if Assigned(ExpressionType(Format(cCollectOcl, [AOcl]), FetchList.BoldType, false, AVariableList)) then + Evaluate(Format(cCollectOcl, [AOcl]), FetchList, nil, false, IE, false, AVariableList); + end; + finally + IE.free; + end; +{$ENDIF} + except + // ignore all exceptions during prefetch, otherwise the grid view infos will be messed up + end; + end; + +var + i,j: integer; + lOcl: string; + lBoldAwareViewItem: IBoldAwareViewItem; + lItem: TcxCustomGridTableItem; + FetchList: TBoldList; + lWholeList: TBoldList; + lMainFollower: TBoldFollower; + lRowFollower: TBoldFollower; + lCellFollower: TBoldFollower; + locator: TBoldObjectLocator; + IsObjectList: boolean; + lRowIndex: integer; + lSameCount: boolean; + lGuard: IBoldGuard; + lTableViewInfo: TcxGridTableViewInfo; + lRowsViewInfo: TcxGridRowsViewInfo; + lVisibleList: TBoldList; +const + cCollectOcl = 'self->collect(%s)'; +begin + lGuard := TBoldGuard.Create(FetchList, lVisibleList); + if not Assigned(AList) then + begin + lVisibleList := CreateList; + CollectVisibleRecords(lVisibleList); + AList := lVisibleList; +// lTableViewInfo := (Owner as TcxGridBoldTableView).ViewInfo; +// for := lTableViewInfo.FirstRecordIndex to lTableViewInfo.FirstRecordIndex + lTableViewInfo.VisibleColumnCount +// (Owner as TcxGridBoldTableView).ViewInfo.RecordsViewInfo[0]. VisibleColumnCount; +// (Owner as TcxGridBoldTableView).GridView.ViewInfo. + end; + + if AList.Empty then + exit; + lMainFollower := Follower; + lWholeList := BoldList; + + FetchList := CreateList; + FetchList.DuplicateMode := bldmAllow; + FetchList.Capacity := AList.Count; + IsObjectList := (AList is TBoldObjectList) and (lWholeList is TBoldObjectList); + lSameCount := AList.Count = lWholeList.Count; + Locator := nil; + for i := 0 to AList.Count - 1 do + begin +{ if lSameCount then + j := i + else} + if IsObjectList then + begin + locator := TBoldObjectList(aList).Locators[i]; + if TBoldObjectList(lWholeList).Locators[i] = locator then + j := i + else + j := TBoldObjectList(lWholeList).IndexOfLocator( locator ); + end + else + begin + if lWholeList[i] = aList[i] then + j := i + else + j := lWholeList.IndexOf(aList[i]); + end; + if j = -1 then + begin + FetchList.AddList(AList); + break; + end; + lRowFollower := lMainFollower.SubFollowers[j]; + if not Assigned(lRowFollower) or not lRowFollower.Displayable {or not Assigned(lRowFollower.Element)} then + begin + if IsObjectList then + TBoldObjectList(FetchList).AddLocator(locator) + else + FetchList.Add(aList[i]) + end + else + begin + for j := 0 to lRowFollower.SubFollowerCount - 1 do + begin + lItem := TcxCustomGridTableItem(FindItemByData(j)); + if (aItem = j) or ((AItem = -1) and lItem.ActuallyVisible) {or RequiresAllRecords(lItem)} then + if not lRowFollower.SubFollowerAssigned[j] then + begin + if IsObjectList then + TBoldObjectList(FetchList).AddLocator(locator) + else + FetchList.Add(aList[j]); + break; + end; + end; + end; + end; +// if FetchList.Empty then +// exit; + ConnectEvents(false); + inc(FSkipMakeCellUptoDate); + try + if not FetchList.Empty then + for I := 0 to ItemCount - 1 do + begin + lItem := TcxCustomGridTableItem(FindItemByData(i)); + if (aItem = i) or ((aItem = -1) and lItem.ActuallyVisible) {or RequiresAllRecords(lItem)} then + begin + lItem.GetInterface(IBoldAwareViewItem, lBoldAwareViewItem); + lOcl := lBoldAwareViewItem.BoldProperties.Expression; + Prefetch(FetchList, lOcl, lBoldAwareViewItem.BoldProperties.VariableList); + end; + end; + DisplayFollowers; + lSameCount := (AList.Count = lWholeList.Count) {or ((Assigned(Filter) and Filter.Active and (Filter.Root.Count > 0)))}; + if lSameCount then + begin + i := 0; + j := lWholeList.Count-1; + end + else + FindMinMaxIndex(AList, lWholeList, i, j); + with TBoldFollowerList(lMainFollower.RendererData) do + if (FirstActive <> i) or (LastActive <> j) then + BoldProperties.SetActiveRange(lMainFollower, i, j, 0); + + for i := 0 to AList.Count - 1 do + begin + if lSameCount and (lWholeList[i] = AList[i]) then + lRowIndex := i + else + if isObjectList then + lRowIndex := TBoldObjectList(lWholeList).IndexOfLocator(TBoldObjectList(AList).Locators[i]) + else + lRowIndex := lWholeList.IndexOf(AList[i]); + if lRowIndex <> -1 then + begin + lRowFollower := lMainFollower.EnsuredSubFollowers[lRowIndex]; + Assert(Assigned(lRowFollower)); + lRowFollower.SetElementAndMakeCurrent(AList[i], true); + for j := 0 to ItemCount - 1 do + begin + lItem := TcxCustomGridTableItem(FindItemByData(j)); + if (aItem = j) or ((aItem = -1) and lItem.ActuallyVisible) {or RequiresAllRecords(lItem)} then + begin + lCellFollower := lRowFollower.SubFollowers[j]; + Assert(Assigned(lCellFollower)); + lCellFollower.Active := true; + end; + end; + end; + end; + + finally + dec(FSkipMakeCellUptoDate); + ConnectEvents(true); + end; +end; + +procedure TcxGridBoldDataController.ProcessQueueEvent(Sender: TObject); +begin + if not IsDestroying then + if not GridView.IsDestroying then + begin + if fDataChanged then + begin + DataHasChanged := false; + AdjustActiveRange(); + DataChanged(dcTotal, -1, -1); + // Follower.MarkValueOutOfDate; + // self.Refresh; + CheckDataSetCurrent; + end; +{$IFDEF DelayOnFocusedRecordChange} + if fFocusChanged then + begin + if GridView is TcxGridBoldTableView then + (GridView as TcxGridBoldTableView).InheritedDoFocusedRecordChanged(FPrevFocusedRecordIndex, FFocusedRecordIndex, + FPrevFocusedDataRecordIndex, FFocusedDataRecordIndex, FNewItemRecordFocusingChanged) + else + if (GridView is TcxGridBoldBandedTableView) then + (GridView as TcxGridBoldBandedTableView).InheritedDoFocusedRecordChanged(FPrevFocusedRecordIndex, FFocusedRecordIndex, + FPrevFocusedDataRecordIndex, FFocusedDataRecordIndex, FNewItemRecordFocusingChanged) + else + Assert(false, 'Unsupported GridView: ' + GridView.ClassName); + fFocusChanged := false; + end; +{$ENDIF} + if fRedrawGrid then + begin + GridView.Invalidate(true); + if fRecalcSummary then + GridView.DataController.Summary.Recalculate; + fRedrawGrid := false; + fRecalcSummary := false; + end; + end; +end; + +function TcxGridBoldDataController.RequiresAllRecords(AItem: TObject): boolean; +var + lItem: TcxCustomGridTableItemAccess; +begin + result := false; + if (AItem is TcxCustomGridTableItem) then + begin + lItem := TcxCustomGridTableItemAccess(AItem); + result := (lItem.SortIndex <> -1) or (lItem.GroupIndex <> -1) or lItem.Filtered or + ((AItem is TcxGridColumn) and + ( + (TcxGridColumn(AItem).Summary.FooterKind <> skNone ) or + (TcxGridColumn(AItem).Summary.GroupFooterKind <> skNone ) or + (TcxGridColumn(AItem).Summary.GroupKind <> skNone ) + )); + end; +end; + +function TcxGridBoldDataController.RequiresAllRecords: boolean; +var + lcxCustomGridTableView: TcxCustomGridTableView; + i: integer; +begin + lcxCustomGridTableView := GridView as TcxCustomGridTableView; + result := (lcxCustomGridTableView.SortedItemCount > 0) + or (lcxCustomGridTableView.GroupedItemCount > 0) + or (Summary.FooterSummaryItems.Count > 0) + or (Assigned(Filter) and Filter.Active and (Filter.Root.Count > 0)); + if not result then + for I := 0 to lcxCustomGridTableView.ItemCount - 1 do + result := result or RequiresAllRecords(lcxCustomGridTableView.Items[i]); +end; + +function TcxGridBoldDataController.GetOwnerOrView: TComponent; +begin + if Assigned(GridView.Owner) then + result := GridView.Owner + else + result := GridView; +end; + +function TcxGridBoldDataController.SetScrollBarPos( + Value: Integer): Boolean; +begin + Result := SupportsScrollBarParams; + if Result then + RecNo := Value + 1; +end; + +function TcxGridBoldDataController.SupportsScrollBarParams: Boolean; +begin + Result := IsGridMode and TcxCustomGridTableViewAccess(GridView).IsEqualHeightRecords; +end; + +constructor TcxGridBoldDataController.Create(AOwner: TComponent); +begin + inherited; +end; + +destructor TcxGridBoldDataController.Destroy; +begin + BoldInstalledQueue.RemoveFromPostDisplayQueue(self); + inherited; +end; + +procedure TcxGridBoldDataController.DisplayFollowers; +var + Queueable: TBoldQueueable; +begin + if Assigned(Follower) and (Follower.IsInDisplayList {or not Follower.Displayable}) and not (GridView.IsLoading or GridView.IsDestroying) then + repeat + Queueable := TBoldFollowerAccess(Follower).MostPrioritizedQueuableOrSelf; + if Assigned(Queueable) then + TBoldQueueableAccess(Queueable).display; + until not Assigned(Queueable); +end; + +procedure TcxGridBoldDataController.CollectVisibleRecords(var aList: TBoldList); +var + i,j: integer; + lFollower: TBoldFollower; + lRecordIndex: integer; + lList: TBoldList; + lGuard: IBoldGuard; + lWholeList: TBoldList; + lRecord: TcxCustomGridRecord; + IsObjectList: boolean; +begin + lWholeList := BoldList; + IsObjectList := (lWholeList is TBoldObjectList); +// lGuard := TBoldGuard.Create(lList); +// lList := CreateList; + lList := AList; + i := GridView.Controller.TopRecordIndex; + if i = -1 then + exit; + if i <> -1 then + begin + j := i + GridView.ViewInfo.VisibleRecordCount+2; // there can be at most 2 partially visible records + i := (i div 10) * 10; + j := (j div 10 +1) * 10; + end + else + begin + i := 0; + j := 10; + end; + if j >= TcxCustomDataControllerInfoAccess(DataControllerInfo).RecordList.Count then + j := TcxCustomDataControllerInfoAccess(DataControllerInfo).RecordList.Count -1; + lList.Capacity := j-i+1; + lList.DuplicateMode := bldmAllow; + for i := i to j do + begin + lRecord := GridView.ViewData.GetRecordByIndex(i); + if Assigned(lRecord) then + begin + lRecordIndex := lRecord.RecordIndex; + if (lRecordIndex > -1) and (lRecordIndex < lWholeList.count) then + begin + if IsObjectList then + TBoldObjectList(lList).AddLocator(TBoldObjectList(lWholeList).Locators[lRecordIndex]) + else + lList.Add(lWholeList[lRecordIndex]); + end; + end; + end; +end; + +procedure TcxGridBoldDataController.AdjustActiveRange( + aList: TBoldList = nil; aItem: integer = -1); +var + i,j: integer; + lFollower: TBoldFollower; + lRecordIndex: integer; + lList: TBoldList; + lGuard: IBoldGuard; + lWholeList: TBoldList; + lRecord: TcxCustomGridRecord; + IsObjectList: boolean; +begin + lFollower := Follower; + lList := aList; + lWholeList := BoldList; + if not Assigned(lFollower) or not Assigned(lWholeList) then + exit; + i := GridView.Controller.TopRecordIndex; + if i = -1 then + exit; + if not Assigned(aList) and not LoadAll then + begin + IsObjectList := (lWholeList is TBoldObjectList); + lGuard := TBoldGuard.Create(lList); + lList := CreateList; + if i <> -1 then + begin + j := i + GridView.ViewInfo.VisibleRecordCount+2; // there can be at most 2 partially visible records + i := (i div 10) * 10; + j := (j div 10 +1) * 10; + end + else + begin + i := 0; + j := 10; + end; + if j >= TcxCustomDataControllerInfoAccess(DataControllerInfo).RecordList.Count then + j := TcxCustomDataControllerInfoAccess(DataControllerInfo).RecordList.Count -1; + lList.Capacity := j-i+1; + lList.DuplicateMode := bldmAllow; + for i := i to j do + begin + lRecord := GridView.ViewData.GetRecordByIndex(i); + if Assigned(lRecord) then + begin + lRecordIndex := lRecord.RecordIndex; + if (lRecordIndex > -1) and (lRecordIndex < lWholeList.count) then + begin + if IsObjectList then + TBoldObjectList(lList).AddLocator(TBoldObjectList(lWholeList).Locators[lRecordIndex]) + else + lList.Add(lWholeList[lRecordIndex]); + end; + end; + end; + end; + if LoadAll then + aItem := -1; + inherited AdjustActiveRange(lList, aItem); +end; + +procedure TcxGridBoldDataController._BeforeMakeListUpToDate( + Follower: TBoldFollower); +//var +// lFirstLoad: boolean; +begin +// lFirstLoad := CustomDataSource = nil; + if GridView.IsDestroying then + begin + Assert(Assigned(self)); + exit; + end; + inherited; +{ if lFirstLoad then + begin + if Assigned(OnBeforeLoad) then + OnBeforeLoad(GridView); + end; +} +end; + +procedure TcxGridBoldDataController.ReloadStorage; +begin + if not Assigned(CustomDataSource) then + exit; + if CustomDataSource.Provider = nil then + TcxBoldDataSource(CustomDataSource).CurrentProvider := Provider; + if MainFollowerNeedsDisplay then + DisplayFollowers; + DataStorage.BeginLoad; + fInternalLoading := true; + try + TcxBoldDataSource(CustomDataSource).LoadRecordHandles; + if DataControllerInfo.LockCount = 0 then + Refresh; + Assert(Follower.SubFollowerCount = DataStorage.RecordCount, 'Follower.SubFollowerCount = DataStorage.RecordCount' + IntToStr(Follower.SubFollowerCount) + ',' + IntToStr(DataStorage.RecordCount) ); + finally + fInternalLoading := false; + DataStorage.EndLoad; + end; +end; + +procedure TcxGridBoldDataController._AfterMakeListUptoDate( + Follower: TBoldFollower); +var + i: integer; + lcxBoldDataSource: TcxBoldDataSource; + lBoldAwareView: IBoldAwareView; + lFirstLoad: boolean; + lDataChanged: boolean; + lTypeChanged: boolean; +begin + if GridView.IsDestroying then + begin + Assert(Assigned(self)); + exit; + end; + {$IFDEF BoldDevExLog} + _Log((GetOwner as TComponent).Name + ':_AfterMakeListUpToDate:' +IntToStr(FSkipMakeCellUptoDate), className); + {$ENDIF} + + lTypeChanged := false; + lBoldAwareView := GridView as IBoldAwareView; + lFirstLoad := (CustomDataSource = nil); + if not lFirstLoad and (DataStorage.RecordCount <> Follower.SubfollowerCount) then + DataHasChanged := true; + try + if GridView.IsDesigning {or isPattern} then // isPattern needs to be tested for detail views + begin + exit; + end; +// TypeMayHaveChanged; + if lFirstLoad then + begin + fFetchedAll := false; + lcxBoldDataSource := cxBoldDataSourceClass.Create(self as TcxGridBoldDataController); + + if {BoldAutoColumns and} (GetHandleListElementType <> fCurrentListElementType) and Assigned(fCurrentListElementType) and (GetHandleListElementType <> nil) then + if ClearColumnsOnTypeChange and not GetHandleListElementType.ConformsTo(fCurrentListElementType) then + lBoldAwareView.ClearItems; + CustomDataSource := lcxBoldDataSource; + + if (Follower.Element = nil) or Follower.ElementValid then + begin + lTypeChanged := TypeMayHaveChanged; + end; + for i := 0 to ItemCount - 1 do + begin + BoldPropertiesFromItem(i).AfterMakeUptoDate := nil; + end; + end + else + begin + TypeMayHaveChanged; + // EndUpdate; + end; + finally + lDataChanged := DataHasChanged; +// if lDataChanged or lFirstLoad or lTypeChanged then +// AdjustActiveRange(); + if not lDataChanged then + dec(FSkipMakeCellUptoDate); + if lDataChanged and (FSkipMakeCellUptoDate = 1) and Assigned(CustomDataSource) then + begin + if CustomDataSource.Provider = nil then + TcxBoldDataSource(CustomDataSource).CurrentProvider := Provider; + CustomDataSource.DataChanged; + TcxBoldDataSource(CustomDataSource).DataController.DataControllerInfo.Refresh; + + DataHasChanged := false; + end; + if lDataChanged then + dec(FSkipMakeCellUptoDate); + ConnectEvents(true); + if {not lFirstLoad and not lDataChanged and} (Follower.SubFollowerCount <> DataStorage.RecordCount) then + ReloadStorage; + inc(FSkipSyncFocusedRecord); + try + if CustomDataSource.Provider = nil then + TcxBoldDataSource(CustomDataSource).CurrentProvider := Provider; + Assert(Assigned(CustomDataSource.Provider)); + EndFullUpdate; + finally + dec(FSkipSyncFocusedRecord); + end; + if not ((Follower.SubFollowerCount = DataStorage.RecordCount) or (DetailMode = dcdmPattern) or lFirstLoad) then + begin + if CustomDataSource.Provider = nil then + TcxBoldDataSource(CustomDataSource).CurrentProvider := Provider; + DataStorage.BeginLoad; + try + TcxBoldDataSource(CustomDataSource).LoadRecordHandles; + Assert(Follower.SubFollowerCount = DataStorage.RecordCount, 'Follower.SubFollowerCount = DataStorage.RecordCount' + IntToStr(Follower.SubFollowerCount) + ',' + IntToStr(DataStorage.RecordCount) ); + finally + DataStorage.EndLoad; + end; + end; + if (DetailMode <> dcdmPattern) and (Groups.GroupingItemCount = 0) and (not Filter.Active) and (GridView.ViewData.RecordCount <> {RowCount} Follower.SubFollowerCount) then + begin + TcxCustomGridTableViewAccess(GridView).ViewInfoCache.Count := Follower.SubFollowerCount; + TcxCustomDataControllerInfoAccess(DataControllerInfo).Update; + TcxCustomGridTableViewAccess(GridView).ViewData.Refresh(Follower.SubFollowerCount); + Assert(GridView.ViewData.RecordCount = Follower.SubFollowerCount); + end; + if Assigned(CustomDataSource) then + TcxBoldDataSource(CustomDataSource).fIsBoldInitiatedChange := false; + fBoldProperties.OnAfterInsertItem := _InsertRow; + fBoldProperties.OnAfterDeleteItem := _DeleteRow; + fBoldProperties.OnReplaceitem := _ReplaceRow; + + BeginUpdate; + try + FNearestRecordIndex := -1; + if (Follower.CurrentIndex <> FocusedRecordIndex) and (FSkipMakeCellUptoDate < 2) then + begin + Controller.ClearSelection; + if {(Follower.CurrentIndex <> -1) and} (Follower.CurrentIndex < RecordCount) then + FocusedRecordIndex := Follower.CurrentIndex + else + if RecordCount > 0 then + begin + Follower.CurrentIndex := 0; + FocusedRecordIndex := 0; + end; + if Assigned(Controller.FocusedRecord) then + Controller.FocusedRecord.Selected := true; + end; + Change([dccSelection]); + finally + EndUpdate; + end; + if (DataControllerInfo.LockCount = 0) and ((DataControllerInfo.DataRowCount <> RowCount) and ((DataControllerInfo.DataGroups.Count>0) and (RecordCount <> DataControllerInfo.DataRowCount))) then + begin + Refresh; + end; + if lTypeChanged and BoldAutoColumns {(GridView.OptionsView is TcxGridTableOptionsView) and TcxGridTableOptionsView(GridView.OptionsView).ColumnAutoWidth} then + begin +// TcxGridTableOptionsView(GridView.OptionsView).ColumnAutoWidth := false; + ShowHourglassCursor; + GridView.BeginUpdate; + try + GridView.ApplyBestFit(nil, true, false); + finally + GridView.EndUpdate; + HideHourglassCursor; +// TcxGridTableOptionsView(GridView.OptionsView).ColumnAutoWidth := true + end; + end; + ConnectEvents(True); + if lDataChanged or lFirstLoad or lTypeChanged then + begin + {$IFDEF FireAfterLoadOnChangeOnly} + if Assigned(OnAfterLoad) then + begin + if (DataControllerInfo.LockCount = 0) then + begin + fTriggerAfterLoad := false; + OnAfterLoad(GridView) + end + else + fTriggerAfterLoad := true; + end; + + {$ENDIF} + end; + {$IFNDEF FireAfterLoadOnChangeOnly} + if Assigned(OnAfterLoad) then + begin + if (DataControllerInfo.LockCount = 0) then + begin + fTriggerAfterLoad := false; + OnAfterLoad(GridView); + end + else + fTriggerAfterLoad := true; + end; + {$ENDIF} + end; +end; + + + +procedure TcxGridBoldDataController.TypeChanged(aNewType, aOldType: TBoldElementTypeInfo); +begin + inherited; + if not Assigned(fCurrentListElementType) then + begin + if BoldAutoColumns then + begin + TcxCustomGridTableView(GridView).ClearItems; + fFetchedAll := false; + end; + end + else + if Assigned(aOldType) and BoldAutoColumns or (TcxCustomGridTableView(GridView).ItemCount = 0) then + begin + TcxCustomGridTableView(GridView).ClearItems; + TcxGridBoldDataController(self).CreateAllItems(false); + fFetchedAll := false; + end; +end; + +function TcxGridBoldDataController.GetSummaryClass: TcxDataSummaryClass; +begin + Result := TcxBoldDataSummary; +end; + +function TcxGridBoldDataController.GetSummaryGroupItemLinkClass: TcxDataSummaryGroupItemLinkClass; +begin + Result := TcxGridTableSummaryGroupItemLink; +end; + +function TcxGridBoldDataController.GetSummaryItemClass: TcxDataSummaryItemClass; +begin + Result := TcxGridTableSummaryItem; +end; + +procedure TcxGridBoldDataController._AfterMakeCellUptoDate( + Follower: TBoldFollower); +var + lItem: TcxCustomGridTableItemAccess; +begin + if DataHasChanged then + exit; + lItem := TcxCustomGridTableItemAccess(GetItem(Follower.index)); + if (FSkipMakeCellUptoDate = 0) and not ((lItem.GroupIndex = -1) and (lItem.SortIndex = -1) and (not lItem.Filtered) and (Follower.OwningFollower.index <= RecordCount)) then + DataHasChanged := true + else + begin + EnsureEventQueued; + fRedrawGrid := true; + fRecalcSummary := fRecalcSummary or (Summary.FooterSummaryItems.IndexOfItemLink(lItem) <> -1) or (Assigned(Summary.SummaryGroups.FindByItemLink(lItem))); + end; +end; + +procedure TcxGridBoldDataController.BeginFullUpdate; +begin + GridView.BeginUpdate; + inherited; +end; + +procedure TcxGridBoldDataController.EndFullUpdate; +begin + inherited; + if not (IsDestroying or GridView.IsDestroying) then + begin + if DataHasChanged and (LockCount <= 1) then + begin + + //DataChangedEvent(nil); + DataHasChanged := false; + AdjustActiveRange(); + DataChanged(dcTotal, -1, -1); + // Follower.MarkValueOutOfDate; + // self.Refresh; + CheckDataSetCurrent; + + + end; + if ((LockCount <= 1)) and (Follower.SubFollowerCount <> DataStorage.RecordCount) then + ReloadStorage; + GridView.EndUpdate + end; + if fTriggerAfterLoad then + begin + fTriggerAfterLoad := false; + OnAfterLoad(GridView) + end; +end; + +function TcxGridBoldDataController.BoldSetValue(AItemHandle: TcxDataItemHandle; + ACellFollower: TBoldFollower; const AValue: variant): boolean; +var + lcxCustomGridTableItem: TcxCustomGridTableItem; + lcxBoldEditProperties: IcxBoldEditProperties; + lEdit: TcxCustomEdit; +begin + result := false; + lcxCustomGridTableItem := GetItem(Integer(AItemHandle)) as TcxCustomGridTableItem; + if Supports(lcxCustomGridTableItem.GetProperties, IcxBoldEditProperties, lcxBoldEditProperties) then + begin + lEdit := Controller.EditingController.Edit; + lcxBoldEditProperties.SetStoredValue(AValue, nil, lEdit, ACellFollower, result); + end; +end; + +procedure TcxGridBoldDataController.EnsureConstraintColumn; +var + lItem: TcxCustomGridTableItemAccess; +begin + lItem := TcxCustomGridTableItemAccess(GetItemByExpression(cOCLConstraint)); + if not Assigned(lItem) then + lItem := TcxCustomGridTableItemAccess(CreateItem(GridView, cOCLConstraint, '§', 'Boolean', 'Constraints')); + lItem.OnCustomDrawCell := ConstraintColumnCustomDrawCell; + lItem.Index := 0; + lItem.BestFitMaxWidth := 16; + lItem.Width := 16; + lItem.MinWidth := 16; + lItem.Options.Focusing := false; + lItem.Options.Editing := false; + lItem.Options.IncSearch := false; + if lItem.Options is TcxGridColumnOptions then + begin + TcxGridColumnOptions(lItem.Options).HorzSizing := false; + TcxGridColumnOptions(lItem.Options).Moving := false; + end; +end; + +function TcxGridBoldDataController.CanSelectRow( + ARowIndex: Integer): Boolean; +begin + Result := TcxCustomGridTableViewAccess(GridView).CanSelectRecord(ARowIndex); +end; + +function TcxGridBoldDataController.CompareByField(ARecordIndex1, + ARecordIndex2: Integer; AField: TcxCustomDataField; + AMode: TcxDataControllerComparisonMode): Integer; +begin + if GridView.ViewData.NeedsCustomDataComparison(AField, AMode) then + Result := GridView.ViewData.CustomCompareDataValues(AField, + GetComparedValue(ARecordIndex1, AField), GetComparedValue(ARecordIndex2, AField), AMode) + else + Result := inherited CompareByField(ARecordIndex1, ARecordIndex2, AField, AMode); +end; + +function TcxGridBoldDataController.CreateDetailLinkObject( + ARelation: TcxCustomDataRelation; ARecordIndex: Integer): TObject; +begin + Result := TcxGridLevelAccess(ARelation.Item).CreateLinkObject(ARelation, ARecordIndex); +end; + +procedure TcxGridBoldDataController.DoValueTypeClassChanged( + AItemIndex: Integer); +begin + inherited; + TcxCustomGridTableViewAccess(GridView).ItemValueTypeClassChanged(AItemIndex); +end; + +procedure TcxGridBoldDataController.FilterChanged; +begin + DataControllerInfo.BeginUpdate; + try + if MainFollowerNeedsDisplay then + DisplayFollowers; + inherited; + TcxCustomGridTableViewAccess(GridView).FilterChanged; + finally + TcxCustomDataControllerInfoAccess(DataControllerInfo).CorrectFocusedRow(FocusedRowIndex); + DataControllerInfo.EndUpdate; + end; +end; + +procedure TcxGridBoldDataController.FocusControl(AItemIndex: Integer; + var Done: Boolean); +begin + inherited; + TcxCustomGridTableViewAccess(GridView).FocusEdit(AItemIndex, Done); +end; + +function TcxGridBoldDataController.GetDefaultActiveRelationIndex: Integer; +begin + Result := TcxCustomGridTableViewAccess(GridView).GetDefaultActiveDetailIndex; +end; + +function TcxGridBoldDataController.GetDetailDataControllerByLinkObject( + ALinkObject: TObject): TcxCustomDataController; +begin + Result := TcxCustomGridView(ALinkObject).DataController; +end; + +function TcxGridBoldDataController.GetDisplayText(ARecordIndex, + AItemIndex: Integer): string; +var + lCellFollower: TBoldFollower; +begin +{ if not GridView.ViewData.GetDisplayText(ARecordIndex, AItemIndex, Result) then + Result := inherited GetDisplayText(ARecordIndex, AItemIndex); + TcxCustomGridTableItemAccess(GridView.Items[AItemIndex]).DoGetDataText(ARecordIndex, Result); +} + AItemIndex := GridView.Items[AItemIndex].ID; + EnsureFollower(ARecordIndex, AItemIndex); + lCellFollower := CellFollowers[ARecordIndex, AItemIndex]; + result := VarToStr((lCellFollower.Controller as TBoldVariantFollowerController).GetCurrentAsVariant(lCellFollower)); +end; + +function TcxGridBoldDataController.GetFilterDataValue( + ARecordIndex: Integer; AField: TcxCustomDataField): Variant; +begin + if Assigned(BoldList) and not HasCellFollower[ARecordIndex, GetItemData(aField.Item)] then + PreFetchColumns(BoldList, GetItemData(aField.Item)); + Result := inherited GetFilterDataValue(ARecordIndex, AField); + if GridView.ViewData.HasCustomDataHandling(AField, doFiltering) then + Result := GridView.ViewData.GetCustomDataValue(AField, Result, doFiltering); +end; + +function TcxGridBoldDataController.GetFilterDisplayText(ARecordIndex, + AItemIndex: Integer): string; +var + lCellFollower: TBoldFollower; +begin +{ if GridView.ViewData.HasCustomDataHandling(Fields[AItemIndex], doFiltering) then + Result := GridView.ViewData.GetCustomDataDisplayText(ARecordIndex, AItemIndex, doFiltering) + else + Result := inherited GetFilterDisplayText(ARecordIndex, AItemIndex); +} + AItemIndex := GridView.Items[AItemIndex].ID; + EnsureFollower(ARecordIndex, AItemIndex); + lCellFollower := CellFollowers[ARecordIndex, AItemIndex]; + result := VarToStr((lCellFollower.Controller as TBoldVariantFollowerController).GetCurrentAsVariant(lCellFollower)); +end; + +function TcxGridBoldDataController.GetFilterItemFieldCaption( + AItem: TObject): string; +begin + Result := TcxCustomGridTableItemAccess(AItem).FilterCaption; +end; + +function TcxGridBoldDataController.GetItemID(AItem: TObject): Integer; +begin + if AItem is TcxCustomGridTableItem then + Result := TcxCustomGridTableItem(AItem).ID + else + Result := -1; +end; + +function TcxGridBoldDataController.GetItemSortByDisplayText( + AItemIndex: Integer; ASortByDisplayText: Boolean): Boolean; +begin + Result := TcxCustomGridTableViewAccess(GridView).GetItemSortByDisplayText(AItemIndex, ASortByDisplayText); +end; + +function TcxGridBoldDataController.GetItemValueSource( + AItemIndex: Integer): TcxDataEditValueSource; +begin + Result := TcxCustomGridTableViewAccess(GridView).GetItemValueSource(AItemIndex); +end; + +function TcxGridBoldDataController.GetSortingBySummaryEngineClass: TcxSortingBySummaryEngineClass; +begin + Result := GridView.ViewData.GetSortingBySummaryEngineClass; +end; + +procedure TcxGridBoldDataController.UpdateData; +begin + inherited; + TcxCustomGridTableViewAccess(GridView).UpdateRecord; +end; + + +procedure TcxGridBoldDataController.DoDragOver( + Sender, Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean); +var + lcxGridSite: TcxGridSite; + lcxCustomGridHitTest: TcxCustomGridHitTest; + lcxGridRecordCellHitTest: TcxGridRecordCellHitTest; + lBoldRoleRTInfo: TBoldRoleRTInfo; + lBoldList: TBoldList; +begin + Accept := false; + lcxGridSite := TcxGridSite(Sender); + lcxCustomGridHitTest := lcxGridSite.ViewInfo.GetHitTest(X, Y); + lBoldList := BoldHandle.MutableList; + if Assigned(lBoldList) then + begin + lBoldRoleRTInfo := lBoldList.BoldMemberRTInfo as TBoldRoleRTInfo; + // not allowed for association classes + Accept := not Assigned(lBoldRoleRTInfo) or not (lBoldRoleRTInfo.RoleType = rtLinkRole); + // do not allow drag in a single grid if the list is a member and is not ordered + Accept := Accept and not ((TcxDragControlObject(Source).Control = Sender) and (Assigned(lBoldRoleRTInfo) and not lBoldRoleRTInfo.IsOrdered)); + // do not allow drop in the system owned class list (ie all instances) + Accept := Accept and not (lBoldList.OwningElement is TBoldSystem); + // accept drop only where applicable + Accept := Accept and ((lcxCustomGridHitTest is TcxGridViewNoneHitTest) or (lcxCustomGridHitTest is TcxGridRecordCellHitTest)); + // do not allow drop after the last row of the grid if the dragged item is already last in the list + if Accept and (lcxCustomGridHitTest is TcxGridViewNoneHitTest) and (TcxDragControlObject(Source).Control = Sender) then + begin + Accept := Follower.CurrentIndex <> Follower.SubFollowerCount - 1; + end + else + if Accept and (lcxCustomGridHitTest is TcxGridRecordCellHitTest) and (TcxDragControlObject(Source).Control = Sender) then + begin + lcxGridRecordCellHitTest := TcxGridRecordCellHitTest(lcxCustomGridHitTest); + // do not allow source and desination row to be same if drag within single grid + Accept := Accept and (lcxGridRecordCellHitTest.GridRecord.RecordIndex <> FocusedRecordIndex); + end; + // check if destination already contains all source objects (and the desination is not ordered) + if Accept and Assigned(lBoldRoleRTInfo) and not lBoldRoleRTInfo.IsOrdered and lBoldList.IncludesAll(BoldGUIHandler.DraggedObjects) then + Accept := false; + end; + Accept := Accept and BoldProperties.DragOver(Follower, BoldHandle.MutableList, Y); +end; + +procedure TcxGridBoldDataController.DoDragDrop(Sender, Source: TObject; X, + Y: Integer); +var + i: integer; + lIndex: integer; + lcxCustomGridHitTest: TcxCustomGridHitTest; + lcxGridSite: TcxGridSite; +begin + lcxGridSite := TcxGridSite(Sender); + lcxCustomGridHitTest := lcxGridSite.ViewInfo.GetHitTest(X, Y); + + lIndex := -1; + if lcxCustomGridHitTest is TcxGridRecordCellHitTest then + begin + lIndex := TcxGridRecordCellHitTest(lcxCustomGridHitTest).GridRecord.RecordIndex; + end; + + BoldProperties.DragDrop(Follower, BoldHandle.MutableList, lIndex); + TcxBoldDataSource(CustomDataSource).fIsBoldInitiatedChange := true; + try + {$IFDEF DisplayAll} + TBoldQueueable.DisplayAll; + {$ENDIF} + CustomDataSource.DataChanged; + BeginUpdate; + try + ClearSelection; + for I := 0 to BoldGUIHandler.DraggedObjects.Count - 1 do + begin + lIndex := BoldHandle.List.IndexOf(BoldGUIHandler.DraggedObjects[i]); + if lIndex < RowCount then + ChangeRowSelection(lIndex, True); + end; + finally + EndUpdate; + end; + finally + TcxBoldDataSource(CustomDataSource).fIsBoldInitiatedChange := false + end; +end; + +procedure TcxGridBoldDataController.DoEndDrag(Sender, Target: TObject; X, + Y: Integer); +begin + BoldProperties.EndDrag; +end; + +procedure TcxGridBoldDataController.DoStartDrag(Sender: TObject; + var DragObject: TDragObject); +begin + {$IFDEF DisplayAll} + TBoldQueueable.DisplayAll; + {$ENDIF} + SelectionChanged; // make sure the follower selection is updated + BoldProperties.StartDrag(Follower); +end; + +{ TcxGridItemBoldDataBinding } + +procedure TcxGridItemBoldDataBinding.Assign(Source: TPersistent); +begin + if Source is TcxGridItemBoldDataBinding then + fBoldProperties.Assign(TcxGridItemBoldDataBinding(Source).BoldProperties); + inherited; +end; + +constructor TcxGridItemBoldDataBinding.Create( + AItem: TcxCustomGridTableItem); +begin + inherited Create(AItem); + fSubscriber := TBoldPassthroughSubscriber.Create(Receive); + fBoldProperties := TBoldCxGridVariantFollowerController.Create(DataController.GetOwnerOrView); + (fBoldProperties as TBoldCxGridVariantFollowerController).fcxGridItemBoldDataBinding := self; + fBoldProperties.ApplyPolicy := bapExit; + DataController.fBoldColumnsProperties.Add(fBoldProperties); + fBoldProperties.OnGetContextType := DataController.GetHandleStaticType; + fBoldProperties.AddSmallSubscription(fSubscriber, [beValueChanged], beValueChanged); + FBoldProperties.AfterMakeUptoDate := DataController._AfterMakeCellUptoDate; + (DefaultValuesProvider as TcxGridBoldDefaultValuesProvider).BoldHandleFollower := DataController.BoldHandleFollower; + (DefaultValuesProvider as TcxGridBoldDefaultValuesProvider).BoldProperties := fBoldProperties; + Data := TObject(DataController.fBoldColumnsProperties.Count-1); +end; + +destructor TcxGridItemBoldDataBinding.Destroy; +begin + FreeAndNil(FBoldProperties); + FreeAndNil(fSubscriber); + inherited; +end; + +function TcxGridItemBoldDataBinding.GetDataController: TcxGridBoldDataController; +begin + Result := TcxGridBoldDataController(inherited DataController); +end; + +function TcxGridItemBoldDataBinding.GetDefaultValueTypeClass: TcxValueTypeClass; +begin + Result := TcxStringValueType; +end; + +procedure TcxGridItemBoldDataBinding.Init; +begin + inherited; + with Item do + if BoldProperties.Expression = cOCLConstraint then + begin + OnCustomDrawCell := DataController.ConstraintColumnCustomDrawCell; + OnGetCellHint := DataController.GetCellHint; + end + else + begin + if not Assigned(OnCustomDrawCell) then + OnCustomDrawCell := DataController.ColumnCustomDrawCell; + end; +end; + +procedure TcxGridItemBoldDataBinding.SetBoldProperties( + Value: TBoldVariantFollowerController); +begin + if Assigned(Value) then + fBoldProperties.Assign(Value); +end; + +procedure TcxGridItemBoldDataBinding.Receive(Originator: TObject; + OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent); +var + lContextType: TBoldElementTypeInfo; + lResultType: TBoldElementTypeInfo; + lBoldMemberRTInfo: TBoldMemberRTInfo; + lEvaluator: TBoldOcl; +begin + if not GridView.IsLoading and not DataController.fCreatingColumns then + if Assigned(DataController.BoldHandle) and Assigned(DataController.BoldHandle.ListElementType) then + begin + lContextType := DataController.BoldHandle.ListElementType; + lEvaluator := lContextType.Evaluator as TBoldOcl; + Assert(Assigned(lEvaluator)); + lResultType := lEvaluator.ExpressionType(BoldProperties.Expression, lContextType, false, BoldProperties.VariableList); + if Assigned(lResultType) then + begin + DataController.SetValueTypeAndProperties(lResultType, Item, (Item.RepositoryItem = nil) and (Item.PropertiesClassName = '')); + end; + if (Item.Caption = '') then + begin + lBoldMemberRTInfo := lEvaluator.RTInfo(BoldProperties.Expression, lContextType, false, BoldProperties.VariableList); + if Assigned(lBoldMemberRTInfo) then + begin + Item.Caption := lBoldMemberRTInfo.ModelName; + end; + end; + end; +end; + +procedure TcxGridItemBoldDataBinding.Remove; +var + i: integer; + lBoldColumnsProperties: TBoldControllerList; + lcxGridItemBoldDataBinding: TcxGridItemBoldDataBinding; +begin + DataController.fBoldColumnsProperties.Remove(fBoldProperties); + if (not GridView.IsDestroying) then + begin + lBoldColumnsProperties := DataController.fBoldColumnsProperties; + for I := 0 to DataController.ItemCount - 1 do + begin + lcxGridItemBoldDataBinding := ((DataController.GetItem(i) as TcxCustomGridTableItem).DataBinding as TcxGridItemBoldDataBinding); + lcxGridItemBoldDataBinding.Data := TObject(lBoldColumnsProperties.IndexOf(lcxGridItemBoldDataBinding.fBoldProperties)); + end; + end; + inherited; +end; + +function TcxGridItemBoldDataBinding.GetBoldProperties: TBoldVariantFollowerController; +begin + result := fBoldProperties; +end; + +{ TcxBoldDataController } + +function TcxBoldDataController.GetBoldHandle: TBoldAbstractListHandle; +begin + if not assigned(fBoldHandleFollower) then + result := nil + else + Result := fBoldHandleFollower.BoldHandle; +end; + +procedure TcxBoldDataController.SetBoldHandle( + const Value: TBoldAbstractListHandle); +begin + if fBoldHandleFollower.BoldHandle <> Value then + begin + CustomDataSource.free; + CustomDataSource := nil; + fBoldHandleFollower.BoldHandle := value; + end; +end; + +function TcxBoldDataController.GetBoldHandleIndexLock: Boolean; +begin + Result := fBoldHandleFollower.HandleIndexLock; +end; + +procedure TcxBoldDataController.SetBoldHandleIndexLock( + const Value: Boolean); +begin + fBoldHandleFollower.HandleIndexLock := Value; +end; + +procedure TcxBoldDataController.SetController( + const Value: TBoldListAsFollowerListController); +begin + fBoldProperties.Assign(Value); +end; + +procedure TcxBoldDataController.SetDataChanged(const Value: boolean); +begin + if fDataChanged = value then + Exit; + fDataChanged := Value; + if Value then + EnsureEventQueued; +end; + +procedure TcxBoldDataController.SetRecNo(const Value: Integer); +begin + fBoldHandleFollower.SetFollowerIndex(Value); +end; + +constructor TcxBoldDataController.Create(AOwner: TComponent); +begin + inherited Create(AOwner); + FUseDelayedScrollUpdate := true; + fClearColumnsOnTypeChange := true; + fBoldColumnsProperties := TBoldControllerList.Create(AOwner{GridView}); + fBoldProperties := TBoldListAsFollowerListController.Create(AOwner{GridView}, fBoldColumnsProperties); + fBoldHandleFollower := TBoldListHandleFollower.Create(AOwner.Owner{Form}, fBoldProperties); + Options := Options + [dcoImmediatePost]; + fSubscriber := TBoldPassthroughSubscriber.Create(Receive); + + if GetOwner is TcxComponent and TcxComponent(GetOwner).IsDesigning then + begin + // nothing needed at design time + end + else + begin +// don't need insert before we hook up datasource in _AfterMakeListUptoDate, so will set it there +// fBoldProperties.OnAfterInsertItem := _InsertRow; + fBoldProperties.OnAfterDeleteItem := _DeleteRow; + fBoldProperties.OnReplaceitem := _ReplaceRow; + fBoldProperties.AfterMakeUptoDate := _AfterMakeListUptoDate; + fBoldProperties.BeforeMakeUptoDate := _BeforeMakeListUptoDate; + fBoldProperties.OnGetContextType := GetHandleStaticType; + end; + fBoldProperties.OnGetContextType := GetHandleStaticType; +end; + +function TcxBoldDataController.CreateDataControllerInfo: TcxCustomDataControllerInfo; +begin + result := TcxBoldCustomDataControllerInfo.Create(Self); +end; + +function TcxBoldDataController.CreateList: TBoldList; +begin + if Assigned(fCurrentListElementType) then + result := TBoldMemberFactory.CreateMemberFromBoldType(fCurrentListElementType.ListTypeInfo) as TBoldList + else + result := TBoldElementList.Create; +end; + +procedure TcxBoldDataController.ProcessQueueEvent(Sender: TObject); +begin +// +end; + +procedure TcxBoldDataController.BeforeSorting; +begin + inherited; +// DataControllerInfo. +end; + +procedure TcxBoldDataController.BeginDelayScrollUpdate; +begin + if InDelayScrollUpdate then + exit; + fInDelayScrollUpdate := true; + inc(FSkipSyncFocusedRecord); + fStoredRecordIndex := CurrentIndex; +end; + +procedure TcxBoldDataController.EndDelayScrollUpdate; +begin + if not InDelayScrollUpdate then + exit; + fInDelayScrollUpdate := false; + dec(FSkipSyncFocusedRecord); + if (FocusedRecordIndex <> Follower.CurrentIndex) then + begin + Follower.CurrentIndex := FocusedRecordIndex; + CheckDataSetCurrent; + if self is TcxGridBoldDataController then + begin + if TcxGridBoldDataController(self).GridView is TcxGridBoldTableView then + with TcxCustomGridTableViewAccess(TcxGridBoldDataController(self).GridView), TcxGridBoldTableView(TcxGridBoldDataController(self).GridView) do + DoFocusedRecordChanged(FPrevFocusedRecordIndex, FocusedRecordIndex, FPrevFocusedDataRecordIndex, FocusedDataRowIndex, false) + else + if TcxGridBoldDataController(self).GridView is TcxGridBoldBandedTableView then + with TcxCustomGridTableViewAccess(TcxGridBoldDataController(self).GridView), TcxGridBoldBandedTableView(TcxGridBoldDataController(self).GridView) do + DoFocusedRecordChanged(FPrevFocusedRecordIndex, FocusedRecordIndex, FPrevFocusedDataRecordIndex, FocusedDataRowIndex, false) + end; + end; +end; + +procedure TcxBoldDataController.DisplayFollowers; +var + Queueable: TBoldQueueable; +begin + if Assigned(Follower) and (Follower.IsInDisplayList or not Follower.Displayable) then + repeat + Queueable := TBoldFollowerAccess(Follower).MostPrioritizedQueuableOrSelf; + if Assigned(Queueable) then + TBoldQueueableAccess(Queueable).display; + until not Assigned(Queueable); +end; + +function TcxBoldDataController.MainFollowerNeedsDisplay: boolean; +begin + result := Assigned(Follower) and (Follower.IsInDisplayList or not Follower.Displayable); +end; + +procedure TcxBoldDataController.EnsureEventQueued; +begin + BoldInstalledQueue.AddEventToPostDisplayQueue(ProcessQueueEvent, nil, self) +end; + +function TcxBoldDataController.EnsureFollower(ARecordIndex, AItemIndex: integer): boolean; +var + lMainFollower: TBoldFollower; + lRowFollower: TBoldFollower; + lCellFollower: TBoldFollower; + lResultElement: TBoldElement; + lItem: TObject; + lBoldAwareViewItem: IBoldAwareViewItem; + lIcxBoldEditProperties: IcxBoldEditProperties; +begin + result := false; + lCellFollower := nil; + lMainFollower := Follower; + lItem := FindItemByData(AItemIndex); + Assert(Assigned(lItem), 'lItem not found for index '+ IntToStr(AItemIndex)); + Assert(lItem.GetInterface(IBoldAwareViewItem, lBoldAwareViewItem), 'lItem.GetInterface(IBoldAwareViewItem, lBoldAwareViewItem)1'); + if not lMainFollower.Displayable then + begin +// Assert(IsDetailExpanding); + DisplayFollowers; + end; + inc(FSkipMakeCellUptoDate); + try + // if not lMainFollower.Displayable then + // DisplayFollowers; + with TBoldFollowerList(lMainFollower.RendererData) do + begin + if (ARecordIndex < FirstActive) or (ARecordIndex > LastActive) then + begin + PreFetchColumns(nil, -1) + end;// AdjustActiveRange(ARecordIndex, -1); + end; + if ARecordIndex >= lMainFollower.SubFollowerCount then + begin + PreFetchColumns(nil, AItemIndex); + AdjustActiveRange(nil, -1); + end; + if ARecordIndex >= lMainFollower.SubFollowerCount then + Assert(false, Format('RecordIndex = %d Out of bounds, count = %d', [ARecordIndex, lMainFollower.SubFollowerCount])); + lRowFollower := lMainFollower.SubFollowers[ARecordIndex]; + if not Assigned(lRowFollower) then + begin + PreFetchColumns(nil, -1); + AdjustActiveRange(nil, AItemIndex); + lRowFollower := lMainFollower.SubFollowers[ARecordIndex]; + end; + if not Assigned(lRowFollower) then + exit; + if not lRowFollower.ElementValid then // if not lRowFollower.Displayable then + AdjustActiveRange(nil, AItemIndex); + Assert(lRowFollower.ElementValid, 'lRowFollower.ElementValid'); + if not lRowFollower.Displayable then + lRowFollower.EnsureDisplayable; + Assert(lRowFollower.Active, 'lRowFollower.Active'); + if not lRowFollower.SubFollowerAssigned[AItemIndex] then + begin + // AdjustActiveRange(nil, AItemIndex); +// if not lRowFollower.SubFollowerAssigned[AItemIndex] then + result := false; +// AdjustActiveRange(nil, AItemIndex);// Assert(false); + // lCellFollower := lRowFollower.SubFollowers[AItemIndex]; + // Assert(lRowFollower.SubFollowerAssigned[AItemIndex], 'SubFollowerAssigned not assigned'); + end; + try + lRowFollower.EnsureDisplayable; + except + exit; + end; + lCellFollower := lRowFollower.SubFollowers[AItemIndex]; + Assert(Assigned(lCellFollower), 'lCellFollower not assigned'); + if not lCellFollower.Displayable then + lCellFollower.EnsureDisplayable; + Assert(lCellFollower.Displayable, ' lCellFollower not Displayable'); + finally + result := Assigned(lCellFollower) and lCellFollower.Displayable; + dec(FSkipMakeCellUptoDate); + end; +end; + +destructor TcxBoldDataController.Destroy; +begin + BoldInstalledQueue.RemoveFromPostDisplayQueue(Self); + fBoldProperties.OnAfterInsertItem := nil; + fBoldProperties.OnAfterDeleteItem := nil; + fBoldProperties.OnReplaceitem := nil; + FreeAndNil(fBoldHandleFollower); + FreeAndNil(fBoldProperties); + CustomDataSource.Free; + CustomDataSource := nil; + FreeAndNil(fBoldColumnsProperties); + FreeAndNil(fSubscriber); + FreeAndNil(fSelection); + inherited Destroy; +end; + +procedure TcxBoldDataController._BeforeMakeListUpToDate( + Follower: TBoldFollower); +var + i: integer; +begin + inc(FSkipMakeCellUptoDate); + BeginFullUpdate; + + if GetOwner is TcxComponent and TcxComponent(GetOwner).IsDesigning then exit; +// if isPattern then exit; + + if (Assigned(CustomDataSource) and (GetHandleListElementType <> fCurrentListElementType)) or (not Assigned(CustomDataSource) and Assigned(fCurrentListElementType)) then + begin + fFetchedAll := false; + CustomDataSource.free; + fBoldProperties.OnAfterInsertItem := nil; + fBoldProperties.OnAfterDeleteItem := nil; + fBoldProperties.OnReplaceitem := nil; + end; + if (CustomDataSource = nil) then + begin +// TODO: +// if Assigned(OnBeforeLoad) then +// OnBeforeLoad(GridView); + end; + if (CustomDataSource = nil) or (Follower.SubFollowerCount = 0) then + begin +// if not LoadAll then + // we need to set ActiveRange here, otherwise all followers will be active and all objects will be fetched + BoldProperties.SetActiveRange(Follower, 0, -1, 0); + end; + if Assigned(CustomDataSource) then + TcxBoldDataSource(CustomDataSource).fIsBoldInitiatedChange := true; + for i := 0 to ItemCount - 1 do + begin + BoldPropertiesFromItem(i).AfterMakeUptoDate := nil; + end; +end; + +procedure TcxBoldDataController._AfterMakeListUptoDate( + Follower: TBoldFollower); +var + lcxBoldDataSource: TcxBoldDataSource; + lFirstLoad: boolean; + i: integer; +begin + {$IFDEF BoldDevExLog} + _Log((GetOwner as TComponent).Name + ':_AfterMakeListUpToDate:' + IntToStr(FSkipMakeCellUptoDate), className); + {$ENDIF} + + lFirstLoad := (CustomDataSource = nil); + if lFirstLoad then + begin + lcxBoldDataSource := cxBoldDataSourceClass.Create(self); + CustomDataSource := lcxBoldDataSource; + TypeMayHaveChanged; + end; + dec(FSkipMakeCellUptoDate); + + CustomDataSource.DataChanged; + for i := 0 to ItemCount - 1 do + begin + BoldPropertiesFromItem(i).AfterMakeUptoDate := _AfterMakeCellUptoDate; + end; + PreFetchColumns(); + EndFullUpdate; + if Assigned(CustomDataSource) then + TcxBoldDataSource(CustomDataSource).fIsBoldInitiatedChange := false; +end; + +procedure TcxBoldDataController._InsertRow(index: Integer; Follower: TBoldFollower); +begin + DataHasChanged := true; +end; + +procedure TcxBoldDataController._ReplaceRow(index: Integer; + AFollower: TBoldFollower); +begin + DataHasChanged := true; +end; + +procedure TcxBoldDataController._DeleteRow(index: Integer; + owningFollower: TBoldFollower); +var + vRowIndex: integer; + vRecordIndex: integer; +begin + DataHasChanged := true; + if fInDeleteSelection then + exit; + with DataControllerInfo.Selection do + if (DataControllerInfo.Selection.Count > 1) and IsRecordSelected(Index) then + DataControllerInfo.Selection.Delete(FindByRecordIndex(Index)); +end; + +function TcxBoldDataController.GetHandleStaticType: TBoldElementTypeInfo; +begin + if assigned(BoldHandle) then + result := BoldHandle.StaticBoldType + else + result := nil; +end; + +procedure TcxBoldDataController._AfterMakeCellUptoDate( + Follower: TBoldFollower); +begin +// TODO: ? +end; + +function TcxBoldDataController.GetFollower: TBoldFollower; +begin + Result := nil; + if Assigned(fBoldHandleFollower) then + Result := fBoldHandleFollower.Follower; +end; + +function TcxBoldDataController.GetCellFollower(ARecordIndex, AItemIndex: Integer): TBoldFollower; +var + lRowFollower: TBoldFollower; +begin + lRowFollower := GetRowFollower(ARecordIndex); + if assigned(lRowFollower) and + (AItemIndex >= 0) and + (AItemIndex < lRowFollower.SubFollowerCount) then + Result := lRowFollower.SubFollowers[AItemIndex] + else + result := nil; +end; + +function TcxBoldDataController.GetHasCellFollower(ARecordIndex, AItemIndex: Integer): boolean; +var + lRowFollower: TBoldFollower; +begin + lRowFollower := GetRowFollower(ARecordIndex); + result := assigned(lRowFollower) and lRowFollower.SubFollowerAssigned[AItemIndex]; +end; + +function TcxBoldDataController.GetDataProviderClass: TcxCustomDataProviderClass; +begin + Result := TcxBoldCustomDataProvider; +end; + +function TcxBoldDataController.GetRecNo: Integer; +begin + result := Follower.CurrentIndex; +end; + +function TcxBoldDataController.GetRecordCount: Integer; +begin + if (DetailMode = dcdmPattern) or not Assigned(TcxCustomDataProviderAccess(provider).CustomDataSource) then + result := inherited GetRecordCount + else + begin + Result := TcxBoldDataSource(TcxCustomDataProviderAccess(provider).CustomDataSource).GetRecordCount; + end; +end; + +function TcxBoldDataController.GetRowFollower( + DataRow: Integer): TBoldFollower; +var + lFollower: TBoldFollower; +begin + lFollower := Follower; + if datarow < lFollower.SubFollowerCount then + Result := lFollower.SubFollowers[DataRow] + else + result := nil; +end; + +function TcxBoldDataController.GetSearchClass: TcxDataControllerSearchClass; +begin + result := TcxBoldDataControllerSearch; +end; + +function TcxBoldDataController.InDelayScrollUpdate: boolean; +begin + result := FUseDelayedScrollUpdate and fInDelayScrollUpdate; +end; + +function TcxBoldDataController.IsDataLinked: Boolean; +begin + Result := BoldHandle <> nil; +end; + +function TcxBoldDataController.IsSmartRefresh: Boolean; +begin + result := false; +end; + +procedure TcxBoldDataController.AdjustActiveRange(aList: TBoldList = nil; aItem: integer = -1); +var + lFollower: TBoldFollower; + i,j: integer; +begin + lFollower := Follower; + if Assigned(lFollower) and Assigned(lFollower.element) and (lFollower.Element is TBoldList) then + begin + if RequiresAllRecords or LoadAll then + BoldProperties.SetActiveRange(lFollower, 0, lFollower.SubFollowerCount-1, 0) + else + begin + FindMinMaxIndex(aList, BoldList, i, j); + BoldProperties.SetActiveRange(lFollower, i, j, 0); + end; +{ if aList = nil then + PreFetchColumns(BoldList, aItem) + else + PreFetchColumns(aList, aItem);} + end; +end; + +procedure TcxBoldDataController.AdjustActiveRange(aRecordIndex: integer; aItem: integer = -1); +var + lList: TBoldObjectList; +begin + if (Follower.Element is TBoldObjectList) and (aRecordIndex >= 0) and (aRecordIndex < TBoldObjectList(Follower.Element).Count) then + begin + lList := TBoldObjectList.Create; + try + lList.Add( TBoldObjectList(Follower.Element)[aRecordIndex]); + AdjustActiveRange(lList, aItem); + finally + lList.free; + end; + end; +end; + +function TcxBoldDataController.TypeMayHaveChanged: boolean; +var + lNewListElementType: TBoldElementTypeInfo; + lOldListElementType: TBoldElementTypeInfo; +begin + result := false; + if not Assigned(BoldHandle) or not Assigned(BoldHandle.List) then + begin + if Assigned(fCurrentListElementType) then + begin + lOldListElementType := fCurrentListElementType; + fCurrentListElementType := nil; + TypeChanged(nil, lOldListElementType); + result := true; + end; + end + else + begin + lNewListElementType := GetHandleListElementType; + if (lNewListElementType <> fCurrentListElementType) then + begin + {$IFDEF BoldDevExLog} + if Assigned(fCurrentListElementType) then + begin + if Assigned(lNewListElementType) then + _Log((GetOwner as TComponent).Name + ':TypeMayHaveChanged:' + fCurrentListElementType.AsString + '->' + lNewListElementType.AsString, className) + else + _Log((GetOwner as TComponent).Name + ':TypeMayHaveChanged:' + fCurrentListElementType.AsString + '-> nil', className); + end + else + _Log((GetOwner as TComponent).Name + ':TypeMayHaveChanged:' + lNewListElementType.AsString, className); + {$ENDIF} + lOldListElementType := fCurrentListElementType; + fCurrentListElementType := lNewListElementType; + TypeChanged(lNewListElementType, lOldListElementType); + result := true; + end; + end; +end; + +function TcxBoldDataController.GetHandleListElementType: TBoldElementTypeInfo; +begin + if Assigned(BoldHandle) then + Result := BoldHandle.ListElementType //BoldType + else + Result := nil; +end; + +function TcxBoldDataController.BoldPropertiesFromItem( + aIndex: integer): TBoldVariantFollowerController; +var + lBoldAwareViewItem: IBoldAwareViewItem; +begin + if GetItem(aIndex).GetInterface(IBoldAwareViewItem, lBoldAwareViewItem) then + result := lBoldAwareViewItem.BoldProperties + else + result := nil; +end; + +function TcxBoldDataController.BoldSetValue(AItemHandle: TcxDataItemHandle; + ACellFollower: TBoldFollower; const AValue: variant): boolean; +begin + result := false; +end; + +function TcxBoldDataController.GetCurrentBoldObject: TBoldObject; +begin + if GetCurrentElement is TBoldObject then + result := TBoldObject(GetCurrentElement) + else + result := nil; +end; + +function TcxBoldDataController.GetCurrentElement: TBoldElement; +var + lFollower: TBoldFollower; +begin + if CurrentIndex = -1 then + result := nil + else + begin + lFollower := Follower.CurrentSubFollower; + if Assigned(lFollower) then + result := lFollower.Element + else + result := nil; + end; +end; + +function TcxBoldDataController.GetCurrentIndex: integer; +begin + if InDelayScrollUpdate then + result := fStoredRecordIndex + else + result := Follower.CurrentIndex; +end; + + +procedure TcxBoldDataController.Receive(Originator: TObject; + OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent); +begin + case RequestedEvent of + beSystemDestroying: + begin + fCurrentListElementType := nil; + end; + beSelectionDestroying: + begin + fSelection := nil; + raise EcxGridBoldSupport.Create('Grid Selection destroyed, do not free the grid selection !'); + end; + end; +end; + +function TcxBoldDataController.RequiresAllRecords(AItem: TObject): boolean; +begin + result := true; +end; + +function TcxBoldDataController.RequiresAllRecords: boolean; +begin + result := true; +end; + +procedure TcxBoldDataController.TypeChanged(aNewType, aOldType: TBoldElementTypeInfo); +begin + fSubscriber.CancelAllSubscriptions; + FreeAndNil(fSelection); + if Assigned(aNewType) then + aNewType.SystemTypeInfo.AddSubscription(fSubscriber, beDestroying, beSystemDestroying); +end; + +function TcxBoldDataController.IsProviderMode: Boolean; +begin + result := true; +end; + +procedure TcxBoldDataController.PreFetchColumns(aList: TBoldList; aItem: integer); +begin +end; + +function TcxBoldDataController.GetCurrentDetailDataController(ARelationIndex: integer = 0): TcxBoldDataController; +begin + if CurrentIndex = -1 then + result := nil + else + result := GetDetailDataController(CurrentIndex, ARelationIndex) as TcxBoldDataController; +end; + +procedure TcxBoldDataController.FilterChanged; +begin + fSkipCancel := true; + try + inherited; + finally + fSkipCancel := false; + end; +end; + +function TcxBoldDataController.FindItemByData(AData: Integer): TObject; +var + I: Integer; +begin + if (AData > -1) and (AData < ItemCount) then + begin + Result := GetItem(AData); + if GetItemData(Result) = AData then + Exit; + end; + for I := 0 to ItemCount - 1 do + begin + Result := GetItem(I); + if GetItemData(Result) = AData then + Exit; + end; + Result := nil; +end; + +procedure TcxBoldDataController.FindMinMaxIndex(ListA, ListB: TBoldList; + var AFrom, ATo: integer); +var + i,j: integer; + vCount: integer; +begin + vCount := ListB.Count; + if (ListA is TBoldObjectList) and (ListB is TBoldObjectList) then + begin + AFrom := maxInt; + ATo := -1; + for I := 0 to ListA.Count - 1 do + begin + if TBoldObjectList(ListB).Locators[i] = TBoldObjectList(ListA).Locators[i] then + j := i + else + j := TBoldObjectList(ListB).IndexOfLocator(TBoldObjectList(ListA).Locators[i]); + AFrom := Min(AFrom, j); + ATo := max(ATo, j); + if (AFrom = 0) and (ATo = vCount-1) then + exit; + end; + end + else + begin + AFrom := maxInt; + ATo := -1; + for I := 0 to ListA.Count - 1 do + begin + j := ListB.IndexOf(ListA[i]); + AFrom := Min(AFrom, j); + ATo := max(ATo, j); + if (AFrom = 0) and (ATo = vCount-1) then + exit; + end; + if (ATo = -1) and (ListA.Count > 0) and (ListB.Count > 0) then + begin + AFrom := 0; + ATo := ListB.Count -1; + end; + end; +end; + +function TcxBoldDataController.GetSelection: TBoldList; +var + ListType: TBoldElementTypeInfo; +begin + if not Assigned(fSelection) then + begin + fSelection := CreateList; + fSelection.AddSubscription(fSubscriber, beDestroying, beSelectionDestroying); + SelectionChanged; + end; + result := fSelection; +end; + +procedure TcxBoldDataController.Cancel; +var + i: integer; + lRowFollower: TBoldFollower; +begin + if fSkipCancel then + exit; + if FocusedRecordIndex = -1 then + inherited + else + begin + lRowFollower := Follower.SubFollowers[FocusedRecordIndex]; + for i := 0 to lRowFollower.SubFollowerCount - 1 do + begin + lRowFollower.SubFollowers[i].DiscardChange; + end; + end; +end; + +procedure TcxBoldDataController.SelectionChanged; +begin +// do nothing +end; + +function TcxBoldDataController.GetBoldList: TBoldList; +begin + if Assigned(BoldHandle) then + result := BoldHandle.List //Follower.Element as TBoldList; + else + result := nil; +end; + +{ TcxBoldDataSource } + +constructor TcxBoldDataSource.Create( + aBoldDataController: TcxBoldDataController); +begin + inherited Create; + fBoldDataController := aBoldDataController; +end; + +function TcxBoldDataSource.GetRecordCount: Integer; +begin + result := fBoldDataController.Follower.SubFollowerCount; + if not fBoldDataController.fInternalLoading then + if (fBoldDataController.Follower.state <> bfsCurrent) and (result <> fBoldDataController.DataStorage.RecordCount) then + result := fBoldDataController.DataStorage.RecordCount; +end; + +function TcxBoldDataSource.GetValue(ARecordHandle: TcxDataRecordHandle; + AItemHandle: TcxDataItemHandle): Variant; +var + lMainFollower: TBoldFollower; + lCellFollower: TBoldFollower; + lItemIndex: integer; + lRecordIndex: integer; + lResultElement: TBoldElement; + lItem: TObject; + lcxBoldDataController: TcxBoldDataController; + lBoldAwareViewItem: IBoldAwareViewItem; + lIcxBoldEditProperties: IcxBoldEditProperties; +begin + result := null; + lItemIndex := Integer(AItemHandle); + lRecordIndex := Integer(ARecordHandle); + lcxBoldDataController := DataController as TcxBoldDataController; + if not lcxBoldDataController.EnsureFollower(lRecordIndex, lItemIndex) then + exit; + lMainFollower := lcxBoldDataController.Follower; + lCellFollower := lMainFollower.SubFollowers[lRecordIndex].SubFollowers[lItemIndex]; + lItem := lcxBoldDataController.FindItemByData(lItemIndex); + if (lItem is TcxCustomGridTableItem) and Supports(TcxCustomGridTableItemAccess(lItem).GetProperties, IcxBoldEditProperties, lIcxBoldEditProperties) then + begin + lResultElement := lCellFollower.Value; + if Assigned(lResultElement) then + result := lIcxBoldEditProperties.BoldElementToEditValue(lCellFollower, lResultElement, nil) + else + result := (lCellFollower.Controller as TBoldVariantFollowerController).GetCurrentAsVariant(lCellFollower); + end + else + result := (lCellFollower.Controller as TBoldVariantFollowerController).GetCurrentAsVariant(lCellFollower); +end; + +procedure TcxBoldDataSource.SetValue(ARecordHandle: TcxDataRecordHandle; + AItemHandle: TcxDataItemHandle; const AValue: Variant); +var + lRowFollower: TBoldFollower; + lCellFollower: TBoldFollower; + lItemIndex: integer; + lDone: boolean; +begin + lItemIndex := Integer(AItemHandle); + + lRowFollower := fBoldDataController.Follower.SubFollowers[Integer(ARecordHandle)]; + Assert(Assigned(lRowFollower)); + + inc(fBoldDataController.FSkipMakeCellUptoDate); + try + lRowFollower.EnsureDisplayable; + finally + dec(fBoldDataController.FSkipMakeCellUptoDate); + end; + lCellFollower := lRowFollower.SubFollowers[lItemIndex]; + + lDone := fBoldDataController.BoldSetValue(AItemHandle, lCellFollower, AValue); + + if not lDone then + begin + (lCellFollower.Controller as TBoldVariantFollowerController).MayHaveChanged(aValue, lCellFollower); + end; + if (lCellFollower.State = bfsDirty) and (lCellFollower.Controller.ApplyPolicy <> bapDemand) then + begin + lCellFollower.Apply; + {$IFDEF DisplayAll} + inc(fBoldDataController.FSkipMakeCellUptoDate); + try + TBoldQueueable.DisplayAll; + finally + dec(fBoldDataController.FSkipMakeCellUptoDate); + end; + {$ENDIF} + end; +end; + +function TcxBoldDataSource.IsCustomSorting: Boolean; +var + i: integer; +begin + result := false; + + with TcxCustomDataControllerInfoAccess(DataController.DataControllerInfo) do + for I := 0 to RecordList.Count - 1 do + Assert(Integer(RecordList.Items[i]) < DataController.RecordCount); +end; + +procedure TcxBoldDataSource.CustomSort; +var + i,j: integer; + lOcl: string; + SourceList: TBoldList; +begin + SourceList := fBoldDataController.BoldList; + for I := 0 to TcxCustomDataControllerInfoAccess(DataController.DataControllerInfo).TotalSortingFieldList.Count - 1 do + begin + j := TcxCustomDataControllerInfoAccess(DataController.DataControllerInfo).TotalSortingFieldList[i].Field.Index; + lOcl := fBoldDataController.BoldColumnsProperties[j].Expression; +// FetchOclSpan(SourceList, lOcl); + end; + SourceList.Sort(CustomSortElementCompare); +end; + +function TcxBoldDataSource.CustomSortElementCompare(Item1, + Item2: TBoldElement): integer; +var + i,j: integer; + IE1, IE2: TBoldIndirectElement; +begin + result := 0; + IE1 := TBoldIndirectElement.Create; + IE2 := TBoldIndirectElement.Create; + try + for I := 0 to TcxCustomDataControllerInfoAccess(DataController.DataControllerInfo).TotalSortingFieldList.Count - 1 do + begin + j := TcxCustomDataControllerInfoAccess(DataController.DataControllerInfo).TotalSortingFieldList[i].Field.Index; + Item1.EvaluateExpression(fBoldDataController.BoldColumnsProperties[j].Expression, ie1); + Item2.EvaluateExpression(fBoldDataController.BoldColumnsProperties[j].Expression, ie2); + if Assigned(IE1.Value) then + result := IE1.Value.CompareTo(IE2.Value); + end; + finally + ie1.free; + ie2.free; + end; +end; + +procedure TcxBoldDataSource.DeleteRecord( + ARecordHandle: TcxDataRecordHandle); +var + lRowFollower: TBoldFollower; + lIndex: integer; + lBoldObject: TBoldObject; +begin + if not fIsBoldInitiatedChange then + begin + lIndex := Integer(ARecordHandle); + lRowFollower := fBoldDataController.Follower.SubFollowers[lIndex]; + Assert(Assigned(lRowFollower)); + Assert(lIndex = lRowFollower.index); + fIsBoldInitiatedChange := true; + try + {$IFDEF DisplayAll} + TBoldQueueable.DisplayAll; + {$ENDIF} +// Assert(lRowFollower.Element = fBoldDataController.Follower.SubFollowers[lIndex].Element, 'lRowFollower.Element = fBoldDataController.Follower.SubFollowers[lIndex].Element'); + lBoldObject := (lRowFollower.Element as TBoldObject); + if Assigned(lBoldObject) then + Assert(lBoldObject = fBoldDataController.BoldHandle.ObjectList[lIndex], 'lBoldObject = fBoldDataController.BoldHandle.ObjectList[lIndex]') + else + lBoldObject := fBoldDataController.BoldHandle.ObjectList[lIndex]; + + if lBoldObject.BoldClassTypeInfo.IsLinkClass then + begin + if lBoldObject.BoldObjectExists then // not already deleted + lBoldObject.delete; + end + else + begin + fBoldDataController.BoldHandle.MutableList.Remove(lBoldObject); + end; +{ + if lBoldObject.BoldObjectExists then // not already deleted + lBoldObject.delete; +} +// TBoldQueueable.DisplayAll; + {$IFDEF BoldDevExLog} + _Log((TcxBoldDataController(DataController).GetOwner as TComponent).Name + ':DataChanged4', ClassName); + {$ENDIF} + TcxBoldDataController(DataController).DataHasChanged := true; //DataChanged; +{ + if (lIndex < GetRecordCount) and (GetRecordCount > 0)then + begin + (fBoldDataController.GridView.Controller as TcxGridTableController).FocusedRow.Selected := true; + end; +} + finally + fIsBoldInitiatedChange := false; + end; + end; +end; + +function TcxBoldDataSource.GetDetailHasChildren(ARecordIndex, + ARelationIndex: Integer): Boolean; +var + lcxCustomDataController: TcxCustomDataController; + lFollower: TBoldFollower; + lOcl: string; + Ie: TBoldIndirectElement; + lDetailObject: TcxDetailObject; + lObject: TObject; + lGridLevel: TcxGridLevel; + lcxCustomDataRelation: TcxCustomDataRelation; + lPatternView: IBoldAwareView; + lcxCustomDataProviderAccess: TcxCustomDataProviderAccess; +begin + lcxCustomDataProviderAccess := TcxCustomDataProviderAccess(CurrentProvider); + Assert(fBoldDataController = lcxCustomDataProviderAccess.DataController); + result := false; + + if not (lcxCustomDataProviderAccess.DataController is TcxGridBoldDataController) then + exit; +// lDetailObject := fBoldDataController.GetDetailLinkObject(ARecordIndex, ARelationIndex) as TcxDetailObject; + + lDetailObject := lcxCustomDataProviderAccess.DataController.Relations.GetDetailObject(ARecordIndex); + lObject := lDetailObject.LinkObjects[ARelationIndex]; + + if Assigned(lObject) then + begin + lcxCustomDataController := lcxCustomDataProviderAccess.DataController.GetDetailDataController(ARecordIndex, ARelationIndex); + result := lcxCustomDataController.RecordCount > 0; + end + else + begin + lcxCustomDataRelation := lcxCustomDataProviderAccess.DataController.Relations[ARelationIndex]; + lGridLevel := lcxCustomDataRelation.Item as TcxGridLevel; + if lGridLevel.GridView.IsPattern and (lGridLevel.GridView <> TcxGridBoldDataController(lcxCustomDataProviderAccess.DataController).GridView) then + begin + lPatternView := (lGridLevel.GridView as IBoldAwareView); + if Assigned(lPatternView.DataController.BoldHandle) and (lPatternView.DataController.BoldHandle is TBoldListHandle) then + begin + TBoldQueueable.DisplayAll; + lOcl := (lPatternView.DataController.BoldHandle as TBoldListHandle).Expression; + Ie := TBoldIndirectElement.Create; + try + TcxBoldDataController(lcxCustomDataProviderAccess.DataController).AdjustActiveRange(); + lFollower := TcxBoldDataController(lcxCustomDataProviderAccess.DataController).Follower.SubFollowers[ARecordIndex]; + if not Assigned(lFollower) or not Assigned(lFollower.Element) then + exit; + if (lPatternView.DataController.BoldHandle as TBoldListHandle).Variables <> nil then + lFollower.Element.EvaluateExpression(lOcl, Ie, false, (lPatternView.DataController.BoldHandle as TBoldListHandle).Variables.VariableList) + else + lFollower.Element.EvaluateExpression(lOcl, Ie); + if Ie.Value is TBoldList then + begin + result := TBoldList(Ie.Value).Count > 0; + end + else + result := false; //Assigned(Ie.Value); + finally + Ie.free; + end; + end; + end; + end; +end; + +function TcxBoldDataSource.GetItemHandle( + AItemIndex: Integer): TcxDataItemHandle; +var + lItem: TObject; +begin + lItem := TcxCustomDataProviderAccess(CurrentProvider).DataController.GetItem(AItemIndex); + if lItem is TcxCustomGridTableItem then + result := TcxCustomGridTableItem(lItem).DataBinding.Data + else + result := TcxDataItemHandle(AItemIndex); // this handles cxLookupGrid which doesn't allow column moving so indexes are static +end; + +function TcxBoldDataSource.GetRecordHandle( + ARecordIndex: Integer): TcxDataRecordHandle; +begin + result := TcxDataRecordHandle(ARecordIndex); +end; + +function TcxBoldDataSource.GetRecordHandleByIndex( + ARecordIndex: Integer): TcxDataRecordHandle; +begin + Result := TcxDataRecordHandle(ARecordIndex); +end; + +destructor TcxBoldDataSource.Destroy; +begin + inherited; +end; + +function TcxBoldDataSource.IsRecordIdSupported: Boolean; +begin + result := true; +end; + +procedure TcxBoldDataSource.LoadRecordHandles; +begin +{$IFDEF BoldDevExLog} + if Assigned(fBoldDataController.BoldHandle) then + _Log(fBoldDataController.BoldHandle.Name + ':' + IntToStr(GetRecordCount), 'recordhandles'); +{$ENDIF} + inherited; +end; + +function TcxBoldDataSource.GetRecordId( + ARecordHandle: TcxDataRecordHandle): Variant; +begin + result := Integer(ARecordHandle); +end; + +{ TcxGridBoldColumn } + +function TcxGridBoldColumn.CalculateBestFitWidth: Integer; +begin + GridView.OptionsBehavior.BestFitMaxRecordCount := GridView.ViewInfo.VisibleRecordCount; + result := inherited CalculateBestFitWidth; +end; + +destructor TcxGridBoldColumn.Destroy; +begin + DataBinding.Remove; + inherited; +end; + +function TcxGridBoldColumn.GetDataBinding: TcxGridItemBoldDataBinding; +begin + Result := TcxGridItemBoldDataBinding(inherited DataBinding); +end; + +function TcxGridBoldColumn.GetProperties(AProperties: TStrings): Boolean; +begin + AProperties.Add('OnCustomDrawCell'); + AProperties.Add('OnGetFilterValues'); + AProperties.Add('OnUserFilteringEx'); + AProperties.Add('OnGetCellHint'); + AProperties.Add('Sorting'); + AProperties.Add('Grouping'); + AProperties.Add('Filtering'); + AProperties.Add('Caption'); + AProperties.Add('IncSearch'); + AProperties.Add('Expression'); + AProperties.Add('Renderer'); + Result := inherited GetStoredProperties(AProperties); +end; + +procedure TcxGridBoldColumn.GetPropertyValue(const AName: string; + var AValue: Variant); +var + method: TMethod; + Renderer: TBoldRenderer; +begin + if Assigned(OnCustomDrawCell) and (AName = 'OnCustomDrawCell') then + begin + method := TMethod(OnCustomDrawCell); + if method.Data <> DataController then + AValue := TObject(Method.Data).MethodName(Method.Code); + end + else + if Assigned(OnGetFilterValues) and (AName = 'OnGetFilterValues') then + begin + method := TMethod(OnGetFilterValues); + if method.Data <> DataController then + AValue := TObject(Method.Data).MethodName(Method.Code); + end + else + if Assigned(OnUserFilteringEx) and (AName = 'OnUserFilteringEx') then + begin + method := TMethod(OnUserFilteringEx); + if method.Data <> DataController then + AValue := TObject(Method.Data).MethodName(Method.Code); + end + else + if Assigned(OnGetCellHint) and (AName = 'OnGetCellHint') then + begin + method := TMethod(OnGetCellHint); + if method.Data <> DataController then + AValue := TObject(Method.Data).MethodName(Method.Code); + end + else + if AName = 'Sorting' then + AValue := Options.Sorting + else + if AName = 'Grouping' then + AValue := Options.Grouping + else + if AName = 'Filtering' then + AValue := Options.Filtering + else + if AName = 'Caption' then + AValue := Caption + else + if AName = 'IncSearch' then + AValue := Options.IncSearch + else + if AName = 'Expression' then + AValue := DataBinding.BoldProperties.expression + else + if AName = 'Renderer' then + begin + if Assigned(DataBinding.BoldProperties.Renderer) then + begin + Renderer := DataBinding.BoldProperties.Renderer; + if Assigned(Renderer.Owner) and (Renderer.Owner <> Owner.Owner) then + begin + AValue := Renderer.Owner.Name + '.'+ Renderer.Name; + end + else + AValue := Renderer.Name; + end; + end + else + inherited; +end; + +procedure TcxGridBoldColumn.SetDataBinding( + Value: TcxGridItemBoldDataBinding); +begin + inherited DataBinding := Value; +end; + +procedure TcxGridBoldColumn.SetPropertyValue(const AName: string; + const AValue: Variant); + + function FindEvent(const AEventName: string): TMethod; + var + vObject: TObject; + begin + result.Code := nil; + result.Data := nil; + vObject := self; + repeat + if Integer(vObject.MethodAddress(AEventName)) <> 0 then + begin + result.Code := vObject.MethodAddress(AEventName); + result.Data := vObject; + end + else + if vObject is TComponent then + vObject := TComponent(vObject).Owner; + until (Integer(result.Code) <> 0) or not Assigned(vObject); + end; + +var + Renderer: TBoldCustomAsVariantRenderer; + s: string; + i: integer; + Component: TComponent; +begin + if AName = 'OnCustomDrawCell' then + begin + if AValue = '' then + OnCustomDrawCell := nil + else + OnCustomDrawCell := TcxGridTableDataCellCustomDrawEvent(FindEvent(AValue)); + end + else + if AName = 'OnGetFilterValues' then + begin + if AValue = '' then + OnGetFilterValues := nil + else + OnGetFilterValues := TcxGridGetFilterValuesEvent(FindEvent(AValue)); + end + else + if AName = 'OnUserFilteringEx' then + begin + if AValue = '' then + OnUserFilteringEx := nil + else + OnUserFilteringEx := TcxGridUserFilteringExEvent(FindEvent(AValue)); + end + else + if AName = 'OnGetCellHint' then + begin + if AValue = '' then + OnGetCellHint := nil + else + OnGetCellHint := TcxGridGetCellHintEvent(FindEvent(AValue)); + end + else + if AName = 'Sorting' then + Options.Sorting := AValue + else + if AName = 'Grouping' then + Options.Grouping := AValue + else + if AName = 'Filtering' then + Options.Filtering := AValue + else + if AName = 'Caption' then + Caption := AValue + else + if AName = 'IncSearch' then + begin + Options.IncSearch := AValue; + if Options.IncSearch then + GridView.OptionsBehavior.IncSearchItem := self; + end + else + if AName = 'Expression' then + DataBinding.BoldProperties.expression := AValue + else + if AName = 'Renderer' then + begin + i := Pos('.', AValue); + if i > 1 then + begin + s := Copy(aValue, 1, i-1); + Component := Application.FindComponent(s); + s := Copy(aValue, i+1, maxint); + Renderer := Component.FindComponent(s) as TBoldCustomAsVariantRenderer; + end + else + begin + Renderer := FindComponent(AValue) as TBoldCustomAsVariantRenderer; + if not Assigned(Renderer) and Assigned(GridView.Owner) then + Renderer := GridView.Owner.FindComponent(AValue) as TBoldCustomAsVariantRenderer; + end; + DataBinding.BoldProperties.Renderer := Renderer; + end + else + inherited; +end; + +procedure TcxGridBoldColumn.VisibleChanged; +begin + inherited; +// if Visible and not IsLoading then +// (DataController as TcxGridBoldDataController).AdjustActiveRange(); +end; + +{ TcxGridBoldTableView } + +function TcxGridBoldTableView.DoCellDblClick( + ACellViewInfo: TcxGridTableDataCellViewInfo; AButton: TMouseButton; + AShift: TShiftState): Boolean; +var + lAutoForm: TForm; + lElement: TBoldElement; +begin + result := false; + if DataController.BoldProperties.DefaultDblClick and not Controller.IsSpecialRowFocused and Assigned(DataController.Follower.CurrentSubFollower) then + begin + lElement := DataController.Follower.CurrentSubFollower.Element; + lAutoForm := AutoFormProviderRegistry.FormForElement(lElement); + if assigned(lAutoForm) then + begin + result := true; + lAutoForm.Show; + end + end; + if not result then + begin + result := inherited DoCellDblClick(ACellViewInfo, AButton, AShift); + end; +end; + +//{$IFNDEF UseBoldEditors} +//type +// IcxBoldEditProperties = Interface +// ['{D50859F1-F550-4CE6-84DE-5074921512E5}'] +// procedure SetStoredValue(aEdit: TcxCustomEdit; aFollower: TBoldFollower; var aDone: boolean); +// end; +//{$ENDIF} + +function TcxGridBoldTableView.DoEditing( + AItem: TcxCustomGridTableItem): Boolean; +begin + if Controller.IsSpecialRowFocused then + begin + result := inherited DoEditing(aItem); + end + else + begin + result := DataController.DoEditing(AItem) and inherited DoEditing(aItem); + end; +end; + +procedure TcxGridBoldTableView.DoEditKeyPress( + AItem: TcxCustomGridTableItem; AEdit: TcxCustomEdit; var Key: Char); +var + lRecord: integer; + lFollower: TBoldFollower; +begin + lRecord := DataController.RecNo; + if (lRecord <> -1) and (Key <> #8) and not Controller.IsSpecialRowFocused then + begin + lFollower := DataController.CellFollowers[lRecord, AItem.ID]; + if not (lFollower.AssertedController as TBoldVariantFollowerController).ValidateCharacter(key, lFollower) then + begin + key := #0; + end; + end; + inherited; +end; + +{$IFDEF DelayOnFocusedRecordChange} +procedure TcxGridBoldTableView.InheritedDoFocusedRecordChanged(APrevFocusedRecordIndex, + AFocusedRecordIndex, APrevFocusedDataRecordIndex, + AFocusedDataRecordIndex: Integer; ANewItemRecordFocusingChanged: Boolean); +begin + if AFocusedRecordIndex >= TcxCustomDataControllerInfoAccess(DataController.DataControllerInfo).RecordList.Count then + begin + DataController.DataControllerInfo.Refresh; + Assert(DataController.FilteredRecordCount = TcxCustomDataControllerInfoAccess(DataController.DataControllerInfo).RecordList.Count, Format('DataController.FilteredRecordCount = %d <> DataController.DataControllerInfo.GetRowCount = %d', [DataController.FilteredRecordCount, TcxCustomDataControllerInfoAccess(DataController.DataControllerInfo).RecordList.Count])); + end; + inherited DoFocusedRecordChanged(APrevFocusedRecordIndex, AFocusedRecordIndex, APrevFocusedDataRecordIndex, AFocusedDataRecordIndex, ANewItemRecordFocusingChanged); +end; +{$ENDIF} + +procedure TcxGridBoldTableView.DoFocusedRecordChanged(APrevFocusedRecordIndex, + AFocusedRecordIndex, APrevFocusedDataRecordIndex, + AFocusedDataRecordIndex: Integer; ANewItemRecordFocusingChanged: Boolean); +begin + if DataController.InDelayScrollUpdate then + begin + if FPrevFocusedRecordIndex = MaxInt then // MaxInt used as flag to only store Prev values once + begin + FPrevFocusedRecordIndex := APrevFocusedRecordIndex; + FPrevFocusedDataRecordIndex := APrevFocusedDataRecordIndex; + end; + end + else +{$IFDEF DelayOnFocusedRecordChange} + if Assigned(OnFocusedRecordChanged)then + begin + DataController.EnsureEventQueued; + DataController.fFocusChanged := true; + DataController.fPrevFocusedRecordIndex := APrevFocusedRecordIndex; + DataController.fFocusedRecordIndex := AFocusedRecordIndex; + DataController.fPrevFocusedDataRecordIndex := APrevFocusedDataRecordIndex; + DataController.fFocusedDataRecordIndex := AFocusedDataRecordIndex; + DataController.fNewItemRecordFocusingChanged := ANewItemRecordFocusingChanged; + end + else +{$ENDIF} + begin +// if not TBoldQueueable.IsDisplayQueueEmpty and not TBoldQueueable.IsDisplaying then +// TBoldQueueable.DisplayAll; + inherited; + FPrevFocusedRecordIndex := MaxInt; + end; +end; + +procedure TcxGridBoldTableView.DoChanged(AChangeKind: TcxGridViewChangeKind); +begin + if Assigned(DataController) and Assigned(DataController.CustomDataSource) and DataController.MainFollowerNeedsDisplay then + if DataController.LockCount = 0 then + DataController.DisplayFollowers; + inherited; +end; + +procedure TcxGridBoldTableView.DoCustomDrawCell(ACanvas: TcxCanvas; + AViewInfo: TcxGridTableDataCellViewInfo; var ADone: Boolean); +var + CellFollower: TBoldFollower; + Controller: TBoldVariantFollowerController; + Color: TColor; +begin + Color := ACanvas.Brush.Color; + inherited DoCustomDrawCell(ACanvas, AViewInfo, ADone); + if ADone then + exit; + CellFollower := (AViewInfo.GridView as IBoldAwareView).DataController.CellFollowers[AViewInfo.RecordViewInfo.GridRecord.RecordIndex, AViewInfo.Item.ID]; + if Assigned(CellFollower) then + begin + Controller := CellFollower.Controller as TBoldVariantFollowerController; + Controller.SetColor(Color, Color, CellFollower); + if Color > -1 then + ACanvas.Brush.Color := Color; + end; +end; + +procedure TcxGridBoldTableView.DoItemsAssigned; +begin + DataController.RestructData; + inherited; +end; + +function TcxGridBoldTableView.GetSelection: TBoldList; +begin + result := DataController.Selection; +end; + +procedure TcxGridBoldTableView.DoSelectionChanged; +begin + DataController.SelectionChanged; + inherited; +end; + +function TcxGridBoldTableView.GetViewInfoClass: TcxCustomGridViewInfoClass; +begin + result := TcxGridBoldTableViewInfo; +end; + +function TcxGridBoldTableView.GetControllerClass: TcxCustomGridControllerClass; +begin + result := TcxGridBoldTableController; +end; + +function TcxGridBoldTableView.GetDataController: TcxGridBoldDataController; +begin + Result := TcxGridBoldDataController(FDataController); +end; + +function TcxGridBoldTableView.GetDataControllerClass: TcxCustomDataControllerClass; +begin + Result := TcxGridBoldDataController; +end; + +function TcxGridBoldTableView.GetFake: TNotifyEvent; +begin + result := nil; +end; + +procedure TcxGridBoldTableView.SetFake(const Value: TNotifyEvent); +begin + +end; + +function TcxGridBoldTableView.GetItemClass: TcxCustomGridTableItemClass; +begin + Result := TcxGridBoldColumn; +end; + +procedure TcxGridBoldTableView.HookDragDrop; +begin + OnDragDrop := DataController.DoDragDrop; + OnStartDrag := DataController.DoStartDrag; + OnEndDrag := DataController.DoEndDrag; + OnDragOver := DataController.DoDragOver; +end; + +procedure TcxGridBoldTableView.SetDataController( + Value: TcxGridBoldDataController); +begin + FDataController.Assign(Value); +end; + +function TcxGridBoldTableView.ValidateComponent( + ComponentValidator: TBoldComponentValidator; NamePrefix: string): Boolean; +var + i: integer; + lContext: TBoldElementTypeInfo; + lBoldValidateableComponent: IBoldValidateableComponent; +begin + lContext := DataController.GetHandleStaticType; + result := ComponentValidator.ValidateExpressionInContext( + '', lContext, format('%s%s', [NamePrefix, Name])); // do not localize + if assigned(lContext) then + for i := 0 to ItemCount - 1 do + begin + result := ComponentValidator.ValidateExpressionInContext( + Items[i].BoldProperties.Expression, + lContext, + format('%s%s.Column[%d]', [NamePrefix, Name, i]), + Items[i].BoldProperties.VariableList) and result; // do not localize + if Supports((DataController.GetItem(i) as TcxCustomGridTableItem).GetProperties, IBoldValidateableComponent, lBoldValidateableComponent) then + result := lBoldValidateableComponent.ValidateComponent(ComponentValidator, namePrefix) and result; + end; +end; + +constructor TcxGridBoldTableView.Create(AOwner: TComponent); +begin + inherited; +{$IFDEF DefaultDragMode} + DragMode := dmAutomatic; +{$ENDIF} + hookDragDrop; +end; + +{ TcxGridBoldBandedTableView } + +constructor TcxGridBoldBandedTableView.Create(AOwner: TComponent); +begin + inherited; +{$IFDEF DefaultDragMode} + DragMode := dmAutomatic; +{$ENDIF} + hookDragDrop; +end; + +destructor TcxGridBoldBandedTableView.Destroy; +begin + inherited; +end; + +{$IFDEF DelayOnFocusedRecordChange} +procedure TcxGridBoldBandedTableView.InheritedDoFocusedRecordChanged(APrevFocusedRecordIndex, + AFocusedRecordIndex, APrevFocusedDataRecordIndex, + AFocusedDataRecordIndex: Integer; ANewItemRecordFocusingChanged: Boolean); +begin + if AFocusedRecordIndex >= TcxCustomDataControllerInfoAccess(DataController.DataControllerInfo).RecordList.Count then + begin + DataController.DataControllerInfo.Refresh; + Assert(DataController.FilteredRecordCount = TcxCustomDataControllerInfoAccess(DataController.DataControllerInfo).RecordList.Count, Format('DataController.FilteredRecordCount = %d <> DataController.DataControllerInfo.GetRowCount = %d', [DataController.FilteredRecordCount, TcxCustomDataControllerInfoAccess(DataController.DataControllerInfo).RecordList.Count])); + end; + inherited DoFocusedRecordChanged(APrevFocusedRecordIndex, AFocusedRecordIndex, APrevFocusedDataRecordIndex, AFocusedDataRecordIndex, ANewItemRecordFocusingChanged); +end; +{$ENDIF} + +procedure TcxGridBoldBandedTableView.DoFocusedRecordChanged(APrevFocusedRecordIndex, + AFocusedRecordIndex, APrevFocusedDataRecordIndex, + AFocusedDataRecordIndex: Integer; ANewItemRecordFocusingChanged: Boolean); +begin + if DataController.InDelayScrollUpdate then + begin + if FPrevFocusedRecordIndex = MaxInt then // MaxInt used as flag to only store Prev values once + begin + FPrevFocusedRecordIndex := APrevFocusedRecordIndex; + FPrevFocusedDataRecordIndex := APrevFocusedDataRecordIndex; + end; + end + else +{$IFDEF DelayOnFocusedRecordChange} + if Assigned(OnFocusedRecordChanged)then + begin + DataController.EnsureEventQueued; + DataController.fFocusChanged := true; + DataController.fPrevFocusedRecordIndex := APrevFocusedRecordIndex; + DataController.fFocusedRecordIndex := AFocusedRecordIndex; + DataController.fPrevFocusedDataRecordIndex := APrevFocusedDataRecordIndex; + DataController.fFocusedDataRecordIndex := AFocusedDataRecordIndex; + DataController.fNewItemRecordFocusingChanged := ANewItemRecordFocusingChanged; + end + else +{$ENDIF} + begin +// if not TBoldQueueable.IsDisplayQueueEmpty and not TBoldQueueable.IsDisplaying then +// TBoldQueueable.DisplayAll; + inherited; + FPrevFocusedRecordIndex := MaxInt; + end; +end; + +procedure TcxGridBoldBandedTableView.DoChanged(AChangeKind: TcxGridViewChangeKind); +begin + if Assigned(DataController) and Assigned(DataController.CustomDataSource) and DataController.MainFollowerNeedsDisplay then + DataController.DisplayFollowers; + inherited; +end; + +function TcxGridBoldBandedTableView.DoCellDblClick( + ACellViewInfo: TcxGridTableDataCellViewInfo; AButton: TMouseButton; + AShift: TShiftState): Boolean; +var + lAutoForm: TForm; + lElement: TBoldElement; +begin + result := false; + if DataController.BoldProperties.DefaultDblClick and not Controller.IsSpecialRowFocused and Assigned(DataController.Follower.CurrentSubFollower) then + begin + lElement := DataController.Follower.CurrentSubFollower.Element; + lAutoForm := AutoFormProviderRegistry.FormForElement(lElement); + if assigned(lAutoForm) then + begin + result := true; + lAutoForm.Show; + end + end; + if not result then + begin + result := inherited DoCellDblClick(ACellViewInfo, AButton, AShift); + end; +end; + +function TcxGridBoldBandedTableView.DoEditing( + AItem: TcxCustomGridTableItem): Boolean; +begin + if Controller.IsSpecialRowFocused then + begin + result := inherited DoEditing(aItem); + end + else + begin + result := DataController.DoEditing(AItem) and inherited DoEditing(aItem); + end; +end; + +procedure TcxGridBoldBandedTableView.DoSelectionChanged; +begin + DataController.SelectionChanged; + inherited; +end; + +function TcxGridBoldBandedTableView.GetControllerClass: TcxCustomGridControllerClass; +begin + result := TcxGridBoldBandedTableController; +end; + +function TcxGridBoldBandedTableView.GetCurrentBoldObject: TBoldObject; +begin + result := DataController.CurrentBoldObject; +end; + +function TcxGridBoldBandedTableView.GetCurrentElement: TBoldElement; +begin + result := DataController.CurrentElement; +end; + +function TcxGridBoldBandedTableView.GetCurrentIndex: integer; +begin + result := DataController.CurrentIndex; +end; + +function TcxGridBoldBandedTableView.GetDataController: TcxGridBoldDataController; +begin + Result := TcxGridBoldDataController(FDataController); +end; + +function TcxGridBoldBandedTableView.GetDataControllerClass: TcxCustomDataControllerClass; +begin + Result := TcxGridBoldDataController; +end; + +function TcxGridBoldBandedTableView.GetItem(Index: Integer): IBoldAwareViewItem; +begin + result := inherited Items[Index] as IBoldAwareViewItem; +end; + +function TcxGridBoldBandedTableView.GetItemClass: TcxCustomGridTableItemClass; +begin + Result := TcxGridBoldBandedColumn; +end; + +function TcxGridBoldBandedTableView.GetItemCount: Integer; +begin + result := inherited ItemCount; +end; + +function TcxGridBoldBandedTableView.GetSelection: TBoldList; +begin + result := DataController.Selection; +end; + +function TcxGridBoldBandedTableView.GetViewInfoClass: TcxCustomGridViewInfoClass; +begin + Result := TcxGridBoldBandedTableViewInfo; +end; + +procedure TcxGridBoldBandedTableView.HookDragDrop; +begin + OnDragDrop := DataController.DoDragDrop; + OnStartDrag := DataController.DoStartDrag; + OnEndDrag := DataController.DoEndDrag; + OnDragOver := DataController.DoDragOver; +end; + +procedure TcxGridBoldBandedTableView.SetDataController( + Value: TcxGridBoldDataController); +begin + FDataController.Assign(Value); +end; + +function TcxGridBoldBandedTableView.ValidateComponent( + ComponentValidator: TBoldComponentValidator; NamePrefix: string): Boolean; +var + i: integer; + lContext: TBoldElementTypeInfo; + lBoldValidateableComponent: IBoldValidateableComponent; +begin + lContext := DataController.GetHandleStaticType; + result := ComponentValidator.ValidateExpressionInContext( + '', lContext, format('%s%s', [NamePrefix, Name])); // do not localize + if assigned(lContext) then + begin + for i := 0 to ItemCount - 1 do + begin + result := ComponentValidator.ValidateExpressionInContext( + Items[i].BoldProperties.Expression, + lContext, + format('%s%s.Column[%d]', [NamePrefix, Name, i]), + Items[i].BoldProperties.VariableList) and result; // do not localize + if Supports((DataController.GetItem(i) as TcxCustomGridTableItem).GetProperties, IBoldValidateableComponent, lBoldValidateableComponent) then + result := lBoldValidateableComponent.ValidateComponent(ComponentValidator, namePrefix) and result; + end; + end; +end; + +destructor TcxGridBoldTableView.Destroy; +begin + TBoldFollowerControllerAccess(DataController.fBoldColumnsProperties).FreePublisher; + inherited; +end; + +function TcxGridBoldTableView.GetCurrentBoldObject: TBoldObject; +begin + result := DataController.CurrentBoldObject; +end; + +function TcxGridBoldTableView.GetCurrentIndex: integer; +begin + result := DataController.CurrentIndex; +end; + +function TcxGridBoldTableView.GetCurrentElement: TBoldElement; +begin + result := DataController.CurrentElement; +end; + +function TcxGridBoldTableView.GetItem(Index: Integer): IBoldAwareViewItem; +begin + result := inherited Items[Index] as IBoldAwareViewItem; +end; + +function TcxGridBoldTableView.GetItemCount: Integer; +begin + result := inherited ItemCount; +end; + +function TcxGridBoldTableView.GetProperties(AProperties: TStrings): Boolean; +begin + with AProperties do + begin + Add('IncSearch'); + end; + Result := inherited GetProperties(AProperties); +end; + +procedure TcxGridBoldTableView.SetPropertyValue(const AName: string; + const AValue: Variant); +begin + if AName = 'IncSearch' then + OptionsBehavior.IncSearch := AValue + else + inherited; +end; + +procedure TcxGridBoldTableView.GetPropertyValue(const AName: string; + var AValue: Variant); +begin + if AName = 'IncSearch' then + AValue := OptionsBehavior.IncSearch + else + inherited; +end; + +{ TcxGridBoldCardView } + +constructor TcxGridBoldCardView.Create(AOwner: TComponent); +begin + inherited; +{$IFDEF DefaultDragMode} +// Drag drop is currently not supported in the CardView + +// DragMode := dmAutomatic; +// hookDragDrop; +{$ENDIF} +end; + +destructor TcxGridBoldCardView.Destroy; +begin + inherited; +end; + +function TcxGridBoldCardView.DoCellDblClick( + ACellViewInfo: TcxGridTableDataCellViewInfo; AButton: TMouseButton; + AShift: TShiftState): Boolean; +var + lAutoForm: TForm; + lElement: TBoldElement; +begin + result := false; + if DataController.BoldProperties.DefaultDblClick and Assigned(DataController.Follower.CurrentSubFollower) then + begin + lElement := DataController.Follower.CurrentSubFollower.Element; + lAutoForm := AutoFormProviderRegistry.FormForElement(lElement); + if assigned(lAutoForm) then + begin + result := true; + lAutoForm.Show; + end + end; + if not result then + begin + result := inherited DoCellDblClick(ACellViewInfo, AButton, AShift); + end; +end; + +function TcxGridBoldCardView.DoEditing( + AItem: TcxCustomGridTableItem): Boolean; +begin + result := DataController.DoEditing(AItem) and inherited DoEditing(aItem); +end; + +procedure TcxGridBoldCardView.DoSelectionChanged; +begin + DataController.SelectionChanged; + inherited; +end; + +function TcxGridBoldCardView.GetControllerClass: TcxCustomGridControllerClass; +begin + result := TcxGridBoldCardViewController; +end; + +function TcxGridBoldCardView.GetCurrentBoldObject: TBoldObject; +begin + result := DataController.CurrentBoldObject; +end; + +function TcxGridBoldCardView.GetCurrentElement: TBoldElement; +begin + result := DataController.CurrentElement; +end; + +function TcxGridBoldCardView.GetCurrentIndex: integer; +begin + result := DataController.CurrentIndex; +end; + +function TcxGridBoldCardView.GetDataController: TcxGridBoldDataController; +begin + Result := TcxGridBoldDataController(FDataController); +end; + +function TcxGridBoldCardView.GetDataControllerClass: TcxCustomDataControllerClass; +begin + Result := TcxGridBoldDataController; +end; + +function TcxGridBoldCardView.GetItem(Index: Integer): IBoldAwareViewItem; +begin + result := inherited Items[Index] as IBoldAwareViewItem; +end; + +function TcxGridBoldCardView.GetItemClass: TcxCustomGridTableItemClass; +begin + Result := TcxGridBoldCardViewRow; +end; + +function TcxGridBoldCardView.GetItemCount: Integer; +begin + result := inherited ItemCount; +end; + +function TcxGridBoldCardView.GetSelection: TBoldList; +begin + result := DataController.Selection; +end; + +function TcxGridBoldCardView.GetViewInfoClass: TcxCustomGridViewInfoClass; +begin + Result := TcxGridBoldCardViewViewInfo; +end; + +procedure TcxGridBoldCardView.SetDataController( + Value: TcxGridBoldDataController); +begin + FDataController.Assign(Value); +end; + +function TcxGridBoldCardView.ValidateComponent( + ComponentValidator: TBoldComponentValidator; NamePrefix: string): Boolean; +var + i: integer; + lContext: TBoldElementTypeInfo; + lBoldValidateableComponent: IBoldValidateableComponent; +begin + lContext := DataController.GetHandleStaticType; + result := ComponentValidator.ValidateExpressionInContext( + '', lContext, format('%s%s', [NamePrefix, Name])); // do not localize + if assigned(lContext) then + begin + for i := 0 to ItemCount - 1 do + begin + result := ComponentValidator.ValidateExpressionInContext( + Items[i].BoldProperties.Expression, + lContext, + format('%s%s.Column[%d]', [NamePrefix, Name, i]), + Items[i].BoldProperties.VariableList) and result; // do not localize + if Supports((DataController.GetItem(i) as TcxCustomGridTableItem).GetProperties, IBoldValidateableComponent, lBoldValidateableComponent) then + result := lBoldValidateableComponent.ValidateComponent(ComponentValidator, namePrefix) and result; + end; + end; +end; + +{ TcxBoldCustomDataProvider } + +function TcxBoldCustomDataProvider.GetValue(ARecordIndex: Integer; AField: TcxCustomDataField): Variant; +var + ARecordHandle: TcxDataRecordHandle; + AItemHandle: TcxDataItemHandle; + lBoldDataSource: TcxBoldDataSource; +begin + Result := Null; + lBoldDataSource := CustomDataSource as TcxBoldDataSource; + if Assigned(lBoldDataSource) then + begin + lBoldDataSource.CurrentProvider := Self; + ARecordHandle := TcxDataRecordHandle(ARecordIndex); + AItemHandle := lBoldDataSource.GetItemHandle(AField.Index); + Result := lBoldDataSource.GetValue(ARecordHandle, AItemHandle); + end; +end; + +function TcxBoldCustomDataProvider.IsActiveDataSet: Boolean; +begin + result := Assigned(CustomDataSource); +end; + +function TcxBoldCustomDataProvider.SetEditValue(ARecordIndex: Integer; + AField: TcxCustomDataField; const AValue: Variant; + AEditValueSource: TcxDataEditValueSource): Boolean; +begin + DataController.SetValue(ARecordIndex, AField.Index, AValue); + SetModified; + Result := True; +end; + +procedure TcxBoldCustomDataProvider.SetValue(ARecordIndex: Integer; AField: TcxCustomDataField; const Value: Variant); +var + ARecordHandle: TcxDataRecordHandle; + AItemHandle: TcxDataItemHandle; + lBoldDataSource: TcxBoldDataSource; +begin + lBoldDataSource := CustomDataSource as TcxBoldDataSource; + if Assigned(lBoldDataSource) then + begin + lBoldDataSource.CurrentProvider := Self; + ARecordHandle := TcxDataRecordHandle(ARecordIndex); + AItemHandle := lBoldDataSource.GetItemHandle(AField.Index); + lBoldDataSource.SetValue(ARecordHandle, AItemHandle, Value); + end; +end; + +function TcxBoldCustomDataProvider.CanDelete: Boolean; +var + lcxBoldDataController: TcxBoldDataController; +begin + lcxBoldDataController := DataController as TcxBoldDataController; + result := Assigned(lcxBoldDataController) and Assigned(lcxBoldDataController.BoldHandle); + if result then + begin + if Assigned(lcxBoldDataController.fOnDelete) and Assigned(lcxBoldDataController.fCanDelete) then + begin + lcxBoldDataController.fCanDelete(lcxBoldDataController, result) + end + else + result := Assigned(lcxBoldDataController.BoldHandle.MutableList); +{ + for I := 0 to lcxBoldDataController.Selection.Count - 1 do + if not lcxBoldDataController.BoldHandle.MutableList.CanRemove( lcxBoldDataController.Selection[i] ) then + begin + result := false; + exit; + end; +} + end; +end; + +function TcxBoldCustomDataProvider.CanInsert: Boolean; +var + lcxBoldDataController: TcxBoldDataController; +begin + lcxBoldDataController := DataController as TcxBoldDataController; + result := Assigned(lcxBoldDataController) and Assigned(lcxBoldDataController.BoldHandle); + if result then + begin + if Assigned(lcxBoldDataController.fOnInsert) and Assigned(lcxBoldDataController.fCanInsert) then + begin + lcxBoldDataController.fCanInsert(lcxBoldDataController, result) + end + else + if Assigned(lcxBoldDataController.fCanInsert) then + lcxBoldDataController.fCanInsert(lcxBoldDataController, result); + result := result and Assigned(lcxBoldDataController.BoldHandle.MutableList) and lcxBoldDataController.BoldHandle.MutableList.CanCreateNew; + end; +end; + +type TcxCustomDataSourceAccess = class(TcxCustomDataSource); + +procedure TcxBoldCustomDataProvider.DeleteRecords(AList: TList); +var + i, {j,} ARecordIndex: Integer; + lListToDelete: TBoldObjectList; +// lOriginalList: TBoldObjectList; + lMutableList: TBoldObjectList; + lObjectToDelete: TBoldObject; + lFollower: TBoldFollower; +begin + DataController.BeginFullUpdate; + lListToDelete := TBoldObjectList.Create; + inc(TcxBoldDataController(DataController).fSkipMakeCellUptoDate); + try +// lOriginalList := TcxBoldDataController(DataController).Follower.Element as TBoldObjectList; + for I := AList.Count - 1 downto 0 do + begin + ARecordIndex := Integer(AList[I]); + with DataController.DataControllerInfo.Selection do + if (DataController.DataControllerInfo.Selection.Count > 1) and IsRecordSelected(ARecordIndex) then + DataController.DataControllerInfo.Selection.Delete(FindByRecordIndex(ARecordIndex)); + + lFollower := TcxBoldDataController(DataController).Follower.Subfollowers[ARecordIndex]; + lObjectToDelete := lFollower.element as TBoldObject; + if Assigned(lObjectToDelete) and not lObjectToDelete.BoldObjectIsDeleted then + lListToDelete.Add(lObjectToDelete); + end; + lMutableList := TcxBoldDataController(DataController).BoldHandle.MutableObjectList; + if Assigned(lMutableList.BoldRoleRTInfo) and (lMutableList.BoldRoleRTInfo.RoleType = rtLinkRole) then + begin + for I := lListToDelete.Count - 1 downto 0 do + begin + if lListToDelete[i].BoldObjectExists then // not already deleted + lListToDelete[i].Delete; + end; + end + else + lMutableList.RemoveList(lListToDelete); + if TcxCustomDataControllerAccess(DataController).FInDeleteSelection then + DataController.ClearSelection; + TcxGridBoldDataController(DataController).DataHasChanged := true; + finally + lListToDelete.free; + DataController.EndFullUpdate; + TcxCustomDataControllerAccess(DataController).CheckNearestFocusRow; + dec(TcxBoldDataController(DataController).fSkipMakeCellUptoDate); + end; +end; + +{ TcxGridBoldTableController } + +procedure TcxGridBoldTableController.DoKeyDown(var Key: Word; + Shift: TShiftState); +var + lColumnAutoWidth: boolean; + lVisibleCount: integer; +begin + if (Key = VK_DOWN) or (Key = VK_UP) or (Key = VK_NEXT) or (Key = VK_PRIOR) then + (DataController as TcxBoldDataController).BeginDelayScrollUpdate; + if (key = VK_ADD) and (shift = [ssCtrl]) then + begin + GridView.BeginUpdate; + try + GridView.OptionsView.ColumnAutoWidth := not GridView.OptionsView.ColumnAutoWidth; + lColumnAutoWidth := GridView.OptionsView.ColumnAutoWidth; + if not lColumnAutoWidth then + begin + lVisibleCount := GridView.ViewInfo.VisibleRecordCount; + if lVisibleCount <> GridView.OptionsBehavior.BestFitMaxRecordCount then + GridView.OptionsBehavior.BestFitMaxRecordCount := lVisibleCount; + ViewInfo.GridView.ApplyBestFit(nil, true, true); + if lColumnAutoWidth then + GridView.OptionsView.ColumnAutoWidth := true; + end; + finally + GridView.EndUpdate; + end; + end; + inherited; +end; +{ +procedure TcxGridBoldTableController.FocusedRecordChanged(APrevFocusedRecordIndex, AFocusedRecordIndex, + APrevFocusedDataRecordIndex, AFocusedDataRecordIndex: Integer; + ANewItemRecordFocusingChanged: Boolean); +begin +// CodeSite.Send('FocusedRecordChanged:' + IntToStr(AFocusedRecordIndex)); + inherited; +end; +} +function TcxGridBoldTableController.GetEditingControllerClass: TcxGridEditingControllerClass; +begin + result := TcxGridBoldEditingController; +end; + +procedure TcxGridBoldTableController.KeyDown(var Key: Word; + Shift: TShiftState); +var + lIndex: integer; + lBoldHandle: TBoldAbstractListHandle; + lBoldList: TBoldList; + lHandled: boolean; + lAllowed: boolean; + lcxBoldDataController: TcxBoldDataController; +begin + lcxBoldDataController := (DataController as TcxBoldDataController); + if DataController.FilteredRecordCount <> TcxCustomDataControllerInfoAccess(DataController.DataControllerInfo).RecordList.Count then + begin + DataController.DataControllerInfo.Refresh; + Assert(DataController.FilteredRecordCount = TcxCustomDataControllerInfoAccess(DataController.DataControllerInfo).RecordList.Count, Format('DataController.RecordCount = %d <> DataController.DataControllerInfo.GetRowCount = %d', [DataController.RecordCount, TcxCustomDataControllerInfoAccess(DataController.DataControllerInfo).RecordList.Count])); + end; + if not BlockRecordKeyboardHandling and (FocusedRecord <> nil) then + TcxCustomGridRecordAccess(FocusedRecord).KeyDown(Key, Shift); + case Key of + VK_INSERT: + if (Shift = []) then + begin + Key := 0; + lHandled := false; + if Assigned(lcxBoldDataController.fOnInsert) then + begin + lAllowed := CanInsert(true); + if lAllowed then + lcxBoldDataController.fOnInsert(lcxBoldDataController); + lHandled := true; + end + else + lAllowed := Assigned(lcxBoldDataController.BoldHandle) and Assigned(lcxBoldDataController.BoldHandle.MutableList); + if not lHandled and lAllowed then + begin + lBoldHandle := TcxBoldDataController(DataController).BoldHandle; + lBoldList := lBoldHandle.MutableList; + if Assigned(lBoldList.BoldMemberRTInfo) and TBoldRoleRTInfo(lBoldList.BoldMemberRTInfo).IsOrdered and ((DataController as TcxBoldDataController).Follower.CurrentIndex <> -1) then + begin + lIndex := TcxBoldDataController(DataController).Follower.CurrentIndex; + lBoldList.InsertNew(lIndex); + end + else + begin + lIndex := lBoldList.IndexOf(lBoldList.AddNew); + end; + TBoldQueueable.DisplayAll; + (DataController as TcxBoldDataController).Follower.CurrentIndex := lIndex; + end; + end + else + if (Shift = [ssCtrl]) and not IsEditing then + GridView.CopyToClipboard(False); + VK_DELETE: + if ((Shift = []) or (Shift = [ssCtrl])) and (SelectedRecordCount > 0) then + begin + Key := 0; + lHandled := false; + lAllowed := CanDelete(true); + if Assigned(lcxBoldDataController.fOnDelete) then + begin + if lAllowed then + lcxBoldDataController.fOnDelete(lcxBoldDataController); + lHandled := true; + end; + if not lHandled and lAllowed then + begin + DeleteSelection; + end; + TBoldQueueable.DisplayAll; + end; + VK_HOME: + begin + if ([ssCtrl] = Shift) {or not FocusedRecordHasCells(True)} then + begin + GoToFirst(True) + end + else + inherited; //FocusNextItem(-1, True, False, False, true); + end; + VK_END: + begin + if ([ssCtrl] = Shift) {or not FocusedRecordHasCells(True)} then + begin + GoToLast(False, True) + end + else + inherited; // FocusNextItem(-1, False, True, False, true) + end; + else + inherited + end; +end; + +procedure TcxGridBoldTableController.KeyUp(var Key: Word; Shift: TShiftState); +{$IFDEF CenterResultOnIncSearch} +var + AVisibleRecordCount: Integer; +{$ENDIF} +begin + inherited; + with TcxBoldDataController(DataController) do + EndDelayScrollUpdate; +{$IFDEF CenterResultOnIncSearch} + if (FocusedRecord <> nil) and IsIncSearching then + begin + AVisibleRecordCount := ViewInfo.VisibleRecordCount; + GridView.Controller.TopRowIndex := GridView.Controller.FocusedRecordIndex - (AVisibleRecordCount div 2); + end; +{$ENDIF} +end; + +procedure TcxBoldGridSite.WndProc(var Message: TMessage); +var + vDataController: TcxBoldDataController; +begin + try + if Controller is TcxGridTableController then + begin + vDataController := TcxGridTableControllerAccess(Controller).DataController as TcxBoldDataController; + if Assigned(vDataController) and (vDataController.LockCount = 0) then + begin + Case Message.Msg of WM_PAINT, WM_SETFOCUS, WM_KILLFOCUS, WM_WINDOWPOSCHANGING, WM_MOVE, WM_MOUSEMOVE: + if Assigned(vDataController.CustomDataSource) and vDataController.MainFollowerNeedsDisplay then + vDataController.DisplayFollowers; + end; + end; + end; + finally + inherited; + end; +end; + +{ TcxGridBoldBandedTableController } + +procedure TcxGridBoldBandedTableController.DoKeyDown(var Key: Word; + Shift: TShiftState); +var + lColumnAutoWidth: boolean; + lVisibleCount: integer; +begin + if (Key = VK_DOWN) or (Key = VK_UP) or (Key = VK_NEXT) or (Key = VK_PRIOR) then + (DataController as TcxBoldDataController).BeginDelayScrollUpdate; + if (key = VK_ADD) and (shift = [ssCtrl]) then + begin + GridView.BeginUpdate; + try + GridView.OptionsView.ColumnAutoWidth := not GridView.OptionsView.ColumnAutoWidth; + lColumnAutoWidth := GridView.OptionsView.ColumnAutoWidth; + if not lColumnAutoWidth then + begin + lVisibleCount := GridView.ViewInfo.VisibleRecordCount; + if lVisibleCount <> GridView.OptionsBehavior.BestFitMaxRecordCount then + GridView.OptionsBehavior.BestFitMaxRecordCount := lVisibleCount; + ViewInfo.GridView.ApplyBestFit(nil, true, true); + if lColumnAutoWidth then + GridView.OptionsView.ColumnAutoWidth := true; + end; + finally + GridView.EndUpdate; + end; + end; + inherited; +end; + +function TcxGridBoldBandedTableController.GetEditingControllerClass: TcxGridEditingControllerClass; +begin + result := TcxGridBoldEditingController; +end; + +procedure TcxGridBoldBandedTableController.KeyDown(var Key: Word; + Shift: TShiftState); +var + lIndex: integer; + lBoldHandle: TBoldAbstractListHandle; + lBoldList: TBoldList; + lHandled: boolean; + lAllowed: boolean; + lcxBoldDataController: TcxBoldDataController; +begin + lcxBoldDataController := (DataController as TcxBoldDataController); + if DataController.FilteredRecordCount <> TcxCustomDataControllerInfoAccess(DataController.DataControllerInfo).RecordList.Count then + begin + DataController.DataControllerInfo.Refresh; + Assert(DataController.FilteredRecordCount = TcxCustomDataControllerInfoAccess(DataController.DataControllerInfo).RecordList.Count, Format('DataController.FilteredRecordCount = %d <> DataController.DataControllerInfo.GetRowCount = %d', [DataController.FilteredRecordCount, TcxCustomDataControllerInfoAccess(DataController.DataControllerInfo).RecordList.Count])); + end; + if not BlockRecordKeyboardHandling and (FocusedRecord <> nil) then + TcxCustomGridRecordAccess(FocusedRecord).KeyDown(Key, Shift); + case Key of + VK_INSERT: + if (Shift = []) then + begin + Key := 0; + lHandled := false; + if Assigned(lcxBoldDataController.fOnInsert) then + begin + lAllowed := CanInsert(true); + if lAllowed then + lcxBoldDataController.fOnInsert(lcxBoldDataController); + lHandled := true; + end + else + lAllowed := Assigned(lcxBoldDataController.BoldHandle) and Assigned(lcxBoldDataController.BoldHandle.MutableList); + if not lHandled and lAllowed then + begin + lBoldHandle := TcxBoldDataController(DataController).BoldHandle; + lBoldList := lBoldHandle.MutableList; + if Assigned(lBoldList.BoldMemberRTInfo) and TBoldRoleRTInfo(lBoldList.BoldMemberRTInfo).IsOrdered and ((DataController as TcxBoldDataController).Follower.CurrentIndex <> -1) then + begin + lIndex := TcxBoldDataController(DataController).Follower.CurrentIndex; + lBoldList.InsertNew(lIndex); + end + else + begin + lIndex := lBoldList.IndexOf(lBoldList.AddNew); + end; + TBoldQueueable.DisplayAll; + (DataController as TcxBoldDataController).Follower.CurrentIndex := lIndex; + end; + end + else + if (Shift = [ssCtrl]) and not IsEditing then + GridView.CopyToClipboard(False); + VK_DELETE: + if ((Shift = []) or (Shift = [ssCtrl])) and (SelectedRecordCount > 0) then + begin + Key := 0; + lHandled := false; + lAllowed := true; + if Assigned(lcxBoldDataController.fOnDelete) then + begin + lAllowed := CanDelete(true); + if lAllowed then + lcxBoldDataController.fOnDelete(lcxBoldDataController); + lHandled := true; + end; + if not lHandled and lAllowed then + begin + DeleteSelection; + end; + TBoldQueueable.DisplayAll; + end; + VK_HOME: + begin + if ([ssCtrl] = Shift) {or not FocusedRecordHasCells(True)} then + begin + GoToFirst(True) + end + else + inherited; //FocusNextItem(-1, True, False, False, true); + end; + VK_END: + begin + if ([ssCtrl] = Shift) {or not FocusedRecordHasCells(True)} then + begin + GoToLast(False, True) + end + else + inherited; // FocusNextItem(-1, False, True, False, true) + end; + else + inherited + end; +end; + +procedure TcxGridBoldBandedTableController.KeyUp(var Key: Word; + Shift: TShiftState); +{$IFDEF CenterResultOnIncSearch} +var + AVisibleRecordCount: Integer; +{$ENDIF} +begin + inherited; + with TcxBoldDataController(DataController) do + EndDelayScrollUpdate; +{$IFDEF CenterResultOnIncSearch} + if (FocusedRecord <> nil) and IsIncSearching then + begin + AVisibleRecordCount := ViewInfo.VisibleRecordCount; + GridView.Controller.TopRowIndex := GridView.Controller.FocusedRecordIndex - (AVisibleRecordCount div 2); + end; +{$ENDIF} +end; + +{ TcxBoldDataControllerSearch } + +function TcxBoldDataControllerSearch.Locate(AItemIndex: Integer; const ASubText: string; AIsAnywhere: Boolean = False {$IFDEF BOLD_DELPHI25_OR_LATER}; ASyncSelection: Boolean = True{$ENDIF}): Boolean; +begin + with DataController as TcxBoldDataController do + AdjustActiveRange(BoldList, AItemIndex); + result := inherited Locate(AItemIndex, ASubText {$IFDEF BOLD_DELPHI25_OR_LATER}, AIsAnywhere, ASyncSelection{$ENDIF}); +end; + +function TcxBoldDataControllerSearch.LocateNext(AForward: Boolean; AIsAnywhere: Boolean = False {$IFDEF BOLD_DELPHI25_OR_LATER}; ASyncSelection: Boolean = True{$ENDIF}): Boolean; +begin + (DataController as TcxBoldDataController).AdjustActiveRange(); + result := inherited LocateNext(AForward {$IFDEF BOLD_DELPHI25_OR_LATER}, AIsAnywhere, ASyncSelection{$ENDIF}); +end; + +{ TcxGridBoldCardViewRow } + +function TcxGridBoldCardViewRow.CalculateBestFitWidth: Integer; +begin + GridView.OptionsBehavior.BestFitMaxRecordCount := GridView.ViewInfo.VisibleRecordCount; + result := inherited CalculateBestFitWidth; +end; + +destructor TcxGridBoldCardViewRow.Destroy; +begin + DataBinding.Remove; + inherited; +end; + +function TcxGridBoldCardViewRow.GetDataBinding: TcxGridItemBoldDataBinding; +begin + Result := TcxGridItemBoldDataBinding(inherited DataBinding); +end; + +procedure TcxGridBoldCardViewRow.SetDataBinding( + Value: TcxGridItemBoldDataBinding); +begin + inherited DataBinding := Value; +end; + +procedure TcxGridBoldCardViewRow.VisibleChanged; +begin + inherited; +// if Visible and not IsLoading then +// (DataController as TcxGridBoldDataController).AdjustActiveRange(); +end; + +{ TcxGridBoldEditingController } + +procedure TcxGridBoldEditingController.DoEditKeyDown(var Key: Word; + Shift: TShiftState); +var + lWasEditing: boolean; +// lController: TcxGridTableController; + lHideFilterRowOnEnter: boolean; +begin +// lController := nil; + lHideFilterRowOnEnter := false; +// if Controller is TcxGridTableController then + begin +// lController := Controller as TcxGridTableController; + lWasEditing := (EditingItem <> nil) and EditingItem.Editing; + if lWasEditing and (Key = VK_ESCAPE) then + begin + Key := VK_ESCAPE; + end + else + if Controller.IsFilterRowFocused then + begin + if (Key = VK_RETURN) and lWasEditing then + begin + lHideFilterRowOnEnter := true; + end; + end; + end; + inherited; + if lHideFilterRowOnEnter and (EditingItem = nil) and (GridView.DataController.FilteredRecordCount > 0) then + Controller.GridView.FilterRow.Visible := false +end; + +procedure TcxGridBoldEditingController.EditChanged(Sender: TObject); +var + lEdit: TcxCustomEdit; + lFollower: TBoldFollower; + lDataController: TcxGridBoldDataController; + lIcxBoldEditProperties: IcxBoldEditProperties; + lDone: Boolean; +begin +// inherited; // moved to the end of the method, coz it fires OnChange event and we don't want that to happen before we make the change +{ + Here we basically ignore ApplyPolicy. We want to mark follower dirty as soon as possible (ie here) + But we don't want to apply changes to ObjectSpace yet as changes may cause reload of data, + especially if the view is grouped/sorted and user is editing a grouped/sorted column. + So if this happens editing loses focus and view reloads data, so we want to avoid this. +} + if (EditingItem <> nil) {EditingItem is TcxGridBoldColumn} and not Controller.IsSpecialRowFocused then + begin + lEdit := Sender as TcxCustomEdit; + lDataController := EditingItem.DataBinding.DataController as TcxGridBoldDataController; + lFollower := lDataController.Follower.SubFollowers[lDataController.FocusedRecordIndex]; + if lFollower.Active then + begin + lFollower := lFollower.SubFollowers[Integer(EditingItem.DataBinding.Data)]; + lDone := false; + Assert(EditingItem.GetProperties <> nil); + if Supports(EditingItem.GetProperties, IcxBoldEditProperties, lIcxBoldEditProperties) then + begin + lIcxBoldEditProperties.SetStoredValue(Null, lDataController.BoldHandle, lEdit, lFollower, lDone); + end; + if not lDone then + begin + lDone := (lFollower.Controller as TBoldVariantFollowerController).MayHaveChanged(Edit.EditingValue, lFollower); + end; + if lDone then + begin + lDataController.fInternalChange := true; + try + TBoldQueueable.DisplayAll; + finally + lDataController.fInternalChange := false; + inherited; + end; + end; + end; + end + else + inherited; +end; + +procedure TcxGridBoldEditingController.EditExit(Sender: TObject); +begin +// self.EditChanged(Sender); + inherited; +end; + +procedure TcxGridBoldEditingController.HideEdit(Accept: Boolean); +var + lcxBoldDataController: TcxBoldDataController; + lFollower: TBoldFollower; +begin + if not Accept and Assigned(Edit) and Edit.ModifiedAfterEnter then + begin + lcxBoldDataController := EditingItem.DataBinding.DataController as TcxBoldDataController; + if (lcxBoldDataController.FocusedRecordIndex <> -1) then + begin + lFollower := lcxBoldDataController.Follower.SubFollowers[lcxBoldDataController.FocusedRecordIndex]; + lFollower := lFollower.SubFollowers[Integer(EditingItem.DataBinding.Data)]; + begin + lFollower.DiscardChange; + end; + end; + end; +// if Assigned(Edit) and Edit.ModifiedAfterEnter then +// self.EditChanged(Edit); + inherited; +end; + +{ TcxGridBoldBandedColumn } + +function TcxGridBoldBandedColumn.CalculateBestFitWidth: Integer; +begin + GridView.OptionsBehavior.BestFitMaxRecordCount := GridView.ViewInfo.VisibleRecordCount; + result := inherited CalculateBestFitWidth; +end; + +destructor TcxGridBoldBandedColumn.Destroy; +begin + DataBinding.Remove; + inherited; +end; + +function TcxGridBoldBandedColumn.GetDataBinding: TcxGridItemBoldDataBinding; +begin + Result := TcxGridItemBoldDataBinding(inherited DataBinding); +end; + +procedure TcxGridBoldBandedColumn.SetDataBinding( + Value: TcxGridItemBoldDataBinding); +begin + inherited DataBinding := Value; +end; + +procedure TcxGridBoldBandedColumn.VisibleChanged; +begin + inherited; +// if Visible and not IsLoading then +// (DataController as TcxGridBoldDataController).AdjustActiveRange(); +end; + +{ TcxGridBoldChartDataController } +(* +procedure TcxGridBoldChartDataController.AssignData( + ADataController: TcxCustomDataController); +begin +end; + +procedure TcxGridBoldChartDataController.CreateAllItems( + AMissingItemsOnly: Boolean); +begin +end; + +procedure TcxGridBoldChartDataController.DeleteAllItems; +begin +end; + +function TcxGridBoldChartDataController.GetChartItem( + AItemClass: TcxGridChartItemClass; AIndex: Integer): TcxGridChartItem; +var + AFields: TList; +begin + AFields := TList.Create; + try + GetValidValueFields(AItemClass, AFields); +// Result := GridView.FindItemByFieldName(AItemClass, TField(AFields[AIndex]).FieldName); + finally + AFields.Free; + end; +end; + +procedure TcxGridBoldChartDataController.GetFakeComponentLinks(AList: TList); +begin + if (BoldHandle <> nil) and (BoldHandle.Owner <> GridView.Component) and + (AList.IndexOf(BoldHandle.Owner) = -1) then + AList.Add(BoldHandle.Owner); +end; + +procedure TcxGridBoldChartDataController.GetItemCaptions( + AItemClass: TcxGridChartItemClass; ACaptions: TStringList); +var + AFields: TList; + I: Integer; +begin + AFields := TList.Create; + try + GetValidValueFields(AItemClass, AFields); +// for I := 0 to AFields.Count - 1 do +// ACaptions.Add(TField(AFields[I]).DisplayName); + finally + AFields.Free; + end; +end; + +procedure TcxGridBoldChartDataController.GetValidValueFields( + AItemClass: TcxGridChartItemClass; AFields: TList); +var + I: Integer; +// AField: TField; +begin +{ + if DataSet = nil then Exit; + for I := 0 to DataSet.FieldCount - 1 do + begin + AField := DataSet.Fields[I]; + if not AItemClass.IsValue or + IsValueTypeClassValid(GetValueTypeClassByField(AField)) then + AFields.Add(AField); + end; + AFields.Sort(CompareFields); +} +end; + +function TcxGridBoldChartDataController.HasAllItems: Boolean; +begin + Result := True; +end; + +procedure TcxGridBoldChartDataController.InitItem(AItem: TcxGridChartItem; + AIndex: Integer); +var + AFields: TList; +begin + AFields := TList.Create; + try + GetValidValueFields(TcxGridChartItemClass(AItem.ClassType), AFields); +// TcxGridBoldChartItemDataBinding(AItem.DataBinding).FieldName := TField(AFields[AIndex]).FieldName; + finally + AFields.Free; + end; +end; + +function TcxGridBoldChartDataController.IsDataChangeable: Boolean; +begin + Result := False; +end; + +function TcxGridBoldChartDataController.SupportsCreateAllItems: Boolean; +begin + Result := False; +end; + +{ TcxGridBoldChartItemDataBinding } + +procedure TcxGridBoldChartItemDataBinding.Assign(Source: TPersistent); +begin +// if Source is TcxGridBoldChartItemDataBinding then +// FieldName := TcxGridBoldChartItemDataBinding(Source).FieldName; + inherited; +end; + +constructor TcxGridBoldChartItemDataBinding.Create(AGridView: TcxGridChartView; + AIsValue: Boolean; ADefaultValueTypeClass: TcxValueTypeClass); +begin + inherited Create(AGridView, AIsValue, ADefaultValueTypeClass); + fBoldProperties := TBoldVariantFollowerController.Create(AGridView.Component); + +// DataController.fBoldColumnsProperties.Add(fBoldProperties); +// fBoldProperties.OnGetContextType := DataController.GetHandleStaticType; +// FBoldProperties.AfterMakeUptoDate := DataController._AfterMakeCellUptoDate; +end; + +destructor TcxGridBoldChartItemDataBinding.Destroy; +begin + FreeAndNil(FBoldProperties); + inherited; +end; + +function TcxGridBoldChartItemDataBinding.GetDataController: TcxGridBoldChartDataController; +begin + Result := TcxGridBoldChartDataController(inherited DataController); +end; + +procedure TcxGridBoldChartItemDataBinding.SetBoldProperties( + Value: TBoldVariantFollowerController); +begin + if Assigned(Value) then + fBoldProperties.Assign(Value); +end; + +{ TcxGridBoldChartCategories } + +function TcxGridBoldChartCategories.GetDataBinding: TcxGridBoldChartItemDataBinding; +begin + Result := TcxGridBoldChartItemDataBinding(inherited DataBinding); +end; + +procedure TcxGridBoldChartCategories.SetDataBinding( + Value: TcxGridBoldChartItemDataBinding); +begin + inherited DataBinding := Value; +end; + +{ TcxGridBoldChartDataGroup } + +function TcxGridBoldChartDataGroup.GetDataBinding: TcxGridBoldChartItemDataBinding; +begin + Result := TcxGridBoldChartItemDataBinding(inherited DataBinding); +end; + +procedure TcxGridBoldChartDataGroup.SetDataBinding( + Value: TcxGridBoldChartItemDataBinding); +begin + inherited DataBinding := Value; +end; + +{ TcxGridBoldChartSeries } + +function TcxGridBoldChartSeries.GetDataBinding: TcxGridBoldChartItemDataBinding; +begin + Result := TcxGridBoldChartItemDataBinding(inherited DataBinding); +end; + +procedure TcxGridBoldChartSeries.SetDataBinding( + Value: TcxGridBoldChartItemDataBinding); +begin + inherited DataBinding := Value; +end; + +{ TcxBoldGridChartView } + +procedure TcxBoldGridChartView.ClearItems; +begin + ClearSeries; +end; + +constructor TcxBoldGridChartView.Create(AOwner: TComponent); +begin + inherited; +end; + +function TcxBoldGridChartView.CreateDataGroup: TcxGridBoldChartDataGroup; +begin + Result := TcxGridBoldChartDataGroup(inherited CreateDataGroup); +end; + +function TcxBoldGridChartView.CreateSeries: TcxGridBoldChartSeries; +begin + Result := TcxGridBoldChartSeries(inherited CreateSeries); +end; + +destructor TcxBoldGridChartView.Destroy; +begin + inherited; +end; + +function TcxBoldGridChartView.FindDataGroupByFieldName( + const AFieldName: string): TcxGridBoldChartDataGroup; +begin + Result := TcxGridBoldChartDataGroup(FindItemByFieldName(GetDataGroupClass, AFieldName)); +end; + +function TcxBoldGridChartView.FindItemByFieldName( + AItemClass: TcxGridChartItemClass; + const AFieldName: string): TcxGridChartItem; +var + AItems: TList; + I: Integer; +begin + AItems := GetItemList(AItemClass); + for I := 0 to AItems.Count - 1 do + begin + Result := TcxGridChartItem(AItems[I]); +// if SameText(TcxGridBoldChartItemDataBinding(Result.DataBinding).FieldName, AFieldName) then Exit; + end; + Result := nil; +end; + +function TcxBoldGridChartView.FindSeriesByFieldName( + const AFieldName: string): TcxGridBoldChartSeries; +begin + Result := TcxGridBoldChartSeries(FindItemByFieldName(GetSeriesClass, AFieldName)); +end; + +function TcxBoldGridChartView.GetCategories: TcxGridBoldChartCategories; +begin + Result := TcxGridBoldChartCategories(inherited Categories); +end; + +function TcxBoldGridChartView.GetCategoriesClass: TcxGridChartCategoriesClass; +begin + Result := TcxGridBoldChartCategories; +end; + +function TcxBoldGridChartView.GetDataController: TcxGridBoldChartDataController; +begin + Result := TcxGridBoldChartDataController(inherited DataController); +end; + +function TcxBoldGridChartView.GetDataControllerClass: TcxCustomDataControllerClass; +begin + Result := TcxGridBoldChartDataController; +end; + +function TcxBoldGridChartView.GetDataGroup( + Index: Integer): TcxGridBoldChartDataGroup; +begin + Result := TcxGridBoldChartDataGroup(inherited DataGroups[Index]); +end; + +function TcxBoldGridChartView.GetDataGroupClass: TcxGridChartDataGroupClass; +begin + Result := TcxGridBoldChartDataGroup; +end; + +function TcxBoldGridChartView.GetItem(Index: Integer): IBoldAwareViewItem; +begin + result := inherited Items[Index] as IBoldAwareViewItem; +end; + +function TcxBoldGridChartView.GetItemCount: Integer; +begin + result := inherited SeriesCount; +end; + +function TcxBoldGridChartView.GetItemDataBindingClass: TcxGridChartItemDataBindingClass; +begin + Result := TcxGridBoldChartItemDataBinding; +end; + +function TcxBoldGridChartView.GetSelection: TBoldList; +begin + result := fSelection; +end; + +function TcxBoldGridChartView.GetSeries(Index: Integer): TcxGridBoldChartSeries; +begin + Result := TcxGridBoldChartSeries(inherited Series[Index]); +end; + +function TcxBoldGridChartView.GetSeriesClass: TcxGridChartSeriesClass; +begin + Result := TcxGridBoldChartSeries; +end; + +procedure TcxBoldGridChartView.SetCategories(Value: TcxGridBoldChartCategories); +begin + inherited Categories := Value; +end; + +procedure TcxBoldGridChartView.SetDataController( + Value: TcxGridBoldChartDataController); +begin + FDataController.Assign(Value); +end; + +procedure TcxBoldGridChartView.SetDataGroup(Index: Integer; + Value: TcxGridBoldChartDataGroup); +begin + inherited DataGroups[Index] := Value; +end; + +procedure TcxBoldGridChartView.SetSeries(Index: Integer; + Value: TcxGridBoldChartSeries); +begin + inherited Series[Index] := Value; +end; + +function TcxBoldGridChartView.ValidateComponent( + ComponentValidator: TBoldComponentValidator; NamePrefix: String): Boolean; +var + i: integer; + lContext: TBoldElementTypeInfo; +begin + lContext := DataController.GetHandleStaticType; + result := ComponentValidator.ValidateExpressionInContext( + '', lContext, format('%s%s', [NamePrefix, Name])); // do not localize + if assigned(lContext) then + for i := 0 to ItemCount - 1 do + result := ComponentValidator.ValidateExpressionInContext( + Items[i].DataBinding.BoldProperties.Expression, + lContext, + format('%s%s.Column[%d]', [NamePrefix, Name, i])) and result; // do not localize +end; +*) + +{ TcxGridBoldCardViewController } + +function TcxGridBoldCardViewController.GetEditingControllerClass: TcxGridEditingControllerClass; +begin + result := TcxGridBoldCardEditingController; //TcxGridBoldEditingController; +end; + +{ TcxGridBoldCardEditingController } + +procedure TcxGridBoldCardEditingController.EditChanged(Sender: TObject); +var + lEdit: TcxCustomEdit; + lFollower: TBoldFollower; + lDataController: TcxGridBoldDataController; + lIcxBoldEditProperties: IcxBoldEditProperties; + lDone: Boolean; +begin +// inherited; // moved to the end of the method, coz it fires OnChange event and we don't want that to happen before we make the change +{ + Here we basically ignore ApplyPolicy. We want to mark follower dirty as soon as possible (ie here) + But we don't want to apply changes to ObjectSpace yet as changes may cause reload of data, + especially if the view is grouped/sorted and user is editing a grouped/sorted column. + So if this happens editing loses focus and view reloads data, so we want to avoid this. +} + if EditingItem is TcxGridBoldCardViewRow then + begin + lEdit := Sender as TcxCustomEdit; + lDataController := EditingItem.DataBinding.DataController as TcxGridBoldDataController; + lFollower := lDataController.Follower.SubFollowers[lDataController.FocusedRecordIndex]; + if lFollower.Active then + begin + lFollower := lFollower.SubFollowers[Integer(EditingItem.DataBinding.Data)]; + lDone := false; + Assert(EditingItem.GetProperties <> nil); + if Supports(EditingItem.GetProperties, IcxBoldEditProperties, lIcxBoldEditProperties) then + begin + lIcxBoldEditProperties.SetStoredValue(Null, lDataController.BoldHandle, lEdit, lFollower, lDone); + end; + if not lDone then + begin + lDone := (lFollower.Controller as TBoldVariantFollowerController).MayHaveChanged(Edit.EditingValue, lFollower); + end; + if lDone then + begin + lDataController.fInternalChange := true; + try + TBoldQueueable.DisplayAll; + finally + lDataController.fInternalChange := false; + inherited; + end; + end; + end; + end + else + inherited; +end; + +{ TcxGridBoldDefaultValuesProvider } + +function TcxGridBoldDefaultValuesProvider.DefaultCanModify: Boolean; +begin + Result := inherited DefaultCanModify {and Follower.MayModify}; +end; + +function TcxGridBoldDefaultValuesProvider.IsDisplayFormatDefined( + AIsCurrencyValueAccepted: Boolean): Boolean; +begin + with Owner as TcxGridItemBoldDataBinding do + Result := IsDisplayFormatDefined(AIsCurrencyValueAccepted) or Assigned(BoldProperties.Renderer); +end; + +{ TcxGridBoldTableViewInfo } + +function TcxGridBoldTableViewInfo.GetRecordsViewInfoClass: TcxCustomGridRecordsViewInfoClass; +begin + result := TcxBoldGridRowsViewInfo; +end; + +function TcxGridBoldTableViewInfo.GetSiteClass: TcxGridSiteClass; +begin + Result := TcxBoldGridSite; +end; + +procedure TcxGridBoldTableViewInfo.Calculate; +var + vDataController: TcxBoldDataController; +begin + vDataController := DataController as TcxBoldDataController; + if Assigned(vDataController) then + begin + with vDataController as TcxBoldDataController do + begin + if Assigned(vDataController.CustomDataSource) then + if MainFollowerNeedsDisplay then + DisplayFollowers; + end; + end; + inherited; +end; + +{ TcxGridBoldBandedTableViewInfo } + +function TcxGridBoldBandedTableViewInfo.GetRecordsViewInfoClass: TcxCustomGridRecordsViewInfoClass; +begin + Result := TcxGridBoldBandedRowsViewInfo; +end; + +{ TcxGridBoldBandedTableViewInfo } + +function TcxGridBoldBandedTableViewInfo.GetSiteClass: TcxGridSiteClass; +begin + Result := TcxBoldGridSite; +end; + +procedure TcxGridBoldBandedTableViewInfo.Calculate; +var + vDataController: TcxBoldDataController; +begin + vDataController := DataController as TcxBoldDataController; + if Assigned(vDataController) then + begin + with vDataController as TcxBoldDataController do + begin + if Assigned(vDataController.CustomDataSource) then + if MainFollowerNeedsDisplay then + DisplayFollowers; + end; + end; + inherited; +end; + +{ TcxGridBoldCardViewViewInfo } + +function TcxGridBoldCardViewViewInfo.GetRecordsViewInfoClass: TcxCustomGridRecordsViewInfoClass; +begin + Result := TcxGridBoldCardsViewInfo; +end; + +function TcxGridBoldCardViewViewInfo.GetSiteClass: TcxGridSiteClass; +begin + Result := TcxBoldGridSite; +end; + + +{ TcxGridBoldLayoutView } + +constructor TcxGridBoldLayoutView.Create(AOwner: TComponent); +begin + inherited; + +end; + +destructor TcxGridBoldLayoutView.Destroy; +begin + + inherited; +end; + +function TcxGridBoldLayoutView.CreateItem: TcxGridBoldLayoutViewItem; +begin + Result := TcxGridBoldLayoutViewItem(inherited CreateItem); +end; + +function TcxGridBoldLayoutView.GetCurrentBoldObject: TBoldObject; +begin + result := DataController.CurrentBoldObject; +end; + +function TcxGridBoldLayoutView.GetCurrentElement: TBoldElement; +begin + result := DataController.CurrentElement; +end; + +function TcxGridBoldLayoutView.GetCurrentIndex: integer; +begin + result := DataController.CurrentIndex; +end; + +function TcxGridBoldLayoutView.GetDataController: TcxGridBoldDataController; +begin + Result := TcxGridBoldDataController(FDataController); +end; + +function TcxGridBoldLayoutView.GetDataControllerClass: TcxCustomDataControllerClass; +begin + Result := TcxGridBoldDataController; +end; + +function TcxGridBoldLayoutView.GetItem(Index: Integer): IBoldAwareViewItem; +begin + result := inherited Items[Index] as IBoldAwareViewItem; +end; + +function TcxGridBoldLayoutView.GetItemClass: TcxCustomGridTableItemClass; +begin + Result := TcxGridBoldLayoutViewItem; +end; + +function TcxGridBoldLayoutView.GetItemCount: Integer; +begin + result := inherited ItemCount; +end; + +function TcxGridBoldLayoutView.GetSelection: TBoldList; +begin + result := DataController.Selection; +end; + +procedure TcxGridBoldLayoutView.SetDataController( + Value: TcxGridBoldDataController); +begin + FDataController.Assign(Value); +end; + +function TcxGridBoldLayoutView.ValidateComponent( + ComponentValidator: TBoldComponentValidator; NamePrefix: string): Boolean; +var + i: integer; + lContext: TBoldElementTypeInfo; + lBoldValidateableComponent: IBoldValidateableComponent; +begin + lContext := DataController.GetHandleStaticType; + result := ComponentValidator.ValidateExpressionInContext( + '', lContext, format('%s%s', [NamePrefix, Name])); // do not localize + if assigned(lContext) then + begin + for i := 0 to ItemCount - 1 do + begin + result := ComponentValidator.ValidateExpressionInContext( + Items[i].BoldProperties.Expression, + lContext, + format('%s%s.Column[%d]', [NamePrefix, Name, i]), + Items[i].BoldProperties.VariableList) and result; // do not localize + if Supports((self.DataController.GetItem(i) as TcxCustomGridTableItem).GetProperties, IBoldValidateableComponent, lBoldValidateableComponent) then + result := lBoldValidateableComponent.ValidateComponent(ComponentValidator, namePrefix) and result; + end; + end; +end; + +{ TcxGridBoldLayoutViewItem } + +destructor TcxGridBoldLayoutViewItem.Destroy; +begin + DataBinding.Remove; + inherited; +end; + +function TcxGridBoldLayoutViewItem.GetDataBinding: TcxGridItemBoldDataBinding; +begin + Result := TcxGridItemBoldDataBinding(inherited DataBinding); +end; + +procedure TcxGridBoldLayoutViewItem.SetDataBinding( + Value: TcxGridItemBoldDataBinding); +begin + inherited DataBinding := Value; +end; + +{ TBoldCxGridVariantFollowerController } + +constructor TBoldCxGridVariantFollowerController.Create( + aOwningComponent: TComponent); +begin + inherited Create(aOwningComponent); +end; + +function TBoldCxGridVariantFollowerController.SubFollowersActive: boolean; +begin + result := false; //cxGridItemBoldDataBinding.Item.ActuallyVisible; +end; + +{ TcxBoldCustomDataControllerInfo } + +procedure TcxBoldCustomDataControllerInfo.DoFilter; +var + i: integer; + RootFilter: TcxFilterCriteriaItemList; + lList: TBoldList; + lDataController: TcxBoldDataController; +begin + try + lDataController := (DataController as TcxBoldDataController); + lList := lDataController.BoldList; + RootFilter := (DataController.Filter as TcxFilterCriteria).Root; + if not (not Assigned(lList) or lList.Empty or (RootFilter.Count = 0)) then + for I := 0 to RootFilter.Count - 1 do + if RootFilter.Items[i] is TcxDataFilterCriteriaItem then + lDataController.PreFetchColumns(lList, lDataController.GetItemData(TcxDataFilterCriteriaItem(RootFilter.Items[i]).Field.Item)); + finally + inherited; + // SelectionChanged; // ? + end; +end; + +procedure TcxBoldCustomDataControllerInfo.DoSort; +var + i: integer; + lList: TBoldList; + lWholeList: TBoldList; + lGuard: IBoldGuard; + IsObjectList: boolean; +begin + try + GetTotalSortingFields; + if (TotalSortingFieldList.Count = 0) or (RecordList.Count = 0) then + exit; + lWholeList := TcxBoldDataController(DataController).BoldList; + if not Assigned(lWholeList) then + exit; + if RecordList.Count = lWholeList.Count then + lList := lWholeList as TBoldList + else + begin + lGuard := TBoldGuard.Create(lList); + lList := TcxBoldDataController(DataController).CreateList; + lList.DuplicateMode := bldmAllow; + lList.Capacity := RecordList.Count; + IsObjectList := (lList is TBoldObjectList) and (lWholeList is TBoldObjectList); + for I := 0 to RecordList.Count -1 do + begin + if Integer(RecordList[i]) < lWholeList.Count then + if IsObjectList then + TBoldObjectList(lList).AddLocator( TBoldObjectList(lWholeList).Locators[Integer(RecordList[i])] ) + else + lList.Add( lWholeList[Integer(RecordList[i])] ); + end; + end; + for I := 0 to TotalSortingFieldList.Count - 1 do + begin + TcxBoldDataController(DataController).PreFetchColumns(lList, TcxBoldDataController(DataController).GetItemData(TotalSortingFieldList[i].Field.Item)); + end; + finally + inherited; + end; +end; + +{ TcxBoldDataSummary } + +procedure TcxBoldDataSummary.CalculateSummary( +{$IFDEF BOLD_DELPHI16_OR_LATER} + ASummaryItems: TcxDataSummaryItems; ABeginIndex, AEndIndex: Integer; + var ACountValues: TcxDataSummaryCountValues; var ASummaryValues: TcxDataSummaryValues +{$ELSE} + ASummaryItems: TcxDataSummaryItems; ABeginIndex, AEndIndex: Integer; + var ACountValues: TcxDataSummaryCountValues; var ASummaryValues: TcxDataSummaryValues; var SummaryValues: Variant +{$ENDIF} +); +var + I: Integer; + lList: TBoldList; + lWholeList: TBoldList; + lGuard: IBoldGuard; + ARecordIndex: Integer; + IsObjectList: boolean; +begin + lWholeList := TcxBoldDataController(DataController).BoldList; + if (ASummaryItems.Count = 0) or not Assigned(lWholeList) then + exit; + if lWholeList.Count = 0 then + exit; + if (ABeginIndex = 0) and (AEndIndex = lWholeList.Count-1) then + begin + lList := lWholeList; + end + else + begin + lGuard := TBoldGuard.Create(lList); + lList := TcxBoldDataController(DataController).CreateList; + lList.DuplicateMode := bldmAllow; + lList.Capacity := AEndIndex - ABeginIndex; + IsObjectList := (lList is TBoldObjectList) and (lWholeList is TBoldObjectList); + for I := ABeginIndex to AEndIndex do + begin + ARecordIndex := GetRecordIndex(I); + if ARecordIndex <> -1 then + begin + if IsObjectList then + TBoldObjectList(lList).AddLocator(TBoldObjectList(lWholeList).Locators[ARecordIndex]) + else + lList.Add(lWholeList[ARecordIndex]); + end + end; + end; + for I := 0 to ASummaryItems.Count - 1 do + if Assigned(ASummaryItems[i].Field) then + with TcxBoldDataController(DataController) do + PreFetchColumns(lList, GetItemData(ASummaryItems[i].Field.Item)); + inherited; +end; + +initialization + cxGridRegisteredViews.Register(TcxGridBoldTableView, 'Bold Table'); + cxGridRegisteredViews.Register(TcxGridBoldCardView, 'Bold Card'); +// cxGridRegisteredViews.Register(TcxBoldGridChartView, 'Bold Chart'); + cxGridRegisteredViews.Register(TcxGridBoldBandedTableView, 'Bold Banded Table'); + cxGridRegisteredViews.Register(TcxGridBoldLayoutView, 'Bold Layout'); + Classes.RegisterClasses([TcxGridBoldColumn, TcxGridItemBoldDataBinding, TcxGridBoldBandedColumn, TcxGridBoldCardViewRow, TcxGridBoldLayoutViewItem]); + +finalization + cxGridRegisteredViews.Unregister(TcxGridBoldTableView); + cxGridRegisteredViews.Unregister(TcxGridBoldCardView); +// cxGridRegisteredViews.Unregister(TcxBoldGridChartView); + cxGridRegisteredViews.Unregister(TcxGridBoldBandedTableView); + cxGridRegisteredViews.Unregister(TcxGridBoldLayoutView); + Classes.UnRegisterClasses([TcxGridBoldColumn, TcxGridItemBoldDataBinding, TcxGridBoldBandedColumn, TcxGridBoldCardViewRow, TcxGridBoldLayoutViewItem]); +// FilterEditsController.Unregister(TcxSingleLinkEditProperties, TcxFilterSingleLinkEditHelper); + +end. diff --git a/Source/BoldAwareGUI/BoldDevex/cxLookupBoldGrid.pas b/Source/BoldAwareGUI/BoldDevex/cxLookupBoldGrid.pas new file mode 100644 index 0000000..c4a4129 --- /dev/null +++ b/Source/BoldAwareGUI/BoldDevex/cxLookupBoldGrid.pas @@ -0,0 +1,629 @@ +unit cxLookupBoldGrid; + +{$I cxVer.inc} + +// v2.03 - 25 Jan 2011 2007-2011 Daniel Mauric + +interface + +uses + Windows, + SysUtils, Classes, Controls, Graphics, Forms, StdCtrls, //DB, + cxClasses, cxControls, cxGraphics, cxLookAndFeelPainters, + cxEdit, +// cxDBEdit, + cxCustomData, +// cxDB, cxDBData, + cxEditRepositoryItems, + cxLookupGrid, + + cxGridBoldSupportUnit, + cxBoldEditors, + BoldVariantControlPack, //BoldStringControlPack, + BoldAbstractListHandle, + BoldListListControlPack, + BoldControlPack; + +const + DefaultSyncMode = False; + +type + TcxCustomLookupBoldGrid = class; + + { TcxLookupGridBoldDataController } + + TcxLookupGridBoldDataController = class(TcxBoldDataController) + private + function GetGrid: TcxCustomLookupBoldGrid; + protected + function GetItemID(AItem: TObject): Integer; override; + function GetItemData(AItem: TObject): Integer; override; +// procedure UpdateScrollBars; override; + procedure _AfterMakeCellUptoDate(Follower: TBoldFollower); override; + procedure _AfterMakeListUptoDate(Follower: TBoldFollower); override; + public + constructor Create(AOwner: TComponent); override; + function GetItem(Index: Integer): TObject; override; + property Grid: TcxCustomLookupBoldGrid read GetGrid; + published + property OnCompare; + end; + + { TcxLookupBoldGridColumn } + + TcxLookupBoldGridDefaultValuesProvider = class(TcxCustomBoldEditDefaultValuesProvider) + function IsDisplayFormatDefined(AIsCurrencyValueAccepted: Boolean): Boolean; override; + end; + + TcxLookupBoldGridColumn = class(TcxLookupGridColumn, IBoldAwareViewItem) + private + fBoldProperties: TBoldVariantFollowerController; + function GetDataController: TcxLookupGridBoldDataController; + procedure SetBoldProperties( + const Value: TBoldVariantFollowerController); + function GetBoldProperties: TBoldVariantFollowerController; +// function GetField: TField; +// function GetFieldName: string; +// procedure SetFieldName(const Value: string); + protected + function GetDefaultValuesProviderClass: TcxCustomEditDefaultValuesProviderClass; override; + procedure InitDefaultValuesProvider; + property DataController: TcxLookupGridBoldDataController read GetDataController; + public + constructor Create(Collection: TCollection); override; + destructor Destroy; override; + procedure Assign(Source: TPersistent); override; + function DefaultCaption: string; override; + function DefaultRepositoryItem: TcxEditRepositoryItem; override; + function DefaultWidth: Integer; override; +// property Field: TField read GetField; + published + property BoldProperties: TBoldVariantFollowerController read GetBoldProperties write SetBoldProperties; + end; + + { TcxLookupBoldGridColumns } + + TcxLookupBoldGridColumns = class(TcxLookupGridColumns) + private + function GetColumn(Index: Integer): TcxLookupBoldGridColumn; + procedure SetColumn(Index: Integer; Value: TcxLookupBoldGridColumn); + public + function Add: TcxLookupBoldGridColumn; +// function ColumnByFieldName(const AFieldName: string): TcxLookupBoldGridColumn; + property Items[Index: Integer]: TcxLookupBoldGridColumn read GetColumn write SetColumn; default; + end; + + { TcxLookupBoldGridOptions } + + TcxLookupBoldGridOptions = class(TcxLookupGridOptions) + private + function GetGrid: TcxCustomLookupBoldGrid; + function GetSyncMode: Boolean; + procedure SetSyncMode(Value: Boolean); + public + procedure Assign(Source: TPersistent); override; + property Grid: TcxCustomLookupBoldGrid read GetGrid; + published + property SyncMode: Boolean read GetSyncMode write SetSyncMode + default DefaultSyncMode; + end; + + { TcxCustomLookupBoldGrid } + + TcxCustomLookupBoldGrid = class(TcxCustomLookupGrid) + private + function GetColumns: TcxLookupBoldGridColumns; + function GetDataController: TcxLookupGridBoldDataController; +// function GetDataSource: TDataSource; +// function GetKeyFieldNames: string; + function GetOptions: TcxLookupBoldGridOptions; + procedure SetColumns(Value: TcxLookupBoldGridColumns); + procedure SetDataController(Value: TcxLookupGridBoldDataController); +// procedure SetDataSource(Value: TDataSource); +// procedure SetKeyFieldNames(const Value: string); + procedure SetOptions(Value: TcxLookupBoldGridOptions); + function GetBoldListHandle: TBoldAbstractListHandle; + procedure SetBoldListHandle(const Value: TBoldAbstractListHandle); + function GetBoldProperties: TBoldListAsFollowerListController; + procedure SetBoldProperties( + const Value: TBoldListAsFollowerListController); + protected +// procedure CreateColumnsByFields(AFieldNames: TStrings); virtual; + procedure DataChanged; override; + function GetColumnClass: TcxLookupGridColumnClass; override; + function GetColumnsClass: TcxLookupGridColumnsClass; override; + function GetDataControllerClass: TcxCustomDataControllerClass; override; + function GetOptionsClass: TcxLookupGridOptionsClass; override; + procedure InitScrollBarsParameters; override; + procedure Scroll(AScrollBarKind: TScrollBarKind; AScrollCode: TScrollCode; var AScrollPos: Integer); override; + procedure UpdateScrollBars; override; // for Delphi .NET + public + procedure CreateAllColumns; +// procedure CreateColumnsByFieldNames(const AFieldNames: string); + property Align; + property Anchors; + property Color; + property Columns: TcxLookupBoldGridColumns read GetColumns write SetColumns; + property DataController: TcxLookupGridBoldDataController read GetDataController write SetDataController; + property Font; + property LookAndFeel; + property Options: TcxLookupBoldGridOptions read GetOptions write SetOptions; + property ParentFont; + property Visible; + published +// property DataSource: TDataSource read GetDataSource write SetDataSource; +// property KeyFieldNames: string read GetKeyFieldNames write SetKeyFieldNames; + property BoldLookupListHandle: TBoldAbstractListHandle read GetBoldListHandle write SetBoldListHandle; + property BoldProperties: TBoldListAsFollowerListController read GetBoldProperties write SetBoldProperties; + end; + + TcxCustomLookupBoldGridClass = class of TcxCustomLookupBoldGrid; + +implementation + +uses + BoldElements, + BoldSystem, + BoldOcl, + BoldSystemRT, + BoldControlPackDefs; +// cxEditBoldRegisteredRepositoryItems; // cxEditDBRegisteredRepositoryItems; + +function TcxLookupBoldGridDefaultValuesProvider.IsDisplayFormatDefined(AIsCurrencyValueAccepted: Boolean): Boolean; +begin + with TcxLookupBoldGridColumn(Owner) do + Result := DataController.GetItemTextStored(Index); +end; + +{ TcxLookupBoldGridColumn } + +procedure TcxLookupBoldGridColumn.Assign(Source: TPersistent); +begin + if Source is TcxLookupBoldGridColumn then + BoldProperties.Assign(TcxLookupBoldGridColumn(Source).BoldProperties); + inherited Assign(Source); +end; + +function TcxLookupBoldGridColumn.DefaultCaption: string; +var + lContextType: TBoldElementTypeInfo; + lResultType: TBoldElementTypeInfo; + lBoldMemberRTInfo: TBoldMemberRTInfo; + lEvaluator: TBoldOcl; +begin + result := ''; + lContextType := DataController.GetHandleStaticType; + if Assigned(lContextType) then + begin + lEvaluator := lContextType.Evaluator as TBoldOcl; + lBoldMemberRTInfo := lEvaluator.RTInfo(BoldProperties.Expression, lContextType, false); + if Assigned(lBoldMemberRTInfo) then + result := lBoldMemberRTInfo.ModelName + else + begin + lResultType := lEvaluator.ExpressionType(BoldProperties.Expression, lContextType, false, BoldProperties.VariableList); + if Assigned(lResultType) then + begin + result := lResultType.ModelName; + end; + end; + end; +end; + +function TcxLookupBoldGridColumn.DefaultRepositoryItem: TcxEditRepositoryItem; +begin +// TODO: fix + result := nil; +// Result := GetDefaultEditDBRepositoryItems.GetItemByField(Field); +end; + +function TcxLookupBoldGridColumn.DefaultWidth: Integer; +var + lContextType: TBoldElementTypeInfo; + lBoldMemberRTInfo: TBoldMemberRTInfo; + lEvaluator: TBoldOcl; + ACanvas: TcxCanvas; + W: Integer; + lLength: Integer; +begin + Result := inherited DefaultWidth; + lContextType := DataController.GetHandleStaticType; + if Assigned(lContextType) then + begin + lEvaluator := lContextType.Evaluator as TBoldOcl; + lBoldMemberRTInfo := lEvaluator.RTInfo(BoldProperties.Expression, lContextType, false); + if (lBoldMemberRTInfo is TBoldAttributeRTInfo) then + begin + lLength := TBoldAttributeRTInfo(lBoldMemberRTInfo).Length; + // we could perhaps provide sensible values for types with more or less known length, + // such as Date, Time, Boolean, maybe even integer... + if lLength > 0 then + begin + ACanvas := Grid.ViewInfo.Canvas; + ACanvas.Font := GetContentFont; + Result := lLength * ACanvas.TextWidth('0') + 4; + if Grid.Options.ShowHeader then + begin + W := Grid.Painter.LFPainterClass.HeaderWidth(ACanvas, cxBordersAll, Caption, + Grid.ViewInfo.GetHeaderFont); + if W > Result then Result := W; + end; + end; + end; + end; + CheckWidthValue(Result); +end; + +function TcxLookupBoldGridColumn.GetDefaultValuesProviderClass: TcxCustomEditDefaultValuesProviderClass; +begin + Result := TcxLookupBoldGridDefaultValuesProvider; +end; + +procedure TcxLookupBoldGridColumn.InitDefaultValuesProvider; +begin +// TcxCustomDBEditDefaultValuesProvider(DefaultValuesProvider.GetInstance).Field := Field; + TcxCustomBoldEditDefaultValuesProvider(DefaultValuesProvider.GetInstance).BoldHandleFollower := DataController.BoldHandleFollower; +// TcxCustomBoldEditDefaultValuesProvider(DefaultValuesProvider.GetInstance).BoldHandle := DataController.BoldHandle; + TcxCustomBoldEditDefaultValuesProvider(DefaultValuesProvider.GetInstance).BoldProperties := BoldProperties; + // TODO: check this + +end; + +function TcxLookupBoldGridColumn.GetDataController: TcxLookupGridBoldDataController; +begin + Result := TcxLookupGridBoldDataController(inherited DataController); +end; +{ +function TcxLookupBoldGridColumn.GetField: TField; +begin + Result := DataController.GetItemField(Index); +end; + +function TcxLookupBoldGridColumn.GetFieldName: string; +begin + Result := DataController.GetItemFieldName(Index); +end; + +procedure TcxLookupBoldGridColumn.SetFieldName(const Value: string); +begin + DataController.ChangeFieldName(Index, Value); +end; +} +constructor TcxLookupBoldGridColumn.Create(Collection: TCollection); +begin + inherited; + fBoldProperties := TBoldVariantFollowerController.Create(nil); // no useful owner can be provided + fBoldProperties.ApplyPolicy := bapExit; + fBoldProperties.OnGetContextType := DataController.GetHandleStaticType; + DataController.BoldColumnsProperties.Add(fBoldProperties); + + // TODO: check this + (DefaultValuesProvider as TcxLookupBoldGridDefaultValuesProvider).BoldHandleFollower := DataController.BoldHandleFollower; + (DefaultValuesProvider as TcxLookupBoldGridDefaultValuesProvider).BoldProperties := BoldProperties; +// fBoldProperties.AddSmallSubscription(fSubscriber, [beValueChanged], beValueChanged); +end; + +destructor TcxLookupBoldGridColumn.Destroy; +begin +// FBoldProperties get freeded by DataController.BoldColumnsProperties +// so we only need to free FBoldProperties if DataController is assigned + if Assigned(DataController) then + begin + DataController.BoldColumnsProperties.Remove(fBoldProperties); + FreeAndNil(FBoldProperties); + end; + inherited; +end; + +procedure TcxLookupBoldGridColumn.SetBoldProperties( + const Value: TBoldVariantFollowerController); +begin + if Assigned(Value) then + fBoldProperties.Assign(Value); +end; + +function TcxLookupBoldGridColumn.GetBoldProperties: TBoldVariantFollowerController; +begin + result := fBoldProperties; +end; + +{ TcxLookupBoldGridColumns } + +function TcxLookupBoldGridColumns.Add: TcxLookupBoldGridColumn; +begin + Result := inherited Add as TcxLookupBoldGridColumn; +end; + +{function TcxLookupBoldGridColumns.ColumnByFieldName(const AFieldName: string): TcxLookupBoldGridColumn; +var + I: Integer; +begin + for I := 0 to Count - 1 do + begin + Result := Items[I]; + if AnsiCompareText(Result.FieldName, AFieldName) = 0 then + Exit; + end; + Result := nil; +end; +} +function TcxLookupBoldGridColumns.GetColumn(Index: Integer): TcxLookupBoldGridColumn; +begin + Result := inherited Items[Index] as TcxLookupBoldGridColumn; +end; + +procedure TcxLookupBoldGridColumns.SetColumn(Index: Integer; Value: TcxLookupBoldGridColumn); +begin + inherited Items[Index] := Value; +end; + +{ TcxLookupGridBoldDataController } + +constructor TcxLookupGridBoldDataController.Create(AOwner: TComponent); +begin + inherited Create(AOwner); +// DataModeController.SyncMode := DefaultSyncMode; +// DataModeController.SyncInsert := False; +end; + +function TcxLookupGridBoldDataController.GetItem(Index: Integer): TObject; +begin + Result := Grid.Columns[Index]; +end; + +{procedure TcxLookupGridBoldDataController.UpdateScrollBars; +begin + Grid.UpdateScrollBars; +end;} + +function TcxLookupGridBoldDataController.GetGrid: TcxCustomLookupBoldGrid; +begin + Result := GetOwner as TcxCustomLookupBoldGrid; +end; + +{procedure TcxLookupGridBoldDataController.UpdateScrollBars; +begin + Grid.UpdateScrollBars; +end;} + +procedure TcxLookupGridBoldDataController._AfterMakeCellUptoDate( + Follower: TBoldFollower); +{var + lRowIndex: integer; + lRecordIndex: integer; + lcxLookupGridRowViewInfo: TcxLookupGridRowViewInfo; + lcxCustomEditViewInfo: TcxCustomEditViewInfo; +} +begin +// inherited; + if DataHasChanged or (SkipMakeCellUptoDate > 0) then + exit; + Grid.Change([lgcData]); +// Grid.CheckChanges + exit; +{ lRecordIndex := Follower.OwningFollower.index; + lRowIndex := GetRowIndexByRecordIndex(lRecordIndex, false); + lcxLookupGridRowViewInfo := Grid.ViewInfo.Rows.FindByRowIndex(lRowIndex); + lcxCustomEditViewInfo := lcxLookupGridRowViewInfo[Follower.index].EditViewInfo; + if Assigned(lcxCustomEditViewInfo.Edit) then + begin + lcxCustomEditViewInfo.Edit.Refresh; + lcxCustomEditViewInfo.Edit.Invalidate; + end; +} +end; + +procedure TcxLookupGridBoldDataController._AfterMakeListUptoDate( + Follower: TBoldFollower); +begin +// would be nice if we could force a recalc of dropdown height somehow in order for it to adjust to potential new record count + inherited; +end; + +function TcxLookupGridBoldDataController.GetItemID( + AItem: TObject): Integer; +begin + if AItem is TcxLookupBoldGridColumn then + Result := TcxLookupBoldGridColumn(AItem).ID + else + Result := -1; +end; + +function TcxLookupGridBoldDataController.GetItemData( + AItem: TObject): Integer; +begin + if AItem is TcxLookupBoldGridColumn then + Result := Integer(TcxLookupBoldGridColumn(AItem).Index) + else + Result := -1; +end; + +{ TcxLookupBoldGridOptions } + +procedure TcxLookupBoldGridOptions.Assign(Source: TPersistent); +begin + if Source is TcxLookupBoldGridOptions then + begin + if Assigned(Grid) then + Grid.BeginUpdate; + try + inherited Assign(Source); + SyncMode := TcxLookupBoldGridOptions(Source).SyncMode; + finally + if Assigned(Grid) then + Grid.EndUpdate; + end; + end + else + inherited Assign(Source); +end; + +function TcxLookupBoldGridOptions.GetGrid: TcxCustomLookupBoldGrid; +begin + Result := TcxCustomLookupBoldGrid(FGrid); +end; + +function TcxLookupBoldGridOptions.GetSyncMode: Boolean; +begin + Result := DefaultSyncMode; +{ if Assigned(Grid) then + Result := Grid.DataController.DataModeController.SyncMode + else + Result := DefaultSyncMode; +} +end; + +procedure TcxLookupBoldGridOptions.SetSyncMode(Value: Boolean); +begin +// if Assigned(Grid) then +// Grid.DataController.DataModeController.SyncMode := Value; +end; + +{ TcxCustomLookupBoldGrid } + +procedure TcxCustomLookupBoldGrid.CreateAllColumns; +begin + Assert(false, 'TcxCustomLookupBoldGrid.CreateAllColumns not implemented yet.'); +end; + +{procedure TcxCustomLookupBoldGrid.CreateColumnsByFieldNames(const AFieldNames: string); +begin + Assert(false); +end;} + +{procedure TcxCustomLookupBoldGrid.CreateColumnsByFields(AFieldNames: TStrings); +begin + Assert(false); +end;} + +procedure TcxCustomLookupBoldGrid.DataChanged; +var + I: Integer; +begin + for I := 0 to Columns.Count - 1 do + Columns[I].InitDefaultValuesProvider; + inherited DataChanged; +end; + +function TcxCustomLookupBoldGrid.GetColumnClass: TcxLookupGridColumnClass; +begin + Result := TcxLookupBoldGridColumn; +end; + +function TcxCustomLookupBoldGrid.GetColumnsClass: TcxLookupGridColumnsClass; +begin + Result := TcxLookupBoldGridColumns; +end; + +function TcxCustomLookupBoldGrid.GetDataControllerClass: TcxCustomDataControllerClass; +begin + Result := TcxLookupGridBoldDataController; +end; + +function TcxCustomLookupBoldGrid.GetOptionsClass: TcxLookupGridOptionsClass; +begin + Result := TcxLookupBoldGridOptions; +end; + +procedure TcxCustomLookupBoldGrid.InitScrollBarsParameters; +begin +{ + if DataController.IsGridMode and DataController.IsSequenced then + begin + SetScrollBarInfo(sbVertical, 0, + (DataController.DataSetRecordCount - 1) + (ViewInfo.VisibleRowCount - 1), + 1, ViewInfo.VisibleRowCount, DataController.RecNo - 1, True, True); + end + else +} + inherited InitScrollBarsParameters; +end; + +procedure TcxCustomLookupBoldGrid.Scroll(AScrollBarKind: TScrollBarKind; + AScrollCode: TScrollCode; var AScrollPos: Integer); +begin +{ if DataController.IsGridMode and DataController.IsSequenced then + begin + if AScrollBarKind = sbVertical then + begin + case AScrollCode of + scLineUp: + FocusNextRow(False); + scLineDown: + FocusNextRow(True); + scPageUp: + FocusPriorPage; + scPageDown: + FocusNextPage; + scTrack: ; + scPosition: + DataController.RecNo := AScrollPos + 1; + end; + end + else + inherited Scroll(AScrollBarKind, AScrollCode, AScrollPos); + AScrollPos := DataController.RecNo - 1; + end + else +} + inherited Scroll(AScrollBarKind, AScrollCode, AScrollPos); +end; + +procedure TcxCustomLookupBoldGrid.UpdateScrollBars; +begin + inherited UpdateScrollBars; +end; + +function TcxCustomLookupBoldGrid.GetColumns: TcxLookupBoldGridColumns; +begin + Result := inherited Columns as TcxLookupBoldGridColumns; +end; + +function TcxCustomLookupBoldGrid.GetDataController: TcxLookupGridBoldDataController; +begin + Result := TcxLookupGridBoldDataController(FDataController); +end; + +function TcxCustomLookupBoldGrid.GetOptions: TcxLookupBoldGridOptions; +begin + Result := TcxLookupBoldGridOptions(FOptions); +end; + +procedure TcxCustomLookupBoldGrid.SetColumns(Value: TcxLookupBoldGridColumns); +begin + inherited Columns := Value; +end; + +procedure TcxCustomLookupBoldGrid.SetDataController(Value: TcxLookupGridBoldDataController); +begin + FDataController.Assign(Value); +end; + +procedure TcxCustomLookupBoldGrid.SetOptions(Value: TcxLookupBoldGridOptions); +begin + FOptions.Assign(Value); +end; + +function TcxCustomLookupBoldGrid.GetBoldListHandle: TBoldAbstractListHandle; +begin + result := DataController.BoldHandle; +end; + +procedure TcxCustomLookupBoldGrid.SetBoldListHandle( + const Value: TBoldAbstractListHandle); +begin + DataController.BoldHandle.Assign(Value); +end; + +function TcxCustomLookupBoldGrid.GetBoldProperties: TBoldListAsFollowerListController; +begin + result := DataController.BoldProperties; +end; + +procedure TcxCustomLookupBoldGrid.SetBoldProperties( + const Value: TBoldListAsFollowerListController); +begin + DataController.BoldProperties.Assign(Value); +end; + +end. diff --git a/Source/BoldAwareGUI/BoldDevex/dxBarBoldNav.pas b/Source/BoldAwareGUI/BoldDevex/dxBarBoldNav.pas new file mode 100644 index 0000000..4d0415a --- /dev/null +++ b/Source/BoldAwareGUI/BoldDevex/dxBarBoldNav.pas @@ -0,0 +1,515 @@ +unit dxBarBoldNav; + +interface + +{$I bold.inc} +{$I cxVer.inc} + + +// v2.03 - 25 Jan 2011 2007-2011 Daniel Mauric + +uses + Classes, Messages, DB, cxClasses, dxBar, + BoldNavigatorDefs, + BoldListListControlPack, + BoldVariantControlPack, + BoldListHandleFollower, + BoldAbstractListHandle, + BoldControlPack; + + +resourcestring + dxSBAR_DBNAVERROR1 = 'You already have an existing BoldNavigator button with the same defined style'; + + dxSBAR_CATEGORYNAME = 'Bold Navigator'; + dxSBAR_DELETERECORD = 'Do you want to delete the current record?'; + + dxSBAR_BTNCAPTION_FIRST = 'First'; + dxSBAR_BTNCAPTION_PRIOR = 'Prior'; + dxSBAR_BTNCAPTION_NEXT = 'Next'; + dxSBAR_BTNCAPTION_LAST = 'Last'; + dxSBAR_BTNCAPTION_INSERT = 'Insert'; + dxSBAR_BTNCAPTION_DELETE = 'Delete'; + dxSBAR_BTNCAPTION_EDIT = 'Edit'; + dxSBAR_BTNCAPTION_POST = 'Post'; + dxSBAR_BTNCAPTION_CANCEL = 'Cancel'; + dxSBAR_BTNCAPTION_REFRESH = 'Refresh'; + +type + TdxBarBoldNavigator = class; + TdxBarBoldNavButton = class; + + TdxBarDBEnableType = (dxdbtCanModify, dxdbtNotEOF, dxdbtNotBOF, + dxdbtHasRecords, dxdbtIsModified, dxdbtIsNotModified); + TdxBarDBEnableTypes = set of TdxBarDBEnableType; + +// TdxBarBoldNavButtonType = (dxbnFirst, dxbnPrior, dxbnNext, dxbnLast, dxbnInsert, dxbnDelete, dxbnEdit, dxbnPost, dxbnCancel, dxbnRefresh); +// TdxBarBoldNavButtonTypes = set of TdxBarBoldNavButtonType; + + TBoldNavigateBtn = (nbFirst, nbPrior, nbNext, nbLast, nbInsert, nbDelete, nbMoveUp, nbMoveDown); + TBoldButtonSet = set of TBoldNavigateBtn; + + TdxBarBoldNavButton = class(TdxBarButton) + private + FBarBoldNavigator: TdxBarBoldNavigator; + FNavButton: TBoldNavigateBtn; + procedure SetNavButton(Value: TBoldNavigateBtn); + protected + procedure Loaded; override; + procedure UpdateButtons; + public + destructor Destroy; override; + procedure DoClick; override; + published + property BarBoldNavigator: TdxBarBoldNavigator read FBarBoldNavigator write FBarBoldNavigator; + property NavButton: TBoldNavigateBtn read FNavButton write SetNavButton; + end; + + TBoldNavigatorDeleteEvent = TNotifyEvent; + TBoldNavigatorInsertEvent = TNotifyEvent; + + TdxBarBoldNavigator = class(TComponent) + private + FBarManager: TdxBarManager; + FCategoryName: string; + FConfirmDelete: Boolean; + FSetVisFlag: Boolean; + FVisibleButtons: TBoldButtonSet; + + fBoldDeleteMode: TBoldDeleteMode; + fBoldProperties: TBoldListAsFollowerListController; + fFollowerController: TBoldVariantFollowerController; + fHandleFollower: TBoldListHandleFollower; + fOnBoldNavigatorDelete: TBoldNavigatorDeleteEvent; + fOnBoldNavigatorInsert: TBoldNavigatorInsertEvent; + + procedure SetBoldListHandle(Value: TBoldAbstractListHandle); + function GetBoldListHandle: TBoldAbstractListHandle; + + procedure SetBarManager(Value: TdxBarManager); + procedure SetCategoryName(const Value: String); + procedure SetVisibleButtons(Value: TBoldButtonSet); + + procedure AddButton(AButton: TdxBarBoldNavButton); + procedure RemoveButton(AButton: TdxBarBoldNavButton); + + function MapMinus(CanDeleteObject: Boolean): Boolean; + + protected + Buttons: array[TBoldNavigateBtn] of TdxBarBoldNavButton; + procedure ActiveChanged; + procedure DataChanged; + procedure Notification(AComponent: TComponent; Operation: TOperation); override; + procedure _BeforeMakeUptoDate(Follower: TBoldFollower); + procedure _AfterMakeUptoDate(Follower: TBoldFollower); + procedure SetActiveButtons; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + published + property BarManager: TdxBarManager read FBarManager write SetBarManager; + property CategoryName: string read FCategoryName write SetCategoryName; + property VisibleButtons: TBoldButtonSet read FVisibleButtons + write SetVisibleButtons default []; + property BoldDeleteMode: TBoldDeleteMode read fBoldDeleteMode write fBoldDeleteMode default dmDefault; + property BoldHandle: TBoldAbstractListHandle read GetBoldListHandle write SetBoldListHandle; + property ConfirmDelete: Boolean read fConfirmDelete write fConfirmDelete default True; + property OnBoldNavigatorDelete: TBoldNavigatorDeleteEvent read fOnBoldNavigatorDelete write fOnBoldNavigatorDelete; + property OnBoldNavigatorInsert: TBoldNavigatorInsertEvent read fOnBoldNavigatorInsert write fOnBoldNavigatorInsert; + end; + +implementation + +{$R dxBarBoldNav.res} + +uses + Windows, + SysUtils, + Forms, +// dxBardbNavStrs, + dxCore, + BoldElements, + BoldSystem, + BoldGuiResourceStrings, + BoldDefs; + +const + BtnResStr = 'DXBARBOLDNAVBTN_'; + dxBarBoldNavBtnName = 'dxBarBoldNav'; + +{ dxBarBoldNavButton } + +destructor TdxBarBoldNavButton.Destroy; +begin + if BarBoldNavigator <> nil then + BarBoldNavigator.RemoveButton(Self); + inherited Destroy; +end; + +procedure TdxBarBoldNavButton.SetNavButton(Value: TBoldNavigateBtn); +const + dxBarNames: array[TBoldNavigateBtn] of string = + ('First', 'Prev', 'Next', 'Last', 'Insert', 'Delete', 'MoveUp', 'MoveDown'); +{ + PResStrs: array[TBoldNavigateBtn] of String = (SNavHintFirst, + SNavHintPrior, SNavHintNext, SNavHintLast, + SNavHintNew, SNavHintDelete, SNavHintMoveUp, SNavHintMoveDown); +} + PResStrs: array[TBoldNavigateBtn] of Pointer = (@dxSBAR_BTNCAPTION_FIRST, + @dxSBAR_BTNCAPTION_PRIOR, @dxSBAR_BTNCAPTION_NEXT, @dxSBAR_BTNCAPTION_LAST, + @dxSBAR_BTNCAPTION_INSERT, @dxSBAR_BTNCAPTION_DELETE, @dxSBAR_BTNCAPTION_EDIT, + @dxSBAR_BTNCAPTION_POST{, @dxSBAR_BTNCAPTION_CANCEL, @dxSBAR_BTNCAPTION_REFRESH}); + +begin + if (FNavButton <> Value) or (Name = '') then + if csLoading in ComponentState then + FNavButton := Value + else + begin + if (BarBoldNavigator <> nil) and not BarBoldNavigator.FSetVisFlag and + (BarBoldNavigator.Buttons[Value] <> nil) then + raise Exception.Create(cxGetResourceString(@dxSBAR_DBNavERROR1)); + if (BarBoldNavigator <> nil) and not BarBoldNavigator.FSetVisFlag then + BarBoldNavigator.RemoveButton(Self); + FNavButton := Value; + if BarBoldNavigator <> nil then + begin + BarBoldNavigator.AddButton(Self); +{$IFDEF BOLD_DELPHI25_OR_LATER} + Glyph.LoadFromResource(HInstance, PChar(BtnResStr + IntToStr(Integer(FNavButton) + 1)), RT_BITMAP); +{$ELSE} + Glyph.LoadFromResourceName(HInstance, PChar(BtnResStr + IntToStr(Integer(FNavButton) + 1))); +{$ENDIF} + end; + try + if BarManager.Designing then + Name := (BarManager as IdxBarDesigner).UniqueName(dxBarBoldNavBtnName + dxBarNames[FNavButton]); + Caption := cxGetResourceString(PResStrs[FNavButton]); + Hint := Caption; + except + raise; + end; + end; +end; + +procedure TdxBarBoldNavButton.Loaded; +begin + inherited Loaded; + if BarBoldNavigator <> nil then + begin + BarBoldNavigator.AddButton(Self); + BarBoldNavigator.ActiveChanged; + end; +end; + +procedure TdxBarBoldNavButton.DoClick; +var + lSelection: TBoldObjectList; + +procedure GetSelection; +{var + i: integer; + lFollower: TBoldFollower; +} +begin +{ lFollower := BarBoldNavigator.fHandleFollower.Follower; + lSelection := TBoldObjectList.Create; + lSelection.SubscribeToObjectsInList := false; + lSelection.SubscribeToLocatorsInList := false; + for i := 0 to lFollower.SubFollowerCount - 1 do + begin + if BarBoldNavigator.fBoldProperties.GetSelected(lFollower, i) then + lSelection.Add( lFollower.SubFollowers[i].Element as TBoldObject ); + end; +} + if (lSelection.Count = 0) then + lSelection.Add(BarBoldNavigator.BoldHandle.CurrentBoldObject); +end; + +var + i: integer; + lList: TBoldObjectList; + lBoldObject: TBoldObject; +begin + inherited; + if Assigned(OnClick) then Exit; + if BarBoldNavigator <> nil then + with BarBoldNavigator.BoldHandle do + case FNavButton of + nbFirst: First; + nbPrior: Prior; + nbNext: Next; + nbLast: Last; + nbInsert: + begin + if Assigned(BarBoldNavigator.fOnBoldNavigatorInsert) then + BarBoldNavigator.fOnBoldNavigatorInsert(BarBoldNavigator) + else + List.AddNew; //Insert; + end; + nbDelete: + if not BarBoldNavigator.ConfirmDelete or + (Application.MessageBox(PChar(cxGetResourceString(@dxSBAR_DELETERECORD)), + PChar(Application.Title), MB_ICONQUESTION or MB_YESNO) = ID_YES) then + begin + if Assigned(BarBoldNavigator.fOnBoldNavigatorDelete) then + BarBoldNavigator.fOnBoldNavigatorDelete(BarBoldNavigator) + else + begin + lList := BarBoldNavigator.BoldHandle.ObjectList; + GetSelection; + try + for i := lSelection.count - 1 downto 0 do + begin + lBoldObject := lSelection[i]; + case BarBoldNavigator.BoldDeleteMode of + dmDefault, dmRemoveFromList: + lList.Remove(lBoldObject); + dmDelete: + lBoldObject.delete; + dmUnlinkAllAndDelete: + begin + lBoldObject.UnLinkAll; + lBoldObject.Delete + end; + end; + end; + finally + lSelection.free; + end; + end; + end; + nbMoveUp: ; //Edit; + nbMoveDown: ; //Post; + end; +end; + +{ TdxBarBoldNavigator } + +constructor TdxBarBoldNavigator.Create(AOwner: TComponent); +var + ABarManager: TdxBarManager; +begin + ABarManager := GetBarManagerForComponent(AOwner); + {if (ABarManager = nil) and (dxBarManagerList.Count <> 0) then + ABarManager := dxBarManagerList[0];} + inherited Create(AOwner); + FBarManager := ABarManager; + FCategoryName := 'Bold Navigator'; + ConfirmDelete := true; + fFollowerController := TBoldVariantFollowerController.Create(self); + fBoldProperties := TBoldListAsFollowerListController.Create(self, fFollowerController); + fHandleFollower := TBoldListHandleFollower.Create(Owner, fBoldProperties); + if not (csDesigning in ComponentState) then + begin + fBoldProperties.AfterMakeUptoDate := _AfterMakeUptoDate; + fBoldProperties.BeforeMakeUptoDate := _BeforeMakeUptoDate; + end; +end; + +destructor TdxBarBoldNavigator.Destroy; +begin + VisibleButtons := []; + inherited Destroy; +end; + +procedure TdxBarBoldNavigator.Notification(AComponent: TComponent; Operation: TOperation); +begin + inherited Notification(AComponent, Operation); + if Operation = opRemove then + begin + if AComponent = BarManager then BarManager := nil; +// if AComponent = DataSource then DataSource := nil; + end; +end; + +procedure TdxBarBoldNavigator.DataChanged; +begin + SetActiveButtons; +end; + +procedure TdxBarBoldNavigator.ActiveChanged; +begin + DataChanged; +end; + +procedure TdxBarBoldNavigator.SetBarManager(Value: TdxBarManager); +var + SaveVisButtons: TBoldButtonSet; +begin + if FBarManager <> Value then + begin + SaveVisButtons := FVisibleButtons; + VisibleButtons := []; + FBarManager := Value; + VisibleButtons := SaveVisButtons; + end; +end; + +procedure TdxBarBoldNavigator.SetCategoryName(const Value: String); +var + Index1, Index2: Integer; + I: TBoldNavigateBtn; +begin + if FCategoryName <> Value then + if csLoading in ComponentState then + FCategoryName := Value + else + if BarManager <> nil then + begin + Index1 := BarManager.Categories.IndexOf(FCategoryName); + FCategoryName := Value; + Index2 := BarManager.Categories.IndexOf(FCategoryName); + if Index2 = -1 then + begin + BarManager.Categories.Add(FCategoryName); + Index2 := BarManager.Categories.IndexOf(FCategoryName); + end; + for I := Low(Buttons) to High(Buttons) do + if Buttons[I] <> nil then Buttons[I].Category := Index2; + if (Index1 > -1) and (BarManager.GetCountByCategory(Index1) = 0) then + BarManager.Categories.Delete(Index1); + end; +end; + +procedure TdxBarBoldNavigator.SetVisibleButtons(Value: TBoldButtonSet); +var + I: TBoldNavigateBtn; + AIndex: Integer; +begin + if FVisibleButtons <> Value then + begin + FVisibleButtons := Value; + FSetVisFlag := True; + if not (csLoading in ComponentState) and (BarManager <> nil) then + for I := Low(Buttons) to High(Buttons) do + begin + if (Buttons[I] <> nil) and //not (csDestroying in Buttons[I].ComponentState) and + not (I in Value) then + begin + Buttons[I].Free; + Buttons[I] := nil; + end; + if (Buttons[I] = nil) and (I in Value) then + begin + Buttons[I] := TdxBarBoldNavButton.Create(Owner); + with Buttons[I] do + begin + BarBoldNavigator := Self; + Buttons[I].Tag := Ord(i); + AIndex := BarManager.Categories.IndexOf(FCategoryName); + if AIndex = -1 then + begin + BarManager.Categories.Add(FCategoryName); + AIndex := BarManager.Categories.IndexOf(FCategoryName); + end; + Category := AIndex; + NavButton := I; + end; + end; + end; + ActiveChanged; + FSetVisFlag := False; + end; + if (FVisibleButtons = []) and (BarManager <> nil) and + not (csDestroying in BarManager.ComponentState) then + begin + AIndex := BarManager.Categories.IndexOf(FCategoryName); + if (AIndex > -1) and (BarManager.GetCountByCategory(AIndex) = 0) then + BarManager.Categories.Delete(AIndex); + end; +end; + +procedure TdxBarBoldNavigator.AddButton(AButton: TdxBarBoldNavButton); +begin + Buttons[AButton.NavButton] := AButton; + FVisibleButtons := FVisibleButtons + [AButton.NavButton]; +end; + +procedure TdxBarBoldNavigator.RemoveButton(AButton: TdxBarBoldNavButton); +begin + Buttons[AButton.NavButton] := nil; + FVisibleButtons := FVisibleButtons - [AButton.NavButton]; +end; + +function TdxBarBoldNavigator.GetBoldListHandle: TBoldAbstractListHandle; +begin + if Assigned(fHandleFollower) then + Result := fHandleFollower.BoldHandle + else + Result := nil; +end; + +procedure TdxBarBoldNavigator.SetBoldListHandle( + Value: TBoldAbstractListHandle); +begin + fHandleFollower.BoldHandle := value; +end; + +procedure TdxBarBoldNavigator._BeforeMakeUptoDate(Follower: TBoldFollower); +begin + if Assigned(BoldHandle) and Assigned(Follower) then + fBoldProperties.SetActiveRange(Follower, BoldHandle.CurrentIndex, BoldHandle.CurrentIndex); +end; + +procedure TdxBarBoldNavigator._AfterMakeUptoDate(Follower: TBoldFollower); +begin + SetActiveButtons; +end; + +procedure TdxBarBoldNavigator.SetActiveButtons; +var + i: TBoldNavigateBtn; +begin + if (csDesigning in ComponentState) then exit; + for I := Low(Buttons) to High(Buttons) do + if Buttons[I] <> nil then Buttons[I].UpdateButtons; +end; + +function TdxBarBoldNavigator.MapMinus(CanDeleteObject: Boolean): Boolean; +begin + case BoldDeleteMode of + dmDefault, dmRemoveFromList: + Result := True; + dmDelete: + Result := CanDeleteObject; + dmUnlinkAllAndDelete: + Result := True; + else + raise EBold.CreateFmt(sUnknownDeleteMode, [ClassName]); + end; +end; + +procedure TdxBarBoldNavButton.UpdateButtons; +var + EnabledAndHandle: boolean; + lBoldHandle: TBoldAbstractListHandle; +begin + lBoldHandle := BarBoldNavigator.BoldHandle; + EnabledAndHandle := assigned(lBoldHandle) and Assigned(lBoldHandle.Value); + case TBoldNavigateBtn(Tag) of + nbFirst: Enabled := EnabledAndHandle and lBoldHandle.HasPrior; + nbPrior: Enabled := EnabledAndHandle and lBoldHandle.HasPrior; + nbNext: Enabled := EnabledAndHandle and lBoldHandle.HasNext; + nbLast: Enabled := EnabledAndHandle and lBoldHandle.HasNext; + nbInsert: Enabled := assigned(lBoldHandle) {and (nbInsert in BarBoldNavigator.VisibleButtons)} and + assigned(lBoldHandle.MutableList) and + lBoldHandle.MutableList.CanCreateNew; + nbDelete: Enabled := EnabledAndHandle {and (nbDelete in VisibleButtons)} and + assigned(lBoldHandle.CurrentBoldObject) and + BarBoldNavigator.MapMinus(lBoldHandle.CurrentBoldObject.CanDelete); +(* nbMoveUp: Enabled := EnabledAndHandle {and (nbMoveUp in VisibleButtons)} and + assigned(lBoldHandle.CurrentBoldObject) and + lBoldHandle.List.CanMove(lBoldHandle.CurrentIndex, + lBoldHandle.CurrentIndex -1); + nbMoveDown: Enabled := EnabledAndHandle {and (nbMoveDown in VisibleButtons)} and + assigned(lBoldHandle.CurrentBoldObject) and + lBoldHandle.List.CanMove(lBoldHandle.CurrentIndex, lBoldHandle.CurrentIndex + 1); +*) + end; +end; + +initialization + dxBarRegisterItem(TdxBarBoldNavButton, TdxBarButtonControl, False); + +end. diff --git a/Source/BoldAwareGUI/BoldDevex/dxBarBoldNav.res b/Source/BoldAwareGUI/BoldDevex/dxBarBoldNav.res new file mode 100644 index 0000000000000000000000000000000000000000..149d2b992dbbcb2588b8cf701ab298dc0f8c718e GIT binary patch literal 2996 zcmdUx%}&H16orq*WV)P3aOu*2ot>Il8cmEb?tF#rV9BoYSbdy%3p|&5skW)(khnk+ zI2@oY_X|(};Fvi^&8&{nmhO%@#zU;}jtAW1h2=9I>7VG{=w4a-z?nU{Tv~;4!Yo$u z0ghM#A(e9ld!#c26_%``?|Z6r$RtIg3QL`Lgxfc@opXNS9MvPKN74;n{M`@zI{ugU zmvB1gmn2oqN#YF}bWpkhNhu@GVd{tRyHJ&Iy5N^2)y=7~aA6f#g%eLLgSY-XeitR@ zN;q96N|kdO_8qvfWS;?@DK;Z-{oSAMyQ{i6$>}3$tmKsT+f=9HzP!F=QkJZz>$*8j zA~T!#=sMDKT!Jv7^H0pSmT9T*K_Nex(N z0|;t7Vy59|awVKrHFJ{HAs|RYfn-1#SU$J1xBfgnKW{9jBAnLD``t57jZ}62ywIh< iLcR;A^=9)9qv{#e=pEFf3u(16tVY(7=hZ=UK79hqPcAwD literal 0 HcmV?d00001 diff --git a/dclBold.dpk b/dclBold.dpk new file mode 100644 index 0000000..82d07a7 --- /dev/null +++ b/dclBold.dpk @@ -0,0 +1,149 @@ +package dclBold; + +{$R *.res} +{$IFDEF IMPLICITBUILDING This IFDEF should not be used by users} +{$ALIGN 8} +{$ASSERTIONS ON} +{$BOOLEVAL OFF} +{$DEBUGINFO OFF} +{$EXTENDEDSYNTAX ON} +{$IMPORTEDDATA ON} +{$IOCHECKS ON} +{$LOCALSYMBOLS ON} +{$LONGSTRINGS ON} +{$OPENSTRINGS ON} +{$OPTIMIZATION OFF} +{$OVERFLOWCHECKS ON} +{$RANGECHECKS ON} +{$REFERENCEINFO ON} +{$SAFEDIVIDE OFF} +{$STACKFRAMES ON} +{$TYPEDADDRESS OFF} +{$VARSTRINGCHECKS ON} +{$WRITEABLECONST OFF} +{$MINENUMSIZE 1} +{$IMAGEBASE $400000} +{$DEFINE DEBUG} +{$ENDIF IMPLICITBUILDING} +{$DESCRIPTION 'Bold for Delphi'} +{$LIBVERSION '27'} +{$DESIGNONLY} +{$IMPLICITBUILD OFF} + +requires + vcl, + vcldb, + DesignIDE, + BoldCore, + BoldAdditional, + FireDac, + FireDACCommonDriver, + FireDACCommon, + FireDACPgDriver, + IndySystem, + IndyCore; + +contains + BoldAbstractPropertyEditors in 'Source\Common\IDE\BoldAbstractPropertyEditors.pas', + BoldAFPPluggableReg in 'Source\BoldAwareGUI\FormGen\BoldAFPPluggableReg.pas', + BoldAttributeWizard in 'Source\ObjectSpace\IDE\AttributeWizard\BoldAttributeWizard.pas', + BoldAwareGuiReg in 'Source\BoldAwareGUI\IDE\BoldAwareGuiReg.pas', + BoldCheckListBoxReg in 'Source\Samples\BoldCheckListBox\BoldCheckListBoxReg.pas', + BoldCodePlugins in 'Source\UMLModel\Plugins\BoldCodePlugins.pas', + BoldComboBoxPropertyEditors in 'Source\BoldAwareGUI\IDE\BoldComboBoxPropertyEditors.pas', + BoldComEditors in 'Source\Common\IDECOM\BoldComEditors.pas', + BoldComElementHandleReg in 'Source\Handles\IDECOM\BoldComElementHandleReg.pas', + BoldComPersistenceHandleReg in 'Source\Persistence\IDECOM\BoldComPersistenceHandleReg.pas', + BoldComponentValidatorIDE in 'Source\ObjectSpace\IDE\BoldComponentValidatorIDE.pas', + BoldComReg in 'Source\Common\IDECOM\BoldComReg.pas', + BoldConcurrencyControlReg in 'Source\ConcurrencyControl\IDECOM\BoldConcurrencyControlReg.pas', + BoldConstraintValidatorReg in 'Source\Samples\ConstraintValidator\BoldConstraintValidatorReg.pas', + BoldControlPackPropertyEditors in 'Source\BoldAwareGUI\IDE\BoldControlPackPropertyEditors.pas', + BoldDefsDT in 'Source\Common\IDE\BoldDefsDT.pas', + BoldEditOCLActionPropEditor in 'Source\Samples\IDE\BoldEditOCLActionPropEditor.pas', + BoldExpert in 'Source\Common\IDE\BoldExpert.pas', + BoldExpertMenus in 'Source\Common\IDE\BoldExpertMenus.pas', + BoldExternalObjectSpaceEventHandlerReg in 'Source\ObjectSpace\IDE\BoldExternalObjectSpaceEventHandlerReg.pas', + BoldGridPropertyEditors in 'Source\BoldAwareGUI\IDE\BoldGridPropertyEditors.pas', + BoldHandlePropEditor in 'Source\Handles\IDE\BoldHandlePropEditor.pas', + BoldHandleReg in 'Source\Handles\IDE\BoldHandleReg.pas', + BoldHandlesPropagationReg in 'Source\Persistence\IDE\BoldHandlesPropagationReg.pas', + BoldHTTPClientPersistenceHandleReg in 'Source\Persistence\IDECOM\BoldHTTPClientPersistenceHandleReg.pas', + BoldHTTPServerPersistenceHandlePassthroughReg in 'Source\Persistence\IDECOM\BoldHTTPServerPersistenceHandlePassthroughReg.pas', + BoldIDEConsts in 'Source\Common\IDE\BoldIDEConsts.pas', + BoldIDEMenus in 'Source\Common\IDE\BoldIDEMenus.pas', + BoldIDESupport in 'Source\Common\IDE\BoldIDESupport.pas', + BoldLockingReg in 'Source\Handles\IDE\BoldLockingReg.pas', + BoldManipulatorReg in 'Source\Handles\IDE\BoldManipulatorReg.pas', + BoldModelAwareComponentEditor in 'Source\Common\IDE\BoldModelAwareComponentEditor.pas', + BoldModelReg in 'Source\MoldModel\IDE\BoldModelReg.pas', + BoldNodeDescriptionEditor in 'Source\BoldAwareGUI\IDE\BoldNodeDescriptionEditor.pas', + BoldObjectNamePropertyEditor in 'Source\Common\IDECOM\BoldObjectNamePropertyEditor.pas', + BoldObjectUpgraderHandleReg in 'Source\Persistence\IDE\BoldObjectUpgraderHandleReg.pas', + BoldOTACodeGen in 'Source\ObjectSpace\IDE\AttributeWizard\BoldOTACodeGen.pas', + BoldOTAFileHandler in 'Source\Common\IDE\BoldOTAFileHandler.pas', + BoldOTASupport in 'Source\Common\IDE\BoldOTASupport.pas', + BoldPersistenceHandleDBreg in 'Source\Persistence\DB\BoldPersistenceHandleDBreg.pas', + BoldPersistenceHandleFileReg in 'Source\Persistence\IDE\BoldPersistenceHandleFileReg.pas', + BoldPersistenceHandleFireDACReg in 'Source\Persistence\FireDAC\BoldPersistenceHandleFireDACReg.pas', + BoldPersistenceHandleReg in 'Source\Persistence\IDE\BoldPersistenceHandleReg.pas', + BoldPersistenceHandleSystemReg in 'Source\Persistence\IDE\BoldPersistenceHandleSystemReg.pas', + BoldPersistenceNotifierReg in 'Source\Persistence\IDE\BoldPersistenceNotifierReg.pas', + BoldPropagatorHandleCOMReg in 'Source\Propagator\IDECOM\BoldPropagatorHandleCOMReg.pas', + BoldPropertiesControllerPropertyEditors in 'Source\BoldAwareGUI\IDE\BoldPropertiesControllerPropertyEditors.pas', + BoldPropertyEditors in 'Source\Common\IDE\BoldPropertyEditors.pas', + BoldReg in 'Source\Common\IDE\BoldReg.pas', + BoldSamplesReg in 'Source\Samples\IDE\BoldSamplesReg.pas', + BoldSelectionListBoxReg in 'Source\Samples\BoldCheckListBox\BoldSelectionListBoxReg.pas', + BoldTextStream in 'Source\Common\IDE\BoldTextStream.pas', + BoldTypeNameHandleReg in 'Source\MoldModel\IDE\BoldTypeNameHandleReg.pas', + BoldUMLModelEditReg in 'Source\UMLModel\Ide\BoldUMLModelEditReg.pas', + BoldUMLModelHandleReg in 'Source\UMLModel\Ide\BoldUMLModelHandleReg.pas', + BoldUMLRose98Linkreg in 'Source\UMLModel\ModelLinks\Rose98\BoldUMLRose98Linkreg.pas', + BoldVclUtils in 'Source\ObjectSpace\IDE\AttributeWizard\BoldVclUtils.pas', + BoldWAClassInfo in 'Source\ObjectSpace\IDE\AttributeWizard\BoldWAClassInfo.pas', + BoldWACustomAttr in 'Source\ObjectSpace\IDE\AttributeWizard\BoldWACustomAttr.pas', + BoldWACustomAttrForm1 in 'Source\ObjectSpace\IDE\AttributeWizard\BoldWACustomAttrForm1.pas', + BoldWAdatamodule in 'Source\ObjectSpace\IDE\AttributeWizard\BoldWAdatamodule.pas', + BoldWAdmTemplates in 'Source\ObjectSpace\IDE\AttributeWizard\BoldWAdmTemplates.pas', + BoldWAInputFormUnit in 'Source\ObjectSpace\IDE\AttributeWizard\BoldWAInputFormUnit.pas', + BoldWAInterfaces in 'Source\ObjectSpace\IDE\AttributeWizard\BoldWAInterfaces.pas', + BoldWAMainForm in 'Source\ObjectSpace\IDE\AttributeWizard\BoldWAMainForm.pas', + BoldWAMethodInfo in 'Source\ObjectSpace\IDE\AttributeWizard\BoldWAMethodInfo.pas', + BoldWAStringGridManager in 'Source\ObjectSpace\IDE\AttributeWizard\BoldWAStringGridManager.pas', + BoldWASubClassForm1 in 'Source\ObjectSpace\IDE\AttributeWizard\BoldWASubClassForm1.pas', + BoldWAValueSetDlg in 'Source\ObjectSpace\IDE\AttributeWizard\BoldWAValueSetDlg.pas', + BoldWAValueSetForm1 in 'Source\ObjectSpace\IDE\AttributeWizard\BoldWAValueSetForm1.pas', + BoldWCodeInformer in 'Source\ObjectSpace\IDE\AttributeWizard\BoldWCodeInformer.pas', + BoldWebConnectionReg in 'Source\Common\IDE\BoldWebConnectionReg.pas', + BoldWProjectWizard in 'Source\ObjectSpace\IDE\AttributeWizard\BoldWProjectWizard.pas', + BoldWScanner in 'Source\ObjectSpace\IDE\AttributeWizard\BoldWScanner.pas', + BoldWSimpleMenuWizard in 'Source\ObjectSpace\IDE\BoldWSimpleMenuWizard.pas', + BoldXMLDispatcherEditor in 'Source\Common\IDECOM\BoldXMLDispatcherEditor.pas', + BoldXMLDispatcherReg in 'Source\Common\IDECOM\BoldXMLDispatcherReg.pas', + BoldXMLDispatcherVBReg in 'Source\Common\IDECOM\BoldXMLDispatcherVBReg.pas', + BoldXMLReg in 'Source\Handles\IDE\BoldXMLReg.pas', + BoldExternalPersistenceHandlesReg in 'Source\Persistence\ExternalPersistence\BoldExternalPersistenceHandlesReg.pas', + BoldDTDParser in 'Source\UMLModel\ModelLinks\XMI\BoldDTDParser.pas', + BoldMOFInterfaces in 'Source\UMLModel\ModelLinks\XMI\BoldMOFInterfaces.pas', + BoldUMLDTDData in 'Source\UMLModel\ModelLinks\XMI\BoldUMLDTDData.pas', + BoldUMLModelMOFAdapters in 'Source\UMLModel\ModelLinks\XMI\BoldUMLModelMOFAdapters.pas', + BoldUMLXMICommon in 'Source\UMLModel\ModelLinks\XMI\BoldUMLXMICommon.pas', + BoldUMLXMIImporter in 'Source\UMLModel\ModelLinks\XMI\BoldUMLXMIImporter.pas', + BoldUMLXMILink in 'Source\UMLModel\ModelLinks\XMI\BoldUMLXMILink.pas', + BoldUMLXMILinkSupport in 'Source\UMLModel\ModelLinks\XMI\BoldUMLXMILinkSupport.pas', + BoldUMXMILinkreg in 'Source\UMLModel\ModelLinks\XMI\BoldUMXMILinkreg.pas', + BoldXMI10Exporter in 'Source\UMLModel\ModelLinks\XMI\BoldXMI10Exporter.pas', + BoldOLLEController in 'Source\Extensions\OLLE\Core\BoldOLLEController.pas', + BoldOLLEDistributableObjectHandlers in 'Source\Extensions\OLLE\Core\BoldOLLEDistributableObjectHandlers.pas', + BoldOLLEdmmain in 'Source\Extensions\OLLE\Core\BoldOLLEdmmain.pas', + BoldOLLEHandles in 'Source\Extensions\OLLE\Core\BoldOLLEHandles.pas', + DistributableInfo in 'Source\Extensions\OLLE\Core\DistributableInfo.pas', + OlleConsts in 'Source\Extensions\OLLE\Core\OlleConsts.pas', + BoldOLLEHandlesComponentEditor in 'Source\Extensions\OLLE\IDE\BoldOLLEHandlesComponentEditor.pas', + BoldOLLEHandlesReg in 'Source\Extensions\OLLE\IDE\BoldOLLEHandlesReg.pas', + BoldAbstractModificationPropagator in 'Source\Persistence\UDPPropagator\BoldAbstractModificationPropagator.pas', + BoldUDPModificationBroadcaster in 'Source\Persistence\UDPPropagator\BoldUDPModificationBroadcaster.pas', + BoldUDPBroadcasterReg in 'Source\Persistence\IDEUDP\BoldUDPBroadcasterReg.pas'; + +end. diff --git a/dclBold.dproj b/dclBold.dproj new file mode 100644 index 0000000..bc04036 --- /dev/null +++ b/dclBold.dproj @@ -0,0 +1,975 @@ + + + {BA681BD2-4AA5-4AB0-8850-FFE2B8AAC9E0} + dclBold.dpk + 19.2 + None + True + Debug + Win32 + 1 + Package + + + true + + + true + Base + true + + + true + Base + true + + + true + Base + true + + + true + Cfg_1 + true + true + + + true + Base + true + + + true + Cfg_2 + true + true + + + .\$(Platform)\$(Config) + .\$(Platform)\$(Config) + false + false + false + false + false + true + true + System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;System;Xml;Data;Datasnap;Web;Soap;Winapi;$(DCC_Namespace) + All + dclBold + $(BoldDelphi)\Source\BoldAwareGUI;$(BoldDelphi)\Source\BoldQAwareGUI;$(BoldDelphi)\Source\ClientGuiCom;$(BoldDelphi)\Source\ClientHandlesCom;$(BoldDelphi)\Source\Common;$(BoldDelphi)\Source\ConcurrencyControl;$(BoldDelphi)\Source\Extensions;$(BoldDelphi)\Source\FreestandingValueSpace;$(BoldDelphi)\Source\Handles;$(BoldDelphi)\Source\MoldModel;$(BoldDelphi)\Source\ObjectSpace;$(BoldDelphi)\Source\Persistence;$(BoldDelphi)\Source\PMapper;$(BoldDelphi)\Source\Propagator;$(BoldDelphi)\Source\Samples;$(BoldDelphi)\Source\UMLModel;$(BoldDelphi)\Source\Unassigned;$(BoldDelphi)\Source\ValueSpace;$(BoldDelphi)\Source\BoldAwareGUI\Actions;$(BoldDelphi)\Source\BoldAwareGUI\BoldControls;$(BoldDelphi)\Source\BoldAwareGUI\ControlPacks;$(BoldDelphi)\Source\BoldAwareGUI\Core;$(BoldDelphi)\Source\BoldAwareGUI\FormGen;$(BoldDelphi)\Source\BoldAwareGUI\IDE;$(BoldDelphi)\Source\BoldQAwareGUI\BoldControls;$(BoldDelphi)\Source\BoldQAwareGUI\ControlPacks;$(BoldDelphi)\Source\BoldQAwareGUI\Core;$(BoldDelphi)\Source\ClientGuiCom\BoldControls;$(BoldDelphi)\Source\ClientGuiCom\ControlPacks;$(BoldDelphi)\Source\ClientGuiCom\Core;$(BoldDelphi)\Source\ClientGuiCom\IDE;$(BoldDelphi)\Source\ClientHandlesCom\Core;$(BoldDelphi)\Source\ClientHandlesCom\IDE;$(BoldDelphi)\Source\Common\COM;$(BoldDelphi)\Source\Common\Connection;$(BoldDelphi)\Source\Common\ConnectionCOM;$(BoldDelphi)\Source\Common\ConnectionHandles;$(BoldDelphi)\Source\Common\ConnectionHandlesCOM;$(BoldDelphi)\Source\Common\Core;$(BoldDelphi)\Source\Common\Environment;$(BoldDelphi)\Source\Common\Handles;$(BoldDelphi)\Source\Common\HTTP;$(BoldDelphi)\Source\Common\IDE;$(BoldDelphi)\Source\Common\IDECOM;$(BoldDelphi)\Source\Common\Include;$(BoldDelphi)\Source\Common\Logging;$(BoldDelphi)\Source\Common\MsXml;$(BoldDelphi)\Source\Common\Queue;$(BoldDelphi)\Source\Common\Rose2000;$(BoldDelphi)\Source\Common\Rose98;$(BoldDelphi)\Source\Common\SOAP;$(BoldDelphi)\Source\Common\Subscription;$(BoldDelphi)\Source\Common\Support;$(BoldDelphi)\Source\Common\SupportWin;$(BoldDelphi)\Source\Common\TaggedValues;$(BoldDelphi)\Source\Common\Template;$(BoldDelphi)\Source\Common\UML;$(BoldDelphi)\Source\Common\UtilsGUI;$(BoldDelphi)\Source\ConcurrencyControl\COM;$(BoldDelphi)\Source\ConcurrencyControl\Common;$(BoldDelphi)\Source\ConcurrencyControl\IDECOM;$(BoldDelphi)\Source\Extensions\OLLE;$(BoldDelphi)\Source\Extensions\OLLE\Core;$(BoldDelphi)\Source\Extensions\OLLE\IDE;$(BoldDelphi)\Source\FreestandingValueSpace\Core;$(BoldDelphi)\Source\Handles\Actions;$(BoldDelphi)\Source\Handles\COM;$(BoldDelphi)\Source\Handles\Core;$(BoldDelphi)\Source\Handles\IDE;$(BoldDelphi)\Source\Handles\IDECOM;$(BoldDelphi)\Source\Handles\Manipulators;$(BoldDelphi)\Source\Handles\PessimisticLocking;$(BoldDelphi)\Source\Handles\UnLoader;$(BoldDelphi)\Source\Handles\XML;$(BoldDelphi)\Source\MoldModel\Bld;$(BoldDelphi)\Source\MoldModel\CodeGenerator;$(BoldDelphi)\Source\MoldModel\Core;$(BoldDelphi)\Source\MoldModel\Handles;$(BoldDelphi)\Source\MoldModel\IDE;$(BoldDelphi)\Source\MoldModel\TypeNameDictionary;$(BoldDelphi)\Source\MoldModel\UtilsGUI;$(BoldDelphi)\Source\ObjectSpace\BORepresentation;$(BoldDelphi)\Source\ObjectSpace\COM;$(BoldDelphi)\Source\ObjectSpace\Core;$(BoldDelphi)\Source\ObjectSpace\IDE;$(BoldDelphi)\Source\ObjectSpace\Interfaces;$(BoldDelphi)\Source\ObjectSpace\Ocl;$(BoldDelphi)\Source\ObjectSpace\PessimisticLocking;$(BoldDelphi)\Source\ObjectSpace\RTModel;$(BoldDelphi)\Source\ObjectSpace\Undo;$(BoldDelphi)\Source\ObjectSpace\Unloader;$(BoldDelphi)\Source\ObjectSpace\UtilsGUI;$(BoldDelphi)\Source\ObjectSpace\IDE\AttributeWizard;$(BoldDelphi)\Source\Persistence\ADO;$(BoldDelphi)\Source\Persistence\Advantage;$(BoldDelphi)\Source\Persistence\BDE;$(BoldDelphi)\Source\Persistence\COM;$(BoldDelphi)\Source\Persistence\Core;$(BoldDelphi)\Source\Persistence\DB;$(BoldDelphi)\Source\Persistence\DBExpress;$(BoldDelphi)\Source\Persistence\DBISAM;$(BoldDelphi)\Source\Persistence\DOA;$(BoldDelphi)\Source\Persistence\ExternalPersistence;$(BoldDelphi)\Source\Persistence\File;$(BoldDelphi)\Source\Persistence\FireDAC;$(BoldDelphi)\Source\Persistence\HTTP;$(BoldDelphi)\Source\Persistence\IBX;$(BoldDelphi)\Source\Persistence\IDE;$(BoldDelphi)\Source\Persistence\IDECOM;$(BoldDelphi)\Source\Persistence\IDEUDP;$(BoldDelphi)\Source\Persistence\ObjectUpgrading;$(BoldDelphi)\Source\Persistence\Propagation;$(BoldDelphi)\Source\Persistence\SOAP;$(BoldDelphi)\Source\Persistence\SQLDirect;$(BoldDelphi)\Source\Persistence\System;$(BoldDelphi)\Source\Persistence\UDPPropagator;$(BoldDelphi)\Source\Persistence\UniDAC;$(BoldDelphi)\Source\PMapper\Core;$(BoldDelphi)\Source\PMapper\DbEvolutor;$(BoldDelphi)\Source\PMapper\Default;$(BoldDelphi)\Source\PMapper\SQL;$(BoldDelphi)\Source\PMapper\Validator;$(BoldDelphi)\Source\Propagator\COM;$(BoldDelphi)\Source\Propagator\Common;$(BoldDelphi)\Source\Propagator\Enterprise;$(BoldDelphi)\Source\Propagator\IDECOM;$(BoldDelphi)\Source\Propagator\LowEnd;$(BoldDelphi)\Source\Samples\Actions;$(BoldDelphi)\Source\Samples\BoldCheckListBox;$(BoldDelphi)\Source\Samples\ConstraintValidator;$(BoldDelphi)\Source\Samples\FormSaver;$(BoldDelphi)\Source\Samples\IDE;$(BoldDelphi)\Source\Samples\Misc;$(BoldDelphi)\Source\Samples\ModelLoader;$(BoldDelphi)\Source\Samples\NewObjectInterceptor;$(BoldDelphi)\Source\Samples\SortingGrid;$(BoldDelphi)\Source\Samples\SystemComparer;$(BoldDelphi)\Source\Samples\SystemDebugger;$(BoldDelphi)\Source\Samples\UMLPlugins;$(BoldDelphi)\Source\Samples\Unicode;$(BoldDelphi)\Source\UMLModel\Core;$(BoldDelphi)\Source\UMLModel\Editor;$(BoldDelphi)\Source\UMLModel\Handles;$(BoldDelphi)\Source\UMLModel\Ide;$(BoldDelphi)\Source\UMLModel\ModelLinks;$(BoldDelphi)\Source\UMLModel\Plugins;$(BoldDelphi)\Source\UMLModel\ModelLinks\Bld;$(BoldDelphi)\Source\UMLModel\ModelLinks\Core;$(BoldDelphi)\Source\UMLModel\ModelLinks\ModelMaker;$(BoldDelphi)\Source\UMLModel\ModelLinks\Rose98;$(BoldDelphi)\Source\UMLModel\ModelLinks\XMI;$(BoldDelphi)\Source\UMLModel\ModelLinks\ModelMaker\Link;$(BoldDelphi)\Source\UMLModel\ModelLinks\ModelMaker\MMPlugin;$(BoldDelphi)\Source\UMLModel\ModelLinks\ModelMaker\Support;$(BoldDelphi)\Source\ValueSpace\Condition;$(BoldDelphi)\Source\ValueSpace\ExternalEvents;$(BoldDelphi)\Source\ValueSpace\Id;$(BoldDelphi)\Source\ValueSpace\Interfaces;$(BoldDelphi)\Source\ValueSpace\XMLStreaming;$(DCC_UnitSearchPath) + 2077 + CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments= + true + true + true + true + true + Bold for Delphi Design Package + true + true + + + Debug + true + 1033 + vcl;IndySystem;IndyCore;vcldb;FireDAC;FireDACCommonDriver;FireDACCommon;FireDACPgDriver;$(DCC_UsePackage) + + + vcl;IndySystem;IndyCore;vcldb;FireDAC;FireDACCommonDriver;FireDACCommon;FireDACPgDriver;$(DCC_UsePackage) + + + DEBUG;$(DCC_Define) + true + false + true + true + true + + + false + true + 1033 + Bold for Delphi + 27 + + + false + RELEASE;$(DCC_Define) + 0 + 0 + + + true + 1033 + + + + MainSource + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Cfg_2 + Base + + + Base + + + Cfg_1 + Base + + + + Delphi.Personality.12 + Package + + + + dclBold.dpk + + + Bold For Delphi - Core + Attracs Components for Delphi 10.4 Sydney + Microsoft Office 2000 Sample Automation Server Wrapper Components + Microsoft Office XP Sample Automation Server Wrapper Components + + + + + + true + + + + + true + + + + + true + + + + + dclBold.bpl + true + + + + + 1 + + + 0 + + + + + classes + 1 + + + classes + 1 + + + + + res\xml + 1 + + + res\xml + 1 + + + + + library\lib\armeabi-v7a + 1 + + + + + library\lib\armeabi + 1 + + + library\lib\armeabi + 1 + + + + + library\lib\armeabi-v7a + 1 + + + + + library\lib\mips + 1 + + + library\lib\mips + 1 + + + + + library\lib\armeabi-v7a + 1 + + + library\lib\arm64-v8a + 1 + + + + + library\lib\armeabi-v7a + 1 + + + + + res\drawable + 1 + + + res\drawable + 1 + + + + + res\values + 1 + + + res\values + 1 + + + + + res\values-v21 + 1 + + + res\values-v21 + 1 + + + + + res\values + 1 + + + res\values + 1 + + + + + res\drawable + 1 + + + res\drawable + 1 + + + + + res\drawable-xxhdpi + 1 + + + res\drawable-xxhdpi + 1 + + + + + res\drawable-xxxhdpi + 1 + + + res\drawable-xxxhdpi + 1 + + + + + res\drawable-ldpi + 1 + + + res\drawable-ldpi + 1 + + + + + res\drawable-mdpi + 1 + + + res\drawable-mdpi + 1 + + + + + res\drawable-hdpi + 1 + + + res\drawable-hdpi + 1 + + + + + res\drawable-xhdpi + 1 + + + res\drawable-xhdpi + 1 + + + + + res\drawable-mdpi + 1 + + + res\drawable-mdpi + 1 + + + + + res\drawable-hdpi + 1 + + + res\drawable-hdpi + 1 + + + + + res\drawable-xhdpi + 1 + + + res\drawable-xhdpi + 1 + + + + + res\drawable-xxhdpi + 1 + + + res\drawable-xxhdpi + 1 + + + + + res\drawable-xxxhdpi + 1 + + + res\drawable-xxxhdpi + 1 + + + + + res\drawable-small + 1 + + + res\drawable-small + 1 + + + + + res\drawable-normal + 1 + + + res\drawable-normal + 1 + + + + + res\drawable-large + 1 + + + res\drawable-large + 1 + + + + + res\drawable-xlarge + 1 + + + res\drawable-xlarge + 1 + + + + + res\values + 1 + + + res\values + 1 + + + + + 1 + + + 1 + + + 0 + + + + + 1 + .framework + + + 1 + .framework + + + 0 + + + + + 1 + .dylib + + + 1 + .dylib + + + 0 + .dll;.bpl + + + + + 1 + .dylib + + + 1 + .dylib + + + 1 + .dylib + + + 1 + .dylib + + + 1 + .dylib + + + 0 + .bpl + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + 1 + + + 1 + + + + + ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF + 1 + + + ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF + 1 + + + + + + + + 1 + + + 1 + + + 1 + + + + + + + + Contents\Resources + 1 + + + Contents\Resources + 1 + + + + + library\lib\armeabi-v7a + 1 + + + library\lib\arm64-v8a + 1 + + + 1 + + + 1 + + + 1 + + + 1 + + + 1 + + + 1 + + + 0 + + + + + library\lib\armeabi-v7a + 1 + + + + + 1 + + + 1 + + + + + Assets + 1 + + + Assets + 1 + + + + + Assets + 1 + + + Assets + 1 + + + + + + + + + + + + + + + True + False + + + 12 + + + + + diff --git a/dclBoldDevEx.dpk b/dclBoldDevEx.dpk new file mode 100644 index 0000000..e3958c8 --- /dev/null +++ b/dclBoldDevEx.dpk @@ -0,0 +1,56 @@ +package dclBoldDevEx; + +{$R *.res} +{$R 'Source\BoldAwareGUI\BoldDevex\cxBoldRegUnit.dcr'} +{$IFDEF IMPLICITBUILDING This IFDEF should not be used by users} +{$ALIGN 8} +{$ASSERTIONS ON} +{$BOOLEVAL OFF} +{$DEBUGINFO OFF} +{$EXTENDEDSYNTAX ON} +{$IMPORTEDDATA ON} +{$IOCHECKS ON} +{$LOCALSYMBOLS ON} +{$LONGSTRINGS ON} +{$OPENSTRINGS ON} +{$OPTIMIZATION OFF} +{$OVERFLOWCHECKS OFF} +{$RANGECHECKS OFF} +{$REFERENCEINFO ON} +{$SAFEDIVIDE OFF} +{$STACKFRAMES ON} +{$TYPEDADDRESS OFF} +{$VARSTRINGCHECKS ON} +{$WRITEABLECONST OFF} +{$MINENUMSIZE 1} +{$IMAGEBASE $400000} +{$DEFINE DEBUG} +{$ENDIF IMPLICITBUILDING} +{$DESCRIPTION 'Bold For Delphi (DevEx controls)'} +{$LIBVERSION '27'} +{$DESIGNONLY} +{$IMPLICITBUILD ON} + +requires + rtl, + dclBold, + dclcxGridRS27, + dxBarRS27; + +contains + BoldAFPCxGridProviderUnit in 'Source\BoldAwareGUI\BoldDevex\BoldAFPCxGridProviderUnit.pas', + BoldToCxConverterForm in 'Source\BoldAwareGUI\BoldDevex\BoldToCxConverterForm.pas' {frmBoldToCxConverter}, + BoldToCxConverterUnit in 'Source\BoldAwareGUI\BoldDevex\BoldToCxConverterUnit.pas', + BoldToCxGridConverterUnit in 'Source\BoldAwareGUI\BoldDevex\BoldToCxGridConverterUnit.pas', + cxBoldEditConsts in 'Source\BoldAwareGUI\BoldDevex\cxBoldEditConsts.pas', + cxBoldEditors in 'Source\BoldAwareGUI\BoldDevex\cxBoldEditors.pas', + cxBoldEditRepositoryItems in 'Source\BoldAwareGUI\BoldDevex\cxBoldEditRepositoryItems.pas', + cxBoldExtLookupComboBox in 'Source\BoldAwareGUI\BoldDevex\cxBoldExtLookupComboBox.pas', + cxBoldLookupComboBox in 'Source\BoldAwareGUI\BoldDevex\cxBoldLookupComboBox.pas', + cxBoldLookupEdit in 'Source\BoldAwareGUI\BoldDevex\cxBoldLookupEdit.pas', + cxBoldRegUnit in 'Source\BoldAwareGUI\BoldDevex\cxBoldRegUnit.pas', + cxGridBoldSupportUnit in 'Source\BoldAwareGUI\BoldDevex\cxGridBoldSupportUnit.pas', + cxLookupBoldGrid in 'Source\BoldAwareGUI\BoldDevex\cxLookupBoldGrid.pas', + dxBarBoldNav in 'Source\BoldAwareGUI\BoldDevex\dxBarBoldNav.pas'; + +end. diff --git a/dclBoldDevEx.dproj b/dclBoldDevEx.dproj new file mode 100644 index 0000000..576423b --- /dev/null +++ b/dclBoldDevEx.dproj @@ -0,0 +1,878 @@ + + + {58D5CA38-AC66-4CE0-9BB3-80CAB1DE12EE} + dclBoldDevEx.dpk + 19.2 + VCL + True + Debug + Win32 + 1 + Package + + + true + + + true + Base + true + + + true + Base + true + + + true + Base + true + + + true + Cfg_1 + true + true + + + true + Base + true + + + true + Cfg_2 + true + true + + + .\$(Platform)\$(Config) + .\$(Platform)\$(Config) + false + false + false + false + false + true + true + Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;System;Xml;Data;Datasnap;Web;Soap;Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;$(DCC_Namespace) + All + dclBoldDevEx + Source\Common\Include\;$(DCC_UnitSearchPath) + 2077 + CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments= + Bold DevEx Controls + true + + + Debug + true + 1033 + rtl;dxBarRS27;BoldRuntimePackage;$(DCC_UsePackage) + + + rtl;dxBarRS27;BoldRuntimePackage;$(DCC_UsePackage) + + + DEBUG;$(DCC_Define) + true + false + true + true + true + + + false + true + 1033 + Bold For Delphi (DevEx controls) + 27 + + + false + RELEASE;$(DCC_Define) + 0 + 0 + + + true + 1033 + + + + MainSource + + + + + + + + +
frmBoldToCxConverter
+
+ + + + + + + + + + + + + + Cfg_2 + Base + + + Base + + + Cfg_1 + Base + +
+ + Delphi.Personality.12 + Package + + + + dclBoldDevEx.dpk + + + Bold For Delphi - Core + Attracs Components for Delphi 10.4 Sydney + Microsoft Office 2000 Sample Automation Server Wrapper Components + Microsoft Office XP Sample Automation Server Wrapper Components + + + + + + true + + + + + true + + + + + true + + + + + dclBoldDevEx.bpl + true + + + + + 1 + + + 0 + + + + + classes + 1 + + + classes + 1 + + + + + res\xml + 1 + + + res\xml + 1 + + + + + library\lib\armeabi-v7a + 1 + + + + + library\lib\armeabi + 1 + + + library\lib\armeabi + 1 + + + + + library\lib\armeabi-v7a + 1 + + + + + library\lib\mips + 1 + + + library\lib\mips + 1 + + + + + library\lib\armeabi-v7a + 1 + + + library\lib\arm64-v8a + 1 + + + + + library\lib\armeabi-v7a + 1 + + + + + res\drawable + 1 + + + res\drawable + 1 + + + + + res\values + 1 + + + res\values + 1 + + + + + res\values-v21 + 1 + + + res\values-v21 + 1 + + + + + res\values + 1 + + + res\values + 1 + + + + + res\drawable + 1 + + + res\drawable + 1 + + + + + res\drawable-xxhdpi + 1 + + + res\drawable-xxhdpi + 1 + + + + + res\drawable-xxxhdpi + 1 + + + res\drawable-xxxhdpi + 1 + + + + + res\drawable-ldpi + 1 + + + res\drawable-ldpi + 1 + + + + + res\drawable-mdpi + 1 + + + res\drawable-mdpi + 1 + + + + + res\drawable-hdpi + 1 + + + res\drawable-hdpi + 1 + + + + + res\drawable-xhdpi + 1 + + + res\drawable-xhdpi + 1 + + + + + res\drawable-mdpi + 1 + + + res\drawable-mdpi + 1 + + + + + res\drawable-hdpi + 1 + + + res\drawable-hdpi + 1 + + + + + res\drawable-xhdpi + 1 + + + res\drawable-xhdpi + 1 + + + + + res\drawable-xxhdpi + 1 + + + res\drawable-xxhdpi + 1 + + + + + res\drawable-xxxhdpi + 1 + + + res\drawable-xxxhdpi + 1 + + + + + res\drawable-small + 1 + + + res\drawable-small + 1 + + + + + res\drawable-normal + 1 + + + res\drawable-normal + 1 + + + + + res\drawable-large + 1 + + + res\drawable-large + 1 + + + + + res\drawable-xlarge + 1 + + + res\drawable-xlarge + 1 + + + + + res\values + 1 + + + res\values + 1 + + + + + 1 + + + 1 + + + 0 + + + + + 1 + .framework + + + 1 + .framework + + + 0 + + + + + 1 + .dylib + + + 1 + .dylib + + + 0 + .dll;.bpl + + + + + 1 + .dylib + + + 1 + .dylib + + + 1 + .dylib + + + 1 + .dylib + + + 1 + .dylib + + + 0 + .bpl + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + ..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset + 1 + + + + + 1 + + + 1 + + + + + ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF + 1 + + + ..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF + 1 + + + + + + + + 1 + + + 1 + + + 1 + + + + + + + + Contents\Resources + 1 + + + Contents\Resources + 1 + + + + + library\lib\armeabi-v7a + 1 + + + library\lib\arm64-v8a + 1 + + + 1 + + + 1 + + + 1 + + + 1 + + + 1 + + + 1 + + + 0 + + + + + library\lib\armeabi-v7a + 1 + + + + + 1 + + + 1 + + + + + Assets + 1 + + + Assets + 1 + + + + + Assets + 1 + + + Assets + 1 + + + + + + + + + + + + + + + True + False + + + 12 + + + + +
diff --git a/BoldFireDAC.dpk b/dclBoldUniDAC.dpk similarity index 52% rename from BoldFireDAC.dpk rename to dclBoldUniDAC.dpk index 455b3ff..c0a4b33 100644 --- a/BoldFireDAC.dpk +++ b/dclBoldUniDAC.dpk @@ -1,4 +1,4 @@ -package BoldFireDAC; +package dclBoldUniDAC; {$R *.res} {$IFDEF IMPLICITBUILDING This IFDEF should not be used by users} @@ -25,22 +25,22 @@ package BoldFireDAC; {$IMAGEBASE $400000} {$DEFINE DEBUG} {$ENDIF IMPLICITBUILDING} -{$DESCRIPTION 'Bold 4.0 for Delphi (FireDAC Support)'} +{$DESCRIPTION 'Bold for Delphi (UniDAC Support)'} +{$LIBVERSION '27'} {$DESIGNONLY} {$IMPLICITBUILD ON} requires rtl, vcldb, - FireDAC, + ibxpress, DesignIDE, - Bold; + dclBold; contains - BoldPersistenceHandleFireDAC in 'Source\Persistence\FireDAC\BoldPersistenceHandleFireDAC.pas', - BoldPersistenceHandleFireDACReg in 'Source\Persistence\FireDAC\BoldPersistenceHandleFireDACReg.pas', - BoldDatabaseAdapterFireDAC in 'Source\Persistence\FireDAC\BoldDatabaseAdapterFireDAC.pas', - BoldFireDACInterfaces in 'Source\Persistence\FireDAC\BoldFireDACInterfaces.pas', - BoldFireDACConsts in 'Source\Persistence\FireDAC\BoldFireDACConsts.pas'; + BoldPersistenceHandleUniDACReg in 'Source\Persistence\UniDAC\BoldPersistenceHandleUniDACReg.pas', + BoldUniDACInterfaces in 'Source\Persistence\UniDAC\BoldUniDACInterfaces.pas', + UniDACConsts in 'Source\Persistence\UniDAC\UniDACConsts.pas', + BoldDatabaseAdapterUniDAC in 'Source\Persistence\UniDAC\BoldDatabaseAdapterUniDAC.pas'; end. diff --git a/BoldFireDAC.dproj b/dclBoldUniDAC.dproj similarity index 95% rename from BoldFireDAC.dproj rename to dclBoldUniDAC.dproj index 841188e..668fd18 100644 --- a/BoldFireDAC.dproj +++ b/dclBoldUniDAC.dproj @@ -1,7 +1,7 @@  - {34E63FCA-EC80-4315-BAF9-24523C7226CD} - BoldFireDAC.dpk + {62DD6777-B230-4653-9B18-180B21451307} + dclBoldUniDAC.dpk 19.2 None True @@ -39,6 +39,12 @@ Base true + + true + Cfg_2 + true + true + .\$(Platform)\$(Config) .\$(Platform)\$(Config) @@ -49,25 +55,22 @@ false true true - Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;System;Xml;Data;Datasnap;Web;Soap;Winapi;$(DCC_Namespace) + System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell;System;Xml;Data;Datasnap;Web;Soap;Winapi;$(DCC_Namespace) All - BoldFireDAC - $(BoldDelphi)\Source\Common\Include;$(BDS)\Source\data\firedac;$(DCC_UnitSearchPath) + dclBoldUniDAC + true + $(BoldDelphi)\Source\Common\Include;C:\Attracs\Attracs-Common\components\UniDAC\Source;C:\Attracs\Attracs-Common\components\UniDAC\Source\UniProviders\SQLServer;C:\Attracs\Attracs-Common\components\UniDAC\Source\UniProviders\TDS;$(DCC_UnitSearchPath) 2077 CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments= - Bold 4.0 for Delphi (FireDAC Support) - true - System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace) Debug true - CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments= 1033 - rtl;vcldb;FireDAC;$(DCC_UsePackage) + rtl;vcldb;ibxpress;$(DCC_UsePackage) - rtl;vcldb;FireDAC;$(DCC_UsePackage) + rtl;vcldb;ibxpress;$(DCC_UsePackage) DEBUG;$(DCC_Define) @@ -81,6 +84,8 @@ false true 1033 + Bold for Delphi (UniDAC Support) + 27 false @@ -88,20 +93,23 @@ 0 0 + + true + 1033 + MainSource - + - - - - - - + + + + + Cfg_2 Base @@ -120,9 +128,10 @@ - BoldFireDAC.dpk + dclBoldUniDAC.dpk + Bold For Delphi - Core Attracs Components for Delphi 10.4 Sydney Microsoft Office 2000 Sample Automation Server Wrapper Components Microsoft Office XP Sample Automation Server Wrapper Components @@ -144,9 +153,9 @@ true - + - BoldFireDAC.bpl + dclBoldUniDAC.bpl true From 17c94a8e7eec1ecb080b13817bfcbeba52ee6c9d Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Sun, 23 May 2021 22:15:12 +0300 Subject: [PATCH 073/112] Updated Buildings demo --- examples/Delphi/Compound/Building/Datamod.dfm | 12 ++++++------ examples/Delphi/Compound/Building/Mainform.dfm | 1 + examples/Delphi/Compound/Building/Mainform.pas | 3 ++- .../Delphi/Compound/Building/PersonAutoFormUnit.dfm | 3 +++ 4 files changed, 12 insertions(+), 7 deletions(-) diff --git a/examples/Delphi/Compound/Building/Datamod.dfm b/examples/Delphi/Compound/Building/Datamod.dfm index 213f765..5e73f60 100644 --- a/examples/Delphi/Compound/Building/Datamod.dfm +++ b/examples/Delphi/Compound/Building/Datamod.dfm @@ -413,11 +413,11 @@ object DataModule1: TDataModule1 SQLDatabaseConfig.ColumnTypeForSmallInt = 'SMALLINT' SQLDatabaseConfig.ColumnTypeForInt64 = 'BIGINT' SQLDatabaseConfig.ColumnTypeForGUID = 'UUID' - SQLDatabaseConfig.CreateDatabaseTemplate = 'CREATE DATABASE %s' - SQLDatabaseConfig.DropDatabaseTemplate = 'DROP DATABASE %s' + SQLDatabaseConfig.CreateDatabaseTemplate = 'CREATE DATABASE ' + SQLDatabaseConfig.DropDatabaseTemplate = 'DROP DATABASE ' SQLDatabaseConfig.DatabaseExistsTemplate = 'select exists(SELECT datname FROM pg_catalog.pg_database WHERE l' + - 'ower(datname) = lower('#39'%s'#39'));' + 'ower(datname) = lower('#39''#39'));' SQLDatabaseConfig.DropColumnTemplate = 'ALTER TABLE DROP ' SQLDatabaseConfig.DropTableTemplate = 'DROP TABLE ' SQLDatabaseConfig.IndexInfoTemplate = @@ -580,11 +580,11 @@ object DataModule1: TDataModule1 SQLDatabaseConfig.ColumnTypeForSmallInt = 'SMALLINT' SQLDatabaseConfig.ColumnTypeForInt64 = 'BIGINT' SQLDatabaseConfig.ColumnTypeForGUID = 'UNIQUEIDENTIFIER' - SQLDatabaseConfig.CreateDatabaseTemplate = 'CREATE DATABASE %s' - SQLDatabaseConfig.DropDatabaseTemplate = 'DROP DATABASE %s' + SQLDatabaseConfig.CreateDatabaseTemplate = 'USE MASTER;GO;CREATE DATABASE ' + SQLDatabaseConfig.DropDatabaseTemplate = 'DROP DATABASE ' SQLDatabaseConfig.DatabaseExistsTemplate = 'IF EXISTS (SELECT name FROM master.sys.databases WHERE name = N'#39 + - '%s'#39')' + ''#39')' SQLDatabaseConfig.DropColumnTemplate = 'DECLARE @CONSTRAINTNAME NVARCHAR(200) SELECT @CONSTRAINTNAME=OD.' + 'NAME FROM SYSOBJECTS OT, SYSCOLUMNS C, SYSOBJECTS OD WHERE' + diff --git a/examples/Delphi/Compound/Building/Mainform.dfm b/examples/Delphi/Compound/Building/Mainform.dfm index 9f68953..9360eea 100644 --- a/examples/Delphi/Compound/Building/Mainform.dfm +++ b/examples/Delphi/Compound/Building/Mainform.dfm @@ -905,6 +905,7 @@ object allform: Tallform end object BoldPersistenceProgressNotifier1: TBoldPersistenceProgressNotifier WinControl = StatusBar1 + ProgressBar = pbdbNotification AnimationInterval = 100 PersistenceHandle = DataModule1.BoldPersistenceHandleDB1 MsgFetchObjects = 'Fetching objects' diff --git a/examples/Delphi/Compound/Building/Mainform.pas b/examples/Delphi/Compound/Building/Mainform.pas index 95afe30..129dec8 100644 --- a/examples/Delphi/Compound/Building/Mainform.pas +++ b/examples/Delphi/Compound/Building/Mainform.pas @@ -47,7 +47,8 @@ interface BoldDebugActions, BoldUndoActions, BoldCaptionController, - BoldAction, BoldFormSaverActions; + BoldAction, + BoldFormSaverActions; type Tallform = class(TForm) diff --git a/examples/Delphi/Compound/Building/PersonAutoFormUnit.dfm b/examples/Delphi/Compound/Building/PersonAutoFormUnit.dfm index 1e49afe..935b89a 100644 --- a/examples/Delphi/Compound/Building/PersonAutoFormUnit.dfm +++ b/examples/Delphi/Compound/Building/PersonAutoFormUnit.dfm @@ -270,6 +270,7 @@ object PersonAutoForm: TPersonAutoForm Width = 75 Height = 25 Action = BoldFormSaverOkAction1 + Default = True TabOrder = 8 end object Button3: TButton @@ -278,9 +279,11 @@ object PersonAutoForm: TPersonAutoForm Width = 75 Height = 25 Action = BoldFormSaverCancelAction1 + Cancel = True TabOrder = 9 end object brhPerson: TBoldReferenceHandle + StaticSystemHandle = DataModule1.BoldSystemHandle1 StaticValueTypeName = 'Person' OnObjectDeleted = brhPersonObjectDeleted OnValueDestroyed = brhPersonObjectDeleted From 0eccdd7999d578110c694be7ab4b7e69eb128ee6 Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Sun, 23 May 2021 22:15:53 +0300 Subject: [PATCH 074/112] fix potential index out of bounds --- Source/BoldAwareGUI/BoldControls/BoldGrid.pas | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/BoldAwareGUI/BoldControls/BoldGrid.pas b/Source/BoldAwareGUI/BoldControls/BoldGrid.pas index cf75b70..6f0e230 100644 --- a/Source/BoldAwareGUI/BoldControls/BoldGrid.pas +++ b/Source/BoldAwareGUI/BoldControls/BoldGrid.pas @@ -1975,7 +1975,7 @@ procedure TBoldCustomGrid.TopLeftChanged; function TBoldCustomGrid.GetRowFollower(DataRow: Integer): TBoldFollower; begin - if datarow < Follower.SubFollowerCount then + if (DataRow >= 0) and (datarow < Follower.SubFollowerCount) then begin Result := Follower.SubFollowers[DataRow]; end From 596a43e74bd4d69f776c8278944d5e8f723ddb90 Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Sun, 23 May 2021 22:16:10 +0300 Subject: [PATCH 075/112] More logical action behaviour --- .../Samples/FormSaver/BoldFormSaverActions.pas | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/Source/Samples/FormSaver/BoldFormSaverActions.pas b/Source/Samples/FormSaver/BoldFormSaverActions.pas index a3f94f8..5d0891b 100644 --- a/Source/Samples/FormSaver/BoldFormSaverActions.pas +++ b/Source/Samples/FormSaver/BoldFormSaverActions.pas @@ -91,13 +91,7 @@ procedure TBoldFormSaverAction.SetBoldFormSaver(const Value: TBoldFormSaver); procedure TBoldFormSaverApplyAction.CheckAllowEnable(var EnableAction: boolean); begin inherited; - if EnableAction then - begin - if BoldFormSaver.DirtyObjects.Empty then - Caption := '&Close' - else - Caption := '&Apply' - end; + EnableAction := EnableAction and not BoldFormSaver.DirtyObjects.Empty; end; constructor TBoldFormSaverApplyAction.Create(AOwner: TComponent); @@ -145,13 +139,7 @@ procedure TBoldFormSaverCancelAction.ExecuteTarget(Target: TObject); procedure TBoldFormSaverOkAction.CheckAllowEnable(var EnableAction: boolean); begin inherited; - if EnableAction then - begin - if BoldFormSaver.DirtyObjects.Empty then - Caption := '&Close' - else - Caption := '&OK' - end; + EnableAction := EnableAction and not BoldFormSaver.DirtyObjects.Empty; end; constructor TBoldFormSaverOkAction.Create(AOwner: TComponent); From 219046ed6a3f76ea1ef319c08ee9a26bcd2a1189 Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Sun, 23 May 2021 22:18:34 +0300 Subject: [PATCH 076/112] Updated project files --- dclBold.dproj | 4 ++-- dclBoldDevEx.dpk | 2 +- dclBoldDevEx.dproj | 7 +++---- dclBoldUniDAC.dpk | 2 +- dclBoldUniDAC.dproj | 3 +-- 5 files changed, 8 insertions(+), 10 deletions(-) diff --git a/dclBold.dproj b/dclBold.dproj index bc04036..9a0f681 100644 --- a/dclBold.dproj +++ b/dclBold.dproj @@ -74,10 +74,10 @@ Debug true 1033 - vcl;IndySystem;IndyCore;vcldb;FireDAC;FireDACCommonDriver;FireDACCommon;FireDACPgDriver;$(DCC_UsePackage) + vcl;IndySystem;IndyCore;vcldb;FireDAC;FireDACCommonDriver;FireDACCommon;FireDACPgDriver;BoldCore;BoldAdditional;$(DCC_UsePackage) - vcl;IndySystem;IndyCore;vcldb;FireDAC;FireDACCommonDriver;FireDACCommon;FireDACPgDriver;$(DCC_UsePackage) + vcl;IndySystem;IndyCore;vcldb;FireDAC;FireDACCommonDriver;FireDACCommon;FireDACPgDriver;BoldCore;BoldAdditional;$(DCC_UsePackage) DEBUG;$(DCC_Define) diff --git a/dclBoldDevEx.dpk b/dclBoldDevEx.dpk index e3958c8..528e22e 100644 --- a/dclBoldDevEx.dpk +++ b/dclBoldDevEx.dpk @@ -29,7 +29,7 @@ package dclBoldDevEx; {$DESCRIPTION 'Bold For Delphi (DevEx controls)'} {$LIBVERSION '27'} {$DESIGNONLY} -{$IMPLICITBUILD ON} +{$IMPLICITBUILD OFF} requires rtl, diff --git a/dclBoldDevEx.dproj b/dclBoldDevEx.dproj index 576423b..1ccbd37 100644 --- a/dclBoldDevEx.dproj +++ b/dclBoldDevEx.dproj @@ -63,15 +63,16 @@ CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments= Bold DevEx Controls true + true Debug true 1033 - rtl;dxBarRS27;BoldRuntimePackage;$(DCC_UsePackage) + rtl;dxBarRS27;$(DCC_UsePackage) - rtl;dxBarRS27;BoldRuntimePackage;$(DCC_UsePackage) + rtl;dxBarRS27;$(DCC_UsePackage) DEBUG;$(DCC_Define) @@ -144,8 +145,6 @@ dclBoldDevEx.dpk - Bold For Delphi - Core - Attracs Components for Delphi 10.4 Sydney Microsoft Office 2000 Sample Automation Server Wrapper Components Microsoft Office XP Sample Automation Server Wrapper Components diff --git a/dclBoldUniDAC.dpk b/dclBoldUniDAC.dpk index c0a4b33..ee3d7f7 100644 --- a/dclBoldUniDAC.dpk +++ b/dclBoldUniDAC.dpk @@ -28,7 +28,7 @@ package dclBoldUniDAC; {$DESCRIPTION 'Bold for Delphi (UniDAC Support)'} {$LIBVERSION '27'} {$DESIGNONLY} -{$IMPLICITBUILD ON} +{$IMPLICITBUILD OFF} requires rtl, diff --git a/dclBoldUniDAC.dproj b/dclBoldUniDAC.dproj index 668fd18..8dc0a19 100644 --- a/dclBoldUniDAC.dproj +++ b/dclBoldUniDAC.dproj @@ -62,6 +62,7 @@ $(BoldDelphi)\Source\Common\Include;C:\Attracs\Attracs-Common\components\UniDAC\Source;C:\Attracs\Attracs-Common\components\UniDAC\Source\UniProviders\SQLServer;C:\Attracs\Attracs-Common\components\UniDAC\Source\UniProviders\TDS;$(DCC_UnitSearchPath) 2077 CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments= + true Debug @@ -131,8 +132,6 @@ dclBoldUniDAC.dpk - Bold For Delphi - Core - Attracs Components for Delphi 10.4 Sydney Microsoft Office 2000 Sample Automation Server Wrapper Components Microsoft Office XP Sample Automation Server Wrapper Components From 84e1017140f6f33a83210a56cd4492ce2241b1e2 Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Sun, 23 May 2021 22:19:09 +0300 Subject: [PATCH 077/112] Fixed case warning --- Source/Extensions/OLLE/Core/BoldOLLEController.pas | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Extensions/OLLE/Core/BoldOLLEController.pas b/Source/Extensions/OLLE/Core/BoldOLLEController.pas index 7ef784a..c72e062 100644 --- a/Source/Extensions/OLLE/Core/BoldOLLEController.pas +++ b/Source/Extensions/OLLE/Core/BoldOLLEController.pas @@ -26,7 +26,7 @@ TBoldPHandleMimic = class(TBoldAbstractPersistenceHandleDB) function GetSQLDatabaseConfig: TBoldSQLDatabaseConfig; override; function GetCustomIndexes: TBoldIndexCollection; override; public - destructor destroy; override; + destructor Destroy; override; end; TBoldOLLEController = class @@ -94,7 +94,7 @@ procedure TBoldOLLEController.SetPersistent(const Value: Boolean); { TBoldPHandleMimic } -destructor TBoldPHandleMimic.destroy; +destructor TBoldPHandleMimic.Destroy; begin FreeAndNil(fSQLDatabaseConfig); FreeAndNil(fCustomIndexes); From f009c56528558d964096af75342d7527e28d1171 Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Sun, 23 May 2021 22:20:25 +0300 Subject: [PATCH 078/112] Cleaned up conditionals --- Source/Common/Include/Bold.inc | 29 ++--------------------------- 1 file changed, 2 insertions(+), 27 deletions(-) diff --git a/Source/Common/Include/Bold.inc b/Source/Common/Include/Bold.inc index 5a753e2..83f631f 100644 --- a/Source/Common/Include/Bold.inc +++ b/Source/Common/Include/Bold.inc @@ -1,31 +1,6 @@ -{$WARNINGS OFF} -{$HINTS OFF} -{$WARN SYMBOL_PLATFORM OFF} -{$WARN UNIT_PLATFORM OFF} - -{$IFDEF WIN32} - {$DEFINE MSWINDOWS} -{$ENDIF} - -{$IFDEF WIN64} - {$DEFINE MSWINDOWS} -{$ENDIF} - -{$IFDEF BOLD_ARCHITECT} - {$UNDEF BOLD_LICENSE} -{$ENDIF} - -{$IFDEF BOLD_DELPHI_PARSER} - {$DEFINE WIN32} - {$DEFINE VER130} -{$ENDIF} - -// LicenseManager cannot be compiled with BOLD_BCB defined for some reason... -{$IFDEF BOLD_LICENSEMANAGER} - {$DEFINE DELPHI} - {$UNDEF BCB} -{$ENDIF} +{.$WARN SYMBOL_PLATFORM OFF} +{.$WARN UNIT_PLATFORM OFF} {$IFDEF BCB} {$DEFINE BOLD_BCB} From 6363ddc74b32bae530c0223b650825b7f8c22e66 Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Sun, 23 May 2021 22:21:01 +0300 Subject: [PATCH 079/112] Updated signature of CreateDatabase --- Source/Persistence/UniDAC/BoldDatabaseAdapterUniDAC.pas | 6 +++--- Source/Persistence/UniDAC/BoldUniDACInterfaces.pas | 6 ++++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/Source/Persistence/UniDAC/BoldDatabaseAdapterUniDAC.pas b/Source/Persistence/UniDAC/BoldDatabaseAdapterUniDAC.pas index e250d69..0237bf3 100644 --- a/Source/Persistence/UniDAC/BoldDatabaseAdapterUniDAC.pas +++ b/Source/Persistence/UniDAC/BoldDatabaseAdapterUniDAC.pas @@ -26,7 +26,7 @@ TBoldDatabaseAdapterUniDAC = class(TBoldAbstractDatabaseAdapter) function GetDataBaseInterface: IBoldDatabase; override; public destructor Destroy; override; - procedure CreateDatabase; override; + procedure CreateDatabase(DropExisting: boolean = true); override; procedure DropDatabase; override; published property Connection: TUniConnection read GetConnection write SetConnection; @@ -58,9 +58,9 @@ procedure TBoldDatabaseAdapterUniDAC.DropDatabase; DatabaseInterface.DropDatabase; end; -procedure TBoldDatabaseAdapterUniDAC.CreateDatabase; +procedure TBoldDatabaseAdapterUniDAC.CreateDatabase(DropExisting: boolean); begin - DatabaseInterface.CreateDatabase; + DatabaseInterface.CreateDatabase(DropExisting); end; function TBoldDatabaseAdapterUniDAC.GetConnection: TUniConnection; diff --git a/Source/Persistence/UniDAC/BoldUniDACInterfaces.pas b/Source/Persistence/UniDAC/BoldUniDACInterfaces.pas index edd0238..a4ac151 100644 --- a/Source/Persistence/UniDAC/BoldUniDACInterfaces.pas +++ b/Source/Persistence/UniDAC/BoldUniDACInterfaces.pas @@ -232,7 +232,7 @@ TBoldUniDACConnection = class(TBoldDatabaseWrapper, IBoldDataBase) public constructor Create(aUniConnection: TUniConnection; SQLDataBaseConfig: TBoldSQLDatabaseConfig); destructor Destroy; override; - procedure CreateDatabase; override; + procedure CreateDatabase(DropExisting: boolean = true); override; procedure DropDatabase; override; function DatabaseExists: boolean; override; function GetDatabaseError(const E: Exception; const sSQL: string = ''): @@ -959,12 +959,14 @@ procedure TBoldUniDACConnection.Close; UniConnection.Close; end; -procedure TBoldUniDACConnection.CreateDatabase; +procedure TBoldUniDACConnection.CreateDatabase(DropExisting: boolean); var vDatabaseName: string; vUniScript: TUniScript; begin vDatabaseName := LowerCase(UniConnection.Database); + if DropExisting and DatabaseExists then + DropDatabase; // UniConnection.Database := ''; // need to clear this to connect succesfully vUniScript := TUniScript.Create(nil); try From 0d97f0a77d0a0fba5c2281765e8261edbaa1f8d7 Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Sun, 23 May 2021 22:25:12 +0300 Subject: [PATCH 080/112] Fixed wrong button position --- .../PMapper/DbEvolutor/BoldDbEvolutorForm.dfm | 47 ++++++++++--------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/Source/PMapper/DbEvolutor/BoldDbEvolutorForm.dfm b/Source/PMapper/DbEvolutor/BoldDbEvolutorForm.dfm index 20ee15e..2fd4618 100644 --- a/Source/PMapper/DbEvolutor/BoldDbEvolutorForm.dfm +++ b/Source/PMapper/DbEvolutor/BoldDbEvolutorForm.dfm @@ -2,6 +2,8 @@ object frmBoldDbEvolutor: TfrmBoldDbEvolutor Left = 510 Top = 257 Caption = 'Db Evolution' + ClientHeight = 387 + ClientWidth = 460 Color = clBtnFace Constraints.MinHeight = 200 Constraints.MinWidth = 322 @@ -41,15 +43,15 @@ object frmBoldDbEvolutor: TfrmBoldDbEvolutor OnCreate = FormCreate OnDestroy = FormDestroy DesignSize = ( - 624 - 445) + 460 + 387) PixelsPerInch = 96 TextHeight = 13 object PageControl1: TPageControl - Left = 0 - Top = 0 - Width = 632 - Height = 392 + Left = 4 + Top = 4 + Width = 450 + Height = 320 ActivePage = tsActions Anchors = [akLeft, akTop, akRight, akBottom] Images = ImageList1 @@ -59,8 +61,8 @@ object frmBoldDbEvolutor: TfrmBoldDbEvolutor object mmoActions: TMemo Left = 0 Top = 0 - Width = 624 - Height = 363 + Width = 442 + Height = 291 Align = alClient ReadOnly = True ScrollBars = ssBoth @@ -73,8 +75,8 @@ object frmBoldDbEvolutor: TfrmBoldDbEvolutor object mmoWarnings: TMemo Left = 0 Top = 0 - Width = 624 - Height = 363 + Width = 442 + Height = 291 Align = alClient ReadOnly = True ScrollBars = ssBoth @@ -87,8 +89,8 @@ object frmBoldDbEvolutor: TfrmBoldDbEvolutor object mmoSQLScript: TMemo Left = 0 Top = 0 - Width = 624 - Height = 363 + Width = 442 + Height = 291 Align = alClient ReadOnly = True ScrollBars = ssBoth @@ -101,8 +103,8 @@ object frmBoldDbEvolutor: TfrmBoldDbEvolutor object mmoMappingInfoScript: TMemo Left = 0 Top = 0 - Width = 624 - Height = 363 + Width = 442 + Height = 291 Align = alClient ReadOnly = True ScrollBars = ssBoth @@ -112,16 +114,16 @@ object frmBoldDbEvolutor: TfrmBoldDbEvolutor end object ProgressBar1: TProgressBar Left = 8 - Top = 397 - Width = 617 + Top = 330 + Width = 444 Height = 16 Anchors = [akLeft, akRight, akBottom] Smooth = True TabOrder = 1 end object btnCancel: TButton - Left = 539 - Top = 418 + Left = 371 + Top = 354 Width = 81 Height = 25 Anchors = [akRight, akBottom] @@ -130,8 +132,8 @@ object frmBoldDbEvolutor: TfrmBoldDbEvolutor TabOrder = 2 end object btnExecute: TButton - Left = 451 - Top = 418 + Left = 284 + Top = 354 Width = 81 Height = 25 Anchors = [akRight, akBottom] @@ -141,15 +143,14 @@ object frmBoldDbEvolutor: TfrmBoldDbEvolutor TabOrder = 3 end object btnSaveScript: TButton - Left = 367 - Top = 418 + Left = 523 + Top = 604 Width = 75 Height = 25 Anchors = [akRight, akBottom] Caption = 'Save scripts' TabOrder = 4 OnClick = btnSaveScriptClick - ExplicitTop = 414 end object ImageList1: TImageList Left = 52 From bc519952bcccd52c717aaeaa96e6e700e5625306 Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Sun, 23 May 2021 23:45:21 +0300 Subject: [PATCH 081/112] Filled ColumnExistsTemplate and IndexColumnExistsTemplate for Postgres --- Source/PMapper/SQL/BoldSQLDatabaseConfig.pas | 2 ++ Source/Samples/Actions/BoldDebugActions.pas | 3 +-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Source/PMapper/SQL/BoldSQLDatabaseConfig.pas b/Source/PMapper/SQL/BoldSQLDatabaseConfig.pas index cd1ad7e..59fbe49 100644 --- a/Source/PMapper/SQL/BoldSQLDatabaseConfig.pas +++ b/Source/PMapper/SQL/BoldSQLDatabaseConfig.pas @@ -933,6 +933,8 @@ procedure TBoldSQLDataBaseConfig.InitializeDbEngineSettings(Engine: TBoldDatabas fMaxIndexNameLength := 63; fMaxDbIdentifierLength := 63; fMultiRowInsertLimit := 1000; + ffIndexColumnExistsTemplate := 'select indexname from pg_indexes where upper(tablename) = upper('''')'; + FColumnExistsTemplate := 'SELECT column_name FROM information_schema.columns WHERE upper(table_name)=upper('''') and upper(column_name)=upper('''')'; // do not localize fDatabaseExistsTemplate := 'select exists(SELECT datname FROM pg_catalog.pg_database WHERE lower(datname) = lower(''''));'; // IndexInfoTemplate := 'select indexname from pg_indexes where tablename = '''''; // this is not complete IndexName, IsPrimary, IsUnique, ColumnName fReservedWords.Text := 'ALL, ANALYSE, AND, ANY, ARRAY, AS, ASC, ASYMMETRIC, AUTHORIZATION,'#10 + // do not localize diff --git a/Source/Samples/Actions/BoldDebugActions.pas b/Source/Samples/Actions/BoldDebugActions.pas index 3d8256d..4398ee6 100644 --- a/Source/Samples/Actions/BoldDebugActions.pas +++ b/Source/Samples/Actions/BoldDebugActions.pas @@ -195,6 +195,7 @@ constructor TBoldLogAction.Create(AOwner: TComponent); begin inherited; Caption := Format('Toggle %s logs', [LogType]); + ShortCut := TextToShortCut('Ctrl+L'); end; procedure TBoldLogAction.ExecuteTarget(Target: TObject); @@ -282,6 +283,4 @@ procedure TBoldLogOSSAction.SetLogHandler(Value: TBoldLogHandler); BoldOSSLogHandler := Value; end; -initialization - end. From 4d7926fdbe56ba9bd2fb9fd9cce022454579d150 Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Sun, 23 May 2021 23:46:14 +0300 Subject: [PATCH 082/112] New Actions for DB validate of structure/data --- Source/Persistence/DB/BoldDBActions.pas | 182 ++++++++++++++++-- .../DB/BoldPersistenceHandleDBreg.pas | 4 +- 2 files changed, 164 insertions(+), 22 deletions(-) diff --git a/Source/Persistence/DB/BoldDBActions.pas b/Source/Persistence/DB/BoldDBActions.pas index 9145b0a..a8394ad 100644 --- a/Source/Persistence/DB/BoldDBActions.pas +++ b/Source/Persistence/DB/BoldDBActions.pas @@ -7,27 +7,75 @@ interface uses Classes, + BoldHandleAction, BoldPersistenceHandleDB, + BoldSubscription, + BoldDbValidator, + BoldDbStructureValidator, + BoldDbDataValidator, ActnList; type + TBoldPersistenceHandleAction = class; TBoldGenerateSchemaAction = class; + TBoldValidateDBStructureAction = class; + TBoldValidateDBDataAction = class; + + { TBoldSystemHandleAction } + TBoldPersistenceHandleAction = class(TAction) + private + fHandleSubscriber: TBoldPassThroughSubscriber; + fBoldPersistenceHandleDB: TBoldPersistenceHandleDB; + procedure SetBoldPersistenceHandle(const Value: TBoldPersistenceHandleDB); virtual; + protected + procedure _HandleSubscriberReceive(Originator: TObject; OriginalEvent: TBoldEvent; RequestedEvent: TBoldRequestedEvent); virtual; + procedure CheckAllowEnable(var EnableAction: boolean); virtual; + property BoldPersistenceHandleDB: TBoldPersistenceHandleDB read fBoldPersistenceHandleDB write SetBoldPersistenceHandle; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + procedure UpdateTarget(Target: TObject); override; + function HandlesTarget(Target: TObject): Boolean; override; + end; { TBoldGenerateSchemaAction } - TBoldGenerateSchemaAction = class(TAction) + TBoldGenerateSchemaAction = class(TBoldPersistenceHandleAction) private - FBoldPersistenceHandleDB: TBoldPersistenceHandleDB; fIgnoreUnknownTables: boolean; - procedure SetBoldPersistenceHandleDB(const Value: TBoldPersistenceHandleDB); protected - procedure Notification(AComponent: TComponent; Operation: TOperation); override; + procedure CheckAllowEnable(var EnableAction: boolean); override; public constructor Create(AOwner: TComponent); override; procedure ExecuteTarget(Target: TObject); override; - function HandlesTarget(Target: TObject): Boolean; override; published - property BoldPersistenceHandleDB: TBoldPersistenceHandleDB read FBoldPersistenceHandleDB write SetBoldPersistenceHandleDB; property IgnoreUnknownTables: boolean read fIgnoreUnknownTables write fIgnoreUnknownTables; + property BoldPersistenceHandleDB; + end; + + { TBoldValidateDBStructureAction } + TBoldValidateDBStructureAction = class(TBoldPersistenceHandleAction) + private + fValidator: TBoldDbStructureValidator; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + procedure ExecuteTarget(Target: TObject); override; + published + property BoldPersistenceHandleDB; + end; + + { TBoldValidateDBDataAction } + TBoldValidateDBDataAction = class(TBoldPersistenceHandleAction) + private + fValidator: TBoldDbDataValidator; + fPauseBetweenQueries: integer; + public + constructor Create(AOwner: TComponent); override; + destructor Destroy; override; + procedure ExecuteTarget(Target: TObject); override; + published + property PauseBetweenQueries: integer read fPauseBetweenQueries write fPauseBetweenQueries; + property BoldPersistenceHandleDB; end; implementation @@ -38,9 +86,77 @@ implementation BoldActionDefs, BoldUtils; +const + breFreeHandle = 44; + breValueIdentityChanged = 45; + +{ TBoldPersistenceHandleAction } + +procedure TBoldPersistenceHandleAction._HandleSubscriberReceive( + Originator: TObject; OriginalEvent: TBoldEvent; + RequestedEvent: TBoldRequestedEvent); +begin + Assert(Originator = fBoldPersistenceHandleDB); + Assert(RequestedEvent in [breFreeHandle]); + case RequestedEvent of + breFreeHandle: fBoldPersistenceHandleDB := nil; + end; +end; + +constructor TBoldPersistenceHandleAction.Create(AOwner: TComponent); +begin + inherited; + fHandleSubscriber := TBoldPassthroughSubscriber.Create(_HandleSubscriberReceive); +end; + +destructor TBoldPersistenceHandleAction.Destroy; +begin + inherited; + FreeAndNil(fHandleSubscriber); +end; + +function TBoldPersistenceHandleAction.HandlesTarget(Target: TObject): Boolean; +begin + Result := True; +end; + +procedure TBoldPersistenceHandleAction.SetBoldPersistenceHandle( + const Value: TBoldPersistenceHandleDB); +begin + if (fBoldPersistenceHandleDB <> Value) then + begin + fHandleSubscriber.CancelAllSubscriptions; + fBoldPersistenceHandleDB := Value; + if Assigned(fBoldPersistenceHandleDB) then + fBoldPersistenceHandleDB.AddSmallSubscription(fHandleSubscriber, [beDestroying], breFreeHandle); + end; +end; + +procedure TBoldPersistenceHandleAction.UpdateTarget(Target: TObject); +var + EnableAction: boolean; +begin + inherited; + EnableAction := True; + CheckAllowEnable(EnableAction); + Enabled := EnableAction; +end; + +procedure TBoldPersistenceHandleAction.CheckAllowEnable(var EnableAction: boolean); +begin + EnableAction := Assigned(fBoldPersistenceHandleDB); +end; { TBoldGenerateSchemaAction } +procedure TBoldGenerateSchemaAction.CheckAllowEnable(var EnableAction: boolean); +begin + inherited; + EnableAction := EnableAction and + Assigned(BoldPersistenceHandleDB.DatabaseAdapter) + and not BoldPersistenceHandleDB.Active; +end; + constructor TBoldGenerateSchemaAction.Create(AOwner: TComponent); begin inherited; @@ -50,32 +166,56 @@ constructor TBoldGenerateSchemaAction.Create(AOwner: TComponent); procedure TBoldGenerateSchemaAction.ExecuteTarget(Target: TObject); begin inherited; - if HandlesTarget(nil) then - BoldPersistenceHandleDB.CreateDataBaseSchema(IgnoreUnknownTables); + BoldPersistenceHandleDB.CreateDataBaseSchema(IgnoreUnknownTables); end; -function TBoldGenerateSchemaAction.HandlesTarget(Target: TObject): Boolean; + +{ TBoldValidateDBStructureAction } + +constructor TBoldValidateDBStructureAction.Create(AOwner: TComponent); begin - Result := Assigned(BoldPersistenceHandleDB) and - Assigned(BoldPersistenceHandleDB.DatabaseAdapter) and - not BoldPersistenceHandleDB.Active; + inherited; + Caption := 'Validate DB Structure'; end; -procedure TBoldGenerateSchemaAction.Notification(AComponent: TComponent; - Operation: TOperation); +destructor TBoldValidateDBStructureAction.Destroy; begin + FreeAndNil(fValidator); inherited; - if (AComponent = BoldPersistenceHandleDB) and (operation = opRemove) then - fBoldPersistenceHandleDB := nil; end; -procedure TBoldGenerateSchemaAction.SetBoldPersistenceHandleDB(const Value: TBoldPersistenceHandleDB); +procedure TBoldValidateDBStructureAction.ExecuteTarget(Target: TObject); begin - FBoldPersistenceHandleDB := Value; - if Assigned(fBoldPersistenceHandleDB) then - fBoldPersistenceHandleDB.FreeNotification(Self); + inherited; + if not assigned(fValidator) then + fValidator := TBoldDbStructureValidator.Create(nil); + fValidator.PersistenceHandle := BoldPersistenceHandleDB; + fValidator.Execute; end; -initialization +{ TBoldValidateDBDataAction } + +constructor TBoldValidateDBDataAction.Create(AOwner: TComponent); +begin + inherited; + Caption := 'Validate DB Data'; + PauseBetweenQueries := 1; +end; + +destructor TBoldValidateDBDataAction.Destroy; +begin + FreeAndNil(fValidator); + inherited; +end; + +procedure TBoldValidateDBDataAction.ExecuteTarget(Target: TObject); +begin + inherited; + if not assigned(fValidator) then + fValidator := TBoldDbDataValidator.Create(nil); + fValidator.PersistenceHandle := BoldPersistenceHandleDB; + fValidator.PauseBetweenQueries := PauseBetweenQueries; + fValidator.Execute; +end; end. diff --git a/Source/Persistence/DB/BoldPersistenceHandleDBreg.pas b/Source/Persistence/DB/BoldPersistenceHandleDBreg.pas index 8ef3721..989c33a 100644 --- a/Source/Persistence/DB/BoldPersistenceHandleDBreg.pas +++ b/Source/Persistence/DB/BoldPersistenceHandleDBreg.pas @@ -43,7 +43,9 @@ procedure Register; begin RegisterComponents(BOLDPAGENAME_PERSISTENCE, [TBoldPersistenceHandleDB]); RegisterActions(BOLDACTIONGROUPNAME, - [TBoldGenerateSchemaAction], nil); + [TBoldGenerateSchemaAction, + TBoldValidateDBStructureAction, + TBoldValidateDBDataAction], nil); RegisterComponentEditor(TBoldPersistenceHandleDB, TBoldPersistenceHandleDBEditor); end; From ccbcf476a3afe4ea153432816dd0a34e6da15b06 Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Sun, 23 May 2021 23:46:37 +0300 Subject: [PATCH 083/112] Change Sleep between queries to ms instead of seconds --- Source/PMapper/Validator/BoldDbDataValidator.pas | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/PMapper/Validator/BoldDbDataValidator.pas b/Source/PMapper/Validator/BoldDbDataValidator.pas index c0c6b8d..731a40d 100644 --- a/Source/PMapper/Validator/BoldDbDataValidator.pas +++ b/Source/PMapper/Validator/BoldDbDataValidator.pas @@ -152,7 +152,7 @@ function TBoldDbDataValidator.MemberIsInherited( procedure TBoldDbDataValidator.OpenQuery; begin - Sleep(1000*PauseBetweenQueries); + Sleep(PauseBetweenQueries); Query.Open; end; From ee7c7e64e9da1dde40dd4de2130f6b6643a4bc26 Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Mon, 24 May 2021 00:39:41 +0300 Subject: [PATCH 084/112] fixed typo and action shortcut --- Source/PMapper/SQL/BoldSQLDatabaseConfig.pas | 2 +- Source/Samples/Actions/BoldDebugActions.pas | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/PMapper/SQL/BoldSQLDatabaseConfig.pas b/Source/PMapper/SQL/BoldSQLDatabaseConfig.pas index 59fbe49..4653666 100644 --- a/Source/PMapper/SQL/BoldSQLDatabaseConfig.pas +++ b/Source/PMapper/SQL/BoldSQLDatabaseConfig.pas @@ -933,7 +933,7 @@ procedure TBoldSQLDataBaseConfig.InitializeDbEngineSettings(Engine: TBoldDatabas fMaxIndexNameLength := 63; fMaxDbIdentifierLength := 63; fMultiRowInsertLimit := 1000; - ffIndexColumnExistsTemplate := 'select indexname from pg_indexes where upper(tablename) = upper('''')'; + fIndexColumnExistsTemplate := 'select indexname from pg_indexes where upper(tablename) = upper('''')'; FColumnExistsTemplate := 'SELECT column_name FROM information_schema.columns WHERE upper(table_name)=upper('''') and upper(column_name)=upper('''')'; // do not localize fDatabaseExistsTemplate := 'select exists(SELECT datname FROM pg_catalog.pg_database WHERE lower(datname) = lower(''''));'; // IndexInfoTemplate := 'select indexname from pg_indexes where tablename = '''''; // this is not complete IndexName, IsPrimary, IsUnique, ColumnName diff --git a/Source/Samples/Actions/BoldDebugActions.pas b/Source/Samples/Actions/BoldDebugActions.pas index 4398ee6..e471ce8 100644 --- a/Source/Samples/Actions/BoldDebugActions.pas +++ b/Source/Samples/Actions/BoldDebugActions.pas @@ -195,7 +195,6 @@ constructor TBoldLogAction.Create(AOwner: TComponent); begin inherited; Caption := Format('Toggle %s logs', [LogType]); - ShortCut := TextToShortCut('Ctrl+L'); end; procedure TBoldLogAction.ExecuteTarget(Target: TObject); @@ -249,6 +248,7 @@ constructor TBoldLogFormAction.Create(AOwner: TComponent); begin inherited; Caption := 'Log view'; + ShortCut := TextToShortCut('Ctrl+L'); end; procedure TBoldLogFormAction.ExecuteTarget(Target: TObject); From 2f69fafe2af0a74dd84e27bd025c7d54985c50c7 Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Mon, 24 May 2021 00:41:19 +0300 Subject: [PATCH 085/112] Unitname->BoldUnitName --- .../UMLModel/Core/BoldUMLModelDataModule.dfm | 590 +++++++++--------- 1 file changed, 294 insertions(+), 296 deletions(-) diff --git a/Source/UMLModel/Core/BoldUMLModelDataModule.dfm b/Source/UMLModel/Core/BoldUMLModelDataModule.dfm index 960666e..e9756df 100644 --- a/Source/UMLModel/Core/BoldUMLModelDataModule.dfm +++ b/Source/UMLModel/Core/BoldUMLModelDataModule.dfm @@ -1,7 +1,5 @@ object dmModelEdit: TdmModelEdit OldCreateOrder = True - Left = 186 - Top = 140 Height = 479 Width = 741 object bmlUMLModel: TBoldModel @@ -88,50 +86,6 @@ object dmModelEdit: TdmModelEdit #9#9#9')' #9#9')' #9#9'(Class' - #9#9#9'"Include"' - #9#9#9'"Relationship"' - #9#9#9'TRUE' - #9#9#9'FALSE' - #9#9#9'""' - #9#9#9'""' - - #9#9#9'"_BoldInternal.toolId=35FDD6900154,persistence=persistent,_Bo' + - 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Behavioral_' + - 'Elements.Use_Cases,Bold.DelphiName=TUML,Bold.ExpressionNam' + - 'e=UML,Bold.TableName=UML_"' - #9#9#9'(Attributes' - #9#9#9')' - #9#9#9'(Methods' - #9#9#9')' - #9#9')' - #9#9'(Class' - #9#9#9'"ExtensionPoint"' - #9#9#9'"ModelElement"' - #9#9#9'TRUE' - #9#9#9'FALSE' - #9#9#9'""' - #9#9#9'""' - - #9#9#9'"_BoldInternal.toolId=362661700208,persistence=persistent,_Bo' + - 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Behavioral_' + - 'Elements.Use_Cases,Bold.DelphiName=TUML,Bold.ExpressionNam' + - 'e=UML,Bold.TableName=UML_"' - #9#9#9'(Attributes' - #9#9#9#9'(Attribute' - #9#9#9#9#9'"location"' - #9#9#9#9#9'"LocationReference"' - #9#9#9#9#9'FALSE' - #9#9#9#9#9'""' - #9#9#9#9#9'""' - #9#9#9#9#9'2' - #9#9#9#9#9'""' - #9#9#9#9#9'"_BoldInternal.toolId=3634E53A00DC,persistence=Persistent"' - #9#9#9#9')' - #9#9#9')' - #9#9#9'(Methods' - #9#9#9')' - #9#9')' - #9#9'(Class' #9#9#9'"ModelElement"' #9#9#9'"Element"' #9#9#9'TRUE' @@ -311,6 +265,67 @@ object dmModelEdit: TdmModelEdit #9#9#9')' #9#9')' #9#9'(Class' + #9#9#9'"Element"' + #9#9#9'"UMLModelRoot"' + #9#9#9'TRUE' + #9#9#9'FALSE' + #9#9#9'""' + #9#9#9'""' + + #9#9#9'"_BoldInternal.toolId=3C5A96DE0300,persistence=persistent,_Bo' + + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Foundation.' + + 'Core,Bold.DelphiName=TUML,Bold.ExpressionName=UML,Bo' + + 'ld.TableName=UML_"' + #9#9#9'(Attributes' + #9#9#9')' + #9#9#9'(Methods' + #9#9#9')' + #9#9')' + #9#9'(Class' + #9#9#9'"Include"' + #9#9#9'"Relationship"' + #9#9#9'TRUE' + #9#9#9'FALSE' + #9#9#9'""' + #9#9#9'""' + + #9#9#9'"_BoldInternal.toolId=35FDD6900154,persistence=persistent,_Bo' + + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Behavioral_' + + 'Elements.Use_Cases,Bold.DelphiName=TUML,Bold.ExpressionNam' + + 'e=UML,Bold.TableName=UML_"' + #9#9#9'(Attributes' + #9#9#9')' + #9#9#9'(Methods' + #9#9#9')' + #9#9')' + #9#9'(Class' + #9#9#9'"ExtensionPoint"' + #9#9#9'"ModelElement"' + #9#9#9'TRUE' + #9#9#9'FALSE' + #9#9#9'""' + #9#9#9'""' + + #9#9#9'"_BoldInternal.toolId=362661700208,persistence=persistent,_Bo' + + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Behavioral_' + + 'Elements.Use_Cases,Bold.DelphiName=TUML,Bold.ExpressionNam' + + 'e=UML,Bold.TableName=UML_"' + #9#9#9'(Attributes' + #9#9#9#9'(Attribute' + #9#9#9#9#9'"location"' + #9#9#9#9#9'"LocationReference"' + #9#9#9#9#9'FALSE' + #9#9#9#9#9'""' + #9#9#9#9#9'""' + #9#9#9#9#9'2' + #9#9#9#9#9'""' + #9#9#9#9#9'"_BoldInternal.toolId=3634E53A00DC,persistence=Persistent"' + #9#9#9#9')' + #9#9#9')' + #9#9#9'(Methods' + #9#9#9')' + #9#9')' + #9#9'(Class' #9#9#9'"UseCase"' #9#9#9'"Classifier"' #9#9#9'TRUE' @@ -377,6 +392,70 @@ object dmModelEdit: TdmModelEdit #9#9#9')' #9#9')' #9#9'(Class' + #9#9#9'"GeneralizableElement"' + #9#9#9'"Namespace"' + #9#9#9'TRUE' + #9#9#9'TRUE' + #9#9#9'""' + #9#9#9'""' + + #9#9#9'"_BoldInternal.toolId=327A810D03C0,persistence=persistent,_Bo' + + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Foundation.' + + 'Core,Bold.DelphiName=TUML,Bold.ExpressionName=UML,Bo' + + 'ld.TableName=UML_"' + #9#9#9'(Attributes' + #9#9#9#9'(Attribute' + #9#9#9#9#9'"isRoot"' + #9#9#9#9#9'"Boolean"' + #9#9#9#9#9'FALSE' + #9#9#9#9#9'""' + #9#9#9#9#9'""' + #9#9#9#9#9'2' + #9#9#9#9#9'""' + #9#9#9#9#9'"_BoldInternal.toolId=327A877801CC,persistence=Persistent"' + #9#9#9#9')' + #9#9#9#9'(Attribute' + #9#9#9#9#9'"isLeaf"' + #9#9#9#9#9'"Boolean"' + #9#9#9#9#9'FALSE' + #9#9#9#9#9'""' + #9#9#9#9#9'""' + #9#9#9#9#9'2' + #9#9#9#9#9'""' + #9#9#9#9#9'"_BoldInternal.toolId=327A877E006E,persistence=Persistent"' + #9#9#9#9')' + #9#9#9#9'(Attribute' + #9#9#9#9#9'"isAbstract"' + #9#9#9#9#9'"Boolean"' + #9#9#9#9#9'FALSE' + #9#9#9#9#9'""' + #9#9#9#9#9'""' + #9#9#9#9#9'2' + #9#9#9#9#9'""' + #9#9#9#9#9'"_BoldInternal.toolId=327A878400D2,persistence=Persistent"' + #9#9#9#9')' + #9#9#9')' + #9#9#9'(Methods' + #9#9#9')' + #9#9')' + #9#9'(Class' + #9#9#9'"Namespace"' + #9#9#9'"ModelElement"' + #9#9#9'TRUE' + #9#9#9'TRUE' + #9#9#9'""' + #9#9#9'""' + + #9#9#9'"_BoldInternal.toolId=32B69F3A0118,persistence=persistent,_Bo' + + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Foundation.' + + 'Core,Bold.DelphiName=TUML,Bold.ExpressionName=UML,Bo' + + 'ld.TableName=UML_"' + #9#9#9'(Attributes' + #9#9#9')' + #9#9#9'(Methods' + #9#9#9')' + #9#9')' + #9#9'(Class' #9#9#9'"Actor"' #9#9#9'"Classifier"' #9#9#9'TRUE' @@ -1140,6 +1219,46 @@ object dmModelEdit: TdmModelEdit #9#9#9')' #9#9')' #9#9'(Class' + #9#9#9'"Feature"' + #9#9#9'"ModelElement"' + #9#9#9'TRUE' + #9#9#9'TRUE' + #9#9#9'""' + #9#9#9'""' + + #9#9#9'"_BoldInternal.toolId=32989F9700FE,persistence=persistent,_Bo' + + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Foundation.' + + 'Core,Bold.DelphiName=TUML,Bold.ExpressionName=UML,Bo' + + 'ld.TableName=UML_,\"Bold.DerivationExpressions=qualifyingO' + + 'wner=if owner->notEmpty then owner else namespace endif\""' + #9#9#9'(Attributes' + #9#9#9#9'(Attribute' + #9#9#9#9#9'"ownerScope"' + #9#9#9#9#9'"ScopeKind"' + #9#9#9#9#9'FALSE' + #9#9#9#9#9'""' + #9#9#9#9#9'""' + #9#9#9#9#9'2' + #9#9#9#9#9'"instance"' + #9#9#9#9#9'"_BoldInternal.toolId=31653E23032A,persistence=Persistent"' + #9#9#9#9')' + #9#9#9')' + #9#9#9'(Methods' + #9#9#9#9'(Method' + #9#9#9#9#9'"ExpandedExpressionName"' + #9#9#9#9#9'""' + #9#9#9#9#9'FALSE' + #9#9#9#9#9'"String"' + #9#9#9#9#9'"Bold"' + #9#9#9#9#9'2' + #9#9#9#9#9'""' + + #9#9#9#9#9'"_BoldInternal.toolId=3C16140103C2,Bold.OperationKind=Overr' + + 'ide"' + #9#9#9#9')' + #9#9#9')' + #9#9')' + #9#9'(Class' #9#9#9'"Argument"' #9#9#9'"ModelElement"' #9#9#9'TRUE' @@ -1332,53 +1451,6 @@ object dmModelEdit: TdmModelEdit #9#9#9')' #9#9')' #9#9'(Class' - #9#9#9'"GeneralizableElement"' - #9#9#9'"Namespace"' - #9#9#9'TRUE' - #9#9#9'TRUE' - #9#9#9'""' - #9#9#9'""' - - #9#9#9'"_BoldInternal.toolId=327A810D03C0,persistence=persistent,_Bo' + - 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Foundation.' + - 'Core,Bold.DelphiName=TUML,Bold.ExpressionName=UML,Bo' + - 'ld.TableName=UML_"' - #9#9#9'(Attributes' - #9#9#9#9'(Attribute' - #9#9#9#9#9'"isRoot"' - #9#9#9#9#9'"Boolean"' - #9#9#9#9#9'FALSE' - #9#9#9#9#9'""' - #9#9#9#9#9'""' - #9#9#9#9#9'2' - #9#9#9#9#9'""' - #9#9#9#9#9'"_BoldInternal.toolId=327A877801CC,persistence=Persistent"' - #9#9#9#9')' - #9#9#9#9'(Attribute' - #9#9#9#9#9'"isLeaf"' - #9#9#9#9#9'"Boolean"' - #9#9#9#9#9'FALSE' - #9#9#9#9#9'""' - #9#9#9#9#9'""' - #9#9#9#9#9'2' - #9#9#9#9#9'""' - #9#9#9#9#9'"_BoldInternal.toolId=327A877E006E,persistence=Persistent"' - #9#9#9#9')' - #9#9#9#9'(Attribute' - #9#9#9#9#9'"isAbstract"' - #9#9#9#9#9'"Boolean"' - #9#9#9#9#9'FALSE' - #9#9#9#9#9'""' - #9#9#9#9#9'""' - #9#9#9#9#9'2' - #9#9#9#9#9'""' - #9#9#9#9#9'"_BoldInternal.toolId=327A878400D2,persistence=Persistent"' - #9#9#9#9')' - #9#9#9')' - #9#9#9'(Methods' - #9#9#9')' - #9#9')' - #9#9'(Class' #9#9#9'"AssociationRole"' #9#9#9'"Association"' #9#9#9'TRUE' @@ -1953,23 +2025,6 @@ object dmModelEdit: TdmModelEdit #9#9#9')' #9#9')' #9#9'(Class' - #9#9#9'"Namespace"' - #9#9#9'"ModelElement"' - #9#9#9'TRUE' - #9#9#9'TRUE' - #9#9#9'""' - #9#9#9'""' - - #9#9#9'"_BoldInternal.toolId=32B69F3A0118,persistence=persistent,_Bo' + - 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Foundation.' + - 'Core,Bold.DelphiName=TUML,Bold.ExpressionName=UML,Bo' + - 'ld.TableName=UML_"' - #9#9#9'(Attributes' - #9#9#9')' - #9#9#9'(Methods' - #9#9#9')' - #9#9')' - #9#9'(Class' #9#9#9'"Attribute"' #9#9#9'"StructuralFeature"' #9#9#9'TRUE' @@ -2121,63 +2176,6 @@ object dmModelEdit: TdmModelEdit #9#9#9')' #9#9')' #9#9'(Class' - #9#9#9'"Feature"' - #9#9#9'"ModelElement"' - #9#9#9'TRUE' - #9#9#9'TRUE' - #9#9#9'""' - #9#9#9'""' - - #9#9#9'"_BoldInternal.toolId=32989F9700FE,persistence=persistent,_Bo' + - 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Foundation.' + - 'Core,Bold.DelphiName=TUML,Bold.ExpressionName=UML,Bo' + - 'ld.TableName=UML_,\"Bold.DerivationExpressions=qualifyingO' + - 'wner=if owner->notEmpty then owner else namespace endif\""' - #9#9#9'(Attributes' - #9#9#9#9'(Attribute' - #9#9#9#9#9'"ownerScope"' - #9#9#9#9#9'"ScopeKind"' - #9#9#9#9#9'FALSE' - #9#9#9#9#9'""' - #9#9#9#9#9'""' - #9#9#9#9#9'2' - #9#9#9#9#9'"instance"' - #9#9#9#9#9'"_BoldInternal.toolId=31653E23032A,persistence=Persistent"' - #9#9#9#9')' - #9#9#9')' - #9#9#9'(Methods' - #9#9#9#9'(Method' - #9#9#9#9#9'"ExpandedExpressionName"' - #9#9#9#9#9'""' - #9#9#9#9#9'FALSE' - #9#9#9#9#9'"String"' - #9#9#9#9#9'"Bold"' - #9#9#9#9#9'2' - #9#9#9#9#9'""' - - #9#9#9#9#9'"_BoldInternal.toolId=3C16140103C2,Bold.OperationKind=Overr' + - 'ide"' - #9#9#9#9')' - #9#9#9')' - #9#9')' - #9#9'(Class' - #9#9#9'"Element"' - #9#9#9'"UMLModelRoot"' - #9#9#9'TRUE' - #9#9#9'FALSE' - #9#9#9'""' - #9#9#9'""' - - #9#9#9'"_BoldInternal.toolId=3C5A96DE0300,persistence=persistent,_Bo' + - 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Foundation.' + - 'Core,Bold.DelphiName=TUML,Bold.ExpressionName=UML,Bo' + - 'ld.TableName=UML_"' - #9#9#9'(Attributes' - #9#9#9')' - #9#9#9'(Methods' - #9#9#9')' - #9#9')' - #9#9'(Class' #9#9#9'"Generalization"' #9#9#9'"Relationship"' #9#9#9'TRUE' @@ -3125,7 +3123,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=35FDD9A30168,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=35FDD9A30168,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Behavioral_' + 'Elements.Use_Cases,_Boldify.noName=True,Bold.DelphiName="' #9#9#9'FALSE' @@ -3168,7 +3166,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=362661DA01D6,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=362661DA01D6,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Behavioral_' + 'Elements.Use_Cases,_Boldify.noName=True,Bold.DelphiName="' #9#9#9'FALSE' @@ -3211,7 +3209,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=3626B0DA0104,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=3626B0DA0104,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Behavioral_' + 'Elements.Use_Cases,_Boldify.noName=True,Bold.DelphiName="' #9#9#9'FALSE' @@ -3254,7 +3252,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=35FDD86301E0,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=35FDD86301E0,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Behavioral_' + 'Elements.Use_Cases,_Boldify.noName=True,Bold.DelphiName="' #9#9#9'FALSE' @@ -3297,7 +3295,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=35FDD86B006E,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=35FDD86B006E,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Behavioral_' + 'Elements.Use_Cases,_Boldify.noName=True,Bold.DelphiName="' #9#9#9'FALSE' @@ -3340,7 +3338,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=35FDD992037A,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=35FDD992037A,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Behavioral_' + 'Elements.Use_Cases,_Boldify.noName=True,Bold.DelphiName="' #9#9#9'FALSE' @@ -3383,7 +3381,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=33377C0D0208,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=33377C0D0208,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Behavioral_' + 'Elements.State_Machines,_Boldify.noName=True,Bold.DelphiName="' @@ -3427,7 +3425,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=328902D000D2,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=328902D000D2,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Behavioral_' + 'Elements.State_Machines,_Boldify.noName=True,Bold.DelphiName="' @@ -3471,7 +3469,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=3288E5390226,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=3288E5390226,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Behavioral_' + 'Elements.State_Machines,_Boldify.noName=True,Bold.DelphiName="' @@ -3519,7 +3517,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=3288D8C4023A,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=3288D8C4023A,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Behavioral_' + 'Elements.State_Machines,_Boldify.noName=True,Bold.DelphiName="' @@ -3563,7 +3561,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=3288E53D029E,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=3288E53D029E,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Behavioral_' + 'Elements.State_Machines,_Boldify.noName=True,Bold.DelphiName="' @@ -3607,7 +3605,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=3288D725037A,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=3288D725037A,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Behavioral_' + 'Elements.State_Machines,_Boldify.noName=True,Bold.DelphiName="' @@ -3651,7 +3649,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=3403125E0140,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=3403125E0140,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Behavioral_' + 'Elements.State_Machines,_Boldify.noName=True,Bold.DelphiName="' @@ -3695,7 +3693,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=364987D1017D,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=364987D1017D,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Behavioral_' + 'Elements.State_Machines,_Boldify.noName=True,Bold.DelphiName="' @@ -3739,7 +3737,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=32890282014A,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=32890282014A,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Behavioral_' + 'Elements.State_Machines,_Boldify.noName=True,Bold.DelphiName="' @@ -3783,7 +3781,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=3289028C03D4,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=3289028C03D4,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Behavioral_' + 'Elements.State_Machines,_Boldify.noName=True,Bold.DelphiName="' @@ -3827,7 +3825,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=3369606C0000,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=3369606C0000,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Behavioral_' + 'Elements.State_Machines,Bold.DelphiName="' #9#9#9'FALSE' @@ -3870,7 +3868,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=3369912001A4,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=3369912001A4,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Behavioral_' + 'Elements.State_Machines,_Boldify.noName=True,Bold.DelphiName="' @@ -3914,7 +3912,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=333784B400AA,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=333784B400AA,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Behavioral_' + 'Elements.State_Machines,_Boldify.noName=True,Bold.DelphiName="' @@ -3960,7 +3958,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=3337AF9B02A8,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=3337AF9B02A8,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Behavioral_' + 'Elements.State_Machines,Bold.DelphiName="' #9#9#9'FALSE' @@ -4003,7 +4001,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=336A39BE0136,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=336A39BE0136,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Behavioral_' + 'Elements.State_Machines,_Boldify.noName=True,Bold.DelphiName="' @@ -4047,7 +4045,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=33FA3ABF0122,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=33FA3ABF0122,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Behavioral_' + 'Elements.State_Machines,_Boldify.noName=True,Bold.DelphiName="' @@ -4091,7 +4089,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=32B598420168,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=32B598420168,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Behavioral_' + 'Elements.State_Machines,_Boldify.noName=True,Bold.DelphiName="' @@ -4135,7 +4133,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=33CF8BD300A0,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=33CF8BD300A0,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Behavioral_' + 'Elements.State_Machines,_Boldify.noName=True,Bold.DelphiName="' @@ -4181,7 +4179,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=33EBFA1C0078,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=33EBFA1C0078,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Behavioral_' + 'Elements.State_Machines,_Boldify.noName=True,Bold.DelphiName="' @@ -4225,7 +4223,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=33FA37050118,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=33FA37050118,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Behavioral_' + 'Elements.Common_Behavior,_Boldify.noName=True,Bold.DelphiName="' @@ -4269,7 +4267,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=33DBC1A200B4,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=33DBC1A200B4,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Behavioral_' + 'Elements.Common_Behavior,_Boldify.noName=True,Bold.DelphiName="' @@ -4313,7 +4311,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=33DBC16D0190,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=33DBC16D0190,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Behavioral_' + 'Elements.Common_Behavior,_Boldify.noName=True,Bold.DelphiName="' @@ -4357,7 +4355,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=33FF4EF7029E,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=33FF4EF7029E,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Behavioral_' + 'Elements.Common_Behavior,_Boldify.noName=True,Bold.DelphiName="' @@ -4401,7 +4399,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=328A5BB20280,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=328A5BB20280,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Behavioral_' + 'Elements.Common_Behavior,_Boldify.noName=True,Bold.DelphiName="' @@ -4445,7 +4443,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=33FFD9830014,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=33FFD9830014,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Behavioral_' + 'Elements.Common_Behavior,_Boldify.noName=True,Bold.DelphiName="' @@ -4489,7 +4487,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=33FF558A01AE,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=33FF558A01AE,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Behavioral_' + 'Elements.Common_Behavior,_Boldify.noName=True,Bold.DelphiName="' @@ -4537,7 +4535,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=33CFD0A602F8,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=33CFD0A602F8,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Behavioral_' + 'Elements.Common_Behavior,Bold.DelphiName="' #9#9#9'FALSE' @@ -4580,7 +4578,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=33CFA4B80334,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=33CFA4B80334,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Behavioral_' + 'Elements.Common_Behavior,_Boldify.noName=True,Bold.DelphiName="' @@ -4626,7 +4624,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=3650F0CC0262,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=3650F0CC0262,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Behavioral_' + 'Elements.Common_Behavior,_Boldify.noName=True,Bold.DelphiName="' @@ -4670,7 +4668,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=3650EE68008C,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=3650EE68008C,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Behavioral_' + 'Elements.Common_Behavior,_Boldify.noName=True,Bold.DelphiName="' @@ -4716,7 +4714,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=3650ECD402C6,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=3650ECD402C6,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Behavioral_' + 'Elements.Common_Behavior,_Boldify.noName=True,Bold.DelphiName="' @@ -4760,7 +4758,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=3742033C00F0,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=3742033C00F0,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Behavioral_' + 'Elements.Common_Behavior,_Boldify.noName=True,Bold.DelphiName="' @@ -4804,7 +4802,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=3C14A984017C,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=3C14A984017C,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Behavioral_' + 'Elements.Common_Behavior,_Boldify.noName=True,Bold.DelphiName="' @@ -4848,7 +4846,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=3C14A52203C7,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=3C14A52203C7,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Behavioral_' + 'Elements.Common_Behavior,_Boldify.noName=True,Bold.DelphiName="' @@ -4892,7 +4890,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=3C14955602A0,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=3C14955602A0,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Behavioral_' + 'Elements.Common_Behavior,_Boldify.noName=True,Bold.DelphiName="' @@ -4936,7 +4934,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=34030E1501CC,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=34030E1501CC,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Behavioral_' + 'Elements.Common_Behavior,_Boldify.noName=True,Bold.DelphiName="' @@ -4980,7 +4978,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=328A5C1F0118,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=328A5C1F0118,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Behavioral_' + 'Elements.Common_Behavior,_Boldify.noName=True,Bold.DelphiName="' @@ -5024,7 +5022,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=328A598B00F0,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=328A598B00F0,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Behavioral_' + 'Elements.Common_Behavior,_Boldify.noName=True,Bold.DelphiName="' @@ -5068,7 +5066,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=36266EA903C0,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=36266EA903C0,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Behavioral_' + 'Elements.Common_Behavior,_Boldify.noName=True,Bold.DelphiName="' @@ -5112,7 +5110,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=364B65E8024E,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=364B65E8024E,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Behavioral_' + 'Elements.Common_Behavior,Bold.DelphiName="' #9#9#9'FALSE' @@ -5157,7 +5155,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=364B65E4008C,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=364B65E4008C,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Behavioral_' + 'Elements.Common_Behavior,Bold.DelphiName="' #9#9#9'FALSE' @@ -5202,7 +5200,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=3635552000DC,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=3635552000DC,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Behavioral_' + 'Elements.Common_Behavior,_Boldify.noName=True,Bold.DelphiName="' @@ -5246,7 +5244,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=3388DE7600DC,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=3388DE7600DC,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Behavioral_' + 'Elements.Collaborations,_Boldify.noName=True,Bold.DelphiName="' @@ -5290,7 +5288,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=3388DD5C00E6,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=3388DD5C00E6,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Behavioral_' + 'Elements.Collaborations,_Boldify.noName=True,Bold.DelphiName="' @@ -5336,7 +5334,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=33CD50F90000,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=33CD50F90000,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Behavioral_' + 'Elements.Collaborations,_Boldify.noName=True,Bold.DelphiName="' @@ -5380,7 +5378,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=33CD57D201B8,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=33CD57D201B8,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Behavioral_' + 'Elements.Collaborations,_Boldify.noName=True,Bold.DelphiName="' @@ -5428,7 +5426,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=33CD511600AA,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=33CD511600AA,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Behavioral_' + 'Elements.Collaborations,_Boldify.noName=True,Bold.DelphiName="' @@ -5472,7 +5470,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=33D1394D00F0,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=33D1394D00F0,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Behavioral_' + 'Elements.Collaborations,_Boldify.noName=True,Bold.DelphiName="' @@ -5516,7 +5514,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=36008FB50168,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=36008FB50168,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Behavioral_' + 'Elements.Collaborations,_Boldify.noName=True,Bold.DelphiName="' @@ -5564,7 +5562,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=35FEAB5D038E,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=35FEAB5D038E,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Behavioral_' + 'Elements.Collaborations,_Boldify.noName=True,Bold.DelphiName="' @@ -5610,7 +5608,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=36265CF80136,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=36265CF80136,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Behavioral_' + 'Elements.Collaborations,_Boldify.noName=True,Bold.DelphiName="' @@ -5656,7 +5654,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=3C14BC4101E8,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=3C14BC4101E8,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Behavioral_' + 'Elements.Collaborations,_Boldify.noName=True,Bold.DelphiName="' @@ -5700,7 +5698,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=3650E6BD010E,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=3650E6BD010E,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Behavioral_' + 'Elements.Collaborations,_Boldify.noName=True,Bold.DelphiName="' @@ -5748,7 +5746,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=33FA39D50050,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=33FA39D50050,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Behavioral_' + 'Elements.Collaborations,_Boldify.noName=True,Bold.DelphiName="' @@ -5792,7 +5790,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=33D1470D01A4,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=33D1470D01A4,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Behavioral_' + 'Elements.Collaborations,_Boldify.noName=True,Bold.DelphiName="' @@ -5836,7 +5834,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=33D142DC0262,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=33D142DC0262,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Behavioral_' + 'Elements.Collaborations,_Boldify.noName=True,Bold.DelphiName="' @@ -5880,7 +5878,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=33D147100302,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=33D147100302,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Behavioral_' + 'Elements.Collaborations,_Boldify.noName=True,Bold.DelphiName="' @@ -5924,7 +5922,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=33DBBB45035C,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=33DBBB45035C,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Behavioral_' + 'Elements.Collaborations,_Boldify.noName=True,Bold.DelphiName="' @@ -5968,7 +5966,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=33DBBB2B0000,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=33DBBB2B0000,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Behavioral_' + 'Elements.Collaborations,_Boldify.noName=True,Bold.DelphiName="' @@ -6012,7 +6010,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=3C14CA560322,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=3C14CA560322,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Behavioral_' + 'Elements.Activity_Graphs,_Boldify.noName=True,Bold.DelphiName="' @@ -6056,7 +6054,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=3C14CBCF01DA,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=3C14CBCF01DA,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Behavioral_' + 'Elements.Activity_Graphs,_Boldify.noName=True,Bold.DelphiName="' @@ -6100,7 +6098,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=3C14CD10031C,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=3C14CD10031C,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Behavioral_' + 'Elements.Activity_Graphs,_Boldify.noName=True,Bold.DelphiName="' @@ -6144,7 +6142,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=3C14C8D202A2,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=3C14C8D202A2,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Behavioral_' + 'Elements.Activity_Graphs,_Boldify.noName=True,Bold.DelphiName="' @@ -6188,7 +6186,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=3C14C9380321,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=3C14C9380321,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Behavioral_' + 'Elements.Activity_Graphs,_Boldify.noName=True,Bold.DelphiName="' @@ -6232,7 +6230,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=3C14C9FC0387,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=3C14C9FC0387,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Behavioral_' + 'Elements.Activity_Graphs,_Boldify.noName=True,Bold.DelphiName="' @@ -6276,7 +6274,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=36240CA3028A,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=36240CA3028A,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Foundation.' + 'Core,_Boldify.noName=True,Bold.DelphiName="' #9#9#9'FALSE' @@ -6321,7 +6319,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=36240BF10028,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=36240BF10028,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Foundation.' + 'Core,_Boldify.noName=True,Bold.DelphiName="' #9#9#9'FALSE' @@ -6368,7 +6366,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=362409A800BE,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=362409A800BE,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Foundation.' + 'Core,_Boldify.noName=True,Bold.DelphiName="' #9#9#9'FALSE' @@ -6411,7 +6409,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=3627D60D03C0,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=3627D60D03C0,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Foundation.' + 'Core,_Boldify.noName=True,Bold.DelphiName="' #9#9#9'FALSE' @@ -6454,7 +6452,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=3627D5E8006E,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=3627D5E8006E,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Foundation.' + 'Core,_Boldify.noName=True,Bold.DelphiName="' #9#9#9'FALSE' @@ -6497,7 +6495,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=36241238028A,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=36241238028A,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Foundation.' + 'Core,_Boldify.noName=True,Bold.DelphiName="' #9#9#9'FALSE' @@ -6542,7 +6540,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=335C0D770302,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=335C0D770302,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Foundation.' + 'Core,_Boldify.noName=True,Bold.DelphiName="' #9#9#9'FALSE' @@ -6585,7 +6583,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=33DBE5050028,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=33DBE5050028,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Foundation.' + 'Core,_Boldify.noName=True,Bold.DelphiName="' #9#9#9'FALSE' @@ -6628,7 +6626,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=335C14690334,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=335C14690334,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Foundation.' + 'Core,_Boldify.noName=True,Bold.DelphiName="' #9#9#9'FALSE' @@ -6671,7 +6669,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=335C14A102DA,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=335C14A102DA,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Foundation.' + 'Core,_Boldify.noName=True,Bold.DelphiName="' #9#9#9'FALSE' @@ -6714,7 +6712,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=33EA67B702EE,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=33EA67B702EE,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Foundation.' + 'Core,_Boldify.noName=True,Bold.DelphiName="' #9#9#9'FALSE' @@ -6757,7 +6755,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=33FFE57902A2,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=33FFE57902A2,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Foundation.' + 'Core,_Boldify.noName=True,Bold.DelphiName="' #9#9#9'FALSE' @@ -6800,7 +6798,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=33F0EFAB0050,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=33F0EFAB0050,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Foundation.' + 'Core,_Boldify.noName=True,Bold.DelphiName="' #9#9#9'FALSE' @@ -6843,7 +6841,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=3C10E44700C4,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=3C10E44700C4,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Foundation.' + 'Core,_Boldify.noName=True,Bold.DelphiName="' #9#9#9'FALSE' @@ -6886,7 +6884,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=3C10E42301C7,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=3C10E42301C7,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Foundation.' + 'Core,_Boldify.noName=True,Bold.DelphiName="' #9#9#9'FALSE' @@ -6929,7 +6927,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=3C10E25D0386,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=3C10E25D0386,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Foundation.' + 'Core,_Boldify.noName=True,Bold.DelphiName="' #9#9#9'FALSE' @@ -6972,7 +6970,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=3C5A72940135,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=3C5A72940135,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Foundation.' + 'Core,_Boldify.noName=True,Bold.DelphiName="' #9#9#9'FALSE' @@ -7015,7 +7013,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=3C5A68F300AE,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=3C5A68F300AE,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Foundation.' + 'Core,_Boldify.noName=True,Bold.DelphiName="' #9#9#9'FALSE' @@ -7058,7 +7056,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'"Bold"' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=3C14DDB20379,persistence=transient,deri' + + #9#9#9'"persistence=transient,_BoldInternal.toolId=3C14DDB20379,deri' + 'ved=True,_BoldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta' + '.Foundation.Core,Bold.DelphiName="' #9#9#9'TRUE' @@ -7105,7 +7103,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=3C10DA8E0219,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=3C10DA8E0219,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Foundation.' + 'Core,_Boldify.noName=True,Bold.DelphiName="' #9#9#9'FALSE' @@ -7148,7 +7146,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=370E7E3B0138,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=370E7E3B0138,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Foundation.' + 'Core,_Boldify.noName=True,Bold.DelphiName="' #9#9#9'FALSE' @@ -7191,7 +7189,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=36E96A860316,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=36E96A860316,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Foundation.' + 'Core,_Boldify.noName=True,Bold.DelphiName="' #9#9#9'FALSE' @@ -7234,7 +7232,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=365EEE8103D4,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=365EEE8103D4,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Foundation.' + 'Core,_Boldify.noName=True,Bold.DelphiName="' #9#9#9'FALSE' @@ -7277,7 +7275,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'"Bold"' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=3BCC459C037B,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=3BCC459C037B,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Foundation.' + 'Core,_Boldify.noName=True,Bold.DelphiName="' #9#9#9'FALSE' @@ -7320,7 +7318,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'"Bold"' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=3B9DE749014C,persistence=transient,deri' + + #9#9#9'"persistence=transient,_BoldInternal.toolId=3B9DE749014C,deri' + 'ved=True,_BoldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta' + '.Foundation.Core,Bold.DelphiName="' #9#9#9'TRUE' @@ -7365,7 +7363,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'"Bold"' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=3B989D050114,persistence=transient,deri' + + #9#9#9'"persistence=transient,_BoldInternal.toolId=3B989D050114,deri' + 'ved=True,_BoldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta' + '.Foundation.Core,_Boldify.noName=True,Bold.DelphiName="' #9#9#9'TRUE' @@ -7413,7 +7411,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=3359946200F0,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=3359946200F0,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Foundation.' + 'Core,_Boldify.noName=True,Bold.DelphiName="' #9#9#9'FALSE' @@ -7456,7 +7454,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=32B6D9B302FD,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=32B6D9B302FD,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Foundation.' + 'Core,_Boldify.noName=True,Bold.DelphiName="' #9#9#9'FALSE' @@ -7499,7 +7497,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=33598CAA030C,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=33598CAA030C,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Foundation.' + 'Core,_Boldify.noName=True,Bold.DelphiName="' #9#9#9'FALSE' @@ -7542,7 +7540,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=32B5D7EE02FF,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=32B5D7EE02FF,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Foundation.' + 'Core,_Boldify.noName=True,Bold.DelphiName="' #9#9#9'FALSE' @@ -7585,7 +7583,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=32A2A50C0084,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=32A2A50C0084,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Foundation.' + 'Core,_Boldify.noName=True,Bold.DelphiName="' #9#9#9'FALSE' @@ -7628,7 +7626,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=3C10E89303D3,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=3C10E89303D3,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Foundation.' + 'Extension_Mechanisms,_Boldify.noName=True,Bold.DelphiName=' + '"' @@ -7672,7 +7670,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=33E901DD001E,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=33E901DD001E,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Foundation.' + 'Extension_Mechanisms,_Boldify.noName=True,Bold.DelphiName=' + '"' @@ -7726,7 +7724,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=3AE6CACA0195,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=3AE6CACA0195,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Foundation.' + 'Extension_Mechanisms,_Boldify.noName=True,Bold.DelphiName=' + '"' @@ -7770,7 +7768,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=3C10E81D0080,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=3C10E81D0080,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Foundation.' + 'Extension_Mechanisms,_Boldify.noName=True,Bold.DelphiName=' + '"' @@ -7814,7 +7812,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'"Bold"' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=3C16032D01C9,persistence=transient,deri' + + #9#9#9'"persistence=transient,_BoldInternal.toolId=3C16032D01C9,deri' + 'ved=True,\"_BoldInternal.unflattenedNamespace=BoldUMLModel.UMLMe' + 'ta.Bold Specifics\",Bold.DelphiName="' #9#9#9'TRUE' @@ -7862,7 +7860,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'"Bold"' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=3C16037401A3,persistence=transient,deri' + + #9#9#9'"persistence=transient,_BoldInternal.toolId=3C16037401A3,deri' + 'ved=True,\"_BoldInternal.unflattenedNamespace=BoldUMLModel.UMLMe' + 'ta.Bold Specifics\",Bold.DelphiName="' #9#9#9'TRUE' @@ -7910,7 +7908,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'"Bold"' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=3C16030102A2,persistence=transient,deri' + + #9#9#9'"persistence=transient,_BoldInternal.toolId=3C16030102A2,deri' + 'ved=True,\"_BoldInternal.unflattenedNamespace=BoldUMLModel.UMLMe' + 'ta.Bold Specifics\",Bold.DelphiName="' #9#9#9'TRUE' @@ -7958,7 +7956,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=3C160E28029D,persistence=Persistent,\"_' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=3C160E28029D,\"_' + 'BoldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Bold Spec' + 'ifics\",_Boldify.noName=True,Bold.DelphiName="' #9#9#9'FALSE' @@ -8005,7 +8003,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'"Bold"' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=3C160E2A021E,persistence=Persistent,\"_' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=3C160E2A021E,\"_' + 'BoldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Bold Spec' + 'ifics\",_Boldify.noName=True,Bold.DelphiName="' #9#9#9'FALSE' @@ -8050,7 +8048,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'"Bold"' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=3C160DEB012D,persistence=Persistent,\"_' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=3C160DEB012D,\"_' + 'BoldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Bold Spec' + 'ifics\",_Boldify.noName=True,Bold.DelphiName="' #9#9#9'FALSE' @@ -8098,7 +8096,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'"Bold"' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=3C1603D1025B,persistence=transient,deri' + + #9#9#9'"persistence=transient,_BoldInternal.toolId=3C1603D1025B,deri' + 'ved=True,\"_BoldInternal.unflattenedNamespace=BoldUMLModel.UMLMe' + 'ta.Bold Specifics\",Bold.DelphiName="' #9#9#9'TRUE' @@ -8146,7 +8144,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'"Bold"' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=3C16041703C4,persistence=transient,deri' + + #9#9#9'"persistence=transient,_BoldInternal.toolId=3C16041703C4,deri' + 'ved=True,\"_BoldInternal.unflattenedNamespace=BoldUMLModel.UMLMe' + 'ta.Bold Specifics\",Bold.DelphiName="' #9#9#9'TRUE' @@ -8195,7 +8193,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=3C14CE1102B7,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=3C14CE1102B7,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Model_Manag' + 'ement,_Boldify.noName=True,Bold.DelphiName="' #9#9#9'FALSE' @@ -8240,7 +8238,7 @@ object dmModelEdit: TdmModelEdit #9#9#9'""' #9#9#9'""' - #9#9#9'"_BoldInternal.toolId=3C14CE6403A7,persistence=Persistent,_Bo' + + #9#9#9'"persistence=Persistent,_BoldInternal.toolId=3C14CE6403A7,_Bo' + 'ldInternal.unflattenedNamespace=BoldUMLModel.UMLMeta.Model_Manag' + 'ement,_Boldify.noName=True,Bold.DelphiName="' #9#9#9'FALSE' @@ -8501,7 +8499,7 @@ object dmModelEdit: TdmModelEdit MapperName = 'TBoldPMInteger' Accessor = 'AsScopeKind' NativeType = 'TScopeKind' - UnitName = 'BoldUMLAttributes' + BoldUnitName = 'BoldUMLAttributes' end item ModelName = 'TableMapping' @@ -8511,7 +8509,7 @@ object dmModelEdit: TdmModelEdit MapperName = 'TBoldPMInteger' Accessor = 'AsTableMapping' NativeType = 'TTableMapping' - UnitName = 'BoldUMLAttributes' + BoldUnitName = 'BoldUMLAttributes' end item ModelName = 'ParameterDirectionKind' @@ -8521,7 +8519,7 @@ object dmModelEdit: TdmModelEdit MapperName = 'TBoldPMInteger' Accessor = 'AsParameterDirectionKind' NativeType = 'TBoldParameterDirectionKind' - UnitName = 'BoldUMLAttributes' + BoldUnitName = 'BoldUMLAttributes' end item ModelName = 'Severity' @@ -8531,7 +8529,7 @@ object dmModelEdit: TdmModelEdit MapperName = 'TBoldPMInteger' Accessor = 'AsSeverity' NativeType = 'TSeverity' - UnitName = 'BoldUMLAttributes' + BoldUnitName = 'BoldUMLAttributes' end item ModelName = 'Stereotype' @@ -8541,7 +8539,7 @@ object dmModelEdit: TdmModelEdit MapperName = 'TBoldPMInteger' Accessor = 'AsStereotype' NativeType = 'TBoldAttributeStereotype' - UnitName = 'BoldUMLAttributes' + BoldUnitName = 'BoldUMLAttributes' end item ModelName = 'DelphiFunctionType' @@ -8551,7 +8549,7 @@ object dmModelEdit: TdmModelEdit MapperName = 'TBoldPMInteger' Accessor = 'AsDelphiFunctionType' NativeType = 'TDelphiFunctionType' - UnitName = 'BoldUMLAttributes' + BoldUnitName = 'BoldUMLAttributes' end item ModelName = 'AggregationKind' @@ -8561,7 +8559,7 @@ object dmModelEdit: TdmModelEdit MapperName = 'TBoldPMInteger' Accessor = 'AsAggregationKind' NativeType = 'TAggregationKind' - UnitName = 'BoldUMLAttributes' + BoldUnitName = 'BoldUMLAttributes' end item ModelName = 'VisibilityKind' @@ -8571,7 +8569,7 @@ object dmModelEdit: TdmModelEdit MapperName = 'TBoldPMInteger' Accessor = 'AsVisibilityKind' NativeType = 'TVisibilityKind' - UnitName = 'BoldUMLAttributes' + BoldUnitName = 'BoldUMLAttributes' end item ModelName = 'ChangeableKind' @@ -8581,7 +8579,7 @@ object dmModelEdit: TdmModelEdit MapperName = 'TBoldPMInteger' Accessor = 'AsChangeableKind' NativeType = 'TChangeableKind' - UnitName = 'BoldUMLAttributes' + BoldUnitName = 'BoldUMLAttributes' end item ModelName = 'Constraint' @@ -8608,7 +8606,7 @@ object dmModelEdit: TdmModelEdit MapperName = 'TBoldPMInteger' Accessor = 'AsOrderingKind' NativeType = 'TOrderingKind' - UnitName = 'BoldUMLAttributes' + BoldUnitName = 'BoldUMLAttributes' end item ModelName = 'Multiplicity' @@ -8708,7 +8706,7 @@ object dmModelEdit: TdmModelEdit MapperName = 'TBoldPMInteger' Accessor = 'as' NativeType = 'T' - UnitName = 'BoldUMLAttributes' + BoldUnitName = 'BoldUMLAttributes' end item ModelName = 'CallConcurrencyKind' @@ -8718,7 +8716,7 @@ object dmModelEdit: TdmModelEdit MapperName = 'TBoldPMInteger' Accessor = 'as' NativeType = 'T' - UnitName = 'BoldUMLAttributes' + BoldUnitName = 'BoldUMLAttributes' end item ModelName = 'MessageDirectionKind' @@ -8728,7 +8726,7 @@ object dmModelEdit: TdmModelEdit MapperName = 'TBoldPMInteger' Accessor = 'as' NativeType = 'T' - UnitName = 'BoldUMLAttributes' + BoldUnitName = 'BoldUMLAttributes' end item ModelName = '__TBAString' From 8b5ac640ec0c4e6eaf793dfe98f7f97f6719e487 Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Mon, 24 May 2021 03:17:26 +0300 Subject: [PATCH 086/112] Fix design time error --- Source/Handles/Core/BoldPlaceableSubscriber.pas | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Source/Handles/Core/BoldPlaceableSubscriber.pas b/Source/Handles/Core/BoldPlaceableSubscriber.pas index a3b1811..26c1511 100644 --- a/Source/Handles/Core/BoldPlaceableSubscriber.pas +++ b/Source/Handles/Core/BoldPlaceableSubscriber.pas @@ -136,8 +136,9 @@ procedure TBoldPlaceableSubscriber.Receive(Originator: TObject; OriginalEvent: T procedure TBoldPlaceableSubscriber.ActOnHandleValueChanged(Sender: TObject); begin fValueSubscriber.CancelAllSubscriptions; - if not (csDestroying in ComponentState) and assigned(BoldHandle) and not (csDestroying in BoldHandle.ComponentState) and assigned(BoldHandle.Value) then - SubscribeToElement(BoldHandle.Value, fValueSubscriber); + if Assigned(BoldHandle) and not (csDesigning in BoldHandle.ComponentState) then + if not (csDestroying in ComponentState) and assigned(BoldHandle) and not (csDestroying in BoldHandle.ComponentState) and assigned(BoldHandle.Value) then + SubscribeToElement(BoldHandle.Value, fValueSubscriber); end; procedure TBoldPlaceableSubscriber.SetDelayEventsUntilPostNotify(const Value: Boolean); @@ -145,6 +146,4 @@ procedure TBoldPlaceableSubscriber.SetDelayEventsUntilPostNotify(const Value: Bo FDelayEventsUntilPostNotify := Value; end; -initialization - end. From f36c412958e5ea2f3e15e9b62569dc4af98cc64b Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Mon, 24 May 2021 13:22:58 +0300 Subject: [PATCH 087/112] Added missing res file --- BoldOLLEHandles.res | Bin 0 -> 484 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 BoldOLLEHandles.res diff --git a/BoldOLLEHandles.res b/BoldOLLEHandles.res new file mode 100644 index 0000000000000000000000000000000000000000..9bc2ce0f023a349deef32cca37f3a7cdbe45de13 GIT binary patch literal 484 zcmZ`zF>b;@5F8^cLxX%>QbeMp%mdN{1&P8UTjazy+?n#a*i};cIWBlmO1fkA7G$Sj z<=q+2?(Gf$teG)dlKzV}1Ky~_IKvmV_(X+|R4eST$2$)ES8nl&m&JX-hUDp%8Rkh| zbKiMod7m>306&Caz)H#t7>0ojHK-5`Sj}^U7r-+T6it(pD@gP6T~k(&Q@qq71{88g zUYP#JcMxq)^%~H5wrb%Z4f?U5?7B`(Fv`B~3!{GA?)?>Bly(*X literal 0 HcmV?d00001 From 3816bd7a96e4f98eb89e2e83a6de838c0f1a7ee3 Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Mon, 24 May 2021 13:46:47 +0300 Subject: [PATCH 088/112] Remove IbExpress reference --- dclBoldUniDAC.dpk | 1 - dclBoldUniDAC.dproj | 1 - 2 files changed, 2 deletions(-) diff --git a/dclBoldUniDAC.dpk b/dclBoldUniDAC.dpk index ee3d7f7..e5197c7 100644 --- a/dclBoldUniDAC.dpk +++ b/dclBoldUniDAC.dpk @@ -33,7 +33,6 @@ package dclBoldUniDAC; requires rtl, vcldb, - ibxpress, DesignIDE, dclBold; diff --git a/dclBoldUniDAC.dproj b/dclBoldUniDAC.dproj index 8dc0a19..716d3ea 100644 --- a/dclBoldUniDAC.dproj +++ b/dclBoldUniDAC.dproj @@ -104,7 +104,6 @@ - From a5ae709981d51d3a18df337d77a77917d89b3e5f Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Mon, 24 May 2021 14:06:46 +0300 Subject: [PATCH 089/112] Minor fixes --- Source/Common/Logging/BoldLogForm.dfm | 8 ++-- Source/Handles/Core/BoldOclRepository.pas | 48 +++++++++++-------- .../Handles/Core/BoldPlaceableSubscriber.pas | 2 +- 3 files changed, 32 insertions(+), 26 deletions(-) diff --git a/Source/Common/Logging/BoldLogForm.dfm b/Source/Common/Logging/BoldLogForm.dfm index 7d97f55..ce1da62 100644 --- a/Source/Common/Logging/BoldLogForm.dfm +++ b/Source/Common/Logging/BoldLogForm.dfm @@ -3,7 +3,7 @@ object BoldLogForm: TBoldLogForm Top = 234 Caption = 'Bold' ClientHeight = 289 - ClientWidth = 453 + ClientWidth = 553 Color = clBtnFace Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText @@ -43,7 +43,7 @@ object BoldLogForm: TBoldLogForm object Log: TRichEdit Left = 0 Top = 0 - Width = 453 + Width = 553 Height = 269 Align = alClient ReadOnly = True @@ -53,7 +53,7 @@ object BoldLogForm: TBoldLogForm object Panel1: TPanel Left = 0 Top = 269 - Width = 453 + Width = 553 Height = 20 Align = alBottom BevelOuter = bvNone @@ -61,7 +61,7 @@ object BoldLogForm: TBoldLogForm object ProgressBar1: TProgressBar Left = 0 Top = 0 - Width = 453 + Width = 553 Height = 20 Align = alClient Step = 1 diff --git a/Source/Handles/Core/BoldOclRepository.pas b/Source/Handles/Core/BoldOclRepository.pas index 81c2952..20ca7af 100644 --- a/Source/Handles/Core/BoldOclRepository.pas +++ b/Source/Handles/Core/BoldOclRepository.pas @@ -20,21 +20,22 @@ TBoldOclDefinitions = class; TBoldOclDefinition = class; TBoldOclRepository = class; - TBoldOclRepository = class(TBoldNonSystemHandle, IBoldValidateableComponent) + TBoldOclRepository = class(TBoldSubscribableComponent, IBoldValidateableComponent) private + fSystemHandle: TBoldSystemHandle; FOclDefinitions: TBoldOclDefinitions; procedure SetOclDefinitions(const Value: TBoldOclDefinitions); -// procedure SetStaticSystemHandle(Value: TBoldSystemHandle); + procedure SetSystemHandle(Value: TBoldSystemHandle); protected -// procedure Notification(AComponent: TComponent; Operation: TOperation); override; - procedure SetStaticSystemHandle(Value: TBoldAbstractSystemHandle); override; - function ValidateComponent(ComponentValidator: TBoldComponentValidator; NamePrefix: String): Boolean; override; + procedure Notification(AComponent: TComponent; Operation: TOperation); override; + function ValidateComponent(ComponentValidator: TBoldComponentValidator; NamePrefix: String): Boolean; public constructor Create(owner: TComponent); override; destructor Destroy; override; function LookUpOclDefinition(Name: string): string; published property OclDefinitions: TBoldOclDefinitions read FOclDefinitions write SetOclDefinitions; + property SystemHandle: TBoldSystemHandle read FSystemHandle write SetSystemHandle; end; TBoldOclDefinitions = class(TCollection) @@ -106,27 +107,34 @@ function TBoldOclRepository.LookUpOclDefinition(Name: string): string; result := OclDefinitions.LookUpOclDefinition(Name); end; +procedure TBoldOclRepository.Notification(AComponent: TComponent; + Operation: TOperation); +begin + inherited Notification(AComponent, Operation); + if (Operation = opRemove) and (AComponent = SystemHandle) then + SystemHandle := nil; +end; + procedure TBoldOclRepository.SetOclDefinitions( const Value: TBoldOclDefinitions); begin FOclDefinitions := Value; end; -procedure TBoldOclRepository.SetStaticSystemHandle(Value: TBoldAbstractSystemHandle); +procedure TBoldOclRepository.SetSystemHandle(Value: TBoldSystemHandle); begin - if StaticSystemHandle = Value then + if fSystemHandle = Value then exit; - if assigned(StaticSystemHandle) then + if assigned(Value) then begin - (StaticSystemHandle as TBoldSystemHandle).InstallOclDefinitionLookUp(nil); - StaticSystemHandle.RemoveFreeNotification(self); + fSystemHandle.InstallOclDefinitionLookUp(nil); + fSystemHandle.RemoveFreeNotification(self); end; if assigned(Value) then begin - (Value as TBoldSystemHandle).InstallOclDefinitionLookUp(LookUpOclDefinition); + Value.InstallOclDefinitionLookUp(LookUpOclDefinition); Value.FreeNotification(Self); end; - inherited SetStaticSystemHandle(Value); end; function TBoldOclRepository.ValidateComponent( @@ -136,15 +144,14 @@ function TBoldOclRepository.ValidateComponent( i: integer; Context: TBoldElementTypeInfo; begin - result := inherited ValidateComponent(ComponentValidator, NamePrefix); - if not assigned(StaticSystemHandle) then - BoldLog.LogFmt('*** OclRepository %s%s has no StaticSystemHandle', [NamePrefix, Name]) - else if not assigned(StaticSystemHandle.StaticSystemTypeInfo) then - BoldLog.LogFmt('*** StaticSystemHandle of OclRepository %s%s has no TypeInfo', [NamePrefix, Name]) + if not assigned(SystemHandle) then + BoldLog.LogFmt('*** OclRepository %s%s has no SystemHandle', [NamePrefix, Name]) + else if not assigned(SystemHandle.StaticSystemTypeInfo) then + BoldLog.LogFmt('*** SystemHandle of OclRepository %s%s has no TypeInfo', [NamePrefix, Name]) else begin for i := 0 to OclDefinitions.count-1 do begin - Context := StaticSystemHandle.StaticSystemTypeInfo.ElementTypeInfoByExpressionName[OclDefinitions[i].Context]; + Context := SystemHandle.StaticSystemTypeInfo.ElementTypeInfoByExpressionName[OclDefinitions[i].Context]; result := ComponentValidator.ValidateExpressionInContext( OclDefinitions[i].Expression, Context, @@ -193,8 +200,8 @@ function TBoldOclDefinition.GetExpression: TBoldExpression; function TBoldOclDefinition.GetSystemTypeInfo: TBoldSystemTypeInfo; begin - if assigned(Definitions.OwningRepository.StaticSystemHandle) then - result := Definitions.OwningRepository.StaticSystemHandle.StaticSystemTypeInfo + if assigned(Definitions.OwningRepository.SystemHandle) then + result := Definitions.OwningRepository.SystemHandle.StaticSystemTypeInfo else result := nil; end; @@ -294,5 +301,4 @@ function TBoldOclDefinitions.NameIsUnique(Name: String): Boolean; end; end; -initialization end. diff --git a/Source/Handles/Core/BoldPlaceableSubscriber.pas b/Source/Handles/Core/BoldPlaceableSubscriber.pas index 26c1511..9131abc 100644 --- a/Source/Handles/Core/BoldPlaceableSubscriber.pas +++ b/Source/Handles/Core/BoldPlaceableSubscriber.pas @@ -137,7 +137,7 @@ procedure TBoldPlaceableSubscriber.ActOnHandleValueChanged(Sender: TObject); begin fValueSubscriber.CancelAllSubscriptions; if Assigned(BoldHandle) and not (csDesigning in BoldHandle.ComponentState) then - if not (csDestroying in ComponentState) and assigned(BoldHandle) and not (csDestroying in BoldHandle.ComponentState) and assigned(BoldHandle.Value) then + if not (csDestroying in ComponentState) and not (csDestroying in BoldHandle.ComponentState) and assigned(BoldHandle.Value) then SubscribeToElement(BoldHandle.Value, fValueSubscriber); end; From 6c16a949c3b5803b4454d6257231dfc1b47c0ed4 Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Mon, 24 May 2021 14:07:08 +0300 Subject: [PATCH 090/112] New TBoldEvolveDBAction --- Source/Persistence/DB/BoldDBActions.pas | 33 ++++++++++++++++++- .../DB/BoldPersistenceHandleDBreg.pas | 3 +- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/Source/Persistence/DB/BoldDBActions.pas b/Source/Persistence/DB/BoldDBActions.pas index a8394ad..2049bef 100644 --- a/Source/Persistence/DB/BoldDBActions.pas +++ b/Source/Persistence/DB/BoldDBActions.pas @@ -15,11 +15,15 @@ interface BoldDbDataValidator, ActnList; +const + cDefaultPauseBetweenQueries = 1; //ms + type TBoldPersistenceHandleAction = class; TBoldGenerateSchemaAction = class; TBoldValidateDBStructureAction = class; TBoldValidateDBDataAction = class; + TBoldEvolveDBAction = class; { TBoldSystemHandleAction } TBoldPersistenceHandleAction = class(TAction) @@ -74,8 +78,19 @@ TBoldValidateDBDataAction = class(TBoldPersistenceHandleAction) destructor Destroy; override; procedure ExecuteTarget(Target: TObject); override; published - property PauseBetweenQueries: integer read fPauseBetweenQueries write fPauseBetweenQueries; + property PauseBetweenQueries: integer read fPauseBetweenQueries write fPauseBetweenQueries default cDefaultPauseBetweenQueries; + property BoldPersistenceHandleDB; + end; + + TBoldEvolveDBAction = class(TBoldPersistenceHandleAction) + private + fGenerateGenericScript: boolean; + public + constructor Create(AOwner: TComponent); override; + procedure ExecuteTarget(Target: TObject); override; + published property BoldPersistenceHandleDB; + property GenerateGenericScript: boolean read fGenerateGenericScript write fGenerateGenericScript; end; implementation @@ -84,6 +99,8 @@ implementation BoldDefs, SysUtils, BoldActionDefs, + BoldDbEvolutor, + BoldDbEvolutorForm, BoldUtils; const @@ -218,4 +235,18 @@ procedure TBoldValidateDBDataAction.ExecuteTarget(Target: TObject); fValidator.Execute; end; +{ TBoldEvolveDBAction } + +constructor TBoldEvolveDBAction.Create(AOwner: TComponent); +begin + inherited; + Caption := 'Evolve DB'; +end; + +procedure TBoldEvolveDBAction.ExecuteTarget(Target: TObject); +begin + inherited; + TfrmBoldDbEvolutor.EvolveDB(BoldPersistenceHandleDB, GenerateGenericScript); +end; + end. diff --git a/Source/Persistence/DB/BoldPersistenceHandleDBreg.pas b/Source/Persistence/DB/BoldPersistenceHandleDBreg.pas index 989c33a..5778908 100644 --- a/Source/Persistence/DB/BoldPersistenceHandleDBreg.pas +++ b/Source/Persistence/DB/BoldPersistenceHandleDBreg.pas @@ -45,7 +45,8 @@ procedure Register; RegisterActions(BOLDACTIONGROUPNAME, [TBoldGenerateSchemaAction, TBoldValidateDBStructureAction, - TBoldValidateDBDataAction], nil); + TBoldValidateDBDataAction, + TBoldEvolveDBAction], nil); RegisterComponentEditor(TBoldPersistenceHandleDB, TBoldPersistenceHandleDBEditor); end; From 73a50d67b340684da7636efeb1ea6b216de3d82f Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Mon, 24 May 2021 14:09:43 +0300 Subject: [PATCH 091/112] Minor refactoring of code modifying property editors --- .../IDE/BoldControlPackPropertyEditors.pas | 36 +++++++------- .../IDE/BoldAbstractPropertyEditors.pas | 49 +++++++++++++------ Source/Common/IDE/BoldPropertyEditors.pas | 19 ++++--- 3 files changed, 66 insertions(+), 38 deletions(-) diff --git a/Source/BoldAwareGUI/IDE/BoldControlPackPropertyEditors.pas b/Source/BoldAwareGUI/IDE/BoldControlPackPropertyEditors.pas index d611e97..7bb2d36 100644 --- a/Source/BoldAwareGUI/IDE/BoldControlPackPropertyEditors.pas +++ b/Source/BoldAwareGUI/IDE/BoldControlPackPropertyEditors.pas @@ -100,7 +100,7 @@ TBoldAsCheckBoxStateRendererEditor = class(TBoldComponentDblClickEditor) {---TBoldGetAsStringMethodProperty---} TBoldGetAsStringMethodProperty = class(TBoldOTAModifyingMethodProperty) public - function TextToInsert: string; override; + function ImplementationTextToInsert: string; override; function GetDeltaLines: integer; override; function GetColPos: integer; override; end; @@ -108,7 +108,7 @@ TBoldGetAsStringMethodProperty = class(TBoldOTAModifyingMethodProperty) {---TBoldGetAsCheckBoxStateMethodProperty---} TBoldGetAsCheckBoxStateMethodProperty = class(TBoldOTAModifyingMethodProperty) public - function TextToInsert: string; override; + function ImplementationTextToInsert: string; override; function GetDeltaLines: integer; override; function GetColPos: integer; override; end; @@ -116,7 +116,7 @@ TBoldGetAsCheckBoxStateMethodProperty = class(TBoldOTAModifyingMethodProperty) {---TBoldGetAsIntegerEventMethodProperty---} TBoldGetAsIntegerEventMethodProperty = class(TBoldOTAModifyingMethodProperty) public - function TextToInsert: string; override; + function ImplementationTextToInsert: string; override; function GetDeltaLines: integer; override; function GetColPos: integer; override; end; @@ -124,7 +124,7 @@ TBoldGetAsIntegerEventMethodProperty = class(TBoldOTAModifyingMethodProperty) {---TBoldGetAsFloatEventMethodProperty---} TBoldGetAsFloatEventMethodProperty = class(TBoldOTAModifyingMethodProperty) public - function TextToInsert: string; override; + function ImplementationTextToInsert: string; override; function GetDeltaLines: integer; override; function GetColPos: integer; override; end; @@ -132,7 +132,7 @@ TBoldGetAsFloatEventMethodProperty = class(TBoldOTAModifyingMethodProperty) {---TBoldGetAsViewerMethodProperty---} TBoldGetAsViewerMethodProperty = class(TBoldOTAModifyingMethodProperty) public - function TextToInsert: string; override; + function ImplementationTextToInsert: string; override; function GetDeltaLines: integer; override; function GetColPos: integer; override; end; @@ -140,19 +140,19 @@ TBoldGetAsViewerMethodProperty = class(TBoldOTAModifyingMethodProperty) { TBoldHoldsChangedValueMethodProperty } TBoldHoldsChangedValueMethodProperty = class(TBoldOneLinerWithEvalMethodProperty) public - function TextToInsert: string; override; + function ImplementationTextToInsert: string; override; end; { TBoldReleaseChangedValueMethodProperty } TBoldReleaseChangedValueMethodProperty = class(TBoldOneLinerWithEvalMethodProperty) public - function TextToInsert: string; override; + function ImplementationTextToInsert: string; override; end; { TBoldMayModifyMethodProperty } TBoldMayModifyMethodProperty = class(TBoldOneLinerWithEvalMethodProperty) public - function TextToInsert: string; override; + function ImplementationTextToInsert: string; override; function GetDeltaLines: integer; override; end; @@ -165,7 +165,7 @@ TBoldAsVariantRendererEditor = class(TBoldComponentDblClickEditor) {---TBoldGetAsVariantMethodProperty---} TBoldGetAsVariantMethodProperty = class(TBoldOTAModifyingMethodProperty) public - function TextToInsert: string; override; + function ImplementationTextToInsert: string; override; function GetDeltaLines: integer; override; function GetColPos: integer; override; end; @@ -253,7 +253,7 @@ function TBoldAsCheckBoxStateRendererEditor.GetDefaultMethodName: string; end; {---TBoldGetAsStringMethodProperty---} -function TBoldGetAsStringMethodProperty.TextToInsert: string; +function TBoldGetAsStringMethodProperty.ImplementationTextToInsert: string; begin Result := ''; {$IFDEF BOLD_DELPHI} @@ -275,7 +275,7 @@ function TBoldGetAsStringMethodProperty.GetColPos: integer; end; {---TBoldGetAsCheckBoxStateMethodProperty---} -function TBoldGetAsCheckBoxStateMethodProperty.TextToInsert: string; +function TBoldGetAsCheckBoxStateMethodProperty.ImplementationTextToInsert: string; begin Result := ''; {$IFDEF BOLD_DELPHI} @@ -297,7 +297,7 @@ function TBoldGetAsCheckBoxStateMethodProperty.GetColPos: integer; end; {---TBoldGetAsIntegerEventMethodProperty---} -function TBoldGetAsIntegerEventMethodProperty.TextToInsert: string; +function TBoldGetAsIntegerEventMethodProperty.ImplementationTextToInsert: string; begin Result := ''; {$IFDEF BOLD_DELPHI} @@ -320,7 +320,7 @@ function TBoldGetAsIntegerEventMethodProperty.GetColPos: integer; {--- TBoldHoldsChangedValueMethodProperty ---} -function TBoldHoldsChangedValueMethodProperty.TextToInsert: string; +function TBoldHoldsChangedValueMethodProperty.ImplementationTextToInsert: string; begin result := Format(' AFollower.Element%sEvaluateExpressionAsDirectElement(%s%s).RegisterModifiedValueHolder(AFollower.Subscriber);', [BOLDSYM_POINTERDEREFERENCE, BOLDSYM_QUOTECHAR, BOLDSYM_QUOTECHAR]); @@ -328,13 +328,13 @@ function TBoldHoldsChangedValueMethodProperty.TextToInsert: string; {--- TBoldReleaseChangedValueMethodProperty ---} -function TBoldReleaseChangedValueMethodProperty.TextToInsert: string; +function TBoldReleaseChangedValueMethodProperty.ImplementationTextToInsert: string; begin result := Format(' AFollower.Element%sEvaluateExpressionAsDirectElement(%s%s).UnRegisterModifiedValueHolder(AFollower.Subscriber);', [BOLDSYM_POINTERDEREFERENCE, BOLDSYM_QUOTECHAR, BOLDSYM_QUOTECHAR]); end; -function TBoldMayModifyMethodProperty.TextToInsert: string; +function TBoldMayModifyMethodProperty.ImplementationTextToInsert: string; begin result := Format(' %sresult %s AFollower.Element%sEvaluateExpressionAsDirectElement(%s%s).ObserverMayModify(AFollower.subscriber);', [BOLDSYM_TYPEINTEGER, BOLDSYM_ASSIGNMENT, BOLDSYM_POINTERDEREFERENCE, BOLDSYM_QUOTECHAR, BOLDSYM_QUOTECHAR]); @@ -347,7 +347,7 @@ function TBoldMayModifyMethodProperty.GetDeltaLines: integer; end; {---TBoldGetAsViewerMethodProperty---} -function TBoldGetAsViewerMethodProperty.TextToInsert: string; +function TBoldGetAsViewerMethodProperty.ImplementationTextToInsert: string; begin Result := ''; {$IFDEF BOLD_DELPHI} @@ -529,7 +529,7 @@ function TBoldGetAsFloatEventMethodProperty.GetDeltaLines: integer; Result := -1; end; -function TBoldGetAsFloatEventMethodProperty.TextToInsert: string; +function TBoldGetAsFloatEventMethodProperty.ImplementationTextToInsert: string; begin Result := ''; {$IFDEF BOLD_DELPHI} @@ -581,7 +581,7 @@ function TBoldGetAsVariantMethodProperty.GetDeltaLines: integer; Result := -1; end; -function TBoldGetAsVariantMethodProperty.TextToInsert: string; +function TBoldGetAsVariantMethodProperty.ImplementationTextToInsert: string; begin Result := ''; {$IFDEF BOLD_DELPHI} diff --git a/Source/Common/IDE/BoldAbstractPropertyEditors.pas b/Source/Common/IDE/BoldAbstractPropertyEditors.pas index 0f988ec..39cef2e 100644 --- a/Source/Common/IDE/BoldAbstractPropertyEditors.pas +++ b/Source/Common/IDE/BoldAbstractPropertyEditors.pas @@ -6,15 +6,9 @@ interface uses - {$IFDEF BOLD_CLX} - Types, - QGraphics, - {$ELSE} Windows, Graphics, - {$ENDIF} - DesignEditors{, - EditIntf}; + DesignEditors; type { forward declarations } @@ -97,10 +91,14 @@ TBoldComponentPropertyIndicateMissing = class(TBoldComponentProperty) { Source code altering property editors } { TModifyingMethodProperty } TModifyingMethodProperty = class(TBoldMethodProperty) + protected + procedure InsertText(const s: string); virtual; public procedure Edit; override; - procedure InsertText(const s: string); virtual; - function TextToInsert: string; virtual; + procedure InsertVariables; virtual; + procedure InsertImplementation; virtual; + function ImplementationTextToInsert: string; virtual; + function VariableDefinitionTextToInsert: string; virtual; procedure ReposCursor(DeltaLines, ColPos: integer); function GetDeltaLines: integer; virtual; function GetColPos: integer; virtual; @@ -145,7 +143,8 @@ procedure TModifyingMethodProperty.Edit; inherited; if NewMethod and ConfirmAdd then begin - InsertText(TextToInsert); + InsertVariables; + InsertImplementation; ReposCursor(DeltaLines, ColPos); end; end; @@ -155,7 +154,12 @@ function TModifyingMethodProperty.ConfirmAdd: boolean; Result := True; end; -function TModifyingMethodProperty.TextToInsert: string; +function TModifyingMethodProperty.VariableDefinitionTextToInsert: string; +begin + result := ''; +end; + +function TModifyingMethodProperty.ImplementationTextToInsert: string; begin Result := ''; end; @@ -164,6 +168,24 @@ procedure TModifyingMethodProperty.InsertText(const s: string); begin end; +procedure TModifyingMethodProperty.InsertVariables; +var + s: string; +begin + s := VariableDefinitionTextToInsert; + if s = '' then + exit; + ReposCursor(-1, 0); + InsertText(s); + ReposCursor(2, 0); +end; + +procedure TModifyingMethodProperty.InsertImplementation; +begin +// ReposCursor(-1, 0); + InsertText(ImplementationTextToInsert); +end; + procedure TModifyingMethodProperty.ReposCursor(DeltaLines, ColPos: integer); var ColDelta: integer; @@ -202,8 +224,7 @@ procedure TBoldOTAModifyingMethodProperty.InsertText(const s: string); EditPos: TOTAEditpos; CharPos: TOTACharpos; begin - if (s <> '') and - Supports(BorlandIDEServices, IOTAEditorServices, EditorServices) then + if (s <> '') and Supports(BorlandIDEServices, IOTAEditorServices, EditorServices) then begin EditPos := EditorServices.TopBuffer.TopView.CursorPos; EditorServices.TopBuffer.TopView.ConvertPos(True, EditPos, CharPos); @@ -247,7 +268,7 @@ function TBoldOneLinerWithEvalMethodProperty.GetDeltaLines: integer; function TBoldOneLinerWithEvalMethodProperty.GetColPos: integer; begin - Result := Pos(BOLDSYM_QUOTECHAR, TextToInsert)+1; + Result := Pos(BOLDSYM_QUOTECHAR, ImplementationTextToInsert)+1; end; { TBoldStringProperty } diff --git a/Source/Common/IDE/BoldPropertyEditors.pas b/Source/Common/IDE/BoldPropertyEditors.pas index 479252d..0e3f361 100644 --- a/Source/Common/IDE/BoldPropertyEditors.pas +++ b/Source/Common/IDE/BoldPropertyEditors.pas @@ -141,6 +141,7 @@ TBoldStringListEditor = class(TDefaultEditor) function DerivedFrom(TypeInfo: PTypeInfo; const aClass: TClass): boolean; public procedure EditProperty(const PropertyEditor: IProperty; var Continue: Boolean); override; + destructor Destroy; override; end; {---TBoldFileNameProperty---} @@ -155,13 +156,13 @@ TBoldFileNameProperty = class(TBoldStringProperty) {---TBoldElementSubscribeMethodProperty---} TBoldElementSubscribeMethodProperty = class(TBoldOneLinerWithEvalMethodProperty) public - function TextToInsert: string; override; + function ImplementationTextToInsert: string; override; end; {---TBoldElementFilterMethodProperty---} TBoldElementFilterMethodProperty = class(TBoldOTAModifyingMethodProperty) public - function TextToInsert: string; override; + function ImplementationTextToInsert: string; override; function GetDeltaLines: integer; override; function GetColPos: integer; override; end; @@ -169,7 +170,7 @@ TBoldElementFilterMethodProperty = class(TBoldOTAModifyingMethodProperty) {---TBoldElementCompareMethodProperty---} TBoldElementCompareMethodProperty = class(TBoldOTAModifyingMethodProperty) public - function TextToInsert: string; override; + function ImplementationTextToInsert: string; override; function GetDeltaLines: integer; override; function GetColPos: integer; override; end; @@ -234,6 +235,12 @@ function TBoldStringListEditor.DerivedFrom(TypeInfo: PTypeInfo; aClass.InheritsFrom(TypeData^.ClassType); end; +destructor TBoldStringListEditor.Destroy; +begin + FreeAndNil(fTimer); + inherited; +end; + procedure TBoldStringListEditor.EditProperty(const PropertyEditor: IProperty; var Continue: Boolean); begin inherited; @@ -296,13 +303,13 @@ function TBoldFileNameProperty.GetAttributes: TPropertyAttributes; end; {---TBoldElementSubscribeMethodProperty---} -function TBoldElementSubscribeMethodProperty.TextToInsert: string; +function TBoldElementSubscribeMethodProperty.ImplementationTextToInsert: string; begin Result := Format(' Element%sSubscribeToExpression(%s%s, Subscriber, False);', [BOLDSYM_POINTERDEREFERENCE, BOLDSYM_QUOTECHAR, BOLDSYM_QUOTECHAR]); // do not localize end; {---TBoldElementFilterMethodProperty---} -function TBoldElementFilterMethodProperty.TextToInsert: string; +function TBoldElementFilterMethodProperty.ImplementationTextToInsert: string; begin Result := ''; {$IFDEF BOLD_DELPHI} @@ -324,7 +331,7 @@ function TBoldElementFilterMethodProperty.GetColPos: integer; end; {---TBoldElementCompareMethodProperty---} -function TBoldElementCompareMethodProperty.TextToInsert: string; +function TBoldElementCompareMethodProperty.ImplementationTextToInsert: string; begin Result := Format(' %sResult %s 0;', [BOLDSYM_TYPEINTEGER, BOLDSYM_ASSIGNMENT]) + BOLDCRLF; // do not localize Result := Result + Format(' if %s(item1) %s %s(item2) %s', [BOLDSYM_ASSIGNED, BOLDSYM_AND, BOLDSYM_ASSIGNED, BOLDSYM_THEN]) + BOLDCRLF; // do not localize From 1b238df316abea86ab4f131a4ba1a70d783654f5 Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Mon, 24 May 2021 14:19:48 +0300 Subject: [PATCH 092/112] Updated demo with new actions --- examples/Delphi/Compound/Building/Datamod.dfm | 15 ++++---- examples/Delphi/Compound/Building/Datamod.pas | 1 - .../Delphi/Compound/Building/Mainform.dfm | 36 +++++++++++++++++-- .../Delphi/Compound/Building/Mainform.pas | 11 ++++-- 4 files changed, 50 insertions(+), 13 deletions(-) diff --git a/examples/Delphi/Compound/Building/Datamod.dfm b/examples/Delphi/Compound/Building/Datamod.dfm index 5e73f60..34d7861 100644 --- a/examples/Delphi/Compound/Building/Datamod.dfm +++ b/examples/Delphi/Compound/Building/Datamod.dfm @@ -399,6 +399,13 @@ object DataModule1: TDataModule1 object BoldDatabaseAdapterPostgres: TBoldDatabaseAdapterFireDAC SQLDatabaseConfig.DefaultSystemMapper = '' SQLDatabaseConfig.DefaultObjectMapper = '' + SQLDatabaseConfig.ColumnExistsTemplate = + 'SELECT column_name FROM information_schema.columns WHERE upper(t' + + 'able_name)=upper('#39''#39') and upper(column_name)=upper('#39''#39')' + SQLDatabaseConfig.IndexColumnExistsTemplate = + 'select indexname from pg_indexes where upper(tablename) = upper(' + + #39''#39')' SQLDatabaseConfig.ColumnTypeForDate = 'DATE' SQLDatabaseConfig.ColumnTypeForTime = 'TIME' SQLDatabaseConfig.ColumnTypeForDateTime = 'TIMESTAMP' @@ -420,14 +427,6 @@ object DataModule1: TDataModule1 'ower(datname) = lower('#39''#39'));' SQLDatabaseConfig.DropColumnTemplate = 'ALTER TABLE DROP ' SQLDatabaseConfig.DropTableTemplate = 'DROP TABLE ' - SQLDatabaseConfig.IndexInfoTemplate = - 'SELECT IND.NAME INDEXNAME, IND.IS_PRIMARY_KEY ISPRIMARY, IND.IS_' + - 'UNIQUE ISUNIQUE, COL.NAME COLUMNNAME FROM SYS.INDEXES IND INNER ' + - 'JOIN SYS.INDEX_COLUMNS IC ON IND.OBJECT_ID = IC.OBJECT_ID AND IN' + - 'D.INDEX_ID = IC.INDEX_ID INNER JOIN SYS.COLUMNS COL ON IC.OBJECT' + - '_ID = COL.OBJECT_ID AND IC.COLUMN_ID = COL.COLUMN_ID WHERE UPPER' + - '(OBJECT_NAME(IND.OBJECT_ID))=UPPER('#39''#39') ORDER BY INDEX' + - 'NAME, INDEX_COLUMN_ID' SQLDatabaseConfig.DropIndexTemplate = 'DROP INDEX ' SQLDatabaseConfig.EvolveDropsUnknownIndexes = True SQLDatabaseConfig.MaxDbIdentifierLength = 63 diff --git a/examples/Delphi/Compound/Building/Datamod.pas b/examples/Delphi/Compound/Building/Datamod.pas index 019d7ab..ed7f055 100644 --- a/examples/Delphi/Compound/Building/Datamod.pas +++ b/examples/Delphi/Compound/Building/Datamod.pas @@ -3,7 +3,6 @@ interface uses -// dbLogDlg, SysUtils, Classes, Controls, diff --git a/examples/Delphi/Compound/Building/Mainform.dfm b/examples/Delphi/Compound/Building/Mainform.dfm index 9360eea..d9716d5 100644 --- a/examples/Delphi/Compound/Building/Mainform.dfm +++ b/examples/Delphi/Compound/Building/Mainform.dfm @@ -699,8 +699,8 @@ object allform: Tallform end object pbdbNotification: TProgressBar Left = 4 - Top = 75 - Width = 96 + Top = 65 + Width = 98 Height = 16 Step = 1 TabOrder = 2 @@ -940,6 +940,22 @@ object allform: Tallform IgnoreUnknownTables = True DropExisting = True end + object BoldGenerateSchemaAction1: TBoldGenerateSchemaAction + Category = 'Bold Actions' + Caption = 'Generate Schema' + IgnoreUnknownTables = False + BoldPersistenceHandleDB = DataModule1.BoldPersistenceHandleDB1 + end + object BoldValidateDBStructureAction1: TBoldValidateDBStructureAction + Category = 'Bold Actions' + Caption = 'Validate DB Structure' + BoldPersistenceHandleDB = DataModule1.BoldPersistenceHandleDB1 + end + object BoldValidateDBDataAction1: TBoldValidateDBDataAction + Category = 'Bold Actions' + Caption = 'Validate DB Data' + BoldPersistenceHandleDB = DataModule1.BoldPersistenceHandleDB1 + end object BoldFailureDetectionAction1: TBoldFailureDetectionAction Category = 'Bold Actions' Caption = 'BoldFailureDetectionAction1' @@ -1002,12 +1018,19 @@ object allform: Tallform object BoldLogFormAction1: TBoldLogFormAction Category = 'Bold Actions' Caption = 'Log view' + ShortCut = 16460 end object BoldDiscardChangesAction1: TBoldDiscardChangesAction Category = 'Bold Actions' Caption = 'Discard changes' BoldSystemHandle = DataModule1.BoldSystemHandle1 end + object BoldEvolveDBAction1: TBoldEvolveDBAction + Category = 'Bold Actions' + Caption = 'Evolve DB' + BoldPersistenceHandleDB = DataModule1.BoldPersistenceHandleDB1 + GenerateGenericScript = False + end end object HighRentRenderer: TBoldAsStringRenderer OnSetFont = HighRentRendererSetFont @@ -1023,6 +1046,9 @@ object allform: Tallform object CreateDB1: TMenuItem Action = BoldCreateDatabaseAction1 end + object EvolveDB1: TMenuItem + Action = BoldEvolveDBAction1 + end object Opensystem2: TMenuItem Action = BoldActivateSystemAction1 end @@ -1038,6 +1064,12 @@ object allform: Tallform object BoldModelEditorAction1: TMenuItem Action = BoldModelEditorAction end + object ValidateDBData1: TMenuItem + Action = BoldValidateDBDataAction1 + end + object ValidateDBStructure1: TMenuItem + Action = BoldValidateDBStructureAction1 + end end object Edit1: TMenuItem Caption = 'Edit' diff --git a/examples/Delphi/Compound/Building/Mainform.pas b/examples/Delphi/Compound/Building/Mainform.pas index 129dec8..fd553d6 100644 --- a/examples/Delphi/Compound/Building/Mainform.pas +++ b/examples/Delphi/Compound/Building/Mainform.pas @@ -170,6 +170,13 @@ Tallform = class(TForm) UndoSubscriber: TBoldPlaceableSubscriber; BoldLogOSSAction1: TBoldLogOSSAction; oggleOSStrafficlogs1: TMenuItem; + BoldGenerateSchemaAction1: TBoldGenerateSchemaAction; + BoldValidateDBStructureAction1: TBoldValidateDBStructureAction; + BoldValidateDBDataAction1: TBoldValidateDBDataAction; + BoldEvolveDBAction1: TBoldEvolveDBAction; + EvolveDB1: TMenuItem; + ValidateDBData1: TMenuItem; + ValidateDBStructure1: TMenuItem; procedure newBuildingClick(Sender: TObject); procedure DeleteCurrentObject(Sender: TObject); procedure NewPersonClick(Sender: TObject); @@ -490,10 +497,10 @@ procedure Tallform.UpdateUndo; with datamodule1.BoldSystemHandle1.System.UndoHandlerInterface do try for I := 0 to UndoList.Count-1 do - lbUndo.Items.Add(TimeToStr(UndoList[i].Created) + ':'+ UndoList[i].Name + ' ' + UndoList[i].Content); + lbUndo.Items.Add(TimeToStr(UndoList[i].Created) + ':'+ UndoList[i].Name {+ ' ' + UndoList[i].Content}); lbUndo.ItemIndex := i; for I := 0 to RedoList.Count-1 do - lbRedo.Items.Add(TimeToStr(RedoList[i].Created) + ':'+ RedoList[i].Name + ' ' + RedoList[i].Content); + lbRedo.Items.Add(TimeToStr(RedoList[i].Created) + ':'+ RedoList[i].Name {+ ' ' + RedoList[i].Content}); finally lbUndo.Items.EndUpdate; lbRedo.Items.EndUpdate; From 5058fef9b5b063b076f9d0c3c795ec579538b922 Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Mon, 24 May 2021 14:22:54 +0300 Subject: [PATCH 093/112] Updated package --- dclBoldDevEx.dpk | 1 + dclBoldDevEx.dproj | 1 + 2 files changed, 2 insertions(+) diff --git a/dclBoldDevEx.dpk b/dclBoldDevEx.dpk index 528e22e..02f052b 100644 --- a/dclBoldDevEx.dpk +++ b/dclBoldDevEx.dpk @@ -34,6 +34,7 @@ package dclBoldDevEx; requires rtl, dclBold, + cxGridRS27, dclcxGridRS27, dxBarRS27; diff --git a/dclBoldDevEx.dproj b/dclBoldDevEx.dproj index 1ccbd37..b9b6ef5 100644 --- a/dclBoldDevEx.dproj +++ b/dclBoldDevEx.dproj @@ -106,6 +106,7 @@ + From e03ba8b3082859a3adcb9e6c6bf3d59537ab3bcb Mon Sep 17 00:00:00 2001 From: Daniel Mauric Date: Mon, 24 May 2021 17:14:22 +0300 Subject: [PATCH 094/112] Added Bold help file in chm format --- Help/BfD.chm | Bin 0 -> 4197653 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 Help/BfD.chm diff --git a/Help/BfD.chm b/Help/BfD.chm new file mode 100644 index 0000000000000000000000000000000000000000..8730c705a53e6dab0459a4aa7cdcb73e734221c0 GIT binary patch literal 4197653 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

l-?_XXvzy1BS@ca15xqU>)jUM@EH{lA}`8au_7 zUR&xy$v;a(;P`(#Wc6Y(*&PJ(519zRjmm=bQr5PX^XMaSHIDy`CjZU1qrZ1^d?@b3z&^5A zpmbjI+$ld+q%+Em+G)N_0VEfgfdveE4&(S1%Bq^fF4mz|zhnd(5Q|5|vr8FK%OU zppS9Up}~WngYvutVSp0BHMh3yR@FI!1x-l+vYDo2ypCQ*zxk|8Au$>TF~T(c7B2o` z_9ud-F+hWrySBe>w%`K+PF$m$t^vzvlI_m;G2@dwQ4u8YzzArpMzBu=fct6v^BV{b z0^a3HJyO`2M_K9W>5&EWMY_C7t_hkCoyE_2Lv!m23`LOY#JDFnhZY74cZnKD?nTU4 z*5_w>IhqQ_Jgf$X|7baF8N6_c;3|hlr!TCiJRveHFxVS~?l3fK@&4KlG1U_GBl!2S zmON|Vs3jaQ2!q8EO!3GINb;)9>36&3b`f|P!r0R=LJ_lNWz|Aa{T=A%=R?^8ZXljp z`ogQ#bDRZ(8R6h_EVzB4iO_zHqTi^YDgzlHeev>v3q6E$jvGd!Ph61BSNss3>naE= zgdsiAj#d^nbJP@^bQ}mWCQ0t$1aq#BTHL2XdNJhgT!Jw{B4`@ z@IVWPn1vDmjZjKAyso76>!&+r3d3_Cc9v!pzUZ6pA{=SxN*JduqJ#TPJD=31z)LuH zoZCUzx2#j&H_Q`#+`4cmw?gD%_}S?r>>+|jUbmI#-^iY|q*0DjC-v2&+cIdNX8?P8 zXrhGxvNOMJol{@%<>pG>Ie}|7}tn9saa>2Omj38&b0+{A($n4jpex=KGEILSujF14QT$m)%L2EgVr%Cp2*%_ zW5Od~6cE;IqhA@cI!^U*jDOp#_{5-v+kG59Z`&NwfUU&3=v0WqSFn(ERuV_`S!0%=sWKu749$IP-0c!Lq3Cf8*o$;%&6|^^#}*@KAuGoe<5_ zOh=SgS?6|p;&CLs*0V0$N+_sbyr3T#OG}Mu(sr^f+qxHhAP&P-Wh0;SA=-mk zT35QzU))PAm|ch|`~LKhCJXj=0H4aZd4+p!3qiS|07c!)-uxzFxu;-BQ52DF**g!_ zUNTPPVKPv>Y&!E-WA@!c-4+iN^mNvz3i$i}fTjIJ0@1FK5zK>uWl!K7PeB7>y|TzN zC|VLzC>pN;{_w_U`fc{9*CTT}2&!Q~TqG*BF-^${PrJA(-Z4WQjn-H83L$%zwBfi{ zZh298Q9x|3W)&5<=DUdN6do=yuPiugfg(?&o(xu;W!b4uLvk93qK@27Fa#@TIZ2yS zdsKTkXv0&FIM-N*6pVQ5f0b@m`qNU=OYSQ%0^9$6k?{|IQ0#vd{1x>X)tE9z ztT@|dfuG3Ws+xai^19o@M1oU z!Q|8$P7gENk9*{n6BJ$n$hInFzqPZYp&&b;bcC)~IR8jgrqL9`Wwcpt|NKRPs1AyF zvb&ahNBYj~EszgEp-DrGsI<$AO3v*rn0A2?ld+^tyE;F*AXsc32}@J3{JEs<&jKAm z0#O4gf-P{?lA}HaJ%mFWXfi=fhqr&sIlJrS4iX%+Dj4f9<-n2Qj>;l+;nV4^T{O9x z(!AZx=F=MLGJ})v^+K{DQOd$S;KzGia!tZH7m@7N0=JLNbkq}q$oyl9`|B&(YYS^8 zf9Kbn^5$0MyfPvTew;djenx@pW7@T%$T=fK7%D~v9oT*1pd$$HSL*fIiMh_gt-?Q; z%uZY8qlt%70LQ)A=ImiPB?LzjGH2S$UbECk%Yq6z3ao)33gY470R>G2#RDOV30qTn zH2Y+EN3`(N7PaCO9Yr=mZJs`|&MsQs&M{fAGKy^%l#m!obcuPd5*&#-lPo6MO(!}3 z;bcd&a53W zr$bu6JUcud*t)z=UMZ1(S@Af*JDI)shsK2;id#I$kK+P!(LYUdT8pb>5cw<~Iy&Ay zRkjX0}*u7!O;z=TJ;w)@J)YKiz8re+ZN^zP8-EcX(KY3nK*c>quLNY=)s64}h z?;{uW6Im5^%<>2xTZe0${iHu6ATV{)ZX79*6C=3o2qvBxl?r3xCP}+jOf769G8Z0L zrwNPdB(boCQHmRC(+bgzt;x z_#Aj%R4TurxDMPW&y@2mwR6R{;iN}`Vq{D?a&e-=U2r22;J_%7%s&C=I1*(r^VktL zM@vCZCU8#jkRfP`6G=mJ#GD4wA}|=!-16Jwnp?&S+5&e$$-I@G_3f~{RsxwgAn%t; z2ftRC*HE}6Sx%fP9FX?I9@G2}g-zrF{%L<+DxX_ZSTgxLO3R}!8u_PwDL-winA26b zhDeK`kZ}?4E+V{kW68k6P;uS(%^rer>eSBUCPl4Qf+5&e z&sv-MX`cAT7FEeZmACMWk`CVdq)-eBGKAdC`l}NP+X_srfMhwFbo#(JhbWTOIJwK6 zw_Ni^i3^0mT6ya;PahlM5Q7~koU1O>hgV_#_gw9wkHiU5Eaw!?NcqdvLB9ent30ev z{w%%usbOAqk(FqFMDd}qo2(UgJaa|A-(c?mzV?Mz9E`n%g}@{gaz3)x{u7!vQSghy zA~5i+JTeaPilmgU+vd?qU-C>LhU8zW*go&iC`VOoZ{ES)=qe<=ZCu+euaa=5p~^Hk zBugM*eXYD|!bw9A6cv}oL3kOa{aWah~p!on4aLDyA>R6T6&TIH!9oa1y3`%;HA?UEpysww~$~N=Go{xF((ZU z9Eg>Bh3E@b2h0{7c`}Tu9?EqlEjjanqqCNhq*v7jtvEe2-(O2fP8gGkrsqCvHTx6c zWWyPtV@47AzlP5fU*kZ8GA;1tabNpPErY?bMNoji_v?gZcP;FbUsJnhsJIaf2r1={ zc3b`PqP66OIE8Ne7k^Yh>$39ajbc=kIJmw4d_QO+p~t^++ytoY|FRxl6~1s^UjApd z@@@gH>E(`=edtox#nU;Z%mJsvrQJ$1An@%E*rA{3A-p!sU zh<;QLRF%W`a9gLmF*+drrq0R-emR3h3c{WQo!D}8R%E`IhYi0lrsNc4%|G2_z8LRf z2wt+TS>0q_Me$g~hC}B*{BA**iGO>Zb?d2fPUjkGmxID2X?OQK?Q1M>B+d>HW-mS2 z7rTglxl7(#^4>2N7B3LduL_3GX(G&!MNSpB1Li>Uq8;UPMIVtC%Pzf?W0}))I}7Ay zaGpqu9uCd4>!o@|(6U45YdGy8S`YrlQP|8$l$%^i*yy|K1pHj~13OtoIP6 zJm9${oqp(SpCpiv1F>1n+Lh&&PfKgd`wh=fyS7jZ6^!YT_V8xI#WlDEr~>lx?x(N%rShsiTqYW%JT&vijU%1>xo?P6$5TFJ-Vw1V zAuJ{gx?2BJEx6e?2WL&`{Z9RGb^~Q9m}{VTEM`CSvwo^XEQ_5Hv-J6@GPD1zVUJe~ z%i`Pe#o~%Au344dVd^?Bsg(I+Y8K_!wteu)+lipl6L{o{9^h*r_XVxT41& z7ry@vQ|1+MyW&U67Nx`}~M=MI>-le_r`j5<>#_s1_nVi>F$@M6fb_&V)#Xo71 z)mTaOD7G>0pq=wqe=t$;{b<{$i`&i3=$KJoF(-8e4z}~zK<<`_w)IVJyt+hArMzaiO1IE#o-JADQ>#R-&lD(J; zeDj`%XO=P=$XhJNH}CIpS&0Um#_ICTH;>G&qXY*utJN>jH$QJmR)Uf`@b*^hqM5&V zqIHU*U1}ThmHXyz47GY1a1pLt1Y=Zk=ldD~7Xz7u@u9^O^qYUSg>{61KrF7YJopVK z>tus7s425F|G^g-kp?`^H(+OQ{)@1T)&{&u0!a9Vn*X{|rk~Lk6;}svLHcJ!pBnHQ z8G}f3B0m=_Zk7>cv`<2Hzy)ioTB{kHTu4%0rCYGGIcRUhGknd!1t&&2xEIx01{3NB zF1YEPGg0w{>)|<~F8Hm@vZ~U%+y9;({VViv_bordZMxKvnQe__h~kV`oLVk-kRkDSFV*7NBMPDorJ1T&;^NJH z3)~ItB*maa)*bynIljC2RIs&$f!$GTYsMIhuYP3>HJX($DaC$#^!z z5=)Ck{zey@QVSBg)5!iTSvzG}2cz3lEVsDiQcHVNL#nGPFE05x&^*AXf3XJRlBe~v zn;R{HYalQDwQp7_BSzM%%(yh;Q_0BI@2y{?acSW=o2!9D5qu*ouYKvN*sL}NDw5cY z*)fiqdZy?2lF}b|$rQZ&>8VPDmOHy)c>CJMMgm<5(H%*#e zdjCsHsDUahj7D>nm%bch9ro@NMF}dnOdO`@vgFQLkp_|m4XMAHFBdj#x3QR70)x+A|K)67TR@a(bo<41j zyU{3KzCoV;Vxuk2S(RET0>(imF=W@)x7>x)_~jf+o&!6tE?C%8JaYIe|t;fHcztFjveQ=kR!YJ55^r zij9emiUuAA`LbJaq)gJ%X+{+0i&tV+Uit7VYegfD;aji+x$@5nnMM{S`L;31_+fHm zRq_-Im(i^~Vq6i-Ro1U8!AAR{Uk`ItVPM8*MyuD9#$2_yjkT;%3r&^GRU10z4=_6V z+Jc#@j+e>qV8oNE;+duq9XP4rw7p`!oUV+XvSpza#|M%vsX6Bl_8JVpUqD$(= z|2;iAc(kq1&)vVgpIfl2e>vZ>J}%9jo0qBY)Vy?sQZ6O^vHkx6GXCKYiv6#JzXp8E zt%Vfezzv_GQW9$-g^f6wqWwFxzy3(VxUWDs(|91T=Qf1 z%+Ur{oTe4y$2AXYWxZ!09%0;9TSj!vAMLYS8_0RF5gTl6%Gj*#1}YMZ?dcR3U2Cgj z@$F&2s_#%|bnTo7(8KHPeW-)1IweQfu4!l)Y!LWm>ri*3tvg-F*P z{a6~`=fAFuc7z#_t4X@{y9Tz>J^!Dbu}3d!?>Bb%{I^bslY&>p*Zv)8t@YpNLpl+c zv@WBxb%KHMud`vKBetA%c@sfT@Bc&-xdRl)L-!BOdtA4yxn-n*%c$77$VErjZF0)~ z(n#(a*B@PXprn=isEg)G5lfM-J6k<-jDgJ4sY<%;YNBPLfm9L8j$#?M?jDp522w?A z#H7l)=XI=|4Ac*l4IUK2N@c8j6KJhsKs-$~QgsE>^_GY%Hv`R0)12JQ>+@stx)}tO zSVf-o>so@L2Hrqi^b@ z-9Qo2w&ZG{uD{(atBS#0fE(+VLtX!50O)Su2-I)N*k%1|S80@iLsL~Gb%S-Bb&P>! zBEPBGP~?*rW)R~=KsJL7o0{c%85r6UzROsXrQ@^ z^;bhx5Eo*?mo%kOLyly)1x%C5s`$D(Y>!xo# zfQNzaL{s*4(+_p6TwNQ@hSQf@n;uQx*u!9(X{}exL!0M*WOXyJJGFITH?QiMUD4n~ zDkWk!Zy%6d(SRqoLa<~mM@MINFu12VJY&1f=PPISF_49-8nT#WOnnv^&R7lh_0zOyT#!$w}ufZh0?QIHq_1d(qJx1 z71}L3Yg;QCP*7EncFVDr*+Y!Fm21;(xl&SUU?2ct_I)vBYPbB{(A>#jsmQayXS;9t zby!w618zrn_L_Oi-&Lef4TKuSGVa=H87;LpxaSaD4AX6$Q&AcP^Z$|kf40IS_fqbS z%Kz%>;#$32^RlH}UX^*|1WGq5^`^w9*#7T`jDPrpV*l&lufa_t3?|QUO_ZH0)Td!n z)Qqo?yLIohtX>9(jN!R^X6vc05?6w&*de%QbX%_nW`(|m(EJGZJJ>5290)Wi0+*Nl z%F8nJEz}|{Sg~9zV!lbMDfKaAOEwT|#s>T*Z;aH&K)FX#M86_Ge6zfQt)+pQsMAg! za(h=>J)@HV3(b->lE-D=oERo~7!e)em3qA2TpJIjyrp}-H19VLMq3&haSrTWsM7n* z?W-#7@ODS%ti}f0D88oOK7XVo#K6{(iw19B z-93A_!4itCAH02MwXFU|Bd}Vn+mDX1`WjqHd{yD?mzn_&1L3DFFueV4XXAy!BEgs^ zwm*GuUA(~srdM`&$2>PnUn8mu6^M7N49xO1+E%d`@s4k5OFfMS5b6@|I66G5l7WVz zDp9=S!spp#3=WM@t$4>RQ+7pzlTTjBve$Pzew~@+VzgAThVhQSoim*cXTwSrnd&-5_R43*a# zJ9oO~L>O&9dUfolJTKgN)@1q6K(67Q)zyo4eqSeJjDgg}P55WKDC6Ciye!>$cX}3A zS6(CC;e%u$I=}Oof5s3avZ~7)?|juL;}e7RpeQy8%p%nQ^Tn=Np;>VTe21E-svPW+ zg7b`W0Ohj9r2A#l?Y#`UpBxE4cyEeh7xS(i-R#i@d@6S@$Gvx*Zf0q2AaMs2S0H)U zcY`e4x7Ib=A(TKS>$&S^?_i)C3T@<7{ZYd4o>4PRRb)Kc?u_@c!wpo*;)^No&YuBh z7_=mrsGL$M*HzxVd@AT`AlFGtb&2KO+dj#hVW5j~d9TcakE0MoMcRF^n{|YNs=&2I z6Q+&MRkJoSV0F?+RfBo=%`Ue03>Zb-gs6RF8-5MQE^FZaW0jeA|1-?d$RIqaU!-{t zn4VSAfaA6Gn)ejVkX(#g2&J3%tSOx}#^4xgsyOf29-3{G>43^4D_NnKN_&pAwYnL& z%}^87Q&K{2YGsgJ-E*m%W2}L^!+j`ap7-3ZZEIm5?-88zPrLui$Le7a-{A1@%0%LfKwfPqFOq4&-i1SXlHV|Y^mE4UK(;~g}uLx%^hVBh1Kmq ztoFLk++CV!5QWw41eHmniTu4;q3V5w-Ll&mIIZZ1VeaN?K|fIEyrMpigV}&#&buW$?0D zr=3_Kd;g|7_J;pu+Fa80{=+@3vHxY$)pfJ?UubP9Vc_c0nSC6sYqI}l>&yxNWw%*1 z?fv(wTa4n(I%CR(wfDb>&NR|Bv~6j+`2II#EJOYijg@lS2Qo%x#=M&_B{D#+ybZs! z3;YbODa~~GBHRa-RLko3UpSKHxF6W?nKkjh?5R?k`@r5n%V+N<{K-m1xqaYdo9uS~ zsRN;4_kpWpt(E=@KdV#p5BxOA+VQ^#F}XRD0|#C-u~hyqj6zD~;k)y|n=Y14@3v#A z;@$@{Vl3Y8c4Zb{=lfu8ds|7P!L?Pq@uUwf`^e&C#4g%)OgTBYv9r00fy<26#U{h- zFlAOUP?afGu|y6YE|ERSz?Z>_Zj;_GOq$cx=%CSZ-nx~-4?b-HjABM?Bwouo_-53? z5=PXf1EP{ue7i&QN9D#Esf@H8O9DHz)h{>RkP6UTV8+{_Q=eoQJv`SI7(aB$Gvh0x z=_qByF`WV_sFVG^(W%#I$QF2bSy#}`NUK*>1Si97{X8?u=tfaB;rZwA z{vp}!M*66#CF7#QXTx%P8F3L`iTv=rM%GqFgx4ube)##o%q~WJB-AHA{Ev&ZvVreW zd5(M}qh?OH!EA(LJ<0E%PHgLM>k! zY>U{G*v&_djLGsg*cQ|(o>e$Ma-mUX4FhipD|UY5#>Yv2wJ_?HFMNLNa(LDNgN+kw zpdY)_J}b(=N2028jyL1j)4I0l25u--3$_)u2Tqm96aZOPPaCQt7}_)k^lm_J0Fp{KFp<``-Y6 z4Mdwb9Mdt5uZYO#X^=3+J@!7nsZpk%0ll?vt&i_EWlT0|p{dG#{AfhBk5LOvf%fB< zTNq}g@uh%{-2}@|^2L|kp&~jCPHpE5tx*0(5U9*$eze^u|yb{d#D4hsp89n*A*@Ceqv#iy|RIhT5K0`wf7U7zcPGR zj(Q-B!A*q_n6BbLv#fFk%9y4G{E0K|vbZ{s8lOIHKvEh`T=O(fHIOJ`W%v_!x>{Wg zL?_bFwMF7jJndcZh0)PtFL#B=&q;HStVTw>#p=Ri(QqnF)Jw{LxwVxp^{XRR60$^yvA{N4oKcu_r# zVydM-qZS(>7p_}l&6)#z)Z*%|!^}56w9X2n@}`b_iivarq38uOb2fd(S)9~vEo?=+ z3uEKt)&rZV)G@Cj^resYDtC{g2V~Th5s$@1XL4 zhm|P@)^E9DkitzZ=KeCqe#`AG2dI6NN*+uf%N|-9oklAn`Tn;Cq)t;Rf+TG5Mg z1ln} z;+fQ$u`Y$$&|kKHpBAAr&mqT*N=@f%670OXqJKG+8{%)1C3GD#Ikt+*tHpoLo6uFc zx5%1GCPbdUV79gsOI}^CtP+)}Qec5)vf=XJRy9#+n zkM^xhrq)^Y_vscM9b-B`pthI4&b;ubh$)qcTEzdp*398u6CCNLf zB?P`fjsoV$@;b+d^nOWj8DrbOX6~E2h@aPTc0Ey}v zzfa@vXmsmA4J!A--)3~^j^a()KqWW+V{(V?B-a!_YH{`3JP+O3mdWd=?*Pgm9RL7`$P8?^;F~k_*!AkL=fF|bo)7AUJB$kaKwhn!P|*uz7>gi*tp?P z7&IB6fn59obS+Hv4fKs|91ToOjV-N>t+7N9pA##Rigz<72Sj>6!}sGz>tc|zHz~x? z!bNa+mH~#lVjY+}oLFD5c z4NbM18?8ue&FtS4nL7+l=t%U2RQ%)ZzwO=3Kg?aJF%Oz_x^jB6l?VJ?ypfk!i}%fnX*qk?6kz z8%-Pe0@RpiXG}K@U+^$41X+qpg9}W-}f8nFCF!F5aDLM{x*qLRuSG z>R9R6SXf~vl~P@0m5R?@MLq|dTKksu_mk2ix;vA|HPgsF=ZYuK)QZ!DRQw|_ z@)psNGmsG?jL~*OXCgAxP|$3I?Z4i;DqVdxIq4!12A#BiJBR}(Plu!}og4p1pQ_(O z9ouJ-8V&_U^6ue9l=71Uirs&&U6CdMPXKcG*|C)VYn?W;G>h3A8a-sR=aLspL`j}M zG5+j#y;QZi!Dhzipg4l-qyDKf@cKYLf|+3Cnl0o@GiPL$O^UT{mC>X*^Uq0*PMB*hY2T-}jH>3A*eA1lDfv42^o*fC=Zlr(-{2Oan&I0T7wsJ{PWZ`JCDgy-H} zMn|#5ea8zYU)h#3`H&|c0JKVhQ&`}Px{Ji{kdszHY^%!rvDDbIz<7Q26Iyn z#X6yWF782pTdQVOrY$_n$){^(3T+P7*u-YeLE(n@w14=qbuCK6XE*Bz4WODnzzZOVaFgG(WcPAo6uK*+& zxp))3Lm*m{TeEkj>d!uc(db8N8n9%I%mU#Z;!K23B4NA9t!FjT4Cm$@NbuROMX_T} zZoNjEx^4Cugl*In=_ntBJp63XIeRUgL%i^y_Z?HW{jotS8*+OA9_q11suENzlOqkO zdPjS#n}rfXywUeiBxwaBX$G0Y${n9X!Ot5WUx{6#oS9xwWAwMRiF4Kt$JU0pe-s~) zD>z#^LeIm}?6;FW`0%Y>#x8FnL{P`!BW&kcZ?H5mw=Mp*h@IM2f! znHOE(WhOEcUj9^1-845fqQS6mXvPW|8%6FHUz8M)rU7p)vg?Ciz=nbVXBdathx6BU(BYAC!z7-@mP38xVjz)|`W}iE{Bw;79t>GFq(2{_T!Ryek*w-yMTPUGQZOc;Y>0m$~nB_6s1oQ{{S=Ac*@;O&a9_K`1s7x&yHF8=<$_|h@1 z`0$w{b#_5-J69!GR(_EsVd?M7Lhxl3q6v0<2FWL(2wm^U3)H zc+#Yo-OsbR7Y%1l$HhMkt5^^6MjuNMr0RzGzVu~66q}<6 zVjSY`2f?bF{P!KT6{HA;Bs^?0l*d;4PJdsGlJHEZ09P2U676=1ya^)nEyC9BoeA6b zE@1X716+SU@`eK*@dpEELxhB(X`FIjExDUw%Is$Mg@g!lMy9lP57r^MnYue8(=K4~ z)z%_AWyn8sNaSGX$FYXa5Tv~!I5wO6?_n&gAREzaL(=8SS^8IRrOsXl&%I)!)?{4grhe*H8Il&Mluwl7EEqCIul~4W{EN{^XSTwl-*AH*p2kkd#~gkiC81B^%C}@Zlt9KXPXA>Aq5e?d&PSB0M|z z)VeT%Yv!`K!7|D_{!=%9{I;2uk*?a|j&A;V{Cs+`GhRZCyia427ZO9r%Z01EzPGby zkh32)zbHCZH1-eVD^o{Z9VjtF+<$r_RBSPmixJ&DLL7sTr?DF>9XjCWJF{b=zo);W ziwAkpLHmr&Gbf7-2p^0VKCo*&bW)MxWbsA#$qt=ckia{0viLH}lN~A*ig%G9pO7Eg z_URtxPYew~N=J^!A?$DtLSKUL6gqU3@D7;)98aNt3GI!vIp9ffIB)T<72^L97RjDT z!Dtaz5zb-cxYB-|{~1^r4}2y#N#K75R>1?8vL&iZ|F6SvMEWZ`<2nAwb>qaPGpXAT zErS!0S20KQ|Iqg_SF9cfi~5l}+Y^LDW;Q+()Q^bXweG?0c(NIJusabc1d!uxCLEGW z1|w5{!?rq&5?p8U?%CZUPe5`cJ(r1hlOt~hK4He@fU=(3IcjcJFw)2NKw)OPNDWyK zI>|L<8W=slE`G~QxF8`6F-SSPFuSV)QoszI#HV};O$B~CQv8tu%@5D?@Yh77$5vH11w z-uU$ti~K{7S)1`ijfU~-XUY}hPz{LR0AD|CPF+kj zAfEWY{&36RJ5%@w^7izaliy4pcO}Y_V;t|zhkO+7PeKOJL9S1*1qmx^;$z=Kd`#w9 zWGtM?!9x54<`jk|OYNc+XJQgvI$IK&EMFKcF=yFqF=+C#Y_#C)R?*zS(F-|Te4iC2 zD}P%^v1&!w%9%t+E)L^eYp@$@@`~seznM!I<{cCgO1{;qkmD?oD zmdx;Fl!^P>_092HX3|qwa4>S?$OXH)B4z4Yl^6n2o+rlMH7ePG0k{}HN7-6^Wh((|th#xCY0FULy; zuxkDTjaV)oc|UZQl(S^O+f;h~JN8nS|9by7WxLKQ!Mca#7PAy{^y2bG%}g>(p^PO9 zITr>jxXM6a@SuM}r%#todynQ{LLmD7Z@dzD*U-k^XRrkH#~TusYdNlW55d}Akyk5Y zH>4B?l`+QT@g%oE7jkS1Gw)`<)pa@=lU%Wvf8?G;s$blZ_Y*WLK%#IP)Pm2h4PzFg zvkwP5>bSX~VYb7YFN8tzEK%N{cSp3g$HpJsvI}&7 z$JYpPM{0Iw2k*nCC_~0gK@S6e6VyTK7_d<2%C1nKgsqHj5*`*a-}E3A6XYEt8$hZg z(P41V_1q{<2QBPU1k^+F#SnL7L>n}mJJhP-+lQeTp%0_u>^Embb%K$a2XrMLiui+-EN7>Uh82;jAlD%803_lZA!^X|d?`*B z)MO0goEvK;YLXG}tWL&F78-0yG*f5f>X@}h?(O0=^O z(l^IF2%;8UI~aO3QtV|m=E)-lq4jpwAxI?#5*0}03!Wc`P+V&ZJ>qOliX$>K4Hmb$ z;j{0ncxfKlV<_eE{yvrpQZ?yH-U)h>8ajIuLxbF{kmHA^K$y;K{z!42vlj`ET}MkZ z8}xCA=4&?oS9br6Y^2E{M@UiFb zp^+OL`+k-DdA6gWdx)#o>`r!RQJk3>GTEEUChrh0YjNk;HTaXM$Zu-bfPG~$t<0CUcD5Unm9j_2^B!75; zB#4>2KAIN3)WAYpqxDzVFjthNI!EJRWUNS6q-x3&TZZj~jv`4=e0Jn$OA1EjX24H0 znA~0;O-~t|T=PtB;U!1MOx707Kyi;C_ao#x3t8-=2a zDRTF^Ak8w~!ALnP+z~m@&;aC5*sT@KN^!Afa$0yCASpH=0BP_HMlKeT4Il@EW(oeG zQ2xUXj*X(Mg&qm^j6m`*^2-Mr0qhh}j#TQSk>u?Wjy&wmcENl%kY_Rl$-%3`ppReQ1e| z@=&=c_HKvN1EK@I|K*H$D9#A!>;)+ft@m|AFDjZlz@M;d!b=g~NMPt04-=aq_Y>BU z96Mg}FS_Aq!310NABy5PvMO5eL7L&w6f>I{NAuxPF{hswL={#5GQ$c9MEH0vnjae2 zY<_D(aSREgJg{IS4?r#^b`S!1nleKY%1rw<^aDdndsrAjJl@bSXzKJQA$_fo3mo8% zWXmL1v<@4+xI)m2!Uhe7?G6bNjFh3VmgZ<-{BFVO(vhqPNp)CDD^k3i$(m-{0 z;14b&S-~)!hM^=Z<3pcy*qelzb1>5ION4@X^fJ7FhTIy^0Q5(H z-siK~KK^~@Y*?hgg4~%{`kQ%vVh1Y53y*WyYIumdPEe3DoVGZ$+S(!ybL^>!#2@k~ zB_Xdic?PLLMe~2y$y1MaBg;2=Z`1Zzue{9gXo7&}clfD%xa*W~SIdNx}nk zX5rjY1hO$KloY(*&4l{Bi*~d$mEkPVlOcK|i2=`n;5Z>Q$iPz&-7sZJ!6M<$3GJe( z4NiyNKzR8BZBj<|iXFNv5BzoeNRmYQry@s!cgc@d zKwjsOA73^f)|adcSS?v%nX?zyExN^2%~-UsVZmL7V){#THMBi6?+CV7`~N3KSOe|* z{|osMggS};t`Nx%isj;k+6k;qaHb9#JwclElO-C_Wo!8;0(c`2)F8jvZbRv(`WNrJ zY=hTu%+#Ku^|i2x!ehHXZx({%z_NaFbuMKe|MbFa$5=spBWPYW(^CL8a`sT@aXNgl zzl#r&(1}Pkfj?hq($8MueXw^0>;tkfQ&?>3?Gl7^mO)cL(vgE)4Rp42XRL@AW$?e% z=Hh$)#S^=12_Dv!sAL_8WnVPuMNi$D6$NG%Ak`?8MLt-$jP*0U& z1vp^8XecxgzT~C(X>A^SNeEIdHFHKw-S{lN=@;YpFSv2ziz!N%u=2%9u1+F;l$4he z?nhg!-3PlVN|Ff2keXPm77@?p(Gmn6aV3pQO11E~MeD`@+hg#ba4`X8wo_42YJp zXZO<-{!??w>|!MIf)glfHNBxIIcEXV?BI-LFUZ$JP>i9-K*}Djj^!4Vr${@H7Sp@|h1-&(j25aHzWpEVsfrY)=G*`O-_ZWw%)rSIPCrTKKvzLKN#jIQLQuro|8KBS?eib4 zNWDTJS{W@T&$s`hRcBb;Gv2cQXX6LfFa|xr=iC30CQ_tMe7^mkqN!uP{U52eK|4|e zdAomg_qX}>fAX`JvJRHA!F9gH<})Xx zxH{kdA2i?ouV;$2_s_TgLmOxGeEUC|GyH$3{hth8ztu!Hi%{(EIDM2!blX5Lu=~P$R4%s1OtgvWWTw zWu#w$Eb^Zs@^1ygLs2JM^t2Wr|Cu`2>!H7p|D!<{AV28ux9JH4^g{$m>=F_<7UOb)2l>FDW#EhD zpouiNQUTOe1DiC#()Hk5Yw&_2xYHGU5(wsnfi|(=R3bQ%0eWSFF(<&1Q(*oj@WNG4 zx)!Xg1LIr4qE1lZ87T1zG<^&1|A0FRF8Tr9SwM$fc>5(_4=;Fa8R#Jo8m$2}48Tb< zFl#HQ>kKaP#SI2Ic7yhj;IkC4I~BZ>4-(FTLzlpn<=~U+;DuYDT{9@%h5x+=RPO`X z2SL^^VB<8nlYrcm$d3stSilMH=LdC#z+y>|Spht(4od2P116x41?XUp|9vaC+XEE! z1-FNSP2u3p81QEtc=RC1bqG9_3)-9j`-;Gz3t&J6SX>2uxC=Hkf<>KRZ8u1G4L0_J z3x>e3FJRP9aEy)ti=XYxpwJSqfd{k^00YFq6lsvC2HI!K$`%tbQh==3DPEj#mQjIVKC?jSa=d_ECjcffRp8*QZ?9h3(RcpeI%48HgbuAT-@(JaK`&59WmVFL$wK~X`lN&;k*1wX6;!`6VNI$)9! zC}0Ubu?9P~fPGG2zYi!K07~oxy&}MoIB+Nt6gvb8WrI^E!HF~A%@UCNGDu$oCfxx` zo4}*3V9_&>y9XQ@0J#Q1=?O6A8|Xs|pD>abKzcT?oD-}N0DDEi94W9$9&Azt^EJR) zBd}ousAdC7ZU((vzyS|XAOL(31bXZSS4V*piD246koG88e;hPD3!XX$vR?)bD?#&W zaKRl=>mjJ$g8%(7c;_j|+6P9y1x1EIlP@6gCs<6!grzSdX7Jz=u$T{Y69QjIfLrCk zC{<8R9gNonL)L>AEWzzIpx8Fh-UGjgW6tTg)it81{UoBcO`-*2f?(XV8?MVzYv_d2tKI-F9O$71D(Qh0 zreNMi@a<;sniJ^Z3x))M9J}$~W58Vp@!vDRyyIZeDRAT>*i{Zj-2~s>2GtuuyLQm< zIjHsuyzmaZIS6)5f+9abW=3W#K6sfyT263sDcC3qj!1xf^7!wHV2UQVQU?^;06Lh1 zJ2!#b9l(QbAgwo;9|R7Df{lB@+E_3)8T3g5ZH|I5$3eFuFzr03eFYr63R>O;bMJ$+ zT_E#QFtQJfe-FO+0v3J;xfifN{IGz@s z$kz%=J_B=JffMh*T^~Tk&!E>A(Bmg)M8k^3TR9UL&kPQ7fggCl1tQ>9QE)^Cyru{a ztpV*dKt2PIxE`Fc0JE&Xf^FarC$Px}6!HV@!$8J8;7B~^l>#2l0%?zc{rR9q0T^%* zs~-@k(m3`kc6*qfw5{}mlk+%11N0) z>NIP z6VYHu9B7gPR;Gg&azO4p(5(=>Qw%DVfxH!9(oL|Z796VwGaiD(Zt&m>Fy~*e`#rd8 z0+jdxo?5U3i@(Z6;89LcjUQYs4)#fd9;%>{1}JF=T5bUIY{4*laLgGj@dQhQ!1x{D zg=nxo4y4ThS7w47CqaP%aCHgjRt64LfmyX+c?B=*NE_1slGC1RAIyY+(RP z*+Ek-aJ3j%Bn6fzgDz@dzbjYQ72D{&brC&jpUmz0^UeFqru82r!+uI>l>K7b>`;M=cY`FC)Dekm58A`8I< z>|hHA*eC!F34>20z%FUfLmlK@50b1wNe58W4OH?0vvz@dwDISnp0K6j( zK9dA16hQ|SP-q=Es0)f(fR^@Pq#GFH3pR#;9uc5!JSdq2)@Ff0$H2D*;LUSjOBvX3 z738}E=GTF3Z6NO>u<#Xl@GWRL0v;X%v%Z5SG(1>*NV0%k9N=m}@TV}CD+$)ff`nDz zTQyMI03;fLJysyI9T?+?>k2jyLHhu(X&1OX3cQ&J@*Mz^vcU4AAXgEXQUa2$gMHPY z$O_1IY6fnXy2MesgMtd;B0pxN8nLR*z5;zqMChZ1G<3Q$AaQraHl?RTT1Q(nK z-7bM$*FeHeu=F1IvjObr1aEeOx_w}LKe%fc^!g0e)BJFS!evt1y{`YaPXA)GP;ltwN<|43WDY#nzbXX3?NP^6YV45n} zq6hLBffANrz7<&S0Jdxe@410u9$*d$WDf!NM}QttU{Vs;Z~**}1u7i_MGL{M^B_kh zn06Datphz8!JCu=%<%?&fp;C2kk(o&7hqJ$Vvo#LP4ROpjr&*u^$vk2P?8cjguhp z49HOeCY6EGH^3(~;E($t??W)Z6Et}OcK3qZ{h-n(uzv(hn+8A72x0LOyBJhp1vPlU z4nB}121cy_dlW#qRp3!g@W(pP%?K1Q1uJdAqxPVr8|dN%N(6$XAs}-k=n)NSC4mkp zpkyY=4Rm`B`n&=Q--6dZfD_|j{a3K~7br(3 z4C!hyc!veFe+y_B01oX3 z!_I<1HK5H?{P$1b_(BovxJ#CUPO6}qB^XHp@9hUg3PHD2~H2~_f%VYZ)SOv;$0|oYh6~$mx8`veSfQ9!-2Nfo99Tl;^Pt<`s z8I-W!Tb6;1gdkDgty%0X>d_>gPd)YoK`p==BI3`xo3g25v|C zY@t6K%%D0y$Rz`6X@HgH;5BEk*B`8i1_#r?kU~)Z2AI|YcJ+c|W1tqD3bx;J9*|2C zG*ttQ48g+9`0suo+B;b&;RgqIuRZv2fixC8& zqXxDYv@a9-pGd>H)8U)%p#Q{vXbDRQx*qzolky>70TSp4>;!ad0TE=dLlKy69O=SF zPeA5)Lsnu$SCI4aaz!@CP7vF)37H&vhkuY8I^K9NVIdMufE1^}jEMfQAai-zEVni@ zyD5epK!_UlXKb)t_!kVkiw?f~Uq5KLnIk5zH1B*2%*Vid49v&Cd<@LTzJjwxw2_)SHuv3+US+@g(8Sl#&EN5+?DM^A z5*yNGjOlcYH~bWmUUYlQ;qYzM&L8Voe&xNnML4ZTP*x(?IT21QxVxf0aofiuFH|0+ zW|)oke)T)wJ7&1TxQPC7kLbda?$ty(IZMed%ZRBu)(kh_DYu&2=QQ&839%V1Ey}_B zj9%s}6ylDuBe>ZNX`G3U%FmQ^yso``&5(4Z86nDtU=&M;I=^V>=UWnKh%_YUu`H>+ ziT~l2D}fc$Tr@V0rG%KU_TA^+#o9s67kxvP1C>Jdv5&7kp664_wE|e*YH(Q{Grae zbJF5RK9@VI9pou(=B|-C6vF4~Bjz?;xxA7SeE3ZX&ia(|aqOFR47HlPt$qF|_xx*uC^` zD`PK|r0r;Z`n`S3tMzU@LvnKWy(>2SX6K389uxPE3S1E^VmqYfSjhCTt+#eqvnS_E ztw%^}%~R!u^T;P6!XIz&-`l)ST>iGAU6XE;HgEB(h%@=@PTdsjr9!{FMa$74a?&UdWh&)~jy zY-B+yyW`lxHxBu0)z2k=6c?#;NELUoz40zHm5;bifzcwNNp11w-w;>z|4cO=4^lcpD7br` z>)!{{LEjB>+I#%_-?CpzASH%cGlr$d?Pk!b_`D-)Qe#`?uPbfl8eLbG5{q}-_-A6D z>@F_SS5EDnvOflz*5<79{z9spWO*EVU9s@OtvvqegPJ2kSDN2`BE))bIbE)}_yI%j zzZ=ICS)cVR7%UUmVrnt6)9lx6$m*p7~@l(eRes>U}*LZmG zSzY^npULJg{H8TmS3f^TztfYGzqu}5#wUkgiq&Y$waV>wy!eRWv1-obuS+)ZXc|9_ z3*6fpTQfyJyn3Cuo65LSjzmWBmxQj&)yZK!Z^PE9njb50Qmkx!98b6Nr-HCVN7;(k zB_H{TXIYm#?Jm8kSyRL!&d0uOq&4N3&(<*!!FL$&2(=hpDz=yAQT_4Ld?LB_uJ)Y+# zQ+IT@C$8&HI3Rv+%OdFwVp~>A954|(HF-k6;NI!$qo3Pi56C%ezp=s0_HHu2Tf~l~ zCYQTL3rAy^`Jbykd-Jf^?#9Rz^O28kE*YaT)>cdRZ`2do-JhD8G5u0-+{D3;c=1B< zg-yBX0?$gN+G}3yf1IW`@cGgat^SvZqr9)VuM7p2H@Ky;Ego}!|M2v_;y!m5#&KB} z%|jbJRwz$?8f+P|NQ%7h>}&O}zTJNDIb{dZ)&&?YvK&-VW+s`iUAZ^>>YM7gX7*af z)f|co#zLPoMy^S?^hN6Fi1-5m#~X!l%>mPLrl*>GXzT3nZ1nxyn=&9%aBXS$bX z35i5JbWl2H7OE=srYUX@uPt-a+Edek*#lmd4FLhqU##0Cs(!wH)q9zAU6rk38ZSBr zymJ)!cQz7#y?N+yc=*{9;v^s} z(@*M%YNn&_x-Ir=XM8C4M~9`FcaQA2aqE|r`AK`mMb^zs3E%4_5(kTqe${R{-SXpS z-{jAy!aGj|HmUG0N)G<1d{CDmP^sMT!6_D&(SU4=w__~L8RSw}tKoRgd^fG6l+>Mz~h4&HPyNvq~VU`+eIfnxp1V z(&}{Y39dHlSwFaTGGT42ewR{DzsJ*6d<9RrB?R#P)xPriou@w;s8;dO`88RjswT+7n8{ zX^#096#8G>vX`MVXL3Dt#$&s?TCVY@N1H#dGC5Q!7dC3l7i+rrWT@rIO$HYUrexixwBnj~6rIFM0}Xe7XMfT65h%rE51g zPO#GnW%4On@AR==dfKk@=Z2M6K6p!V-7p|LDIq!dB&=SlG@d8my(fLQPd+jex)pow zx9GjvTf7oJ?DvQmU+_45+J3EUkMaP9ZWF)u(XSvWi+4rX=Q;TQ46KQ*OtqW}+4556a*M$0 zY}>B^<7;gXn>oi}V`y+I%Gc|qhRmTDlj!FIdW8+!>mFC#NC-|)*7iOi zRAks&={of?|Nf1Z&(0DR;UPL52oqE41cPmRP zKNoCV`#_ub$Sa28tPRgB$5OboE#ua@y|kTLYi}kJe!Jkf>CJCJ-eZQOaj%fvel_Ryn^_p*tN&#`R3!KKZGhpwSED62 zoV>PH`&q~9KCattnH%NoMM70CYJ5HF`^Mk3>0jSzgsRT$G>A5&13OT%CeUO0>kR*1zc6)tuFLcyD59%o+n)vHr45;}yb-{?#$z zVEd=~o9XT+bu318!Wv%^6`Qn|e>1*$*|FgG*P!p$xJDnEOcwQ?{b;$#k|THnS50IB z=RenSysn4GOt=NE6{vfC;-Is%oSi-sP0o)q3=c~?SxrytRzCHVGuXOcdd1`D%HbEE z-=NA8`dU?m=nZ?Y5lCwFp8EvBp7RB|M9bpp+c%lz&-T@l|q6C?sisdf<= zLi$VUXe9#LLxYwqQLsRxJ=~ePG@r04hFcW7Yl!Mwa8_+ zG3|R6P!M7uyT897av6JU+6oV&;<$KU!HP|vu1PwJ>|j;W81u8fdO=%@J=f*LL^)}= za`9P5@1G|#4NhzLSf{y2a#jvIUaj8yBR4>8|B^439VY%puP>{^$1Wq5ua* zwUCB8&uY!~tM~+OwQSuR%&s4E`Fc|{sUZ1i;i)W%!-L|r8-s_4*%1o}ocmVXKk8&v z{dl?2dtcX_{_>!s`q76B6?%Dstw)a!UocYq_>!|iFR^Id<}iiZe%CUhS~ispntt#s zeA=vWTR=X%xPbXK{g=L&7^nJ(ON+BRKIJoPJQr9tIUIahVD!3uVoUpR9X7>}lDB!5 z2R`^LAyg{h^fK$*`^s%zLcT01qv6sH^+&APh_^Gn1~#NEmOaGD!Nk;eGj3ziKN>E} zJo?tG7?sX-Rk0>)p6&`{$i{AE$lRwx-|Fuif}f zZhG*xm|?JQkKq}~^wxZ}3t=h7o{e!&ay@qal-_pc+vdmSLBn$X9Zz~>d8etGXiSi01?QlI`41y)ui`++H0PnCfKc%iVve zY_vE*a>;-K_oI|WSJId5HQu$HVZAMTrQ7`ud+qZvPg(=_MJW~8kG<|S@g1nU_2v`* zif5N!wr{(ZlThz`;+@h8h0cI4T@1d5`tM#B(@nU?KJi2}Bf@fh;}Kup1&ud6MP168 z-&`mT6{snA=@%(kb8o+Vd&$k<9+@v8`XjgK<0P8P9C}}^VKjS{M?`O#}`(dd=+W5@QNds=ktd;pO5>~9K8NY z?sUfovz?k=^bzgH9&Pl{cDbeFI5wt{<3(%~*Nfe?o_>fqVz6p@ST3(9r`n4!rLuDR z-Mij|78R{CNo&1y7#Q}lRv!Mc#Z~&cdV~h?S7oxYMWkI$gCx(t(}7c~gzByzJz?G@ ze=P9zv2N?*FDp7P?Yp&M1G`Pu;yvA_3x`^w4 zQlB&FuDTy{Xweg-uhy-zj`tr@G8ok7&_1p-WwcG3WzqA&+z~sim z`;`Zznqxhm=S$_EHt(&eb9va+iYd`@@q+lnVO zOfLWMrcDURJx-XmbQFl6UMOXvxQp>&-%1Xham9anRqG-)xP4>O>dlsDdtMWLy@{<_ zL0o!S+E=}lp?&UFBm2kn3}Z!)s$UPuc6qguX33_j4%Njs(oaZ9Z6#JVJYH@S#PsWJ zY^i3uK+o6d`pmeHHOhjOU9SGVrU6nX7T3SbD7CfiF0SnmuAw(b3g}w(V=BWxq4I)r z&#zGP#=|s8*)5tQbQgE@){&MwGwt_jxYIsWvX=S#P?BPFuXzMljP(O2CU476GIweU zayu3a+zE4&J#*YOpzh?_4Ss7KqQ(VM`dT%jr1X!As%D#No^j!{9N(Gh92cm!ApD~v zQ{T8Y8M;GpFe<#PPVlr%yBYf&hr>&OT${v%o%L1ZRH4JZT?5;a5mD?Wj zMX^ip@QEcPsfU9ViXK~4_jl(FyWY*cAypW9EpVMv+&g8Zl9R5bZX!qCZ69SGx?Jj^ zW95}~NM?^jvIc)4hg8`n$I`B38ODKA9*t=>v7Qo(%8t|zh};cbDD>?0Zce==tJ>5% zIZn5*Tw*i%bc;4tu4+~O+E-87PCa^}zKDK=qgH%~E3!A3|G~LuEY~JVUdH()+|u7v zpxvxcc6E26x%#0`Lcxy(uGG|6f0%B!XK>%RZ?Oy8pwVRNt_P-`k@1WY#r16$@AD7Y zl$niK9lT~^nwK0{D;86CifuUK=$beh!P}2GGV?&r6TXibf~7ww*iD*eQBB3EdLVw_1nq8Si@@u$4Ac|S3b3( z=byV(n$t&r#ilri7Ss_U-fxxa@4P#B$KQZC`!I)|ZrR2ioGZDjKio@|=q5URd(>Kx z;+n#jc%J?&zj?htdrrCax1$sHFKV=Hac1jWS}}d#?ehWo6{*i6W9ZLFO6lg@`Nj~N=kL@b{GC;b3n%WEK}&?>l$Z+-UXXKy0};{xROoom>*|}M1@W<}3{F3-UF~9g+ z!Szy3=N8sA*HnFwOR5P8KE3AUEn~L&eeQ1+M)V`r-XGoiWcbB>mKRE6pMTxbTTBzd zaIe&4>DhA%TeucfUw!uFs(nSFlZmi@ES=+)!V|^;_OZ@+&kb$QkvcnDg`Vz+=xxcm zRLW7l^uhD-D|M+A$#sPfeww-lpZ3*yZ}&o0MO-58bs$UnvWerbRWt@=MV|~PZ`dpK z=8aN;z>zC$a_J}PIj4M7`_^{~={4l@nlk-zT4TPR#wDF#R@A$qAkyg8n=Af5>@}r= zb*eZ#EWJteC9geKs!rtB7WwWupnZ0zYd=YuRUnInt|u*o=xEZ}@i}*E==Ser&z`pr z-_8+b{xQ1a$Kvbl+ln6qu9ytwvNj& zfw?y_-$`TRmw2Z~O>dVS7k_@d;S5Xbec8<^?Tub1B^&t{tJu;+x*d8vqFkYW$Es-c z$^}&mt3EKbCvVbz;BFHrr5?FM%sXkb-Xmt|!Jz|mLseaQFN*gJaO@V~mUv@oPUS z4J{}s-CE1E_2h%9)k_!nSA1dM_KRT3G>j$ zzD;uN+di7(HNBZp#B%YTWwgC77JWv z7RhM%&J{>vQ;b(#{PWeu1mjC*s!cENVy*uk|L}e2mw+(i*WI6+R4X~X83T&GN-3+3 z9a+i~*P6Sv;V!eyv1+~il`H*+V{i9;U*mrBhFR3Z^et-@47%RMu)o@2ck85UmDqXZ zed&UqzsYiUKWUI*7e4w(WGsgM<1ua4uhUt}oA2kHT0F9@{@;d_h25^x3wPvi$#(BK zckZ9vq|p_o!F`Y8OUI8Vp5Bwka{eT*3GFr|@mDr>4|-glyytj(Pn)(vTwsEIuCA-n>8r4Ot!6HZ&)Fz~(^Y$!ry^+$xIJK)f9@ZghiIMxe z8n1hN(K(g-M1Jb7gJS!}_N!*^8ISX+BwxB9sK5}zO>M_RnLhR7@{8^|tZLub zLFfJ^d5imc`7xW%>U*k^q9(My*a+_VMYALIzMZy+4{M^9t9tKCF444gbq(t2J8Y`l zXoG|GWcR#3oAJCstt$11z1o?*eBZBsdf$I9aY^z@{_uZ<9b7zxJA6OMW6AXR$MonL6fnhgd;LLaxv|AcxOLS6=u)5tT)Ot z;{E-*VU{NSH~A!6K1sH$kvzY{!zU^!te{OxqAZ^?OR4aXrYeKvb2ck`ZmqIj?U}M6c`J~whb0k^?mv{AS*-AJk*(dW$h(TtDd?&{{+~+ zX;8mnHSwK}PWaoU0V!Uoe%WwevyW-(qC|w*uHK_(mY2C-9JeoWzx(v$i&bd}pV(vv z1f$D()kgbI&@zq=(1r}tkDgu48J3hf+;#4b(lphsk67}b4n1;tp=WGUx!8FNf7jjNGW8O}c2#`S z)!mW{vQBbV*gkfCUBNo69G_6MM2`QZ?CD1)&b@0+Z!mnyWP7CYbDmy@-D&G*XLCQl z)~s2n^``!K1ABbXgXJ=>O60g}^d$@k{<^kuC0t1@mFEZ7WiqI4qkDd+KZNn6sjBI+ z17*KlUkVy#t!;EWDQJ>=eVhA3kg)!B%zOG%j>yC42Z>#~?(!7Y=05lPCuFVaO0HE|@!!5?XCg7(68hC7 z!Sws7$nmu$llSfgcU~*1KJK~HAe8Bt^uG@^ea*%D)b}Jx1oZCT-hJ!Nqa3~yYpkEk zc#e;ob%_cQoL2R&%6U9xlgH9J1voTEg_j;vEixj1M&X@D?rr0&pUjpspI{UiXE(ZRJVOYGh*Wl?sC5|;n+cH z%JIcm{W>8M{%{6DCU8-AuL=DAgrEl~L7JxKcV#X&6q@ib{@#L-(-cfB`>HQJHuSA- zw2_d=FMGF<3FwWKYGw5o+_yrFQH1;Sc4jH~$|;Y-=O^`cm*fibN0C7RnVWM$>b*dp z9;vYZgqfc9iBUKuRJiYie}hU~@IkxSb`(6PdwJIbxjG_?I?C2<4}QlJG$q}+@MOKr z2tZ0Lqx=iH-lkk`B%#x3ExY}x;NBF9{X@1%fx^q0oY!*Io>S1UlbudoJ34*C&lFGB z-BhP1pLAVL!(8teA9~S7>rto$-%t_Zk3aU6F8-sWH24IuVy;J54@G0q2k{Shsy+6jGgB?iGJlO*sNORY&Ai@RtV4@i(eJBB^qptiyZHuK<7$5CQ-I z08>LiGXMY%MFUe!J2M)C1iZ~N&d(CA1l&j*3D}8T+KngdwsEs|+uf}=uK&O4{{Rfk z0MW<*SbzcJ28oLAI+RFBOp-+LuYW_F<>d{bZgAzv2WCrF@^V&2X#j%+ z05U`XGi3nwZ)MxtvXU(R70m~4y|}Y%Yy$!$VRwM;Y6dvp0M#r~kF$COzGsQE%vjC) zmYV+ZD9w$YQ!($-+%dF?)6~|QguhFD2;3}l=P&&n8|e3x)xERQ&u9PWf4@IQK+$m> zC%OH!f;@$I%(POc&76HbBPyV>nodx==MS$|_i3URNfw8lc5>syvv9nt=m3D)(5aCN zG%?JN!@4Y>(RR2`&GR+ib5+|K^*4&W+4{w9z+Ha~f+| z(xMwBrKz{5gN-CsZC_$OI`eQX&Fiysw~?CWlkOVRkcBkdxCP-(t+;mIc^crJ2N65z z4co;t2r4Kv)W{1KuC2aLE~j_&V`b5vK`llw!)dc zYyhWr2k`y<>F@5B&5AmXCxlTgtW;BX~|$%n$TJ1^WU(6=~5o}vul zC3h}Bt4ieLb2H@Ox+vF29-Ocg34-fX5OYptnC%I9InMjqbGTO?7Fy){3 zO0~B>nnBklD6H9I-xe2$kb3 zVN3l>NY$s9k{#21kXJo0p!35l-a9^PhOQ!NBkX0?3+V5E*Yy{5lIzD)5 zRsxwh8-;8r)MZ19VqZpynwIQzCbC-L%_yhLuh0eH-N(`HKDCL~#h}xZkp`Wp8}Isf zw>ASn-H}*GaJ6BkG`o{_2DIGbAz9?_t>5)3SqV&BTv`cBvP087sl};K^GbbMfuX+B zXEdfH$aZB`F416@&tDh0<$^G+B!}oxazws$l}KiUi>LEt&2+7|iFpDw)a&&^I<|gMx6c0fn{d@i#OM+>r1F0AnvgwN-hD`7y$}S3o zyd%v@Bp*iXnBJ0pPdCnlc>4*Y8uJ*4DbppVs?dJybtlnjkb6(u>78I0w<Ymg%wC@k&c?kY!q`2& z$c96CEfK;7lm}+A!XE@j>*SapP+nh|WID<-A{x310?+!wi#HN4Z1KY+rWBq#WF7g) z`d+_YYL0uiy`PNzJGE2kr7Pn`v`|}oVOtv3T1=N7;03K7F$PAKSLBD+kZ~n-VCbe) zv(HieDp5JF32U~4{BZm);{u+^B^U?R_(|pd&r%hb5|H`3GRV%=R&l&--dZIuPnvMS zd7pa>kkFIF&1S4f81!2UbNVNRN*YbdFyEr3V<5^xaAE!!`=4KyC#~OvcwIf;)qIraVKi6;Su#Z- zhX}g(g8>Z+V4)i{;v}4g!zAt%z8oMG)SWN*g`ImbzYsQTn4^5JMDK5|jP3eOsD^;k zIrTWln=^6sZ5uLF6*=t_2<)XT?$fT>cbte{RPB!RggpAI_C)^{ z5zovR!!(bZh0k~QlaX%a7T@(@$%5<)RfrZp0V{q&WFaqaI=bUowcFE$*g4u|PpUt)B3Fm>W0l44s z^a%{`lX(k=DHHmRuX(o#mf$A07Il2?Q2z4GL4!pzp3+&=Y^<^xj*Q@xCq+5Q|6W#sMzx*>4?#%_E+F0ik#q;~R_ceBmPgP2a zfRoYjg>sV0+}OW&zn#DJ7_oHZTqD1H=@bS?-5aAh_iDk!(@U-u;);+G2`BobK#0In zg83W84ay5;nDsBV^MgC+0&6v5t*mvwkA*Q@**1r@$aMNzH|7Fo%hT(s+-d!9c_=ng zb#$LL=!X?#JK$2DJ~BR+v5>>b1301D$YE{`Ep0_U(vQ+&ik-U zOJ71z{DM~m<2fg8-p`NT_ogjlC&SB=cD`kkh*(RxKWqrd#?7rKJzI@NwZWD7aH`zq zm^aqO5n$-u|FxprbMutgJ$+@ir7GQ|BM%YknznYGf22ZhKhD`n@VH+A!o0+$<%=1$u5*(J z0i+c5v4am=phypV0?``uH~ap5P3t*H7-MX?>l76{^;Cj&ql|?4cH*o;o4!zIFWp zdq40rE(KN_-=(Z^5IzxR+hf-cbgs9+toIcfMIIB zHv2rAPy4TZx<#NjM-dpE_LN_hG=D`=6{y9CX1k^N`8T@`t`{y?4fp7r z={B-HcW=18)(rRW?~6TxVBju(j5j2;N$hCbMV@6ZC;ftn^2pGrwg$QAtJ`F5Z17Tx zGjEEyZr|F}-mm$Rr6eoPG$`k2=oj?F{XvV^ zRN5DccMk$ZCilE65dxqd)gRV6=H389fZW*;&!^5WM zupJ89$hR(fK_E|!NQM_6L$l%{+E?faIHiT@)dyaIVJ&18F#D}y_TRnj`!|l59$s^K zB@&2wYd(C|zwbd5s+7^yQ&-&k)CKFA#bld;OEj;On&Z@Ew7!%C??(PlFJXt@c`{k6bblAzKe(;4io^zU{yYxP4 z%o0IdNBn6Pj59GwLYezNS$Y#Y1+GL`F9Zx2;KI$RUE%o57bQP0prbQyCL)=Xon#vPO>052sGC>L+D zr#ye-Eph4b)auojmOSOpJtr}&$|OLgFIS@hOFX2cK^bUjN|R0;(Jrkond2r^(nx1- zGI=Do$e!EKfbE8{-P1+w7o6a;z*1-`DqX#JFO3tohOSbnn`=u_G==bfq*|b ze3D~co4z9%$tNGk^N)EQ&vL1NwG;tj@&_?-EfVy887ZQ_++D5-HPO5oLCVRm z3nT?7=t#9vgNwrf0xgb``*@`1neOmO%%!>qWcDaYV5<_b{zDA-i-sM9AF$zH(96h) zMBpO#<^JNW(9>J&l!ui;%*zOFoHo#s2uzSq4UI@2aCLBXxSNVijs16lIe;@aKU0cQ1;}gV+$E-9)}Bg;CbC{I08); zSH<(3x0c{7mIKRENNAYYA8*eL0jtMdZ{CRRRvN*rAaqG;*%Qm04|0I~Tg0!)QUoH^ z2u1%)kHGDOv6mS{@H~q}eBz1_oR>`8j6cu?00<9VJgk~sU^Uq~whal?7(+T=p5M!;+eWm|EG`^X_} zo=il84iVtTv=hU1ker=d$#VS|cjuzQqef^XC$`mw1L?oj$}jvK2h06l^&d{_H-4o0 zq`iNt?km(2R!Ng`_M>m~tAwLO}=nWTW%Mc>BU=Qm2^O%j$7m{0dIaci6@1Jfb`>91P|TofH(yx z#2{4gQkozpBO{ir6HPZ#s0^K!r$^TiVy2VVlP-8JR0o$O0x_v#bQ8;Sexq!+^kY3r zjDCYw8m#>aKloqW?3q1}ta=Nv`oUvW65J&)OF?EI1SK@I;dN5ciJLF&jk3kg#xM*3 z#vAx_uHW2ed<4dN+%c6ljF}9X$AXPC_Y-yDuO7}gsQ~3oYNck<5xTS#L-O#Y!%IxhB~Z}B`DkPDc07J(WV5YA==!qDs)5V$d= zrL3giC7Jy{WcYyFk`0;dT^=mrKkM;+j5Y@1y6ftA1TJ$UXQgH#b4Yd@V!BZ27FwWu z#hw0|ov!H;aZ)F}R}0%8VW&BsxKSs%$?Yhgf|~x$(SLc-mnc#XChB1tC{QxiWv`b# zgqBgXEy&V9nts%2RWC*$vVJbkI4wXDqfEv?v8tY;DOLs3+?5YCyNFm{ z=v55v4Ez=SrE?+)1;BmwN;oOLH@&(iNqQ!cO-_R}r=!e9$*v?qJSYSK7wa#{q-41Y znZIb)8^`)cScV!w(6a%dn2@2UkUbU4yZk~4Y>`}oAfu;55_WEwFFOnOEzRU6qf!>_ zrk&5GYV+ zQyAmnKT*pEUi-6QopeTiseW?Tk|ikH$RLt87A^>Bhn)gPe?)6#?5!A81G#-ciTd#2 zjFYAfwv_`8f5(im;Mj=W$3GS5?HdpAPbGXX}>EeB-_|Eewm1fErl zS}H^iR8DXkkWxy95-P*iylRIw;noFV!YoSi%^iEr>WyoS!@vb(61UGJ5Y~+jI6bmZ6rN-vpD~t6o2jXX>NDx>pUE2ulRJNp^ zI95Lzf_eB;tQ1rQG{7VV9tJ!pIS~GE$M?76n;zyYV?*YS*Ml2{SK!m$)oSXemAdI? zPZwvBPGCfx(Z>g&2swqS@;D@BC`G%x_P0*kmVgmmbA}yy=tvEm5H_0f4E(MCU@_)S zbPP$i-yX%}nm0ZMtd#-+2MaFMdJB+-w`M_Y%^0+dtYa0Lh>$LdT5z2()2du&54rg; zIwU2tIOKlYIt6F7$Irau;)8J#dW=#Sp7Nx-XuL~Kmee#tM$_pAD#L!u0gENxD<@NH zoIrLRktt(g3BAw|kP) zj}-DdzOrpPTrL^VaG60pJ=RA2emjdPGm)PrALBQRTcoJbz~U4sLo}MrOBoxjO*t2G zm;)XB$breIju}3t11TIPAN{TOtyhm`{5uuzOo(>mw%9s{tYu{qY&)~F!De>uAil9_ zWwbCxVu7(cMPu|}k26{$j>+B-<}(GeK12=;O#*}FQBS$%CfAkL_2KqUb=Dt=vMC$* zW0h)J5@`I=Y~bj)i;NkZeNl`obI4$M7z9n8ix9~I&x|FaHH0rig);@xXi-_sXqMBg z;0h7C!y3?Dm)ug7&tL-hi7gb^Y7h?$7WKC@OGO?H|ICDlsEfs7oX)CU8W8(Umk>&U zq?d?m10?35OFHD41TaZ;iQj?5ySNOx41c#*c+w{T*F8%1$@67^#dbn)_gqsh9_C4a zoDKwRRd^TLeuM+&1Ts_A48*wqQlcPsZ%7C2u%y!oqJnAQ7}949gJCoU5Yr)Wgm$=2 zzmZ8ZK}mh0pWNz0{vg4UZ~(@biI_PF?usaKvEH7%kd%O;S`iGe2!j373%DO3A}9K! ztDctnhZ6Sb=JfSwl&nyt(+8S{#1UHD=K=KnaJPdSAw$w6AkTu_Sr(HfjWfu%o&|WfPm87hd5cO(v?XqQsHxNd>I?k{p zig0Wp!38cZSBxNFvt8}81OdRIb{j?;p8%Wzr0etTR?sA71jSNgtked<=j2s+4L z1l9g;DmT$f^CWteEQ2nbk{F%A{`okNF|h0U*ak5%lxJ*&Nfc%ssS* zbnN3V@vNm3G>ozYx#Z27eIO$el8_C2&dDN8!>v!m)v_g?MQz65$oZd{z-5^)SlX>UZP+H zk`IH<6o?ZUm;GO*;Q z6KHa%Xm>~?WFo0rvKvE{ftQ?DMoO3oJm@8$l2QM< zi7VT07(pUftO1~m@V=l7zLAiZ)#ACadw-RdpH|5sOUlzf^7*!8D+VR-Gv1(Tg6% z*JGj9v7`M&mV za%zkr9WKwtr*?}cf|g@4FCgBb9t2BC>0y*_(mIU+PSDGie;iebNMnXX_bW1>XgutI z2zb|_@yPbvL#T&&yPeubQK0INEExAdyVl6Ztn{^}dx{pJfz94pxa2CqnaYS%gqKrY zlOA1GNqsr?Ve%CNK5qc7rX03aFkb2lfs)TFtGAC#kkw|gp;^#2)W24TDB~@;3~XrM zsi-{|nf-Mpuu<+HlQ{Nn$R~d>BRdDe1QoQ!QjCD=e@p1l0mA`N=f9(|@mLHbBf05% zM=O;CXeOM2qLk(-1Tx~`m&=gKFqp4-AnX;>j2r&sVe_>B1l54dU+o5(SP=JZ!jV=` z20qq7(iAbn?`2(H{Je?`T$fH{&|YN3aAmwTdV@5|i3_dwaq9Cmd5>%C%`E-4d?yC-W{uO0XGGUbTsyuI}r(S3^x$j^Og!<+<@l%N;HG#go@LcBR9+sw{ z$^}1O|MhI7jEPbc+gGKK$nHTc&?CZL#3uNy5uyP`t4f^M?^7zyrzLX?;+me|qVd>_ zM>wokkV&*eeRwY#!47XX9JtdqT;Up-vUck;{ebnv6KL;g*@k82Nu$e=z0yyHiDAW1FNp0E|^ivAVXYU8GfX-j-@!AuR zsuN)fk}-+kgYW1}5t|-b6S!(u;Z|0R-UvZMEcn<{#C-{zQvB_ z*qG)~#c%aq9(@ADGE)$3%ezI=b>T)bkRoWeDWM#mp&U^c^!PLOBbJ4&LU?Hu9<;>3 zGauT;5Svl1l@$lg)hwZA?(>a=+t7eLmob!4m25Tm>~D6R*_K~9&}XD>N}h-bDav#E z;SR)W6g0i1aIn3;6=>HEBEZ{LjaE+(uh~3g-7ypZpScv5D2-=D^JLrIAlF8=?(P!Cqhvp`?wkpNSm2@ z8Nx8Wd}=rv2`6p?Xb=AB|3kqjVJ~uvbVRJ;*P$Ps{r>&;zP*b!XC+H$M31w95TEPT z92W9E7a~g~(@?KNB6VN*DD-IYaz&3jtW^WkZt3I56nT$R54_WCc2!XohtUp=g zz^$9qg`ZLustgguQXVeofj;M<&cLEBDG8>)XUYL*!)hkI|A2bIj}_RDcH`xJAvRr8 z6e&Sag;v5YUKRpJN$|A)XH%Ad{5HZ&WpDoSIB&BT579LK*tG*6uFHa(>Hs?)QJ)zN z5-Yee3r-T{1bH!qIX`&VI4rPBGP@6H5mQ2yGJP;5A0000(G(aN&0B>b-EjEo3_q+e5 zjZd3M92=m+24F)oNm1c%aq||hm+o8$>wiD;-++-K02&d1D=+|VI+)D%Z!%{GLLA3o z_za&-rc;tKHvvlOzR!lLe%`w_MYZ1RUFL0T{y(%zSF|42+)dPo9_fn?P!N@?^wO)H zsv#=c(xR{Wptd#z`_L0Us#BAYPI?{9OrV+o02v~ikpqCwvcGMzr7hbiklV)j=1Xcz zd<0P72WdcUE(n2W46V_zZ_O;s+~eQL3TMY)B8Fz!t_3sRahNOZGV zaji^Z8@S!7p^^sUigxT7ll)#Q+fV!rDgAp2I;uJTqXX~v%W+v$yVo!>x+%EE z$c5>q@7;qD?YDDZhf)#mRfo+zn>}QQuNP-(_v@48d{WE+vJe%fZmBBH_6qL!h;{>w zNrSK4RX5S7Pr8U;Y!T=AM~Rqb^sGo?rK*=qiSJM$e8K3iq`ongov-Cu)4rNeWBFce zLYr*qn$D@W@-~3xot1$vb2E(fU`ISZz)(}wWG~-6^joDGRwScqtsmg2rM#)<_4Ug< z-Gl2kXxoH@z@kn{^QW#k2&=o#6D@6WM0wGur=pec1pm{WVGEZn(UAaDE$MD|&d9>a z2Gvw*<5a_^DYf)rK|0FCdjoEe9pQ=vNSB-2zBgUi(4SP{<2~+sdrk~z7CZb30~mWq<0G;ia7YZ$)>TJD79M|fT-AX8;XTZ7 zaY}j&@!yx#EJxKT5p4i;El(DT4>Fjp;QAIB1h*RA@_WAHYE{x-Ig*)($_2=2slrgu zOQ+6X?x7KoL`eZ(r~?UjJI%)uw60{U?7Y5Oc7E9S6a@s|S0qIEYjhz8+SUY!Meiwh zzo*`ckKiKwHWE=TH42;&#JEl3c* z2AHqST=)dO-E?9;V&c;ib|+zhjleZ$>+ni{ryLi|;<@54Td-U~i}P*C-i+4<{oUrc z5zWxi0#r{QW#KIQq5N$(7#(gl7)jZj(nO7YV-i37R_!2UGaY`p*_S5TDPv`SB*!sr zWS8|!+MVo@`Xzfy*T(5XaJRRXoIDge{_o4tZR4lMvyG7QfOPuub#K=Vr(XnwrPq(n zriz_gDz3Y!Zi&sn4VYR*aaJ{a2kPu598qXDw^0F)TfY!RYo(^S+b5|dwtevZ^N$+p*kp1w>dBvuv!LDb_T zovLmh>mNmHr28n`u{=;uciFoP;Z5owjiob%-*8sLTncr6hKEr%UUVa`;KNCIKAu#~ zR1V$A@tqibq%7C0-Hbe!lSpX= zJKUeQ?)c2uQc+KGzGLXD2tFKM&o(={U(#dCp-uipaFvT3!NXns(y$-k8UOkyEBKa? zD~P?+(8@*Kw99Bm{7y(NdQ;v#`DpFtBZx>}<Te1=P>CY&=J>Lw# z0iTu=1Gj@Y!NYhFoVcVG{mC%x*!T&515*P_GpnX8pOR_L%gk{AAjGExR&H<*+$skG zVe$(aZph7$21p?JsQ$3F-6{cE*K=~*TI?P`Yf>%aRS`eu?(k#2LufC#apIb+cKtp{ ze=o!wjGw%`$MLZh&K{6v=p^LYa>oq3oLO=b&@Fn=n$?rmW*MWalsEDKnD+w%fLQnD zQHg!+!km?``+=_+3H|3XuU4_~?4Mi0$@9g|`yFX*pK!y9kc)Ev;*gv8(BZQ?Xg zF;YvY_>c?S%aA2hh_-d%MOufadc}GzC?=QY78Be`?GoU1uQtf24P__;G>ZOz(OT8J zk-G*N@i}^z*Di;ENUeTg6@txz_75_k?oDJP?Q9(yTM7Gn8$RY2Ce|7Dly28MNJL4- znYwVbEgF3dlNrUUb+K}_x~=S7G#|aJ8Qmb5g~R;krs6)4QU9AFo#H1rudL5JrIVHz zlZ0T5lMF31yXcR4{@gLKxo19u&vixZ!H?FpU6mQ@YfUJQK4otY7uz}mgsz3ffM*?u zMOTc^J4pc3I5g2663yRF_*1o8&k2NADhofkd+hn1b*b3(2AF#FdM()=(*|&5Ux+ls zI03@d$~!Jp5CfZxyG_aqd>lIe%yl$yrvC#NNy{XjX&}Mg^7axz1C1xkKyzU~4VZO4cj#Cov_4EE?;W}N zMYpFmi4(^%7V7t#g;uGf~*=3(<4u_CBQ|wh&7JeS5A=5 zcL{XX%Gh|jF}s>me2K-tnf)CJabGxMCxO^abY6tesjxYTy{CJvpeHLym5_$;uaJZz zx;|gV2U(LE zz44v07KG=<=;Lcbg)eC>3oStuAC$m0*dif~GbRP=()b2)ppZ!N>AD-x%~4V7YHN;M z6zStBs8!xB5a8AfZgp9cbuK{fx&KW0I4EP)UXe_>$d5*g={sgTe_-o(cP8mI0!yjDxIb={&@ zdtI@Fxzghh=*t9=^j@xio4G4|(9LX-&#yvlgEz)8R*su}^bh@iitq8)UtG6RLkVZdaO(f>(LwC@he35l ze~+jq@c96wYT4`DM+NrVNNs6V4{G9S0U(!!QrQ3ZMgYr=xrOPE5CFwX{TK-`q%(Vf zgxd#K3!X*HAs3Bo-mG^NU_ySPD^g)s%~6LTlD6&Z@h6DwkWFDh&ykCaRc$tI(9UDM2CF?LBHnz z!0uW!uP7;~{Aw973sUvvl(ZF11LNAD|2W(pg>vXc9P*E*4iC{jspA9Z?SX*38W9_2 zb0foje_-V63n_Sla5wi(0UTrhFQ=yay)#Y5vh}zxGBGjUE*!=h>WyGMs58+jTD!1_ zA`R!lt$XE0($wr6HG44zRJAEDQAPF$a&+0Mzx5*a$d{a=GD+fBaM(OuJccm)7DMJ~ z35Upl7=i_VMd*f#;Vn3R4{3InXg$Kt$4T7gMjuHh&JQBd#)=53;br&)W;ci<+_)UV*J!Fps|u*MZ3Oe|GZi9 z_1J{du`NRJfq})ywSW?t1vN{_5MUxozV{i6*G(MA-tGIvNg}e`tN2nN4|JDvFJDP{ zAMc@o zQQ$AaO7gdtzzoRS=x^regKxfU`t?G-M$y)vX{v?h?9zY}K9J(cQEF~{;!A)DQ@{A5 zU=op|j9@0$!RvV5$ObF(F_6q-!H2mS0)OBZn)fk7$4(Y6gvFEs*+KKfvzfdk5&*PD zD`P^Y0n`iQI%q|B*_zr%0(N|EUnE#+?cjS&Mj*-ZE10!0f;ZoGybC861>~wbv$KNV z=o#T+uPW&tRRtOAR8F$?eW1YUl>I%nkZJmV|`Ba5Ot&z2!czrpn)~jq5^B1#o7uy z7iNg!qQQ(eU2Y73~IeI{FdQAxI-6=yV64DcqV_r|$;i|X?M?pd%esmfDj8F=CrJs77# zk6#n;-Ml<1RzQW&F*O{=qG(W~RzevQ{$@y1T5N);{xU=`HAB2E+%Q98FzB@%D+0UMCt2!V_zU(sN2pn5xM{rI}Sl<#()xq+e1W~LN3;vOQRVi%H zoOJy!P_e76MZr3dc-d=cjeeS*XXA1(ZsPx6U#A##9T0oIx}AH;l~e$PNdf6mR1>^- z7{SgtARC)*(b|$NG!}c>KdnIf_=y=As*nHtpU3rM5f2{ zWQ(!i&g`Q%n$BUuv$O7Oaz7XTDvY#-aeiX8d6GfcHl2Q_bXVHSEQQI}_80^Hh=#pmZj)cIkRD-1Tk@|~nL zg{?pVWmWNJ9~?G#B_HE*>hB$+9Tsx+PNCt2OMl&>xm6Zjo4V=p$M7-`3DG6dp7zrX}me;n2@`AEBVq z7ZH5nPqI;|Z?E%V9SlC8V$7o;h=H!=sja0g(O3T1iEy;96l6gh{V!TOE-}ack*$mR zKhmOgRmbz^0b)&5>t;K$rbyrag_GYvwxB z!Dc?!_VkPSl2<$YORQLVwwT)}dBDwnfORH2q&{ofhD{n8`kPSDq_VX{rY2iBj#@G+-9& z`*(eK_-yn(MP+u2v(E!q6toh~fwRP{#b!!teOPyWA>7{%Tn*y>{N_JHy-DrjbLTCN zJ&6A3rDD{MvDIXbat!ERwm-!GpLHe{Mk}iNHM-<`Zu|3TCZV!HYt^%lI4HFr(at^; zS1Px{gs>YuW_tozSepcz(<(>MOTy$qtpIJUEX3}?$WV5mDPK>wCrB3p`6d>{l-Fdj z{^F5dgDn^I6H%uf4=Jz`oz~q8k$I*&&#zqtH|!Qcck0n0wF4f@aoE?t#~}u+UH1I4 z5l>FIa;j0()Sho0rb&>jxA)kqZ~>zUsf>9epnOoer1!|nj(sH$9G~G&wR;3GO{ows z{}+pPE2!}~QO)SY;Tf511~OJjY$DdNdLUhv4-3Z&8%wAHvFvcs zayN{KWmP(wbY|9AH4<8V*umF7R$@236@N1fgS%WvytV{dtpn#z2|il zR|$`Ua0puqN)WdRD}d8#$;%wSVAE3~3xE&16#Gs}*xgu^^L~x)kIT4q2w7vHY$i)X zRQzBkNnkNSl#-fXm@`V|uS6Ev-!56Apu#vS2Xb$wj2*2!QR=b>A|`l?95tFVN+8}w z5~o6Az(_Heh!Gs_Pt*!}*frTj51&-enef_^!oib2bw}au(wuk`Z03#DePDSXQ^f^M z?|xq-heKE0oRH87I@4xTG(BVV=jUdk0~tdefRmADV-BRwwm>pZdz$B8Z4FqOhpkS}SjHCQ%23B%d-|aa3ax=$I%JEXY?C zW^perHdsVDpq!MFooVk@@&(#`*the1cqQ*jJ!v8;6(gSWe&A9fODPCWz{MeAFg$Sc zP{J*nB=h)u;TPv8_>?ROVq)4dYpGa-NQ|~sWKRmsn@JcK%@C>e2Ey==*$&UP2wK+6gR2yjMO81Zs*((#z5k%>K~lh6W79e zhe(FWAGu3UoTpoFhBt?+w+4SYQ?IAzTdJJ2Bz`qvYk1T5#svPj&~vjm5SXew4(dcg)#eIKT`+H{@MWOqZw`E z>y{oGX)l}G)a9v@paRjq`Qp8`vQWIW1a$7d$tW+;O(8LYVXYA)x5o%S)=NNM2Kyrb zg_z|)M3)7>vczzMN@E8^5v4_8BhpzcX@!|9sLm%^_;1ndTf|y=@`KZZi4?&O`1_DX zA_MzB=7_&9YSg5hSYiU-R53;g9dQXcBP>Xn~2sJs|^Z?uin3PX*^sP()AtuXafa)e*n; zc*);cHKx|eJzl$|fL1?Sl7_+bdw@c(N(*zvRgBRv0F|!cluxRuFlJuuIur}CH?G==ZWiM?j4GLmhm1B0Jt;BNGXKxDRhZb%;Y-y@5F?b`#hqpnJ7JduLNf`IC8=Y8VQgs{7}P zskV%?e^+YN6!R?T$u$uZI?A#&Gf{3 zmwn%y*2nZeb&EruDXk1phupB}qX06z^nn-=hVe+GATH_pCmGgRq~j%w$7(NuMwS4j z*AW!82c2kjhBl<@&-&qPVTX5Co8_K%_Y8$dS|6?K-?-gaZA*F-Q@cDEj((cEW2~;+ zHyyrQ-^pesz^GDZ%|uiQdgMwqxg#zCzuuJ{rXyx_j+K3Br4>Ecu0n1kW{)hF3Buxx z-U;lVI@K{6+x;s zAj&E$+$u?Xw1H}cdY_B$tEsi6JUjOAs;i>@A+H=J0=*Yk$tKeTS~UaqEVHu(rIS;w zk|hsaQbEwWEeUYX)zF03D=nkaLCG-upKOw_?*(M8Wj2Xu!gN@0!uOm2duEl4h=nv*#UaftD$#q7_1>kWH+`ZeL-jeM7jifD<%y0(Q5^`w({-j$RZ#gF7%y`(=?tC zG0A`^tPG#r*_r5q6v+T3nltc>Ufr@H#|liBf&YDklPan+8whT^yTZdZPTtBHJbAGL zD;=v)uF-4`E>d;vfA*ZizZ|5AxRXn#2>Pmpot$9C8sEWnr=<+cPfD7sZsik6%p4qdL#6jVza_dF%ieiz;Zo8V}hV5D~VkcN+{zr zWC~kGWT)?`!V^d3`mCl2QgoZL(bnlPh%B#EF3B<=_<@eoZ1Zo!MozQ$u=~-<1o0Rm z6;7O%CGh6UAw0fU$XbZP{Yas5C0~BFMBoW*5GqA)su$1R*Kz)Uit1zx3v-L@2wb+e|u>V5~B^OHPA@j|7`2nqg~2V=M%-H z&1uEq(JDwRx2mGUZM;`X)YQKeA?B}N{=+P7)J-YZxgfy+*<}op_7U`IYS3=f(L+@6 zN7*SX6n^Aj%I;+mhP%&)VhgM?Pg6gu*0=$z0&Z)^QuLb(F#R`9jHJp;D6Z8LdnQ-s zT3wnkah0!bo$9u?(?kV=4o>tW+6PE+MM0E>?m z1W;-b(t~SX`)pcp1ac`@q|pZVUj(Hz?JSM5Q=WCbO8uz4pO$D>2s}cmvWyGkIDX_! zb*pI4qv&9#;J-gwxBm~*dXU%0nMsLV6aG+%f5&a0Kys3OUq~e9y z%mM#f+rkHOtMy6Gm%nZk6}|A6bWj&hDXfn032HrUCTMO3d5%-CGQ`3CCV=%8vnz_| ztjVYz|BNiIV5~6g=mik=htV|v`)6RD+u3yh45=sTiL8B5P#46~iaL{-eFP|c%9O7! zSEjDlTtpV2_s4i1V!;0F@9B0{{R3Lo`4m000kF zRjq9jlQzxW@XXsLsn-G&&}i&JO|})Di>s%2v}B#@AZ`C={r|v75CDEn|r022oQB1CXB1pxPJzq_{H zb@#2cY7uTO`?~`)w*j^40jk=f9n^*a$%Hbwl1ckX_uonVyw`E2084OaxBp8l+2_M< zq_5awB+efuT^Y z&B0n~lOwRog1N*7{O|dZ&FO`qa-nFb{*&ON@=!4554j>*X%)IaQ6=IKA$ZTwvvWFz zp2BIRkFL_IEgIKZQxYDCS~k~&^GA9bhB{LZBiIr9jt)=|EAP+9l>di3Q*px+m8kmT zS(4R!flI{xEK>1CKS$EAL}UZ=?oT|AXURTcnb+Mu2ADh#sW{vZl9bbmMt>;r^gN< zrzQLoY-|zxj z|6;oofH`eVAYM5(a#JD)^Kfy7IHOB==qrz2NC&t+wvrp*LRT?uQU7|*HR~(xi7=sp zvZh)}-tl(l=<>_<0Aj)(b@4S!mG|zpBR%Zvb|RFtlhp@&bhlog`#?T`8?iBD&;IB* zTu?bgr>4N|jrL6MrRF8w;9OwNh>M~tKIb0bztNOcfRjAXABS8j=*_4d^n0@JrmCSJ z#NH{KpwJDfB892m7KUD-$Ij*QO)x493ppL@5aCfrtk|XAbMJWHLU;Cdh&}R7a6IDr z;64(+&f*v`wz#F@P8YSlCl@71nLkZh(Wy!=DNkiS=1lI9Z2l+S7N(`37(aS@<5#2a zyisHHmPgc%)5pL(wmnlt5k^~0*XZx&5yx_IgLe`rtI@VP#-57N*b}e3Ql1VGL!-Lc zw1M!p5i;8qh|=tZ0E|QA&WC+!IuxGa7Vr=t#SmT4>$e5%0~#uk)pFvl6%|PA4yE^r zIL@CV^^g+;!{jOS&dEq{1k!31X=|;A{famv3C(j`XM6D)Lg1msyib34?Sytpc)VCN zDiKa!!d!OI3=On$L@lC7rO{v=p6>iAbcukw(9IMcb`{a zpcGsY#u}?ACs~TSF|L9e3r^{V^aYcl&!5_gRrOdt)Pht1!Gv&&%DKA_UMc`gBdkKF z4RY2lXlxc6G|pi~&SpkIK(o^}1e}D!>o4|JUdr!h|t+_D?{ND{XZWqOD(I zNN+vlhqod_LNht)#0s>ri0=UX5d6M{erti#+Ow^t{85f%m24=T`n)1dYRi4vVx%6o z9(fk6%QY!0w`x>ofbL5L_6NbPf3UDdSm4qf1|1?fSQPFaeEF0W{VSt7f3yVUsrnEL{=Gg>32ebI}=EfOY zKa8Tr_5=Q(bB6JB8{l!t-Q;_@GH9xZ`un!=yrK=+*hLPUlB0MJrR-L{+HG_H# zuUagJ6CG>`PVtO(=rMtqinks!+wT+XBhP)9X-^fPmeKX(z6I=9UoqJa_8l#Z4{q6UoZVKUKDIUWyOq;? zTeuz}Zl&_fM{>1V__FLX={$mlf=g>$e~4>STtObKAXk+yAF?if`bzXoPUzN?d71a0 zQizg5zY(PWO}|}?`JhTgQCC^+cy+0hhSk*rfO=o*bnX0CUH`+LLsk zFL0&xo!g^gV2s6G@?H)n&fq?aATt30-( zqCY`*_}7NvW$Zf0sLNx!pln>ihiRo(j;B0&9P%(_VAb*A2N?OR{2z%N>;Aj?pOtFcHq_q5AI&HnmF%jt55j}?}XzN5FL>7mDn!`%pA zbDK4wWvysm>pRM{EGEQHj>&ePZm@_STFM@B+uI~fvqKTXNiPT{9ulq#e9aZ?h9iM*Y}BMRK))e&aDV&uAKJsp5!q_p<&{zxc7n%=tbd&8F+cBA{(Gf` za6LU7tCxXV-x!5)ac}SGiofU})_vDPjS8q)ljSMoHFbUMd+9uQuzupXaZ2E^)n*92Vqkz~!96w=TBNmJrhf$6z#&i| zKeC!{EFX#i5WhX+O@V*yi5#M9<-mSko7+c{xzBkHd_s_R5)Sd%%jGS|>01pE;JY%u zR;%uK2y*O@jl2+M>gz;tmkmUk_QGB<_GEYf)$tL&iM1P8;Y_kl)au?iXFb$+C*gE3 z$9Bk&Q{HbV0fMeh5(Nvt{#tatuac^eQj3=7Dc&X&#RMGYLawsE`snvm!W!?qk9@WE zS|x8ock|~4j^W^FRX|dv{pdqsrSE?)OXyxnq}M;b%YbRjF0nZbOAJk*0Wcw33-kp$ zWRYbFABlPwk;$s#2fnnfHfN)~a|$138K=e71BtQc|F)4To%y7vwZ&s%cE)@eX7|um zD9x?rim@0{yIpM1KZK8fwN~XjPU1RWe?%GPIX@-IIQpfV{f;WjUaxBm6cH3b%EaW}Q3= zZ6Esp6NH+1;yvtB$$4%(o)xMRSHC_lg;}tb$SOJ>qR?7LA_6Y-%OfMrnl05T zlV9)7k`I&0A$Ou#cG)g^*ujNZX}v8F5T6`(p~2PIXFW7MOV;HuWcFv6l%)1hp3Hm_ z+xOUtBC#KSVWR9)u?F}dcFVS|VUXG)QlA@FGsU2+!F5d{^71%0dSu)@NOII&0#^hA zTCvf>Zy3_cgchaWg{Z?;W=BS}mXeUen+TlV$POM@lO+yWmVr#*4fI2e(Z|Pun)n)MIIJ1fu^1B#LzrS(4 z-5Rt{`uhwC=~?exnHpW|8^79F7rRL{5Z>(_MPi}gl+=WIGrLWRUZBccE`z7$g8hlU zihbNWGd5S>Ft}{l7*3Wf9Ulat!+a)n9KtGwP_71u*wS+#gUM$aGe=vWb?z=#KjVDK z5)?rhoEvAAkI*$jV4t*>s!1?>gRMmM7$e4Rj`j+?vFFxhm~d3k?Z-Y5xkaV>f4?`3 zO6if$cJX6JKdf`^#^#6@WIdN8_B-V>Y^XxO0Ls@$dS`hTX%%2MB68ZREV6bn55&BV zE4jFr`9Y^M?WkziT9<#Cj_TUA5)pyG1$jUy3a0Vexx84;$}5raxFZO}!ToYtXj@@1 zJFrXqdM%!>k_?l119;|y1ww^X3=4iyxHhwy{V-q}@pF+luz*RHSRewtyOnO_6V7P? zEa#6FdyjXW*dU%eoO9vHfBWrsHoko%fQrdS6VrcGSKH}FSTdGJT3|i|JhwX#R zW87CYVMjfzq>_gT$m^^Xy?G|Ir7arL8Jw?UK)*w|JS6&r*ZYK2JXpmrMq;-Xq;G~A zs+doze_PGj!2lqix^-t3EFN0un46|bXsP@1SP2; z5!_dTt7e$|FfLlv3V`Ap6NX$p zP@KkCvI*wJY%*Ag&EziHD-sIs0AtvTl}Rcz@wzZqG@o=YNlWh)+=%_cQC@`zCEQ3*@69(z0yRci^?UL#!BJc2 zU^&CWk0ZO{Ci|GTJYSA(c>DMoPX{LEbjJ4O`C{9K_zT4nD^o79q~R|&H1(Aq>DyNc zOONyT#H>76;d_=7!cB7HL}~J?Uj!8U7n)yAMI)o*Qq+xHp;=@#h38pXrO8{iyXjt6 zz}wpZS&3rNDr7M)_hNhb@$r6^o7?x7>-OFcy3`-STMKgTdC7a^8|U;ZIzny*kX9L= zC7bZt5x`|kkSqS!6Ka(5?iHm2&GOq274M#eZ0Nmyu{ON#cSSw>z=4+F+60<-fg42f zxc|7gZ2tLqZ{SzwO)-3M9KPg3JY>$xW`KMrDhGtrFrP^KM@L$OjNp#@@W+RV&T%FO z6ab+m1sHg9hp+a6(sn>V?QZc{Kb7Y``h@mEayqtqLU*Xv7U!y}_NU&wK(?0-3f%!O zL`;G|c{Tb<&9;0RSx5J@ZzTsG%qN4>xiD;6o{Ld1Fe6>PB)0Csl9v=G9tjL|Gj#6#ICT#ryV(7oZ)cGSimWWU#)Ak} z?op-0;;YS3cT1#@gKEI4D zJxj&f@C@fnP5r>PoLnyUZIG{SL0HZ-fKO#=E%v0~qkZAwI}}vj9`l?9HT5Vnx(`Cf zM`eq^>~$*iFgnPSe`G~vWFL~kEBH8c8KdrvnBp{C$@miIulX)EoNX7NtH?&9gJkoK zLQq4B3nbKA7u^3@DcJHJx@fZksXCSU~qPkB~Xba8Kx~8(`g{Il^!w{lC(hD_7VHhQ@B3Q~% zszhqBdQ>%ov9UGE;~#MA;av~CFn$5WO>cDx;J01^KvS0LIsI|jN2PARqUj@!j5&{gDdgO1w zP;-W^V(5Z~a3Lu!<+R|_h(Vv$><-4zekn;c)}9OBbl$jWLAV3pG-}Gb&`OQV@h~aE zn4X*(!hH68(@2xE~thz0VJ$aLPF2jz?KnS zYY&v@qBL0IPH|;JmZ-kym7E}{%AJ#R+@rP`l4K5IfY|`fMk$gS^KBr*OZ$d-Q;%aQ zg$agS^*>F23l}%N^ilCH@Yswp()JoBhydVi7AWM`{V%9#lcO2fv`pm>v!?7XF);BE zdZQ*oHO%=94-vdcwD+2+ch_Yt`3{+~0I%|^x|u|eVvV9 z)}_yCoQnmvpk_xI4L>pB>;Z>SYNWE!sNP5CY)V2`JI5A@`?Sa^R*~4NPqE~QjfgMO zVxovj^Vw*aI&XrY68*^`WUO+J6Bsguv1~6(5w>hn-Y`c0IGrJ!v-C9Zxgj9ky&=~n zXx}3p(XTf+3Lp`tFOZ9K8gy9zo&c7PTt4`ogQ#_(_DIPeQR-Z;P%VGkE8xyP(G@tP z_A-0TKRAhp-XXTg{H}KMGR-fYvo@ve0>K?m0Lk0WBuhQZR~lpFIzFaVOSKT>9nBrB zu<3`;Vd9dqBX6K|&LhKNFwK2nVy|7l_-rO1BmrXQOTuSO-gk0xaD68isXm3)*a}OC zs2n*)iRt_bM&ig~7-|RH0yC6--cH~~zou%4?iSmAq*T`If zjIRdZVYh@mLn=xhrf)#UWyj2VLSR~;dwxm9Tkhh`E!+_epW&8sJHm1S{&T2JURFJ?Yv15m;n#GvsN)s@QVEP^81?;RGX*2xvBuHOV8~!@Eok!x_JFindWDdN z(_mFoZ>Hu?f(!(}=)K6=pMpLr^>FWb2tE{-q{`t#BQ*`84vWC9wO4Teu=QbrRIts? zI#ai+D-yH3lpN1USgi|do%<;Rp;F4to{LwF7*FK|$gr&-Gu@ODU@gW1pR+6kzU4u1 zNyzeI(G*r!QzN%7fHTJe&2LW+q}gz1mI02~M6a!ZAvA^Uk2ybNoy&djk+hium2E8$DF_v_MS3~Mqz=uI zl%}iq-84tyhjmV=p;*P~-Uf-yb#UA;0BiUf*te@$K{(44ZH!wTPmGLi5&o4kG<8P5 zL6!|9?F*VYHg47i5&`6xAxFBgpa?TBJ$vLx)5C_zydSq1+o5Y(p(xr2cAkNjL{pI1 z0uHH$oj3TVAey-X{euHremZeACe(Aoi#i8zM-X0n(KW&0J6Eg=b3sxE_4*5su$|X~ zF*WqWIIWxw1-(xGMuUpvr)^MS@QrUDOl?^}a|j+^a)pw8A86F{ z_sx><>Wuk*fQCAp7tieNt;dMNFj$jA5ddCB7*H0opu#2GNP&jw%HO_oafD@5U#>hWpr{n>K8h=0#F;DiAnfeO4ltz z@R)SsS3jq&RI;(^T&1YWZdEilfXg1y_tye|KBUPD3P44P826&l5!sIbu87gEPi3yP z$!*-|&DO6d7j_awEBb}iKxDjdV~Sm(qPDeL9LCc^UgYx*I5^po0})>Yt)78R52fFG zm~$|B|J5f32F2Kt9B}6f$>~E;(DDZLfb&~iH0giW=tZW_&+0Nu(z(bZIC@0k+@F{g zw>W8VjrdZwCSiyxQwnq2{=$j7x)y7?0ZThsV6F81MC)^PZXDbxE~xB+BHl&e-wL)k zuGcurhnFkSPwm&M-*w^1WR5iQq5S*o2~`B}{vDER_2XJj9@h;7Gx%4suW_Be`3!CM zvh}{gh%#RT3rSf2|64vmlgO};jb2T2)-w!iO*Z^V&oidfbngsC3vZ8O4~8oGRNn@} z4z=LX0#jl1TY5)S?;43t9eQY${4TCq^@!fUz-Ld{-#CxOPCX(^)A12VzZ3Jt@ov2o zn>+9(3kT>?i^8IlHI74oBS4L#!2AEf(Gp2QAE{b&f+WH8Ahl7GEgG1vf28aDqF49I zMoLTwaa0PPGjv;^kO9=a zzS|QUe$77&9kLtmIsfQ2Ghv}U5cCnP7z`a-L5&dRLT~*3+z;`<;7B_f03qc(5Y&r4 z;i;NwgbQCJt5c7(G%ClXL`{{PzSK1lJAk(s{}`^QAcoeXgG^^ylh&H^$S0=ud5lRP z72cwCf?Pk`=kcOfI#k^Mj=uuYT2sk6V8tW4EF4j%A|QA-!JqI7ip|CnrxG~k0=pV# zQ<^f)-gB8z`8G@8RvJ(cqwkjxh7chtNDpJQ!0&(Xmp&96FYki?=P|;LG}?r_(25@o z+|y9h!74v}jYc355**NA+@xVxWxc>cK=(sqw9OzStc9!yN#o+v_6LFTix&6I$Q-IG z#0ZDf&8>emn{b&%nf^(yCK=z@!JHBhc@BS}E&*l~2rR1`A@Ak_2<-Pw%m?x()+VVf z9#AV1B|ztOM`-gN;&-6H(H#=)E;M)d=yGq`#%~5m=`qet`Nn)DO&)!uqCOLYw;vqy43xu%5@h-J>nbIEygc31n#!@x{(_5?_vNC z5D)_Z002WXFf#xE4^?2SB*+2yispjx0*WMA3Vo%M)=s>;jUm!4&&{u0Y;7-Y|Nnvd z0DzGpqapwRJ2)(vvW?BmnQZX~KgVti34Ug#jZ8APK~35_XF274?`Z*qYTvsd`MQ?h zH{USiDJQ&eB)1Sf=!7qnmZqlDH|px9rc;IKy6MxQZ~3aB1)ZZ4y{cd+mh|bhmmvT( z000cp6paA@Z&JIt+3oBm5RwK1csje2K*}(lAR(X+7~bT-W`o2hRjJ)&_|pHX|No-l zLr`=2T19RY=4;6OM0J@|t}KqAI>(h&t-fLl`zT@}sTCX`SY#DeVGwO;(F+## zV{-7!d?ek>%|}E2P;C8?k{b4Q`CrGq{+;f;4gwd82m^Pa`-DR&6?TH#%4RI8oUU7q<~YVyP|>F zaw8Y&P{+cESHRsMXd6(iQMmT!I#@LLjCW1c`~*JB>sm=BYs9g?Q72z9 z>piW&00yRz!ZCWc(Bj(jmZdDMNwxhyOadt`Upfv!=%fzvS2e>rQ3-fqdv+FU6b8~w zEW*-l=lizrT{(;4ZE#0!bc!=S@{DP_pG66mV#5Ybs%|o*oU! zUsR29nm07=d+sRp9OV-^>XlJ7)m1rC<8k}CmDcwFlT2X6tS`K?4yDhi{)&eSZJP%x( zA`0}Ar;=wGh?60rog}LLu7tD&J@_x>-K#%4MYnxhj;l8|zh~N?5|sj<_N&<3dz426 zktMUSo_`XBSjPA?cp>;qh~b}Hh}{@&^9># ze6xV^F(l0gxD+3g{~jT_pb;9_R{sSJRA2yczBVUl`7EJKsD$+_9zt@Hc8})t7WD@? zo^+uSw_VA21Nw{BZ~#rA<=BFAD{Yw+G8~}V0(RiuIK{w?1v5Zm-0VjK_0y{PFsx^n zrrH4>TuDh_OSel*m~08f3OriDFFj_=F(IN?j)_d$!m7liShIl-T7^{HQ%3y^Bo_B8 zWSseL57%RexK$^9L9U%U@NwqO4A7YZ`p6W(kU6hqvX!AnMC}CyX5hl#xK@+M@^?Zt z9#XHz4D1G09p3J}Wt|PLfTQ;2>dH*ppeajM2Ifv9e>!=?NFS4}U#)NX+a@z-q}7aM zft=)br0Vn@cC>@jmv7G#0?BPcZ*x# z5Dr`z0p@zm?WT*U?c|8o02xk)taSP-)ZQHwFQWqp8<0PZ%@S!=E?Nt;FS6K=Yod+# zoejph@l+e-Ad;y!v3OdS4>CbIi80jFM)HMWJ-Fnot->w6_~@gluIR{TMP9!1h18+O zIVu37kU;UYUlI7;PehCPMcq--{fp2A`np@nQ#q0c1_X;M0z^+hT;;-sBW=m>s@h7n z4J-V2EiSV4yqJMyC65+zP0Xfaja6E2&s_hf$#7lS@txj=6N?q0jmD_np%OxX8UvX% zj!?J*8VJv=&;$Yu=T@euq*6w>uD~YMn@VI4Cp{AT1c?mkdlSM7ZpLr~oCyvq#0Auj z5I`1PlQW>y_6N3gqKJ^deXUaYr!VH)$D51&@|3F|TO4+% zQjLa9Z%5d0sf=VBYGHAzr6jRo(jofI5_TpQ4m9$_0O7w~a6nFhM_~zV_4b}-+F_{@ z(Us8!zfsETXOoP2np)pUt)j5RF-WkkhZ;)XN)F9f4)ajaSfvZ8s2TF7Zqt@h&6_uM zR=RmEs}`&vRgL+YYwv~bsLmNT_fZ)f%#A2dsy}ZeXhM&RANJ{0(Z?vX*$q4!68t0> z*}9%|+rZ?=u+Fn1i>S)lTm7=ctkzyj;U^~))M{a=B{-(VOdzVVjm;i|fSL|n@!zAtP53!asGea|+L@P!B80S@--&@Nbn#PLer2KNgCbGwz0Q9G|V%dZyBE{$7BpF&Ow{_B9(rAe|XtFV3+ z=NDAj=x0m{`B7(Sw=$KDjLSxDOkN8)r=l}ZGoxu6O$_!X){yPZ5cwbDSE*V*rf7bv zJp}XM$awLBx8PQ&j_T~YAWovUfELY+WqzaRX5*56zzPD_R=X>)@C21EYif8&gAxXe z2r^jkQfy)(niJfCFYs%YFH5ATBXuNzmKcB#>L@ItX`{eCu@f*CoTxo#rRbH|g=adX z2Ukf%brDCjA)#c((wwF2_N?~qpBDQA3QO1K67xiv(&Tv#K(kGaG!Is|RYRNoFVYQotH+ zV3+@~9+n&QIhGE3}H5Ep3-iA5p*O*dI5 z3@s3oU;DT?H~eOh1j-{FF5so;W8BzIs0<2`$ti5<+h>|4h%aITau(rYEq;NpB8=+;{0K)*qkM)$=BGMBd5del#y}=wpmWy zC8mtOM@NZy&9;b>AC-B2dB;7MJm_{yM{_&CFrYVRPkE);KK1$n^M$?Z3FUL&wv2aO zpVCXcR_M$hZH$-2pk3ytcg0lLD!VmqELY(Y>jaW|gGrTlqy3(sNLC(0_6SQO=l_CC z^kO=Qh%kLO0^QU5XLm)U=w5BYS=(7yk6M3bkGvYp0);*`!VTW(=zkmPPJUF<2f7qDw}T`90QZE90o-Rz0<-6fgvS(5Q|h*N zGzJqJ*@DWd-@q)+>(~rB!z#zhjo)a?N*e*`t!l$yk)N6l0I+v7SnU%*$Xq!+Q(@L5 zK(YfTt_;nDws-ey$yu?Cp{16Jb*_PkA=F*)AbkQvRlC8WxF}&FEylwfJ4@B3Tm_~6;0_RBGb1%vQExjHB_Ji-CHD} z#+z-VZXGVI7HH^LSk$U?;htYHetmz5HA}Kl6TUSe(sRWS-i%ZXSGOKkxcFzEMWzS* zZu7Lk&!e>4uVv>CZWbg^qcOe>$J<&4n1Gru$DUBwk@lc!cTdvZy1w@1iqgzz1EA5@ zX7%d?1Bi25TcBe=(gxbIU7qs|B?<>!8dN&2FDBSZ04VPs6>rMG781O5iC1-^D$97x z1(YNVs;`_NhBIKbSv#cWKlbfihZOZoCvZPI;MlkiB^=}UyAj{q{d9jf?wZ%1PB&~N zX9&8^#02kf2NG=Z37fg!k`opyxYu~C$xlT0@c!JemY>h`-1$Vk(s)2HEL!jJ=|pl| z1BxvYNG~IQ!#9{#nr37NjhKdm#hX;G@V zE!L+xmC(kgT32#n@d8OH>Mx-8vO}Odd%=KFL;yKsC-7bQzq=tTGUcc{30nF3NPx6M zCKUgA2DsN@EWt|OuC=G!xu9w&M@ykhDGxnxp@-xojy_k;6gqQ`(6$Xv)Da!_ZK^Pe~WBs~omCIfX5iCaEm? z_zfVr8TMH7}-JOk7?p1aqMLGXZOX(`jRR# z#_HjvpGmEWTClgAW*j6y(O)3XuIPgOm0r~&&)5=Jb7`GI^xO!GRfg_d%5#)@x-d@* z8%1y83#urQeas4LCr#w=xdTtmAf6!<$up>Cm&xX&2Guno5@q(N5Nz z(Vd&gUG^2yPtEJ!xkz>XtnW|IiXyxMS9IN~Hr=MCB6bRW0!2n_jNYb)NTVLu&4nIOMXNQiLi^?@iN5m z{OB+g7bB}RHK-em<1MEENI!2W3fg{tr68#9mnjPJ{Y|_FJ;CR)ivmN2Tj|L6E!3L_ zLaAtqjpKUIGbDcQTvG4n84Z@{vTG6XWI2JVuNRQev~ERuiO@T!`MCDiclV~68hl_n zVGDGxCfHHE42P~3+Xx8A8Lq}Vjvj`@Y`ar6-(_pa=Xkh?wuGyX<^W!6f@$nv-plA6 zTjCel6euAXPp;ozN_jL!HAwkq`q?P9WRoeCw5HS1;ZRdb9QVZYbK&7F&?=>3s+h&*=e3hv`K;#S_lZnA%9fD_|*)zh_LhFLnd!||Zdt%ZvXe0jOOKG)#P+}+ z-AVz0ThT%>QZ`f#a<;~iXgM)z(KvpWmOoWK{?8H&N!KCrD0>3FPbG^s8dl5WO>K~L z@q3s#{3PNxXy48GAJ4(|y;=O-yBO#YG?N~QA0is@VIbq299eRFiA~VN3=V|z-BDCJ z3>)NLe9hHz$vcD@!T;f4`M^#_Cx6f_HY`e+9Sc+ufP8#YZeHH-O+X&KK5;N1hPtE?`(F?uQ6$}R&(Y3QiO&oDR2O=Wu&%dk zx5=(as#I)!n54bO%cH;lY#-Z))(VY1SjkYh>%fRr)t(9f>p`g>BC4PDtO=&G!B-8d{bhj9YDthblFK0X>*CaFr#;&MF6YQ4952azDcea*#%2g-c@ zh_^}HNHd*>vN_t9nl)HMwnXzky(~`F^slb=mY=-eg7y5p*&S_(2u8+E$XHBTcS?4n zV%ce-sy+;1OX~|6ib?d_Nz+LS)AhDt8W2=Fge)dtyFRgq;Yrr%G8U5-e+q;@P$D}( zSl}?FaDrx5o)aU?9C&a{r%6-oETs-$@vWoyBNeY7DflB1IG+l8II@F#i&ig5N5p?^|qAfyHG zDR#uBSc}FXn#7j=Vq)nc? zEJBubk|Fe>)q~ouqoV`$`mCXNha~Wv`r8JH`h3IcQPQLi43lHVd}4b*YKaWt38>GH zvPo|58+}g?B2rjtJ9k_^HKLQ*s|LNw9Atj7h#SDQV+;M8yF603vNU&XelUgHCRJM4{VQFiP9billjX}d zI%xB=c&*HhV4pWCgTN}jxW=tN%l1E=IbZEN!7qV#JFDNdQyPIR`f6_pWedsr6@T2v z<9N%sH`PyQMnQWhfbcOvTq^fCJ(GHt`5Sk7fuRg3p;G`4RR0DRyLamh1M-AuK+IP>>&FJpDfKSM5rDLWq#K4%h%VLiWNyLjD~t)8!6@Govp?T3Us2}Ae0e*S*~ zB*vF=)u}Q!UgfBWpOR8AM!-pbGz3hZ1^Qp0KMf2tSoU3d)`|g}$!m6D^_6SAN>n)W z9-|uKz54}q{z+%n(a`B^q|$DdiDx^bW-tbSQI5_>kaR&-zRz`^AvkL9h1gG_1b;4V zLH)m|7QLWz)tygYBt#c zzg=pPae2n9Qjly+w8eAKS8Ip^{MIzcW>6;?DaPtDr;mrX9f}>7$uMmj%PQ)HL3^7L zM1rJyV-|4k%H-5MhB%HhBQ_}ff8r7i#i zYxY1PKcw$|P;8 z(mzj&TZNo_OT5Dwl{DDJPo5jEG=|+;mk9LB+KE+v=KH{GZ`Sz~7yt4^*D?HefPfq9 z`#SZF>kT#j?ZlG#x|r%W#$m2!&ANgMUeKuW&u9*k{eK_grMQ{+eOA03hHj;Vs;;3Z zbBV4tqh>$);_yniNTkCH6IoJGdx>;p4b{lnj-E3R_-C#Nwaul1Oy{aqYj4b# zE*0n*h~~S(M))(F>zOj1j@HQ?*NB=r>>xLebX4c#_yeSN#@kwHy&n=gW58c*9S9zv zO-xb&7*H16-cvMMf}=REGYu#T9(dlWu!pZO0paiuQxfp4&Ry*`%^&?~NQ7s&DZLYD zvtT(2nA9|xYiYMqMsT@rJX?xf62C^z_q5-i#IR#B{6@e#OvQ+Yl`rQ#{I={cWcR|N z$|g>BL5+P@uG`7FcO>TZ?QDV8%m4!}WxKWH5Z6@(qJ;Ys-uy$0VH z>nwqb%Z*>jmb+lVo4M(}>j;0x1;y8XBdn1E`Ob)gdQl_}URZ#NNB}QSWct(f8re$3 z7|>1#Z|)+)%LvFi`m^_;0>!)Yc*kWsLaYoZJ@XqN>}lg$5KXnHaaq&zCYqoPVPLm6 z?hlsy3=s_(itM5@i7%2oKp(WQ$yl&vjp^?0Oiggbgeb@gqjmMAp$MsjCNtryi~%Kl z1qrzILpMfK<1)qG8h0ue;2q89`3vJ1f!ZyN>AUq^FaUP^@{SELTcz)U*s6?ghrAg_ zE+Jkb;DT3MkkTw?NPNL#y<(PB0|^AsXaa|@tWxBg6yA{wU0Da4Cl0pyQg%K~OT+E1&IH5jZJjhRf#Swrt;3C^N2@h%kv7V;9!>rsjpjTNl4 zrd-OW#M!i6SJaPxXD*k^eUf&7n3Ny`&^4I|(3bBTMjT2BdsE?pWU1s6sZyS~RU zXF0C#dqWunkN^s!FKfb^duKDKLNo;VMEyh1@%?#poJLxd{JzdwS^6YlxKxP6v6CFp}$EH83#xt4AzSYj7E)dBsj+xE6>Ajyp}leX9GiQB0qAF>7{ z8z2A&z<|VHF0otf-PwhFx^)ON*}UYUo~R^(!moeOj&+7|*@c$Dfet$$(tKd{TbzD$&mIT>F<0{C_y zO2n8V)wfDeXnHq*18OozVo5o`D+~Lt}SeHI^r2Esq#| zF0B)n8NbrA3vKkKq59CIJS?81QtX}<%F#t>Horhmwo*Lh6VTclAA)*Zug^n-AlYmn zESx~!6uHnyw{lG;Wr7;Yve7@5N(<2GyI~+wxIm%Vtx@(RpVgN@TTsO7t>@0c?ulSe z8LdtbJnq6^<}zlU*Sfm*8)Q`~HG;3NxJI`^NKmnB4ud5lJUZDW0~0!8_Sg8PBUOph z$Xr**lo=!Omvq`r%~!X`PeXf^?Z!Qwb^As$)`gAul^!~*_n?v6A#nLL#Fv9X6L2#k zvY+n;FdDzwKZTyDhgcraZjv#zR^Q-^TE{A1tHn-Ytd`%Nm2^P2F1o3gc1f^&Y7LAyGNtFYhT+l?n0KLO7j8!>2gYV_D8;TR4XN7`yBJ5 zXi_*^jAX7HlFnG+?fM&3OSBO(@xm20&l(AT{w*ty#t?-sp%G6E>RVCnZ>B%AOk77 zxHlG|xv3ify<=A|0@>D)kaf+8@V;`&=AZgX#6JY&ohc5cyT7Zk(1^l{L2c$4si@7+ ze#J1|#rr{gl17Noo{IJ!AJhmif(#mWwK+y_dCJr|RQjdqByWtoE+avDyCCtUkhS|E zVYtbbF20J_?f^nSy}zfft3<-Y=zH3I%d(r6pqFI35!OoG&Jm5_E|krvw%hSF=H27Z zZ$Lkcv@nSvTU6jU%8Fac9r^0TfnzM;EF65_7kJZoF0e#JJtm@GH_4WK1K~@u`T^z^ zKLuR}Q>o6lEJHq(xmo@GH2^KEEdzEw=(7JaAlXgh&${uz=z*7F1`b?SF2vk1cPMUV zwjx)1ZC4@bi-#8tBf-Dg{sk^|xe1SXK~ogMM!JExRhWCb+et?Dn+Q19ya_B8r= z_pq0Cyh#B0oX#t2JAbEc+(+^bS4CApt8|);d9{9P>y6R=1jDor=CAixbHedibUPD0 z@+ZYcy2BTH^GM0ffQp|*@=wGWAsTlKy?@7kw;{Z@)y61%bLV>36_4WOZ3Hy}&XSfL zh_l4EX|ka64Rd1~f_oojUtn*7HNy6GFTR1G{5QUGZZT@T=Ace-=sFs|^zHVCg8YO^ zTy_XByJ>y`O9C9V0)M~-a>=LiA$rMKQ77N-Jy?3F&)+!GUC58wsk6zjY?4*L-v@x>aF~7_vFFN<>ZtWhs!oOSJ?~ z*dOaf%k)8Yh?akU#~3o*bsZ)^!t#yuA0HQv|uAxxmmfx%4y!SK3gquZ|$ykKM za)D5quyp4v_o(}P{le8}@=LPrRKLH(Rhr~;wbUlKeerGTZxryhvmsWp40k_%HVgtu z*)*Zc4dO}&6y+CMzn3XlRwcdv^})oIC0iOCo)@kC1YkHdh^5vqy*b&Uoj{{~`z3;B zJ#phF2B~^4w4E#8AdlF0!m7A!{i)}#q&b0teD|B^yfvS%5X4c$0d>A~ZRrw~T4&KE z&bAMp@%j`prOUN;f2@c|dfx9>7h2U$uFLyu(`krls$8TB2y9k@5?|Fub2lo8}fmQFaVvqudvH$o`1DUlJqRqE<3ek z2iQRToi^ZYvZ2a?@J==si2BSto$mAN5L=kO^6igIuCGs=`6~k1NK?rk zA%>1!n^MD99UWal;0tunmvdaCi0SWV+wzPI(A*@CHVT{@cv$DC>PtySD;`TE!Wg%w z^b*{j;zZjPdNAz*3hJae0T%9-a}UD6wUEx08_-8E$25d}0vw}1-<^MC83-`8qnqixCv8%CMifdg1wfx5#*v8bgFxeu8i|KXVV$E!_A zf{B2OUXiO&D@z3fO%P_*tG_}|;wK93ikJ1Z#h|@XTN$~oqlN!NZ#VG!gYnjJ$pvp6 zm9qjSqNAj%8!*~Yor6j>S(9aP2r6HDPlb-=zDU-#R9NK5~zS^Zv&4~G%;J1dQ)k#dd za=57)>-%qKV5|Ia)?lB~>EZ6YgF2)Y3I3|Nu(71iWIi#uV-=IuKUc`yp=vPkm(rwu zj$YcwcD4;WHr==*b%TJJPMXGomZIa;a`<~adgTB8W(;8o)Xvr_F*Hk;pPcd^+{9Z- zPZ6{LX9O17S)agfV9YpiTK$-2+>$;+pu%{5{?auEesP9>KXAzt2U2vp`xG}^hq#uM z5rL0>EklBA-&%ZrxG7#5DfFF0+cWtD?n=0TRd>w;Ijh1#Z{=+!n_kq-D~Ybo!qb2g zZ!xaoAs|VgTw*|Mp?-~`-M}?a*|IkH{A$8&;Aw^*PMEc`;i*j5|G>Y)u9V@=^U6;r>BimaLqoE{36AQjwQq0>&C`O?hIsZ`o~3A-{`3P zrS-1Wp?k2fgkc^EZt?ViPRs+NB#i-{aw8d9R|BW(G9KGRPgwnNO+p!jix6kvE>v*Q zs06w6z2XPe?p%vrzX$Xr_&!#}fJU>~Oy&-ot%F8zw~sr(2q`jRlX%a)h!=8Ois7aO z#~R3rxA2Wej2T0UaN!|?z8I-qN+Di*AZD)W6W|q>N|cYUCUO9l`Vhd;=K@dE?6+*z zca`aVk?xQ*2wSZn0#D+OM0Nq|bZ%G!cN3Pt$1^a=P$7a^XW|hBZn;F(Y|r;zWYbp> zxFvYj>vgaLQ0f=Vrk(2rb4cnJ=x`;--IoYWvb(@@Mg1d`*mYPtUwsG$=lG206&2nFl-q) zSjeW8b?QvkdNQnsatWBLvJ%+Cf$TP7D%A!$GIR&^v%9Z?eG3I3Ikn2dh6X3dE&x21n5YTu<`0g#Pz3Sw{GyBg>-bwl*#kJ4BQ&&J^~8{qV56GSQSG`Vf(*4$}G0CU9IW z{e2`Q6^P++Zam3ghRH)4eBru(-bB&V}IP^wS#Ef3>6A0$QG2XwQcgKD4iwjy*^W&JyWF zYK#J4xjPatr+AVFt5m%#DQ*;qZ>v0>pn+lnyge*fFZiFb(-NjG?ao4^zCO}$pq zay3PtFlX^0y8qBmPQgW4Hcm-RV&b7xs1*(Zuq;8$oW1JQuXY};;y+!(m1}7 zcL%0Y3sSg<5;>u=Ph-h3gl&>VMju}Z`PBvMKi{8CqN`yd1dLJN=5vFZOp{BckY{{j zqs9i{Iug;*@-w*xwH>t#hP#ngJZ*9$g(i@~P(q+wPzLad?iik8g8yJWj7k_8ZJcoD zP0Rb_$pDbQa-WJEf1q{#wy$dxU?y!@wscWJTFl2|51C*z{tusbW!DpPo zR(pe|caRZw`1sURukRBDyTVD)#oSYC!P5VzOyu;Yz1ppcs36d2T3>CbIM?Bl(l^8e zE)6IwZsCQ24wq^J;Bf=}O)A^l0Wx5zmrA+qGDUajWU?}-%};ObI6qu zqPbDzOB)$C{FM(oo@hSU?{Z)sJh1wNa@1~l zx8ibW@LJh;;>Wv-e28jtHu>(183$XGoW}C!th)*RDwO*Ow6@iyLcDwuse!EHMneN# zZeU1q_#&g(rPv4a8^R7mjAo>{jPVd$6SiF|vI}_d)}gNUcT0p0gm0i~KExc-FfUpW zKhl}*0B5!U{t~4-3-=DUKo)+sP1FV5KY^x<7(Z#e%4Y?FL?XGfr z->FPJBbTDljfA1S!^b~kWnflOJtoRw-R$@gZ+38)?*(3-Ijv1ktB|MBo-#|D5FWIZBg)ND3_h8C=`T3q6GRw~=%2W*p7kK%H4!!KrZ&67FedUS(|XOIOq$8&V!I zA2VW03Zh3b=_R^d@YT?7__ztXeSO8XK|pE~-}Doiv~JJj=RY`SNcGnb6TYR!FBq|# zRRQMP=xu)AJ~jrf$BqHby-Olb@YWr}1=kbjMM9<;@50vOj9liW3wY*vTx-qm=jOa#RXWUwNVCXR<+F)IHEcWWWppL^7*oJp|2z0q&lX&JtMG+D zby5;z^g0TVvO4>3pc*&i$+?)f(kPtHWQCnaQzSA31mwJn)#~h;DmkbWfTF2ZGh|;h zSZAsM?i5&M=%4~_pLJLoNuk*GE$cb6Tj>g=6or0vU|=zy;rYpI6|SQ@=6^aRCG`XD zTy^%)pr4Ibex!)0v*M|8OM(Oq@0dU8!AdsBJfLwdY*X@z_yN49Ite)-BQ9D~@r?P^ zZ3f$oc>s3#4}bbi5Hi?3WJ1PAAa~)Pj!I};$NHlJ&_JgbCEN5kPcA)}Hyh!$zo^u( z|8I`N8)O85Vpdz_+-2w?5h4oWsi_6i|B9^CHLIif&r4o%lUpG)RqdsJf*FN-rn3l{ z-DJmkfRgja5IsByt$m^)TM3io+B}{hhDu8pWo=4k=YWszm)RV)Ln?vky+6gFzwIz% z@5O^+>Uy3)a}^K|wCy)5Ya_`#(pWP1FE7lfO_kD z78s7Xoc`m%-?R)AScfx&P&Yxg^$ql4R0GthDNPh*6H8tNx7*;5IP1az(@p?rPfu+a zQ{qFQe;Gx;1}_dP6(mcrN zyHPZcm&Rcc!UEZOHxM^ap`#_zMID2NFCOx(?uG!GA{#yo=iPoKanN#*E!w;{5~PTv zQ=UL)ON+ErP}d89oR1Qi+SNRSRz7n)C5~Y|PP~mykOczjI6~eFkOMO^lKF&v_3{ub zIyxGLy%-^IJeYG4O8ET#rr$9Z%_2n?$l6T~T?%VC%yb5+5M}n@OK!z87&DyR>;%ot za9Kf35?AEMQ~MB^I-h~fKDploSvCK%WMP8r^o9YZcMDWd96&8bW!!e6=7i#pPV8)7 zeohoDhJkUUhNQO#oOk6-As6LPp`SzcmGea3OQ!#li+}7jyy`HMj8{Vlq?{Z|S)CzI z#`cYB*eriXcz($-xKlP1Us9EdtmM_QvyMxRbT8EX89YuPj%Jny%_4~e8gMnlu$u7g z-xqS?91Ri5i8BZo(?Gk){jSZ8`dAV`z&sawG-Nsp&4>g|!ih?9=xp@MqhYoRxhX z2bOGZqt_N3MB8|l+`rHdZhyxRIAY|RNkQCs2_k!FO4h6k_2~XbrHeO{NXLMj0VeK* zWRR*>%-pZ!K2Es5tMPPP=^!2zzBy38uUE-+UOk>0xhw;%?coG=Kt7wlB^+$ceXXF+ zq_%UDw6xO-P_&mkksS*Xbo^X3m6HX7+K^ioWK@2&%R0)W2*M5vCY833E&|XzUM8{b zrbrE9%WNL#iSHCTQVz%vAMW*R-;+rafRq7qs+$K^)d@v@G@VN70wIJnpM!5FJ-oM+ zQ_3y$2acZ1#U8k;eCdnnyl~b0)|t2dyTi>lU7XsT!*^;K!2R8K+%Bjd}^$)53K!TJfwJs95vqh>_{@sipYM4d{ z>rC4*HTeJ+uZMch<0!GFjiez{9NGD5UcMd_Itjm`%77ASWrZPblQci9h3AYe9# zokLxK32{b(NI-dc{l+ecQ&wKK_nKlPk-4&XalHP!xaB4n!!?Sge+eu~+7nGa?!!PE z?Iyq?3M$GLUj-b+ncq2e<{wOBxJ!0p9HLyC;&`qvsfrp$)D#&e30K62?F?k{Zs^UJ z;Alkrk@V)?C{n|*QGcRZMq5}&$vam8p!>g~6q(SmW8}s$`V3(f14lRGMcgk;v9H-~ zMuVg;L7 zLRTM~*6hE(J5;3f8eEx|T=*;^ec2FQ`G*Jaj&e)4$x5J&rPd`imlTKWLV4Vwp<^h9 zW6M741DQYyErm9-1#!&Kg+zdBt7qS!K^^rbTPbceq(lNOv&*WRJav`_4p41E6Qe1v zShZNxhhej=8~m7b=3~yzsXRkSSsm!l(lxgX3$&O`ZPC@p0D=HJg%>#7S9|>ABjf6Y z9j46?7w+rv)q(PE8-bnJES=#;PS7{!$gy)I<6_h`IvRq9Lfmj|cxp?Hs=$DyAnL2? zaXDQ7s^rE-9;pC1k8I!wMFttm(WbE;p|j6x981RJZmt41z0rmWO(Q9$ztV7c%9Fs2 z9hOt0d`nOy0eNDGdyaK+)IYWLB#q+v&Msh6=`{G^Ze~77+Wk-axamRG`YiRw>52CQ zWb>50im`(H#5~VD#;JzlND3}#GbTOD@rqLRWtD%%KR+n}dmr~9#z?IN`i_}+orO`m zW$Ig$ja%;bm%Mdo7ipBmPYrLKBC&7uII*RRxcpx8f*QWfiuFVYijfYiJoE;D$208s_fN0*V)acbhRa3^Y?3AxAYa zSf!zbJQf}Z(HV7j^``m2xpfAHf=$KZ0uBypuf9Pdz~e<4OGRt07>X7^aKa^>ZqFm76ruJ~C$*PGT?t%rC;9l2b02q?ktaF+ za=F|)$;pqL%ej+wf8<=pon_@o&c57SUY+Dy!ewZn@)hd#LrW!5!og60=O(p1bTCgrm&beX}sP(QF@im7Q`TS1V4;9&N*DT z2}OzmYq8Ei7#(*UEobCZnjC;7`=DJDDi~L7sUC$q$S}ViIh;3+Ir26JHm^i3Wz`y{ zh$-w%L13i%2{2$?N}OQy72!mJG@rGrQGQ=ijBuBt zcRv9Fe=M|k^-h%V3n~F%g1Y2m0Ky0C?<5H#qo60hcQ06 zh|3iYi?QFhfTtZwK)*B>q()t(HAat3(r5UbI~&pyND;F@3h?D(-jGQoN_*dbc*D_p zUqoC2=>or|*1a@q_r~K?GwKe5hFIL{#x;a`W{c?2z(1Yv)2mS@awUOb;l@FB@U~Hyd zHk{-dVtNWm0vMGxs3ZH7XG%$wBnC2e^ddGS2cba^K6vzU;aNGPzsExd{?to)@&2(0 zC;CVUmqIxR5`3z%qw!DS!R{aj&N`}t&%5~>%121`6G$EWq)^_+ls@I5w6}uJ^wf!f z&^Ky?!@L&xr*?&ORC14RH%e#;(~7Z0Lj*Et$yIysyYNv~g^2?ZlX=vqrh!WOj03Mm zC$m>NKrw?hekEgB_j zwoyI(sg6Ou1rf(6x(fsFrCK1gF^*EQ!2|t5?^5e2)zD}&;Zct=BL@(> znqOH?MI%r!{_Az}U?^C!L+N#FIo{8%-7kd+v?e?eR@_O+vATP60|>T{S|iaAZYu{p z_KmwV&OZpds7vjkJ^&yP5CZ@J05mf&GXMZ@We}9w58^3A0(+3YxsX6I-dq0A^<3XsiI={rkVWyX$tgb**PBas(0F$jNPX zEVe;Jl6Tv#ZCJNr^-V~G0C){AM1TdlNFAjATn_$wB3OWU8(9@q8f z0O+SqKGuXk{dHq?^Nj|bpDz}kP24^?_|5K)x4L%Cc%3U}9}ptB-e}`uP~c<45YlAY>$!)bIx(k^UK zhg5`yOLmc3|J_)%M*W0V=`24f`{)F9FULumjZo8tv;7c_VL}=iha2>fMl_+~>Ww~X zBihP8%_2$Uj>-jTI=5b&G|&K80`O z`6p_d>D^kX*pvJsKz>!z>`1 z=we{)h$6{Z?PI8j#PL3Wx{o8E1N^O=Tih+DrPHda7ZJsH_Zi%VJOHOjQw zP?LRPnKYdKi_oxe=)T{)vX*=uqg$!rYG~V)+N`CLDAG#l4xr)$79r)s|9E5~Hl#CB zf%}d&9I^Y;$3H_@en7iSG2;?v060uvezw|`!> zdkheEi^6e~&qv!JQgjGH36`t1<6Cz-S|P2pPC8@TDTSP}v3L#P#FmInGG^hh zE@Wr$n#N{QkOG7>14H}ChsLtIHtejg7RG-Y2xQ}kcblVrtoyqMVL6HLQ!5RM?c?0T ztq2I%2}A-U+hIkw160R5c1FYGoiU{3TV#m!pvLnTAlMVh5OP@&-<;CB?kR!0O~)%| zbfS#hR7incR&b?>Pt=NAq8i@rqY_K&+&*ikL?67NJ>e~<#_y15K>3#lct zUK98LKD^DM+AV&0l_zo*1B+kdRZZAU>a7*+W?Kxrs~nC6By1ts@zI!0RUA^$Q{`E! z!Y$`R1L#zDT9szCiZa%!iI7C0RA7>fBq9}14Es`8M$vpt+$CzIqDpVlhPdOC8C1tW zV_Q~cU0{4Oj-#d(*3&RM7H4cwTgm|Et7V&;Q@W|8u&`2ew}9*LnG_%8*9~GII#pbg z^+bczCe}@Ac~7&)upuCLx1g6zy%Ml|ltWBq@?d@h)yBKI7fIn7BP%}4vgDe?Pbl`z z3DIj5Ev_Do%ESqA9}pR(VpVJ!1S>{2KirZ6MxX#r=7(#l3_v+t8D7>KRu;3i{8flB ztHWjmuh)!9qO~WkdxH58<=3Ga*r+opC&l{KdVs@rhwEfafvZm%0O?8`U$`Vi5XN0< zjGo9P{hqFUY{THF!9@_Sy2m(|R6RguS4a>iAuLH7UYu_Xlm&zr$gPi`WB0PreEbL~{E0@oGaws&{i4LT-eU{0kToi@KW zgvKC$-b7=NQz!~I(>rVy=E+OVf)1#_sI$CvfrmhPoM6+4h+MiBYP+GQ>(e-+?P48s z{x^}+W|-eFS3shYJIKLL3Kh+iq+--6WS40xz+SLrP=;AAVuHFE<+P;s4z#fm4Tcpp9RIkF!BHg=6V$A*=aT_;@pDiD|ZU z{$VByCu7_ESw2EYWQj!2`h-1iKmiJ%&-{)7_y8Boyp$3sBDqg0O|vs}LM2h#Qrg$D>mbRgAf~z$02y6QHMtW7VG;DXKe5}1 z@+GNtseq|+j1|g@$x(2BXNu}3zkMlL?tM2+1iHnK%}tap>FMVCpnm`dD2ln*??Xo- zRObq! zK9QgiLA50UBJ#xF%=nlqsIZ=R#MB;LKm_8VP?v)Lx~H7)A3IGn+a$2QiyR`U@sYvy z^E0WOufzhzn<84fT%9EU7(g{n zB~k#?mJwFf2VpjuX8QMAh)A=0l~tQL`0qUlv4)K|N5Mk0fFDdvynM zSrB+c1&@aG?6IGFB;q=oN29cK3QVexPb)~!+)4;rM%=sY(Xjs~ZnufDue&px3 zCzc9c5$4R(UGor{CB0MN(9M;wpuS#R5GjKzQWupbSTueI!`UbRRhaN^r;8|h& z=``aLSqt55jnT2R9y+p13#d=mRJ;O`ri*Ku&R59kY((4}`5Hsiq&V?Jr zKO8p>o@C)b%}!5f?XTn(A2n^6Vd3}K&g*_dj^`$fCV}RfDWh~e1U+`K3W_8<+qdYF zD15HWICf=m*7Nxe%)SBmged_E3@z|!*w^OCT|}p)mb}+%X-SkmSG*UOQRQS@H@`Mz zj)waAVG8CBP--ehDfXd-VdULuJrr%n{`;8aUv^x-UTNnuYa$I~AM1Osf98($u+;VW z+o|>Rt<(B_db*dU$DkuCQt>f8qN*bgl5AhJ8H((kbFy-Dzm@JZBA*o~GkRh$e%9Eu zr)`7f!UDYpM$9siVN!9EN@d+GyeP^>7lCos(eg!`>6*uR!<7)eCzgFFOs3lw+`)tL z`)@#~p?==+AUd%et(4oo0qUe&3f4!P`H;S%v_c~VeKi)@Xa(Eic8?#Kk+X>7uyZs) zeRQ>kk699W?swZclI`k$W(k|T=Q!9#cgIGBui4>=Lmmo;BDi>*{SEuXcTd|i{wV9m z*6u&03FV#VK#M|-{P6*!vI0$p-3?4V%AS@n^+aPhQHNz?Z6NLeHcX}Jyd~3OBYO}yf(n50|+S=ovz#VZtYS|a9Vyi?oC((kFHJ;TIynL*&Vp{YaPc$t_m0Q9Jq#Q9HP zL(H!9LQj@UP?KZ`R+_0C0=pL*IFpO?#E5a5Dt8l z85G>7%oNbeg}Rq|t)#4N$L}h)q+;AttN=J0r86{<76iOnhRwb(sYDS{C~^m^5L z8q)mc@DR78hQJcAxv>}&bAZ}_t3uC7yL7~EJ*#5%%}6yGNZLYqiIg%BJAOifaLVf$tMHX0?ZSpVQn@#S zkdPH##S#TzvwAzt!TD{p1&Racvt?_~+%t~NWJtnLtM*_nU&_0ahIqT(L}Pe7wvJdb zw4K}C*BmRulVG1XXY?XQ=t&d2m>>2xs_y?1@vCqnvjqj=Hh{`vLB~1lJzAxU+??vR&|G1xkic@cd*gri*PX1u_znq9@%SUFrniwTiN!x?<0UVdf%Y*H}lVR(NJWkqV1o5%LeW zrKkq1MPp%YAV*kQ;xPEtLwtmJ?}E$0ngpAY^Ve#S5(<<|9;T9?$Y+^|+?&ZDP-Lk* z<5_1x(WBM(%*WWR8=m)q9`~y3gz7WOWweYc1wq-%&BN*;FSHiN#W8G%16WZc!%64? zuu28CiSGN+cZtC*<2+VND4O)VOm?;@hvG3M)iAAJ6o@IxvE@ijT#8T=aK38$Q*$xb zvD8;i-F`9sP49zzH08b2}D9n5dnn0iLf6cFKn>DP5peotWh1?Dn(ddKa+P{q? zZKu$hQBs)TIW)tTB6iAuTOmGI(nu7r{NBug!i}1iQO8$F@NVKa5l*XiIrm;rt<4dw z4p(?#ygn~j4fWs)VBgu2V0!3FaJ<(ds!cc$kg^3YO^2a7Dk~Hm6+s&Hj5B3)1kBLu zSodCoo&X4%9H*{OgRgZk=_kY6t2r#=Mst_%(An~iP-Ws#-aL%ac_FNK%7q4C)gvCvIu^m_$BkXS#FeSxLA@_FDT3dDoWs3 z%393=f>vcKIv=T&hQ0v`mAy70pI&x_WVffy@APYRnhYxKx_-|7niPv+34zbF^ool7 zbxLcF)VUeV$MqtfKBa2c3VHgTKR3tzOln+eRxZ;~$&nY>i2`YyDg+Rs1OQ(TJs=CH zfp{k90Tf-65#8G2>X8}=wS^|TS79<@+2eIGTULQ+qRlfa8iM)bhk3PY3dpaM<0qk_zeOcF3zjB}-v!c!XO zQIwploGaBCGci~NKef)EL+M3VCF|G?p%xh_e=y#u}(rjMvXyB7Z+6lFW z5X2UMIE_aG-vxd-APiDinXpDZrA;SvOE{RQ;H6*HiLBY#7~Cml!z)WxFO<2@irx!N z=g4bIcG5H5qcew`HGrNb5Z{#T&~_jke}`)L1f$q8w2}(0;8$E6DV+pYiw;VuIn5jz ze_kyrP*us8m85G=;9c_$O)OznjTwJiOh6=p9^gR3NVw3z4icU1i{yWe_J!NEH-XUb zO(vcP@M|==5UC~4m@t24`U&Jyjuo50o za#pN}WSPAP(7PpDucWA@(4-ER67kvW*_#dQyg4UCS_aY;OK$$Gb&v)vC#hq;f_<00 zPHIhw7+qkERY%@==&0726H5+F_Ik>K9gA-?6+_d)P&?aLxxz4WE31V`*+)d78FVBF zu6U~TnRfNc#C88BLZvf&S0zl5cmgKeV|Gj*lbU`m99(&bdR)*)eUP0@ZJ}PWr=e0Q z2?}FqG#*fIb)TNXfm$FkG?pd4uyug(p(%7|03R*qSvRx_ru0eq+kHfZX?i9-K>zzK zeV{K$+7{gwsU&tr9|(FYl+!p5)?R9bL|O(bN>3_rzR{Wox%TZ52n)}$Dx0Y z3GA9Z#L4T8oUOPG|GiH#72V=dQ2U0XR4NX73_SIRXo^AC@~T}<;+nd9!l`kMYfo^C zPxePzIg_nvf+pI#g-L3f4YOyq_@DH)8Q!9MQ1NFPv;ZkMcm7rDzn*;k(KeCme9mudy!rJQuz6|v@nnbVS7c-V z94Wuo3+I&Og|hXUHitG1z~<89mXQZVU!R5l`1c=7x<~)Je45szLDP@Y?2I+JT_{VP z(%l1h=}l1v+%vi0_t%@5YrS>AmhE0_r0T0|cQydm;VcmJD3 zZPKrQIS~$Rp%j$;%NHWrU7zYH9xMe33IjycCV6?P9`8~G;7ZY>v+wQM!Qx`{D^u90 z4(8_!1mzjU&p)VIuiRMnD|>)+^5vj5e3nvslm3gji*o1k-+$eW&) z(w9W`&(6Mq?O(d_Jj~X`8It{Fj5GTFr89u@OQFomy4;qK^ZwRdK+l)q9fxm!C9#CO zr1$?3+X)ib&yiSMu%*)jqkrj(oE8L-lrtXHkP$IBU^1}uQbrZ2`;Xv)u^;RIf!H!; z`&%&Tqs@=zxC_R4JdBpqf#7X(a3AOxE8xdbsc!f9=4Yl{YcuPH=UV{sqj%fh{}X^c zD6PMJ!K`6>mVOrBi7#)FHdr~O6kO;oE4!+9Q=)LbY&Ze2_bMR*zWRvsqmU{1LRJqC z)eCKuU6YTrQ0HYVIb;-$YzH)dI`XNx0cL#nt1!!EX@3J;328q%P^IShM(zA}nScuG zrKRN-owY@+yDhEeZ`qXONg{jyBZJBGzSBt+zJO6I+r? z4oj&i^yMdRfdHRNH$V9*i%mOi-n1!bK#65UXZwtCBP?-kPiZwfaTFN-@eO`3w&N&A z_3-X1LUMm9e%{!zPk-gc)~D#D(TJF(itx-g3#>`Mw&tMqJDR0`7k{BF^2)!u7!{9r z*u*8^>yMpieqZi%1lWEi^Q(@3;Mt|uRRZ%HK0YI&)0`3$H&Cb^qm=cipsfINH+i6u zch?%X>Gwv78rdg5`UARMShPYW+S%Ra?1|C3lh^b_;a_v@qeY@fg=n`D2&eqwi?*~r zwW`Zn-UH9gfRaxbF3AO+}Wbp}FZc z_LkPfhlQ+r69)b;<|9S9{x%0iF!kg0NBr%6D}J)rCr0j)mrQe;C`rSWj+E20PFl^ z^o1qM(%}n_NzU;n5NREp)`e>NfGiC>1K55k^9_&#Ec%-4Lhy*0JGRUYhe#BM)cjDr zsqijSV`k~Js$jh&rCa4Z3fX@sZ2M94V}z|f_Tv#@5I0Fm(x#=V`Zb4voy?;d9~1^` zD7c!Ez#O*sIQjZ)5%D&o`kKrucrtz^e(u(-)wvM*s~KSaE@LQKW;9;S?8qs<2KpuZ z2#&lB9_YKEkof-*#s5UiT};oa?5T|czA~>eY%tBid0(UqsQ=8d6y5d}a-_i0&njSh zWU};tIGh@j(J0IDR%#!sS^d|6L7z&U+>CK_bwunwTt>&AlT`eQ+mb4oT>aBm~~R1Dzi((b1`O zU#gFap@1(C5CZ@J05bzXG5`P%RcR_}KWQG@B->JrBqO!dwFa(v`R@PP4`+X#>?5*7~k=d${;cZ&KZAli!FTX-%1hshLg&v8;7?JqE8$8Gd0Stop zJ%kVd07d|cW&jZT(B8d!@4NH5*W32Jy|>*hTS>OH`M0y}Xu4+GvPfBNZFSdTvLq<1 zB@$H%s+@uV1Are8PzMno;D3N1)CVvh>7s!A0QARA)EJjD+s7qslG~A+CSyswr>A!v z>b7Y$U8{>{J73npM%(*kJ+r*lkv=iu7n~S4X%SUEUb#!zFcHmvA;X_h<|$VkAAjU^n5zLd)q^i zR|q??Pl@%1O|4MC-SK{g)k%x%q{sRzo6z0o`)Jm?`ugz0(z|i@N7ko)FBh~a(P`DtA+sD9a(t~-YQ4wd=cS>CIv!bRPnKAlysjAfJf_Wxa>?erpFAu0i)XEsP^VY}gq`(Q)rdFm(onek)0nSB>l^FenAkvO)%D$I9@2Kv?Tib}d3*U2b{y((tDog= zj&czJ3W{xGCvMX%IfS&G_`micJ5c zHPtXAAnE4)5nlfMG)fa(R1!}YK%_nWg_2qy74{wXDhu=3HJclB>Ya-e;R%n)aCM@X zs7TCXJE(5EFNW4TybZs%Qj#bS@mDmI*Vs%u_enIJMih1;$8`iE#N@ z7*oK3^YWPx3Ni{$v1C+joVEG+53WQyE&`9grE?v-f0D(TXTogzyi=Y#BDbih@mBrh<=J0}nLKchfA%Ci00 zD4yo&OmZ`+MiINg?<6?H$3pkX&;(k}%oAHWmBtANA;8^9510Qgd+`6xB`}#0^w7g% zqkS;Gg%mQsMnv^w#wSWNu@*A1l9etgT0w1~3-Bk4i<%B%@DFt9PcdKwK%1cd%YIs@ zMLbMp)MSxRP2Yuyc`Ao{Nl>wh`m;;DbdYzDs`|L%0H7R%WC&uMox6FT=ubE~1e73J z3e_Ltr-WM3qRPm`o?a4yd)&r&r%S`*T`UbB<_6P}PBe_|c~w@&rm5;iq2T=_rc>Mn z>gty6#$>i0zEGd=%r1B}YN&N$oU0y@j*{CS_cwNG_q6}2Sf3y9(t2m9ch$sqo8duO zM%f|HH7)iP``W7Z=i7q&W5Tq{)8yHtbhIvoMcPor^oC3oZ+-?*pnt*eTtGeD?rz?? ze!)?C_#2q1%Mc#mK(p%v0KuRMW_y5gm{YRhFTq2xc{-4^XM;NorMC+vG3a5YSmH`1hN--J38ZQ%u#%fu)9Fbe@fGPz zF~gg1gS>a)5SDgNITf8rYCwB2oGbRRr(Iv!Y@f&x=*FfDsWFOM_O~BFPAh48UC9>A z(PO0LQV9Cik_QAi!Yw3ZB}H2lLB-8LZ1u{UZBDgud(f=21N2jl9c*!_q8_CN%#;m{ z($NEKCZ@~9NWumn49-$0`_MIcYt}H?S(p})H9H_R(<8vG17nh>sOYuWL46$0xWEwB zLso^$K3K~jG%g)gtXB7t4#1rUB@cqif6&;V3k^)JYyeFJv!=yNW)Wq$h3s8J{jcfO zT!J;nRIrPJ*I5Z(!s$y{EYQGS)yRuQ_4`nfpXQs20GU8$ztD2POZ%SZ80-S{DNr_M zpVn#t4+@MA8CdBI3k#1HNfXpkR}A{@b2s|H3ju(UMXaL8PZ02e#5IHyk*=;}(3e{z zE_##7Sv3T75K{?G#^l!-%}+@8-;59eTZrMQp7Mnv@#Ta3u%FrYb8k)L;b%r-oyBG# z;3Jy`0q!W{QL8@t^f{V}c5GFKk^{?|X3`Ueyud641AagXdsyX{c-iz$IK4d-iPns6 zR^xwDl$gNEFZRK7o!ZuD_e81&XPj0U{CGae%3zZ@=i(2)6IdAV0d>r!Qt83VadM7`+@tacU`42B68SyaV(Tm6d zNa4E?yPII5QK=u99Ar?I2!@ov;0mqgl06O7h#%c-IjD^>KD7#~EK?+J6s4xL^ts}m zz^880=3ncR%Kmz6zez{(uMapv7|THjN<1->8~QTM$t9R>&y*p5ok>R`whaUy$m5QdX`k$sWO4Jz(Guz8#krSv z?lke%uM58JLV>-E1y8vH0^XED(K?bm>TR3ptJVz?fM^tU0Ad`tUAzFI64XUNNaGj-4^#Gfa$vGyLlI~p57LW!1viu=w?k8-4rAPhir(<5@G;8g@{R| zz9qA(Slf7Yx3BqSVl_&CPpqBH<895-X7{9;5*L+b^Et)5sBqDDt%xnevEdRkWKQt2v zECNlfx({dt06^sWg^$!G%@JE-TF~k>tbnipy$oyvK5rDASXcrkE|!bp6a#X?OxZT^ z7T8uccxLV5%tH(@#2x!bP~|Lwff6@Mw8~5QWKa=U;{Wb_)s4KfJoy{HNtC7uk3)Wc z{Q)`^niID)r3cKC*^sU6-rj+~`gw2S<+(z5B0h3lOe<=&4d@r#N&1nkA)5;SRMv#1 z7!ji~#?ohTL=e6}ECr-Z2ocLUFLAzS%I6(3=x=e16F_>90;6cfhCZZtff0??w$XB z#;dHRTN}nI3h9wMy8#7P`TOr#VXiF`>3*T6wj{;^q zWG*ZTW2}xNHc>)c-#kqb?ZU3GpX4#W*D~Wc<|c;TzbIS#M;a#pek{r=-h03%lj*HF z9fO|+&fJJqM_tQ_in!-sNRf*gaU<12mgJ~T6hNqf8ryELtg;fdi%)ffVu`Gj28#*R zk2=!;Kha7(jQ_jr`}%0grz z!#pPIh=nZ-TqO!yP910|-1PcF5xZdzt7KIYXE0CdZELNI~~t=U+Z1+KfLo?HE2_cK>|)|VC9Ohq#99DIJsH>B#_m~S+1@pG{2ve z?Xk)(Wx@GZNaFQld&Jd=fx#g0oCn2tSa=K!4nm)ASo4e+gAylKX-yXHgP?I39V@_g z(N_q9aDW=4xaM%0fE$C4xWY`D;9j+%`7x-8ezP(=!7#6@P?Gjqt)zkRxUW+%o>se9 zuMEV~_@)c`&c;6I!_nN=Yj#tB!~iS>SHGnIh|97Cjc0d|Tzp67U&$!Pn9Xs>_u|e@ zhT(z`^aFno5Q9WDKp$Pi8PF#dpTpjnm-`Kfs9yp0-L>e*)hOEuACeGLv)GvnXUkN` zQI)^|pvEQ3&7r)&4hyv8i8-^4(>9v1vs5b^UR~rJs8|CVQwV^PZr?p|F-ScjBSx*Xf5S2&`P4M?JT*kgMNJHLV6<00uL1Ucd;R|JP_L?8{dxmNn^CGR6fG z0Q+h$_`?;WjQwfh000mW0ssI2GXp>~000kFfhbIS0ICW}Bg+P2ik#O5Eoo*A?apsw zL%`jx5Y7Mq8W|`e0sugOdLo3u0L4$3K#4Md3VZ{R^ddG(}-m-s^MiE_#%yzrQ(HWcuPqVBEVtz zzy}^i68Ok(0KxzOGbC^}PyqIQZ@>P&>)W@r^;_NAmaW7~YqD+EmM(1BmXR_>BumYf zOD|;0<>e~kD~K}XMfedw2=U`1I5`3DcfjwM_-MpO4Np%%4lxficsc%a(6l-E`{kP2MIk!j4Q62hK#iZ;>7K^2LCDa1eMR@ z?HN=}eNP`JJ#`;tE+$m(@oj*0x{RZ~EFMDdOl+Pk6#dHSW<}o(X@y*^+}@X@R)PL=TW+0fy1IS6 zqO`Z`Ten4y$4wg|VaocaNbAL;9R=At9{9SVy$ov3QwJ~=m!%20h+r^bPcO^D$DbAD z4@xqHDE%IqCgn1P(q$E;I0cDVO<(ho@kRUf4BP0U#2R&9d#!RLbKc01@g4DvvjfK@ z5qm#zhK|u_diFjL*i$eUIQyzE4(I#vH>e-a+}*aixVP-M+j{1ni1s`Gb?ao^`_OG| z-NEkbXzuY!I`nP%@152ia@M`R4tMVbdn@^tLpKqtWc`2c)&*U|*suM%(ZNl?Gt^4t z)ULMX8{%ZaHaNTQ>kGWS;rQN$Bp&ml10M}-@AjLz)3AN<+}JzaguQM0BtiOZyY7AH zeH(y>#=N`3{f5u>E|}4GujzEU%6*KKdAh)QJc2u(%KzJmv?qggYonP0)RJp@XriZd z^Q7=V`S0RX+K+;z>3P2RWb<2hUk3qK-5f(wAL`fFtiPU=e8+tq+unY18=&*Aeoe== z2+H-xTwK_FQwxm|U*J6b@~l4+4RO!=fJC#YWgm`Fg(hQ*l_+hCz4|Ir_f>zHrNFHtdlFX6)7sVvI%t^ z(2*UxH~s(yr$ zDNT6#qzi5S`>Yg-qaN;{>fI<*lnWh{=l7pq0vvez`L1&oga`|!UZVwtlizT`;huMY z$cHFIM={+&9ovM2lVgEJ6;}%wM#nKPm3zTeb9#9s;gxQihX6BQH?nYyl2AdUb9pqf z(zD@7@zTapH5OHQPt8eHS7p;OFH976)$kWSDq4WcZgmxxN{sHxQM1!gm&1~py5tR~ zo^s!QzCje{bAR6%mD62xOK1%+ngiYpk)?qq1jex-g<~<9l$Tk%|63E=F`6||PXlA( z^O{v&*~=eO6Tk&Ij8?b<{2V;#fKI@u0XrKIEnNf56sTj`KeYJ+6bYmQE|#CFcY_(p z&4*+zuoD+~J$)$tnR2y@`z9;E^t;uQ6S2GL>6@`pv-mparv>T|T#97S9-Z(G`b*qL zj;@=5gn+zjM|zt`2pypQp?NA;e?jM0Kc&kG^*yf~cxCPVN)Rlo8%&iBvP^IZNOTl; zTOG!22#X@KOdS-YTG`U7kZ@m@2=4Cf(qF17i6FggTln{#jSA~T|3qZ1JYj@8XAV-o5kIO6Q0^mISE;G3)n zp&Ns=SEgh-Tz|+PaZ8B6upakwflvhQvmk8tgvq76=S6sYh4l12#&K~geT;>r0GRHI z`&}W5mUD&hZmCFq7Al?lhBNXnUFd59K~S}Ql#4*>YgLVKY$~+z{N@Xh!&+ns{=2{2 zqAq92K-Nt~C57dx257n$XQ^7R_Am5pgx^U8LIgFhDv%DCVD*m}i48Y6-x=mO_fJYf zRYDgs`%=LRD5DjPZz)K!^TRZy`eKHtTS5&mQ~ql&G<_!2t(2PQ6|T4yx6=q6`EhUU z3kGrHFz2{3^fqQEGW_*K{Ij(`842q zQeLxaWPap{aiz8z6h&drN;pBQQ|AgK0G;s<++t+*RDr_a*9Or~tOCDUjoKPf?=bzq z0~jwDxq`w2yunj7sS-4oaE$%wUjp$xUii|cf3*GDyb}k*^^&v?HNnYyfT-bG0`%I2 zhu~gAQMOgm5mv0VqcA~0BZDvq0E8jHYXickn9Rz{TU@Vz(NpF#GpzgI@gk?O!$;=# zh29r&268vv@7ambq!k!W{YWky)r+Q^ra+etQv{$`KnUsD#qbi4aDxH6aO5QW+u~gw zV}QarY-j2f+M1o~2*G z#uI8iA@4pcd;&FI2>Ql2K0og-Fi>C{4TztvfDvQds$<|?k15^N<=BM6nbeUuwro|M zXjttTax=wQhYF6#+g8|Ty>cwvlJ-cjR^{*H!U`SDX9;8u{hQhJ@4@_FZzKWeKh&7S zrr?&WRvpmuM7_c%ZYB@in|YJC!dN*QNvu+p545zXT80soYyd$B$g^ha1x+~RKrY4U zP}m)&4P-?C;~*FcH2=A@0=G_23txN z;RHB*BDsRp&SZ13jz{#s$oQ)Dr-1&2fbQ+NkkLgq&rc(p9NSXp>7b_e5tJ zrGc8@K#LPAbMhLipDO^Vk54B*n1FRi_~wQo-l`A zwRj;VCn+!1Kpo;CvkWZM&OCz2qP#K%5?lvc5@?BLih^M@sErLk%#ZtQiUS3`_-WZq^J6 zcMLNWa*2Vv!Od?hwVJMtFnoZ%(9JC^WB}TLTLmo}WB}G?_&9XUpDQ^n#~oqDL?5bN zOs`yKTyN?(p>pc@uKB>5+201P+C3kl{h9Fc7>`B0hN82mW+)Gy{l6#aMV8}SkB}AC z;;a@!A+cw%1X{(I74b`Y5JBJ<4ul+OnFW_QIF%Z&$7F5Y(b3$53fylY$Z7-8)o~)q z3~!>*?uPqFNMG$bAivXRns@wA372TF`fLvB_5vmXsdfTRvGz$3Fq-u8eH6m3t|b*B z&&ar0b0CN~&YWhk?>_-^1?PD1518!$HeX7g=h{a+)%8Qep~U$m0X3c>EW>-Oq*Qs| z+IVP;KP}|}nd!PQgTrG!K?{%p?mk+dBxH!dSP#hB0Z5yn5pMrMUrm$z1?DgDW;x?a zo0&2J7YBuvn1CPxu~mSr6PF4cHjy44_92sBqYh%_Gfc}mVWS02ITXej6qApb3BuG8 z51I2($l4iNs(u$TMcxP zU~~b+1A+ASCa+2gFal#af?)%ab&hK_|M+OpPeKS(wvqkafnjV@3dj)+Z^kY*{#sBd zv~D>JR^N3&-Wc1i<^NIzr4kVVeB%8a2bnvsdCk2G^zV^0_hNg>S~_WKFs>dn+!e$> z6I7<9orj3GClujxYCTd^EcN`Cx)E0$v*;TlfjJ&4ojYKc1<{p{J}T+(tWuedLP^=jS}9?r z*RZboQjn&K`Q|+I#$2)(SDB=tD6>b{vIhQ*3+Nt{3&yLUX=Ca^yW+S%!ufxXxwJ>z zqIT4UU)tu>b=s!6t(IpWWOI!JV3yx6Z()fUE~C8{6fmlqy09Z3$Eu~WPQ~US)#VZS z@lQPez4&w=t)on6X+;f{-{n`KN@EIuGG?Ra0cb+t*9PTlH<^`}SsT$p@O!2; zn6+ycYIohYTMbDzaM`n~Vs@%r_)pK;f%@kRHWkEO#oD<(UPj8OhZr*qB_|bR`G66M z1!8vA<<+zZ9I@R{dNSD_HP+y;K@VqGbRId-pN-7grdVqf25uZ==D-+eMj%=T&;^?q z&wP%OvsMP^`#2UTr7v1*2{n3y9j2l$s9`i{*H<272JVoLJ-ucmh)Yg?ag|hO!`Zx{ z|41e0iTHt3a&tJ=21q;PY0(SK=~`x(H`umjlpwUVU2uKv#fWcWh6R7Z(Ma5K~(KBsWuAj0+0LU4YJjb zwIQr?Y+V-$y%?ntRz-t`4W-$hsgJV6IGc3OzdH$abgRT5E$H(J03;9)0ssI2GXp>~ z000kFfhbIS0ICj2MR z&Za3h%(&A)Cuh;bG<=IUd_=DlB*Vn`!kc&v9~BV-5a9Sb5C{MOApxwJ0|5I&ZP$M9 z>uuJxrS0w7vSgM~Ep67mS+Z>TmXUPWcd~O?*z=gx?rd zIEgHujoDdNz2}%K5{W=@R9Qg&$H~dbRK9ZxPr&-#?5ObtGX&q zM1oJ8ot9s`ny#1B*`oZ3_`#KmbXq}|!r(+Z=$e^DK`58y=Dgpcaqz~FzI$?-s;axJ zr;1+J$o#uc_kFbk@_f?ZK93=gLCG-*yZ37T?Shpuc-$b*6P=kTTOa*obE;{B%ot4z zhN#}YI#jr<7I)$zds}(m^usnzpW6BU<@GMa^~#w3w{RXX?q0y&xVve2wQKg;Z9NLd zi2BF-?bggX|Bz{Q@8A6q{fY0pxtj`qEvUcM?G2_b`>S~CmsgM07d*$y=;Y#5tS``; zUN5$7UY+ON<&uMdMaY%M)TXr78|08ZZLjuUyBp-aN8ynw>yg}eU&p@-O67_uMlD;JN;iAZzN3#v};8flGW z%=2v?3Y;&+IJ0IkdrB9^%~No^7mr_Y9s|$!Fp()9Fgq zZ$loGPJNr#$guU)P|8*Gd-=(KefpyPXS9#ED!Xo{>ahF)5Fx<*zv6WEPu<3dN>HK$J>^KTVLnse<>f`Z+mraGe>H$cK zRoF`>RYkatRFA?^et(lI>MZj~Rq6@`j%<~57NQ~Y!n^mTLrOK61tOJSOV}MR1jnnwDYJ#y zJ3XVWL6r=bocIq91qX~Ge^eGf(~ssCL>}mFrQ(@j2M{i~v_v3AAL66C6MC_W2H4-p zujI!=zx8pXKTw;UAxK~v^{w-B;-2mzQ(LFjnCf@OkXlM@AH?g#N^ zno3`O-PG!~yP2IZly)s<(s-fl6Cyh1Z4jd0P$H&BK0?YCS%wj`rvF4pxyEJyKw)S# zR?s9luTZv#8nJ(u9aW^ddU@ofGDs$4O4)=EL6H?K2>~0aG7=%IHd&QK;L0S0M3h*r zC4?yBB}+n}ZK5j~;T9+gl9OU0IUxWx373Vq-SlmO(G$oHl9NNRix5JLQbZ?2z$OY1 zc6gm^0>lTP$_=dCluO2}cuBFSELKxvZw-5MWX`ixfqz9d!z|ynR_;-l{cJ0@X$Ny> z*%c|~VzUg3eO2=my$vX=PxTLmu@OEL(8C|&{e*r|M=D8GW$qiR5*^sjc}y$-iKAQ6 z>~pg*v8YZ<%u(}mVxo>{)+Y_w_?M3(w!!f8*l_i1Au@MQ3K@!lnG5-im*aQ zloC)UBbQ8q35jX~7a6--^SOH6wDgF7V5+P&g9(%r(?+ zPhe&uW}`f!(7CBY+*u>mqP=sXW-ZRToS>3t9&E^?%nUF-JlxEH zGXoDskxdjsB7ISGau=pK%8<==dhCJ=5>7P)uC^!%XIfK4q_5tRgu=43-??|b1*|wA zR8#D`h)cz+yq0NHH;{UUtRFz*^@B4#OETx>jcEzip2j}FqBCoR@z}$ic-7 zyHO%D6#7N_n+Yq8UjO6QhppVaM+OvcS*hc(PKj!Pw^0y{&SpIpt&|dVhI%5VPoHaI zF1c#KOVQa^_>OY8M&l)>D$VqGU(y>c{>WQtBw=(xC3b|(g^{DttrcxZ2u(zi{8`Lu zdSRAvU$&NC=KP$aOK|2piE2k!{utge!j0wg{5PXO)eP0tULRC3s^fZ+}l)fAmu zbBUN0^w6IHyFIVW@G(M>{mz6v)LQ}zkIKio6!Q6!`)w@azmCXYGj}IXJrue%Z(WIu zld|cRDftz!1{$DxgHkG(Ejp9$e40v!SvKW*Nj)l7@~tAuvouTq^j-QjWd_u= z_t&k1@gaaK2R>>Ft($a-m=*fs5(27aLY+`s*F8>}FGS}i>!+M?eJdD=$lK>m*%8wT zTct2m{v1Rk0KU%6(0ASu!r#{PMVU^>>V+fS@BFaD)Z_+WX4HyQd=+LX>6cZjX&og30`|NN>pBE4YKoHW!H&orcrXw$6o7%?Egza!CQfOdA?19(HugH}`?0EJlR z;E2e_(2}W}h_ZUr{!@i?;kMhhLz>VA=xh0C0}TiVBOG2-OYE$;hRA{rPFxJM1U6BD z5<1j3NJpP9jL3mxrT0%(P`_zYn{usev@K^TGU_~NfiXO+O|KJ^Fnj?n8p15wd`rZv zpvPsKdoVwpoWDKmMcwJjEnT=d>DbBIGy>aAha1FBdAJ~{5w;Q)Y$50!&^%mAAUYqA zsjcL2MnZq{6LQFm&~okcQpEkvDfHiNxzDiZ`Qt_yO&#ON8$_%#op zTTE9w3c%iu%-K_C$+9cf0QFWjfI8Bgbto(sVRZVs2T_Ip4jctT+tIiSjU2WM)qiYW z2j6|*v8*_PhcWN5Q?i2&LZE^`$F|TxKn^Lz{-L;_7PX1@VM&q2IY*Y4s_o4@AktYf zX~^W;%@cBVBhOUMKA9xAMzXMApzML(tQzmiPJ?lVHb@OCPGG;RiO}f2dSRNkIvVF zFGm0VeBz>{FCJI~&0|~SAWPhS{DT`VVJr)aQlZhd7>4^UG(;xDZo29?IccEki~gGG zXi2>xfqVU!#~!6jkb?Qa1@ps}j(q%ESvmXJNbG!|LAcHM7$;`<_xbr9;M=h0tKZ+K zB2fdT9}WLq3s=z~K*CaaWbybJ!{*|wWksx!ruWXNS3CI(!HE~&vk<2+;sO)|b85T6 z#6Sc-5f>?cfr{D2^=ihaZ4?nbe;S2`lLX|X#)y};$gL=5MJUAY@R`0|VV)KIm7du6 z00R(6PAY(HgfwrK{%luFf9PepT94$oMne-HD~k1**n(~S!BGn1p8njq^h&b8(O8kvfe6DV$?xP_d23ik&4(z(_68vr%VM!?qj=% z8_C29C*0HHiZI_SWT}OXJH2qr2RFwSZv0C!SkZ)wVm?rG{Z135OM$B-s3y$n(NKfj zscX+c#Wo@?&Jt2BO(tuAVk)b-(6q+o+5Vw4AW}ASTLRl<`0yjY_fIJo2y?0EoV&S~ zEy*y^Q+9}$iIcA40b!vcxIP~c57u$?jf?oQ|HJUaglt9{%l@)T>GXr%uFWRAV3FPA z1dZ+vbxh(5%eYR4Xp=WY8g?kmx~`%U^82@A+|J!9b-%i>I|_b`%#_g>-8fZj(~h5( z({_TSx7b`ONw1BvRdou#E!SsVtW|hs>(|0p8=;QUI4Ze{ke@VHu}f#HWbHp2=_mGs z1UV)Q0T|r+7|1YO`#G3l)|-o%XID{uCy4x%!>^1v0Re-MZ68I1@P(aSW2yhRw25gwe&y0h~@|mVnssWD-$Zxa`1u*hksskYmhxFIZ zrz~$envK2_yFq9N4=8lFI@dDF2z($gPX?!561WQ`^}z0JiUjKbPB5)#F~`Wc=0||~ z@`}A7bDwmv9?`=W_c1%?RVAdaZ>h6yxz=%44^|vVts%s+%C}9--fQ+|a+h7sn>!(o z;%wE^v7LV>fw}jkEILT{&!WL|6l5rPOX}Gu(B7}Mq;YQAt~$(mC$|lM7XIL}VawZ1 ze^lPuzvvcrH7)Vc000mW0ssI2Gc`~%003`gK$O$IfG9^2jw1*@6CVX?YS#_ruU%tp z_?&hI+wD`Yvi;ibQcJ%V`0oJW833A@IHNcK5Cqbh3yvBfLX@BYG9bWzK(wJ1XHi`u ziq-Z#BeBSJ-Su9y_Se?1WqY1(GSYj`_9j>Fz8!8fEMB}#^=N9myxl2UEPh@?N-ZQ_ zTppWR5q$W#BO@aC??`>*hWr3P!~ke$0Duh&yW8E{yW6+Ddv|-cx_g)Hw=Lxsxs`Ia zf6GZ`GcHFaWHK$2tC)W=5lB!FA_N5jR0I?e1rU$)e5B+<2p@;}K+Y%lW8SfiCYADO z$D{W&O~w&2d$Wbz%Z5DSZ0~Fyzu^6{b)D^-g`XsEzUkZ(iWlzw4Q?_?wmq2a&2%R1 zHX!>acVpwL-p<86+0^YCmy(WBA>I&pU^4QWk%?3S4^L!fyOt%jSRdcSDWkWgmx?KIyTw@rR%7Z{^Ys%L8|7EU;eewQCLggNJPKuWv`OKjqwu zS9ky6u74f>AM#K1AME{p_@ldd_II}%@5NQH8~k<%b+A3pEkj!$5B(!5tb2hT^K9H> zJ$KLJ%A(9wkk>To&6mx-hBqT_+acd;7WjMi3{Hn*4qvJAXRPEE%c&D1o_N>dSjitHOyo4WyxHMy2YKvyFZOmnT&(82`yKv< zZN}8Sy}A76{ydXUG`HF4?_9>!KU?0tFn#Y+P5Ms>Uu}APdx+cYRG^TB)35%rPF_vF zFz^2uSuyg&kByk?y0U+bpSxD3n@s`H!B3IX4Au0v!C_$y7lk(X{& zp>OXwFBP>_D`@1btxt?wZBE+r=7&3a`Mvvz)GufK_nI7;`N(B3K`R0qwTZ=o&u+Y=EnMZ-aS)8Qfv89RBno&+wG#?f1z-uf6 zP;%~^_6CtyuXj~U#Gq7zPCcTT_UfxVxR0O^K@n5}kbO8y0<>z7t%{_rt`DPsKxK=9 zoq>X7;Kr@qfp1 zn=X|HdTJphbM6Jmii^@QS zVQ|x54>E=My)uE$pv=fg5f>wuB z*{~oh?1{!Wcb@wXEkm(_MbkO6tZc5@6N3rmMfbNEbecYYPQ-Li9_1fMh{;M?SBo5H z5Mgbu-9voVv2O~U#O&j5Tp!J*NzoJza_JxC7RtVp0ktjdRwty*BSXBDVRKeD1t~gKJITPnrGGRC!gOH zq@C!4Hn(F|Qds;;$+I@1q2YiKK2i>{?LPF0XS+$3Nw;b*tb2d?$}yNHZ(Go*mIVb6 zvimPo?xYNNkoI!Eq40XZtv;U7At-Z{XIHJAwS`lJb0m>+w6FxlF4;;-KC>`5S9aP76##FO00~Nb9qadI@ajqZl9_dmYil} z8d}lm8(R8W(zZ^L7tEUNk+vt+&sRcn@0@m?%Zf}2l&YQic_N*vI2d8r7A4@RwLbJ1 z46(w5wz3l{@BA%%C`4{p?K7_L-3&$qEr?#3r}88kfkZv%DeV`(*Rw z@Bc^TMW{Q$BLW41i<;X_LFw#YN07IG)?B#?hKCLM>E0!OrlOE;}w#ai0}b275Bc$7ZG4q)u4K^6l@ z_KA_-Op##ild*?6s`?6Aa1mr(v0a;-vvDTS3uM!nP|S;vF_t1S=l?=vCyMQ9*15F^KpO*&DwHJlwr)qn@32lo16634I@ z!mKtX^;C>>dNHa&)tvgrXbap^uuspJ+xBp_CT8ZvCYz)F1_{r}A`&9WfxeGjPH^s4X7-4X7kZZT@i@Fl%Sf-6_8+HT@>BLj;pp$nA^-jO^fDM z4Bjq`g(5!(e*R&tm?iD@9S}z}!>Y%*%GkRes)H#zRIuGzoE?HpM{k{!tP(x&M$LDy z7g9%6qpUK@a&2M<27>g{nt`||y((%=gArl~^o?_&U!?*vY3J!*#)8=Ti2X*Yuw6Dr zk1gc49pCfzAEp5KIT;&IJwbu9YHLX!L2;RtAtqK7V*W)KWCt~g6kQh@rirBfZAY1mZhlv>H9AYy z*i_CY54$USyDqSRji4!_AQ=#{DaU;K(s9E2PAeod$Xc^2%aCnWh7(N621^-T8$Mx{ zO8B0M)PE4+3zRNVA^M$$1^M=?c`LD>Z(qH;c^vh(#FlN{fIIwULpIYHSYh!Zl zh4kUVaaSi8T#!3lx~_{AJN)jEQf&%>y7a`YjYWx!!T=CvB8tA?K*~5#WyP#$C3#D+ zi7c_D5>GF6gx=Jc3d~O*UrCK{f?l?2Zt|s)E3QaG zpVf|TqYJTVCt_ZZBV0?QgXaXrUkWr(dqcMu_obT00C93V$X1N?@3}!WP#QvVQSK5u zG%k1R>yn0%z)mt!CVVl>h7lZ!auyfaJW2WWtA{_mLd0U`a{|J8r0;&LL7|)A)b8na zWRBd0$xY?;z6t4&FgeWeleZUpaZ$2A5|Ez_V@~J4uQs9TC6y9bb(;~c4D97-fOsDi zb8MwzXao*k7mzT7KMTmA6v+088yFCl3P+w+Bb`aG5-ArEUI(0X2%k%7I8j5-Btwzs zO~BozahrfViR2vitA9h%wtu_jTkN_^YNt7nKnsMbTx$0>hlrScM4)cgH-pkagn}$nc`jvf(=DQxlw!E&Sk{gmcFY+&h3F z$qDp@eprW2V$+-Ssjmp8p$P%@t!n)PE~E~vl~1-CuSMug(x%22iW0TqiTJAI{xF(G zqU_Gz6cU=piB|2`?;=Klr)C8ZD20L{KX$ z!ujJ%%ajzRY>WYxvFiK8l|-xy=T>b|R-s-@)qK_&a~dR8Vn7jL=!ks zTql-v)!q;xV8tb49sDn7&`^@I7@}b!u(ZUcrTg1wfnS#xI8BqCd5nS$F>-wUCO!vL zO#am|^22I(Pb7&v13$8?{Pv8%;N5#4n)O!W_XlU=+?~iw*R+**%LsLolwBesA`<6o zl<6ME8L9fk{ffUP7t%ndl2;4sGV;8XPhlapBbpTHi#RJw*xk-S91Y7v@u~W;dH23x z2?|6>y10JwrKMVMR^>lRx}9Vac|Tg+&J(O0WD65!gl=sbSMQ4rio z83ETa0KjpQ-`6A?>-5Gx$OViI7= z6g%sMTp;b3{t7drsQ$^n3~0iwB;n`KdCcFEi9pKz{uATc4J`piPFT`0E<)BLd>ncO zv;a^_-KgD_P4Mfu5&>*Yby-`0TV4+BwKvrQUEeLR-0i(a5H8*jmx_m_=pfMx4> zPZFO!_0j2H^x106jVs34=0*bL`qXeWSM%6{^s*?XUi|L}kma6;gX4l0&lE)|Gr^ zlJ?VQdKCpk`2AJ05$@Q*%R84NST}5(kh~B0m|ZFq=|XDjSGpBhSNw37r8ehx_Uy`s zEdPpBi&{uMgF%@UR%i7?svx_>C_IH$k1Fh{GxjpJ!G|}I25=^scag2Yw3V-jZ|tm* z75yTCTA`H|fol<175a6$-zuzK308;7U2 zCH|Ql>7(88QNTSH=gn0B06T0pcj#>0ObB4Jks&Gt3@%@@ks%P=Z{1$fqYfnNtM~6f z>t}EbSxuAtxhq`ebKbrkP`h#d?}|*A3mL^GN!g$1J8`}e11HJmztC=CcrHqu`WcfS zLz%z?B8t55<J}!GzC|t8S|fQnE2Ub{|+$2nT8OUg330u%ru6s3q)jIyM{_a=}r^*MD5`hS8GYI zd~$&Mj+0J080ScTKXP!2{MnJAa|(^KdY|kV0BVbox3?(ceED$ZM~3>v1cFt&JTY47 zU?$iQssYWm6?P4Xk=x?SzNRwi`rbF!uWHMQQW&A&?Zut_ZZ_sCv{&|)8t?aK_%D-5 z+65*XPI6QX7#UU@QCF3Hw~;PGe1kF_t;Bk}#v0nbHqOWrxN(Kda6<%pjLXKy40rzr zKV1K!OlUF{RD;*$c}Hjj5jITeyBsB=8}vU~hw+guM+m6Q&pTqPgy5CTXlLkuzVtAh z@c&SJ4iE@7REU*=1s`LztSk4ptc1ViAo}QHkyPT2zMfVucDf@ERq&wy%p^Nne&G=N z*r7y}WlrhC25H$}8_KK5ZcJ8am4b#Z-L5K9h zf=X$Zi}!1bwMeTBy@6l#|q z4hmc2qhO3)8NHBiJMQ4^f&c*$+^x6S(;f|wGEozl)vkAZJ9KEsfObd)Y+Mj{1Jhdt z17(q+RSI)!plmVZQ;xal24#M4i98m#_vZQFUf;kvMd#FUr8%%43~CLiM386J$2B(>Z6`Kik1zdotmK@yWI92IF>@lbS>nVWD-a0R`1 zm#+YpZK0)iOFiDx54Jh{jYo3pC{PQA;MHH-wTh1~Hn3u=@kCcB#{IxA3L)_GUf>fwmxS%ib413E`Zfw<=nqg>&R=XFYvMuFqi4QA!Da2?iS}q%> zH|6~%4nl8CT=wpF%zZ?^rRrjm;_?WTm8E z705Cp*BXkhKmK(z*@P-XbQU`|6a2tj5D)?Y001)sKr;XU4^@FEOnU&T3Q6P024ZTQ z+XZcFWex4pZ(~Ei-LBChk-w8;F0058x*vtVOK3sj<*S7R+&DyhV+ikLLbhce@+hiqc zwzZN-r9RoO7KU ztJPPo_Dk0XN@|j?sK`(OQ=74Iith3Rs#=|VUDCEOV)frrbE(b>AWy4yg8j1*?iy@v(XO9cD_ zcpZ5Z@Qu<*+%&m=)NlwVckI26bydFn!Q>9|o$O6@vgGTnBM03}Uv20*4M;ARJrL`? zeB*CA6$kf|8b`aey*4E~8KplVEB;>Tzw_pi`~!5}kSr^?*}*MjkpDepQM>L?!HEpG z6C`17LWl>CoU8}PCf`=}ks|8N=+5A!gZ=CLVA2bikl|JNS)U2|cte(Oz6&EVfy^qT zP%t5={h(|F5`Xy|WdJEX01^aFkmMRL5>rV0ISW!5H7=dH=sV8hsD1D*hYi)-)lM%l zGI#Oq123vWH}$}w=SdzqboTNRtA2n_9>z_02tdNdwSp zrVeSf5VWY&M?j25H_?*So`z$nwIaI2<<8ZsmSx-2rL@GciULh2 z)!wVi{6c-0n5;rUQzZ*KB?PD`TBKgJ)e^K?;vR%Hv-3G1wJ)qHLDi&ndtT-h9SyW$ z-qvcp!^?t?MDtK!UJwUl2L=U|$r|9Q7u(+AJWBs-E0yTIH25By zMy0W7`)2eNCHvJ9<CP+=yu#g)vt!&&PRQZhs! z0lPXFJ#s#q^n4cVyZV<4U|&ucF^MgVV(RzemqY^BOBFm{r?%XfvfZ*-Wfx8M(R3im zH8IyAP7h!;YlT20jQI=LeWE^|^m`USHpY&f)(vWj+_V%i^^Iy^0l)PzcQM(tDzqW^ zw-o$YIN6PULVE5tlky*F4)UQwI1r1}DFH*xpr<2zH8JG{K|u-E)llZbLT*}dadj}Y zYLND9%V61GM_h?hTxt%I67E{=-x<* z%SN?2%bc=NM)zdZI1bJgQbz6+qD zN628pQO9v)Gr=g6IEjc$sdGLJ?@$>^(ztk7-W(Oy*GfplrXTY*W>c|9FW^#itk%6R zbRxcvjid6~r>Z=^8$5uK;StaOnRw{RChl> z{pr;szcSTHeNFi%h+ek!GAw7d&Xp(NA&8^jvmxp)>o#2$CWYg`o$28+{imUwfvhQT zRwGQIQTcZ~tW=>{aWvnp3kLyXuC4K&$(%EP<0S91D`|MNY^+QrB9@$e zVil=sGsA*y*8}rY9y#kg3u@UHQq4oR%%}32c@Exvwe9|0;;3QbH2^os{ zgGw)b(NTS|YAc&5qo`d!JjdRO{d%7fzH%}Lq@1#RXKgnLLCzoa)yJS6sJ`B+Pe$7r zBdq5^=or5nZ`)KZ!GE^4YoNgvmWnnuV7gVFH-rBcEpN3TC-kiCtZTyvf(PjOh= zAaX3eTqg<1l*MdMp|G0%fDX^dyq*4$1oX@df13QaprdGDn*5E-N*78>Mb**<{+%AU z=xPS4Ld9l|eq)g}jXK%#k_VzmoSj>@V)DWj`;qkr)##$-F%t>xK^yU1PUzTElU=PQMbD+&atH8NG3N|RI zf*}mVRLO2C-bP4c|N9Q+^Dzc0c7ZxAyG z79ttwC)ZSbXF+87OMBoLsXV ztMU2ocqUbvr3aa?l+=f{flGYTHj-?Y1j5dRm}fEOur`iCB`_2S+uS$^YKEXr-C8dD z)Q+M4<*Q;ArBy8Yz;kMLB=y+DTD5v**rc;dEkd2Ag`wN!5}D{qyK(j8vbh|Augn1BwQw-f*#P}X_TBKEgp|_i<9eca`IM;qkLm1<7K(|C z_*^3GF#!qm)iC{~eM0HrOwp9$dbB1a1s|R-kN&D}*EjyLbtn6{~;*-~cfI0GS!EnjiqSH*eo>Z|iNowQJjVwzYoU z#@SNVuB*w(m2M>)H#m~H+|;NXY|ua<#3V5xhEV_q0wBaN7sQ2JAnl`I7Z{f}m?6mB z2dFE?NAihpI{*Ei&H}=5H_weS{q4=pi+9KKY;>wa?`>smY4LBKGeP_3*ZngSJWU~1 z$Ba=cl_<9s9USH8PXj+&#EI43Bqj zXt+_sayqm&QpiUGMNIeVLm2OO;tExaBBaqBh!Z;JVJ{!q68THWx_;e-nmX+98^Ualbh^|9iSt7w>i$bbJoa^1e@}&sN_N z!t~P;_x)G`gPB}6HJ&4y#1lSn6tys)W4`-X!oQtYgl6p%3yNCXQ20W`yV*C>jkLi* zcSb>z5|9(Q!eoa^o`j&&*Ga+ECaPV+fTha27|ZJ_MwvU);ts%Syw=V3C;*7elU zj1V6+(Pj<8w3c=1=58ma$Iu7DB@LCN19qY(5m->66iN5vH9=$1Nc<(AcCE^&*>V@K zyN>aP{&>mih~5?BR@mBPCaysl4(TR0P9RcTVsc%$$S69wkZqUp9o2EZf|rPyf4ZAC zIuC#T|802(Wqzs<_cl0=w&|bR9kM>0b=b~zSRFmSmH_i*e|hwZ?mhHp(ak#_?QvuF z;b5-?)Ul#E*bJ?E)njkk1~1>lkzTVn=o@iO(MRjL?)MziLE$=|wTo~jsFTOkh|boH zZDhCk7rNIYJuU5E{5yy42D3?R--4oD_g>Yc>;HRedOIt48*dNNY0i(G^ui~3_=n!E z?O=O@zV~ROe;7kX_xYwS@c|*I-D@xj+L8b{i8Iw zd^lGT?(y#een**Od|Z0^NGK_W=Dv>Df0G&z5fIg$5% zO>#)0506f9sU%`}-vIt?_p2rjC0lioC1Ncn#8ynw+UwD!!;^eVp~pw`Kg=Gua=a4` zxseLiTE9~=wVO=w>ZlASXw-9XLA!&@j@^O)1rC=BB6MWzA!T8VmcPG`(h6~NekiDf z!(-cjpgTZjA6H6vI?OOtMUTg;P|>?gQW2cR1Y3)n?8Wk>w>C0^ILI+UAx6QQ z!RQfrc?*`%H;>X7EhfS&=3!-g?ps$)C{U_9m%bM%S}3n=&ovzzWqU19BN%e`ZaW<> z(_^C-YPK|#Ru%{-RnSKt>D^A0k1CR(t?q;!lquz)e|O1JKZ$P?%4KGhEO?u`HI~pZ zwVE491KcxMDP?5o<=GySma{cxzUf5j?lvOWJ|!trpNq0Hcr~dfqa8cms@uJMJV&V4 zl~CwSGSJCV)F|_)$xSURkzfnRSXZJQ6|zLmz>%|FmZ=%(V+R*4_wm$6l6&f3m7>Xv z@rA3Jup;~4G0J}|kq56Yu^eX;0ExW%EWdb9CAz#!36Z^vNVfPkUU97f+AcULw0rQ? zDyPlT;yYa-bDFUh{`;EyyqH+`(hPqEg3(bYUqtOvfbR&`PMibWV=n>t`e3bVjCu7E z@j6Q4D@5rjO_yBt_K9?kn*IXC4vv4hgoSR{iOnYl4NYINh*!EW8-f#$C9TR!Su$#l zzb@3G6HH+sg>S45ZDgV`F>YZdn0PItBnUj0?E_9uR9I4LTHPMzBmSFXZiXNiM*@ws z@)NBQ{v$FOyo5=}N}`X&daVnjN9D({^LJ$I7=Qu!9w25PQBYv92o$v3M->#&n8hA< zY{ejT;$D^y?XPY@w&<7y_NAl9Vt>D2-ERG@2Jpe6KCS$IeT~IILliN7f-Yxd6H5hPF0tubZSx>(+$7is2h!=sKqgQ)sHyWzLTHkBvr{BpIk0 z6Iq~mLa>}4*K8+y=)UNd7u153C~*?mlt6)$!zh9W+n}n~j@GnAzKO#4NuDh$iwQk~ zv%B_C1caL=Ml;nnieqw-srgK*ON4b$?1dYf$1ZCy!GNQ@E=C5H5>E^RTJX!6^`S&& zljs(rl0q!BNICrNi)Dx9+-Xe8@&})_fFcDA2AwbiidkC}S_8X2tp~29@jJz_j(klSthJ{4e0@JKMzVkr zg%~oH3j9@az8nJqEDk&)UKXl)snoIKd9v4QXXCNpC=^x)9RYuej07l);F^I}t!hip z8WXMkR*8xsthDyX7qVg+mnXo+KGJ^W=u*{y%hBQC$vzuuh3 z1ZfsDu};Mv+d=KeV>-!npu*R5lmx-V%Pa*ht`1u$AhY5oc~=_tSh$U#tieQ{kl!7= zGD^co6rAL%yM7ovQow`Y1dY3`zKd8aYQ9Y>HXhkR;xr zlCf4^Cq3B##Jx=4q2_}$=QJe_6ea&Cp~yq6TvHs4w}rKI<87}t8aw5kv(1s&iPl~z zbg5iLSe{m^P@c$H#=&uUgZNBX#dm{Nyfxpf`rnMK>$t(X1>-2d>_G_<&)SVmlxjt# zhwK|(OeV(m>sUyx6q7=)fAZW|D*bmG*;Ea;rK%YG$^+62^Z-hU30`h(ixKohN9R$9 z*arAEYE8{9T6dtP64Sdo1-_0j%z@y%B6*Rxkd5FMX=awAWzCZ1!Q=d^dQ%Hq6*j6~ zrezZK#|0yh{Rb$SZ*!)Sl{6buO_bLX(1QVn9^s?%^x%14N@9 z2x62v-F~Qvu|-|vRvMeY!-0S$1X|WLU67A%F?HG2Si}tlOp6)l!NiEz%ZTeDV$_28 zVj_|yEb9xRc1#6BVvFbA?(*uMyUEr z@GS-VxS$x>B1Wg2j_I6@1pMJooiF+b>WT^W#MRuzHQe$!m9)#FuHhe2$6&d??IbnH z|J;(7W`cyTA>j^~r~}cJs!7cJw|o*EO5`X?!OyqrQNlhE5G5?!MqKsGopClbLeLCj zwNd&$0q+f(R=oI6fcsIfPS%}JeaB{U^nmyTp~xqt%DArt-nCHj1jZp3XmJzPfA68Y1Kaz)D{MLQ!Zww!;!(&VyHQ6SQg0~ z`P)+_sme(BC4ySzQSQmbO%@|&!fxT&xh)%7fx*FEK9_+}S*-9DFF^{<60H6}FG~v0 z_2Sptnwfk9U?Qc*v99<3k>IH2)}~-vK2&K^FD-1c<0uVSGigeYhVj~Lnl-KXByu7Q ztWl7hpkxsWMqRCHOHERbv|O=+y2Ny}cqU?uJ8*s4JS|sEXeJ558L`J{wwcsoZL9pU zfpSw|wW#`kaBi?bxkv@9spP)PnW~)k@ysPg6R=p2dg*p$Ba+?-KRAjOqGM;Av3KmCKy}?!Gp@JdLaCY<)oa$c*br#-g?JND3?!|?Qi-H<)a#l}& zwOS1KfT*c7=`=1`obVsg>3fVIgIFV!H{fF{8EWHclM$MiBCfl6#8E;sUx`wQ_rO>~ zwmSjxRMi(aQOC#%#q*UDurtcUZ5|_l zf^b>}Z$loKvpNRxb2PkKnETq^lR%56we=62UhhUWYJyDMKUM1wNsIp2mjdP$#)Zi&&5}hkKzYOb?{J_PC3} z$9v`k)u;vEDDS;boP|jQ5Ez>3vohvbT25KlQq9rSU%)=aH&!vDQ2$M`ia0QU=7vja@ALgyxc??kSA_e@K{#{E(-BmAOpET zeAMr2<2Vv_!c8kD=Za6m+1<>e(7DTP4ZjN4fGjD%)6YdDPy1SBoEOtfT*?dXFfd=1 z5}H3$GE7o4qYT@qeY5+zt_O6^Yi2+W#^zkUG34EJ99Kk8iA+ZFzg*`y}U& zlrJ}$t<^u=hXN-aGPjXi{`?)u{{Mm(7)_2^YZ>sb%6Op6IG zLdn5{=nalwSQ4OWV`^{(yX_2CC4;c=*1Hmk-XAR37^lsYh1$II!maoQXYiy+r=)~v z*D?c!l7djM@GMGBL~B$TVp8y`PO(jh42tt%hJGcno9VOURQ{y1U(07xldv5RUNm{X z*kvTQ6RlH~&cHC)P8=U~{>0@v=3N7@?j${X;#lIyrl2qhP~2w%gJolJncw36xgLl5 zdDuYeuRV1$d*_7$@Lyrk@RW{m<5f&BGP_&3p0I`YAN&9Rh>DDyK>y@=B*aU^_~^f6 z(ZCo5CkEcN>MdcZs7EvHhen1>IwB;84gBcJ?yY-fjO4&Bt_G0yQ8g#h#himWXq9Je z$Q&j60aU1k-$ucH>_94n#-I!_yfdC;vj4e@qVcsiPQIVhn&LmNeIUJf_BB$PC38yy z{1OaHX_O-Wff)5@k3C3EkZ}oBw)v_=ZJWtHv~x%lKG~h3zOhL!Mt@KVEDWCOqZmF+ z6LWuk?Hs59V|WJu&=3#;0000p13)tX0B>bLl+(U|C_)m*l7ZOTw638`+G#`EbK6J= z_}g{7uI-<0m)zC8kbnOO#{dA$2owzHWX*tq3IL=40A^;uYJdRS-o1VQy{&D#_O)G2wnHLGk=re0T`RVdRUAvzt+E{B z=wTuv0LBmlh~OJx5Ml#j00?&D$;3(HBaF&NaxLi(e(JzH-{pk7#ZM@&^vycPWeT@R9k-Fcy$VaL zY;Y9k>IqlB=5}uRnoBFA#OlUdoq@UL1)QhJ5r3-j$#fU3jPySlmREbC~ zgr6Nvh$5E<8tTh8?YTk7nCwVi9DO1s-lgR+HfZ|gaxLQuFT^{=eNlphzQemq&)xKF z2VHidzRt&!yUpPbEq|J&$xR0?DQ>HM9Hn2L*j$7*i|gt$!}sSKZ|~C-?YYR@ch`3M zE@k>uHG820b6*)#53%(~kFH~KuoRc%(6u9*%jpsyJ{MGGp=Xt=ysl#=ByZ&~&o(g{$+uu0V&g8_2;WnoS zz80}4tNZMIx#65D+CJbtK9f})Un?VL6imo*L_R=#_Wf*S*S{m;H`)j@sOx1y64W+Z zW%cz$6-uV{X!h1R%|^d;!-^_?-+q~;_2^p|`N1JSg9;PXt04#4tCNnY3g78v~mK|qm?V)K3K2KHYXHIJ{jrRR#p=D4QXZ!8XD^J}J`G1+>l$IkT;`{uta^s&4 z@9OFJ62bskW0(G6vKIDL`SM1l0E%C0CCYZ&R4dv*1}#1sWKUE3jNJQ$;r{njnrm^L z)%YAMoJ9jw*o8tjcQ0RSKqZSw{D_j7SBbApf4!7w%@6)%murOeKexF&Z(gd3`8-E^inX zyn`0npNW#@u1z8gPT7v-+HG&{E-7gpW83g&>!6(bExj$c&ismk*gZ?;@y| zY3hwH&pop`NRBo-&ole;QVs=)EH%%glOV5%2^A_eC?Z9HRU1^!%WnIHNJgTaQ> zz=NY@iv;s=V&m`@P|MGhuCc1(Bdq%J%mQ78Vxe*@(=Uuy&b{UTbDU5i!rY<(Dse_N zDtv5b7lz9cile#H>!?dCAVX0%7$S#Fe8wJ(X2O&pV)shy+^fhK*!l=HjacY>`2dYiyGG)WO{qT@8}-$-t4g7Y$#3nK?x+8G~wVNiloLuy5bE%it|v|#!C z1N0j7n%2t&Jnuqa77Qj^Xf99oRL&ODrz9ji_9dzZN6{smLsOP3O2`+dy^&h*9bN0j za;h*2g}nEU}VkCO`8 z2kqRe+w<4J2)MDP!UcGU0rIyT`5Bf|%0~`CPb zNgUzs%m22B$75v+Ew!qGs!^K33?L|;8&NAdtd~!Q0Q0r@4NpO<-j5d#yZ zQpDvnW!28r%?LT{oiDtJtP#B|bfDrf-s8DhP52Qf)KvJ`3_FXc+NVw$Q3@z55ChEh zCG6x9v^wT6$3m$ievIAk&?dN51T;1BJ5W!r)x3!N83_cio-?brEOA+OKaP2LI0i<6 zXXRPr)ds&GSifKRnafA?c6eBFEpl?W8H6y>xB4S*DvuF{Ep*e2i6?Bu&2;OkJlv6D zLJs{0u-#{DdxY^uIR@~Y1@6dn5v++DiE@Gh{33%ON2;9phKiI~arS_T%mYYV(x*mN z3+!5)g@Rp5xSdHIv#RfPi_s|iGhr8mecC$3Zie@fl_)GAhY*x*4X9Ne%1b6bpx`sy zEYaFancsM2-dr|TsJ+w2ewXMpS>B-1gj5~_W{x6ytNel(Lh_ghmCn@?zDfHyqw^Uw zvd)fdcmZ!>c!jxRVJHIagKhI66UTra9R7#GzxE%b3HheI7*uttqngNiVdF)Z2;~GA z+agT2fJ25!2nzvEeUUFO5^U<7j4#u}Ekt~el4QYgIYr1)9d*PeiDgdlgeg_0ox0)K z4WDZyqM$;`E+PgjG|1wJgi)Gg=wxv!zr!EIF5&|aia`let7>(JFj7fC-^+hqw0xhv zOxVVQbvtj*KmOq26pp17{*V?v7p6fGUKU1WgK$&3POLwFn4fN0q28J3d8w}Gki%2( z=FU0VTuD!fh)*{TU*|rvO4y2gM;fJp#%S(Uu&V#x(R|Dkc`U<@{Qn~aeYC=)UIVYoELxy$vZPD58vmdO23SJb5b-b^zq8A zAK3^`izZyEV8@&4a7y*f$yc2qLIHwqxud2gJts}4C`^ccSN?(&|Fvm@3N$YvCfx8aX7{+YSf}HmQn7CZuN%8vPO6@h04DEBAzAZ7@!S2f*4Pf_ z74=PFpQzD;vZnGRUeF3LyNG=vgJ9adoK3{Go;c2+2kRV>1@C6ijAGCRZZ#}Co!RVp zVgi{7*LhvUC{}6hxB!TxJC_NidYdWAUPR65R-Z#$`^t`RYc)n|f zTiQx1&aT_Vmy;TA&TF=5Z9c0q*M?rJ1NFm#>lVfccm|rc{Po(@V^JRi$tWo^HCsUJPD@((rQK5QV zt!7JTyw<`KM20BuASE^igd_M%Yz+`^@KY1VDBGj2w@g@XBVi5C@yC~WCFeh61I*T* zGr3I|y42_qrVbYKMsQy@!tD!8D|9246Tm_@!gz_;NL-gM1kdKPH$q{j_WNa%kOP0e z)$au*Odl}5=QH~^BDz3T3o(#QJkxH`F(IMSl8%zCs8whys)GOa_mIli-ZYQE8*7AYe6mMW zPD{;o#NIu@(zEIabZge(s9pi36?lm^4Aq(NlT1H@03h!{o(;SSf*jE8t7IWi6O}*a z#M=k>00p-2Xa!ydo`CK1f{;JhT8!+Qah7s|%s<;htm7I(JYpwt)PiP3Aks2+3L_LR z^Mdo*5JJYnU)^e1%@z}xt+pg%|2AsK^1~2=2GD75*1iK8I~mGKKoS`T4|_I6`2+^D zz+qDaMZ^S%UK7W^KOD7Li=DK+W>6&eKJ@c!CY^U(`!OJ2wL0pZ3B-Li(z~}8uO(9r z69hPlz@w%s4a)>3;8)hQIEuPs*xDZ?qic+J6?PucfyJZ*P5JUuCG|`d3r%;y;2-rK zI~%oMGhD?I3o8?)I@6vi2V=k$#-R`xUNma`^c0B86meo`;>Al`{YAQv1ayW!Xan^X zge5qk1?saKwWUKa3Ck_=@z53jrBnn7`^kzrE<;f|(ns5~x z);j=*tpWEMfLoF65rD16>|xsZ%=`eMO?`SbbU+g}>h=qa2pD4SYb22}%F<=9-BgK9 zKepY9OnX*SFDfyNOfBcpX^4ID!U)B!TYHjmAv4W4ogn?q?Q_APgh3c~}%&>A`A2TabLl+(U|Dnb%Cl7ZM7xBG!^Yo!hC&Tk_j;BMRU zx?OwSjghWsfK*-IfQGSSy<{!zE#Y<%CDpf?(; zYoY7*-J9niWs}L`Fr^aq>qZB_H>7WI$M^_%xF+c~N26xC!smEfUMFgzmUo1-8&l4a zkZ3?fH9k`Nw%of}P~T?4Mvdeywk0p&9;wuy5s%7da!=Ud!xU7az44nViJS^qllJ9V z;dc!p6XsIx($t+gkLo>w8TFKl8u==U4dfVwgIsmW>^>cLUHXZUznt=%Y2{R&Pg-p7 z?^}MEh&G84x4aLW$&=sRikEXY7j17j>C5wfo%RNUzu`5LxA`fLnzIbwajbRs zhOrCS!+8km9^9R~x%Y&f4puU&oBrxqXVj)w?%0l@Z+gGvs~#?42@O}@_9F3+MVr0b zi*F_xDi~rbGK@@MyGY*+wWu+Jp9lNqt?G*s9RZnEp=$2O%tu~i4(m_Ts*fq$qNj0 zN8FwQFh~Yj1}+QiZhO`c%mMv{K(|IltCS)ZmXI&^o?e*`DsrO;1?H7QPb#|eqOZMA zGK>I5Yony{A2=b2-0YaLsDszC@qJ8>ZiWWCPn?16iPZOxdI4h-{6^&#n|Xf)EHI!4 zCb>l7dDoYc*93-8piv>porKXPrHDr-NRIu=xhB^Z{+9p`!dy({I%fSyjRN<7UYm=B z&b6Ri!p({IderL0FSfw9x8WD8ajU0J`)m}s1Fv3+n)6Fl5SRWNu5OyM$uzv^KZ58w?f6LE2P7Ppg~NgCxrQ#8H#64xDcx|lh>C6OCp zE5FJ3q}H)sj$hvi*|(KCjBn?Z>835HGyWwTDF`VKPI z$L5CF6zg)*+)^Y3cvBWvgy!%OL#JMDAbg?%?i?KJ#=qfBb#p-!C#=^3@gLf}=~&B> zboGO4;nFN&EaLU8>YkL00SAbFXgv?}rXCTOF@XYy3a#ME7+g|0efHI`WYVhR#1`6? z4VAvWB=>NVb-fRBp3{K0Co`xZVfSUe4avB96Y$Q|T)x<7h55#}#QxxlxO*w0D3496 z9GLUPTz(IaE(RKQ2%vytL$o?6TH#3ablgN~8N&+*DqyQ6YGjA*C9U*S93;~o^dX~0 z0m0l1JD0MPJxdsZG=gKXA6B8+qmepjvadE^5*s9JFfN^;MdTLUWuvf)}~OLc8ko=eQnH-$35y$i(Q>QM{y1Bt(e9v!7p zL7O2lr8ZOL1av)kol|tdI3nGb2A5{^cKKauD5|cQ;0}EO(NypoSmM2|5@+?uEx9AC z2I(tbSuAm@h9*wJx)0OQdoCqz@S-PO{-jUeenYqNo*<{wyQ+$)*>r)vJfN;~DhcyQPiJsM|g>OXB6`!dXs(yPXDnl9y8r zFYJ+8b4h%hDE43OKn8MM7$qvR6+kT#P|Yg)j^l1#(OXrvW$M)(MH)nFDORej zBEsWyy37S7W6GhQ6?vu8(Ygxv_n}t^-x6k1cs-AR9(^lECCXPpv|A`j62B(K*;&Re z4T4WfPL7PY(;4k{NS4U1+6ppSsEza*xSC4UPzzjygqzqU#cF0tlACsdR?!2vskjLUWR z^LSrXlxKIF6AtkTMXp>U(E3)`kzyA#EL)p*cL}=xvXJM4+H1Wu0f%@b)<`jnm z6UI&s;U);=V%?34@kR21bXRNzobUV6m%CRl&6&hWX>@)|y}B8OYhVdv69Z40PIwZ^ zJivveRx9AK8AT?}uZ~|W)}RGEp|vjKK08}KT?;~5z}W_FdIu5nkJ(8006673OvVaj#DG$l((H`r!XH4A8(bX zW}TgWOrP))^~5Cxmq!3vV@l%F0^yk}>yKU3AXHn-d?36r&RqrE3kkYjOR3j$_#~6X zSe39nFw)Mx$t}3T0+6J|^%Gt!(RsHjuMpt_i$OgvX0Vh!SY--%?hUdc+XwG`Qu_9ns59nlw_hYoqnP0R)N1jpzeR)(%x~d4@`Xg9&Uwo3b7HKa#Eapvg&H;aTq3N=E2Jpx6aC4BRv;2>)1hilbFo6P%3RZ7O900)e1uQ8* zJj(Sh6T;bz_D=hzK@k%8y-v8}Iyetr%E|D?e9@t;HbOVtzr!HK!7luYYY<8SgNZ=e zLKv-53R_S`up;tOEB(qOe%DM0fobibo@_E*2=I(w<-^5M`nV{!yw@7{+j0WMAyx+g zWQ%$(MlEj|iBDp}Gu%MrT-Gc%4o`GOPL@($5B;0mn+QLPBA_EQQ; z1Dk7wR&Q;4@46uN!3*?43tBqDM-0i(D2FE3|6`vFP=C+4zg$-CBtbC*bt_A2P_`wcz=Exl5wd*1Jpyu&0IvSo?OV~ep&)DkO3p{7jb))V#LviO4N?uR@s zUC=TGf|1RpHci13ZN*AXM1_rsE>qgb`%Jb1p~5bhL! zLlCL35ppmJ4dPP`5^^YCgSon)4EyuXRWIIO`_2H<%s$E(Xc9rhh3BK$0U&kO)zhB7 zpR5;IDfRn#{!!{8?l|>3R#7&jkdHA92IrksiR$O1bOuKRBR zAutl_Cso9KvZ;L@>J;F_trab{#cu`${(~qJR7(Ox8$=p{y!KjAo}P^$CI`W@g+B^Q zXc%A;LB@ra&@i~!wiZlfyN#cYbGG(5zZZif=*}h$h6KG)LUHFM16l*=#JGmc0dz25 z28sB9as=pw;NC(VP*x;eZqllvEIeu^Ksn^RHUGx!ElU!J2Iv1Z(c`jGp0tcDoelgL z^-FuN)`C7ahDw)xRZIjsP2f@4QOV@oUbPfv5-UoxCRNM;mL?I$hwCSzDRDhGO;;AE!W+QNkt zX)nTr+b4l7{0~p~X6IlvE@O>ApYDKGHJ!Fkp$c+uf4y(~&H^t1kzeNv>`o;jk35W{7?!XPO zoKgv${S1cmjT~G9e_~I1dngd{?ONnU)~@8K%?Mjw1YN4m&M#K?f8#2sR*3lkenz1A zp++l|QWu%bPg|xO)@gNECB))C+i*|Ta{+sP%6J~>ar^N-9*vkaHx!)lcPc0h^034B@B&X*v{>Qv^buAALBW`gNV zqvStEwrmNw!_p@)o6IsWCupf81IvObKX&*VYsN-u?B5c2NVKoSHxU?f5D)?Y001*% zKr;XU4`uk&|30crNdU?YV&mKfhKg&~4JFTIWNq+M*CD!YoASqQ)^3nW|Gme500;;G z(agYEzyX3Pkp9Y5VFC*f1pGk65G^7KmZrLsm!gX9+P6#BSKIcjBcT@BbuSx&mbP?n zUX_hDQM`>Kw`MKkdohOj002e+YGwcq*N%JJ z?QPd?c57X`wzUFTSwfnmZSSOAN3M}u-`XwN0JsYUvcjwT}n0)c4#bbLNg<11_-40la!o0AhfKC8yj2d8qWR^#RU!mqZlt9M-3 zImd$?x2bXt>;}2pYdT}ZSy+pT_DztcTBlKc&9Ue}PEU=Jz7)isTAK<4{dDIj$>vf% zjSz={M<*qT8ai=FYM)~*iba~YsIFu!-l*w2w$pO-`gFyl^6amD#U)3-SM+)lIvGH% zb(Iz-NFMD(_oP9I>5?-SFJ4M1$ysHfQ>4ix{-~gMNnb$x7W-G9z2MZ$;)eU`@4Xhn z`+hj!ak1z~AZH|O-(s6~jl0#Io<_QB8&2@=x8_0}Rh7uW-9W}^lkDXyEcM{-69;Ek zO+@c?4lhDJDC_$!{p;4JaXVS$1;=PJH=`SNp(A0NR=c9n%2O?bI@ysi_9;oS(*Qa| z!tOH3zAtr|-4x)pJH$Wh|Npn`o#M|H|0C{r(&D`i%JacNdbjoAr_0v1ERJj}wXD6} z4W=mG^ZxYhw%vIUu&nOi{pI6%f0x}R8sxQLc8+<^nyMeKgSq~2#=!$$ymkjIBO+;g z^}LPqn?BUF^Ei(jMY|KkNMqEbu-2R5$cU^jcV0Gk+}hzd#s>5aaf5N6f~;%vFz?N_ zFCL4!TTSqnVIG!RvClj1gOAwU`02(g8*DFVXI`k&>~I*_hq%JEIy>;A`R<*fcONRR zyB8$KZoLkjmnb1NU}vum0msUE>$=Bx8#2b#LBELfVZw zaoGO!$Yz?_IdZ)2@6D)>!SY{XGuS#McetjnRfp$F;k2t`+TKt7Un}n+87K-4iLx8y z1Qtq)0cf|dx@%}$!{OEWJe2uFm=*guvX;rlrY@d|-Sm)&nKXu~X2sKs6$jJw@n9(vTHkjmnm`4Z+gB&|x6{-Ww20oe!1<(s6|B?>h0iT!xcM3wo{o+>X(%J3epgTx#B zD7uhUv@0RPgCr6B%7fxFVE!1J&876D-;A0@N?e8L={b|ezQ#A1@vhDtbSX{;l(Q1`S(gp|~TGxm@0XKBPGW0vsYlaigtzFsO>$KA`%Hz6nLd`RFqI6bt_)T{8d85F%^vtS<)z0hT)?_0Yi?V&dp>rddb9g zr1mK6XY1zHkVt_-%w-Oj&E6psbi4y~-GQFHiD@_XAWfjWH#^M=8*W}=F`|gkyuv^l z7_r%wz&W2jJ~c221O<1{`nU?pi~!>yt@olfo|C9A;HK(Wk}D{79BFolIdNX!(&6ZF zUp~FT%n}&Hb@gK-Uq-ws)VJ0e46X*D=TQ?J3fGjV@_~a9PTtdMDOu7ubYR^xN16>; z7WBh13onb`&_K(L=)CyC+p5el&l=V9Tf2&JkA->>sxeGn^P?3(XDesmAczxsF9;`n z#M~if=N{{4;k;x=El}9ZCYqXjy$Blou7O0QEWdaP+KdYwxxxB!Y&NuI9BIFQ3D-ey zu=(uCwA|2kY#tlo86oXq*E()Lnb#ExI>{cSN}`yaohk&!Apv(c-D@ zBm-1l$?KjGEm7)oa-9E5&ZbCt_I^Zqp<>k)J=Eh>SzJ?MYhjL##1NvsYC)pIQjKkH z<=*Nwa~ZIqRY4XN6|lphN?C^TBg~WsrCYOUoRo0cEI1wSW0`bFqcV#wwng1L(Sj8h zC$j*mb2CRy7XD1XHlK78FP6iO#27uKYlaO>=I8dTI7n~3s!VcgTH*X^>?iJGR zJ4%CFkQkoFssaL*SE?%MDiO*zeNnSMixFb$a+T^4MCsA;9nyex=ig)dq@z@9e2DD! zAH>N$i!h?Cl9S#~m~H4m(=}%iz(Xu2)pHUXxz**d@O?6t+|bGLO{BX;BKe+=(wLO7#|3P^yLm<~Kgb zmQVVw1pM+~;f64O8BRWQF%pe^lhp!97heSE?aLbiTIMn?p1-c+*^hw|*KcPYo#*x^ z)?tB|Ki-6l153(-y(fr}7vUzUy>z1S632e|f~)4KaFtIyKhHsF2qvAxD6@F;+S(h; zqgYvEJ&})`@@+*qBkL*{H&I#NIZZox=VNmh4s+GQ3`ylnwuKiCZ@c-hgp3LLi z)~u}!zeT{`M+P&_ruKxVEs?OBsPNsV>`imX8VQ5qYZ1%|QFKe-;Z*aFVm-;Hz>fmFysdVZmtS*>D=5PW0UINOY$Ej+c?}Nga0U{XNClJ!tS00kj8Tlm`|!D}cX33$OHD zS+dC}zMB65c6>v^y^h6)kL2#h7wuzRhZ>?*M6NO4i9gWHp{?zg^DN^%>&Kt1euO-| zafCGeaInL@^7B0GG0=#O4@TE0)4C~cAv)dPxU=my=;??-5lw%tHK+J1RVZ|xkiOB9 z>l!XGLaY}%fk$DPb?G6^B9Ye{dKePrOC+6U^jhFpuZm+yHFRJSo}%rr=95II%ef+6Rv)W`^(f47MTvaoTA6iIlV** z$8Ts`dG@MAY-5R^($`VfoRAVvjMcPZ=+a*+{eb7^C#Y!p5UvTQs!6VEpb)?dfdZ@| zTBgFJ<`YqosYSnf0_Oy2Ke(#Qp~ue{^Jrq_puM01Adp^B0IdWU+>GUm757tAxbN@i9%FcEPh;*~(XvRFZ&e2TXCvP3%AmfwLflzEA}k45QyHX74GX zeANUb?z8G0M*Mvxe3Il%4wL5e_m{Jt?JKjh9RHm|RBY8me1GPa`u_hATH;vLWSd&u z)O&2OYWC(`o| zCNh-I1&58q{KcLn{wm_@Rl0^Bpkxoq-M^?pGG)bx6FB5>SZt#Con#h@S&y`PU1ex^ zyh@d|Z0q9K59&i@LL1V1jjFSV;jR1wQ}e|F>p&A6|8Xp^Q)R2f1z&Ehg*?M$9g`>f z!JL}gn29WlB^Iu*)hre8IW=y$Lx)@nCgs19uZ*t_Od1ugJ}>-Lo~4d8tM*%AB8uKP5ZBe*kshC z8Z3P1q$}$>UxnpB3ppTF!u6oBSbr{Mx~V=Da^Fkc>wJDusFe!FqEdpeo+x+=M;|J( z@MWwF0eOAJ#MU!G^$vgc4jBigk|e*Zhs*A~Ht9#{r)d`pMF; zV4-rzM`1OObXCj~Q?4R$vtLZ`et}WVv}rBr^BNRB(wNCjKt`WFM)49%_>!Xp2rNv& zy2?~0O`78v@Or9~&&(tf-gn&I+ZBP-A3Ch|W0F?TzpNTw`D}&5PtD1%L0<(;8$OO5rx?BfHQj{j_?-*5x+qE004#rz-9{Iz7Oly z+PC_4Ztd%`vbM>x_afUm+jlluE$eKoFP$TE+Z!iYe?>&35K!_43Gg4r_z?0=f(Wz^ zM}0?lDBLKV4+1;@-_O$)Zr^P_-=>JYRCIMuiEbv-6l0OlrF`(DD0-H|WOPU+yPp-0 zIzoRuj00cy_fUn(mlEK;93dP2CV!|y#%V&q(n*;Q#BE8tUI<&-D^Uk;?&>j@QBXq~ zvPqKFxqF*fORD)S@KK|=7h|bc=_W|xgvWDwm=Fx7x*v!-M^ayp%`T*3Xr^lt-!KZ` zp48^HW0yVeDH+XNs8m=;l~>Hr)TQTTQ`r04g8$X(U)KII@tMP`_`sr0DCpkcCn}qJ z|2ZK8*SoiFPgfbYelB(Q(Y?LJqtOAOJ^tFvKW8i_sH(<%+dGi?>d7t0c>r*{UkOM`y)M? z69TTSxYK&uXscdn>ZtM|qh$@M$7$j>NMx^8cenR%qm(u%FtMK{@KIuJ!amR7>eu~p zTic!PL)|`ome;S9-FH9yYl-r;QP&@_fW(IRLUk!k#drryciONkE~1H^wL1B7P#x*$ z-|D_P{nM9wlv$R3BW;6eCCy1rc>W^ZNTTWd$Csy`GUNmwZ~e7(@^w;g3Fa@FKgiC! zx%;M;7~A?fKVN@c-QSe2owpK_A-!V5J|ktrK@Pn1)mw-netyq_!5)sU}HE^^@O zfWYkeCz+HXTAZ&qXR=^#YSjYF-0#Yj&&fBInW49=-SBeUwFq28U!6%;=JlziOqJMH z`MsxF!Y{tw>_@9Dw8hQaLmMX@2s3)h48$OK)F2B?bTc|Jd4i%DPhi``UN<=<8TI({ zC!j}7&!)IpV`~*f6-gUKfQ{`FOmXI_Vf5r1WLp~ZXb@)lrfote$V^nRqENM=ky%tOyN=`sbwR|J z|BdL!Dok|a^Uyi&9lcH^>JtR4SKzJ*87En;#*Vxkk9`g!7i4|MVd_E6uM=JwKzEzN zUM}^TrYA_e_sH7L55ZUbdB$^O||&`}nj%#4Dvwe1LA0a^tCGvhI8;W=hUF)zG*=v*wk++~El ztB}qO2El)QgOdn++JxYujIF{;f`OhcK*}5v4U3t< zg;2)-yP%5@0)l?^&FsXeh38NtmzN^_yXIJ z0i3S@dG}BCzKz@H0j~~50Ce0_;UO&qfWV`>nc`ma{GX(_o9?MEWIud;4ecG{KoFrrne7<25S{Aestts8YDj=&H0iRJm15ha-F%$s zGdE98Liil09fG)-@BC=(RRNB|G6?p|)S)cuH;M~hhq(L0kk}6%Q-PJxe!x@00{22O zx)1>TAmED@_h1n#>s8sC9j^eod;RtJy52w>>jKg3ksW-++xB@VdYgzn(Jd*+HPU`yZ&Gw z*a%^INof00#7-C49>PFSVO{J$$j#}*ABDTDK`HKpn)E%ZK8+gyv9S0#l+(t^FNBOx zDR>dTB9wd zKm_xALOq-_0Re(}oqtX+n;AsLXymKWn}zy;Z{+x|D4|K@Pe{gE+psw9@#{HHd#(aj zGwH~6)k1`w4!3(WH(-^6q{J{t1d-MS`V!pCP7HaF<&nctrMQ+w9BGE?y$KshZJS$# zODmd<^MBrehCB522&pzok%TWboFgz}pcHyGq8kzHi=T-&imx>gz`TntIpX0WM&uk}1O=juOsE{|c zhXL_PvyqO=e;dew&Wd1D0}&mGPgAZ#7p*(b@*v8i(t2|{n}>{(8x z$Dr<&57hJU?t|b@i$S~bDqqWwn{2f>5FiJ`PEHI=LI5!+{52PtZ156TODtcI>d@)n z$Z{YX9f;J@(?9_?laE|7=uGJM0q=wfx+FoVm>r>fVO=21#Zpf!f}C^6A=sD)`!3BP zLh&nVFe`756Q2rk18!KHc$}!n=@|=jr6{S3dX{spa{=>KF)DG5D=1G01mXfmoyGUKw zua{`79UIDJX{E<@kLKo%Z!tp%$X+0kT5-z#_TjZ=x!jx>rG9EH=VZu7yN!stHF599 zNw7cyt7WV9Ruk~NzEtYXLU6r*jXWvN|Z>?)Iuh@+E%C#TbwkR(gQ!hmZ z+$WqQteW^#)}k~u%62Z4Tmm434D)dN+!Avk#1HRU4ng{3&fYlt3x~1LA>(M|xHYv) zqyRigapG0^^)5Q$QoUkgHU`3ht1$x!V`LIUs}<%%99G`!IjHbGxn%z^dti;69BP|T z&O6*L&)rcaP;h{xExrNVj7^N!`qhST#pTme<jQlGzrw0B9I6>2 z#^44C6>H|a zHs-Y&v;&&Ejnr7PHrrabg7z7_)*9OyOXpxgkO4tnhvKrktO!8}3)aZGd?MVCI9tR{ zx8=93mhqf9^DLLM{P3tXLksJYUj*4lU<^1?mv#GMf|sxPuTA*3)odc@ zFNTfPa~pa7w`uQ-$;mZQQ`Hz)8lWL6JHWos=?-vfhkw-CZS@D(joZUvW$prpedh zMvGRwaafCNsNy!f_%fJmjPZgOCu4*d44!9>MtlI6833A@fFd&j=4Lm0wtcQ=yJfq% zHg}5L*3az5%dWCzI~;6eom6VwD>^%V<(E|{`m zkN^Fw)L(V$=rK*;RX0Zc9kwsD!JUP=VDZ*L-CMdu`;Bk<)z>!vRh!7xPBK6qnztxo zO72VtqrSnW%?2Kul7XL&2QwXYio&^MBY*LBRJ-ggK2gJlbYy?C+_jlbIsPKRMK z>Zq=8VWPU%PHk!#FMG!6DG_GWj^bo1sVe90IPR+$*+BO4q1-07=>=uze0p)&t5CTb zjxyE>xtXWK3z4bZ{ms*zZd=!B-sXR9x?5;_*c$cFZ*>cCuv?n? zAGXa>l(e8|9A=EJj5_DMWMoW=?V?__^#LV*e9PI~9b^FERI9rS1@E(RSaPI_2@auJ z^X|<;BF9RS7R-xKG*0ii));KQGXrsS^quNLZh{~(pq7Q*Z>eP-p2eMR(+WRCh zIvZPtZCKx?y&H&Rc)E3c#@!ab!!ePkK!Io6Yu!VncH29cM`!oJx2)UNk46R$iJX4= ztFPbvr-y#(@tPu=MB;Tw>&~9y34y4HNxVuQN4JJIV*~pFQidS+@+caGS&8zyM=RgG zFMU|-H)Rp|G`>FC9uHr6)LZ_*(<}V@I}w}XGV$u_QK+5df8cUIMmEI%;MALrT^sR0#3QGu`1Qv?&cHigO|-o%I^yfn zEeJ7#Dx@R@J(;8P!pxTfo8^vXla9mb&2fU8gc&UvISKoD-PgXT%=6*;7<_Q?W9uL0 zKU7O$AEHlrnBlnGHoYmL5FVIed>E57iJtG%Gxa%+CEVe%%~l^cd-5pjekLLs|oi!TW-YqUa-;N+}^!UZ$HfIm&gq} z5oW*iW!)J7R2L<*>X)zhS-aPyBA@*_YRw1Km>v-5|D`^;~5^{kiF zSrsy_u6JmuS9jpOca&p*TfQt-SL>dYpvzW%UK`1|ddGp~9GtX}r_3t>V_b6HoqoZa)j?QFq=RA;>_nRDsivd-2^h~~Jy z3(xS`P$-7|{z!3*^d&jTfKmRP{HzSQ#n0boWx{{geeNuEaJK3*g^*)5k9{C#sN9pp z<0^MYbb6l3ToaPYWRQl*GNg+J$u_O6-w}>HP>NOk`9g9Et z!cW+y@_%}vguQl*w$~$RE~A!%p0uiH!>o9M+VP(8G^{4`{vD*5U9|xrDkSc@V z{dKntHcKwuyc@v7!AUv46*woVhA?mt?OB{&FxW#i`1U`}mVLJ@g<6+{^7xJTn!}}~ zyen-jm&2X2-@m z6ZG?&Mr)sX?d&lw=I9AAUee)a5~#-1vl-KHYf1e}s<$zd>GpK28I-XS5unjyYx?5j zpII|Wq6EELLvS;;as(1ug{!`zW$Tak`)42`2jtP*!!#`hb2;4D*qdY+@$*;o#}So% z)+OqDHp6cg$#|>#2|c;UH10hQ2*2UqLC#XrnZU;KHOg6WA^_)-9%Qv$yp9R| zy+9^$F*oiYfA(6FyQBpeTvn9ao%YdQ?#(^MeiK$72qxbNH}>dL9AE2|z!5-+QLoD@ zgqu&KEp}!?$xGW9P}32y)anE$q_orJsL4rBdueY__g)c&ukCtJ4bt}9mh3ejB1A#Z z7+!1bR*?9%X|tJ3(8eHCzk#g%tF2$gOY*$8i+=t)HmOf7Zt zfL;>g#MD-`wkNo~FKEAJnvL_y_}`5{Rp586jfkG|U zOUfsiKQEz|#0;#tHl*~~KJFeWkmD^lrjM~U^lc^o*t`C9VfR0txn(|J+1>f|6WfgN z{zI{s2H09U%~*E&paG}H$LhsZ7rw?yw%xIfgTG>|MSHH7<@0=O%#5jUXD=fyftmuV zAzI!x*wWOFdUYTDb1(U%V!HjduJTgHLwHy~O73{`IF3n(R9N)Q!KX z1CyUV_oq~Ku>{Hp(qD-E5=EEL{SDTA?@PuSec0HY#UanFP~G&l@7_|wRGHyYO)AUb(gDWblUb! z7{Rh~LCln(z6kSN=kCX8L)gNH({V}b9YJGD)gZs|ldGHMS2d9UN35M*&nVHlhyHm` znuE3{Cjpz1V&U5cIg9*1U#7e+Z0%FE}@=$~?&53o51BFGD) zSPZsnL*%jvx~+_8dTtAUhZ0}q<4|;bA(pQqMHj7=)uHO@$vsaFW6m z+4vV*9s-4vEPPKL`mF3p(IbT8COSnBi|h0{{u zpAW`AsZ>ZnPOw9wqqdVx39{@2GFyg+2`Elf*(pO@)T}l~1wT1bvfpl_50spr-PQ}$8)O3c9!sgr4vzQ z=`hdro_Mh;52L62B?BboJnF8Rq!?sW-GL_;&WpJ0U(2m~$VN91hxAaQ@#K_OMv&^j z0Kf)Zg~hi3n7kXdSYR@6+3H&>d`b{kSXD<&Ux}TQeBUc9ASxrbPnfi^exhy*bK_t0N& z)P`dQ_m;dtBg`}JGb@DK<9dW6wky?B|Dr4Yfyz}&DQC$v?b?C27U-B7w&8qNF3@!^ z%;ldbslgQ-8f*#Z<6=}Gb#-~;?!#Ad10nS= zjldj`Wh}PU!i19>vrZW2|8#6cKvd-?vpby&g}-P;WO19~S}We_vn3^GMwoA$9(SxB z^PT`6i&;EIhY~sUq3nAQah+D1f7>{mjXK)(ye9J}Fd=#Pz5F$$mwe*C_9p3&38VBq zbt4n+%Rp>K8|B9L`ZqSs1Oko*R~7h=1B56{Y9N*<-y;(+0tXo@E>L$WtxGO@>G+4Y zyo3;xjlL(xR{VjsBxcsCoKfi`I=#kao#IJgyi%$b5)P^>m(0JCm0SDUt(Kel@f^ZO z??B|5xX^A9JY3~!tdi(iM{swg#7OhSsYH~^&I0HQsCcE9B*vXDHliI(*$5b0o~#io zDom{Ars)Q-4<*jZYVZEh6c8jU%+qad14gI?v}_lMxD_Y#F-QBLs}niWO#?@d&%&Xc z#dE+fj!D5}DMAm2R0XpY_F4OsjBHTji82knEDJ~2y?xFA9FnsotQsGB@ADxZSb#Ed zEZ$yK1WHPAvk_lttsJCCm>X3(Fp{9;{f3V#7LmQ8K24KJkXxsCxC-q+CgRWvC9SfF zqqW0Gu6bL5SOOaHLbPXrSNqnu++7Y-Bij`^;+TQ@Qftw%M2$%LH%cDh97|YWF>x(( z;w0oY!^xrvEV+gU3J2VQlU1Hkbk1DsOZRjs5s9*0${dWiZ*eV}$PH-BT9r4=+_4L5 zOtAzl8^b z$#h>_@Q4tKEuWx$z+*QQR0v=3!5p_iEC-5 z`%Gp{Cm-$duI>s%sh{l69Dqk!!2?!6wbc@mw|H@}*@E-jo!zR~yT_utl`6D###de0 z6|TDRh97{fP!PBLZ#xe%@wA6snNQJVLv_{i1I+^dWQCq|b3r0YYn0Q_JW> z^KTVQp`n^1t!$xe-oK_|kpNVrsZ4??EVSsRSOU$o3y$1S^t44s0I6xN+FdCy}==cN~ZuEdj2W zsolZA1EtYEzszqDGuI^;)IXp*1=-H|f}f?+O}p9x1^^o9q%cJSH)8B%uT>o{)zKgx zoMdnXTRt|0b^sYQd7-d?l&yNFet4#^g$1na;!JA|aPGBhU?l_K2;ro0!v7M?{>B&r z1o3LYARawv8GI-Y1Q-<{RKkJRL_%9%*2HBX;|oTm_>oFw1g2Hhtvv%$QEZ@%CwgQ$ z0kl>-mwx1+FxUrlumXuh(GAeVEfgap^O66pFXOuzZ-Q+EaIL!2&TmCBRy=^^)Kx7% z?0lt79mSy}yoEio1#HO*i9)l}ou|<&8i@o2L5d<)GnvHAwJOUGFkdKY6$+e_o*LtX zPd!VMJQX0RDlE!laY082C&N*IYy`$FA`1v1Tl^7?t?v7xPlV8eZ}Y5$@D}hvY^-sM z%&%skM+2P-SdBo4AvtZJTJpm&MQ4a^9H#Hw7uB}@9Z!diK!_nZ)&F1)mw87Hm4Mm$ zx*TGQwipu603_qM!gjP-HV{l#6|x=4VoRVS1oFqAWy5dPml0m@SwIJbmyWrD4qj$R zn>WtPy*-%N;3OeAQdu2hIy{)ORih(_FULOmYV{yR$Kf)&XTdj)ZZ9D|8V)cu<}8kI zYARkwV0UTUjij)J(Sd@hhbc2Ri>SW-4Nq_hF+$p|=;L~wR&xw#H7@G9;)b~YIzuW> z;zmTvG1H!7{?ia};7Jo`Yd_N88u|B+rcmJ|ebfkXk`ZC{S8{!TNxyP8A}J+aw?zZ(PVapiDCs z`I!{;WK{>87aU{-)tvjY{1Zp2i2JKE`X?;Nr>d0liyib2w-C=%Kspv+NU3hoZc8eh>EO;+iOZ!Ot~b*Xw(I91HPPb40nnHq zfK@~=BNYVTJTvCA#g~eTma`*mw}?GIJsD$iUfSc9b$o#yX6&8 z--~wy!b~%en%WZ}q@`VLLoE$y=mHl={HY`!mpz;BdAfDKr^J1;w77a?q%@4=C6|k4 zL&&IIBC!*mqR_eM05F0UjJZWqXKFg+pJV<|Kc_I)(BMk1a5l_+iwn3MPQSF3(Z~RR z4zQI9P=cSRF?u)5x=E#t8rD^X+dtUd2h$K_;Uo@SPeulcu`632G(U+wqZF*kL*Q3e zk7CwK{O1}^s_T~MT8ZXb$b$^f@(ByN1VexPVNe9vgzV55%+m2Jr)}>>hnVz^l@k3U z7J=8=5dj!*cmfv->KZj~zNss4lSI0RicB6ep`^nV2Kuy2E8GWYA&45|cGrd`duB$r zwcrfUp%o9%(S(LvY`i=$PZy9Ph+SUh5Sxnm1hnCe3s?m}%!(w3*i3XJYT*rrP+zqC zrt!|}WH(w2Y4ZD1JLImWJg!DLPaBS88{O< zdtoFiAbcP^1zetmbuZS<U1l}RtXMq%}FeO z(*+o3=`{HEHldCVh4&_Ob;H1e=1r|Xsz`sLNV&N&DlUL9V!In#8^syC9p1bzz^~!*IFctm}SVm;z9-7jf?ryC9weF57&rmm~5(dEZ~?p zqtQ-+`65Gc3Q*)5GOaEa9p18e32gwb?Fwo*_XyZZ)HiMWUT@cijfX~ys0ml!HfFop z97+t@a3YPWmlo7h*+UwzLC{4St9o&%7Fp6;w9fsb^bzmBt8z0-n!T?{-%Iv& z%^l8A)1};xdW5-VeKw#k9WuNx@&ktk2JmZv*{>d&X1RiY@PmPAOf4zm2ESRBE9`w~ ze{R+@e_Woj|Hn?NUV0tpfmtuP$lXQdDfpIpoRm1a1wUUdNX`}WZFx{VUwW*{Ts!{9 z_OXu>)&E~;7WK4?uz#wLUeR&>#sbH@STPs003qHYDNH{+pOK3-Q3;97q_un3%AgMfFxU5|E>aPB_T(0LJ6bGxKV!% zj*yx(IBARg{3NGIPvEEIPwuAULy{?NUFQom&|{^OM!c3y(5eynU!g?IFWHGrJT~`! zT6H~ZZddEHx~^~NjC-FQ^<=E&CWHD+Q5HoHSd(!`g1^JfB0>fVb=NX6s2k|RPZ#<$n_lx$5hQ5$hrA?IcD&lK$IIz9?vRhPy}JEtBzD1gL(-PNGj49~ zz9DlD(u5_o%B&hy7MNT#Gf->zhMD~PWC65v!ASuR5E{TVrEOu zy~L= zKKD+u>hqsn#=PHQ-%O96qFy>$?4J8PmR-}x(xbcIH&OkIPhA3>{dFqyrA6M$skUDI zkUhXEucB>}_x6AKzFQ&?A|4T|Y@||%i_EA?TloB@=t|MZ3cH={d?NL_{|&Akpy{WC zks~A4S5d8LwUtKRGg&8c;z7C8pVw+JMGe&86XSJiTy#N0Xh?*N;thp^HDLWD?IikM9g{kxY$2ud!N=e1hUgo7>5B+xdQD?)D~>Lq^{_^RS2oQx`_A8B=op`ByYagMjG!-4Yh zP3uXRq*Rs6Q>PD(49rIIVD#RJD4cEuxn#9@5;c!2JWO6_Mq&}ip)bQD^d->4AV0j=a#W*_OAE|qkF6iYWdVc?g0R?R zu18C~6fV!2E4(sI{dxg}0+d;s)sJCu3JNVtTP0{2F(j$Z98;-t<3u0Fz=~LK zh}qz03rf3{pI2&0lMV+O?R?k!zS&#V9!$LC4|dg~P(7(fA1ym1Pc#1k1gv&1nvoLB zd4X$MaL)v_jR(6-#mo?;@A^Ud-*v>hq6{G_=k?l@{L7`|L-SQF+$5bB3F>5pi1qaR z;_tFcuzCU$l_itGtAZX1#exNrF~kN$Yyu?1C`?RQyF6B|=&d8?CK>_Udh+B9R!&zi7eU+evDnf$MG zDo0#!o=gWviIaf(dwerwh;49m2udE76BvMkYG@4H>#fL{jPbPzV1-R^;iRwJl56Bu zRC5fbGhK?ywp01Y2tAV?Tj&JbzP?69j+0F&Rs)iO4)52BVO-MAJ`{A`&!fqfVD$)0 zweo#36I^w4CbJu79VA>vE@XTrT2)=KY0fvQ>$DvynpVe_mJ+!h?H5ZMK+UQ78eL%yL4}4#A#5+sn{xt4Q(!wrrxK{Dp?;xX-S!wKGvw#4%K_#F!#JDXgtL&}1@SWwr> zdtRu;P9&up7@k^lyr!CT$e(0om6iC<4zefB^3bx(b+xe8U=y45PsD!NA9FdP-Raqp zhGmU=??^n0k0hMivH5YFz8(kOnYJ>G|4!}JFUo-xE&N5Tc!Xi1U_}cx0S)z?3;h)- zGAr-#6Pu-Wr8N^-bHPPiMBYe2SYf}<_e$jvvE_M-lgUH{?xypkHOx5#Fo@2AhoA*A z>d}U$v*xRf_a_){HAAc4>M)!!9h|W~L|n?ZQh9(3XNi=*;PN>cx$P9Ty?lX3eMfJ5 zjz3a{0F)JLTcUzl+NoAm-mkbB9`mk-h-vXg-6TeJ;<62OTt4Ju zyH_+~{N>~pe9M_{ZtQUlHm7_Z`dX>ek!iS;2->cDT^yNq<^qWoz5CK9QJeo;DrJua zgN^008NFVQy--xx)|pSKG_56#epj`w_`Vu2axZ<5d4Xma+68pL7dHRL>CXMRpLgV7DbuZ#xx zj0-9HdxPJhs4XFd8wN1MN-{46OSBPsu2J)6q@A6lzo1xu6eH;Uz!ks~MDQ-P7>)_oFn#IX2ga$XIT=KwxGy=<T%tZ=!M*%ubRf)yXaF=onV@)k&MXfo4Cady!P_5q5wBh|#4Xv}zJcKQ z_+V;Xw#MTqA@>>Ay0Ab=4)&{245;E29EtmZ^!oh9 zR-|Gt^nK`QP5o#zL0upbG=Krbou(rIf(rc95xY!4^1~7o&cf|oW+3>+bOa@nnc5l0 zMtA?|e-B1o=FS9%Lp+dA=-q^UfMunVibai z*1*!FpxV{s&T4z#-vnoZ+k`&inyh=c9Ni3pBx^Jm$h^Q!t>zlu9gTJP1Qy=6&1~|x?;^Rc$vDC5ntv8;KvVMDe8 zQ$$d`v(GEFoXG}Ykwfn6B&T$VN(0slGZ}AvOnY18(@*43{q4+_2&A|iqx)B7xgm2{ zD(Y45;K!m(Qo9t|a)Id+Yi>qY8msZT*-8ovx;pC5jKoF>dIbb5MyRE$;7Fx@o9afIw8h&>k_;4ozdbod3bH$IpT18+;bUejt_LjgjigACq_ zL>SU_>}3p8KvM+BAH33H|L*Gmoflc+&$BOP#S$h9gyh}FJHxLwgn<<@N4DPY|TEt*I80hTv|2sQau)9$D;j9 zkam5bx#Ws9-@t{!FE_cDTxbR}7w>Ri-x_YzR@S;md0DAG>Vx-?4H+>f2|zydR$d>; z=0H8=?$X`TetRne1yb#>9I#~VOkKW1K!R>YP;Ib2uhar26!~_BHiXWzCoQ1d0bk)v}w*eqxel39@9#RF~j_V`jY=yna+`7a&Av+GjaE?&tB0 zUml^Mks%J6^?E)83=_rrXgn!xQ8OOeZan{4oZjcG_yR9}+&t9iA|1@!6 zK@o)5J)o#$q@|NNGD>-^)Vsw<&zMWJzftF1{-)wj%$a{@JslxEC$XJedI$wa(Snsn zO))ssk|xsTkCda|^6p|GR%tV`8I>rSpLT38sr8KAs+bs@M zxfo2slg9#!+5VmE8_Nb*IK?Hkatenuwxf5Umx&;W6v?hm@@sfNc%%8ou0EMX%A zd&_QYmB@d^jaxR0U<9@K8yX{%$F7LUCWPh2l$H>=6;t`Gh)Pa+Vi}z&vTm%be**VN8#3I~bMIk-Ju_+o*flYEfNY0bA z0GkTSS%|u!cjwIOG)R2n3aIKgk4|%yUE()|3VpLPO5T4wVQQZ5@fO2lQq5hJKd?$#)Q3^x?TABzjCJKW z)4|{sFy^zH6el+czGY$lu;-qSkmu<}n7vT7hdlRAq|1}RUh?^k>jJK7JGWX*WI{f4=S*TU{+^US9O?b8WPPS-t17DY~U8uBs6ClA3| zHUSfUJQD;E&`(c-hh@$y$|oSHIB5GyzaBJe$LqGfASi*;=`pd2aOG*)fDmncknx7g zS^APF*~0s?grB5TJE5wQsm+C`hF?VdW8AEY-(4g>>;LyYH&Qv6wg1~2^btsiy0Ng0 zyTg*U=;80c*BMuyD%b@%7)VKO!-sOhTH?*gpV zmAcOKJn#FvZP{b)diR0M(2tkutUq#O=Fs0y&AeB>4_U`Ov^WXx-NqGvJ6A`9;=jUH zy8f6C(w0$MkA#!BJk^ve^3T3+6MyXp$h}JlS23=wvYn=yAHLWB+)>_*&-jq+Dom#0EsMLF}Uk*m;JpFpt$6+8HMk_pGd^udv9OAO(d* z2aGxrzETL6j}V-~uqbl%Q$Dz?sJC8Qh~->|3D8OqI46rr6-%~})`4Z)2YF`7nbK8oO@q*%(m8=YD-HPR&!>TdGY zj~{0M5U#2ZqmdS1rxmt%a7VSsVeqQ8yonD*F)dlyEMcVIVYQ0qZY^6sHy@M2bc)L~ zxF@W-q*$)?3PoKg>YKyMSVb*UrpEG3J9wV3K>-J)Mrs0BN!b{#04%)7E9Py{$RfIf z=r4^5w5u@pPpV)-XBEroh5{+OL=&*{cfOHO*KSZpJHLsZ(?+*~kC}#VVHtUB${Tw# zjdz})Et*A9*o2oG#>?q0gpW|^>5@%bAHnKBOk>%_9evWn2G+V!Hj8kvcNy} zF-K~HNjk}LjCWEC>~#nUvTq2uyW$-l4q+_N2v_cYC+LQ%!nRO?bRN)#l|t$y+fpTr zD;r0}^na90WgT0{vp|8ZqvP}Vx*Vn8Xbe54}Kbd7`{Q9 z;=EAHRdb|`;;TSTzS|*eqFVVzK|(0IU}C{&L+;hNz!FJIBzieLS}JLUFZBp)=NZsi zQBf5A1TLrNBN0rR&ln{@t6d|-z9{r+vkQOh2|cMS3%5}PoCW<~a0m@AE1S0?C1j)) zGJz1-ZLs)@)}@8{cAj>CE3lkB_Bf=QaFRDF6TY=K!|DQHc-1)*@30y`-85<1jV52= z$i*tFRGQCb`%lQKGA!&$x>p;ew_0T_sC-VwC8FxvkPH zaQ-4v>BUVYh)psrE0S-_`l~CaC%w--kVxc2Dl z&c~aMQ3h2peXC&<>D*g_650h(>M(HUO5$!>IKEXkS97V)oC}f-_rl`mV2_}PIXO~U z5SP7Jaa@JJe@qmN90HPC<4GcDVz9XDAv#jhZS4_%W0DjL!--V>kj|AO*dvtdy&ib( z=>_lGs%Tx_+_bYu#Y;?H+W4WS+`9Tq$v%JJw2n{?4n|6ZO2=M-0E&Qos&%C@2*~b) z?q+(XO!D{$L|_FCCVr1z4X8q;#()G{wG(?U;;^h!^V;rW27mF*1Rk2*>s@#1h0+)J z5JKD$+4cfuHt5KNZ>UhCMUAICzVIRA5&-v3l1pf^;@K6HOXWbH`>xbrJrAPO zwA;70KnodsYG>5_ZSfL>V7BC52KHaoQKF0#`|NCU0S?xgRyv5{T;~?y3dtDb;E}|7 z22p~P-ubd;5G9avX-)gurF7ZAds(kW;SqLZbSkm069yk+O4%~;MbI`b=@Ai1==rnR zLiF?u%HRM%{s>H?7s26R{n(f?0b}nA;tinFoh(S<@UAj3vO(f)+&yO9ktl;*AlV-9 z9h)+E$eqR;8KN2B%{whyv^$9+tPP+K`^;_46@c1rLb(92&GjX0m{{U4#NhhCm(e3K zh~^J4)(OOb1h$SRwqLv^S$?zYOqr$YCAOGc3+LTAOgI*ry=9m=`6Jp~#wch^d+(Iq zY)q>w&53jEMY>K+|E*9$4KDmPHk!{&n=)?DW-eK3a2dAbv?}3!X9G&2t(f~*>$!oXlsK88ZzjP!ww6(qA+$YIC6HxHI}BLc1JX%Fku5hH#eP%CZ6She9f|( z_1jk*ovXBl$S?A@7U+x4>L#yiDMB~nF+wAJs1#Osu4 zFS%l=CEP|CE-aySPGGL^U!kKnVUO+YUp(nJ!b516bJ=Vci>p@aKIk=QvuH?=lFhQF zWI39@jAdWIgi6|P@~33vuG3W-3FyHEA(IC|)-7v<^ZP?2N;#A zlK{$lPKEbGR1Zb6RcR8WrbAN?lm2&dX$35+vbWCMoU~uZTaNqg5?%F!?1+f4i?W7J z)pb+>1G6s<)dVUO*~q!j*~KCXSR%M6yUHhYo7IBURlzLh6nJp(Jn{uBFLlBDk1OAP zk7EQ}xD(>6x+F%~D?(QV2dy4+h6mLxTS-@RfUrnNI{;?@RK>5SviCtcf6Tk#>g>>^6P6HD@0se@a_s$Xc?|fSx z%MJ%vzcjdg9d3-G>o&mw;DZI)E!qN$O`4i>f&yv=s%dEMfMoMX2WV)JK&=Uhr5El& z*0Zdxf_bNN+&hz}0J=5tCfkB?9W;F5WKKXpS|Qr2`y+;*xey85NG)}v6yDsxn;n7R zr}vdA$D1oOrIX~sm*3O+{Rz$^+XgerqxMcZvbjHO92AWL65R#F_KW*O>srqBzUjT} zE$Po|`FeJ?rOWnrHu(H!jHw?D$r_)c4O)j8R08JbTQM1~#u2jxDt~0vAVJ4{WRSq? z7GiK^e3$h%XPAwq@SwkM24hH2yiTCG8a$hpax}B39Urt>-X-ABd~}X#tKHzVDyNOr z%*9NeR1i0kb*QU`(9Z#$u=jjEgp{DJ5Kn%72rLKYh7bW9&!jb;A9$jP$=?&d`5x7u zptJJ^o#d{{6GHyp-j8+5f560uv=p`xFDDA=M09FYCsmQOBd`uQoimUs1`O-Af1SZd z)0*{7s}!3YMATVRJ)HCQ9zh9h6%TF%bAYByjR>I?B$c(DfVrAyJ?97pzi^$s9F@J4 z^U;oHm7uE7O?SOdmB!vR1Qv>*5h`A%7DmoddUVgk62>S$&bdN!L)7*i%eI3U1!#MB zi_y5CuzAZxNPWb%bJ@Rn0q3Wbf;LuiKeyW-((R+b{sMndj~d;+2o*t{|{X~?bS`?f)aOulCH6fWe(Ju;Lb6S!N^YzF%9b=cn`#7 z?1+@T0|`__KR=*)lF}!Jh!2?qHE|Uxaylo`G3tP@p%b5=&OW}f=obSC)G1u_gkN_N zu{y!P80R1{;zD#1$OVGM&kNCIHWNa|kZ6;&kEp!qGp|innzB|)Gibwd>@)pv{~sF| z6u+5l!?1jBVw<(!w_8{e_O}LOL?dh4p)KJb**{<&JV$s808fCeha2HC$jSj@{eDld zKUaujtlg1Jt@W>zF45lCKx<^Qo365m9xW*ftt~TydpZg*!MhSn9pxxxYS+6kgg^GO zPyKInf0lA^{?{R?^FilY;TrW&;s<35vPyLAC6Yqo_^lhH{5@`l|Ddgc(7gvJw2ud> z&I&1SnLP0Y6+0xNCPg=?)bE!KY^KWp7ymjIP?4(+P`+*+4avgzYBpb}T>vjth%0`s z+Td|e-4$0W`tIT7^_vJ1l!U4X%Isc}j`#L-SgQ1V_il9^V|m{2?l^KnC$qM%00Vok z_1Am&`LaV~LTC>8vFp(RtWOvbo;Mn0%#v{;j0CxXpz(8xFq`~=gbB0$^?@Re+2))| zA%Fff6V=JZ`uj92>Z8OE8bPR9cOJ2$&2@9b3cZd-H0L%c<%mIM!UG{D5?(1&7b!*$Yt}V+F zdSy%Pwz_okA1q19mQiDx%Mcp_!iYmd5`X{^2;fCe5+K5HUjKefumEYN{2IuJWL>7G zn{J$+xk|jYUEz(S^1Mbq7(kat?>w*b(YnrkU8C$o5mVHzpiwCG@ufyGrHN#XMsi~v z`Zx}W*~TVnioF_JcP&CU@*OF=E4`Me4?g=`*DB(xL+`6z!=oV|`PM1Xd5GAXI@0ld zm37bcy*j%Tmdx&Nj_%1pr}r6&VSUu+qs&`n{tvYyN$TZ?bv8(}+Y(p0PSCcC5GL$nU4J`bZT3atk4yX^|E**&9vMF;^t!Qccxl~1W9op*9T&)5 z4`*8%w3`pT(BIb&VLtIchiuUOL$@`%b@nIj=Y8KVC_Ce(b$)j@(?LnZUmABy6nkpE zA6;AM*y7ZnH_)NFA?MKj`K%N9qi!5^(%BesbD)~t*0<@6EIbcS|8aA`sPK;HIn&p} zO)Y$9H1GP@)YR*qx1Q)->59Z-|3psr{Lw|ed_9lcp$#vtu|OmGf3AVlY5ek1fvNuE z)01${QyjYw?{3##yZDt^Hr{0s7y3#^RqAoXYFmPCo3q;rR8m*rjisi}yvQy-_ClBF z>z`d#-`|PeJQ|aNURr93+@g05t77fT6nE|>PdQ>m-O--F1&n*Qw5 zDoO~SBX%2akHYf}spBN?5IlX7s(gUhoET!8E>sy43Fq05zi^QGzn~&85r@Ay z+1@4=9oclCrwEW(u=>Qg)SuUFF@k25VG9nNpf5k7=;W@3XS=;?I`PF<#0bqI1mqy# zta7eNSh}xv%!u+beLlJlh}sHB9&s%T!WgUAH!+64aTp6Kwy*61KFZoPFLdE?T~7xQ zlo#U)Q?$FO_`V?l!llT`gS@essy`AnBJBO{+kSA}UrW?17IjMhyOP7)hshs2Wqu0~r_+fnW}TlB#BenuZ`K%7K^O zQK%IIF=?_Kr0VbT)L;H8uzpWr;t^Ri1o*ozCS>H{fLx;iObdLU7#&&9Yqp?)vj#Lf zhZCT`JcqTPes$6Ja)=97?TTI0`!l?KDtOIp@i^Af1Ksw0Dzd{@uo^XH!*#w=QqOGJUUT za2}i2lcVjP!!lBwVJL=aS!uZ>)j-Fo>3Ilg)j!?Ka7+Zm0Mt__Cn&-;^zVgG5>SHH$m)7sLwK!xg`7@k>o(~XX>E?E7KNs>sj)pT!iJP7bK8hnxa>G{WkELSoK1~=wgpV<+ox0|1e9W`R&elGLPaTF$cCKZ#>Q6d zF;%G^);>mpKU9VE&ei#MIU1%tHe3#K*^D)nlpUZ|g5yWbx*EY*Glg{Ptiir~+*Eqc zxc^Z{AU8_?CBQMYyf1O&*j#ZA?_YC9YW_7>J>B`(HvQa)m@#KcY6uV#;n-rUE%+X3(o!O;i#jDc_fk#^nzBMWA_t|i|f5X30V`Y7_D zfEPxsnfBTS$NMj@>_v)HuK+Msj`50U+Npiz857(f9* zidR7iSW@VjII6Jl+sw%p#C#yat%G5rIpHlEh|%wNpO_(`mj{S+?j8WmeS1f~6Hm*W z@x5pchZKlOY`qjMZ>mNdCE?H@M@HBs=IrHh4iwg1y$+*rZ9m=lxSk%x{r`t^xhl0@ZgzRi|!)#3Jl*C=;T2}iu`OIljYW8gg9z>|N0|F4Hg5i2Vl2d`-Lh`DA<@CxCmT5d8|UVB5Rx?$D!`QN}zu3To| z6DPS^t0ZW=D&3k=pN7o-?1ZSpBQeK4LmjcQ13>Zu{^!Fxeeqr_2}X+i*d~NC$1BA{ z7suuoGd+y@Yo;rr*4vJQ`=5ybgsU4F3oQv@uPs1lK6l-^TWWP{N6u+Ofx~>STHr)z|w%6vgn7B5ojCW-`grMROrt}DbQy@Hn zBNbzVm3e&@@mSUwCXl(97-&|#1N{SC=5t?~VhDN}hnhWBve3x<*EA|eQpK)?D7WEp zMKg-4yhAz9=<~JAq?owal^8BI%x&!9*$~8P;$H*B=OCGU_mSN=xD<`Gf^%1hgIM7g z_+r0Dwoc(AQfh zA(+grT_A#GE%yeb7U;HY8jMuGnc2dKi_T}}Ne65IwIM=Rn7(G3#Sru7jw-{rz(tY4 zs?uu*H{(UtfJ3^&B7eK9n?_cIrb8hMPv*tv*rW)R6^nzMW8&)p4`q%q-uEllN*m2k z3~gY@jLAW)mkgr;1t~XWy_24N>XJn7?Q?4@cJr!fT+RtmYkPEXs{k^ue#^ov$u9R`X5__x|Nu)u<(XP}mAN}tXkBvO!$4GU@=0(<^AhOo_*n0S`grz3=U#*q9Hs|I>BX7;j zT9DmcU(ndBZ_Iisae#loH!_tTJEPDeYoTs+nd4Qu}gV+t^ZbC47`p#C)!ewZVoF2dN0a^7M zS$qp9Q6Ed|tk_zrQfAdWn3N7Nc71U(50!et<|dtV^B}cY%D`S~V)QsGpjd{vWp3W1 zVn|{Ov%fBc^~tVCC6qGe4EHaQML8mAehaq=E)<_eT#N0Kv7DC3{b zoBh0;TW=hEdRMqRU&k&n`Jatc!!kk2=A-c}f~)#j~tt6PTGiNxv`f>I%0K4+w z7_28mWs!uLd5K<1hvY2A3N!jR0+I~{2ItL35u?FO5$}Y| z9K{S6$mdfzhtrXp_0-czY%aH55vUq-l$o*b@0()={h1&4ksX0ZDvp&(vIrn1`Ak?B6*Z@i7+vb%%iH(QM!b& ziqeR#^;hwD(UfhNNE%!$FSD&J%u#+h(2*5HAt4dSqN1pZRHM|4?p2f&?5g+?qasp! zMm?~I%J|#K&e(8h;LX`u@3a!;$^_#*J9$Ti^$Mh1VV!@#KfyPc(eM$oE-(>y&ToqI z_zj=SZfBgzMdUigcd9|{qLk2du{WJz!zmUi-NND|yNBYzn&Hk`n9|#+Ocl^@fJn?D zp>=+52-7Hl_q|N_RHPJQz?Vtys)#Q48jBx#)EJF0kBiwz7KqLm@gyjcGbTXe3>b|w zkLeEQoC(E6LbxD_$|4Cao#1L2KoVi2j7OmO~553Nwr-lIunpJ^Kfa;fYXK#}GAC1hX>qfuiF9$=QIT@k|jfot@53vC){a ziR;ZnBw+D@bERCv*djXii2nzoXJ;hc#*5zi0hvO!dbzqr zGHZ2&K|<|5Q^}&`q6I2680MjHfP@f=GHM_&@k8JQTt~F~jpQq~LYth6E`X;rK&t+t zc^@{ZQ-wmu@IxG|4zyIWKKAJF58epfu7gt(x(oVNusj&+;IUJ@fdq zhx82C$VkpKky>cgo@Gn=kod?)r$>XXBU!94gP)At9%E}p?%UVetabapoMyLgE>&yW?Y$+& z+U@tZ)!lgCT+&TVN51%t7QgYr7ksr@e7NF@voGV3iN(3Oz$ByuFNlx;1OR{t0MX0< zoF5e3@9y{S`?tHheg3w+?rpo)bz9=sHQR1AYu46n%WI1!{aP=Pk`zS*1_T5o5CA4H zh(}aKz>)Cq5r_{lo-iQb3HTr<1W1%rKt70n5rQEEp0!Dary(&1w6snIb@mnxG7MhMjQI}2!#OTVu`taw z)LUbSUxRqm@VI+toO#EF0NF&ZjoX}a4S+QL{oCc76b$B%Ecc7YgP-31L|pd=6M;|; zf!*&Fk6)atGvaOB5P{mO^g)gTjX>Xq$+?3_lu@U0nqY``5zq#Y(k<-q5Mc=n6GucI zLX03J`Px@Q+$F@Liy~4LI`g@GlINs@G)bTv3qw_)0wcdWIvCP_lbdWGGXN0a<;uzy zcdsk~av;q{$~=U)AvRhDs%Ipbs=`td8AJO~7|0onMFwu!{o^=wKo|&Bks(#X07s}e zMMk(&<&Za29gM!0Gb@9rBvYMOlh2K%HuaJa?{ma4NUjo=nNULmmo&_p^NeA>-kvfT z85uD}$c2?h7~g*ZOelw_hKH)UlsYdO&&^BcxFNhLs~3$))r^(ECT_3Ik;bquX#e#h z5YZXc;nY;xy@<(kBr-^162nMV$Tq=M|5in*2a(0Q!;l;R7{U3GTv(2X7)R(Y)se3q zxxc(LhY5oe9*;W^u?g{QW3MgJ95M}*ZzrUi)6QW>Gi32zD+9CzVmp%jXdy8+$&5Qp zn*-1g-Yv`E(B-(xDgs(@8;@@Hh|y(oj9-Ww7bt754la!|#3Pi7{Bll7hkaL@2F7Hl z#3AVp`}`oPVlrm>^o}GsFJebrDqYYfE0`p6{JUG<`W|JKP9jSznckV=Qg{RGyK)AY z1Z9UuSjg2IsQl`BM)MJJLpN_wys!0y1x} zoAtCBjMmi+P^N~JN6oRsV`fH5FE+@FVn{DNHz{GG$w_n#s;-gMSPh-iKUB}`=VId? z8YVLJ-PU>jw8mH3v3(Yj8huh*rosXQ1{*U>N)g+joR&{)+(#0bjBn@Vru*H zxXG;);5xlGv>utc!E>a5o5tUfgKrmoD^11TxnI&nah@lRDImyO-rlBO%mfyOK;G&)RDFQDT^6&KW2P!(E13}6^q)1|6E0yA zZ~*5}7o&-a;(~wWRP!`!y^9UD7|M zQ+0$W9;4IC1kDkl9RnQ@ zE_m>mt(5>4KJ;?Z$e(kN-I?KGG09Zh6hZnc9j%_}Q(@yR01u2qbSzg>ndIbRo74Eq zs3zg~{)*4D?)=(b($W6eE#DM3z)CVm0$Nsy*Y%Vc9knZ&ofwI#Y9zTnSfh$XrGxT8IheD3&zras_TN^%VjudF!Yb*#V2|2X$fKdO7Dpw!23wd+4Q zoUKpG{#Q4xs%Gs4>&Mkyu=-%uz81)+%E!CP!s5@_g>2YO93ef{h5)|c6&CIR&V+Si zb1Nc|y=_ilt!FE`pJ*=QVoRFBd0jwp`jcaRyUIa!RN~_oiD$lNlkOUT!rtj;&6mqw zSCX}L>APqe;(3BOg$VCvZHuquX=#o`wOl?u+GuP`^QK$vkGK9Ijp6GmGb7?Et*eI3 zVEssKorft|(!FaJ3(!|xLX-XQp4hF+XavFUo0Q#Z4%sb>aZ%Qa;I`MOr0+*`+*_Ay zK34ShNFKP$DT=|2Y4A=ZXK_X=%2gCq2e5R-8o?AKF!~ZcqqBfp98oN8tJ?F#r5uR1 zkN~tjv%9aBdU4t~bEWew|5AD)Spr;LVDP^BjLgC;eZH#` zRC1m|@NRQN8h#y!Rpw#{)Z~m|ucMT}^kZzva-e=^Pi-VNC&}Ud;r!-1Cf?yXi?z6G z-`1m}jx5v@G_>wTCQL9H4N-g`pNv_ICzY6debm^Y3~sOW$s=AX5rjVSnKr4F%=-Qm z*z2U$oot_*G$uR;4rzbj9_bU86!q<-VXj%e^3UfyZtdao6Go(!FATWJbPl3PRR$&P z6cx3EB)}Vm?JC%N$Z-xS?;87hb%KgIzmFF-#;cb&&t%$rv0}i21PdOw7cK@P(=Yt_ z+ulCjAblHDE4k#qq30jIR5$G^_2g6qHt~I{qTA95m7LgA0!eT{z#6?h%U+ja-GSSH zb!z0&>`Q&UP;~J7^H!eg%9Qc&i-8G|AQ`!Z@T!>pSgy;AocAlmNZ~SKsHG#tqwSsi z`qkxD&7)8t{;=KB%l@EUU$0q`^F+40Uak=L>A6zV@Km#~XUqkt&Co3^wi9IyRH#86XT1O&WsA6;Afx2IIi*guv}$?Db_ zqTSR!2VWeOb?_qZsWcKC%q9~VO!Q0Bnd9al4ocNe3&q_d%?#G-DW+rYkrW0@{!x!{ zP*d2_g>(IZK_E&AOs)ja2rP`!#i7dl!!8~|&O?>n%NwR+rxX92qTzJbhEbJO z)n(NABp|1}&X?=gPDSJeUg242S?P>z5l8d>dTKu->?02MJIv<`^`AZBb#yD0YEM(0 zkxm^B!+vugSg_Rl-(8B;Y!j}B-{J`d~+3p74 z6xj`*5vw-*^5>U#IOe3@KK=q=?G1Cco|~X`%Ac+Yu>`erAL|-j^;1#n^$s0A@BtuO1a)j3fGslzhlV*4PNXDRXs7XlL}K{I*_;$$)KvOwp^wVyooN9{Fb4ZUhA%iD{0 z%z;xx$ErsW@rcu`XWNayWO8hLifl@)C=te|0YHUb-52ORO;IRShlUgseEAXkuWb-d zr>OXwnNxV)VGM4>h|-_d#fwwvcQ42Rmppd+y%lP0!}|=AE-}6#v!(ARzMb}^Dtb3~ zUXzCy_&)=)q6t+7E%DrDVl+`0)F6R|hcr<<-6>J{(0t-Wu`ab)q?s(d=Qgamgwa!d z$-vfzaf))8+cjBY?HIpCrsPPv0PG8+0wR)QKC>hfQm9~fDxFd++^vG-gbmr~gVLIS z%Eb8rfvx~}l7l8BmE6S~1RlFUff%%?Vn=H(f6SqJ9ClPZ$1^GbHycSeq@~U}Zn&5m z6IkS<@9v;Q)3M2p9Gi*%b&fVJ$#zWyM=*xt^L?p?O*hZ+boKRoi+VCtj zYBhdIM!*k1srZVyv@6p1_frCJ?S|&bf#r(}^K0n>-GcN#^lu1v7zWPRBvnn2K8XoxNgbpXY#MXcR5!KgzM%Yw= zwU*DB=?YtH%wy#P5r2?Cd2*Cw!-`<*udLuE1v8X^Yk${9?Wfnfk70PPE{;}^Jc~aa zq3P{KoF=}*eX~pV5}LPS3%W#KK8El8B-oPwDBm#S8|Ac6S5u(5#r6!gW8WG|=T*tA3zNLJN zs%yG?5fKYk|GJnVY-y9nF&*n+BeQbXw;*S=uc?$eG zI^zH2qNYn#TCx?#UZ~N><=7Nkr!B=4+?Mnx7{FRi!4zB&+$A2!<9($S74jQ&%Kun- z_n9$-JFX)r`HF|E|D6AFbhh z#LSxSU$my=wf}gOEuWl_qnRfu{4U@6QN>xSzk98yxQd=Ntr1E6R~{ugqpK~6dp;Ib zkY}{v4P`Fa%)Jx9+e)YTCjV`b!y773d%AuBnr9E~yp{0eVUOfs5_`%T7@VGS3)A3`AD7&7JzkG~ z>ApK&Q=3f-4I{21sy?H#6^?^kj_|ccwE2mBM&$3z zC;(WuMJMcG%M>YdQEDT$8PnoALu>_(>==mW%gDWaK1@nz>ljnR@Bl0H4J9)(&j*FYn9j;I2 z1F)-b%Aq3SW0&m|>JhigV(Qn74G!{LV8NbAc=?Wv&{!F@zgW>+vL+#J-^n-Z0@ ziD3|q=w4n&Xm}4cmvih?skp`l!K0*N%FLWi(30V;3{J>cK~Bz-45n$_e$!M6dve0l zY(>6-u`JvU89@cM&khfh#Q1~lqUN{)^(}PH*o5`;sf-a+b~_7%$;x=I8No|hco3}= z(pnFV5sa0j!y03>GjJpysM%^MaQZqY55sAxZ#rwf1QE0`*&&6BPKOEVRt*wSXpSx&B${oO=>OJLG&nyq`;E*RslV$qj06_Ag&Ynv`QYejFJkPjJbUg#1wUv%Bf(?JpML zvk>|lxfrP$s`HYi@^TTNy=#A4R}<dCE!TZ`Dm(8*6k#MCyC zTMd+`>7(R&kz+yyK3!1J>G{eiCW8w3v1<(v=yqFDJDBJ~4v4onxrfz@LSOJ61Py&5 zaF{-3lCreW%YL43)GK-nm&@K_$;*8Bz*V59rJdLa=i)3a!2|MrdM@gIaFo1<7;Y}R z*=K`Io>>~l11{p^*-(RK6y=#}%v0Z3{k#MI4wjg&JNL@N@F#2JZt+xTq~NFS-1db; z0n#~gZ}n{0XL!pdF}xj=ABM8YTrGAk77r;|skUgQ5`qfCG;%wJhG7!B^uoPy{@?%7 zWMHn^Ncp;;2UbG4)LZ2+Vev;l)&5e`)fh4igq>YKx)udYzIx0oroI}ASC^pE# z946vr*cGHQM_-@aQypa?lE+G zuu+)q8exE+3!hITey`^YAHr<@OW_FH7sdn{{7k@8jCSMk3TV79!xXD=s9dC(;(A?xBBYXJ~IG!K#0F? zdWQr*6iW80DY*rg^w#S&VDkw7o02MiE+M>G}P zzyjzm)cJKz9m5D)_Z002WYKqCMEZ)G%< z+Mk%Y$({wNO|q;_Y}mh;*aS#678tB<5cu1=d%@c__tgn?Ph0ojbo>Bdh6sv80N@V{ zGi>5-kmStbmzl{VJ|x^IB$MWD)MRY7U7VcQWfuc^lUJ`zO_!T{JfH{v6g-qW@?O!F zgNn%M(P50YE!I`|j`E z&U>$G%{lYV>zZ@9wsfppZMTkQ_NpUWBqkyd2m&A~h@kuk5sL6h(jr9yjA*I`Kmk8U z3L!$$AkFqmz$g4d6$Ak^vurrv?+O0py+DB}la)3Vvmgm7gv(`=|0ylL^NY(7xe}R3 zWS_{*M@ByWPB!pA8wJPa$w|sdBIf2k{cAI#Vm{J9z_OI1L54^S>hxfUQUqD1X<%1{ z!!kc*lsY;M@PEA4uCMoxk)TVKip@=&kwY?7uoSfEsv=|#5kj^5$P^K?*$6!n`yX26 zqBNzFvzV%8=_p(y9217Ls(dv#WsH$zC(ef*gJklePzWu$?I84?%s)vf#>%rUktWgk zX@cIGH7VbKbSA`m_64R>pm9l>-9*m%n)I&WdvQwU<7hE+7K;=q)}UpBy74?_Fyh=S zhOCxp$4KSoQ~#LDs^nF|GZ|Z9*o-{B#YEOgP@N*xsu>F!=roNW&1Sk*%ree`Hi;Hh zBXBUna%l(bEuLaWdi1B?$o3{AYbc8s&8z5Y=9UgMCcj?S4VIm)Q!h?DO!K5j#*ldJ zwwPtzHib$qPR@yr-Nnvti2k(~Jg^e_84ARjAv6-3n zsC#}%L|YPJb|mIi4M(d|WE;W`IEk88=)|9FEbnQpc$lT6#~ZHamv|$3ArGxvIEyt! zc|z89W|Q%Nx}LVbnfL;P64F;{HOEHuSbF9jtgv;7niP*@l=j!DEOL*#HnTq=KAJgB z;3trj)pT+uDM<88lx%Q}5m6&n|GYXX9&`Ut@`d!q z^PwzRtb|EoTRC1#{Ub<*5!%c$O1dmiEUJm2NO7eigpO!3gNm_Kq$Gz_&)@k-|*(OB9r)2P>4k#h1_0#^5%b`@pVAJ z+P_{VOtW6Io5i00mc`q*a+Q7FKKciLYFA;UgEdp6W~zG-Id$8Qphnz1pdIj$qNIln{fBaW$GXkBW79gM_sPum62Xd@-2sEU)8 zG}8o8G{5L*oPgCeO;+n$H^foX<%0TKoGajsQxs%OJBnrFPZmmY9M^nV7bfk-60$GS#B#3PN_PM3bFO=F zc!nQHhP>EoQ}dVRhXqvpQ7-O_g?q4__rHAIgP(?99{Ir{tqStl9`V?EeTD-@2K%u8 zEi26U5qm?)8s@R13ql7Nr+?9zNd#ULOJtdD>!};ozL$-=w}0v;EZBqq-J3ngUO3CO z=Bv(e2^6iha!(z|8LZAtb*%(wg=}S8+?F)%%e|;wz{KVqQiHLz+V|LnH7I3O%<$r! zDUCoS%*lu zuor1z@XF(`lz9)wjW!ib*vztNObdBF@MB}xb*sh*?vvFL*FEf!@Jp70y^&Ga(xe>z ztq0zQ8sUOt^+a1k#YYf?S@Y|C5s*_vZfm!DCCN_tLaI5%b-@3w(EH@oNi z6yMXJf#kAyte4z3hfp-TUk;D?zW@!38`8Ytgy?`LfC%od`Q%xyXmpgZC0VHYR2 z!kYMyXJ-F^F)GqmvX37R6u1rNswhTh7_`Uogso1Guv@hYb7gI$n~Hv=>O7QoL0JT5|E+h6esqm7V8K)k9K?W8gh%4orNz%r&=)S)nTnA=_Ie&51id z7pql!-a5Rq-1nTV61%fIE4*g}J{$WF2$I@3ZxDZQHcl6u$qyq?t-Ks>*kyT{B3O-6 zr2;jGuVrV-lciX3l8WoU7p2&JmJo*i?>%Lp`9R^UW}kSG9WaX58$Lw`8W*0r!ia3^1P6 z2k3wvEP^G#V+K#Xv!;ialC*uyo?mlI-o=E>NZT}4G_J&Vi1UVr2AHsB!mVMbn~xFH zDJ+oN5p?aU#>k-`Y7*e&j&HW-S4T_Ijnv=8y@%?YJs-2&-AiQkB0_jLv-1PEH?^hR zN5`GPe|L3UshUK(a!Q$Vf7B{~Fp8rVK3`b&yco%Kh>4uv(KnjLQV&3+^^EK0MUGdQ zO%#3SA8RFIOr=c7SxgmB8q>6o`c^Q3Jg!@X?Y&oK6jKJg;01u0ixA!B&xYeCQ^*InDK_@@Z*I$ zJ{kH9+)PZ`0mY9`?^WezrOmD--0Z(zxwP(_+f&))UB9NwpD5P)dj0*M%XUTW+cVdy z4Dk!TeI#5urR)&$zT4Vo%b$jhXCM~Bqp+@bWQ1e?UpSm;E+Nmn%jH^gz9-$KeYDZh z1+4n=yr&7#U4A(21S_nM;D!5|q6c!>unA!ha6~;l4GbN0D%PI+fG2tWb_U-kQ2?T0 zBp;x91Xbdt3LE|B6Cc4fUA`iqm?1e7n{Z^rPlrGuOB4b@Dysk;NEE4j+<<`)J`LSZ zMgZ6h)SVV^B@ZE&PC?OA+^aF_02Zy7Ei_I9)afn43Itc|flhqX{9ZP%J|Kr>sq@P* z>O>80aJMeg+Kz`w7-z-{wltr8{qFE|uDaf|v%aSRCvEei-@O9JN2(G-^Ref5kE~zgf zv7Y4`SAlQii*tkGbel*-!|dq- zx^ovfcB`6Eyu%?jQ&~^41Dht+XH_BqlK0_@jmh(W~ z{H?8!94LAbvX2!(-d2;>JziJ$=$T2VO^k2a$Xjd$ zX;Tg9eLt9SlHYX3He=k>uVW~lo1A=;Tgy4^UR>BW0 z{7X+ffX4BRUp%9t_H})-Z)FGT9QURx?F{Dfn@@=+INKOc@S71tb2z~{BZ{BwLN-!E9Z>0)OB}JFB{zfxpZxUn!O1TJZ`$R} zeD?WX$u%sPvN;xtT67mKsA7O)TDNoiuSam;(or0-ikDaw4l&x3#3?`Y({)y(Jruug zSFkfra@#WAh|v(+J@4YpKe`+wDbw8Y#!H}u$xzN}1xp6i^%lV4Tb$)$yiYoLZq@Ay zF+_stBp;l{6X37dse_xF4(-})i7i`Voy~8~w`a+E@OtY>!N1ZAhM#TH$7PmdII6Gu zMJMUQR4!`L81KnZ+xNq}ZHCi^CsD(#x3tvIh|Ue%Bq`8l&TM@!ZRojvtx00&O}*Yz zDa1bJq>MsLr%C#O;npg@N`Rb`Rqtwr^Z+gp`5rn>pgTm$;!k75V*;w;fx$7o((ZR(mJ~b}1gR4<<+HTafqHZRVU8mAF;^k6c zd<;^!4z(eBO8CSVVBC^hbNP;>ErU#QYVmQayTzr(qiVSqehja$&`s$nVb>Sx5j zSKdai%6M^a36|Qe*JmefRS)eTne`JNJH$qxh4qg1uSEkEfN=UWOM2%5{i75H0iU^T*~-74`(|A33@Na(s--<|zcGEtp1AF)`k`Irr$A%Z zQ!OZhAdDFt*!$fU#PWqfciU+Ix;;%t?Y9W;yn4DKPfm*qM0K-7Brk{bEu_{v?|?A@ zFaa3mdPr?$dvDMzgUTkj0}fJc(W!379T(2P7&-cRNR@lsc{O$H<4+HhT_BR(@F2DT zGHF1>1~Z2PEg(E{;td-&jcLYAR-0f8-l2J8BO1we@g3wtTH9_UA(0x1VIVsxepTB{iQLya}%kVbhXm3O4VBS1O zoZ*nM zm1$H?9|bknc_9o?0BaEP*sMBUL#NskDx)w;a6eUh*T$Wh1@Z&$PQWkhRxq`8gL%4E z{{lHMJ!uPK@K(kFXwT{;q_v)ShNsIPgrRE$`+%?6$U_75nzZ^ULcV_4dA7xHg0Evi znhT9XE)1*BIW$2}a5+`7$RZbE;^++rCAq=&t(W^QEjfL(T-NgSND|rv39KzE-arAS zt$>&FKbXKrUWC$ModRFW1N{$V{R4e7$g$bZc*!9i24Qw5Q}llEn5{!F=t*pi(Iqud z&aZ~rs=uCV{S|sj=`U1dMZh^#tArv#(3Mnx>_VW5f$$N0a|%Vs&%J%v!Q1M-Fn_+~ zQmGDP2yOWKrmE{$qyevY{;_Uex_4WGc2VttbibK#z}y@%nC-4D zDJZV`?3TCdC8O4F&m16So9@w0JD;*OyM@s6EoJqvn4b8DI@7BjMJVpUI$xhE0ufz* z_*vRO$a0oU@h6Q2*M0`|@8&DvVJNQ&a3SBhobS+X20dI1h%??Xl?UPzLmZwo;ey}Q zU%V`T!?>mM{VnNJj^AE9&;bdj_7lVlDD4^o!W67xSRoRTW(FR95s2XvneH$iQV#Zs z4b24gWK+FF@U>TYV~FGqihT)9i`s4?5V0Ulr}N2%sMamSqD)?ULpA9{684WkZI_;W zo6~Rpw;~l}kcr3MrtBGdLR?x9eE>QxuF@N0Bu6b99B85qy7w{^7j!_s71QKd@Biin z9)-xMR~JMWhSrhXjt~J`?2Hz|iy0s6fUZgNT=3ljKhc!RFR(;@Sr2pIGkq}f&D1i- z0r1y@4`3m6t;?#u@1a_(y8$}ICR6Vv&3!%~E*Dv6NUw^4v@5X$p)s~R# zS5tk4Ukh*K6loFv5ktqlS+d@jydXTdl^=UQS3cDziP+ z-a!SO>_|7-lkbH)gWp;Ndqc#dN2k9Uz%)u!?4iVe&9n)uwHXyS_+?U_{=tkc-f4*8LG zz{Tk)FC_Go^fD7%1zUJLza1KfT{q*5D)_Z001-tFe3l}Z)G%< z+MgP;ba9GH(H*2VItdCO6HW~LbT2efvCySf~4XFI0r%_fFJ^@vG`obDd{91u5CJ5- zINawPKLE@S@mY+`aWE)GO_ooV!jLm6)io~0q>}{FWRj*Sk@dta-1i|sxxP5tgBbZ-AS7$rtR?lM)g)q zvZ?n%Hb%#COg8MPIjbk}UJP62GzmvxuvZ85dR;#hbC8jB?U@6vOw@EJltsueifwU} z6 z378LEL~G5LX|DzBmaC-{)J!h{bZM%a`0va9-~CW&)G$rD^fCRHttF1rz7o`zOs=G* zCXKCQ3Vs@7^gO^cUCuD;7UY!KfjqKhwrqHXy5*>g(s@Nx{1N)_w&N<3#oYF<6ta^w_xnhj+HUFHPwe=sbsSLFvS54OC ze1vcouQR>jLzk4N-LFG$R8A9baVt3=Nf^-P%H@((#wb!vK0INoR!#C8+IdL} zgwUxLZ9#3n-$D4$258r5l2|vOD(1KX}&<# zWnOz3=Lbrnm?$<7Ax!^R(;zOkPVY1~8TSFN_oC<;rAfRC?+tCY8`l&-7WSaGA^& zYeh&m$@_$CZ=ba;Cw7o;(Qegswkknx%ybLf(OvoQjQhsA^ASBYG%aB!YGh$bJ6zc^ zX+dknUd_|RYf;92S8`Q5;2N&QSZt5=n3=a+qCXNlc@@W=X2~Yx7U!h6|6S^fpL*4+ z=0#U4)mW?2mZg#A^ob{fiKh|eAhBJD!(`8(V7$xKPn;uUFB6SQ@p3{gwEOmMz;nEO z#ePgu>Apv-?;PnfAaC!9Gsv&$?$BU9st_e#)pwLRl4PrLg!^CUw`GDNI@izI7q@E*|Nb(PlyD7M}gg zgADg;^);G=QpHicjbzdJc+i^Z#6;lINQH#HAa`|Plc&;waIfO}p-fEBy`MZdux>~Iy5`+;P&$;uS?25(lJPHPo~owJh9lru)|Y9$ zDb^||4tf@a&tPlfuXhp~H=YG;PT3qM?z~2^mRJJKbZ2QhOHlAkorU)$(hi7cgDOst z`GjkHk+>V%2Y`+@s}lCzrtcSr%#Bie{`&k^cX-frFvGIY;L3Paz7_X05b+$cRBc7q zPLgm;SC(={C)G~(y2uuYrNpNc)ogn;m%F@19R-nLF$s<-G@RYQT(SP}pHYA^xx;`} zK*7evS`oKIVoC2U7i68PQTMebVjrW)H2G{o;TfBkQaRDtG+EmoC~U6MO_BNfYc1+5 z3e|$D+w~;iL0JuZTKu5$hrb$xE2RNK%H4yq19atb%1KR^JmCaN_R8GURd@ z_J+Dz^=AsG_y@urQBWYLzhQyh9gG778SGDt@*4VtV;tBN)Ifix9M0rpFyEBX32LCK z^r~J@fe~-BZ{0^2gn+ZO!J#|Fv}TK*_H+AnLGF}))oY=RVsT>7L7&ucjRPU%OdS#| znpA>S@y5OelDg^3gMIB%M-7wkqYY~~F)JsoYcA;RnP#3T@EGSBf)iKJ9!v-cW9q z_s4FuT+&AiNx%U{`L}P?!6Kd#tt+Wi<%oTr>{Dn3?Z|zPOFF9^2b&M8Ti|Df7puSP zo}9_d2uoT$-wPM~c;E{Z)iH5P2E51gE_l}Gb@KrC%dpaIJWCDvnOpF4!3V*c`PAsX zFRXi=Ci~Axjc8gx=*>*we`(FpK-3!U8|4o@q z!A5VzRgp%>p(j=2i~XRJ$){E;CkcyV@HDAK14o1)*X(w$ z#_>#dDJ{0MCD`hh3D#^1kTYR5VMy$Q2^C{|GYngH%A^XevMwLZ7=)Oof-txl0QpwW zs*gWC_X>`IbFwVpSz=JRth|_S>1p8CULqH?UvEfw42pQ)W8X@)i~X(1O!!nK7tT(y zuOuNL-OjBqjfR>El~GF(Jy~61c{!NH39@B1EA{psu+G#?NYIFxC@2Xy?m&J zLH8j=eNsN3WrTipSxrn2=@#k0-zpMTp%i&QGtfzIxu?Y%A@iIKF;PLt3ka2 z>QV5AC9GL3Eg0Kf9V-6t4}btb9smPC0BpMh{e>PXxgZCRRIuSZ98{fz{}p480d9xe zSkOVk@XaO+rCR2V5BIGK(|lLYit(tas&QdgB>_?fK&&eGirCoUp^~b$b9&#ep9B0G zh5G2eDO}n&+ckf!rNUtuCaVnlDQ5iZ7RFPK^zzzK+rYviFk8HrqQ89S)E0PwHecn} zA)Cth4R@qqC1+W?U1<>&$Mi&S6N?l^#=N+_+HSqby@M~AO3e|`>Hl5x%ezCChrv{^ zz~OyAj-N0^-+2&gGUOupMY(-FL;=Zj$4x#JLo1)gLXSKczJxP)ExBqY`Pz=s>k8HT@Yl;__GKG9CYG*-ifbq8i zm7+3`Jza&~MiFx+s6x*>nZ^ss$PWm|yt}uPwa+st0GPd3Oh<*}l$_yDq%)ux5#%$m z9=1@FKWUJsHuUY8G5|snXM!%+6-ru?G1SNbUMp)!{gh3gZ$@qYpWLpEQx7FM0IxGo zDC0?11Z;lz{2!z}pwA9f)|JondcY3vZpR9yO8K7@`xp9Z1b}t`)NcUPvtU@zrlyoe!x*4FE(1FC?-{%Wa;BiJ1rTyj+6)n( ziiS5V|HKOBMs$`9%C&mn_Gpf?~yin<)1Mnps*G|!D&J+Q70$yh_HxTnZ(GNpd1G|H`sMtgHH6Z@n9|xj;zj0aI=61v* zeW!I1s51q#!(#)d77Dbk=_Vl3wfGXit7{N^gyO>D#ni zT)sF-AK`JT=?rPqlH*0_>r5#NN*iQngr!8V7Hpl>@%rK%G|JS9^P7>s5Za<^J>>ud z^sA2{zSxq9C%CWd1Kw%HwMSoSiPy>T7b)in7D??tTq|)a; z)zsB_%6z*dw!Bapp6SsN{xbiBV-j72h~TvPjU&*T3LXos|Az>d99ORA%!R6A&=-_D zES6EA;RXPJ5D)_Z002V+Fe3l}Z)G%<+Mgn`2z?Zv$${Lp91>c;Y(O#~(b;M8W1&lJ z)|~e2CD=c0-+$5Z005BzE1CcR1Te#bknAvr*$4p$;%5+MSq(KI$6BtO)$Vt)Mm4SV z>sz~4gtca`?lGOtgljYED_W8Tp6<;L{ZWwTWIKWCk~P5 zB}f?+(uV@P&wXaEHbGA(LXt3J)v~`^rZ$=_0n&5wW9@ z5?Wi>Wf=a@vU--p)RWgV*v0*Q+I2}vI`Pnc*A-o}l@J{0oB!1>tl{eDbXH4|r8sI{ z#bzCM%&(sPj6!^$oDhdv9?fZiB&jyX$RsXsH#IY0PEc3QPZr>j7HTFq|SA;$&My>$wI321NG73QUt-_tXiX z4^Mk6=C`ncXgE@u=PZM^+IlrAkpa7L6G7gBZGD?%(RUe1;C+0|zPBmp*+h1U0Z%fq z_1Ld1y>YkJIDMRFC&wMr@E0B4U1EybPN0wz<)pe>RI3r$J~V+6n%80T+|EXLYy)h1 ziHw=+6=e{kBk3_AU&P{f7MTS9>Y|T2L6MRXe>P@q zY*n4@MJ%8#4e4Nmdy22)x5Qn53z8BQ9`3sYM@C>Q_gm(KRO^dHOejW*(Zn`e;El8F z7I8tWf|Y*0%cPp-PdunH#c>w0Um>r<7suIzt10Z;z8=R5Po{ed1{M&08bx;HYoZ(0 zi0l#GBGluCt8?tyS@jqW!;0ltmA>K9SN1unVyiCBDqUvVNYhyPE!SCRiCySz9inh%B4PK9R#ila zLbI5ukeR~Rs;_v@yrw#12HGz_Q%yhB$c-6j0OohQY1Xk>`PFwI_Ue6=+Cog`Qe7@i zr-T0KQ9ngNUbwv7T7gMK1}B~_U@ZuOf({l|+E8R6xKz7j5uRe*J3R<@h}_-PL+EkY z(WMrl35(%~2gqTeCk*uSixBiZCOR>7=wQd=Z_kcj3B4h{<*$QgQdfxCkuQcg zVIh_ogFaUMY^~>kdj~EN^+2-%e+;!4NSuHk20G(lYmw&7DR-(NpD2A+*yZsF4U*bJ zvJVWJYrxOZP-*9e75#Vqtl0Um(CAV6XFexN=vKtk z;w3>hcq^nt+)n_21i;C8pn9Mkktv?>5FP>s8DN})4j`om9YVUFR`z!H7j70H2hC#p z`{AB~P-s|y7y!vQ0HHU)&^J--gqolN40OoC2@s|NsTp1NyyUr3?*QM)eE&_GZ7-g*@{~3uH1(7wlE0F$hO9QU;06;M? zoKjYRM$%htni*9Fw4(z8I)Eky0e#>B4LoiTe>W(?xpU8eN^JK=Bk>U2003$NPNx9~ zS^-#~VzkPKIMAtMj~FX+075#zCI$h%pa7~oEG-)QJ3(|}>$Ys-!s&*MBE;lV>{7?` zQ;Nnx<1V*`lt<-I1&#x*aA0yx2Z8{ARZYQa00ew19HK5TAj|`EX2388n1PZR3*j>? z>^|IJLE8B=zjjk-G}^8|H~bax{t`2yH~=m{2mom~03kL|W9y3^Am{@NW}rY8Fo66S zK?52{sJ%Y3YthlY0LXul#`@JtRsa~&Q_l?3j5Lp!Q!CW9140v2k2qp#17DYvx z!jEQ3h+qIvsz9cdkqFEW$`Ay5-~kSF@81ImtAU`jf$qe+073x3;$noVU;$V8YJXN{ zDmTk$9^jx04}QEkjJdoI;S&xiFX(W+8z2S%5ie+FP{{u)q@m>20>-|;H$XF(m%UY zIiUpkcvf;Gk18b<1vmq=;;p#|UEFo`XpSFJ$H+^%00@^AB&wTfYm@r(iLA^b;yS+8 zhb=r6@J>W;cnC$cNHHMHJEynmY;OPny$vgWj$v*`F8dm5sma@l6D2<9i}3NT zH^&ozNKX3iqTJ}vDt-fr0b>&l0kJLHq-M`^a&5Naqgr zZwez_bH*UB4n$eLNoI2GXxr21mG45`JIY(n;Vn$Gg_jhw#@RB4OQrZ$1V1^&TO>@< zVAk1UB3m|TFQe%~bQY56+Ddejl1E^K!+BlN8yv zM9(wAjt(C--14Wkjgq5n^6$GS{5sfPAMZvm?wrnw<$S@k>ch{KPMe>4&0Z_x!{w4N zG9w%%OT4*!h{w?uw}}8p;4b!41)G?lNYQQ70nIf7yK#Rv+B!mpjyHo)HvD6kt$%aR zp!vAE2&5H-X=#KxLz=11NDDSO$=jO$)B9{C=>*U!U?q!%pYY3re<)UT!c3)_`?;^i zc;}O?wh-IjO_V3E#T?tJoRD*N4!PR{6>9Ln_zrPOMj;d*TT&D(npwW}Q{hWZo{{gM z_|r|%X(d|9^ixVdbCUvWl}t-Tg-J8wc%P6|+*PDdxbzkN5rz`ZA$LbiV+pw^r7Jh? zutA|-s^_SM~?xX?nyW$ z9>d_I$cE+3@KyShHUxk*S`VK`OSm3OlREkLXP)7XS135*i*QjFv zsJ0ep(<*)#3MBMuH&oQ2zWr?nfAyV0FB463lCIT}G2HZqPtH-=MR79NT0g+H^*mnz z0vRJyLts!r{3wBgQ@y5-vJ=xJ>(Ip1obBX@S+yX&){~R0a)6RoATVI7w~U9%?B-0J z`MtOlC;A#OwVS2XEOkqd&{|~lW5{w|L9ji$h*o|gRYCEMx%MA0cG|Ccj{rseFs$wI z3wY}I!M(3^(j~cCTdt&dd_*0&)VJZ_juYQkaB;f^sc*TR=st4l1)x{UUp-~~t$54o z6dmGm&(5M18YZ?t-jm#I4T3zokXBD(C^-wS%Uvd-gB3G$i2X{K^N7QqQcAAIMpx5Y z&P%uXT_FT9;QC)PAUypc?!CN7IkY2pw6;Kfeaf7XO3p=@*xVufp9*|*jut^ap2o_c z!s6ch``099XHs(?{*}KC&XR=v+D_T3_7h7PT$A?bj729$JC12~h$FpooZ5MllUiA` zcyxN&bON4*FJHhh^&neu|05ICLTAN}*fV9mOa(wswC%o6O~{x(dV?>!L?G*@6*PCS zPfAH4RoER1Cl*&yTd=$83lp6$%!GiMKu>8splZ}LYjZPOIxf3}9|ug3^l~^2afw5J4yU3@AH^34N@)2hcYjdzPM*&AunDa=Al);Y}m zmX(y1RHs6{bq49WB+d4yTFP_te;@&wfo!$?MN4F9l?M~tXO?mkpcOLJgLFlAP~tCaKBX zZ(gQUVWts;pG3^){y@ogX8H@*+6AW#N6z|X*7Z5a!uVQzz_t$|BDSj zqAwa4wUL_NG+G`=J`hO>OqXwt-W;jb-%}lMWfbR92~tT4*xt=VH9ooCRPW53GZRN@ zUz~6L3PWB#K{435WR_5rg^fSd40Jf~?9!Uf`rQO)giI40+*|*L9u?vTba65`0pv^Y z(!!eO7jBc4O5Z~rhd=Xo(^k^&e*e;j5?;6X49<#!hO7wIaf$@NB=yZQmTJP7GQ3SM z%vC=_G57@|^)~NABYT)r9cqcvn3ief!hSwo3-=EM*nMWrD(98nBUi9R4lUMk_OcY| zW=%D2asCq6j1i9UbxVx)R)&A*Ck8;yxn|0|@o`%V9BwT0)X-;_zEb7w1 z`_$qy@Mrf^;fn`MW9?1zln3pVG?4yL%|0l}t09~K1%d!MIj_YeYzX*(CM5x$Zswvx zC`;j!6(JitVPur(I8Z1ufhYig5D)?Y002V+HZuSK4`o2q)4veqFfxrL63)sw;@oV@ z1a3ug?k>OM76Pnonz)wTxVj;y{(Fx9009pf((x`C0V?6FQY0Rk>)`c zOB1D6sOnKoB4sDP6EA|3FLaqR_NR@IIR#hN`zl2_QrB)qOp5w4$8w&Li)c6>!lc-9 z4(`FadiJkTcCcR}itGjNagta-|G}jPM@(NN>6-F#@#IHsJP@Iyle%AeHmby zPW8%al1s{l^}teDk{C>014=kV;)bFgPr8cDCZj3h4MXI|K5_$*T1n$fAmnmeNt1BZ7s+Tjd_6P>H3@?NTJDvJdm_B>it2itXxT+osAXK2j&G<)`x~^<&NT z%Ew65VrhSTtBrT=REfwBm4)vFE*mTx=8hZW!!O9ig2(J@q6%O94+058`hma?g?&Rb zzRCCW^jUCdeIaZvnKP5)RRi+ptmnu)Wd~MfWy0u!dHL$NqfkGEGP1|b#(iyZBga-D zPeku)-CP}}ftThFcz7lL^$382l6Ll}l^=AHFF%{la=yR)!Cye;iOg*dQc50}gAcj# z92m-e4f`BBi0qAcqSPV#t0`t`v22%BWYVKAb)6|q20FElIdhv+pDI)z8~xg^vG2f7 zlBYy|=%@~{QQwa>`P*}x_Ti@vEy`yqYd9NSz0q-yMo9=P4 zp>oW4<)B;b%#bP?IQd@RhWozQPqk$Y;+H(GV%MZX-@frxn(uq7$%rR?H|-7|COXHY z^!pR+8R6n$RY1~ICSae_z4*2^?k7V<)5bF3M}G0)xEc)$vsHg!e(NU^DX@Xl`4J41 zVQLy1BY;f%t)9ea=SljVp0zq534(K$_QG7x=?ye*Sf zJrxzX|42#B=+VAee8%PTp7)s3#rl9$WY0A6q4c5NXFk_7(dK7OP0HHfEuqzr^+jq# zLOaE*pJ);W(1)9!8ZAwH_$o+SxN>`Z!@X*_mTQabrrPG3=JU3zvk#RSotGb0-|X{2 z@0b9Hx(7YF=98g1N2iTlb@u;c;R<#d0OIeFXKipx*A(MhjLEX6!YC;^uRpc+CzK{EBQ4O(YWlK+%MMnDlDY^Nn4*b{t%$sG8*OnQ;q z+TTBDmf~ihwWAv#vH)u22v;tLc7V>Q$kYS{cLJAj7Jx$4e~p&_6&l`6<-(}x^0z%h zyZIUTGFpm%bq0_E^{n})LTfQM3b+fX|9q3K6mZPKVtb~hMRZL15P|>!KaF^4MIi;o zY1?f!@93NV<*#RSS@pFkOn1a<&wA5~K%D|xk=j6N0dB}`$dpGABwR&fnwG-$EU0M& zExcfb5noNWcR79mHrs&0;R3${wNj$6HVt1R+w21f0)+iE0i=6k3QfHY-yQEXl3lxX z|7EdINzUbEPQ}#Mv@5Qo5`tU-+!C8ohoD%7r${5Jj{eYQ#T1QzWh*D3;)~Qa*N#hY zrKkaI0vw9lv{E|+pFNu1N>la82@o>+Jz099++Ra%$NOq7p9Je|yeEGHDt+h4R2dq9 z?!xOK=}tY_0itdiC#z4)BmJBA8)|+uGAbua1Ng>y5GW1;sf;2v693)ZOcMwtHPZ`B z2msL9*UTwW6CDB)0<;o2poZfzI8~;L#&AyX*XH3&C>PrlU($#FV)cg~`a8c&3vhL& zH~^_@XS!)j^yMZHxrEi*)O!nv0tD?e1%!KI1+Cmxn27Zh)F&)<7Vm~&xT7E-vH+Ch z2Z&F{-2Aov1k^MFlkJcu(H_MxFlyV7-;w3KYX_EY!>6_TC9L4I1%wuWVw}K~#%PvJ z0n_OL+1(Q`c-n1Ao``;MW3|||`33h1m?m%lQdbU`F_`mYK~&c$i%5hLdTEhvSRhsc ze$;EUB->F}U3P>bFa`P*?$b<>KwZQ?DveRe-GF(4yV~MTw2a2_ZE? z_a?f(E>3P>6Zg+rf_?54ysy$V_5$|`yN0|A%wqgR2$cjDZUP|XA5QrmGrZGdYR}Y5 zr!`UT{$yH!OW%C5TgOJEsz(5GK#aem&*|t}5uZHqUa!j!jQ>4g@bP}aHg!_kpA;9I z4?|xmu+vhuT&@L7kzE0u3y>m0S{3_@cM7-~;kRbDj35@i=hucA>{okaJO%Uyz)@Do zcxc&T1mh(F+)5~>5x8n81Os7j;`q~juf4*RQ2<;8>X6W@V$ycna_t=%T)v@y_z51goS-V1yEyX$7VSh(g{#Te)q4Ed>k(c%iHg zsQlmUnz7?tF-#+S*Vz4Y+1-Fe^ar$-+|cm~uo3V^UC{Ao@nHg$pcl}ggkBn;n-(q? z5Q4lA?NP7YaX&Dkd*0#irHx5~YCJj9PkdYEJ;1P##XihAF z0H}Zn@B%2}8vqgj03!kbMo?h85Bt9RzP7eawdF#Z_y(Gt>q=;}+o|m$y#f;L1qdG~ z&;TM1l1z36q(=}pz=eo*r&!t|d?uh#*a-8Sj}iXZqksHkjW1O2p6KU5)WkDj9jdBE z&nULz7G3Jc43V#`iZ#yA-#+1+`EZo)FD(|DtKImceGFgwRhA}JmNt&v6o=)e*!S2M z#g=ZN3BaWkfytpXRWm?xO>TL9j3)N{snjZNx0e361Df3-@{bd`w%9RE_`|(9(bYkh z*}Vk@9F~82vdUv=Wu4071oAh3AT3LHrrb&D==;fH_prJnt!=BYKlpgEIncby}|-QK#Z`C z1BW(3L6AR~6{+q7unzQHio?YC;>4CuQ9Acp!DpQH6r#1^<2ToBqUCpP-TLeM4R<12 zaxDDl2s7$Tm(P3GF;MHqrw1s~?6{i=JuwoVbqI%4PdQS?A29DJnIp!Fy;ZiySX`bcne&_}=ER?_`6Wy~LEvqaaz$@RPEs zpcUgV&{tE)3B%2|o`9N;^|-NGg}N+yPDKN+Rs7eAx|+JZn)PF!F!x(6QWcl=SFm6C zvdH1@!aI)BmnRQGJU53J4a;P8K?Uku+z1Us2;HOiGZvZmlk?|n+Q~C!4F$cQbsZJ$ z4#u63b-NywcBtERP2m71$!86lO+_&wgMQ=%{_eA{KL3tNpBL_AN z4vn(eN($L&*JNLy-KwdMCAIK3&8b$%kLG%DRcixmI=&4xemU)Jc2kO-rQ>z7cUwuW zIMFJ8#;q@jI>d@~gmr1Cm6@upREg`jL)|=$5t=t+ZnX++sBPf*8>2BAmZ5??9@;0A zS##ToyU4bm{#t9-SaLWe+5s{h)qC%?@)h-!Tr}b3rZ!nyVyQ#KQZ2PXDA~5p(A(@o zn9MsP++!N3{UM)^pi2YEse7EJ(?H4GDv`YGz?ujBAiPL5DmaduYgn$SQpt46@m%P0MgAM zK-~%i6a~IUl$*j$jK+1^VWpNLT>|PU+?chUA6r7p}a?5?Mb;>QG0a%Le#Xc>qIR3VfP5FpDgugnv{R zl1BZ&QyO5^V5(CJczlCd9#}~6x0I3}=K=7#t|wH(9}geJnP9sF_S_(ByigwL;GG)x z_8qeHU=#q-b39ncA(`u7I1NCKl^Yn<)B5shW=8mtM!>}|-@9=Aq*;OYrC;W!p8DDS zir|y)%X+m;Lt`h&y)(ODZxe^cxfC(DFFj4s&A(JOiJVK%@0o@AZ zGmGw9kx`i3`vj}bKnF*B5(>shBuxOCp%ICUBs**bYZU(h2(hvlkjn!y(V|NF)x?bi zTX57j<;Yu4ZH~OK%3(k#03>J@kdMRvc3F$0zCZ>VfcB~z5PCzwi?aOc(I7pdwcoxB z_Z4wMSQr7U0o1w$hACCepRrZ5r90(z)qfimR3C!Gx)Ul@i<_`5n>iHGY zCtM;$08G_Hq>iorUhEV1REbDxV10vh9hQh&v9i*3k*oa>lLaq;aT(PO zvuZHcsxzt^Sd{dY3`3q>Pu=5i)E=3q6iTGkm#QB=sm`bY_`0rjly*kl0~noxma@no zZ4tvrM7zLOHl`Si;O|UH&-IJ`q9H`K&7H?J0%Sok6hNFY5pjwpPoard_3+#sB4e%DW=MbW~Z?WCB$7|p5QUTtsM zdNDsr5;&jRZYHfxMa);3onof8xv3r1C%fw=r}@Pqt(&E09v$)ebP*AGBzs$7Gsv8S zY!Dmbttr{w@a=3ri~oqi+`T@(dv{g{u@NXQa&510+@X{BZ|%7IGnf~1Nz6TW#F|Lr zEszk?F-GAyf9-BR<`EB;+`VA~b5j%7UL-K*=`c}+n0)3&V+$6`s5~Ne<=ka%4{h6? zc;J}zXOuHs3Vb$JMxjkJIpf5+rq6ZB^32K^t_p4-(cO=SB3Z^{6v4AFFO!fX%Ju;* zT`k{={>g8hxer3pKBHV})-{)LZQ)ZxnZrYd71%qu_#`6Lgn}F*>Ofj#ZAN9Pu)7)5ib+LSQA+6Ze_*JgeSkt+AFLjMQWSj z(Vmx!K<3BMI~~}OuS+xv*NpI*c1``7`jemVF|l_F@op!Kq_T)%>)E)xk5EmnwiSbj z1TrS58dn#2^g9MWl~GT!HzC5%pY}t4iGw1je_8Ol5mh07=*H`ENsg(_M@M>}pf@PT zpqJ&7l6DSG?qs3Ukin=nA=wlje{yK;bBFGtiz?R&o;)6MvRWazs*yXjdpU>q{o;g z#IE;>errMMdbzIVbri>9_{4u4K}_?!npMD|xI9`eSp{NPx9>^AJidY)3F_De93xbp z@|obXyF2M%kV+JdJFFQdm%)i#EBuq=cC!<7z7U+qwF>V2ZrtHF=h3p-wH!c~)ub<% z)|mhA_Zj;=%i;YxGwF#`%H!>3#qA8PzL1s;EB~OzMboy6WTzqX2$!XW|4=4==BF$+yuL+HVFI<%X3!qOh|JLcfKw2QD{a;yn<=r>)QJiRxpGC& zxoU-+pL$ZY-?3msX8q^Q#Q!+zWV%a8)+=wD)BYXEN|KTj0x3s^Rn{e!ceF$U?`BOj z+7Pm$=X^_2C=X;VhB*-|E>PDddnaFF?lTC%)>!RK(@u)hj;=E57&!d4i#3&{o*&VEVYi2!~s zD(w10@aPgjf$$P=fQAsLicjKU_@t>SdnVvwPqKp65C02IC8kG*lK@BF`b2SJ)7r+I+v>K|_8KAoe&fFY zq5}XlBVbTq0AK~J&nAiRlY}I*05$OqP(frZwOb!{S%Z~nySodGEwS$AZf7LbW@_8L z*Uh!L_Ty_?b6DXvUgA~5x@(JwPf((hl#swAF~A|1Kn_%r03>)oA*4V60Hgq_M&JPc zz`gJ9?Y4KW)!VfgRR_Yrd+ynron#@4HXu<2DHFZ`haBJ>;C=u<0a26y5x!AP0T8PU zMTh{#585EIS}4+v0)7PmA};5jbNVqz0aBv@(o(NgX*$&Sg3yjMEfRDZpDvBq)O?^u zNPIQcbFq|_Qj6obeS4LHdLwifyM}QJ1azXGCDsm&pn%V_V`1ZcG*3UN^0X-`T83_t z73wgBJ3}35V$w7mLDG*MN-aI7EoW%fv8EeobRLJ29QLhKZeQYCq5zAZ{twb%m# zCSh`h<>4)4Tg3fqH4RHILMo6G3`J1s1n9P!MX1!&ug1euX)q^JU~#&!q>g#P9TZ7R z?hfl+H$*88w2_9w$8)hq*JVO-9WmB1;jm>z1T5oLWyq4-3g1>)^fJ=>T;0C>la^CE&MPg7m#%VfZ93|zs7&YO*_nPE zrZ0-!NIX?k^3x{jMFQK}XqV`FOJKuL!&XGPX@)nJ$Bqxzb*R&t z2I@K0|++i-F>FLAFZ)~eSPP?c({q^zL%`+jB>WhCS!CIK5V z+?9*u(~I_2yBGy$XFJ3r@cJ&$#tq{FU%dyls{t#V(kGTTQ!5%i2SbIm_P+}Df|n$xpi#7Acsq5{5uc`XiA@E?0tS8;~AF__GM=OT!f|qA)he7kKupg@kjZ^!uR+~q&;08 z#~`oVAtqnbQ{>?olEuazDL(7IE7;2KH*3L!c!Lp``XIO)eDC!ISW)=u31Dx*7QwGi zO$W`Bk8#Z0h1fTs0-*u*UL}A7hq|)@@K1>0#{X^Lj+7&QoR)wBEMNkR1xB?(01_M^ zI20&;LJK!FU@7=7^`tw-L*ff;FB$-98NimUUFnQvC*cJ^j45;~1hA(VfmvH~NTR4dF!Vvaxquq{i0Ucnu0?=J83eQ6@AZV2@ah@ytq zssTiJ_`fa|Bzoh<6ZziNJR4odyZSGM$6SP?O?Qe=N$^Y0K1c1B3B|sT;PvDHY`hg3 z^?fAm!b)BbPXuB>!N?(P*RIONAq08EjRv<;)R04-IVp$XFZ9`~Z8_~128`P;N==Uj z%wPKHy{v#0fc5+W78j<{bze#mwF)o~0kD@-dAJc_6)T>23I|IH?56J)5Gw!*dICbb z;V0EboDi&iEhFj_u;;)k1e>qv9~)FFfsokSixzRlkdmJx6=(4D66^=d9E@L30j>ax zyG=9)ToJVl*`%(J?tR91SPjnG5$l{R^k?i_^iG{(k8^!NkLvx9mt7R;4miul-)^+u zA6I3rzue#FDaLlys=eq@SS4f0r;r+B%C0ta#rx9LD_F|3#s{xY#V^@Uq0^-Fy{)gKJK? zqO+q52dmpGI>-ClBYAK?_KBL~sf^cSy&GZRcoZY7w+cwW_2q0}X8R09PLN0D9#%%n z0cmZgbUTQ<=v*JIxm1M;1o%`V4yrw0u+@;nyjttbI8R|+$=;SF0qYgDJJxee9*`|LmY zZ1w?lf@+Hc_0uKPbvP?g=3kz9?`yr=wde#aaKMf14|Q^&reI*~;md3E+|LZc2tRV9 z&3pL_^a{)6OgVSXh=Tq%GoFOyi)|H(WJgF$8ZRwC-H&>sz{Gs4brojqRfu{9Cj62y z_22|B^mMgh$)W%XF|Vp6v&MzE(1o=4!s*8$R55wlUpM7ljmNw&;mQKF|f`wfQ9#%HA-Yy872Qv!~AvB~Yf}jUCs6&;ejEok2u5 zj2N4MW`T=hK=Bvow4?|zK0$A(s8GS8AUGMaVB8tb0oxPE7%^uP-i>Gq^f^Hz8bf_U z4`W%dRdy)46|Fd-_?}ondaS%0(EvoN=tq=~5x)v?L{lKh2^`TkN}2_(JVqzthzEci zNI0Tzq`w396k8=g z*fsQ!Stb40ngwsz5(53ehUE;o*rGt%U~aJ7;h&bM)(&<4x0Hh*I~|=ITiGhg#5ymj z+@V_bXmKesey=5qXc9V~qzOZ1W49DC--S1*-Mw@CL%`yLs)2LB`j-eFY9BZ}bSLlN zoC>G_cwTnb1B8Ncc=w>gr>uYHkMY!Pdn0>H==lG+2=LhRE`gnQSLF7p|C34mGru5o zlm&LC!rT2q`_fOsZZ?KJH@f)1j4Au2IOHC@8!b^@k<rK~rxy5-y~upVrfT$)#%p$jHFRhA`=XcM)%BV>z&NrpSzVr}(+KNZeF@s{?1t7>c)3^cNAt=VXoWdk1Lz z+szrPc4|E;BdO%qo0Sn?_5??XoGZ84tXy{6zw!06k|)<1b|Ua+Rz|8(=8V^FE^Bx& zn6=V5&i6WT?=`*(J_46Iv-LL%?jql*XbJAWRD|i3StkPQ!s>Kgc%jV!9W$D`6fvQ` zdGouK7w^I=v^(<&f9{EFLS5&%k?aRpt>9voduKsn7yuQ&?!u0=Up_^u1`hC!J6tS6 zQn?{=VRzXRt+XgYxu{TEF3a^CEu~MkhbXKTO>OOxu3hu~n+yD9&$awqS1Tpj0J{1c z(vEzT)B>tHKGe)T-_$Uz6_+H9Gy&epaiM3GaL;quj9k6!LH4;^9JhBam_BUEtl42e zWkfCMk!KXSHX)klFxR}8ug+EPva-&(YQ~;dIizq?w!NRtd}^HT%VX-!D#KPU8@}8Q z_j3=L3ppOncdgLk_xIpyX{AKlt2LB9zlwkIYTA9j1@RrPEA5aw_s=kuhxAg?`o^C) z%+o%DmZ02ctumjrrN1u6l^dmie-zi3K#VG#{?EA(Gn9WC66SdiU{+gW5Z*bQE9-0N1Z4o$=yfc$>hdH@WAaucT@*!T|E=S zhzw%CX0E|ap_H`>zRCm(>r>>Fkp{8^R#tvb*`dj%l9>buF@&h5lGBM$BwaFf%n&Fj z$x^xi03!faGXPh9P~QEY_nUV+a;|S(zpcxW)>^i^u4Pk?mT3h*2m*X%BM@l-LMVS! zDhx=p1a)M98UccYFCRpM5SFb1415G2LjgWU1R($dyd#@G2Ge|oMd zFZns*Akx?pQyMv?R?&jYC^{PfOORH#Y*e2mEtF(pv(J{Ef6R#_rS0Xr#Zo#|2U;}e z@ox;>jsr2H95ucQkHarA8lB`z*IJnz5}(r}Oq?hrtfCi{y9UcNT;o6u^USD43sh zfqBGcD^QVQvil}yd%|v^Y;;B=4oG;B5vvNH@_`kO64;upv$&zT{Sqs6#x$dy6Tng{ zImH;n*s@iP-Xer*m(EZjoa{wElz@s7n8(}Xck{}WOQdibWDS!k(k3;jC?uDasJ5Th z_=5CUrQ@g^Eb4;$a0r!Q2`SH}gN8IQSf0MX@TJz=K-o{cqrdduSN#k*(>QTU7=mwn zWCIUn`B`#?48BWQDP^qc{sJ6<&Rv}wVVoSbwD>nyC`Mb#_}MM#od&__*u^f3F2z`F zY%I;?2syF?V^S~nRFZt6Q0!W?0$9P{Ff?f~&ViagTVv9u0o_u34O6n|G%^f$bW!r{ zr;iNnNRi_cFH$}~(-Nlg3QTilntj5p5+#bEJmrp&Hg0tXrFje4VUXX}GR!yYKU4e@ zl)P#gO6k{Tm4qkEp-;`5DM}LmRS*A7=riaKh#&q@&^(gQPFKm1Zp-~lnWdmDSY=)|LR%Yt>RO3w< zUc+053s2CUs`Jn6r`y?OZ}R3e^K(?vr!GzCS0DZGnDI%>EorKhJULpg7Hc891} zpcnlhX=|AZtX|n!Nf)6A8P=?SuWPWkwUDdh*-g%Wi8a^=acyTF_2`hkd{0DJ>3&_4 z#;^4mOOqU>6M@>tKc>gpB2~N73Z?pj?Jw&A@51n|=;LsMhUS2zf>=YV>A)>Ub!Nix zzUiU6MUR;)d|ltVmxc27UO9Hk?U%}76Zy|hTb6YN{!#d1ZrALTWY9zQTa>WUKOTD# z_`y!|GCOEzCx`EXY4gi_K}Q#ymS!yV^FLYI&MXg=ewl)kNRe)FP~Il!nROfZZKWd% zm3GmH^OD8wwa7I*3`l(jK-3K^l?EUg2JY2_q5y(j0QLk^nEJ`4%0`ipMi=|Qq568k zkUPrH>gs2aq|S3JH}vImWUsg_&2^!+sXzED4EO*RljrzRSIHXNSWr=ahcC|zW9ZOg z7dJoX`CMO8PPtyl;_yGytR55has&`AP&`0WUm$P?vZpJ}oSIE9wIJ()a2M!00n#sK z9Ih9xZVBxdW=PnE{zIQqqQCyp;RzM#`E`9Iia2@)t|5g^N}k+a0Wi}~HodfO;;`8E z4jWNFH)m@It<)TKck(Rh3wogtl7NjNXC%BMAszay-;$< z>OAGM6_CU_RK=p)N+?{WKmA4m**^VbxPCgm4BK|RMe}=qo?WvShJK*QL$f2@ z$q=Uk@fVfpI9VwbfTCgG!<2c>s9);(d-pf{j)C3p1UXC5^{M4@VG)lUp3q2Da`Jytb*NAU&R( z?)uB3dBrpvhS-%gXbb`m5azEzaR+VvBt(bxQG6c6YwkpeZAYEavjzb!U~~d;YBLUk zUU+U1LY*LJQJLiy$l;gbwQawAxuP})Q~-Zbid_*84ittvAXEv-&rH~mafS!v$w-$+ z9owD33h`S~&KtT7N0+T%1D(=^o~=)8A+HIoubaMaL>Xu|L$vdqJ^3#y7^Q5v`c9;L zFFMNtBy@EvM8`o!08c%&=)v50n#sO z9NRQJ^UZOK>LHak9sOCg>H_DWjtuMQ%1jK_M^yjE^bd7jRj_vm-~m;WykqrvK{gdK zlBu|FT#Q#V6GKz2Zc%3F#`Z6T|TfG$XoyAMV^vN{_eY731a$yTw*C^Po6XdB?Yx706ERBj~Yk4@Bq~eT9 zJLvZmogJLAv-*c+AcelM$f<$lhe=k~{&+oVQ1(@rtEUt|7wU#-yV@vWTht;Ke;VWw zM%PJCM|TA+-t3a6fN+Snk(J;FmoYRGMDYN8Qbphlgr+~d`R0Wy8ib#%2-LxEMean= zOpu^0aHCb9UNP%TT`Z&F%7PP2N^ZJ%rZx3%F3+a4jiBA!`U|x91E_Cttm;!)A z@|cc;_>Y!q-N%F)%%9+md-XBX2Z{vg$t!(MON(^=wO&=tR!T><` z4vM~yX)Wk`f(cyEk2pA_L__<+=l=dK+aHqv0O4OIqo6&Y=4-ovQv_SM_P{AtJE_DE z^ZP$Nc-K&uA7URBm>HQdzu}GtvIq9mEP&H=03%`hQ-G`n0AbeS{G3RbE`XpGbUML= zB_1IB1}73VCsdh&s`!5M0Mo1)D833;1+Wqu?`-{A0P-)<2!SF{051TeTmr`jTKObD zXGkoS*MN{3IGw=A69^E3gBA*zlTVBpN4_3PTqFizeotvdnSt?46hLSI8tDsE5(0lF zn!Ud3Lj(1J`-L#%z5QX$C8wTDFF9rI$$$Z{u}Ra+Z;lLQWBD4kIv)jN)+cJ zkTp+PE5JhjlEZJ+8rlh~X4H}_yq|C0cNo@0ad(Lm#$KQh8k{hSGLO{M z$Mz&&C6%DG^S$MNpTOU%5O@d^&M|}vA>-%S600G4<0aJets(npbd|nA3vVr;u;3ni zA+b`X1;!K*iJl>0b7bS`QICu}7J|oN*VdGV4=W>>$F}ycwQ0^aG1$nQ3&xc8#SM5e zJa0z~4MUFnA!Ts2VzUf+hD51(QKTk$!aoq4CI9|RjU)X7oVn&K1&SqK5k?e}q1mf5Gib+3FrtlayCXB+{rHt-)XQvt>Yt`Xm0@MMqC7vFqX`gZ(@=?JkL zzq>g^4)`f@c1=>b_*mw*KT@(`>khqJDeYfT>vrNOL($P4DtGyQU=33&E_&4ec7;&2 z>*+8g3eNdx-@`s6y0qY+ya$d6%(kmmP1d1DP-2Swnpn(j;&BZoXu9XmV%Bhup+4FT z|1L$mUQCg58O=RIJB*G6%O8Tny8b4po6#>0+fWIOLclW*J6$8#3hLnn z;YwD4`t_dOczCTXM>7Akf%eB1;>3yt$pj<lXqmdCJi`xn;4rxui6kIkf_ij11pqv}N$yzlrv7 zIX6eVTK{${rbmvoAY2!z& zJ;Cv75riUzepizUq?7_mm7(>S{_PCv86y~02c<6x*iDKygbl%K0ySxRWM%feC5sFO z)RiX6s@tRq)&y{*#RZ_d9JACClW;z+j#?S}09o?Rq`SZ^yZ{&c*avIm;lhpBD2yGy zL&`+h)WMw5UG-eNL#1wr#1CF&zpM5HnC)gQZ^MWCZV*+;s?}uYQjgKk5hWg!(9o?y zoc`q=>9BXf06A&OZHv0MG@YK8JwFk(pXUxbGH*Eq;U!N;O~%&8v59erB*e7|zIU|y zE|N*ZFO=tUcFBY}Le`xd64p0b2?~@=l=QsvthT_g^dy+r7Kw=)e%FZm{g>I+X(yyx z-E~7d3<*=2IP}zb1zb}hVu<7r`kx*^7*qFO_?Tg0j=+4mxeDU%T1Bfwm5Wh<8h(Ry zH%x&mm~!ZsVPy)r+HaN-sgooidCqU0hO}KdypC00+m{x?;nVXBxDTiMv_zD6_I zLF{F&*o}PXRHi*xZZbU%?X+D3b@9#CAnWk`zHSFahm6qX`x(~5(5Cus-$HMKDK@a$ z%aEh{cH1N21wEAYmk%cDSASje6tOpZ7dZILzJp=rzxc}QB`EQ}J8$2N|3raR`yVFZ z^|T!^g>F<=4?f(YzX34w9hg!Osh)hJBPI;GKjSWaZQj3wSWBqMVqlJ$g8yzws_h5O z_tB>V*}#a2ZGr9WgP@Oo?L~Wt2?b01*FHc_N3nQ6P}s5L@_qZ-M^R>Xkf_|qu_`{~ zm-0pI*kH6Eq$B?pOM(%Dl%u-;s^EAaFpXY11wHb3EcpMJVAYy8#|L6u^cUkuR-hB; z0$pca(J~T#P9Yu(9tMeD0`+zo>HkvJYScy?|So1mCT7`;PN2?n) z^a9*px|Mrw!N&um@q4oN)c~JxUcufo{n|6~1TdJb!1W1CfSDxi%Cxw-apXM;pyIG8 zJF7dwUbU^h3ezZjyp~4Y{qm}3c4Tw&oO?+xNR0oY=p!#YelpmhRrArMbDsoDv*JSA z7j8W5!-kMA5K{g@IbzDUr%h7bV1$@FU!@E>NyoItEiS&_Z)*{63v>HTduZp}YO?Fs z(hIdk2tykkXTlYj5!!x2OZ;OCJ7#Elzx4U;U_G=UlT6vOWkf2aWg7SS5Rw5onZE5WapT9Jx+mk84kzia(Ao68`;Tc^DqpB+qi9?hBmVM5wSH9gi$ z?b5k1+E_!2zV#{P88fqb+~1^zI~7p%JM3*5B1|mCsjOCrughw5j6|q_w#UWo`{4WvH<6kdiW$kZC=aM@-61X=njnarsN#v5(CkaRg zZ-VnFGOXg=){kp}a6;%$;_RB5cGbNc$!NhP5*S}MyRR ziV2ZiOWQj(f zBi=IVZkd}B@_7CSWZ-*U=`KB6>?Onmc$cO^3QlltxCCoC|iGt zqlw1#CX?@rxce5;^sS*Hgf)a|g%eS1Ba43_i`~2mFOET(AIP^tODG{NC1r^5mggKz zT0t%QD0@gi#LcI=$H6E)SV1z`=N*b{xgtJk@HBnh05D*Xp0000(V=yBC z01st+)!&!j>OKu5Qb}4iIfA>$amfP01PcQn-3Wf|TJD0~mfBvegzu;R`!G5P03$MZ zMF#-I2S0(p-yfS6LP^4Y3qph@$s{Q(x$v~^h)QsU@>m}15qH&sY|3`FJMUbsY;E_n zo#*UQbVb8-TcGWm{C+IhLLwT_TY5wrWfSR|`X&kjg&}EVEX$Gr2mk<)2!Ry_GM;XVKT9$%w0&VwoTEviC###L6C<;cm7kBC05I0Rctj^dv%aNr)uAVEEcmBl=_bQG{=fl-%B`1W-RM`)iBnw!QjiKtouBu zHn6uvm6;sF-Gfm`b!Y8xHRC&{OS6#^kB3f>pEV=9GV?H!lBsznxrj+^LVkS+60mL{ z?25JCET*a1Z9*>BJ~lab%*$E5IxF}5yq3&utxkjuJ*c00$&yU;x3{=v{Dag~O_Nll z&$Yv_xaR6jbso|xS|Q1)?s7=0-ae65omE81q?Wp_yjjmd_T@xY=^porEcCRdM&~54 zOlxxDp3BbMB-9#qTh+ALrZ?)+yS|zWAAKRZ5Uz7*?iuL#47&-?n*m|AzH21wg5~sg z=A4nO?YvtBgQS;DHusur$lT87Z}w#!L3Ze+?I=U3_{~XnW=B11Q&qBD(XUk}Z?)(R zxu|8vzPv_Y42q&fzzZds9IP(AI;SSAhiC)K@T4Yrn(X-Xps zHkhtN}#YEJPD(&uZE zDEoI9KJvvLeuHKt^x??grodQf&)6yww5Ux>p?JgtXb+Z!v?&IecI^8#!p5? z{xz(JRJCkb+R?oS^A)`(7mGH$yQVJTB5D`GBoP&}WDAONdby#Z-?7yYoa`jV2E2Ak zPivW{_(|vea$Ad?CI*Mf8dfkf0YMxk{02W-YgE(tcM}L=Z$w2Q`8VP2T3tl7Gl@g4 zObVHi49Pkd9W>BwLaUD2V1aa7H2--2{XWV#zx?#{|Gb?3l3~(na?6*IO4%{WNJ+{R z5%{s^JSAJnpdY*Xn7P%0WZdkpR!?-7#Yspx{>x?4(~z5UqnG)*DnVwvd<)F~t^al` z3GBUPCiI-atW_CExn?SaU$Po3!nR_m2Ki!(h3~#8WxCmTjW1T8Zg%4hhi4gr)`uU;a}D>nbD4h&r6E z?jrGylvv*;nac46H{||J*@a?IUU9{@j5=A9dElhjZAEU(sg4Us^};p33HPXZ$nS;= zHaJfO^nELa6tcb)W)JEk8`+_T8jX=u76RYnhK*gAj8C<36kIj;uMB3A+%jS&Y*JLUcp6L7~%Z4zcuz;+n$S|CE#8^#v|Pc zjRJq;yYx!R-QS5p+S-!(t;(_zfV1$quQ+t4Y)hbmQwC;%gotHWINO4X6sdV7hZb%- z{fAeRjHfvFQzqNY{aPd`_Uy6jFSp}g2g=s2pZ7Pqhss&oUinECI4XmWO+O^uK@pt} z*ZKBGEI4>-FgpS;f$e4ynGf2yRowV(NCLjlrld+o;^}NktFgm(FSfO)UAa^OqLLyI z?g^=6DT(d))Aoz)jx^z~eG6sXQn&A=;=q`4m>tK%oy-?T=6++C1-PbW4)-AmnUJhL z#38T;tp$v!0*NGy$ASZXVEE=Bz}7r{;$xqM#fWn#tj{NQC8ikcsjuVjH`)7()(ahf zKd18SJvc?LJk1d<`{{w%`5NAWpscFvCiE7?2_npr+m8@hb86VNSuYD1_(0wcL#@BM zR!vPh&9{B4J3(4cXB(h1700N#c8ZzNLDA1odn)T|d*1&;`F^~h*H#slEYiWBp8-B5 z3vB*Lq+V&v$tDqgy#RU4#ETFor*{lde6i^?Q`@TUhbmyW3BDb0^iW}66&NSP!Urds zsQ(9{F2JW)fQ#}N9PUapDR`gL-@pWMQ{GvO!+%+ONCmx!O{K$v{==HU>$d7P_#YON zy@8AHL)hCE^VJ$TJoOZKas%PDS-a!IidUl&R)g#ns5wGw0LJ#AHNeRj+XU8j!8p^b z#`iOjr1+FkJ0OjyQzp#xkGP{l(L{5;w^lu;f)#emezS1!!&Ngeumj^}*^nt*#)kl( z*UK2r2NY&rzPJ=LV+IqZb&RoN@L6+~yKvn^Soq*-@a?DR|IeY@WUwos-(>1n0TYPqjl`)%+ z?RiD$_&z)(bI~K;_(4;po{-^mm{%LZZTAcYm|M@G#qh{UJpg47bDu41VvsI+wxnXc zv(H!q^GelajYk3x_==5Ad9DK5!s4;15?UjLwt|8#r?~>xTaE|n)Nb;_Q9!k!yNm9*M8SDpm((E!k`{5*u?*2EUut<5t zT_mX1Q2^Bn+(rS!v%6 z5nuo#-!w$NI2b>EhA<6IeCv!jjok|>k;p)4{ZB-0PS8~o8JxRcB0I&PcXzuh;@+>_ zIM2ZbiKXGjWi$tL07gUnhB>iU>78F2goAvdl^e;Nqln%0;^{ttsZX^Or4@osClV&wIUC_VSrI#7>s0c%W{F&k zCn~1EI~Noh$muYp3U%6N8VZWh`Dlj^Oqo&6$BK9zo(R)Q@+tn}U#h8c?nIcC#8|9B zi^)%Ei*bkQ2Ddj7q#b##lS-hsn~(xaW>4fe4M(+o$AFX9{3?TK3<@EXQ>4B&@Y%*J>j@ zznJgdSF%!|<(R6CG_cpsb?(#kvx znnH$pP{@nyKR-0jaanFiTw>W(v#b$n0q*m%($5DM3rs?p#5d>B5kd*3?Hy6WAY5>L zTmw6GgbDx>F9g+CShKn#Mr4_c?sY^^g0#&e%owgrZjTGNu}3@rWPGEHnUG&3e3F=U z(%l(EL%AOez2WV=x6dK|1Ym?LQyYG59EO-ccYOjR>bEm{3lN9F<`1ZIi1GlYRmbd) z!hReV4@-CtXjEpz2#!W>{vRZ0uZyJ=`t&`fHsUvtGe zVg;ZP5Ol<)f)G!^37+a66wFf3hHzI*NaN=FUQgNV|9vf?DOe5llZ-ESuYLN&Ob6|Kb%4jJEQ*)$z zDjHdK72J47bk2gDlo~Q`GgViAqzBN;ohx#^43j*veo@*-*0=={Wqf&6VAbhKuS`6W z?5Ng< zOhjjbb$U>QiBw1KHsnc)xKR9;110(#A>KzLi%7J6%5pQ5S1bduQ!pQU0&&zJADZ5i zL=n*q^nNfH@34=$VX8s_u1hri2Lp!b`1h;5{}I^WAB_S?>Hxr2KJ>4e1OAAhgiQNC z0=Gd+a5W{DrxOeI`E=OeBToQEzU>kJ4NLS8DhDNC+5@3%*@pm!KzP4OBPoeAhcx-M zxqb~RRzR*mnsX*(hpPwqQxhK5022dr^O7LcW^YDJ=3ttwJIi6a0D%umc~JxgwSn0< zUZD|xvUEVWjt{<&OWxEK&?8^~w1OU?s=%aCEb%Xm8SX)hXfV`+SWFbehKC>=>MEH6 z2`|zcA-z2L--TSjTV9(KIv@cs6gB3 zlCb_psTq+akW@m!b>6Zg-O?)C%64|w+1}dj_P&?xcF%i3?d;sQo}>JmO}})JE6pO) zO&`Cq$kCf_dSMR;8bB(2q$B4k_oVKN6a4AZq$dE0005d1Ga@Je-3NB}cK2NN-OZWX zcel%BmMyVb%iPC>EG;hECP}XXP=I^{3IZX%ktzy75`hq^A->sQ1w0ax01}o!7RX7; z@C5>hAp!?PP{LbA2!anpOw=;wB+8QKrmIfGY{X%_g$o>;@~Dc~sl0@xtW7paxI*^G z9;tlR&%7#zqm||9sw9|azy8ze3v0JrCNTS3y2t^>4StyZ-eYc)(1CP%sZT-h}B23A8k12(?YIA1oQ zqL;L3?FEqi&61fVnNA?3W1`->`}gR3o$TsTqFO{%Y_f{NN#!UqSF%(lX+gX{b9PJ& zP)@O#Sj%HzYXO|*kd{8b$|9{SDae_D(uvj#&>Y>mynjl6OKQ}AgQYIFbl(T`=I>&% zntyDvC@=DlDj%Hk0;4G8pMc1VADvWuB)Y+-^iST9+5Vp2##@(>@RK`Cd6}_PoR7Mz z@|2&P>n$+3iU|#!SVSt-d(2j&V5iO~o4T@Tl3o>oYi(N-N-2M@bKrM0ShG zF`76N>^#I~F<6KuX{x1%IPtP1$vWLQy&8Cx#tOWH6Oc(*Zk*%>vQ-HwSM7&)rmFQ- z5HBH@$|5V4d*5-g1A$9!uuzwWJATnwurk8(u7TM{Hi=A0PNTT~d{Z3wkq1$8iGL@#}nxS`WDurrWTVcyc%S(~I~|c(PbySZL;V%TCeR zk~O#HT9^@3$wLzzdU~*$!xVq4HrT9|6BaaCkj;o2V1!G_SLbS49g=FZM%;EQb>L{G ztjErb!0b(^Z!SC{_hiO*?gM$oIKzbp_sRF&NB1&iELnD^NxdXY)I8*mYiKrgZ(+E3 z2Y)Rz>{Balkmhr=EVxM|Ou}ND*rl=T4$Fme5Qvw-Jn&YDmD)aAt=>>S00OLFZN#k-n-NCruYd=M0X&_I7 zKBcyL@s>aRf&+OKO!TKc^!MldFO%leAmq}SpM<(fXRX#-`;y*r0$8=*9@;;W5K)z< zIqD?#^1HEeKgou zCho3Q#N@(R)TYNnT`oOaLw zsgm9l3)IKZsp%@^)@kLx;MjZSJagOOO;sM{NB<$fj!`Z5@kn*|+ll8T4hTfuv#KSL z9B}jKUlxTwdnm!hoLna0GZ!bE@;4kY=WKK;u(s3HujQQt<|2Mp~l%A`i8%Z+;x=BogLcSmg z<@S91CWhI8E}V81@OJdUpoqQGHNtC<57my~gZt~=8ue*wKXvuIKsL|Ze(R&1%xxvD zj!D9E3cL!*^HUTcKJ1YLmVBwd74J-UXY@XHv3~tojwffPgr=ysxs|#{ajUf2 zqEl4#yBU2r8VL9oVaOF?v|eRahsrgo;0=SuqVbd9DjB<9^jqdNd_^ZR4-TRe`@i7f zX`EC{|83*|8ol;b?)}WjFPCg;NGmhk#JKnZDstZHT5_pv!}}J*50cbb?c49HbqX^6 z2n(=ZO#aFXn|QE8e(BOSTcPEVp@`c)Sv@>dsN*Q7J=j@{eIChSYtP|3nQcYAaFc1N z=Ol*lv7%|+tcI?anz0EwIlgVdqgec&5Z=p6jQ7)O7unu?IrO~IhS~rsz0#;>ck9Zr zV8>&;B+X?bUxaw>y?u7cCD%Yb^zU>}D7~%-uTZVKL(Z9AQU?lYPr7&N=x8+xVJuon4sntBN_Hy2-=W;Z44=l2 z=!)G}Yu1G|a-J1hHj(1Xq9MgAJi&NUC=1e?&DXmF$i#K0OS8IS;@h#O$OWu-yjiZP zZsB`Xw*@%R5^vZ~GCu7}!Aop^-sZ-={EdAiea4?YX48Dvv-ICJsP{D34s|BTg0I)o zR?Z|$be4~9gKpAB)c+M0?{F3FIID=2@qaa-Y%1vhsRO5amaCPEc3*ITw2^KAXgha8 z(E}(60ii&vLG4jsEeKs8lQsU3f0oS)<>{Qft|XkVIWuIE8y5H;r~-P6;rw1tP-lUc z8?2r-Qis&>P&5yI?W}W)MR1Tqkie*3WA(bp*!;$zQ45MO3I~0$7YVU#8sg-N*zEd3 z;=ENpahMMZttcmZw>8&B<{!9sY9nhTwi)MZ6q|P8<5yiQyS(%|+PFd4qh$^f*jY9y1M|KpcGA%@{{Zm_ZkIlnvr~6Rl*{_d^W|WDEQ$>d&C^9ls~up%(w5-?4A^&6>Y@t)sbEtJJ)#B>kpBh z`tL7jP#MAYB9fnt_M08CXmt8|^{+sYjCi{C{YIc)azKlB!nSxmd`2HjN%<@RTVOqL8}=DH z;N#-nTC(d|e!hON4?YKI^PK>ypS}56lgmSOt)2^w+t|h+`PTxdaCh?*(C{Co#_Z}I zdcKrB;3oEa{v+uU1hV@o&JqXIz@vqMd`b{pxHXUh85y}})sV7oWNJRlfo zs!*_;H^PMnN+9YchAH-NRFW|bDg=CVR6O;OM4s~3_GnK*3X8rcUx$s27Ql!kLzIs? z`XT?Kog9rvbS0zm-SbSeV<8X@!o}rh9dm<^|Pvsq3*5bxWot zK%9X1peRFeDTMFi2)yBcri;R000snG*w%!DhhA?Bgg1IH{i1Ba{jc~ULOM>*^vZSx z_k}+dTg+Fs0Cpk{O_E92qpy1UN@LKK7_8$hOn^i=Y?myXlV%ubUVVfc5?Kp{3g*NI zkpI;|kWm855DF6y-iuEVbAw5$2?ATt)&v8Xn}miz5PSnt-|xhfx*wjKV^O8eQ2Vp? z>C>0y>+&VP!Fk=#MsbV~lM>VDc1;n=AD{+x{?ki}7zjK-7(PJ24ZcFTf?*4;n1Jxh z(*J*?p;mWF{nUR#og(I)4?asxqzlyTx4W}Qq~U*dq{5>eRVl6;G_)5HlAAqJR`&J? zKY%Td0Ye_p3nb6i@D~JImd5ZyG2t2Eo_H{Z?gx${TPZ*C6!at;o29$}VN29>oCN<* z-)9Zsl8;+`7sU_YER1PhSJ+M*RS*v;0Z3#~dYr0cOWQQ{d|LBW)_PI=qYr%kR-E(0OMspt#*vk| zkch>SH+G8;Uu8Bgip#cQVv5Fa3=KSt5=(*ngm^FPExV?}5t{BlL>K!pH3gEMJeELP zS33-;0DgULav1=K7POiCxc2}NpBLNq2`=!(ieUgFi1>^E`vA_{G8zIP{8Qh1I_Acc z6!3cj=Syz!8RDLI@bGdSXT${QiO`C~)yOON`PL{A@Ae;f?;$j3_8ph-NFP{VscI%dg^=E>WCcSz6p(J6Eh6|rY$O*fY@AWILzul8;Z+dg zQHU*+Ov~-*!~suy2tfcK5F2O-nm^bDFuVYS0u;W@@leMf{_Jz2$^yT9yBb@c7vEGl z+Q%dPtYnDz$PP1F-F|f@$$dav03X)_i2m*an|~WsVtw=d@>WO04>Pbs~_dfh!oYz#UN$cz=mN&Id&(98Q4yptlTKY2wkU z|Co+<4Imm-)OkvSyz=Qc>BJlrt<@8$~#(sQ&c-DD?H;J3%-l zNv!`)f-BD&b~?SfKu5~Df$%x)D^u*5OPX8rYUOj-P5V&OEXhNs*m%G3vIKIK+z8(986|Z`!+wS^s&FDp*5GC zBwzU|dBJo5hAAb&Y7hYEa~Lt03c=pOX#;W~@#a4TYC+)?;y({64(`^0o5(0kLU%mU zhRyS#Lqo~@6d7UPA_PW7fxSKMOrgrLO+XUhRBnhX*^ad_8f9F~K4QlpZxtaDTOV!c zc3rp6UlHwGpou%WT&s&%fooyoo;q4_*-iJX-J3&bds1KK$N@y1JwrUzTGmnhG zFUECL{|v1X1a<$-==m6%CYVsltNYU%Ke&Rr6ZH-t090r?$oW80$Q<1}JY~rqhr)8= zlqNmY5+}Kjt=JAkaGEE2+D-tO;C{J}nRK>u%`a)dQw@OX^g`HM8s#f0Zs-D6S7kX< zsPgZ*YL#h4aZt9Zkcj`Bm|b6J_Zch&xpoXW8b?Z*qd~hpx$7;-EDI120{{R3Gh;v_ z000kVeAVBV=IZ1$Dv@jfsZEq^28+?wlrV>3QB*E8yW3j_?zY{1k%I51{`(+0001L1 zU_}4`Z3aFpl5Ij6$k+=&0SE}KkQtf@ImCC&#&YN0E?d^@Wv|<wGbGw&w*|w4_Gb`>~$X2c0U6L)a5o1eZvMvA%7ZgRp5b_#{X3Nlo9YMuNga9(W zSpZgDL85&G0EWW10Y0A#pa775HZHh7{gntgRW##c zq#|HR2h>h1dFZIvGWD$lMH+^IyOPWt*bHu|LOdlXGm^pvi(tswQH3^T^G0xD55hY* znm=BJi!e5atZinsX5fW##!+!7ixsLwX(3V?l@M!!|7QkU64ngQg+UfAz z`p6|vNLG1uVY!=ay;uIOVLRHtcoR%eQiq&1% zrC&Sp_R)|jwAdK;@8G;*-?&WGVdGa5{0btrj7inv0xpV{PrmMz9b~ zDY6aFRdfP0x6$N0S}f&bS%;F9k556FW}7%u*rj7CT2zcqHJf8|Ze;1H=c=tCc$=cF zl7lVj>#Qwq7M-|x$tIVbCA6VdarSbw9y>gwSaB6m?dHp!vQ~X%98Hc+GoP+~bV0h| z-N8@C#ZV)T{k%)jZ+SM3`radxg7}+J5)m^r%LUBrU$R0zU+pJ)=vuR5K?mdMeS26} zql5h_SOMUnh7y_7$RCWxE~km9&zBxtd0b^=L8F@SIZj!v3vvJLa302Oi>gv^7n}3l zNtADd|J1I*LnlCVv1(_!!)%Wj51DZvTSrf|k4OrU?V6G4MBIO08NdPBN4q=}rQ2El zAzg;M48gFFFV&_$dViwfFABFx*7gL_rt^K`@6l*dAhH(HM0^u|(5+$OOtOYJB}0AmXC@iMk`+h(Ji5GN<2v5jY&s^EG4SwL+Q>pz zM5mdov`n&HgkjYeGvAZw9ylX4OF&VIb_K^92mqyygSc0n)0Ee#^z=Ietg%-%PEhz=kuUP{-??*8B(XMEC>wN$?T+*Glm$oPS8x5__E4t zlM5l?1v5!AH^u*koiufx52(ue56EV4f#}g33Xk6A6zQe zVPmEsQapUdHI2hQBjZ~w0^=#~Hc#_#?9ZE(+mUV+c+K3iq+2(|E2lrASJ4CI{6I`Z zjVKnuis%E$S0x#eP(TYOKIa1Qe|HVnU4Nu1g07{~mslzy()*cqyIO`#k^QXaG?_|h z^w9YJLb)qw#4J@Z-VdKD3DY+($;2C3U`Ol>v9*_^expAT!5=_P;Lx<_fsW@1HWUXm z&f$};I8U*;k!Hi8Wy_;{@_18DXe0bxNPkBT;@wp~XtsYsy5f(9iR?a*oIx4+1+s&j zLPuKjuKyPxampSe9*5}%s)rF;m#4XkBdS@P%Cdq2k_p>u-=b7*l8xhJ6|B>OP*0QA zIU+^~E_9@Ke=Maa_%94dHlp57Vp|fro2*PSH9iK@x?NVR;P6s@-ER*-U8-o`d5op% zyr<7Ax{5I8`t_PG=4p3d|-Z{ zKR7r%0`fh?(f{}jSl=%S-*xu27g^cxA10!ZKJk2+C@>_OERZZd#{RNg0eL%{M4y`1 z2IdYXa}9m_URFn)oUT5W$6wB5@Rvs(5EKiQNBU;1kQx}HmqZo}p6D8kQ0K{hb6G4! z(9=L)=+8$PE!g&ZtP9WpDhaj7J|Hx)6>m9shzctHKS3Q?L!u$%0Xwx014uQis3qbd z!K21p4atx#-pSIs@8)SR8Ul`}Kh@Efl{o_1!F*6gWu~CH3?iRterWb|!A=lEHw8&k z4%zqiXu5EG+vYWH)Wsnij*QYlvr>cVn>v#m$b=e-lC%o>2hzTAfPiFRFKx9YSqggk zOA#{Psh=yJ$C0op1%hCv<2!@9RITJB(ozEli&<4(Mz`-v_#URCMt8EcQW^JNmveaI z(47JfJBP8M?sPJ@Be#EDykFrzIlPXE+Z<4w+u%qhbE98wKasfBYA-9VgUfFdG;?|_ zjx55u5{FdHhA&^?YXM>Dz&D@U1uG!G!7fabv;6^4GbJx z+SCsX1{@+sCE(z$!rX`sm&{1j$MAFE#p;g;)dwD7Whd}x?5UVo9W1sbhY8}u#C{@P zJ384BR4-Uz+P?ykH%A#;s94$9%ipRPjGm+Ky)TVpSS!FSwWgan72sM_m1fGSFqlgv zF>=8wNJscnlKG5`lisbSu08Ty`SoaQ3-o006^!?*SS7|ZQac-4?QBG}AB%oBSWX!v zg15^wcZQohONm=7=wEFsBupgHsLztJe!pG=g$rcip_ zg_>i_s+wepa>~vUdhFb4DaQzLhWIDFCMq%>6FE{{>pBqe(Q1ia*s4~hM=hAz`;wz= z7*^N2P)UdUrF4r&bIT8<_tPU6O^+@ujiJ*bU)c!caz zu4SV9&ir+!FQkddT{a=H-;8Zm?TXb9+GPK~XFF2U_*K61e{Rn_3e8>7XMZTBxTW_T9&WS0fr9Np zyb^jSn*#E&9xMyW#y?erK%I@-3Aovn3YPhe5=4L*P^ zc>bW_yp*JM&P4C?Y}bK`pMk$#p^-c%P@-DPse(7^!>uJWS6uP2(mK7|g2igB5vSLN zfgddS91O}}OWU~1=P_AU*Ee2QxuCXQ!VVw-kbnB8AlL>NChQ>oA0VIv?s*W{0~3R| z2TK;Dx73uOg)}1t8awM;@9A$uGeigzs>35O-20s0IJn#t%lR0!;w8b=LDj0aYSTOz zi;&II{X9_!19J)$rE;m9q!r_}80wFaY=OZ@X z0w0UAgKJjI!UBqto}crj_6m38lZFL_&_C_{Fu@8z4guE|5QN--w}ylzKoAdvbw%}o?uRyE(|&1D)=z@0nKa*?fpzc&t;KICU5ctt`PrNfYBbM}do*Rk zMbFXCLcG}y=t{b}Aj%XUdzP3*$mw(sd>_Vmk0iU@qMdKv=kg z&>LdYg8&u0^8l#ZLp?mgR0sbY9|DEF@8b=x5yapW&b~Y_WyM8uVWQhA8Og$c4ew&K zG1wXs+-sTgNnT{Q>UhpM3gm9=v|nwbfnHBG?FedqpDwDok_2D-Ns-EJ0Cphez5<5; zusa9=FQ^H8LihwF)SLAX75l_L4Rg+U=3$ekp)LBlc3S@fchXgPWCK;~Sq! zRu;`v9}SG1C>JZ$S90*}#A zLX}H=CK#^yuElJ)z7TCM-S%&Z(5%EQeufITWuo!;44rbkD3)2sXkx}hL>TeX?Z%=U z)J`BxL)Le+h`kO=`DZRm7%RphiOql3gGs;K?lZN}E##}vx>L}~&zein2HrJ<5rDW5 zLs$z!3DH=5#sesU&oK}^crb3rC>4+(D`OeclJtzeC34)_y|!nndC2%i8E987u9lP! z24r3w`;S>MQu=NvaQ!c&W!t2LIvJa3&r4S!{?V*nZk!dS{s@oiZ~z3TyG8)-pm3r$ z>@9~>60jJ9ZTAODCB{LBzK=JcbP;=3KL=ms-trkXr5S2uaBtMI!M*G)zo~BWBA;Do z))se&#;r8K3C#f{UcIP zqW1?|MH-P)kWW21dUJ?V((M7?0bF(wq&dJlQr_U(F#@0jo_+i&TnSq0?~L3P%W~tm z0+5vA1eQEfySAs1w*`!aG$i(@DZt)!vz+H8tx)G;oG6pFD#n?zvT z70m0Jh;DXquA%iZjYmpOYq{|7#vH`3+?8>^fihtFJUd|%}%pY}L?)P4kUfwewrjjl|WU`8aYB5NIDw?Hcwzk)jQK|x@Wj=wr8 zEt8Y5F$)hfDDej&0I23>2O&4GlrYqbvLI!k=YdSC^)D%AtKBboI?3Z>eUsFY;N+1j z-XyzFtg1QTy*h;n7M#CUgG~V;27nh6gz;Px*A0rmG=qH)5dYhtt_QvJ9;k?U4fOz@ z%m4sm%faWm+NfUHPxdG{fA*Du(P=fb7 zhiqxNa9I!#0{{R3LjyJ=000kVG}Zc_W4hB)DT3iK2z3wT)&j zXScMrw3Yw;$A17s1^{SA0I|RTg!%uoNJ0=+Aqy-3P51#=K$*yz?F3tyAj+%y%p1K` z*Q!Q$>@D5gw%P5?Z?)F8j^~@!P{XMqP9cx5T8+h@3?y5ARyY!~9@$_kT;ho@JQxWB zFunkQ7y!|X9Gu?`-~Zlwdc9VbpGZU&9*Q1dt?od!R+0n=qaC=g011de00-d9E+8=? z0{mIqMJ+I?1c{S!a48s_h=YmxDOz2_T9Z>^p6OkMrFqhr*R+!}Kl(nGenU~$_+i9N z;@C=3ln}&w*32O1dulBjR2w)DVc3EdMW4}XHL{Wx#i5xR-$++UJ>e8toJVI{D5?AI zVg#cZ-J}-7FUl$%yp-@v2BQ_N-IBFHRB^eJHk1Ys$L`+j!;VT54b7LlHRQ#W( zR9%9Dhs|0P3zZq4C_spV2}4798x8JYEwc;sMGZ=cw-KU-lkjJSoK5-hXSi!6)jcszM%H5n6rcssX`{BOPt)*sGfYZ-*vgj zU4XO93U9EwJxDsNb<@ThHIhaxICbH);R2*yTXzK>LD+)dk@B+k1Y$eO`Cg3@Z0%=i z2q2yIhElZ))^^#z&i~1&y)4{Sh6q|E$lY`g(Q5X=8?OPjZMBCxej`i0CA@=b70!nr zBJ`KPgi~4=yAJuT+Ee}cNIqvf>KUxB#ug{>9i2QS8LcDAc!-0%%6 zVj5PfOQL4Ck|HTENtW$8Q3>?=nlGei9g@913DtuU7>F8Mro=ERE^sXWN{wZ#60P5S-nvTPw#lQLt28BQ;S?`zAm4Vqiie zg=VEr7N@3xc6|^vv}4B(&JhNA!iwi9e4MJv%1&(*Jj3)uw+x$pLrQLq2F9n<_PMr& zt&vMb6o`-1>z?0w*OO>Z%Qk7ZgcP_^@zF@3dZzfDQ%Xo+e)LlK`=Rju<6Ku>(g~(G zK`B#eutLO8amwX?w_6cPtl9~2?un^u^&yz)A1uXyd8T4g%Akl( z!JG>D76E2%&<`Ygg*1o&%ltmv!MWXx*2}@Z0Nt)Grqu8bBV=_2qA%Gjs?u;Puu+0| zMS!WH%!An;DG${vKBZh4W54F{d%Yg)1E6j3r5(0SsZearvR>DbRMGe0}+*<(%kL_~SMc2mKH)DQCtt_cs4Y~hrKj^O6M`P)@_nR_L8D?clS zvCG)MUn`F(MOA8hh+Dm-Sgt??#<0u(SRW#Nup9*mNx%+Z5gwWcxdN~JnpXi>V}QcZ z0G7)j)mA#rn6~ViuD~HxHwEE~c2kv(!6*;S+Df?F)ZDMdW1?mc;}0eGplmy16yFGo zeJ9$aahY@PBDCjIbkJvJEY{!};)tX!Q!s%Eh8EO;I3|>M3a-Ci_Vf>X z;<%Hgt!7xH3jXk_nWGN>phBy#S;0vMtH*&KMofhC6R+cIH&Q+b+Q-9~dLZX1sD!e2 zWJSG(W<$9r*c({5)PN@U6)J& zz=Rdui?Xz{dLfLY66byg29QT6Iq_M`!t}isoN{fl?0{9*!C*3o{e1t2Wmf)C^`;n< zoUmvS%4sm|iLC^aC}B4>vivWVVaO7OSRe*3pxg%Nl|*XlKM>1Jw+O;8CR|zs<1Ce^kEqm}*nMn; zTYkW#kXirhTy997(#UXsJNd=dY3n*lNlGMc#cM%#F42_wzR|NIei`>M)VSh~?I3yM zIsPh2cRIVQ7fqURwW73g^A}Re6ZW?+|8BaV-Igihtxi^9`Y6-rNZ8(eQEf&`Kqw<> zP!1O?_IzVmWMKe6IUn}Mf6|qC%|ayksfEeTU%S=>__q$wh~(g z&zqi$-hm4h*YNCkawl?cSs8g85e0=C86wwN%OO5(-Sa;7U*MYDi=q$jA5VHVqa;6R zr{wvG-I>xO&oHTg>-k=j7UmTnM3t%U1?u(V8ur**m5nTRUE3@UmFsl-)v(&g83*yVsa>;*Pd@D1r>ePf*e&y&FkUKW!)4!?9T6ow^c z@geRN+Ka9+?~FVkS;O)C^&Vt!AfL7YlDbcFc~FXhQEpz+39J@@J!TwOFIgn`tS}ty z?ik^bYG%T7{UAVpQz|*tl`EH>0M=*!q*)-8zcG^env+NwN5@a+@6?9RR%Y-I2vGF1 z01Vy3#v%Qf_j+cLN0!Hc;h#>!4A%N*WTK4HYytWb-t;Hxdhehpq(hB zlI#p5DHk%s0y*dbPx1mD)`@DmpZBTqHiSLIz%FIv-V&Yl8dxvYcdWH zO3u<;@Xg{9zZ$p zOTsnH9`TKE{=dv-RA7M@b{7A^9fO4MSA-6pL9x%{3*Jq>uuKM3s0_M{RPuz(O}$*) z;tuw>`0@x|Gpt1**!(WuHe#_w6Vjg! z8-8KiD1U}%;A(Ptn!*U#}z>mzQj@6$UqF1qP5gY z-og_t&JCFCu^y-C?QY*IWpxz2ANwX!e0SaWL#yP#54<0~cV;n)Z*;l66Zy=XCetV( z&=1uu?$&GYns45%V(;rh6uZ;ZTl`!5_QK1GD6ZYSHQ5GQcd3j`1D*LtQOIDE2uyOb zsSc@%9tq;JYo9V{oaq9i5CuYG(Y(J;6gkqFB5>%p2HCBnd;U(Gn ztezy9oHuu}%n9aZv0&fXS zR7?0?vsY%A`1?SZ5D)_Z002V+HZlMJ4`npf`k!OIGD>MBoMc^_QE1Cef1u!AdBL5!-RDdf$neYLhK%<~=OHZ3ntyq%v z^(?}&WqZ5VD@HBd+Z`K7-P(1x>DJfA#$6$xfvf_JjX#HMqT-S`a8@3rK`biZ1ss3_ zz(jDW5Fh}6007a97#N!o_ILhfTg(wKE51!SQrei|(Z~f*9^&|6pdyIyv@`^WRt6&w zPRLt=Npi7j%6L5@FQjYAckRAb z+GARk<9neiqaxhD7@?lb{iJwdbpa-v<*D`Nkz4+kH=%QIbO60e@*0M(*!mq&Wx~GpxBUsBPb9-PrK+^5#{JFY%$tkwI~K z!zc-L$YT2`6|e7}0hg4D6$LPv!}7+xuPfFMCR18fFFe z{iq!Dn}+6$)i-8Sn~`1|MkJTY-TGrzl*D|c_GvoVLH!^T7VU9TY!*u`okmkhU~(Og z-mA?%)1hcOmB&jKT_=k93 zY|Cw!VZ7eR;1in7@HK5WUyAWg|w9E5vj1|-%rImmw9s5n;8@Tn9T)J7mZr53wY`8g{>J#33*d4{oqP!U{YjI>Za>8B0P zPbd_;nqGOaxPKqvx~q%YyXZzfo#+kpldIZ}ObUSS$G*1IGB@(Yxz9}c1M_ck8Skre zT5MPExl5Ik@q#O(*W#A_o*H0LweLAnUM%yoN*ErGa>*G{?#k5YqvO6xYH;NDlY~Ov zD`Ddbh9}uBIm$#je$b*TTHyr-H#5X{##K~wnu}k4;V$~yWiZ{)k zxR`w4(>opxl20M|Ea)SQdlDt0kL_qbi)FvGd`6NX#sWidxPbeb0zon~tKNvxh(Lk{ zUu9V*=?9N?*kUr(&fdy&_ny;Y!AiJNE7KxTBw);p2sM(mT!+n*M^fz%6i?#=zbI~S zy?&Xh59mJ%uFPzpzHd;8CMoBe6;VOzYQB*4at(4o;{sr(Z9tt2x2mk|qAu`c1G^=G zoORlUr-fu}gPAVhal1CD z9y2v0$|m_C&Cwx)U(v_QeiR~Q34`m?@7+~w@um#UhwE&vvk9ufPZ_*ysOGFLWM>{4 zybRYPZ_`EWd_O;I$EeXCIMKZfwivcPte#j!`MQtYm|<vR6VcEWjNRhO~&AClI2`BTnp*Z~?B#5Mp1;mU3) zAQA;JOweSkKnCFhQ8jO@JN(DnB|IC~!#aqsp1i7&YB@Y=BME#N>+oI;tI)HMGp-kq z-$3j13&_pkf6tb7fW!^B%LG8c4q4!!#p!V|o5nlkF4XstSVU#Jd*#SKP#s1{crPMj z-4QssaOMCo^a#jqK@5&%PMHSiWrDikr~`92uHxyt9hZY(4EeurXD2#57Ft2Cw9+w; z!TJJpNK}~5qoiGMo&C`us1uT%&j&?{eU$u>UvjA8;*fs`|B$aRuHT?87)>7+6tq}@ ztr>{AK=%_g1uwDIHvIyf$z7<8n-lFb#j3Diu_RXm(r~oTd>e!}c0bYMkqb0@G&wUA z-p*Q4>I6yvj(|0i9MFudDmlhNkb-VbT{;!3%qN%*w6ctII`*Q>&$i#`~%!_ zKqasZ3Alojtm`~{!d&}9vG5s*0Kaf60F_4#c$?k1%Qn(N89GG0^ZLi`8ry4w(|$js z=Um`Iq$IBQp>}14y0vfr9yglY%I8%8<2C^aISeo`LXJ0`BYnY55_mUL>{7wgf;fzs zPC#>ziyZ@y4Zy3(q*P>Q_c_@zhFAv=70IbNz{iN&U9Bk+LfBEN-sSn(Jn&`+!i01yp; z=+j`2wi72GrTngipnOT-$4j%Xq~w4B=bL=q9AkGJ&mwg0i(j2>$LZUsDZWIWzEal% z=0E>EM(QFb>m|M++P|2^kd0-OBGLs8)x=KFU;?^Xy>i9}9N280y89f=5FY^-lAv&{ zu_kz=GwwqtfI8*#?YukSm_HWxJ82;DPGxX{03@agtj?O&$6ogH<^*>9_WYQjx^E3PCwqZi`6~983WD9 zm+YkT;7Y&L$hZf|kwgLz1f3*W4uO@=29ijlKuHrg1uG#T#iQu-91>c8sptQJI6P9= z{1NK_XYo>_#t}R_ly+^5frGa>7-=5Z?Jgap|9@$l$VdZd*RM!vP{^=k$vv2c(lZ1N zyvfuv9v=aT;OT7o;S3i55wvgyDZ}ggHAwm1(X|Kw2^{Px50oDJd>)p?j$*B?>`W(h z;Qy8c740o20TePSR{#KT9=4Q)3tFFy*p%@|_@UV=K$9uO=vs<^Dgh=MDyavElfiv< zZS491=mI+@0S$xt#S~)`Xj@iM%{!N2Ylq^0(+ULU;WRoT?1woAXu$dpR{%%SKcF=E zcL8&F=zs(c!^;jh-X!w^u?hPhi|gR@fB?@ua;~{P2mb;+!UQMa{W=8#@<-bE*Fk_k zfr0=9bQ7QhQ9%GK{9$SWNFhchgD*6-WAgn0j6&~g_M83xsvH!72Y*o5X9fJ{)L0m7 z0Nzi2KLkpEI;71kqUyjKc!w~i81cwd!6}l!*QA0>FvyflAL{_`f5&(a{(16POiMI^ zrT~g;$TSHi1enX!K2JEHofCO_NA%T)LYSX+=}|l}0QIg8a)$FHhSD8Jz}+y@3t^d{ zsW>s1zK0%^&Ff7kGI$3xboRg1^e{d9sXio_6@Vn@_EVN%0B{fx0{{R3Lo`Ms000kV zG}Zc_X1=Z`L24#R)+TOfK+H)N5MC_|dn6(Fw{`Y{Z%cP}33X3f_uq8<0AOYYj79*! z0Sbtzp$6*wAcA#AWTibE3CTR`s?M}{u80>D} zzW|IamT#La#g;5*PFTf8SUcNQ+NPm003x4?ueiO zyWe-ed~dnk+q*WG$@CeSB$FFi)^;T1?Y01XK!d*|mp->5EgKM#1`6>A2rr11fDo+3 zLV-XNAOb9q76d3Ig(%A(M4&h_K8S!+fQA78D?dcY(CA6IJ5x0VK9_oGzzns3DAlCo zolJqE2Yz)ICYkI#rJ#W-4jV<-f$^3yS3_ubhsJ3xy`z$Tu64>NqSn=WRd1-w{tG zHB|q^%jAB{@oIB(ouhxhE`m} zwBGoW1e`(3v|nHkBG0i&7YQiorhuYU$~6{SaBZJU8~u7Rk(re?qvh%DXY6$wUD%bA z_gdNDp2Ur+`&o|6T|KAgGD+uWv1;T|ux8qX_yPpXie&Dv(0*e}aO${OO{XQ%I!y1< zt0-V2GDnj104ja%NdvEIn64R0L2EHqb zQ@w`VKL9^CV<>66XX~z{`1!N$+_-C&~SBu~=to((b5w zw64L%h0s=bUoJU?$qIiA;==*7GJ&<%#XS}LekPN?lcL3oH00cNns_pknwJ$wr~hip zG@Yg<=O+=Lgoy%&}C^tzeVeP z-`-#W@Sen+eUG6>z)8}ObnM5|J7$cbU*n|1CjcKv``9AU6KTNw3JS@?N?tE4?=Qh4 zm}{zqZc%d31!IBEv4}&vV68{Lv2_%7w+{`51vcKV5BbRe?~^BHi#WTprK_y~<#DRe zUp95+SRt4jjkVb9Z_@Pg+$|ks5qmD$U7qGD+VPV*AaSwft`QGDcMqyMxG?!Nzs({b zX``Z6`=mO_3IYUCrF$_to^yNyuS`-9(ZWNLK1oPI5V^xBq1fBG-aYkQ#|6}c zv`E+CS#-FByDgM!3Hoc#9vA9QMj7hf6z}QUv&gf2D}k;#>HnqFKYprwLvI}^1eJ24 zD90qo0C?`9&Pl&T_E(}1&lkL6n6c0CC>KXvYd{C{*=k}ez<#)v49C1@-F2nsRV4*1 zX`XVgnkw>Z-R=lK;>cC2^SjZRCgx(QdpcEt9ZHR6=t-=#@@n6cQ8sR0S0rysfp{fy z@CLqKYi{$C?Qu)bQyqLnDROI-cDaQsoAVlUMOk6CtS8z7Q?ApWEsAfn?Um-Mc$aHX z^oTGu%jM2B|AJAh(-EdE@F;qn#dAx<_go!;_K{ zFDWeHe#+`{i0e&j^jtPXW+Qev$a7dRB-Pz)x^))Ve4K@DCflXg6e+;c}-3r zU(4{bnq48iF0GM=LSr~GCva+-lgn|o2WSZoG84xsBL(gbDLH5q!XM)%U%tROt!sUV zZ5{;8t#TG9h3g-Qd{`-kavv}>#Rww@bq=9dKB^vj=nuqDZ-9CV!NJMr2B6C7s_s8E zk;WPQ&~y=*ndIsCl)CA)dfhgUIH>Ark7ZeS`GY|#(cCA_s}hrXsb^cI6Gzooj>xe2 zSD~)^v(HVZ*CIE9i%j&Nl*(C;w)J^ug-p@Tf z=-79Y*bhmrX6c1K5eaV?Xzq--qwz$$F_KLt0)T}&c{H)5YX+qG_-_=ZFVO*88A~30 zf`vhpwGLCpz$ojtm8J_TbA=Pdlj;;!iMR78`bYeZIIipfVW7;HIWBwi(yoS|Hd452 z%QcRh@uI2ppaBzBKlb+3H^#rq>Dj}rcR8*}d*5IKf)COL@gWpW^`IN|R3kfNx-f4OrIN?fdtM5ro<&nM34Ba)ME!Q+e9l=%)$)0$e^D5K;7ZvMRwjk{ ziL`~(&=?Q!QpDpMwCcKoZVbD?DTQD~%-Ct{?p) z;TcLu)@$<0`t3)qSG>hy7(>iQR}9JK`^Fa1g}E#@jP7J1Bi=HD6%V86!SX`=5tSDB zzF9V^%JB1=E2_~(9dp19*uax0J=~`|zAUk*m8ndgh*WQYiAWuUx*&%6gr>&Kj_wbnnHI7w?L z4t>gJ@yeIBIrA>ndev9vyZl|{vdO!TA<4v-{3)g`gvZXr>-perQJ!mRt=TKAjv>N- zIKtB|9V_e=vBRsV(sXpzpEw-Xy{lC?-0CBpQMH6u4<4s)zlNXOp!HrWPi7&Do|7QW z0%Dk;Ma{^v2dSs8XXm7!K8xbfSV64uM(B90e%${4l^x_{G%spxkI)ElewA05Yh-2nq z0f&2zK-sd?|2~TvmLuK}tl0QjgCY}<4veH}LkIp&w6!q>AKkhsOk@c5$UY*!pUqiu z-ml^7s#LIjU?UcabS@moFPX$qMj2%*G~q=6V9kqjaXd?hmCC-1+E1fhWoBRYYa3nv zVJ@0~bCf&TY*9+reoG=FtjjSEU-~EA{;5x^7oq}US6(C-jUP!w+IP!9Vu-!{pLH}r zCHDG6bTOX-@ecDz=@#jQb(c;xT!9X{gx6tA9@zGcBi~xBkb_p_*A2Vg2cG3MrB}&+ zLH)BI)S3@}SGs4a*Pl-*uUeB5ziIU2N2JgtnAd3)5Hb{P#!;&YDz$LUfWHTo)K$=` zFciQshfytESp8>e$Am8zb$)_<@L4w|PJ4PQ`~aCl3MVZ1fN9cX7m!Loym4QWvgKzl0ZhW?DqYuc@7)0gaa`fi9MD#R9U~Ds ztsS?i1Cul-DvV=qtBA*lNWB{Dq~Uc}Z-R9&$q_ycK3#l%rL7|`Me>w8hR4>%T}ate z7Y)RLu*AIvVsQ9f4IrQfaJhi!1rrt@hNf?ciUUfaHrwY#cmFYbunX>hjS(L%VZeBy z9p?h6f@B&FU|=Dl1s0otQw8N7$Z(2u9ZFVGGustEjU>Z-kC!`2#x{6SOnW}SC{xa0Pr#**20k%nA6I2s-Zkr8nZ z#Iajh7FmouzN^P|WDcSP{c`@XZqFc8&6K9xBFGAs>)+i;fOu|kynAlI$Au#Q-leVu zTTp()q_CzNc~(_N9CXAbRPEHaBPt!t@zke#6l=@D-Ti-(V|#(4V2En0uCMM)owLO9 z$#InKZ3GT59+y|B_6tk?t1VH(M}_U1bTH(5$A`!+{!mK#~*GHA9jLgem~-_TokXI*CQ?t*sHGfz_^dj+!{FN2feozLqSv0#A}v&SO->r(?(8NDlD!@FDLcwrsJ@C z7PJ>&+N&y|crR@bumy3KmfTiFl$>zY`De6KJ8% zO#Re^BqJnavdr(bxG}Wsko%)J#qtb*cunsx8QR$6%>NYnMiRoRQFGp_AJN}RfFYGPljb&@VWK6f?QDi5{ zgeH6!k_uu*6~PlO|`#Igy#B8EAoyHB$_9p}QhJD5Lj zBW=P6ftjtAq)3vYtBxv>sBC@ldm2JJPYU0p$;2@p%pK+$m?o1cj_2s-;Q^-$*3d^> z)qRo9`q*nRnEhrKp=aaO6tSnB#x%^xFf3 zG?X5v6xVA5&X))8;|!QoemuvO{l=f8=O)c<0_Ql&Z7q&?7p1Yg+^e-*w*FUF{+rEh z&peuNlzCx}BXE)hgnb;gHX-1xxoTt$A?*dIkF*V*4VUxKpkuI-H z_-F|oEDHnr`y8v|eBCKY-Y#H>5qCon^^h{Zomzc0h@)kIAdlC;3E>LE(EkMIfuV>? zps5RZ`a4WFHqkwB=!u;9v6T3La^O`g z(bRaBc}4RA#a{tfZpN`ini0S=d=Que3S2;Pf(VNmUFcf;p%;e?-pb&Y4=VgUN!{Nl zOXR0q83$4zi9jF-My-s97l8@e!Ian$VC3-Ig;D&lzeA7E?PGY~2G~n99^A?XEB*nK zUXb|o7>F=GcL+Fu(Sr*-f>2@r5J1C(T*P|-0a5nOjB8Q+Fo*uX(R~a9LX?(bY7hXl zcg7_T5l{~PTyOLt^5IdKUMRq{2m93QP-CixSTQ;nO8^A3fLuZXVein9>I47X;J zpLrf3b3nuZTW%gEX|jT(95LYR0GA?WG%j%N0N^=5Pz^(J0hkAoUOq09Ug3}}JY|8b zBSsTt8K!hWw@~v%9-=&{u=L(>t#Usuboe_+haM6Nql? z^D<7%?WI|<;z8Sw&G^ytsGf8&z`3OG8{#?5AA(h~PmopNcSZIO_sYz4*W8q=x2)U=a!q ze);Uaku|A+OArtP0000q12!W701ss})%u@gzB5kZlEj^qJX6^eVnnbI;7MGH;h z8s*%tHcD;NR{i%K{{Rpf0HPUyy8r`3ERz4}K!X4PA^0p9P1QhXP!F=gT5Rs!ghpCg z_O&f)A2ASgLIT~`saS?SXnsjf0@wQE@V zri+7HZ#;W4xV+YS(~if8>$@?SqCz>6;`y$pb7Q9>R*28fv%xJlh3(O2raotnCQ)|V zCGoy&jgnJKF5xvc!n@zZWp@eQZRijhNB#8uYQ9Bxvw(RA;GAYNguydSBDT0%G}EnV z0m0yO6~jg0xRgdgWsTe6Y?ieZ2jzf;L?yi6@?*WjRg;)Wfvb|MxbKmjEl}+`Oe%XO zxn;KO+28tP%GWB)STW1U8XF<6_J~VJilr%m!#Fi0n1Z`Q9DT}xnu&u_IK@-@N)|ci z(Yw9GS8|l7<0OSs08OWmU7k!p+)vu9(r$>b-)Y4K5r%GHEDh{5uITcpVyX?|>Wd^= z>=?tC!K1fMCaSL)vNp8~9@9(Tbecj*qo}0J=$N*v##y&9mKPXgZtljOrth6$;DK%R zM>5PuNK4X32M85vM@xh*#-+_Wlq?o23Nv#ract}UNmOKmVSEZMn<5V4;?re;&b&%Y z7^K5~Lf)ZGJKQu>SJLUU>za0^QR4S{!huotiLv%UqGHtEd)s{21vAm{MR+W`2?MX#2O;s;e z(plagM1AWDBLRqooqs3iy3E?L*joE-mg}Wsu-$qg>N_hfHf*fk=3*LZ1v9YlXi=4` z3x(`qrA?#_P2h?V*Qp6ZJTYOFwLddxrK!^!htqI?51YbLINURH4Qd+CWebzk1vD zRu#l|m1_2(x0kjX+||h}mbtohX>t;muQD1fy5c`mq+Lw8HcLv`A8Aur)Gfts470Kk zDUY3&qxDHNQYmyux%ozY!WcVigmA>1=9(N)^eh61EN019L};9O^k#>v(AX+=yBzD@ zm-U6#npkx%*bew_qj6mNTA3f)OO(~nyyD<@Gf|N~Z3PySr(99ccG!5_o~XBXlde;?d=RdMluA+9B;IBoqA3?1_oXK0f2gLq;Me*y=OIY}fS z=inlmrl#~o`NU)f`4nd)Tq{(BEoW~t8RR?Gs%&T}PlO=|sA~T2hUg9DEG_@{;JJi; zyEVKgQ;qL2E`;UKIK+7-X`-2On#0b5tWoy6gpGZS%6y80bU-3~ zEhJb(#)(03wlca48T~-<-NN)$8F&(ZbbAn`kPBpl%=0K74IkVomn>30It}uCvM)db z;egF}Q^FbpX3DJ?Q-mFy)}es3ltypC2R|T)c?5Y`9=ngrc|;nb;|}6u9QmM%$IZl_ z;ml{NZ-Tvtw1j#1-_e+2=CM7}ms3fcn3Ok%cNv&^Z>L3|%(>l^Q(#aB>bL;#V7eG! zt&xMMgAYi)$b&qWm%!Q$q(HCRbq`5^xYx&<54U8LdNfgBeAxw3chBWe3%d?!E%Z~E z7+3!mRj#CDYg9Lf{1$~%UQ%-MjqOUHzSsN`>;~SwD|+!MBlKtJs5HZ0Cx)$hH&3tFyO!O$~@J2Xb{?9nGnCE3Y4*w2is-u^o?U*JdR3Ud7?k)n_?6SSF* zhvATwF~K|@WU-2Rss_V8gOv1#Q|;ez73J|YDPT@*0VFkas((XikolULQ$ZGe{!aB^ zNUo1NgYg{>En7~?bTp^A0E(8$sagz-iC(LA9C-~bg$t@69s@0((PO=b%t5b$olsQ7 zQu!BYMjh1s>SFSIKe)?9cmK$;;<&RS|J^fwtODS3>Q>eGKL+?vmI}A5Z@36B7Es!lb)^=KvV*X(!YsfETaqx`x^P{`dhrgNz>N8Lkf>u1rF=GU6Wul?N07xxZW1 zBtVT@o-)O!(Pap&jw6{j!iH{{B2wIlop``?dR{n7dz}cx7 zUI!X^(qRn;-T<{Ae}9S_mb@zUSw|$Pw1@2yU1HpaDHk9f?Par=k$hj_yyi@ON#VAxe5z4g6{OX7vA_LMWM^r9%*TUm* z{s+&(^eP-17E76T@cSoH_%qJ5Uwiy6UjZ$Pn0jdBFX!5}x%vAX$vbqb8Fgpg3z~7R zhel!(jq5-kUMV(mo3+py*G)A|0nk4^+Z6q8Ap4oQ@a1#RPcnwF;)S+cXQP!@z8~A$ zzjJNOFg#?DHYgaanxU_WPc1i@O49Z&SB6VE&EYi5hrzAtfSebVl_2+rD}G;vbJc zK4EAMXfuX(u%*5n2iL~QfqI4Qt=r@7gzp%Y`tfyUQK~-@>?V;f$8o=Ec4^Jxr~Bt) zdVa`Ob@9r<9;X3*M>?~`0)dIBw(@Fo+eaxN`Am3*|Bk$wt;Su15O6}kwme==erOnx zX89YU;gC4y7azn^UU{Rl;RUsmu%3DoCJ6~2zG!OlAxUfGjPZ=R}!-!~;BDgO2Irr7x3x9YT<^t`WP z_op!9yV|LhWo_qsb+78u^9`LrZ)zf!l+qG$Y-Xq>T<9&Jy%Y1U?LK{Sr8R1B#w=Qy zUNFyi4XjhMRS$(Q4k<`nre8|jD2+N+W802`rs7Uje+Wu-igbd}A4kv!sI(@@#BqlM zQ3*Mr0{i~g70W*0AgAP{3qCt((9wP;p+(1>0hw*dIo}8RBwGogZ!iAlsMm(ClQG_0 z&r6odncg<|=?isETsRA8boEdL#y7z;wgtu@;mBA#z=DBT)Db-)I|uA?`AolbzEpc` z|N0vum7<@Mb}{(eAB(%ogm(Z;5JjY7g8Um5ut7kwpa?rX4jjrY=m|MtWEkFW7cyUu zN^<;y<8c@ofLkmctlvNiq86N?!g};ig`%EUUqf_LE8&r-IAplji2#uwu_Ew3jdl@j zYA?GV;aCdt4^f`227Lhjv^9wFa9pTf_@Wq)1-!97!W(r`pTjdATcXMlvjUHcR+Asc zU7kNj<9SK9cX_o>2-1ukzCZHARli*B#tqL2lhj#m)6ce*8n|CJC?!K%!;?ztHL;%vTbK#CP>ex(WP>Mn9(w0R3f~gM3Zf zudIG?y==~_*GKmiJAZQz|E_s28cXS+t0^uB*BU;o3n^@@G@r%J{oZff-yO8;))4Ae z7Hg?az*JdW$s!#E9M zjHMuw=BcE+6u9yhH5Eri&v?BIOEtw^v87fmMvyO@N6sXOAvAv-C_og}&nTMpFf_fD z4;Bd*tLAIK?PXcirpy7-eS$AfO3#v@WD z@OxZa$gWoZ<-StI{m2Whz)n9@F;5L!0fnBK$M`GG^Bh_+TxZB*tBTw&^JLI{HCf-U z^Co4V8F|I2GlgInPtAT15CZ@J07L^oA^-pnRkAE>Uu5cryF|$)12nU8G^QYM>%j#{ zcL=^0&Tf$1tLJ%bP5+nv|3G*E07ho+iVOg<0Dnr9WF#5L0tP@Pd_b166jc{GY~8lo z+}#Ugo7#Hz%3X~u*|WRta%`Dp@AtWtU7PX3R~*S`ZI|)!N86TQ_=Xd{G9ekIQW6g$ zS&$GTen5ioJs^<)03rZLHU)tG2k-8?yZgTTYUNKvb{Uvbg$t}s7;F( zoSP+17pQ06R`)p}O>Wmy_4ZXkn=Tb`gROEv?l2U%-FR`onvMUon*Cuk`9 zYnv+gO8n!pZ%J7&1fH#T^7~wZx&P&{K2w9%^wh3wx>e*{VXL|6D*5Yr3tDj;j7-*2 zCF(_FwyaU6qIn~sh1+r*pO~lOIrg;I*lJ9H&TWTdo{gVS8#T~jfDcz%Wro$JqqKv1 zXVV_%R99DFG`a>|d}jyz+0}d>1zqP_!)vj@Rx4_=k_~}xnXHKVmhs4iC-d=F$ewOU z=r^)fgy{IH2i{ouSvnWK>pXQ71@@h+?~aN?Uz(=%I@`%BBto zhF|;4QaY^FaN>nJ{|uYT4rcXD`XxgH`e)GXFFvb<3>9{7Uwahd5i?07g6*1@p}Ou? zzoHIP@LV$OIE46I-qd2Vw%~N2r15M^YPmH}VS$Sa*LfcA2M=ZfCkC0hW8;t=#4jVE zFJej!U4no_WG9jaK-x>gm&`+h2mY(*MYY2I_=NFllqms@cm4;B;GpA_wQb-jb6Wp0wX z1xn*uL(2No^DemF&N9DgW)QaM^H2Gk6|q-dt-Z=7n^&CN>ILJ_^x)p`%^C;WDB^XJ z3#@}i6D7SE*&Q?8H`a8~$^Pdo=AY@A`WLW@ZvdwSiB@{C1Z2APFJVxeA++^y|gFLTkG;jI9?+}ZfN&lhd>F!5lAR`k^ zb`#oV5G3Q~Yrv)U4h&LYf7kBGvLyJJ){x0T%WvpyeKAn33&9J@Q-nyZi{4gv`)9d8!c!%a{aU(MZuyLRO zBLH}jp2pG;0W7W4#Q?^XuzeEaJ179WQt?&f#tY2v%F1u9PiAGB_u~M}vA2r7wMZJGyu-H z6T)cl9JSp&t?UBPAwdZOB_YHL)2B(I+ImI*cRN|09(GanArk;3k`IAyxQp~N6Hrfl zpq9XJ5~#2!A9yq;C2RV5^3y%|Q-AsuOUwfafHeFAb%o3NY6Hat%97wEe#iqvg{(-Q z+wyyn!l(XWwbG!E)(3zwzw$r=Kz)sYV#DL6ZvD{Rc%#i-#WXmwC z%t01J!A`H9djzsk^@6QDCn6au(kW zU8gD)qR9}?#gc61a!ieCHZRNkLg~*$0ih{D(8LqLDM8ru?@i==UerJ4JhTUSc_@Wd zq#?h@-V+H>mGj##Kk|!ku9*kB5yKjE;P#ZJ{OL#c1$j^bzz@qh5`!Yc&Ff!3u6Ci_ za^DmLL)d7@y*}nXBc)Cp!6q>Dgzqj3jF$oH(ZVQ~CLv$4(zI{v{M(&{;=i*<#VT#? z)#{i6fGP1pN%HeF>ZiJolhYT5lex-Gt^BE$h}$}P>c}_I5ipLhACjE6-Rq!BS zv*HAjUZ!N}(oN7CC!rI_KFh1$nzHb|=YvnzA-81+4HHW{A<`UaH9`cIIjI~5C8B9fIXqRJXVkp`KS{>vk zse3q}daCu1iHG1)h1O$u36oakh(E!&QQSP0K_T+38#+oaDvOHP1YF391RI%`y+u~& zdQ`zfpEAowwAaeuH7lIIDfAi_W|<^Dr!3;n4DDTuVnkPpo(?UHx#2im+EZ=vsPC($jB z@JjdN-R&;9MgG8#AfZumc}L|NOZcJ|B@MLLANDs4X5J`kZMkCALr3mWX$z0Rw=oC@ z9w_BA=~#hc17T{2(I@1Yp!%a6$G4d7xzng9L>p%)jL*{p|M+)uuVokZQrmXh{m2i& zuh8r?^C$zNJ9kb>9VE34{bP02Sceorb)S3V74quZ~qloOB;uX(_O~ z#?zM@eWB{2=(vjx6O}|0f2IlbRI7}Uk`2yje7J9M^8FlwfbU8(%10&4vt3e@z9*Ku z`lMSFaiV!u7^4M_cQ_X$|8$`aeXRT(Mwo7{WFNeh*Giy}JGh<=(d$aQGG(Vy9J()J z@wYyzto3T6yb;G51z7RQX#Z|<{%_%JO$;^2XC30(A3GA}qiG6WhB0 z<7ZF_;(rmDl!L$k-zgY~h>}Q(k06U90@6myVMOoFeETguiEa=*Mhz3AR3J^~P{iJ?~dxCv8 zXq0{ALogMK%iW87yVOG+087I25C;eUzelqa!l(hs7UZK%4e9xQwnl%WX#nc}7?iU1 z(X)q6sxU?b18UIH2mvrOh1f`7{-Oj!i~#ziDB?+=ANbxGISElrFn$x;8_4~C7r@Ov zBc7p5eb`3;AH6ZCDlCQP0N#Nwst0leSQzWmuJlJi6C0?}JO}&}ftwlq@*1V1836PW z6l^m2(f0;SSrCZ?_-dff3IV4@-E>Cz{)b5(ssO;^PW2`x!Qmn*_-rBK3HZGssuy$R zi#5S$*MB1z`um}kKrloH00PqYl@3GPuO=hIJG~S9KPXp^BCoI^{I}$UhOps$-0+MB zny9KM2ij%5LU7H;@nel5*8$m_}W?CNS znLSE4?emHB_-5#Sr}Ka!eR)y4vS)!S)D~(pmhjlWj4fWPLT?FFU_l8uc;n1KHGxkW z{G}PoLa`zH$30XS8X8F9L;!=-0Tcq%IJ>G4q1Rb6nGPC6NSRYHrOA(ZIrkbT`HR{y zzRwrN7&G(ST+~J%xHk5=&Y2&~dKE@PZ}aFn>0FKzWv{c?vTr+aAwvm1N`=p4I2xb^ zkzBUo{4?)}{SY1$o$shNozATFlD)$a&8LhfMeZAEjfxof_Q*-MR0hT}=Ih(dmOBk4 zwOM3nZ^+h7X}b1jKFLHf>+WJm6-bP>RMNcaY;KE(|7>H;Qk<-c?lDSwvabK}nJo$w zf-?CGdzd~yS7`wI^!{fV_Jij^+`foEyl6xiuj+T$5H7s@wu!e=EojO4Z5@)QwkXOQ#ZM;1on z>ye=adJA?%uS%HF_)1@6&90x9nqBo^875ioxF;de&ei6@%E$j~TVVS!cZ1LxK}Axl zO^}CUz;;lTl`@n6dGsyfq7K?sCp{dml73N7azWrr$w$9Moz^a02a^ldEr{bv;0%UI zt{e=wxue64$c!x%MzeaeaWm%}g*VQ5S_=s*WNf+qtmt|f2z_s7qp4c24HLo_J+j(y z$!Sz7Z+@Ky^P~}j+#exU47z0d=whwYj)MNfY9(BvPnA9k=Aia4A1VDM0>AkHu@Ddg z0000q12!W701ss})%u@gzM)St$s*8BZ7dEgR2w+30H?e7DPtjRZLQBey9sqqTle2| z`~W~k0E=b-5DyF?Rb&71C@}&8Ld8b@r03jgjo;ZqC@2 z-)-+-x0!X0w_DR;<2Eki5oB34{&-3cL8%P!JpmYeX9!2Y2~Y?h5K4dmKmY({Mh>ju z2)6gzyUEs(rmOmp2LeQT?_uF!7zIK80V0AW0cemwFr1Ufc#!Z!c+@6gOSBjo6c37o z7$xKo&mZ(gjFPew-K3ARX?(Fx>?%+-A};ZO%mdB03*;<2S=BW(Bb$ZcT?NkedLj1S zwJPkS=Yhb`6x%g%#1k)8&>iUc1yp?bdfUA}Znq)p5`m)NFT7iC;Z_pK-g>z0WpQwt zaKC(cl@rHg?6ZZ9`D?B4h&Nn;6?PVJLanv2vK6i~C3`mVZtl7;+B^Rl@5EH?4LvE} zZ63eXZrQhPvr$7eT5-JEjIAV^?Q4-qZ9^uapYLW76A6tem6LT;fu}MRtIuh2OQdr_ zM30X`Oi4{m`ofA+9Pc-__5?oTSeOP!h=!S4`x`?0?wgoL!tIfDU0Z`KXH()GVBSr? z_hmm(O|R^v4Ut&gWFMhcsYW?9*)4;UOR0WflAKPUXDN*OKZA`;@3()+6Wwg=Mg|No z^;s(Mm=;H^|C!%UBshEw5ATww!rceM%tMM?`g@_Su+7;S7ro0j9DH^U>}01Q!_XJ0-K0vb=&GX)P!QaxkC;es)-2k`TY4K*q7ee3i^+YhO} zDkwQ$;l5Q$phk=auoQsAs(^JYM880*yIg|9{a*;+=l)!W0~VwKZ1ETL0eNq(qo8;_ z1w}L%&#o*{Gc!mJWXuIKwi{Z!-@XQoek{y*W}^W7JY;6#E7`ZJWeN91`c-oR2<)hu z>+#@bY-KpEP-N&HfaYzhL~Je&fQ1}OW!hY}!kWpix~MqkItVKB0&DM-oaQ$*AnxJ*pMKbTs=r&$ifZa%J{=4IBzlGi3kyqM zEhgK6f`P>@NZ4I)V1i~y@jA4+F5ZMg=F7w7s6eF<;|~LaybKKdok|n@+w4T7W(po& zqN*9`4GoC=j3Ix94io^0D!@>e=aS@K?S;Ju4D*7+?t23Wr1W{?ylF-X0Ejv?BhF!> zcWtC#t1-&Dm;T<;g0(A#6pc+kaL?e&JGRV z#SO%vF#1T;R8O+xN6h1bDOZ2vBRrQ-`mLB6rZ19&zqYF_0j#fcYrHl(#7Vsy@ zrYlZc;Zhg?D_~$z1(vv=0L=A$kjxB_wZ_uGa1{zbY6#9ZSA%Hilk#bnf3fTkoC?5k zqxeI>>>&)9?)V_Gc`hUX7+F0b5?X;U1`v2IfR;_{4yhi%1Pw)zSarxb_9>#;T0h;p z_z_w0Ni6C1iefbh;W*a}0Wf%9dqp>$$D)He0Eu`9GaotaMm@n$4sZqlL&|J3z8j9o zt4z9Oj0i51T<+H<@LR7l3iBV!vx#bO)8YsF@3hFBPR|Y$EIL?i;Pi#C@UV4)+kYQSlw4JuJviOm2pvSNx zx{hvth}rUOUKXlW+g3w6CsT)rVCV7ZC{H-H{5O}K;R0})j?MsNpn`CxXil916t~Li zJo_=(ItHS>?#Oe0fFHiODo5u!fSGtR$cxVG3M7v7x_u67UJlk2vZ(_06}Aq1JdxR@ zjJ$Oc+HCp_j{iBFt-aui9%Q^8GSk=sP_YWO7w|N2EU!tG=n7PJ&SlPm%j_68aT`zp|uiNAs4Lv-CxNx#ns*#mWefR7*3hoMX0_}^-J zv9k64gQoLZBvI2(yww)u{a-6d=$hQnWw`l#{w8buYUO{&VzLO6Uz?0qoHax^Iv^!_ zY|9F}0FQ%DjCk|{6F9wmuge+;l{>5LyrJCcHuf~9cBgmY?%&eM=eb|%Fs&l2QBSm* zYR9%m*G%}={bHa?+~r)tm6ubCoOq zGyja|mM3lbxGKKsDQf;~jsxv!A^alg&TpM$3M!_x0c$@q*i$aQpMq_!PVy2evKKnO z@Xg?5mdQhF<>staY;AdMr_Pu-nG?xwN{Gcg^i3+%Q{BnlajVm={zBEt z(cYi?$ zfu$gWL##{4VC*@iyfJ<~vJU;j|LHD;9;-sBvQd>x8 zGVRj-l9+p?rGNV)yD^WIKhd)$2TqmDk$h{M_F5fmr@zvBqBmol9Z@#>OI?|-BqvNQ z;FWI$Z7}XhSZ_ei(M7bq+cp#roc=rQ7E!S`&AQTmLRz*9CR@~3_+YMG`QO=&u?z3lq=|k(Yb}ZcPQFh;I}!G|N-yDa z;|Q{%-_TmaGMKenw|(h?AanQM#jBhK$Nn$u-oHoPkE!{1g*1!1E1T{FMrjz^^+emmV#E$H`Bo6fHehei0CAc>& z8pB_$w^kb?UbA|F85Y4S+^lb9al*11WYAG{5pN!PpT$XbgCY8O zv&(IqCSv2ja{_lrNLd=_mZ$pqh?o?TV}MP7mgYM#!66lP$$d#oRc!gqXx1JhO3jwqu3}R4}R)$La( z5p9Ax&;ksn)cge-X=>!G1$85dESm70kRMgX;?jl@Yd-Fl0KV5K> zJ@pwHO@44Y>s5}zBN=DpFC}Rtgp>-mLp4g5HcP$J!yxu=Xz~#-7BJIi|x*}Z8~nI zhwyN@^O+D6Q=F_&k)6&mRWUp1`G|^Rw(tPM_Sa>{?%GZ6(YXVXg&yJJ3q z;jr;iJfR-ZG@%p+c1wjIRk0-Y$oaoQl=XdjQDS6@<&NvCe1Zy-km09(lucpQ|)wunxd0hD-8E|j@o+1#`vDW*y(OW zX8SB|Ls4OYjLb6D#}hKUvc4h)Pg8ZKASpI!5o{P@xhz&&{m~;}?km7q_7)R&&ll=W zXQ!9)_%8vf%*^G6JS=S96?Ih(HL<|1b?poAZeMGKdQH&pr_r_0lKGM$6=fLp%-e5a zT$%V~3)*Gm;H@nU12?ub@jB!xYeqb9Ec6Lvv7~T@PZ20b==iw3(mT9tdOxxfgP?A# z>b+)HD-l8@4`#@?Y|Oo6CWbn(_)jEy%u9B`g}RY2EzCuxeen&>@ww4O#i5@b2XLnS z$(j5BXF!<0#_FCjI#tpqAvVA3>?#O(rSy{PM|V2{u8T;*dbTY47Q)tnL03XhJ@`%A zg!2M1a!}ovG6ZgeTw^ATVuM$s0vx6PQg3^(-ll6qCmf~>A>07YRaZi*p&i(Ef5L#i zm_r984k-=M+wi8C2}3=wL-S4{6An@)5T^jbsw*+2unV!bKxN262PNcZsSu3~?}v?J z84n=b4t0Tz6pMT#%2`2p06?m(u$19cX>*kvqk@46J<4FI!l%U7XgkJo*og5N%aSHw zNvXji05hr+3yQ=9M>pY;K;=LrDZHLrOx4f7A@S?|Q>2PR}^d!E(80tlh@Hp&-9RnEZ+DKiD(0ua=+1fjR^ zZ2$PNR$MQLm{6h|qG{+0Z7q!Ck15+O7}m)+H(Ec&BPk4`0FcwITu*Q=-(7M`Smw^V zM&MAPr5$jmkRy!noCA=@Slw+o;bgbl*#o^BZnz|1;g8@RfJy%ZKg}g@xd5MF=bEXh zjZI?^Fd;-aMAM)cM){BF+aXf2kuh)dN{mNR7(@YRR9T`=APku|0D$bU7yRrA0~7MI z6Rv!?FT);AAICFUu~81i*K$g}w~Ptb06;9xOU)!)Tfp~RXsDNiHsP0 zM~L$VO_K9mR7hqAT;u@r$N59ey1QWF32F8S`LckM!;uahs*2p{v(g07^AXwqi)*>tj2Q)^Y5Ul!0^@xPK&kx_q1u~V)fM6ZK z0aAcqgG229b}yg={On+tZftHrhk7hGm)k=*U3hrQSV5}*lKkL?Tc7>o*uFd_ZbED- zjB^rr-(J5FYJgfqPV64Iape)*V{kHQZaYATQtK z_z#I3Ux8N~I{3;niiGaI)^3|{Aayr6yF(G|kok!}UbQI#kMnhgRYa*XnH_Wd(eAo? z%=Cv_|9tkZ^Pa3v-2V2%u1}*JCSqc{{^I2mNrvP4Ck3p?g6x}}=X6BJAX_?;X0>}E z+54j2<9$5Dh{w~8rd$o7o$DB+O4khfWE{I5wPdgnv!Ty5HQ#3b=*>q=^gZ7c{dTx> z$jGXgDNnr?29-G*77s@p>Da1#?IT`9alW$y6+@X3BJ}^*n)0mcrAxOe=(n69;GZ}; zMWsJIQp=AfG7!2J%q%a=*|TBHfND!!GA2Wa@BDeK6t$xXX#*E=v$Hem{`L_@D>pi8t!N;;)d>iQga;a{JBi32ZCpUAlB9(m+{FZ^GJpsWGV6<80%BTBE*)zn6y!jsmMUVblTl=Qs^GxN>w zWp@4g&=4*J3CYR*0Q6$lJgT3>@khpYeU&c`Y2)^|Ox0#?_V2Vm=R9KyL-|*}6fCGZ zOtPqd&U42GhyLIk6wH7(f)b_XP_VYz-S|*271k}n>?|}CRfXZQbC;M!DA*2V$n-EM z#!yuNJy$|VJ;+S722$jh3>PjG(v5=ok%gM^ezfiw0DKS-0{{R3Gh{F$000kVeAVBV z-|BM>rEz2n?i#^Os=*)yNHhyxPa8t;+QvDT)o!Tm+&ka9{P#d~4gh9k;ED_Y*#LhQ zK(O$mLK0a3neYZeU|D13)egO733ID?>n0s#mfZH(z@rg?)J!o%HO)y~(ec0J42JL%-Dy!D8 z{?kqxaK*KhfhQU1bDR=wwbgO|W@U}itkjlzg0mDcBFOBV&gye}YRiJc>RRsyM_|b8 zjOE@5YFWSemTX!q64|CT)d~iwV;V)8p@3M3w=0|MG+&?5t(Mak(owP155E%He?`G& zk$&QEIkwf_3egTz$m%epBleaI^2g{2c-%|ZH)Wp1>XF>wWO8>QzUys~UZozzWx6ibNUK-vuGCRu zIa48bB4t_om~(`|=ZQ{zO~B0xh62Rot%eYhr|l*;W499){;Qszw3{1w&VX>ShuEmk zG1IJHoa*H6*YEx8DixaQ?xiMaJD2s>NB^C$`OtjpG}dX%(AO#_&8kUFj{@+xSelu! zMWVYA+GJg9Y6WHlV`RSgBHUofQ_=IE3!!u9PROUpYj_?qdY4ue_qe*$J`pRc&Tvnf zBh+_A@uZ*n1a!UodF@shDBT~~e_Bom{Msc_8X7)|71>J~X}yxsx_VElh`onRM-ki( zCWxxEC~R@ukYCND;vLmklGh43=|1ZDJ&fsoI!RF<=d;8T)y-X^`o#58hQE-=2s&;p za-hM~Hc0Z48XqV3VZ_j^F3{O*FQF$w?{sYFl-Xn)`ts{e@f@D|vrIYmETJ+?`w7vH zGmse3QY_j>0s#<`QbOomGDdV0yhJo1L(jE2t`V~zJh78ahH|X)+(e#T_1S5X@7?(2 z`p~T{Cb~dhy|jyN%+?WuJ`d4;T$hY{Nxo-kH|*Rcx2nFu~nZZi%Vm{q(HP+7(tO52 zi{jXj;1}^t21dQ41A#55a7!j#VYC|5Dd50i zpf`f4Fb7uvq>LP>aez2Q<$Stg~U^xP8K;H~wH*UEnGnNkUzy@%=cqtVIvg5tL z1pvu-z%m86ILgJn&~E+Z?#m;a5Ez0cH85=^6$ov?XjnEinJ`bTGvMQ45Fz1Ya0D{| zVpKtx3owkP+l?S329q05KocB6cMn(rBz*2p{K1zH1hL=`&j2Uk4+P;r8aV>)Ud-@*lJ(K`ojLs;P!Fj#Fi>-MmP(i;9D8<2eT5dLij2R;9 z-K$?JG#GHaMIZ$L$!G!rE*KJ0Zir<40q25B8lY#90?q}Rk-6jvs?fM*fSt}&E4~W! z;2c0KRsfSwfOA2zNprguq6j%`d!ST7i48QLh!0^r&QK1Tsp>9RUZ;x1>F{2RGmH>$ zsRw8dKp{JlL9Pu@vq%Bw2U;=CgC;DqNRs>n;_E=N&Y`UW z1porq0XnzbnFrUTtP(;1R44%C1- zfS0lYpN11K{SdlHzoS8`gc_g`8H_a%5rp;N5pcC7lv2Pts4y@teXNE*QRVkaoGm?4hD)HD}GwUJYILAA69jE{>NA*BOgXpz~b0mP7FaiTNtQOV+tZEE@ZN?s(DBWT_ z^^SqS04Tf}fD{nkb?Ejz4p2cJ;Rg3K5PD6}L^=AN6N&9A5dDVlk@nnmkQCqfhFszh zER^aL+^x^#Tw|Ai38v^yx7L4+**P)!Xw}?UVx!2*(L|B;FSXUgMxaFMYJq-dpXnW@Ts>|$2X2;#*}0NjiWoB zXXwntcZ8v0`%sGFDZ$E)oAL`82Fr#|+}!%U5zanjqCoBxT<1>WX}~L7_eR`oBi$?V zfm=!O)%S9!he5{1&xB^2;Yqk3)c&C2E=tOW}ToGHr7 zfA~y#H5uZB|<=CEM)e z(uSgwJd(0|d$8i&+|o5MNb0o$Gc8;nVZ>q=Bg}}#Uf@fJ#OGSRwig^30Q3Sy&IDOW&X<``mYB?iWq zYm$oDk8p}76s?x0$oPYowoXlwW9%5{lGJvH8}Bp+;{zFiUzeY7=wjUe^^BQ54kY)o zX1YnPcMUlE;xAbgRL>}-*i=oR1VKGEOKtCTBoQg=j{;uCZTNp=RDN~1jEg&xyq%eY zk1m;qE273+(C%TuXOJZ5(96B<#C{TyC}uo|-_}~^$Xl}KW-db{YcYn2_)$0Yg|{nW z|4>=#Y%%N_M|P~axOyHD@9`6!!eDfYNMWX21Z_^r`fmFqsYTt6h1p-!En4r#TF89G zBuL5)gkpzs>cMfDfskE}w*n1?}O0>mdnd}QkJ!Q>^$MeqyQi#~y<-QzXPN}Lc?pMRRg&!ZFwW&p-?HH~V^cXjt}m%?5Z{-d zz5Wj9{ZkyK_;W~CfIlTWY1wip1gZvPOCTh+{?@4lg>v8oTtY^Y?i67QlsNp1!@@D% z{dWjjGHbNk`otVBE_ogl+LlzA$rxiyjlIxKA-aZoCvd5c6hzl7KI>q~e?oi=1!ey4 zg)(dp5mkNc6|7~F@<*HzJW*Bz%$V?vYNLHCr{;gz$`(mFf_QuCq|Lpj1`@Ksq*Rsi z5Qg(8O|ao;SR^Vt$%3ya`_1oRGu*67H6@>&H?Urd{3@2jY-U=7%S)-QvUWZ?1SPqg zOR1?-Z+3E0q>$cX!fUEiuqlSH{7SDflN4p#C`R*+xAe`jfysqiF7fAp`!@%5ym6iP zltJUm2>7$AW_I4B$()z}Q&ISDQ`V-o@|Ig05_SDuj|bqxwmr0Ylb#Jdiw;m;X7s&1 zo9`(Cbn44PQSF$*336cnJx!`#dTpjdTfpCI;kDO4cBog>e0z9ZS5F(Fe_r%zssH{h z3OPy~MP8t40W4Mh7t{q*IKWF52sgaLd{-nhi04UWRYVz@{$HuemOu1PDdF=BM6unz zOX+M2SKL>SXev`?Kkjn13uh%n1Jvg)nMDDKCz~RaNwenb&`m^jQ1U4g-?vnWzngnT zWG7TFVM0?c927WMv#Gf!)4tN-ntKaG6wU9fcVRA>v?KvAgi=bzlYV@~5T81iqBP5y zS~f|VE*N6{D8JgY#X1m0{eu=VoaKNJs~g0`us`sHK^2jX59t6aKp&cz1`0wUp{txP zrSk1XT5?TutUV3onjwN?nDIfmP4U*+Cv;XlE;Y1AC?v}rXSH;GRAkA$3z_rMsksGVRuZ+=T6SLfRXYE_&O&Cbw?F6 zMY%_a1j#`aP?i@(dT*D44fkoq!U7h4rQLEY86e1L;yHojDBa6IEN;(sQC7kB+{F6b zR7V@>qeF;l4&?Oo=(A@Oixp!gH`F)P@UnE=sM$V)w|eZ4?}L{f<8SZ`dg|m zZOP%r?lVnkg$E^b1V&geRTX4dKZE%)!?HZiZt*{~F*>PUSHgc=t00m-Gy_3>bol~S z*BYWHMl@69vsqqUn&Ul9>NPB8+oPj`{%!A(TS6G_jeI3MuqH5h#L0GwmaMDAsTdF& zts+uE-Ou4(5gOs^d9uY0P^2TMR%nx-tRX{XkxZT})s`nk^>^;w;7>6b2xlkc6wIi@m7ac2z9Urt2%@#_8 zH-tB9UsoRTTRJWfDzAgU=7n(174AYt8{lMC;qbeBkK^3{ZIj;7dIcwmF#S2p)RrW` z^Kd_73r6vNX%dpkkvM;7UD<1ENbD|O++REYG!_FXe%Sr<&i%1V9o;`@pE8aS6h=MA zD%n_cGw<~$J5{npjkP!NqU!U@)b>fSIl*t}{tq(x-i82a9-nPbBm^6xiDDvAeIwU5 z{_N~P79m~4@Et7|AG9V@3z)r-LX7THSUx(^eg@>t9imNIiFHGtd?0vrXRhz17>Qgf zZ+Mvu%&&_neMpk904E{2u;b@3mAyucq}SC;*-s0V2)7lqNXI&gWf^+&-1y_EMDq8I zLkHNmN1jP0lkb`>3bK;lg-6b35*8fh#&whX=5{IpWFP+ZOb3-)Kl)#)r%zHa?QaL| zu`F~C;2P;0TBho!%0w4+#i~f@aId4SI7X3Dp+Cx0l5|^}UBq}q<#P+UL{`(Qf%a-b zAfK^It&q}#80CE@$C2E+Nk-9$7ejk~7LwXMQbrX`6RJ+=++!}&kEpXbftNW#5e-m( za$OREqU0xO`K&*>{N%FVNB6NL!HJgM)q-Lye6V7=ER#TD237kuz7#uL8JnfQq=YxW z#V?ni&jyZv#`o?Ey0?(BNk07tNG1GqYVTb<46+Nmw_NEf?Fk6t@BsGD?gBBB101;3QBWNkCcw ztF;wqRVV~_KoA1F+BS&RJg8755P$(Mk}LugSU?Cs?S~yo5oIzgWy|Gz=Bv4M9_{3n znd=GBU_Q**EU}`+)gTzBMkz7Si6+U8OB;n2ACZK5+p+#i?9aAoGbbu#eJ4}pT^UGrM=uYNkOxKnPT9d%Hv-;T-W0yz&R`r`^t%+L(+Ro&MQd2+EpUYpGCM;Wm zzD&O}vvSf?=gYDuOu|tXX~gm^(D#~=({rM8R%Rt;mjsY4vsBir-Rw^Kaqir?{A+pBjRT_X-?9i0FK+AY4^Mcb1FiGPyLkS z{kXreg(O}YXL5kSzjvy$18%D4nfmVEetLTQ0Okr944;|cs9fJ8${L`3KBI~1%)T{# zC_4S)5x$=vSqDMsNJu2``6T40A*siclN36w&vcem`$5!wZ2}Ob1ACXqDFBt#NoBJd zsRSWnDAWZu5)4T!Ml{Zwc7$bm=nEhX1>r~1H+L1$cP0!Bdq?sSlMlfeOw{v8gfZw2 zaUY_h9(GtCT!SsfyoSTJU~ofVZ-P60OXJJRXf&6|f??0i>dTZ_p~&gU>#SXzo-_ZT zpl8rYLh(PT>^k0Z=7kwZ7}YT>T#vEvubr9DJKN$2+MD*6KhOwhcBD##1AjJK|00wk zeDSX1)|QN>+Uc!Q<9%|cs5ykJ9WviLvM4LE0No4R-nRdT%cs#Fn*tW- zdI;X1G%m&lI$qmkZC<6wrdkPI`ogeiws$*zbCC(U45oJoXo5V*snl*g{MN|2;y*=q ziCxx#15h-q-y25u$p(CNPY|En+T!zUhVHh}=1iU$z4zJu);uv|?wX;Bq&45Cb6F9O z#)3A^wV7$Fu|FYZ+PGNCEbVFE!DfYzW8*kz&vI5vafRcJ5%^@{#&S&sQgQLuV#&9~ z=#>?WIGfFOVB@|>8c@+0zg%h8rUesowa`r{MYv722o=RUP_k$~3*@(?F8J@UBEZkh zCLmt12)Y4dh|3{ds0@NF3q*cM_YB4NExt*61vhV#muPN@>lE|g6fx7@**k=B;4(tOOR)K{x`qpNid$c_u&kLuYe270vu17)7k?uwd;HcO|RZhudR zSb0Op02KEX48c8^T3kag3nbwn&_c)%4}(j9MaJ`S3?Vd7vns@plK;%4_nLADZ5Zvg z{HtCV17WcEN*2jykOL#Xtr6d12mnB5pFe~OoFS73P}mtLCODS_)OfP@=n%UK+3_r~ z38|&#HHf<`2X8@!|1iaNijpadQ{+kzRhU!pB51FZsM+CJ9!eV>d=qYUQA&s*j*Gs< ze2hke((r+AH~Ft+-f&MqwRy453wH6y&eZG}>EX2@V`2fiaN-nw$pxN0fWm^bB+&m; z7%bBE{4O|-L0zHie(Gjr3p`GBTXBd}?LhkAc^|VV9tn!N*})r-AmyF7|;dluKHunj#1~t=u1NVd6~*-h(a3cKBKCL zzkeusU?oPE8Q^7Ua#!2P$8!{;y`dW7gkmjGXdK%}ezNKZbmp&?fBW4q(IPDZt9w51 zmc+e4_{PNlP8_qal#Blz!LSGGq(o^xN0VEpSTd*1Yr^9KZkT;q6L^@j=5Vd8p~Ewr z3uyR?F1cy0|ChqpMk6q^@Z3lAdk;(%L3hB=Ohv(W=H&dRNz!Ao3&4^90`J0O*9@lH z2G64SynEx_j!6J;@GX;3@En(G0yW8e7LYn7upsaXCb3{Tip}HT8)rY_OGj6J>o57N zoV^d_=-D~xKS4-_1y5bM8)#&NXK#6an0NsD7Xy%l{Fq_`=zLCYeoSbAT@p;>0e?i< z<%@pxo{kOkkMC- zzF+m73Iu;pia=H204T`?JjyD8*x)Ri;ZX>h0SFRcUtI?X)qx51yC=5IF=YVDyaiMQ zB*!ft#OoXU6IUn?oD^j0+uo7F46x`uOhlvE{pbD}%JNwhU+DMyL<56+c6h4|#{C=E zeDPvm83^wRb}6`~U=OcTz=U#kkr__`pWk(j{~%Xc^NoswzJ)xwBC3KMR=Tid;Of74b~)w5VB^dy-O19r@md7 zds}?uGQ5YZ<_U&m9i7HCaxyp&3W;j#8`LK;6VpB+rzH1aJ1|UyqaKNuKU`W6c|j`@ zF(`DXe`+>hF*Lx(nn_ymp(Bt{WP|3UHA-hvPle6PbTZIDK+Bmau`nC69#gcxjZks9 z5`RYe-q6`|0mjY>SiF!$%d3*}n0o}C&j6>cIWxzMpzSp1{!Ss*HVQqrOK@km=V`n6W3oNLYHY_!BswLdBl0n+j~WwL&)umXxsfACYtxG z2WOA6OH|8oy0d-VK2pb`fxgQ1m_Pa^qO#yq?$!W+PzIt>xQz$4)cN1Aglu4GgSI2| z%>I(Q^F_?jC^LlKl_gAEtgnPKnI*!(9& zXOf4#j*V>lxVD!#@^d+(MrZzEk(DJZL|Bc8=wn4Q%m~c7Qy9m6wc?j*Ue%)>s<$K? zTI6K7*!jO!Z3^zMxW{DB-$Ol$7ioYX97(67XQYG9HBIUnS+~%m%Z1D1Y%K(vNqo6) z?hPy7Oh!@;sS{=}95kv3G@H#%bF3H+vB*Dx&A&H-xfkx3d!ITM!DVqsQ}cDnEmC5>%k#qctdz=$Q1e< zGv|0)HuSE@b+d(x9So(O(^lRKaJHdB6cx*$C_%Rvc>F8L<;^55*42)-_11wEF668k z_;qp%X_@z`Fd3VCtIh$#I}aYjkO?Et#|tHJ;e=bnWR?+4(@b_R;;5{7e<7=Ac_MzZ zj&<_kgTH_3r;2|daawJ`Z`G^grv@~n^`I!XONod4L zW1HE)!Zq+mm;CNGtYfjCVvK{jeXX7)hgO$FFFhl=L#?2P@g1`HwjQXSo+Y0e*vs!+ z`0N|*>Sd=$tb1CH@6*rLJGH77OihzojdtTBK3Oh9Q*^FuBdAe%6Zh;#Z=JzZe{DiO zb*0oA2D&|8j8q@h#iwLro2W)bP|+h=504ZW8&GIelGJ0R=ZfaZK5G+G6Q3Q@AERyg zNFkMesPc)~JzCRk!7zLxA$49IWR(Az0A5#qHGk$q7EBV8bd{wFExlAg#WExPOYb}s zw1c+ZCHo-Uc!@!33X||xYH6Pc#e3XYT8Su`d7@+fAHjA6V3>#`R~Z@bUKZ;XId%9(5;mkv&2t;+xhj3QWG6*pZi0;4{gh^ zl=7!@&mTVHpF?446%pm3pSYgZwtR`?>5{q%N&|dK17cYqJ>U-6d=tBI+(7VI9)KuN z7G&zNU+)-VdDp+Ph|>Bo&?NMRW;JGz7DdO>%ErAuA_94;7qJrl*p)VrDmtPvU_r6~ z$&)}?z?dWL>X=Y-bc8_`f`W&$kKCmvMcpz*Y@=F2*n|P3+m0PmlXj!6sNc@6@rc*b zfwBNO#{m)uyd+MbeQ*vTdO1L#3sjXLa0d(s+QE)QB*=zOup!6d&7JA`jfaoF-BKA%0w~-}9p=BJSR( zavny58GzUnAm9d^qTUXUCZG)lSl;vg9i|#Gin%RDfohOeE0lxoJ3d;Cxtl`@o6bUI;+wiRpe_$JpytDaCc~^cxJx zUg2bVNU9Ff2;GBF)|LkQYE0XpwoFy@Dp4|hH<&TeukbP8rkdK{RH-nRE3Ej1vxHba zS>$RSrI;A0=!;F4XtZMerfxR1d+>CMd0qL}ZI78+)C5!52{+BqCetO?Z5;FnDqlFM zVk5XoNE=S7f>YJvqONwKn78T=M){Tkkk+8WhQU7kgOrmc(ta)SR4)s|XXsll|BPp> zs*VeoZ{F%)>UqNvz#8eJM8D+RdM!aa+XTywpl_Vq8I#?d*DZr- zE76S%;Q$19VW~7KQCyX_iX@aM3a;|an-SlZ7h}T<>bq*e#YCDQks>oVax4>Aq=hQ3BP^2$y4Y7GGZGGa zr|~6WV%RdJ6Ze(!+CKH^{%DaJ9#SuPS(F|oFJb{bN`#CEK^F+|HoKsjpztsNC$2Ay zZ2%X~7)fAW0_2@rzR|K5JF^Xq>f(TD`@1j&b^v`;*kxC_sR97}+H0q6a$IdjRBn*_ zu^ROH!ebHeTLlF4pL6lnV0gN zt7629KfXJx1Q$HDPbI)~xrm)P2OAdU=84T>vQ1xti_N?w2~9q-z$>K%x@`*5CGl|@ zjsj?T>E@PhI^~dNcK+Q;3iN!-Xwa{zwMKU;5g+Oy*VKTz$*I6;5j+%rjQ z#7Llwwt-S)J>dYuLJ`z5(L{;q_#^SF5o}v}b;E)Y#ItnP zW;cg@t+lrzWq7baEG~T!ib=5NMALUxsBsd`Xjjxcwu12gd(_QafBjXWn>&UTb9K%> zvupkUx)D)gQA1l0#|7#uw)U%ij`X-Y&Ob6k}k$XVM!oYcd|oU3bLHQ{X}9~b&B zajI;ME(AS0W31!Hzo&iP3*4pxQZphTpwj7F^ZHVKO!9$dI54-cGbYg>o8FdALt=YS zZBolKvq%eP79)sT!=M~lG)+4$4ZiKppWR@0w3+|?$A17s1^{Se;I6;` zmJRz;LrWn*ge3u+BP;!wd|IAyNuSY&Gx%j-DS$|jl1u% zS_@|59EabsRSq%y@NHw;wZw_HyadP=Nn${45P=K{k^}%^001L$XjM=EyN~<#=e@Q$ zGuP&9XM2$FJTj)WCO0s-0D%fXegiL5fe3*BC;*h@;B&Py_yE341OgymwS~|+7YJmC zM`h3gA_$NIPxJRdw>KPt(3oOX{oo?XF7Ks?=zv zB+JnRGo@E+Hq0%l@RK3cmnA^j4{1^b2#m1-=QO_CaA^$;X;R6n+8I03!50ICD5uWm z$R@M8b4(+=)hU1VXFiiF<;in;5NbDVlKJOl%t*e{!UMN6wvB39vuZBzv#2|y&n4Cp zOV|EF5L-6F*inIC&tz!4&xdhX6L}-s{t0kORJrFD^()b;s z(_QKKwdJTNVqh1)A_^faJ|=E*nLh60W7Iq_H;V5(Cfcb zw~>0|Dmp#BmVhcMD5QS;_o?1SP-ADOs%LsmpuWT{%jZ@3%ihSD{$C1X<~fC37$X@> zP*F*dUz;%OLRp&MuASX;rE5!L z$~u;g1N)PF^>WHA5!PL04RskI*+mUCkg>L!A%siQjca4CNh&{?4A!g;b&>bB!qEAKG+pBVjg}YD zRo}kGep#cc-c3`yxDo&ASteLHcsg7~rcGG(Xx7Ndtz=#0DWPOI)|r~k@EB(#g?Q%$ zaL$a8^Jj**9dAJ6#B3)m&MN;Hwp%Fz9^XMsr4Qn+w6Jbl5x`4&L@eS9WIPVGSHbCF z+rRS?^9Df4%cojxQI^&1zBfqjhns{d%M2%ze4FB6cjP4x0s))G&~M4imnOXu_OV_F zgke)1MXV#&$lTQaeR%CtY*NLPJOJ&%*+LR~B@~=DYu$i1n!F|D_?plB4_Pfa6?4!Y zo*lvu$fKwh`yB{c-c(T$3gzTrGRw@P;uSoRdbOJVzofUR@bj!LIGkibkVmRX-MAW`NExwj=m1b}qP|%f< zfE`4&8{PV#s1gP3axkH1+)?ogs!Y7oAUlHdozX{z26Vto0Sp2Fh^mlG5I&|`AQWMR z`=S(p(81R7uYgN>8S41UZ~f|vx8(=XggLF6M&Cu<)znNx^tja)ai2!^#Zoa!}N1 z`>^trH~Zuz{B9}8VQB#6Ggp4ku$%((F5DHyBAg?NaJDLgK|GqAMsPT@LQd<79Cjc6 zK5i_rFDr5*Y*r$Ttvb5X?6QqaP0uvw?5GL=2)K^QTYzhb6<rGswDX2_FaKm=n(Q9`e~L-o?_Hr!qj~_;z#~*g!g>hP7D3=017mTnJFM{V z?}9B1;lDau@vsI!@>Ro1SIEC_sT0~Q!XlayfX@|9U>+QZHJd#uVxi9}>C54d8$^~L z&mhZpOOYh}D^Jk&w?0;v}NWgYf*}`GW=26<6N2MZk7z`D8@Exwfl(oD|85qgJKCj-*_Al z2)hU{2>=r?0S37s3wek>V9*E;(1DEcfdO`7USds~R4&+$+7U2%00H+1DyjI7sC&ig zKqz9Ut^>;P4iKlVaR0Yrk&YbY=amBQ{N0e1=3u9E*?fr}cwgar%5_4?00}4$qb}*I z*9YJZj9siDfic3^2N?_Jim^-=Py_=6WkAsVsm~M5$REZVh=l-80IlT#$vL1k`ZXib zb4cxGo~XEKKEMMJPLqIfD~z{PuQZ4olZyXw37-5)&^~HY^rI>Ol&DA5Hu%WD)p^h# zDTrAnAC>aJnqDxGpGzXfd&QMO71}a z(KxZZd>wCk{Wq#-?NPdW&qrPRlmy@)M*xj}K`2|O5u#xzWyK5tfC{|pfYOHtcAHgh z3HZVc&OCkv*f*{d%E=f2G61P}fRc^}Lf}Ml4oozxA7FzB9tMCxEOeP(UYF+Hyx}3x zzM_#B5-4!vYC~LPA7BvxrQib$?4iNkxE|&V%SNjR$Rh%6$|01~(Q7Uo^xQugCyPP; z72hwPj)Op~(t_(d4`)ii;zzDLT`BU!&56WEG$dEEq%vTQw3u5HDM&ZyHBTMa%`jq` zmm}B^bh_@&C^{XzN?4dGF=oPC6}a5>^0*vo)sW@|_jU3lxS2m0rCL&&SZQ@JZmLJ{ z+0Eowe9tJn!rcJ>eIo5ui5t8%ZO8Oi>dn$NhD7bwGh&=h?O2YhH7~_RQP}w|1$1`7 zjo24=A>-DmQFsM6Zt;0xtSj&_s0h;&_R>D+rCZ;0B+r;oEp)ToI5mrJxQ2Q0$91iY zjuYI9$H*olu8=ZH$E4PXp6Rrl#1ki$*en$ZtrN8~jrY8^x86d?GyA=*-=pQhl0v4y zZpCjkJG9l{a+w`7`;|=GkC3v_D(^ZLo3U({ycO+R+Lc)@)#MjV1Ft&N0tT@Zz#TS$ zLv9kyJX3W4%Po0l3MwG0Q^WfptOS+S^3e8so?;J^xSnuZ zrq}}>Tlp*U*)e;PKgBCf!yD4bHPN6O;_*FV{-ydS57q4fyyB@Z&QdJqy97ti@D`-T zowS6nbhSLe`7NnunLE8VH0>*g)q##RrY+(RK&J8S%kIC9(6YHdTXfgz6KwcI5r>b8 z@DWvgf>~Rv+|->fez)U(yNdyLNfz3qO{a3ND@U)t1mjSIHM#FirR|5l9EXS2!WFLc zLfK~bh*b;S3}C@uT9MChhJ*&|1AhLBK}37OHq^ov-O%f?LlIn#EcE5uU@Y~I zS>Avqogfyc)?OOTK7%Z{4VK^+v*-Z4rsdb6g^}VH_K%YOiGK>AFDY3ODWqDEBT@tSu6*V6$=NkA8ryul%*q)ugp>_99 z&KYFVss-*%U>Fi9667XkP@B79?r&R3onVJr@etjQZ|*Yf*{EihThu0v&NQj9xv6Ea znz=!xRw?f8IqvjdtLbEdZ=IR^_OYJbzb77u|}PXM_>@0zg}w^+RK}Q82d%d$nOrY zoUHprYnx@C7Ok6Q+|nf<{+l91J@tzfpwlA1c!6d3=46#MK?so;qA>JPOjJbQ)3auh zglL=@-QDB=Qz3;ysypCmR4H)P*w!Z}ian5?5}s!Fe$S)Dx&DrdtFKg_l}6tqZ>G0I zmVo{^)EKjpT$Qh}k<&0?P4Q@P{mb@tlLsTEkBB=yWS&jsNDn_Cz8ysWy8S z>@(pA1W+2TkC^ozyETtm{%Fh;@RQZa9Qu6#v+nrFQdR{bzpk_qiHe=!v5amsbWkwt zu(!(02}e>q77V`;m`D!AjqJT<$-I%d#qFhqp7LfIpj>X7zKfm{OM1>p>HI-v)m~f5 z2P#zZthU++cr9#p^neeT=7mA^jE>_NWl z{tVP{3`XbY>(=VF=2uw9b2kK*|6*YN{rE5G6IBM5zVLnhP9<}eB1ZV|CFxU+exH9X zJ}9~_buV&eGQkHg>c1N1#6$k;jQ0LkPAK6e*~{SZO{WlMD?6s1=3ErD|E5W0CHQu9;}kz7AmeTo zF#t+bKt8}K2z#VduoM=;!xWm34>Ami)0L!8Ht&NSD*j|39Ye@JX?$@>E4?G@&Hk9m z=g1)Pez2Q>c%k9}dgdVlRe~xmHokn(5o15+X(5m3)VLOxhg^fkEQI&Oj4byySwk7| zCwch7$$(hJlkWGsw@`K?&~87*Y4bLB4I~<1lTeUqvaQYepUNqNAl|8ORLM zk|~ys0J4LKQ`sVAhqzSB08tPS0{{R3Lo_fX003`gG?m()7_Q`=gVZL8)+RP-Ura&5 z;O{2T-|Gs2)0X7A>+ajmIl=w3fB#0u003l$u4VuL$KY>t5x>gENzOZSB$wZj6U8K# zBB|nOHxfvKSX>(VUDqKs*3fQ&fV4_$>KfYx-BOnCEteT+Kw8ksRE9jPD6J5AkRe}E zNGO=h$`G~@(kD_mT7YzyNgjbf001cfBN6~aKOo=tpWnNEmAg)EyY0_fS(@Al!_1O0 zO09$i6CRJp;wO;s0|;Wk4)8J}l0zU867VR%pkx6LikSh0ggo%TTnNAez&Vd00FS|Y zq5j!00yxaZ2A4%41VG4064g+PVvG!ta4}CA{^bTw{7e2bAY1kq5X-ofha$oL0-WB%X2ckLx#746W-7tCu`Hd9645t9lnqRU9ho(7S;5-yP9_R@ zS{5coW+}u)rDbP5F_ajwka*d~45GF!1F^OU4GE>CrR+s3U{k6noVr6&oRIXDC?uxg z9T$f+o1m1eOdtqxERv^|l%mLpS(x$mMX&2GPSd0liF-*UfPRLG(}{}4$+g) zZ4zn_!f>5Rtt7-o1WS2RFIfBgONXrrJ+WwmwlTq_Fb5jYZk2&7Dhnru;U^S8U0S*# z{IE^q0$QAb7W;YtZ$Oa0rN$)`_0_gfmXHL}VCd(vN+Ye1s0UZZ5n~;hjBYJhBs(;= zFs>5e^4qK|O=?m)y!JezR)EWBfjR|OQFQ^)DPt>*j)x5Um4}trpf3-e8AV1V<l^InN|u9EsFWqYu+>63){p_1X_|>;w6v!y)S@a9sY;bEZNi>8@yn6q*lSl- z>nDOySJsS8Au85IL(R$|r8Rvhii(82MlY^D=?1aXNU+|)nk(CHxjI4GNUob5T**Sg zQ+hDPgpVRJK|Mho+PFgBLN=;b1%_!#i3dt#aSDa(`%t-6%`U|6WIMA$YU10=tm3Y= zan!p|tD!1cQ*||hU0<3s-Ew7Z@#!JPdf93~!zJpiOgHsIY!3i8fgoWTj9rr^IT6e@@|A?#`ro_oO6c)c0x= zA-1wctk`;Lx*~~&v58pS_EklvTXv1unuBe|%Nkvy!=h^}J@rpB*(Be~MWzL7NXZ6v zb#;69p%%N{p_VW0dfJoqaO;ktR4JF&Nci;d{mjJPZ*WM#6w;Mh);6dHsB^N0cm>hv zwoa9woY{e1xH0^4!1x+Obd^q4irdm*c>-QHIoCA26a9E?RVL@uPa3*pMn>!FJB zYWf?M(2(23L=N!L0(lh{T3hmVA~>>RsL8FrBkf1IJ*kO=b&8fYXxU3}aAbqeepyb| zk-S;vO5U~IgGT@g?v4c@aILcr5j(-6Fv)OY)#i7$IQy>%)#JO7omQ>6wllb{1InGT zpHN~?M18yhuy82Sl`FhiGg$P&UK-jzt?hWg7W5cJvZdIKF43)Vsh%mSS!hMjA<3?D zHnfqyw(c}aZer&}XIgP~ts%LFs|c%+_>v{GG%d5>s6li1_R2+axgb?>t^qT4QKHbW z$Hc?kiZ2}X2GxX(V12_{xoyLgSfQYuD7&WUR>2FKE#u(IwmCsJbA?B~{C z1CF>f8M{zt>BS%}!JaKO3fgv3f_A$jSBs@OA1T#V5b9;X%F6LzNu$$!FU4MM17g5% zWw#ty#>;p$*RloXbWR*YTYXP)ML}b;6VeS3BrlIZG)S>SH)I!mofGtlN1ZNAn`qFh zhz#}{Y7jXm9ab(eywBEx^-AfoBt8J)VMc2V!PM@o})piv~(^o;Z=hF3%loMC? z!>2SWgb3kP8z=wQOAEikZ)*vk`8|azg+vGE^?L+lp|k8Qz>KVyUDdX@wcw^5`5CkZ zC_uKjRzEzB10IF$KzZ7G(5#<3%D7G|DH(ICt7c}no%66&0}>^HjijtvL8G=U71!mx zv8EOMYM4R{+fkxL#g5s@t;)5>RqoRftTZuE9oHtu1n);}%k48774^Lo&FG<{ z({*f>lsvKcx*sP9whGs_SOYI*I9@DW@+PLK29h+R{3PzY#+ zDNdL6(t7!DS1T1MasmR<8OWIu&JYADcU|FIv7`zlN~w>hVezClTg{`1gdFkeEDC-VPO_x#H+m zXipfkW}`emPa;|#KE_Xpkg8}lPAM?F3}iGoTo6zoR$u%Nv&5bsE`R0*Wl%+qiHgEE z+F0gpa3(gUP3V}XS(P`jSTHhivM%zuF6HTyRtRAg*%_S{AO=CnJxR0C-|vV>@p`v6_RU*pm3$K0f=dvJc6l|hg zoMfEtNoYVsbx(rvHxxg{BaufGIBE9`@|-H-Sp%=QnSQ>i3YBsI%#r(svGH9B;UZXi z*FgCO!H5aptbZv}N&($>=pnsb3HBJn!_6<&KDeNS)K3bJ&B)1n!}zakBH3te_l>Hv z)6|g6i}3By=UmvNgvyc=*+$1G={tN<_8gFfXOsuy#J1UACE-NhDY(uiPTN<@on#Lg zt~te?&j=^q1(mzDOK@s{Ozl3wz$wAU1-?a0a9n{H5)N9^|MdWy@Jxk=Qq9$xt!CO!L?h`Up zf^qx#Jaty4r}ZN}wnfWV9(8_nE15mHPMVvKAofJ@0Jz;am7rGbxgKQriGT{j zlHU{d+|oL1ldm)1MiM9qsJ*jVb!+9zB6o)tFK74Y)Uz(NY&c3qn;m&s7gPKivLU0= zI{R7kAOirG)aVXdlrZ+m*qawq0ZaS`6*)Kzv>98M$qt@@AbKS8&NlI)%I%x6)pnEG z{@1kYZ`Mh&1^|ppi+?&*p-B+Rlf>BHx#txIsD3oqfur3IJ>LMuk9O#);2sIC|KGT! zHzw(KgKYLRD8Or+0VMQZ&<~9mGf28bOW0_b0x%?-v1^027$VyA_z|!A2|~oVCs+J~ zqMp|EirCQ_sWQaF`WvlE?i1c(jHuO@`$>-D7PdfJJMrbC=(-MlRC-qh^0G&wQ&$q+ zGe0*Vy;i;vJ3=Tc<1k;SM&%neDNiHc&jtK@7k+j3T9`whS~>GZY`AOuuzjetzESqTw_ z?o6zP-XiGKB^Zm}UvDEH;Y?TOL9a07c!A(@jW=SrqUMOKsh+mD1!)Ew!e!8RK>)Ph zxDt*Njdk!<44vstuu2OK|Ez?`i|5EIyctroAc?P>5w}kdq{D0~-~fQStu#czaN>8O zl0fDHDaB2Y>GckLLf)G^_BTOW+*ndr=!E%vqo1sqNYrBAYxSGf>@rya0B)T!iFN^@ zBglGaPy+2qV0>ZQ(S`+@8rH6nz6)2%TD^^XFq$nU*SH z#eJaZlYrTl`Bx^~!P|M9wc`VdFvob^JkXx3n5E{pfQhrW_iBg#W1;y4K|+Ym;~6)y z2P9pm*lCM@?0b>wB^aBHu{-UK4OlX}vWjCQO_K3P@uQ<=fSkRfM;)VacqJn5q*yZ)sAaq_Mg;c#VYZ+EFmVTVnG1LZ!1&h@ zZy(KGAZzT=1O@a-P>f;r(Uk`kxoO9`eAJsYI{tkDz$yQDZ>@q8fcQrm00|cWCm#SO zJK_0_3D6%2Okf*+G_Qdrxsr~Ro#$!o=k(k7XaWH3zR?&5?LNw_?Ex|+FksvOnX}k4 zC8&%{@+W2axn*ecRImbcqW?O+T=TY{cSf>79 z?*#aMe0?(+&@Nr#aGRd?_VROHbnqMa$FS;@{Zl005L8`S%_+ED&gCdUot)^6a$vj~ zymc^TXCk`r4VU+ZnB zqE7Lx(SWiMk&H2$rRsLqwPB3zV6&(RAi$m?yQDA2KVBSPVtz*?kWhLf?>PgFN>3e6xi?9 z<{zRH!HB`U;J@$*AqNpTF7*lh5~LgYE~0N*$!`0En!;fk=Cqlmfo)O9R8kkKwVlAE zlG08KQsSLV`N6=sQPU_$8{J8hHXeBd#0S3F>HhJ}``+~X8}IXdw)?!arjF^qxx7MX zmjXO4R6vtssys}iwnD?n)yotN+ky-<6u_bOSaPP3qp`Z%z8D3etZz>NaX$T5l#o&M zB?UPlWd3Bv!5GdhXFl{b$LfgXVO9MB&$AI;j15jbJja}ytTD%w;=g`YsH@t$__5Dp zsNZis;vYwvURcMSj$4a!`Z6kH8)RS{`N+7ae)_==zeuBkX3@sI#mI=J;1~_7#ctg6>KgojO7wTrmboF-OrN816bV<5N#nZ)Hs1az%6cKj^`CO>NqY!-#fb+PkV%i{gM8PK!-iTgY(yjoY*b8E;UZ|il^ ze{d$v{2Bgb?ku|!#s@-k_-A*2;#-jYcHm*b2gh7J={WoY{M>u8?Gg_j8~lxatlUdD z51!}^sw3(R6)%3tRiAhjq*LX!%~wfEcIVCJPX2nnMuc~DHwougGub0CVm{Amvum#h z#YAn%J$s9d4q6PlSmMr#(q}eiu&5gNbob6ZDu~!9TIt@#$Lups_dHHAp*uWsC=f>R zzJ8m7DTVti5l>@Ma;q=X}T{L8`i315S%a$~mIK6@#70a-T+3o^0f_rr@$uE`k zX2{Ol>oxd$`StCgB{VPFsLS&!-+F0HcO6?^a_2>Zcs}+G)$gf(^ohTNs)yG>y}wQ` z-B3ldm7!QD$>z7g2H#A#`e}L6?-Fwc0^6_#$U3m_yV5j{1n%55de3fd+mHV0a0Fda z?p7!o$wHHP>Q?E56y;}DK~1>wVymC*UT1_;UmX8}etikGsD z4kaD+g?A%U$?1nvEu*?i*s4!fsPV)qooo@tzNnB$6%%*h0rnVWbZygxBpUBpT^8@e z{BoImW@_B7Ei$ETYIhjl?`Ekuh2hU(BPv3?nqk~ROzLj7W_rSdfWa>-gg*)(j-^ea zFEv(brf0erw|Iwdz2TlZikXrC#Rg_I8G_KOxR}SE z={i^SMLVa zFZSC09r$88OYup0HMwY?4a0GzkDd*~V{E~VZ-Wn+SwrYGgF7}xq-R7-hHrd}s+2$o zYFd+=@9N4T-ctEcV%)jrL7TvN_`xNDg|t~B)8|kN*e|wD!&Wid`=)7`*FD7r1ajq& z$*+XINpBazyY?zx13fG#I4y=hEHOKjZ3oivFrT`< zB|gPH=?aihfoqCjjp^3^qYPzw*o>MkM_~s}p+3Rg&{X zcp&MHdG7KF$-X~593J-zvTXRfKZCQKz2n3{DAnHrp7uv@6Mb_;P!X|T1}h5Z8XZ*67evNvaH)p^c(YnD%! z);Y?^BpILxNs#iCA>*vUB$vu65I9On@41wl>cy zR&9ew=!Hke<^TbJNr-XBI50VYl7u4zQ9^(s+yM?j1ib)32+m|8AOQ{z0TMtL+4>pi zOPnJT@=Br^B=T}$j!qtvaWP5_ zN|Pc!!atSdyCIZK(zR1 zxtbD*oi6rPjI)NM^27|SMYF{DwwC}1v2jTuM&+1P3O`#W7K(f<7F$y3P*tP5i3_7e zOc{lm;vl0%BaI~YTK3ah%PBML*^!5<@nqqmeGEp5&L>u3KzzjAZi;zPY@)}~Xo(oDAqFANprE#`sSHih4LfNQ8R-2Bn6@zAIr&_!Quam> z2{26mNWcS#{@&a*Yww#+l%^Q&N4+FwmNW`utszq#9sWZnNNB3<&&5FODQYx!!I}c+ zye4p$nbK^ayar`t1diOmP_nU|B{FRw5W9|_=u|Ao>B211*10Zn4OMjD?{29%)0Tic znx_FT2HZK%8W;_TlQTl|5EHiHnos}^`3^7FSoR7M$}UuQRNHmoju(eDftEU4r}M}@ zcey&{FG~K~UM7jY->hV!)Tuu#H+tFhJd?-?dYL&viK8M!ZhL4=`Bgsui0=z#(23Uk zY~)vC-O|)$$hmZ6>9=jrXSC81ewOt@oNA8la+&{Ibl8zbLVs<|Odg3egWBYf(Mz2R zVJh0yv`5SvH}owN^cxQYL8|75?+{e-Zfm zvDLL4H95j*nQmdevLB9qadA;jK38fs z>fue!HMC`FcCz_A{=8EoW2EOvn!UDWULD1gscgPnUC@bl>6(`3bb&$}k-5SV#u6^{ zur)Vj8_-(eqMWdTG^F8?Sk(a!DvY(hB%)#yDx9%O!&+rP=X#Tjt7Bn)D2hMp%0}!2~sLyYnsO3mQ-MsbW-v00ON4iXi9( z=T|jJNVRLvXt(bb8 zSHgzsn;F2Z(QFE8ES$;Q;$GTGCnm7a5%ew)m}i%&S?Yl+ZlkhqFtGar`KEdj*-C~_ z*J~D5=>Qr0meCI~rl8zaP@%gIX&54?OSYo+h>tC~26^RnU(bcVPxFR&PpHQMAtff) z{v}Zc0+~BI2q?g(oFK#n@|ZkL-(^!=_=B(*%=3V>mrpu$OSpW9=-eM1CuhRArlC5a zp>qFux+wwMQVo#**ZD%Xk0(GM---pW1*cdvWystjc2pc(to~*m!!IpTMVSlAeZQqe z?Zrl3bJGX(9~=6JZ8)7>DitK{zT5jMxJ*+DsI=)L0!`f0d0QrQNNVI>+qIsV)hVGa zi?EAcbL3vS80%g4B6X^W zR&=hWQ?F9gw_~|$vC-&&D z#nxu+RP_O^+P$9r+B;kgz|+6HO%OFgbquEB2PFYug@AuNJ)xc@y~uWhyi9t62Y0CG zb#E=AHoK@Ubo8PnS&W7mpy8iJJXJ&8O!OEB(}^3>d3&Vy>K@05(`T;3MI!ai*2ixY z8-(uXEQL>Ur*|6RNqX)NyPYx^J(AF!;svb=z*$H|5De?szBAVr|1E3V1^r(2P3@tu zc63#_mdGN|r`UdB*I0^_xa^9!e!k{ai@Zz5UQ`Jil3(f;536QP;g}a@%-?Gj$PZ{d z!6oM8Dr`d{8lwmUHk)J-Q}}e=Q-V63`I9!DPsL0wnhdDCDmh5pv^kWd7T>dtN`Fnl zbYY9?^>@kMFmmt+H+g3BnLJ+DQcARH%c9-m=h%Og!jm-@KVd1D?2oMustJK#=jQ>su`gZ3M#VLIuDp_;sID07POBh6S~p6Z7M0JuZAN!yg{alpuBPh$-}dc`F_!PdD>PF zPlAy7JY&`|-tA`B>2iw0@+<@a0CS}wW(Q!H*9eh;-2>jc_yAV4C+Wv2bx*rm=HacHRtnZqq0pM{Q)RlWeTh872t(CSomhPc(3JI9@ALzl3J^7Mi z!B%w`ZeZIA05&I9wtWCKJWKvEaff&#xPrDkP;KSYgK*tv^FuHV5KmMK+j2tFN{0Pq zIkZ8*{<`BSZfd5Ko2E663@;ZlF6}N63E2itmkPZz^n4@#--4!|jlI$y-JZCetGxtZ zS6IenDra|eef8H}pnR+UB41O0vz_iKeEY%Gk2RD4Xt@U5R{ar6LDYVM!q+pBFA}zE z5QKwc<(7AJg3skJqv5;P=GGC7@0?RnleTEMPR@Ifk%?!^GR*9ih?5~q%05E<&nHY_ z2?gjdb&|xBlPXl;J#MOzh;EO3K~>WISSVxJ%kJfvePnwdc3*Hv4bKthVxUmr#;ZKTzZjD`0`zMY4h;w@Z3O1J?#;N zgU9}rNe!$;dsO_V_YD~EYvi8$?gRtQHlmus^h$y=av!=2HPLdc?ZRy;rhk1_`q4bH z*E%x4#eg0a1@Zf=P~cmM;%A9%(C>5C=szABt}8yIg%PPE8WGp;`Bzmoak zo_`1O_c-_fteF4_%)mJTSe5Ybz@;pYXE4D00f%hJj}9`KMx$K)hrYbWgD{UK08;cG zk7sZvm(@ql7BdN@9Puy)?>qo(=6yVp!Tkb;^FAZ?KZ{5(Ll>TK>miMaC#se1|4w+{ zom?`I7{R(~nUu4k5OEIOx&)KJ4w(Sd$_SwaAQ3*w1|=mdazcnf2@iy{IMG5(1*b;L ztAS78Zhm^zVGaV>WzWgY#pml-wAb}ySe!(oDBEBVFBslnebxEj1Q3kyJ!Y?M5#S>N z=ZEf0$l-MnZhc8jvLCID`@~aVC0RG|{TEQGeZCrs&4i$t)dhqC1O$trh!_b!1%*hZ za)eMo9S6d4@j(ZC%)Vt$F|15Jc_bb*JxKLlb)Vr~bPHIAh?NX&8DvLmRe9mA{*s^> z@%-!DrTK>=xiYva2g;G}*S*sd1FY+sfMga$9;vU=T1NTE)O3vw`W_{`A;&%Z6@?u? z>TwTAvl)o3@}Sm+Xfy81UZOB(BW{p7W!PIbjkU^p(B&Ckzge4vn;OkdG*~cMH^!Q|tbs!T1VKeTcA1GHctFYTAT^I=H z-Ony4;2IG`R6dRDr!eI?L^nbofd5(`kOiwRq4B9-A2S%6T3Ix34{HR;~b`8%hfUV<~I1^P}!GL+s!=opjneJ85m& zUjNHYi_Y?=yn=m-yq|J?y*J5Qw#|le3rZxpr-&BgGV$K^Sw`-;T|^FygO^&o^hKi7 zA;4y(iq+~RN!4_GL%DF!8K>6es>8oPyt2oaV>=Oqx#4NOAUS|50!%GSC(_LwAStmJ70S0t2}!)3oWM? zWgg|mi0pubgQL~7)qjQK@u%<=>Eb9dOu3|fZR193InVja41IUq!pkPy^#J9zj0!ha zE9D(V|7`ADvdtY~ZA-g%<5k+>+F83K<+)ZxmWOUe%Jm^5d$Dq~#dQm7;wVRhgZvJc zB@&)Q^37DbjvC+Vtuia%FR%8jX(jN}*|JM7dhHr;=ltldZ^rtY^@S;8an|uh0p2uC zzrrjIjC5PtL!pFPj6L2&590+Pji^vefJqXMuC2y@VK(Ot%G9h0QeLtasjsg4BCVBR zjOVmEzPgrnK3TRv=~|@{crEw(^W0^d;9*-4_KCxxd9V6k03;}i-EeVal3yu@Z_}^q zFOyEpxNUjIqu|(}QE5{XBFRlIvnnG)|NKxhxe+=aORAGonxkF&jy>37BcYE_8%Mru zd(^5*>?U#2>Vt!z5__YPt`%Ht_i@LaDKr$B+~vAbo;lwFPzMPt^nR8OyaQCFCvv4M z4#5wv|JzLRa_FA@oj^)dlNSU@Krj^OJxw}U3+<)jf3;$92n$r2VCO11ElR%^;}W-V zWmTV&YxLj9e5Sf@DDBW~L751{%t`bx=jQcerq!Jlcc=pAMwpz(`6rMt8W|4j9CL6z zQ{FUtq3q@h3w~Sf-_10@sM0~jm8p3WBQU)pT{^_wWB!=YG3L`db4f?Hn~_94nn!{T zhgUSMu!l2+!gT&t7-1O`R&#VVuDr!-T}}m(MmztHg-**x{O;4N(XmgwvH=ur9p3Zi z*pIz4115g`au4-x0R=DH%a0bt%*`jPjq>zP2sn+bT*J*w9RUrZa+LoM zBLVKvc0))F=$q3IIuq;MbFPQS#W01+FZmR6IKR)qWA}WzJ9?A%;a^kTZ@U`}<3F7< zM`OIlo}tMxf*SB37wpt`@Dp-GBjgr)M9>r9ZLz%_>>m2($i)XyL_g_HSaQ6F>eaat zgZyP^S_(x9s?;s^u0+uIj3AeZ%w*m_6Xngw?)+(*1FoM$oXv038GVtwXw&PG@;As1 z_IurXu_*W!jKNc8JF{qF!ul%;Tn?R!wlzh|TEBC`rPsfN?3lLOKPC!lI8?`|HLVrk zev{jzo8P^}_-|hmM%;8(%wrc{wLQRSxp|l4u2aeOlB-9VY_~xmDs*sK$rwpuQ-2`4 zq=Z5hdv|`v)7S3v5m1bs;|k}n;0fGLr^q@l+jiW$p>A!4xiOHtr^=>F=usfJ{mYtB zR9Z(b4IjuT)^LsLwZ`6@-g zY_cKZ$zL*YcE({^3;t~nTWFS&A=~@So)L6`Op2x=0Ow!}@4;t*-$|^(d$8Fq`M+bK zErr@L_!y9hn|Ej1t}Q=X)#X%0HNpwR)pak^gU*j2sH4vW>s6z%HG?{tWK`Lij&pEer31a);1`bU~ER z+QK$U^i1QfPLJ1k_Q0kP5CZ@J05e2DBLDyoRm3XVvj)4kwF=TTNiAk@aF%Mr(IpWn zG_@X3tM$5G>f3T}*9LVhX8-@4{{R@70;3TCIDiA%Qrh3c(rk-tfk?7s*`<+8me|6D zWbO3MgFffn_4AZ8yX>a7DM58E+uI%884laI-@V9JHa2~9M-R%3Or1V{m4kpl&D#=nH5Q(451hz}pZ0a&pYuC7~@JqF$MYuJF>jqLJlJ5|Nz)2A? zBZnXo`wm#L#486UIE-TSOljKee8PnETt)JfqViN?iKHLb?68e^*^n zSUxpr#fozE0bfbYoI_2oJIt1a4cbdCkO=i>RSGGf-YvJ?M^{ERq$~2+(PpgqRJGLs#5Qyaf?Gt}Wv9@?hy`}Bxco%x%zLZz0Z%77r!JCvh|@;^ zS=+i-6zegfamT^;@?A~NHHDFFd2_F(3*PEo-fn#R=Qhm<2PGP&_6UsjObY?xM{XT$ zIv*AKY!>mm>#|c?v;cK(-oVN%OB#z5>7&wz(wEpQYCe@-(vD>=a35rXeNE>ajs#sxS!cg z5vdA}R%F!@IPJ0qUeBa{KHSNsR%!)vX%UGh_lq0Kkk*Myj428XPH^)0mTM;Lu+l#_ zOU#-2=IYg9O5iEtByN>PLEN!3Y;ux6bP|capJi2WBG#2VT8&|)kU6&8;>lgsYUEgh z#U*g^f{~~mftjrL-$bZSie?G@es-~o-Jx8F?NNx5sl{MPt3GVOT@g*HmrU+%W`7_-nG!|*YWKd`9I-6jS zW;3rSrjnZUO=f2;G|Jm|J~d0O zYK$^VG+VeF2u%~38BsQ2-8E=_&Fs`|B;(tN=1d)Z6LGWOC?uWojk z?FDhoK19slGLc{)4nZU8~8$p}nmU~J3n(lg%uf$LOl`HiODmYxkZLrrM4`;Qj`Z1H{*$ynWd z*U4|Bw+60L$yzUyQ4py`nW#^4Ff@6Lq<-Efs~fsPL$brhb`5so*68HyFYB0Z#W+r> zbyl3x#uzbDGMBapSu+F(YyHvD2abaKXl#SVXFMJMOjRU&H1fe$h3(+OOEWS3b%XV< zW>~bPG5ZAgXFyM2rWKk${D$he;$(x{vy`u}5}*kjYTE}UhVk22T<~ZD0P(ib6b9b3 z-*om7)xM)(3iFnu0Sv$`>sQTkf8J1T4x`mLM->35x7)_c=Nfm1XE&4P_T~G3Ruh?@ zr4lcHb>O_>lW4Ub2;YP*A0wtTcelNm_kykaRJJJ2Npm`zL%hQ_$R^>LT3GgS80#NK z;%T*dBcy=vR-K8k>n=9W#M1>D*mj+hFQdnozs}?_cNuOSpJ-<04$uC4kOS0dr|du` zwl%EKF{>_?Dg{6O*AYE+iOE)G4zOTgv>=N);(F(cDDog!!Qq60Kv%HFJ2z-NBG)|( zvyNsZO@+=Kp8oGWF2pg`_rAlK<*%&P)!?Ou=QqP9L*#gdFn;|u0|PEMYQ-9|;WHu| ziG~v=8v>A&C;X9dR7i`M>QZ*`_0<*D zv$$o;*tRIxl~krr$`g(dc$*9vOBPSE_H(3RQW9+K*BY;N{H(1d<8dQRwmP6_=I<;J zhdR9?P-L;by?)2dolp6~`)esc^?**IiCPo2-$`_Uid}_75EQ0SB+-b^6(&YIPW z7$9j}EIl^~k&dBQk)$hINB0?ea?wjxdX3cY-16z_r9=NPt7733b1@fJYa6zG^Iycj z%IQPX&%`yFBV2C&UE-_Tus~YUcT_rs_tZC4E^lXpm4J6v!C_pq!)Z9O+f6#?V=?|= z7L>=^`u8Tw@U9UyGbJX#>7o6&VC(sf&&>XFwSwv}tq9cI67DJK1kY(5 zbvoVjfxODIjfETuGllcwj?EDjbQSF6hV=nA>IgvpVgmALNKX~Rc|EJj$x7gwh7(*y zlG-Nll|87FQ9aGZk^(UOl^dK_L*|T$4a`f4&b>^;SN#Nt zg>Wawt_W;LQ`+B}uTw3Y?XCE%S;b>*t3RX4F3}!6$+WiWvG=5RZ4y#Z{Di+`2#r>Cus7WH+Kp@4< z1`CtQCM2^B#KqO_s4DrRfS#*CxG!?kyc=V-zR7vl%C4`09JuqTo#jW6WEC*U%HbW^GfI>^+%Pi5 zoZquxCfhAh=LQd3PXq*i$UXu#xAGudfaw){{Jhf+_tFB*(ZigT5 z*Js}Q^#=uD){zPEf)JAq3KmG$;p5>W0+1R=JGm}9*&BO*i|3xEnNln~hYd{=qT(ZGdK3$ z?Dk2gk^RfMYgu~Cgc|_DXPA+9H24 z@Bj`s2!%R0ieLZDPF^e;bnk>Cgb0v`jEb^&m^ zffDoJgn|Jjn8LjPaN7Zt+)m8pYKf`_1v%c2O zD1(m|P9ueZ?!phm(q=Gcj9>?3TmgQd-}P2;oIw6#2Wf>F=x%_fWv5xZ0KpVfDBzTX z8CyByB{*y8M+h&a2WGT-@Ft!|vjDh^6sEP`uq@!-o#2;jX>^Ve`+RZo_bDlM?tvdLMVh$pRG>rcxj|)K3YCk zPud!e!Sb*K(eFDNtC^n~kBI07!G5C|8^hqMg>HZnM3uv_Zf-XtEUCHofbc}D`jO0O zg-Rz^9mdPN;oqy}v$>h*x5mEwq;MS) z0eFJ_L!u7eheA0N^$r98p#J&O*+|?io*RBpK>?%Dp%poTb15!@doB3D1#yy-S&jt> zxd$M0t>zFFz~pLkXbqrOuxT%8b&o6UF815{-awZjpRwF8JN|jOkx?8Rmc~}~S&{4b zj{kdH!b=qSRhyL>52G7~zT)Zuc6Bu4aT;SGk$UhAz4|7(UwAIc#Sw3o>JKo5kfF4c zp;`RYKOM>W@aa38awHr(9+2h>ccxJFjomQ zqvF8(++gQl^Nj0utznXGJF@ z0R%Phj0c4ZpmK0D;G1%&z-B00;M>D06fMY78SEg#haAzDb2IJgL-eY^I&RKTLxblC z{8y)ftdi_8p-~F^S|p6bakNH_tU<*{MiK23&!9q*m<>jMTO4u8B7clru|=^5QX2J} zcqyJ29aGtOkpP8o&c!UVlJaz)hW{a_vl9~rR9N9G@@{OXW8-DBH1u9;9yhwtN%~_l zmxe4j_Ap&h0J<{4kq2ZOlEhTE0II+Wb{5b>@?40t*x2_JZoWI1wU+%iavVwCPTpD5 zHOj#b0JX9J#|=8*R1gpY0000(V=yBC01st+)!&!Q>f_`vIVYsoCXhfv<-pkhkz`?) zi$X4J*PL5hw`$wA62G7L?||q40FBJR6&L{i9Q=>~*@RydvY!F12^kPNEic$Y zIyvv$vA3~pcI{q^B-Y%{y}i1t-Me?MIhBnXzT?6?DA_9P#__w46)Z;xe1fyQ)?ir@ zaEM0^+gkxiz<>k*0ErY?5fs3`AKraC_r1H#+^pSl++MBqN9GJJW@RQ}R)td{&ZvSQ zAPTC0j~_rNArLCj3Q$U*w1^L)d@N8%#sU%?W#Itw90H8^#3v5*1En$!I$%~a($0o8 zE$MnH`t>wQHBwq(Ox!m=_a{3$H$gG~|DgR9WhzorrK&)Jh1B6q76oY*REfcw1vky< z;a-KFK$K6_oTr`=7i?CgMOcwWV{rNoh5j84^Kr; zOXX6wUBX*;a*C|%tcen?aB7CuOJOQ>pz3NOrt6H2rAIcZ@<)N}AD(K%r}HS+;8nU3 z*BUuUS75zGm7k4xB_69emsI8n%b2X7oLzv4M{uc0;b}K!)2VXbgOJNve)*j0?+tN} zU(hw)3*SHwnms1#IX@S8$n0xqq{%IG>afB-Mxw98XYI4&3gZ5iG7TC64J>vNS1{b2 z0ygxzOmXt+DCJbjjub_Ib?T*R(f4K-om<&HrK-0X2n)E<6wzEg!giLK0J&#vZk`MTO~G>;mGrJBjp8m(2(Q*9%voW65TQvhM9LLPx%s!WwA`1)pr@j@g_YRXU0M z)E~Q`fUnMhe%NF0W?`OkqwX{IVZNJ_0yc=w-?iE0LchbM7a33QF5`(R)R%vQf8IUWDiuv+#n<7(9 zv@7VVQJ^8fSa%(6Kau`MC(E8`gX5C4j?7geoWh8IYuFEgdqs&JxS+Wh-aRIm<5(!1 zTE(qvSb@hivtn;hWDM_g3-;0{@~Xi9-vp=tdO(H049L^`@i`JNFx8N4wc&GjKFD`I@auU=@%9$7z9As9pN5HlhcP`pmibBav&G+@Na=OLglgzHC>@_^`31w6;U zb*rZ#@}muZ+qM+Byn=W*YnF-F4GJeL@46^rwaT5kCq@Zu*}=K)wQhf)0pqA806xpFo3sJw=a}aAxa*b8RY7>TjlVaL3p*2;T0)~CK zY&f+>3M4r_nM+25q#!Q|2XifkDWnF<)W8}t1l&cmFu>9w{kQ@0jnSHY>?vC`SbqlP z$VgCwTSP|s5fQo8>sq1_qYTABc&_fa3o2P{BP$3Dq3BlI$s5z0$wbtvB;K_uE6~#) zG!r=Ho};(8o{Vv~IlK!Qfyj19&(1tl%PkUQ=e&%;d-0qid*iNpMF>i4MU+`fH5pX0 zYHS9l5x1{yt{hWp35+|px?_8JRrBrouBh%xi%Y+~?n5dIE!&c&AHdIInxPaJkmWQ`js{28<|K4=OP3E7(7ML4aSmW!XR)i1X8Dmcu=)& zGF<4zay(r9k+h_ipld`ye`1gU-sq-?c)ngmAX2aKV7)z%4Dn@jbAWp1!ZKV_P??ld z1QFJuFZ$7p}y@gZ9XQ~d_72sSZ`j#(F1axukuR1ZCEC;LwLg@$yGp8gb83maj) zR5zku%R31%EFG!llwC1`u4Eky;O>#>ywpC1?7-4)k0CXHps2ZoU+BzA}ZF#t6Y0GYx2?)0|c?@^$8Oh8Z$JtTq}&;hG>6d9v7 zL4@aL0-}6oQ92Q70k`A}5M}@kx&lxr1PJm$V52v~0~k~=mjt7kY5*7yffh;}7ubHf z1uy^rg0UExpaOhsaR~w#VjxI@;~F#oGz}po>X|1({N~`voXaW&h=73m0Eu8cKnrI9 zMgascwxMqo0peHzf++X?Kwu46^gB6IfNvNQdsn`&2=WQ_ce1KTaP6Z1;%$L|061_K zf>iJXdVEH!5(q$n#UF6)6oK0rsgpG{X7wN98tnSo3J?Q;NE%>_fp#Vd=%gLsM1dX> zalJjjJcmITLMS-+P^&jG5MzY(0*(Nb;W&{Ta0)YhEd?Tu6<{Pm5e-em(*t^Z`9GTz zV@RHe1^@z1adZF_lG&n7?uRw^tdOAzYu7(R@qyLbEu6pU%Mu4wfp=s(CV1Lzdr7FR zit-uawK#YyjJIl!@N4OIUU;bi`t@ETC=^jv^EN9P)Eay^xJ4fmBoN&P%1-GetD}A( z?pbFuD40T%-~8%kK;>>3=QIFqlm-g%b}=MYfAd%mnYo%NRS?lZN!$j_&sr;A%VRks zf9_~JO-8xATl?$u_@Z~&%tNnWODBUVs;W8OIlniv&CoD6$_XC0#CHQYCh5cU*Toy< zIu!lGT#Nrn97F^4`}_NewX%ery=*7vZ2P7JVKy@t7M4CkW3-9Q^59nk+yoCND&dkL z%Zd|k!hvjJCFs6np1)>&%-cykx6~&DdLFN0mzEOtn={C3M@>jq3u)WT@@UH&S66m8 z-Ts*8Js9OF5W@(b0K1&qFhY!j^#GEh0KhKj1P9e8g?t_nu+hf(k-cqy718lY2xG|O zDtg05gBtPz_=jxMu9qK8!!yrcv2Y08pWS zP_m%e#&)9q1koT444~aB1Hm+yP!im-maWgCTO~wUCU-FE;2X05RJ#U@J(ybYhl>o{ z(#RvKUfZca0N}uM!Hj~KAg(Pl3lb%EB9vZP^;%+9gK=be=h`yNl3SD=*xVc%Qv^AA zU^Bzd_tlr5Mk-~6Y&bh)+gS3N)+eGaWaJ}Ozs4pbGq3^%e?1NMv-DGX&VPMwYlWA=Ti?({bJ)9gK5T&;?QlOy}QS{g3@vf|vGXISW zd7ttOTar#sf(*sRRxOUwwm}Im*oU~SXN@<-&LLJg7Ce#!>F?e9iiwckus9kgKeuV1!LHv2Ph@8-%<4 zg_`uxNHZ{^N#2T#&Wn#>lL5vNmvGUjSZM?2R4>#{rNn%{&w^HmjT>O ziZ>ArrZ8z$Fx~K+tb&Ds7{mVQ;2SS})H22~b4nsJ4!7yi__dX(@!4kqSo$+7#CBR+ zvdE9F9{sYMX2k}XkffA8P!M~_kgE!6M7YK;bO)7dP<)xldu7G&aX}QfDeMTqH-HO6|!2F8)cxw4;D8u4Z*a%X@ z{!3rxEm!n6&LJnGH6*@gce5#fG-xN%0Z9g%k6ircZO}Ctw z=H$hPHuVEBY-njxP!q@BS&2Wly$X{Uk?svKwT*T_9jM)>;n+8`;b=BPhHLx>CEPk2 zpYm;EqXnJ>Y(dAlf>=%j&bZ`_8M9i7E%m}9jec^438rOEX8Lr94sy_EvX$eG_mv4H ziU5{#6AR9SwsT%{Rzb>>+@JU2TnXK@cxxuZtk!UKi^XmS5m)TlMYsp-BO)gjXf=yP z{`>E^T&*kD=(@9DIZd(^ZELOLUXEgS{6oC2@Sg+&@z&d8>z38;!flRI-xf+ToEcT) zAe%ad<)7b+*33M_N8Vw|^KsF!8;IIof6{&_5ppukCeMC<9!qD@m8oVP$z>$vWXEFz3qicf9)w`93+lm?(!#}cTHT| z1xG7r`CWOuoHWmImaB#Pllojz6jkHTnI@4ug`_QETD^_LsQ{BvrOzHQlL${u(=^Qq zu1P{}^H9{;$%e5R}V8Y9xYlf$Ez&E)C@^GAXF1NzCAu$dcNL zu@_sC8I%*^utbmM*VUF4duQ*Fc9UC_`KC9Kg4V_jWeRDp@@)`;!-q-684TbDAP0O| z(tU(pj$BUA6#U5J9ZrQh8$DmU@TBO{L-d>Xf=6WUO>;ihgBW0Lbs$6}YJus02`F|X zI$9;RlS|U@8cHu;j^;R&e7;T7xZx&Id2&WZpz;1Oo}68y(Mz!0ZTUjoD|9KR&L9?- z{EOx8G~`9bDpA=+EXU-S5{~D`;2?L6WH~7W(++4wB!}o$!xYnk5L*>V4!`V>vfzgp znXdodx=oPrOU1sEf^E`2~v*)JcwpQV7 zxkI3CjoHMyqNi`AMC*Ki#os63`bY1vStwI5Jl82XU5UT@Na{lUe#2VArz2g9B{;$9 zPro|~vPO(3(_EyWi3|+KhAocsQkR>!^pzddQR3k{>NtU_tjLlT(dc&|&Ct*kgwi&| z%iwGE(LD83*Ypq2I7xg)_H%9om&%)qJG?y7`31Do#BxS*o|JHsCQOiBc*`#?ZZ-jF z5z~@YoVe~7$fk9QaFhKZn)%DM7$HH84v);I8+8MxAK}sPm(~MVr}m(k&3#y-Id!C4 z`5?D#g#PKe!fG$rCXZoo4-gt?0aWrHq;jo|`NjRdTNghR#USO&rj@auUQMc3eCWP)F$ZivYZ7@m5%432ABnQbi>4_-i;1Pg6 z1uc!H=yg0K*25Igfv+SRaZe$cpm4|m(HXQ#C2`qcIFbrBkb#n0E;#TWNTLuB0{{R3 zL<2w~000kFvMg+0%nCyWY;g7^U@LQ8N63`i3J0RjNT002e=0IICO?;Xy2 zck|htOlxE52B>5dtmW*oIoFY~pFpDs_(Jf9K#6OCT4@8Wr{DyUep%_| z@KMKWf?V5MfIQY$oy8c$^pQk`S)G_#JORyG!lObArRp#D(!?n$N z*!x4qI%MKTIA-4dL2?|1J9&^T%ZFwq>Exd%t|HAb89^G}2xWf3#XF^MlG`3fjiP3Q z^Y)Xr*wWpm{gTVh_HU33^^^$A(-E^JZ1Qn&*OrYh>vK<8>Ku6?_$!m{3eIhT%d3<{ zSJA(WbFU>J+ue<)KP1UoWTjj%+nzET8k%A4f9hBPcDcIml*n;J&ma&Y%WngOLqS4* z!hk+qCyy;Xz065_Mswj>1Rqbjmx)b}*C_4EfjaQ0mdEZ%cUTf_#dW>Lg* z34=|v&D@xH-}%m!B2Kk1f^Mm$U(PH(2k50kGu>A8in*!%ZMpL*9?2)uIYogcj*Cg$ z^pN>c<%ZkK6wlt1Au;+Tkx6V56kdD|pQv%b!foc%XS+Mjzl8hTzl*AqJ@lsgSWVlv zvshz6rF~X;T08p6CFZ3p7ntm~-IzyNgdZjQFtt0woCV%J)V+hvlP_kp4c!cO-7e0? zvnpV+t=$Qd9#f(DUb8HgthJA!!n$cI zB{BoD7tk)my%qm>72MP59`GR7$3oVe(n!AY~cz>VH)mYh<+XPuTq1Qql2D??C>SX+a z`TC34!!MLmh$%6Dc#N(^Sah-=X9C|1NDI(r%&l986?}Z zP4tmpP3LqtC{1MJD$*2n%|GZ!ZxLHVa>n{JK(nDo-n_5+iXY>^u0D$1?(Njs@SK(Gj&-o&Zz;YE1#E zEm#@Y+6{F)z0xU&K?D^&5bg_6Q93`JJS0$GNm8k5Dj4E`!>Z!yj4`VWZIY>JLA!);9j%k-MlMz-TI5;@!+y~(V5D32mk#bN7^t*In3T%V}!ZI&< zQ1XEsleVeLLp7SA@IsMO@*N$o=zlFzN8T8uSMyQoebIn&0P`j*g|&w`XSMcoM4uiv z$5AHq{%VylOdB(wv3lpG85(rsoSVgp?0iWq6yQw{f|)-& z^N6!LCZXquY6j6T%-}KXQBQw{iWOF%`to z3^;$lt7mz|qyLRZL9QkL$(&}qJdB9mtRF{u)x+Ue=aHbWp}savtQ(JaPS2~FOq}3g zqDnQ+WhpS+HI)CWU0z@GPj9X?$TXiU1uU+Yv#u`g`MzH&bVZf65365p%zVX{O0VR{ zyRF_*&Q{aXFBG*TOD!|sT_yNj2NdEi*o%r-Jra$u{S2$6s^{2R@)5Fwi^Jz$AC{#7 z&_AqNUf`Pue`^OrK*}VRcg>(tzogIBAE(jG>CLmU6KLC5adoAi_f>wfUr4Fom%8Wao!HKI z!`;uNuS*5hk+OS#(atA3)~&|K-ETUwvOc}OX(>i}7Qng3^f(SuP5BT#>ojEkbl2W6 z3s|4f1~4s7^=-d!PXvO|>!q`O-t}hUCb%Z;gF*$%xP0uN;13EH;=~{0z0K7F)oB#AW+X$2EqzQFSO_K3Y^sWbQ1@wT~0X~2Zp}L6q-~YrAf)6`@jFr?t zd^J6?Yfy>0w{H~Wq(fF10Dw0S96=<9x;G%`9n#GpA_s(xVLOtp6Ak3=hL(HC2tY#9 z4}o8>W@rGhL;;E%>$M0FZ%={Kf10;D>{`nKI#UD0PJqStnxO^6_mZu{q|1RmIzZdm ze#m13cAoXCNKEEEoc!#6^`|n!8h{qSo{DC;+Hk)CP{Mww%phh5Q09UA+h17D+tBg` zRFNP6Jq4u{_75OGLnQ_IauDfoP;2-)>65u*c&W8slf)4I&m_vXWSLBDREL5W; zMK%9G{4TvqY59j}0H96IaXoM;Bg>q)TC7mwOaHFXp47wq_ZoC-<@Wx&a)AO6L7#yl(sA~0 znf=@XmVxCCxnfcS_>WY-;#gmZ1bFeQ7otwmjUT=c%`opI5S7xs{A=>)qL&hj3sC^e ze3e2JN%6yTKmS9#5yp`NQbtf7QPaJi8zlXt|BD&^pT&>E*F*3X;k{^EyJnaq>4-k~ zXgNUq03he5h$RLE{r{93FhGMSbF&ACxd$C2-=uqc!prhK0_up~yg#Q#`s0P>77!!= zCg==^4+l5?K=dM1X9o~u4-zalQ9KqK+yvkwniZL>u8iW~^^ z1|Alj{8x^W1M0*(5D)_Z001*%Kr#RT4`oEv`ls!?mQ(K3 z)-}{7Temi1E)836*t03JEcgz%n*)dg8+Wu(|NX~*07k|DXhZ#(;V;Vq zi6qSUSuzVVf?-bCt57Z3DtGJ-JB3BI#qM_(ZXyNl-g|e>DBEZ6yKLatoE~15BZ^ef znLg7+J8Y<+5&JrP3wfpCx&T^8Bx!H9B+38)qyVZ$01p1Zz4!axz5Cn#x4pJ|Mb;bE zwY8?*s@A3UD%UCw!VvthNJ5}MC?G(g015{D5J-V7L_$Ge7!YI-$Odz)Uy;HAIPc&b zAPAER3&cO*SSu4{nG#YjS&5}8vL#vh$z&Qd?hN69i}Q_@#X?#}l~Ak0xgZ#0ypAQh zw}cDVf;M$JXr$$2XDREK%6iy+EtieU|CN)(Nz+-oqx2JIXJ(&9%+1cu4NWU4EiHB0 zRP&D1{6}72B#R}`O3gQG{6;DXpENRyGL^G2=}3mxO?EAnGy>GqgAx=?!o2n~Gnq)p zHp$uPrSW9Z24*Rlnrf92G8h+PS}C!w-e$oyOqGGnuNBRnOD5-^ zY?_|ovxiv|bc87sQd%lYuvb3pPR3qVb-7Kgnm8_XH(jZmMW#}i0_rSOq)HK!vVG4P zHL+t^NM>O%jiTfYV{IiZ-hX2msazY`Gozwa+ECyf|H>mPCPLNlEVNJurSmpz#z*5*Q>oqD`4ec66o!OUHmU4kX&me6 zIvb{3fx~vwsdmIb*S}dBz?_j$htwpR&dMEqvs&>11M@K6d81lW{7Gm2jV=X)xun?$ z-`1itX>9h85@@!~#L0@8DKCQP2-Kl^WrY;{o1OrAZ_^_3$?O-C zVti;eNs3@iVz5$ErlnIOTjR%?%2X&fY|`?hG*Xx;> z6yqf9#lZ23z}AD2Y{^VZm#}yH)7E942LLFvR)%HFo@VYL`^_ZF=0@sh#vz#7aJ$ie zGK|uaozyGp(y@l(DA74`0BHTZmO=EQQ^CBwYiVZ(NS1c}+w*=hXk%DtCU(o#vO=jA zZPDAb8Ql6a8y+1M^h8jT*0FDw>v>c|cFLOohB?V#tUdQ_lp5Mca=}+4WWJLcfgOYE z=h7!KQ1a*94;oOehX0Lmmzm_r%>GNRkt21<)62q^!DDkc0?w+winW`|Fs9*pZR)yn zos&{Qbj>16a7C@4>xdASxWr<~U8Aa)11tqP2O|8fi2@E4W*6(e4 z9K%Pa5KZHl3ij~!>tkB^)yPr8(bB(;(w>lCp>f2CQ0-4aq~}Ng^E2&h3Vo9ybfyGX zR07e#R>6-h*Hy+XR3@ElUe-xCF;h_D%-ZQ!jpLnxNsB6+E1K;s{1yWlBPTIqv8g>| z6n3~LG?9hncQKWDh^!$BB|%)E8%9 z<8AVP`~|bDD*PvF^TEjkb~3B8y*p_j4R9WX?tgXB*)6C@-W|Y)k1eIN%_wRhdY%8 z6@5%1a@GacZ7t~|&ZhH7KhrkMc_f5poM~ZE@!n%|Bd&EjZbN6L%Vg0V&~6Rep!&#{ ze&oxsR+DV)CePBTSG(od%eonX<1RAH%_z#LG~;uq^*hz87#2m7-Kr*Q92mno7y!A% zX2XgwJ^T8ZJR;qFwut@?FJCU3QW|imHR`X|G+Z0zjRq->I8=E`$t9w8#T>)6$I8`= zDEpHkFnY;D+_o>#_;OyjMipJE@aj9Ho{+PAfY ztG_a|OH&f*$stxxi-?lHrZn`ps<|}{GFvz~{B~Q{F$xIa*)^wot~b2C_PdvOn@1AW z$KiwRAfe;VnzIR=x;~yG-L<9?5~RPXSI@}N;)_TPqp-L}vn^|Rc}qd(moqHly1;I~ z$c?HtbiT`%jqx%pg;&U>cblLjOK!~^-9JGgpO7}4?TlyS9hjSXdRY7UgqI3fZgwS| z{BV4~8L|`y>mR$-1@uQ!bu3&G590`hf+54}acV=lA{(>e4~t~kryW$eK;Cs4@-xai zrZ!N{Fub>Q%Q`pBg$%N@(c&t>PL8bm{8DV#^3pm?6ePzK9!0?EZ|f{v-d<;p50~P6 z^ZVcDp7qNZu721EPO(8nIJ>y#$qqW|$o6(<>g<~6AG!Rv4ZD3OU&ebWp{g)sqs%Qk z38L|B`Wk{o?8sPvn=q=3^s>rhyp$V;adE^~0>#xV=N9(wZ(0?~4`5PcmLv9{oXNId z^kv|xH_4jmeRena`h~FcJ6d*5!N_TfhS@MAM;h2tvsRlCHF(~!;6=T(+NE?=&I;SM zcuD;Xx}d{TWxp(ky+%bQ9LWb_D0d=Nj#;D9l*wSTHJz*vUeES(I?=&0gz#*-u;b-o2&=3->(d5Bkv7>V z#=%+Fs5=Ph>1aydrfpGG>n*{=tr{AGyg#S~Qs#C?L3a}*Z;s$o-m}u4 zeW%xkpWZu%#+e!nFz-B!72J4Dw)wIn`WYwCTdfyW#YDK9rLXPoJrz1?G^Y3(T$9&RqtMZfeo+0hw`f4Tgy@9!PZvv!6_+Jbb@-HDBK@o6t zjJK$`>uP{)dEgG2YGb*4c?1iY4bJ?wmoRFBS>8oDEdS(EAieh(I;>Zw zmDUG*oZ4n^!7de&AHdAVQKN8BzXSZoRti^ zZ>yU;{FmF;qp)X5+3w+xsUKp9@SGjDkkqBv;g6X=Pu8Y7xh^c3e2+p-!(xU7M#Gyg zOC~(Z&d5AIMVu4iQL90_-Zx35X_M&&$BNg#M!N8*PL1W_y*PPF+h_gS1DDx@mCLU_us#Z`h|JoC`8Em2ct*5lR=-;?bT)YVc!nfH_Cs)q?v*KP5-X-Q@fw!JGJF z^^N4o8Q{znmBd&`=8TTZwLMbHMmYl3Me+cIA6z_%0D@8w@qsM8AP54dQUH4ig^L$b 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

BDQk;B?mX3XcnI|eYN5gjd^ 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

f5Y2(_FP#uT*K2L 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

Tvr&#KM=^==>Y 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 !# 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�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¬>ceb_Sjv{XdN-sw_QHm2t03o`+30n@HB;W$z)g)Os?l!o|ZqwUz zn**dRrcRQKpa6gn5CZ@J05elIGXMZ?Rp6-Z9J!Av5KFd5mL$;QBny$PB~Q8(=_Iy5 zm!?t6y0??ITE*1|N%!Ay`~YBN5Q;_s;1CRqmcslq+md9$mK#aT@Un!KVhBTfTNfiB zl~(qYo9#tAjEb^Q_SwCANpZH>z3EVo%2KA~4Ct-CpplCd{iO#l|5Bw$Um^bl>7}#Y zMmCm~gugZ*8~^|#16MQ#aQy(@?|1LLyKcL$>$qF$?5a@Ogtgta>+Nktlt7^X5+}eU z!~ldLK$K;GAy1Nom?c^i)Ko6D1*lTBqG-556h!!01R_4blG_#`KKujz)M+BBa%kNw z6fnl=$%KYXl$OJwwb{&r&mFI4tDqBVpn}b;)&xyu=Y83nY1}j$-YT!gq`uQkDv(0y zVq(aQ^fiqhwrXneuc@d}(Bhq`hcIcw1ymQVL3zz?ueSInOR43yp8$7Wwl!EV9F^F8 zWGMMGQMTAcwb6_Pp<9?mnxSY=$hR}w?Dq`MQ_-^0oLI&5wMs43FqG?2(C{nitI-rt zt6=OVIAbB8N-QlXcb1kiWbJ7$7|VVt^ka#4F;2~|O>@M{pQ$G8>`a(m+NS<6}alijv`D*KjpZ~*Bm9Ee!?!%S3LWqvl z6l)MdS&0dLm~OjSUyHuJGrEk<@p9hAoG)=gcnGN`oLS&zIkK%6TgHuTMlwB(fs zxw|`AH|^{#4mwS4)iG(zJw5i-kEZM`XJ!}6)kGIQUlzNbvP%or=u}e0JlLQa&!Fs| z^%@&VX24i4GA?Gg>V1asKt2k#Vbt=;C&^AcoZIi_D4aCx?*^ zgRvQ|vp;~|CnKvNVcF7s(A&A%zRD}F7b&QBRmu>c;zh-?4Rz(8*iHkBebh7LR6Re| znhwLt|2n5EZ-%MEV74F89csk&1+ZlHAo(%%bX%5EIJr${^DuqYbC7f$Tzt)tW(FU? z$Se5$jt_#1wMBX{M2CC>mOojhTq^A>NLUS_fx|DtBw;M7gMsW#*jLzVVmrI;fSV$q zC8(d6C{)5S9{yb9?h~)wjx$q!P3qq%>bjf$Bu8BOkH`S`j*JB_X>4!AM~vH;7?COo zx`Q{@RYF?kDkC)GZ}2qj0nf}eL2qZ4V2-O*H~NspcU@&gA)g5T=BfkS}|;MXqrM5?5v(H&1%A0hoG>)7+o? zppVhTM34!|Y%oCrQ8e&A#_96TjOy+aQMlKePcRc|RcVf#CN5JprW+ z^eogUd^#TXrC)`a=RXet$q4SW4X6h)ICXj`+Yg9yaAyL2J@NtN51|zg9MH12$6KBF z#&R-4&GpyEI6t5PA$hPMrlCKj+CZiQe;1r@FFzo=VLA}M7Ew)o^pe8?H3<014P;u} z2VOoGi9Vui$lC=-+pv!<9W;pgU%&ZqP0p&l-hIU-razi=b%>RnifW}YnDjLYVpS{mk5^GsakeFkJd1ZG@^ zltWtkYHTFVp?5(e$wOfGO6Depwikw^Pr@E@aW8Ji1Gng__w55)*1t!)yMC)0=A!sp zfIhn?=n;=#d$13I7`W%|*!x>!ei{({0E{F%Xb&}7(`L2$DWWPsO+#lUSX6Tv(EhMB z2YB)`6ZnW^wU8v#hykH|qy*IPHXYRA=ThJIkTl^o>8Kz~nd$}#Mr>U8Oi0p0tBAQ% zpezQ@O|5>A>qM9{!q)V;+r!E1ZR5QZK#fj)Q_P*$$4AThSBsGDcdbzqge2H15;eWd zvq!;b=vm`5_Sx@_j>cMR? zIrCRdJL1ZM-T}#p=b{Ux!+g-(tRYNJ80bbbD8BL55w1@QBt{NteUjWAljI`fUpK|N ze-7H36uDm6u8;d(TTM>=%}yv(FHZKSBGh^C9@As;mMw6;;f(Ia$j`ymDy;>lZ>zL~ z0102Vx>>6JhE~9ziVL7A+RW^I$^*u`-<8 z97xavDvXbiKfZkC0ZDM_KX;xT^3hPJ@2cO=61x6_j5S$eVWXdq&m$?iNID0{Tg%Eh z#EX!QAcC@@I~X~@=h2-A^VMkEpYoM+Pg!KSK0uq+;O;)AFlDt7VTEe!;`qw4P8fQYVAn0Na&SILW7KJ{5!E((;*Gy z;)+)Xmv22OV(ohOHOQwfo8H{aUtKHH;@TEs09#*8UTm4VE#0F#p*H zimf19kj-YAPbwg)^)SaBN^b3=-#=6+~&Z9a(+jE>0-Q##1^O=FB znY*7(Lb~VJg_EOf&j&#lDUw8K)E9A|DVU0Chl$zj1){OzGuu zL{Ui~*x|NR%xpQ5)#d0VlsF-|PL}9a*xLb$p6G+af1%Q;GQ9IlG=V6e7-t) zkqx&Z`DXMTl>&+}|Kh>X<3A&a?V(=CiZ2M;0VWu#YL3D8NcT0pQ#$BAk4gmE|4s`a zSoi|;xyAWI1Dx2}rIeRzB;PPfG_du?3j`Z2mW<>rKY4xkGFKn(XgoWcFPnMUy7ltA%4K#TkFB}`pS!W4*A04}M#HUsbzZM^1M-OAQ%P4x| zk$59m*`SCYO+UoTE?X!T>20rk90`)KUV#JzWspyn+N-{kA=u}K_)3%ZwfsYe&2P3o zc(E-q~u89OVa`qW_{e`nbhPB_R0TD+hoap;OKK zaZ52q$yZuf((lQB)$ppv^yYHxs@jxwcj<=3rcCb_Jizx}&$Pcp*U=IHx?z-&-33n( zzjy93%!ur$gtn*-F;h^vSVS*P5LG5RJmeRRUR-jQidp_bR+>&w ztiPI~dcRmm^21e;B$2@_QP_06!0&Yu+1JJvm%@`Xy^b05^ZtBl@=Pk8rJV?%{p4yx zRcl#49A-5O1VqaFD3q~|(Prvrh~R+&KG2xDEP$0A1ZB7eaCz4D>Hv;MeD87202r*l z2Deo)B!qZ`dqGG7);E9vtLGpnZ$3kWEhK6P3kC_>Jqvs;Jsz^k>_RYynOGUFvQLPo1QmQLHfUBqk~nFOCMg9 z+b$M65^i3fca!2WYT-s-cQ>Qh46vC$7UDD3lYZ673DF(~eI<-#pt78V=KP*38#q0-7&-NcI-+zIG| zs09&scsX1kC)aZhOD~Atj&`fB(%mXhEG!t5q~NgumFm$nG!Mls0$*kURvZ-Kbm?* zE&+o&6HGim>)9p@m!t-B`d^kkky5!w&=B zJ!^G?i8{*Lv);XRiO$VSdI#VMqFJO@1Ys58$SPC7k|#7^pU?7jeCeFN(+267PH_y+ zO)ZUATUxEHrl`ba<*`$|#zy8w^X5!(^s-+qBC%Hcv;>d!>%!A16jLg3^Q4DUcIXLZ zs0m*oS?-X?p_(kg5Df}4?kXBsZVF^W5v~`jz*;nytA={57>!OFMnl)QMnv*LhM6)| zt+<>v1KhzBnj(h$v+$lcol68BjB6k$=wU2T-t-&mR^Q>XMn*pDG05L!Fo8Mdl?w3F z801%c|6(@)T5G2LeDzaF*EjlL&gq!$10ccIw0<1JR>$~oTn|5k&r~(i>o#@OV_JH{ ze=IL2y>=PaAe2=t0e+O~?Gh%Dfbo5)IFO?Zrll0lu8<$@1v@SGXx>OFp3EdL3`0aO zD_$t)cCK|MV?d~WJrm(c;rpnum!dPgP#@!ab1tnx@+@U7r^!%V$`qD<`$y&V%t43> zA)fgdtYG)TyhcC!ju22o?lcScJ%*|lEr()7YKnC5804AVM7gO%IpurarVT7i^Nxh_ zBY*p0tDhja2N)TvFj3*qEWuPZ3NpeVY*ShH>@ROwQ51Hu>VBg7ElK$-;8^AWiq@$1$$_I}i%9OJW zj1Q@Q?Ut()%$hss*1rUr@yarcKvtM?Mw%dBPuon>OG{+3lDq*7IHijDU6x!r`WRRR z8P_#8qK`e)xe}LxSFKq{Edv>$6LCJv1No7gMrNX1){t8cG*{l7U|*)W%hec*UDC0I zF*6RYGzQ3F`E;3*?3TfzMLLHpE1t2LPans?ZV;)Az@*Ph+~}Z8YBWw(tfQo5d47FL z?1QH=I$;PB%K&=JMAOPHQoTEyy{PRZm)99~j>hdWgIq{+-%`y`=E3U@nykyAMcsDk zLkhc{js-H$yVwILaM&&FJk9ZzfODtN0N$Wma5GPJD={lex_hzr!DfwSTuOEe+a<52 zoOcEPxvl2&Smmx!!dR7x=kcb~QP_ln+p$=ZMhyz($ZAm(x{?Ax%r02QioC^((slZE ziZeDyF9bqg1IlCvw$Yu~p8^s({@z5%5;<(+2A$EUwHL^uu7EH_B6HMof;BMc;XWpg zq{%l9Xbh}MV!)WOyU&Xy;>37yD`sU3<0(9#>Dc2eCS^^f=r6KRjJ7DsmU8qCV6$Sk z;F^u-cXO*nTv4%P0CQHclvZIllhHm}lo3)W;>cw*!Hf=s76y^pf=;0L4`;I4(tHe7 z^?GeEu&xjySb&ig>ykwt}cRl{|yorE87Wow-`Ac3_grf1WK&d42BSn zq~XRj81#OwR!JpC+c!p5GPK%CA~N&6s?%lF&GdA)&u&TCe4GWnrV5kPk_!9mxj&MO zSjD|A=Bm!smMS`hlBq>GnoQRtgz5fcYo@%!J(erTdS)i}P$`aH9_oQu1+;x`D>Ia{L3AH?=LDOsh># z2Y1IU^;vW{O6M``roR?K=76*f*C)cCq@WcmlaxAb)VY6<$_5*D&J=oC?#Oaz z%>t+l5N-1GCIcXA;YO`@hENFJG=S0`RtX0X!o!HEazK*926ykjxl1(+>|9pMo#HyDCH4c z?=f{02aqx|H}zTpVLLc>8Ub7K=70u_*9=Uz+pTjF7e*H)xr)||xeuT$(j3Th-C(2d zF0)Klj(NNNf-%a%Y|xgxO~-mhoGj#m&886#$p)D}C42*NxRN_+%AA;;qQlT3BPnPUCfiGvY2o$FL5Z z;B9W{^kU(5^Ge>!{QjWKy)QcdBDzU7`}?m4Y@QO66HUFWLsgL0Fe5+D65#lsVyvN-w(xcim$yf8ko{FJJz~ihl z<+8Ulqh-e)-I=-FF_+hJ%wRb${QIH`x?h1y#`SPkFMrGNzq#st0$m7Vs}XmF-wPt@ zEcOY-@THoRr@yHt!@u}J`lOhT@l;EVb{oRO7+=iO%RDTtDau}6xD=`F&&_!vm&YwE zDFst5mU_hdrhnu9(W!8lqLc>`XN=~UqUeSA+)l2Q3`2>B{lrVS(I~UJ-bRPrV>=Cc zJFzWc5rrHnDq3GUKi^YA6hrYAU3rmFeGOzGr-R5V;Y(gd8syX|Y)_8vSKx@W2k$Ig z#Izu47!41A-#l}6JQnt<4;Kr*dut<>O+=JXXK-u2Fx6{h_fEAuo59^P5tr_y2i5op zWTu}RHoni0)|?F~lX*wfy#RTRKMz(HSNVh)b=Edw_$B2z|E#>?#zY9Ll2xU9+(T+P zzDa}Dt;l*Oe*6uCo-c~s=`BB>8n-~j68VcRkd~6z#2*;(v7ek`ompX z*g!XS@%%EGHA{M%V*Rbq8TFH;1@rLKEDch8+>7eL3=r+Otdr9r-7>l<5z9+^Z2sHe zo%i4#&hMF_l^8G3k$bw%pexTb##tjFPPA0Gj~)aF8uOv#4gV&Y&nxdXdmLtyb3}MI!T2W1j1DZ;MTJc(&Pb zV3uhq#T|sn=m{=C1$-Q{RFCt~DT)e;c!1vTGUY)r4nm9ia^=2%Xp6$ANRW1nE*eh> z3ii8n%NIFa-GLbZ}1~Wn7%=g0UwcMg-Dufm#7vNooqI4f`-bwFZ^O?)prO z_N)T$0N6aoui{=nmIOl|BRZdvezNud+tT?=l}a950*rV7dq-Qp0*p5lJ3bI0Lj+k6 z$h*KRpOpY&e2D)JK@toOb&Lkk#yv&^{Z9+W2>fvtz_*G@Xa|38?xHsk5JPQQSCr(9 zQlXYu???;m!4@9nK96U9(q?QVVPR+2$*X#UU}N5LPoD%jxd4c$aqq8}6UoMV!vI#8 zdz&?@>RC_U)L|PSuCzo07t^r}Xa2-q#OkC-*p9V;IiTxJvWE9V>81lc){{|QmkT)( z952`T>h|rc>tpG8I3k$nPe61WUo;C;TBiqMV(>Q$ML7C+bon5m0!p0kn(=!c5rfqE z&3sy&M?5+!H`+8E`94R=)R>-)so-*>Jc~QntgwCYBKa^UxJ?{Gn)w{}t+U@oAm+Vh z42E#ltna9~u2?dyw~emdgC#TGCdl-9U!>NQz2c*EGBo?Yc2AZ`O3`-Wtl@mpZ;N5b zEBV)0u6JOGS)`zkJl#{tUAi{{fzIw2C#cBg%kK4qv;3l|zT3bXrae{MABk2(k5Qgr zc`Mdbv@sF~c%ef^JE%&2Ee!VDlNesh$G~KjCM;%N(6t>|OYpC?yx%t?T!&OU%drDp z7g0`nPXXwO=Uco#Zun0j^~ZJbr>e_dxk zilM}I+9?mE>~(eYcsX-I>jSbe2&h84lxvAkyI{{aUYbt^C!yohuPiP4J^`;0%rk)ba^Z8RF@E5CsFm zELe?wMjmMuA<_qidS_Hno&2Fp2+LpLcZk>7>G*n{4Fw_c$x(rw0{kAIK3%9a1OLXw&C6g!4z z*IrlS{Y}DdYku@zl|m{4nBVePBR8j{1a9pr%rhtrjf>6Rk%&8ZP zBemU6`-z!#ID6u`6BfQ0UJuaLvX!RLFXk&O z;W|&q_ZsQE^#=sr`GO!DKpF?oz9mQ4H0$R+z-lkUqew_EQ&vnbm|m$l%)(e-i#q(H z2%PBr*_@}4c&)6LeM-r;T>jSR#ROB_6^_%M`oQ`GAk1BtFHUQECe2lc@5S?ZhC1{_ z^P<@^r_$9V@DsY-g4A7dG0kuel7O=g45DQq!s%kV0UnO5kRb~H_Tl-2=^;25LeQNt z?ELk2q;7f4bGu=XwCsf)fD89Aru;RaPeY+|52)atP~$I* zsL2cnDVIQvL}i8f4l&d)FctaPr}iCw^}=Zff4=J7KD>gj3hRMbig3wqfN&7B5E+^} zCSu}(a2NnD$bg|5waFmhhcoKg7p@Z6GTRCu2ZVk{Agl)rnC1wIi)#@OMNA+VGhRIX zsHlHNo6^Qq!c=k)F>&w*eeYR48NmjT!60L8W(1H>w4>v<0-Z_9&{2h!C1j5F@&`*6 zR8A<*Q^`b?F>M(v|M+y_SO+@;7(RE7>qS262E`&qL5$Xbcq!|mk> z`W>hG-+$&v+*x=Qe}`;cVof~`SjMw)8$@~~WD4eO6u%-c(?J7*hM3q&f`H5&*dS~0 zAdA8_j1ABWwG|Og5}Urzn`SA4P~yaq4Z;M8zzT#V3>y#^gbxNAb`2Q0_Fq20M=i+` z?I8t^fV9z~!YW!b&Ki*N9IOY3&gEyW9MpgC#rFTfftq=weA@-P6(a^{aM+DfZuLcu zcQrLZEC{%1h&CnIl@1u!td^Uw{1tt&-t|UQtz_Lu+ za_6NLH)a8@p5HBK;L5??HhN;Kj8Z-Lz5k7%^6K}8stvFJk!S^v zf*MF9-EWa>bNNtf4VgR5~O`(ph2!8EYIoP+|-Di{9pEmEm==cDD$N&}10Neo>6O35?vW7AM z0uTwmKv;=23u$Sim9?|mJDp{LbF@4N55?Yp+y_y25bP2(IJ z?Ye5Vo{CzRRI#WsAdngeK@b=4MvOvypn{;F5o<1&f<*x&i11Pk12XY`@ta6_b^+ka z4-hNnKaV_1mT_oS3QxA2RxDgJj8U8HAMLA-FPGe3cG7Dr_4|cGgtuu8XkqeVo$f1B zEFr5n8B?+@`YhQGSyjRqfqGEMe`~!irSjG&7ii$Fx)Pe!m6EZ3GIL&wP9v8Q=1`bx z0gDvI>GK(#i`2|)T|CV7wb~zX2f@o3Y%wP*c&WoJ+s>$xw+IqHhZ+lhgFEyW@xxS9TR`h4-)uhlXfnZ|6GlJp z(GJg*1El@XJAC0J#BBfaxLkc*`7|Y~Bq#)6DrDIv^ z4Y&O$eE?t)laxPTMT&~b3Ytdc>N$0LmVr)9FY`6LtJ^}mY&%pH7`|AtokxiB+a*2J z#sjgRKjX@&9GP>?Og}hO-@yps-Qvjghdo|zYYB*EfYQ{x-*p_ffyrv9xn8`q*OcQY zGLX1}A!ch{AXGXm{6r71vRvRN)A0oc0hK;itCB~G0BmR0)K0GBi=Z36{DPOI>Mm;x zRqoVB#+jJ`i}t)<+rb+ni=AS#i*41+I4;4@mKrRd!s2d36zBYo55(OexmTq#GkY6t zK)6q8o-XUJz2w<;6{U6U=)~AKGNHCJR^!sRvA^OMD5ouz7c|u@cR%fTwzJS}Hd`z> z4P$Icw{r{<9bCDY8wH=+`+?{UUR*7t1|j@B?X-|jL6pmPgU9_V2(D$PC)hLl523Gu zg}K9WH(2*^Cen~JA50t&&wi&cf)<2Dys2W}_)Z8k|l^hU*+$4TBhf{9iTWCspxDL4310wlEj z?8)woGL{3zE=Z%aHd^GPYsiQ*X)z8v>cgn$dUPB*o|#Dr1vr%4t`0BNGfi0Ngpzql zKBX>q+lu*^DlE-a>{MKik;xusdUL&A>YQ9E`{kG>G|kts(3rzXMpIX}U$X&WH-x?X z+-N+U(GRhW#PToM#8oPmD><-QW|oD0?w!-3c~tEMKB>@;_qWp2-$bhPX)E^D%C#Wk zSz9VrP3>JZI90T#JW-wYK6OyPfAsaOsLF*~d3v_(U+gP^sHH3Jtrc95+tSm$SCvX% zwzfUKy@$x1;O<>Qo(rz4krs_sE)p#*Mw8e%_mnp778_{S>XkJ$r&@%O79ELh`hYs! zdey7#+kJ~69qpPvy_U9O%=B8Xzb^W(hMh@^FXgKNmTIfj>yovlT1T_viq-DS$q+W^ ziHKQI-$e|)?mFXHBqzDY#m>Ak`7u z6*BhJG3k=2A-kK6)d`dZ-25M)z6z?UQJ7TsD)HjNu0Fe*T}0CL0gHOYR^NgC%4^YN z;mJd@OzOkjfK5{C+pGtFPCHTj?m_%3Miw})J?ixH zBQ7V-+6F>=TBWj^yrWsUrxSM^^X6Z;K4%?GMfScm9(NLs(6W)#w1d(!_;kGL83G2) zBl%kHdC>|0B+KbbHK30Ci92DF4#;i3*%Ps5+>8n<<6@VB6;aWV5gw{P2JHz6F^Du6Qh9G0GK2l zFJcpr@S%!LC5I-Wt6vQXa*NpixmGmi=qx&dds8LiElZc^C`aEVjv9y#3&DBJz!Q}3 zKWwNDd&!*~0VdH>tIB9|aTz}OCD!EAGl}#5^o4V_b{O&z<<$w?EAzex`1oKX(!8cA zkjqotwOIMZ73lV_nE>KFEbGV)y0rg&2)KKfi35+Cc@8}C54fuex&(>aZ;P)LqK=cl zYvi@7y=6@Ez!!(jJ1vP7T4-<=hdr;w)B9Pv_`09It#a&e_r$ZMJam6yP2tB%kaOKO z&y4ND;tcP)y;L2AK~u~Ka6kdogNtcjsT2Z_F!BuPo5d&Vy3gSEi{7qdl*GL77p*|s zA;ji@cVoC}DTFty?S5s-IU!G$ z`O?cK{_@?_=o!C6yg4LIjO0wmQVUUbk73kn;V-ZWn*shnvtt`2Kh)h#mPK#$D*c0T zH|j6Cbe^Td%7q)6#x;Z34o$UXn&!xdoa~;%*W?4LrQ5aL717*z&w6pX4l!)sywS%# zoHRqoa*H@vYQ*J_-Uqwx6<&7hKU*12ru`Tl#U_Jf6<1CYN5@(LOKts+w}gWwcX5P~4J|60!LU?fBSdV_M4k=K zotE(lzmoIA#xu~Pj|%2s(xji7oLO6!GUpq~YI28*Mt*0D*}^sYAPk0D3UW(2SeKl| z=(*65>@h&g$B7>vvEDzl#PBY1m3tl&N1X^RD|0E2Drew!CN1-vB@evp@nsOs0-gyUAr#De6{|mVoVQKQB$2EATUJy^()$vC`338A;tEDYE`Kp1!|&_%1x| z%cLaVNu^y=wGQE7s?&}?t?;2bUAZG!W7E6s;cjRwTCz_f$>+GU!SmgBiL>pO%8a3u zde+&D?i%rs`aJ#4R=C?s^pkyE@w@_G+B7xuYoyBnwgX^|;lWym#C7NQ{&_^!@AbF! z<)oL;+-q6Q{E#)s7cKtVU*3J4sa(;9vnq8;UqWBxWg?X=v(`h}2lT>s+CPc;o)Q1^ zDl({tegw528!(vQ#LZFoR|R@DX#cXUk#;OSs=)?ucmkV9=JCzQEwPxILEw(@we-rG za$~9h&1pV;e|h1we9GD*M~Kg%NyO^zr`$SQQ)2`GakL0j;1A~9#LoB!2T}I1_>&TV z1=vf$C`30b7_=iKvZ8!u9hOlyfUE#7I29yHfC1Be97+R-ppcCZ#4Zp5Ms0OT5*Pm8 zS#L6PLViXcgK0o$L=)jEOszN@08TT_*&}2C0Ti3zFR3$z5F_~zl0|gdt%-!F#JA;2 zlc(AweP=S=lb)VaLa7T7@(K zh6jXRV!n&a!!`)zc~6Oar7L|TFbO=m6tt=^%T#9&Fv=>NzZU;tchQ1v0%1|eE^fuu zKS5aW|4DQ3iO#s0IEdZXTXkAm-kg4AS%KsMV*)sxctH1toL7Km0}puQ-|Cy~0&sxz zC(SD7xHULEOzM{f^3ts8sd3sJwtnH_fQiG-V=)hFFTB$QI5!=SJD z(uOjcid!pT#~DQOUyx466m2s@vwKvt9>GCu_k7FvZ(m0vMHxXucsw z3^)oEl3*AE2OnOBxVKTxeJa{@ad8cP6)*RQ_ zgJyLlQi83C*b~-D8%pYSZU1JPr~oqnhEbrx zNPo_6Gb}{&!izkB^fG>%(?%n;AL(KvFm9>nn$W}y8JA@kKl|||YXp$;K`}(#Q>(f} zZ-b&d=Q+TFn8I)n=d;6t!SjJyKR-^yDpKcYC(E5!Q+TRBG*Pu4{kf_#E608Icgm;+ zfHM#f0{{R3Gjm5H000kG{3`F4{%TJ2Qp?4rHn9n$fJkUDXxYR-c#gXe>~`iHv)k_O zqYLj(|NV%L004{(T+sml+kuB9$?WP027v%U;j;)WWCqqzhr!sIx$gT$4rW#BvbXNq zEzD(m+orup{qNhoyl8E9ExvI{Cz`DpJDzWAX5+%kXUVLFikQSpW`QIj1ULvLcS3Q* z00031vJn70M=0)h-|g*o+ikb+*xG;F39C{7*!(x00$La(T2PPxK_L)9d_c2A5a9&` zV1Nv5lm!8AU{F6qwTPI-*m6fUw59$3t-r~b~=)KA} zDtJ302-LX)@33Xu?0Dkp#wFGrt#Lc`m6u?FLN|q@_vdmaJ zx)84Vk*fcUL2If#WT&Q-C(TdNV1^fGv4vD|a7jj)37!xORAk@&i<@eCro3MzOgi&# zgQg^fJ;`(P4&|D0k+Ixb__iwtQ`2>trb^WBfizFe{z!wQ*mwq5?R&&I^7uGxp3-Y8K$Ahylfaf)U+c* z!)$sP68)Kyq!ol|55m$^{+)7s6rKkbP|u0VwFfL=BotE9);v4%Tbi!_sg3H~!jG%N z>S+IK`v1PSH3?S)p2(e|*=4a&+euw5Cj%!p6A1lQhhr8jsbSD zcI)u3X3W0lt)484%$aN5saaS>P12&Whor@qy-Dg!eXuTUzg*Mej#4U+BY*&yuSQo%A_*1JkN@hZCDk$&v9PjC|O+ayKn-W2nf zORGJ#tG*9R)}qqWWX9(E4-#^x%WMy@_PfX`+{9z;eQ=y9o?-+BJsje6TY92li)x+neY6zxe_#$NBU>G@sQ9THCR=I-L6FrEry1~ z%OVNErV?U7uRMxxJ`;DEb(+cfxNyi$h`3LToKAOHk)BF~Ot{nJ72*=hoGEA$8msXCin53Hk3L8{} zAt-C^D{6cSBL$pJS(b*u282xUVMX)=h(2^j`D6?^r%^+95S%3)%unzFYt23jVQ;WA;-*qNa}uK!}uX5^A`k9vf(Cggx5C3SU91 zQ=4Q=6d5=_fE{AVBEI;jr-ndra9{5RUcmW!ZlJeLwoI7Q7te8)`(c(-oeS?rRWNZ)D-Ou4iM?Vn&L4{&b^{9MQvbq@f)Sa%)6$Q*BM_A2r z3pPjt77)U52V@HjYvgB~Ko;6SU=6~_Ak5%y012S!flwc~DlTbJ=9|wPLgF-BIoJDc zuZb~^oNhxNp(3vpzs+g5$R;A_=g`7=npITvSCx1<2|@P(niE5TF`1N)`)u+A16>(n*D7up@CA6eN0g? zYzBort`N{5QA>c>lAec%xDIwWW z&kk1dfdvh3vtSwvv%m*O9Z+>x=SQ)HWa{^!F6_|&8&sS#$PySwZAowOt~s3UkfKvx zJ$pa-Hw8Ja{-T-u2t^mG<*=Ka*1Gh54|cE{L7Fn?0_|8aN4$fWjd0JQN=AprrxN!2!CF zV@wwLzT2~rY=H{k-jr1=LB*9g9~5x*K>~1I!2rFyp;wjtrTBvT>SgLASh-0T@@KT} zDb*-=#u^62cc0+njS%VVi9lX|ksp(pz`RBZGGv^azhO3^@_d}PvIvW*ULN3J+oF}` z)}0{)T90o7BY@UpAwsjLtbsgU3G>tJis{ zW?(IGU%JcD-Muc;dynNut|08p5bhw%Xqqa zt&3$v7FGXVWPt5oP2I)8FkF%oDf z-6;fC4)HXISY#Y_*hoDoLI?N1Tz0c3-uc2$IbK~kZOj^;Dr^#RC3)c$PhQ`J%sF^; zFrOfH)FEgNISd8K<&XR)QYH?q&E-+Lo`3Mq5H@v(nDZga5*!qiw-K+6&48jIR^d&@ zamwCa8=NQP&fGGZfLl4C+t33Sd@XxzHKFumxPUTW{YcJQas|Gs^+`D~I0Q4$H-P_{?*+Rh9V7_cx7RQL&kJ$Htlv$ZOhMEQ!s5 zGtdZ#Ofn$r=(tRDCiCIHs zEHqYauWh@v92EmtQ1dNvoly0{)UA6ds9IVKz`#pc(|zjEB8Qt zxhHhp?BoyQ>6$vRUf-H$6?R}&Y6y|k+3-Tg#N9hJr>8gE6?@OI0)8wt;HHjcAadwZ zE)*c*Rza>a@z=!fRGDxl1 z2>EIvd!M$V=JKD1J;C|}5KsTzW#ShBZi0RSz$8oUmJRVB@t^pyH~)7a=R_V}&8%H&kUzYMu@ zfCw6TcTV;EJ!xS3!po$hhk5U-WXoo%?EvM>AXe7{HJ3E8a_!)+$PY)Os!to$}0PB4>4XKOek*2g#nh=>Ar*&pjgQVGUx2yCRH}(b~v;JC^zc)y9&xb0398wL- zA4o9QSR`O-m;0yVnwz?vTU*3l4aVjyv^;mMe*aF!I8No2xapp}*?*GJEj15`;2Z?< zi6jG-2g14@Th zSOs@^rS=+HVmTQNbKG92=K>;fmmq`d1BIfaaI4IV5NFb&XiDPgYnVmCM|C{Vs=i^| zhu@)V)kokS2H+bU@oMh-RJ((Ff8VKU@b)F(o?{+S5a5Y_lxE4(Fhx;5zyy%j2MG5A z5fItNUU1Lc{x1~_(?iHAxj-)u5D&UQ$_|stg%aT;6u}xM z$!gUqxgl-cpY+JtD7>d^K$w)yfo`>9mPEs8vNi$Fg>-7)uk+tdmkfDk27y}pTTuLW z&6IJTBa9qE5oK3g=Xh~$Gy?cPIdz=CYlk&HN!V}%AO>oZCaW6R^I4I1GH#!O6@wlEM70{{R3Gekxs000kVV%7dxu&-Qe zD3K#j(|RC*OVA8sfkd&T(!_<-_txxC-ge!&9n@LO`|mpb05CEIMk4@#2nRq)#r~-+ zNJtVw-$*jUBwH*{%0I(dCr{}k*k0Tw>w$o~`_4xo3cK0u+;O)5w)^zTvh7B6nU3^Y z+sfVaf67rsDCkL_?@MZF=@(NAt*6r|g5Q#KJJ~?-0Du$#)ri1d0~r0@cklP!wR^j} z-JMSiXh|oGx2~F&!_iJ1w$cOwCSDx7k^MBd@TO{xgIBqkUvD z4AUx0v7E1$vmj{;tVmceVM0Hf#AF(0oz3f&D5lU;c2g#Y=$Zgk2h2rWCJ`1K*}CR{ zSEzy0Ye^y+xmS}3A`UY>o25B*Wh*D9p&Hy?tHwMWvai=#sunEpo zWT(A$dQ{>$bZLZN#hx^`RJTo;vQZV=iML%Dnz-G1*%8|5Sp_NT+Sked9z9oaNNXCP z3e*Hm75#7y(h|Dwdg$fsJ7xcX>(geF1seAm|5f;pwPwbzPn7#7kj2$y zVl$UR=g}zDYSM1n+1vz-nG*@hRq7flUs9L$d+e_tmzngM<<_XGQB|ENCECC_eHu$~ zU^^ISbQ0?5>0czNtBSmTt@Xs^Yp@II7Q%6VG3pF&TgzS`L{&D;4z z%F#3H9KOP~TTh+I?Rf|84uKf|lg?;Uhvoz^O6AGIfI4cT*=b#2f6JGj*BU;ZO9GRj zLR{Vq3sdMqF-jZ4!Tm~)&W+f&(%d}OU z!EXG3(-z8Bo(t799Asd&aHr#zH{VF_I+J%tv&m2ZaUQV+EZNpIXx?^Ox5tUyn8*E2 zdFxjHWJGNU9t-}-+^ozyrI;lQSNd3ngV8i!zRS+Giviy!#tFYY?WXwb$jf`t`*Abl zr1pZBLK{Q+)P7SFKQjYb(*d@ejc@{o)(n7_v%FS8xnt)1OGTRKoYq1u?oU&~gesrs z)|lQAwJpjv47d0OD}JX>U&eE0lRHQI9rqGm+oeozg{DY_FU}2iAHm}S_?f(;AMAQe z;&Tk|8+0WizOY-YKOBlFJ@374XHrI6(-DcuS$t&BI8~Ze)_ZeJdH_+wvXlqt;B)mc zlt1UPijMAFlKcS|JyF5<2|V7RbTWr-fFWrpN-j|uui%B!9&_Ia46MvwiknGR*U9V}N1+w%L* z=y{7BvR0mU>M#8>z-N7jeJdocL~>6R3Tz=o|x2$bdGe zb;h+6<1`nxq4l%5irGvv1q`MW;KcF7SJv#}E9RJt!2Ect)1KQdYYv;QHEFX&AMx1h z*Q8%1HTRB|w}-_8!Vd3ORVJki>h%|@+@JFG{op*TLby@Hol&+7`__B$TEP~!n|JWu zQ1JK7HAXIW(|D5H)~vn)?hZj-P02JDB(vu|pXz6#{R-_W4rjfxHtQxh`{Q+>_TL+1 z7Y#742F6#6D7rqw$(MWJ@y)+;Tz7hO`!H%EbzJDKQN3&fn4(@t;?w}^G>~YBCrh)9 zqSXNBiU=RN-|rDnd=*JNJ-LMb&C04B58pB{i;NfLYOA$w7V(F3{HhW=G9u2Ba~h3kK-RSPi&*CL*iA z(8sN}jNI3N280@>0~#G-pw9fY-lW%nJO^C#VuyT65QJ*<{@S}f3?C8G;9VQQ-Ws{7 z0Tl?SJPjl?oCbO}l#tYbkOsV9fVzj&+D*DYF^t9H$QSR`AqZJ-GH`$+Ap~1jhJ@gV zvqAXs0}>iuf*9bIhhH#2V8d}*;DX8i%J~Jp1V)@B@e_v!1PUrcGEj=)-{}5CLlAQY{0F-R(Gg3#6W)CSf-kq}Vqb5bMzMrFY~ci6}V1t@9lf$k#cYN947eqU&TPQKxf`R)k@-eGvm?^%7qs zqzWPALxD(T&m-9(>^;upHnNZXh9&YLr-8lfQ3{2z#Dn#B$Mhtrig-eUT zTkO=xj1}nsvr5fs;$z}gBZg`b)bKGIIwH2cC#n(Um;UG(YQC~A!!>3}7uL%#pE)FP zb-{l&mV{Gn<+kw2;;C_^oop+)08aTGfGUdFFu7lChZomf za02i%%gH4DGAn}u>;tE01Ue>K3R5Xfz$&nsl{W%KzG~w4CPoR*U`d^XekOB}E5OE& z*Boy^r;=ezroPGr1sCkr*FBHG%aOfejR3L+PYSbm0gok!=aiOc0SgG(u#F9?!Q{qJ zOp$FQ7^;DEdjKT@UDyM~?lFrkqw3`WLcml*UrdtQ%pG5ChpLA1Cvz zJ#;M|F)LQY&|}}$FH5O~dzb7vYFu-VykqXMl5LEamdkD220=Jijg-c?`L)|{NhyuR z>OodSwY3pmL&~J=j}N~`s9CN_UZ{XwtM|Yh6B)R!wi0;N;h8tK7RBXoRc0dh;tHC& zDibQ3-ff{ln)3$hK*lR)Asu%8sr8U$>YFi_zy+oio(-_ZE$`ddjp5J1?d&t>`h?j_ za@l#aMJoX|Ze!h}LIbW2Ol==_$o%*ca82V?DLJEF=yTt7$qEf?keJ!J5-Indz<6(| zRhVXGu$e6l<`N@t$^B}B$P4@b1Ie(gi?{CrO6(Y@Tfwm5BBp$&p6cB-@Jw&Xx~iGx z+#mi)BN(bRxcLK>MD4z!_q);@;%Ghg`J%Y;$jaSf{+et|+@OKUCm%@1ZDW}70c?VA*;A-gE`lk34(=N!jj20RSdXd-8~k~B#g9ZiV9WGXJ5oUqN$JcBX2 zy_!2q_2}16@jc$a?7PNb?%^{W$4>=8YIynu{nPH&Kx@PM>;^nbk1f9lpM@I=Y5>%Y zVQ8vbN=JV$`c7+~Wx*lBGzAcs<|3(no4a@*F#GtxnU&SC&EH30gOuqe z3D=eB4Iu@9pAP=3t#)NZ#NCySA?~qd7SjlSub_?cUh@6mm56HY4@<6q{XNNgyu(>D zbq$hv!1I6PZghh*9_-vmPO!7dV&i-u|GV-h#m|9k8hVzaNNv01Eg7;slJtpf_5Xx)Ah8_)P~bXgmTJ&9&@Dw|UdIj9G3!{F$qn zq!NG;IlsaOT{F9!(3(h3ME}L&y_UBitgVYH05<#cM4N+$wD>)xD+`K;j4(0NF2nhW zr-g8b%s6)y(QN)N%?HIOIMu@d`o%`ovyw9ZuDXn`_Yq8);HFnHBfUoFDF@+-rLAa# zSRY&&@g|%OS6)Hs4}KH|p)uGKhN#h7S6AU+ExaTZ*ve-#h^Z)?cWr-UNqWx3@dQti zA%yAVgv1B3HpopL(8SPB7-TkmIS?twuAKi~9HNt?5%H#Ok3c*T%+Q1&DR173{%Xb9 z%;iMEdNl7uw$WGFUP~$`!9^tbg+M4U@ti+#HqIS=u|OooXfv{Nq7L%eVnh7+B4o0_ zKuHLJ3``(aR9}t2l?}wkKyMg|a;E8AmLIVIah|K@TR53HN<1YSVa(cpcv(}-@6A1+L%~Z(3(c**+p)CR zPbxET(CVEDVIfR@B!n0pqzB%iR6tY|V|_9y)@oOei&&uC$1PlIiNFD+u%C3FNgq=2 zc~F4{h?HSI{!*~5?g*NV$3g_Ei%Ee(fikx9Ns=R14qm<$+DU{M2yZex7djk>IQiT4 zy$YU3S4+HC+_pkmn8Z=B7>EBPAgEMp948FiG(31W9kGa|&_tXnw(2HlLL2dO@lEn2%h9Mvj`R<8o&S z!K$}iDHw*CFj>GMHDTx_5?BbcLcZoHMIU_*{dpDq*1GU-6Rx0& z|8<5*V_>E9Pe0hu(@}tt6*MsMoKw6;&Rs@|jv6maMs>_dk#^QY9?{Q319)WftU9{f zu%RQiM$i|PK|SiXt62QD%rRcy)AFOO8};QXu9Dpo@4m*GJzNS==rc**&oAf{mfZ7rvz6(N_6JS*L>3_jDd9MDKnC-h6U z9Xf>$s_f}_$gts2ZlK)Yw!>@7kgl*lcbk77AIfRA(Jo8jyNMr#A z5|wT5EoMuIQO=u9B1D46+c$+U$&4qN@2D&!`prj%NoQQu5t{_33pVK_7IdrlX)PX{ z{GTgn<9ovIqVD}GkIdMh<=EopKbTnlIoB9ZEHi>PGbRM0Pl z0?8|S-V()ncJFeIZ+%K6FpL5uA#`jTo{ReG^h$q8_tGCB4d+7O-9M5qtN{^&Dd5b? zl`W_)r?EL#GI_WRc@NH&)ucO`Ee8}hNPy)K5CZ@J05bzNBme*pWi-|LpJcvEPKQ#F z7Nj<$q#Q>LS_TCYclfJgA#rT(oITqGx6|hR_Z|NL5E%fXkpQp&1JX8`&xK?NvItrJ z0E|X#fD1{it}2JQ&0Sbp+p|}Dk-J)?cI~wKSHSFna;n2V_lAxjbjFaiYM#}bJE00IC;BLD|~P`>ZJ@9plbTl&_y*>y!bB-gFm zT*^yOv?vk_Fc9VNk>nMb7J!;igc5)er1>(*3Tmqn#t8A03W6XZz90;Mv;_DTe?Z{--bkx5zy~3gUNUYYb&QYh zk(y-#vk4T8a9(R;bS#k4sY#AAbK@tSBXkVmmvb>RTA8JzFoDt0CXwxEcFh><@s7uhiBv_T-ws8-O;?xsyVk-E@$TASkh$d$j_Ng~_l4lw4EnV@Bq znyUnfDNS%MPL`JhlWb&mbhdw^lX$SyKV|#w(WV45db(lxmq{rdCdBk9qh}zgq{bIr zXQV8X+?gpUxE`)vB;%HSGI0sI?r2_>8Hw3k0AkzvbYoD|mLm8x9f4(-tZK?rHqPjG zOXF@BYE9NI&-1Ccf4)-7fNL@T;6kou2GX_--&l_?D0sQKev=Pmtt_C!BQZnfP@)NCG zs4ax7unOs!KRdsNUL{dK&pg5~;y-=|xV!a>YJhBd^B?9cyRpsbR!t7VfxwK7MR5W7!`(oAQY%9#PK| zJ3(a`YpD6^=)5lyyN$jsZIO7SGpN^8uv%;^z>-xYj_NYP%kjIp2zGQ3{1LQrhzFz~ z%abq&#?}y|n=*@FgbjjT_+s4=AGrs???T{2QO`hXp(Hm(gNU14)S;c!<7Xfm+m}zi zz?M~z&rV_q*-vA@ZF-lm_w6o+)M*jap=wE+S>?lr>2B`u!7pTYXpu6hky&Fm-sOwO zcmpFx;DmoLRE9nmyC{-+VBrhqdieNzM?HS+;X{Di^r9DRiH8x|i9ZzOFiX7XmTi#5 zREG(%5E+-@35?yWN|BP)J~_yIUnfxOoAOgBu$d^i$-8~MRO6xe1bs)&f+Rcs;+6Io z#q|ZkgDO{70T;q9-M_vCQ3ZO#$Pp11q%G2 z*mOZP0|Sw0NcRd)7z4HVGHw>om(5JfoUd}Y$2jQ$Cv4w$Nv|eFh{sks!4s!pl#QF&prp* z9N;yX<$h}QUe}JbvZJ?wCWgJ1{NtsAy^Fs#a42_HNbFxtI*#rrk)lE?t86XFF8Zs z`Wcct)oe#SJ)t|PySEL1CB}xLFwO|h($|#rit3f%1smHYcAUXAD_0Wph@ewwOFX61 z15Z~>Qq7b}$z#*4I2+X@8#`4mdMHmYu|W>X&VUAe^4&pjLyk9Cz-p=`i%zNJu%k=- zneEUjN+z3vZAD@O3{t74czx0!H%rt~Bc@ax%B45q6q`Q~?lY-qQ&amwTQOq%EIn3K z!!^&CNmO--t+?R|bq@mr`E3u}YI$!!1|KsirfXRP8ldA1_9JKzG_=pi-; z&>jvr0z8MbHL%`*3Pf;izScQ~{$4m*J{*OAF99YHS%l*a2CO$M0URsvU!v+@92vg6 zyBq@eaEEWW|v{`qS-Bi80zTp-_?jnu*WEjgBim_ooUlCV7yL&qper1 z^fpuKZFmyE`is*UPIs4Jtw1w(ezLgYsA}0YgITYe!Dp4F;tM}|?HS67XwamIYfnM$0140_k*_A)k=K!0VqnAzPF{6G-%#{Om2NG>JqE z=P|b}%a5-2wYJEkySr!I@5On`QI|-0I@q=)w+{A{6Tnp*zQGB@dXe2c=iqvQT*T`` z+!8}+Z$C5Ha7}4K5sg8THy~}8=f%zQ1>R0uYJ+k3Kw?*Wg~jO5^3PV#K@}rSdMd-M zO?JLLl4rdzS|MjGvRu(`ei&?`4pniSLz%O}aLw?}F@sOxgrQV|$4FZz*+kr1nb+A2 z*9pDch+VB;%#tOpx3|~cRpA!|+9wLrZcQ2ZVuE_M?og!n`Jhq}k^RQ;u3clg=Elz0 zSQfCqG8(xwP#=(A-w=DauWmPn5^y;zC2=H+SdT~}K1galeJ z4C&|YK*0KIqyCbc^8zH+04%TT^7r3=&DzhJ8WlS--lfB@l%`N@ADwEL%#>vK zQrL52>%oML$Se5vdvQbv&GglHDbC1h6*!C=4{|acZ|8HZ(qp$z!-Q2QGfw<{x|yiA z#(YpXc{?BYwEFHm0tvlf_F+Qww*THwOTqBIs1QsxgYw+!@~?>wi5ZhgNFzC9riku& zDqO9WAA!i(K|*67trzPvek=hK4r2%T(7Z&0FH=Sysx`5qTVpTmht~8DFHQAUwV+|Q zFaezXE$_Z$)B4+Z`?E99k^uAU!uoP0D@BTQpQNrX(l|7TPHzQff@jNAS5}<0cx_XJ zRgLTr5K9B#qM@3RT}E_wO0pu5i6woCLD1^^txjvQ;A1c$0^$1~M zc{se4gg&|=|J|>rF{lNBRS*~IB@dA@6xw<^pxqv{c77RQ2cYhtXM0~I#_g5?=#f?= zyySn;*>r@Jg`@$dH5Tw(X^C4Ask#qNLzYW6sbWQ&dW2#uq6)<%nVOsEO>^oTAHa%^ zqw*c$Y(uCQbFi$q`KQ)=It4|3_lLpe%+2vQ4te}4MIbw{Qhk4zQ547@u~k?XdqQb!$wI2iAi5O)dKJgy<#L+}*oXW#&XmLMC?`ldr2GAP&K@Lc~#_IQQHV z(_g~Cz`QA}O9@NGf5V*_zvG&%=vq_Ms#CF+ivkl01QsqC`7mLuIC}8(nZzLg4ZFQB z${*+dBGb&5`>7s*xr#~lZ!Ra7S|3h9atPaOZ`EG;yMAH;~dS` zW?)AEQL{X;L(6YhOzVdTDlCEEQnb_gvM(j%|Nmw;Dzcf5uhriRw64I)Gh-@I9LoG( zIrSQVnGg^I0000p14knO0DomPmD-;@zmgNF#7K)$n^IEzEgBRCEnIEjQ^rEJ-8Sdv z?%3UJCVxNi-vH480Gg3FC@=tuKI|tU$w0~o8TKiylb` z_yAG>03>1nML=M05AD5f-%f5Ed#`Na4oC}bscn=-QgF_T6kNmtBF+VJKggHyt_2c7 zAP7*9N)fN6lvf#`04Wy&1OWnxh$^@dXOjDJ%pF8_HI?iU;I#%dR^M*Btr2121h^a6f#Vu`%@uh-+LiDkPrgW-x#i15wA<%%8WQR~Z)|2J zJfw#{>GeE=20=lY&w*Y&)Qq}G3C#lJ)o5qur+(}jvz`6)A;cKSOJ4eXFi~-Jgv7{2 zx?#84UsH>U1h>qvHTPlv+1ujEMZfm$hzfgPj?Yh(JFujFWV{fXRwcL{v-7N*z5-RTv>BPp9vx=o&SHSRe1kL;!-* zrtmOUcUt?EnO85SrJiUr9Y!lj&uIx+tE)7|tu(UO#8~#E8A^DCpjFk-gwU~-Duw1b zJoVihRz`D5W9rG1Z>gtH`Q+lwGaMhoRrKm9%`LkPoFmnH<4HrxP@T03G>=@}lSd!A z@$E_34h?rwX{yqTng|wYEEZ&mxUw|593o6MV6!h}2h^F-k>mIx$QJr-G14GLQam>6 zMQ|E$E&IXza-Kfj^0`QW~Z z!dFMsOK&E5Nm4};Z#`G`Pf8eu@2RmhCEhz&)fQov67PI+riM7~PG%40%G0S1ZE6p+pB0&>7J`l5 zQ&&_xn)CK#_%Tf^RuMdE$Spx);JmGbm~AKpZ__r}+t3E*;PUEf-Lfsn8wGEkbln6z zYpisa6PdyiLm-w}Aj@xopMt{DDY1MB0@wl8HwUKn1k|+GBy7`BA+`Gtwh@k_?czU~EsR{+wQmV-D9bsUUy+^K%MBk*B!$#&yLYI`P0|onU z?S|BoClVV>Mut~Oe9~-r!G3@z=Sz*wiEz!ekMqIY-n+5n~B^~YgDpJ#8AUi)YLN{$P)?dt;lNBfSQgd z!r^8k$JJg~GJ!;Ca#+P!5P`IeUCifrG*oZ^n1f}!ll=cvv(mdEYiB+ZGp_ehdneWz z@yYQXANFP&31Yw9diHxl=kji{Ep+dZ?AhzBG09#V8M5uc^u!!jdBaAb?M*QUtTk)c zB2Ke$60pCM60o%r4tCs}9p{l_=?>jvep=tLbxwej>7z@kTF8rP9Yd<0_P>7lFXd}> zqw4k?0=@RG-9GB>3JApqa-@!c$qzcsA*trDrm#Z`Bw1LK29e2zJsH`&T!tt!^xfaG zynNMXbAg9+Tc(mxkOl9=aA4<&o^|g_tZKraQX`dsLFT(wJ+ENQbiUr< ziU6ZkGjLj1h)i(MBY`qM)8esfv&7e4J?O4w&-y`Ey}t-wsye*gRw*sGrVnYebxnA(-B9pV5bWCB)qmBugm+Y&YGYv|M>SG7CZRXOm>!0MHHcDxsZ0~-ER=Yl zX+oKeVVg`%fL#N^QZXzLtBHF)bbDyy{W*M;nH+t7dH62_$I)YHvF7`AnHoKjxMA3G`)<2!_DQY$ydMJAmsHzX~(ZLGtyDaQmgi>I=l@LQo()jug(=+9ydd8K4C3Mr z9@A{X-Ns?F7<+L2>jkO)pD7}%{;WyS3G04WFzcc23Qk?GeF@?RKr~ZP?IpS+2*HHl z7#0!Vu(DhI+#_tfCW(IZfz$?Xi^#wsngLLUorDoD4h`kbpEw`UH{ci?kXodc#;9W_ zEh9J0XRo7L#uQT<-R=Yrd<3$yGv&*{xT1yQ&)g!oDfX+J- zsyvo*0jIRHFmEBXs-V8HED7hz0j))SYC+h;8qo5wa8Ww&A}n^nlMo?CQV zXRjAzD+Sl$_JMu9t%7lgYx;5EAp^*N@UA6Lg!s@$zBgv_PI`#w;L8Gt&-l$57k89) z28d`%0KyJ8!fVgD;f^P-WYGUm02@a#YYS+(G0}2G*EU;$3g8e`)=L(i@zm?M6u^48 z3E~I=9O%Lk+prBCkZ^xBY4w)m?aq$a)7q~4Z_Sxa*zvl-4Af3xGJVN}XZ7pNAuCK$ zBoQLGw!j$2u2_NxyDb7oPXst+(69q%FrNV61(p?CXtcEM%M=Lmka_rCjk**xd!cx} zp<%M+sJHZZs77kV8)jPQjWHjG{W|}A5X3X4xl@yz_%OqFMlLu3umEQOzt?kg9N=t& z7+v%jUq#p?#9s#++-mDS+auZMmTur!)d1d@8B5538>hMXFhhl~h4yuY+4V#XkM6tz zT+n0S&R+9|a=+IXuEb`S!j6jD$z_evGyPJLJ!^z@G5S6-r#2;Bq5*9 zXgqtjcSoqQG&+!OyoDKuBKao4-{nF(sKmu98Bj#%v`K-bbQ_D6KsM9I;mH|i*WZi= zDSKXN(t%Lle#Oa)I6trS|94W(Dlm?^84Gi8M172|gQgnjD2kZC*#FTzYi{m2`fA~| zx9dlK*JwG0a&F!?_*-wxq$T_v zzoEX4%YHW3iV@N7Q9oe^(B<@lw;Zw!n#BhQmC7-FRq+G8e7ECn^eR=<6U(JC=);*c zU5F_NjX^}e+#x(&h)m;U4A4A z<1j4VP_ew*t@hqL)qK=$%yGrTabxgZKj*_rMVJ(j4u7OgPHqY#s}sZN&8wshMLX$& zc2bu2;;Fn%>c6d!g?x{h`0g`M^1?{d*+kDB#0~$DBYoSmhGY zM`8N|o8nB6!YZ?=$@xmMa*yc(;g!?2+KeLo@|2EYcnKbJn?rPVU(U*vMEcu85DE{c zvLT4ahqNj<;oxl?B~^jmN?+$JZpL=2c^=nWD@M&Zx&Ypn^oy{~xoi(gdD_d)+7}yb z0LqtP);63xREEZ`wjdEQl*BtkxL(8XV{_N_yz^bmlBWLA?%ESn>Fy-IyZu33ogSHZ z0PFbXmV+2w{i9^b7S%0wJJI)1J|Ay?5)gtCdTs4HTm>MezjnCnhkk~X%TPoNBrcpI zLhOMr-*O*2NdYX>K`>VjqGa8+{I&=h00mqZf%ZUk`FRJ;N-)?M{HLUf_O0B)$bge1 z6i3?EW_Pvh|M&V&hd?>H71PVtS#iw&o7WbPG3I_E+U8~!VRmd=^?vZqBj{UyNk*+6Q`&-yiFQ<}YIVs4k7u(!^UGJG>ln3hez5V50a2@R=U@EQNBs2) zE+5@jyno(GwZTb}&BCs*0IMwb5%hqsY^Ny&zL$d&cBXb=HJzGg1yIRViMa%id&7=v zddz#TF16kgNct zxA0TOLfg8woAvC8*H2sb-*o%{Kt=$HW&rL143J2m|Db`@0tyf&{DERXlB<}lM|QA9 z)^Xi>BeT{SZR>7c0a?;)cYSoN+ugg%+IKvjHDDxT@r{?Ca%+p=C%hmH7J%;rhwvg4 z0tSfU7f%ov-vB@W0BA%I&H)R3`|jJ_?%SHC=u}By;pz%v>F#Byvd}UJ0#jT?W&8*D z1jq|%B52YaP=cbU2qu8q*_zt~Pyrtb1b~l_KnHyf^4whRAjjBV?vx9bVSGG6+e1F|&&> z-T7s~Gi~0{{#2$-=in&4z`}W_+`$`tna>@<1J-je1lM!XtvoW_&)dTlKQT6*%k=xo zPtb(+M)~~b3(vi|;x_aY;~&&0r;on3Z96+B8)!Qk{*iNZO7SC4;(E--ENmXLUmD;p zRxu=B01{&$a7g1%&_o-sXYYhDEf_}Ji(^6^9Z@b_7?8EEt#uBv8BHVh8m~;N{^=Xw zsp%jlHjU*nlDV&Hg7$HT-?mXk=EmqII~$0878z_r2W5!f9;MyqhI?&(wZeRB7G__n z6i2BzA-&8J&WS>RdEeBioaV8e8zTQB5nu*Q9DL;GSae6@WBj(UqK8p>rq0hUIlgFA z>b=-ji1zFie?(`DJ5adg|FHG(^|S1&nz})w?-}K3+jml+t*19xVj6$AUS?GUVn@la z?Og972h0DmKYf1|0gim#^RoRt?8TVCInYbsgD9vCNGFyjRO8$enli4ZnsV8{Kl*O{ zb+(A0Mkb7wV!WN9>FrjZHnJjTy6y`9S)mage(sX+#3@{JePU;&gHSFvH#`Ty0?ouR zOzUGiHOEM%&wzM3loNLA)nsDrN7B(@X`whO>#P`Ol+Me0bF>|u`E7NqJav>auH2-t z!hiS=3$oEy#)vQO(#O%+cBHH>ZUk;?+i_=TZxtrKl3jPErKT19SlV~4F&c(2-R|M| z^;=V&Cd=&|SM>oKmfV3>M3%QMPABi`Sz*-?=Q`mhx;9*E6`CDi>T_^jABk)_S%7S`wuRgOor!A4$5Q2I$9Gcv!o*LY!+Z@JAkIXQ?| z;pK<)G=+7?DtOVz-!a=|?3R6(3#}>Mt{#rZx^g1f(xb(VL&S_tx@Git@ny~;YyO^9 z(jU3wPCB}S{wx5P1%0zzaI!ydag5Vuoy`gN-H6Nl>1ScP&4Yq*h(%_Zln)O6I-bwy zGi`6KoUZ|LA^mmNF4=iFe~CwfL{ygKnWNvNrJ-zj(%$Si!AguIc?SA}H*b7=^d`A! z{zTo0b4p(fCQNEV&A(Xox39G#;#MX%yNgEXvYPR>M>D#0P6^Dtqh?(H5N=jb2cXmb z_Q`XG&aI%_?8s0#wgqu4>;c?=5!A|FAT95J8Q+c8HT7*=Rex^HTGhfW)&CPqFLTT!nArRof&Sfp{E&fna&4&~@x14qg2fI&9 zz1Ar z)=T|6lQ7Az;-oEw{`WRth-1kubOj@xDT$dyC%Xqd;KDZ6l>CG#*@|wYSU}B(MxOeo z2nndLF#E^OiPo`Fg`~Kgqo*t-9*C)!D5dO#8duHHG^5%XtFGFz2E8cmJgltWrm05H zo#W{gb;5bhgLGx7qP7KJjVr-ks>1Q&*Hgt-dqa9dzl`k9#c$xO`^^ zAes4i#$Q8EnwnZ#f-e3ha>ruizcE}X-A{cSMgS1@i{K__fl}X}ae#p39~tHi_e*-c z^#dg2y?Bxs&ldqOJ&0%fEOOYuGXoIv^6v~y1;az!y)@BiXNmw&dce-4S)q162<%9% zg8OFYExY$U!GZJDUpV$!nte%M&%TnSv)@*G2OW7O`NPPm6-ciWuS03`)T(Exyd7D3tpDj{^`2dL)|2B@p9h6&`MXaGTdhfxObw*tA=WyKdzao~KyKFPpd9UN&)hWx`6$I&L<_XY` z$zaS8RorHe)Ip77TyPiWXZbKJKCi|%Py}2?$5;_1c5Rxj!k;79y*~6$-1aA51YqjQ zIE-W??B*4>y=*H#WBoCe+v5DcohZBZycyGT@d{<2vzOp9?raUciViUsJe1>5= zL{97v3><8-7gEt3m@jL1&G##4m|vqq%bUDAdEO<-F&tPfIe!3AWq)!pg)jS(>g<>1 z>z$}_cOLTM#q_$d$zMnQgAhu==J3?e^od_zM-alSnuXea9W?+h13{BSR!{j3Cs+o{6I&`9=UrMWmBI>$` z%590Tx*VcTTd1oShU)T(vV38x4y&!bARs5lR;P6RZEM7GRGVJwkG*5rq1<&XWx0$~ zO`1#U<0Rf7I06Bd=*Lla%6ok6A8y{s0K}*N^B3dv^l_9Y@QYN_AIZj3C0>uJkvQ>4 z|IwFKd}H@IWs@#qU;)rx$k7z=o)q;!abr2CXNjY!<1XciR3UJ4Y%IQVN4^I6ptSKpKvF?ArHl zs^KUESPRb|DSX&C${kWL5-2-C;Q~HySxh(~s^KUEC=HO|C_f?T00>7g!v%~uicdry zXp>(GgrcDjj!u9Az`;?=;VAmRp|EpNSaCx?`~5{~s6DEBE{}!)01yxZ0000p12!`N z0B=+vC}>(Vz^#$x_W%L_03!l-MPLBk58dzg z?%liFZEc-atwFYKl@zU81p?U(E&>w2Ade^@)I)$MB7`Ikz`hNq5*6WO6`-J07C;0M zzCR3v5Iv{}P(K1<$gQ_wm%BXXx=*{F$m;}-K`c9%vd^=vEm18`;NS}5bYqsFc@|EJ(cbbVV7@x(uO{WWa-LbLoQz}d zn(GX~W|~0<&TSs9QXG^^rSTI`wY<5qlbi2Lk@=(;93uIjZ{;Xsy zvEOhO*9U(kxn-+B%sGuUqd{sKr;+9qp)))?qqu%e$j>s>^1Y<>3@Zho3rXk*F;BGT z4RX6(YAXHx_Zre60&$FYtzPgWN_fZ z+NF+RXGEzM^NW4ob>~0+RSQ4;kSFx#sCHPBR4?e5VFjXYCW>-&hB6DpkUe(pOgx8w z^!2%BD~Vjn{ASHw>7R<8o952gC%YjxGv`+Kx<6~1nnz)anpu94N4cON%tS)I%cP>h z1ghL?NJL;`EoD0H0O4)Nxp}uo zYY%sQ{GOoyCU#;wO_^i#kYKy%SKUvTpxFmqWGAQg6YB`GEijp<`5!>-hY{7ZyI$#i zV6CZ**ywH5&B_VxIRwdl{gk#yNUnY_o0j#f5-7(>JDLO z^Q5<(+w@K;89%3QUuGpEHTe`Q0N~%0hAr?g2=V={L>My@0Q}DPZ^n8tUTRKbjyTeQGWa*zW|XSEIc;RrKD5L&b(nyj|s;Og> zsMmJk<=hCj>x>D*JxxHHeVLp?pK~C8Nl`#FI%uyh<>< zEm@O{xOp0+I-RwUQ3}uWmr~Nn7sC_BRdkAxk>kk~EX9_4;oQb`jzcYq0gHkwsv#wP z-uOV!&o(jB`_nllpfHrvNY}+pm#V2xAJ*n-KplxT&KvKK& zH3r@MiugIJp4W-J@H5HJ#LM1_;GJ8CwXtr8Y)|0<>SBrp{x*qh-DBT6DV78n$~7{v zuBqqhr`~GFP_o$dwTNQs_W}#lz=CQ>F?6X~-+&esVEQ2yLtN}PdAJjahVk0SlogKB zk04LuFZo4ue1U(@v-{;(`0fG!)Or2HLJ#O z4@G(FZ5TVFzqC4-+6-K-_LONB96RL;1j4k|40vcCyK=LQHm(^Y*fxqvR!UH;u17<` zn6Rs>C7@>JsqUZL)k{Fg7x{~kBNGp)HA6n8z3E91-j!IbiIRd#?cm%K;PZ1L9=rl> z=tlKRWut?$!1%nOl!Ja8h+6q-Q++4GK`|FP03?V8Ap3Bd5uQsLvFPKM9~;%kXv#EJ z)uwtf8nR)@Mo0uWYPEuAmIS5HHcCE6@OCty`OJ4F!)?tC{pD&LYbzWgJAO#?J#iCz z+A}WAucOevmP&M|!{2qC^lu{t^|i|PuH!^vru;H&o; zL4Y(Lcyr{+BMDcmu7g7wiFXU0?aMAN0BU< z+Q?|yG*s1PVn;1@IlnpW0)sHGOrrzpRHVT$Hy0$!Xm~&Lv&)>k?013uLkN>lS>P&f zKC@M7BgW|pveb|wt)nZb%u3WA-*4IE8Ww@%n8>!T^mw#mhTP#Y@w8()GRHBPh$4aO zoz4M|H|BoO?RnB&4{pYY5`w&K1A|5wt}?0?1SPP_=SwK=ZMAR&&Y%DT|6%3g!wh;DRr=0`@*APV z^>POSZs3?0hOdsPmDzs-`SQqcO|q4pKpG!$mbm<=FqI>aAl&gPTNAX|XUp-S=1#s# zOvmz&+jl!GN+JKBmfgq}1!>er&~y?JiW{ zap5V9tts{*;(~kvPa+&hk7qel7}72SSsWoe#-(^Hs5GX?OQLjxI>i!LGWbq{jkxb>%TJ-3)3hihG{ovKPQIesgr73k~f9v<3N@Ls)gX*SwJP&)JgtW^yFvJO0slygvaDyc*fb;w9o9Gt@24PE#eA`IG%KnIX;XA!AA1M zPXRS(_cyHhTmw5n&jdd}4CIV7fVjg2qaYrJX)Mwy$~8_VAUpy^K;3MVNzX#@BSEFy zL!f>;KZPG>qeGlnMr~x@ihESB288u{R}^p~`1usr&VZ%bw0rF-m!3sMASnbcF$7|F z&?OXzMPU*|(h9FJQY=c4wU`S8yhXw)PKd-3p4B-L#h`9CTMH_~8ge9C4Bpl1-6@8R zME#_2lqMDVGZtR#*mE-bW{fpo^U(oIYNbJ`3JC~n-V+Ghp+Q~+>W9`eAVtw!>40QZ zq)@KJE+SqdeO0NIhf2wl9e1FDghB^rC|yp)DMOe-0B}H$zn>cSr+e%t;KSyAm|9}p zt5CP%DIh>BRNPWNp)a7gXk)^0L$$%;A~h=Kl9E@1g$-bF6d8y{AE5wmu|y*KQL#fr zkmLe=4;2f?cZ4udT|nu9S6=eoB_lV|3yOqbK)dlSqz>^EBM>t}hpI*YNWv{MkzM10 z4O!Brme?vo>L29J$vg$c#Tyvk%kJpO1{pV_!;VpZ^R9qM5E_7}Teu(Kj{Tur zB6|Sp|LPlHc-x?$wXn57;c#CJl#k9h@e98v??X~gLtUx=AqOy}!LxWmj;0v+Y-gAD ze#8!tHrMEDNW)_=PIcjK24E!+6#`ojfYe?R#LaJunJVHY^ort2tiW{4M~eZ z?eH*0MxHUqm zo%?74B-iYceR#+(;V{Oj!zMym@{cvH{_sZ-LmKzgdUqAvy>S#9bImkHv8a59`BA^G z9E?2~S01%@)RLcrzS(co`To2zMGl?m;uG%^p9KTqoGJ=f4qnOrT;%*#NOSTS{5IA148?ci zP9slTcQTB%9aKj4irv@O8?Q`UTBGM*x_7^~dI=fd_TKS*C%5EsIyMCSG@)K&zT}Sr z>_jci;lAnr^3q(3Uqp`>V>WF>tk1YZHHA+@89@)(87K(=b%$qa`Ou?)j)CArj7unv zES`^Wt0iQcJtl92WQdogpTNwb3On^bKWnHrq0e<+;g~`r%>yJ#$AmsqTE9%J!*ggD zT;1cy!o}Ww%uiE5ZB+y0T%qn^()>z-p0q2AV@wr6l%|L z*@ycfm_P>X(J=i*%L$O=wBO{7)M9->Ro!xgY%=;#0_);WPRnJCsCY}SOu30WGgW|S z(QH=k9?p0LcneoEf~1wJKZD#sgY33t8u;Pz-zTg3rg%H1bB`VurCz4rF#0;}W>~@o zUUlg0!Yl|kGkjkt_$2)_B~u);=tSqg>uuuTKE(h@5D)_Z001*%KqCME4`qDS-Osx4^3a;z1$%hqLYU8#-LlH1wUJ65-vxqH2P)tcGy$5)qdvW|sG zKjzzp#2+VY%Yp(sVn`+x0|;S>fNx+R4+%zm03ZecG$IFJ2L|`bW%=ZGhlc$U2A7mvhw+<= zV;pYRxflH|W*+-@7kx6`MBC1D?QU!1o~@hh{%+ykTG8No566G2|Nq>yT~SEJ+m15g zueIK5Gh4+XcCL%e^=zGWd6lUPFxdO<`${O={A0AwR9`dvU9{b_@LOyqeOc=)tTwbr zrehgnLELs$TI}1}k*$=e6?3;weM=QOV7X26WYG_*VVDuXt({%;Vu1?Yp*l%^>lJR+V9EM zo2}M5mAjZ(!RGM-UV#MRp(pV{(iyss96x?$myIlx7WI4skn75Jb&SeTVOf3@1BJQHdBVmX7sA#l^Fswx= ziG;|CdKg%AMI2h8+Xdo5dVgO`w4FHussq@_GgD~r6zndx_pTr3>hwP2+}$`h6e3;_ z=LwZN1ba&(btku0$VKi`&S3A2+!%>;0>+({kIat>E(DU=BJ_Sg+#E}fglrFaZXSbi z2Mu4@(Jw#d@>-2yv4L@!q#o=v%tgjs(P>Vxk-@@*nx8-R-z$5Q8gyY+MK>*$Yq%Wo z)sXQ6%7(Tp5{?c5_SzU6k?ESSKW68x@T(<~iY;m`Y`*!hiNxH5aR>w}SxL(Ab@OZy zUoRysFwWV%JV)EgdKJpX-d^?#;pVI~2Iwc4hHSSeoU$oGa9)VHhTiaIs$&3r1V;oX zQM5;dG8CF}{Ji{gUsfa$rV&@@&b0noG^;84E|Oma(3|cw#39m_7XfhR<8%wefj^Bgo-$#a?}qE zF}jQHmufZAUiO74?{E8q9V6rN4R6AyAWucLXY*F;C^BK+c8^X^$tvP{FBxr@1-i;q zgp#PHrrtc>=IYsF-m%%%9#?^x=A-h**G>&@jyt<6WJ2&Rn#zxglZxDdTgBGoO2e#X zBnz6}YLMxxrultV8VSg@#2KWn6;$ufD_|jDca43|{vO(WWL9@z*Gk(hu*pI$Qa}DZ zpn`5Duj7XlqbZjcSvwpWK>x}So9KFw$jEcYITu4f088x#+3JX6E#7yoWRlh3V!L^A zcd^dQ&N!rI$prE^e`~0rR17)oTUhB!*A_z&1`QLq{%B3?d;%t(aV zm;3t9Y6cROdu_MA_(`pQ;_jL($hyj@IBKC$*YC}s@pFPqqqOw7|JgL9*4w;wJNb6W zO_TSTvF5Dzd3MAPKHd5AN9C}H#Qh5Y_CTE#?Ko*`6Z6jQTlA;05z zG7q``t}Xy^k`t(ffSa3ava45EB1sx0LdW|*Z8MlvVn}f~_Qm655eii-7|<7;1pMb*W;5GT1Vptax;6 zjp$BjUI`;49a0P`y|L;0XOwtmM&)(5HZ}Jd0@pK~HX@Ayay(cud)BUzzJYLoTPaH% z4U`t|+g>P+U0(*@^l2%UXgF}hodXIj%W-D~{fn5-AV&lzTg*A)nPD2nIVYggjNx)l z^YdS%`$b*tX4L9jFHfuoVFMT;fCRA=Mv;L580v)sOvnKkUU^y>$t<8=(TAmg^&i8G51WBCM^g#8=d5DN*5Ht*3FJ9Hq~J z?|qGbRB4f#+fYOysXNW1v0k{gF$j@g96TT%K#G5kr|ErJ!h&injfT%mL`r0fP>iT+7S_H>3-tV#%ZY6y|43ZQrIM$LLuz1Zw~IL(A3!xM{nN0=%YM)F^a!=w1Zr2|LNNtSQ%v{cNU7w_>4W2dmn&7 zqD?3|(E*79I-+(gIsl_1@B)BuN0g670FxT10=FNAn#@T(}qn zly+b{3sua2=e3>Y-58U`Zn|x8p4~CGC3J&OE4-|VBKkl%-c-onH$$9fu>1YlgI|2t zB`qjqwTVASzwfZqB;+q^eZluX0)4p*{ni%LTz&5S^68PP~3eK zREXc8O}sgzYY|A@RdVS4E)g3$K*&oST7J<421(0$B)uf5qJSidZILw6&CH^Ns-PkF zC$dRARW1Nst%xKdua(y18BQ57#Gpb>#9G1-($Hnu?@*cm#R+(mdk0mJ$Y{G?5&)XC zMtdLwr2^ii=K%^B(1h4;e*^~heDwT*Kt)gooe-au63;0zyX36IO-U!3B=l7hHc?EVvl!1N0X zN1y%uFNLbYZcJewBotZpnjO?p)3l{6Rmv7s($T8^p0I$iR+Nw$rol!L3NEWcrPO+= zt&0k22B1vBrRaD}TI!+dyyUV2X^lurkS;io<(Q#6q_&Dq;HbG%3GM0-(KsNi*VrH z)M5;`)WzXqvssxLaTY*Oi-%)4muzR!_M!i~X!^VqnL^{|V(Z)8T!(AY-tBXGoGIcF zQwAjzGgxU|24(jm-B#ewZh4g&pkU}w7$t*;hOxpdt}kOtEEI=v7vOV2_GC9g5L|~cP!h{7XHXslfIJUv3ZdF^~%XQgq zXt%UM{rfup03ag(MKb^f00u&`SRXJcil7CE6MsN3jM-!*I*A+Wv9;@7CSsm>E5@b(#FNJxTsauTjS#+8B0;%NWA#c6De925Z=QFJQOAf0|6qy z0KotNGy(`#Z~*_0d*8k9oAog-P`ZBtzEKhThrqZMSj6T2}+}B zAY5p{5!tt}X5+Wkb8cvM7r{~B5rm3h!5}#N(<5UPuP3m~XY0|J8d=#=0(E$#1llYO zN#zVM*PP#q*{Z?2RN6kp$1}*!o9wGYVslSn*IM9`S$FkNnb1X+CAnwofkSXTU|^T% zlQU)8wBPwoWb-ar#+?uv#~a^_AhynzZJ~-68>?|RVcml$TS=nn&YYn@XO#nz+&hj;xO z^dx`vVA$&3cAyRH*h^vBT(C@GZHP8ZOYx#`0mt5Wcm=qufGF(e#R{(P3`U!cO5MQ8f7M zoNkOYocTN-??y*MDh%fc!g$haeh6@jM%x14(YJTGsCBs8OXRS)_@WZOk~^7jO}~fNkhg?o3&IZ1(@|tXPwc>&(2rv)^-h*St=n>18w`T z9nQ)Hs&nA@BafY~FX2JEFFUFvy9Hx8B?5~fFO#=_v9>2f)SY7on;99eo7$dEUwp|y z8dxVlkLQO;19d3#z-`aIuhKmpbz5hXX!OBx@9Z(b(WTPWXZGtN@9;XQRU9d3)V{jp zY=XIp)p3?TqoT!ola%!%laqWn9c;!yC@fA-dRf!cGU5_P?5>)X9i0~w-tTA3M4Cm30_4dRNPFE=pQF?Duwmp0Tal&X_B^32Y!Kdv55R z;7p*#NP`^TT||C8@o2RKm)m=KyBrH-qTlvF*eN#{rjLLHPXSBR3QS%Bv7O%3aC>0t z2Ucmq*60_QMFWLI5adFSs@kmsvL|#iD}kM2ELW~}vn0wOYTt?V?Y5~8gg4I_sW=;; z2EZp8no-;V`!`1mlcxbn5C+o(tMV%l^kD9c%J9)p< zdmpmoyRJ(oyT-&9rNy~lYgrwMT6&%SV|*=#e>6C_gkx6X(MD&J=z4=jjg4RKv{+3Q zb-5=8b2j+p-m)mXP>zI6MTqL9cydIsJ+*Qtx^%ys&c@|aQHCVpB1&;W2_6la%RO>Q ze^RGu<3XDndxe(&+%SI-6;$6Sq2`F0*gPpq#*yHHwx?PuQv=H4OpM;%o~S#;HZ5u8 zj+YT#(X;*Oj#jD}$vyf-`$425_S~PSXwf>p2n#Ce5$xh5=MJ*H%?b@ZcTiD2JdUo` z6O^gJ2Qe->+j`SAr7K>8`|iy1#Hc0iSFKU^m8kFGSe0ZjZ)&oTA^Gdx{+sMCXZpFGTebVU)Bn8Y zt*qk>a^gpfwTbZ`%IL)|lgpT2VWag)74hj>^?8lhd(6-+AE`02{4QAzEtx)o0sxpLc|#B+XVpg$3Zm5*X^fqCnl=&AF}Lo*kWQbJOx%8E zAGb+|DY$44TGd*DVk;p|qp)8RHBRYUe1j|q<7Jp)1UQ_%MQKdSVASPq&T9DEZTPsn+<|4mQi0vI!0QT8B zN-8!0tQ&%RyA69|CMF(X7jW{tD}%KhUYR; z>=ArGm-$1|6QpLsWHwZXvo!RT;1cKQjt?vWwodnOaOrqX5%>i}skscd!H)0O|*;r*j2lLz+x; z00B(+nLGefdRRjha>*I4UEKNN!+8L{vIz51fQK0i(db%=Rs9`y^vqXY;F%5;ABs~X zt&FMLYJEv~dEQ<9kqxt7U#02B8R%E7!T4J}y7jjI9h85$Re=y$%4k=TB$lHj;iNO~ z*Z(ZYGNbb+^!!1cT5`tPJ}}Z@on>qrsGbl`JpnZo4a{*EmN5E|#)1=sO*%Hm9?c4$ zKnq_Bt2C3jD~xlY@dZyF1_@}LR&8u?i2r;+P)a`2lLqTMrP@9fo`KAu0suUc<>lur z|23m*ysrYe=KYsYo(x>0C~3)v(8Q)L7fzWBbb>S)?>fV1tzCnPehoat;WF1}DZJLX zI`SCc@!1NSmGHCXxF|ek>pnHpejQ>qR+g8-X3T8^?06S$jBL}rcpNg_XTjysr*$~_ za9;}Zily;q!aC-t#F(;SET8qn=wZk?pM(EI1C|K<&!|&M6UZvU`#5S-Pc#ib$hA?& zrJmRZCCI+S=q*pgVw866jc8ups1!21oR}uJHfeX`H53=CgG(EM&7Ck<+X--MXWSDZ z!kY(`q_WXRtY{*GlpugK?&mD14 zZ22`;jUUCkYKI!bK=I)JO^y+QJ3UBDT8hTzk8?&!!w6es-sAM0JuU|9s?f&5O5(WY z$w;(`(&KvfuXW>em1p0_@q%*5@doJR~19$|3}S)zsk>|1@~UILRxZ^ z((U?IBwZe&(=Xm({1rQKX65kXu9!keifyWpP5#$Ype)teR+U<5*Fc&sks*S=|5#e! zr#bh|WXme#Pt6@L8LUcf?JaU)ZrDwRL1XL;Ws;uFUV0nTsrL=EE5r0oLLeme=$uM; zxnyt}Xa$B&WsZ_GjSx+>fy5tF00209pcr7?OrgS;#54d3%(XcN!R3wc!Y|l7XX}EU z77{)tFc5@aSDL}iQW&yW9UGCu)25 zikK#Hpx@0pamCuw9bqNj)CpJ;j0#5A%NZ|d6b!B{rc!k6Ol}Uk1g4nz}yT;8lyC!8(`op;Ux2ni(cE-Ql3xoT_kfUNFpf(|a zo7c9~D-OWeMKWqRyNmrh*y1{>{wUL3!F>u|W-l^u+P|K2z$23BE)l4C@r2({XI7z3v0-Z#{)PHs`;SDzJL>BYfuRn-6{4 z6u7j|dn*q=6OI5&wyh!IT${n(ZnYL#<=U8CfM>l%^vd&!=Q(6-|0n$a z0O0`uq8TtFC;&wU{VM{Iz{e0p_zH+h1O`?@9k3C%nandGLT%b^yU}Hf#NKWe8%vhE zdr2&=+|IYPE#t<496-@BWV|2Am4Wd-A{vm6(h(gZ7T|<}@ZrQ4h<5`@VKxw!g0KkVTL}yDe2`c5asG8-*ppA}II>@yQ?%tx%FBKmY(Ah_K-k8W7QG zq-xL{n2$$5FVaAq9R2pr?AjZ*g#0fJL?9K<4G#?TyjXTAw}o{F;^N3s3}Vh8kLTO9`O{xv%X$@Nj2N>Owd|tVN^m2G^3;6 z=|XcBkqS$0eWR#?CbI+|;vx4I9qXfryj_wMYmoR>UX{1f1s$%rsV=7JhsvlAE)bx@eYLd+VP)=;9&CucEe%MM@?bGH)(S-0uy$;n{lh1LBKo^NqLDW?9>QCaE` z$&*}0@<>s!8pBYZaWcak>Frs^^maS;lZ|N0nH zjo!6RNC7LUy}Awi>zDNiS8Jx8s`EL_Fry=<*P|_0 zuCm)=HYkN#XK7|%ta#w275l{bvUx2ph0L7-B|z+BeU<^Dgnhdce%y1py74jT3U;~5 zU{C00(Jf}M5c0SbsF0VT?z#3V2BakWkkUv=gcUPxIBqxW$ucpMU%XE!aFh~PM|X@M zv8u25l#(Zldtg00H^?97vpfzcbv`{xog*rv=Mjs}4ie3S^hJO~*;k#-t>ijJK^G#` zRF(-fp&S0>6XY#*d`tlfh(p(N)Xr^R0tIa342%o1U1&7o1aX&iY`5;Jr7cUPMKrwx&$f=1ftLY zr~{F*0LZ;TPyGOiD-aHbGM+F1KY9XbMgUCj0FeMF*pnbh1_tHzNm9Tj!U%&f+4TXi z@c)f=(Y#e4%I-wmZsMSFb_XH{@BgF z*i396%m8b2?gNyQ*ae?&XDlk%9t5GiaGs^nXI-v(jhIQU`~D%pXQIWADC%@GRsbOD z)ePT;YiU$-%@9;@6$sHy5SxY3JSsmQ5{lhKF>CQqBd~vunp7DN0IjSlF@yk{hq<{P z0@Q~v?M|X|&kxkFy%VVBbA5n`oje?d=XwnXYPa_o)1YUsSf^(AD$oi9guUQqY&5<- z@Ps+$5u2Jf$QdI5x4C1H_LKaa4dZ)1kmS4^tXrh5hz^qFPKOqNt zA{O^cGS5o&nGw5thaM;fJJ~G*iK*tK?u&r zd+eNEzPM~qvvPk&rt4Ri$Nj5zYVYyiI4-hB?o3af2I-EVU(bCk+w`wQd2XZ0q`i$B zb6>dR`RnRJ(aT+FwTN>EYE+se=AGm>a#|BfmxZ{?GXDonW73w7o`l}q81N%?v@`mj zW@RtmRp{!-eYKjO!A&oT&zfNJ>wfNS{4xZZ_NkA9bj7ddvV%gr4PNkGttrphHit() zsxM2x$k9oU<;BtkD)GhLnySUTr*)}=CvI$xiOtv(F%I!XPeTeooclC!0=@LSv~WsdS~S{4^5&@yj=KJ6&7OK zSSvXwY2U)x7=dxzMXBrA`rRQ+;@Bs6K^ZA~dz*@X&b%}XF0sF7*HKM56e-bC8O+xW z%{>Wr2<^fKzy;?ne(5(usQZQa_#YBmHNz_;Y+Vec%&K?zRLB#9+)_QvP^aizgn(1G_JF zn@FyY!JxWgdUy8^G#`19%SZs{krOPc`wxdbc=AQ1R!2pcLFT}GaJ*At?ZcosKZ|z- zq0X&&_KN~bVw012p+Yaj{^NA=TEC|pt+=AVe87Aat6Qy)>tXkMcag28VWH!pASi!< z3WVg_9qNwm@!tzuV9nwdRhIJ5sQl7aV9^LZYl_0ij>|7s^~$pC+^_5^AcsJ}$jc*; z>BGwKi*nu5>^g%kYj(8&C-3i&&SYhqG+wDFCCQ10+-%~%>2lzS_WINBTBf+lq2VO> z(8O7967V9B)}@`NVha=7 zF(BtR9<3}kYgyChpcpA0y0Y@sY(f53^UYFSP7lk)K!iF!*O7C?32g^{!}>c<8UpKv z3ws|wis56+6KTqqF%j%2MKM1U9M(Up`$EMtIAx5*?J+#gD|Q?hUynk;7Fj2GVb^09 zAhrRx*cyYW!8>8^`XRJ4f)!IGXOJ~mp#-$Oa3A#UN|QN*2EfTO8AuJv?dn77K{_H- zyH$1uOoJ**gUluTQP7T6&tk2w)a?!+eFvyzK38u*53vxmf(t~bJ*)?arU6eVz1Nfc zVusKFT>(~T1cs@L@4xj!&VEs!q%Hpl)ZgXUN%kALdP5JO z?JG^zZ)kUH)<2a(7(+gELY7CC>Z>%f8>Ssdn1wz6A)A0rP7aWL0jF{Bfoz62=s2u# zI)PV@XO9#3K<|+K5GZR0WQ7z8JbdClS*GJyFhW;}RxmyS5fgKG!1z8wa0sJHgqwDUSQ^I{pA4BLGD+0CxZe zNW`sw=0F8}08zrPP-zGa%%r?Pvf8rs>kfBB(pc2a@3t9f)^0o561KK?-fUa#8*krQ zK@_sa7Y{F4>*DyM9s#Ksl)w>a1Rvo5KUg8Y0tI1w001EXA`&ow2Qa(4@80`%ce|~+ zWo|M_1kBr=+jeVet=c3Il!2H5er5ndBY;3uKqBA|03xD*!WQfRR;W&Zn#c?qt2|K5&%4U4MXBZ=;uf^#$qIZul9D|L#-;J60 zgPcCOzVg)JiwTQXS9~5PH;lJWy5T)ZPXxr2PItreu;#8s7^0tBy z74_xrs}2kpu}_>2dIO~%z_~(S^+@JSCM`I8*=Z4xE{r+(*>#i?Lw>KB%v~p}l@W^a zb5Tl)4`>(S?j}MjOWqjQTuz0;Q4YKBO^nZ%ZjUQ zZufEKv=T8{;|srm_8K}uHkIo^T95fzW==91`Xo(7nn zCQNhnP~hc^OzEY51k~IdHE^d}$t;nFy*0?!@x9jZ->0+Wue0EBG+IMVD~nnY8Em## z60e!+cEIIb<$a-?5BgrbU}Rp?(Ywpt=JHvL*7zJvpC`s%+4V@+mR4M>+F4xYaC_OP zB*vL0tRn?&y;iP*II{dT*(Y`3W8AS}rNvH5VE<#=I3}r~5^=Z@voE;UwrS(+pl>UW z+S+sdRvRPj$XV1N_3AHwQ(41T3tl!{VsTs3`a$%pW5-}Pr>wX_YD{=yz#+$%@IY{d zX?_T5;KaEr(#Sa4`k>vo1S!Y+4$m*j<|~u?YvjeMJ>rXl2eK1=CTnD1Yb1eVe|>bR zHg9#jZJXBOLi2C%GR?B4XR{{Y!jd*-#VJ}zzh-q|s1C5FT*8eyPShJm+^ovA7cZH1 zl^9N{LeB}kn?{Qt@9ZDbI_|@YVLm!QTUma_ z&%;~L8ByC=DR?p`$Eo$(;RL+}$cn%NUj|f7On}@T#5W2c0EO9?K)ekEt0B+tOCS32 z=<(wjDgdJ9=?uCB*+)YP>c2kHYM5REfWw9Fo?`0Zqs~wIP)WN7q|fkt-UcI;j^tM7 z0nP=Wz5v6@4-{D@yyz1%cvuI3)scX+@UUv33d-6DVkg=TT94=P;=SS-AqtZ!40ne2 z)t=`wtRB1+i8Uc?X;J|q0dQGSgsQLuS^C_b&({b@Kp}G}5IVyV&doqbQcVOSFa9}s>v~^K<0S6^WK2i`x8g?X$ zrx&8#^{BQQSUf4}2Jey5D5~&=ssgOBLlk<-tZ zQ;2^LqZ}96*~Aqc1P;IN>4)4V8$e7QiPJD7!%f3w;;Ylxvr@a$hAcgTAtp^3lUD9f z!Qlw6fO+OGcrI)8klw>PS2c4Bm69k(vP9=_LMMWiwMVG(5vuclFZ-4ZbI^!;%)!z^ zQU5y$lINkSgQQM^k$Ii6NGo--uJ3$Tg`o#;F|vca19d%9TFoOzO8hN+-4Z$i=s8f7 z?yd=P2k^cl|MLMKFPM0uisdoV7*l|}9Hy$OD6Sk9A9QAaWu>|^H9@KhOhsr}0BJwC z*}S}deCoB(sKWes8?I72$SsclTCcarT;pu!Ej28R8#9BQ>2I>BlH^5yWCO`_d@Zn5 z@?n6L-S)&G_KkumLc`Cpwc*cIgH?Uz5iXGEmK&eXzW(rLRdI%8=J?fn>^g+LS*}Sw zN1~ayeO`%pr?!0+uQ3VJsPt)F9~ssGmmzav==XeTNvHf83P$rpY43qM5dCqVYsB_1 zrq>tqd_NhS=XoE^F&`XHTOSvcfzJm?IRr>3q(uNB>e#hx?Sno95gpz&;(@(Yx%cEM zU>s7!R7=S#Xq0!7SDZO{PW$*Y*Fv>^k*55E8d=rKgt>0nC^}}&(y_K;>*@?k2Hmr2 z>5-Rj=x*m9*>cbZx+!Cw0XH2?mQig+xx-;S1_yxI$6A?kz+D>;nrlprA+GK1#y_(U z7B-}Lme*Eq6h=4EsDM%ldVUHg*&T%Uv#6_*Qw!>DbD{;{WEERfNOX7^uGjd6Z-1!A zHk*z%wr}b}1>ACH_h}m^KXj!}8I!e<^Txl~6O7o&Vx8Y6-3{2f;NPKR$5`+-bMt(c z)a{wYAN0oV@#_`goOU~D8|BW;=hL|UPA*wEd0*N9BSkV#13kN_*93=rM2{Kl%`{T9 zsV7fn8%HjO#n9t`KGe+p08p6*QGQZAr#ld}()2o9>po>t1yH@0v0 zvBXefB7<5?KELVCxB0tjwH^!<3FF~!Hw3(IfajoP;~VQJu6{Fef9b4W$Pt$Vw~XlZ zWrxlkDpZk_4skLr(G<#2Q~_BZ@H(Gh`muGWTmJY)N6ng_wYz0yy^SfYe2?`XJqT_zlt_Yj4~iC)bUmml!nu0v zy7n>jU*g!x{(i2`!HdMVM4MkD_PIZvVdu3o6nT|vgIe`V)ajI1-fpmzqPknK3s;8( zb6Ov#djT} znS51zVo-zP)3#9;V#`n!i<;(6)WAV{SKeSoH3yL{PiiVBARw6>InoAGj`A|#z`m^2 z^%21eHBzJ84R}=iPVfD%0t${3)1_pjzrhDf@;}tck}UUR+JFbmttmgz7a>&tQjQ@% zCQJh+Pr>SH&ql>+fE@}L39*f0W5Wr#SVOR)4yF~UinXO5TG~%zd=4u^wuA-UgiV_9 z0`OV=1L>hQ=wt=}L_lJc;DO+trOmlLnwk6Q08mZIP)w~X+6w~3I+#|Zf#N=)l_7D0 zuwnX+)!RIhYFhrh;*B&>CjOJLA6COK>MGiMTm6_Cp4p|UCX@9w7%Z?=s$;Bc8fm=h zKVA8`_V|E|7g@KK9bnc~AlrrjVs>yxVd=8C1ikEMgDF3%XH+!Qs3-q0dr$fRqNqKi z1|X~g9YPt;z<-&--A@JWL;hh5!$5GWZHN&YAE*;@VPeEU?uS5O2gSnNi-Asi5UZ3I zrZMOi#xeRAc?`ORfeh`1M}|eF4S$)N71iDX_pS18m4Pn+D2!kkg7u=zp#`Lf$`fD) z&H$|Te8i=exKjlyVaeYNd8{#NxnR@b)R(TR4U2!n{ z5WktE7Dq2nQV{rzgIo#qp?Ri26@Vd3hUog|c?xV3hy`t78`*gi%&1%D$Ex~Do}uK5D)_Z002WYM;!2!{U z_{EcNbC$kon&urzQT$CJA1hsR;z$sSXd&$cB&nb->moMrNvEYQb_orLLW@%SAT9s^GXh6725{~G{qEk~ z_U>=*y=}dB+I6ZG%>rw^+ogI&mys-6#$rSi6eUPN@T0Ye2KZXR5ki0kCJ5oPAR_P! z*^;y=2$CUygdbB-{0a{OQNnyu|3o=VG;*(mN?tn36_Sb$ikQh*oEeI|o`i>PjqR*R z%X*;jR-0upM$APNIyJ`lbs*Df8LkUSm}xEPpc+ycCa>tp!hCd16*c`TOb?i{$_d3% zun?$iV>(er7A(1{7C@zGWR3JkXeYxh3^I~}Rab&bm1vV{(~>6v%a$Z%BqgP!3o;97 zFJ033(PcA(+(JnW=1$TzGSWXa6@8T@;}>e8j+JsWPQhLU=*+d(a=WnD7Mx{{aI?$? zqRNI;0!y*0jQ13Y=Za~B8H&MTEXp*d`FxjZMyLN~c3GtDe8X3)nIdK;Y>uUsd%QAs z9et++@rWf+tY(UsiS*o?qpa~Am9Dr^d42MR%#Sp0LU3G~INN2Ke!vfNpm=Q-?saip z9o3dSQJwU~s=A-4{ol{(!rbR&;BP-kqc%|NcqK=jI*AGjsVURcj9_|@#RHp_($5|> z%Au5^5@JTr_iBIAN`@zm@!O~pnt2_0ontf1v{ck6&`(Xgj=Oxkj`iYDY!XP*2H8bH;Zh&%JU=d>oqMxm?rWDl%$uR3l};dy zWU{$3o?Jp&UQb55OsI9D$}F;H)97MwdZ(cNE` z$i%&r-Zt%P>~loJl9?pGak~B9*|?-X?|ddRvky&5#l8HI%fq5Ma#4Eu5Agf%BbBG` ztJmM^FSYk|ep`8YY8EGbc-Sy=ndXnzt6QAH4gcVw2x?QGq2P1QsdFukL&Qz@l<}8+T(nSckQ6inF!J14S z71tboDcR~Eh+CJTGQTu7EoTW@FUQ7@U=K&<0h>KMW=vG9H}7E9<28WgF{58aFae4U z*(N2KT0Vc1&)2xTvfo#dmL(-gPb z%nahc_qJ6dGf>j`HJ}Knklko0!ODcYp5Ln9$SEHz&VsCSZZBy%<4d60JX1S*8mhE* zJ(0xq6Z{(u$r+SGs&=5Ft`9j`5-~ztc(75;0HoA z&QE0fWTp6#@@Pp}o(ywNoGVSsd3Z$0jB>6_aayh%Do-ZN{gP(vu_)l<9uU+q&(M1C zyrwyS_4oeAjoyEv#f_L>STcAyPf%gh9Qzmka zqNLCpwG)}<_JwBz(bxLQm8_gUi;RTa5fhoGVi;e~Mr!ZBXlvwOcNk3K1AS1@35SUg z+mL1#KM?-}m-H?CX*q9f{P|wt;>5T5{7sbQFc+GvkVjEJU?J%LtJR8?b&yHedZq^E zz^O%t*rz|8&ni9KLK~=K=%|-=-gjv;`DS1|>a*|(CY{F>)uA2d>=7FNi z#@0NuSD54}jBAH_y^)Y6z9j%xx`sx7@p6KBPL#hO|$P$5PbQV-4GTNHy6gJ$(TH@zak#932xD5}lTO{hIT zhez*PG8e0J*@`7QKEkxt+ln+h)ChlOlbu|h?@oo~(ehF`vwAv9{Fi8_#`2k(8M0=t z(&wHgZOmkVXTSlfbc|_|$;4(-&XFb2P@`^-jRkj8cG=Nh*~LILB;&kALB%h?4#FgGZz?WCoBRERk(Wv;8-{eyT+CVD zWnlJ)Clr8M!pVC{X`qM8;VC}+(VNA(w3}?MZ|VU*ud><2;H3s`qfFGH^*cbG&v_BHA2io(X*r3|3;CZJBTJRNUa zapt+U&Z2N=R<3y?Q#(I-$yd3jTz$k|Or6LJxlEr2XuCoYNM`O~A=eK+2R<%B^_!N+ zzN9k*KWV;l9mnUy=eI;+!Pe?M?k>N*zko$Tf!!^ExNw81n7=7KDEhi?yQ-3@)XN%2 zbav^DU`xHC@HEV**_x3B*^2(bc7U!5?7s%&9+&cREI}ULTOonA@;a7(hiXhNZL{Ji zZ53o*PA(z@E{C=j*pUbd;IBnXfhyT`B>K3nxMl@b-Cy*}Rv^~t`5b#8%e?580*BL~njrE57EjZ^49RFh z*yTVp-T`GrGb_fnXG}8gfd&Xo{^ep<^#xF4$>$6*Kg6@lkKWnKVcvK%xi$i~vmFIp z)=DeoVUo~7Pp)2pI*;pa3icNsc=gDh+->|%eEpa!PEoUcymbZ%jKwr)a`v?_!*>HS z<{g+Pd?o}2Oj!Scdj(kyn^SSPdgM$#0~WlScfi)ee_<$)`8K;L0A20I?-RbGJ9fKo zz?ez@>Y9$J)nVa`lgJ+)L*VsuqpRds-6d`FW9#hiQDJ$lse3nT8V|Lvww!>$=ts%uL+~aqSIpu4-_No3M!-`GX@jrEvIx1O*+U5Ho-&iW@t#4UGOSCHP zsu2{*dH0NgzKu~Ipqb0bwTt;Z)b2`s=F}%r8s!*Y_pkqx>$Xn3xQdPJy%Vc-@+P0r z`tARvwnPSQB=G$Y2p%U`5C8|IHV${op>(h04^s68E1ta|acaV{nSH+_^) z<#MO%4@fK1Nf<_F4|4D0ZI5pJ#?#U55D+6YBrKh?hNMHCW24N4S3IZ`b}KzNXM&3JByp_w*k%=F$ib9GT;Q8Vfp^3W#Dzb_RSU0WfdPvjGeTlBHBzU1m zSfFA(5a|P19Y8D&{E1E=z=nL-aLBwFFW&8e=#&FRKg9G}w|q_12C-Tel@tdD!|^(} zm?*j)QMAub8CNHj-?Yi*^ABxaVEEpNWTJJPmkIP*$iM1Lh*8wzT#WX*jq8n5XT&#+ zidrfrW`7ymicVUq)f<(x5eRW%AX5b8#|SGSBG||E`7>a}hDzofzs*}_d?HjN?A6zL zwc>F$(8($Ash9y9pThN8Od_9Z>gCHk+;oq7(L;X9vAbjYT0h{eTa&cA`LsksGxQZH z3f|ibF`=DyE3n!f-g;6V=t z#0Y=a#l1=*){w%DL$5wSLtRr?4B%)r5KnW!Hu47a0Ct#W7Xt!v=ijv>iv_MFn(VNl$5w=#*(JxHU>+ zm$8_kPEF5bHZTEd4BW7_Z2F_dLN(elW04fF!l8s{u`|@~%&3M!{Z-pcY=Qrwvz#bM zOn}c{&%|1!c9zEG*x--X*2XsIIz6$b8vd-iBp+QJ71`L-+#c%V)to>?cPy)AovP;` z*9mNt!o-@fGR9j2hQN~7bEjm;SCgQDl#mYY$YD}OUI|5O1Su`xD+&k@)Mq2?w`Af} zgQ^f%#&X%VdHi%u0Zi2yax}u+>OoHZrNpn+Ce-BSzPIiK4p(gc#t@Mst^JkPuNpq$Y>bUL4`@ZUQN8fb^(Ilz^E5TYR{;DR~F^JY+`0CF-P zUL}VoAuB0^lYsgJ@A_fU4v|<__YdJ9u<|lQTOdCF@5#x4AsgD7f%NVeFtkaJ4htTL6aZ#Y1}}&@vsfN+JDLm7iJsAO>kvLEEC5PJ~o-l zg~bCub;E07$ImehsR#DV5>4Br-*?$J3f*KVoin&3m0h<=ATGr#$EAxhHn`T+-xlv}?IE@uIZB z!r_0y^MDIoK(>Gdp*zs&_^<$PL9h*C%nNdAiRcy)S%yeUYRE$!h}fhPVFm=o>HSJv z!25#?y^eEuP6p>@*!VCUkNm)##uB7|`xb2cM4|7n*-tb}d+{Q(oZ5 znaBNgv^Wmj9zG!Ci*W4FJq&-3a`8Y7@XWAfVS7CCLq(dbp+Ovc@yd>{+8YqIwjIU~ zO#Xvw=>mv4jGBRD>l8rv81!r^Gj5R(rBKv%PGm1=q+Dl0lO<6aLKo`=EcXfV`3SU) z2M^^7l`(@(Q8qp+%jwYDP|X=I4eRBa zxbN3F-F=SU{iagbv!mASM|<&>)ZqnJYn=33?LSh5xnWtJ?>|<{Hi+Jj1@5iU|01}H z;t0yz|Dwly1LYS)x$*|08?>_qL>}y1UJwui0000p13)qW0B>b9mD-^w159Z#{d9E2CirT;0(YYQbOv_9FT+!ffGIe zELPUF4s;01w%fY8BOSGA*<~+ovscyDc6ZmyTDjhPua>nPZ*Q6a7OL^Z7ZzsE>KEF20&(;rIJc;sR)RIJOT(oPnG^&b)}Vk zwE|nboLg{RgMGiHrTSlXA=~QGm|QC=Ic2H%W4k4?C<-hr)rRqJ0g~ckVn4jOB7*y0 zTIm5Dnp9$9c&G5)y$nI6zH@!=2TFe;sa*HL$oPi2^UheQ**>z&`WDTt;Fet%Y&;LC zG~&0v4RMvOHeerz;EM7TcR@;M^w%IA@bkHCwCrd>W{@DW;5o5Je)<9pZGDk z{iG#`HD~T(5{y+q~QV%x+ywdXlZHC)FiNbJ;9!FFA$_(j)PXOAQw` zg5i=Dm_qtNAbGOdbJ0p;Y{G24uRH3nb7E;_|l|o>k5wD{={Iynh06j5d*Ek4u`LEQ-5GWXlm+ zanueuw-fy0v<;}~(uwTuJH6UQ$3Ae(y&=AlR1J*}uN3i3+R-Pcr0CK5>DKo^M)0X2 z7O^qa>}7b*jqCxyB4^UT<(-#9xxm2|M#-(SP9C75^e)UQB}3h7J?9+Ux2N&KqxJ63#1W9?0@8p|Z9Wc=MW?&joW4=LG47=)qlCgRvHq&eZ}_;? z7uTII=U8X8+r((i|(Zuxn6Uz z#cbJJ7ri=VG^k_QT%w+~h2vP|EH)DfmGM-$x)h;w%c*FwiC|C5Jgf;ezZ(mrH1uOx z>|<)}$0H3;Xub+Nd&~y9ZJW3^x9xjoO?I8Dp_Leq**odWE@|i~DTTZ>-zKxn)zE4x zc8S|O=0tW_-_GNs=g-u%BUeO|&v9soLtbtV_`V&8?Ju;-Btkr@IWyNv)!Ya?GVIS{ zRQ7qq@(WTG!N9KV{V_dZAN55B_r4!@D1M8;mW`5t5e>>6y!Pd!#eG#Au- z&LLi16jbOnBG$4V4m9$NcA3uUAR>_)FCuccJ zyf9q7Fro$ocYU+1&&Xa|Inl=) zx%x0_h6hMJ47>qzXLHIujEI4c6QeAA=B5XzW7gq|K*NpKGls4@W~aRJpr8WaJ{1E? z5&{@`18}cBs9j+rOsMb*JwQo3MC*5s&Rvrk+a3891+JP3e;0PJ91|@zEVlU7xOa#& zJ6VkKLd$nW%W0R3MRs9Ve(NEWFdAC1HmX_0Hc1^MYI~P`XGuw0I&s-m)|jl+u&%CS zu|+Or+DZ+38&FnVPBDQ_P0GSe!w=-9M28YWZ6?y7E28e4=F|6a{;ls?9MP3Gg=^w+ z^477F;_`krf>Gs9s8HMHx2?TA=eqIZW}=B`cG9w!d4Zg-qR-W&kK8X6WQ1EK>}f{; z&og$$%slz+E8lqpc~0Ghj(W`uFF<}#%t~C4rhU{dYn4!+*=fzB5{vbMihKOLwv2%R zLpSuBNgA3C5NuQfB>@U5-Owj~eY^(27=QwuPJe{x`|NtdS2>~cvUsSlM|9gxbDXkG$l%cyK2v)>R4p~*~B7+s}@CS438y=ep4J=sh^F35JbAZ*uXdt<5qho-6jVrW}WVY zLjVI`g{DGUTq|3U2*; zdmyR+C>w!cyz<|$C{w@_2}7-^0VBm#4pu9gYcW)6 zecy8J=|Of_eqTstZ%8lzU}R&%qqhMYGW!~C-6zJf{L*8f3gn|q|)13W}QiV`LAHct6Zl#{i5>p`9N?TpI8LIV*)l*McPU+re$Lm(Y> zeh;yCz{I$Lg=F!*NZ)=jKQIri07%F05aWg#Szxfbx|KlG9t9!w9!Hf8suU!sLR^Wl z*!~u3;#3gOb_xMTD0Wo!AXsXT#v}B^EP*x@Ol*4r!-AqGNQ)~!0C?y^D5`Mcc4g3E8T}wFm z>-kC9yeX{0TX=fwS5ljeZ;dQL9-p%bSKjPm5EsoYA$$*fpbE6XG<9#_9`hb7i04Yh z#6iZRmx7q7$nVDrBm*`~G1@}lnm6BOm$XrYD@2>!x34hXEbd)M-U!ZUr3Q(^2{gL5 zg(7DN{mAy7SG`M?mXpXC84&1azEu%i(W1!B^DavkaGVJTIqSY%JUK*og!okSevbd& zs1pQ$4n0&}`Xwcb`d&dtAJF68=RIPpuX#G%$KMyCCy7*_{w@b|3khjYG!P$a zZ&8{b6KTLb22+>3xWrq^Yy5guxF7CcF11mf}J+guu`iow7kBu&Lu*Q@38Pf##MK_ZM&7PUV(c9$R0LPexONktJzwk}pOA^WG zn%S(N&*o5z;e0_7+#$^*Fm8tGD;X>*U6dhi>YjUZ*6B4VJdHMdlnQZK7)rV(Llz=6 z(8f`-Lro~k74xmBsb3ddrIDrG)Geus9$_YG&7-;1RA`OXUXf7A^wRa9UECb?(@U~Z zYt6TaH7zB9qb@lAH~zQAR*?dSHq?)6M(d*6O&MZOd0(u7|9#HZqK*w}7k?Cpl-%0mL^kYm^q9Z+$CV{+S-!Vh^`%>R*kfo)XfxPROpl}O(fb%NJqq_! zj{**>8)ieI~E%w)F?m7>OF zQAbg~rkSIL&=hCMnv+Tl4JrF#TMIRz<}yW9Ry-NXKfE?Fs&U8}Exx?2_O66;&bUfg zy}F-sv&oMWO87wak@8_~)|muWE5Mim{y+#+&n9x5WTU9kJ1WME^R+5!S!zBH z;dS7Jkzh;@2cikaZ?7CmzV5 zOaen}7EzB97zTh+PQbVvq{x}UCm?}@D5nR&NE&<~sBgv?+@Rl@~DF@0J*R+@COBnf2@ywE_WCIweE~A zU;Km^zvD>I9LMI3gRT%J{Gdo6_#y*Jg4u(^hX`AOdO?8j;Ay~|bvw5Kcj#RQX8`## z7WaePg`4*w#tPm60pjiKArcQ!4Kbm7MwOqgh*NCpjcvVI-R5(BNc}+%fF7omqCj;Y z0ZY(b&(%gS00b$y2T-}k1tP5Kpq5`T>-QNZ`2th}Fb%G?B0xnSE*Hd#|5O@q0}jRQ ze1M8QfK70t1>_&k5m^vE03V>spMnJdKoAfE0000q17{)t0Dop%Quih5XLe~!I>sr@ zmV?0)MUA_IKeh{Lnh~QQe=6KO@8j{yHvad={{Vyr0BA$NxD+P3Q5JzrO-cJ5BM)>`-YHf-A2_)LS}*2)o@@%YP0 z7FdD+&-k(vf*`;k-~=4s37r5C@c@7j02PVAT^khdy?1}!d*^q%IdZLerB`M()!5y3 zYj}6W>FjPW8IS#0rur+~FS7m)$e>V!IVfke6;AbDoWLLW%?$GW>@2c85-B#<* zHG}KZUHx>~KU328XuwM^E^d@Uz7j54#Vh*nA#6=S!Rm&gC(fTfqsEO*bE}h2*9Kt7*-@pgn z@^TT6cgQuswWcM$u5+=M$006VgdeQpUoJD;*tND;+Fm(M!_3cQb~btuH^Cn+-TmEb z`%nzhByBOk7|7CE2tZi0Jg^55j>rmBcX69zcm=o=x0AO(;?pfWzB)pN3y z%5JO0yI`5-X4V0QHL^91ADQgyrH0vd@oL(U$F)vjolAo5a5V{E^*h8i9Wf(8dO+cb~l9$f&q z-uZhF15qzc8snNu#!eH*<;0O$du`kqwHS}h(|@Nu-_|s;^;*+ik3SmD7myzW;csNa z2^s$0O>4UF}bS*G62w`Ut-nhfE7Kq z{Klp_v4uGB0SHh3$bmvK2zAg%RVa_+vMBx1Z@cx zg@xTl_?xKbQiz@k9l?I6;sBVj6RJIWiKYz$AR`C>VgR-vbW2ynsVy3xFM+MA-eXcq zv?l$CJplk>%RK;he6WSUIdO?IM5m-waSy?xcE_ub-fOxhg>)Iuj@!FDBiHlWK-|hD_cY3Ah081m6OY*io zYF|hk!fe%?q~z%y2e($Z5C0L5l~%5*`vx!eSeX@lRl{e99lPB1F-MCeO@$53zX*RZ zcRR3E&_bLkyEb0S62f!C#uKVW{rBFgCLFe;W(tn){C7*_{bc==Y?hgQ|ILU>$wuD` z%C?LiIvF0ANw~C7e25%P*5w>?c)T!@$NK$pX8oInb2iY@W}luU?B&K<84h?Bt< z0%|Kj6$THEnmu~dQrCxYu*zgLB6~ynY{X^@gw&(>swktFKcH$X*!JdP{aokglUwAr zUhgR+|J{6al%e7L_sc884|-WhvZIO@{W$2Awk4Z?bhHEkA!YrI>+xMB5HBkE=dmgj zY?Y-W6~@~l+;p=lloPm+Rpx!rK6VS!HWto4mN(YfrSg)HMC~C-o>-aNlBuWpyp*Ul6j6@`<#sC_^o&XXh`zn*=4p!{vf(=b{6B0&xcdJ3g>;nqKnnmMHzo)k^tL3M0pby9ef6cMT*64Tn0;kY?1P zs=ov|mO8a2u@AFf8gMD}Pt77e1VHNw=;;5UUeNa(scF@nxIyn`ugik}KrXsCqA+#8(OCPn1LG2YCTnB>RB62GnV4iYXqi`6KMbwNu8|-Ge0d zrv=>{w*PsACb5KQr6pEHI^d&x6?o@$LB+*i9s;TWvLYv9@}+>v7Z@bv#ECR>i4Mf_ z6ySh7JGF47Vr;h4Z}+w>N}zQVXbRY|BV#Fg(zaWYtr@`B}iYt5Z1QeKEE&-0MA4Zj<0py)vvGYr^T+A zXPcvUMAAhU29vIqj;~;DQ%xZ7rb%f7L1VRY%EF4b0gro0lX%qyvUa(Y*ICbm!F^Rl zA|t|a>bm;MOc7T1OA(Ns_K;3lxS|D8qFE%Li%u`JzckSNkP3s}-{%9rh)OJ(W!``t z4tRAz@JvonR({#QpX`i@lj0rS))6B5fWE{?I$P^CsimIV{B01AohSUvQm+Rugf?F40 zTTv$L4`CpLS~bPWc<5BlE14V8Ry<#=t{@rVnGY!`^&HCz|6gkQwbGPDffwMLq=#nL z|44iATuWx}5#Erh8R`iNRkA&}OC&K7oez?FoyX3j_f(fROvee!zd&ou-{>UNagwGl zsL0ywA-xEGIiZZyfl!%7Y0v5Hl)n9DMs;P;-T%DNU?Kfu#+zZX@c+Z>wqWUPedc@^ z=#4>dzT_A}`oeAhbL>*O2?K()I}SJUx9%F-+Y*VD3syG_e?2>)0vOqV9&b}%~BaqcV=jvaI0xu0Wxj5Ye8R>QdrH%ZKMOndP&PNnsL=)GbdtINWHH9IqD>%2Z{FbJjf{gsvDi~7_aODhsA zI_(29%{>MC=7_}6C+br$Sc;CK)tG%u#}ndCTDUhPQ}K`V?pQbGG$+C%v+nNIJdb>5 zD2k$6EgmnG?oY)BJ&aow%^XP~Q>j0vMQ$t8Sw%}^jw3pvNg}GXUX(luMLRgL#=ntn zp(h(e-sSTF*ckg}&6w(K1EMJRy!Kd^=R}ptd-Be!@75j@<6)M4)5DgG#<$vEBE%$+ z(kY!T9szrjKxM|d(0XPt*u7>rxj$9W>txS3Zo77wA6mlO8)d{@kFxp|DYrerBPAoc zygK{{v01`e>g(?<`?on~a$z|`=Cmm8Hu!erouCXZk2Az~Xv6%_Moa0oz4s`xT2=SHto7FHz1_vF+O2zgWNO!T z@3XdR$Kq>TtV?B;#f_8O+D81u!OUW6OaAfVwT3}i1OS2p{^5K803iS>5`eomDBgST z{@*+2yt_HJYi!Xo2N832cXhXw+uCuGl$@kSFhT@q2$3idM34~iK>!+x_*#*HfJA`t z0Wy%#YNMzcga%*-csao0nFBC>{=$egnut1riZ)wvu!+GMPT4&9&R{N=$xUUi)a|cd zi_9i94LIaBw}mz*GV4^d8^9tj#!WFa*wrKze$Z5Orr=7r65CPY>!mQ-9KsM3WY>9? z)0Nq)gIFU*#)Zk{lkrg4TvEU)+|B6jYOa>+5|czB4Ty2-9^5&9kAS&AoyN9hC1^peXe!s_dwYGP%(+8G~I>}|Y5kSBE?N1l~dQ)j%!z>ga0eDtfT z2oXd^D7q5zg^_|LqWRF^xsX?}qQvvEAl%RNrjw`N#dbVzR^}-|WQ1qDt-CU9Fj2Qm z$(C=ay}m}iyB9ZWSjca|V?am|O-&ro`d+({O7W~_>0ksUh-054BIlf|mHV`;>fye# zrBgY^6aKDFMo6T)kIk^M4e^u*%CuH6wy&p+bP!0n@R91Djmg~dN{k&zl}Ll=g^a4m z*~Wf!{h3F24lffU=q^>don~G+gzbg9v;tXED*S39@jLe2fD@a4CCorSvJvMfyw<_GQk}$E zonKov#3~hD#A9gf28reJ7;=-omxQV62kx9_T9V~fHaezk!h#l9S-8f`Z2fl> z#V8;Wj(Y8;Gl@dtm__alj%%^iu0STHOYUUrHK(mVXEq9>VeMWw$*zwt(YUF+ z+JW6)-nF!A73?csDveT)F6pP2{zp;Ro$;>gtJW9I)YqNrU77V9HGJI#UUBq@^=4`r zBAl;OB~r%0xPG13PC^Y$fGfKa#hiDBHTRre9glR(u>ZR&jg#wp>&W%ctma4=wJWHqqBQ(1Q|1r+%1H`F`XAnO@_-v=>YhtH zBEc>BGChadRu_V)1ZXCT04yL3g#e}(K*kEUOn-#ANMPg{n%Y!&qLKi*E__qkOr^HK zDiqv#pRdC34-@n9taTG=wt@OMcsoIIM=;(+v!Gi9R1x<+%p0EKowE*hT0*ch+9Cu2njl}Pp;Ggpi>bf71WtZ0BkEb-K}FV;$_)-!TA&JLVVwRu>xY2&z85C zFFaotWrIBkfTkizDrg&lf0NAO`Vc^Hnz?u6ApNq1nm8 zAEwtKe~MRuG95_F1&v*xd>Sxu6&^?8_nSSz?(@x4I0(ya8&cl#jxvT&&CQY~C_K2g z*7nP+$-Zawcz2Gd(Qc-(=_=4lLy;8uyZk+>7H_a8bAQN1N~x1d5BMs|5Q*1#WcW^c}R}>Jw9e~g0HV?Y4o?TEhuE?0dRKy2)T0NCPkuva6Cu>{|H>THJw92Qu zhZ)3t0odT~?mch*kve;g^ES|stpXa1{b|||cjYeO`(K=1F`5IY0tCcUjDSu>fIaWP zT?j~3B+kWk-Tn_Z5om}N!JGUwd@cY08H>_;XEFrZ8a`4jEY|qO80Uuew2?G-rF-|b zyqtgF)_GAVR_4awGNWAOJD-e>4Zi7MsGNBypQKRZRQ|9UJQCHm@qN0n=S*k=yUywa zNA&590YnU{wPH8-E%LcA%)a`I*jYQ<@yWB6ISt;LA)7h?stCM(34pTz27O$jTcAwH zF9lT#OAl@R_RBaOfdGCo9+=GvF;yOUmK98D4fP!ra^z*+_jzvEt2JOE%5r}6WDVz~ zr|*?HswG+O=Wv!hI8i~|d}()$%*DTTty_klXnSy3H z3OTXL?RR5-rtHJyM-ylN_QxIH*?Lkf6Ee?gw*&dIRS$l=E%<@wxGyoJDD(sG@0~5OUfLWJJzyIbbV6P zuYh<_)OFI~ZT1Rm=$(q%{9O+o$hH7Acb3Uh(CAExP7a!_N7XYnY+Z5hSRj<>RY8Zl zLKaH&i&4LExV;WYT9+7Lh6viz>!K8*ggu^;mU@j!aWMs9{7zOIj`-eZ8B| z)b+;YSFnVJf703I>-^vV$K$?;SU-R_1dB^0nae3yFf*OK`h#FRG~w>10c1Rba+A2BbB~ z%85ZqT_8g^=k;1mD5}qg2;ts9Idc~<0SdkR-n6Y9Qzx))*>h;lEY$P65F%shaGs_?u9t?{~ zPZq=P>+mP3A5p|oHcO!70572XNp6$I)oO19_|Kkw@)M-GjKBLY+-uoE(7(qWSOw{z zXI*SKk|(N+MjafktAg?Mr&hXvl5OK-al?gbnZExLP7nG?*V=Yjexxt@fK7oOdjGrEUR%#V_$+B6&Y0}Ws<3DlfJzt z1^A6ET@piDQ^A>uE8H*|WEF%11`duYjHD?n%7_L z!nmUt6m3Q%ZwYo&HK^*-9P7!{_6*y%_%`@CEKWAxWr5jRq_7{($uqOQ2HDnffF4-n zDx=uQ6s)7n4A@%i7Ri`tHQz@2bxW4zoG&hzu3uDR>BG!Jq|F3fI#RkFSXe`T%e>yj zwQZsP7wRPaUv$F^+EV2l)tGlIswBo+vWV#-+#8>uWi-sR`IIt~AFsmX3=nN@pDg&= zK4XWGWuZ`s1EbI*y?!=}vA+WvKL5?KVvoSrP)kC{c?PRaXU;~8G#EK2I<}N3pFYy4 ztRa-`p$Q_1r~+xjDEghl@rUuIsK!-Ma?*OAWeZ_BgX+@Qlo|Kt4fTK|45DBu!O1LH z=~lL8G3U_(bHy018L@2CSl>U ze(#_7W;@!&(w<(PY=fW`6;O(t(*c{96yjSd1+W^^aH9(8(ndvU!k&wH@zMC}jPakA zEuhc*7<)sOeWq?LJCmDVXTkHrDT|L*KBV1j4L-flwlP43T7JHF_H4_%uV3}?Do8iq z2PSGTsjraO41U8QR*q;)TXQe_)RTU1DCo*KE~VusQED;NB5eC`rj_32te7%$v24^D zS-B!WKBFVbaz$BcX8_a?5CZ@J05bzHBme+!Wi*xApCYr^aX6L4wvyVBk{xg*U`R`4 z9pF>OLOa;|J8ilzxSuxfzv%b?z{mg_ zn>U0GDpKsZSMJI$Q^^rmS~F;q=9z5c?$h|2WQ7rsC!A4OO~V%*Z=?-0VARUIQN6!eRpr}ZuV|w=F8;WGF!E_U`g)TGK877&Edkv zVpv&iWztuOA~C*f6cq75fQt&%eMk}U}(kj03>AU+aO0U!i~`8;DEqG^mVDMUtM z`^?N7w+K@ootCgMU$xaOqrJSwSYvMRupXK_gCsyP(=SUXDKSN54Y4%b+J4SSyaLJ{ zDcMQNxuz*!&5LFNUT%m=Erx7BWab(QTVK0c*fXV?1^-|OCWBt&Mnpj}W0={B`MN*e zK!8Kfh9QDyCWz&VJzNJN_k+R5VPD#zSY6`rJfz9qb6-2js3D%JTG_MIzN5(OX6@|w zP|(T7?y}Qe&n*w+%Ns^vD!xM0i;({bekN04L5E%W3<+c*B#qEyUlxV zaPb*OMD}5pZFY5SzTmlz$2utQq0}edEDUCk8i19VVcA(T*=Tir*R$8Nlk29&N!bb7 z)w-c=vmcNOWo^VD*l*L-8W(42Z=e>+MhfbzrfA5)Qdy;Q;k}NN|50`6*}ok9E7p?l z3(~CjEz)55jHyi_N-*T!YdpKCZ@cy;bXE!l`T=v%x#J)mOGYBfInnI)ab|*VH25xpK2!+VF zg@A|@Ed@zS;aI~ow3b68t<|SE**bjO=uf26e$TJEGn6xmpcXm%nC8z69#Px9!CK~$ z)F+_fWc~S&@edU;H%8YimfG$gYJ2U*(3RnG$M?UM-_)^0W^@F!pb9tEl4_SZ#h64~ zkxH7~-{B;yA5f(Q_1dM6xQ8QP+qNR^bgUNoNO-%tkT#5*rEZ8()0y=Ed+__l{?D$f zK?H3!T4-eYX?~XIaiE6V=olGFTYf52Ok8M4>nP6}N|Lnb(sJ?S)u{`lNtTpoekU#K zh6$xus!CP_I%hN7LZeZ-h7Z}N)``V?e}oMcK9C^?;Al#0im2hp@KOztlt?!@{P}|7zJqzV80#{e>SXs=@h?!AV~U{in%EP%Q(??TLgz`RWyr+Hu1g?q ztW2Fg?=@xD#*DG6{LcDjeylUhaxW&l>wdw57dX$-G?vV)rIs4WJLS8ImUcVSG!#Bdnavwv@p z`fJXf|C1S`oqg>0$IC=&dlFy6K`Pr(U*K?&SGF9?DXs8{ZjuhVng#c8ta@~Ub#oBB zA2fMT`GLBeIlLP-_Zc}_x2=4Jyn8`bt;>6IyyHAQUbrw(9(}|Bh(LG03Be+dQdGq3 zhL7J!*tF!b`GhF{aaELjs*dwD$l0)zbv>FJy}?`(G$)UMd&yiw!v2RD7jbg2QQGZ; zRr2sQEf3f>vu8NlYlU>k_FHW+4rSd{0meD5VwL4xbU*SGQ>BUO%;|R{XTY*oO~jFV z`CD((acAwyC2Gic@zbva?@wL9KswQjUXiS+WzBwLf~ z(r831KxBh{C?%G~NPb|G`1_J-rZ4^NADI%pSxp6HG`AJ`qMg0ss_arC$n=d5)&23v zTMP+tZv4&ZRFo4+-mv>8qt7=R@y6$q4U1l~Z7fe@XZ@GXE%D{}Kp>{>>br#y zaDp6U!M&ge6gnD?sf`ceY+7z`eUVOPiSr=Ssa6{5YuG=z+TgmH3jzSZP;#JJib1Rn zw*47%Nn2Hl#w5bwD_J48Qm3e}5Rs}y_of@=@CHQX1ENCdx|fu!^Mp#4!vl z#N%W_m83 z^{?lw6G{z)F>w0YTDc+DpL||f?nR14d}MQcX{nGRg%})uC9b&6?8?5HWse$34?^WG z6%tbzln{y^aPLs0FixCK$Iv;UH0~y-AMhYYb=0X`SMiK`+nm4DZqB#DTH}TPD@Rw- z*0(k3*v_c}$xANjG9u3v(c-D?Nk7G@v~Qe>j{88GpQ5~-s7_Gza9d0Oq=km?9Xv;M zgS?_PM`hH$s(kRrkf{u`->VkEk#;m!eX6Bg>s19o=rU$5u+^O*(-~>6z!rt%>Ds2{Kn|rLQ zP(DRnM0{%q2(^GTpaGbJ4MKMS36vR}$-q=n#H!E+1}L5tuGBjDJH1=E)YFpu&{UH6 z0_6bRng(To_lG${C>JO~!3lGjA;&6ggnB|5T|xK)kY;YXbdL`QZg zYg=4vH6OH_x#hol!&?Qm*P_h5wDs1t)9TL<1c%FCU-(wrA8rO8f@oQBuR4qn#Ng^T z$0B?ZeB2?5M|Y3^hOZS5sbgH5>m-WDvq0z{=&P?b^|%U%FA&QJ>NU5OzYP??8>~hO zL7(=CQk%IyxOyh?L;K_Z9-75j^)WtAD7)UpOhZi?7W83@p$N4cqUj;obgPqQbX=}4 z4v=H;L~6^-I7{A>MK$s`mxAQa$BdR|Z>jTIQm$bx2u`W0Ru7|oG1IxGxDc=;(!%N6 z%Uh++Xs%;jS>L|x6uz_nJ|wO)eTMrR23w6dto9i;&CUOaX>#DSw#IQc%Ko{fhZ(g# z2wdh3oeLhfd^U8k^Y3Ulo|MTFU+E8>wE1cHUXN*|BZTec!z#oE7!lhHCaNP;VK(+j7l2p$&)8@Kuj?oE$Sp47d!O^nvgcNEl< zr63PN+Pr^{WVk4#?3BZr!0Ge=DmX^6r!N1$Bv(WChy0ZzfiQDaDa2>dkktGM4uW}f z+|eDKzd>AseJ33RQsjuM8q>DWt8$feFA$5(ie+EIDf{yj=JpFMg|^^_Wd60oowCdKucR zUOu`9RWYxp- zXUR`ahi?|;LMvJif4mh0e?*Db6$1*pZ7+8IWUE|l@gfW_4L&gj4;_c?S0PcKF!kAT z>05)^xb9dR$mVFe>5 z3)6j$@+xzynZf9FdTUR$j6~?a{t`gz7o2mG3kyy10@#P?zQdt6YehxB7Sw=Sq$(VN z5ZNZ+P#ZeJQ6&Fn!(upRNh&zg;z2UlsY^MRqI~Y=2939~`QM;YwZmT#90eXHUrAs8t;VySLU%&9r3Wuw65MTx`kE+>zh^{q*Rs1Shn%&h zn?$AJnfzVCp0Ul9Bw1b>0*Zv|Jw4%1)>j2ze<6#t%3NxTQUEUHzzDj5sIv8;$#$Ax z5D)_Z001)sKqCME4^?R@YClBgBI3YMHW8(yEVi%)01`FO&#@N*b{lgx+HH1s=C%LR z|Nju3000>ou%ZJ1RRDcTj97rIAW2z(nfL>LAVDIlbUodLl5|}6?$Oe$YhS)~$n4vj z9$U25-Mx3UTD#-jZMCHF8bdtRRBP00IC2 zBQpm^Pyp|L@4oxKvb)>%ce!0|H?9U@&GvKIw~N*KkYs>lLX|(IL9LeX_?Fg2_?A^l z2=HYHENgyKE=d9l+|CHZ( zPU~7(+L*xzN@(mf2`R~Jt9#7`XiG~$n>yVwaUB^B`!03{S;Sk~!8C}fp)rmuJC95P z=7rqwVrSzJ-#LZHEaCz0NH!d4O=A1~jjYik#+Woh)fz?GGdK`@8bfAXlRmb^FL<;o zvE>^-uL$dFVn|&>_$?IP>_t&~{t%Mc+fWxqA*yMxyRsj399}8Ma0@<;i=Agn7+IYi za0aY@mqUHduYTT1ayhBljiLXYYtmL3J7g8sb?E-C%5LxPc2oTf$cM9D0@VxIghb!<+EQ1A(#;aOIgeON$v zjWQb+P(7p3ZU@{*Fh|Dy_W4rS+3Pcl!MImP{dj839q%o7r%) zvYw98_u{1SwLDyn)vLn>)e`rP7`9)!{*o?r5u`E3T8nG!%o8#qJ!ngC-aNM7!tm)C z;Lkb7`ROk(PXX$>S6JtL|j2ZD&$3kr5c_dUt%-PQ)Mbie4S9|4AhdC3`}VH1RL#D~N%GHQE1U zBK(4e>4UqZ6Wi^0U*~rqj~jCuQ6AbI)UiTE(F7lN$iOSz>1b}aw^Wn=&3b1e##j|8 zsV87@oLhTI?2&7jY#|e#?goO~#n5r_>%+PRP#g(G54|a2_b}Zi=uP-R1->kqw;2*pXI?a0KV00u^G5XRb~5HBnTgtv*ano>r%Ry>4VdYfvbo%A zao76yx)CInceyr3%nAW%dZ@eZ&+1T7QBdT06a4p>7&&(9qJY}KICHR)BKw?JcJ`_T z;(%gdDbB`%GeK&6o)Rol4w-`$e!tAUnq~qCrw#PvNDB$9{!jV5_8;XJ^S!ryQV{Sc zL~~rWnHW7zn)2V2;KcU2Et^A1iL_3}KlJEF`&n|m-$0s5m9l1sbiIsKsw!Vbq@$>* z8l`%2UO24FvZWf+*gwVkPn7Bc&$(?Ufgf8g+f6Rj7hzgmH`~}#RX?lMR#?bZ^}O#f z12ZDw|B0_ug&G27XhuU|Eq6t-n{!=rg0bcKj@_e<21&s-n`>gl2#TJE93N`0s;W=q+e*l zY(P;D+L2e8v>ZuOpn)I?fs`h3kOs^@ ztn+d;9EPh5$6QXbdl14ZDC^|hvmG*U<#>v`bd8;T4$btM71P0b*H#PF2n1}mwPxM(HCOg2z6cv-gC>M zODbI5el6{G;C3KLExcR%ztsbB%W7iZCyCWiu(aX_t5y&AQ)98|q7*f=y9ax_mI6}Q ziB^e{6!nrm3_<^3s4}z9kVnN0te!E=LFjB2SKrq=+Ib$+45*yRL2om9*=w&U z@Y~K*i>b5#Qht(s5pKBDxQtBlH74eyx%<;OM-CPBS`)y7hYjL?rW95 zBLiAWkKyZcJi8T3_OkZHz-^mb_f@mU5OxEEO7KMa3L)!(0V0J^+XVavx!29FbF1a2!2EmAc8qJAR0*vV^ z`4%;Bz!U)9A_i7R7zn|EIV~Va1ZAK=d4c-ORXNa4&?Ru>mK|bxh6j0)W~Uui!lcfO zT3&|YrJK6Ac$4Sg#mtf~9c6n5@;DSctIO|sc-AQ_vHQ}vvdk_P#yF&>DTzn`iMPO%W)3&OktuF${it6CtfHRX=tDSG(;=VV*W@cp#{gKW{& zC|~Iu$RufC2M-;F%(krymb~lj#8k^OcvUFi>STfh;oFEeL7g;%Ir;U}z5HveSC>Eg z#orksNx(^-ZFCNTi8Ay;^8Znro|um{(J$xqRG-9W9I>*?Rmz3A1UbyOTuIvDPS_`P zPuUSQCMDew;igqwtg15!Yc+Y*YQ!48RzVC;^3vXMfj`pXITt4L)Oh#y2Md-F*MzXDUpv( zx>6XpgxY!196a7&bxP>s=;rZP_~e+86wwkvcTz>QJ4c)>-W#cvI!1qcM-D+?O_?>L zE60ztt;b2fbrROqXIYksGo->Z6HhTlx-1vEF~;X5JaAIC???A(G?E&7?X zi_*;e7+}v#kU^+@Bwm<#T>p<$x5VyI{g+K0rjjI~g=DfbLzL#4Q?@L9@EtLR-7AJL z8(a**E0FL4jUm_uHh*Oz3}7z=Ug}WCi+fwpLR|nC-46IF3xPLS_&FiMfWHh;9xG7$ z0EegpvaMnwpEgm!NHLe!!@`nxa0mc|fHc@lKk!v`LQ?Yr5CsjwuAl;f4);Hx88Jm!CTx*0kFF;j5yV?J z4k`dpav7BtE(hZepNbX`DM%28HtxU4MO7z6h&ZcRdY8 zYNibI{mMe#;VI!OjU^U~|NT9fbuyEPyvVF8XTzAV)JwATKuDhOl5#+>fgubAo5X0I zNVi2i{Le^Cf@#i#dL~gec9$X(wwqo z_)UfgRAxbVKnxE6ZZsdjkmWa;1#HYPCSu-=TqeZPD_cXoXe6#|N3&rQ-;ir0N-3!o z98M;FxbNeyk@tbb+hC5LD=C!cIrXR5h`Pb!CGg=Zjirv8g``e56epWFsIB`(`8{Lo8riPX&|=>3MX)+e251C zIGPUKFZ}JsQivIpHCQP`07SqH2xrt$FCL3Xoi~qC!OzuPa8qjeEpKQ_N;(4bf+8ET z3SVQrC46bFP1F->@$do2a_n%=72+*Y2UJ`D+v%B!ir9S#<@D{p7Bc6lAwF*!j}o4O zj8hKS&=IKOE_d{HZG8lV?88T6WD#9{AJlDI{ZlwP7G2EL%1~283njnRgcbNK_e`j# ziYYiKs)PkVfY!7aiR0SFONaz3gh0Wu6-f7h&;Y5wd14EAtC6CcD3N94C>5#dkFD)uLB+xzcu_7T>z5(g@GF31X95ilm_YqbbYf?+~UL%LV=_b&<-IA>?vX?n-UHH zTTnePKk!hnDIsG}SOy_tASnm!5<&-z2oFLiAW?wpvIh&jP=@f?5D)_Z001*{M=}5a z4_5pt@0b2+PV`bqEx0z(+N2TPEVeD#(`~q7fu{jvbHH(cxI2xx_ox5 zgHptg{4fY2@dLmQ@l^+qwffl0A~rmKfvufP|Ih#b?N)A0eA@3BMWLai+g&Zw8U+pQ zDJYb*v=kteo0_jy?6zwtOEkQw*jJn?7I>!UJGOnSwe%KcLYs26XuwvM`MJ@qt@2o> zN4qpn5(*leszxsJxh0Pimbw|3S=Hdl6i}7fOhE$88{%xa^Sy0Nw~gvzwP~)slafE` z+>f;x+|F!~9{qBOR^8^U#`=Bkp`KZzP*3Hx!X*2q#~ya+c~hF*n(dLgDs}bQz2BHl z#28qzKYG|`Qhk~jW2tB@X>v?32@SOdsXTV%Y*EA(?zq$d8M1l7yM{`Cn3y1Bx6RKd z!vl#=oVKLKE*_R5dG4DCf6kOg5H{hh2E8G?kHv`tIuAHD_7|qaXw}vyaygjT2LXNB74*97Zp3x^ z2f9hwM@8gQO1(=D-i`W$MIf4ICt3o6UkjsoV{k2K2FNFZaYP+dvOfk3iioYLxrnDM zlch$?z`In6{`KE-=$ytOV6&;)6D%C=2A=qi`XRO#rCT7oU2@ySx7rQIJhHV#IUUO# z-J=Sdt<$gxmXmAU_Bcnjx0;|) z^X`o??D!xJ_))g6$o2x2vhjLwx`r6}*VE?`_(EoY` z8=Bc*n;H(+aj!r_tQL4vClaW-MdRO(vDPC$(6r9%UG~$LoSSFPIwuF$bDG~hC9qy< z>xw8^Ft64eToNKPotS(E)M7YFRM>^9(2ni3klUD9;*uOIg+$*=W9c>ov&{ z*~DVO6K^mTK8^AVmSX)K69)|2Y21j4hGzv@F|`g?mZb7TpCs=qMc=X|_o-}&CRpJ= zr0-%%C;;Pkx}(Sv0YLB!K+99w{^dW#BCh=afU&kKGC;mb#0&S-2A5tv=_pK`D@wK& zYD*3l$-&pDWxh#NOLEH5D^RDY^FM#)0a=C5obvC@r@_&*5J$cs`U@&X6KO9 z;c=!fHHKsC!RP3Ym>1zLzUxUHNbB(v3Z~=gi^@xXyx=G0WSr+Q9Xx3adF%F_D=t+L zms{J|w;;RAjSWuz7#PAF+j`)Q-k2d_R|M5eZdY9&)njpvv*tA3K~f0*unAJl{vd{j zy8(gF6bLXq-^>?r8ayax>ACg__!&Wo6)I>D>q9xYo@kFDk?e?3OgflS^>xU8Eq^)BO>92Yxykqe!|ttNJ$C4Udm&JP zl4?FhT{3fE^L$GSQ{20EYa?Fo^kBtncO|-HPtMT|uCkM_lWiZ(Bg{|Vc$Q?)fRgg7 z@*(xFPh7V6grFl03_lPT7KnewoMC(3XOV~q%^9lnOm4$)Rp31LDEImB27$Sj9V_Sb zB0r8TMkNqpKv;xNpv16Orr7$vw)+-#?Au8862V)iB%}yGvq*^KPPP>pm?pjA?nUd) zUONVPvOfQrPIS20OQ-tLbkD!1zVpV~jNHhN(XX)DH1a5h=vHWznLI*GwqA4wX%4QA zbod{e+DVZ9agVqHsw1GkDPbW_NOE7fO3&SYEkzPYBu84Fq$f#mccQYcF?Eu_VcRtu zQ32%VFi7#|i}U-8y}m^hD9vS1ZAUT))nc9BL<@Ok%U3%K$M?Nh_MH5>X!%+@73R8{elDr_A&RJ>lc;uESz1Q1YaYP(-(|PpM zzH2U4zO4-_QwO3K&Xvekd< zJI*a+nbv1OsU%!!A+4NGQ|R_Nv;0WrP%}E%*p~BzOf{x`JBT>Ve;Aw!Z&Y!d0EYWW+_>BR{P>Lc#{Lo_qLWlq1W&W>Lpl0H2=m7Y2 zR4Fr&QnGC4*BOccmBP znn*2~#^N0Q+VPE`mgZAy=LgDkie9f!$r1mQrA+FeA4~|aCDYW_XAtv4W)M&Vj4)s% ztXr~}=@@Z!L1YYtgmDLwASCNqg0LRqy(|!c16ngYx_1?X>hRXvNiqSytWZ~vib>*_ z#g>4890~>O#{@j^5d#e-;UtXysYL%e&f$=WfVbrR@}dL+0Dw>qb3h}8E6|7_d&E=& zf>06T7w{dt?jHz002zP81p*6@NQ_?qc96wlAZ&&ZW_Z4!0ity%7iJM?DO>Z7Pnu8= z-nqM2fFQ=>mRr;=V?0Y5F%2L>X^dMu$U$-K3#;ccyFiEjN<}TR9Ga=3TaN&6<{q$I zwCfm%&cVnSxIp2{hK&3MMpwo#14KVSZo!;9A_#lScn5s_#?V7Y2;zko7>x+YOuxpc zLrExl(O8s>3xvJoCJseRTNR zl5b<*(uE~`4P<#z*r(Y1dHAfx33f;8Lqdykp?Bh5hUbh~WeV_UKwNA)YnONMDmmGQ ze~fANEJ$;8voaw0)ZQ(DG%vF~4r*jpQsLm;GbU25yU0LCY3TY;{&uR=;L*JtoE!Dz z>AaVNE5G#vkjk6}7 zf&f;29)4-p2O4&bHc7B~UPl5d%>^swm&s*Dijl(+XN)wY1nBW`4M+QaHAYa|c4^@F z*cBcXW-RAoM#ICsTP#TiV|}SEcC#_>&KUHFgX$f67)WGc)e|Ig44y5P^Jqn8ip75F zW&0VEPPJtXyPLEM)_RK-?FHeVTM^B!d1zgpo*pWEv&T%HtUP}&6Yu?O6JkKj?V+3? zZ*>WbtlrTQ<}WDqL{^xigbXtPCKX+#_0>ymbgN(Bg#Anjx>!RkLXyOb6{V(`vXy{d zN>VS(W2cb`+X8XoNKP_F9{#sbZ!E18WYRLJ49OTpLNo>WndJr2Vw}MzltS`@)=e3? zOrjBq0iE=np`^${4jxM~*dTErB91NaBeEu@k%UmWZ$6pQbg$gln!~w=7o;r zi6idJ=W23BysuoI=d>Jo+njIY1<%9Xs)B=`cR9#;U{S)#ln)~F}KRZ4A1Z;-jDs4(;xX@C#;pXq2?2K%-mu+{r_ou{I zxM#Hnvn$Xie{0(3GtAi?t$a}UMi)BVlFT>E9%MO3?rh8h$|`$TaT7FM8+C}+N4SOc zpgSq%%m6OR!eaB?xq<}i99Hkca1 zQW@4PNM17VyrQr>XAZ$Zjgr^{&hjL?tp>`;w(B|sK zP|K&y(#Zgt5D)_Z001)sMk4?K4`npf`k!RJ%TBja zEELLZu?#?KNR%M7#bHeoZVTJ)n{%HXYj z3E#L{*0%omf>TbG1O`ju;3O{#qW~d501^NIBVu<}PypU<&-*>!ocG-3wbtWV0X0{E zbe8t*Xt^L_@P-fY0Thqxf>?qC3TFtRfQov#Km{>1TM0BlGCk`N4~T9^Yk?x7A9yj( zYqiOOb1L>RnrRiXq*+c;)fOUqosKH-MaG=5c%7?L`>0lZ^nb;uXqw}^iJqS2KGT}@ zd^Fj08k1HNf!!L!0$W*)Igpy0q#pC5S4LMJeO&HYbj@c3HXRaXbp9CF4}6C;IunPG zoeO)tCkWlxu)_o2C2Z^Z0%eJlHEAmlBU=Q)tz(Vq4Ewu%HMu)|7dz!a+iZrgn$L3FdNVd?nvM0S_ zNV^~);;Nd$``mD|F-Bt(Y*6P@6gjm=%ZOp?TbgWt?as-&*ofRcTr;kOrI%WSQg#U+ z@QDZCYfLLpi4@W>wFYYHMfz3tf__!Z0=a+?DdyHYJqAy~@?~HDKPk$U=h&KL2Wua^W$MGM`Kb5`BCgdbAMb6b(snqCNps-Tk2RZ+ArADc0-xmj!PfMU@=Mv? z+qe|E_>uX3%QT74AR>oESI1WoS{>8Qx>JvKOE|}z`qMsET-zSPrT#`8cWF~uf=JoL zamvSCpwRVPhZp7xN(q8u&fwTec4 zb#;d(=3m*2L;KB|s;#7}OLfdRPpAFUzHEC^yIihTU8YD+MWdy$*XBc^n+(@U>{_Xq zGik!sLOFOCYO|3h^>k*U>~7=ez1)N~Sw%wx72yNrPo$>_b7G$|=oYY+VQ@C^Z9Y z-XMG7l#?SaNf%_}W8MpN0-au@jAyGE5yj}4HXfKX7gj0)P!HS+g$N%M;2=A%+yLFY1a$nacux(mAqRZ38KW=`WHiTss)4(eex_7 zdjq`NYRc=}0Sk7e_>b*?{O81K*KmJ_Y8fwBwnXpxw~x_`rq9A^y2zzUH0fD)tHy(~ zOnsW}txG3=memkUiEOUy>Q~vOPX^_-sn@!Vcojr{z3-Z>J)41N{d2H}4gDJp-lOKB z>YyfMEpzW16T$p2GD2qiuF${P_5PlMHnz^ z#yVg;yB=d04z+bZ7=uFZ!9dQwo;&?0#?#2?sP;(=?!K?{N_1J%K^;MffEqf--8(Vn z&Fyia*Qxc> zBQGBFFvQ|2?BcYi2uISJ{8V>Op@ttjuDEv*$c5e3EN*GzvtPW{HS(wf(aT;rx<<0H z(2)wHD z!p*!QZicjWSbKCo`_7&YaOQ{K&_6Efd>-_6tGd#e(l2it%~I)rYA<^1_5`{&fSdDl zmN)q`;LzXbug-6VXy<)*N9?J5%jWQ{H%a_lgrUA17GiBDVH@3gj> z+|Bz;bV0z}EJ7cSgs;iLF#j0=Ij5s~f!)H+!@+~chdEVS;kyU!rIqL&wf4^xZt<)E@-ub(sHF}R)rTj)}$QMt2<-lyLzVv zrR2f8$OedaPU{1_C(Y4Kp+k0`rKd5r7*V#LZqDsI+}Ot(C#Oq8)OWE6eT~qzz!xGH z?!vy8buCP8x@EVucXpP{yx7$Ru{ZzRSq<2ccJmHbW%C87zH#q=5H8Y7!no%OCt;#q zvU|*MGIie&mJnU!eu}7uXxk#poS&MLG-{r%h13J``gM(#j|vnZGbOC?YG$HE_=dR))WtF| zwXMMF+4KyyVQjaibld7uq(TU#cAm`+n{oY@f$z26ONpJR**{LNr;ouSzDvU=QBU8H)0w`Q?M7^4uP`eJV zS?`=6>Hg&wj$I=KL@ctbS|tM<37Wgei!78gGi4wvl@hCYnJZ;#wUI=m6==)D@h#W?x5CT~NCp82NYr)vP0V-5T?+7Zh zPyr-sRD!D#xD^5UEk8gN0501YrQ|O_FAnC95X%zoFb>QcEW?OHfb?w{Ux%(deMCpV zm13cLW#(`Zl#la@jK$y(wgMdWgkXFNgU1<|7-o!Py@NBsmZkH9To3@@hZ`^~Lfmo_ zBU`vCD_u64=p@{e`H){qU^z&^F#u?H0@DX*qinyF7$gEKjX>!YEf`Ki^kF6C$ehQ_ zmP}zv#dXkMMdoD>fB_i*p(#*45Ez!@OZy89AR&uJM*GkOlG7lg=#%7B#QV}h%)kl& zq3KvoB^tjuyZkT;1puWmxP1X&UJnrIfcZixKwCf$lmpx)yEmjYsPf|yOe*|1I`3Zx z+2InpADf;@Ppm?ts@Ri#i(C{mFJ;9tRL_ZT2`WEwLm1y(AZ_5G%IT4s{{SA)rdjyP z(SiU#NCic2vm1aC05}8;7xM!K_CT0Y3vQ2E`_Pimaw%r^exS+FwiyFPumIGQeQL43 zx+eLc41nfzD6JtrDYHTf@Ss@*3aMf24r+K%&11N5B&iTZp{dD6P2|Jsu$mX_h~Us) zkQ+C&0UbKu*CIz?zZY_d4kj&iaCh}f{S}Rcp6*Mq?@*4c0C@?m+__))=J;5+7@?rY zEju%pH&~(h!T%`J;;KeqoZ8M4{(Mjk!cdvNK|Kvh&|M+=w_}?!PAhpVhU2HHFbQTYfHkmKn%~=7$};ff$) z*kDo%ipXH8kS(IY2pIvLD1%8ng($KR8!UM-5`{~3>)*+4-O3+=^;)hGHz)$2-bCm{ zZi%-PIkvY!^9&o5^MJ~oM-P4!IyFfo%~9L{DYs^%hMCx0;T%CCXs0Ce9fNutOC@HdjJguobv`ZlnP zK_W=w%ZM8>yqU?4YXzN~Yo%bXP~x9Gr%Ypczy=~^W2)E&Bx-cR*G`q|AhanWKs5k{(-cBda)V48dG*53$78l!8 zvWl4=DZ|VYZkvTD%a$1Z+(E_vB_qdE>kv_PFCd0wwRNv&dW1p#fq|co<|K%i?)vV$ zP|d>&l&6!LIXgjv`9t&$FJFE7{j)GiM7`vbV6vE$@c%Lm`gHdM+@nnZ+=^$bW!uu$YON}%?KHUA_~Y{O5p%yYUc?`lzgO%}94z{eS_ z2}n>q0w*AQ5D)_Z002W{Fe3l}e|5gf?@P1VKCRPy|CZTDApQ0fGS@D1rb20D=hhD;Cun zltttLJR&YdT#=}b{~+}M0S^c`6fl)#7C$t(55+J`ld{yeKjx4kHfo#$0(Hw{fju!t zgB{caN-Hd++S8WO>Ty@ur8iEKvub0?Q%G!;>5^njJmO-`57Wjxl{KL5&ZM>yqcs{; zf)+%TEs`SZ$uP1uBGe(fO z*I$r)bFLzbFa^yp32k9fLq*6|cD-5j+r*I)m9nxbS#Bm>vr_9oj3`ZDMN<%`7XQv@ zigoNC!^Yr3O6(AIaYj%N`Dktbn|zJwfs;-tj`WUJqm;@DM+k zbLAqj;^K55u?9^U=@Ec%;At+VU*uI`T<8xXBBBik#%DU)3EpcOks~L_nVXxLndmt! z|D1s3pNks?c=aew-aN!ojAs)Q&VzJTg+z*1g~C-E)0$#Oqr^2%D!qHfptLV{Gt+6h zdO^ZSHDWl$46mANf2{FI4OHV#oOy$`v*O6>pouwKxjTCfl(;9bC4l{6#wNYw(B9UP z|A+biueXNk4bZehl%~c^)kfEd!e&zZ*qWHn zp|Y+zt)fz2HR?_QtFf&zPajy7HLGv1=dyk4qn|0ts;S;oR>XN??&%_vYMyr0SdC?^ zs45-lg^QCUKE8UQ*ZbPNi6@q6WmxUz97(8FP@F{4i4A-SSEq^Hs9(GVKY>#^zWZ{PX8;(A1VnE}vTHlftYUy3+mF5jy450N}6kxi2g4Zk_yQkChI<=G2 zn*R+VTq~PCy_4@z4i{B+dCoYa=N9JcI7GGNlalG-)>X&%y~gj4yR8uBdyDgPwK{_1 z9aO)V=F%wtkd@PaW9#U^6ku=7IT+nwbEdF@uk@ zQ`@F%brfA6nQsmp03uKs6z;YmqK;wJm#@oP!WsPWt%$fvfDQ>lJE0;gdh*G3HYhxK zxlQr_gkyCaJ>*7HF_#Z^;5I@i0TnhH5xsB~v^^g;IgmTTon5Q4Z*08#8bVj%PdnqB z%Q$?8ax<+)x_ddl-}2>`_;Oi$ID`n8czbhX8jI0uhE<@(;RuEe@7KJ?+T9g>WTQ5d zZ&|o}+zs`M93xx~13oWB_$DClySP)3-oRi9wDt`cWLrRpRVA%7K;Yc2rEHs*eQqC& zzeKb2ok-u!FO$ww`(SidwGC9X|em+c@iL8NTRnu0Z}7Y{%U zWOPuu$P(B@o@Wp2!|}LAd~Ubn=i3QBJY(~0?)Mmbf1NQR6LqUsz*u~r#Ke}i9QO{_ zle7kVWyhehZ~ER8m2|l_dzr5X0(H^Qbu9}wo9zMfJNfpr*Dn1wVn0N_o|6>E3>-EIF~wWe4UzILdsDR!WIu@7wV| z>c+<@sUF{2#dYhJxY2dU+pAk>qTBV_9GAs;6!{B4A&I9b9@EXP#`J6AC_IWf=qbwV z)3&fos`)Tfa2lR;(XM5c)bhdiFoOnbu=~so(aC7EuPZ0#tWzKx^Tg_Ha){g8@JK{3 z2i#?ru1{H~L?u}4oTv*gN6z~?Z68ozN9drS%{q05*A*wy`W~8{C zRmXW(sE+PI zUwBmRRgGS5Gvkl<&z)JBY2m`E>UZszG^qN(6v>l|YWj+^4Gve)m$=T2iuJUkqlz^& z@=_VEp=E+OuAhaG#o|w~+~R?=4()HQ=vViqpys0GE6ty`NS|d&&v%P~CqU>x3sv|7 zkb*LaCJeT8X3y{I_8bBn`;w!b|`-X)Jyy(DX|hiyuxi z`-jCA>C^#E1N!siNc!Hgw>jP$wkwQ3e@4#SaZ&h2_SmJcVKj@Bh>U~it*DzLyJYE4IGSCP!28l|=N-xPY0w^IHG7D=(gT3oH zGDR2B6D86LN-t4;NtGF#d5e7No`&UK`G89H0rv#;h(_WkrY(x=7>qW2ZEyF=7gT4m zzWb<^`1UXtNBEyTxuns6wHfWl3^Bo7jC|}-?<%m(Gtx1iqobYCCsM3> zk3;yYyBk{S+TY_c5!V`Fnj_aR>;RL;0*#!MD4sCHq?CCO zO=aY3giwNPNG_&D4Kh|@*mM7<{y5w}KhFm4g6uZS_>gYi3x_XluCpyN27T%7LRNar zz%u-TD7U+g*vPs`H>%M~4L@#*hI?wLE{JM?QmRQ0)TYm?~;iP^8sv7Q;Bd`bS0=9i3 z=%GHZyr&Yir#8a6@In!UyWwt%>(t_81GI5;MNE02m^HTZj>B&W)g`n@k_!E>&)B4X zcu@`$&1_`QJXq4&N|AZ;w6p+u&TkgIufM0W+1DtC3t_?-9Q=Qb`imnO6Ct-_5JmalP9gu}KWX4vUI?)RsVV*(A zl*Wi~QbwOQPsLZfhG&*~4(iXBGv_q?5MT+w$em~RJO^_m7PQQY$4!GNJ7Kb3w|La5 z=Gn_}f@78a1rSq*{7^%GijDfR5({%qzUq;ZfdrS_(8`}lq*`~c!|zAcqtoc>KHs{g z0dFmR2t`pIVpG!=OVxJw{i3`|`qrpf3=1^9*Q^ncKV4e_%h|}7EvL%@dUL#D)1#va zNO_wiw<|fPXGf+d$ayB@a#QnIL^JZUljf=6TT|?3i?B!abm{!fOpHx*zs@L!9zwm9 zn!_|5GRuw>^P+Y)l^q;PH*aZp)~VrTmD6fYcqZzehoAkw+2p8&prRTDD&OOew;%^i zrPb+J`lHj<=?mB}uMhR4%A}h30-HY$wvRE=7>vd$@&FP7YOF#SfP*%Y&??q^R?dsDz3Pp-C!;2<>d81sfU_G$od13Cc&Or~v*u<^m0Z zyL^DSAr@n)emFw4%NU|N?fL;*4^_NL&pJpDK>+~#tRaz1#cT?XBD-%&}xr$sz@ID-^3~wFprJ zK>&e7ctH^e6`De(qD4@Oc@a>iikZoT7o1y!dEp^36tMsqLO*Ev6q{z)P)vfVI%0NX zYN~U7E8dEW zHPzIN?5gey9?#$u3++ixoN)=2=6g^Q%%036Pd76)HHtTqIj1crJh_gtXz$eYfD(h(l~+qK`UfGT;_B>sQpI;T)|Q`pwhm*l1xj|1JZj<1NqnbDrM8ug zOaxMDH3(YjpjwxbI1ttP?br4vO=VxIsaNQ#<3+I-k*vG?#myz^yJ0F-ED<%>7S)zwva}tc#aOMH z#)oB>W9*?uo-@E)ECWLNWJX#uEYp0Mt!qo<>{`l>U8iSkLcl9GoSeMWXD_b#+e7qzV; z8uFb5%Nh4=pC&4@eUS2-ACzo(<>MFY?%WHn#_3zT&v!Xp(*k6Aw0MRx?%vxYTX6wFDoKXJsyR+s|EmFt^@$x|nxu{AL9N$nc`BLcAs zB{QWHK@WXOWZi7`bmLq%E}vbVP|EcvEN(lmDC$f-eeAX+kuCmqlRfinaiRA7!muIo zf_%vcg!|FZOUzmjR4*k4g5uqPmJ6wvtcli+JJ_|bq3&eSh!&;;p8hVftks1di|#nr zY*(`1lrA)L^PxuIC$Oc6N$81ut-#4>lD6oMzqdLQAFiIE!-D{hZD_1J>b2BWps#rK zt$M#l1pBfOP`pa5X9J4@p--;sLaVwTbz4wcvnOgy?V(qCxz#EU6-sTeyFOv*#hr@K zXw{e1HzAN?vnEVZ@yxvM$=S+bzI*%jlraJ4U7=hu1!T#Hrp(BamCj~jWoyDbd0T(X z);i5r#O$%sx=%Cr9{I~wCy7l8r#_2ZaF%JU(-EUJ#P+KHph0UGSs&GoBdv0{(!w(eD354$q1R;TGf z6Jh)v935`LurxGs`9lG)2pf=y1|-7$F+(ATh_G0QbS;M13rnrM+;~QgaEJsWY~fnN z0VP5Yp`HnCw?k-Tsc1H;LXb9TgZl-%;+&kPA_xg*i{k!@ z+3#=V7hrn!&4kLcy{qGSUMDZzFs}X4;n!{crYm-zt*F6VvDXmXZDecWh2~1l+rqP+ zY;%(m-l#P2VF3WcgBXqlesW)O4uJ$33_z~k%X5xG7OG93XTCr_1X8`4T>m&0nUF_; z&b{N_1=IfCkr_Q@$Jc{;N5DU!jwaRAjq-LF1OWiy)QrM|MT}0*j7=b2Bq+g+A|$Ip zUJa3?V=vfzY>JP$5!^-qfZQ0zMHor-Skq4c4uCn#=LT}#h$9_(>Q-)$+XDc^!*g7IkoWVm<3afZ{feNxI{%=Y z2kw9lhzEKfHaS0t(EuoC20{jXP^lqjx?0hQQAi-82n=dNKpGy7#`+^)YU><`_HLKr zbvJO4I_K#4zwycP9`rmpdMf`u|E%c!f%fyPgnKi2X6H|--gIy*_Pr*lB7w2|sP|JE zi3R`}7c4WdL1t^I!R&^sf^ zqUDK$0Vd;GjKN<`l6mC({#eGe#x@g zOFckF_YAG{Q+|YtajMjX8-UFBQ+|rbW9~{PAEC11d*$Y_pQZCM@@%IY!$Co)4}xJ} zARFq~_s(&C@V(J+d6YKr4}x6{DY!15i&70EU~h=xWOhPIj=wA2rT=r{yWYJ73dO5X zvZ@!eQu;9)2*>NkF4TpVuPyKF5DmaR!{;*Rgd?(w7E1l&!~Vz(Hs*fw2v7fvh{@I*}WB+}2@ zqY{_YlJbO?Hw`&( zgZ*>+D`=l$LMqEIJ(0V_DM(gFx5L?R;4sQNo4w|Fyvg#)EMdE6&sw7C;0d0&nY_h) zgpc31+C>D+fwq^{Zp#rrAQiD3N29WvRSSGEG6^>bLSr?66Nbv)p_5KyqfyIAxfdii z+QS4le`*`MVy?GdaK5qq(pQp+5FB~9fRU{5Qffag%r>&Yl-P365OrML=m@wDqGBRD z7dlsbGd~+VT`DS6^L^hjb$-}ixj#)n=dB7Nyv3bP#S?_=J6)`g{i9r@tlGql9JDYA zb43G2Da6)a^=_1_TuPF>>he-w-S`Kdwqvn0l}YyIpgQ%?sm403zq~fZw${ER0;$J8 z;_^-jwMO=mjfX~PFhP@S^E#QXBls&fIjY06{xtJ{PrM7eEE&tt4bMJp=EBse$*->f z4o?;0maZb%VYTBov{+)z4DRd&bN_wyjEzBCTkJFV z8b<EgUXvw&c@aMF~1*_jn~Im%iTlK z5~js*HC3N)@)TZoV}zEf=EMAsU+8H$Kdo_c%Py&2F97$QC;AuJ1d)!H+sGzR&s-n~ z2Z^oIy>L9Cozm6HHA11{vxP$|j6O#?!c;OYFN5GZRn_=)RwuRd<^P)n;w6uT=X)}l zeF|l<(ctHXHwwNV)#s*JQO^**=tQ}qwvO7@9c9u$Q>kHx7R(A1xNbJ|m7=!I19so- z`v4%E_}L|IsNiZY0N{6x@A@|qXKrSqwuXLPgq$;^ z(A1C7{o7k8>O7o^T$EUFVA3^9b6-`^gW;da*`*>Xn&S=~iFLkbj=7<%(9BUb>_%04 zgDuTRTx#}t(P5$M&7DUoswTz6DU{;Hah1?9sd0Wb)|WoHHL(7((SBoFe1S)k=%N~W zkGAm`^$|s!&m$&8)6zjVsnMT36`t-c8p6nciixOfX*NOWSV?7fmJq|$p5LoBJU3)X zeMQ%Dxrh$q6%xlX%RQ)9aEsjBymfbF8MMv=Sb(QS&2s_lu~W_;ole$_=inANK*;KM9O zSa<&Em&cOQ%Jf>*g9-Hy3{U=F#KJf#j5x5p00|0n+9$oRpZ(k}!}k)%J;aw~PFKgG zM&j#IJPV`$U^pixA~_s z4)(AZEU|DYpDOq>%P2R$SZ|MKj||gGmyE`lSP@v($N#iGU&@F!Wwh{WBh=M2j2Oqci~Lf4^Hi{K6CFD*yA!n1%o7Mu|9GiyTJ@hC8KmY&`5CZ@J07L^vA^-q?Wm%TnFH=9vB}z6KD6_dV zG>Y5}DB$0lq9wO6mX#M(>%8t7@-N%(zwr0~fXo2ZkO15Q7$sZzp9hi@NC+9<0PBPT z2qDSITBRv>v{F4N_imRjwQX+PUYE|jWy@|hYp>>Td-1KS+-u=EZZKh&uv8rqe_s~X z5)4ncEfSKH;0i9j0eliLBn%J$KmY(}MBtzg414e1z1{ZR+GlP(Y$UoJsjhA9Z@QgG zw4yDenaENvp&`or0E8qz$owg^p`8Fzg-|GhvaB$y2&||ps0{HSqw%X3kaXtsiA1`U z>kWQxx8cGXvEb@XroZ&!7j|p6rloC@7AoVdwAx*(+JY4;>sk@1+gY(HT4YM~>5U!R zZva&{d#2cUso52H(%-wszfdc;t5&i=xzwy$Yf8!${A^csp|z!}AaF_=Y0S%(xK!lz z;HZrgs?}3TiJ46)Euxu2T-$QNFimQ)(YlzK*2-U5w|}RQ8!ppXc8?gdw69#dS+#lj zCe?n}*0w0ES|#OF$)DZXXX$7+s>BQBYOIUtRj5?@z6vdt^>unw5xrH(K_ILzN?}`5 z+FWAsd@wa|hJ7)|U70?Yi&!u;Zd$(ud`*IfyGSkHAoVW!y>{0E6-@fx%H&R>pHxL^ zST;-euI~$*eF>rtY319#ap}|W)opuV?>=Q{Q?;vBjx4@0RzcfcSNB~}|BU$c;Upa| zGMkxXhK7k{d$6SsV~@r^HLZd&Slne_X}7&qcERHorRcsymYQts#k_A+09*Mf*A2^2WTEyh#gl5&ymLf7d4BH(TpRf6GkL+ z{k5c2)@|t%+_{%}PkNcw2JGX+zQV3I*dhV~Pra zW-~Ue4*=qunP3shZzJ?lrYN8j2pKnx3Aor*Lt) zSOEvB`v&lZzY}LvJ@Rm;umw5yo)VK`$5=+R~Duvrl2Yn{v-VFDzI%&J2jU<(t6p zB{bM_;@weLxW96J9;=xB5}a{jNlLQO+lN;6np?QTgdYIc)^(Pw>i`CDAY~sIR6_tW zU@!TC6-Vp<82WAJAv#KF2P2kZA-DpPTh~Di>Xg;4y^>^K0gv;B0`S^E=Pn9|Ux8Pj*CJL0hhz)}u zW+`}jCI81St7(v>dEHZk0%NdLMU|mH%;y+oyCN8!dLy1=iH6iQ*Ba~VjyHp|Zu1%J zr7&}eT?C{TzyE>BZ8S7_a*lQ4a6TTgu++)0g}?UT43zE5U37wq>i%Mbey6CzU|+%` zX=G(Frd*>lU%YPzb6bq9DV}#cWZfeCM{!O?&g5Ne7Lgk{^}bNGiPAgb%+v^!N45V& zEa6(4Xf3UXYvrTiI6){xu|(&BHj zWVS(={^(;e+8)CEdg2E8DD_ZY^QhRJkfDSdA-DT5WF-26MADf;*!*SJ5^3cbrBTb1 z$aoK8=iS71kD2xD%tKC?Pml=ZLwZl1UIw6bbw3BSu+I$N&5IAnHwh2uTXfn9SGnU_ zME>Eqmh)n|jTMLJX zY&?%xrukJhJXRhQX?o}EAXaL<{U{sifl@lmyTXU=q1O_Rd6|LNK63Nn>aLF*ej|=w zeblS+`mc4Q-c2UG;zkC$7LMDu9)$?&kvX|Q>p6BO$ zTgY|CH|RSGkv=JvU4)9V6pwlmy8JbFgtB$LGYS5~Uk>)&zeRt;!!oV)H*fHo?#PO! z2mRNQvq(6OeF-7&{-u{-CPy=q0)K*O_|~%SWr~DRtE%nzUp|H81HDqqDhgF7$%(JI z#wKx z2@jhg%~_Ga=aqwXWf6<$nf_wumSl>29h5C*61xx#;Tipr+s~&a*}-*D+~xK_vLAz! zo^WwPkoK<fLP4_dDY|j8Zr_@SIJz}Y5vfcWFVa)!7%{qI0U0>fO~bg&xR$i z2%O}Sep{<`&ip_(1USKT<^?tH8E?+@6^|-F@>Rxn2^PEuFw$2%D{tU831p1{`V9O- zZ$K&lsV)rCI;TLd2j$!bqeuw83sD~kgYh~UVIIutGi!Bw3<0SCQu8pc7Iy$< z5{=g`;a7K#HS}hh;R7H#7+Er$12g+7AE7f|<^mclb%@Fn&St3oEDS<-XBMwBGi{DL zNqF?6 z>C>dTvUg(pHinM;TKvdfYc~;drq{Z{;soO!{v9bwh<-|v9+aVXNUBJG&?WbwZ~e&h zQD%aU11xk*kfH(Uncz&}iLfH!N_#osYINy|;Ie)DGFxQQ=}(jqCvgz^N=%__%QRDp zSI;d?iP8y^Y7q=gf$IqbBWZ~AY+3NUAjj1l+gR{h-Id2zg%$pOh{M3AXNrOzfME#F z+z3EkJz;)4Ey5aN)$O9-*2GZ6T&YZJKW;-HArS(|}u; z4uQ637q*7lkNYohypEaF2K+pps<|Oe8);k=bQ6xA`h-*J4RE-3x2-bXTQ0ye@R4M_veo&-ER>T=e&fxjs zeR`ZvEQj#!Xh~8%-~u45WO56uBP0(K&_&^W8PN2>6+eSH0wj}31|hdKnIL()8Kgxf z5S$IDoEh@G&+1r!j?O(q`osttq440y=(tEp6AY`3Ff@glFcQY{FapgKuqZDAO+C(z zRHJJ=3gMJ(Xah|E=4pA*#6duy<3w@t1~(acKt0Z&X#jPE1;7<*o4q%7H{!wLYeP;8 zn61e#4b`{O=Gz&iC}Wf+yD|h{3{z@-wA z2xtqFc0fuYJ%XbxLR~QKTsU$wBofF4hs0EmV-r&k+pj{!`=73$JHwfy?~^_6>VaJJ z647H6+MA|+;|?f{g>YGeXj0_QQG^eeI8m4#oB`T&HbeVAVU{ob_JPqDLCNC58}upe~QjQT?h4+uVUT=(j0x zl2L9jN8R2F;2Z9ymc`PwQWr~CFJfcWvc+o9yamh~<>2G2e5>jw%p)y@k9oE$iT?k2 zjy?eBWTD>@Z#ogw)d)rk@g$AnB3C3CMrX_J$Mpjj8>FS%dJNg|v9o|qjW)|97htqT zX~rtK8Sq-i7wq9dgc8@BW0cWM59su8|+qx^Ke#c!9vfXj)Evk0&_*AP^7(0000qb2lRZ z01st;mG?`(+9$G!B%DIV5rm|u2zOeJR+a%Ml4zRkTI{V```feXP=4CK|Dxjn03!of zGys5lU^B=O|I#50AOM8nvoJbR11^CBY^9o{ymc>4s+87iZ|)kl)w161)mPQo-uGUc zb8UQlb0lkPQ;i8{q?_^LV<)4w1scAO0XW$PA|V12g7Hhn4*(DV02&bkC^&=Od-v|{ zy|?XFcT&@m&=x@VtlebAnG5iUB0>t|{6hR9!&;!i6t4&~#F$GKO+ki00QeCCMZ%%* z0|AQs2mk}9ez!DRiFBal2YNKhV~T3l-qWFYXjfrEn${>jQ~5E`l$RSC#At1@x;{== z4UVg)G)N~@!F~42pQ@*6(z+_{w?5JFuXa2|t+l2Jl++}VB&GdDMcmKtXh?5O_oXB- z^$?xXgO1YacDza6qNTLfmj1R147vT{D5gT8)O&I?ZML`4P%w|z#UGu2ju2gxC|dL>M;DH8wdnbvoJ36PW253GQCp>H z%TXn-(R$$4SOjo;40k4z@Jq$(K-$0m>b407>T62T57f8!ZPs+;?=(AXz2c(Qp#T3} z|62T1>+<7S8@ktR?x-8qiNv0kR@T)kE=|R!PUF6>ux*EbB=(Ui4F;lA_Kn-U*xht* ztEa2!ZZ=GAO|9E?ENXAn)vcY`G;9=lkxa~7>eVIdM?o93R4&rzrM^W$J=zhd?!2gO{kkxn-7<|+B5xETjDJzQ>Xm9?8h#rv)!rruAHv1 zI$Cc}?yT!u>}@w&5cJCJ)wmoka)sRCEl`S#2kHGkri;{uQ1UQADO!s>6RFgJCHsvf z{EZyZ?ibYOKUWVEJM^t0)o=RY4vAVwpVGedY^6sOSMCd!_xdHGvudoVe}`9d^8tP& zIvcwxchVcn*GJ8jl33O6efTU_j)Yk(L0t1ep8PTsdpv1qHAO*ucR!LbBCTmm?zJds z;Z@pY+Twnen3xZg*y75+TZ)iM0N+!LOx3IM0;^s$sCk^?t7}@-HA1=bh{ zx8>Cc^075?oV!Fe$(bxbN;!qs#m(pihG9i=HbeO)5L)=M0_HAon-Mo{`&uG?flkl^ zu+^uqid|cgmSVpjt}S<3{3MkynS>IXbb=WV+UDmF775cp^Qd(ZG5meHc|m~*KXKBa zLh6YNf>+_UBhe%gO1>ULAPvP}Wq^uGO7V5cLn>QidmiPnp~%FepLhcC*q;z7+p`)@ z4&5qry2~Gmp~*uW4if(H!rLVWf*}$CAEw!0WYH8we{Mcx){FoJ=Hqo4Mh(seoK$I5 zm{IdR!mg5ew>mtGC4}mwpyFxV88r<(qP+WqZ=B`~Qvmgg8Jfi6GaDZOwt&wSOkpSQ z8I%i;4({`m!L(=408GW~8PE$t5Tp5lJW?oRop5JfJW;Xw{d=A{qXmF;e4Ih|KrXq2 zZ=B?D#!y0aikzYFV9W9C5A??wUI57CCXAwmAJ2OqEtn)*afI z^_OPN)pV1cEC7_ctQpb>JNEAkEY+W~lfVRMrDWXW?AEt1#Qr@NuTBO4+V$*_F+17s zfZX(UC;@*!og|oaom6MyEguOpzbpWw;sQdV{b7}J#!$j_ zlAXcT05HVbd&;ZyH2yE2hU4z|>_pJfrnSaD~xKSlbF z+|<`=uB$d645oe%Y@dpWq`7Hyz*R%R$^#`(B{5dmOW7FT6vH!VkrSsw`#6n?u&lEU z8p28&i>!0^$$4(ukH7l3(1~_htQb82RF|xR$NQ&!&NNmrvbi1%=9BTJbnTqKM3Cwz z#A=HM`~4Cni=P~poHOf^L1v%nJG~=$OdoIFaG|x@Yxj{hI95Ge9yWSdEH_ynlB*Y! z$DQN+uA$~Dh*G$WWR=%VI>{%&S<2oYOdVfcY!Vo`SwZSwmB?G}GK~~%vHyWzRrs>^ zM)>d=W_+Hu@qCw{*!<&Y#{I|su3r!ju*5>|xx8BvZ2_m=LyYq6DWY%`7o2UUPn)?Z zu7yV-UJ`{y<(irVE8aZmqlsQ5TQZ$VTit^IKJk2Sw&~P*2NbqiSYDWRWZrOIb~>Zy zslq*ox#Ay{%C5B;EGa4Dtjt>LPJm;Dna8oVg6vmz%#>eap)Q%!Hz5X<6)3k-_!+t( zY&wm7<|(%iDB8@DGk3K5?~1)6n{Ex(Y)>+!YG|bRTKjcFsHxQ+0Sj8E)Y1o}qUHCH z8;!rtfdua5UKe?(yj4V`%4wWWS^zbO|DJjD4~-LD44J_hZ1HljA2lGd!KwKqukzxT zky6|8su;fR7O~6xzMzzMliK@VmE%CS+hNlfd)6vvi}Nga1Cdo}aw8N>0=%<)w{c}y zpk5blUknY@qKuT_xMV}oQxrMGP`;Wa$JBR%8N!Bk5N&YX``&E zg1=<_Ks6kw`wVaBHRQE-WK_Wbu;}hEyI-LBKiO;p>~KZTINiv{EMqbAK9@ z#2{1oy|%ZDGDLV%14d>0GNi9w0;5JmF*nYkGQN8`KZq#=I%iPQgHiFLdcN@NYx*A6 zQtvqqg{Gvi1*|{1(F<&QNLo6OIt=8jXQk7`vFEWy^thri7FTh;<0|Gog^{w#S+|yh z|Gvx_t78g+hqOery?8U>Y}O}n;^zKC&tl&80Y71j?fP^da3szD(fY_i&r=5VT&g&r zBAT->xjX+O)@r^XDMbRjO^mj91p0BB`m87S7>5x69tc%rWc@EeE3RBj1xR_1qn`xN z^{M!8Zps&ZT52n?AU}n#K=L|redB+=?4)b;|`cZ*^ExQi8x9}ewg*XeODO7_Z4|g8MyA+ zjJ?;2l9>oQ<>p>8%v*bE?wrYxA;7A9isR^Kk*)4~iFJb(#{*xPcmCY8(|2BT zX~!1TyICBU)0Ogl7b2(t^iCHxP`%t9q7K}Jk>~U^uS8Q>%p(5n2+X%DZ_Nq+Td9jm z=Y;KEv-~{U763H{$&JHwbqRGbXIOMd&@!W7LJF$1RsUJdLeUN@&hvp87nx-_Gk%vw zU&A6!bi(&LFx3)YMJw!NZ1y8POGd?WkerQPa@;@UVv!>e*8)*JMGFUGdKIOpOwOA<#gVY#XxLU|rC#03j@@o-ygM#BecLCOT&DCbRMy(UN9^G6Mo(@jr>e?Vh6x_ErZD+JJI9+B4`1nTrT1K!~eqP;@m6p$6UZ&qf*oZe(C%>cKX$ zsAdT$?YI6wpNvm%tmgr7ax~CL2#yV9q#1|_)8#?FW4<%h9X+HjSa-nbx0uFQ&XNIS zy`91Ha3naL;hX?E8P334NF`YX>pfBy?t=+nH~0jjsDU>Aw-!Pc5VHY7tW^V-WYD^2 z+ur29GYbI77=Wd%1yK%U9pKa@jpQ*+sT&@Arl;3dp7b9ZW+`>j0VA^wCE&P^b9tqklS& zHCsysP12z$SxM4=Y#s3#DvO_FZ@+;$jLy(nv~;Z zxVxzpStV*5JXhWn_gMmkc#0KRj%7i@kbrWdbu~u}Q-CLtsF7L;*fBgcQUpfB)5p%Y zNP=Av^8_7RYV0&fB+K)TiwrP&y+Wot3ga0YHdw|M@$apu9wLV=odN3^(n!L^X47j} z0bqJV=4Ji`PG!*70Yi$CCY4}%Aw<={IPqbQ7(&hsOOl4z>nW_ClyitqwPXyS+afv9 z=ftwe$bQhv#Pl>-R+KY&u;!z932iBG&NsJObQ7i1!dA+FyQ@}6D>D>I>i3F7E~LpC zS$IYmkr*(El8rKANCPZ4qS=0{l~YWxtRr8eFgY1RER7PedgHh?1hV-lW@RInB~w!Y z*WJy9>(3mwgvY6tk34bkr+!}WjnPxJ&eDX^BMSbj;c^{1->LK3#e;puHC^IKYyD5k z|I=PW34eQu@@1*MeMvplsb=GkK}yKX%mPb7It&0~mq{(;P(yxG>=;So6sn^>_fqrf zlpa4yHFL9*W3|9{TOA+8~OP~Cbh}$06qWP0L{3~Rd*+CCsWh1dF0*FtlW-x($Ke>Ow!Tm zy4!y|vH>fJn^WkT69rpUMJTJ;<#YKQc`0+2!gDeULBr|E>Z6a!${1v4kFC5+I^m^E zWmmp4ggMfk%bUAMf?%+kT&ID&N=g`GHVeD#YZYLL)7=oxjh(cqmrL-`w{X2?mKcCz zkf4UEj(ibx{|~qDXl!~U7hs!Y;KpJ1;-&~k1RoNM13|c4l2p3umE} z=oqj^UqE9%Pixd11*CQwlgIQ3O;iXxKME^i)^3&{Ep?r+wXzX;bOaUR3JZUIGlMrS z3)a}Ec(X}J?)8M7c-u{|G8#ZiId#||PoXqY5P*OO&N9W9*0(TmR%y$t?+s{UFpdf8 zhF}B99y#pY!$EfaxFCsvIK%;Tf&r`tv?60hZy;mgIfUf*_8pM-0Ec&HP_akN4QRTM z4r@Tt@AuH<^x1NUmqVA)G)9Du&pAd5HGdf=RUSxmGkW@r>;jIQ3W13cd>l2w!C@Q&buZM&pcFRMaw>9s7#- z+#-ZuxY6(Q#yJLV_Bw;h@zho>p3Yz~+lIKAw*#YaUi6GY8mTW~aL}W>S+tog%Z)X` z1BvadEmL?~Z5qA62(N5X1q|LGuO|z;bo(SO2Qa2=_}n*YIh^OG!4R0<_XX6`7LhKplPCRrgPXlP22V+PgG1SagYPSr*zH+%w~&1u@wA>!M{Mu6 zQ+V%oHy`zD$%F+MDgxZamy^wMi)6J`B^}Z$Sg6^PsNO5;vq!gS;4ouM5y8VrD zo*K_i8I@5x>^x!$Y>X>GR!mi)1E>OkVbGDN5BPx68?r+DTJ?=N35Z%J*Na5-tl1(y z9Snd*YP^_IrY{6An3GPYdVD~uSgo;p+p?X?fq>KR>>BQ_y(x+zLiS?E^}z%5Rk$E z9Tev1fJBGht4WnL6xoZ3wBg*9wv{R;`n!yR(nR#o1%wa`pWgvq2jv?9Ee-sibBMIV z0ehag<`N&J#m@`sYc=k{ql!&hR;%$0<9Ks4rf;go`9*XOo$0*(`1b`4HNAP1v6RCb z-7<$Zgj$10r(|@PKQFkT@WC?kx6FP<5LamW!_X3d7v9?8i$&Tw5y+y&ph%Om@1@$@ z#OHCt%t;seW@g?({+a&d+Gr+bW{^BLt$j8JkhaM==%9X11T^!!*sqejlRA0cGN(;x zVvM%{-h*DQF>2xWDRi3QU+#0;svLIsoUUW-d$mdJNI&z0^Zw zwe<#c*5?Isd!XKvlj(iribH&W-lQD`TxtzQHl{baqj67fqckb~5|#L?hMx$%8Zh#r z31A5Q{`8LSK$RULL!bv64qa{em9U14kQ&ob0=8yXD?L92k`yPRM00acKr~XQaw+QW2K>j4I}bAE(gF=lZB@ zQUi+1JkPE2Ug`Uux@oCGy)UYy))=UUx9MzHph{F{CzuTaYC${4DTtoJ2~q>m2?0@U zNTuN7-_{RF4yDO{5N*)m9+xjH|Nr@C7Hau$HfmDYVL24fS@Y&N@$g>n=0#${>+S3M z(RY4i{Zsn%aYudgb>^Lov@E)C)cPpA3kA#%-Fcebf(SP7_BlVP4gNI@O)teE&jR#h zTG185+DJd)9vOnw!e6^8pe8-YYbGNoRZKn_YyTErP+E`!MKB$){_<*+jdHF3c4sU7 zS{o>u%K_Iu=Yafn>H^U9xH6zw1?eS_0%Q7h@A%$n%D8G27B_ANhDN~M3xZu-1MoKb zNd(b`Z%mk!a|mJ&*7RV%k!dss{W8c0k0^_4y;5Nb^XW$*nL;H_0}%-cq7D{T#9YQT_Mg1A_U;z+PlT2-S4+l_J#Z_CHPDV6%) z{@dC|i1}t$uAtd)W6zW$*#FO$w_Of-`=-U88`(mKoA&9V8n-6aEhp}DmK|t`?zs)} zl{K~zt@h7Otr+!Y`rxjBni0}Uu9c~twqOlD`!`aD`l~J5GVtq`zIX^!KLC*#;K$Q3l z5Hp71A4XgRB0LVp4AC)Rd)1agbF%SL*n)k%ok?K-K}U>>AXrk}#SI{TanBB1RjqHm zHw>YE4@F*d@J%*3`8*%n_uVppSiSYATSP?63O6xk2>QTPqm&H^`G);2h2K&;YnArPFRo^EaWu|cx^Z4nxVJ%))TOOJ z@u4!PHoBh7Kx3)fC#DP#z+|$0Z0t+u3_9z$cE;(OY(z1sB%%ce=;<|a>BW`m-`Eq|jTqZYWux82P) zMb_NBr`->)z^rb6r)|}2by%K-JzU_a%C;gMj6lOtG-#wc>axERZt{2$6etnCw_NAj zEZh@BGw!!m6-`ZZ>Y{avMFJiNBHnJsnK(5)K*N<=%wDl)4Le~$HB<3|hkn20KUvJ} z8aOAa6~c4iYZQ550gfL-8E6=RFl{?*ZAa{=fEydZM|*$cADFA?t26%~HE$~S=Wz+9{H%hoRX2D z<(~IEnsxoEl4^EA9|IX3$?=;le_DnrHshAWTjC!i$j@+hEsxs>(2PB}cd_sI=1mYo z@ADqhU6eC)^xw~C#v34Ieq*7AYmS`bZv8?q80f9l8cLJ~bSjwUaKd9+WQF%o>lNLi zV`sSVDkONw7Cs>r!&Xi3amdnvG*WA|D@>FEt(v{k>8$g*G)*~^p&3C-w#&U5CPT+d z<>^k^SUoUyTxzjboe;aZi7{&b!DnOFr*zaAF{?Uw$aClppmQbNJ0RPE&*dO`p&D(Y zh?+|WVs=o4)_u{6fB?DIqDtEVxQ2i2fap3blQDg(6zY68 zbh{o9fMDO)pr+wGY~FxK2KZ^15LF*g>5w41lCbgL-6kFp8YJj;-NEx&zd$zly;NAB z3grhx0fB7Fh)6>bF1z$PE`UG{+u%s+AOpM0jY`@89!&XJ*FID$P&c!M`E8&dXP-cd z1VSzceq0E!9X%J}_31$58kD7h!EYxJQ--U^{Rv{jm8L-=HzM7UaPjO035Wv%>X#y` zkOD>Ss6heIX)uX~+Q}000kFX)09rzHscgarxs00@N7$ks~+cOk>#rlPIx?xi7%mEGnpySf{; z);4akuUN~y_O{Pe)sBU)cqz5gW#PrQzgj}V3s0V9u_c5!aFR(ffr3DMz<~}+i1+|N z003x2;J^?RJnGr&_HJm8tjE)(R$g>ri^P znu&eeYPfCpDoU8LPM4P)22FS{X5h9&-GY-|O~xS!*88aU=i0P|{nFdQoW)wQDZQJc zyuElkwpPckR@677TY>)Y#}!W`k}$X%i}>qo_t{r$U=2ObGh+Q5i*@k|si~{gcF^|K zvi0K!*}hCwx)7Vnx@qC(mdpAr>8Sc8HPP#TLwrk9QG`sTC%-W4|;uzUzHfb%#72)3AWEefaFVne5Z9(DaaY zJHNWx1^bMaL6?fIpCawIKK`C^%A?(0*sQTLT3rFpT}usQS!}=rX=V`JmE@|Ydb82J z&7!jdu8-602;E}NwAGZ42wYQjgKTDU{$0p?)N6NAl;3gW^UGznIHKSMk^pNLC*8txh=aCF>>qER;zqI)a{Lci>2T7lZBaXXsdj= zU|hkr)utTU8O*1ey*@*h3iBMch>##>o|KSa@XHyu#M8ZB?Q;m&s}GV|7D*B*4u)@{nwV z(&lC_hoWkgpxtbd7BM%!EpB+K9`Ak2R}*EpIYo6dnJ-!|8@rW;Y}2f8y4=S%#oIHT zhxyU+nKl4j5@$Sc5w>jmvPwZTGk3UAc}He`ErU|^dbO}Wm#bDlWm;)dR|E3ASXY!s zVy~nvxb5HWI!UIrkCHh*M*gvAz64F~S-0^n)$EIDgOTx4{f_{rS7A&YcPu*QSs~WGk;;QoPHG#M|VlI*Fe8P^`^vuCyW`&0upz@;T}$ zd2^n+?afcA{HlXQy5Sl*9HTtAmhT9{ZxN=E7Wxr?5qOEON`;iN5}f1JgURE3{8$E| zS>IQzU+!s3&snQzQbNXIApV9vL!QZF(=UsxbX+Hg4o~eOMtqJPrnV6`>I_5j6rDyT z`+QB)aS39F3fjI1A}Uh!vC2@{uE$G!VhAc=1Y~>7Rv^`>umbc5(-tn51|SQ7EwlvE zkN|Y_(Hjr|f+X{}ACdC#4ROaJJn2LLurIwQK$rjy85m+nNC5L}t8Ta*+90{5Ab5rc z$Ppl@hYIz8R*>2a)s~u$ozEvP4daNZy(pSr+eb0dA`}2SN&-m;&qlj?)V=*YKN9AC zR{}X{PKxbyr@et6enSA9eAXH}LnqPb`|_5n#Y(Y!+gO2jYd8EU*(ADOsR`xfB{rJW zV-2_rm48j6cJdt(Lw3|}RWF3S&T10T&LO9Mt1IWUF90t}EX>r07x98jA9bP;p@X63 zRIK1AecX?9<7M|4{RX1{#zguc%T#?wCG5|VBLADh$_^t#_ZLSI;yk=_bx^1Ki_OVm z51lDIZnn`~!K=LV4wz~>HSc(0^rY1W*N;XeH*Zhz2SHa70s$Xd&T+^7m7gm>^iz}k zsvmVwXw8i&f`VRa2h~5l4 zGM|dBQ6~8rDksgdFNCkxw@rJc+O<4`k@@HS_*SxKOA6jL-OrnCC^9I?t5{yKZWG0_bVUeP zD3EQJp5){xoM!v;61fpd!w1twMJ$K@R38lSG2d&B$iqqm$-v@_r#E?{rgg`ud=WKd z#gAiL;%i?Y2Ur9VX2@~!hdHVVdZ2l`kF!;8u{P7x`j6&gOw)WiD~5%aYtt^5#>K2n z^rnnXn{j~Su8t=OF4%P1yKx}n0_Tx8g4r=}>q0Md(?MU(rRZv#6?|_@?0OCn_ z_y~mC00ETLlbG@YRaoMU?cXX5HEo4@cGLt213=Ih6;zFo!B0JDn&&lG9X3k9W1CZ7 zvnUuRpYq4@@*zbgaMDGcXvE{(P}|}aMlo(>>c@x}lD1q>?1xx`K}KEYYLOmptm*ft z?3hxka;bw|Ak{9QacFEFn_?+@F7(+F&?1kZkGP9syA}&FT>%#?!TaJxDI8&PIR3HB z?Qy#b>eIl8$lM2rV+n2%8y?L)rHsQ=Ok% z+InYS>;t95kmPpp!bkPU(G1d}_Ys%`gXVW!8>d3cdKG~1DwoC1Mr%tJfqEu0Egvg( zN_g?};31Dc&mBIXjYFc;kSyHiTmI^?Jr!|bi#cf2gi0l1E(7>OvnO^kLRf=*PnZ;M z-M|A3(w_WNrO6iqA;U-{lQ3HJVhwK(VHD|yv`X#Nzc3;aP-^*LwaSK3lnVU~$?X#K zv1EPpcmX9}iEv1NI2bd!6#yp!tGFXYqW;c$c?{5x0euF2r~i&~%{Y}^CBTzM z6esl|y=U@|CCCK=pDb9h1%;$t<^>!87}TUr=mn7#C0(%vXaR*J%GnTWLl=6+g@_o` zR4}*@GlnV)f0&z*G^#ToVF#!JGpHV5;;Dt)BKWp=a|QUI3YmcF-ahOkW;Js_UL+3NoHE~ zF;qV3*bV6dq3swzggqOpY5Uuom$D8;v5Ux=Vw4rBm^%0UXM9>!GWVf7 z63|KNo-)jLOTx=gqk%5zx3B57T0H%oG6X4O!S7dAOMV13wE zRQc47HAG8FerAT7Q4e}6@a85wFGnHY=P3|n{IDq2v*;&txf+}LpnU;}3`Gf3mOS`d zCuL3(>sod+Y};y!VoCKdLa!g)j~Okbxqle95j`kK;zlCepgrrgb?q_6yMQ>I4rgLt)*H_|BSMjspjL@ss2=L4}3|Hke(;)tMxjf)Y93dAGX zIcBg@qQd}-i2fk{TLkjqs1bksk8FhZW1>i7fpH=%o}7o28YHL(mQo4qJ}NpopF<4* znxI2!3#AbX$V~{32ul;EBPtrYlm}3S{oiYgJ5-@$@GGUmKI}!s>f8h%1^^<^fJhby z_&ra~xE%y0d|b!V4sjg!|BQ5>E8urL0B|Mecq&Nm_3re2W(YQNpgj-}0ssI2L<2@L z000kVfz;DKVCh|MTM6N|n;~vlstrNyS=)10fDF|LuIjvM?#`BNdqV&I5RL!KMt9(5iW2BC{y1Rjwy^tnjuadED#m1gM7IP+|rlExKF( zj7Hy?pI;LivX~6k5D7%HZyJe_)sjf+kwx4MQdGnv#1odnl}=))l%B`^veT-!ZyM$^ zVqmt<=WXdcOIuI}?1d1Rm1uA;+CBn#FBI7)Tp?gaA)mY>iN0kX-(Qn9G$z7S zG)}+Y8uW%4!NhRHZsu<~|AIU4UG+nQ>e#N=+n8>1=-jC@6bMhklXi1h(a+KxFg?`82`%vyQxmY*8h=FJ9b9Qe%-xeFE$8(4Y65oT8aL^Zyh*va`p7X&f_~#C(j;RFqq!+0 zQcx~a#(21&(^Q^GmV3eHKb=w{rjN74!zYDNP4BLnf34Z94x2hDx}hZo4?d9S1fYUF zy=%#$89nNn(Fc;0VrBEjl=x^h)4YjE+C>3&FVCmYLBVL6*8@?ll+!6+=FkCz zH;v&F0-}Xkq^gI)+ zZ9S{Mt7O7f3LT;tCjPI6#%;W$n=F6tv+tIE$`|-{@C_gE&v+;t_np}daUR_-z`C_1 zFvTw(frD}{72+orK!mq2<}UcM^wkT@Xd*C@$#dOG2&5vl-Ikqlahd0PoHGxwH;!1 zyWEZWg?2CVY>>axZ^J0#g{yZdRr&-GCyjVG2_Mf-;QnuXjBCi$A^tT*s zOA#p26W&PBQ~K{Yr^~GIMb+Rvmlq&un5QCi&Ql#AO0)-hHX7ag-^VUyx~@AV7yu~| z6WK)I4?4vc+EUkKQy3t+RSe2mMtEsFAX5JQ$|7zv3g>eKIja)kp7c}1V_c}vb^Qap ze9Qy?{=hZ>zy9&(qN)KV3&5$%z%(d8)68IS5EpC)FkTD?m38&@mdG!ja!A0Nw+IRm z#%$4ZTRM5HY=f&av5J@DcZXHB@~?64pyH~O^Kg3M`Z?CE&^S&O>Yigo9EfqqDUuM> zY=$Xc8`0_i5YUz0haRVQDA=9CplkN33q5XHthX7qMz1DGkjp*ykvLF1G!{2H< zgRufE#61R6p+GXdGWvq!&H((SW3ZvF*DuW^xj#dy>?cJ4in{vA=7oRUz!j4Gk(*}# z0awsXL&xcQ`wu^51fM*9L)wZ_Jl*FXr)UB=)IFSHLGfemMoIu93lW{6j9f?n1u~ay zSYx>fNh!u1YSO((uU_VAIRI|~z5AxbI{+LSw`Py=#e?rD1`y$F>?y7uM#%#j`TrXE z?E*(bl2kwcnnf3Xu-lxc_W~Sgkf&Hrg!GkRK##0(Qqkh+I@S!Zjuo|}&v8XT4lE%! z*bJ7x*B9%-VUpm_laBrlWZR=5^T|EgIk}PBjh_zoEO1?QV3z}<0JMP7i2HE7K-zLg z01N=aoXr3x?SW9H6u`0(z*qqoci+GuCmd7Z{by_CE0waxNz#C;LVT_m>b5T6_8WQ= zo+V{Kj|Qx4QtqwO)J0+u=9eSuCHuhGt}si5+a*qgGNh1t7`ptWEx!QpVIJftbqaJK zBhmmY)R7l}xb5rztoGx3F>v-)J=Xl{Jl=ev04* zzGk0t$RUlg{xh!lCYEpjI}E0Y5deHwtd4G;pKK6FDu(u)rcbL3*C=0kK_50fu)~N0 zBX!|9ubBMV+I<(P{A2_WrAx^+Vfg(=`y}EgLx`9xAS3jz$;y16B>k&9D}X#sdJ3vaNGvlIp(}W^>hQ zJ75F=sCxs}jIXTrj)%}wD=|@LV;rsdsaeWOzL3T5Ag`p03IwaR=Mhft znpLcHjHKV-?!*iV)9~M(;hEl?ni0af*5VgW!IyYdXRRsO0N-BOvHI{%toUw&&0pkd4 zHtP#uc@oDDi8~J>SM?)m&FkJrUlVHd0?b7s_J+Dv8mncI&hw@^DB4 zuK-}(2rzvQ&vkxH0c;}3>Q(DxDIpv2DAjlWXR-f?54p&Lt8ASV`0w{D0!z`g2rvfd z_sSR&JOohRof*~wkZ-FPOx8mJ&mv`)CDGVsT80`>dHB_Herq7eHeeR$AIP3V4gYuB zu$1W0#$0L**CZyuy_IE(W-oxAFX>0Qe%!poAVS^rAJKy6Dq zg1%5wpFT0N$P;{anlf~;S|MT9000mW0{{R3Gjm5H000kVewFu2zuG6VCm)Hwo_?ii`lZfyD6^@g>15WeY+gl*!1Wr8ln_zpy)O|zR9(jDte+X zdLSVQ0??42o|c4?{J#020KxzOBti#9Pyqjb?!LSGdwXts-tBF-v0aN@+ih)o(zcm? z+z7MG1_hMAKt+K-fMEroATNdZf(d-LvLh>ls0>z%V<0o0W;~e#FyckV0A>h7GC#>A z>C)9fFfa6_zjc$a4=>{l)hw> z7~Q1^k}6F?*~+#rIqY^>ljLtu|xhOUU@rXQBGyfbYE7P3{(Ww)EI}Eur<|Im?}8b=8gr#ak~dsPMMIsKrX|S!o_0h2aUPs^PIz5s&;a) zo6MF1!rx<+EHn;hjhUZgszU|kH+%W32x**+|zCEH((tx-7T;M+A=NzJ|4z+^_|22!cplUKT zwXxdzGyq0xx5|B{2Z5Q|D0W{e4z|mFi^%#Vf#W_m^L=x5$pf*++1Z((V}D369l z(B~y3vZWchmRwg#r=>Nc$E0#{wj5SMOsDIX#+!PuSc1aB4D!YInxL5Qiy*4>7gJ`l zhDqL-R+G!Vdm-wVTpF3QB)%qP6@N_-clR__nomSHtLWZD-(!Y=&y6Mn`ReqToGU2|DWh)ww{k$dLEJfwGKsR=&f^y6HbJ5GULZ7Qlot^}r z8KKN0xV&waU>W3sjV#4x`P07{ov+nf##cGW%@q@x{91w~(NkVx)dy65CyXA4eZcK&OvV@;11+AAc=H%I&A;p@5 zvwK0U288d4k0(HI*jL}nSBXs5JPQY zoPmX?payE9;YZaAx2kf2o8yV5}YV~@<%oJowk{Ct-#9Av1 zAZuSjiT0t?jN4@eIOfSe%{UR_KKmv}xcVH=kLxTY-gBjbF!2-V7AHr@G@< zB7lHKa#WKk1z$7bYkot3v23;5e3ayH+08ndELXY7Y4mGzno&taY}yKRL{an#AEQ?Xp8^Ad?JO(b_a z(G7;_3G7?xAb+I%YY<7`nmSSPryX1IEb5aRO`}MbcASLQ17EVoBevB`-uCWE;0B&l zdqs?<+c9#=KWmCyE;O2Q3vyaAi533euB%2UF=3aVWN@@DU6bprClxc+UXf?4ti@Y==sW716>L*zkEAj5NcdgAS% zF(U%32FMhS&>%x@nsNRi?2+pN2q0^SvIr17@QLw%p4*meK$ME)4|^>ae~$aO@;_ko z>S%5WSx-E=?r0=7;<|7YS!1T=u) zM-Lls(!hzv3QfA1s;&V@ubTvv@t99(yL0qqweJfOsm~~w2@kG zY0KXF*c=L)Q{LBP2d=VJOlm=7`Wv?QTB!5U4O_kK^P^mDACweJk|YX#y2FEbJpF@j zP0^>0XR(If$E7wEh)PYPZ_(Lo^bcqHNNg=vVt+BEMH@DB2s=cEx;(W8Ae&NpmSGol zK(3lMU4P5Y8c(D**7)rLf!r0&Amg4d%y-4XdeO&uNSCJL9uWG@^D=L9Pb2c#Hxu8H zKj9*}e`V!|Jb?pscw?o`Se#(&2blfq(ez}3UmpuMfO^;H2o%7WuknouJ{_eaHG;sj zW|62RYS+xTiUKs6S7afvjEgkD6Nk^gnU2xJmJ!=URo$%1bg0xNM`Jb@W-w~_Uc(A} zjP^aR0um*oF(ovNFplxCN|o#dT7~0Le-82rAg_sj{wn!{mp7_%zsaAzd8hR{J6#w0 z9_8v@D69Mat9&=kvg+usmVdvrRuu(W`S416s%OBMg~+pk~R+@v4agr zx2D3C#@W4`oebfpryh!HQk&iwEn>XBtv^nC->0hRrF2h#F@<{ZXqDSv9J^7S z_3ptQp1U%N>-d=xg5hR~M^C%Z!$#b~dh9Vc=}aKM1)cUX4CN(;+f=J}4#;5}46gzlIEaKOZHp#3jiZH*E-~OzG8eKBy}Mq>XJj$dsnX%Ef-i<^Mf{dd7O)kZ*!qxsvs|1Dd_ z^m78*2e&wRfKk)stuTgNpyihKeW)_sMJ`4i!wQtZ?Xbot2bRv5=fI+ggp8ZKVp2Kmw8fK3)a)18bs59}Y` zE8~^RF=xVdo&AXs{JI#x{cs`K+&I!rH~+$7N_Hjp&Yi1Sb(J#M$7(!gl`a{bDZUG% z%6PV6?14VhID!dCwZ(`%&=a=WGy>!Fr`c>;+Ni%1vFKg+*jhLFJ9OUQb2;s9?@kE; zEWqQM|EFDq<6UMIAwiSYs|eimW$JBXecKw72%LNhWyfYe59uOz(uiY-4IMRs6HsZ5 zao7kZl-^t{OBwtwN-jZ@#$j#|M#t^{XjQ|P-*CSfqpTv0mk5g0yRB>e}D=3OBW6gC^B5E*V7s# z!xUhmL6pSdf*?GZOGFEsJ;&I0G$rjd*_JLX1>C>hni|J9Y3i-2MV0?;-auf>~LVXos8A zh!&*zb>5>ieTo@Be)vwwmz}EcGAu=!g!`E4hq7T}j5b)~bD;QeN`|e`CF}j8pw+oi z4^CzJ3S+xBNX2YAk$l?|s{|A)pGGIbOH#gPbP7q?z`bWvN{`1m>wnSI-E6}Ai)a0P zZPA)*1~`BqE2^lt8Q`n~;5dMuum;qlY)~L*ls{T!$@SFeMRVqJ~qHR)yOt7i$6t zIk|RDeCCvhZt7EL=|C?n%+_R|t^boK7a-%P1E_RdGy|}$mI7tHx z4(k90`cZ0vIK}e3nDfDT+Wj7+Qmdgi0uVpYuSk&o@B-34kOn|aFjqp-&|u2>B>q$F zuy{+#$|H9?8ZC#9m>q`OvXr1Hqrzn{4K5`q@>-ZU@%kFeZE(99ey-TAPQa5Kspp1C1qOh?_TmCVeUQ7{FdzmiXOQRJ78s?2KfT){AW$DqTSU0o(0{nUV1x)`A`dkE zXJFS3e76HpHK0Djg70-8QiqfpL=6BFpq>t+TWhy#y-up(U{BFIk>wz21b-t3R?HAY z`w%Mnh-5(^8K$iJf`}dl^!6>{Nf2UyLx*!9#qtdCad9yngJ#8oBRGw zpQ}=RIQu571e1T60a>~W_kkfaqj4!G$rlz1Uk&r4Le_^HrlZv6%{h-N(-KsINvxD0 zEm0@xf)e+oA)_%k+XMvcHxfbNx&N^$k8mj@AP_@18LSMTd{7MJdg7WOk_M(1CUK8x zsJ)DWQx;X`3gL|+DJS*bD#~gsH8{2u;_2BnpfboBH9`pwm-Pk)?64}NF;oB#NMit1 zV*Endhpj2g6%r7Fk~|@CgIP)bg+zvH)FBck#1%0=kT`*_l;sO42m>e|OQpjSfSC{w z0{{R3Gy_I5003`PX)000@N7fW_Jxu|f`kO>=Iu$tyM?rL9PN-P>VVSi9}o zkEShq?wv1IosEn)F_5ODk>SFVKe9lB@SVYzFC+mJ#P^_J|6f2+VkiIr0suxMZ~%T# zyYKhy_1(AKn{cLDkV!T`_O(i@t?f?zA1R_31*9M4fB-5$vSXKh|(RYn>ueRzHCyyfAc^*&^s;((XcZy%eVYB=rRINH>7t(IAD zZKkVahKsGP8LmlW5)SVsGxD&hS(~gU$?eWow5p+ve83&%B+6`bi5QXyz07-qbu3bE z!sA)nOnvo8Qo}UraYJoi>1zMRk-DM=(c> zo98ogBPb{t-VAHd)HKs^3iqku10^eS%4Y2^%|Y_AkC3gtq}yl zzWdxpj@}fU9`m!`(Oc>-1mAt1v$YX_+a`fjrP*R$%e%b~X_}1z)N1+VjK&^`X-0YQ zRgr*(FIN0yUaRTnlHz~gTx}%Q2S^D@5;wPfp9#@;xC3EvEGO8T^}E^~wRb~wzEd#y zf2~_y_L>h@OEN=E%^71@OSp#w)*Fj>W{FFlc2l_QbK?^h&)-qRDo>U#j?A8|rg(kH z0FTM^Mi0Vq__mzgF?xYa;(#xpW{m$y^CH~JFY?T;)0h%p&m5SY_^gsx%S=6|Y4`ke znB@F@-I?e`$#?D<)N5U0Ze&VsotTsAW-{Oi6Gls)eywDZY+^Lp{o8%U#AeSl-s~I7 zhe&fNM+mY=ATG1!5&BM zmJv!oWv}|OHFZ^$n^jK;i4f;oDLgfI^*5|x+_|&mz6$zC$%k`uD8|zF!`yi`x6GMG z2?n93CD(Wx=FMbg@Rw#H+B8;wMN`*u!OGVh=FW=h502z(_@xq|wi-N>`Stukg(!Xw zgYtW*O!_#gB!dyu-{IZ_-?%=u(UocPQ1i$%v0WXSr`(vIe1BDrdzwv%fyyAGoFJy4 z_}qW__xsg9yUgjD=It4N#Q*o}%{d2sA+tLYq~CZ%zL25Oj|jYcPl!)YlJd_WDinj; z^jLof?yBCghYvzKM2=%ygNN5Btr19BII_X1^G6>|tIR|D&|JI8;j2O&dCxc4BB3At z#{Guvz)R=2$iH=)~?Pb#nXPKUJzS&M2e4Ex?2I;qv_ zF6!^?1yYcySacsXhPvLSN83XGhQI7{ryZ&+`l??vT`H_hU1kNIr5w_^b-jI2MTL4d zOUkjdqS}SFDp<#}jPCxjjM8@9@<5`#;a zio#3t!e>)RdPXNW&xRP{j0Bc2`@f5DiU6xE#qSJ@eh;F*RK5@MqELXvUFw}B!-%`Icfu$HfFt`D z0k$ucK-33ZOd%1ya21Cehmq6)fQ4RHg)kS~xEJ^k;35G*pKRdb2|w*WC^iKEzYvk1 z{$mv$@{<|rmDVdY0{1CL^2^Kwil@K|Tm_=!sDgKI6;>pG5Ci8gVCpalQr7xWVv91m z0epUB1mav`Fw&R>UjacuEr5iB>_9RF2g?pbeNmu*gZf`w!_!3@Bqmk)^ngmvd7@q!WH7PVJuZ~yW~G#3z0phX}T5Ko0g6X2@*z|i3iIZX8P12B5fNfc1QZ;A1!k%)4M z!2G}wT?OU@kpQ3%AA)5H5`;q#*TsYa;Sd6Qg2(_HMYRMG8#Mf$L9_!7Q$Yyn;3202 ztnx#?Cc9|ATSTs2T%Y(TL&mTC8N@Ugy*LBo$rzkl7=M6BWvs}Yarv8f;lmD0s{Pzg zd16SX&WCtG<8$qrku95lZt@UL;cye8g!-kmb0kh&8g0Uh1-xy2&Ob_>%qjkUqz}V2 z6;NYQHsVR}ch;CcPUCTNTBrT?zYAR!C@^gIc%yadIL zRGCxPARt~*#(VJpH5sOC06|8XscGUgR;OtSu)pa`{~J<0q$uBX_=8+HFwv{ z6@#XEe22OIh?;(28~Ls4s(d4{_RJlFBmAtc2hd)HqEvN2$jk}=&`Ky$h8RHEF}MVS zR-gkO06-8B0{{R3Gjm5H000kG{3`F4{%TJ2B|)L@;g2Zf>TJ5@~4b&8=P$7tABfKBrlmP-1 zphhN9K@`tIp@bk5e-T+~$g6@vA&U3{5D3UY0)qbmsY*_9B#Xs@BBE8zN;jFdr>o5j zrz9;Mst!pN8ZNXgG_Gp9gT~oiM!nw~mQUbEVl+(b9q#CRrd^gbG#>_tcBEfwu!+Mg zm1i`Kpp1rWDuPK9A$r42!X~FQvn0mY%fMr%No4zi(|2^HH}-2}`P^EY#0n3G*u~y| zD*{FExDswjE2@j^k%q0XcwcsO z?L`z-lvR({U5lG7eA2|q)#Yu2WmmNijc+}TWjE5T#r>B!gf<{^8z$a{U)xM(VJKbz z#@^*Cdb5s60|ND-Ky<{es+M1<*)E-ZAe3#9u69t`vFl2QVyBHQoU3QD%Xyx?Cf1q^ z>ohE)0*KO%KqTgMJibw9M8iBFsa6TR*Aq9_Rl*+}&OR0|f|N?$3c~*^(n*|r7VSNI z&qc7f%`t8#ebCd3s+nc!=exWG!61@GK{lO}T7kjY6*k1Hu~m~T28)9vK~*i zrk{Xwm(r083bj)dV9!7(UujbgH%^`Pdy~++dKSSvO^7{uP%&p@+lm&O1~=JPb!_ek zbNDT-zbXI!yRE71{G-(Pi}m%GDlDxdS7RnrH5yB`3Du8{5WiGb|sqMl+|s9)EK%ZLE=mkNk11kuaJzCBwy zCO&rEaxi=WE52v7(6Pnm8uWRUgn{z>;wVJb+T@@|XJ6UrzLE8!T4Eag-%S$#%bbO^RjNiYJROy%6?d5hVZk;@toKz+MMuxMcH4)P85XBiLT8^< zjS3o9eDAvKMitOOloWL&t<1{b=uWc4K1crd1U?v#lgA=~PK{w{v85pRK_$MFkQ`CIE zS6~nTCE^Q=vtd^CFd2x}VqgLY%3(0rhBWGNHAD#xT__IbLb^3ekJJng@uM5q-zQ6_ zX>^oe4M+h{ih+=%0UKAlED8hCCuGe8B;MM91`opcjZHzi1!g$o3|(O;$&k#%Hv!M- ze*E(#w;UwSFbCxTBw`07dN`=D(LKYg6{Q7qPLVZ0K z5R=_8yzSP3&P`TM(BVS4u@h;j$I)n{Sl#aRB)xbM^+)H2OjlGEpASp zincz{Hge_%WB36$YIBX&wE3{(i!#Im_;Q^jj6`!KNdq>;iQji^-@A+mWn zMHUEM8J6RX3N#G5T!5;sH9@9lum_eUYq}nktneKk)nU5b&DSc!1-PO`c{gAkHSE=@ zL;tB~VE~UzSO6zuZw4R{F{OlzYCRq0Fq1GhaeyB4{$b%@8<09_~aO`FkSaopim^-7_ENPwaE=v#z}^OvnbTj&LL%ddhz03JxzA z9hVDjZfcqRR{HSiI$VbW%a*H3_=XU~^=~?X{+u>W32bGP)(a!TY3LiR0?GN>C|`o}zL z>?~z;tpq1(KB&Zkl5e~8{jG}jGnL-&|2Z1B5Gle3oP63R4hPKXJWMM>8h z+Sbk!?ipsNa9K*n*wszKk-2o%O#db_TGa@1JB5t)S&grG4BM+7_S0e@(2(ykn#+&zPN-qF%yAtX@$9JB=nmf3OQoEc5p+f>fz2fm^E5` z%DK#`{RO3N;+qy^B$5DcTN-1x(rl@gyLi|cQLoWT;RcUgJCt&jl%}11bC4tN$~sXa z9Wj3~^D82wa{UO=C5w1ySCSOLmQ-H{io7v^Y|+L7nWD_eRoYe42`%XE{6foI(Km7x zL409DDp6a6qo|2&BLj#W!+`8LS1+yMr>(v1+GN#1>T>%>W0Ab4X` z_`=+R)S-h|5;C(awIO-@ija;i_IT1C@U9Xg^4ODb%s&W zS*ye~cc{dBD|RQ_PWd%AshQQr(gcd$MT)>gTNSDHPi!}G66az3$QX88lC6n9npA8{ zGhrwdo1A=4pt+CLpYz+^Yf;nW-Ma*B?;N=bc$c)j_NVjb23Kgz{Z~r&+e;}etC?0b zUHwm63vsCt|0ckU3E5J{ic;X+?zg|Fe7df{PH-Hr)_!8d0FbZw&U4v|-0MzMf#wMP z3c^EU#S-Q-Gb8W25VLPVSC>%{S$wqv-^E7?;i|1ttH+~3R5wm9Wq;Y|Chm8+jfnWZ z`8K!c>50rl$Q^Qf8%*m=$Hxb0`QncQdy%zzflQYt-@=4o72n3DM)<)sd9+6`Jxtt= z@3(WT?!##zjhgQhr{VpLm;gUcWsc8&%|c@ISwp7e_0$d)D*0S@F+282hL((a5>d%l ziO~3_wR4zn0H?FNrLB#*!2Rq9U}Rv@zFPbMBH4T=-9RUD|M$^aO8~bj&m^v@#kp^b zHy-%i`mhp+bk`-Hj1hK<)$oVSuV94g^d7>Gaokznzb@!tKRU~7r`L99+wqBX*4j6e z(a~pTTrnxm7Z0^DP7b(nt(FnzAEDZ)r{11WNjgVa;HpKIH;Ge6hq9;FhoL2YF8iP* zW2yY*jS)le4>GHEVFDRaKAVXeE9l59f*AH98=?t3pNf~ zl6xD3$3*$tVSFKkU?2pBfg|gELx7D4rc zlD==nB%e2vFW@qOZ9gugPCMu^wm(nTu^<{^KnVOcH(*h!0<3#(;s$rOky=5>z}?TY zSE37mct_%)YAHb`FbyvAYniE8^i!y-b;nzD8PTP_`p_&qfyIJN1Gen>WPKAi|A??Y z(-A}{i`@Z;U49QrkKjazL7|G3;{YH6&`*fLi!l&iWyFOpIFNg7{>AAK3mD6=GQT5k zXc-b5J6vfT8R7*7MuAU!p*0Q!McfJTINCEB0krKBOoscM9BNESA$CR30baxKG$4L| zmxTm6q*hn6*c|iwzG-)F*U+hbMjHr2+5~A|#J|uVFS<(Y1O9xp zP;}x!Kqu0MoL%Jj!G2-qd^3bVBXPE*Dvmcn0VReyF2A5~0KDR7_AR8=RbNhiWPsSR zA$~b72{de=1hxWz|F)!%&VcoB)s_GEtAtZ!DWjOxLJNlwD|; z`r0ZhlKN0h<^_Az&f`0;uzj?(k7*fwE-W?w#H>cGLPeJ&+P<})-Jar zBVPP--j}D?J-;_X7TpbRk#kz%(QbAs+(@M7l`pf+j#R1~P#YkB7f|9+)VnJ`;Ds}ItfE`t9`f6DInws8G=@DV6df(R@L6cK>L&>Au@1o{*#$vbOlFC_P{+ZbrG zO5vlb)@&5Vi@79M>?XJXbcdm&bc%R}$G@MamjeqRiNep3^!fZw%n(PC1uQ{`a&L)= zw#IUIbBq4VR1zT_AC_%ohd6Y6_uY4yw;@m7r^8l|9$sM50u%;7cIoh;aySyAX|1A9cAZ7yq@xM9? zK>Ypy5Y%ZecVOd!VEv?C{dS6GBk0bH5KbYC3>=e1JquAR)w?g{JBOq@UvyG=Dz-+? z*i8op!os66ZLcH`K53AdFztud$c-n^A-C^>#x0Bl!asgOCY&fayU>zHj5{6Zrk4 z1c-rA4-s>J`qtF9kSeIERf?T+$v*#iRXzI;MpGocRaqsMC(V%V8Wa}rEiR}cjoF@p z79D8!cVC>{)5oQ~D^!-1ipna8swSIVOl+9Sfgup$UT_(C|Q7I4p;Jd zb_ZDdc5*_5&=%F{f}?jrUNN?Iq?8B{($=OZ+f%W`ALr(|Qg@I2ZD%qpjevpRGTB{k~w@I!-q9SJsef_NtXytNTUpBHv`*SEv5cG@o?Y zsf;!bbbf#nu47t_Z&KB6{Qm8)zHi7khUoz)&ikZB+JM(}50E+HjY1NUF-vS<_sF9A zWD?SXPJNwk>)_Wm2qIz9S%_%MaUED)Ud9?(fkVN&!`)DSWl@QI)jr^x(HT-ncn$n3 zFcKsmn4XiSh|WuYwZt#6;hNo3Wmz9#42?tyw`PSXBK3kVk@Ok2edqS~p+bM(9$?{o zu{6NzUejK$9GEAi4##P7Zqk5rg)}~F`awvXZR)5kn{sj@`1|xg(oO%Sq_iRIf-X|8 zH^_*EpPo1ht&xEybRsu=HEOR#xTWh8#vp5WD?m(Zy4U23w!92Z0GK4i#V+6|8kJL*>gnqZ1d?ffFx0x8%DTfTQCC@3UcN}#&feLaD<{*4LR6*E`08YI5S#%j zO8_zY#8}l~Rs~woIJt=;lJU^RCJkWMlu25xE9JpwqGgj&A1|j-Ksq}!#X%7yEK|k9 zxa#wCZ?~-M0K07cOG?4v;9kFBw+C)H!!7+ zWl3#~s5&Qsj=$r>RnxELnJbRZiykE86+my_*T!r#>2*CnBKiFsS;dRPw|+Cn4yrc> z5ZV)lgq0b5SzT&pNPxgv892og>T_iJgR$lk!jHl04LN;YASS;0HS$iTv6X06 z``A?Q=avJ0QsM7y2o2hRB>{p-eWYYKx$1ebI{`m*4zDb3+JL=1s&P*msMhR1N#5E0 zzK(WQf&tl?WU$`&pyT8{)fg_1R{~CRj%&4=jW8ta4jdQGNCX}7apGhA7P^2=gMDGu%eyG9C2b zyopwM*jv%?f@oaR)l81v4yeN;4EJ+Jm%(!XaGi8qxEz%zE0I%D@qeV&t|X>yIJk*e zXM0e#$l2=eAi$N#mAIOgRUkagU9@)+i zc7)jTyIc_3zBe!g2fw2;PLNu zV>Z*MR*@3ESt<~qN3e1N&haCLV$yr zHGoy|`D_Q9tJ_ZO(dq;)MW+@G%T8DuLuHFd3z08YSJcCf(`Ae%3$lBP3}c=221fAz*?hceF)vPHI$>%*fj$R!}Cpg5VX65NF~`LyEy zQ25qjeEiVJ9M0s;#JK7IO)Hd#09yFFjcq6WJDxt*%h)qof8l#EG4=gAQhP!Doa9+X zQ@;^nfz-uSQ-(kWp8`b&3THq)8Y2F$?n9P+G$+>N9^F0aK@RG z&B6C%r=;+o!Fc6c-m{FgMDs$h$kJ;$uq+V5)KjJ+{4XlNTU8$vepDCmL3!T+Kvgb0 zA%!((9c@o@Di;aXOL-ir1@^TmYIiM?;caK{96#R6?|=;H82W`W0!Qkp@zkrYk}hQk z#k`tva$MZMI`V236Ac!+&-@oy;HzGxbH5+HRu|Mklpk2xeQJII!YvJ-OmiJ%q*Z?( zKzf1>a|b-V1?<2p?v4!hJ^(GIAQAeO0QenU=V_D?8B@oPhzT_$K>+gT98XXo&MQYW zKQ~VLUDw*^&Lxd4%=`Lr@*?MZBt1NzdtQxV#isMQ|`i1oZ8aCQ`>W>>cQ~2`_tc0S4 zDGli#`H!5$KH=B}46o>@JSEfP_ ztTV1C$8k~iZfesqZ7-!$g7@uH&q&$kU1ysG>b2uJN-=+s_72Tf8XU5G>ketHM59e~ zyCIaZoQ(udbA#@D&FC3ApGtWppR}arw`0T5@docw6ee}fp^Yz@LR zn^J5z+|w!M#tpTX8rhBGSxMPc4XJ)QiL>4ish+sg={1GONd9neNcKgb!@Y;LQ^}2~ ze2(z@mk(tbd{JqNzb!IYbsYi4w$x6v^agu77PhbJWcYA*L9lJ-3hqA?g}5`%)bRl= zq><*Jw+4-5j$3W%R(?*V^O82#5cYvy+4_al@~0!n~S{pE~2C2;dx z7iEh3LLOhi56W5B@v~jdxxeC0$7)!#5~-`0`Gg{WbFy<_TxyWK6&U|o%S=z$3<`j{Nj^G4|tW{L~=6vsh%f^#c*F=H3xt8Vdu20Nx3;wCDW=M{?E6FrXkbS|kJL18R%;AzW=?l^{&) zu{b@y=Tpo~G9WwPneaDh6znEK=u1a2TK3hNH%h15-Qf#pT)P2O3mFM`(kJEh$+M_xlJgrq0%B}X~R6-?!U z&F%-A%Jl#ieH2Cppgi|}CF*E-@sTC{P>p~BNPX2tP~oUxBG`+4tO(O~P*g!%Qf2r~ z=p;MJAX8f+B)(>+X5MV{4(`F*BxA24^X)cR|2{m!l>+Miw?Tsc-?n6H?4Pv28&r6@ zx+D^3r!_^bb*^!rxHY1mrT}^0lD>Uyy_IdH`V#c>^&fWvGqKyhoG~2o82kFbEa8){qA*LbuJ3apzB+s znFiUHyKoRVEKJz$RmKgP94!to^b)2E__r+)|HJL%^g0nfu6u4auFA1R?1?TyKsrTL zi7Z_L#QrpsA_AMIKDg%z{9?*}4O_Ch>O{OW)X&F#Fc zeD9@-fb^`U!lwR+khq5*ZYvcMuZIjf6MOt+H#1h+(e9D7gl(qiAC4d_$$Ww)n?JACjcYgqUjC$$>xev@S4tmSMw>F@3sf% zoB7i3hAUI`aB`00I_?%|_nAGXpU!Ink<==f*ynav5eC|5I*OmD^I%V=T8uBTN6lKm z!O;6J0)ZvpE)(kBRmQk$aY13>a&a^F1P7^a!2+VC42Fmylkv-wIbW@_Yg8({+Y2k$Ttwk1LSZUyUMwk4hz-Y^08G~MJT_!5I(CNQ zUc38w0&SMjIq!;{>OrVNIKGi;>99#K=s1n^81-tSsxsqB01-ksg3pMD>Vq%jOL%!@ zh%SqYG)~U_#d=jB%P%-VxJc(pzuM|57R;swF zJhRFBRNg_FtGw?G+fNJWnq|z-dZ*p;ToHSIxhK%yN2e?xjF%2y^>@=~R4D;h`cqi7 zA3TlwnhxcIM(s?qd-BQqWc{WClFmIV5<+onStcuIKY@X_5YsbHOdcB=wnhJ4NkL~o zYWdAP79YtTeDQc(g|j*pAgn%^32obG|Jl4~$S zpb6LzLJtp%dU9?x<_kO*$iul8^fQ$RkqSSWONRZ;hi>cckfr}EqGip)8%B1;SXnu} zrC*A}i_5rnn|pc*IT1=U-!>^qLSz;LAFo}9E5CW|X6zRAD-~J>N-^hT!d~}&{2T94UGJJWwVN(@`6rpT6{x++fyF(c!Yx#ad(^^*M;+xS>f1Ku`ud1Kc| zAR>Xr*KP3i$FlB|c~(-k7sA!=&z+AI+>T@sLZMNf%i!pN= zZvQ|{i2E$_9gb*kOyC@n()KWHHsqK3|wA7daI-cZTXn^_MI%8UC!eciU*Rl;tr6w`;fV3 z`KxHey7sB3dFA>cKg>CouUvb4cL0p9*}9r(EjlV{$2`%PZ~Z({(ip>2u7jSa!1ypt z)ZznmA8$h;E9ks%&fEeeQzbh)sX$JO#O5~`}x*g z@A$PlUAaJ`yoZJN-OP_o;|(-x_rrlp*7;Zy7^fnc9)yzL^}T=v+{nB)QJA}__h&o` z+Sb%!=S*c5_75nv7(6RmcFM(TSy6^X?1_tukb0o_Z!Uwte&d!)NWI|1a?vmzIVI+O zpojN_y9p#xfXLi15bsfa$_mvCL@k{ov-w{nZ@}FdDI`hAn=w98 zE97HI0HcW0FVp;e#QM{E6vmjJ$i0vIUsJF zI!&a`t^d`Xni&DQSo*|Ew*dF)kW-8s&_S4;*#dn62cz6;fbCW$3Il^ygP_SPuA)3R zsL9F)znp`^uo=%(C3;lvp*k*50W6Hu{Mh?)hkhsN>VVBz(dpp^ZK%txfUUIZN-Hk1 z$|D(HYg}14&iH<9nEMKCr)YDRwq1t=6vV!dS?|r^G;_=2e;btQ~3us z^$qdp?b><)-%)sP&{`Hl_td}zcQ!Hy+{YBxRRLjN1Nz3Qip^Ea<7h43-Gy`2!oucZ zXKZsgrP3viYU9wp?-ovt^V1>we8NMuN&~Tp01>WNDf)rW^1X`b+6tguu~~t4-N)SL z+vWUi_t(?PxQw&J`Q?R$om0{db}?1{ml$Q!+_N?hy*Av9^4=_}zxL^3K~2d&6=~nvY7G1Fx^H;W*1W)rpH^ zkh&nnZ-!0=`Z~KjceyCJ`??N$_hE5BD;dW{9Bbe1G$M4 z_Zp(53~(8H$Rb7ZsL##ZB0;UKt=bPmQs0Cs4g&b1j?oi>JVr#)M;O4vX+sA4t(x?^|NSm2 zx!}_8w=X!3w34VRy)ad>-~i-b92^PhHecF2(NK-<=}~fP;su3oB=Q{^jh}z-@-g^C zKwQas{u>y~WNeraM*$*mcRo)-kKDBA-x6b2q9%0~N3x%FqS*A&XGI~+rczN7Yh-*xkA|{cZZh!t9aKRpB*^jG%V1i#!di;XHC$&J7Y-E^#Nlg!LY@5^PNiD4 zgj)ap0Qn2R@`Y>Pmv`Ze$bboyET|U{fM0388IyGX#5FRRwt^b(N$P!q52AYx&H$~K z(#s-&*#{A665nGT>ZVf1hpGwc)_@q6+l4Vqa`trhf@fk4eNe>YmnX`( zD#TsPBF5ya0Kz@hWE{%;0O;lRk($`U@T$J$HW6!k5}F6?4u*OBVYmRr^tT}p zl;b#@7z=UtsI+%4Xs_e!=+5bM*zFi=OCS_S?7QV5i2G+~1IV#}>%9QBx?iq0I&EAx z&$TZdI+59$t2I+Q*d!@h2?%#7nSg=6DgFr8^#uV-#zDXSkv1nx27rTNvO(vg86CcYD-`63WdUl>dXnS(!n77lqXe{-o*KMR}^0$;o&X=iH zSJ+3^h*2Zqhnqx7c&w@m@l2SlU-i=lkxHa6N2t-|X3r|i=V^YWW1y|^Gj?vBj3l*X z1I1vG)K%bv!>Z1sw}r);Ci0I9Xw=PDs zzLpp1TB^9Sp6$^8Np|f~6?K7rq_+jL$kw~zMq-MTyKx)6-SAMb)m&aWN=Y2wyY-j3 zd;ZWak?w_3MWyNt`>xIwBlS}%x!x?G1UDQlBwNZ+rT)lin<&w<>nd>&nfs~1ugwO6m! zsQWk+Lsgo~^3JmK^a#VF*tw)L`SOMw4_hWfV`i!o)QFsby>k!c;fSG{D4GndU>8+= zW+5_Xgry3d?oggWUZr!+vY%FUB&MnnX4X~Nsu9;THdl~%Ha*%7)aOlGHX50_hzqt> z@is2Drk~Q%{k|-oFuo&w_)fJc_V8w(KG~#Vb&;1^7!HJOs=kU|%|MEV$29%kno`rw z7x6x=tPIS6|B zK^opWBgddHu$w_c&)lL*ohNRDYq|7XM#WVUdUbje2+FdnL}PSSj=1EiuvV^kCLD7; z=u9dK7i3N@X-BVk%9%{5I;zSiTXkvfIpVM>Wo%?;D|dBW`|a0rNRlV!Z91lH1-;tP(zZJ<+-e;OR0GexuGW^Te0 zGB*kJ;2%p743rV~%Gd$tw9$w1QH|nnBvlWqn& z#^T2bqUgBo8YbZn0Z)D;rSW${C?kwRS6esVlYAMP20B3U!}SLe>OaAZ3^wA9lD%@h z$j{q97~NeVI}O}J4mJ5(uvZX%&`=UHd>$shDrUNshih+?`n(V`x%JLL*zJwmf-?_V z`~s|Udw4aOPva7Ae$*1NH0%;Spt(Z_^w9h(Nhc!9Vxs=KXEYS(=}Mj~l3xTej|UXE zu*fTF7}vML_Pp9Rd;Evj0Ondy4fmMB0u@Lf@sc=OQG)|~V`7Z%IZk*h=BRI@Sk zc~M_VE~W<{`^X`34YZ5N5Q>QbzBi+nJviaI7mHa4m^Xt@8u6mFlT$EE!xU-EXN^pE z{7&-hVfNm{Vea%q?us!5P`o%HKE#w_lXOCbK=pHCNW)qQy3n;M@3Nc1_TRU^A3SDX z8glE0k7cj4>Rh~$eOM>@iIsWZh|7b$Ir9Su0ACV*EC|%(k~ux|9BF_LPNND)AbZ!3 zfnx$Z!kWJL)#3p6bS6vXwmIE~2`lQxqVouCm>&ObDhdjc=xqPu3D;Axm&fxw{M;}M z`6y?8KQsU`6A0vL9Z-%EMFto-fZk2IP54wrYmrYowp<2X@uPiu%+4sdd_`XO$KJ&2 zaOTJS8~w*(kBfVx1Ph}sfUUD_hJ`~iH+5jrd3!{<9aW`@DC9K83H)kQCRuoSmt!v} zZ=w|`G#>Jhh>68D(nfSN+KHJG&o2Csp6HF~aWZNKyKc)$k>H^AG-NR(YCo{X@P?9& z@NgEYy_#d#oQWi%^~9evFMgHPgV-VT#=k;9pFGcBzJRs_&YjcM| z8AoSRjKq07x`F(a)(1iY0j~!sb@pt0{V#02**}?eVV`8w>6kIsw+iqNh$2v4SuF=U zn#93DSbi3+tAllSW>8jU4WcXon*SESu1G$&0*;B z;`w;eI&!9T?aBl)14nNQPEG6SJ@I_t?`SxxWa(2d9(g)dMCdqjn z)FQ{Zf>cD&n|XNUE|XeMTB}IT9f7g)%jG(Q^~_vcrl&h-Zu48?>z=7U&%L#50SMlXpIe%axmDX zug#JYnwz8o7I>FwteBhhowKiIGI;%7O)b0xktgE4r18O!Kz<*u@zn7=ddcl%%otZ~ z!Wa$RrVA}z<|iF}k+JKnsw#kQLE#Uj*N^H?5Z*6&gR2V_9ig(Teg`FJ31X@?kza+i zaZMCxo!e?EZSS-83*sBY(pJ9nAQ()c>(OHFJiMk{pN;O^2>x(TBiWU&OpKt}!v{uJ z;A9@Cz~lG_6nbTNkJ7N&V&c6EsO0L`0)MprveeJgmTn;7dW=nDg_0{$<4NG-8Cguq z%dpB597}_PJcF`P@!VeqvM$i3h#?HR49YCH%RHlKW4WMHLk;_o4~nQr*{a~`Hh#*< zcG;rN86)di?>2#1T0HRyp`TZpCs*s2tRWb>vsJVzPU_kjavFV`dB=?Vhr|?4lN}qk z79aFKd)9f3gD)l?k)#@1(kokTzUU!BJ3xucdTt{{k4C^bM~XJpnzg|tT$2Rmu%iOT zG^Fu0x2jAo#L`>3S8Z$kkGu(Iee{^1@(4+nvfS^kUVkuwCl^1(y~I{%7}#}GtY(JS zs!qK72=u!id4QMGLL1HH+g39pX=dDf1szImc=@<7up1^7U2OqI4DXR zWKpk+_u6s7pr~vD%1hnM7n0;pl^B|cUc=;*r(>iJN3s0_ePHZ=lF#btV<`7G^_QDO zok_1S4+F%ELY9s{$m~KT@g7RDGa>P%q3k=I(v5yf4grMYoQ7 z3h+^K`AG;!9(N6}*q^M?Pa21sW5!*mi|-#qoo!@K>WzWOOf&pzYp&Y^k_LU$a4VG4 z1otDM_TsfaVyl-V#tc?ochH=p%vV#mmG1O7?gKet0Bg&TUD^gS}uY+50dmKZu}TU@9}fO+ocs z)^ZqOZikA_XR#wzgoKO?2jPntpUF)9(!oV_alkQv&%8{j00W!AD!pJ)@Z^Kd`sEkO z;te_!YdOH;jvKhL;nvSK9R+lfr(o&%JT694FqwY%p{HT4De5Ng2^92LFLWhk4K>a`z4H$1}ZJWI`Jp`puM={ zyEF3BVEyC-PL&EBUUAlBDHQ>G{vqTfUOr7N+*17#o-1mfyHmb&cJt*clqu73Y#uA{ z03{ukzkgwwcEON>$=XWgI+A=+5@q3M7SW?t{p_K(RHqt_{~z)J#N-ez2mQEk8vYHT zLz1|Vb4F|gBlY2XJ%Mp}=ig!(M`Vyxg|S|mH1+BbA`mmZm`dH))etui|0$tE|BY?{ zG1C1+^nPlk-vM!xbW1{WI+zTnA(XegNvVkXlaa+IEUsk34VDZPNu6!haW0W3=`XAf z4L|MOEe$yX@FStNNfvUm4d@L-hW?$00h@Jb12_8uhMPs6f>9yFg=|;wkA-j)RG}?b zkQ4%Fas4LEBHRXT2Z3~g@*{-C-~!0wL7rQ4LqEfM#tCBb% zF;D^@h))m-NMH&=IsQCrp%5Z;B|Uy1Uu(dnRI-{90O0TzND+37VCW@fVgg%cr_q#1 zFUltCZ=JN?!Uh7 z0bcpSqN5hS7oed@qk>kbIgmyjxtxk|shDNw4CMHDuwjYPBn}ek<7BJ!@&yr;Or$>B zV$nibwp|ER$_=&nd4HO!|yGd3^VGwhrU$0 zbQk-^i>=*pt5WasFltMa`lLC@lAl&zb8INNq6$`}s%coMBM44_qdA%88#K&Op~^$0 zXOGWH`oXE*1BLA|`RT2cco*`aY7#&W|#TkS?5H|4i^W^mxPX%QfALs$gu zo`}YRiz`d+(_I`;&?POc$}PdrWu+E9BcxnFKlxYt`w^oEdb)o+x@A#!_rfxH%_81- z>q|$A3fupFgGa^#x@QRrtL;(wH&K2kQTBwmNj1G7ylkoB5QC^Xcj7gt?It4XN+s?T10MCho3n;WvFI-0Wql=peS~p2(J>u zpA&Zt4Q#|?k8JXHL>a0fyTb$O19aTYYH|Ixy4K(a+5;b1YA-2f0R#VL?MATbJTY$F z3v!r(1h9ULFxP1sZ`?Lz4fw})cP)_deYX*w;PlnrhV;1sZkSw`hdX}xzgFxSf z){rL(wVeH)F4!(TYRA-IYf{`%3mY-}sIJ6{*N2X!Iu5J+FbFct2*loRpw2h}KptVA zJO1n7u>#P{fU4*cJz8{gXR0sZ@{$%OZR*X-7J%#APag$=jz_1(EJja zcoWZn+7?)=c~i0vv&%?p6T3*#&}FO*;@_ryj2_c>%pZwq7BAiBUQ9bNPbZGFOo6$b z4qOUu(@rCJzFnSFsO3L0zP1xbF*gtj5yhkXZ6r8yLKh1CwysixyxZ=ThCmdZEa^0M zJq2_V``;aR;s#ajHt|z^2h>uv8;#t*No;H&z)e+BzA8E>mXKji4(XpQA!wl+N$&Sz zn$#;h9@LPf#hb=G6)d5FZOWE^UcE(a*t6M(AJ_7As2=yO^Lz z?QFqkb1jsRej#+{JJkWgcwGe-&Kl;fFAu?Y0~&bWbb$aQ-pFVL2WV=BMuSf(Mk3MW zDF^z5`%04YSB?riUO2+kbdvq;=CQC5=)nYkC*$%7H;*^w6NSIrTB;!{*Ds*CR^B<- zShB-H+L2hQ-&8$FZPe(emHRjGsPOCY(I!#Rhfa*NcTiTGQq*mEqQ4sFgv{f9!l|9)cDn9a5@w z)~poIxYTQ zd@1!vza0Pm!_BwMwp8?3xFON!AsbdGHOwyNEDdS)6mDO6Tv^!n+=1Ia`+NPyuRNu0 zwHnUSB>p;UeA~uTJ!aj=Lv^2UJ*lxXqTxd;=2=57+0T|zU@gR=X98oi@B8rI$A^4a zp8=67SywCO3XjMj{n(ssz--I43WMpBx?J3#N?wU->LNaI$#L37U!`4U>WBOFpL5|+qh_m;{KpiRLgQ<}2 za{jM`oPDd&+OmL+d`g(+qVRK7uCr#dz*z08vu|qXZXP*S3%n(ogU5pJSdryc)=T<| zUI4*hIv>MB-(jFVypfM?3ZDj)2LzLMA0RanRRXEe2adrt$4wjw zxY3D~9A)LvU}?&>GE^AHd;L6AGll`Oc64z0xW&^Pr!jp9Ck|k<5I53c2bo)W3JCX94H+It$tQ z-kk89K#k$!$YI=0#RBm+g#;E!Oo-{PQ+84LAv~GO>FL20AUJX=p_hSZYA$hblIVdn zAAjG_TNCq+d0{?JQ2MXwnGH|vCwV_lm~gn-M4V;J`5}RRUMZ$?jYa}3}2A>M^kc{r%8*F#~ z+dDy2>hh@@n_!PuL3g5=+*5!iRZZ$x5EY)5?`db}b*X+g<%w>lD*OxAL~YuIK=n)* zijbu>-P`-xA(cFsaOA`5)PAKM4RXYcg&Z?484%qldYE!YVCt@xZ43yeFre9CXo6V& zqu{$H=@}lCas()eQ&tbIHtr3s^%58dbNT0*L-Cv)1@II0eZ%JpQ2Kc}py4gH1%86Q zQG)+PUF8lvKudF3h4b?v50=H!uz4E`upu!`vY+X7o--B2QiRME`o@CjgY9$TM>vX- zs?mcO;`$mjvEkAykvrsMU-kEnFf&m z|MyE3Cuk0O6orsM3Q>?6RvK*9CiX_lO)grSyBpWnje=LXY(GDzp8&rxz|t(B4;PbM z4f4Wo9Fqh%E@+0JQUZ4>P`qXNqH&aLscKWh)wQsdR>7u2^J*!nx|Q8lv$+{tSGHgX zeae0`N>ya%?t57rTZNl(oLo5p5T_SLFEu6#inK$-3y1>&V8wGVfPi?pPCr~-w{~c_ zHn%{?n@G28HB~2JEX+cqa=?LxRmkQcBv6O}mqCKU5>P#=k4gOz56{Ppdr2+d`vocq z2=V~Z@Fpz>O5(fb@6kHMGD_u4YaQCh#NUoeeVK*#)MjVXTlI*@oIc`&H$D;;-dwTK zP0>s}cCdrFmvbJt?cO*bV6f;1V>g*31si2lilTX^6sJdJ)4_XowzTSMGI^lIyf)cF zwu#L=%=Mra202wlb3;T?kVVct4--_n6%^Oq+zf zwhPpCWyl9DeY2ovlA%r8JlP%X3Ot^Sfb8|}rN4()F6JLdFk*;ttQ=zvVB1JUc>n?Q zHKAVV&jII3Ic2DZ?`5qN-;bl1=8Z~>% zf!2tYbQ4-}JFhPWWuNZmKY`;;9UdZteGvEUg3>1^M+H>19Vy@O$w|@?~7xpi#W1jht?}$(p4jCXWd@8aKZZg*v$*K zUhG+?>kU|s^B1A5jmx|ztF%>28Gm`T}Mb;$p;@Mwrdo6=6l(9h(;DPKPh!^{`O_av}Z z8d^jFR!?lUE(TD5l2wf)zI-=%@MO-xL95V7JWpW8jRMUk!qlgBydP+UZvG3TKwH0P zlhvpHsZA~DVw9`5qhww#V7f(cGX3mU zQl0}p!9I+Fuj_+0qGFN}Nnn)q_^Bc+n~h2)Wq5M0qWENkNeO6Ox*V~;iiQfaNy9Z1 zQ@iA=Ta?x8MBY4YsAFPYdA{YVmVR2YQ;qKRXu{(-%mLk7@5t|UvyrhUxT4O!!FP;h zWTAE|3`mw^$Njm?^V)6d{@!<;!rmk44GSs@tVd)}8<;PNp3tEv0v7<8iH1&*sM=xPX*NK> zFT<+>k;Jj!9=$QpUcA;?8Hq9%x>BTJVQVJWE&ThSTg;n0%Gz`|VpsFY#lj#^qeyGz z21f4hg07P*kjRqK_4jLyaMWE#g(wP8;QTN2oZV z{c~kUDl*T&*3b=@Ce%_G9kyg)tUa>k)qamNsPtU=RAy{M~ zb7YNIHB0JWXM#RAM8$Iw1y2Kast(Z%Cgu64WKaYmT|-%NS*hJ2^rVO}FAST)jLI~x zP-^$3G^5{_(Eshhi15&sDVU1S+V^v096qsT5KYg~c21zSufD-+(NunDHhZ{acDopw zgwEfdE>lPB0fkiJ2bYAZ^gJbQ&{JrUvejl7Q8lSYeR^$3*~nGI8>{Clzt$6g91kc(H<00 z+z=m|0CCy9yPA~jmJB^iuHOu7+OBJHS(Kz2}@(Q^aO zwkkv!kkdCR1bMJ=Cf&JW@BV~2GCZMx?uS%kQK;3Zv{hVxdf-FUq>3aZ!i!?XxwBGh z&G^sl2CYU8g5x3!!5>hXbSd7qw!28D_mq{|U0$trp|I~T(q}jiMCyhkbC6!D%d7=- z0(FM~G;R^|IQpG#5OjgIi(g2?%lrrtE~%)Q0L`2$!)<-`|b1F{X4bcFS!&c zO^-RSdhNt;!yof$__@0YNv3uUYnugRr010Fuml@@IJUN7$!gX*j=jr0ghPmYEAuO{ zv;mK7c@Eolj}DP5>U#pVM{?x6ntWtvtT`d0B65b|-f(kr?1LZ1%sf5vXV7fBiynW` zo|jYfl>aJtLtHH1%PB=iTzM13BW>oOcbo_~O8~EVzB2;miPzgj3kz`@rz&lY$Ox=K z|1)qL`{AcA__d;7rNVQJilK57hmKV2 zIwl8~Egu%;zrBBT1<|~Z!@!WVbP}ttC@Ed8$vaO#5C#--B7~G+0dr|ll2iZz61{66 z)&mNgHyqMcX0x~;Ii9zhvW~#&`TBl@s#{IPNg@;>6MO&|08|qLX$utx|CGNFKfwnU zAnm&Wf-?XdXn7gm>fY1*Oeq2Y0PO&nQ~#u0LCev`&x!-RG+gnxVJ^oAucy*5sErhp z#6{%zg%uSS-lg?#mRcQKpksm4Nw{imBo76*fZYUXl=$DAus)03Au~d|d*GN3!ZtLI z2fMzRV9&Rk{yHwl=ixDlb+nNg%|J$(+9-Z&D|e4`9Vcs+C8cMo1*%pa6AZs4WgAcb z$w}@&KU#PAaJ@T^d6Ge$(59@k<8WGc_GvP9w;6GJ*dyp_^CQ0lk*5VW4qa{KxrDb@ z`5}<{DQ^#B@@^A%d5I2N5kWPBWh3-TMGky!;app&ZIXqp3p(t%Uxol=Y zjpBE^gh*i&(xu_~rh}EcGMYQL8{W-+wt9M`QH2TQ14*C%tXm;>5bV~P1KEG>C0*}TT81V}@WViP>o1k6!|)u}-U zHiDT5;Ft&~1JX7z)-EMfF1)j4!wf4&DILQ%1X+bdNC0#M41q=|>Vnz?P8yJ3GIoG= z%9IYjX8MEFLUB}8uK3^KH7|}RXBJm1Z4aIs$K}r0C7==~t6}+pfHyJ}}){bq|2l_got>*i#v$snf zLm`hsH`vjtHH=k>LrpA1P;IM44rL>5RxM08u-SBi`&z=>Fa`LR_{zwzD|^)ZBqF{h z$=7{s**0?EO@#J00<;Wss<_DBkd@B1U#C;{q%36uIBKE8KW)`eA5<<#Cb67IY zY}GdQ2yPrjK$e9Vjm2}_QL84|hJ7a?-~O@SZ7^Qiuuu$?)iSolD^0v((FFyJniufj zjWZW(xCg}^`8`=Tm1r1abvlZ%p#Z>Dfz+;KM?3?IONMF$-B`r8pj-msnZk28Ohm5u z*Ot{@A_*1*t;ozN>mWue7{{FA*8FU;tnFj|ZApZ+oMCcEypUVjmq`Y+ZP2-o@<>SzgL}vYwy<2M#n45bIahC~<_mPUNb%uR$ak}5jhz1k6g_(8Q^_eqC#vvL z8-%UN#dBT4br(tR1-}v{Rgb8G+c1v2*YaEV30X{W3pA9HI9d)%Q(vV#ZwZdA_+ELk zTvD;Ni>$PS^AVPxuKFLy$}KSno?d=V|3l~MO6|MLUXLQlyR~3Xrz+ry;U@$* z$SSN365AdSFl!Lwuc)!CDrVmzQSXzKM5YrVvoDdCfU)R(n&JsGDYCTDVYh%UG~4|^ z&&dEzD5bN@Bnf*$Ls6=m&{M^l&guve15!6Tg4O^$=#Fq7=-UHf-5?%tW(UmY?YG?t z(|{cR29Vj)pGeg|)Q;c2VMmw`z%qi=Chrk>2Nxs14pF-4TAhdkK-xP~nPR#?C;j_Q zl#1YV4?z+X8BlHEd;IS?k~XCoK6Oa(K?Z>E@6?$eR5d8>Jq{+rj{vR^5CZ@J05k(P zBLDz@Wi*xApEAGDCz-@oC=N-!}%yxMZh&JXT7?|vC~-n_Z|NL5E%fX z8GyS00|X&LsTby)G5LOj%~Hm&&aM@IsIg$O(b1;inSB!K}KfFxjihaf}%03rZjGzA9x0PeoG z`_^~c?P;C02P#Ns6*f9s)kEz?S_GglA4K@`l1P*xFw9b*0`NJ&l;MrFC3=-&hVl^% z2qC@;@E_}Y%KT?}Pt*fp`@HT8Dx^Q-zQv}D8PaVJ7~ zLThk0x>?z*As4nmLk=P5XXiSdRm& zhX;En1=O-_A)^g8s7OfJu~z9uBpe>u){LA$dPH@0jLkS5#Z9Kz20jQr`pHn=&y|)g|izxK8xRjBjHP{ z2ytWl%d=Q-b0x>}iU0V@l7db#X1lRWe0P)V5u)c>4B+1n`SmDL;@}4I^O1Iw2cJ!3g)QI|MHfch(;dm=Y(O|VKN_ei}Z-Qq_--pMacdj59 zy2EHwCM{EYPXPj;he~|KW;HX|liIJz!c%FHFe?2--4|sm<$1ouAxBiZW?m-nT)9dO z!@gvvT*8Z8O2cPZ>dIgEyVbVOCphMAuW(n&?FwmD*4>F}lTFt} z#h*yu-fytDv3^MGJ5w1B#Hee#w|};BmdDksds1@ic-@*hx2m|o=2fW^_B|~WS5!<) zh>NGL)y>2*m0-y{DW4Dn=(y;_CQe}-=^OoBCup>T^HfMiIKE)GzB{MP4X;hlN2B$| zdKR`~E@e}s{`>65K1fvw&n^`dV6lR*1oGJifh*5G4|_4UQ}Qph&l8&Bxd*+s(WrQjFt@8k@}e|(83fwkCt92%7~&KjJwilb8W9m!8Q5K=l=np|hB z07qrraq%y{Mw7&RYSJnx-?|7AWP=89@rAA7_X) zG>0qi^og1_|C@epLyh9X04j7}SBs>}_W_CS1H! zrTjBi07+Q@`qd%CW&ot3usIk=ykP>*=ub*F;N<8dKr8@N^99IlVY9rESPdW$ zg)ff)2{bI3aT7sm{Z4{`>XY1)1IEonE8uby1CN$DqHuUIIQfHc1wD-)Y&FmxbhiE` z(x)?4*a}i;H#wh7ua#2{_Wn;SKKLK90M6h5u*wPl3B&^c;&o6wLPWd}0Flz?+>Skl zQQd;SQ!TQPpY!DxAMUsEj2Hk?({=`f!!1{z#kYfLy)BHM5uzZd5hJZ3JvpO7UmmW* zpHlablqkfYjZ~!2!UPx6EfGZp1zOr{!=nT3D#GwL7Q3dyA$f>=I;!P%YV25oP zRPa_$^#sCc>BB9C-T}9*?`^R(h&E!cOxNDOZr=%iJNFaRKW!nqFz%(Uzo$%Hiqgi^ z5MKaMEr3KDr1hS

2HNUAo-O13kyzb#LpN3$m!X6AS=~xj;7;d-I8L!(s$Tbm0n4 zQ5Akq?O{}F0-p*a7<{^U#VW@tM13~8FV7Yx@WJ==WMg-hEAr}IQ~?kRz^T;`rvm|? zZztaZ^Z*dB44a*Rd>#PfTq0E;r(Y*MA^$QD0IMT2F~3ar$anf3YR=G8fU^h;E{Eng zk4U}esCZwD)IRlIP29ch(I*%NkM2W#@P4;<5zhK2nJx(JOYwifWPPp zNK9d7Cm`PjD7G(vh-I+(`hGrxAbX6_by~9qL#2!Y|Q6K znhlr=zNSY}NmiP7W3RbxlU}Lz3nZ50+Jr}*`-W@gc{AM3kJ}eEr))QL#^2OeHClvR z$CEXzNO=8LmZnziVAnqk^K#90a=^_pE0e|+r4L&5+cdIz_wgCUH_lFvkXs9jg_nO( zFdshH3j`3MnKp(F3;gq;Y&(3-{*)dS zF4T2(`8D~aB=w86FJY-c%ZXX1=WUmW3@f_+?1h=MqkU=rhBSwbx3p*8-ENe9s^7re z5d#PwhfgkhT{T|PqgC>NSWrMXc+$6(u9?yvw%z<+Wy=3#VIY=Qz%!iL@48FN)<$xPEv1gumYel$ACEm4p5u;XN4-c z4gDE^4MR2ghm=1y63?Ik(7$8(89oVlFIAuvY(s~a>4B1XRlW2c^e=1GJn9|~V*YQo zf7AxW3%}m@;uAFD-~V(EKy&^Hg8Z-3kq+IA?j1*~Kmr^CW5hfKssvbq`6=3RYv2G1 zQ7Z}nQ8tK56*LMfJOZfD_k1pwky81xGe^g{qq&i%vj z{~6=}{pC789Pft!v=9&j0000(15hFW01swamfJ5~J?$>xr0GEIY>u6&f?%;l1FkzG z_|FsdfL7#C`LfOb|M~v_;Q;^|nZPSB0E|WdvS4c@O=JKAAQ3*mXIX033QkJba;$U7 zE8S4an%4H**%{ftJKf8svUc{}+jeHNq%U*?zD`Qj=1)+cetHgKh1Qpn_oV0r`p$ zgd{)&k??^44*s-(QWT&DL+su7eN(4gPg}KHs+4BW zUGsC4w3t-DE9z?1mFY@)m#iuSVSB6$wiTT6RHa*CQt4Y(5qncaGZPwjb;#&_wifCA zZUKykJgFv2O3-HCEX{rP{NaiFGOSH}$`4*{E8fr2)b$Zsti?iqv8_}}EL!PKw-M}q z__5vDMcqNL+P8#H*8u!4Z)9Xq$g5guR7CwMOM#7A0gnm*#ccX!r!|8SWRsm$Fh+{3 z3AL6?V5}Z$ovJ;-SRRXZ|J(Ji0vk4JwAj8Sw%u)|O$(7GOex+Lb_-GEO}13nMNOoM z9DeL`O_cTcwmn@6Xmm)rdrK2eIk9qeKZm9RZ;%$J9!^b{C#tC8xlPD zlA3AJm?n(L4J>+XU{s7?tuh^irk}kNsZnf;uIOI+)mD5)N55EJj50GC7YR;Ga^Wiz z4={s{M-$d<1k2?YghC3q8fCETu{GcODGzgMgl^b+1DRJr7h$>$q!sJ>X!u2WD`vFN zgA9i4?{gZ!xoRvXj39L-lF7xtTa@L0pj#h?Glonc%?Kcx~* z%`vj2g+`&1HY>Z2UX`B5gPQKN;`-A>;^oI2Bxb**Jznr~Zc{uM?DP3X0w-4z?q&6r zzNI9@DMuu>8E0R+f7sSDM_pNs0!l6M*#I3FoFj*hFlwN9$u)Gb&K_N8lr)DgU6O}x zyzK8Uty{ombN5pJh{?Ehrk9XwyBGH%Fe5fFh#jA9PIFIkw@)#D1*~e}6 z|FQOz<8?beK1tkbIr3>{2Eksu^`@ly`8Wz05xvd}@A+a`r_&d9#dt(`!rfyY z;j=*Tg8Y4Cx0pxG0EF#d}udtBF{DKWWD;-q5Y~&PI_tkIq0NQ)60eM3Fi>|XC z_|!B72Xz4Cfw(V^QsJ?`zJH8&pdORa)FiCc!{SAb*ptOukr!*O)38;7?XuS;o){H! zpkXq{1W>Oh$zmmv7I0xjD6>=JWHC3;C&${8b$UYNBXGEGx+tV5XpR{)s$K z7JY-f5ewwMR1g}&XVnh}>tDT*${m&4I>F##T&R;bc=+no%db0re^En1&*GM9i^QQD zkncRkt9N#e;sKei{YS6-_@MKZmIeRu1{$5SkD1&ohedVOL~8X%-mPaM@7(wq>-pst57ETX#+J&S zYGRy~M33fm07`49mtO=G_K%C>Fia8^n02 zv_QV+K&}v={r)r*!7|DD6-(ox^j-|ioXmB_-Pu`B13n)HyY?a$fN=f90^Zc5trC@% zrfc2tsv8B(0ocU7@*A%oultR$;z5VTHR;x*M@bjIfN2hZvB30(UR?Uk^ko1E0)~>m zSJ*U=*C+;?8;sLZh-?@3p#J-v%qRBDZ?%jQB<*STBgC#lc=$k9$Xoye_XKJLyG`+A z@<3tnmOOZZ`HzI`RMfD;7m(oqF~D6f6{equinjp$i}&_YHNgbpgY%ob$S;BJLNELd z#wuuXStrQ({@pVh;xBd=kHU`JBY{vnY$M?htL%iM+qMzr;Y%3IJ2iH z0wc)tqVV%0gm!5>q3ldP;%DDU{C;aQWc00ayG}J>uPpOxpFTzeAQR*P7!-hLd41Dm zz5sB(1EcJ~_#X^I3=D5W04Q1?@nG;G(x5+O22p#kAO5)%ZsbP^AJ@2j1jWNNlv`Xi z%!sD|(6>~mS;SKdVz}9}MGENM-jE%f2ZY@XKpKDsK!&tY{s~w;*2QMvwv2WYz$ahM z5i9}XHlRjo3};)o++q|6j{XY?CIF%`)HmaM84o+QiQ0K!+k1tF`n98GK|VdVCKg(Y zHltfMbIvH+CPPsNwziH_m7NSI8%FQ8dZ?D~CnE2+Bf>QVsqT9n*uJ~uvdHwKE_C-8 z7DHQ^IB4C5gi#BLoUVTI$GY8Eq&wLLFa;%`N&S!sNrK1@gF#@c?Ny-5geC1$FF=aG zt23Xh6^8$jIRdo-vTMX8`c(>;!Q6^`zb3wA+})C=-zJP}0_^Nm_uXeuVGqFVS&FTH z0X)F~Z~IsVC=LJv(1es=d>aOXlK?n>RjT=e6BS1H?})sA1bD)cJz%sJ0Fkng58?qZ zx&Q+5Dn^uH0I7PjgbMzW0l9AaXAv7qP=EXzk$;v3U{iHx2^aJT{t>YV{U-x>Cj`Lr zH4hR6jD5mg5e{Gzz)c-r5&HwR0Y>d%0c8NR8xmkK8xK(f@++bN%z)>Ms2u3nUX!;5Df*XJJD%%b>Thm%k z)E0kvf)Cbour)(MbLqqD96=9eqJ znxrLcxG8Bz?D4vIR=NRj8g$;Xl>qB5bB46?X6!wX;&ncHO-moz3=kU*F1>8x+3A zrMyAH^3hVHdC}Ln?+e?B7Zr}tS2!H?p5C8xg5d$!Q0^fJtce}g0ZQ8nu zt>HursMhVJTG+QXB0>|0AmalC5I{hDfPy3dvMrGUKA^}ANh%D05Y@T`Sdf$iP#G@( zA^B1t31-M^&Fp1s2{l(MAt@j_-Cm}T#W#Jf+tQ~x7S~K;n9P`?ivDz^g_c;smLMx#DwK77X4F%CwB@3{<<}HYXWMIAoXJ*d z@$Kfo-P^4a%LSOI&abN$JSr7zlp1;0vS_qsLFN{tkzh5YLf`IfxYBy;XlJxSDT1L_Qqsxz=~`i2=M&g~wJjU#W^J2&Eiy|ZEV163t-t!eQtG=HZmbWMvUhb&cY8e4 z6+(2)rcqALP(q3rPT#CMYpkO`diE)$s)^i5>TV4`*-zbBE2#LF=fWRdk)V5B?)9v- zI<(X{_%$USKIe*kE)og)?wE?oQc|UAOB&*5HlBN8Lz8V&7tcvqcORtM1!wEhoGMJVPrmJD##>HZ(O0vsP@bYjo2hJ=@-jE68s^4x znsgvJTzPJ%wb+^20?91iYmtc&adeD)&xEOOHa3eL|Xzt z34;0~O%b^Wa5q>LwVs41NgnV?U7NHDcd$u`dLXy%gqdBd=ul?fl>y>&9!*uhAF4$s zL6H2b@WNrX&o(7Fi>)?hv%O@q2>#AabDPVoi0#Q6y9OnjjpQJ*uBHQf^a1{xdG4&J0Pkx%u&cbJNRL7Y!>C2K>g(K<~ztGhjF*r0WhdHAwvB)3V@t@v0V#u`@C3QiC4k6Z8w`{ zsbu47^s$mK{0e7d>5MJI8&2MTcezt>W*8YbDw%Y29^PPd9rq-#t_=%cS8^Bw#p0ZP zHDe^1IjI(@4!36WhgMeoXkkW}pr;$&V-ObzXn4V@085hwqtpPr-wj*zXorI>QZhk^ zYaxvh(hH`X01{gkbZiV%0?0hNmnSk0=dHpt*UcOxHObL6L82~aDi)=RutctIg2K^p zKE%)Fm`R+5M$noi!*;bQ#l)(Rjka5u_VK~1?Sh&AabYo*hd5#C3#oQaxha0v=%RI9 zq4`SqSE`5|xehA`1If@zh+UHhgVYd2Se^|WB}ff97)1w71P~w3=Xl#9B#2`*afy?> z@m;hs|32J8+_`mLkQ~GY`P{MdHH|gi^M7L7pDebCgXoV?w;Zj;c}W7A)Qc3B7GB+% z-GRAjIB3XlR`Q9_&kaSKjehfe#29a^hKl$4+LA@-9Y|ZdQxL&-eN+fI_n3!Of>8gv z-X#5MyN~p|`5Ppts)ihDIHQY)I!w?)?69iLR3eFrWA3M*k&iugRpytP0nV|zJpzB1 z1J&u#LDO2lOC#2fB-}M6K1kCj8zZz;Kl=uKr#vvl+NSm1V4XM&E6|%h=N;$1S^=J* zC&ctU=*|tW1VVz&|EONE?X1k8T41iKp%2)rFEC)*_iQ}TCK3e38nHA#3S(iZ*nAnj@3s-(hLh?0adV=&* zXvNFiblw<3?y1Z^a(g5}_nEd24+5UQ^MT=VV5ua5!E1o5A03v!=ohG#yCg6G4&l$u zLM02i!|RcQnV8I!cMrW}dNo<*Flb0LAHT*xw!?RsbHgUdYsVQz)3^gS!HR=NFlP@i zBuX&v1q^3H6ElEu_z4-U8Tm})B`PDC{v71c&-3zbwttD?lrzAlJ?uT9dFrD~jBnGk z%oC(?V?~6W2_Jkc#^l(pNNbpUv;HwysY&aflWPJY82^X6*0jnqbo-eY2OkPV=%(4; zn?H*VAg1BJp5wm-KAcNKa7Co_V2;I*uAiO_z0(EHsY zE9u^iVE8YQ|K9YIoefwnZz^T*I0B|U+KI+(1NhtU-#15isHl}cQq-)DGWhK0gPRs> zgCXjewN8jBO@d5vmFN~*QUb6{8I%yoBWpC--q$Dc{F+O8#T@&Cn-=+I4yahu0Q8C+ z*TW453HhoQyG?$Y(;r=1j*%VcBN+>(}EHkcti;r$V({N-a3ef-ECJ}pZgL$;vGLCRqHx6Y#xkHnPtUJY{x{>+;;Fa&VZA_lz|#40JM=MrmYs;xk8fK3g*)H&EXOo1ORnm- z`>1bP?D;qX-@lIs5T%obd{6u^5pd76gh!XlB>6bb1$ZpP{_R*}nx=baR(Q<3zK)m7 zFTGnxe#=Kd1s1*&bBU~{bYd&s7^pXeOY(G;+3Bk zi?+9M7nKe#BkA&fl-5Vq;)wT%SWf)Q=Dj9VTrByK{h{_PE>{0&F^dBNqbY&>Atv|!1VgMPww0g+!vf$)n#)nN3Bf&0M-+@8 z0<*vbgU|4`*V z@byzulOaF-XStm2GXfOe9nVx|s6AB=3xz*Dz91419}hh#awAFgrK8^TumXmu9PYu;fwqzMNCH4%(m_QKQUB8mx>$}e zWR!s{E`JK|5X2S*-H(%{O0hg4y9mMX^;A;P9}7s_nu%5919aY}o}W4DjJ;yZb4AM?4d0DX1MoN}T_#CK;>9 z@+2YJPjEI4zLWbnA(G`mPyj59ynr^U`G1Zu{78X!JALKn=t2Fr?mRu7Mx%y$u=}Xy zKU_`cxB&Ml3K}W>IqW1c@ua&L&KE@3w>VSaK^?%ulw`gn)7nw*0FQ|Qx&RUo5CZ@J z05bztG5`Q>RcWf~J|g2-cEOT~wl1~k(guS!yJ`E%f;EC0GH4%yK~Ww3WME$W@UG{-*~f&D@wz7sng)AbS;dj-J;7p z0oHhj1HL5_ckEG%l}?8Yys`(3@VNX|JY0vz`pT|jYKWMww}>4V*14tNk9EEvDT;Zg zr@hEnTOi{FHJoUHznltBraIpKY85`DNqo{OnmSrtI_nc)Gx$?GiY0d0RRKto$TQc+{}g24)1W^z9p7l%UNd3vD`_976+ z>|PJUh>1+CMRPvuEYFBQ+%)3I($~u?jMW)!w;qgG#`^cr$(Xy=BGnthiDMF{97P5P z|I^tmd5WB|I-KyCY*Ik{Udb1^debh>Vb53RF%3J$m$kRlz?~~u&c194o+N-oX9oj0A%2Ai|A=**v)X!|=AF6#=`lW&Idb`cx7Z}a&vzqHe zHhUF@8%^I@88KO5ZI@;JX2S7e*3xDbVQwt3t&u7keP3xOY!I*+5pI{ejca2j8qS@w zo{zea8#d7Zg?C$5*lD)gtlGr4qtm|C)UvVCYAz+(U)wJEwn`dLDtk4yc5STES|_0| zp?$E4$7)lDg3)ppl|MgQhBKgeZ15P}w^re1rkfSK6^@RkW#f^Au=n$$bk7sp00>bC z?shF*C(_mP6(8+#;eTmVIC(w;giD1Gf=JMD2iwoq;^pS{6uv73Z`?oCaYhm|fE3TB-yXJ$qcU10^IQ>$qj20Wl3>6Ja* zY6ALZZ;XbVr|t6OcGj^}S%ER(0fcAvuCg~~xqnnk1g=V+_xxiu?@#l{Jj;y4+0LDb z*?!EyF?-Pz?5lF(cd)7#@I34tgXqwBRgbL>R02p@l45#Sn>@deR%)8Fa6PAJ9{hLI zx@X2NIiBC~QZW;~^n>^MP`G=^Kk7wHF0Wyo+j<#q!6FQuAEpxtj`J$}M&` zyYdSU43&Q1IgXl8_63_5@X!u7A^MLPT838-%@(?0&>dB%Zxyr#EwKKP;B9oQLY%{vD_UiL4 z>8elcRf4_P?C+Nn{qb*1oY<$XjFnT44B8$kbVwWv58T#HlV#$mox;uk(uSdz=W&n8 z=)-D8S9sgVRpNSe0cT+(^X+UG^r7}b|BL8qQH}6>lUSSkTX|crS$|mXB?*Z=22YtT z`Bqm(Ke+#D_lZxE?I#OEh#6YpslxND@je?tF2Wo2_r7k3GbWX-1^?G?Ebg&@{||1{3Z-MXfl9hJ6>D)5b(nq9#; zAoNSKe7hG*cPORZx(m4<>rk(n_51h%iqy<7kHK&ACZKcOGUzvOrU-d4U8!Y!O|ITm zIY;Nm(AMPa-u}41;|vC#nxu_y5$`u01k#v%fSU`Y7(GB*53u=X1c(q)BUtRA_AoM> zbPz*hM{20RguBx|44{!kja z14)(wSf(cHMY98(O2v&4JQtxqx+Fy=(x{qhj>{GpA*AKVa zj*M5f-|hTj*3yCVUA^1}EWKm$F`@k^{WKj?Vot$ng{q7NDlFEu%%zZPCFs9hZQQ}8@PxoVfj$MQ-l4VOE8u*yh+&Vehz*$M2 zw8}O}(({FK^Y(0qfVmF6N*Mn8yVS1Rt4nK?vo5Qs^uX(ok}Q{9zo8}m6c*D2>bnFh&vm+=hOssiIhGxt4$6i;?d)eettdB2Y`autcGXIov-g-i9mFp;BL5%=oX% ztCn?X5fiF4zx{6%KA`+oS50FFqFbD0l<4s7m@XELd`y z1q4;p$kF_&Kou~)_azuqFm(T5kIV&+S#6u754+#KtqH`ujdOY=_l z>_QwpBkv>95<1)C)|}7Ma7nu%Y@F`3beg7qt=Df$yt9Y)sHn{vQ@TAiGq;b-zx`R6 z)B{}{f*{2u-hZqCs5p6{&b_>9MG5o<%jg_Wbp88PG=Y);Ica(M<03oIn&CuHl99!$ z^u=<9*5c4i=hJH9%^U#kq$d)^o5vsh@$Bs_{(^knZ>_msDLIF7sO z5RlU92@J#s+L&XZh!4|YYgs^IkR1*Ib)#kL@O>yp)@bz}3wQvk`o;oVNA6Mj8?J@~ z5-six^)q0s=SkmoAlHw1iksxt=9olXnlnu|vrKgYqa;kwG}`*CkLG;D>`i zxmcI>>2Ror%k>~z0uO+HBbGqxxO#64;me@_g^is;ntIJ10QAqCMl|0isF%!?AqmTJUG-0MaG^X*L-5{|v;0{ySmtBB0O8Q#KlU z{oem(MjOI9pS^PDMgzVe!Y2R<*dWLOKqLU7=KKuj1~e0FMG3F%E#88>t5v01G3GtN;YkP!HsQB=RL`|CD(1wxaCf(Rcty0gRRo zK(h)`(*QC?c##tlPJjSOQwby@2;{f%0N_)2&msXwY491o3aI`+RY<_N6VP+eviAHo{rjm30Hi!mRX^IfpZ8NJ2KeHBs_F3+{eS3N6+`{|-+rnG zAo`R1RIy`J{ek=((ZyfNPd7ha?dO00Rq(+`)oaS7d!$e00IL5meQ5VxIO@=Jdj&N` z2Bpb$RRnTq-7>oMh+6y&6h`80$>9uED`8;eCQuJG!6InSKdx!`V$={O+v;Awxj|@a zFKp} z(9iF}q|iD7E_xj477$3o9-H4l%nW*a5MdhU0U<*KTdQoDCXyYMgx?6lSa(1Z0K&~X zAj1a;`oM4p!KSe^L)|flWDWY1Jisu3>%1K(ynA34G$|&dKVYp85CZ@J05bzXG5`P% zRcR_}KSbuW?Sm^6ZB2^No&{q!x7oF_;G-x&hyffNAnrb+Hveh=|A@{20E`S+(E$J~ zfS*wzWDo)02x)sA*`a3W&BlSb#W*C84+6{?Lys+zf3;hbo62a>&R=au3p@ zUJ}c;??YLD9D{U;XAN~4r51KzNC15b#=h5|3xuQ6Hly>>OpCdDxG`w#5O(7(iP7Zn z8ipG{cW*Bv4}5;G8NPcNJA2lz?rnzQBUj_L3#0_b*i=1l#Nj{b+EC=mTS_JWtCk|W zTOo>Ssl!>P8pVVFY(SI0>y^zitk+@8DQwQ|a)bsN*IrMDDd5YghIv8--)mfry=e^c$ zWDlejwwv?uEv*(r!sIxW%}8R2(CL)qlt~tQIu0+kHg)nYqA3tPibY6dp4txn6lS5@#!#Hnq#FtfBMTxPu^}ysNb%#f1Oxc z)3oZ#Myk@RsjH``L>ayD&ibB~vc~@y>08iL7MK+2dwKO{+A^JGQkCY_(%o588a65@ zwzhqlZe4Z_ggd{?a~KChYpS3IK2uhCj+f)D$Gvp4I{MXWOv@y$p7=WIn~t8TwxG#g>Z{ZjrL8yLhpg-N+jM#)4Utm1 znqwD_%AamMa5=H>xfwz@>(4Uhvu|3G)Wdm;@yila+H(P8_@rXo%(|ZUfR4Ivh}4wS z?&C!dIwFM^ztMgJ+FpIUr~C@*?|_4J?xvE%u6wBH|t?@Z{e4bcB;AbakYYq3}ZYx!miH5bmIgz2rl~2$l^>ar6nwa6JQlnnOI~9xgMkg zgRPmxVPV6Y12R&p5g%Z^Iq%0Ni*pndJ>sJB2I#7t!W3SC)&tA61>uAz0LyfK%fPYAwyQjncj!S& zm)3q$9;I5=m#r_&K)TGW8u0B=-6069{%^!oZCh~2VH;b4Y@M**-Wh|wmV`_> z++0h7&D_!gf=9J-9n}X^ZW3+-li@n!f(CPsi1CWJPe>xFr?WHykhtiUf%6aW^KSzQ_yWkh-1c^~j#eYp-_gx8nr z57VAhiC=w~*YPI4@<11}vAz6m;#~INjG1Uz0%^%}@ z5@Q#ijloqzN3k0o(nqv;L4aO-xX=hBc(|sOQF6c+cvVZ6VpFK8xZn#GY=KavAm)RO z7m4X5Pk$~NofK;n34$R=C<@97DpuiO4ahP?-StnkD;txj?8iCfsSHJozk4k2K3Q$# z#$G}9{Y^umKr9?Umgz!-DS(3#lCbpMM}wgB*v;E+lmLXVpMUrn7ik zTndi=H|;~qa>&WYO#ol?A`q@Y5130p#1niv>|vURmGG|!49W>{yxX@g#M#Vm7RC<0?C1fDzO%6}K?(NrLhTZ+o zf_2ojjz`EOWPWi=%>gWvP;s7e)P*cJKl9XEySeZkh`$QpTA3#JcXubyGeN)o?Z+S$ zc(Os3tO#0|GrNR`bG*CIPknIn#e|6QPEX@tNwDzfL!K?u)df+;bxBUGmn;(GY3_H6 zf^f@nS81%j$<811kuO7dL!G<3?Jm9S5v*_?~9;+Z_MU)57x!0=>sCQ=)fT3&pAeL7@z&O z?`>HyG$du>**8=Y`JLMLZFk-w)7s;wzD|E|BU<`KU~F@GrhY` zA50JQ4(d}lo*!Bd+71$tCYaiVPM)s{Dnb4j5Lch(1WGhb<9pz7n&jAd6O5N z7h}0-8*VcZt%Gy+M}C{sfn(&*IRCp?{PMyF5kH~twtAA{Wxeod!**DNuS&b9lewo z;vebw>%D#^mF8~3Zri}{^zsVDxG~(^M-hr%Km9X$fA!4BaE-TlUXI$(7PTzo{|S5m zwMXG7I5NY`75NBkPSlZJ&JT1_r5i+T9g3dg!!{(CzLnzY?a)G9u>T*=;-%p%i1--$KaD)Xhh=R8@xE!|2rf5nGfO+ypc^4pnj$^KW zUHGbmur2y}w;?4`(m?9wxR*Ro!J<9mAUy#Q7(C3!5K_Sv_w9cLWpxt}kb&hBQk4~q z7MY8P{P8@2v1H^N(hX<{X2CRbRq!FnK)bM1TJnrHL^9{yB`HT1*zPaQ zt>^SajPQ)$EByd*7&zd^2rD21Ow_11iY5-|H%zo}KLE{0+Yli-_qQ}m0%%?s!^9y& z;k7hOFF1qHn81W+do#r8sc5mNRFRHTw5EFR;g7O;s$m6y0M`wZ3RVdJrnImcw-}Sv zS`7>U!JjTShXvW^lm_zzub+AxFPqQV1b80uIhj`u!gMEn%`6m%`Om-=WuNoQqG7lk zI|kO@{D~A%MW4dA;o}T!-S}t*FJ}RUs|Rbfr}qZX(u+f}N%JoXIi8sFZX}@?cAPvd zMub@nE|yN)-Km(gpl~>MO+M5fjf2tBoP?c3hR2KlHEq6(LlhybC3fKX!Ii+T|DA_t zd&O0!Z_uvK(ZSj0^){geZdk=o5+cQwzx<@pdn`@UugIG;ZPs!9PdrvZk3-4@2lHR5 zonk1)!Y@5cGKj$NzLO(+tIw2ox}8CQ$*_$lVU(7Um0NQchCZ;;_(5J@8x{vpDSC`( zyR41Ra)dmY&?-9l=~vlzU5ywjuDo5{*4uGTEet(>B4+zq9(#GZ;;hFtGAdMkj?sQ_ z^X6hZteATlDGQiLQ;T2)atT}D?Vp8dsf{bydt{IUm3M(9a{wA(Q#u(Sc*Gfd?g=U% zX)Ol{0M@4oMyV!nTew6iqp}215~L`>+$EJD%1dF7mfxx>bHaE1Ck5YO3-xlJs`}0KWKb# zlmu#H#_yVZo40jfq3O{XSRW_=Ct^M#Y;cDr5R`!d33^6B0Pz_#kdwiiRml6EjstA- zx{?yd)mk3A)wfZb;bMWof#Sw8CZgQs4b1>I02TAR&8jvH$QGJxj5{|#=miBO1w0P? zQ6^9lsPCN@oL&TZP7m9JOk>LUMt90Wy@n?X*yuR_AJm==c=^lSjqVzgv4d0}#^<`c zA@BZl!-WYK7)$ELwG>Y#n(^x!?U4U3#yOZ$D{Oh3#O88_)+C+ht=lz#umT!XbHhTAQVbLDr7U>^%>@BQoxvgLYS*6Dhn+yGC4{#i&zoMLAA4?rc zQl9v>XOaGt4o--?z%UUvG3lUPP50Uc5Ctz7omIhR*vSWKd579uRb`YC-m{{}SQwm- zRlPc~bK%&GU|5%ag2)W4=VOQ~;3}NYnr8U_NV9?ylX<*{q*E+8QH5#f78+=3D|*|d z$tRDMbGEkcgk}JQfePODyV(G#!JR37;{@j`wpMmp_f5vva%XN|$bSWKM2_6E#YL(D zNysRh5D)_Z002XCHzNQ54`qIlyX0T(7ukUBQjjJRK-Y3|qyR*N!hp-kE|7&MmbD$rOgnCGM9&H=Z0@=5idZXG=|?T%5?O2{0vPPu@W#p5z zk&*7DP}U#bhA6Bhd#3hzH36U{e6&x>0PTJ+anC?Lt53IfVmc>_B^OOjNLkyo>Nl0wg1Mt zXXMUYri7c4HcMK#grX`te$urnlDz8NG5Yr%P3O(J)T>3i-+TeR*1(`bcs=eALa5Yp%zYsAz0Y2xipk%I(&;f zSok>U6^a9e%e3v?G2vG?vJ!pF!4_Ap>#cn%n7qH4F_kVkvb$QHwQ-5rPOzos=BB}= zAQ?_~CC5=Oa+o_kEXlUWa|@m^)m99>R<^cdEzE>nl_P1X#yZEYlb4c^F4wEUm!_>vKEa63thAYN0q0Fd5$Lr=?;Y<2xk7vC*a1lE zA&uDc$A|X0PjH>pmj?%uV$-ul4F!etc#}nza-pD=Zy%+(&=*>BVy~qB=ccYc0{ndK zlK<$hVY7+2SJiteV zQiL;GzuGl;td)T!V()=TxmP&h>#NzFbD0A>Wr8B(_1^Lr1n0;Mv9wU0yR@j=S@1Sa zVq`8#7i-QJg2zv6lL^%X^tC}w4k&{_wI@26&_kyj1=r`mEVh_V9jQo((A%Y+n_LQE z)p!qqn-BKm$G1fpcAW8!)7YQ~DW>$RMCBg)5AS+1C*?V7yB9 z8ayH!gqiPX#|)&D)G^tA`k~Jb2>q?4PSpTH>yQV8jEXd*WQYDfGFk1ABL_Wq+aY%k zgZ1~|SQMu)Y-C^Zo^D#~s6!kO@=aSJSv{+7c%YOy9ltd{5+^ReHJd*j>JG{YyGI78 zl@?wtwDifVc4lth?eJiNAotUb*q`}3sm<^8btX+foxb-nGXi+$wvs}QSpTzl2yd7& zlJvWL&O4Y-F8r?c;Zsq4B-}AdaoUNW0G`V|a7j2%%!Q11A$pQ{;@F5;-V>^&(BMzbOY7*$ZY5#%wPNujyvi~B%!?fKyL-R z%E*4jd;}%5-5-_o_R~2R7u`z}{c`AwW}OacUT!>YCKT#iZQWvIP4r7Q;zp=1#49ug zW3a3<@Z1oj1#@G4BM3kM=~clk=n&UFCg}*m9@gqf5ry<)25Jv~HOH$-FAAeREgoz_jPpHo)CE45arn??0}0f^$;xYVy$~v#P0;0-WD$3+Bib^)$^H zpnZV5BZ3ADFc00V5NBr%lr3(Slq2p|ew;85^|x?l7b*c==L0*5R*`^Bk>S6zyZ9VP zUgO;K25h(zqt5GlK@E!R=%OPK2pknp=qRt3R$q5lljlCa(THy>VH_wu@LX#`LP68- z?SSQ-!Ao?nFmJJ6nIb40H}qgjK>RZ4e8*_S)sEQt;HTXzmKe`#cWJ9j4-vtXloZ?F zs-hNN8hKjuBlVx)e?9H_d4c=qerGuX#I{772L&7&_CmKD))29SUZwUYAGGQ(kh93o z5o*IL`l@8KtYWb~j7xJm4hGHS=pK*LzS*SR0epGcyJ?{u+S;Ny;pe6Wi5l{mX$1f2 zz2Kf==g`;m_DAJL_=R>rj&a5rHRyF>@5R3Jc&F^A^!L-FBkmOIEx2-8k$88%x*7Gs z>qd>nLV+(xGNAg8QpM3;B{9$?BR98LlT-CxB{zsK{tFUw^C6HK=xYK-Tvsc9~N(u-W6^)Q5nLGpVd# zj_cMW_E10aHMKK7&=^i#IhcY!y$5Y_92$xjkV&ed8r-2Ddv zv;zl|`+b`D$)tRVel18Ez`g~?yl=|u&Rftkx5OPF=&cohM0SPXf-KNDDQ;da2PW%4 zil~@|gB@QG89n`z36E!aAV_A1dN=e*Q_hpLxZ(TZ5{|+Q3{y}XSV9!Olu+@IUWbQO zCbu0D^MET)?Qf4te~g<8Wd?_qPp0LEPlnMrvWQ+GjT`RK3~)KpF!|PKU-2DvnGmKk z*nZQpC{>FB0pEKN!1}5#bvzS{bZCrbKuma)SO(v9B4u1QpkxlWohZx~OlO!z*n)hv z+hmK&R40=$R@+v{T29r?41IgP??y;WO>Ms|Hl`HJYy#XP1Q=$)lphc!VA>7Bz7Se_ z{*y48ij@D5a#4hzh|aN^)FN-}N_|g~*%+7-b5G)lQ4vv-o8Yy^DZI4Xj1}zxE)m=) zPGN-aHGPppUt#RWCpK0J3!G3P^cYOf@kb4I$J;k(D!?tBYzVB4*_r1DS{8oPl!#UMO0{`xlUbf}uWAGg&`AqVKZ)jYQ zO}H_l#zfF*vq3~fE|_#XW6R|a39EIjNYNNCXsuj9jr_OGFrBL6bA7KCG#@>q8O4-N zT1TJ}r zJ>B!f*uq6AgO^fcwnsh^6;|KpV?tu>82k}UYn2?3Rc`!Ii2k2Yo%4c zwrRB8wk`vxMCemQ2wGt|>b9t)$O8pwoBIHY9P~i{pK?X;7*r4(Zk4+N2WI@mmhp?w zzjNtalOkUiF-aVHJ!|4<{QpOB!Fb6i#%U&SxOW)&jv}i*43RrFIV>j>mu3j|)`_l5 z1+NE-kT0PCPS9+He?xZ{*NU=dEBb-xlqRvQ5OQ|=XYgI?k)Z4KUM zLXg}>^X=WXuDV!Etu{CJE1u?M~rR=+0G74>G>rRtskUo5B^=` zpp3IFrIN+b$nl-Bu|%YJAsX2ipF?okL*S_kE!!L1i#c!!(NOQ; zTR;jb3AzjmSqwhBGX(@l0_PPL68U8FPBAcbzCj#JKR!qemy}h;) zG(dv5yA`SLhmk235pKr1xZ+v4xMf-IIstX_I)rZ3j3`usz9DUb7r~C`1S@sTaD@$f z6t_h{$SRz~k%kqe>oRu?Di2u%ql_DJT5ogw15P(gM&1FZ*z=j*M^u)S!ezA# z)mf&502A+rXoM6B{<2jvXac6V$>O}K%|US8XqY3qgMDJ@^1NJWio_L~)vjz6+dw=?7>4tl?l7{0tB}%_3UW5YG{jn96%TRtzEW87gKR*QgC1 zRs$%^CRY9rnASI9Ho>|iYRi*bk13Oa0KE)sHVKB~u?0TJRCS;s*%mQ%wZ2b2L7;5SG8 z#{sf|<`t^EDXNLPC=)4cFb&p6X;AGz(sWVf_+ce#iw>Q4`GI# zwvk=B6}f!`W#`E^<@5mm|0wjOChD>QhSVY;DjHEGidq<3m7YaF-wGrR!lAKlx<%xz zm%NexWH-E+KeDmLhWA9HrJQVLa&rIm=-hXagC))l|8nlZgpgmk$wvkd9Pq&65D)_Z z001*nHZuSKZdKr@?i`GdreF@xBUz9@ijyrg#+U;t zEo<(*yV^V3>01}IP}7%QzBFu`O`l&|R76D3fWFbOJr)TBMA9HlvIH+eQGNg*2LLr9 za8L#X-uu1xH|Ned+I)7_%yz{WwzaL+bB&-{HNT`t;Ej+GA3;7DmN7*b3_=m_K(b*O zgh^3?_6D9|;?Orbe?>#mh7EvcaNS!kyWAEu_GDx||4 z0VX(H+aV2tvoW$=O@5(%2#r~SwvDeZXFoVapbw_V%;ry+MpP4g=b6q10KK34tXf%u z;lruwUx?VzUbx=d(X>}C*gq-j`e!U)tK%!&GB2_ViEBC)nuwr!*B6oMd7LTj&Ba$MVVRGi-u8w&qh+Su#yb zBWRzO`uj$ElN5Sx(10+NmwV&6I*UD>?Krq02I0%XuV~$=R|J}uAiK$a?{N{Y*{Pe7 zvrw%-#leCJX%PC~)y`U%4OTi82kJxlqCfAbpdL^7bntS|UdO_(`Ru&|y(PkAp`}4R z01#YIgJrZ%C#Qf1q(H7BY-8d#kKD2h!1fsq(5Y!`PgT3D1{5;x-- zH9uE1)%JmLDU7O-f`_L$*$@(Ax}yfzw@{`HA+Bm3p?pu^=29vrmz^OUC(y&A6F!dG zw*x?N=sD4!Ka;b2xfa55I~nZlpog%MrGsfepB*$?>Av z4w&@(4BG37@mG$m&j)c22*%VM@kN6FqI16J&RlMKJ#RP9F{$swab^t(X3rI?*Of*) zi?Emj=H8FAnVm{jCbTLQPr_Jco6T7eew-C?9jrqIem}&KlXk<{q=^!7XHPoF0Aqiz zPoDcK3kMKK2r6jjEZGegPx?}sFKz2^Dsx#HF=}ue*k#AMZ!FNT+Z|8jtk-> zIto)D)@V>s1g*`)4(OnlTU&yk*mc1(M%Z|s`ZT%+v3iquZ^LZesxt5Zv1 zgHOnByM7_eM#BGjQ&DjO+EimE$GqV&a+?&!E7NwqhmHbCAUv?lv&Ftyk(TX(B2Oyb z6@F*hBnM7-=ppb7PxPTqcn`dM&UfK1Bi`H}P=ekF4^I!q4g{z^*pVSPfY5nIve+wv zOkC_Wk<5-P>fjucH?<)oVg!?5TJ^Lc)BD`af4juP_Fb(?rkB;@Wk~r36(Z13^5B^` zC-&*=W{88%TUK8qGeL3?e@&s+uljjBL*4`UGMr-!W3P*|_S?BlH!=ihp*+a%*hsL4 z^gG;7UeP`3ScwV_&;{$9PhOqw)Gr=~zIqq;Ia{9ELrG0FoC8@9ytt!xmhq$Xi5!i@ zgMNPC2#lzS(fr=xaFek12z8U4b&(JB%xBYy(LE+>)qA5GG4Focg>mP9K-AITf?0u3#jYOAmL>o~*Nz#Qk2mv)+NU)Z=PENbLxt%#bMHP>qHt#?xW2 zYGoH>pj(H(bc(eZIrfkSzVdIDFB{K`lF|ys@bKoQO8(?53um1U6Z-F-x|e8|$X2Ri z2uQMLy_SMR*g^v5_pI;Iij29VMa>sy>7!!W*zpB4S1|~b{YS{x;z{#g{D<7Bj>FJfi ziP;tKx>Dr!Pn4o=A9Nnq;6IID$?1{F+4NHW&2sAK;4=qOmkna~l<7|fpdsc)VA2i= zFM`%0?*Mx9uNahnW!scD4Ae2S_`B?z8$#?V1GNrfnD?RtGTW_hdbEpjM|BtsnBmmY z`26NtmOzFtW%6Ax*LLa@2s`w@c4}QAW#w=`gTHxtsuUT5ONVNRfud*FA^f$zk*w$# zag}X6Fr+t#>*v@=AqRGvB`!!><`})+rgE(vppc5}jP$*bq{4!ESP`249SjZ=*P*%~ zF@V8`H-SfnC|~F~UqB-kD62tdD)@rNI;dzUN#*^~lWvxE1+b;WPZ#ET2US9`8+EGk zp(~bgimiCkOvhu|H2q3qh7KAKp-4d`)6oaM#r`mb1_x$R@7CI_8&rb8r`#lg@H z(fehsjk5M94l(0TEzs>=Di35=t9SKQwz5~cz4i|K`%)rQr&=pkT??ZwQcz%5Q7m*O z*spL|lW+l50A&ud1d{7F&pVz{QrCjBD%y|u+`Ong-lmf`czx8dhoZzQKxsn}v#6<) zIzn(|!0)R!2=GTNW=^U$T1$5fCGTIm7;u`E@oL$#EsaKL-5!^Ge{{SX?TXJf>rC{u zkqEfoPRPQ&>=AEM8cssD8jD|M{EYA4vD8IE^^B96b*bU1H9?Nh4TtSr^Ju# zBS@F|k7$O0f+_4RzCtAti48K8aZ#mM=?yv!l+L}Oo>fb!%-#wF@pG~jx`qn`y)SDh zxv1WITjv1Q49^zsz*<8eEhqfP47|Am^H8PS&gL`Jg^HW;&Zpf5l7N&QIUrO#z`7Wp zC>zqN1eiR-M>txS8DO*xjS7P_?CW);(-|qAFDdx0Go|+TJTA-8B4W5Z94M=qM-(%B z-r2#jq4x0tr1mHjz(fBVJJ*IJ4e!nn&$~AyeV|Pt3HmKNr}7-wN!|lcfUx4%$)*So zKOT;JfR&**cb%}7-UjLca>%=9jp(!eZRtBoFNT`KF)HI~ryENfsT|h?&2NGI=Dzb_IFjWRkTh=EdH8?l`wdWo{v_Z+PfX{Y1Y>BNZ0j10a zV^4_oC(2X4aV@DfL02s}Jl}zqSPt|vI3U7kmPPpt%MYJ)itY-G$WVC8hSBo7?#9O< z0zX&!r)4<6yH*scAtwh7-leE&bvCZFkey7;wYa5GBe@Z%W4_t6@a&2+0zCPqFQB73 zvf#UOJ4r9kz{NeNDfj?^Ga#T5n3%&6rfQX`_BG+hA>bY`kOq28CTb7^Andb}%E0~k zi~M7BE|Ive+^7(dht`R#HW>qswqv991K*wDm(RlbC$V1sDCp&hegwa}z0zGm{x*4eSK zc~f(mIOI*qGc`Ye38{hKj}O4Cb1e|!MnKOCY(w8qBw*Byq?+-49T75iB3*mRLEojA zkm#`KlXtJ=sT_p0FgqD)q_ol~6IoFE7h5vHmcqu~JWv}^c*G}nL(->ZAL~+*-!04Q zR{`v75#G+nY;1?Q#>+$zo|`{O7ercCTDO()B{$igz!Ygw2Y23D*f z3r`WgZI{JYHl;Ce0A#Y-%fD*t6TXkY9-4+Mu_>f^6i_K%6eB-(g)F|6es=+C)@f;` zn0B3PgCyJppt9$VbbSXJ^^hpc3nSG22QsD`V1Uyx(dvcAG=79-o_9dAC{w);J1#R6 z#v~bPPG!cPAR!(0nXlm)4l#Dso^K8-p70M#7Jp2E1F{y)X+UCSmBC7+-4UxJ)JKvCx3e(?OFK_=k`6=Lv zOVIZrS|DwNZOA@VCEk%z9&0W+g=@ajev{VS<;$YWhFPCjRi&&k0)}v z&T>n9bj9&x?bNu+$ummi>CMh)Gzl_nGV-2D1yil6e4>lnZXPx?E!IlmS;awX|BDID ztJ{&=)IY$m!zi5?=v9!Xy|AuJgs!nIBeQjUZUd4tPYNRyQ> zN3m@g<|9{>+GagiXk7!;rT44v8?AOIqJOR`Xbo(Mu}RU}YPmS|NNUIKjxmg}`j($1 z-2RQy!uk|R)&!5PFe?N{!&v1MtwhVanXYYFiQI7+7E!p-d~iF7tTa&ZMVWDgFh&mT z>OW5@yc0-mmC=64D6ok}0$YsvWKy4eTs3F{mrq)D=@;l_Qf9|~LC zJL1eyZ8vy>jIN=L6c(UoC3=@%ND$*-L}yb?#KUr`U2Ou3AaRak5ZmyRZe!NtF?~Y zwtIU3US)vUXTSC<9#trt6#YyGI;5p+cKZHQvW+5|qStzXloSa1^!oVsPdW`ApC|8n z0>uCTQUFyX0B3(d?|bik?!C|~60OXr3KtLoGF=CBbVvt;hfK^w0tNM(pgNXM^3?otrfM_=Y9@7sFdbGV zPE2?LWVS6Y;E79M8AIuePL+TC>h|mLEtm@h6b8%E*1n5E@*+bl!7PNieZC_t*#%jC z%Em4q_Q>aq=qJ-wT(6Yka&cGP)Kw*8b*6j^6xJwAPS>-rFjXAKBYSO2%2czEV#+2_ za`i&`+t8XafaD42_hO+gGP@2|An^M%`6;O?f(kWz4CWs^oGOoLTMa=@f*<2`{?i6k51Ps>vWg~%(Y>lP^8(99 z5M8Po+1LerR9TgQ^HO%dy@S8gN_pQtjmJs>l97|P$e)*50#hLkUPd91I#A?Z>O2EF ziJtI@4xrS0pj(L421Jyd?9uLu+c9r?Z!g59&6&EJd-}e^9-9M7Aj=o$@AI}o6?ELc z%`g7Cbm7m2aINF;4kOJFsTmB_HLMFCt(1?VX6YrqUp6~ELXhr}d#0N*l(ZeYqLrbb z&!~&KT*l>rIWzxe;-QE5YG+i$js#ZsxZiW{pJE0***fBW34PusQcG47)|AkgU_RUX z#+-w#XvouJQChkw<$Z^`*+bc3^Ed4nn|Iq5?Q~9Rb23Quc{a|*uV^D(X3wx$o@Ll( zQkV(7>p@mR){N5I_W&xuY2!w%4QBGWgohcfa1L6i5I?p~| zz!(JCGPC6Y3+Ut>t@hfW9O^m~tIOROy~S1F%0{<5z&ZuNPp}xjT2z4+b>s9W+*4OD z!^}2rfVP1cbw()LEIb*xZQrCcr5P94PX+;kYCXI8-p-=D?Hm;T$Hb)js{R$I<8C3* zUW!V$g~^g5IF%KIgEL1*35F(HY#neJo8nL4RyiHVV@ z;z=7}JYwxSxW)beL@W?{$AU+H5;~-;SpBkCp7PPCG@8>S$fDN7u&)No{dAXMF%31i zyfm*$MDY?4L`Aq5J0cs`Vx1Y*<}PoDw8k0sKgGp9ECmkxnZjRmA3q94glrx4_!LVO z16}d!^>YWh@uMwX(`34Ujg#kffgiDPU|*yTm|K}(y4KWHSnJ_Z1$&VtF%k~zx3HLo z1DabwFo{O7oplB}&f7mDO@y+_(l#^+re)0-*aDC!rk|!nMs`A7wW|);PzGZ2<-*;Y z8Uj`=CY#y02sXb*a{{wl=C@C`ej3WP6mW61w`>x#9{R{Xrqri)PD{@^9H?28K(r5z`lf#^apL2NkP)HS(OM-a0~4Ycgdsxt zKd)4&l%pT|Dbx>n&=*BagoTg<+klEm0%CVC((D4YE+t#->>@#kM9f+`#Tdf{_5BAPmVlEHw#0$qh5~L=!@U5qCNt zv6wIbkv67^^br5U;RGGeo`h=S|C=YL!rlhdFcqTQQ1 zxNoAYz+*cbNolZ-H+2(XWKKM&8&m4-J9apx0YSd4Ohf~2pmWF49Y-~QdjgSZegFH1 zShc~%`b@#HkHsbf!8bBVbvGU1!VoapkvBj}ni;9rUzw@Q4UF`f9S)h)TUe*Pi$f}K z-Ti~78x-V6ptw`#8LzjAua9u+nQKXlUc$H47>A=EV?9KA@ ziu-lwSwPzdO4n3fTFKc$3-SJ9uTyqz_vkr4)cL-!YI&HoX0{1r7bMd;SiA&KZ-5O` zoON}c(5=4>p}3a*FXtH(NQkPxRQ=~WZu4*7?6wqmx@ zwRS}(&l_hszrkjdUo$>CGBsKw#6rIS9aJ{2TPbrl%1)O0c=^84amF+Buy`3V5o~n5 z^2vNhFo?%lNIaVgm8!I@tW{B+q6*B^g4tfDysf?8lN)uFA5E57EQ_)IS?|ck*p_K! zd=*wVytT*H4j}i@1Q0Xjn{`}!ClLd8^K92k+${NGAdJ_!zhD0e2&3})4gJJFNn<=P z%AZ_aNn92%`7YxO5A%9HsUdDQJX=!xT-)XV0lk~HSF4q0k1aL4yc&sJeHb_6paVq_ zT}LAhSzR;yOg)>GrY3u+cwS|!7}OBQNgP?kDwcFzTGn^?C4T{mwSF_|wzK!yH`9^5 z^9LmjmPmvR+VY%2hAkJ1`@yEtC#T0l8DA>;fsN06$ToA6ww*(Ljlans&(rL4W&WiNr}h*=`&VTw;?CJR}Z!Zo(YT^2{+s2=JO zcUJUH3w2zrt1MGt-o3j%YkurtXG>>y#{>{DV|bthHvK|Uml$K8!lYtJMzBSpS!W~Fe0H3 zPUo~QAz<@EoA?+JkO=noBX$vABe#tXJ3zhjU@QY3dAA!=AGFCo#x{oTM+=3(#*^l^ zlUI}Iw1hm-W;6@M@t3h5A|Ba6kaEiDMTQ{8ANd~F|!)`hvMI~IclcbW-3w>D>-QC|C<02@K6;!~zR5~?N z30GEg6XJH+t6nl6pfSwFbuwE3= zS))CD45=41k|rm1njMJPU9$tE9viVS{VNQDoTg8feiSd_jJ!xC4h0$zBFTVQ9!_LF zj@;P2IF=%Hsl8Gl=}2qvwgjZp zppIUPhCCHQOw+U9rY2MC0RPUzjsjH;U(r<~@}yc88Q-WQ@BsiV^G`g;BiU)FIQ)%C zYVZjL(2Y}d+vPSU0YR9w2iKU76G}iE3)Iy18x!iFA;UOI6u3cg_@`~|rUyYhwE;@K zdQ5o(uz{F52JgVubO$8fhmKC?QQ44iN$}xL!b4zMNoJDg{%?H+0mGAqd0>ln zbB3$SrE?3O{i`Fjng0`+LrB`C(prLC3Xz6?-y1 zl+5x@{6NCRGR)Z+i2FcNh53$Q$J&6CK6`C%G+V!^7OVco?HAz*3+@OUVIkEkyN!|l zEYWr?eP669y?N=#JSdctIC=E@CsTuZ zECZ}+Oa7qRypgy{f*u{;#1d6idn2#N;;gT^?E0GivbXE`DwTnL6)knoaBS>oDzL zH5-kABS8uW84xUz386eV8YTBgM%A+Gkd6lR3Y4P6&4~t6&ygguk$iZ-BLF;X+yoGi z1C2@JqOosm|C!G3t9ii^^gm_zzyBux2cYRT$Yw}K;H9xZyrv$b|1X#TJNNt0Bq(1* z!Y!3pOTXuC(UPk`=b{o4)jQ4xfrkTf8e0QPDMo{u17``>lOixNzf%gd_5;7c;+G;I z`v+*m$*UnY8D4Q==6Q0)+Xd#MDI{V+dxsCa{0Q$4`!uyE=rfru-zNRb>zMoT+wIM2 zY^t!RDA2$GyR&ixsCUhyV^VfVXnQ%#Ti-_Op(CZM+O9G%0ihz9P>o1+sjiyM9Y`8> zE5Ue~GJ|W8kO?}-xUuvCSWPyUKLa95Z5{E6!^@0e)PV`X+}UZibRci|w{+&X60A&# z!)_E^ADvV9uFrxa9j2Nvl1`ad*rW6(-B5yH`tFt*>wZZO!Ikga0H*OhmZOt(V8HOk zM3q`X@jfwquyZ$0)a_Gn%)?xg35ejqN$cr74Pe8wpEs9l^`8R@UBjpt_zG~P3?LuN zO`uWx|NIzH@em1VMM;SnCEEihx7Y89?AE?C9I%^#Z^V@jvVSN^HQ-aWlDQ#g8}0rb z%%Odd@XtPMVLVsa;v`bFN3oS(x*#9D0Bt~$zgoYNdpUfD<7|T8oqaT~;o=rp1+RHE zUJ3OD9IbHpqh*BzM~?zIi}&N@`H?`lLxC6(AuU;s(I(c01lg0r-=dI~jTv7=k?9h6 zC-U^H{r&7Ln9=|C%(9wAN1A9XT-CtQD0eaNLKiv5!8R4W@gi_fVOaDp|g3e-Bqb3>LL$Yf%kmvvg1WXBt%LNm}6&}Y8S(BM6j)S!=cSt&T z#sPaUVkEC;V+PwMx9AQB3l}g5M_%O7Nb@P^N<*E*Hh>b@!(K@vI-q8+=)iMj=?5fN zIEF!6KvsrCr~G#|V%9+a)f&1=d+O!4ndOZ5DH3_o zvjnVgh9PDf`$o+Xt7v;9-a0uD5CZ@J05fApBLDz@W_VSem;CCT$Vx2%+>RuaPzH;m z#lT-%!}J`x5ZGp>ul}1OOD!Y>+Nm5RTtaaUAsEjYTJ8XYn5}`c=%RGwyopFqd!*Kj0)d)vemZL z;tG%6r;yNV z*~SSNV`^ryNa`t)4GuV+%~2~5m^n>X+Nexo#;(V9nw|7!p&rhW2~WDxJQSR;r4Tu4 z(9Chwlwule$`woGRFX1ul#Y^U+h~eJ^4fi3S2Os^Kq)YJt4)y2lqrqyPT3OAoS03O zmzR|i%Er7svkt;op_DU#kB{&*@5HR7q-0lqsf@lV(3W`gk6^swx9FOU>34au#h+xZ zmg{K)cyiXJ#Df7&Sk)y`nMSFRr!1$9W-JHJ!q%f;386Yaoz_yO`SxiuTAq}gS-+;8 z4TdyRX5VIjLM^77k3~9!Vs>ZBtV>gc@^va|_Yz7z!Wt9vX9$~Bz>W3~?`$~sB4qU_ z)yGYA?EsvkjcsnEI>kXhGi;W$xmQuIp(~*Md(w zk3Tm!JuC?k#8(|TM_5^X@aX$X)fSw|&^B!Lz17k_YXaTJ)uHZMS99o77WKh8wUY1ex448^CK_>cM+S=LZRP~uu#`6v~ezlZG=OyR%ffZR{ zaeaj5fhI3%m(6SkfY)aa)i#4+!Ts5rseAwKD<+TK9L^H+th-s~$#&0O`R^39;z~S> zLRu=KYK|D%igh(i7PMa5Q~6$phlC`77T7ummd*>hUc|%t8ZPZh+eu z*+q|5L0ATc={hD7mpurv?YShf$H$tkoi^&b}= zg!0<^!-N8p_h+4Yo^>J#sAGUc^?%f>q` zFu2?!MZfCiO>F=XM6Hbme7|-zoxoPCFeBo2rGLDhL#=J6(L2HydvqQ}t z4k321yxRp^R=sQ?p=L62+GnI=&vBt8Yhf)ehFh3QX67U@BFt~`j+`GbFsC{ zKF3$KecSWqpHMT}r24wsa@ewZ+sMPo$#?EU%RM&pJD*RE!{A$0g052CmUP0yp)MrL zOP_S4OZw@WJ_EFZ)U#K!SSdpYDDp(UwWF=@FGph%{T?n#%rwflgM=KIT{}px;bc5a z`RfleK*<9-lF>o(4VVdVke9TLGV*V2<1%F3_ZTH;8A@l+1UoBe3%76j#S}w@S{UOK>Ck6^G znim-f|EhQNPRoS|@V=oeA)(+#6LjT0ixKfv1ZV~Y*Q0W7@BQjlDlX^U`)3SM^DGa>{x;>F792+S%&dI2V)L8Xd(nN}zw&1+WKS8v-AA z4Qk%L1x+q0+E8K{|Fr2^8=eY|8V@K12^BxYi!Qs6xAo;yA)7KEQ~UXZ^c!9Ot69b4#2SS*SYHgKb#Q`qU<*~pGwm2*;#V~Shb zQQn8xVo>+$b1s8Wan)w!@e~%^!FK(B(1W^OiwmaIjQK=H5RoV)JiqLH27toK)Z^Bu z>(v1EvfXtjM`A}8)&xk%!N^1ai8YLI?brp1&vo&Dgd0c-uB_dpr3T?ucUG~eo z%v;B7WOI%dcJ9`20lXm%2qe-WiVnT1r7yYvUoqbjhqh+qr5{tMK#=iJizpaY;-QbR z2)TB1c%B{{1No9?qww5XT!hf-U z){z&r5Lo}zaYe|OOaks^1LTZ=lph4D4G(Egg4qO|SvJ~&c}s2?qke{X`QI~!3KZWa zjyH5o=#a|82k@20zPqO+g~yEa!NT!e_W9k@7qH_glu4jNkPyhV8KQUk^YrF78rRb4 zi_hs>dCTF6r%+^eI8jiYR7fhQ9=%$%`IC3vPQL$o#TXMtIh}r^Ei#TQ{Ecq`cVIu; zY35;l$uvEzu;a=~)KIrIgCiyo8|+a@J%2crjrk=}gC^c26rrS&I|E`ZLRhhSrp~63 ziW}F8^6h+%`OPq6WFhnp)*aW;5X4_G=}BT0y!=@UGk7pMgoP22t0k+VUJ{9w=usLU z{Prv;bhDW`&Kx%l*p>3%$r9JH(nh~Q6W^)2F`y?ag{Dp-{4d7bo<5*c3e@kbcOy!v&Hom(6TW=8ObeK`XP6{4yOtRD8>4aZ#>y` zXi(En5Uq~xTe~Vr9y2(_&w;YzZXmC40>nQ9qIVJE0`YrB($pq?0FWDlu%k06fOHH* z<5jL+b&I1L6&6WxY*G(;!*9I5M!f-0L#P76A$kuQ5&lnL;KCGu9m0SriFgR^Lz%A*1IMCv^B*}rtjml1 z>i{!GBBa&XqX@yghddzp>MoEk5YvBL_+wHI*!?}nlpVS(53Kk%eWp?nKI4F_VLqm9 zVF>*oBnLfk-{J#PJhP9S|9}9`^WcJS2dVl%A)@a4$8B#Os9F?{9|$#mtaG;>s345r zSo+PI+GnrtBOmMjs#B^QOPpr86wV$n6+DF_E`_hpkYZ+Oa|+=0@StKE zPofH#HGjNn0W6+HkTpPzKy}lQMfYf3OyyXKhx>3}Z{Y!B21m4(>9@~tMLnkSt1CxH zyxJzJ5p$uYJQG;_wW)zSVB#>N@@DXA3xiQ?>@lEmevbqywG|4WcDreXe|3?Q69KHu z&;eK8nriskG#WP`pZCob`-;qrgN?UCw`fn>GXL%1WMO3T0U+)Jw2Tu)XBuLWy9`kA z)>=CmW5{kND(SYU)n0tImqKpf&^8>|aJ5nP<=0clBXQU#-pYI} zZ3Y#9wrX=@3hki7{$t*`I7pu5LQxoUqbw(?RTf)mM4j`n7vcFZ%*VNWYUQryl-ZNT zX!At?ms<>m3OxS53w3JBT$KpIozBL&>~)>E-2j~m?Y}L99-2%iJLUp~$Gj0)E z-eAKCCE6aO0?mS9ZM|tzI?vaNB++a7cg7U)_P>W|sHcHhL-=g7U^BPkP}*JuNP5@| z-5X2a%v}o3T_i~aoRdp}D`BetBqsL7^|#62K)UeCiOan>6Ayw+SbA%g z_r>SyKhm^UHk9%i-i1K{;YYJo0q-Eu2S@D(2{e3dL&1UYAj3t-4_JMwCF1HNZD1X6 z^`tg%9pZp1VjU#yfO|t5$CcFHCQ|-HoJUn)@;J_5-{U(l$_hqh0{9IWd@6oRGGYok z4icYHX#LTez$2qd;UlBB)2)kjBpM${XjnjW?J!d~j#$+G?0|UEiR2FjxNR_gU({~~ z#+gwjvrpcqlvS-&c2nX&PGZzj3y(M*dhYSL&jd#4g{PWHa9blzdS-AebjI7ye^JLM z?o-KNt9QWuTW^pL)O+S*Z$(Yag!K%JC%pJ}J9(FZK==>P3HJzL%wslqju?$O6#3bF z|Dw>CVYyu$&^hLB3aERi_}^YA9$)zw2@cfPIg#IXB-|dQc$oqiLo!0N0K#%Dnw{dL z_mx}-;PD{sxlw_2P$|Gxl#&jTkAX@8Z;$${A*DsJSSS7@{#-=CmJ^FR4HW~pd9@E% zI41eyW0AZzg5x9%gy2(VI&*9^VM&v2oQ7@=eBSA(Eu>JLtdt{((_x4fFU*fGasK!S zJ>6+Rg_{qQ=!7^>!J#XpREzQ4f15=;(kt$dii!PGz_7>NDmFlWe9p^Ql!1uaVy(pj zb^b(}!g7fd>3)gKin|0D5WMV!+vwoENT@`01bKBc*n*&DDX^S?(7G-P`d2VJ7X%hg z7%w(gm0rJ;JDx~Jy+!C6gYh;nEir{_@ifTMy7a#cBG)V>usGOoNZrgnNSZJFI}&0| z0g$ECCc?X149MuQ5@wyoP#X3EgSN`tTJFcxfY7Qc-X;RWl?CU)0S&dn#I%2t#KfcQ zKpkg7!Y_f{d)*4M`CV+OERzlt8pXW3Yfl%T6O6}Bld(>*Y}bq?ZY^y7DmuI=ldYC` zCH$N;nyojdCPU-ECJ+z<0000pV@4wY01sw(m7kaOYAcOOB(|8^#4VI4B3xoXk*i^R zj#~)sZ9AuSx80passGde|Dy8%05StuGys5hV7I`M{n7&i`~YFZH$G`H10%^uDBE(? zUAJK}H%Ys8hr4C4x$Kp@v{tih_j~7Bwfy+-*%+t;(J~u5K4)uI@rO-3Wwu%yalvaZ zA#D*0zL+f;BmjZ{A^`ws1R<~SAo(8W^ZWaE@A+-lw$01$-gbARY`=GOo5@nalKK+* z3NNUXz?LXib|DKff*`kRsJrN|8?kNM*h}=X>ed#JI{EKejSc#P&=rwgy86u7)Ptm=0k< zdSVx!RlcT!=1x_6+|IW1Nh$AzkwTs6+4FVw~ly^c^lF4E4NBg%EOXn zAf;zBz)=L?r?JGJ%D4)?j$Nr zCmYo60=WSgV!z>9KF8$#ZMcrD7B}ISIhzJH0lQQx{iRZniOP>cPP&Z>m*F%`m)NLn zo=ZVE&eu^2mj_Pl-UEN8Y_d^{dSk%7e**mCTJ^_)0B?xqY8(yJ3Z0KW|O%N9o)eFs8J_R zAepKtEM>8VEEyq0AJIEVIW;TcTiH5&>io#ejT34O*#rn;66=$FWVo@+OP7#PRpyyf z3K5G|)03!fw7w-rL@Litrt-n$lz617IIcveADVcDN2IC&O(}&i$I_^(FgnrM5%N6_ znuUUJH*b}&-H?IQ^#di@OEf$M6N=JrkOwk4!Jg#x_sO(;>Lq8tga;DkshO8Ci zr3Eic61;1)VH9}gA}scx=zlDQ3oZ2f#fYD$rW4VTX30kTLJMKt^KdDnFx0MEvEwe% zng7fG|9e#B>FwcD`O{PTEA`3Gu!AqBAiDI$DI(L8lHZ5zyJ_Z6^Z7?^pFFcI=#rfq z{eH2w9BX3f>aP}dhhlcsp-=a16~YAS`ML`^?&-LTNjl4=yED1spH|AAnKC5ilNGrZR^B8h5i1ST<*J&Ug z#Mxq_GkT=_MuIMe;`Np3jACwn-Ve)@1>d&CT6px{Z{sUr8g0Uu7(0rwq(eKL;Xmz3 zf)-AxY1{Ie3sloQD~K)GlmZ=$WJEt3Mh=Z8nTredj>>kBWI;0*xBXL>$m^TW$vQea zgcxVpKhV*TLMG-xOZ1(ntf9S05-3Bhpz)9tg1=tPu^FHrr%d#?BUX4(KZA9+XV9=4 z?gv{v*wd}3W9!8nj$(HpvlNwLZP(*<<`pMjD(fIDLT~PU6kWqP+lFDVjL=X_&&5w2 zC~tPm_6UJ57znmO5J_|03{0}6gWwFsZI0}do^+d&Tmbgiu(>vU9s?Ui({uGU7KvEs z2ZvZvG9_9=y`pl(-DtG)#jC`3qxy!w#uKGPJ@!!f>hy+jpee7dt;+30Wa&8EzBqc3 zx(jMLE(V;)-rBKSpXAjavQHPZsmIC0UNd9JaE16`w*8}tv%6i&^B7IG%GZ1M5Qn_K zMFw*UjWcirI6dVH1VW#F0 zB+W3O1__xNeQsTQBH&5W7_A>g#{*HGF!0AyZ`F}QouC}=MnKuuvFNSMm zUtivcceOL$jY1+(-V4zbF$HVBwr^BYcY(X(-O6h_FS7j%k`Wl&8f6&w=0X{>w4*5- z#)<{-KlF}cLRrfjZxtxDo%tf^zj}|rv%^uOP@d-J*8w2A z+j2?AC+GR9BCG}mCgq?y^?VKU+xB(UX)gluZhSwi3{(@c0SiGgDz>3P_c%7>S&Fh) zU(^xaLk^?Anh+yN+fu7xl0UsHy{8@!{B;MqG&$*^yz`u_ZDz>+pWPq!Dw*7%cUR{% zHmv7JN*wR7HCKFdZ`vPp?AN3?%eG1RA+n3@R8f!3Z_RGtdg7YF-IO z)|46IseTA>(dgy!8)mMF^}>AFmhvC6{C+4hEipllc9~QRiZ2O3RsmBAJ}}CHJ2t@k z+UK92xUyWskHNUC6jCb{FYVF%ldu#Ml0}QBqQZWFsaJjmr4@48vl^M~DaK z0kGo&xr%?i*$f(lOZ=0J6j!dvY4P$r; z^n2P)7WpWCQAAQ>) zDhW^vHpuJGs1*^xG-w&Ey`W07t^w2mK=w+2{1d>{UFy+og0{Xb3{jG=ABVF_JJmQttuy{DGil7VLGGgE`ub5Wk6B@ab77% z;oK@lm%{Eu=l};1uI8X$0<#=t95Bz6A4Zn=yHV*3eq)*`a*>!8jbsQQ29*NN?d(}` za-R&376fA^+@JKEN=6DzI3&gILdW8M3&i-2dg=>*~k9Yj}DvAo<{vp?EH+JLe1~{CTb#AxO z&f|OQD_Id;r6ObEBpujzEqPuHW2$b4amaYz1uSn;yAW9GXQ9R0$x! zDJ+0}7bg2sDlAB71f4mPQm!B!%9eFFTEUu0!mLWVy)IYEnxeDw`k(oK_QB+)8wToF zS#F2rfkqo5ndS9_D4}(oMjX&$c4%f95kHi2Ea+RTm=1HPm)u*hyNA&n8!CbV236CH zDnw3Ebpf$Tp3=zXzxBuB))YaT4f4r|N|>ohU5mU@_8%b-6hK6(2D~_koO5)-Ej4Ex zmE?M%4XT92to$THAs7S$03B6M;we<$QJw+FN~3c8zX$?bxJgmdD zuiRBA*)8|(E|+V~ws!AcS*{#Fz>fLIbtxQRmUAC<>2_zu;0L%xdFDODZ93p@V5U|KE zfKZ%sb_zrUl;wjUGAMv1fNX%*g4FcYS!-)wwbsZjbqFlxu<02Z!>}&(EF5U5x$O0@ zjH+bDz=|`&_TO^3jxu|>{H1xKIDh%mDuZNnM$Saa{K{&+Rc$RaIdls|HPNkAQqoj% zl3H~iy-R_nr$2oB&{PG54qQFk=I?dX@^th*-kpXSZRjc(?Pmrp-gQ0N8tKYX!quAW z0|0ku#_fGB4UU3kxvD$nVffA$Ud_+X&Mw}o?N(}2)h*Fg^QHe}f=n>rc&}2|d|wk-m#& z`RcqAH2UOC%&~)g=JQgpkZhm}g-@{LzZcnYhG_>De7*h<56vw|>uIwoD_FcUiLvmB zs`?e`yTFh6{4Cyr2r(ivfOWF4;y??UHOt08n8E6v)|K-rY}1OBVnSWE2C}cHFyxbW zI$7vB3vj(5rl$}6tcX*KwGc6idtnrN&!P-L3|jv{U&F;BAtVjvdve&{YXlP)F(Eb3 zo)|lui-o|@iFS&72;@V8Yahit(QWOLo{frTvp!}t2|kZplhw|=F{vva>P=;WHg3Q2 z^{Eugjiw>DXSqi)eI9Jfkui|3`3h0ojZuk03Zwb(w!pbo`;=YS=C@eGYU0v%NHd$T zY&~#t3t*$L_%sdS>?Jlk)+PaW$(QaL>PHuL)!+03VLaH*mbFrlk!h{{$gC#w!vKVE ztOi7FH;A#zZ1p=MDvZmvuuCi!fsoPz*EH8x)#hp)CIvFsQMjZ^5El<0m|nld|xOIJlDu;oQHUsuhRoGO(T8M zK5Nbwu83J%&6GIi$~S-Tn`mdJCo`y54ceZ}hlNR;gJnZD3dPy%YVy8suKmC&t(JT= zkimon(2L09SHC5~EeFf%RVBFc>a0;J1Dx2Y$E8BsN+U#aV2$Q&BO*U&2PkqpR}Fsy zw)afpIz+BM<7`?EhMTWDIv>EQcoF!DpwT`j{$~$N74c*~ zN2@?E7o+migoK+!3^!OaIhy0pis6#6P<-2!mU4E~#cuU3 z4hUh0e*}w@*wN!5MgBH(J187Dgevy|*uW4Y1B{jwBGDc&5Gj;?2m*P59f_|x5dH;v z+I1v)`_{bmI{(fSW!lk7#G9STK6&64dh3(5A%)w${VlKSk{}b5_v3nt^B7}g=_?5K z0TTrK!fZo~di-UFB^FXHLuW4KIN5C5G0Cp6PVIh-ms?gp<@>DdB$BOESaJ6ioUsbl zTtx5hG-rou&YZbhIKdbNCBt7jdH7bKZtv%=`e6y#5W#TQd#WTiCMi#qg+G?*<`v;c z12)2_LkcG)jq|gns}qI#+2W0PVT%q9Z#*TJ^t`nt9)aZBDd2;G>o(!hGB<`nuQwYS zUpFp8ArZSiO4{K}#S@l$ct)1AUbfnS@juES0g6OQFYv|hhlx$_b>%p$4eaMbZm)(_ zMUYen83JL6kg4>$g+6aOJ>g&NGY#g*q_;%0X+J~-lG${eN3KV{#REcHCEZ?G4Iblh zX6~=gFMksBG%uffA-{lMDcJOt6?K$^z5ca&#Az4o0SE~Y#t(jvUK^=&OG4cw;(-tX z2~#9-gqRRAKnoOL_#DJy!(>7}a}XzRhIyXG?+uv<>g)IosgS-b=`ap?JZT9T5Y!9K zt#RTYa1u0e1P*a-AmmnzYcogCW9*Gy7T*9Nl+=FkH>Y>>4^bfy%+kkma$MJuR+SlKUFR(Q(QO~q8 z(rbp44Ex7-jJwC2u5rd#q6|GIl^OAit*p8SrQINscQU(45f`fb;DF=?w6HEHgqUEk z33FFxQkx*T>DkGgfY=US^f8fuBEvbiw=6>-3{Va*6Y&lL-V$aKfi6x2Kl~O}OZ>k5bbRTkMFBGa5Ce5Yys(@FIsEi)5dc`AAD?tuETBK`R6f+`R)xFh zttRf6T+pHROY5#dUzE(0e+N}>Hu>FWX^xA}QCw^m2aQJ3&n+(@+wA+@A;xHaBt7kl z!SbL^zgr{tV&n8ox(Nl7lu=uXw==}<{AKF5W@C&*_I%8LNk{RJMS@!g9$f|%wFCv6 z8`#zRKoI3T^81`cz#Wb2!9@HWSqi~EFqPb+)bki$@)RcIHqZXK+6$liA|8mw$l+}9 z=V|SrCDzP0xcb1&@$0hYq#AB^8m>%?z{;Ut&#&J()(Ghh>|`Rx-2Z{DP*~7Ob9GG9 z)Tn>U$#@b{U2t`ECS$D2+a;C)@Cp?Vbxi*aPuBmz-xhsmrRHz$?U>p!A#89Squ%uEj#-oHMS^iIi##Gve z0>^}n#8BdqO*96~wBC5|O72!_7omdi;v@z!t)rim!ZJ%MxU9L*m?OPBkcGwTRM3y!&o|Hd3gRat}^3q`ci{|tvlTSQl=A2 zpTQ3i9|;&TLpx{9o|!(h9c>O&!RT-eO#owB*g;IyYIuJ`tem z7dd+CC+8m)qvv7q(&X8lpmg7(PhZ{j%~!kWK-tVj?3v>b7Xig`zaO7x&s%J5=d2I- z4i4-ouhd0udZrLmQr)4)Rkos*PhHkPvb{SFVh>{n>pfNZ6s?b<6X>Csn!bSS z`G1`owTJi6@^+&GYkt(vq-Q~Pi9)X7eIqkNlPKLqwFCN8;T84WeD4Myu*qOZ!XIE* za}}%J48vo#cMWyly`Dg}gq(&#a%)(?{{=5%0F)* z7~P`B?3Z?n-Uk0B71Q;_y^MaH!iwzlG|l(olEAXu;`KUEEwkS@gQ;>xE-R%#Bgv8$ zbgra6QMn2&ZI{v3)R)sP$?U3ih8KG6@x3I%JHP-9U1~1{0uS#;|6cRkf62YSN62-Y zRq%OUV@lN9X_;ye@S7Cn$%3dkW{s$H5_;n7R*#ewafgZ7eb}(rssI0Q{s4fC02R#u+yWR!ih}+z2Z{g{AWZlHzbK(B&3lm>U7~cg z8{1JvTZHy{mxje{?RIBdw(Z{Ut+95F+nd=!$22AJR*Yrc@cd?1B&&)_Jor|VMIgW` zaQGhhj`)s%ga81D7{JjKAipE-cm3|&-EOy2?4te|r?wDl-K$PiJt>x9_(fF47ZF}x z0H`REr~@J*GZ1Jfjf4-Cf;qL@s4vRo+cW`GZNO5oyIldfTI z3~~yT!Qv(DuUlLuy72NWo+^yy;t(J%K{cHad!AB3Tprc6LP2os9S~LCd6dPIFTP@T z6xaLxTIxD)*1BF8D%?i;Lgwq)W!so$D+rroS+ZfmZ|!!At4DOQ#@gBZTTqhJUQ~cI?I*O{Uisao7 zq&#byG{-FJf;8r8Z!+2a+csAD{j|6m#>8DS(nJR66y8SBX2a!ZQR6Uyxz(`?k}e#I zFz*GkfGifEp5R7U$#64dnoSyD+80xw5PQ0&A!xp)n@&?NdbgQ6Nl;U?BDa)cLJbj5 z;A zwxyLevzFE`(^~%y(h_ZI5_X}~&X#HkHP$Yd*j;b7NQ%QVZdx0()0_AoONonM9@}Yp zKQm4&?KIo&-0q<6@U=(#m3Agt&80zI8goDV+-)sSJ-n2*W^J))vpHM+_u{pYN3uqv z{TbfdVxFR*d`zx3(C0KT=saSlr0n$kkYDXYsJ-jtHf5NA<#^Zqdq|Zv-+9RzJj_?F zCRH|0Pr$5w1Ep^#w`ZYf0sLRi>VAOk9W%+T>pLtHv}0@&XJgCT)jn(qyF=OIB%DOq zQD|MTW>!YsPA>xy>y%Ek_^+HVhX2rW?{Y?BWRON@yyJx*H38X+dYCQ%PY02x6Qo%R ziv@4x5}vL2YAhyryU7Q9kH?u<05#Hz16doz@#0*Qz(cae zX%oaG$KRQ!h0%Yd{;UB#tWEXl@w*dTYkE#YfPK0F3{m%ddV0e?>N_NW)@$+cb@LJd zykoSK=o)X=sn=*r_UQvV8q)>6sVSM&)Qk44v9U(==`YO}D2%UJdhn#Ntc#D9m_K!7 z!bycKT3z?&o{{Y2+eI(mE2Yo4_^s>0qZE$Qirap~qLrM_xm55K1vyWyv#Y=82=IfL zdZkh#Yx`YtkHg8_$eM``qiRszO+Tck=8|R5Jumn9{Imb@)Ls_T$iU&mJ}a{YKhDJ? zkKUPjeR25MhSz}JbuQ8qQE_^4Mm3w?vMDpqCMvzRggxuGk^v5v=BYl7{p1f3vh21l zT0XyGFy6coA=A(bK2{wI@XgKH^pPpTLvn8+^X9SkAV)8l4AzXj3k;mAE33bdD3w{z_UqYxQh;{FM8h3o=DkqQ=rGGe&%4F3tdCBpU`+Ag9v3ZQ#C`?l9aLlD`-bnM zI1Z@$7)btgfga`mo|cPeVgP8-$V^EF>9O4qH}y^%uhwMyS5@uMJM?_0u*e?r z8PII)sjrf7Innv<*wFV6WAv1KIGU@efO6O>1dvA0&8#Zh=n5Sg7yYR5gaXvj_A@$P zPa{L)g!QdHfnN%Y>GbhHZud*FQd4l!$+%5PFI|4((RIIS!TK{)FgX!PhR4S+4g~?QKlTFG_^`+$~5>we}HleK07KzO@RR>K<^>| zQF+K)m5efux-GMc=RpLf9L+ybq`D$=711fgB6R?2=tcz9 zkNgpz;RX3OMo{)HP@4HA<^qS|Q73)TEZ$>|>kWtF4ChT3vqEp5;j=r_+AcC zX4nGsX$cNo@%UesV?cBOTA)WDmJ2C#8UYm?6u{u7ksbi=%L)J^k^sPj4*0~a0C0?= z0D>t1{GwU{+&**wNX!CY3-SRtyj;u377s+Q$t}18;2N|)nu6;M<5L8eZV~BTPJ)XK zm1#-cKDVQLr4(ja#Z^@p zTwy4FsXJ;jCsHrL;0eOU*JQ+2X4aWuUHXXXC&=a^9?fCHT|E!=v{`TlKusbpr!fov zJ@urj`i(|K;lDXo#7O1r(STly62@fGmSy^(m=o`P-dEik^bkmfJ6zI%zIVvNAw3Tbn}iljeY2el%X-!$pib;Va_gdA2ZrU-91n z;Q;`ek+>@`0LTLUCngm5tOyBb0b9ZbNU)@~YMVp5tfMw$-MLwdvRdoa-8WrmX4dZa zmAbZd@4Kzm#`xJ|V~UKe@#9&qOhMsbIKxMWBrF1w-~vN%LXtp7{0RgA5&!@r0tZE4 z0QY|Gy?gKNcJ0<|t8&E(HR?86wY^>gwA+kfDZzyNAn>E`ivEwq`zP+m`fx6$REZ`4C{yUW#m zx388G=3v|4U9Z77;4QXY*>{Zqm1DPlZMuT^eznr^ z-P{`0EP<=(0R(5lj;t@4?(&)|vM*bUs~3#8R*w9Y;NFkxyD?d5ZaIazw45AHMsQzZ zvLmS++UMKr2*9i2S{$7(<8ooa0+m@ucvcYtfW4#mYZXXDj4CsW+BSHfQ2aVYd`4lh zw59oLL)k46$9q)8vI!=yyZhVRZy!|%TWEY^8-}RfiB8qUx0QFhvk+OkM<240$HaJ% z4AN_%G3yp^$ugTO(6RR7X6zNhwAAH$Rzz-Jm5LQ^Jd)l)sl8$3q%)4Jas;~@38Dg$ zlIz>Cs$lK1zf(1bqX0?n$4KE)F37EqvU0b;wR(=vMMmA7pHK?1IKT{0>Q(FEjhq-F zoZr9{ED)OVwnz1h`_Lt4fOrCM|0AfEyDCn4SOO7?6{p=KXF^3whEpPTal;jSUugnk zyO(oy&mvv8e<0xz_ji!OCE*k2A)pXOctfjSq;J&7X@F*#KAzO-EyqaTrZ|voimO)Y z<>_f@X=nN{)>L4|_Kgx08NTXcLBI2XfpsLV-1oQLIn9;&-Bj2ytKoTVjtVUaGU<@^ zTKZlwr>S3zfveJyEFkSxvPcq+v&8L-u>Bn$=|h-Nl^05>eF3WaaR>qwnj^M*@fO7LPRE0CFaFQEmfu>N)oxGRk#Nz z+a|a$;kuUnm2+ie4e@BH1KuWE0kr2zW_JA^;?3*c{H@eht-9HC_%FCU^-)K)@|s%u zZO!+AC08uv>dnNDw)VFqr37o0GR;D01Kt<-_Dk>AeP$72W)n=_ZS=}h>Vq4PaO3=_ zUH7EUvYZ?tUiOW($EL05BR^RZ#eWH^JU@xRQ>Hc%^gH%qOF6k#ZUq^q{ia2boDG@Im#6=#&E{3W84=P9v&CfKjoT`4nv5 z*?T>wTj1+Zm%#f!9SE#o59S!SIIcYah5?`!%4!<;W7`^B@tT0i2y($s17?!@=B_i> z=Bp0?kme@bCYJm=cA+Ov!20nmuXFQRVG&v1=V=HlYpIP}W#=a>_a#@n`Z!+k_IE<4 z?FpITw;4M9r;ax+j0in?V?tiT%<7`@w!QZ2emA1SRf>c#YMz zEZjUsViy2OqQux9Xcb@QBwYUi!!(bh+u<6! z--qbLcgGgkH2BGCOXhc}I}-62OoN}1<_<3bUB4l(+CMH1L}gJxo_WUWV2jYU8#RS5 zElJ59AYDh6xJtD?K9UtGMq*&;pC+i*n2^B>m}n45MP!*Dvo{S3 zE_LD&Z-O61n0>0t^^4&9e(l{HKv41^Y`)Mnp39|&7dtyPrXSZgl5yBz1um!Q)QL+6bRzB(4 zzntM=j_@CSHQgSu1zRHnB&oqr{F`u}Qxa1KPZ*&XN5^gxOarW&s8QtQ=`z(*?gF$0 zP3QcU2q>n$64bvl1LCvK@HZcMme>2*e{?;LpFF)Gea@K6JC9wUaE+s`7;6dtM@sH6NjKagI<%k1;aW>w@7R#}c3 z1ANNZE;Bc3gb(>%$say5)-KJ~ZGA%>RY<{vSG6_>l?!_OLtwBTYFTaU4jw`&p zNK(yzzAa&7_(;O{G~KzhtaLFly~}&z zT2!WQFP#7jM9q&YdJkm8$=_Pdv>cUZ&q}|q30-|1tt;0DH6vO-NiF>)kFyNuDQ8FvJH0oX-m1$1{qE zXvbeFEiBqyb#Z00pj8dhw&+r2%DV186p8_!vOu7u@cX@$^IaS zfps^4QeTlHqEm8*oBab6B1aF>ewYavj;bz)&I z2jqF*(ILCXFA;>66iJ@&v3X61n}6mKaXXOg3uHl(hmkrVjES0@_IG-`W0SNY-x>#T zCIEa@2w5HjkaIMKe2WBzlv6rm0tWDxNZfJxDdE}akB=Oem0gNd+w5Yy9f$^!4$zeJ zPFIcvdDdW8MPW_@pLxO-2ZM}Ph%vL+v5uGY19@@2AmU?^7=QtyFJit-=Ky6T3qH2TEi04fi0yU2dv~qwIhMyC5L^BnX_W_Yv^+!0 z3`mE{_Rm!k;BkScSLhC3Q>7*fNmee-k?A6V{%ys8nYqI^_ERLb zjRN^twq^6HQ|9M;)_hmDU!aeS%%cj&r4|KZ;`YO_isz>jNQo-q!M2J!Q{m^o*HNh9 zCgdt6(w#S`o}2H6%Q)9v!N8Fs4J@{UNEbni3CL!JFM>zD(g_ z77$V^i$6WV20w@nXqi;Hn)+AscHmRZ3HB%|7 zQ!3FQjVx;DdfVY+2BQRF&6@a!l^yk-AxTYqmwu`emYs_{$gqyaW34yw8xPdDjx5zh z*cTvtr$lj^Vtw_WGKbHGUFZcF{AvHSXvDoAANrGqIkmT(H?0Cj5=ZVj)Sc1&-6UFP zb;WSeL2_K7-z&KORXVCzzIM1XUeIH>1&WG!+6^^J{AB5$uymueMx?-~W<}+Wlbs}I zdyMh%hj)F7Nj1+deuW)f{s!!#;b_L}X{c^OH*W=e>G5tPIX3rC`UZ+>Qs1q8DQ@z) z=tfOO%+NX#W&x@7znTV?ZUixs{nkhGVavadaBO<2#WIi4T*Vl)yKFRgvOhEuX**Bt8ulVq?fhSWV8c0b!sjAv164>tr+eWTxBMvXCoK` zDzyUDVQi$u0tKlEYnT6-cfOo4)TFQ58l~!O39wEGLpJ?Fu%5I59b?`KjguIMWIKcJ z7EMp3=|;wz(=)I?w3hJ&)y~uwtU4>)!_BebmN2k%L8nI%rB>nOTY{@mv!#f!4=rWJ zUM~OdpCCIJGwXj8DN9-_p@u2jLK%+PjY96M%O2wmV@N*i>7~xV9&3j@3nSsFu$-o^ zuj6+BaO6LV)HVq=iT~*PG&p@91Tjp`wgxhTF~tFRTSU;H=F=rvu!ZJDLvxpl-Py&E zAX?*NyPJ-d>0bCWcR}ys``%s&ma^&%gTA{7Ren4QGCnk@q6AqS+70>+0Ei7h2?LP! zW3;!sy>Yd>aZNB5Pt**>7Fm%@tQQyd$#j~wc0Q)L(*VH%M5ljnh!z0IzeFR@cazJA z<7mlq#I}$HgYQ@#b3{I3p~!bxVVZvD#WjeaUAo6I#!Dz@-cB++jpw8M90h+BT32!+ z4q{ZIM~+&GugT~xwZ#0rHlTFR>U#ETpVR)$o@2U+O|4RrN#bXORan^q#S&9nt5xC9 z>+s}XWot)c#+{+D;lQmr$akg8>wW87veH1tvt2O0w(+j(9`&)kCr`qr;63DG?!ULT z4hURkTJxP+#HI-fMs-tj7Y-yov$3hN4Z-N8trzB67(0%c5*lx*KSKYWm+!@=J5KQz z@Gscsr_d6ZdExeVZFvX^fBdqrq-n`Ik{g$A^$xo;al}|pWS(nHDFd8pDe>xQh9+P+ z^G%QpVw(r(w9n)^GR@y42f`1cQ#Cyc|LAV-*TG;&CEXyVAyQ**orYTW-U;L#SElz& z4g3DJo@KPMt&h> zqqx({SOqT=1h4yv!l>Ig-n%Kx?EY;_U5(>8Y+U)d24CEWthr+xv-E#g|Tu7)ROCEW^;2gs|Qv%{nCJCPY?DXxo{SiE!;(5twt;yunVH1CNE8(l7QjnyDEt zD~mh|bAhsTso#ay%w~y{Id#40B8nFhA;75gSR1lcDo zkS|Q$mMuC>$%1YjiaUa;;Vs5jZB)};ltoIIKiwZxk0(A?&26B+3r4pXJ2xN!s07dpeI2;1--L<<>2E=H3*t zq7tVmVyH=~`hD$c+cZDrN|ncOAvIY1rXE-y+th+_$(mo)JiyYDbj0H2%Gj-Q-(`lq z4$caKH|~r29^wWxwHmY^?xc);rl!R2GdoVfol67Rbg4$^9Z8YWY zqOsOOru$2(P=%_(B3W5`r|3lg&*9MOZ=F}2NlpX%Vb*pTc(oOdW4( zg5{rJp_q0xg%xNz*Mi)ULY1tz&@h{S?}OskYh)*NM53?J7cn(St*eTayMmR4Zs5oJ z@j}=lu-Pv+rnBJ7r|}g2Ah=sL!3@!pdQEYTnLp0{KVZpr)86Ir`kNb?*7dCVbvus%+aZ;l5s;;M0a9jR~ z63GsMNBwZRS9PJ+WSih0D|igUWG6*kLIm@rF&{Ofhd z&_Ss>RTHlM{vIS5IgRTQ&DCtlhl8~BOp`(C#?1LEmzF~<=fr+{{qE(IweH+ZR;GWx zB|-UbiAY0IPTEB^qfrw0woU#P?+*7=A#!%E&yD9D{ElhUdZ^nzI4Daqspk!0@bnN; zlPwe}nG>(>9HFHB;2UhJk&K-l$yuvXCTgg(I{8m0b*q>KNuDq5)G`C=c8v|P+jPW6 z;eprG>I`*nzUm}~AHh|~0$EI(0P&{ER&VOO9(_tOkt(nS*@WPxILZF}58JyNy=a9V zIoVCQZ`ygVc%o3&nO^n=tf0JV7bIEIBd}2Ntk04-PZJkKF%su4VkDGjd;$s4IC>r{ zrZQvDMc}GZ^<}!Z#{x)Nu-lPzecAXEm1A>L7>M*Y#+wE|P=>1ntAi`iMgCsO28sP} z9>@7%lEExYMaWi0!)}iLgPS*4vV!cZ+XIsr^ow7pb@i8=*t3pD2KK9OhR2pFHcl^! zRTVsQ9$e0!{d9x2#7c09hMt1n_m~y}i7s^{T@jR6a{@@>r{=301S)G>-(&4Pt~v@y z9GdRn4=H_u>^SPs@E!v8v$sE^zc>rFOCk+3 zBmOv~l9Kc&;*!VlfCPge=QInkl5p>Y^8?8M&=QD-F-Qu}Gn?f)Cko>%D9a<4a}*$& zY{${ddV``bMz|M)y@_DEg1imzJq@$A^{@DRYlfh2 z<4!$OhF}C>7UhKb+sxIUKjrm8J)rwUji5!&90*yzp?CK~XDNdYm-8E%-p~+$$Yhde zq+8A^u&+Q>5CKeL5Zi0SXU~VC#O|lN2a{}xIY}mrDCYDP%a%>2{NE3U{m<^uP{QMX zkOe}{p69`N^Z0%cYi10Ia${SUw6j^C{B|K7M~nk#9{vp_5p`*f1qCvVG;tz8o3C0q z_`66iA!o7!+~EWPum-Qy#4x=za{45-Fl+E20Jg*s98UQ@FUplkEb&1h1{)zUFvCiM z*?n}NJo6OP&X*u>0Q(16Y74X>2#gv$^H4AZN57xiYKo0i7*u4@h3Sv$WY5E0TIve= z*Bk6VfF61{PE}lHctE8qeCZD4S0`yIE^}ybhPYuM5*v=+n{fC}iO$$E%1?;Lq8HF1 zkeR#PV3k_XufwJe7;LeAGivOOe(1pseks4&hM^w6V0%M;0G2+kqBdoZ2fpAm6Me!w zWMeJ>HCDA3fNdno75{k}L}={fC9}$q6Y+PK#20XkfD<6LMM8ua_c;J<#7{xI9CU{~ z9xO=nO1^(~;kV(!80eLQ2y;h*1E7c!MaREfWA~n8f1Q;tMFQ2VF!YAD?9WQzN6Qu* z5O)t0xw<;FspJ~~%PrstCFytl2)Q;v{Hrx`2L)}_|2xuJ)u!!L6(zW)no&Pz_IpL@ zHhj|E>%#l2>8%cvR&0K7O|{w(8%!_pY5c^58omSC5V}vSk%;4=0$?xV3ScZ-D^kKF z=$O~Ht6GI|+IJUEzlG@m83=(zDQbbYS!B}=EwzRJjKuFr)~oI3OHLo633z5VcT9u_ zMswHl_CI6t({^t6e5HV|c!5(&E$ReJSQ^iD|F&pSXMi>J_ zv^YV@UoX*Fb+aJAujT^{eL^9DV!uct5kF!LqGN7G4HtSZ$bk^#6U=}DyHZfLgI>zO zaYsY$F+!1;7QI@*(8fq)VyJmg8bxUM(Y&JDJmqH~I61*z;11WiG)}Ej5b?&N#pAA{ zzNlvS8JH#{i z64}{0joF;u$WecvdmA%g&z9Pmb*!Hn0ICulCLMQ;@KpxpJb9 za~PV$y{gplOZ|>^vIO?-O&vrMsnXTsocp_ z!+W4CfVk9P5Mmo7y8ytqMu@`nhDyJsMgZr!A zb6TE*4_A96z+OF9I3ZJ-$u0E`{@`y~h5tZ*W(zvEW)45p-$=%Wlfz>OmObghUYt(! z#%yC|BqcK|{jz#NO=);5+8Kqa(iz^OQL@7@w7qfBgC7NnDbHz2E0M?qesR$9iu{D1 zxPY9)eG?{nS2`wc%@kyxqa>J;)tA20t2S1} zgVze1s1V3GQJbv(p&|F9K0%01CauKC1~+DGzqU*RFdms_!e;G<*40g zEDz_bRdNpIy34|#YkpbT?rMgXc>cUjWni%%{=u|*n_D1djrRxM;2u{rukN0He7|m^qu>B{bR}qo zR~L67Svmug8SJ_O`FleNnph5Dk{dW!uVMyzCa%HTk*1C&3c~J3(#v^bjXk$fwH& zDX%g^?Yh+dlShrWq~|Q-tD`1RFYlsMqO-kDf}Q&NGio`Ne0$g$_k~oK`2ioOsvM0` zx>jAe*Mcl}g6?;?7K%D-M`NZ{tEfq-TJDsZ3#@6E=Pj<_c8kEz!>zvRa=psF?jhzB zF5>R^D?fXDob7XYF~8>c>ow{+9rm_&&@Pl+0}tC}j|pxKx?R?^!@^oLn27j{i+QR$ z{+^d0pIfe-t40}d156{|Zexhn%7|GQGuwxnQkw)fk?i-pXpu9 zIlbO9-J)mOzmuOZn04BlkzPk7)&H*6Jp{V)THjXN|GoYY)Lra&NetUUpIzNzw1`lJ zO9PNDK&bt#3!jaMjzM++w%K|O=nsAi+6gBg>L_NjL@BklUM7@)nWu-5jVNdhs0VfU zxKo0Y{;bKMxMNS&y`qaFGJlYX0Retemjb;s7d3pXR6T_he$9^WKHqir?&3!LVZzUZ z6$6IqcH8@dJWhpX&>qzgmlTN4vpU;mqEl5t)P{dD%%~x7&EQ~|BY?eyXBB_v$@J3^ zq~GzptEd0&(rKc$Q<_kjEr4aeL5p7<*&6}B9G=(i3~Pz73iOT+U%>3=ke>akuZirC zXigo8{LKZbQMQAi^4B1)t0f|KhBp(>i8_&y1%K6Rw-7!;cJu)NSO^_RcT`?avIq zU`(xEb~aq++qiOF)=}F8f?Q(iDH9|)Dc@MbvKTWpn<(0}#9d7_atHZof_3Fht+U3x zU7Jgz=H)=z@8zg}D=g_iqk4Et<~_?uX*qazX*fE5&`NoYwm@}nWgJlU+`Ui<>wR&E z9NjGkOE;C(X!yi15rVFx)?i#lx3Cu_%n?!15qQ2|Uo&yKf?e}=fsbrgcZs_5R@S2g zgd>aj2AW0X*=*ao3P=c%?ik%NFds%ih%tUNyMXBq-PoUXGpH=-emuAAq(%!PxKglD zP=gw7BMCPXuJ^ZOaPe_=Twlw_34dM-l7A74@Mr*9F>%#y@G3D*nNH?wU z%N)7j2&;DQAL>t!Nxjap)bgcTNH@V8YDM*nB1r+8X_Z};)FjOE#cP4j>hqTXdR*5p zB%Pr3CBe`d5cOdpU|Z00b3AFiDt?IzLyuVa877Eeg<;E8QNmz`8HP|DntSS34-|m% zASdqNC)g=CkUUv<&GP2MH~XNEK}#$~unGB1*V_$%aNjdM3l2t^N8oT6;49Ec)Q)a1qg74`hnO2Pv5ET1*8nN7!q8#y$b;wwEbLI0nO&@8?H*F zJcl3W@6VV3hj;XZeQxhHVp&2Q8IjTVhE+qL$Wn2sz9Vh9dCZ}&WI_Z&XUjdXNw_f! zhC)O~afr-0%yVz{jfmv(uPv->O93EOhpUu`xr~gqVoH>;Zu4KqkK`Y$+hm4$0JLR@ z$eV&aitu9wF?S`27lcZ`grk4d?0%h%mBTV1MHxbS6bRF%bxM{pvxuT)9Hq}gBe7&8 z_$jt0&?V6^*i(CKTv!O%+EPKP3m$hmeGFe7waCCMF!DvP)c8S?-8%-6)pmy*mwW+V zHTb8T#6t|PZ}3UI(9s&O-c5zb&a116{rMy?+_)i%crQg-qI+KPnJ|YM+a8XJGGf>O zYhqH)3X1q?_uN_n?ajX&r_2+{oQ>pWC zqZ7g#-eXhXTQt!r?I-j6_2m0}2k80VU2%K$|8~W%3-xI!n=ThZ>uqbNY}pKL5w^1c zBI}FWM`1>`rrkoHPsF?c06UqXIJjXr;42mk1;$)hwT~{-R0(qA2ktf404=Weg;N4! zY}`V5S38*&xkT$q{S~RxTDDd)1J1OpJA9l!G3YfY(Ip5s8E(`yGE!_PAoLE~93cE% zt4Y8EdtsZ_T9K3QC+5WCw6qo~n8+BILWj+r~T7{yRm*A$a+PFuW1tK=QoZ;sVO!@~{ zdpq2Y8>ui4G`~N7DIDKH7u3Pk&4`5?+33p2{w2}}RULGArDW*zNy1o`*Q})HY1h7^ zP+t%nmq#MtSD&9X<4@hi->u5uhXKA#3A{&I!Za-Bnke)W^Rv#lK%PnvVkz^I3zc5 zv_3rhupHIdM&4<2EN*`&Cu7>2Y00`_BSgJN^kJ2&-QP&EkBb}8!CtEwlo_U5JV)*t zjE7mT5AB`kiNw%-0}1NDp&J>@IQ=4Z8Iof#c*A3rSROMZ#@f6&CINxMCe zyiZPL@gHLBRd(Y#GWbX&ad5g`c<&fHp(z|`*ckavCpSIZg(A*v+U}y6Gn(6p7i#i2 zDKZ^*)N?RFm9TE9G;Au|5oPOIEt$hrNC)wVYGu$Yq*n57b^jn+dv_N)F&g)pOdTsb zv;N>8+l_aaKQhL1g^Ab2Ie+c-sFJ$Z;np>5<*2|ejJC`5z8?Ut5|u5^>?_)9EZLY4Je3x1Y;RswoIqyc_|VCsA6q(LT7}kT zjps#0g8M@rT>3;Cf6n`$Z~tz#XF2tonu*`ATOnH6Ich9hQ#1CZW8N*{1CfpVa?wPn zBqO@EH?$AkR%sO!@|@)IaA@u-DY1t-{nzs*?1O|wk%Z)~SDZv3ho=*BwGi`) zNbRLzukP2#y74!a5ciiAQ0pmrr3btX=8svCRam<(2*O8u+QRaJ2qZ^)IdBO}efy_^ z>ZO0c)S2KbL%igy_Y<1NRg|r)5j#L?H~v(L?!x|%;Ln!w!5EnL{5O1rWp_t`ew7h} zs?lrUrN4QDnfnCAwEpETx%Yh)Pu%sCx1)ZrfBMy#-e{h%lMy@Y(|_asxd=QZ-F#7j z1lip9LnDfD=69xgUiuq79O^L+eC)S`*9>R9d%M?K16m>0NrwjP_dW6lAsu)|e-97T zZEh@yfkjg4JldO%I6tGui`Z0~7Lq#Q}zQ5iD z5l7uo8$9Y^Xm-$UQ|0oOaBW(wx9^CoCe#OIMs~XnG`;yZ-J!xtjn7-FLV|xzdVy{m z`BKQ|<~G)srB-t4bbftsb&GBY0C&n(UUD40F2Q4VN{Qet2X&h%4zd?05%j*S#LIcB z3NMiafp8p{_hBfwPp! zM&E-}|LMVekKznS{PnmD0$^g23(x65_zv&XOxT&jA0mVPdMFX33$m4|tIOFilfe59 z01 zOD5IYT~)@VwWLL8F05hlyS9uRMl}Nn04Od26~h*cmxkp?C7Y;*n>c9~uQX9uSa`aE zuNW6x%#J{fM|gNnGP9}>B-rMYpLiub?D(1D=*;Wk1j;(ATvQ6xQ*!sp7GUCV%<_Qv zU4U%;F985qFsKx2SDTSH5Doo4f zd_8N9+)aZOKd``Bc-;ENYSO@sau>XRvq#(>}>j1RYE0aUWY<43o(OELCO zKmt^*BT^4D9W9N@7`2Knm!0wZbsBqNjpV0J%Z)@2Dn6wG$b4DoVyAS>EsW-=O)$_N z;P>Ae?At5*J(=*|8q9LyT3(Bm%D!+MpVy`~Q3k%JiUV{S3`JbWe+zZb_V@p*!Jx#! z9eNG@pz}hvlaNu|;lpLaKx~i^+=b&J77M8|0C_g3ZrL)DiUAH|8$L8#EzLfy6eq>k zHfWm=*s-kq{FhMfWFS%7B)C8*{_T(^(w7%CxKfMcO*}b1ek{k)b9pI9EM&E8yg!Hmmb>v~!nA&nIwpCWB7&ho?(=T4VHc1;1Exw5Z{n2;ApoN||Q zmkG+M)BSnM`=S+-gO5NpI!2m|ziNWoAsbj;!dyj%;^W!|%VP&Lx|`?A6$$Z`F1K@y zr6(Ol=ovE7qI=bYpQ^aoqoygECP--PZzn(K(@K@PhC#-BmzGPm5=q;uTR;UWqr%&Em*R4{yv~o~=4g@pD{Kd{@SC>T1kPe@}P9+x4=iyj*zQJtSWUG}bm> zJ|I9+P-H74rdKR1tE4ENyW|uVO_$id(4LbwHq|6sF{hnPQEtL2xfgVOvwXIN7dI$f zP!IlDDt^QhxNGPzYUjvntH1_}eMnA9e%T!NyloiVBSl1iT2|RQXtF0p$%5n%qu-^T z&{h%k9%L>18NReS+yAlR-@Q8hsJ+vClb?=_{)uqov!X57F;4%9=31-cS>F1}OqWq& zmz8$n9z%BVGrw>;sOKnc%P?$kOyX21??^unAV_iWv#dmbc;huL>hoCdy5jZK5pn;o zI#J0ao#fqQi7y@5Gn*xoesfsi)zz$N2A_Uw&bb-ZHTLVDh5q?6PYX*(U|Hj<(ZY(C zvfCgNsGG;9z@xBd8--w=mTqUdV>uI;cEm4e+hi1R;;_#b65r=JdeeH%CXhqz+bdtH+;H!dd09^U3{h zY-5vKQ(;BjhU-;@yTH=A0UW(FjRKqs!w>&D1aQTh{lh zDIKFoKH6ElI_omUXE8=#UQ!~lCQtR8QE9)<%*i35u>5M+B-PCFld=`I;Hd3=r; zbjJ|P04@!;2jr`NN|}WiGHl{Eu!Vc%>@5!_uo~l^Y1xp|ukXfpKNx&u00}w!C>Gd2 zZ!fh5M63@S!rn!5KWx6u*7}u#c|Rx+*j@j^ld541NFn21N7~NK06Ex9vG1@=N~H-l z|FW@Ol=KAi(rq~c#&B)1<05!|e?07!gFn(N^FTEXEOXzoifKsJQ6tT*F5RY+bX{Opvm*-fa<~FVtrZHjU zC?I-+p-Efbo`j95nl@E2GZXefxtBMt`;ku1^)Cf6&16vZ#aUiKhR z#j=~Z{gKqANf`VYmH-JJMAXSKobm9BApwM~QARnbZA+=ek!7BaDwC zwVbr)aK-R^zJoMU19xGg1DG+lUq9JF2Tta!!}^8L*$ch?V>zLAO?wk)I0LIr$t)!E zo^=LFaZ{(VAUD7v$j2+fgLL5Bsok$TOij{+IBc5G=7T|W_uLkZ8fCuoGDx!5vBH%=i&jH8x5V1 z=Yrv4$_2sAokyq>WFEtuwDf1A98K9t88Q0Pv6o#a8+dcgR=6t_b^xo5n<4t8f@nlXeOUqLkHNm_!1C0UfNL<3C{c!$pyu_+vqi=ruLMTR2eQwvP`?Y?UGr zVTW3){h~J@qWb}0-C&hB@Z9gph!NCafmV{{F*!2jQ?7w2|qp9u*@KzSX!=gi6`Y=(EtpT!I$i$!cLT!`kp>cm8Rsv{3wgDYG zeYfHkle62!kW!bw_N{5_-IW6b!1 zb2vq;paz~$b=Hy!r-aRtUQ!hxK$m%>iKDJlTkj3YopDS8sS@P$d3 zk?!!?|P6)NGyDXVXy&}if$mGkr)3O^M^QMAbJ#|G@5#%;9ygm2`Vsz#|=iG zoJY`dZ&(55Ao>b)+|>SHg8??glh=4r*+;upQ~|Y;pvD*5!fOA&i?5Z}jxqflhd7Nv zG%tdbs|^>>E)O&x$2FDRE#w-qy?NFd4k#M% zk5R|?px-Q$dE?nOhR#NB37WmDpPTSOA7f%hy z#e@@4kcouew7fVp zZ@q&E8fw#e4wau9{ZZ|~E|M+!H85hZPe5wW0q=8Vo-(YNEaC85FBaT@1GV01pL&V} zl$06vHaxW|z=Qs3n2?&J?BsT&m&UmGHm}g`Jc?r_&p^4e5$w_R3M)c=ZX@|SE!OGf*zKj|Up^mVxE z8_ksMU~FCzvpgyINF&0{wI|1A7sqQ|^mq=cE8BzV{_B0SaIDcIsgvi`Sy~CrBAoZ! z#I{}S1v!V|68!DVf+l;a2Yx)m%o4eoRMaOT=|}4>GS_)Y^BI17E!(>ix;C9G(732U zkE0FK!9xFNV)wAg9Y*W$pbwB8Dc0dsU%I%40cjaNx~-++oMb~$q*9TT>E2ef z($Z6Qi4bbsq=ZF*;%yq8m{t5-+}MBR60o+}r^hs6Q!)Fgc`y~qU1VQAL?t*_4`}7M zN+Z^;21QgX~=Fk%5>z`kkUa-KKe*gLJl1%+wiShu9$A|P60y|1c8F=2G1 z$3vzq2S)F#IyWvmo5fn@ctH4WZK>@R_-r$PPQtg*D*hc*?qAm&{@O4RDt{E@VZRa= z?ZX>7IG-776I9O3LL?k#7JnU6Nw0215yonbVR*a`*E?CGFB3XZ+5qlujZhexx6FSE ztJRex75w{`vH5WX0&DaRK1Y5!Sqj=c4Cz3VGQfen5GnHZa{0F|V0{1*zyh_+8iC-0 z(Bn=m{1ZIM^%}tH9<7LAVPiB$GBx;2;|-#}aJGGTtFdD!IeF17`UPgWMG+awV&WiY7G+*s}Z=r`MkVVsnU`520t z<>XrVmlZ@O5@DCN9NDZdsJA+!@uk-fpeIx%4?KzgL&~^5X))jYAmlwUzLTBf5Jh}_ z=VKW)>*9kn`k(B7B@Cy)M3cMXs*M zdLF{hZLCnFaaJ9&0o!FAhJ3g_e^x*9=DdWB#lDwB&%39Gd+;VdKHCuat1W6Yp@{&= z<=ELPZJ$AWkPSZ<%^pIG1k#zBYkcxJUfVbECyPO+QL`d!uLUeG%Zp5-oVTG1j=>Qt zS%<@#cr9Lc)+vqOz>FPk(P90@QvoyzGW#5b-~D@o{HAv!AKoB@<;Q`qyTZ5UJwhMt z1I9N>r$D5!Flw(sBXCL^$Q!@bwl{Nf=I~sHU{-#;6d`-5caEY7=B?Fzm)=kPSm8js zFf_DX>6?FHcSB0WGCfv+!TgCTgvvAVdRwYs$1j*oH(YMsLLO1?B&iQ*6~lL{6aE0o z)(G7^6s;$5tjtQgYbk{|BKhh(x_l(IQDRAq^zN!e{qr`&r(<*bD&8fMX_|az(kIDE zC-uOKcBGBmQ<=EQ47?&OP+o0CN_pC6j5<1frcTShmV$wljHLAUvL4zsMRDwtDVn|` z;}*RbCm-Tz#?OG<{}+%Y5EM;7(Qul;W)Xjd#YaQ@vl+F&NjG;wT7M%!9^QHGnL>kS z;Um^NT=WDf4}~s^7Js44c&(~$sua)ab*eDtpTAk-az8Zho@Lb>*6PDGi(p z((9Nw7ujD8rv?iQyh{dCZ#;KWkFJz%Y!VFjIn{C-581D1r4I{W%SL;$|5)9S$JEfLWsoIr2 zJk8Z!(uI~C^d=ojzN|&p-++XrY>^M(Hs|}0mEf$wHp17~E{GyEPE%NWw(P{iss!d3 z@)%)4t#Z)Cpfgx^5IPG{+L;BtNpG^#lSi2Yise<#QCn}!!B|$gmITTD9Dha;=(mUv zn?sy(7z9T^*#Jh<#jndT)XlG3f&pfi$G?(s<;rXJAkOL7a4KAwSqSUfuq)vGU0>-& z;me2Vy>NKS+Da-1x>8ddNT;)F#*XjA*JmI^XQR zcj)@{7#@JjO*GJ@hHTx3LO?yq2Yhh|0P7qj>3=x9>BBzbPLaaZanFazex2Vmo6%K@ zE))UV9y7C}drW`?RNJJ=Nca_@5pZ3ydHI)gUBjV%nABy0)W-I%>_U1fT|7bnFZF|G zbV*$>V%Wk)$^o@#SJB%0OP~?|$Q)+my(l=d(Cx4c=u-)mFtixC0T~NTE%!U7go1+M zH9>NqpA-z~XD%+B;q7cvV23b?fV#k5zvBS?-da?~I_D=Rv97iG-%gBFc>fksaWlT= z3ii%*(IL)rCoaUc;^?g+hcK{)RDS3Jz-tE-{m=#ZhMAbIAPSoi{vp-O`^L7my|KMkWp!QtrR*8m2j80%(F>+lRw5|G~|l%KDo@+)g|~ z5I%O&z6oB6n9vg}WAhin;of6n0MrjdYmT29)*TRDsAB~?N5mT00;kz-SVm9_=*J>h zc*S%Hj;OB$xdjXYH-X!Pwcx$@eC`N}e1_#A44_EQ)+gZVAlM-Hou&l&@1pGPH;C;up3kDs`QWSX;0ur&fA3ufK+MfmWUt*538xrlnB zpXqEa87FdkbEBMEoTw))I)35J%fzONM@;MbzR1_yl*x^+U56VF7`{0@0s#K6+Wnof zW&c0S^uP6bf~2FQGxD|rFiomxvGDJO?b|9tB8$$cmPwGx*kEgl*MUq*?vd4R5cUICq24Iwpu~{?04any2L$v6^xMY9)7HmEyKA$k zW0orZF(bFczrneT;zX-uxDn@N=P~C#=Up-gbUg_7iXk{ZR_h98O=d7@I{&Vmhq2|> zF~e&_yxuc}_ps^ReOR0^o`#BaZ$W7OEyev#S;+xI!jP_TFI79|LQ5{u;RA5__}QNl zJ5oGdS{N%E7&j$x$(lSarI2(+XGxSO%5@nqzkQ}+=V&U$^pgT}CenO)Kb@4RnPaY# z$x~>8$$z~U@x)0QrE_=M%r&-eJ>$FCIB=@h?Y441qGGU; zPnrcI$}Hz`k}?*t`@!22skm&ZH_6*mrK+!0Kjfa~c&Xkns+w{gL8=DjPj3-1S(?0& zQ)5;fmU&D>CYnGc!NMXL*DDa8YRQw09YW#<6;<)W(e`RqliL8_=5mPtWsk?e;1EZ$ zltY45nvqP(cwFpt@cmse>2@D1n;i}8vsY6j_sUUEVSR^1Y?P+%_1)Ugy)e2?UMRin zc8QI?r=0zbH21H2;iB6%=5SaAtSx_$5>ni2(Lw$r?o=CyA)Bs`hKCnrTt$|OPVl1* zr{Ct>;$p$pYzeeT_Q zY&PxZAorVUSY(+5{pS? z?Nkpu<^%0)xGm8uw`t$Ty2O+;Qz3rqjXp|8j!$J|gF3CM(Uj-+DAoDprK#&5 z8LPb-FSWdjo;%p~sn4E{>YVhYxX}%#rMz>lpTWv^N690nbv?c*&#kvZey7rTcYP0q zXvT-HD^8pCS5SFK0o&gzGN!hWpunmEArjutM1cM z!hN7*+54@?Dx$mX3(TxyH{JLQQAGc@Z(F}+A>9>4i_XF+Y8DoOo@`eDJdnC$br zhJxn2tiC-L{kdFTD5FnysKjLYul|im$`069 z`pY_h65CWku_9Lx8G@Z^xbPF z7t1-5nvx$U5 zqy5EF3EEf72Dws!;>G2}6R(_X%*QH9EyumiM0K{~1?^K2Bqnkqc4PH5rc;S1I5`Tt zse~lls$IMVL~v#+kB9if=P(of`5eW%IE-E#M(}T<(wU;WsEt&ivQdZ7vB?) zat{;tib-3Iz@rtli7CGpx2xZF6ZDuig(kC2|C3JTjb^}~WjVutR|VJfQ2AIqgYfZb zCZsusD!x@%b-~AjGSQ;>%A6VN-|pZ3`iJGQP#B#*Xx)WTse^_6ec9mOYhTwF8rRVl zm-UM=>|Zq+a+NOK{WW$~CGAuz3p(RPkEB_~RVA+!cbw|y+Afug{q%J+@%#AilV2T8 zBJ0?=N&mOn8wSnz&y^v=wJ(bzc_~pBoF(k^76_S#Ma=_ozL3%C0|Bnkw-Qko5CjqT z4_=CB;>waBYyhh`31ZKo=wTqz6_8fKz}pN#1U|TVL;haoK(GMhIP$Rapn)o2OC5lq z01dd6I=c}FAiN$C`nyaJC$|Pc+W;IB$3+N1#T)=-CkTKB+)9KTgAzvGA32P`F3Um? zHUMH=fxvU{a9P-)PzD5P(5+zgff|lK?tUKsg7DA_b9R>HN{gOc&W?GfFdG74FlWGJ=(F5)Oz zFnIaA1eyX9O1OC2BM7($w~x^tmjMv$06H8tSbfky`#1y9K-eqftpwD^_&^vv_y0GX zk*L_aZ}Devo+}#kc~Ps}6<)i@ab=gpZmkC-4hc=%BZLb8L{1^LA0nXXD-TA>330Me zwh~0XLM9yPbNt!KP4b$o#DRyBhwdKo*2OFJmE601miq(DD$3ymT#vDRihoHxs7^mO{ukHsa9$H6a3>p&BA7Pyh#}xP&+*(!yW+xMl27nKDXE;1#?BIB3O; z91FZLHOCja)WBN_XJ_z2h!=&|E6;fCQGym;-0w2F-O7LqaRDyI7CPv_&Uq-M0aOX% zcUy(x98{+STo7wmyWDzs2F#gV+Cnz~?;HrS1!$G$cH%EYPz|+}Wcx5fO1{OgZl>10 zBjjb)xv~&h0Gx5%>{wQa^%#2NL)1c3t3@!t?t3`Z$1gu6l% zOt3HA3nFx3{EB5z1lxa4@QsEXD-(t=0bs>#5MK<|PEYGOAfe+5G~k_E(9w^Qm;s$f z(pZl+H)VSCmWe`VSLhvpQNqi~g-&sd?~%zN3!PUW#2RU<(CLk`Z1RAO3O2hJ3eM0{{R3Gjl*P004hwewFu2x!O6AN^Nc9 zZK8BZBihzr|Bd!+iY*9yaa<0-!-3=On`z%q{P$pV002g0@QMrosS$r+l9E_VOGzYQ z_>BQ)m?T3AQfyV;<)(K_q%>W+9mC zP1fIw{Hmag5AK;e$ zbY(*Sq48(Wl6&b05m%_5v@OT-o(DPiGBd)|w3gE`j8l4SjMA`nM26g&;j=Rvddz;Z z($$B!1~=8hFS9XCq`7vxr&$6U{Fb8dlh*nPq-Uw2nds_vie>ZsR5sWa0%gs>1ay45 zOI@$$G)#5&nkVDsMs|`?lY2oPE|jGrUqf5fNJpTSwJXxgcCm`wN|T)H*}Lf!P?I>T zMZLSl%a&&*wC$*lW(6!D@ibf}0k=+@y*YVtUfzQxvf8r|&N74@OLy?#FD z4>x8Gz~g(}*{x{FzUYzGtvUZ>|NnpWE`A7q%#Tf9%R;B9B4H{MGD`C)6!d6pSxAI2 zr*Ej}*Iz!M^z~;;1|X{xn>BrD2xgcWUI5El1hgAp*}b+YB-$n5Xn%?6VMbV&jGxk5#ryHGL*4J{ks! zPwM;ILpxobQc(rMadI7#M<2TLiAjRJn(d3pHY({8!cOhCJyUnBpAVzTtuT@fNYYt0 zm=qjV(pTFL*_xp43C#@-F5l|H5y_Pn=7c9IFWnvEP^Q<3b5_uTjxSE7{gm{~AK9^4 zhL`6Ym+Fw5avJ9*f?)qXR$CrkE7;9_=k?8SuIs_bLC3#Lkf=NBJs^u56>(9}J9dxL zvL;PxB7o|e>7`yJ11V`uIn`P%eDx0$HwJ9D-0Jbh;Ws_M)J=u^$(5b=xNjp?jvqmW z$*OMD-2REij|iKJxVyEkCqVKS>^R^`+ijl`phsPw8zCsCiUeQSq(RSSS@9^$c&m+y z;%lzNBjS(IA-2Tl@+v{f@dh_qH73y&Q3U8l8@}UXh+-6J)uq;~TM7O;B8zOt;rR_- zm5_M|W}UdguOpe;*qmGwU;2QWrK2A1>+KM?_D)+1++sS%x&H<;T61xt?L9I`4l=ZF zi5nxqYIyz}nZ7|degr8DKGB-qZ4>QXVcqZzmx`8rYaeWhplb*_Esso;t$uPCck zJ)~Vz7&r~a_+Zf2AOtcPU;^Oa9q;R+L)1IZKpFscbnF8r*&0DT!;5z{-1vQ2}cUb1` z-)cyU+hRRo$T(hxei$Mon;^uzHFWCD$-bShH9=i&Av$`Y%sEnd;^o(g80SM+z^fQ# z!&CrcA(cKb43GgUNGLjs_79G(n8-SjqE@&JUL$6eubO=Pl%spQBTvrDGH6d56umI?|r#xId33C?{*p^zK z)PLU=xk$8-!+9B;$BT&^@w9cI^F|mE@o&^?X%V=QXER9NI8qG;W=nB9czEuD1N$bB zcqMqc$&5BJziTtiX=E&gFCb{UUSo+=;9c@!h{5|8?atT~K6RAWTjE(WWH*b-H;&W8 za>?T8Yz%`#@+vV-NT8S3BgxlZ^XDlB*2QX~lGL~edS?Y9jBVK9?QGuEuk_yo$;g-k zWG&KTKyIM9MUL&~$DbNxhCW6A#mm8SyU>*UfJ)qkQZkq$R{DRDQa@z#3t5)`nq$XO z#FaBcBN>OUC~bNY%Kpg@R6psmHk&^D zBdvva(i-g+Bc@NcNY`eg!SN03KvC1eDa01&`@Sdx$rduqc{Jln;Es2%|V2!0Yp z0M$DP5lMf1QsZw#gVoxNuQKVjG0m34bdLMq(z&3%9091D_I?yL5O`o zbN;+;(MS94bLx5YK3gkktmABa_}}>P7jYlR)XzRa2Q@%zdGAL7I?Fi#(;yn7ws^;r zIRyO2!2XZTznn>p{Ovj<&g;C}&urjn(3t{c@1{D))p#1ko4}fysrhxRNxVQ->GtJL zj{l|r^y@j;_Bj)LE-o}rf31t{{)87Z&`O_d`2;veoXL9~dx3i=Yok~0__g**0r@l= zy5CCFFaFV&uc}?3tDFCwoV+oYlYWM4_`B}gPpBRWuDEYyx&;^J;dgnWHnxyNf!Dh& z9tAvUn!Wbzwc7d8D5tN}VLL}`COV~S1OoCO#dA$pj!-({U(ItcJIc(&e(y!nm235 zj*Vd!9!2qUllRM1AybGcYWkVCE3$Ojbt94Gg+nLqd+b0ep1qKw+yc<>3SnB53e+Y6oA!Mj6Y)aQp~Q_yUl@%(vko`<>wY+OGkV zNvnA^?n*gsiNkl=uV`c4e}=hRKaD5cFn1EXxl1dDef1OBvddGv@RwL1Td1Os%oF~? z+Qn7&zrC8(CPh1akGnB)xbYx5z| zXMc@1+iqf+tz8{fl#I!PEL*;lyWO2HyNi!{@)Q&?tGjHMQ8hps=hXh4BA?@jX#@{1*VWo|{HcZ86aS;5H@y8F` zKYpHqr%I+#+`4$=M`+uu18x*H39@7}I=h|DMTHtmX`Bm1(hWwdXGFOynJzsQJGXMh z_|0Ej$6CQa)_!PKGj|`8Cxxno7;47H!4Ae`mzo=Em_?8Hx*~2?{CKqa1sBNQmU*_< zjInlpD%S%tOI_VzOPGRK?M`O)U!J*Az|BDl0EQ_PrS7&hKeY%7vz`;E!652Ie+1%| zuf;_i@}iV)k$QHZypI~5%874DS(5ARR@Tk%=#*4TddAjjGTofCJBn4_B1}K+=m##q z1RWLd0tW6-$tcx}M#TUFjH=aktjx4X@=*MO*`p{;WewUmC!)!S@=qq{KJmzJF*5|m z|4wnG@nF33B*z^PVSr>?Fzx^b6A6%>05Ez6zNjApsBlCG2&sd6k+2jIR-Uf4i)t-u z>^^pM)FBiASyPAjG%QLo2&F=FDWEJDbqF29mn8cVi=tt;oli5~xU~GWkVp?<06;RC z5Jd;~QIP@cN}yJczbvy-XL@mrk~?IC~)$4Enf9qyu(Iz96#N1l;?< z>40Z@_&~F2Eb(8aqO9?urSc|V$f8&&aAc9bxS{7Vy^VN?s;a@;uND(Wn2 zcpRxdi55y+=Vt2{ya0!~?jC))j&r>KlYtEwETfaV%Zio*QVU{YEtEXaSyHIjL3kKd z{wc+qklEI9^H1hWOve1z=QG?{Ykjc(<76UrDc1?LXIY=HTHH$}`oeJ1&*PR6T2)zQ zG*f8${8*{dnV5I(Ho@=4#p3jt-40{ScIfYHa(&L%#v#i}?^l)}e}!umm&hMsCXLP` zIj!hSHTuZ6c?gAPna4UJ19lG?EVs;Gs@T^`Qt_M=K3KJlY)3ptJ--dezhr;`tN<-l zBkrRGWR*RY0i|pvpE~w~PVBa!?^m;iQC9c(48-2IAFB^8B#}ctce->RS<-T@NE2`A z(n>S-B&QbM<=OI^ypZf|ix%fGHO$;#B|NGFo*NB<>p=R4O0?xp-i=TKD^mZ@cDGwa z#xelzwdy*g=9gWT+YM6^&J1d-){qFQ+|$#HtU0o?|I4_Z9?5wL(aljDS>43aKwYDKrm1|noB)(}s1m>vy40v(P!UqkTwdtjls2+3?AFElF60W?yM&w$DNNMbTDeUMa0I(1c0{{R3Gy^vy003`wn(F>f%&*Rg zNbbie+C+wvUlGND;E&QW6Gc@`agAkeSG%FMX)ONxj{g9N3;@xLz+Hd=gfjAI( z0fNG3d}d+>&A}(k*)}SB=8nx)jkU6Od)u;>w)XejY-_bU-qmy69dC!O*oxJdjYpnQ ztu_sR9I{9@MDU1{;0hdI4+5Y7MS#Tj0Ac_DBLa6tU;uj$z4!0#c6Ynm-8ObQQi^VI z(|XZaD0aX!1-gWQLj?c=55h3QIi-LF1wJiQ1SCp8_z@ulZ2%*D z{sD!Btr1pPaS)0Pqd*I(qBty2KGSB&`!cH&ZD>@~DLvmDcEBq^@G8%fYR3Wb|t_jYe?E z;ByY#rgvzpXM=d1!^{Gneq#;a%Vf88RBGc-p>;C`iYTS_K0lWoX-am2Tf)#%m2$N) zJS7nlQhet#crlf_^sV}iO4o!YF5AR}pq zk^vPF5P}CAEWtHS8^jPG2pGtwzQ}vY(QF94Sh`$=i_h?uZC(oYsCz!@=Dbs@)u|qF zhe!-Ilid^grxic9NR6IgQA(#TgrR*GHM zma&~I3~xM(E8LD^=RB@dn_TH29}jP-(uy*ISqr7y==z~%;k>SksHtnpGCl_6NdQQ` zlffk%^HAmYalK4z)*fsYI|pFNUN zjjmgVOIhm-G6=GYin?{7rWhfo>-K6oeLEu}-|(|c=v38GZB1Txs{3t~V<$>e9m1u` z4Y#qb(&DYwS791k)3hrPbz5PWRzl~gR#bTkrDj<&Q(*08FL_&Yd6QvmIa&5gm#cSm zxY6ef#t-TXnCk0Nu6A6v`-b}2bvmoHUFq^t&O7~d);}leyeHt5g0&Uqv=lfjD$X@r zw?Hh)R-T8?SG>%06S1;G4}@*IKXQ;0@z|#LI8z)O#fETB=BEbn-4#GSBWx zND(bj_j3rXa1%2AXlnK@a8$wPJj<$-%_<%_0yIIvemNf30-o(m{#dK|`>*r4(^55` z{m#Z4^+rcs&!O54FMp(VbF?<+$HVm=^_`vB!{h6Ve>!kyP93JCoW`f-{3F;vZ)LsP zH*~+T>c*1ju#Sm`diyK!*ZPO5l5Y~(;*(ZCS+Dg6%)5|WeO~6b+Rgg2O{x1U{v=bV z#JEL&ro1%DX;P!l)kImr*^vyh=`pVjUvYEF|0r`v%+19}#(0&r29ZWal=c@ zcpP5UPS{Yjo{}c7p^JJgZhN+{uSgd;)Tvng+3S6?E{7(+fJ+Y7({n|&6p3d`yH(|8 z$eUyoJZ0JmiL^aW2}aHfp8(9wIqyPNM6q9b-Pz+PEjiZN9M)8E|@%fN+8q;ugItKfI9~~PgH4Db|6BeyM5D3Ou1FiJ{KL3Iw>a)Q*7;2q7iRQ9kPCxm2Uc2GwH zpCtd=h@)Ls=Buu5zH_YRI8aE;DJ*Wq&DC}x0h06dITFqQ`i-Oq!xfB*t>HgU{fMEpzfADw zBfp*QP^hP9dYkM?-QXL!jA?Vz{ec2TPL2!MB;o+k09^7hbkrI^+6E=#OaLJm9y< zhZ2mJPiv87#0ej24}2E2sE?)k)m^_fW^e$M02sKaK*l_tsTwsX2;q`GD6;`K6rZER=sWJ(7wxJ9 z0N9sOGbwf@OTjrk#bXu2x<|({DTwFb9?LrfcEImg1F#3j<5N(j0Du9umg=-ShA=Jg zcP#ucd|=1FaBP-WL_3%QshqN7WrH?r6lagjd7L$+@^;<)lbVGSFU3wDlp=pYwWc3Z zgfuLUFIGReW%0EySIp?+^UhRC7uPL77C8<-O@iWzJ@JXwH=FV_b?rd|hIQlt6TW17 zRM)Coeiz%&b<4pS&lwtU!SZ+5YrNLeTkgG2do;c$aL`y6+inp@KszS#gx{d@QKBH* zdt*(pIgc(tvW6qAFsuef5&&6FB^Y_tWI)Ha!H%0g!&6j2lHDfbaK*S);X-EDefRKf zGb20)!Kj2Efkw)6we!>c7B6~t5a%?gM<^I>ViW_#wM3)#wyZ}N@ zgE||cnhJFhFb4rBi6mR9tK%~oe7VvB@jjZ8{UH*A*~QrO3Z0E(@axyIVGFC7t1&Z~ z%fV07fBQzY>xe?;p3w2cgj?3w-B40GFP7kZ+4e(H7?A>ME3buYoo5KvJYqCTZ@~8O z0o==TeQcujByTcAv*zwK@(_rqol&Qg2P7GgEQC)mzXnLppzOmw5e!a`5LZ(5qQ-(N zn)%G;R;=##%FEcS^Se9#ny8x)}6#|fpDvb|-k3mx%) zEZ9WTfd*|>?Te0N?&m$1d|$rFiwQW;Y1H&W@tQk!?w@F|p;zF-60q(aQd44^=94a) z?jXC_K)_3f{Q6T*w<@^2Gd+N$0bF%64UDb<_^FggNCpHzCz9bxN*TCVK*fP?Z2t>w zg7@VfWk;ts;Vp9-d7aW;(<9w%>XfyO75$|%H)F8K-R&$o(a|<7?`z(?Z_W~dvPsez zvL#|b5CC*0KskmG_`-_Whz|%rkj4+ENw0gb{?Z+SuY&_Fa-7(oh92*LD>i+b6O`+( zct*WZzA~WziL3FA+$$C6{Dy3odlAt@FhE5=7qBLR`tSit)Jj)sMqICJ58==xB$^1F zO8q(Eq@afG-zKyyY1Z`s|Hr*0kr6;&w#Zd zaoj?RB6bq1jTvMnmjW$zev%M!po)PQYBz7=D45W0>aoJ9ajW|t)I~bZ$|rBjVo5-G z%rWFSp}$cDH+F#zKMH@zCg#$he{7NXE$16$pPuA2q}14WyIiWMuI!Q3S!Gy{qT2^s zY)ZaS41bwGLt?2kDge{J3eoJMakJBj)vsl2YTdnWYu6AsgNmX|iBGdU!z-Lk+X{Q2 z`uB8yA|(zpXe7pHnbJ+AvgoL6N4@P!2CvKLI28#eJVZq*vrURy(apaeSh|M%VA zyjqNfD?S*+iczfNy=H&K8%O0=JsEd5-uX(rvA|urYF91en~U0<{SsINi?nTQg<#>3oJ5|y$E)Bl~qEJ<>V(v)EwZ_WwX^y~N>PLM`DQD<04a<1K zv*Y&j20iJ0E+LI@LobO_3s;XwBY8c4KWR^^B{0W6ur4E{yvGiBWj+<|Vm z003`PX)0(|lt7eJu1J=V)?VEN8(C!Cy{u%jsqVcjtk~J^-?h_r-A{Iw zTjTL76EFxGta0&MY%Nm$@K!Ia01+bMB0LHOybE^%{fG$T0077V7>&UJK0w{wefQJd zcel1~nT=@#t9VXrS*O$J32UQJ$V!9{0(?FKKypM85D*Ekqf{MbCFB4BHbHe_N=$wd zuipa^5ab{PlRsUzy;@6qhFbqVci$~GEUo1JlhK<$(P$#GvRd8mMvVf>xU|}2;@Xv< z9q&KA!*7tyKD`IF+gY)aTXk0gbUdr&r^{@l>V2FpYCwpHJv6trX{xsIU3MtkL-X5I z69J#`YHg<3gWtY~)kBZ>U2m^2WwF(89i}%yU6pai_3%~o>zHfCCTnfhwipWic(c}a z!_gPFq-V{^4(fO8mvh5M>g~$y=h{5I#OS2k81eT4xdXyqV!VMmQkx`R)O{vd!u`iJ zoF<-OGslPY)cAD*)AKyMzxS4?8NPPigf&U0c`MFcxZruD#d&ov7==VQ4*%94ds*!z1X-O#Me@$19p(9HIpVlyAC6ccEdghXnFtL_(K|pXQY>-Z3t&EiwA`EapX#5YkS< z2l{x|Elo$m;nswuvJ7Hp%ira8JD2cBoVWd<8kf{;4&ykGE5# zM&>b(Co$xH$f1bHxxN#Z@7B3;TU}!K+))9C7T-(hpz;gZ!vUpULo2oD+R`3S>9}A# zTTWSL*RM+a+N!#`bKR7?VbLz&mrbn@f@;j75$7tr+t7BIT_S$xQ&=NnmkZZ&(k^>( zdV1gm!)BZ^^E+va==Q0-N0Fck67fh~R;EBJ2$raRe}&@o+PS7}Oe1M=I^U&T(?_>*GwB+782BPQ`p zNZjq#*@iHQh7bV|npYvJ7J%iei>3?FoZ#jV5bX`T_((zjtB-hmM3?oxR2a6hcE3P> z#<(!@B^TK~IDzsa`1w#u|Bc>J`6P&4fEsxfVv1n~o@o)FI7|itgn{P}5N-`MDLDa) z#-!*1k3;+wwPj5`9qyJVkCxlIRC4-iGv$(@_U9BDtq;Zcu;f$ApCIZNg`nAxIUxvC zfI?guLDgUgva_VYxyc4lP9RDMs^8H7OAXGa;LbB~Qr)O1r7xs1Xi=d7!J?x`;sNm{ z@KwTq7z|7*HX!PF4JIC!bn6u=SBB~-V>FiqmK_}Ohelie+;T(E0I-U!gs+mi|76jR3yo`tCSEN0CB1+$g)s_ zYg#=-P@!re?En)GcU;|5^2?6;^kHu7YndTh0QHSKfMZ;yQTx10Hi4=c@_Wk;k0# z)bN-`l_>t|&QC14t^WCY6|=j7|L-nhJBRoIlWx}gd~)|UaIH1Ce)sPhNIO_sE4mL9 z_O{loEA5-=Wi87;=M<CB zgKB0RJI20|^E%N3jPm_&1>qt6z!!aZk_+TvhFt9OqDe)rU(kvyRHU>7$k-;os%Llj z(|PL~(Y-LP`gNuPlnw4M`Ji_&>z_qg>?c{fr`}!m!OU;JdDZ2)`1wt5k&>Tsr_46z zk9*3zdA&aa1~$gC9U||NadcZuJ?r5y@?VzSPN5`56_$}|HGB$f091*Me%a^S$$r>M|;q?U|CC4>hRpm z7r+r%5f(6UOVgNsQ1A9i(0t_zdMB=&fruo1HEAqft9N|GdBY)e>7+56W5fi{x|UH- zEYrZOkPL|dGxQ;<3unCx=FOUzpg>X(hG%s%{!?zIgol>h`s967l4`bwT#xl2!fw5K z?Q{xm5`&n!AR!q86IOz$9}9r0x?rTB7!Z{%A8US-n+sep1F!(v7Ysil3~+J5jDZ*s zA1+ep2JmhHA4ZO1(``&Jcp2yb#wfQ8|h2^NU`i-+X0Lyb{#Ms!GOcoPq6$OVRfm49>6ZZ>R_}XmIFG%>Y;S(c2uA`6QW88T*p zhQp3*k;9vZT5vvH>}a+b3uRz(fLHM}Cu0!Ukq4dl5H!{!OB4w=Wq}NULi2bdhu&r| z2~~&qX-<@3X(U6lH{D3+T~qxBWHwBXgl-b#2R<_qKp=PX*4_M%<@zfho}rkHx)F`Kg^T!#5{>X|J2M=HcVod>!|-0 z^9fn{`CoEA`L_Td5D)_Z001-tMKS;Y4^(NY>OZ*i$()oDY`LjT%Q6L#X$x%`1tw2% z5Q5tV;B`G3E!}B@`}cJG06=5_YG?r94-5oZ(EW0N0)YTR;WLssQ33aehWxR-^z3C* zc7sXF>)yL;Emm~fyQ?mi%l2+xTd%C+;j5S742;b&@MTxar0|H3KH8%q%7_3y5<_?j zAtVC6@l5~;000>ogQ741y$5&iy?5QcyW88&-LB{As0nrzsw zy>-uym+swya@)3waIj@T@sJp{hVF#0yqE*PTtXwlZ@e*pQC15~2QaX|h_bc2%l!^_ z+Qxfbk-Oj{mtX{8?F>iT+|Bon4gz-9n`usWnYtpV-${T?-d-X2gia*4EIqSsMwp9u z3${LAId%qtC(hcgak4>+v2}4_7!$g$-fd<(h^y&#f@>y=gB4ELtUZdn>R0%o#+G$FiiBdZJ|FxB%mg21|$Br{I=Je%^ndK%@OtuC-MFf*@QWa&WOn5y~$)6 zyU|N-?G57v!ObY+{~DcVZ_)O(SXN6F^V88olsDur)$NZPo}_%q z&_Sq6FP{((oU51I!}InCnEs0CdpplKFh2YvEEZS2}L zPV4DuAG`Ki4<~_&)yV}FoI_ZNBtfX|k;OeXV!;#V}3;AvD^xD|W0UO(`Gay{Pjma#yXe{ZO>v?K?2lGDLWqA;!^1{2r zhuqB9uNHUu8f^ZXZt=v?h`BbbS}W|{v~=n`9IRZ{S|jE}!A!Gefm|A&@r=6jdqmj{ zjJM8ehsAtJ=Esl58`Q8C4IlfM#@jlqB+kO`@vu!!;>*xBk-ETInmnl>(d9!UUA5z2qS@Wbe^Is3Z`KQs;*!m}2H z-P&3(TLLv54`*A$KB^$yE?74Nkq{(eXH08^=sctJGkaXeKkJP-Z*cNq7z-YxdM%&v zD|)Mj(NFcWT`2sRma>TEQ1mkg45Iaf0fNL`&?ySl_tgMP;N3sl8!n}UYj*i0x+QE= z>_*RWu3abjo}`roK)^?r?a#5i>*yC|J}v2|uraBP*O0x1H2%1#P)T-gBFx;&zEa5- zGw;xa@pKXWg}%lrcaJYPflLq>jWmAUv-Xs79RJQGU~00^9Srx*jRJ!i_j4aDeQvY2_&_!#Hma0hE(|#oFa(hc7$^rT&Jbm(>qgH1s>-dRyE5$H`~7Qa8u|`O*G_L8TAHLK5`x=a;_oD%v;8aX!8_)GcMk=k^B% z%Y&p?sQvV^-iQ&#Zv59KT=Z4mYE!=hZ{Zo{gL>y;#%~uE`LNimtZwIJD`2<|7dNF#7e}3UfGlsZY+}852eQ_p4f6}_N9bb zk{+%!Sw@8q_CzG-2JvK$xmAhX>n7r(+eXtQMTuvUmY}j!qBV(+e=mti^Pr@ReaAVN zD8>zEc&h&*Ak^)r1923&(Wz_R?&0Kmr-gUrDBZjN?xE9JHhUp{vF4y6%YEApU6DYc zg?VSdiu(j{?T{354@tUqGhq9Nz(z2ULmFA$X_BwUPC$O(mZwQR`h;P4-t*H}=$p5v zg?S;%{Z6Rbs>aZ$OX`4^@2IJVq$%@MShH}YTB(ps%hFg7Z3Bf21%W-7oAi`l&K(08 zMMV<#w}YZZs2bC*&=gDklKoDZfH)AwW**p*#JzXYuCk0 z4a;SV?yKI|y*ANZx3Dy8#lWV8Jj}rA9i?WowwJjBnuOA0*-R6wdpFm7| zDFWxbWlI+?hVgRKiOK>3NEn=KaqVGhFlU%D0GaP6m#la?%hY7u*Y6(S){#-bFRNMB z-qIuEwnq0O*1YKQeez7&)F)bzkejj6azt%I(FYt6-LMi$5xouBn4sn5c|`WZ37=xb zs`>%zg8W3Wr2&v%%i0dH(U|<9gqQd|wdeMOZ2mm}FM}$7`jT$sO)JFm~ zrDH@`gL@wK``GMgq3qX@PTvG++(t4W(jYr31v_##_4d=2DBOFT!aLSf#i_YDbAVK6 z=Jy^N#9~NT4HFrWIo_04%-(C25bfFKGpIWlpNCvEYL{}Q4wMz@#m(0ARnxN=s%TkpeYr>ER~WxF&q;tX57=x|{xdl=qXiogRt8y>J1hk|{HlJD(O9yM>v|t+l$9GvPH&F}WWAkX8&ckr zBOP`2oC&OJ88%}W;u+m}^YV-XGq3;56|>y#xp#SiALCR9*k}$zxh4U@uN)m+leck# zmfd~vILO_BwHcm=&U`*+8|VL-w-g;yPA+UAivBYz2{T?|4B7jKT%PML(3Kr%wmBYI zg8mJ^gojcZ<}}E~B3d3v!f6G;A;>j1D1OHd$}R!c4AZ27c($wfhi{<*B!?XAqzgx> zCl^MXI3OI7GTozZGB-6Qt>9}sX&LKP*teg>zZrsa!HwoX1A;{;)k4BbB6W=M95q73 zSObP?&XE^v>Hwglroa=Wo*i8b0y6fObrB5*AIL?Js2IzFbxkkI8JvE={8y){5eMuZ zjS-I1b5W-6Y(p2YIol?LeL;UdAUpQwGY;IJiDlCp`)E@paYS+l?M!WKB79$*PWW*^ z^qM9(*a(k8SSf^o-5#w|u1FOXqk3^{)#rx)sM3`e<^k;0W)tk8psJIaqUZlQf01R= zS%aAt&irszM$Y|?(a>9^8OpVRQgZ{9RpykaENP~W+eGj_fvS-}1W=Jl(j-@lQL5)j z*q#-`d_5u#ZrNI77A7 zn*TwX0itc-3ZZ~FAACv@lv$hsq8dw#TRHcXf(Gw@7Ye1|LDxuoQ6fo1GOTkfWi%OE zOGY(Ud{Lb2b=TSw;{+<7-~ciZe$%K!hyz1jG-1rq8Bj(Nhn8cGqXl8R)* z@;666QqG@v$gFnG!Gs8&Nfv^tF;#1JM}J?Lu@GbqnO^z9vYzzLnKuwjBRe zANBkYk<%z*flO>f=#wT)`TMdKC z#`W3YCPceb0Ff)G-U}$#dT%1%&k!|5S=1EPDbacOlD zFHksT|0=2yr|U#RcZG_?BP{9ga*og-`xK!Ni|1dibRZRiQzFiY-;3CTj7-V>;rG%N z@?_J;I%fuAoyCv|?W{Bc=in_i)Mv$a)s^ZWlUTZs37z*IJ)T3|tu`CwiDMdirnYos z`JzUfyDs+lzJ~1*Ue;65d9Qt;1}JLKrq+rL=Ibr2tKhrq=E{0x-YT}ecS+o=_Uhf@ z){-WTYs^qCuT9(;j5ZzGXd9HPd?OsJA7%ieKwZDAa4Ed4>hH7>i8MV9)(uFWqgbmj zIXocM;0RB}$#tQJ>!^Db@x5_CLpi_LQ1`ax|?SzJzcpfQ+c2|K< zldaR{hu{Es&Zle)JHeWP#|g^e59}^wI4hc@Awc|)Z@_?3jX^>W|6*l6C`$Bb-*o%{U}OM_MgZUr4ARy~{;On?Wy=53ldlv5#F((h?Mim(g-fCvE5%m88^7~lKu-h1zDyLETk{8`UedRC@xlcm?| zwtlZ`+DTP{5K7bqD4<{=3uHw=0s#mjJ|uh=41okKsUVag1PdWpia(0XQ4vw#2cQ~$ zr2hjYC2>Y1Zp@{*BSCU@r?Zmd62=}NrIzZGm@{-)g5iuK&8}*Om>!HNn|`@N_x+l& zDVwHg4%4q$NO{j2y;`Cq5l``@H;5W<#w`h@$EkngS`-Ggq?MAodiV9<(TW7WoAPy< zFk@Peq&5UZZFb<5WPVD1$Hdf)cBnfcN}BiyoonD34Y`G+DFY*#RQ_)FL{D@8h6hly z*TaWlxl5+fY`2Iu*t0+W?54aOL&%QhbsADz;z__v+B*#ZL&*;gO&K>?8DCe0m7*s5 zjUTMMr6C<NiXYc5> zUutnB(=7u^+fC2W&WN&Q9%k>99trvnvuVJc>QV5E<(Mjxhm(Sk?CH$>jMJ0P2gV7W zt^pY+P2S+qb(jfT?;F3N@(yU?!7EnhrgDX++UQ)Ab{%b_HUvXz432jG<7}HQBKz&C8QYBb@v)DPVNN`xWsSVP(VYI9nB~nG zXWJn$E$32?GICa7h6R;u3>S1poPK@=Wik?a4~TvC*x(qOn;RlPxYk40lEs>sj84jo zefPZjY{4~Tl)>%q70aNUGV{;uhug_zFQ=v`W~XSR4`0REDPMN8TgQ~w>egP&Q|G7d zC9AOgFlv3-AhTGIDS<9cJ&jjjwKAp{?VZ!%pg4nIt96Qdk-R|kBzK#`SLJ7s+oMH} zKOT46H(qK3)cZ+fMD<~Ckh63*!2ITjF2cE8@%`s($@-D~o4tjadAp#brnQ)k~ z;c+C-&1ZhhMD&+)l{}dh*Zd1TUSAaM6#9#duUS6GX8mRl22{mJ>^s>8BE!j!=%X43 zlp(&vvXVLl@{+6RnQQo}rQ?%5K9d+Da%)2E88IM!t&3_aHtm}=o;$B)I{~Alx9@#~ z$je-6{7Tn&cy%Xv0M&d0DU6j!@XwZoZH~8`((ZdfD~5|UNt9x5JAqftxgVGMrDreZ zIBhWosj6|`9m@OEBJT5()U^n8kK<5QU~zBF$io~j8o;^+*7D%Q*~$Z!&4n$0$i=1K!ykBZ3#J!wA)U`f6kSKj;LCA!RH7*lE;8s0*q)z zklnS%N{O0%>Y}Lb@cQxnBYjR6bK%^F00?q}heg30>RWw&L=nJW8C8Z8AvJr07pQt% zW3Jj+XAQ5vjKRy!m!N4-bYELO(8(m5y{g5)=AAdz(S~(p*d)qN;p@8|9USWX{Osl4 z6_>QjTzC|EG~B|~klypvc}=#Cm%$iHHP=oA!qb`aJNzL+Bl^k*!1#dm@Lrn96` zP{=GyGjg^pMBzvK5Q&~iGgjklQi`)I-JmhjFZpghS2Qu>S^Z!gs7_dmmndw|I)lVG zvp9D*y1thS>?$9Td&4q}w;U(j;)z5boX?ooJSDdXq*7nlF{|&hdRQuU1@(U{%!@#l z5JRw6ZyiUrtR+Dld1jAR_3${5Io|t`NkL9fQgo7e{k#b`fXfNytpeO{5r${Qt5h1~ zX;Y{LF4+14E#~ePnelZFLnT_Jd=XPp|a~O5Ln;rC0cn zyo_}Pz98nOtqCa$>>}M~4TLlf?h!WQ-FAPps}#I_oHzo)rN>fvq@CP99Pg1)U5Ax7 zEHuEUEvoZ?m_2qte7I_oDO?L1Q3tG zBr+H-5d>mCP;YRk1OWw_0&PyQS)>6M08at~;ynPBDNG_T4})Y9A(-lb9RdCmycD7{ z1M(Y?WpaF}RssV@E!c9L?b!7ok^o8P0<{WbK;i*{_)wW({{qYFtskoJ*MfX$-u3r~ zY6b6SFSr~U&XP?6|5G)fUFg{SVgu!8YI{Y~$LvUqXDGB=M%wpgVBdouW`M9`-dRVx zV#BY5>890U`>6PSWiJTug|6aUly+O3R#91~D)Ot+y+W7%1o9UTp8>-Ry4=e~+cE=J zKQ|ZK9X#Cg!F5gb{l>~feIGKhU`pC!KzL`G-bFt6h8pu*MgWxbNss7a8IWIf>wEo1 zR;%dKoMNa&zYnh=E?|Q0mR2ei7G9knS5=7A+qgqT6IXZQziIjThoBh`p8s`Sq)#zsprkT zx&1nXR(hhvrR8&42YaP`GEyC)9<#l1j(zpMm(H0Nwy3}&<|x=zw@5?Z7v5#9#9?(4 z_u(pQKCdnB=5Q)Bq)|PbquC1#L>As9-gXxl>Fs_fs^nMaYUQLAjAoA8k&|(j9JI(r z$M?}S6{oM>Nwrl-J)7;2op@bLZvDa?(&tv9MiM%54ijXuMmaJXN+9Yn_7ASZ5CbKx z2zvGwtrMFL6PEf5R%V-Z(TeZ*(bV9`DMP7R85(5+mg#B!gnO{pLSW z{1|TJcmJ=qyAE1bJtCIZ>X?zIg-H${`WPa6lE!YPRS6?BQCr(Uq4$A8fDA^0S=)P5 zr$~4w0IBdE6`uxP?MqMk}hwAXn+u0+kL(en$5A z5jTw&jO2Dz`l3`<@{JYb?kSp^=6pxbGdsg^0bFIlgN3{0h{bquG1ZJF;uyycHL`t}&Jr*sfYDp4dQex&O6meTk~s zr^yS%a6fl!V2~z5k!UD1;UhfR3JuFP-h(kuw4#|pxOo|b`tbZ1V6(b?(`jr&OyiJg zFv1(=Q{Hj3hI@KMlcn>k-GN(D#&;6jHDwj>tqhK;@EKOn?7xU(=cKf5Zizcp{>eSJ z(|p7yEHAa(HuwKjc=OTbBWI8aDr??U)fD*`I%j6v&&wahe+Y{(Q2keK&fzwNI1IF0khBm1KwV5HD*z-10L9kA$p{t# zELZrmZwr!dXG=JRqq=7}VWrTfI5O*;E|Hu+w zXHWq*a}9%Kz75q_K9n}Ye-^kY@<74v|A*P3vluFO(OOkV|5P{K(!Fp#gyDDtqTp^H zv&)8ylfmIJNWJskVqDTNYTm33FO6sLKX^yGjA>4th-W!>1hik>LXMFsuiU1n^};_wFy>`=A6rc>cMI+ro z*Gg*y%}IT~l7)uSIc#_|rV?rnAeiBPv|*{blBKt7v7Ja4SJTmVAodC^NoD1TG()1p zOGF0HE5jwfXiX9+<2hEb><-k9A$dJ*3gLy_RFv}lx<$ymjygxiB8;N~gL+IvO%RHl zYO+Ws&V{2T1b`;Lmncl8`Fn{SZzQazm|6!E>QXRHlX7~fXm-+f1HEo=j zuF1#6t(`}D0j~Jox8gN%F_Hu+W=wlwhF*k!u5c98r({E!n#G~YDBjemM9-vI+C55& znIM15V1jdcYIGn`G?(D;Y#XzPrq%C_0TF~u!1YS*Ax-ZSOZawqYCbe*Z$|`kF_`EW zYh%|RCKDGp=}HF_YR3k)XaJmSt!RK%t@B!`7KyT@{V7TV9Q^8m45v!GR+44{l;D@LJr)MSc{E|N zYQ`)6*vbhh$L^r2k(OlWzw4XdNy3CNeC&Hw5xf+L_rr?#hFlg%uR$>{^sN?p3H;2< zHHUg`L}RGqSnul#QPg^W)6sAht^i{32^XcU3h+;ia;5}ONg$4$uvJ&1@hWPs+>Z9> zB1n4C%p_dvf68jEWIK9Wg?q-)KET>yH!=b{1H3Uvq4i(6@wkGL7?AIf+-&*uddw}c*{3~56=syyZI z+L)b{TLstIfi0qRWfe_OqT3&xDx6E`cW zcA$0ZV&K%EYV)bJKWgW#D;sI{6%BPGb(oYj!THvePpkcqi3myn68NJ*&4BpwXlMh zOW!&ZdN>d-Y4DufNqhFJa4qbt14&C~mP`7d<>*$GpA;tw!rX`(UDL)EACQH`Xw?^j z4gJY5Z~3n?ASQRQoB*hbeu(u=GImXjd9xT5I=>z*l775^F;vU>=xn;WSW-D877KUu zW;_*p- zJOQSj+~S{wIahd8NZLSZP+-v0`M8b<$4Von8baUZ{}wr5%RUOpqgHN3;h5y#v@+ES zc1*H_+?c!tS(ArksHTM(AePW>;>4r6dcQJku%}rVcF5mkM(%qbSzX8(zc4K$s2&K_ z0}-F7uc-Ig8fN%ZW*3jISRBF-5CZ@J05k(IG5`P%RcR_}Kg7;R=b@CM*GX+&)&hv5 z-rz+nbS8=rnzRN1&bEgJDgV>|{}7!302vvuq5}X}0H4SpXarP*EMEYl#1#k!i)xfr zbFSMrTUc9a_uZu1mMgpMUaqan?t33wXS(j=tF3ET@r|=DWo#Mkcz&#sB^6%bs~#9= zB%*K;+<{X(Bm)5>_xFCiy?Srk)~#OQxMkREud21!FKec( zJz5tLueo-Ojnp1wT(rLmRdRNS2%zN!I{?w5n@LCgR4W3YS`5E>&7FQQec1GH?5G|7cM3^Z%*eNkBmTe$* z53`rsY{IG$L1sl0R@`7jmP2pCwl5$~4aj21Zy>@6#yOE}xxSqftNRw>0hM46UG+nB z>K$5(4s@HB(0z4{p;+>^z$R~cH|aF~-py2UG1A?sXd`nhNgxrSQX(7PqG2(ypx@nr zHIXmFmIbxI<`A`3YMD&4JK6}JaPXW+pGAQn$Si9(>(NidyIE<#kUrtZL#n3N^@F6$ zUXI9fAtx)FNPs9Rx-0`*7-J@r8v zy04md4Pvc|vEJIXAkJuex(*X9KT$=1E^E=ACpP@!5`~CGs$`X2!`^S=;ft zqlr*d$8k&bWnA1^!ybF6zQ0dCX2b;djnRdJ$?Qb9s!t%*%@@5q9+MULRq-nLdfQjW z8&|67D=CbVrPB(=8Z}q>T~qv|&Bz~{pG6fZ`zz>4zA8qUSG70Y1`|{q9TMAAgRU)& zRH{c)7P6#abX&hTiHqyYmJ#`_mRGHQnWK?~M~h+QG?_^SQ$BD@inU9`Bpz!qBR0pjN^<)aF%#FT7`pl{4Ej_Cp%BZSMI=2 zp4Hl2o_J0mU%fHwPvEH~UYg-H`M3JNer*bGo=SXpDw$ujqs%hRK|B*pA`C751|()C z=^xIsQO?YJnrD%68@S^bch%|Ej{PKp*F?`3ARK-5vRHvNP?OQ>T(prdCe-|0M{G6s zpolWz?H_~W?U-sG`vGAy2z`$rBnBKH&j?4s1B;I!90vk?o3OTWO=iEFB0HIjZ+wQh z;RXOn4&melt1FeOmX~E^Au=wxh*+`8rt>KFBN|p%X5cnS!sASE4g=-e4AcBfY*CHg zSqsl|T(5rVh-)$01Su*G97IM|l`~-LR0}jJSGG{-Bj7l8NF9OW{Ny4KegG6%0#x(^ z!fNog;JLchQWy*g1kC^&0eBOlK#>nP#f3A%tM9PI3t^Ht11SK@p9ow59KEUlf`eBE zpqh6A5F5ntxH!YoTU@OVrL?FLFk1iv0ABJB!CchpDYI?uK<`Jv#W189%NU z5sdUt{Tq%!Lro0= z-N0%hdvNqoa|cUeE3-BKtAZgfWzi3R`shsA$WO ziv5k=Bt$S!Qr>g=2hQtCfDPWp>{G>4`Bcna8Y zQ(fC<*BRdF=1m4eSMSub>!XwC=YebHCPIs#3x5}e>wG?K^Us(l+7!O=qA480V-~xd zj36;C7Zl-9uZ5kW@a~yn;DLS9D7_xt^0(ab4XeQ<3vLs~g^lHJ6q0ipc>~-Vg8PR- zy^u`v_rr6&uRU+?IJ9n9WR2PIXh4p?zF)@j>CQ&BECGdNy?K|X38*19+hc?6?zm5= zwh?FZp9A15e4PDV=Ph!K2ALztg118>ayI4j<(uivw$G&;GRZhO$x5+n$As56B78ZM zbfWH#TSD>$`}4Kg?ufiBzQ&nP*`223Uvmr_9!ku!7GjADq1=c0NStnXY{T_Ek)(ZG z$DeUI-5W8w$Id@r0M`>vj_EQx8##X%%jpww7TCI+wvocToo%1Eq_jaj4iu9>+cITy z2VDdinNQdVpw99xKiCW(aHAq~wz7GXAiGw^a7N&F8<}k$g_lT;DdMfW)qh-_mD6)$ z+z*0Zz^8~U%=`H4RHlPd(dWC-6YZT=J(j2RWe?Db?k950(X+oY(Mt5Vw$BbR622C)^EqpP zkJvV`pJhLpj%g1KsRbH?aPLjh2kDD{?qkPN_W8>{X zZ-2}>dBFnxgC{~j=RjDKdyG)>VV7NO$f;U}v?(Yd6>4{L6B1@tegAE?X(lUIsi`T? zP))Yjn@qH8!9>R86B{z3=<0P4BK0D6P>iV%7Neo7F0HRFM( zJ>ST9QwIjDPVaFSqC5D-j3E zT%R!FaOGd<)%je+r{;))4ZZ%Tl?!ixmU44=bid8S-Hen$=l;la92iZ5>Jo{{J)q;1D=s z^{;DKFZ21Z|P2@3-+oIzzMhB%jidoKZzesxdO(UZSZbTl~~YmQl>l_g`F z`P8UOplK|d%0LB5STzo*t9S!kLt<>Gw6TfcE(1!Mh-sRM1Ned?|8#jv=zr4F zlb4qM32@R6|KSPAf*aj9V%+|^p;K~(K%g|oqoZ`)%Zw?AVR9=zZ-*DbYeb#>ufPGj~^QOY#i(41XxmdaGo?=gd@hi3}gMY+UkX-Q|Z zxLu|TRJTFt1P=24)bQ_CXh6G02MV@Ud|q0FNO`C#BUQ0-i~{L9m;j`n4`h}0Ek5KT z)p3I{JwP4}F_LofTbZM-++QuAo~Cq_#JC9QN*Dz}dLi+dlIjw5CW8B$dY0{#CA$(_ z0Yi=k>$h&Op|q00Hpnd3lWjkyBlY^DAB_}PAGPLu(wlnut+56|Sp(EaeGWt+*<)DzhtPq%+>PF!Anp1{HSCkWQ$0tqfw)&7T zD0>nIpdVf$Q8@2ozwn%u^uq84`?Sx*d}uq9x0gykviI-mi|{MbblC_8*KVilG`Jet zc=7|c+*b!*aEV>@BdiOx{F(LD)&#&HaCrOa>UHK=m#YEUgHzKEhyaq8c^%LeGz8OH zs>(x!pzaIu!Dx})(vM5@%MGMIyLlz$PVLR8R#K0uHSrVW(_sRK+u2$G0OW=vcUos`oKJ-0jL>EZJTugA^Bf{7lrwN$`B9&0000)13)qW01s6HDNcJ6jsQz- zt3$%GHVba;R;{E}wuae)5S};8s_y0UoEew@3IG2v>k6>twI*bn8i!aDv%YG zf8hZ*MUMecfKlM#djcQ(0UzQZi~s;40B|$~2kr*H{qB5j-BsHVCtAD~P}}WOQ?;jU zXWCi?g+U1L1`vrp2z)^>B7i8B!Yc?AimDHWh-+8MN5BgqUP8PNAbfyGBFrDxG`?pP zE*nT!=86pBy+^Fy&o}t}o-gKcj2a~@`Vm==6OnuQ33r?hfldJ~(1k|y4I%^2wBW4A zLegY3Q685UKaxpA!eiN{En%uR-WH7vYkrc;)=se;IZ+sAQH#7g2Gdr;$sjXErvxMV z=Ot1tjrL{;9eM0RfxqGV9(fvf+4_(|5(pI2D4rIwiHOdgi9|1%nC~qf8?bog3SDeb*m^B$LMXailay03w8t%(8Q8uXIL$%K{D1#rAJiAZRXy_xxGuJpy@t((X z>Cgra^csH^jAt2n41c?sQ%>{2(aXh+pUN1db^8-Dy0vdkX{Sd5z5D!lipiBD=#Mtc zbmF6dANw5L^p7juGWAg?DcJb%#xwY4`M0jYT*@R+go|^c)JsMLb>{)7#3ggW3+s2J zeRvNZU9}^Jkg z;K0Ety}gy4Ky&B9dziSkKbHGacbo%UCgYtVKiP81$K`Zd;+wF!W%)bjO0yL_%(q%< zeT)=*@?9qENQI+s}!Fh|0UO#ELcrSOeJcMJ0s&lunP{F3`dzS=p@e&Y*wnR`dkqagQul1VY8}GPRQlq~L#wJs^tNOmHOpIfO)-pI$gSgZ1K-4sg zNoVCUdd#!p+>t6BP z&nD!#<&3d&+;MYmNKLFlQYQbgx;I}_3SOD@xy8`pO8EMIhn=t(s-aK8nGRWCAK#Yx zn2{ZM$NUNQ#djhe7iR6SM&c%qJgeKyc~9$A(lV=ArW-a4t9=y~IB8)Ea(vyqzjtPL z=|W}SA;h=Xg~dU5_6{vsUD_Vge$|cs?OMZhE_nC0mUZ4u8rVnYj;Mn}iP{DZ?GlM5 zlv&5x7}8Qnbx10?6m2W&O%J#s6wX{V!4j~{wKc%?*&Toke)W0^^u*KQ^(#J~yFY)L zF01)ZYlPE@)k=PHv~l{^ZimA4&lN*jvTnpLxvS6QcA-c zn5Q_oBz2zdHUCZ2vp)wGM1X&*@0^`zT?4X9*!ljrHhbL_&+8nR8WGBN=@sbZm7EX>6f z#pZGdR@(vZN@(J_-b0tJ15I^S&9|_1`6@F%8Vi{X{n)UJp11w59fkA;|A@FNOb`FW z7yv^JAf#achJc45a4>)u!?H#M7+4=f%o$*#dY^~{Ol?vaLI4R1YcK>m6q(`$3*fQii+v^1ViAmDG?ZR0P+M97{MKeIKl+FXpknLzzOQ7gkgbXeBm92Y(NG= z8Vu164YJS!LyTdJE-(Z>IGo||lRrGT@d$<*K&itK4A%#Ns8>=3h%*SM&@hw$V*xwq z;t+ng!hmCg6gWVAeXq6-PGFY?3)JthPtwpP-=E<04%-b&A zO3K-06|h=BaFjB`VHRoGA*2Ru8cP%e9oZ_{g)~||Uu}fLBx=S5!SZ8l40IJZ5)Bln zg1d%TF<@6vzhObo+HU=8GGJ~FwutN;Qx zd5AlP0gjTjCzNA)7YMw75S0^balk-2EVz1t5eR|9Y#ND^GO1Fj4p2^-3x;7V|) z4^cNG#YP;(_ReQn%*$H{gX#gRiV%ZsIK4Cuj0e<5{A-gRgKF3P(mqh(6kmp`X4X-Q z+^4L{j>7v5CQ-I07L^vG5`R7Wr38_KEkDRX|@U^+-oy%yS8di+G6XNy9i->BQ3ux zW;xw%=Mysb-*Ef@fQ$eY%>dj27$Jm0|9}A$L?b|z@B@AzNS5eX4|Y>a*h#zeMlFPm z^>U9rGCJGZPJNYi?c2B6Hmu{swRl9?$U%zLc>ZJq5v3IYz5!Ek0z051;E3-LzvKG= z2mk<$2mw@GfzJ81_jd2w);4!pp}5HlsQu3?iuM!i*P!e2ReLOK>0x zlt2bxWME{iP}(p+r}%(;g!qHkCs?MhG-Yh?p?J;&e0q$CNPa^rk^U^kKi%AVI?LRz zcWZBao!#Ai$E>=1aBE!af%* zuln}xn7w!V8@uK1rk;H9(tyu2T1cy)Ff~@tv*$8h z?qSU(VdS5j#>J{%oAZa6WJyqrPBKd23>byA=MmAgX43-%6vU_?2SmQ{_@YiYfT+pJ ziHjGfYh_aE=`525IE$5$zIEp_dm@mjD!5JX!zMfSc5h~bzMJtxxBN=H^ZWW4zw1w; zkWzLzDD?}x1gnYu#Q2M!vH4%N`b~$hO8+KTAeS6IzR%L6ciK0!#FX-qd0L%r@7o;6 zzMOB3(q*A^^gXjr>D4sM7M9!%9h_c}oXXjLR7sQc$X&1b$52m84{k)Oufkw#qg420kIr}84Z zJdid>w|Y{NZ9dQ4&R8dlgu?11QpNgwa_~pbqWD^WN;F-pYf`2#-nE&KygT|$!#g&tg2(BTW;)KXy;PvscyL$PCK{$c%&)B zIAs1@EitmgUsp2-ktyE4y+%*0eZjfbk80`-)(+PhWQhb;pEJ!8y<=!E$$kIIG$X|Y&rVq(2_*&P}fyiy2{

$DprMg8Qh&EF(}y$a%TUl9-9;^xF7nv8vK7Zc)9dygM2>CChr zjWu$@-!(bC_4V~8|01Jj@I+!kpShIsFU{$-b%+@U6+gD0p_!Fba9Um=!1!2GeDNlA zUs9ATcP`wPwazogyUvq?qC+Rm`ug&!o4Qd_e)*93eoZ^pXAi!v(-2$$>hwgwvba;Rwf+)b z221f(DYkui*yFHHoOh@%6zQNAO^9=^@NyvXnC|tAEqX-TkbU_y1?>9*FQpuvS{nt@ zAEO1#wzADozQT}A9^;1cajfg>Yewuk9WOYs5aN-)ED2!nu#PM|PPp0187?f>RM9X= zrwab!FCs*{F@O-}oA$l@(eJm=P`YUn|EL9>(1sXDaO!jZ5w6~ro5qfaJd_U7*)ltm zyJ4sNO*e-gju-g5uC5m3>fOtw-NVf*gS0Dmg4_M|jbqAB{As%+W4k)c>@jaQ`FLjU zcH31pe3pUL(zerY@2VZOo8)`6=OrP&jAOZr%?g_DDye(LkcYegt%}hJuRM&?f~jl` z$%~d-zp7ePwL)xdoI=nd9Q1n(D>|JH(@Lwv)b#m8hl_C^p@q&h*RJgTGL3_MzLb%) zd6iLQCch0eoneb(+xZTlVyAors;VG$7AYw$h{cE9x%jlAAj=t-J6c<{jw4eM?Z5F# zTyyKiM$5$e)gRUedQqWDcOUNIOX$WV*qq@_{S|)c~HxHqv!LtRJ{kc>ov7 z0t3L6W%W{Ocd?C~nPW^IttPX8G2jf;)BcYP&9h>dCYX!>y#^=ClD&e|g)!d!o?Th# z`+c|Hm0Y^-qmk%cnNHREM!pAgK;}MK7h4nP=f}GI$D3+##s^-@60belry=^AgJ#Tp)p30YKZ7 zX(UyOfrtkX8~_@`G6M$Keny)FkDB2t322is(Sh?!n;p^hGxNQ1_{+&bR1Jh@+>D-e z41S27>a`>6nqR1e`h2Ey4?}rf26C{uupWc@e@<%BQop{dS zE53*u11_Zui@&|nHCe4VTnqU+%*UBL$PaYP95Efd!NgH|1J zP2dNv0#u?Q#B9UUqtXG779J%4n^`m$_oH0F(*Xc9TnT{S!Iai!xvjx>^d?G~$UewPeQ$GHpgfFG^=@eCX;Yc4$QGu7d z^b{pHeSj$%3VU?w29XcdM;Qa}hL6(htM}$?pR)XS_$eT1>AOCVR_qdb{zs{R*?J0! zm=40QVfIm=z#1(+N;cl|#rwX}sJj*on^AuhNBDiu0m>8tKO#IwSpwm-fGAEl{EF*{ zC20JF_2ZEW5-dO00Ll_FKjJ$_aRcXC6qG7_eg${a!jyjKLG_~!zyfjmQT-7Gk+dH{ z3+w9p?bNc zS>7LW0CGm~j}VVh%s~DvqDmRgKjS)UA=*F3G`zu-IoN-$0Tempe~xY+B@Fy%QBm;m z|3A10mP7%HAsj&G0Hu);Ag2!u#gGDp1y3M>Isr%yKxyzZ>Xqe~=rL?S_!}MoU=R=j z0000)13)qW01s6HDNcJ6j(|(HRUzSBn}XZB)hlV0wJ>)O!mmd5R=jHN&f{`FA^-mf z=KuiA2tm;S!0mybK~Ss$ETSM00kZ%#;T#k}Mpfq5-MtWy(nPzxtZx5}>fF6O+TGTB zFE(9m_ughrI}BgN0C%uR7HXXQ5DQqPhytGAL>?iKB7wpSJl_Mp5fCE)0FeVQ8Uh4v zgzx*lySw|VwK+>0ZmE8qXtK0j_AR@AYk=sPP=NsfMgfrw^Qa^v%-}5#9l(GwzO4pY z1;1D#EcgiUg@6xzK=!Boxv!on^%@s**?-wMw_#S9D?-}{=*%KT_AHq%7L#E8!~CUBN#Y+n zCy)4l&5aFclTJ5su^5ZV{+syjIGRr#Z0`5EU)d!X5?Db=c-)U5z2M^O6gJP3_alU3 z@Z!!CaZW{}i`cU~ME)hi7=0Ke!8WAth9u{vWA7$-Y@jo)SbJSo_hsEQX}Y_e0~$yM z=EMNBEJh3?f5daPSm%QZTmd%EYN9Dn$?82%YS><)_FePlhL2lWN)1$!zAn0l(NsplE1s=oyNI?@SNP3 zexuyB*!DOx(4+WtEOWn<`D4MFip!s@oaf%B)_2CappD43=^@>{Pv^5Xgw`>r;Nfkq zCS8}23+%>aQW!yRIp|2^&Mt; zXYCBwc0|6VOeJ|_(OXjJ=Crd{xU(0YH5l>_NZLS%Omfm>1h3&PDO?9v4rNk6{?4xO znk6`e!G6IB?cWlSNEcpxOd62}>O$a0UIMl3Hl%~=SO4|4KDxrgy3|ciCn}7v>B0+T zS;T-EcPng`9TV%Hi?=ZNHn5RzwRW^Iyywf9#E@w_>1C%{Zad~s_nI+iY(12xT{+7* z#_j&M#K;bw?daFd<%$GixJ*2X6eOM>?AHl%I^|D!?P}*+Qp%`>JMv{!{?GTwwtxPW zF`LEpelx2#(r#&8LmQ)OdloXER=oEt?pF5)QoiMF;V^_|&-JsEZxsK7&9E<<(I9<= z`MC2(*>_eOEL_~Q(I@`+Bzw4bu}4^T>sO?%tqe)Y4FP>-?^&=n$c-h|+WNCgJMV5d z4z1w|Z#)6qH`{FSvxs}Zdzm}?>Q*}~7sHuQrCa^?+&e#8U&LPxU+t~io3gX#MZKc> z`%uFlk8i==JO7kLYMJ5Y#b?D@w1VnjnJ}GKeu}p}IX(LTo4S)W0*>;v?<22C>(6}a z4XllAX8>XGDlPB z(r;Hws>DA^VVygx*FnJ={mSEB!ls2<+N9J%B0lRu?ngTWMx_V+6Q_sZXlc_*bE#1z zJHw*3kLFMrAD`_q>GR{(*(dE!V1=m31TZ?8jj}fb6#+1;2#M9x7I`o)7jFLRq+}?_ z?Qnt=snn`IQ;-4rl{1YM_HC0>N+CZWIK4s7bZEHQq7sX~CU0`x+?wYD*(qSH=LJ(G zTVPk5Kyx$GlkfoAd`vh21PIjL4+xl5gH9Ka4aH(;hjSf>N*&Uj@L-|)lOsd1D6<7dYVsnEsqowBf838HuUzalo`6%zj^lX95gCaFCIlK%G1y zGTsA04gnzpQ0b!xqy+{5ap#}{gaH8=<~Ja%ElpcENUs_l(4VOSfHRF7>)|EA^vw!M$S6V?HK$>uQc)h+eNzaB|@1qy(_ zBLDRNNN;Zjab%8;aJeK7f2sc%lDSV~uc+ zn&aND4myq%>B8TDg)-O7xnu|s07TKo5d8|MYdD4oOjkNG#7hIEEcRxX+r8I2>fI)G zy5|H+K2&Fi02Vpcnd%DMFwb;M7!U}`X255WG#X-2&edHQk_3Fa<^ZigQomObi~E$S z_y-K{GRT9_0hmk*5K;<&VC@LhO~4NbxxLQ=oTKmFtat3P-C>yBLqZCEYhz`#zbRz**b)loxUbiUydr}P*uW>D_{wYAFeO$lGlBgmGTyqW6-SI8E?5gjCL!} zY9l1Oa>a~fe6DD%-HdL0h=41HdJGp08DIeQvGh?&JaCJulU0;qVTuwwcB%xGxe|+0 zb>i$_`Qsbu}74iv>lS>QD^e^ z_R32l*`aJz#12$d2#Cvfa1YDc4mF;PkKQO+)T9a#f)nlA-FpN*P;7Wa=w1+;$g}F4 zq^e6~gQ7^k!LDP4Iq=hGBC!vpSK-@r*Yqc5ObD+^ftY0IIVC|rJq#V}0H`J$u#EiV z07@SUUl5N~lnb+NIC~i0s)9bYwPREyi~!L9*a%QNNCE@zS$%*AOz^A=qHG}qccc3S z2d?Q67#)#;!T(~610n@rDJlbEx4}PAP)kt%GMZGvu@eA5>SGZLN>VV-(LI9+8g()I zssx~~S@o;&RG~o_J47XEs7k>Z{<%P1OhE)DoV*F*slk4l%dwdHX=1=g9Sj%oH6b!k z3P40XpxO;%?||#y17Vn;I2VNZLk`o|I6TJT1F!l?E{OwS0&q<)KrlDhBu#+I3BE6( zEgxGzjfaF)D2qw;#R3(18cA^n)Y+&7NCTomP?y0K+PEO7(t&LWAAp`{Qi>~x(*>Yv z0En#^4SjIv;RKkc zKx81RflvWxs81lM9AH}&wFH+)_=O6}X3$8r4wp=Tg^Nfmr_{p-9J<+{2-N^9hA=jX zp`L*S3)ceERM<%gWPvj^)eD3Cbb?*M0MHN+0ssI2L<2`7004hwft1re!ll4ys~U!c zb88iDb#44fx3LU!3L&poz2)07ch<*sge?8{9RC0yBLGD+0CxZeu&QkTuRtoo6(CLc z0~8@b2s2BM?h=K#Ro&GcFKIGZq3+!w%(ScB?}=<}>%KQ_*N%%vaX@XXmEsm(e~?v# zg2D#)gp=@s4vCNWMSPF=7~cRu003x24xkYY@7}w6?%ulVZQ5LI3<5W(t!-9k{;kWR zDl`NTAgE>h2=R)dKQM*?WdI5lLI5#-Y5{a@sSSw{F@AvnF#h_1$O$9Bz4n9cEysQQ z=l&e-ZJF`~?I>WHk{-fGhI{gJkThYg7-0kL6J$Q2BElIqgH0n`TCho2I$quW1omPQ zOWu;lVFyV-aHKFu#9e88@X+g{!XKZne?RBqiLAk5Jxg-%)C-Fb{taMzQ*otG?Z~;? zFhk5O8rn#FjLkl^_Y2BrEW^9DjbCS9V`H>ufQLqmQr`7Wm%;NFECDBw634>Q55u+V z;lMxAtUHT>pivor!M_;z zC%@{J_%=^V9imGx-ju zjee)wZ;Ele?uzoZ)m4Z4x0i7Ah7UK9`?&Q@o}9kA$ufo;Xebgo5`s&)+#o@R6=~17^-d~@0YZql-ujto|FPEJz zSvT#;aBtAzdoS{VYRKeU`;5O7XfGKhd_mzt8r(b_AS0?FjBcZbrUpyUsWS&=YwA+Y z4@$6$A}6R{dk5s>7I%C`f9c`Oz7s8JSL2(W}VeS`M|mD_`&6u$(*fV*>ecbeBLPcu**T)pe(tvUvg)kJJj<`#ShYi=SD{ zRpTq%&gu6%yALiyKXZ_gi}?G?>P}W2>Y1?IV_K{PXJ7&fIzPRkg75u+!D{D(uWX33K~5@V^kXu z77thq{$?>=lVs_%A3O!wui-&2Dm2l#DgZ*#=Snw7;l16_bgn=G=D%EF2j@_y|B7dx znyx74s{qmZIoI_8@&0|C)U8j6C?tiw@Jc!FKa^7>jpinH=@B>kToQth0*1ZyxF|obM9Eo{Egg$9caN z`8?CD@F{1T;w7s15PrBJ@RWtFTx2bL~T1OtB8|Eq{=G#)jd?%B~bnM$G?@pxapTnbU@r&911> zvu|f%GVj*~vdC-)m;Pj+)bP{jCq0{KuRBMV82LE4TQu}OD!eEE=(j>OR3!FY$D6`%&Ba(Z?Pl zkIOBYZ>G3k?25-8UsZCXm}4-0Kw(Lb$ z?2FZ;7y$-l z?)?x32^v2F5M#)Ixq64?7%&0Qr8UAqp!WKn;g0tDeD- zEzclQ*rKG$eLYe>fO-H`glkb$0qQL{s=FWr2v>mJ;67x%5S=yR?5`)?~RGPD>; zg)ud;oIY!JCSI12sPVN=(PEHKKo> zmW6Jr2DC#eMj!ER%aU_jHby~aIopMtjx7Rl(BOupAfz99=N|~d1|3j1>*Y5POADzm zZDXoN%+f-673~Uy48UZq0`cL1db=6GI72BYfWd|{(7G&|*Yx`DOw)4ZgJ2!Pu-%Xb zu>-(%#~LE`2C&S~0UUq{k2gQ87w9|?Fa~f3JO^MoArGtiItv{LAca=HLM{Oaw5kRt z6(PUJd9mZh520cZBdiSs4uB`Eij_ck!!`r4>yQBja09LOrU`3zt89daKmrjBZ~*`1 zAnHI3BE z5($9gjk`4%o1g1wC_yx302;$_impvj1_!`Ukfem+1TiE<0Eo;x+xx3W&GgeYbe6>w zqa-i@P{X1CwjEq=U;2pjqG^)S1|mFbCH0Y%pB0XRxl1x4AZR4FO-C09BKc@Szi<+X zLQ}bAQX)WTB)8s6q#%Kb3?RJUq-d;(-Efkk1}70i(q1Q$%hX-M8e_ex#oWnVNNQ4} ztY(mBMcq^+F#usHh$e>>q{zXFVoXX1u1LT-WVvLKfp6w6>+C?&B&7gcfOC?vk1hk; zA}LewfEbcujxQ3p53C;?T0nl@u;e-YaWcQ1KfZN~4H|NRJ$007Mh zT@3-iD1bktB=n$4qJSR(vV;eGgepkNNIJEhm*N<;x;K-sNm!wFw;`l;tnKfMPIv9S z+1B0Icve%2M2@Anev+{)6+gg0Ul`5#KPr0Du4h)rc5C-xcqjb9>yp zHt$ZYTXPjDHvp?PR)5phmo=<1EHcFTf(*p?kp*M|f*}SKLVz*e)k&~D#eLVrB)K?TT-p~-6y!os=WijM1L=GQAo__o)UP#Itx9t)bK_>^_-8zGnI7Am3 z#@jA6)a{*uSvk7!Y-fK6J>YsW%I|tM@28-t(87269gxThP1w^Z|VNWuIanTqnhlf*|&&cPBd5sexy1Bq4AmqPp^P&ZY! z4so(X7bUu2S1~o9}gRadEtL9y81tmHhb>Q}0)Mg&oeVOl0sV`lBXWvvV%S zW9n-UEcf;UgZOgo~`H?8WY<)lR=@NvM(qiJ0E>GzH!dmQQR~Yk#%lZTF@N zGruMu_j1)DT(^ByLe(KN$-LFkyCa>{6@SU68TmV(iDvnHu}xhsnD^4H?OGAWxLBCi zH&`&Gq_?{pFYZ=&$I^Yo8^htK8@@&kulY^!w%X46yBlUpTpKROQvPzc-qo5Tzn7uP zJ0A$2rLGosS1E2ROBAt7Izs3UhlSiIJGQsQ^lz{+t$XzdZbK>Vps|-XQ3H614Bk z$;xa$RlZ3@7h90j!cD&%^?H=^gQ9NX<%gMBwDU|K1zOM@NV!6?=AdnPV+j?Ng7o3Ur ziWWD`RdS%(M5i{vZNoOBOwWS#a7?$4_q)xp{7aL!EsQ$YC_pj*)I9;BSr{qpnYaQ3 zgdp=JknuwZqFb3@2cZ%79z1MM0O0_9)1M$o1rKzXAiEtvLI}QI03vzdUH5H0d_>4D z(L1a#(qNF!q{I^%E09#x8>l5fssKWwW}p`irAiPO0t`!FT1^H>t>H&a2gr88!0G@N za|QyShr1o89PhA_CRwCa9TJ%s7ZgTpYU0?xUw7&npOxnhJi*3iDgm%DABrjxs zab3UP+$wAIMJJT{$WEE+m5d35jRM}B-8Rpy9#>|NMOgF}@9*hJWm>&HZjZAa54LGvXZg>UmT?eHS5gK zamuV#YhL};R*@>l-g!1{d&67^r2+7DFNxALu0QS(f6IL>WoO658_VdxaT7llOYP$v zp|wLy@kVR>U7cW8((`P9+(x&9UtclN33y>@qo^*vz6^4)XCKc&q`8QLd74T?-+*%c zG=%#4_5{3!@^CV<*}Nt2M&`qZ;u>g!k5Ck)dRV46Xzf4h`x90I05MoyI*R(mHXl?q z>bD~Dt=83v6Qo3~tk_4~bNk>VSHDPV5}oFCI&&hb%`~PJ$Gi4(O%&m8}<8h|~ z05b(9gIeM^#XpyjI6H`Y%_`F`aTiQWUse9 zeGcETmUcs~?#l7IFr5km@S#}F-B^rw1m`0m*j|Xv7I`9HLVAB|ANnzCu$*-Q5k%me zey>8Yo{$|m^;;2&R}Z|nTk7=>T>1#5qy(-2Xi`9&CR1)nj>@ef?<*rE+$rM@c4Uk}mKJQPA-)cgB5lnVecetF7u4;9RV zLb<~*d>fRj9vqRMbb7H4@ywG;0Qo<8$t4f@;(tE5ps@ZnCl^1+{dZG(C)NxwJh=%F z4M?3_ZqQ}ovKSIAz)IT+)D&|~DHZ^%hG>hbS@qbIuUk&y00=K_K*P?RVzpG+s)fR` zy5G@5e4!x0Qmi^8uL&S^F?s)vpLPWiwHb(><-SoMowhf^$uz^r#ae@5qpA_|k&Z9V zn^HBhs7s2dj!f_tt;voTewk(i^T>Y7pC`lBw3vS*_|0;b3%6Ek9=Xo#dXNfw&Mu`w zO+DYJjIEYpa@R{7Q4}QrPgG7^drjq25Q(mcJV)0jMUTaQO&C`jz9Xs!wqXGefa`=(>28)EepVxhGb+?R3Ye5kj z2p!~PKQx9TAEP(EijJ@5+ah56PT2%S2vo=t+$wRoN1!N@KKbh78GGr9TND~0{MJe_ z62S}z20-p7AVh~LBnBc&gyl-YH5J)!AQ!QoWLL0-zR$b3+af#w#-B?h*&@e|{N_GG zFoC5cXJ|dVB3sn!-3O&tfO@U`|1PuS^y$LRr?dtCgy8d3?4ht&z`en;uyQc{-L*>T zyjjUnq?Rt;C@8Z)Cjf|FT!B9p7uOFe#jrjJHQoS1y&8%V5a^y?9U&L-a6~7`hI~Xt z@)P?B?^TAKJyOA$LIto)^igxymxnFvow-@!tT# z0{}xKaA!~eBLw{qK?xC_fRK0=zDlhFybwpxX8~e@B^5FLr4hk5$^%s#Jlx>0E7SlMg#zipy0myx9@#- z|J^#UF=+imN%w^>jG0;mI!AK-ZjLe8fdz!m5ueQn+dqj0FTuQo z00SaGJ_7R*KM4N5($ZqtyZ<-$J=6lmN27WuSt?B!_B5Q(H=B{CueD(bb~(fEyW<#N(9dUt z>_*oO5J?yhBGmZy&#Wa-5T&eZDWjy@c)hdHB2@ybg1I#3`7pefXh|1n8 z79{?8#SM1uBM7%9IH!8HJ6H3st>3?!%mJbaGCRKv<-Q1gPY#nZ#`kIS_HJf* z{C>rWr-^`O)yA7k(gYo#OhM${+7hE+c|5AmR_AC!!f0H$6T2<;p6Y|cl7?inb&Z_} zpv3I5hp}@nKHIYtXRh1?{Min1Mx})@p0(B0QwMu*(1iPEW6rL0Jxy~NoN@hJExdEBNPc6IusO?ep@d7sL$__K41 zOw*=q%Lt}z@Y7pb+S=^fI-m-NdgoKQ(jjVX+4CMPm2%CBy9lPIGgm@9GVw}f)xssc zh$ntIwXIp~LHw1VOTHB?Ir&)Dzy3(&1&r4_C$%1#k(S%JU@9)BlvD>}AVq{9o`(WL! z>Xt~(*Zi&9jJIGK#A^?@e0h5*@aOA~)&^#J81)L@r_tNt{@&OugY@5MM_Yc%0}h*ZU!VP1xxIL0tHF_GG_7rL zjyta4Y=pZV{xX-F1gQ)tqJ~~;xz$cGMKXc(|M3aLX=`I6zPOoYo;~GMu=rg8c(J+w zN<&}(S_OotVLz>hAq@xq-+>8V1V9)(AaVQ~&v>b1{2=R-r1*yv0PL!Y4>?}&Q`=o@ zf@1|xfd|vnpr9KV5;bRY55x)l?J}Ri6#T*VP5#O#AO>0mPRSf7>;=Yo zv2+WRXMY_3Mf{Kf z^z#-AG0+F~6MvkCpkx3p=~fh^g9SPS6@BmmgJtZzfhsjzOY9DYWq}1}lN%5$;q{aA z1*!{BMGzfTCs6hU0M-bE)`1tm7ua0XK)gztkPyFOEdvZhpeN^+&Fx0 zc$}5lYr~w2_t41S6=q!~E9XJ;>^19O{`On6zgb1wUUYmJ}tLc#ql zv^^2JdT~DgXLvKmw?pfAjLC-Ib*9>)izH7su`gnd%=XM{+tW2kbbe$GQ8Gv-eO3XB z3G}awriMjoU^dd!5?$RK$4)0WYZ?y*nK8+YtCrlTtW^80W}y&Cgo3f3AwH|xHH2y< zdV5^;|BZVD8+!?iat>yj&JX&|Dblf2_|UqX0(BGE#90D0KA1E=pw)#rUXbP0b zNVB-s7^&6mfM-BwcSgXLzs2o}|HF=@MrQ|=E`9x+Xx4>FN`8+X z3Jo>oGD_sh|N>q|}NQLE`k019p?_ zf9+9~O{Bs~g3w!yJqq@6vK8{HYEz(YOV}?a706OG?NMPJ18?PDH}(CCS&zITrm8)u z$xdLaN>(~)YDL%O{SV7gKLOs?V!KogS1j&TY7hb;^^7gN8e$r;NrRsLxtwp-YAoV! z^bCgpkf_ce_e;b8s2N2*M1F}Go;-Z&b`K1&8MOfs<@Dh81c;awsI zk4?4+k}!5fWLSsx`hD9y#Pe;Y(a#V z5E!9as!+rPi58%Jpl~%=zVqME3>HN4=oPjF2mq2R{bDPK%}~E03PPL2o?qgC{8rHo z;!r7w3DDdpOhFHmLD+^$6=4wdBvSg=kPd93K5~N40DZu<1R-1U2*7oMaraq#+zi}C@oz=OT(F|Eg_p>FtKwpCk zRe)PoaH0~;H*-+P$XqLarZbyyYpB#_)k%eseSy=dI7z4QAi*jBR1daSSxOxR?kvYP zb-^*3P^TdGky-Zr4|+gCgya)Qk>a{M;ymatRkRe8U_{P=-n*02{R(8-1l4tK=yA zL1{`rfF^+%0IY{)Sz&|Tt#C=dA2~E;yt#u|m0tGWQG#BfxaW)#2%$Jg#AxU^Jic6X zDjtq3D>^z3i75a@0HzX8wTWKvD8Uw#A^{yytyqYLI(u1)8lOq21f9y>?8yw3Yw;$A17s1^{Se0Ia|Oungw23dw+!2uWuFHsS`z$g;s) za+dAJAgem}_qHNtF8kSC-IA@@+ud(lYJ2wW<<_2>?{vaSl001)rU^E4A{s->+zVF@ccelH3+qR9Rkp4T8>$ciAAo69PiUEI@6NCOneXlav-nfKdNSMVSRR~?A~plw}Zt~Bf+zUHp3#3kg^oFczu*1>=2cp022l-wMX z7{uj_r^#4lp~iySNvdLcz3zMM82ZrwHTMB-Afxii-J51S8Ko{3x}(HqxFdsq)@W8R zhBsvHHCg7>Kutyji(QSzcZmaC>rP`;?MAr!Am-s*itS-`{vDOzYMMG)k4KUmL1=}g zy7XSQNTC%C3Ts(-zfjLaJNF$iZoCN{A`&J|tKn_P3lMi`qzEIr?x_mk5qWG7ifLSY z7FMDPlQbb)`EYOBfh!Td(KcJ%qF<^-1fa=xfsSBzqUS{g_4@wC0ftlEdD4Nsi?ZO> zE-KgwZW%e+t-medqOV?Mk4zSS=@et1y+pSCOF@yEr#42Xp2&~!3=4hWX?s5$1)&ZuI2OS@**$;uK{q=;KRdhE^=c30aEMpV!J5EeKobiS7z^JP6d_5^p?Wev(uf~7?$?^ttj zi5Qy@*b|at{asfel9viEoF8+AQfyq&-DR~rwf>w4dG~Wb=1a%odsr0hKJZhl(%zr+ zMW~1b-seLZ0ct+@kls>{s#T!L)cRgHcQy?A6i92egZt=6+cTYqdj^E;mwW$)Bw(N~eqEA0Q5ne|mAgE+ABA_8XG4Nf* z$GYMf_=qqD5znIV;XWSd=yC9mBT5*VLIGI=qXPkq*Ma-c^9I~jYKmmqe{p0j0KF@c zqIK|ZIFb8FXlFti9XPw3Hf6q<`v@78*FBh zH&c0wT?H+M0?X1!u_LABk)%GY>YQJhC=5r0(6-*v>W7r6ZM zg2D$GWQm8oYMCKdoQ0*3zEc}Eo>HjZQ1oA-7gU=K57O5io-TH{%x)vBL`QgO8!=S% zw!8I<_Dfmk)`|2)@9aIxD@CoM1o}R_dxsvo)1GF*?0*bx35)9!@EV7)G?5WWmN0@- z;Eei_|6g0Bsmj(IwCs zLEV+~a5q0~rQPCFA&G~H;T85AKh2T4K;@{jI?qpwmTb=_!fI-L`+q}Xh}O=ES_3l* zqCirI#(uQ)5C*jCN-l9~kmH`lTldsy#Hj`6GzO@{TnuH~3-?*qMOxgWuDDJ#IX(3c zPct1JDVxk6cE4r>R%V<6FhJF!nA*z(f!c*(5&WEUc9Zht^~iJHTnywsE!2rB6k?~* zN+h<(*tcPLD;>EA-*r=O`@e9sbm64pjJTp@DIDA!8=MM+EBqPIEuj&6HO##LQ>KZP zvW)5U~3~vdVr@xTF3pB~Uex%W;1F zi!+XTp&P-w2x{2;+~RqJcE=n&FNV?4Fz4vXN9<4zw|D!N?NQv8BIv#G?Q5mxjL+7Z zywvK0ehXh}|B_iL)_-6M3k-rl=tIRE?}aWI<``S5qNpp$qiUI=7=0M6e#;OF(iF|h zNA^GW{WJbK9gg)l>kNmtbfJYeiEp%E06@?VP(YTAVDg6)?;=2Cr>N8ricfkC<+R+r zrl_XCyl2u2;^pI(o_j!8Z2ORX9fO;a(oLv5E0yvjFBky^-7qynU{DSeKIa%R0|#pu z_F)Ma*aHGtJ&^N;qItU>IdKlUX7SNgfS$RN2aOZ=ba)CzfH3~vgDY4Cx_3BNq+mb| zu=0%ep%akSXsX*6OXk*jGC$vmYMG(7ID;@?&kt3=2bgytJ*GxNumca&_b7~jp$S#i z_>bs4z-bsgZLDqWsZ~L;U$|bfL)D}P>pAe&(wvc{805k{%>&j!L3IZQS6wAoHd65r z${fh`R6wjRG7(I#Z8gEhM5msATI&x0Tj8R5aBL|@E#$c>icNNCtW2W=Xak^bQsSzf zTQy1j-U4eQ@-1PckzhRph$gbEt~F4LLP#LNKLN*3lkK6!@~JI2@{4AxaU_vovP6u+ z1>Y9$rytHT!=&xj7Kq`Yv_=G+{USH#<7J^?PC<)2@+8z^XS}K>0&^_Cp(3U*X zyy4!aB@SMTEvd{loJX+@;0m)X&vL_C&VGPLi#<#W+7>2g3-&xxP^RNrPCW1NOi$oO$8q|*PK8E<11 zaYDfa<(IbmEI;duqhvp8S0}eEG^GVWC%++Aw>jiq>)xN>Wd72uxD)x_g$OCmMQqUJ z%ZZ26Z05#IvQQS$@jRUEb`2~L3E;KM!AT=>-L_6K6rGyy%PWH}r!J@XxNFG}%>e0w z8D6Yu7W@Lg+7BKi?&koe;Ta0^rn^*i%lXKh_uCMQImC<1VT-;XH)dQC(0k8d2u(x; z3{A2B5u&k(G9H%xN=%svTCy8f&rj)XrDT_`z=zyVy#<)B=d({ zc#prvokuz53r{6!KhQnWz}o7kKnha64_-6Mf%A)ds|>7TKu}ocu-KSGMGM3={f@JH zQu4b$C6NGrK#qfKM$@>V!iv5OzKwc}q9W{Gra2{lA=i8)ZH@c%H|%Fz!&yAz{HK0q zHHlUjy`39D0nXfQZ z!Dk4$Pvs2rZV?4bu#gb9-+ZaVOWS=K=tNtBf6vA#qmG%Zu2heY%`zKfb#olQ`B!!E z9j&(niTBcolo?w}w&^>@bQX+|=bEE@qYObnENQYU7!YN>u%6jK^)9;3yiyI844q18 z`oC7WV4 zWoEXF^`lG{<=yKsV}q&e&>xBg#?4gUm140NA`B#<$?&*~qecUbI)<*!wz3l1$ zj7yvo`f==N!$=G-OTaQKF~WILeCDK;dCTyJ;}`)bm({iv44c004hwG?m()GQZ0wQlhqn)FyZ81rgQ@{iV2T6zLH7jf*%#&jxpFv@!qv z$A17s1ORAe;LxD}i4oclI|x<83J^>90Us1$MV8WIyD>vdi*CC~mtw7Uy0@4AUAwho zZ?Ld^`_7VVwDI_@EUS>l7H3~pR*S%&c%=`50K*_~-fws#yhrgy#uES#0{|M412BMs z-+lLecX!#{wCzS+LD)bF?UHqn?pi_0#D-LZm=F8?KE&_=g$Yp_itx}3sh!XS3?Pza z69<8Xgb>C@M_@0+P_V>5ynO*a9L?=*K_ZDExEp+E@JCHf+O;SO42QuQ@jhvz*($&5 zy0_o(!`*>933*{GO}|z-@R2BCK++sK5i@CiVDZ(+dcJ?T2Lg(TUiaTIB^L3Dw@kso zk}otu8CU~pRUKRs@sE^DLNlA-P(wRLI&vIB5Cepj+pfNCWnFE3er+w%Xxj3(ZB&xn z>dqx-7LsUWHrTvv?fUUVD4xj`eS`X zdQYu}B3l@#KPeE2ljKE8emic8*Lh#^N4=&sZsJ2?Xl>2z*YieJhC17YVwq4hW#5@Z8-SmCST`?d8_R(v?&ZeLJ3!gwOfvYduPGwdSR(>6sDH zL{w>(H_4AFYi@iV)y;jUIV!9H9ec79aUb<=`{pBi^?bcDV{hhW$LJ}Nq3PaPpLcC5 zU0GhnUPC?Fc(wQALdlM6wp89_^nEil_~L{ln3jH~_z0;T;<kMr4&6W8A8k|Af>1N}3suN6i`0Qh5{@9NPGfO+S%lYZ@dOI*tGoh&VkpR?(NriH%?DcOj7c?x|DAzyexSyf<1fRJ9Jbfs+>{v*7CFOCzDOq z!?=5cTopTx**HnGhx(t*AL_gC%(BJDLb0JTNRH>0HE;bJ6Wq-g-{m`vwOs12`Hbi6 zZ+ll6*BOQKLFN;Q=yHkfeKF0nl`>1_6TE#JJw)&D*dD%b`!Z#p_LFDxUd`C_`BA<5 zySS?PQ;l27gLWp58iAx$^4|&FTl^6nqXbXeLkkbIzs>AXLr6I)UfoC0{W)1-m)cgh ztKLX=X}UKjN33>2SEu_?YRFyOI01x^UhPA#3tQ|?Q|DJTEHCDtu@H2Zo)WBU(}F8l z3Qc32J+U;7qsAXL1 zAA(cW{-=x#syv}owVjTB&bRziM+f~fI|n*Xk4b|z^m>+Kk8@e}(U!;E-BM-!RB+$Z z?@*}-<`jixvk5LqCc*mqGyIS--P6)Z(t*Ke+v}yNh8s%7iz!+tp$ddsEK^Pc*DvT- z7Uj?FJyT>_AWbK>*&g5$YF`$@ef@R>CU0{3s)cFY_xjs0OYr8``)AR4}4+ zz3m$;v`{&;-KnjdrXhDWADG|Xa`iEilix|nHicrQl$>XoKVur)JUgS5pHD06%s^Dbq8W7-Npr;ix-{Gph?k?+GLvH~XVQV93O3=$Tq zB9t`4)-e)RFof@RMI+NUQsV1a$PVU%(40K@!n);zyjWerHU&mdDgauE$DtWx94*{> zqyZ~;j9M$909*#voph~)xqueXRXh8$77^A~5){C;H2|i4#X+1~s`-pptpusiXGdwl z$NWcLNVwoiz6~LQhAXj%h%2rD5W|TqJ*Zf%cxiGaY=lqG=9-|I3o2* zDK8}~1$)neL?m*rk?dE3cF7S1=qt(s2_|7*@5Ta@3*K^v^Sue9U|z5WO*2Z!3-2MC zoyPig?R!7@KmUn&!Qqt#<7>Adcv?z80MD@iE~(iNF0{uspA}+rov8^pL1#yi!biMB zsCV~gEa5h|PxNI8!CA7z0$>ZfvNRAWYvC3BSOP}S3d~%8Jl0FN3KD5W;WA?eA_WSY z9^;R|$bUCvAM8)G$CkWy4A0;gy0%zP;V}~L!n`0>iOlR>(Og`K^X0+}7+10d2|49k zKf+rHU||oiRw8@3prf9Z;1mD=U@j$cfMoz(O3)0)AQ@Q+E@7c;JS*1#+6lsLm{v4+ zj|H`IQ1M$?PgnoG?qlXYd@0D0Y_LXM< z>M)T7hh$b0yb!?>tHRbZx!!)dB{YSHSx-l8t%0m+RS^7Qk9Ee%M*D0z>;4$cw!v!) zinzPMK@PkuVkHP3W|oV`C61S!hIG#oF2Ed-p(T`;5|+ZzVZlTsva}KHT7q_&5d~Z= z$^r={VQXB6OMyCg`yHcWe@NE0m?cyOPGp8ij^O{8T?E}p`qeuDzXb5!8%tH!A+0?h z`=&o#{1=!AJeC0f#Tb88U064(rDv$2iiztgI%3I4r4q+n8z0*-b&O6WFbd^p^)=9Z zPl7}!2tD|*&XsI;s&P20xM9Z!)Hh@_Y19peL;1=gxn3Uh2&ZswyciSfrvuAN#T;4a z6&OwFhdzxukdD*>KAE4XGRhE3Vp(q+_<&(G_RK)BHA9)4|Bp&&+sja_M!;If^ox;4R))OVQbFTD)l;=p()SVjrKA}AM+3etUSI#&FffqejIxGu0c zku8FG=naDvpfDRS{KbWW00B$`7@$lT0oF*M^BfNV!zQtN)Jb2Pe@e3RKoxSgm|tct z53mlvfVmJCd@o`J4aNoE1NEZ(_?NN~zysI|*$DswUvpRi3Nv8@U%o!r8&EU=0?O>+ zhO+vDN})r;Jv#AUHb_KBXou_>>^X*znhPo-<^S0*5{gIpxok`cvLi%7Dgc%0`Pb|) zfZ{sewmOH&_p`%*0PqkH0ssI2L<2xF003`gft1re!lhtoT4hMM*Jj{$x7r_Sm8~#$ z5W@3DdezHMxjV+)dqV&I5RL!<85ujH0)SS4KLkM7o-B|77Jy240Z-Uyi8RVd+SM0g z)w=2?O~!WFvwQX;+uCX`??tz^yI(J6Rvn7p49OQU#fmOIpREPLjJWV2hCz%F;r)0g z_ebxD-VuN>004*pK+zZ&+XMIB+k3maw02hO5zZz;-7W1X+m(t*#6oFR{t5SoK@dfm zP=IDYv;Z^$2mu7zhJ+M`MHo;(kwHKJ{y|T~K%lj-I@x7x2fU+*u(Lh7j}#m>TqJqH z>mfGaT&A7h9D{AR?Q*pMqCj20)tkc*h$P;s?d(1J!DLVew=vmkYfHSz9Kle?RKQcP(?Eq2%<{FoB)HopA2}_h)7DXQTKze|$mF zfeyFDC0_~C6q%l^l4sH$Gt6awa>~^|dpm9NLYd)L&g z|J%+99qCITPMf|B1c$?K$3>1zj1sxjIKJ5iKaasoF%Zm~!w@twJ<+b5;)u!G^td-s z2lPFBD+lrYZnL~Q#XtD!kbR{^DTWF4nF2kBHsvG^BnElTn>>isC9!ZVy0$6;Ybkw# zLvQbOnTZET#p8JAYo8B$8u1LZJ`VLP^+AI@aW&cdDo78)_icOWYMUU7UFE!(l?{TvuaYGJ!DE%b82 zo?;m!rKR2TE{aRj(lG%U+_^Cfdz;WL#17RA@pBlT=JFsD3`LOi2;%Lu5xh?Ql1#Ll z_GLO4Fw*mgxkbHd4>GxU^YVgK5y zjb+Rhr#1G;uN(Q7->N0PdTUd6+s$2c^SaHtyZbV2YvOdv+$0Nk`lTK6zF68j{}}C# zGu|6`Sm68izSVBnw{E-F>ox1U-lUyxmDPUj)oJ>Zy?hKV>zNbl$>Xaq8CA3HDua$O z5n2+DhX{cFnKZ z*zz)tS5DVm9kn+hrMjn{t#tCWWupZ5Pfo_bCKo<2(;WIl@!D{hXha*=yp^RjUlN{B zlFB~LFXy9^j|88)??#qveR&uol{C{&+MJP^M1x`fKHJ-;oeeMNbGv>IO+`LK{sx`( z+H$vznfauXZZ&h2UEs&5un>$xr&>~nPia-jY&|9JER4O0`mn8JOp0dRHjzs!)i;lq z)g{O8_G)b;)(1!l%ZZz9KX9rcEm8~b5jQqZ_EK`=*y3d25kd2=l6$c|alPZnU`?n7 zLLFX~x0)D?JO9yRXd`KLp17y|p}oyK+p2{_k0+IC<|>4YFr3bO^Sa@FeqUcEhcS16 zbO7d-ZhC1xeM2cF_mFoJOdVAx@KlENzlkwq)lQNie$~OCbDBgscAId1DpaIN)aHn6 zC#{*Zn5m{(dGtdu*I{0M=Dle-b2j8mWKZr%>0rIbt&F8ws7F;9>)mi^*4GP`asf1? zjw(5rTwJNz!kjwoKRWA3c<%U_FVaaa7RGovZBmYL&+P4SFu><&J!EbC_Shx<>qBFW zGRN0p|1Mh3lF`Z3$x26kG*=GWVP*1!aB`K%lVe)1{4g&<8>ctwj$I0N6u6^MH^OTm z4{8J`wGcwrHU?CG5P}Fr^$=eUdJM)!SdRXZGFrukY5~3n&&G*~*j70p9)kW5nE*Of zBBDs42K}{{*>cpt4u?fpDy;=3UI{GHIbnSHsS$Zq5;dSdhKnqX`po?_ z4kFFZ1ml0|DTHXRR9ewu?h%Gi&y{dMU7|;}>nGJ$x9Sx4gDsXLtQgY#C+tRWVE2(( zo3Ij0$17@Q_dKhc8;^e?HYxtSIf}fEo9hcmrQc$0Hkut;^Cj1G50N_$Y4Sfc+t=1} zE}xgL$$I0u8^FC^`fv&6>R{cz$0EG6%6J+=w-;YQXM~2iYw7BHc5mhOk|8XP$5VIY zyqroLlp-{R*bGc3H&P%`!n$>$8a?zr-XLP_&Xvnn^>G z+*5L`sec{G;!kiK^g=wSLQ?}m(x^g3w5kvSK+>XXPjHE_E(=)|auHMtum5cw#**P& z6~z;7YF-k5v=ixBR3Rb_FZ;ZiVoU zV*IGFLL0z2B*_XA9)&=MWnoOnB4}0+>7B$VT0DR(@o9xMfMUd|6~7zQ^gY~h|4T3I zfP@CE)fv@=M1XS17Cftrnk5A6DLL<<1eiNs&DlYb5}6NlKFt(-I!K5Re(<7j1DcIU zjfpdx_zVhKw-%yqLJtOM%8le?8*#wL-boh@^DFA#n<&K|`b}EzdDx@1&KOov9h5p! ziG&|d`;1ylEc?n3SNfmLE=W_fl&EjHarmLSI+S6kIpq7QU;ahB^h-f%LVLRD#C>LV zDowpvI$ZWH?$r}z1$-m4Iz>sq_~r5iIN6MJ)2#=7hr$$M@H(%2qYD-#!p<;M5G=q2 zspFM|eC0+f^yDnKi@D#L6>40IS9HeH(6z^cm z0W`iWh*FRs8jsQ-@FTPd+9!!=jha3Q$7YDR2QO$j1S^rR6O_s*9xR-_8m|4@5Gw%H zDh^@bkT|Mi0OJg(o&(`>vK-ZXU?nEVQ5ygiM#@p*2Yg__Kx!d^6poGxG3}rt`kUhJ z(@OP7zqHWTVKCu)o*t_Lz(KEXC5N8?WbY5{#Nqk~dX9okj<;})2KZH`@6cw;!}hvE z5?X16;5q;VJ#ek9Jlwx-D5{X}v_lE4c=P5XRym+KV}wIFfMElOL%5HsaomMDA`g`tXA_aXPEE9%=ntv^;GknvpD-Z4;C*;RW0HgC6Rg$1 zXwLx4E_%}yLCKSOVF1i#)IIv`$Ycx3d>v#j zZcL$tg{M_({{N4)Eh+wSkw3P`lmpm8lE@VN_?ifHu7ns;P+AUdj*Ach4{~pfV*ZZV zW%B*e~P5IJSawLl=S4*zQc5OVU2U2C+CfM1Z_jv#j|EAz-c8?t7uzLSx-_Qxnt0b-kC} zdfUC64QXsmJaHixWc`ndzaQC)z$!Sv$M*_P!T{e8zTXG$5g@Dp03ruqGzAFz2=DIu zuD-ke-K^P&?H|dBu!U>Wvu$hWC^Al+eh}b;eI?+T1VTVi2&77YP0&z)H!Y+znE<39 zpaEW#03Sg3SPwLkAFj1BT9PV@%d%T zSzscMuYAr@9ER?p5sa3wn@XlV25odJvxa1`cof+r*4z@8#94(l?N*y)W+PPsX{Nvu+(etGW6O?{77^iqQ%FJitye#9uw0liW1xsG|i1;zP zg}kHnLhbs^?+ST_5p0}hiW>@N>PlV?e?c$Trj}3*3yxGIik+5;sNkHxh-KP$3!XiO zrbn|DOZt!7it;t8VseVmlXo2YoWl#9pFaLErBbiBME>m1k9prS^@l@k(rS0c>u$Uk zf;U%Q1=?*m+$pt+b-W$|Uk2A;+DH8_;2>kVH<4Wzyv^n|+L!y?ErKDY>A?9)+xJ!- zt=?Umpfa?bk%Uh&#^SoG@b)z{N$9#!$PrMNDUEVt%gd|(7H(U_;~baRkdL~|6y29P z-Mw!};9%cl|5n!Rwp=ffw^Lwa_xRvbKVxa@XC*J3uDCkRZr!3TIOv0zQcvUZ>Q%jT z;t&{u{LQZ$)e$?5pz3=kX8u6GU4LtoN_T+>(9;a1bh3wGW6BDOo7f!_Mx;G zE3&5r#4mnwGn{5c%t@=+_VrS~#?e65gtzU1jJ2Jv33U)%Ik)v)Q{S#f%>QkxhT-dF zm(Rn!OwPkbtXQ3klbZvuY5VEH<^vXF?^pLI@cCt@GByI7lOMYeY8lT4`pb-8>WOg} zdOW1zDd$4Iijf?raZIBqKApblvWv*x)i^T8aDKbeCM%QtCL zCh~H~2`8yfH<>eIt1D&alT8Em*KSI%=$Wr|K$v-OSND+`T>%e8TMU!HFVqaAn9(pP z4B5LG#!%s+C!zLehN^jTI?ln$Ik-VMVf*W{uY_mUYiU>ERS%_Cx;tn2SjtMsE~+pp z0P3W|fH0u0e=rydoj-y2LP)|3H3!r88H-ya-DLW)hQB77$V_|ch#3IlzK$qhNNXdQ zu7esUFy5lTR36Ic3*XSbexfQ`i~Ds0JRi{0iwn4$@_e$Ypl^!;rUFn+s-~p?0z|^t zYE;1lDpB-cgc_ppm8FFfL?y6-S*O_)#shSikOQFZtB@lQnbE@C={N+hSaJPZC6NJg zS8obN->a{GwN5hC#XZe-AArw+f4)zI|JJwS`_K=to9t0G&b>9R5i0#d=`3-f+wovY z$Xl`Gw8IKAzD$a67-^={O844xi*4=qjW%F;CkfJ$%^OT?@1@4yGN~*+_K&~R>@@4l z@9nTWGGzI7X)kMe)t}NbxkD7(V-wF$N$JSLW+;s#GttVU+UDSJkx z?{ydmYg(pgv+;`W#S^;z7d_Bzw(H^Kc2rT?NT#3(GryGsaR9X;7fp6QL=(h8S?w-)JJ{h_{wPR?vd`O zTg;k{zV)F5fQ+qr%&5fW9=!jd3L*Gv4IeYi_Zk{MR2euVSB%b8yicJ=)O7FK%~W^z zH+V{rvFVpf99J?#X@YvPG(^(_d;Hm<Xffdxr=;_ndUFPR;QrCFNxMnJN458 zq>qznC==U6P`2{6C;wwoF^SA6VF6C{Fo;l?8~-k=8jV3e!Dnl^kV& z@GuQ&{aDukDYgSFVUQGKe_#OtrE^qOirx28M}Rm9ZZXRNK>N1)W#mSA#%cLH;^dvczA)XOuJ}f*eE^N){jn1wyIC z!P(_kDE6pj$LtDy00DBiLdeG`Mc5Y{Rw@K}fmjbxfN*gD9Af%`Du8PNJwO42v#$@| z!3hafxudkI5CX70;N+^RLRUjNOtsY7iVS8I$h(}E+$iCmR1rXt>IB6+Dgpq-wjzwM zSz0gV5l!nW#3%S@=+JgiBGx+5}#LW12J(Jr0i*5*E75 z1PaL(+l;Pjg=CK*W}sTg4npL|v>)?Uh*pRP8x@j2p6C$Tsp*jg4;8>GRG9^t1}DHpf5NZ}H6f;%fWAl_;=Idh56 zk$5D;YBVeY0Es;$pJ2C4y?&A_EIpsAXcj^l9y>brT^x)h7Gxlayt3iI!w?Vy0000q z127{10B>b9mD-;ovz&1hmnH(>)I@wq0U*_7I3m5KiH(JBarJX;ua!>yw159Z#{d9i z2C--W0P(=LWJ3RQ5{&Qwgu-X=X%?F4LP=pu*K=<@n$pVF?sw^3wzPY@gpIi?cif|2 zx#D*l&wMQdDd-w2yyIy+b&$>E~p6l|Xb+XseCTghB(3O_S_07{w zP&+y`AR#j`%w*GsQCiKigUMOx~sg*KdWjFXl6T1Vtw*v~XYjDQ!#*`Gc*J5V?wQX+oMw0UTAG%f)vk6?9&J`b!4&ydi?c`*R}8jI zQSfBsF%+zDkPWO@!R9tNy6yI#7a?)dneHpb@r_Z(+u1M>#jVsYS=Cw%{-!^D)5;0y z2@dL|-Hmy?s2D@we#wGJj8NOo&j0GF3Yz;^Gvug+vqq$Z3$H1-j<3_V1TF~(Fu)2E z(Cw88NJ5)+b0V);rOdM(3o@H9OH{WrnsZ^I6hDdxVk0nKvU7$_1K)Wii?Gv8%stcPWO6$6y+~_S}59X^~bnX*Ns%FS*fK=S=2Odg~LKwyqqXl2luCt<`Im zbeE0!cGguc($>^X#x&2%xtPRH-=u z9VH%zgxge#Iv`I{G~SJobv?GdoMOBv4wa8as{Fi<_=OSSr8X;C8b&&q&2SX^M!rwS zm&s*UVNoLXeB*5Ik4~cxNwLs_Gd5Z5u7L7WH7jDEOoLKXAif?u$3s?2nQH7 z0IV0?*1p_!#7db{+g6B+(jRHtAd1e?Bj$2MCGs~-Uw)HFDUoFnh^z#;4%sl*f2u^C z2v|F$aSzV6&U4F+&D@GXSoqr8=sZC??H^Ls&lzv%+go%|cj=a^2k!MPUnev z={tH@C$F7?j7^NWtuZn%DY{OV&cb?j@;av?neTynAzOe%N%=MWy6-n&F1clQYSGg% zX+O&kGZH{PZ0q7w+4&ZlR!%#8F_OP0k`Y?g(U9cC96|b%ZdH+x6Da_sq9Er|H+3{6 z5Rk$=O~lwB39!=8Za0rWhN$F(a%|t*J4Eq9E_2HzZJ2pz=SVl4|HW3O7(jFYOlTM+ znMXio4=QW6DrHbHc@J4hUcneK$%IP$P^I`dsV`9PIB1&@`OLh^&(lb{Z!E$BkSdy`Ya6oTLCtvknQ+xGo zA|21AnQ(!$0c?_wbgz%yvYP5>6kDY3R{6M03SjoG=R;x0b%S`yr#QAR{x(hTC4Qcr z)oZThwU2k?FWql&PiN@)ICV#ey259M#5XRkcQf-rD-X;^yzhp(?6obs;8Y!2MBa(2=e6JHble%J*ql6t^_=7-HQLR)=DiRkF6@^FmGf{blkY+gh2vc%Ps*e)6a zUY(KS9F$k5$d2DQBZfQaZpg~Lte=P*Le)!)ZGFh4cX=-~y6GvK@24RMyKyD^HJ-Lq z#9?(4qVuLDwrduZcNaWGoO;i0>eDGcc~pPzn^-e>nElYSeN|jOlx-%Jt3XyEDT2#y zmhme2_8!iMbOkcJ$R9EeCn9Xf{g=b6Bu8%7_T9OVFFTX^nv3_Ia^KsRNl5#UZF&I` zj*)B)`nHCP?e%wW z?lyVnGO5O0EsQ}v%i)#rv;3u(Cq?on@fM#E&Z~6^{g?6?p{>3N=UyaEmQT0-%DEH3ca_&fa+;9*bGI#MU1eD1 zyuHYmNF1iPI4!p>0t{-+YoM>Lheq6~claDutkUchSP7t4R58yyk2(L)+UHf7e1I)sEB2HRz%k+mD zWgo|q*9?op))e9{KTU3tj-2sUPo(!$AQzmSzR27{C*}ACwyTFIaN;i>RW2y*;M37e z7%BjprpB+To^G0I!Ch_NP6K?)WGI%{m7n#GNz8$ijJ8Qa&Lj z^05qK(k}>^9mcV`dN%XU$XYQ=^0f1DeIgNSys&1~Q+8wX@q9^8c+`9Bm0AAOYfgyk z!X|=D-f_o^epwexp$?~7PxrhR$O!?~UfK!ceA{+Q4YnS@^LY(t30FuVms{@K#6QSo zy)?;sZ-3~N=j@dq@w@D2A4o(tVy5!%*QbVQRJ(-NW_+(mJJW^vtbX2$k_k(64KXSZ z!T7l0V~@>k!;kR{!Z5uEwD7T`h;jw-@XrnQ{2q&QGK#bO+sMkLVS-t4Mxjpfo3;(# z5y9j*qBnB+B4+NP*b#pxE91!K4erUH8Qe^-0vdOWhmmuICRZ+Q0>uqF<0e+smDWM_ITJe3{V zp%-y%MozfGm6*o^pLYt0X5im{T8h6$(0v-PJ(WS$9&nWICaZ_#Xhlw>tMSS{Q2Aj~ zbccGubFlp{*)+%C&;LvE|2`*ux+ z6YqQMn;u%I$ZK!vt=0!yE;reFJjyn5X7_>zEhn^XH3;@^>P|-{z~-HKk zq(>mX2j1EQ!d8G>3c??d1o3SOoGE#jFq8st;z79Z3vW>nX#go#2Z$A>KsgT8L;{M! z8K0O>Csij70rWzMl6@6e4#7ed&C}3tFN5Q^kf>B?@00$vA&j4XP z$QcOJheKH!m_>bvFcsXeu^;mr5CuR?bRe__H*5My%e!CzVH}@d&tSP?ybtr*5-Kly z3+*|n$E429NS93Ic_S@^HWR|L1`EKFG&PtmtQQi&-~!Pg82AUodvFL| z)VxlX{5e9W4ldAc*|-2GKotN*{Qyxnq?qL*PjCSbKyID^f@+vSNmvDgUj zE~e&J>au5FmSz;=E0O?;xaOH4kN`{Q3TT;|KtB!#c?tx8AaE*({UH^}xi@=%wAv4O zo(v3xKql5CE3^Q#2x!H*1toGITm(w^8RRy9dkI9cV26aZ;>9f5R6-yEU>3_$(SjP0 zM+k$`wc7(713|#?P7Yu~>P%S73q+$Zuf&j&#JqV!NB9i4i>WU9pY?}iZ0jX+khnOn# z;B+be3|y9yF9T2jtkg4F=)(80Jo|q>nAJ&BguT_U_*E}FSg#`WoC42O_F4Qj3KMJp z)+M9JI_Rnv&(&ZG636Vbh{69DQ(?=2|5QoDF%-}QB&4NhGa)R&AVl&OeLsO#;Es3Q zf1mwjSN3v2i~q58+36?#psoyNOzk87Ye0r9aF!Y)n(KvLNL!%(ML3}2pM@b_O> z^fy|1$!;{6aQ^v?t_)mqw3i4-o{rZk1%K|fPf7&i%-O#LX6k4e|kMN860NyumFcu2s^N71g) z$LG-=?6!ue#oo&hS|7{+?Fttf4O->XIMW3x!vj??#TZ?hF#rG%5CZ@J07L^oA^-qy zWm%TnFS$CyF2Q8UK+SB^9V#M8Xejt(rh?BoF&pIbin)7j4Bwah_ds|60A@xGiVOfE z5B-o3qY>Xg6!0UcmPiKQgigxAw&=Wdlbuv((YEe;>4delcU_il-MyFQ)~x&ZSR?I9 zeB;=+TEvWNoWFH4jn*iLGw=e>h>8Rt_yi`t1HL1GFaQ9E0D#dJ9PT5#@9*y2x9zrC zZHaB1&|OfXww(d0)1YY-mhb^04CNyzA1i=_04k|7Wfv$>fC}=51nhhcU#JHe3r#*4R%Y&;)=p^Xt;OV$jmi1EIxO}29d$LL}PB9bM_Xo4@2C` zHb^Wi;*y)uRuW^F-=pZa2m&jgGg}xF>=B@~zaY+|Ybj1U>EZt5)!1xj5zcfg$}-w) zvjo;{J%8n%%Aq^I=3x?%dE2jMc(r+Pu-|?Tcq|AV^btbrNg!I&<4<&^7tyyzh{Mqr zoTKnd$qkdAo$QUpZ1o*)+-XT54N1Hcznn5h_j8{0>afdlKFr$%QcL%()@6Z zlZsu)9D>`vopq3l%q%8j{5JPN9J?<#NjU8z+G8tFY>*A!gVao6IMzbYR;)I*^577wXB!Z3C+g477E)~2h{Q-FnD_-!X488i5K17h6oqV*J+`&nn)wv?!Zh6P?n1m7R zg9FA}ia{X;`Wy2d1M)PTG_7}Y9v~WE51vdfAX@Zunvn;xTYTBNI?C$p%G-lq!|*R9 zk~%)sE8-FJb+;TGvrf$T)UHa_ha|VHR!yunw>+ipd{t!=oUvrhtv_3L ziP~w8#Wf@cefd5X_gU>6_&XRox%JE&dlxntO|!ulP}x_1_GJrOS6;uZ`5JAr+Ap8C zF3rhvyOY-Ke;~JdJ4e2UJHdU%7ocYen~J;5M0ikT2jz`)_miRXzG6h&QQB}%ZtT=Z z>kj!(a%)zPud}1Bt#W)o_@9qp-{%#C-14(ZzC8c-R=NJA%Wz}2%T7T~)~MEyO2V$_ z%bzSB&$7+~pT+~csU3ZEWv+Devm+LL1_pvJVEskxlhM`zjl4PaERU)?pI3A;?$mk? zN088|O@Vv> zk<|ciM)o-fY@EgbeJ?x$)4Q~B(0gA=$d&cCTX|KG8E9!E;`6(uahY#kv3E!4exJi1 z$vP}VH!mu}$PNH+a^b9K14E7o!sMPpd?_3xg|JfqLa970B~4Qk=iy0d(*o1)T!@`v zf5n}|b5vX-HcWJ~MF@ffptflsq#S&zJBAa79@i~R4HsOg;7@U1m*Ak!y^R1N}X9pL7?*h>fgnq!$>87E%^KLuF%#<@zas0 zWpS?g95ypXbC|qLCLw&rdC{<&x3rTS(09Oj2GoxPCd>eqoGzjAVa?j2awzS9L4_(` zBp~b>;$QA5&GF;K9D~Xn+KkBuRRF-8)u^~*K0(ISCE2TE98{%{AWR2T8^It1;kck|LIJ_Z5KauiUH}2;vFjw}0ThBkaN0g5L)-8e#)k00 z84E-Vz)9~wNG-UewBQQ`=zu1r2TMg#($&|EaHLCBF+92{jTi&!001-`KeFa*hlOzF zC#VccN8=eTm-No^XMIqMUb{)!JHg!?=?^=({4tFXhT8B`z3+EpwQk=bqgUkd)$`J$ z`(qTG=zVZ6XG5%R>0Qqa-+K-h2@U->M7JP%ByBWkAYSeDP*HO^(d4MT-Eefb$y@OW zZKgLy>e3k0u&1{Z&N^-Q>mQ!<`wi6-4!+wZ-XKvO4vL-9vx<{LK593Z`nkASi%!a< zPC(ygGg3os$ z-1NAk8z~@}%W%b4op&0y(rnH1m`OgF`9lPcyiNL;U*xC7Uil5V-+ik6ctL{?zxhk+ zV`kQUbg@0g=9m7mV&Jo1&-R+2ME*g}n%}h)mz#EFL2z-dCi0@yacHPzJO{15YvW(9 zGV;(dvwJ7>#_n|<4IQzELAQ*Uj)PKoXNK^XXT=Z*+(h$SvDpD+{TN`)NbCH;LF24N{my@pvqcEW^tFf-@%O3g!J+6h>uCFC+M^Dkya zdGG?eTg!K$z}znHnEnGRt7dIG!bfPLC|0SnPv9kv&>gVXEB~iB1KJnY)0YFwlEygX z((d!A|MhLLG&Gs*Em3f#+a}0ux6EwyG_pQ5r?l!#=P9o&SV3qHA&O zkY8xl+^pl^+(gTCGu1zTNI#By67r|I z2bPj&m|7~r50Nos=+Z*}^Ks2ik@m`OOKc+&Y0rgg=I|3=d?$kZ{%^NwocH$+7>j)l zy?G1vn;$d9@>ko~T(eQB+fQ>N)qjIao(_r=?dYnl-K!s`tAJ0l!WkG zRFQR!FRw~XRqF|gn)sbMaFwa+6lHvSojt&P_AniQGiL@uH5r)tG4uw7l0Ot8j6)bx zv_rv1_aDN)s7dFlE90QMUu!r7i+fz^U9{9lJAQQ*h?N>eB!4%Qmhz0~AXfk?O%KA{ zK>)al4h@c^N(C>3F-3jVTx=nTc9aCG#%aS-uTL+L7kX*4^jsB>HXa$0iy@T(yd=)n zvju552-BDZ1S1(337E!lARyVi=@ualApTgG#$X{p2V-^+Oy1ak8&BXj2tfqp4uk`{n2|>aG%5w5Gw$c{s9rV5Fe{RCBkDum^_OND0sL@f!aR%tHt4lFh+IG z4D`O$ScRDb>HrX?X640@0h$kev_dE%Oi~CSqKrZ*HYL2d)J9RuGKhPC;QdvJF4aAk z`c%q@NPv&i6>i8c5r7Y9iG^qqQM9n6Jx8UqY)D^LeDps=Q~*qf?1zYm^23cWNQkID zz(h11QX=XABJ?^oMC~75bwmUz2r>rlD)1r19?+CdbIp5Tp%xpgB~+L?iOLwxRxe2W$jYYJ{GRcwodK_$k?AQhHhqFajPH zi4ZLSm8L7v#efJ3_YbAm|J%{38lhMjZK@S46deGTT0SRW&`wR~Tt;^Ebj5c2QSh?9+ z_=3wH%NPM=czBX$5rPCFUQA>^eZ8zSK};G z^bek;TWn8>y0(j3jd741#XkNJ7u%wq(v<_6;cL=zh@#X7K`y{1;UT#XxY03uZDnHz zTkSw6@a^q^zd$w6>jZ?FKxeINxm3ScF_O^EvS;wrmZdaJQGxvlWqS?V@|BG zF&gU}!K33POitXKP7So|p_`J1y2W`l=AO6QyN3HEV3)7Cw^ywUtKkL!Lc{0eR#!uC2uUuc$U=}Qo2~IA=QGKn-y#XN!XLEc;i)784t*cny^#G4H>dx zPJ-jtuJ;axumAp^@XqkamUnPPZE&t$Hwn{@5?sdtO4~D1O3)Q7Y+^XVu-&#KYF%1zsEPDzv|#gM|$Fhih>(iGw8?n*K$$3})es&u-2h}0%?!BWbi zZ*H~7qvC|3lZJI4hUJW2XC+xrN5ppc4NwG&;3h0tmx)@Z*vvvG>Vn?KCP>AFHl~?C zJDmvP{EG}$+U5H*5CrmhIt)UL46kvXpgQWCk3Tm%JCi>7M(t1{Wo*mBatQ$>tYLsP zCL@I+JAHd>30W*nkTk3ghcpUbSoJk?@a8dXYH4AH?~= zal_Xn5ux3dBuR=Qp-cMLjJ9OEMMH z(xw7+tt~Ys804nY1JraCc1Q5O-(;EK`<}w{YrXC>_p1dR`vxo8Shh8*E`X{ktg@D> zs5U{n{mSemB*0H<>Q9iJEQ~~o%;|74zG?#7cM$`pm+mx%gWfAQ*D0oqY=Q|jDW z0U>VBfeYF-){>A99}Bvlcc93A6C}$h8}I#f>{;h0>GXkan>JfHc7hHwHjnOpq4xng zJFxOUte03$KM04`HmCJ+0)^^y`t=gBQ9`CQG^uCoKCIMc(R3Y^rv?7!M37L=QtQ00 zlNc1}^LZO4LP|8F+D8fC8iIqoOw+aHrj?atC8^`hE-aNe%*y@Q-M`mVa87Rj%+c;) zmPS(R^RwGxvuF&;DTA+G2f%p4er|naJWZ`v23U`E`~cMaij)QuQ*+4jfQ%`1%b_j1 zdw-}aeZVp~j8ita+910E<8)ZXQF=`21Jm~5?+hnF35e+B*->qy1g>N4B-#g$>>f8^ zq^P|~IQbGUdPtB$daeR$BGf}^8xgl3lH-sF2lh<@7_0-^*}IkmKG>FZXy0^R3wtP{ zp4QA>?J$u$B`GDL5A=dLAhswlxCUk{&B3ESWU#^oJNa|4DkZrFV!%RGPc8+`Ks>fp zlIqD3q~(b}Naa}>R>3cZ`c_Yi!Q`tsB}qkP1FO!FLT%%;$kA*^J4aZ!yk?oJ-E^2V zT+v>F(PiOv@yWK*&~L=#Q1{9pJ)6uf=?xoe?Rj3=EkMt+?Bwc%HM&%-tL9&-RAtR- z(6-$LxHk)l9o3SJ7b$Ro#7!ATW08aUqYu%H)h22C54=>H500mk%w;JtYbq!AyjLQ% z+L*{sXl5=6wx;>H2J9Lsw;c56^EQ5%)D6UPIR7(Yya;3MEHK^I`> z4idHljOjt)U^xO= zFct0)J9UQ;{#U!7dQ(Waddcd3N^YSp16X;s{oI|DrtLEjR3O~tGzLTf%xw_;EbPbt z%c@M_!o8`O%%}s1NMdpZ6)2Y})W;g`M#xcin!$$BJ;Q>ZJ`Ml5hMIHk0iF;zWOYT* z46zS~?+8j7#Fzsp9xx+8{etodHwug72tE*aXpW%W!P2P0rZBj`cE9+;S60SU(hSzHf#DEe+ZK|B<_wCZe{#WhlsHpBWRs6D|C*D4Gr^9sJq z)!;oanF13`2YVE|!q%`HIsIV`KvvSb|1TAMk$T|ZdRJ77NLgItRf6-DE0)IdlK$<$ z8g_T$uu_`H6Qmb++^U5o2ypU$VLo_Vj2h2@|z(2edTZ7_2Svk0TLC zz=o1iqcUn@Mzp%gm8`eVR!wzi%wB+quw8_6tlj$qKU+eu9ggo+$?cELH4n3_$P+@8 ztQ|w|HGULsD*7#l*iyQsS}OU99zCQCk7{;J853q!$>rbCH-u}gQc_@oulHKIx-=VoA)H;CVCIh`>z>DVXn57nbt~l zEEU!8OW9Jyvn7O|%mx+e%|(DXSy zg;LrUH`Rerqqy01NTP#?iw=ow$TH@06*Wyl1wjo~UAs;a6QzRa-N7|u<4J<0#n6M< zjr!O@{Sr@h_H0w64FNmA0n|l@G&Wqvz4Ra;27#yOS!)k1h7;~P9qSdPmg?}|c>z78 z0Yk-Ydn8_0+^u-i)s;rVA}nYMJfpPW@Hn7)L( z433;F8Yb_3KDu3Sy4J>{R|OGM+0Z?F;Bx@2!@$ucAV+jv#}>;xg0|JZ=s5_hKBM!Z zUrQ(_FD!jnkau~!^V>NjPE>q=!HWxew9`V`7 z<5Vtb=l|bFXvHJMdG`tJi=Z_m-CQNj)}!--@3TGj&ca2 z*d%62SBFnb-WVKqIg{hR&g^jb?|=ZoVsCkeDhNK(4bGwF!+*svdto#a$o%z{KRL2Xc1E=4>p7(r71Bs@F#1~IA{5{j-7d+3V0cv znNK-h@hgVKt-Cts%y^3I?6S3f$;liS*8r!Z6)5J>9}$7QiUq(pCf>!o#Wb&6k~Gw%Gr4tOm<5oF<$4AL4|!LIGID_rmWYI`6N_gBJpwTMxO!tt0BpTa*!rf z!x9otpz)*VZ0}6YWuh*aIr4eTQ9WK%8RD5iu2*@Okp%PNj{(I8C?mj&DpklZ$duIE z)z9M?m8>O2&Bg&)Sw(DohM};Pu@t3OR`86Y#2oYOByw7fv?kbNrl{^dx?K)w=ZJmH z5;&fdR2(w+4VH#=L4uJiHyTx7(y8j~A{n0Bec&}>lroQ+p`t8~@ZuUh&HLMgid3QQ zgR#t>n^D+w-#r_I!D`o}d@e5>!SZH6aRcgB`->4fP}^{sSWHsR!D!fiss8d!IJ^jP zCdTtAohusig^i)Psw?iFGDu(MmLGsm0$Iz{9JENnmX0&wFvTP1l87+N9+dy-AeC%I zh@1l`WA+Mdmf@)JlRODJaze$2Af@;$=_nY%gTt6GvIbISh>nTlLy{@T+hNH7HB%XU znBHfuFbce^T~Z1LW*N>14`?2VJhPQVhQh~l5No&?&_9Ed10B#LtbWh4_W`};0V`qw zJ>cI^%g_xB)eYPM>aDnZ<=ef04vG8(f1R?oVa5E|(}ef|Y7n$b61d$37Kq`M6a5hE#=u9tv91LOt6Z?JC-DHT6^irza*mZn_ejE2CA{lVIV9o!+ zjZXwLuNkI5c*RRh@BlMr@Cmwzo(P!-H0?CL6C%1)WxTZ!bBrpRmuhI_FR~yE4uCek z3{Ocx=zIBsekKrY`h)NX&aPsD^6ozocZC9$Bu>n>;eV;QB)q`lUpEA{npIi6FtG-p zDBwgG?$oUNn@$AzZ5BS5$J^epsFm5CZ@J05bzd zG5`P%Wi-|LpL)I~Crqj67E+sTUD$}(EHjy5fWQK8wAd-e!-6rpB?y=))p zsJpN<(}=FoKu&S$ih_RVFfRcBOBH?TD-S|SOVUqSNJ!G(OT-ia00aPtNB|7mpxvF_ z+qS*$_RIWc{*+OhfLXgyS>tB3N<@GV5|V)ULIDJb@dXnKKt6y{0Ro612~dC%QIe=o z#3&y=gb`CQ8z36_P*u^Qrs};r1*=7?gDzY-t?~eKK#aeNQAtWq>M835p8A)HW3PP>=+jV_48dor zTeW|oWTKA2r+3k0s(@Koc{!TyvKnBls?vC}r&M~odu}ub(K#@*qWW2^*+n5b9#Y2S zw`V4Lx`yOR8EX z^UiTXw+oAmfME5KqQ!2ExIJGB5}i(l)Os6SyAatQPw1xL3(B|a<33Jw#`Z`7 zys8{8EY}p?eq3Oyp6pePVU%Z|^;C(SeUDEM)_CK%(hYaIqE&%r=XFnS)ifPMNkw~3 z)pbU*@>DT$>GOdcnM6gjX?lAN&Kq5>)MlfAiMpKXdoK`U7nlu6@j=#h-Gwr)dDSKD z2OAuZ5S`8<^mPWBi-lefma!gUu~TcNyWS&JVV$Y$W+7N5(rePhG2*lW!(U=n!Qdoj zZ+twOgnSTkNfpzzq1yf~PcbdF>q1BESW&z6 zO7LI5X7=QzD5sv?TSJ@msaJN2>1CGfeC_QgU|l@!+$jAK{001Ek##mMSRO(VX{Jrt z_;hZ9<@VV?sFssnrAPqD7S=?a-H|_Ytu%Lfy`S=2k_2)IC!O?3C}??d9y;57USxJr z6NS@b5sAvYU$6LGc~`WxG<71nM_ohGM+k%$Yl5MHwiqp_2*_ZqQBe<*B`nHmf5O6G z%jG2AwMLx+H9B|%<3?C)3j>CVEB(gHewlR}0)8WIDrHt7ljYR!9tPGJk33^j4)eFg zyxV>i5pPRW)Nm3!~+oQ7R zW;>H>P_&YMgo}hHgG}R%Dirn_vww1ZRAcJfQbLmB$>Ee25xgE40l+jA!AKke?<`qf z9_>r@L4^p8q5^eo;Z~EId$&`+{u#p~&{Y>8Z94afF0dH?KfD z9C{!9wv?(~YZDdP&+lQ)x2l_uIH5T=o9i>K`%}S@El(oK@tX-9J7iS)xQ(zhC;Vue z50(I!j3SKs!5;Kx=ouc22x0DD3^xEC;MRccRu3TMj`MHb{=T}9w!^qy0G2lZ1ch}l z76;*F3z}C-rkpw$@WGj=juVpLE0Gb(c7*)gv&)X2$?0vgC4DI$aYe1$ z7$IxnBr)aZt@wUXrDi^ty3;K=w(iuu?A9%>55%7hJHCHa%=M3Utq%&VMJ=%S$I|pP z#Usi|i(XBc5sf#Cw#_9pX5;WbPrdH?$N_zomzBrqsQn)Kr($(1QE4H%V6WfVY*^_T zHtQ{oj>^3xld*X7vQuB3^cr{wlvA~wL!ODtPU;pioZxw~og!r=oj*iojH>kgWWH!F$){ zfUyAVU}X@i6a}+AKnsfs5NHzts%qGx)pK%a^^d#;L8}&B1t*}zEC(&ud++1^8s)`!9Hfb!L z#h45^3=R%3olZJilV@6zk)E=R+LTNRt;Vq#x@ps}iVt^WEgpX{?6A1fu1KtEQ2&aZ z+Eo#>(`X%dt%-Y|~zgdx$o(g#4Lw3jhA z4QxbZ%bhlwBe^%>V!77qiBlps8(&i7f`83w_(5^BDN0)L9mx9TXlzLcU0x^C=Q;}| z*nK*sXO{>)>9i-O&D^m^v%;GL!3CnbN05IM1Y=l(l0il}1`zRxB~K6P60^Vp7+<^C6^1QZzh3Ebq#AnGmG`Zw0!#g;037y!acTs(BNrT$rx}>AIL6DXI+BpkU@4+)9zk*Z& zB5#88K)$L6PI2=JfCl#gc}HHs@By<8tbvYUhd01U-ql*REx)hb=0_(W4R>%lJaV+z z{V?CAX#xZx9#?3Fw?`%Uc}ZUMyE1s;+E;2Dv7-Y^1e9vvZ}=&*1Nj04A`qHr;wyi$ z#x&nfH#&9Eh5T*$L;&qOsELnmGefdWs@q&u z?ENDp-$R5s8{2}*-fd@h#JvSIG0jr29PFuL37Kn1v)r8#Gr9HUAM8oR3;USMC2~gD z8*JR&ZyC1Bc@D9In;X|G?VLd59;*WEps||WJNdDjQ$=OOCCXz64rEeX3AWZ`nKUQc zjf?M(%c|E$4;L!PQ?GuiwQ<|SDcMLEF`ol?$H@_N7?OD^ZDK!jFJz*Mtr3HLJ%P0J z6>|S`KD24OvIqeEb+}w!j#~mg^W74X zV$~fkc5%aa=RkJzrb1Gla=CIe(Rk{`a?j5$;LwHdH5>S^snU+lzH-<#)PFj!?XiRk z_u!fwi0NHI{!5 zMg&^9rp|xjdh?@e-wfY2w%`giQp0m}@cpX| zJE227^;D7#{*ZXnH(6>0#+on_YInqR)KfSQyx+}!;y9UM009A8_tNIDYi5$>_#hB6iw+mVBx<5%~%YBX;usieFEZpdB6TUP?vdG@a zQcTgdYEF4f+&eT%8oD5>A_I5;T83DQG#KE6azU`rnKc(g9xH^=3rr6K8R~E*0J)Hx z#RG^6U@V|NK}6tUHL3)IEEYWg5Hu{7K~V5qoC6RFG*@7JKvs;d#xO6iS0Dm5Ps7R~ zUjXFd!GUDOrjR(}qV_3EHfk^GJ_v!gB6OJr-=)vUmNiYM0sZ;7x2;$Y!Z< z88?1d!Xl*j@U2H%Fp2VuR002hB0gj;n{vYq|+ue4zvE8k<{A>YM zZkuJ<-PY7*zV-!RCKwm-e1zgd865CYD;Z08RKQUnssMlj0)y6+5J2!jZwP`QFd)Du z0AE0VA2!*3U%g|0adqTYu*W=0cC^P`hvci>ByX)s=`DtuhLwDz4+Fd^mdl8qCEM-| z6%Q_{=o=s=IP%P`OGi59o^o1P)BJuD@bYPJim6m>9aeFh5gqv0ug`Z?7v2c?_1$g4 z&m}gBU`hmE8RklG(?mU>rr-SW3Iu=q$tU_sl|s~m4BDhZ8Opwr?ZP#=$|}4wlZ)ym zt3BE>FJMH`JMGtIVLz&^K8M>tT4avB$2Myol;j4P;@3{vYShvR*-o#?r*I|bR53B) zz&mrUx~OgHI39n%=2jp4G41VEldNdMpI4a=5rG%HY$ezG*d0JxxwM9g+vCc~z6DJ7zT!nQb2~4LM|C zJ_*&xULp!`JT9<=uGO7d<++5y=wTWkcA2Q1wA8@g89Sn;Byr0Yn?L|H`6HtBr;-2I z>swvik(^dDA@5(ZtEpMTTM?ax)DsJ__(!yQS(k6qRia<~u!$P@t5xIcusM0G*x^;W z&0DflY^*!ntgfXgKsF0cti8FrKaTs%wbp|%_NtDaU+g-U=Wf--csi=C`}SQ2rr@=% z-fe1FUFV*gx-8GegcOv@-T76CX$?`<;hm0_i7X&Bb^T@ecMcu_@Lq0<@o#Fv1MC7P*c!XHnyl% z`9NvrU*>XBS2eG|^|MTFR^(Z}A9t%p6Oeyz$AsdT&%vsO20spFiPc>tZ`Enq&^~pp z_hjFdte(Wl7KAtgWt}wTcoT|riIgT(PxGPN6N-6Ht#u|e9R~ph0-c0r*Mqu5)~$^5 zrGK>N=V`T-RHq!Ly%1SphkwAd`R}Tjo0Q}3dp-leE^l|&X;n4h0H-C4D zk$s5DR)OGftx0=^;)a(2H#C?2yz#5aKXGE?3B*SB)Kbe%=ys>ZgqisCXcD_qZsT5- zPfN3v)|amd=u7yOl@RWz_wr)61a0iWPQ5?xx8eSw1)@p0LZ}=@5GaP!<%Afz8mW#3 z(Cb$?{u-taZ7>{?SJ)jUgQC!LFj-ejoor>Elh3ql=roQcGepxJx$ ztjVZ?Dh8i^GwKyCv2#Ig8Hc#LZ>wmVO}o+V{L7rMYJYu$y!Jcd&6JDp1kW`eyduze zd(0F5ZX6i$%cAe&Ht_snFA!2y_~-wevv^1rCs-rGkrf3nV-9K}iBT#1na^B@a)7kc zwo{)=oqJK)ofIedMJ`eMdqdO+tu?yb8kmLs4kaeP4x)^?Ypgq7om853~yUDEc&*G9^P8qy1h| zj!)DXl6xhSq`xga^%}fOw4&7E{O%8=#9zGMYx8oR`rG{e0@+qrSADwZFE;Nlf64_K zb!6-t_mff(hcO3)t_rwF&Ic*xtpxjCK1CU8h!_bO3sdgJSIFs0GH}8b@%9SYec9$p zoOU&+Y+q{w9zW3$a-q2PtS9C{1AF`yfHQnci z^tW~bYao;wffomC%(%n)(@wA|W5VK|qGu98Z@67k<$)O?;1ZjEOl<0X;veg?P}F_A zG3e^eNX@^_r=UeL_8^jvr_)Hn4Sj4g$|hKiL;Xg4)bY!0YN+Ij+RP>{>GWVW0VAUP zTKOYj@Zmjc#y&QK8zau-cz$@TR#_7!)gB4EQN03ptq^5KCBJ@~);m-T&D6(fYa(lJ zKdqleGaJ#KDc^fSd~U#RE`$JtwV>ftn1QZvf5z^ae>XoilEzh2Fvt#(A5YNSavV4LzScv>{{{HBqMs z=_QdPk$puFogUNcD0AMwrt|hw#W~&*hlh5jvVQbv%2#2Y@o4^qQz)$f zSX@9`Yn?wb%B1kXy{pk$fId?J&6N5?;mcUUSUp}^K6dQE*+OL~9P9UEfBc{o3QKlp?HWCD;=2UP5_DY5|I`q$KqBD5jc5yf9pY>ZK)ra*ER#h#tH!A1a) z9igt4HUFIUUEbB3-%N$CS8w*;h*{$3_Lrs za|ow#wEJbBX+5czYqDWdwmiYXou!a8>&++jn3AP<4T-I=ES8`xEhGSdX3o(}78%EA z^UxZ#1IW)J27(VVVeg3(jBZx{IgmqI;v9}%GGi}iaT%IqV`df?$y!*J&cWSEjMv_* z*{>5rch~F?@SZu^66=pcwuAeUqL(%0gzXOcKXw4XxIoCqu3+ky*g~KJ7wJoa3wfbs zud_1lWIPttYiXM#KhJK_O;Y>;iKJV^N36txL@e6@77kQNi-qP7(i%uH$1^%Kpk)0B z{UH=1c!!F-J^+K^9~8#i1&YpLA}{oVQ5Ne#(UAv02@xI?>Jb(wI0uS>gb#~|#nBXn zdH}?sI8gWh>As>E!4!M!j1;6$s9^VGQ8QcRkODWN{z~%=>2@?2!W2vHSITEF(ztMI ztR!U3ZfG)cVY|aRlf{?%V|IHfGon(6GnBU!P*5OSpnT2%vj%Ay5)(GRLOg;c^U^|d zDiIwTgv=N`*SSPUY?!=c5+MaZtA&iL1296?0wm_J#FjiF#d`>0AB~875g`wNKeUJt z^Ra{uC?XCl_GltPz(*57A)=7@L`VZL2Ja$7I24xMAwmEGT74qq01Wwph!EQ#S$2U4 z0tm9};K>MxA@t!7cIF6K6Mo4g!~dY_LkLyiC;%)wJ%op^ArwImd1+C3c?cd2?&MfR zdjAM%4R>XShmZnbyA=ZqpbHT7K!-W3fn{?D@g71R1~>z(*548lr&J8bTg`Sg0C8k3*jSLU2MGDwu62hmZph;U@~M*viEdf)R#a-TV-; z6z1>3`6WXxPronsB9@(bGMKZBvudMl9p28@M+?q5$sI}|^?6hC==9Y7^;vU5vu*d2 zcq^~%5XKZ@eUg-H&ls9)|CBxx2eB``OLHEySy!<>Q05R20{{R3Gy^sx000kVG}Zc_ zcD~amNTLX|Q=4J9p%nvq07q-feu`KK7S}E3J-g$zX{-MGj{g9N2msN{z@0z=LL2oz zeo+DxfT+S}@KG`v(Ih@V;j%itd!>z9xz^byn~YYa#opaxjjHYX`(|pVcTBuA$4r%R z8ZW%q&}uUN!U5o*5Fh-pj{qXxNBDQfAdCP2A^>1C1qSW_ec#`=b8WNMo!bPIIdi)m zgt5EYwsY=U5S610h!0%!R{0VY}M`Vuh=H1~cI1EjW8I{0LgSTHT z$`xAjh&v2sZ;?m^k83FIOGf#`8|;m4`Yg zo>I)`kVi85d|)yNSjxd1hzDtyAn~j%6>^X9_}>)M;zClw;A9+RkOabtTUHIZA9>Tj zY(cb5h~>1#g(isCVP&^0j~iisV`pb$iME=8o;D3q@-c~lYzFRVI9&R}@GW$C`JU;z zFNda1C&{9Kl=o6zc#7FfCb+U{1O3cFSCYY(yJ6gafXR@NoZ)GbPAwwgI2)4b!C$6F z*3xW&6eqM;Qc=;OYC*(gC$*FW_$TKQPVCP*PF=7bMBUB%Nt{s&=`oH?rt^uq&Py<8 zdwC&Cgy#7B-qzjkePb;i{g^KAZ7=xV&X-=;clS$n&gbr~$gRTKk8r;a;kOrV+aLRV zHG8{*+{W|GksotAzj3?W#(Kx=&Nzi9T_w5SdwW8E*Z(_6wiYgXtP}O*@!gv&(%9CN z==8#9RoC=3=}ql1gY|^J>-y#4phpKAk+Cs5xA$F-@#5PSI@Q`9+*`l7?RYtB7Fq`$ z?|~M#Ulw_VdyV#V-R-5e6&Wv7?j{&@94y9Q=3fyaJn=zNic01hu#GlnDRU`hhnzpA zNfBNsYcg`tgZ_D5=ZD$c;}ap_DxUmjw_|@ZMYBjtpWx<8onbUTM|I>gPg<8LV1KyM z_UgprpJBj+whKxsc~|M8wML9ps$k%c`ZGJ4E#^JJ(qLG2D9LXC(6z*`*V5z;v}^qFODb zi3E0dZX4@hW6SH8xnoTpHbvyy@uqQjM7ELqlA}L{zAVuCE1A6fihTC8d}_Ge)%0|D z=Hg94V41>>*Q#8coPF}^+N5;}f79_+`P+GP`MJk8p!&)ZM0i>CZywJ&%3wYzOr}NR znV?3~3~j{7If312IX0GE=S^94#^bLN|0y%s>aYo3khrBVfNha5ca#hl%2JD;Iv4Av zd=#=7joOln!>nJz{fe_4C#*4>^_(}q{sbOvS-N`rSa>mnvBTm@hTwdVr#(Z^9w533 z1UrK-{nfIAY>ALz6z)}>ciXr(9ec@Lgj9kd zq)qYG&VJ@sZUb72%pVS%Do zo^0;LrdmnG9WJjV4;@kK*->~N71Bxu__|`2+%2DAJw$3jkYzRSJ)Z=JlKU377iWs( zoqS$%+e%TW)K2ShWh@c@F20-&lcUqp-sk%B9LwvICY(oVzoY&X zd8XL(_JuV1T9(?>OV%dd%P&$4TbqP=oQL@1U+!tLoh_5kCpcU{Jy8;Ng(06!bCQ;6 z534Td%Ec&5mar>%#LoR3vi+bRW{yd?Xs(*^=}*>Ucu%loJMkSFr*D2=XTOF&_>REEqh2F2eDUqxwD$Vp? zu%V;~gP;fC@;M|Ww*Ex_Pg3ndU1~|e3_FP0vOpc*|ENhx4maogB&7hNNaLP?|nlt3|(k@o)u`^btA=t$fH3J%yv z-frk}jHJMWmEMwa050BhmoTdRL&T-GPGz^GskkJiJUqFYB&8lS84b(sg&b~{A6-%@ zvyan~*M0DHLH5vvyIriAePeo+WG9 z)NVX|LZpO-W%mpsf&jIZ3xV694=H5fEL}qi;pmDf$U~6lAw>b)9?U}u$fy)IFo#`$ zN*#zpkL=@x-G&7StRcVw6c&(%zTI1#sCWYpReAu`kq3I9+z zuQfx;dWeQ7GAe4KXz^44zz2N_MRtgFwE}TWGf+EgDw+BP&yuxlgSP<~J)xl51p#X- zg9=@?1uArrRInu+pfZr>fJ$HvsPGLkfy%l7syfIHulR%>Km`B?uUM@EGyeP8*pKEh z^QDjv#p;+$^6`7C^R6D=7~uzwIoXK!Gt~1yYqnET^8;SrByW{NmvTwGD>Eow_1i*R-*SQPK!SrxrHqML* zPH`+9>@RG@A+(+ydyBK;{RIVWer#nAi*JG1BVLczwybSA3N~TOtT<-z)=Rc-{gHUd zO3WylW1=qKgaizMEA5>}QPeg0p90*A*i)H_BodY8=EBy7`3atR*Nu)$4?`)DKrD99+oLI?pRF* zLJA8I%R!4msE*cv10`(GpU_nx_|CvJ^_`!8qjKv9;)37i8Mm_Wj3M1;J*{}W}UY>q#3obs7r zhZu{g98W}8T;gNat{~~|VAxXe?Ll8~W=5|PUx<=Eu0P}p02b*6jx8^^X^jFj%#Ujq zt2qT%3-3Q|8^$_UNcj!{qTW{<=mjnSv{E6i9$=8-7C6F1xSA+0$@-AOJ#O&PAf!D2 z$YCU;@QzZ@f)sE8u5Z2z13PiCYeRo17hC~w6TpWQ`S6K8AKez#YynhFG61!Ex9-wQ z%$Q3>52vHcKe{@QSYb{tuX6TZYtZTVq|--k+1&zg88>CgEhw$vI?^vj6UG4B5D)?Y z001)sM>7BbZ*?H*^k1v|b`!b<7|Yy{Myj@bk4meSY_t(#y-r=bZO$&c*Y1!^|Gme5 z00;~K(To6CfB^y)R{iKfCBT4?eikGmSOasg$!fILTz9>u8Ld;h`!d%y)w=DDyH>ik z+r4*dwb>nCx6Wh3WgPKsSG8J=iC?@}s}(ll1+Iu&92Uy}5b*h1^BVvN007O5m=yp3 z?>+Z@y?0x?+wJadw%u8`t}A;ajcd7WNoOIX>qf9D6;VV56ckhh1XLhuhzLN?2M`NT z0xe`&kc9}eQUy|gksyNsh*A&&1!90yz@X-zv!!vrNQK%bf)vRaD`Ra;bgG3Ns3B=0 zHfMW5no`y@Hd=tSd0t^}qQAtjnx+78li$v~JiT-W#qC?KY9pVaXEIoT8f$c)kwi6x4RMS04 zGaYPEC>SMnXEli;YR%l75%KNh5fp_KsKejwQ4-cbgfqZXP-NRnS(K}-Y#y!76jYDJ zbYBv(Bom%)#0DPKh;sy|&DoJsj=h%n9dr>M?&blfJ%7)66YxKM_D^%>oLOtmZKH!$ z&UuaG81T^`hqHVe)ZCxby4KdN>yRXuu$JAleC$Ydc%`%@Z&^S>fSF!Es&MWWG7D07 zFameEpQt>nt)@Lp-UB;RVpERr`ILtG&G(TrT8l?bz*M3{qt;y}AUf=x7?nTO96k*L zce4kJXZi!SvBaB6CY5YJI%d}}3vG5bq`J8FEYfFPzkaUPD(}V4_Tecg*ynY1F%+;+ zq@_j$dV-FU5_~b!b$u*dYyU`~1AbTOo@N>fZE5O;Z=cRke$ZN45f)Q$*G@b-<@2eb zVVzS?#~M1(OEZ{xghJEIr0xW$?AnUTU|m*YG40Y(A>OREQDH+fwD)}!_)7-bgJtHX zzFV1|4uzwaw0ZeR&K~DaYUj{bro4OM>6vf3)3wdaYxrxoHVTv!)H&(a{Z&iB4TVvh zMbQmgG_AHZ41|u)f=;n6<%J~S#DhX^+5S`SY2u*Q5|xoJ{rc@u^E3Qlj%?kze*>8j zc(|M9IHLpfe)cA3Y;RFLKkVitHT3DV8O+qv9rRRO=($pPjYVAr7ZsN6m{*M>tXwta zQI$|9zQ}0GM}#pZg_QGTG3il?3>@x+0WPWt;E(wh zy?J45tVu!48`pq+?)M(hBVqAN!Q`=-{&MN-xY1dRe08F_7|z2#ojva26&~?j6ZH1;4ZOuM810Cinq z5H|QUx~{#~jm*_=os5--@D=90uCLu zB1^)$l zAA?_^dy4o0Rji3SB~lJQuu-yVPsRIakM`e1_Lu+i+8>81;0@s@UJUNRKd1Ak%rAjl zQ%S%_^N!Ef-EDk7s%vqJSO0mF&zw!!>xHc#h|*5Nt(TLnnP0oG0V?n5^PWjQtbxNy zly+(8@0o~Ea>c!e@JT9$J5Rckj~n>BOsg;q2l7-XTkyO>e>4V%jr-V)^~rta$L{~Q zGe0XH1f;GMl~is#{->DV!KqEFkp%6CcmE&r z8JM4ZCoSIwfH^oo_R+G3qPe=ftu~;JtMkBo><4M{JVoX{j50GcdiRADn>7-wIG=Zf z*Gy%xU+zB~=d<@UcM`GG-(00EmC>YG(sFia7k7fY;nrF0j$6}(y0gFH_IK%%>_iri zqj?8|eu@2gwt3`Nw$XKDHtk6V9b5uy9^M%#WqWafW)F!_f4 zWZ>w&7_ikr`3V+|3*=+_h+AJ^SS-*B=zv34pvQx?(Q6gY7P~LHux6f$g4?CTfJ2lPJLcBPIgv&q)x-ip12-%FQX|4n zKJtF{3a$6360-onun%jsPskbl4;8ujqK7?h`A;FDI3pl|%V7uXe2A$n1y4wvs+r;w zPLNd7Dz5GmDI%4g-rS_k#HNU~9`A2p6GQTZj+Dye`A_r9`hoINPVC1;a|@o$1iQRO8>kqxAs-?9b@ir<@s!MMvte`I(r<%O5(s7w$J zB{DB-M3%q8o4@kzj}vk`7hfU1**W#zYSR*irq zkgx3z#8WkDVi-X=6Y0#L8s}Dm_yw~NYYfYH^# zeoNURQ(7EHCQ~lyqG9SaTx=h}N1KOMEozp_276d%A0SV5zTFnF1JPg+2Pra|QyL)9 zlxM=HOPW$EMV$u30Vl|@ircs-g$dvBz=)(|p}MD%FC$qQTXNJqOk+5Bhliw|E8daj zfZ+4e8WZKHc%9+S>oFi4l9eZn&o&}{F=?!aB_qM54%jgF5SW}FG&lE^2zBmn0cbCJWb4%y?kWmVDjX(0tg-mC2_2Ve?b1>rvx!}CKzx7Fg6T&ffG#D z<(QtO-huKbiJ1N4t;xgH@C0)}>-PmicMyv5MiAf$8ptl<1Os%?))yn0(N@?t$;h09=CPrhmt^O;5B9F8Yrzd!BrGO z38fo=qxKgcKwXng;5_*ynWN1y5*e{|mF?P01A3uVtN~i4_K@-b7=NAKLaU+p(r9iz zXccywC!LL*Op#AYH4fhtku-!UrgBt6CWs*7QO3n0uy~N0sA6`UxXIw)i?Ixf=ZwKG z=z0MI*)k10%AzP=jL8#ZdtJzZ-3=?|Fu~y<{JVAD^T>6;ADHU%{^vJDJng(AY_m} zB2nNir}(2q3yRzH!`6I5d{?(c9CFms)(m9@k^bQZl*z z7B!r2_yw7}m*T5n?=ga{k!L7ye9`NT=eDvTCzA63_Bkt?pw`HoVFsbB^DxqKsP(s- z=%4Ym>qvL)g}7ZMnZpAKL-#3NoD^iE?)Z_eo4LQ13tk+Z&Yd{Z*-w{=C=Pi|r&VWs z!fA^;HJjFeIAvTHmA6K-fT3LKuCwNh{Vsxd-^wwdD3d12nbtyfovknV_q}YzlodpMQ9bW$`XZ=LTC>Dy@yp-Qb(_y}5U*m!myE z?ePbKXMmo){OUVzn&l&s4K)cy7@kOj7VZK7*qVcVgRr+MSvN_Fstn!m~}Eq%zV zcsA?wzH=gtW00@6_mTt+#__)fjc6*te{sh-1{@^R0*Bu8&z-;yhoPYpxQ~yXeYjy3 z$0%AKD6;s9!b8Wj9K*g6+|s`|Ph`s;_=4`*5wF#U&`;&9D>OGlTG64!NDMQ#P@7up^rg~wB6PU)cCiX8*e{9mI1`o-Zz z5ysgR?hzcGlPmmptiP!b{s<(w!!Dml=+Wa?VFXoTH~O?Rk@2U4>3QYCb!&h+uJqdx zqWbKA#S}CMk-N5o=lCFpRSL3!X5O^Ws#Cln#tB3}cEeRf`jFwUuqrPfV$`GEbtFQ` z!C6#DLs;6CFCVQ$6|9MH%BzX-;a}Dd;HTLjZI8=N380s2BWK&BXiXi%rx7;r>hx=o z>n{LMc*`I4oLQYrhCbnV34ZN#xPm-?GGeP{CKftQYPT&j27P*uN2P%DR^ZG-Bv&pT zxtwq+a2~Cg!^gpjr;2O@p@htPhFr#))TdhC=xKYn^CNP`8W3hy^TTsd$V% zCUv_tL@q7ek(AWOAX`}r5Zd#|shS>~Y_3MaZHb9|)w%KEhnJuqJ{dqA000mW0{{R3 zGXq8=000kVG}Zc_dcI{R2C0bvEw#-pYXH$qLrNlRf}d>{2fMa8`|Jg~PaF5&bo>Bd zWB`gr01N;OVB6Sy8%vgK!j>CJ%=lRrEi=fl&JxwiY~)rpSAln+WkS&%>oKyV}>_yWd9GCsj# z2Br}K1VN^JS^!bjHxLTUggP^{s7f^urNYgOtz@l@d|vK6*9N@iwVyHVT|cS|z{ z!vSy}B=%!jG$GR}kt(dy> zK_xQca6)>@rfk~mExf996eO7$+FXl-WX>4rwc5#t#v>1Oe&Gql6^$%O-+*3hweF>B zO_*s@{e*aD8E1?_u-?_0|3EJ%;jO=;-_D^wN&LsE1>WDSMfcjWH^nJ$AdIv$tTtBZ zpL|b|a_>x7%FoZ5uuSLc!vDw2|s>yoLuY?>p|Fa1}l=qjBpvsF9Y zlKgqut*=_09>Up)cY2&fRjcx|GwkZqNTGCV(hFu?;SW|Wr>}`8t|(Yec9z?hhc>nx zA~+kvyxjHrudZ~C9@(p} znfV!c2qEPwXtBH?%KbozpijPbko)8`x(aFVYJ!R|!i91Unu4A)Q5jYIon}OX>l6mv)xi zX0y{Xd|jC|Sja=p`HDtewQnN0z~BZ=gYH`MajypoQ2o-nm3mV=eKz5ZgI5(76tpvj zHZ6BJHMPAQOj*Z5oU2K-7B?AES*np_>zxc`4`SN7OblLZ;si_5ZOYx1Bzkh4jM+#n zLTj-;s%_+Hf_+3GR{lx0rB!BhduEtPE?LCk(JnLze>GAuS8yx!$Gs?(s!PEyaA{D)LjqWMtT9 zcm8FPcp2&b-f&7k@?|#vRz^-vW>l00qfnS}l9KzRVd7S(YXE16L=mid7~(WKc#lru z>m-h<2hhpER>xlJ<{3agLblKj4ys&9l*hFBw+{9gSRoK|63ovcDoPk3gbkh5B$#6! z@qG_(KGg~#l{4`U8m=-2UT0I>jaELzPKv~nD~8_;?6%adBOcW}Bd)9uA_YgB$%Pkk zlJSKyE8bz(DbI7eNFA8?dykjqc%bmx1okUTl{E;T843&m09fiJ1ftTb%BdU9RyIJ+9@CI*7?)m z!pw+#13T(!CX#YXC);3>`kTz8b+|^kp(V?RPZW|8;`PS#pi5y)lA|ACd8TD`Dd|9L z!eymdJFasrJwNH|i-^2wd6lGYQ@i;0Q+=OjrkpNLrdY;`BhkGlC<`B_vsCA{e{F@R z2i$sNp=qcK({9eEWujXGpb7@=IhCeT@_b9;mLI)_z8-ZIARgcEi)EJPBxj-^cxLfA z=nVdBIrrv^r~w+iphT1I3C0}ukeyxMkb80XflOE=xzw#`5hAgjhjOE=l^D>AS2zCpp7NeXd2XI1=347ls! zosCt|m-RlhExcEfoNg|!b`0+Gh#&v}X}1PyJCd~SJoKCf*CBukUF&&6{@4eQh$KhU z&)~w#5T0Dm^7e_EK;{dx*kU}|D;azELJDV&b`d>asfZp- z)hu(GJC@~msCe65Lx$hJ;w8n&<{S$Ea(S&F-3_2J!A~7jlu}RSH+~jJN#mtHm49P0 z?Mon%2!ho-i>om)6{EGOEk?i;nYTdv0Fk4zWQyG-sX!mC2F#4#Q9VM2ZB&t^_R?V0bd65x`nx$e6z>uXe$%;_ZwX#!B={2Yj{W`i)OfyuzU^tq4=&%N~LYZmD4Ri?T;mW4VOynO!iAFt}(t!gC7rf3}eo9C9cAM2~(a zLTZSFP7TS7xABus;KEw3=`)?1E;W;7YA{Vz6~x{$g$GUaApa4++G zG$m>tWsl}rWfp96GKkM9>-LFv-Ic$=`@;tz1q<8|6UEp%ukRog2*$*ioF2ws@QoETT4Mzs zyaWXRkPrw3V(Yvyo)Ay)O%ATxwEGjMIp6&&cv{e#`cwo*EY-XO(GB$~k0;W8a%e$~ zn~(cly9`A=b2YzmP8V4carS7?D8<_mGf-rIue6eg8Nfq)0SK$of(j4kB?KP?V=CV1&;GoK)9V$s*Gg2PJmcf__u}fgAqW7Q;cp0h!*D}D9foiS#Ht~|4QSVk z#`QR?qmC~3f<7SO1+_0V>l?mbPn8b5pF2P63i(p4j0!b6nVIl{CqJw zDu|j7Y{sal6i}$~p3P|Aswie)+?5@i;h<1+VRhg$vF*Qb1Bk`LE|Iq2veIpk5*f}* zG-ly*d~@(qnrf0V1UDWOe|D$3S@Pd^R3lVkIMd*uj|-&XptE2AG>{G70f@K}P~Jcm z&OwIg!CWA~3`%l5;zfg5klq&eHU|K&agtQRRcM@cthR?+j_}~}zT=EGdE_KP+SDX({iCSkrEHR2HT*Ylidun)0F$7h`{q_0T2oXN9y#^ zBg}wV2hn6_@}o`EFaE|hFS50jFeA_*>}M`>bT`)vb@C`#E#7Fvj0S|5@S&~R3W~EB$asz=osN=nvIr5*5S1paEq@optYc443 zDHvk4c}QQ>>q~2O%Qt@)#3VKx9??V#Zn{PzOVTP-_9CL0*iUP!he|)`Ox4K6#gS}$ zG?s@6Mh+(EN4aW37`s=;o8SeBGXu~l|w>z+SJ)hHc4yI*Ei~$;|e9Qc0 zzvp}D*O-F%0)(Z9=>sr;-AJ&Uh$%XLDh%$#50q1QxD4)^p!hgGS`=pU|5)6X`>Vyg z8$-OWvewJ+8ACNmsX5U^9+rtZ9NZ|Ua*Bj`Q4Sj)HO?TG!o4xR>MeS4$o(YcpV3sg z+Awc-C)`A|0jNwwsUw-&_NzD}D=Qb6Z-V znuF(7?2h!QdctaF%mQJQz7h0+^;G9!d0C}R^9)B5?DQ^a*gQQer+W${{y(z`91ZiA zT)}#a_+}!_9RnD#+{a~NOhHZQdqF@MXM8h)VfwbkP&Q$Du%<-2xG8D<55fsHS`fOj zR(f=2Mh*0QH8P5J&Wc?(QlzM5dWRWbo*0>TTGn4!PTDW$ookPX%)Oq5hF_gR@>tJK zsF^W69WjAHH`xDNFPG5!G4oyx7`mF`cxTGBON5l-caWPwO`)If+i#o>`|+`ir6xOc z+Nvk9Gb&U(Tg10}K4mJ|uhTCfBE>kzyZX>w-)X{tm_Bq&76=N zBw83|IJkV|PwrgimmH?s+t?J6a4YB3I7l#g$xRlE7L-wOyE`J{ zXlbdjDcdv8wZ0%d6|G|@W$D1aqMIOUOS=EV()wvTo%qfSF)Ij5)zc}+b=98w#oIrG~MR ztQd%XSp4`vbVI{mfd?N5$pvSTXz#HHa5635o&P?P(r-k7zYtHAt15`BB1&A&;R|(?=xua*>MITjirp?{tV40$cU(- zTcwiLG}2PEvO?ZMimaEVFsP=c96%B=R)}l4HJZ^WQ;I2;A+wU|>vj+=qdzcFOd+RHie1!tuLYl$4t;9aOr<0MApY>(bZ|cX;q&)sl!+Q7-NTk|byMv# zv&)~(;D4)0n@}?z`E>)LomZJfLHZ<^LPna`rgtkE3H=5_Kl%*xj28`+m$Y6Se+-6* zpVDrSUyRm6S34;>{61BP6NcGaQA9?*SV)6+uJTjw8ru+Mf9K|CrcRZlwNb$HDS!TV z@0s!?`?c7WTJv)dvl&_3L^cBlkO6}$-OuoT!Pgn`lKogxAPAQRmYOCW+s6SmG+Wd8 zNV&=JFQv@lAnw~%tGs@E_QoHlw3wIFPgx>5^+pD^%l-i8&m*Qmdxf(6UH6i!pUm%( zH>jpQC-aK~zNhNG->-6`nQ!vf9sd?Csb*nlZ8+^44T$TG<3n5)oFNU;6aibkc5>;C+01DO*z7m7bIcUHTLrWQ z4km;1==zQtTr2R{OmP=(ZPUxO>`7{;T@aNGM9fP{x-De3@zLf}6fBU6{#8GP+ixa} zhCg^C<|W*!?CxO8aD7gMDfW88-TnZDXj^t67|^PgaDBwA;Tkcp?=U??I&S?KUC0^P z6^JxgVp)Np<8g1(B2=c6&Kiyoq(dz4hzOx-KCB?ehl0;&il-ph2Hj{E;fDh4xPTD%!{s|56ay}35qp{n9+BZt zIGh*{&}73%+X@K8%a?JJv^)bJgz=-`ND;9r0s?^{fN}yQ5U)c(;8ba`i|f3@P>59F z6B@Q=4{)(474@jnOpjoe-T7=1HOLXZA6kH#Wo*{hM<8&zu$(gTuc|#~HO7`S3qkS} zr(j_quCPct_!N2s9()fy#?1oQ`UONE>Y9VKnb1h?jwsc=P@I!Y$KT@hM=U zc>w3SF6sqe%m6Ct>8sTrhzNmRLVX~|2M2;8MBHE-4JfQQgmoAYVS|Ld+Kn0!L>pQ? zQI7(Ez=EoSJ?QZFn?ZC4tb&937($=g6KaHM*pfEZvt!}2mI%1VW%EC563p68bhQbFhsv%+x%Yq7B z13*x?eq!k==$$RZ*0E&$xZMTDMO4L|Z#s^ug5b0;AP*`v>vi=hPA`%J-A}c=W~@I} z8o4AKzou7;Bx_+_ADN6see90!4!|WJOEVP7 z>le$Vb_#bJv_CdHariMf1L{%kO2yPakgz=&{Z7+Im*GZKmye8NEJ? zcwGwCg2cUR-60R!y0Iv-wYOfUs_6FTCO_Me5j$k#)zvl+VPHny@ZK_$^2@VUwEyM& zhQbLmsqFdg_s5=&i%e@r1FXS$eL*JdSylM)pc%i7+;gi`fhgA%Deewh1dSD4T&`)k zZQ#c2;N>#Pz@j z`vT+tdGlKJb+{O0O?n#&7WBXcK|1Xm_ZaP1UU3Kz+q+ZP?MkbAnp_jo4kROY6;Khb zjJJg9ac)^}@l8Ktpxa;*zXyY(SPuX!uKED{BlHK-h)^U4VfGyS&<`;$cIJwqdq02X z6cL`2InVK7(Lev_#@Lq)(7S}V()!wc`x}Pg&h@7D?E|Yltdt^C8cm@)Zx_o5#oM7j z@LxiRxWVBtqr}Z0s{=(gx|%`bhKsJfENu^vWwA3wp%K4ynf&bf2kyH!D(tSN^@03a z>6>j>kjv^EJ6q96?r}5A#drF&BDW2;y6t^EY^8KlZP467Qu=_b*>!3ipWq`jRnsu& zysYzeOxEq*3}0Oae{6;o<#x}oX7Nb6v3)L|TGcOg?tlq>-a_Bx6&25Ms+E3Y_A zS1JKv>jrZk&#`00O%D5U_OZK*bvJo{76Z;I8j95a=)oQ!EWKzk+V5r;yEKu*24q9KAf<;#coiN5;3;f&&52f9>W*m!l)2^gV5l+O z+TMwUU4?rndQT1DVwis0ZLEKW`0AS1TCTd}Mwg8Z^5D+18vET?_H)j_O-Ob!1{3XI z6^w*Bu{mN%I8oWy%r{1a%587znN$|$gHxRrE74<4c1q!FDBB@g70k%%jsm{N=Bijy zYq=3EWzwO)&pu!Iq`O(+XMbGT)>ziK3R>q{Y6XG5SjN?InR|=o!z9MvKEDp9LRvPn~r%xzy_B}w!aS?=Jy zJBQnMY`JY6K-=y?ylUR_O|Wd^(xL3XajJ=7$rxytc4>SFPVG1f`-82qIL+u}Fu2Aq zmRJOt=Ojlj(a7oA=1yXs@hz@c)fiEHb*XRJrh4KYAwk{G&V;ujr1$n!>1A4(qp@;4 znz$Wm(7;5_d{5a|(Iuvz$lkv{lQVB&Cnfq(-i(gUhg?cCTgrF zC%tI9-~s^exd!Q?QrM|UWOqk%N~zv9VD55~XU?N`d08`CPQYxo_(wXrq)JQ@Qbnb$ zPEt+$-+8I3O3&PSEN8`-e5j}}W5#+KB69VZ`__Ys(H{~PddK~dwnT`H9*3Pmc0tI> zFbpc0kkO2>GZMZb2Dj>78ng0Y{kw^kCju=ds9!j_k#Fy2Y(d&p4RbO~qHYj;`@7{6yDj2hZm+1H7bX4)AJ`wrU%KC9KnUc zsIh=};aQ4=#iu)mD9S1@R$HbW zTCzs|c4Lu4?tqBd&AC+fTG1(u^N5XK)-MNCwj2z&X*-9fEcu^(U$NJF!e_s9YcSbr z5l}S`vhKaVAlZVvJivzFzY&i^fl!4~ZhVD6ZiTnkj^jN=eM&C3!Rrx8%-mOCl3|lj z+N2E{XA2^HV2eqIMo~2Btw)Pc3rr~ARUX<*v$Hk_EGE@S^;~Qhz{$4!AJys23sdKO zXOinP-KrxP;t{w#tx8_?GE5~RFo{;O%4W*K25iRU7R9!l>{gzkaJ}fv=c%FeWk(-I zq9N7#h^ZT{40&zL8HStLh>4#1kZzJ6oIs{CI)_w ztSaK~f;ShKOSnJ|2!Tv-9?N-MbmMa<_Z}L`U^yjNQO_(ue`6<2dR=m#fqFl*P~YFO zTA@9IO$0>BR>)p=CP)>f?nxKDer8_e0^9H3U)AC9={jzYrTzWQKCCdZbUDHg?|qvw zbD$-f_nyGy#E)|tS>2;w?ULzx3FDn3 z*a@R{>_RG*8m(J_kC3W9c@F(P0x|ggBZv1latuJlwe?H@DqYHsWb&u~ z>O?M+Z+H(Y5ze}lV7A&Xf`9X}yTqG$6St2VTyrkr@o#c>e#QS*Fzk7-YqE?H?ReXH zq_gDdjDQ?$xO_=#=`%~V2g9^8G<!O$YXj+tU@~$waZ=oJG56Bp{WbLH!SMe&UW#bxrx|3=d{|5_|`$PeYm-$uwbk z=pu|+QY{sas2=PIoYsV4r$;iXr7~f`p=lx>4V=w!+U+mJ2@xNCGC0_dz0YcKX69ZK zLSJh0^2L|H7$6OC^55;EqTMLenYbsMn)wH1&*qeTP5sHKEY^br1YE)(PtYRRJtJxl zrW<5Afu`y`n0l!GuqmPR^p`?&-V;6Kt+zvdTDXHi*iyvxFp-G?vNgQZ4m;7B+~6s0 zik8CRwI;PMz|)IBP#7x*QwYFP4#ovUpK zI(d7^Dh_)R(@Et$bL5+k2j3zZ;<}$3YTu$BX+veFBCenJkTnR?i(l7f@8?=OO#sU3 zrLvcxcG-J|Ju77eT88VB&%plscpnbEjE=JcXDGLr>4Zci$i3ERg7iMO8BKiJGCLi) z$HBl7H+}e?Ha_w0k%{i@#QC0{Gdq=@=MYY&-TV$45QFIi7RPv>zJYX%H)tTQVEN?m zWrVME!JGp>Ca9f#X9|^EuB`ex@gJc+#yAo9X76rCNQ^2hk->6UukyJ5BnMv#p)>0k z0$UX9PGDg39~2N#*o^T#t~YWHKYwWe(2r_S%aUn}L?22gNHK)MWHY#}Z;e@9)o~^R zOjr=55xjohxg*tu|7%Rz`C!^1^ldl8AMmF}nqq1XE&cG3=llK{w0FLuoDWY|Fidg3 z3+V}ppPT64PohUg9-UQ$ zx(>+c(@p^1USFcf`bzaCOR2~M3M-3r5=4^z-jB6PUy0(s62&<9($unGZ(pgNrxOpK9pNxF($ANlzRRBlz@7Web)Cd+0 z!X)OiCAlMWiNQ^3%gXCh4xu*V1^ItS#O^MXF$*KQM=d9@8Ba2t87;kboB3LmPMA~~bdibXUob3x52z9#$4@F0%ipeL<;>HEdt zyOl9Z@e!heIJ0ZK%k0gM9+v-e&;>tCg5gO}cU%di$H!QnFHM2@G2912m%xrz=6UeW{5(Z3F>K(Fb4*>>+pJ>Y26f4z7pvcm*cvlM3` z0vo!7HSi+wfhDl_bBj>^@69Y=8D>b{wD+tNupDeKT)U?_&3Q)PDJ#WxPIQ)I4f7Ua_J~?jt3ttq>>udy_(x2f)#)|FR!&3&}!H`mePc%S3{& zK0`c>l;4`C8N~!OCp)GM#RE|mAuqRO_kqunGwVuPsS$z>toQfgSnDPK`kVc!9h_W^ zW%WJo8N;mN%f&qv=<~9Z3X-n+t-Z4IlW$g9HAgEx9@;$`~(fjW@{s1sC07WAJU;qX}XsrE2 zvdOY#TSJnF@?=>y$OahM+w2(A;={PM9X(i&vO#uaH}1}^$eHYA-}Iu**;w?M4(UYG zmTaf!yH7b6MGAUA59v?`C_qajeKaJOlJa{1fdBv*8H1uQfcHP%y}kE;+iiE&-7mbC zREq??wzsX`W?{QYrZf_yKR_t>Bu@yCfHDF`NrJ`+BJfKM3W3NpASl zl8cZ=5si@i%KnRi_47%Fv=>(!afXVInE?Pk@kp)PZ-aGtxN*OG@P`F@h2Cz zRl$CzFB3l+4+_%BxnF zG0p@}YA-JcDC@|bkXx6YDR8OkKh^pc8CRkiGrC#dC$iFeO2mApsOSfi3)Q!dveHbufEIagj8Mbw}FgPY*lsT z0gY!-PnENylsc`*yAzE1x5l?f8W{;}AoEX=vr>7I;D4ThM$qtqI#H(pB%rm+$>exv z2@`6lciqjHB*_c{G$VG_p&JZQ=W$-K#K_4q$-HD|s{+pC-x=vVlH4t}tb=dVl?Ob0 zGl(3YpRXm73UEj+LupW&Z|^6p8gCaN?#viyhgccBAji}|7rVuP6(^o)T4)75B*4{e|^bX!EN(wTD_Ic#-dqt%bx|+=t#UV+I}TAqkqIZO_pd=)pbZ& zhUUX0jU4!zb;H=JZMkT$=KCZn77_-Ifbr>n;6Y>RewYpN>jro54HIGbW6zAw(Gi zzE9zfedu!c}*)YJeQ+G#7xpT1g$tT2$JG{paKM3m~hF zZ?bzQs{!zU#p2Qnw_?ly>S5fED2g@|mo;s^!Lt>6y2Q5EML??)PcR8zS4r)BD646e zqYi>^B!h?vSvG#0K6Nd>w`8yJ=x*xONa9apXNFRjrS@Q?Jkb`fHU?Exie$|&ZA8Jc z^t6e~LNXxLs(SRH=e;P4*f$vUL$#iRVLPNZ%g^65tTz}`gY7bp@}>!Ar>NOsD*;wv zQTYZ}l#h;a)!9*G8t(t>X9oVd=kw4&MS~Xy<62h!{(U*s` zVkf&$TL+tP2l6n(x4gp0RR;gn#-db!4Rb(JPavv?*J^qY>_ycl!x(-;GBQ+qiJ0?~ zR6u{bzE(T$s8`Jn$l@#q?Rf;Gd{?I0=K^}9Gg@W(dl4m<;M&VUsSxhr^N{flS>qPkv&?;tPQcN#Il^_ z49|fe09avOPlAK%yLulKuUpmpTV;RLR&JE(tbP8gY^lIAQWq84t_kux&C}|j2Y+Nk zIEm-YK-c1gNGkMU5z63%3TMhq?C}a8gz*8hFbqCr8ScCJHbGoa8j_%|p(d(?fKR=u z*uDj{FWOtL)tzq~Y6EZOc;4ZZ7qtt<53k)Y#M-<89>eWEsY+(hGucnGIB2wn%pX6* z_LH}ZdH1wRF!_8Ou8PcvP`_Q z+eI|*X)Y0-!hc4yZ%8lnEn*=0#o0JpzO2#G?~f+|-SgtxW`4&Y&DNEpb!5d9I^=cl zKJ>l(F>2la_0Qq>T{dXd560)hN2>tMd=ai9*e0L2#^sS=PJ@n<6BST!u+NPcI>8%W z?tPmy04Rr(Mi{0c7|LAEDLDWR1VTBP5D7l7fDhAh=iY@$Z9&!CyjMXFTE;^BJzIw zqKVJ~N7pYT8nf31C2g9m*xSGGi6=nR>O%~MFB(~Jb&eZzDd(eanP%nMC~PoMz= zEP8R|KO>C-EJcqUY9hZThc#9Elq}wvR#c zdz=}2nXxnwCuq8&zN7+CX@`AfvzD8_bHFaBjQifXpjE@yeWO0!gZ*~(#?H0&{*>S* zdb~k?uD_R<=Q;ne*7Z-p8~88D~ZCW3QSEb_e2X) zh{*ZYr^jMaa{bSVf}GgU z?;91s73QP1^H{HYm*_Un z@yye;Q}xW+H+AE$#`@^t&=_dPc#Zq~sh;(1^7CER4ZL}4XU6SOZ+*rnDo6AW91Z(z zYsC?^g9M=-Du~1#(OaH81B^6{?RghZUj+9!<`NrD@ta=|9>ckTi%2XY|1c(_d&*u$ zB6?OoE7;=BCW+kOH?;G(Y0YY4^grrXaoD3oFtCyXaCjr1BR`JB)mxx5G^)_&iFAFi z!&0>V?)w6!-n*K@0K=VXA(GR1I*4*+T+G0Y`Lgak8Ij%LX6M~geBmuyB%}`S_3$<1 znsqV=f(EUZim~zuk1HUK%gD`3!w7WN$bw;lj+Hk-1XRxJMZvv5BbsgtF!Hbfu z8*VYoj%r|lh{G5n|M289}=* z6b7E|1|i*{!wl{T>4&6lC<%?935&y|3$OyTKTB(v=t}(1D{7Y;WunQfRW2CrgG@+! znBIjLfrBnERAJ~Y;e29V%ML82ha_QQK=DJqwR_i3NHydW zhjC*rdGr~xM54!dz-)Re&Vo<1Jnk4e^4v^qT*c-8h)cPX1qU z>|bPqK|Fv`{9obvew2-i|Kji#4fHGVtI17-J&>Q0xK29~r|K-oi?e6N+A!uxqcl2( z6sEh*mo;NL>vb6S;frFA-HpUC%xOz-r@}L55RQ3H6tCj1!(Zt@%^#-##{D83n-VPf zNB*eNVOgZG$wJ?F?g4Elv265g3sJHAHwY zu%&A&&bU|)BWkXaBH9w;jYyj@r9oJhNU4(q9mm_pQe<^+K6a?68yLfg5W!3Q@bu$t zA4-em|0u3Mq#ry6j)a)>Q+GZlycWwu6#L@L7f+X(>ZR4!CsQ#Sj@vb*Ear!OoJYXf zFvE&DLZFwl&F3_*9@|t{7FB!?e+!#R5BDE*Yu}Yc`)q_DEDFd3H3Se>E>cE$5;q0A z%+|7w!~_>Qw<0c$w}<$wml8E3Wd4WAgD1t1UFlazqP$6_pTANYJmQu-oD$05AIAK= zZ#jszDV3sP&x$8o*(YXv@z|JXvN0g#+)9pezSu>Zm|~?-wjLK2R1V|hR)>ZH0#VF_ z6Jvj(ShbX*A=i*IM(uqTwMoVFdN^E^8+OAsVP-DUmeI+Q6C}@k2tk)i(O77bb}?LL zLF?}=yXhl}a1j|jFIrrN)lwMYVGbP>14s;0elfwIYz=PN^K3Crkdcina>oWk)EASE zQves^@*-_au$hqz_hBoG2?vB&=n~Tgl;7BsSd$Xa1jh2XfR7EZs{N;SOsYD*F6vN$ zz7T~mAs{XIcPLws~k^>Y~*`5^$h?%x3PP)C` zx)vD;qa?{NZ6w4UrA!snQ3=vB#&-E97}>+o#XWr^Dn9ucUj?R`u%-^y)K3YV&fE8kXS{K zm^D1G9iVL-1X%+lvS`e)x5Ke-T_;xcsglznK|x}BxPbqleFwA%81-7oxScNKrUV}* zKEzcBqQxA1srqjHQ$FO|l8WYn$84#FQ|UR5f0V>-C#XWivB)EvOr|`PC+EKc9MkGw z0XfWsH&(30Vlajy1;4wFy?h00ilcdz%}$PlSR9|BY=!Ac>1K6sf9?$>L9nZWZXfz? z_RSb=jueGxRbfob$&y&lO2cFcVWxrfo>!V#-!p9o0akewmuV{-8N+ z6F~*xv&LGz;uE9=I4hRhL(qqa!n!0Q&}ITVygRnx(4esqo8#8+C<(r5@H_@G&}oTw zx_#d1J}?5-5+T&4_(|I_G2uNLb^r-V@tuKEh^eLSRH{z%lpShpu=2;!(zLRO9v21%GLuwyhLE;Lj-tZ9V2a%1%T$uam*X+eS6>@41{`=MGJ{ofmmll5mvslRik2844~KVDQ(^UF&2FjrDx z$_v=qEuPW^C-rcS(&H(_-3|x%? z0QrHR$Qpi1?(Xy5UnI)-liiUb@X4oYFnV%1S#RA9HxvmaHsEsIk|B!#cGhMt$)(tW zJCmuT_+hm4zBP3qyPYBM$W3B z0C)et@7}wcb8~-fm$akSy=(KFRW{qz>TM<fM>Q=DvSw0~zJ0|m8QAsJpDM?UMLJ4D$ zx)c_{N->I`cjsSt*U(~Sw$#=^l2)5-gRgvUN}+(mBv%Qeu{a$J(()7`x)c(DnOGe| zv@I85Rzxd_I%x^iM;PXm2@g)|A@;aXgLNQjM&MA zy2opPR`VL#%63SRbhePl3`Cj+&zLUT5<=o&SzemI{~7)_P2YXAX+DIq7Vl%HArqRe zRR(NQgf;5&lGM`Ue?lvZ&Jz0)t;VgGj=(7~rinc+jkVY-ZtbPOVqJ~olm(_Nua~yK zzh$MaWl?x46mPW_y82QmHP3{Kj{n7DiJsO41X4v{&}ev`jtd@^>;9Y#FrPf)VmLEz zpKWMf_I?TNz9wToyOhXR`8w$FvyqhV0crOFJog{O|dc2?KAH zD8X`HtJbZZC7S#DMH%btXWqnXs*+rNb+Q~jWz(My{!{*3OV+xcr9VqDJBa>Zm;egs z7UJ2+p$OTiq-7?4u%=#_e2ljev3|p1LcU6B$rwgd&zlsrV_Nk;Q9+eFHb0gc*VbKS zdQ64_FqePP^mUDbX?cUw{6ZI3H_P`LifoP4=bw0W!TY2Q$@G;zHH0kTEem{82)rzF zsv3`@yug_b>Vb6Sv^>(fIM!f=>ZRbEn``n`+t-BPmQMC%A|@jU*;`5BU5l1J#!kG8 zDPK!@)YJfOZd!y&e4@^2X2oK(L)8o0m_hwKQ;wY#NEiyKv%!VfyKyFV@M4S(CI;ZF zJ!A7&!tP>3JZ zBHjSJffR2%FM>iqPMO-KCxPl1HDr0&#X%Lx=WK-UJ$l1aTO(f0_;+HXOw&PFJ1|}1S`eAOUNvY z-zmX?8-yW)f>sVD4z&=Bs$9OrBfU&qdlMq|fH=tda|b|Rw4P_1c2+v>F6p|lso z>O?2&v-k5lLfUQt?>1`C4Jd*gdeduLmBw_L`dGjyC2JH|TveWQe;Ttf_QRL0F`t`n z5V5S5n&k9q5mzxZQ&ad}E5ljf6Y_)>*%BUy>9GE6a5$XRDE z+nZzQA(0>~)8ZIEvB2l3(@ zS;d4R-&fQr07TrC_yX3$qZvM#j_X%0+v;vp-jw?+-4b=S~7WfS8h;X~#4R zuiS=OCpON$tY4qlKJ&Bf+xNJk3!gmia3;B8^7dp)L$HZN;&Cr)xI*ilQ+;C>7W?ho z$&XA?K|6LAgwejz0_oswPI%Cg$)^a-wU$w;yXFI<6(z5Jyn-!P9IpO-w^Xf z`pkUQVUW@n;V?oRb8OTbM-8^qY`M}MsFL>AriO?N#jwsSlcs%DskKS}SW5au%*^Z@ zs9C)f-?A^f9_mh3>kYMno!lKRCo7k8HxnHV%CAN8B@+$=kKF%JQUmg(?cMRpcI5Y1 zp-dhIulcx4PVGhV4wbCE;AdK97>D7ZuNzG|$qiKb*kL~#Gb>CSqmrY7JN@C>mSN#n zYz+mpP2+qc=LxV>fRC}nm5YTka#RzvVDJd!YZCf8j(MrgkFhteqh5V_nh+7LOBTW__($1xMZNIL<3jux13_9S)e2%r-+di12V0|?GQ z%a{NT1(*?+1H#78G6iHzUQQ1TRYC+m=%VCwMF(B};)^;HeryEzfF?b~%Ym-{20R-@ zW|hH;qvEg2cU>l&wX>-C_bq`7!QRrN^1$DG4h!@u}f)};!_e9x}hU-v$X zn;U>@B)(NK5P|1_-oyvo8`U9k4iZ!}f&gHRCuoH6V6&h=YIsV5GGn8M@K=)MQuyI) zw{~+@ap(QkEj$G)mmbUan$gSb{6aVV@G*MX%o+_8qWwSOTy7XP2vu+WttSZTjFN(8 zC>xQh)AkB@R>OWWSC+mZ5y;}7YzZIeUv*KkT|AxQxSdYT8Xd)EEuLC`jsoa*Zt2&I zR9c#b&Fq-{Cy((WAto4pu{Z02LurkAp~7^}hSZTr59b)}P@&4`xlUzTh7XWOG%H!L8qqt$)^>Nj?4PVhK`=8fEEb^Iq1QnT!6V3anv?b5pF$rLQypOf@bwrY z+y~4z;{(!ag7^9nBm>^nh=u5@;G7#u;Prp&dN=JTU!JMfj=ViEb|6qpe8$Gudj2g+ za>4%OF8jzp;&-Vg(8J+V%tU~|l)#L2m|Q_>4+ymv6B6ciOc#>6GMnx&EdPOCQDXT4 z>{>@^@SP08!r86QPVbk+G`nrgxk)_N%f0f}eoeit4({i9ZMVg3Et(Ag=m40#1F)nh zhTR-rlF)=hkPJ4cU_RT>Lm<`>lk|@1$1Y`ARRoeCHSh0|v((WRYMYR;(3cKeW<5tw zzN^-D7L)vf@#vp~&_frv;fA=RHOuD8X5*2SKV|c^+lGAW7u%WXk)TQZg$Dp_fWa9d z1lj)C3=s4J$!@TFT$T=6Q$O(?{eh`?3tT*Cdp5XPJP7u(VB^O9`Y3~8{f!&_?^cu= zYTtVu)b?@i>aA`mFQVn7dwqr-2DS%-jk57!>_Fwa06&34C=cAP&tanA4h1VsT+$(W z<;DFR6muV9qJyq7d(C1iJuRcOU=4#6`@cE5M~#iwIXmxg*#vmkB>>;%iuZ!w^-Wa& z6OX}wKxtzDG%oV3$6T$>xZ!SBa-aQ(>gxA>pZQX>3rM%1L5xl|K3C{S z90kDu7y}M)M)-xzrv|)WG6HJUgXW2>U@5ARV;UaGmm>UfJV-N&>SG>y5%4zrJXns_JSr}o|#{2;YnaG2+_*g7;{}fUIymn!+W{<8&%!xx__f= zZXG#MSUi9;0dA5fQZn$&-)SwXe%i#!L|Rvt+Fq?oyntnTA8TPMF3e*-w@$4CammEo zHNq(|9=2WoVerp$x ztnie=z;+E&E;rmp4rED=B(#dm4>n42i#>lKndmd1KgU!m?Lb(fswMjKiPEyo)0hRc zX;15hHgyRZ8K{TPMUtMU+QYN<7d}~d0MpuOt;mPhY{z@f_mYUPK*+luRO#w?iH?d@TveGNG ze9!j{rl_I->>c-GCK*&ylzjGS(0h2o?G=o~k|HP(%O_D$(hkV}zkk_$Fr4BV3pDPF zMm-n~6>W?N#@EZvG{|~c(POsEs7yQ1;i)d-cv{qM4OI>T#b!6OAGE#bO%t7sVdB@b ziG6W%8RJgtY*Q~cXg9(aG!VP0g?;EzVfIrSxv}{0&MOkd2@Zl}%2d6AS+6?$z;?nG zk93~GP6UR(DMV}4-RHjqS&=WA^RE_DZeorl^Tpf>%@g5)azy!k)@`l2@A+bS&@S&) zAPssVtA)3!YPxMlD~5_7am&(#>$c!(=GpAWf|GKRzt{sXoA1U+|#Cp(JR**7>#+> zt``^YZ8_VO@{G27_L{^Q1dGzL61&2dR>E}<_Xq+at#`JY?O4c?W^fy!s0FmS@Gt%E zG$c?2F>}43#v&tM*4a899DChK zM~y_I)VkX&s7-q&r`tT1{c-Di-m4a9KOv}&Vb z_w%D!1{%gFguH(y1!`|}Z*X02?7X5aLneO~_huaNJkO#bf*7UMU8<>|P+f`py|GZW zOH>`!YI2veKoWp$PSXiixe}5$t0<^F?t=-g^#kW@H_X=I9Sp(RHeN%`8HfP9lf(a$ zD4z(0kYTmx&k-7!*fL9nbKP>t6`crsC=zm$W?PL>6r*a}R+;8p+ywPWF6B$(nnMQi zP(+k172(y$5qKTETwqqTg=om$m$o1my$6xBn$b(fLoDbV-hJ1q8$E(xOJKcGqD5NF zOU1g`wCAwhN+^_PELvr$#obHz>U!g|g(7v zTLp@TNVqa-47K{YJuzMp0rV=(AzHd`Rl(5Ko%5_YJTH-dLE79ysH_=^|8hn=u^`ks zR?kzldrv)PyL1&zRo>-L=ANbLbOR^eaG>O3b`b;2dZrrBQ_sb2<%m1BR1x{OO>wet zY#hYfvmT9Hi5n^fc$~6;Xkr(MevF*wk5G_<+{86)5)r}i8o$F3Hoo}_v3^@6HU`IX z27M;c4QEx%Ulog>#;oi+&Mjl0GF5Fu)TB%ebbjL`k}{5!jYb{N=?e3rzDl72(etQc zVw|Z23f$wyQ#P1F7IGB+ux+jLw6L_H1~m!k9(Db;?-8Vo?K?dm|IOh7Y90&ZgiY~g z9j6bn;f3|%zT>fy*!}m@SQxamo0yjO0Bf^$Vt-Lxy}zh)<2xMQ`w#7Jk6?8<5k*0~ zCp)hh+GGqS!09mP5nK> z;ZOMnYmV+92nc&#v(ttdsqcu5%~#%?zPwX)aF*~5oD~Jh>qyNDkSRs1Q}b2yQ4TZ~ zbnS}ip@7#_?_7|2f8BPGj0mD+nh6%03+UN++!@~8UIGFD8P7QWvgDN?$}WcC4N-%! z7Am)?FXSe^e^k`w?GNohIHy7{hq-V$x6wKbAo2Z?F+kNL6h9p2k)h5nXwc+mjbt<-NnP?9!UH#UL)*dIhX)!Y`z!x-RwNDbGa;2gzBBR%pmG3~dPNgEMT~WJ8f?{If9n zSD)m1K3_b#>vOmszXw#zKlr#m3#GGcb>|9Zm5=(Q)V(TmWL3I9#X?)8yihWdd^k2j zCMXj(%l^SCI(LHLojLg*ZT6|S#NNXPvQ}B@kgEWL4@paG3DE=EkI4=kB{)u`H)fXI z3`94ee?hW|W+0Hzq8`=7F#%2LYqF~hSoSS*To{P7-Beom$2dtlOXu#esj;;Uk3^OT>pa% z|Lh+j2dE!vh@%Hr|MVg{BkTwJ3!>WgKf*Gk`P$~Z@`KTTZ2brF{=Gt-lgNvaZfzz( z%%)h*8z?nWdvIJC6*;D7Tr|i;tbfXAFWrnbpG5iL2P7-vYW>*|+m3j-oQ-$kFxYN3 zgzZ3ndUsR|*7i6(ZSc*w3mn;v?c^e4n>2&~wAR3J{;>M`$_$O58I%J7#9uo-Zd}vi z&Kp0}4L64$;eN%vt3ywJ=Vvl+zJQm(qj7oi1*NSL{;IjvT*tgQsZ8p6)p0Z#2-(yj z;lY75dXS^;NVm<5pH1qUeEW-7&Y?2y1kDaw)7ZRro&nV$$y~yr)2V$s;uQZe)>C({ zUsK>|w}bXM$(KI>0HEV2!KEwyk1vlvEEr%LZ@>SX1NW!Kd(U9O_pqMl7c~}pw}kFC zree3vUW5`)`gpBsPlJnGLhpV6Rq~1u4Xb<<;gWN;5W5TfURVR;k2~rNP-<-Ys$9+@ z(BdMLR!82l&6UH&j~Hg(V6hMo0{{R3Gea;l003`gaFq5PYK(IQNnmVaLV_nw{RmDY z8v#3!VPXP&b`4zCw_V#_9a$eF-+#gJ000>(vl#$@131&mSico;;P2v2JpfDmfYVMY zSqUZ%Bw3Sk`pqLOowRk`U90k{ZC&lMjaAm#vtKw?vDseu6-RNgNmklQ!{5>&WRcP_ z;z(yTkHjP`pXGP}J($kt01p6C001*1cST?T-Vb~C@7>W&Dt339tYxACSeA@d@A?Y#jtp z{sS^$71ElTx?5eGB1Fc5iDoTa1`%sY2@Nr2I$k1rrd2tV6eUy5!s)F{!xW_suf(+_ zYA9AK3CoPz22-L^6ijurH3c%k&%O9_@+3^zTc%#O#;Cp$2P`giYbNA6$PLr5WmqNU zKPh!us7=hzx}7FhND;cF(-ee`_tsr<34?Oc&hmj9GaQs7EHK4+Z%rh@<>@^bL?f$M z5SN8nq_dY(LX1vv!hiF@!%VK6DO)u;p_*`0Z5}1;5yzpqYH1ZpmIlU1WT~maE*&u8 zpZf5d7kZjddwKnroy!bRd^;@B=zzr(z_?g-lTG7BAMwHg6Kbw(4_ls%O4qxj#CN${k9s6nKmawMn_ zt=BN9!O@eHx^0Yw_n7TnmEJ04@p_RsL$BwWoeNLakYKh#|3P7KDX$Y>=vY1a<;M^! zKHYY+{9t?G{i$LuU0MZ$x1^c~z7tSmmdnAu=1n|w=W6k!VjHWz<)GP{cIAlXuNf&8 zxuk-VX6C}bUS>yNUKqE;EIQ##jTFPwgV%u*mnGa0*rNM4%1rjtvVznG2190Y$`sz8 zcl>rCS78My2#(ZCJDZ$B-g*qYl<vpkbs&b3uLm3Ku-$Mh+SO9Skxm`(r^0o zMWc6bWSE`gRT@IH#_FQx{VciHBXtAeSjqiNR@4~EZTyqIp%9&ypRk_48#z?v^y6)X zI9H230&g>AhrH=T2CIJQV%H7oEY^|~vmv2)YIkGa+D3*9wUA5?4vlZ%{R4sW8)0Ov zG9<~eC@WICI(TSgxf`&7#^mD8Q8^_bI@R@XxS!6r5p24PG$Zg|A8echY-6HG;w6`^ z>~!BH6jE^FUHIuPsX{*+E}BAJ)D`Xmd13230pT!Ux)bzq9CLijGMH6ObcAU*> zSopjRiD&v9R;wJQcev`Bw$toO-T8~Q?=!xOYQc_=URc7=9BuXp+^@(wqkjJ09o#?O zTM?{KJ-rpUh%zfccVk?U!(CpXR)qSTJ&q))oiqvVo8rckaLZU6au(#0EoQ4_F7181 z35OTBaBSbyPPC25tX+~`;>T7lf5n_3<{cD+KzqXN#Y3nbu0PgeZ6?+GM30YR9aPtI zn~E5CUVvt&p)hQ zY;`teP|F-au+eqPLWCW?il>M<*lju|!CdUPp>h}7WO5O_D`O1*C5V{fw=pu*__|nz zM(BO|Z%QjQ?Fif(EKZ9qJ>G<5U}CFlllc*&vtF7fC)rL2KL8XrAsh!fb_c5cZ-YZ^ zEo*{qKokj1J&(|VKBp!Nal7-re%Y$;C45F$jnLhL6;ocZp*JAHSj&pmxi%N)zrWRJ zrBj%b-ApeTG4-7nyt4eHm%;bC)IZZWbQdQoL%R|9t*m|4+NA5H5GZgcoP$LJKn;QD z5B%|v%TQ&So+qWi`@5W;>i77#C>d_oEO8lfN72fgZco$3(+05CWl z!o`pg{BROfKPaH!dK2Qf?Sr_Z6dBMSM`dND`2qXPtv&G-pqK#RBm(e3!vlDYDaJ7> zAb6~Tf)meUbYPSg8XapWFdwtP-bD!8afGbOMm+;dR0LAd)O?Jn2uPSF-09S{gC|qt zLCr6xl~_Nw@H}V!2da|W2=b5%YlMZMTcwu=9Z=hwQ%LYW!Z2c&s3V5b=C&z1R^Fa4 zsfjhtFZ@_$9p6z#@GO4L7c-E~-$q{tJ*sd9iZTT1+wd4ZKZp&01{x6R1FkZH@8%0t z7D7${j|qT_EOY>u{p8)We!ks6@$fJ4_X%?=07KUw;CGm z+IWY*16TUQXN2hDCx(*5?`eLgKQ#rMWS$>8Eumu3@I`uL6$O(xPMv6X=mZTNl96rD z1zMWqn;2s~;h}Ep8Q;~0lIlyt5=l-WmSgY9)r$ubL?R8Oy#}6sK*z zlt2XLEM69aT)e)n_2L8C(7n`8VKW`CS?su;W|YD|fo=FzK2JRANeVS5ir1NL1@=nk zg!((YQ;06D87_H8;yU>O#hG`&zoK{3!J%50E!?_Tq(kjWYR3ZtP>XBC7Ws3y8?8mxr<@EMixMSpaW^NH$uQjFYI zJs-HSFqMTNF^1egvVRX$=B*+F80?X`fXAztV2!nPho0pMS#b~?cBm$%rGA?We(UJ* z@)DfpZoR+*M^}Q-sGjjZej@Cc^L6oO5Z@GW#61?H1Vi=5$w;FP`#F9$G#5*LG>R)RbzmoUgs)3Qi=8y4e#BBDh$#PHQ7-BrLS)6_ z!|(A_1PsiOHYnL5{fXQN@p;orOql>$`NPHwNavQQD6#S}2{wow1q33Y`ZZrh@B7*= z!rn?jbnbOjJ?ydm)4e`XAI7ZyjftoJ^&?m0-5<_&Ae8yB`IftB2h7$AWJ$vY1oCQq z=po;)dA`H>84nVPZ(aq-6>+_!)&X7@Ssp3-1wDJAALY1RsLSb}nlNHJeKH1nxEcA^ zZ=lKAIVJ5_5trD&hd{bT>>>Of}nx$0f4(9`9Ks#v4rixf~$k1AVl>V_T_A+~r z%h^7T^A;VpHRS2i@N=?j^Jx)_H01M={W2(`uO11JEOUg^Igy4Ts*WjiIlUh+Gx__; z4h7YwHnr_eIKQaU%Bw7XtaSl58zhf$$`3186 zDG4U4gn;yzwf$zlmpP46nV*NT)WlseuDQ*qoV`f!jV}{vTGd5w(99X~L=+$|?z`0> z;gu|?e<@K5OPfPrUWx4l^!WULR5xZRzz^lfrf!gaLbZF#Pw7s$>tCMY0G(Pbj=8KtuS;cK2W=X@!#mJeJ(s9IRc`Of5AMl#-? zmY{1?#~~eKD=xzFQyZoABtuKI7t*Y4f%{gfuztgH3N1Mkiqg=}-7wggl01!#GwDeA zLS)Lok1n26)pBq~AtkDP2~n1I(-6b@Ea0|$ItrE4M~Njzrz0##0Ngf2oxv)wUiSIn=QXd&(FE=M@-1kgq@)272P-wETCi~tii40bgAf#~ z@q*On$2@JEl-6W^-@y<=*gTiz%phlNx|;s|2q@C&FBfQ1)84O^<289jTM$aA9>G&F z0{C!0)p5DG%ZbESG)+j2EY@i`sf+Xa=wu_9j&``jekL`OOhra&F$-~wOp*3~`lfI} z5#8y^p^0snxJHwe2Sq~e!zaI~iRJw?X*J8QtW$6K|3>IEp6Gk^Qm<@=Zsn7pl8ED~ zrN6}@3=h-lDkPTEjMFYn!xck1sM^(!4|VbwevVlBW0Q2&E~=hC_uVqYx=mMmE^sRNfktAdTj%MxXN-MG zi5ps~9B#ZgU}=xru{fWQJ0Ljztix$gVWV*ewm~EgDouc?1u4(tH?2N0dE=R%E^fs6 z>VbVlM)WZ`tE$|hh`&!^`oT_7=DHckPG?7URs*N|m+}&xoHhJhgCSZpV6lkG2H|cI z#0?0>Q9OW(u@QlY$O@u3SHgv311L9OgO%yw{U4fA`7<}ocOVqhdl_37P7sSLF$>na z5?d!Dd{QJ51C6y0enftE9xnwebqW}pA|%C#EP2D_S%Km07?jY3>fU;(R4|`pl2)4J zS?@K}$HK(?s@t&E#B>>-|DS7MGS>OzP|SzlNN9L3j5(HBE)gE}$RpwDbg zBgV2U-qtM*4b)#!tjS!6BIp_B=uLV#mO1?^g(ge6@?g8$sMb4JOSh8x)bQ7O@nIu^ z0M}^P>Qs%9ZD6nwp_ZlFle(ti`YK+J_uD-qA)Gzc`n!cjxzGUkP20?lRkqcYEhORotC%uhXd zGUMt$485|AMGo{0BTEbsnpupTLV!XL1;h+T50_(|1jqv@8K&G;LV$U^E7_vzT?qC8 zeB?AltcSbdgFBl;T_5R@wo2j1VUWKH$mm=I(1*vc`xW2@S!avm0{|Ip{DX0>g2e!U z@B=ZigT?*B`LUA#bYLq3kO4gjrO+Wp%uhc^#kz!%@RStxC0q7liq+dqP-MWTSpb;; zdtd;<5D)_Z002WYKqCME4^?R@YCkdO**%4+m?T-7*|1PC&@7N>Y#CVGXqsDGywtbl z_pUB=)7Jn0o&NwBnE|4a0I&c9>_+Tswe7YMt*4+!<+0+TQNK0osGR-3JG-!7d<=GA)_yYHE(;(V22?biIo0c}lVOf@|%*&4_#XqbZ1D$x#Ma}=zEao4H?B{UYl+x>yGRkD08`D@&h9vScN`ku~UZd}q2 z;G3V>!3U}R)?6`T@0!to0LhGHH^kl^p2Dg7Fm3$JPf! z$sx^kK`S3_oPjDgQi?STqb2jrA_-_oG%=24bGc^wA6?Q2sTXv9&vw}JX+FE0%YSA; zfwu|`yb$_=k?n}UnX93ygFg{qz9fWuhzA3CaSSyPhf5q{xSJ}UZ*z-vGIG&+XkQ`sd@JyG>QKsRZEACwsh-KIV}Wj0|Zz69zEXfQ=BP)w3j6CUl8 zAdCWBG~n(+$YRY`bP-)=AtyoonAU$2ms{(VF)dxq-&YBCIlL9ybxSc!Quxd5C=s%ppa;|SxPxNQT8 zh6-lCvsQ=XNRKU1k}^_D&Bn9`MNp}68w3xKLgaB<+jx%&^yAeVUeLRCa^B@>oXvl0EBRt9_660fqEiSva`EQxHnzUKUs0 z^$bc@FS=Po)B=7ZXQ$%gswsXR3o(I@QWyI12Kc$#UT*ka&_`2vX_?MUF=OHST5!lR zZfD^`(9H3)+`^FgH8bqvicF_R?z9YO<(OE~{oIcA$%Kf@HrE(G(ZjD5Q6UrQ?m)Gd(dnGajM`5>KGbXQSud2#RC?OcYV~Y)CH0r8~5C5lRyoU`L5MAD>O8wf2q2|>1 zaR)xPyL-l3H+MUUJ3G;+xwQra&a&!Y>Wg28ak+C#oXiSSPAolpxkFG&%1baOigD4p zrt~bl#`(Ku4E6M7XL?Oq6hUf7x`To53C9d2xQ88LZ>(KPwMe1;3~r5Rrkd#7i>t6-);6(j}Qmw zmw1)7YBB9vEzx?=E}ZMIx8Moa#wpppzM<<mv^wN%KR4MC0QpV_Nc>TI>1HmJPVB{ZDV&-T?ng-(0qaSFF=;cVK= zou1fI|IV>CduC_yU)!5zIa1pFh27>ael2zydZPD>Qph!JhnI6fp4DSvl)&scGHb%U z(e8&c6`1gbJb%2F5@$;|iz!Y*Vd#A-?qlFqoCSM5m)N+9Txq(mte6@19tszg|F2ob zMS{O79o%~`)@#HsUrcJ#Lu3c2YZkZm_vP<#&MG)@GWsWo-|#G0LaUzJ0~*{fHMc>0 zXD<8IJ{OqPtp>yzPaRtl4E+i;Gwa9={M*YoGtEccHd`>;x)fiUX?E}B9AnA_g7NR$ zw+=-PC8wgm4cGk#$5Z4-F-18%ic9!XJ}j85Vj23}Ea0a7h(_wIXZ};dzmlqM5Vu5x zyg3Q9jTd&jKAB#($lcnl#it>#a@qMJT)=!(%_iamX1cAz^N7`NuKfOlRwnM|Vyl<( zMMoMdBJ)j6`|vv@o9z$k(kR}+kvYAOhlZJU4S4Qν@P&&=FKyEi$Gy(<$=AacF@ z@Pdxmpyw3kw% zV>@!uD&31yZkYUncrfBPB}`^NMbnRncT37C(?ddC@a$Yv$3%2tt$x=05ky{OoQo?2 zmdC3zs)dnNoJC6hu{PP?Elr8^qpdyePT-F8Tv;(!ahsdq3t9p@(u2sg#8h*-TZyE|HTP^d<1VQ z`VO26ezo#cCMZ@r#Nl^_G4<1f3JPbv;GP`mO?4L?6hl$b7!jth zb|<46<$jy*qULvRepzLTRnb$I(roTPi&7H*OmRW613F+e*M5t) z?@0~P@IBVCa9qvbFZ_&n_9RpVl1fnsexd}|p3rla&!u}m&$UMLUqKYBq*bwOok>?5<`S|{z{LrOqWP4l+A z-2>8@@NZ|+r?S0H(Gqam+iRt9?&k;-JAHrPQAm87&Z$C&8wOLyN`nU;&Y*PO&Y{3R zz7F}sZAinVUPC(AX&dp-^EH>_o}z4Gx$=alrz1jDZqlQ8yV&*=AI+G~;j-|*wDiz8 z2XxYrUF2J@RkEl~z=yJ%p;o8HmXX!HC=Rzw6p^%Y4)KeI2Zwb5bUQB7)~G&e)ivkn z4_W4q^aGvnkTC(7!9xO9WY8Y*P9hErC=K3i?gyW8J_bdp+u+JjNgcE(95InH-7#(h z8?F^EVme421gEfwC7c?O52*h0noCt9K%Vg}@0K^}b1)%ZeM?7cW8*OEsKF3LQO<@=;H(`t3lbbq;S`(0@!ZihEjftp6Z zkav%a?NITu-Mf#z{$$SC4wyovc1L@2ZHi6|}aYl;j zfCl(}dxZ=XzQA}2A{pcVX(wVmV1aEPl&lI^(%J#sai|J!>`vh(6d50tkj90zJ+|(A z8YnWs`dz!27z37vw+V&$&4We9{wrCfU*@897#%tQ7WWQ8AA~BhaoCIwffrRsT$n1| zk39{+MQi54t03jLVXX9Kr&|1=9g0)j%wOLbw~LXw@(3RwCeG!K>XQa(*?oBE?%-(z`)o`Y?Px1egaWxqEjuckoY?_`c)}C_E zw3xRDFXZ&sQ5#Q?yF~YFa!A^-C6ll(YAxmc(bc`~e)9j?o(q8U{PGeKn}}m5^}F{P z;UmWtVz$SXY=GONzz6KIN$kgP8~c4d%(r~UG9sH3|2Z1U7-S*hjw^^(W#>O_nx@0r#|zL=m) zpxl97YrKOa?fVy#*b zunDE#0xs?;rJw|Wi#=3f)Si^GeFpgyBufBRE z5MP8zLB;s?R&ra(GiYXg6aL@*{n#DsZd4l#-Cw?fI0HN8*&Ss(b9?|m>Auen|7{7c z^#0CYj2XEb_bTDJ8^{?RLx=P4z(mp!zCnowgKMLoc_H}ef3#Q$xyd1DI?hQb?f7j7 z)pvRi{74TWkLGUcG2JerL&yMt<&KCgU~!J(CQIKCc)^4ei?MT?)Q{+D2z|i?pulKV z4a1HncFdMN#GxBn=hXQ;aLRlhBv!QPhcY8&`IcM9&8Ug7^M;1@#~uBA$_Cf54IdmF z_CSsREr}h7$3TzXfSm9p3NDtD^vZ&a$5f)-Yd9@t&-2ax?@t7J^`bZ8UJ7|$_L7^= zmyY;kFcMt|6#5;6IMOInKRjtJ4}@IM zI|btVf5`bq__x{`5eumP8G*z7Eta#>`2D9V(QIg4ib?3sS3w@w%}G}FJcArrj(4Fg zssjy>5E2kLfhvRp@)#kE0&?KfD!PD9X`ZVbWl3Xv4Ut7>*obS8z%C3~&e%QY3EK>= z5Lja5r~lMu%ZnfrxlzCwmDy;Xz_@_(!XO;E220!vWr(m4!f*xfQqW};<-_@2mRB0S z3(GjNwhWJltK!h0`q z10hF8T?UE=2uL09NKr{K838f@!al=Op&tZj7*wjAB!?$N+jth>~ONeI&TEE#)ZDIQ^W;P7eS8CkGb* zj`UK<0^BGGAU+CPi1xB2vM(Cqi_o0Bc|f>~CawE;B9#O`&h=ptP*B}s7zmv&bWD+0 z<*b5e0KNx<7KCwd9(+M;1zu;+GH@ygEV2eeq#%ETK88U3bHdvqBR=Ld;%$^Kb?lUB zg6X&h4gwb^oe|V0H0_o0{jc!<#YWB+HcsT>4*i7GNziuZ53y7siAtzK63HNM?7r=g zD3F;84oQpJnWdzvSHwdlToeVAR?Af4H_84lw5_qyoq{QXN&n8Xzi`wOyQ-4z(L>37 z470;5TcX(W)4vXj(0$#pgj{p^ago-}BDyg+o#31&TiGchjiJ17Z8nk_(Aqha@ z&S3z65D)_Z001*%KqCME4`qDS- zZ1*-7zn}Q;z~}$~jmX>;8~}wL`=ru>Noj2)NtXB{ft`)M=m3ch2X$S~;!mTy1>AA?6n3YBlm*gxCmSkVt$%_yPsR z4X6qzpo&(Z1B8e#yg;f3R8que_$V(3fH?Rl1H?)H#yp3Xw4_K4bJWX@8qRf9iFE3KI+QY ztMFy8XQKUJ=h1{eEqj6w6xq|FT%T>IjYr#ZXmm0)?Q$-+JJ7f0_d~%IK5-IG_y?x&ufhdmSmGAMhC_M@J?;%B$ z+}zV2H*cliTHk)PviI=ih_lf?;Lj(e=e8m!V$+-o8wNjFjG!!t$^dubQ?p+HQBZ0?F>r>KBiySHHw@MeuwsGyD zldW9rsKma$zZsH@T5tR@s+_3r`?PY!ELQrYTw;lO+s}dvv(;BxOG~lz(Ogp9>E{P+Y)Awf z4_CKN{dz9IMVSe+=6bybSyn)nXkX9DItQ0aRAL&}W;>e1q;c*3h>%C;{d$opWtx}d zo;6v-QS#~{mHbTzla7}5uyx#A`3CrnWqEw+WzxDC|Dpc>@U@{WpFgF@q^i_ouhkR)(M6tocaC@~w!5dXP-BL^uR|Dp@^|+tEjhm7F4!BU0cr@%ZyP2>5?J zJf5nn6$Dk1!l@V$wNXT2jbXTV_a0I2+G>(i55iJdauw8O+W<3C-0*C0v|ytiOG$3i zAjcgs4&PS%<66ivo(-DFpe>EVJYX3)qxn6fjeAGi;CciPWA;q%aGku1g1X^4oT%Vk z_~^dd+J@rOaFmc2IQXa|EO@40E^%KRum5*#kVuE$M)6b}1c!DmPUdk)5JCfiNa#Xx zgUp|m6dKO5`GhN+{Jp6Fjg4xYTv=u{cHBF$qA*Ak_bp~`&dH?8NI;E}x&_+f5R={a zC8+(!*>;5ENvTgUz!@%dq9YBs9x_ww9w3x@AF|L-zjF&Rlbu*PWpcpO64>gV;2Q#; z8Sd_R5T|RM8)##IAa`p9wUL;#g9Z~#CZ^y4Fu5(r4lp5v1_GGQ0tbW4mlWnVE9&*h zzxy-h9pwVXojj?o(181w#P)gX&)YCmmKE?c5ffD6L>%}xEo?9$LI^Aj2`O1nj@fro z&j?0TNc=U^F~b_|N~(#0@ZTfnwD8;}9#*m1wCtIpE|dIrGfu1aBUajxNKXS{5l4Ka-leLj&qX^Yz7$sS{|`HhTA3YQVI|s5S}q?J|y2k+JpE> zOzrq3`RpVPKszG?kZkRc$%V41W2p+!0s+$rdo17~x3Gx-Wg0)AAiFy%l4|y3fi(5Y-os|#pp`Rfo}#rOF4bFvqtPyOrEsC-$(nX+-^RlCPbrd`i zi*=bh)F?*I9(A3~-Z}hJ?HMJJ&0zy(A8^{V1c;0f(5J4`WAzAug)Wc~6nEj(5M#iC zQ6N1(KuoE&)&-Byr_ICmIg7qO>*2?(pU!3)I7$Il@cGEEPZVBy)}XdWoFU%3(b`ze zl^^ZMlP$jZIf8z_uZ}_1okZc6SEg^0NWk|zAMy4)mXTM6NXTIAdn0{l?YZ2YXZn)8?Y`_Y%P`3 zv9yJFmH_mD7fX47AS6rbFw8*&2ojE@PTlDp`xF~Y0F*>j(&=u;^&aj>_LV^SP_}`{ z2&jx9XaFz))RMCLQ##C+H;ILn9dq8fLSDXqrx4meJ38Bg+tEUoQM!|OdJPF>g-PD# z@k%Vq(1Qxg&7$weVW!SsiL`nViGT4I+ud{5c&3?_z9Pk!QOp(!ivUzL3=(S9Xwp0U zHTMS-iyaw9y>)2ErunDhG}+Kaf=i_T-wsFqYkA^2qPN_gkY(rJ?~KKko9tK3jv7U} zLqNtG?>|;@jXaxfAGk6&pEvCs`c16t=B)+mqoHnD2mEydjbsehU)o0SwMt_E^pF||aw5z@sn;s?e=g74ayQe<0W z>n+&^v#bl#5|naQZed&{gR+=!=o^l{`Q;Od#E29e5oHG%~w5Lv~73`2V+1@M^q>~{Owbmv62NLU?c&JbykdsfB> zikJn&USSB!fR9rHG)3~MD{KL@)L>)~A*ubl1&uXW7YcGyYG)A7?Ft6V6QX!nhAz>D z;MxRCoPh+5!1NYcp5<8A#3oY|D}eey305by6s|$Y*kq^^3gWVOf|@2Za(T#(jj4m- z!TX0nmV_}f%CXKbv2aS+o+?u)du;OoAm))CkFFlPJ1)YrzMB>T;Vx+lncl(L9#_fz z!?&?Dk8iOiN>wqUhxgPtBlpJN2epQQVOz6r9wJHy)Jy|i) zV_?g$LXvzjt<-#vEsL?-JwK*rP!%% zC~?oBjF@2qAdbgOJZ`7rMreB;YIJjp=3GNa^1qq;T5mv>UH$~FWh3?Z%u7*_P5ggu zICEOmrhgwLLa7u{h*M2m;tSjll1ntH6O<&oz4h0hN9hr9NlL$jd#(otim9XgY4Nv? zONV|`S%itvGO0JQiJ9Ch%#ns0hoCrjScD?Juob7n1TjsCV6t?DFLT1#>;(L;v$E8k z0|sQXSf)PdPw2*5(BJhN)xFybT*YO{#Bo=J$*hPt* z$jAh)ucWK+W1%C+Y_LnIkH9FBxN$n`#Dlks!Ue2AWbkv~CmH2%NDpQ42r07yklDvhs>>{AsedL8N*6-|zc3(K9^l0){aRpsaY?iHx4)&{l` zaRpMdFX^uqe)G}XK-~J%iy)j~%-u-!fsX1?0w7@&OjSV>u(%lS(=jH*9o8r6C+y=E z!SCz{^H%-$06Y*70{{R3Gh;v_000kVeAVBV=IY`^Dz(yL)FvsRZ4fe~0Y$Qgny6c7 z?RImH+HH1sn+xAh{P$pV002g0z={k20RZ+%NCJ|y*hV8s8GrbTP)t&goR-J7mSwUV zdk`-oYh|U}?k>H;3ESMed#F>kXL@=7YCx607uIGW6PQlvLBqDe^ynoYI1xYs=#V~i zN|Cfn`g;nN@Xqf55C8xg5kNG90)75>_kH)b-KT5UZH8^EsJ9KxYVFjsvjjGQ%Had? z6(R_L04Oad%7Ws8B$T2X0w};Dz8h&#NriYJpU8(1K0z4+M1B1SML1D|y`&ahSTf?Q zwlfSgJuO+yDt4M`2&L8m!*0pm(f-X&<&(kEF6z~yJCw~6K6Nv5J%eVJRJ1#0O9%~f zGHO~Wi+0PJO3o5WE9Yl>*QzccwJ(;ub+?(6Yo#*CO zdQ9v;aU|a;>Z3-0sKf_(gD0*hr++J^Dzr9YXY#2*TO-oJ1=kc*hwE!Dz>2(d2@f=Z z*Os3YStK|X+GdW*lung6I6{jy*grK&z_VwcDEd1?X^{41ZAn|94o>UI#}O_A67?U#-)kIsN?9APV|L zD#ps2nm3NqL$51*tlmFm`mR&j!mU~AhIyZ%E!kPtXFIPgor4Y4T~)jkwdpG_stWOR zZZ%zB-Vz30Cna^+I9bI|w7lTXh7b;>@#eNM+&q2X+Mv1CU5`B(;O?~%oce54YIN)8 z+BteFzxCO4bQLvSD@@XFD(R=z{%>})IkR1^S4dxhw&@4zs>9>W(~w+#Hmk$AIQGPB zHKaD{x2uMRFCT}ivmQ;|I%+acWS@C{ihlI_#?JFaud_@!tyg!t6Q@I0z|~1JcQ{h}<9hqjst{Rk zixpmwM6};cQtP>^hkP_T8|096-F>hB>k$Rwe7uAGX6jB}JP; zLBru+Qf>t2!D`WTS&|-aq1aWBaWh`P$Z#AeWgi+lH z!!zP~IdqRwYGx|}w#&`@aT;En`OxrIW`D6e`e?dkuxH_S0%CkQF^<8d0*0cg2tv!PGp3%=7BSuxN)`f01Auj z9q#p1VcDtFad*TfJ<4&p?i?=L%j-&07_5yAmOIMEtmSaD@LT;V>viM0Mjd2=4)IybTz0O>VBO%y!g3ZVvRrP547DItXt7JIw)GzdQ)-0Uf4D z12-_;42mRq;Om*52$| z-)ryhT}!j=$WI5+t6fi#z8B5(J zmh}$onDrev8zg|XjPLct6`$ENKy`N`9EU4)tFgSievRMy3-0gu`uB35i|+8c9pa(p zgI42Z`UDp&T1iUX?QV*d?_3g(b;w+ABE0xdIh%t=cF)HC3KsXf^nEuL*`erH7ezRb zBaRyN5M$WmRd^KZw=H+tm`r)g-`qCbYp=M@?axCSt0@RzyiM4(coIQ0lu$~L#noMj zBw3fY-&|6{0+Lj2iytr6ER4Myzozy`S7tRB?=X?|Y&@gc&qFtIVns5Le2?RW-Uy4i znct2=#!fV{3r5E9vU$fx_s&;$I}8bcygol5*<*NZXd^p)r7c5JUs)NAC$+e{%RBQk zDt2RR(bd7ircn#z6BEeC zHZQ7nXIL+kp$)k-VUv?7`{ zMH-IXDss@TTonk26EL}_!<*rCz8q$+&HAuZU|m`1$f}XHwK`JhO6HOEQWPCO9S6l& zE_+onQD8F5BoCH~f3R=(LgN*A)UgfQeE0hAZLc3Ii#n9zTRzX*lV&O?FOw-#tnW~e z(gd^JSLps8LEd4ep_R=OA}f}a;*8?XkZS;mezg@cBsI_ll~*Z8CY5yI%(x;dmEF%d zDVe(u%c6~>M*93E$MWQt{``DIr`2B!STg2?im7A@B%BJTe9>H|U>?QkGdV4nr%r z$Dd1#9;lYa_B%V=)+dyBAl~=ibn7q4#)RP+y^J$m67ZAkMcjgT-+MYt>y4Jh@m9$5 zVPx9K4-pw95v2GvAFzxQ^7#Cg(P@D>@PZ%%EJ(4S8vcB{00uB9*kOjh2Qa}f2E%%& z^B)%skCOnO7a0NkF?Euk{7DZy zlAxfT2^nt8BM1%2JeOB3&%`n(A$=RZDpy+V(&46r!r%tV08S8Ya0!R2r2rBXgfKzp z^a4m|fIx{s&a+1A9hE#kU!IxL!cQw{I}2TnFr2t}2XKr9{mh{2Y75pz!tK0!ig?#MN5YnPYNHv&S?~BqE`71KlQe#jh!W<%GNj^bO5DGHaRI6Nspb zr&xC~+vi~hdmKNxRG%0BJ+D5i*O&;K)}!M2Y+%$e+2AJ|6U0kjz}$nDnm3ri1rd6B zfC#7rBN+fP;EvysQ|DVO$p|K;irF{)algJTtzJ;2eeQy-Cnp6b5qhzSx5}jJX6&F+ z*j3YHvtb1gCJ@ygOB1OoNxItJmq~cS$@uuAQ#gfE6$rD30mkNNEBE6`e=T*2Gs!Rh zyWCrz=;S}K$O<8Z>M{rzE|AVIU9RYEl8J4})S6xBzdLDu)bH$WzL7CG?G!~D33xXKtu4ZlyaIp&VXW2%p{wHiTkbj#$>rsa ziw=T8IyA;~NX1$U$2e9U%ogZ~DOx};!fdv~=1k*p7|AFmWM>yvcZ0Ij-b4a)TmKjFAakt)qi6{L z+}U&b#`;mea+6KgzCo20cZ94q0n!iLPQ-MEDOl`$lp)FxB@9yJ*!}qH1?!Rk0FVWe z`W@smLkr^PGFc}XfCB&`5Os_Qfrp9}u2#P1-xbM|*jySrBwQmYpY`LY@P&phU z_nk7=DRI`}; zxxhqb$}EV#m>&zfNBr^9{3jQ*&5=9Km#e051X_LG?&o z1A$rqRnf^-%~ha}PNBA~D&t?y5s7#3@aRv<{tDCpvR9L>;HyA8IR!th0>uF>eoBFM(qg+dQV-=6L^MHZ^*xk!kjip|vUU*Fdvo{CgA!c- zcU7^WlmPB61E&)n%OB_jB>|W+P^EyF1gJx(1jZx)96|9wCg%WZ2QmqChxs}{i2^q+ zmD?v#eV;%8pnzwb$wn?)ALM^MZ3<8*j;2I@KM~ZG)zUsZHSvjq^gN1PpBgU2oZR-M zJ&&?-3P4o{uRtvonLQ$s!cUBPuJ*59#g`~l>I--`haNlTh!2ywrSBxe{r^YBFGOLm z?yZxga%t#gi;+>1o>DdG94Zf0Cw z_e%gn6oc(dM|&TVm6m{*N39-UpMVme=WGCuL2e0Eu-8~vHsqL+6p4WubNl{ZHe>Et zsUgXg_lnC2F%$X;B|yor%|0*&@Ahm=Fv!yBeX8U+jbe94$`S@u#0CH+Qp-vp17(Lu zPKcMXLO}?5f)8=X0!SZ$cAg^R%d7>!9ro0SOi&Uv00cx;StSs55V1s40+<31UTSnru=w8U+R|k`VmsxV_YEnfvO)x@l|v`;Pwrj7$O1hya`d z0&hJ}ya?F|MJ*(fq{SauFwJBPDJ`XM<%WYB`XuaPH*V+$*uH#s10G?D?Xw&HvIyJl z^!kMI@3QHpN4-+nHb#GRs44$Z^iPjoHEoc3Iv&1xlG46>OC)`so&cl(0A^(FiogK( z9(%vryVu>jcedB-db)OWYr9C>c2--Pw`6H0Y)BXoQU(bL0TKu)00bZkEhDHH`hJs6Ita4B33|=*#Vx3|=a-3C;OGMM5U3&Er=9avH-D=s&r0!@bwXd7bNTI?GHw`{4oVW zWB1Xd*4ekpU&yDsTza=1qIn5k?^FkkX!(9G^94{-c~U1sFXTcCQGNN}eT{|zrnY*= zgbX-ixBu9#WGi3GmF)G-=rL&#;sSmth(4I4jkLTkwN=~QM_ZkpN|PlYy=yQ}vFJc` zk4to-SoyuYWXS?tSs`Iooh(}PewE5JOGbXukTMy-yRC6l>15`e-3K9>>@-|K%ww(x zEhtf_GfR>kY_7)vr>Nj{jk*(n4@zJK{2kZmsQC%;WHLX<+MB^%aXq)p^rFsNVKu1@ z>gEEU+5YK{ik#d3%hdmRvTtcWYyCFff^^dP6Pek`*-4&a0Ge+x8Xs7hcS+i7~yS zvph4kv!i}}v+JxV`L3&X%}~-tv}~|3VdZg@RAqamFl(Ro)sTFfnSQUdWuCwa*GT1` zQc>X0A&W3@h=Th?f+t`7NEsOA1DJ5QmSbRG4Q%BM z^+62o0oUIQ3;`iu>5jm`@b)u~bVxAhKi6J;CJ~OjZ)>53N235R!o*_ss6l&ZQYs63 zl-A-as&;+gYRf*TRjx~r_B!or9h{rrzIZzX;e+eeNLKs%ODum_aZZ@-^4h9q5S>0& z_f5p05PePb$*Ay%e#M6+NjB*zhjNGmjUYwXDd6F7ww)2?cWo~4z3}}Nco>JeH>9tX zYIk=E3r41l7*-qxyGJanM|wVo4t=mFfu)oglbo-PF$*kui*_)Y!%|<$;X?pG?zrm4 zpH)SsmcN+GR%TMF6C}B`CVFClgRa4miz9Yw)jU+aMDVAMFBx~*Sl|yIckU} z=jU?!K4iCbtc`%+s@ z7#3JoM-S{|xDx{8u80L}y0?S5WuRTj>Uiw}Qf`QS+n8T%?*4&$I?xH}43lY38)@}@>-4>A?|add5`dK z)c?8oj_yl_O>VD4^KHEzev`h}@2z!J;jrWjwk6P%PJFhEE^B|6#=K|gTvJ?qql*`f zFv!CvnE41Hi-86IBu{o>q;A#`?8U)?nM4^8c5-WXju# zY1?2W+IekGtGFc(B?yVn)iE2ptDt(1JxW{so{9kX+gG&;+d9ph5w0`>XC`sQhrpOO z3wv=Q!?w6sR4m`w7RT-9jEON8qM3)!wuG#teVo(t212JSi4DAJj8Y0|EjM*}cuP}> z!U-Ca%G?$f(5$*!|J-ilu*L?rI4ndBS9x0Gljz!-vr`MER!5=1Zl@^3nGsAsspk{B z>sv}77F)Kr306p0E->DlaP@LEytBZY_gSi9zv-RFpORc^3nld_!96qG3;05T%RbyG z69*{M7XtCyNl%ue8Ha4;TM>6IbE>`Nr<kce=o6N=M(&3^ zi*8$!P~HOnHvAioIHW`s_}IaCnp-FjqZ1o>2q|XLgO24BBQ5dh;+YXi7T`_3gf?$8 zx)kI*g*|hm>lSeJjFAm31z|LtatmnoG%v2Gd!95m{P50dZ{AeTTyB7*#G`XBE9za5) z{U;#8wotjK6g_!8nG`VzEU+WvX{l;n03QBOvB-K?~Eguzd92R*6 zWBUf`0<1KQCIJ|y^{7G=M?0J<=D=+RV`Qj74d^$g{aq}mU=}XkV-h_KZ?$?t6ZcVg zo%hANS;gSBrtmAiPCasr(m@Ec+S%oK^DYYq@J1Qsv#w>YkFzBFTc2wFsFH5Fm+4SJFb$PK^Laqd6Jb1wEO?v*(gzwHCu6%_hJ zfRLNBdvj8()OpaTcp24>Ng;i@bBvS(nl3;B14IB#XE2S!PojTAf@lE-Ys;qaK+lC3 zyF&|n*3vj_7DlFP(EX)6^NnE&$9u;{M{G&ON5~UH&b<0LL*Lq%;8-ai;`DTUV2lXS z$_h;1a8`^kZU#YWu(k*Zj~fqd8^lF@ID4`*5U${m<#Ox+c9S6hS5wZVAqg;r=3;tJ z@-*awoFk=K6N9JF19?Plq(3nCh6C-O7>1H+xM*GMi_s+a$N^&?)L~#v+t0~0TxEXD z(GuqR&zuK8z_Hgj`D6TaS2l%0S_xaP<6GH-s5a&)Tl3_~W_)90r{`9`9u;8HW-lGT zs3YK@gfwcIw&FmKN-LJaD_0ih6!rMd|(lQ|D^9} zx(+{#k5PVo)FPbe-LmFwX(;haw+7=tKvH#3U#7v*8z2mWAwLX_IH-@@L*bnY=f6`1 z2Vq8q4Zwg6_jr9RGCKbNjL-}KW>Ytiu}vlO zd>wQ5Hr+mOI%Wt*2uM8sOldkt?!ee+j`M)J3{4!4i1m@N%}&>T?yz|*Jhjr&zxjHE zP7-lP?VK&9kI`)E!XyL~l%vC*AHmX)U%JI{9dIwv#oHoLv=`zl3_#+A4lv2^bY)exOB8yP(~Qn!vcZ4fq{&wJ|7}Y?0~?*I1n<) z8lFCopDEg!{y{C(wX(^0%HGOcQz6lbI`~iI(8avv(2gqHRnPgi z3>6LAkB_2F-Y(%!Bw12d6=`Hz>$l-tm*%h1&q-_n5-2sQBbT4b(&m1PLj>Q(G zcjl4>cQmT9C>e1|XNe`EP_05%VZmJ)06wcj8TZsg{0PNBt#DRuM>{njd13nryR6`s zQJO>PCkiMJ!WTXx>b(?|5`^=^!T$SpX~l1v&L5pN@YOUlPyXZ|5T$sbGLExCt>f5Z z^np~UR1&5#napUG9t)ZZDBMz|$Mz$#?bMdR;dM>y(~58PXXTkH?n3#pfPYwV2JHj6N-Y-Y ztVnQ+1H4s8=t2dP+*o6O7AiA!@ztj{8GjrHQ}}4_gIrw&EhjVI)6_rIWU&5s-rJSw zTH#TR8eVbW0$lSiv6RFMsDfX+$MdQ$lzrDxoRLCWhhq(-M_PY*ohFehtGiq_iHCa6xmWL60Y_3PT8Pi_D{R;KI;xcK9DDiso!Z&#berJc zZ9o6?Se8D)Wne?*DD6Rw)SAvaH?FvDqgPk&OTwJ9BG-(w?W~JgGN$czy1K-0&60(5 zRs$SF4@B5Sb+0P+%NK@waB6XA2B!et`k?Al9gGv{xVg82Uuu8!a(GE8fmXoWG2n~a zI&!|LtJiWmt&wAg91oju!`0ts>3sfbXj%$6Ct8nsKfkesuF}cRSf5;uMa*5k9UP-S zUU5fzkIq!zAXvh^N5wR4*K+(iM%>_eTXk4F4&X5h>GzUhA$fWv`0(khBH*ct^S@#P z^gh2w#Fe?E@5Y;C;RoH^CM-^yTfyxN$T_@&)DdZ}w7D+_E@2Mw5tG83r!`^a)P(ko z6Gx32DY>JLSSl)(cSoA~%e;BpfEnu^rdg@_zJw!cnhDA@pHw|myz2=<)Mct;8c~lxlPLmXq`%m>z9i0@u?VZYh4Let;(llm(R;pBt9> zO?~DV4^>!-Pwm5b3iS>yAxt@Y^79_UKJZbSFX|5#odNAhPAaUGXFQB``ISaofp30J zZ*5(kpP7y0Xez2H;@CspAt_i(>h!J%_nx-hzb-3YrF9h-+qJCqDs|Yaom_mfH}V;)SBNt*(~MU9nCMJ zh^1UTWie1%Q46TY3`w^@c@p83wSeyUyFk0N#T%x*I-0QxLf7*XgtVy)np6#$9l}RP ze=t?}!veMl{ff*;kpyT2Y5+R8x-0|kIUPTck?+b%esKf>g21?gNmc375kP%_M~!5j z7*zEnPE+nj+J+47BcwJdqIzHsh?kw;0w&~4Pvfqa_&i~`aV{J{*d=MCngcMxheDZv zaW)`KL%c-^VB8Ko0^mQl3I-{#0Lp+VkpYb0fwqdE*jR@LHV;Vo67DH(he|IC*?|Qu z?mY=E?|}{}xE)U5S|$T?r+e9Zpw5pF?=hc7AQ(H`_OkP>jXh7_Vex;27h*MziJH~O zsM)BguxD&nr7oYtcG4Y9i+m`QXayHLM!hDTDWQ!eC$q2jW--ds!sFmgeZ3rLQz4e8{&&KPT~#tfrt*aE`Tc zhU3uswv<|n+C!=IF)=YNli@TYGlsF0JQ#V2g)j#EaQzt`Ef=jvN*X(%N65B{5 z;it8UNL{uesR7=X1tx3TD%+_QSr6j>|KR)pzzhx5i~ztK7^!U?KQ_^AKFy_)sKiG^ zuT+}NU6OTcK8gf67+|x@k-dOg*VsSn1+iVxU6q42}-!E(em1`NhdnhYV8T_;n zf@$T;WJCH3E-2R~$G1z#7fvQF$@k`|!~g&h0IHdQyEiD`dwbu_-Ojn)b~88g+Fep) zP28L|yJK5$b<&VQNf`wNERP~kjKBvGC^jMjT8h|&A_5dgcqGVKq+&3_#}6PwfFJ;0 z2-*N()E@#t#X3ldi4MJOejh5QD|ys2PpU>lkf(%9(5Vg}HBH4zmSts9QAv+lOY+93 zsg2aA_7%v7c7OM$axJBuQke+e|D{7qptSXb$feOJ@Y6&ycqsG)=$e?DoBr?xoeM?( zLHfHhXu``RE!)P=b;$0Jr%(Thfbc9ynw9FExh4CjMN6L3r3uVJK*qAy)ve?k;mbU9 zsAs}wP(&vopQ%Vt2#Hu!MoO_wX1X!$Hgt(d(~rML!875=jgn?qu5&fI^r%FAwf#z$ z;`YFUc0ET(r+tZ{9KI&hrw;yW`d&Ncx<;jimW39oFF36R%AzHW6MCapa8RInA?l$Q za^MMF4ACn?Pg{CrwW}ip@zkYks7OX#Q`<6%x# zvvQR5-J8u|D%Z-#``4wIPK~U4WhK$lwlb$yD>{I~Ok+O%36`4Tgiv-zkJ^Y*HO6Nl z#D+jxRT3gr1aa!V6DFWVe_>onGzFQ$-$vKbvV%0WQ(HA?XAyc39jVZU-!fg&BCUpK zd_b9r-vxN|i~|ydc=Tty+J^pOc_YOLw1%2LUu3Ny)O47%=&?*48WtVs-KvcVcItRd z+&vfix#AZHTE&#wj^NuN8?X&;i)tn2cD9o)0ZuHiiBqJaGQnMQvBSRjdiu>s%iA-Q zY4MaeBgkWc;bx>4iDp~=Ra+GBpPtC^alBh&^TX`LV7sOip@vQK9aW-0wziL-4#a$; zw8E5U-dm;&bo=h*x>CX>J-;*cSs-D(eyV#2lg{MfwkK=mCjaRL#kl)Es0qXl+F@

YN~3L2sZfO=IECaoWklteaP6M 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 z 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
    4%~BX(|V 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

    kc*G$(EtGT7A<|L&a7F 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 _!^etZ|O2%mm( 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 xN? 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 z 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 th{*q^wItL4&ifbVeWKXGYkuTQ|>KRk9=eq(}! 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